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:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2012-04-30 16:49:26 +0400
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2012-04-30 16:49:26 +0400
commit1d8c79818870b92df46c443d7778438aa67d019c (patch)
treeba3fc305671261e40851d8a230a33ebe19396e95 /intern/cycles/render
parent796dd8a321108df26757fb9df5c2aa6eb42c9633 (diff)
Cycles: support for motion vector and UV passes.
Most of the changes are related to adding support for motion data throughout the code. There's some code for actual camera/object motion blur raytracing but it's unfinished (it badly slows down the raytracing kernel even when the option is turned off), so that code it disabled still. Motion vector export from Blender tries to avoid computing derived meshes when the mesh does not have a deforming modifier, and it also won't store motion vectors for every vertex if only the object or camera is moving.
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; }