diff options
Diffstat (limited to 'intern/cycles/render')
-rw-r--r-- | intern/cycles/render/CMakeLists.txt | 4 | ||||
-rw-r--r-- | intern/cycles/render/attribute.cpp | 54 | ||||
-rw-r--r-- | intern/cycles/render/attribute.h | 29 | ||||
-rw-r--r-- | intern/cycles/render/buffers.cpp | 22 | ||||
-rw-r--r-- | intern/cycles/render/camera.cpp | 39 | ||||
-rw-r--r-- | intern/cycles/render/camera.h | 10 | ||||
-rw-r--r-- | intern/cycles/render/film.cpp | 22 | ||||
-rw-r--r-- | intern/cycles/render/film.h | 1 | ||||
-rw-r--r-- | intern/cycles/render/graph.cpp | 4 | ||||
-rw-r--r-- | intern/cycles/render/integrator.cpp | 4 | ||||
-rw-r--r-- | intern/cycles/render/integrator.h | 1 | ||||
-rw-r--r-- | intern/cycles/render/mesh.cpp | 80 | ||||
-rw-r--r-- | intern/cycles/render/mesh.h | 3 | ||||
-rw-r--r-- | intern/cycles/render/mesh_displace.cpp | 4 | ||||
-rw-r--r-- | intern/cycles/render/nodes.cpp | 8 | ||||
-rw-r--r-- | intern/cycles/render/object.cpp | 83 | ||||
-rw-r--r-- | intern/cycles/render/object.h | 4 | ||||
-rw-r--r-- | intern/cycles/render/scene.cpp | 29 | ||||
-rw-r--r-- | intern/cycles/render/scene.h | 7 | ||||
-rw-r--r-- | intern/cycles/render/shader.cpp | 4 | ||||
-rw-r--r-- | intern/cycles/render/shader.h | 2 | ||||
-rw-r--r-- | intern/cycles/render/svm.cpp | 2 | ||||
-rw-r--r-- | intern/cycles/render/svm.h | 2 |
23 files changed, 308 insertions, 110 deletions
diff --git a/intern/cycles/render/CMakeLists.txt b/intern/cycles/render/CMakeLists.txt index db92cf4ef54..4d4fbfe6814 100644 --- a/intern/cycles/render/CMakeLists.txt +++ b/intern/cycles/render/CMakeLists.txt @@ -16,7 +16,7 @@ set(SRC buffers.cpp camera.cpp film.cpp - # film_response.cpp # XXX, why isn't this in? + # film_response.cpp (code unused) filter.cpp graph.cpp image.cpp @@ -41,7 +41,7 @@ set(SRC_HEADERS buffers.h camera.h film.h - # film_response.h # XXX, why isn't this in? + # film_response.h (code unused) filter.h graph.h image.h diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp index 9e90bf1b625..c1a089cc872 100644 --- a/intern/cycles/render/attribute.cpp +++ b/intern/cycles/render/attribute.cpp @@ -31,7 +31,7 @@ void Attribute::set(ustring name_, TypeDesc type_, Element element_) name = name_; type = type_; element = element_; - std = STD_NONE; + std = ATTR_STD_NONE; /* string and matrix not supported! */ assert(type == TypeDesc::TypeFloat || type == TypeDesc::TypeColor || @@ -81,20 +81,24 @@ bool Attribute::same_storage(TypeDesc a, TypeDesc b) return false; } -ustring Attribute::standard_name(Attribute::Standard std) +ustring Attribute::standard_name(AttributeStandard std) { - if(std == Attribute::STD_VERTEX_NORMAL) + if(std == ATTR_STD_VERTEX_NORMAL) return ustring("N"); - else if(std == Attribute::STD_FACE_NORMAL) + else if(std == ATTR_STD_FACE_NORMAL) return ustring("Ng"); - else if(std == Attribute::STD_UV) + else if(std == ATTR_STD_UV) return ustring("uv"); - else if(std == Attribute::STD_GENERATED) + else if(std == ATTR_STD_GENERATED) return ustring("generated"); - else if(std == Attribute::STD_POSITION_UNDEFORMED) + else if(std == ATTR_STD_POSITION_UNDEFORMED) return ustring("undeformed"); - else if(std == Attribute::STD_POSITION_UNDISPLACED) + else if(std == ATTR_STD_POSITION_UNDISPLACED) return ustring("undisplaced"); + else if(std == ATTR_STD_MOTION_PRE) + return ustring("motion_pre"); + else if(std == ATTR_STD_MOTION_POST) + return ustring("motion_post"); return ustring(); } @@ -164,24 +168,28 @@ void AttributeSet::remove(ustring name) } } -Attribute *AttributeSet::add(Attribute::Standard std, ustring name) +Attribute *AttributeSet::add(AttributeStandard std, ustring name) { Attribute *attr = NULL; if(name == ustring()) name = Attribute::standard_name(std); - if(std == Attribute::STD_VERTEX_NORMAL) + if(std == ATTR_STD_VERTEX_NORMAL) attr = add(name, TypeDesc::TypeNormal, Attribute::VERTEX); - else if(std == Attribute::STD_FACE_NORMAL) + else if(std == ATTR_STD_FACE_NORMAL) attr = add(name, TypeDesc::TypeNormal, Attribute::FACE); - else if(std == Attribute::STD_UV) + else if(std == ATTR_STD_UV) attr = add(name, TypeDesc::TypePoint, Attribute::CORNER); - else if(std == Attribute::STD_GENERATED) + else if(std == ATTR_STD_GENERATED) attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX); - else if(std == Attribute::STD_POSITION_UNDEFORMED) + else if(std == ATTR_STD_POSITION_UNDEFORMED) attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX); - else if(std == Attribute::STD_POSITION_UNDISPLACED) + else if(std == ATTR_STD_POSITION_UNDISPLACED) + attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX); + else if(std == ATTR_STD_MOTION_PRE) + attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX); + else if(std == ATTR_STD_MOTION_POST) attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX); else assert(0); @@ -191,7 +199,7 @@ Attribute *AttributeSet::add(Attribute::Standard std, ustring name) return attr; } -Attribute *AttributeSet::find(Attribute::Standard std) +Attribute *AttributeSet::find(AttributeStandard std) { foreach(Attribute& attr, attributes) if(attr.std == std) @@ -200,7 +208,7 @@ Attribute *AttributeSet::find(Attribute::Standard std) return NULL; } -void AttributeSet::remove(Attribute::Standard std) +void AttributeSet::remove(AttributeStandard std) { Attribute *attr = find(std); @@ -218,7 +226,7 @@ void AttributeSet::remove(Attribute::Standard std) Attribute *AttributeSet::find(AttributeRequest& req) { - if(req.std == Attribute::STD_NONE) + if(req.std == ATTR_STD_NONE) return find(req.name); else return find(req.std); @@ -240,14 +248,14 @@ void AttributeSet::clear() AttributeRequest::AttributeRequest(ustring name_) { name = name_; - std = Attribute::STD_NONE; + std = ATTR_STD_NONE; type = TypeDesc::TypeFloat; element = ATTR_ELEMENT_NONE; offset = 0; } -AttributeRequest::AttributeRequest(Attribute::Standard std_) +AttributeRequest::AttributeRequest(AttributeStandard std_) { name = ustring(); std = std_; @@ -296,7 +304,7 @@ void AttributeRequestSet::add(ustring name) requests.push_back(AttributeRequest(name)); } -void AttributeRequestSet::add(Attribute::Standard std) +void AttributeRequestSet::add(AttributeStandard std) { foreach(AttributeRequest& req, requests) if(req.std == std) @@ -308,7 +316,7 @@ void AttributeRequestSet::add(Attribute::Standard std) void AttributeRequestSet::add(AttributeRequestSet& reqs) { foreach(AttributeRequest& req, reqs.requests) { - if(req.std == Attribute::STD_NONE) + if(req.std == ATTR_STD_NONE) add(req.name); else add(req.std); @@ -324,7 +332,7 @@ bool AttributeRequestSet::find(ustring name) return false; } -bool AttributeRequestSet::find(Attribute::Standard std) +bool AttributeRequestSet::find(AttributeStandard std) { foreach(AttributeRequest& req, requests) if(req.std == std) diff --git a/intern/cycles/render/attribute.h b/intern/cycles/render/attribute.h index 7af4657daa3..707d558fc79 100644 --- a/intern/cycles/render/attribute.h +++ b/intern/cycles/render/attribute.h @@ -47,19 +47,8 @@ public: CORNER }; - enum Standard { - STD_NONE = 0, - STD_VERTEX_NORMAL, - STD_FACE_NORMAL, - STD_UV, - STD_GENERATED, - STD_POSITION_UNDEFORMED, - STD_POSITION_UNDISPLACED, - STD_NUM - }; - ustring name; - Standard std; + AttributeStandard std; TypeDesc type; vector<char> buffer; @@ -82,7 +71,7 @@ public: const float *data_float() const { return (float*)data(); } static bool same_storage(TypeDesc a, TypeDesc b); - static ustring standard_name(Attribute::Standard std); + static ustring standard_name(AttributeStandard std); }; /* Attribute Set @@ -101,9 +90,9 @@ public: Attribute *find(ustring name); void remove(ustring name); - Attribute *add(Attribute::Standard std, ustring name = ustring()); - Attribute *find(Attribute::Standard std); - void remove(Attribute::Standard std); + Attribute *add(AttributeStandard std, ustring name = ustring()); + Attribute *find(AttributeStandard std); + void remove(AttributeStandard std); Attribute *find(AttributeRequest& req); @@ -120,7 +109,7 @@ public: class AttributeRequest { public: ustring name; - Attribute::Standard std; + AttributeStandard std; /* temporary variables used by MeshManager */ TypeDesc type; @@ -128,7 +117,7 @@ public: int offset; AttributeRequest(ustring name_); - AttributeRequest(Attribute::Standard std); + AttributeRequest(AttributeStandard std); }; /* AttributeRequestSet @@ -143,11 +132,11 @@ public: ~AttributeRequestSet(); void add(ustring name); - void add(Attribute::Standard std); + void add(AttributeStandard std); void add(AttributeRequestSet& reqs); bool find(ustring name); - bool find(Attribute::Standard std); + bool find(AttributeStandard std); size_t size(); void clear(); diff --git a/intern/cycles/render/buffers.cpp b/intern/cycles/render/buffers.cpp index bda20a8ab9d..a80851b945a 100644 --- a/intern/cycles/render/buffers.cpp +++ b/intern/cycles/render/buffers.cpp @@ -221,6 +221,28 @@ bool RenderBuffers::get_pass(PassType type, float exposure, int sample, int comp pixels[3] = 1.0f; } } + else if(type == PASS_MOTION) { + /* need to normalize by number of samples accumulated for motion */ + pass_offset = 0; + foreach(Pass& color_pass, params.passes) { + if(color_pass.type == PASS_MOTION_WEIGHT) + break; + pass_offset += color_pass.components; + } + + float *in_weight = (float*)buffer.data_pointer + pass_offset; + + for(int i = 0; i < size; i++, in += pass_stride, in_weight += pass_stride, pixels += 4) { + float4 f = make_float4(in[0], in[1], in[2], in[3]); + float w = in_weight[0]; + float invw = (w > 0.0f)? 1.0f/w: 0.0f; + + pixels[0] = f.x*invw; + pixels[1] = f.y*invw; + pixels[2] = f.z*invw; + pixels[3] = f.w*invw; + } + } else { for(int i = 0; i < size; i++, in += pass_stride, pixels += 4) { float4 f = make_float4(in[0], in[1], in[2], in[3]); diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp index f9290dfc835..e9ca7c3a366 100644 --- a/intern/cycles/render/camera.cpp +++ b/intern/cycles/render/camera.cpp @@ -25,8 +25,7 @@ CCL_NAMESPACE_BEGIN Camera::Camera() { - shutteropen = 0.0f; - shutterclose = 1.0f; + shuttertime = 1.0f; aperturesize = 0.0f; focaldistance = 10.0f; @@ -35,6 +34,10 @@ Camera::Camera() matrix = transform_identity(); + motion.pre = transform_identity(); + motion.post = transform_identity(); + use_motion = false; + type = CAMERA_PERSPECTIVE; fov = M_PI_F/4.0f; @@ -124,7 +127,7 @@ void Camera::update() need_device_update = true; } -void Camera::device_update(Device *device, DeviceScene *dscene) +void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene) { update(); @@ -140,10 +143,28 @@ void Camera::device_update(Device *device, DeviceScene *dscene) kcam->rastertocamera = rastertocamera; kcam->cameratoworld = cameratoworld; kcam->worldtoscreen = transform_inverse(screentoworld); - kcam->worldtoraster = transform_inverse(rastertoworld); + kcam->worldtoraster = worldtoraster; kcam->worldtondc = transform_inverse(ndctoworld); kcam->worldtocamera = transform_inverse(cameratoworld); + /* camera motion */ + Scene::MotionType need_motion = scene->need_motion(); + + if(need_motion == Scene::MOTION_PASS) { + if(use_motion) { + kcam->motion.pre = transform_inverse(motion.pre * rastertocamera); + kcam->motion.post = transform_inverse(motion.post * rastertocamera); + } + else { + kcam->motion.pre = worldtoraster; + kcam->motion.post = worldtoraster; + } + } + else if(need_motion == Scene::MOTION_BLUR) { + /* todo: exact camera position will not be hit this way */ + transform_motion_decompose(&kcam->motion, &motion); + } + /* depth of field */ kcam->aperturesize = aperturesize; kcam->focaldistance = focaldistance; @@ -151,8 +172,7 @@ void Camera::device_update(Device *device, DeviceScene *dscene) kcam->bladesrotation = bladesrotation; /* motion blur */ - kcam->shutteropen = shutteropen; - kcam->shutterclose = shutterclose; + kcam->shuttertime= (need_motion == Scene::MOTION_BLUR)? shuttertime: 0.0f; /* type */ kcam->type = type; @@ -175,8 +195,7 @@ void Camera::device_free(Device *device, DeviceScene *dscene) bool Camera::modified(const Camera& cam) { - return !((shutteropen == cam.shutteropen) && - (shutterclose == cam.shutterclose) && + return !((shuttertime== cam.shuttertime) && (aperturesize == cam.aperturesize) && (blades == cam.blades) && (bladesrotation == cam.bladesrotation) && @@ -192,7 +211,9 @@ bool Camera::modified(const Camera& cam) (right == cam.right) && (bottom == cam.bottom) && (top == cam.top) && - (matrix == cam.matrix)); + (matrix == cam.matrix) && + (motion == cam.motion) && + (use_motion == cam.use_motion)); } void Camera::tag_update() diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h index cfcc5406ee3..935489711c8 100644 --- a/intern/cycles/render/camera.h +++ b/intern/cycles/render/camera.h @@ -28,6 +28,7 @@ CCL_NAMESPACE_BEGIN class Device; class DeviceScene; +class Scene; /* Camera * @@ -37,8 +38,7 @@ class DeviceScene; class Camera { public: /* motion blur */ - float shutteropen; - float shutterclose; + float shuttertime; /* depth of field */ float focaldistance; @@ -61,6 +61,10 @@ public: /* transformation */ Transform matrix; + /* motion */ + MotionTransform motion; + bool use_motion; + /* computed camera parameters */ Transform screentoworld; Transform rastertoworld; @@ -82,7 +86,7 @@ public: void update(); - void device_update(Device *device, DeviceScene *dscene); + void device_update(Device *device, DeviceScene *dscene, Scene *scene); void device_free(Device *device, DeviceScene *dscene); bool modified(const Camera& cam); diff --git a/intern/cycles/render/film.cpp b/intern/cycles/render/film.cpp index cc17f86fcb6..55c89b7b1b2 100644 --- a/intern/cycles/render/film.cpp +++ b/intern/cycles/render/film.cpp @@ -67,6 +67,13 @@ void Pass::add(PassType type, vector<Pass>& passes) case PASS_UV: pass.components = 4; break; + case PASS_MOTION: + pass.components = 4; + pass.divide_type = PASS_MOTION_WEIGHT; + break; + case PASS_MOTION_WEIGHT: + pass.components = 1; + break; case PASS_OBJECT_ID: pass.components = 1; pass.filter = false; @@ -154,6 +161,15 @@ bool Pass::equals(const vector<Pass>& A, const vector<Pass>& B) return true; } +bool Pass::contains(const vector<Pass>& passes, PassType type) +{ + foreach(const Pass& pass, passes) + if(pass.type == type) + return true; + + return false; +} + /* Film */ Film::Film() @@ -196,6 +212,12 @@ void Film::device_update(Device *device, DeviceScene *dscene) case PASS_UV: kfilm->pass_uv = kfilm->pass_stride; break; + case PASS_MOTION: + kfilm->pass_motion = kfilm->pass_stride; + break; + case PASS_MOTION_WEIGHT: + kfilm->pass_motion_weight = kfilm->pass_stride; + break; case PASS_OBJECT_ID: kfilm->pass_object_id = kfilm->pass_stride; break; diff --git a/intern/cycles/render/film.h b/intern/cycles/render/film.h index 8a3dbbf1b08..c7d2ee24388 100644 --- a/intern/cycles/render/film.h +++ b/intern/cycles/render/film.h @@ -40,6 +40,7 @@ public: static void add(PassType type, vector<Pass>& passes); static bool equals(const vector<Pass>& A, const vector<Pass>& B); + static bool contains(const vector<Pass>& passes, PassType); }; class Film { diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp index cc29047f048..d9486de47c9 100644 --- a/intern/cycles/render/graph.cpp +++ b/intern/cycles/render/graph.cpp @@ -120,9 +120,9 @@ void ShaderNode::attributes(AttributeRequestSet *attributes) foreach(ShaderInput *input, inputs) { if(!input->link) { if(input->default_value == ShaderInput::TEXTURE_GENERATED) - attributes->add(Attribute::STD_GENERATED); + attributes->add(ATTR_STD_GENERATED); else if(input->default_value == ShaderInput::TEXTURE_UV) - attributes->add(Attribute::STD_UV); + attributes->add(ATTR_STD_UV); } } } diff --git a/intern/cycles/render/integrator.cpp b/intern/cycles/render/integrator.cpp index c1f066df10c..b26ebfd91e1 100644 --- a/intern/cycles/render/integrator.cpp +++ b/intern/cycles/render/integrator.cpp @@ -45,6 +45,7 @@ Integrator::Integrator() seed = 0; layer_flag = ~0; sample_clamp = 0.0f; + motion_blur = false; need_update = true; } @@ -125,7 +126,8 @@ bool Integrator::modified(const Integrator& integrator) filter_glossy == integrator.filter_glossy && layer_flag == integrator.layer_flag && seed == integrator.seed && - sample_clamp == integrator.sample_clamp); + sample_clamp == integrator.sample_clamp && + motion_blur == integrator.motion_blur); } void Integrator::tag_update(Scene *scene) diff --git a/intern/cycles/render/integrator.h b/intern/cycles/render/integrator.h index 0817fcaa457..afda41a857d 100644 --- a/intern/cycles/render/integrator.h +++ b/intern/cycles/render/integrator.h @@ -47,6 +47,7 @@ public: int layer_flag; float sample_clamp; + bool motion_blur; bool need_update; diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index 0ce16e65621..5d96611ff26 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -113,11 +113,11 @@ void Mesh::compute_bounds() void Mesh::add_face_normals() { /* don't compute if already there */ - if(attributes.find(Attribute::STD_FACE_NORMAL)) + if(attributes.find(ATTR_STD_FACE_NORMAL)) return; /* get attributes */ - Attribute *attr_fN = attributes.add(Attribute::STD_FACE_NORMAL); + Attribute *attr_fN = attributes.add(ATTR_STD_FACE_NORMAL); float3 *fN = attr_fN->data_float3(); /* compute face normals */ @@ -145,12 +145,12 @@ void Mesh::add_face_normals() void Mesh::add_vertex_normals() { /* don't compute if already there */ - if(attributes.find(Attribute::STD_VERTEX_NORMAL)) + if(attributes.find(ATTR_STD_VERTEX_NORMAL)) return; /* get attributes */ - Attribute *attr_fN = attributes.find(Attribute::STD_FACE_NORMAL); - Attribute *attr_vN = attributes.add(Attribute::STD_VERTEX_NORMAL); + Attribute *attr_fN = attributes.find(ATTR_STD_FACE_NORMAL); + Attribute *attr_vN = attributes.add(ATTR_STD_VERTEX_NORMAL); float3 *fN = attr_fN->data_float3(); float3 *vN = attr_vN->data_float3(); @@ -179,8 +179,8 @@ void Mesh::add_vertex_normals() void Mesh::pack_normals(Scene *scene, float4 *normal, float4 *vnormal) { - Attribute *attr_fN = attributes.find(Attribute::STD_FACE_NORMAL); - Attribute *attr_vN = attributes.find(Attribute::STD_VERTEX_NORMAL); + Attribute *attr_fN = attributes.find(ATTR_STD_FACE_NORMAL); + Attribute *attr_vN = attributes.find(ATTR_STD_VERTEX_NORMAL); float3 *fN = attr_fN->data_float3(); float3 *vN = attr_vN->data_float3(); @@ -348,7 +348,7 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vector<Att else osl_attr.type = TypeDesc::TypeColor; - if(req.std != Attribute::STD_NONE) { + if(req.std != ATTR_STD_NONE) { /* if standard attribute, add lookup by std:: name convention */ ustring stdname = ustring(string("std::") + Attribute::standard_name(req.std).c_str()); og->attribute_map[i][stdname] = osl_attr; @@ -371,7 +371,7 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce int attr_map_stride = 0; for(size_t i = 0; i < scene->meshes.size(); i++) - attr_map_stride = max(attr_map_stride, mesh_attributes[i].size()); + attr_map_stride = max(attr_map_stride, mesh_attributes[i].size()+1); if(attr_map_stride == 0) return; @@ -393,13 +393,12 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce AttributeRequestSet& attributes = mesh_attributes[j]; /* set object attributes */ - j = 0; + int index = i*attr_map_stride; foreach(AttributeRequest& req, attributes.requests) { - int index = i*attr_map_stride + j; uint id; - if(req.std == Attribute::STD_NONE) + if(req.std == ATTR_STD_NONE) id = scene->shader_manager->get_attribute_id(req.name); else id = scene->shader_manager->get_attribute_id(req.std); @@ -413,8 +412,14 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce else attr_map[index].w = NODE_ATTR_FLOAT3; - j++; + index++; } + + /* terminator */ + attr_map[index].x = ATTR_STD_NONE; + attr_map[index].y = 0; + attr_map[index].z = 0; + attr_map[index].w = 0; } /* copy to device */ @@ -434,6 +439,8 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene, for(size_t i = 0; i < scene->meshes.size(); i++) { Mesh *mesh = scene->meshes[i]; + scene->need_global_attributes(mesh_attributes[i]); + foreach(uint sindex, mesh->used_shaders) { Shader *shader = scene->shaders[sindex]; mesh_attributes[i].add(shader->attributes); @@ -456,8 +463,8 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene, Attribute *mattr = mesh->attributes.find(req); /* todo: get rid of this exception */ - if(!mattr && req.std == Attribute::STD_GENERATED) { - mattr = mesh->attributes.add(Attribute::STD_GENERATED); + if(!mattr && req.std == ATTR_STD_GENERATED) { + mattr = mesh->attributes.add(ATTR_STD_GENERATED); if(mesh->verts.size()) memcpy(mattr->data_float3(), &mesh->verts[0], sizeof(float3)*mesh->verts.size()); } @@ -489,19 +496,19 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene, float *data = mattr->data_float(); req.offset = attr_float.size(); + attr_float.resize(attr_float.size() + size); + for(size_t k = 0; k < size; k++) - attr_float.push_back(data[k]); + attr_float[req.offset+k] = data[k]; } else { float3 *data = mattr->data_float3(); req.offset = attr_float3.size(); - for(size_t k = 0; k < size; k++) { - float3 f3 = data[k]; - float4 f4 = make_float4(f3.x, f3.y, f3.z, 0.0f); + attr_float3.resize(attr_float3.size() + size); - attr_float3.push_back(f4); - } + for(size_t k = 0; k < size; k++) + attr_float3[req.offset+k] = float3_to_float4(data[k]); } /* mesh vertex/triangle index is global, not per object, so we sneak @@ -712,8 +719,10 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen foreach(Shader *shader, scene->shaders) shader->need_update_attributes = false; + bool motion_blur = scene->need_motion() == Scene::MOTION_BLUR; + foreach(Object *object, scene->objects) - object->compute_bounds(); + object->compute_bounds(motion_blur); if(progress.get_cancel()) return; @@ -759,5 +768,32 @@ void MeshManager::tag_update(Scene *scene) scene->object_manager->need_update = true; } +bool Mesh::need_attribute(Scene *scene, AttributeStandard std) +{ + if(std == ATTR_STD_NONE) + return false; + + if(scene->need_global_attribute(std)) + return true; + + foreach(uint shader, used_shaders) + if(scene->shaders[shader]->attributes.find(std)) + return true; + + return false; +} + +bool Mesh::need_attribute(Scene *scene, ustring name) +{ + if(name == ustring()) + return false; + + foreach(uint shader, used_shaders) + if(scene->shaders[shader]->attributes.find(name)) + return true; + + return false; +} + CCL_NAMESPACE_END diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h index 585203484c7..047a2d2624d 100644 --- a/intern/cycles/render/mesh.h +++ b/intern/cycles/render/mesh.h @@ -98,6 +98,9 @@ public: void pack_verts(float4 *tri_verts, float4 *tri_vindex, size_t vert_offset); void compute_bvh(SceneParams *params, Progress& progress); + bool need_attribute(Scene *scene, AttributeStandard std); + bool need_attribute(Scene *scene, ustring name); + void tag_update(Scene *scene, bool rebuild); }; diff --git a/intern/cycles/render/mesh_displace.cpp b/intern/cycles/render/mesh_displace.cpp index a6f8e3f6be8..dea694a811e 100644 --- a/intern/cycles/render/mesh_displace.cpp +++ b/intern/cycles/render/mesh_displace.cpp @@ -140,11 +140,11 @@ bool MeshManager::displace(Device *device, Scene *scene, Mesh *mesh, Progress& p * normals, as bump mapping in the shader will already alter the * vertex normal, so we start from the non-displaced vertex normals * to avoid applying the perturbation twice. */ - mesh->attributes.remove(Attribute::STD_FACE_NORMAL); + mesh->attributes.remove(ATTR_STD_FACE_NORMAL); mesh->add_face_normals(); if(mesh->displacement_method == Mesh::DISPLACE_TRUE) { - mesh->attributes.remove(Attribute::STD_VERTEX_NORMAL); + mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL); mesh->add_vertex_normals(); } diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index d71438ebae1..7039f5b6412 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -1514,9 +1514,9 @@ TextureCoordinateNode::TextureCoordinateNode() void TextureCoordinateNode::attributes(AttributeRequestSet *attributes) { if(!output("Generated")->links.empty()) - attributes->add(Attribute::STD_GENERATED); + attributes->add(ATTR_STD_GENERATED); if(!output("UV")->links.empty()) - attributes->add(Attribute::STD_UV); + attributes->add(ATTR_STD_UV); ShaderNode::attributes(attributes); } @@ -1546,7 +1546,7 @@ void TextureCoordinateNode::compile(SVMCompiler& compiler) compiler.add_node(geom_node, NODE_GEOM_P, out->stack_offset); } else { - int attr = compiler.attribute(Attribute::STD_GENERATED); + int attr = compiler.attribute(ATTR_STD_GENERATED); compiler.stack_assign(out); compiler.add_node(attr_node, attr, out->stack_offset, NODE_ATTR_FLOAT3); } @@ -1560,7 +1560,7 @@ void TextureCoordinateNode::compile(SVMCompiler& compiler) out = output("UV"); if(!out->links.empty()) { - int attr = compiler.attribute(Attribute::STD_UV); + int attr = compiler.attribute(ATTR_STD_UV); compiler.stack_assign(out); compiler.add_node(attr_node, attr, out->stack_offset, NODE_ATTR_FLOAT3); } diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 28645d856a8..ccc654965f1 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -38,15 +38,37 @@ Object::Object() visibility = ~0; pass_id = 0; bounds = BoundBox::empty; + motion.pre = transform_identity(); + motion.post = transform_identity(); + use_motion = false; } Object::~Object() { } -void Object::compute_bounds() +void Object::compute_bounds(bool motion_blur) { - bounds = mesh->bounds.transformed(&tfm); + BoundBox mbounds = mesh->bounds; + + if(motion_blur && use_motion) { + MotionTransform decomp; + transform_motion_decompose(&decomp, &motion); + + bounds = BoundBox::empty; + + /* todo: this is really terrible. according to pbrt there is a better + * way to find this iteratively, but did not find implementation yet + * or try to implement myself */ + for(float t = 0.0f; t < 1.0f; t += 1.0f/128.0f) { + Transform ttfm; + + transform_motion_interpolate(&ttfm, &decomp, t); + bounds.grow(mbounds.transformed(&ttfm)); + } + } + else + bounds = mbounds.transformed(&tfm); } void Object::apply_transform() @@ -57,8 +79,8 @@ void Object::apply_transform() for(size_t i = 0; i < mesh->verts.size(); i++) mesh->verts[i] = transform_point(&tfm, mesh->verts[i]); - Attribute *attr_fN = mesh->attributes.find(Attribute::STD_FACE_NORMAL); - Attribute *attr_vN = mesh->attributes.find(Attribute::STD_VERTEX_NORMAL); + Attribute *attr_fN = mesh->attributes.find(ATTR_STD_FACE_NORMAL); + Attribute *attr_vN = mesh->attributes.find(ATTR_STD_VERTEX_NORMAL); Transform ntfm = transform_transpose(transform_inverse(tfm)); @@ -83,7 +105,7 @@ void Object::apply_transform() if(bounds.valid()) { mesh->compute_bounds(); - compute_bounds(); + compute_bounds(false); } tfm = transform_identity(); @@ -123,6 +145,7 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene float4 *objects = dscene->objects.resize(OBJECT_SIZE*scene->objects.size()); int i = 0; map<Mesh*, float> surface_area_map; + Scene::MotionType need_motion = scene->need_motion(); foreach(Object *ob, scene->objects) { Mesh *mesh = ob->mesh; @@ -130,7 +153,6 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene /* compute transformations */ Transform tfm = ob->tfm; Transform itfm = transform_inverse(tfm); - Transform ntfm = transform_transpose(itfm); /* compute surface area. for uniform scale we can do avoid the many transform calls and share computation for instances */ @@ -171,10 +193,38 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene /* pack in texture */ int offset = i*OBJECT_SIZE; - memcpy(&objects[offset], &tfm, sizeof(float4)*4); - memcpy(&objects[offset+4], &itfm, sizeof(float4)*4); - memcpy(&objects[offset+8], &ntfm, sizeof(float4)*4); - objects[offset+12] = make_float4(surface_area, pass_id, 0.0f, 0.0f); + memcpy(&objects[offset], &tfm, sizeof(float4)*3); + memcpy(&objects[offset+3], &itfm, sizeof(float4)*3); + objects[offset+6] = make_float4(surface_area, pass_id, 0.0f, 0.0f); + + 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 */ + Transform mtfm_pre = ob->motion.pre; + Transform mtfm_post = ob->motion.post; + + if(!mesh->attributes.find(ATTR_STD_MOTION_PRE)) + mtfm_pre = mtfm_pre * itfm; + if(!mesh->attributes.find(ATTR_STD_MOTION_POST)) + mtfm_post = mtfm_post * itfm; + + memcpy(&objects[offset+8], &mtfm_pre, sizeof(float4)*4); + memcpy(&objects[offset+12], &mtfm_post, sizeof(float4)*4); + } + else if(need_motion == Scene::MOTION_BLUR) { + if(ob->use_motion) { + /* decompose transformations for interpolation */ + MotionTransform decomp; + + transform_motion_decompose(&decomp, &ob->motion); + memcpy(&objects[offset+8], &decomp, sizeof(float4)*8); + } + else { + float4 no_motion = make_float4(FLT_MAX); + memcpy(&objects[offset+8], &no_motion, sizeof(float4)); + } + } i++; @@ -225,6 +275,7 @@ void ObjectManager::apply_static_transforms(Scene *scene, Progress& progress) /* counter mesh users */ map<Mesh*, int> mesh_users; + bool motion_blur = scene->need_motion() == Scene::MOTION_BLUR; foreach(Object *object, scene->objects) { map<Mesh*, int>::iterator it = mesh_users.find(object->mesh); @@ -240,12 +291,14 @@ void ObjectManager::apply_static_transforms(Scene *scene, Progress& progress) /* apply transforms for objects with single user meshes */ foreach(Object *object, scene->objects) { if(mesh_users[object->mesh] == 1) { - if(!object->mesh->transform_applied) { - object->apply_transform(); - object->mesh->transform_applied = true; - } + if(!(motion_blur && object->use_motion)) { + if(!object->mesh->transform_applied) { + object->apply_transform(); + object->mesh->transform_applied = true; - if(progress.get_cancel()) return; + if(progress.get_cancel()) return; + } + } } } } diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h index 14da2cfb35d..e84c4b26767 100644 --- a/intern/cycles/render/object.h +++ b/intern/cycles/render/object.h @@ -44,13 +44,15 @@ public: int pass_id; vector<ParamValue> attributes; uint visibility; + MotionTransform motion; + bool use_motion; Object(); ~Object(); void tag_update(Scene *scene); - void compute_bounds(); + void compute_bounds(bool motion_blur); void apply_transform(); }; diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp index 079f2744e73..b6453339d41 100644 --- a/intern/cycles/render/scene.cpp +++ b/intern/cycles/render/scene.cpp @@ -128,7 +128,7 @@ void Scene::device_update(Device *device_, Progress& progress) if(progress.get_cancel()) return; progress.set_status("Updating Camera"); - camera->device_update(device, &dscene); + camera->device_update(device, &dscene, this); if(progress.get_cancel()) return; @@ -166,6 +166,33 @@ void Scene::device_update(Device *device_, Progress& progress) device->const_copy_to("__data", &dscene.data, sizeof(dscene.data)); } +Scene::MotionType Scene::need_motion() +{ + if(integrator->motion_blur) + return MOTION_BLUR; + else if(Pass::contains(film->passes, PASS_MOTION)) + return MOTION_PASS; + else + return MOTION_NONE; +} + +bool Scene::need_global_attribute(AttributeStandard std) +{ + if(std == ATTR_STD_UV) + return Pass::contains(film->passes, PASS_UV); + if(std == ATTR_STD_MOTION_PRE || ATTR_STD_MOTION_POST) + return need_motion() == MOTION_PASS; + + return false; +} + +void Scene::need_global_attributes(AttributeRequestSet& attributes) +{ + for(int std = ATTR_STD_NONE; std < ATTR_STD_NUM; std++) + if(need_global_attribute((AttributeStandard)std)) + attributes.add((AttributeStandard)std); +} + bool Scene::need_update() { return (need_reset() || film->need_update); diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h index af4301b1cd9..7d4acf369fd 100644 --- a/intern/cycles/render/scene.h +++ b/intern/cycles/render/scene.h @@ -33,6 +33,7 @@ CCL_NAMESPACE_BEGIN +class AttributeRequestSet; class Background; class Camera; class Device; @@ -175,6 +176,12 @@ public: void device_update(Device *device, Progress& progress); + bool need_global_attribute(AttributeStandard std); + void need_global_attributes(AttributeRequestSet& attributes); + + enum MotionType { MOTION_NONE = 0, MOTION_PASS, MOTION_BLUR }; + MotionType need_motion(); + bool need_update(); bool need_reset(); }; diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp index c1f7b3518d2..f50709146ef 100644 --- a/intern/cycles/render/shader.cpp +++ b/intern/cycles/render/shader.cpp @@ -133,12 +133,12 @@ uint ShaderManager::get_attribute_id(ustring name) if(it != unique_attribute_id.end()) return it->second; - uint id = (uint)Attribute::STD_NUM + unique_attribute_id.size(); + uint id = (uint)ATTR_STD_NUM + unique_attribute_id.size(); unique_attribute_id[name] = id; return id; } -uint ShaderManager::get_attribute_id(Attribute::Standard std) +uint ShaderManager::get_attribute_id(AttributeStandard std) { return (uint)std; } diff --git a/intern/cycles/render/shader.h b/intern/cycles/render/shader.h index 35f3cfe27f5..48d517ce21a 100644 --- a/intern/cycles/render/shader.h +++ b/intern/cycles/render/shader.h @@ -103,7 +103,7 @@ public: /* get globally unique id for a type of attribute */ uint get_attribute_id(ustring name); - uint get_attribute_id(Attribute::Standard std); + uint get_attribute_id(AttributeStandard std); /* get shader id for mesh faces */ int get_shader_id(uint shader, Mesh *mesh = NULL, bool smooth = false); diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp index a52e30c6030..1ff3ac20d50 100644 --- a/intern/cycles/render/svm.cpp +++ b/intern/cycles/render/svm.cpp @@ -337,7 +337,7 @@ uint SVMCompiler::attribute(ustring name) return shader_manager->get_attribute_id(name); } -uint SVMCompiler::attribute(Attribute::Standard std) +uint SVMCompiler::attribute(AttributeStandard std) { return shader_manager->get_attribute_id(std); } diff --git a/intern/cycles/render/svm.h b/intern/cycles/render/svm.h index 56c930f6217..0db68f400fc 100644 --- a/intern/cycles/render/svm.h +++ b/intern/cycles/render/svm.h @@ -69,7 +69,7 @@ public: void add_node(const float4& f); void add_array(float4 *f, int num); uint attribute(ustring name); - uint attribute(Attribute::Standard std); + uint attribute(AttributeStandard std); uint encode_uchar4(uint x, uint y = 0, uint z = 0, uint w = 0); uint closure_mix_weight_offset() { return mix_weight_offset; } |