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
This commit is contained in:
Brecht Van Lommel
2012-01-25 17:23:52 +00:00
parent 14f475fcca
commit f99343d3b8
36 changed files with 1528 additions and 243 deletions

View File

@@ -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;
}
rgba.x = rgba.x*exposure;
rgba.y = rgba.y*exposure;
rgba.z = rgba.z*exposure;
bool RenderBuffers::get_pass(PassType type, float exposure, int sample, int components, float *pixels)
{
int pass_offset = 0;
/* clamp since alpha might be > 1.0 due to russian roulette */
rgba.w = clamp(rgba.w, 0.0f, 1.0f);
foreach(Pass& pass, params.passes) {
if(pass.type != type) {
pass_offset += pass.components;
continue;
}
out[i] = rgba;
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]);
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 */
pixels[3] = clamp(f.w*scale, 0.0f, 1.0f);
}
}
return true;
}
return out;
return false;
}
/* Display Buffer */