Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/cycles/render')
-rw-r--r--intern/cycles/render/attribute.cpp10
-rw-r--r--intern/cycles/render/buffers.cpp12
-rw-r--r--intern/cycles/render/buffers.h6
-rw-r--r--intern/cycles/render/camera.cpp11
-rw-r--r--intern/cycles/render/camera.h5
-rw-r--r--intern/cycles/render/film.cpp2
-rw-r--r--intern/cycles/render/filter.cpp6
-rw-r--r--intern/cycles/render/graph.cpp12
-rw-r--r--intern/cycles/render/image.cpp12
-rw-r--r--intern/cycles/render/light.cpp16
-rw-r--r--intern/cycles/render/light.h3
-rw-r--r--intern/cycles/render/mesh.cpp6
-rw-r--r--intern/cycles/render/nodes.cpp45
-rw-r--r--intern/cycles/render/nodes.h10
-rw-r--r--intern/cycles/render/object.cpp52
-rw-r--r--intern/cycles/render/object.h9
-rw-r--r--intern/cycles/render/osl.cpp2
-rw-r--r--intern/cycles/render/scene.h3
-rw-r--r--intern/cycles/render/session.cpp29
-rw-r--r--intern/cycles/render/shader.cpp8
-rw-r--r--intern/cycles/render/shader.h6
-rw-r--r--intern/cycles/render/svm.cpp28
22 files changed, 218 insertions, 75 deletions
diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp
index c1a089cc872..5c7966d6d96 100644
--- a/intern/cycles/render/attribute.cpp
+++ b/intern/cycles/render/attribute.cpp
@@ -74,10 +74,13 @@ bool Attribute::same_storage(TypeDesc a, TypeDesc b)
if(a == TypeDesc::TypeColor || a == TypeDesc::TypePoint ||
a == TypeDesc::TypeVector || a == TypeDesc::TypeNormal)
+ {
if(b == TypeDesc::TypeColor || b == TypeDesc::TypePoint ||
b == TypeDesc::TypeVector || b == TypeDesc::TypeNormal)
+ {
return true;
-
+ }
+ }
return false;
}
@@ -286,10 +289,13 @@ bool AttributeRequestSet::modified(const AttributeRequestSet& other)
for(size_t j = 0; j < requests.size() && !found; j++)
if(requests[i].name == other.requests[j].name &&
requests[i].std == other.requests[j].std)
+ {
found = true;
+ }
- if(!found)
+ if(!found) {
return true;
+ }
}
return false;
diff --git a/intern/cycles/render/buffers.cpp b/intern/cycles/render/buffers.cpp
index a80851b945a..a79a3591e0f 100644
--- a/intern/cycles/render/buffers.cpp
+++ b/intern/cycles/render/buffers.cpp
@@ -117,8 +117,8 @@ void RenderBuffers::reset(Device *device, BufferParams& params_)
uint *init_state = rng_state.resize(params.width, params.height);
int x, y, width = params.width, height = params.height;
- for(x=0; x<width; x++)
- for(y=0; y<height; y++)
+ for(x = 0; x < width; x++)
+ for(y = 0; y < height; y++)
init_state[x + y*width] = hash_int_2d(params.full_x+x, params.full_y+y);
device->mem_alloc(rng_state, MEM_READ_WRITE);
@@ -311,8 +311,14 @@ void DisplayBuffer::draw_set(int width, int height)
void DisplayBuffer::draw(Device *device)
{
- if(draw_width != 0 && draw_height != 0)
+ if(draw_width != 0 && draw_height != 0) {
+ glPushMatrix();
+ glTranslatef(params.full_x, params.full_y, 0.0f);
+
device->draw_pixels(rgba, 0, draw_width, draw_height, 0, params.width, params.height, transparent);
+
+ glPopMatrix();
+ }
}
bool DisplayBuffer::draw_ready()
diff --git a/intern/cycles/render/buffers.h b/intern/cycles/render/buffers.h
index 77ad4a5a4b0..78712ed89ef 100644
--- a/intern/cycles/render/buffers.h
+++ b/intern/cycles/render/buffers.h
@@ -35,7 +35,7 @@ class Device;
struct float4;
/* Buffer Parameters
- Size of render buffer and how it fits in the full image (border render). */
+ * Size of render buffer and how it fits in the full image (border render). */
class BufferParams {
public:
@@ -98,8 +98,8 @@ public:
/* buffer parameters */
BufferParams params;
/* dimensions for how much of the buffer is actually ready for display.
- with progressive render we can be using only a subset of the buffer.
- if these are zero, it means nothing can be drawn yet */
+ * with progressive render we can be using only a subset of the buffer.
+ * if these are zero, it means nothing can be drawn yet */
int draw_width, draw_height;
/* draw alpha channel? */
bool transparent;
diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp
index 3ecffab7cbc..55a0f23f8d0 100644
--- a/intern/cycles/render/camera.cpp
+++ b/intern/cycles/render/camera.cpp
@@ -58,6 +58,11 @@ Camera::Camera()
bottom = -1.0f;
top = 1.0f;
+ border_left = 0.0f;
+ border_right = 1.0f;
+ border_bottom = 0.0f;
+ border_top = 1.0f;
+
screentoworld = transform_identity();
rastertoworld = transform_identity();
ndctoworld = transform_identity();
@@ -194,7 +199,7 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene)
kcam->bladesrotation = bladesrotation;
/* motion blur */
- kcam->shuttertime= (need_motion == Scene::MOTION_BLUR)? shuttertime: 0.0f;
+ kcam->shuttertime = (need_motion == Scene::MOTION_BLUR) ? shuttertime: 0.0f;
/* type */
kcam->type = type;
@@ -248,6 +253,10 @@ bool Camera::modified(const Camera& cam)
(right == cam.right) &&
(bottom == cam.bottom) &&
(top == cam.top) &&
+ (border_left == cam.border_left) &&
+ (border_right == cam.border_right) &&
+ (border_bottom == cam.border_bottom) &&
+ (border_top == cam.border_top) &&
(matrix == cam.matrix) &&
(motion == cam.motion) &&
(use_motion == cam.use_motion) &&
diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h
index 7a09b5981e4..d2a3cce1817 100644
--- a/intern/cycles/render/camera.h
+++ b/intern/cycles/render/camera.h
@@ -67,6 +67,9 @@ public:
int width, height;
float left, right, bottom, top;
+ /* border */
+ float border_left, border_right, border_bottom, border_top;
+
/* transformation */
Transform matrix;
@@ -75,7 +78,7 @@ public:
bool use_motion;
/* computed camera parameters */
- Transform screentoworld;
+ Transform screentoworld;
Transform rastertoworld;
Transform ndctoworld;
Transform rastertocamera;
diff --git a/intern/cycles/render/film.cpp b/intern/cycles/render/film.cpp
index 878aa87510e..035821fadde 100644
--- a/intern/cycles/render/film.cpp
+++ b/intern/cycles/render/film.cpp
@@ -142,7 +142,7 @@ void Pass::add(PassType type, vector<Pass>& passes)
passes.push_back(pass);
/* order from by components, to ensure alignment so passes with size 4
- come first and then passes with size 1 */
+ * come first and then passes with size 1 */
sort(passes.begin(), passes.end(), compare_pass_order);
if(pass.divide_type != PASS_NONE)
diff --git a/intern/cycles/render/filter.cpp b/intern/cycles/render/filter.cpp
index 9bcf57b5a27..0bd4fb4d579 100644
--- a/intern/cycles/render/filter.cpp
+++ b/intern/cycles/render/filter.cpp
@@ -73,17 +73,17 @@ static vector<float> filter_table(FilterType type, float width)
/* compute cumulative distribution function */
filter_table_cdf[0] = 0.0f;
- for(i=0; i<filter_table_size; i++) {
+ for(i = 0; i < filter_table_size; i++) {
float x = i*width*0.5f/(filter_table_size-1);
float y = filter_func(x, width);
filter_table_cdf[i+1] += filter_table_cdf[i] + fabsf(y);
}
- for(i=0; i<=filter_table_size; i++)
+ for(i = 0; i <= filter_table_size; i++)
filter_table_cdf[i] /= filter_table_cdf[filter_table_size];
/* create importance sampling table */
- for(i=0; i<=half_size; i++) {
+ for(i = 0; i <= half_size; i++) {
float x = i/(float)half_size;
int index = upper_bound(filter_table_cdf.begin(), filter_table_cdf.end(), x) - filter_table_cdf.begin();
float t;
diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp
index a0e7af66100..34c8879aa1f 100644
--- a/intern/cycles/render/graph.cpp
+++ b/intern/cycles/render/graph.cpp
@@ -375,8 +375,8 @@ void ShaderGraph::break_cycles(ShaderNode *node, vector<bool>& visited, vector<b
void ShaderGraph::clean()
{
/* we do two things here: find cycles and break them, and remove unused
- nodes that don't feed into the output. how cycles are broken is
- undefined, they are invalid input, the important thing is to not crash */
+ * nodes that don't feed into the output. how cycles are broken is
+ * undefined, they are invalid input, the important thing is to not crash */
vector<bool> removed(nodes.size(), false);
vector<bool> visited(nodes.size(), false);
@@ -495,7 +495,7 @@ void ShaderGraph::bump_from_displacement()
copy_nodes(nodes_displace, nodes_dy);
/* mark nodes to indicate they are use for bump computation, so
- that any texture coordinates are shifted by dx/dy when sampling */
+ * that any texture coordinates are shifted by dx/dy when sampling */
foreach(NodePair& pair, nodes_center)
pair.second->bump = SHADER_BUMP_CENTER;
foreach(NodePair& pair, nodes_dx)
@@ -516,15 +516,15 @@ void ShaderGraph::bump_from_displacement()
connect(out_dy, bump->input("SampleY"));
/* connect bump output to normal input nodes that aren't set yet. actually
- this will only set the normal input to the geometry node that we created
- and connected to all other normal inputs already. */
+ * this will only set the normal input to the geometry node that we created
+ * and connected to all other normal inputs already. */
foreach(ShaderNode *node, nodes)
foreach(ShaderInput *input, node->inputs)
if(!input->link && input->default_value == ShaderInput::NORMAL)
connect(bump->output("Normal"), input);
/* finally, add the copied nodes to the graph. we can't do this earlier
- because we would create dependency cycles in the above loop */
+ * because we would create dependency cycles in the above loop */
foreach(NodePair& pair, nodes_center)
add(pair.second);
foreach(NodePair& pair, nodes_dx)
diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp
index 6417d0e2103..dc20dbdbea2 100644
--- a/intern/cycles/render/image.cpp
+++ b/intern/cycles/render/image.cpp
@@ -66,7 +66,7 @@ static bool is_float_image(const string& filename)
if(in->open(filename, spec)) {
/* check the main format, and channel formats;
- if any take up more than one byte, we'll need a float texture slot */
+ * if any take up more than one byte, we'll need a float texture slot */
if(spec.format.basesize() > 1)
is_float = true;
@@ -171,8 +171,8 @@ void ImageManager::remove_image(const string& filename)
assert(images[slot]->users >= 0);
/* don't remove immediately, rather do it all together later on. one of
- the reasons for this is that on shader changes we add and remove nodes
- that use them, but we do not want to reload the image all the time. */
+ * the reasons for this is that on shader changes we add and remove nodes
+ * that use them, but we do not want to reload the image all the time. */
if(images[slot]->users == 0)
need_update = true;
@@ -189,8 +189,8 @@ void ImageManager::remove_image(const string& filename)
assert(float_images[slot]->users >= 0);
/* don't remove immediately, rather do it all together later on. one of
- the reasons for this is that on shader changes we add and remove nodes
- that use them, but we do not want to reload the image all the time. */
+ * the reasons for this is that on shader changes we add and remove nodes
+ * that use them, but we do not want to reload the image all the time. */
if(float_images[slot]->users == 0)
need_update = true;
@@ -483,7 +483,7 @@ void ImageManager::device_update(Device *device, DeviceScene *dscene, Progress&
void ImageManager::device_pack_images(Device *device, DeviceScene *dscene, Progress& progess)
{
/* for OpenCL, we pack all image textures inside a single big texture, and
- will do our own interpolation in the kernel */
+ * will do our own interpolation in the kernel */
size_t size = 0;
for(size_t slot = 0; slot < images.size(); slot++) {
diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp
index 267cb8e6d3a..e918de990c2 100644
--- a/intern/cycles/render/light.cpp
+++ b/intern/cycles/render/light.cpp
@@ -109,6 +109,9 @@ Light::Light()
map_resolution = 512;
+ spot_angle = M_PI_F/4.0f;
+ spot_smooth = 0.0f;
+
cast_shadow = true;
shader = 0;
}
@@ -359,7 +362,7 @@ void LightManager::device_update_background(Device *device, DeviceScene *dscene,
float cdf_total = cond_cdf[i * cdf_count + res - 1].y + cond_cdf[i * cdf_count + res - 1].x / res;
/* stuff the total into the brightness value for the last entry, because
- we are going to normalize the CDFs to 0.0 to 1.0 afterwards */
+ * we are going to normalize the CDFs to 0.0 to 1.0 afterwards */
cond_cdf[i * cdf_count + res].x = cdf_total;
if(cdf_total > 0.0f)
@@ -451,6 +454,17 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce
light_data[i*LIGHT_SIZE + 2] = make_float4(0.0f, axisv.x, axisv.y, axisv.z);
light_data[i*LIGHT_SIZE + 3] = make_float4(0.0f, dir.x, dir.y, dir.z);
}
+ else if(light->type == LIGHT_SPOT) {
+ shader_id &= ~SHADER_AREA_LIGHT;
+
+ float spot_angle = cosf(light->spot_angle*0.5f);
+ float spot_smooth = (1.0f - spot_angle)*light->spot_smooth;
+
+ light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z);
+ light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), light->size, dir.x, dir.y);
+ light_data[i*LIGHT_SIZE + 2] = make_float4(dir.z, spot_angle, spot_smooth, 0.0f);
+ light_data[i*LIGHT_SIZE + 3] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ }
}
device->tex_alloc("__light_data", dscene->light_data);
diff --git a/intern/cycles/render/light.h b/intern/cycles/render/light.h
index 0ed143f5ad1..fb8684fa59b 100644
--- a/intern/cycles/render/light.h
+++ b/intern/cycles/render/light.h
@@ -48,6 +48,9 @@ public:
int map_resolution;
+ float spot_angle;
+ float spot_smooth;
+
bool cast_shadow;
int shader;
diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp
index cabbd5760c2..8f5f2647ebf 100644
--- a/intern/cycles/render/mesh.cpp
+++ b/intern/cycles/render/mesh.cpp
@@ -474,7 +474,7 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene,
AttributeRequestSet& attributes = mesh_attributes[i];
/* todo: we now store std and name attributes from requests even if
- they actually refer to the same mesh attributes, optimize */
+ * they actually refer to the same mesh attributes, optimize */
foreach(AttributeRequest& req, attributes.requests) {
Attribute *mattr = mesh->attributes.find(req);
@@ -493,7 +493,7 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene,
}
/* we abuse AttributeRequest to pass on info like element and
- offset, it doesn't really make sense but is convenient */
+ * offset, it doesn't really make sense but is convenient */
/* store element and type */
if(mattr->element == Attribute::VERTEX)
@@ -528,7 +528,7 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene,
}
/* mesh vertex/triangle index is global, not per object, so we sneak
- a correction for that in here */
+ * a correction for that in here */
if(req.element == ATTR_ELEMENT_VERTEX)
req.offset -= mesh->vert_offset;
else if(mattr->element == Attribute::FACE)
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index 16c6b07261a..0f64d858de0 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -332,7 +332,7 @@ static void sky_texture_precompute(KernelSunSky *ksunsky, float3 dir, float turb
float T2 = T * T;
float chi = (4.0f / 9.0f - T / 120.0f) * (M_PI_F - 2.0f * theta);
- ksunsky->zenith_Y = (4.0453f * T - 4.9710f) * tan(chi) - 0.2155f * T + 2.4192f;
+ ksunsky->zenith_Y = (4.0453f * T - 4.9710f) * tanf(chi) - 0.2155f * T + 2.4192f;
ksunsky->zenith_Y *= 0.06f;
ksunsky->zenith_x =
@@ -695,7 +695,7 @@ static ShaderEnum wave_type_init()
ShaderEnum WaveTextureNode::type_enum = wave_type_init();
WaveTextureNode::WaveTextureNode()
-: TextureNode("marble_texture")
+: TextureNode("wave_texture")
{
type = ustring("Bands");
@@ -1789,6 +1789,47 @@ void ObjectInfoNode::compile(OSLCompiler& compiler)
compiler.add(this, "node_object_info");
}
+/* Particle Info */
+
+ParticleInfoNode::ParticleInfoNode()
+: ShaderNode("particle_info")
+{
+ add_output("Age", SHADER_SOCKET_FLOAT);
+ add_output("Lifetime", SHADER_SOCKET_FLOAT);
+}
+
+void ParticleInfoNode::attributes(AttributeRequestSet *attributes)
+{
+ if(!output("Age")->links.empty())
+ attributes->add(ATTR_STD_PARTICLE);
+ if(!output("Lifetime")->links.empty())
+ attributes->add(ATTR_STD_PARTICLE);
+
+ ShaderNode::attributes(attributes);
+}
+
+void ParticleInfoNode::compile(SVMCompiler& compiler)
+{
+ ShaderOutput *out;
+
+ out = output("Age");
+ if(!out->links.empty()) {
+ compiler.stack_assign(out);
+ compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_AGE, out->stack_offset);
+ }
+
+ out = output("Lifetime");
+ if(!out->links.empty()) {
+ compiler.stack_assign(out);
+ compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_LIFETIME, out->stack_offset);
+ }
+}
+
+void ParticleInfoNode::compile(OSLCompiler& compiler)
+{
+ compiler.add(this, "node_particle_info");
+}
+
/* Value */
ValueNode::ValueNode()
diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h
index 2d0d58d1e94..efd814e4ae6 100644
--- a/intern/cycles/render/nodes.h
+++ b/intern/cycles/render/nodes.h
@@ -44,7 +44,7 @@ public:
float3 min, max;
bool use_minmax;
- enum Mapping { NONE=0, X=1, Y=2, Z=3 };
+ enum Mapping { NONE = 0, X = 1, Y = 2, Z = 3 };
Mapping x_mapping, y_mapping, z_mapping;
enum Projection { FLAT, CUBE, TUBE, SPHERE };
@@ -55,7 +55,7 @@ public:
class TextureNode : public ShaderNode {
public:
- TextureNode(const char *name) : ShaderNode(name) {}
+ TextureNode(const char *name_) : ShaderNode(name_) {}
TextureMapping tex_mapping;
};
@@ -290,6 +290,12 @@ public:
SHADER_NODE_CLASS(ObjectInfoNode)
};
+class ParticleInfoNode : public ShaderNode {
+public:
+ SHADER_NODE_CLASS(ParticleInfoNode)
+ void attributes(AttributeRequestSet *attributes);
+};
+
class ValueNode : public ShaderNode {
public:
SHADER_NODE_CLASS(ValueNode)
diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp
index 5c7e48a38eb..376a7911fc9 100644
--- a/intern/cycles/render/object.cpp
+++ b/intern/cycles/render/object.cpp
@@ -25,6 +25,7 @@
#include "util_foreach.h"
#include "util_map.h"
#include "util_progress.h"
+#include "util_vector.h"
CCL_NAMESPACE_BEGIN
@@ -38,6 +39,7 @@ Object::Object()
visibility = ~0;
random_id = 0;
pass_id = 0;
+ particle_id = 0;
bounds = BoundBox::empty;
motion.pre = transform_identity();
motion.post = transform_identity();
@@ -87,7 +89,7 @@ void Object::apply_transform()
Transform ntfm = transform_transpose(transform_inverse(tfm));
/* we keep normals pointing in same direction on negative scale, notify
- mesh about this in it (re)calculates normals */
+ * mesh about this in it (re)calculates normals */
if(transform_negative_scale(tfm))
mesh->transform_negative_scaled = true;
@@ -159,7 +161,7 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene
Transform itfm = transform_inverse(tfm);
/* compute surface area. for uniform scale we can do avoid the many
- transform calls and share computation for instances */
+ * transform calls and share computation for instances */
/* todo: correct for displacement, and move to a better place */
float uniform_scale;
float surface_area = 0.0f;
@@ -200,12 +202,12 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene
memcpy(&objects[offset], &tfm, sizeof(float4)*3);
memcpy(&objects[offset+3], &itfm, sizeof(float4)*3);
- objects[offset+6] = make_float4(surface_area, pass_id, random_number, 0.0f);
+ objects[offset+6] = make_float4(surface_area, pass_id, random_number, __int_as_float(ob->particle_id));
if(need_motion == Scene::MOTION_PASS) {
/* motion transformations, is world/object space depending if mesh
- comes with deformed position in object space, or if we transform
- the shading point in world space */
+ * comes with deformed position in object space, or if we transform
+ * the shading point in world space */
Transform mtfm_pre = ob->motion.pre;
Transform mtfm_post = ob->motion.post;
@@ -246,6 +248,38 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene
device->tex_alloc("__object_flag", dscene->object_flag);
}
+void ObjectManager::device_update_particles(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
+{
+ /* count particles.
+ * adds one dummy particle at the beginning to avoid invalid lookups,
+ * in case a shader uses particle info without actual particle data.
+ */
+ int num_particles = 1;
+ foreach(Object *ob, scene->objects)
+ num_particles += ob->particles.size();
+
+ float4 *particles = dscene->particles.resize(PARTICLE_SIZE*num_particles);
+
+ /* dummy particle */
+ particles[0] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+
+ int i = 1;
+ foreach(Object *ob, scene->objects) {
+ foreach(Particle &pa, ob->particles) {
+ /* pack in texture */
+ int offset = i*PARTICLE_SIZE;
+
+ particles[offset] = make_float4(pa.age, pa.lifetime, 0.0f, 0.0f);
+
+ i++;
+
+ if(progress.get_cancel()) return;
+ }
+ }
+
+ device->tex_alloc("__particles", dscene->particles);
+}
+
void ObjectManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
{
if(!need_update)
@@ -271,6 +305,11 @@ void ObjectManager::device_update(Device *device, DeviceScene *dscene, Scene *sc
if(progress.get_cancel()) return;
+ progress.set_status("Updating Objects", "Copying Particles to device");
+ device_update_particles(device, dscene, scene, progress);
+
+ if(progress.get_cancel()) return;
+
need_update = false;
}
@@ -281,6 +320,9 @@ void ObjectManager::device_free(Device *device, DeviceScene *dscene)
device->tex_free(dscene->object_flag);
dscene->object_flag.clear();
+
+ device->tex_free(dscene->particles);
+ dscene->particles.clear();
}
void ObjectManager::apply_static_transforms(Scene *scene, Progress& progress)
diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h
index a3bd748a8a4..6d674731b07 100644
--- a/intern/cycles/render/object.h
+++ b/intern/cycles/render/object.h
@@ -35,6 +35,11 @@ struct Transform;
/* Object */
+struct Particle {
+ float age;
+ float lifetime;
+};
+
class Object {
public:
Mesh *mesh;
@@ -49,6 +54,9 @@ public:
bool use_motion;
bool use_holdout;
+ int particle_id;
+ vector<Particle> particles;
+
Object();
~Object();
@@ -69,6 +77,7 @@ public:
void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
void device_update_transforms(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
+ void device_update_particles(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
void device_free(Device *device, DeviceScene *dscene);
void tag_update(Scene *scene);
diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp
index b0173334c76..04af9b48280 100644
--- a/intern/cycles/render/osl.cpp
+++ b/intern/cycles/render/osl.cpp
@@ -167,7 +167,7 @@ string OSLCompiler::compatible_name(const char *name)
bool OSLCompiler::node_skip_input(ShaderNode *node, ShaderInput *input)
{
/* exception for output node, only one input is actually used
- depending on the current shader type */
+ * depending on the current shader type */
if(node->name == ustring("output")) {
if(strcmp(input->name, "Surface") == 0 && current_type != SHADER_TYPE_SURFACE)
diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h
index 90bc47d5c8e..8b9944cb76e 100644
--- a/intern/cycles/render/scene.h
+++ b/intern/cycles/render/scene.h
@@ -82,6 +82,9 @@ public:
device_vector<float2> light_background_marginal_cdf;
device_vector<float2> light_background_conditional_cdf;
+ /* particles */
+ device_vector<float4> particles;
+
/* shaders */
device_vector<uint4> svm_nodes;
device_vector<uint> shader_flag;
diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp
index 34a0c0ff877..a9f7e5beb56 100644
--- a/intern/cycles/render/session.cpp
+++ b/intern/cycles/render/session.cpp
@@ -27,6 +27,7 @@
#include "util_foreach.h"
#include "util_function.h"
+#include "util_opengl.h"
#include "util_task.h"
#include "util_time.h"
@@ -115,8 +116,8 @@ bool Session::ready_to_reset()
void Session::reset_gpu(BufferParams& buffer_params, int samples)
{
/* block for buffer acces and reset immediately. we can't do this
- in the thread, because we need to allocate an OpenGL buffer, and
- that only works in the main thread */
+ * in the thread, because we need to allocate an OpenGL buffer, and
+ * that only works in the main thread */
thread_scoped_lock display_lock(display->mutex);
thread_scoped_lock buffers_lock(buffers->mutex);
@@ -139,10 +140,10 @@ bool Session::draw_gpu(BufferParams& buffer_params)
/* first check we already rendered something */
if(gpu_draw_ready) {
/* then verify the buffers have the expected size, so we don't
- draw previous results in a resized window */
+ * draw previous results in a resized window */
if(!buffer_params.modified(display->params)) {
/* for CUDA we need to do tonemapping still, since we can
- only access GL buffers from the main thread */
+ * only access GL buffers from the main thread */
if(gpu_need_tonemap) {
thread_scoped_lock buffers_lock(buffers->mutex);
tonemap();
@@ -184,7 +185,7 @@ void Session::run_gpu()
}
else {
/* if in interactive mode, and we are either paused or done for now,
- wait for pause condition notify to wake up again */
+ * wait for pause condition notify to wake up again */
thread_scoped_lock pause_lock(pause_mutex);
if(pause || no_tiles) {
@@ -223,8 +224,8 @@ void Session::run_gpu()
if(!no_tiles) {
/* buffers mutex is locked entirely while rendering each
- sample, and released/reacquired on each iteration to allow
- reset and draw in between */
+ * sample, and released/reacquired on each iteration to allow
+ * reset and draw in between */
thread_scoped_lock buffers_lock(buffers->mutex);
/* update status and timing */
@@ -293,7 +294,7 @@ bool Session::draw_cpu(BufferParams& buffer_params)
/* first check we already rendered something */
if(display->draw_ready()) {
/* then verify the buffers have the expected size, so we don't
- draw previous results in a resized window */
+ * draw previous results in a resized window */
if(!buffer_params.modified(display->params)) {
display->draw(device);
@@ -333,7 +334,7 @@ void Session::run_cpu()
}
else {
/* if in interactive mode, and we are either paused or done for now,
- wait for pause condition notify to wake up again */
+ * wait for pause condition notify to wake up again */
thread_scoped_lock pause_lock(pause_mutex);
if(pause || no_tiles) {
@@ -361,8 +362,8 @@ void Session::run_cpu()
if(!no_tiles) {
/* buffers mutex is locked entirely while rendering each
- sample, and released/reacquired on each iteration to allow
- reset and draw in between */
+ * sample, and released/reacquired on each iteration to allow
+ * reset and draw in between */
thread_scoped_lock buffers_lock(buffers->mutex);
/* update scene */
@@ -405,7 +406,7 @@ void Session::run_cpu()
}
else if(need_tonemap) {
/* tonemap only if we do not reset, we don't we don't
- want to show the result of an incomplete sample*/
+ * wan't to show the result of an incomplete sample*/
tonemap();
}
@@ -534,8 +535,8 @@ void Session::update_scene()
progress.set_status("Updating Scene");
/* update camera if dimensions changed for progressive render. the camera
- knows nothing about progressive or cropped rendering, it just gets the
- image dimensions passed in */
+ * knows nothing about progressive or cropped rendering, it just gets the
+ * image dimensions passed in */
Camera *cam = scene->camera;
int width = tile_manager.state.buffer.full_width;
int height = tile_manager.state.buffer.full_height;
diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp
index f50709146ef..fae1d6bd81c 100644
--- a/intern/cycles/render/shader.cpp
+++ b/intern/cycles/render/shader.cpp
@@ -81,9 +81,9 @@ void Shader::tag_update(Scene *scene)
scene->light_manager->need_update = true;
/* get requested attributes. this could be optimized by pruning unused
- nodes here already, but that's the job of the shader manager currently,
- and may not be so great for interactive rendering where you temporarily
- disconnect a node */
+ * nodes here already, but that's the job of the shader manager currently,
+ * and may not be so great for interactive rendering where you temporarily
+ * disconnect a node */
AttributeRequestSet prev_attributes = attributes;
attributes.clear();
@@ -91,7 +91,7 @@ void Shader::tag_update(Scene *scene)
node->attributes(&attributes);
/* compare if the attributes changed, mesh manager will check
- need_update_attributes, update the relevant meshes and clear it. */
+ * need_update_attributes, update the relevant meshes and clear it. */
if(attributes.modified(prev_attributes)) {
need_update_attributes = true;
scene->mesh_manager->need_update = true;
diff --git a/intern/cycles/render/shader.h b/intern/cycles/render/shader.h
index 48d517ce21a..02788008060 100644
--- a/intern/cycles/render/shader.h
+++ b/intern/cycles/render/shader.h
@@ -53,8 +53,8 @@ public:
ShaderGraph *graph;
/* shader graph with auto bump mapping included, we compile two shaders,
- with and without bump, because the displacement method is a mesh
- level setting, so we need to handle both */
+ * with and without bump, because the displacement method is a mesh
+ * level setting, so we need to handle both */
ShaderGraph *graph_bump;
/* sampling */
@@ -109,7 +109,7 @@ public:
int get_shader_id(uint shader, Mesh *mesh = NULL, bool smooth = false);
/* add default shaders to scene, to use as default for things that don't
- have any shader assigned explicitly */
+ * have any shader assigned explicitly */
static void add_default(Scene *scene);
protected:
diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp
index 1ff3ac20d50..844ce01569f 100644
--- a/intern/cycles/render/svm.cpp
+++ b/intern/cycles/render/svm.cpp
@@ -251,11 +251,11 @@ void SVMCompiler::stack_link(ShaderInput *input, ShaderOutput *output)
void SVMCompiler::stack_clear_users(ShaderNode *node, set<ShaderNode*>& done)
{
/* optimization we should add:
- find and lower user counts for outputs for which all inputs are done.
- this is done before the node is compiled, under the assumption that the
- node will first load all inputs from the stack and then writes its
- outputs. this used to work, but was disabled because it gave trouble
- with inputs getting stack positions assigned */
+ * find and lower user counts for outputs for which all inputs are done.
+ * this is done before the node is compiled, under the assumption that the
+ * node will first load all inputs from the stack and then writes its
+ * outputs. this used to work, but was disabled because it gave trouble
+ * with inputs getting stack positions assigned */
foreach(ShaderInput *input, node->inputs) {
ShaderOutput *output = input->link;
@@ -418,8 +418,8 @@ void SVMCompiler::generate_closure(ShaderNode *node, set<ShaderNode*>& done)
add_node(NODE_ADD_CLOSURE, 0, 0, 0);
/* generate code for closure 1
- note we backup all compiler state and restore it afterwards, so one
- closure choice doesn't influence the other*/
+ * note we backup all compiler state and restore it afterwards, so one
+ * closure choice doesn't influence the other*/
if(cl1in->link) {
StackBackup backup;
stack_backup(backup, done);
@@ -448,7 +448,7 @@ void SVMCompiler::generate_closure(ShaderNode *node, set<ShaderNode*>& done)
add_node(NODE_END, 0, 0, 0);
/* set jump for mix node, -1 because offset is already
- incremented when this jump is added to it */
+ * incremented when this jump is added to it */
svm_nodes[mix_offset].z = cl2_offset - mix_offset - 1;
done.insert(node);
@@ -482,9 +482,9 @@ void SVMCompiler::generate_closure(ShaderNode *node, set<ShaderNode*>& done)
void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& done, uint in_offset)
{
/* todo: the weaks point here is that unlike the single closure sampling
- we will evaluate all nodes even if they are used as input for closures
- that are unused. it's not clear what would be the best way to skip such
- nodes at runtime, especially if they are tangled up */
+ * we will evaluate all nodes even if they are used as input for closures
+ * that are unused. it's not clear what would be the best way to skip such
+ * nodes at runtime, especially if they are tangled up */
if(node->name == ustring("mix_closure") || node->name == ustring("add_closure")) {
ShaderInput *fin = node->input("Fac");
@@ -597,10 +597,10 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty
memset(&active_stack, 0, sizeof(active_stack));
svm_nodes.clear();
- foreach(ShaderNode *node, graph->nodes) {
- foreach(ShaderInput *input, node->inputs)
+ foreach(ShaderNode *node_iter, graph->nodes) {
+ foreach(ShaderInput *input, node_iter->inputs)
input->stack_offset = SVM_STACK_INVALID;
- foreach(ShaderOutput *output, node->outputs)
+ foreach(ShaderOutput *output, node_iter->outputs)
output->stack_offset = SVM_STACK_INVALID;
}