diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2012-01-25 21:23:52 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2012-01-25 21:23:52 +0400 |
commit | f99343d3b8676543e2bd6acd6ee2274c21b1b388 (patch) | |
tree | fd40cd33691a783f82cf877e774d1b3a64d91ed3 /intern/cycles/render | |
parent | 14f475fccad7158098ddecc285c617f990b2f8b5 (diff) |
Cycles: Render Passes
Currently supported passes:
* Combined, Z, Normal, Object Index, Material Index, Emission, Environment,
Diffuse/Glossy/Transmission x Direct/Indirect/Color
Not supported yet:
* UV, Vector, Mist
Only enabled for CPU devices at the moment, will do GPU tweaks tommorrow,
also for environment importance sampling.
Documentation:
http://wiki.blender.org/index.php/Doc:2.6/Manual/Render/Cycles/Passes
Diffstat (limited to 'intern/cycles/render')
-rw-r--r-- | intern/cycles/render/buffers.cpp | 120 | ||||
-rw-r--r-- | intern/cycles/render/buffers.h | 46 | ||||
-rw-r--r-- | intern/cycles/render/film.cpp | 179 | ||||
-rw-r--r-- | intern/cycles/render/film.h | 15 | ||||
-rw-r--r-- | intern/cycles/render/object.cpp | 4 | ||||
-rw-r--r-- | intern/cycles/render/object.h | 1 | ||||
-rw-r--r-- | intern/cycles/render/shader.cpp | 5 | ||||
-rw-r--r-- | intern/cycles/render/shader.h | 1 |
8 files changed, 324 insertions, 47 deletions
diff --git a/intern/cycles/render/buffers.cpp b/intern/cycles/render/buffers.cpp index a6bbbc91901..08dda944111 100644 --- a/intern/cycles/render/buffers.cpp +++ b/intern/cycles/render/buffers.cpp @@ -22,6 +22,7 @@ #include "device.h" #include "util_debug.h" +#include "util_foreach.h" #include "util_hash.h" #include "util_image.h" #include "util_math.h" @@ -31,6 +32,48 @@ CCL_NAMESPACE_BEGIN +/* Buffer Params */ + +BufferParams::BufferParams() +{ + width = 0; + height = 0; + + full_x = 0; + full_y = 0; + full_width = 0; + full_height = 0; + + Pass::add(PASS_COMBINED, passes); +} + +void BufferParams::get_offset_stride(int& offset, int& stride) +{ + offset = -(full_x + full_y*width); + stride = width; +} + +bool BufferParams::modified(const BufferParams& params) +{ + return !(full_x == params.full_x + && full_y == params.full_y + && width == params.width + && height == params.height + && full_width == params.full_width + && full_height == params.full_height + && Pass::equals(passes, params.passes)); +} + +int BufferParams::get_passes_size() +{ + int size = 0; + + foreach(Pass& pass, passes) + size += pass.components; + + return size; +} + /* Render Buffers */ RenderBuffers::RenderBuffers(Device *device_) @@ -64,7 +107,7 @@ void RenderBuffers::reset(Device *device, BufferParams& params_) device_free(); /* allocate buffer */ - buffer.resize(params.width, params.height); + buffer.resize(params.width*params.height*params.get_passes_size()); device->mem_alloc(buffer, MEM_READ_WRITE); device->mem_zero(buffer); @@ -82,31 +125,76 @@ void RenderBuffers::reset(Device *device, BufferParams& params_) device->mem_copy_to(rng_state); } -float4 *RenderBuffers::copy_from_device(float exposure, int sample) +bool RenderBuffers::copy_from_device() { if(!buffer.device_pointer) - return NULL; + return false; device->mem_copy_from(buffer, 0, params.width, params.height, sizeof(float4)); - float4 *out = new float4[params.width*params.height]; - float4 *in = (float4*)buffer.data_pointer; - float scale = 1.0f/(float)sample; - - for(int i = params.width*params.height - 1; i >= 0; i--) { - float4 rgba = in[i]*scale; + return true; +} + +bool RenderBuffers::get_pass(PassType type, float exposure, int sample, int components, float *pixels) +{ + int pass_offset = 0; + + foreach(Pass& pass, params.passes) { + if(pass.type != type) { + pass_offset += pass.components; + continue; + } + + float *in = (float*)buffer.data_pointer + pass_offset; + int pass_stride = params.get_passes_size(); + + float scale = (pass.filter)? 1.0f/(float)sample: 1.0f; + float scale_exposure = (pass.exposure)? scale*exposure: scale; + + int size = params.width*params.height; + + if(components == 1) { + assert(pass.components == components); + + /* scalar */ + for(int i = 0; i < size; i++, in += pass_stride, pixels++) { + float f = *in; + + pixels[0] = f*scale_exposure; + } + } + else if(components == 3) { + assert(pass.components == 4); + + /* RGB/vector */ + for(int i = 0; i < size; i++, in += pass_stride, pixels += 3) { + float3 f = make_float3(in[0], in[1], in[2]); + + pixels[0] = f.x*scale_exposure; + pixels[1] = f.y*scale_exposure; + pixels[2] = f.z*scale_exposure; + } + } + else if(components == 4) { + assert(pass.components == components); + + /* RGBA */ + for(int i = 0; i < size; i++, in += pass_stride, pixels += 4) { + float4 f = make_float4(in[0], in[1], in[2], in[3]); - rgba.x = rgba.x*exposure; - rgba.y = rgba.y*exposure; - rgba.z = rgba.z*exposure; + pixels[0] = f.x*scale_exposure; + pixels[1] = f.y*scale_exposure; + pixels[2] = f.z*scale_exposure; - /* clamp since alpha might be > 1.0 due to russian roulette */ - rgba.w = clamp(rgba.w, 0.0f, 1.0f); + /* clamp since alpha might be > 1.0 due to russian roulette */ + pixels[3] = clamp(f.w*scale, 0.0f, 1.0f); + } + } - out[i] = rgba; + return true; } - return out; + return false; } /* Display Buffer */ diff --git a/intern/cycles/render/buffers.h b/intern/cycles/render/buffers.h index f4a9b37c09b..3062e5ae3e4 100644 --- a/intern/cycles/render/buffers.h +++ b/intern/cycles/render/buffers.h @@ -21,6 +21,10 @@ #include "device_memory.h" +#include "film.h" + +#include "kernel_types.h" + #include "util_string.h" #include "util_thread.h" #include "util_types.h" @@ -45,32 +49,16 @@ public: int full_width; int full_height; - BufferParams() - { - width = 0; - height = 0; - - full_x = 0; - full_y = 0; - full_width = 0; - full_height = 0; - } - - void get_offset_stride(int& offset, int& stride) - { - offset = -(full_x + full_y*width); - stride = width; - } - - bool modified(const BufferParams& params) - { - return !(full_x == params.full_x - && full_y == params.full_y - && width == params.width - && height == params.height - && full_width == params.full_width - && full_height == params.full_height); - } + /* passes */ + vector<Pass> passes; + + /* functions */ + BufferParams(); + + void get_offset_stride(int& offset, int& stride); + bool modified(const BufferParams& params); + void add_pass(PassType type); + int get_passes_size(); }; /* Render Buffers */ @@ -80,7 +68,7 @@ public: /* buffer parameters */ BufferParams params; /* float buffer */ - device_vector<float4> buffer; + device_vector<float> buffer; /* random number generator state */ device_vector<uint> rng_state; /* mutex, must be locked manually by callers */ @@ -90,7 +78,9 @@ public: ~RenderBuffers(); void reset(Device *device, BufferParams& params); - float4 *copy_from_device(float exposure, int sample); + + bool copy_from_device(); + bool get_pass(PassType type, float exposure, int sample, int components, float *pixels); protected: void device_free(); diff --git a/intern/cycles/render/film.cpp b/intern/cycles/render/film.cpp index 0ae2866f182..bc51384b873 100644 --- a/intern/cycles/render/film.cpp +++ b/intern/cycles/render/film.cpp @@ -21,11 +21,111 @@ #include "film.h" #include "scene.h" +#include "util_foreach.h" + CCL_NAMESPACE_BEGIN +/* Pass */ + +void Pass::add(PassType type, vector<Pass>& passes) +{ + Pass pass; + + pass.type = type; + pass.filter = true; + pass.exposure = false; + + switch(type) { + case PASS_NONE: + pass.components = 0; + break; + case PASS_COMBINED: + pass.components = 4; + pass.exposure = true; + break; + case PASS_DEPTH: + pass.components = 1; + pass.filter = false; + break; + case PASS_NORMAL: + pass.components = 4; + break; + case PASS_UV: + pass.components = 4; + break; + case PASS_OBJECT_ID: + pass.components = 1; + pass.filter = false; + break; + case PASS_MATERIAL_ID: + pass.components = 1; + pass.filter = false; + break; + case PASS_DIFFUSE_COLOR: + pass.components = 4; + break; + case PASS_GLOSSY_COLOR: + pass.components = 4; + break; + case PASS_TRANSMISSION_COLOR: + pass.components = 4; + break; + case PASS_DIFFUSE_INDIRECT: + pass.components = 4; + pass.exposure = true; + break; + case PASS_GLOSSY_INDIRECT: + pass.components = 4; + pass.exposure = true; + break; + case PASS_TRANSMISSION_INDIRECT: + pass.components = 4; + pass.exposure = true; + break; + case PASS_DIFFUSE_DIRECT: + pass.components = 4; + pass.exposure = true; + break; + case PASS_GLOSSY_DIRECT: + pass.components = 4; + pass.exposure = true; + break; + case PASS_TRANSMISSION_DIRECT: + pass.components = 4; + pass.exposure = true; + break; + + case PASS_EMISSION: + pass.components = 4; + pass.exposure = true; + break; + case PASS_BACKGROUND: + pass.components = 4; + pass.exposure = true; + break; + } + + passes.push_back(pass); +} + +bool Pass::equals(const vector<Pass>& A, const vector<Pass>& B) +{ + if(A.size() != B.size()) + return false; + + for(int i = 0; i < A.size(); i++) + if(A[i].type != B[i].type) + return false; + + return true; +} + +/* Film */ + Film::Film() { exposure = 0.8f; + Pass::add(PASS_COMBINED, passes); need_update = true; } @@ -42,6 +142,82 @@ void Film::device_update(Device *device, DeviceScene *dscene) /* update __data */ kfilm->exposure = exposure; + kfilm->pass_flag = 0; + kfilm->pass_stride = 0; + kfilm->use_light_pass = 0; + + foreach(Pass& pass, passes) { + kfilm->pass_flag |= pass.type; + + switch(pass.type) { + case PASS_COMBINED: + kfilm->pass_combined = kfilm->pass_stride; + break; + case PASS_DEPTH: + kfilm->pass_depth = kfilm->pass_stride; + break; + case PASS_NORMAL: + kfilm->pass_normal = kfilm->pass_stride; + break; + case PASS_UV: + kfilm->pass_uv = kfilm->pass_stride; + break; + case PASS_OBJECT_ID: + kfilm->pass_object_id = kfilm->pass_stride; + break; + case PASS_MATERIAL_ID: + kfilm->pass_material_id = kfilm->pass_stride; + break; + case PASS_DIFFUSE_COLOR: + kfilm->pass_diffuse_color = kfilm->pass_stride; + kfilm->use_light_pass = 1; + break; + case PASS_GLOSSY_COLOR: + kfilm->pass_glossy_color = kfilm->pass_stride; + kfilm->use_light_pass = 1; + break; + case PASS_TRANSMISSION_COLOR: + kfilm->pass_transmission_color = kfilm->pass_stride; + kfilm->use_light_pass = 1; + break; + case PASS_DIFFUSE_INDIRECT: + kfilm->pass_diffuse_indirect = kfilm->pass_stride; + kfilm->use_light_pass = 1; + break; + case PASS_GLOSSY_INDIRECT: + kfilm->pass_glossy_indirect = kfilm->pass_stride; + kfilm->use_light_pass = 1; + break; + case PASS_TRANSMISSION_INDIRECT: + kfilm->pass_transmission_indirect = kfilm->pass_stride; + kfilm->use_light_pass = 1; + break; + case PASS_DIFFUSE_DIRECT: + kfilm->pass_diffuse_direct = kfilm->pass_stride; + kfilm->use_light_pass = 1; + break; + case PASS_GLOSSY_DIRECT: + kfilm->pass_glossy_direct = kfilm->pass_stride; + kfilm->use_light_pass = 1; + break; + case PASS_TRANSMISSION_DIRECT: + kfilm->pass_transmission_direct = kfilm->pass_stride; + kfilm->use_light_pass = 1; + break; + + case PASS_EMISSION: + kfilm->pass_emission = kfilm->pass_stride; + kfilm->use_light_pass = 1; + break; + case PASS_BACKGROUND: + kfilm->pass_background = kfilm->pass_stride; + kfilm->use_light_pass = 1; + case PASS_NONE: + break; + } + + kfilm->pass_stride += pass.components; + } need_update = false; } @@ -52,7 +228,8 @@ void Film::device_free(Device *device, DeviceScene *dscene) bool Film::modified(const Film& film) { - return !(exposure == film.exposure); + return !(exposure == film.exposure + && Pass::equals(passes, film.passes)); } void Film::tag_update(Scene *scene) diff --git a/intern/cycles/render/film.h b/intern/cycles/render/film.h index df24fad3725..511ad316460 100644 --- a/intern/cycles/render/film.h +++ b/intern/cycles/render/film.h @@ -20,6 +20,9 @@ #define __FILM_H__ #include "util_string.h" +#include "util_vector.h" + +#include "kernel_types.h" CCL_NAMESPACE_BEGIN @@ -27,9 +30,21 @@ class Device; class DeviceScene; class Scene; +class Pass { +public: + PassType type; + int components; + bool filter; + bool exposure; + + static void add(PassType type, vector<Pass>& passes); + static bool equals(const vector<Pass>& A, const vector<Pass>& B); +}; + class Film { public: float exposure; + vector<Pass> passes; bool need_update; Film(); diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 3a9f0add735..f83c85c632d 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -36,6 +36,7 @@ Object::Object() mesh = NULL; tfm = transform_identity(); visibility = ~0; + pass_id = 0; } Object::~Object() @@ -135,6 +136,7 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene /* todo: correct for displacement, and move to a better place */ float uniform_scale; float surface_area = 0.0f; + float pass_id = ob->pass_id; if(transform_uniform_scale(tfm, uniform_scale)) { map<Mesh*, float>::iterator it = surface_area_map.find(mesh); @@ -171,7 +173,7 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene 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, 0.0f, 0.0f, 0.0f); + objects[offset+12] = make_float4(surface_area, pass_id, 0.0f, 0.0f); i++; diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h index 7fe83cf7d91..14da2cfb35d 100644 --- a/intern/cycles/render/object.h +++ b/intern/cycles/render/object.h @@ -41,6 +41,7 @@ public: Transform tfm; BoundBox bounds; ustring name; + int pass_id; vector<ParamValue> attributes; uint visibility; diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp index 6e827ec94bb..12968a79ab2 100644 --- a/intern/cycles/render/shader.cpp +++ b/intern/cycles/render/shader.cpp @@ -35,6 +35,7 @@ CCL_NAMESPACE_BEGIN Shader::Shader() { name = ""; + pass_id = 0; graph = NULL; graph_bump = NULL; @@ -167,7 +168,7 @@ void ShaderManager::device_update_common(Device *device, DeviceScene *dscene, Sc if(scene->shaders.size() == 0) return; - uint shader_flag_size = scene->shaders.size()*2; + uint shader_flag_size = scene->shaders.size()*4; uint *shader_flag = dscene->shader_flag.resize(shader_flag_size); uint i = 0; @@ -184,7 +185,9 @@ void ShaderManager::device_update_common(Device *device, DeviceScene *dscene, Sc flag |= SD_HOMOGENEOUS_VOLUME; shader_flag[i++] = flag; + shader_flag[i++] = shader->pass_id; shader_flag[i++] = flag; + shader_flag[i++] = shader->pass_id; } device->tex_alloc("__shader_flag", dscene->shader_flag); diff --git a/intern/cycles/render/shader.h b/intern/cycles/render/shader.h index 45efa123ef6..35f3cfe27f5 100644 --- a/intern/cycles/render/shader.h +++ b/intern/cycles/render/shader.h @@ -47,6 +47,7 @@ class Shader { public: /* name */ string name; + int pass_id; /* shader graph */ ShaderGraph *graph; |