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/CMakeLists.txt4
-rw-r--r--intern/cycles/render/attribute.cpp54
-rw-r--r--intern/cycles/render/attribute.h29
-rw-r--r--intern/cycles/render/buffers.cpp22
-rw-r--r--intern/cycles/render/camera.cpp39
-rw-r--r--intern/cycles/render/camera.h10
-rw-r--r--intern/cycles/render/film.cpp22
-rw-r--r--intern/cycles/render/film.h1
-rw-r--r--intern/cycles/render/graph.cpp4
-rw-r--r--intern/cycles/render/integrator.cpp4
-rw-r--r--intern/cycles/render/integrator.h1
-rw-r--r--intern/cycles/render/mesh.cpp80
-rw-r--r--intern/cycles/render/mesh.h3
-rw-r--r--intern/cycles/render/mesh_displace.cpp4
-rw-r--r--intern/cycles/render/nodes.cpp8
-rw-r--r--intern/cycles/render/object.cpp83
-rw-r--r--intern/cycles/render/object.h4
-rw-r--r--intern/cycles/render/scene.cpp29
-rw-r--r--intern/cycles/render/scene.h7
-rw-r--r--intern/cycles/render/shader.cpp4
-rw-r--r--intern/cycles/render/shader.h2
-rw-r--r--intern/cycles/render/svm.cpp2
-rw-r--r--intern/cycles/render/svm.h2
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; }