Fix #30551: cycles passes combining did not always give identical result combined
with antialiasing/defocus, now divide out color at the very end instead of for each sample.
This commit is contained in:
@@ -266,17 +266,6 @@ __device_inline void path_radiance_accum_background(PathRadiance *L, float3 thro
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
__device_inline float3 safe_divide_color(float3 a, float3 b)
|
|
||||||
{
|
|
||||||
float x, y, z;
|
|
||||||
|
|
||||||
x = (b.x != 0.0f)? a.x/b.x: 0.0f;
|
|
||||||
y = (b.y != 0.0f)? a.y/b.y: 0.0f;
|
|
||||||
z = (b.z != 0.0f)? a.z/b.z: 0.0f;
|
|
||||||
|
|
||||||
return make_float3(x, y, z);
|
|
||||||
}
|
|
||||||
|
|
||||||
__device_inline float3 path_radiance_sum(PathRadiance *L)
|
__device_inline float3 path_radiance_sum(PathRadiance *L)
|
||||||
{
|
{
|
||||||
#ifdef __PASSES__
|
#ifdef __PASSES__
|
||||||
|
@@ -94,30 +94,18 @@ __device_inline void kernel_write_light_passes(KernelGlobals *kg, __global float
|
|||||||
if(!kernel_data.film.use_light_pass)
|
if(!kernel_data.film.use_light_pass)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(flag & PASS_DIFFUSE_INDIRECT) {
|
if(flag & PASS_DIFFUSE_INDIRECT)
|
||||||
float3 color = safe_divide_color(L->indirect_diffuse, L->color_diffuse);
|
kernel_write_pass_float3(buffer + kernel_data.film.pass_diffuse_indirect, sample, L->indirect_diffuse);
|
||||||
kernel_write_pass_float3(buffer + kernel_data.film.pass_diffuse_indirect, sample, color);
|
if(flag & PASS_GLOSSY_INDIRECT)
|
||||||
}
|
kernel_write_pass_float3(buffer + kernel_data.film.pass_glossy_indirect, sample, L->indirect_glossy);
|
||||||
if(flag & PASS_GLOSSY_INDIRECT) {
|
if(flag & PASS_TRANSMISSION_INDIRECT)
|
||||||
float3 color = safe_divide_color(L->indirect_glossy, L->color_glossy);
|
kernel_write_pass_float3(buffer + kernel_data.film.pass_transmission_indirect, sample, L->indirect_transmission);
|
||||||
kernel_write_pass_float3(buffer + kernel_data.film.pass_glossy_indirect, sample, color);
|
if(flag & PASS_DIFFUSE_DIRECT)
|
||||||
}
|
kernel_write_pass_float3(buffer + kernel_data.film.pass_diffuse_direct, sample, L->direct_diffuse);
|
||||||
if(flag & PASS_TRANSMISSION_INDIRECT) {
|
if(flag & PASS_GLOSSY_DIRECT)
|
||||||
float3 color = safe_divide_color(L->indirect_transmission, L->color_transmission);
|
kernel_write_pass_float3(buffer + kernel_data.film.pass_glossy_direct, sample, L->direct_glossy);
|
||||||
kernel_write_pass_float3(buffer + kernel_data.film.pass_transmission_indirect, sample, color);
|
if(flag & PASS_TRANSMISSION_DIRECT)
|
||||||
}
|
kernel_write_pass_float3(buffer + kernel_data.film.pass_transmission_direct, sample, L->direct_transmission);
|
||||||
if(flag & PASS_DIFFUSE_DIRECT) {
|
|
||||||
float3 color = safe_divide_color(L->direct_diffuse, L->color_diffuse);
|
|
||||||
kernel_write_pass_float3(buffer + kernel_data.film.pass_diffuse_direct, sample, color);
|
|
||||||
}
|
|
||||||
if(flag & PASS_GLOSSY_DIRECT) {
|
|
||||||
float3 color = safe_divide_color(L->direct_glossy, L->color_glossy);
|
|
||||||
kernel_write_pass_float3(buffer + kernel_data.film.pass_glossy_direct, sample, color);
|
|
||||||
}
|
|
||||||
if(flag & PASS_TRANSMISSION_DIRECT) {
|
|
||||||
float3 color = safe_divide_color(L->direct_transmission, L->color_transmission);
|
|
||||||
kernel_write_pass_float3(buffer + kernel_data.film.pass_transmission_direct, sample, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(flag & PASS_EMISSION)
|
if(flag & PASS_EMISSION)
|
||||||
kernel_write_pass_float3(buffer + kernel_data.film.pass_emission, sample, L->emission);
|
kernel_write_pass_float3(buffer + kernel_data.film.pass_emission, sample, L->emission);
|
||||||
|
@@ -173,13 +173,37 @@ bool RenderBuffers::get_pass(PassType type, float exposure, int sample, int comp
|
|||||||
else if(components == 3) {
|
else if(components == 3) {
|
||||||
assert(pass.components == 4);
|
assert(pass.components == 4);
|
||||||
|
|
||||||
/* RGB/vector */
|
if(pass.divide_type != PASS_NONE) {
|
||||||
for(int i = 0; i < size; i++, in += pass_stride, pixels += 3) {
|
/* RGB lighting passes that need to divide out color */
|
||||||
float3 f = make_float3(in[0], in[1], in[2]);
|
pass_offset = 0;
|
||||||
|
foreach(Pass& color_pass, params.passes) {
|
||||||
|
if(color_pass.type == pass.divide_type)
|
||||||
|
break;
|
||||||
|
pass_offset += color_pass.components;
|
||||||
|
}
|
||||||
|
|
||||||
pixels[0] = f.x*scale_exposure;
|
float *in_divide = (float*)buffer.data_pointer + pass_offset;
|
||||||
pixels[1] = f.y*scale_exposure;
|
|
||||||
pixels[2] = f.z*scale_exposure;
|
for(int i = 0; i < size; i++, in += pass_stride, in_divide += pass_stride, pixels += 3) {
|
||||||
|
float3 f = make_float3(in[0], in[1], in[2]);
|
||||||
|
float3 f_divide = make_float3(in_divide[0], in_divide[1], in_divide[2]);
|
||||||
|
|
||||||
|
f = safe_divide_color(f*exposure, f_divide);
|
||||||
|
|
||||||
|
pixels[0] = f.x;
|
||||||
|
pixels[1] = f.y;
|
||||||
|
pixels[2] = f.z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* 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) {
|
else if(components == 4) {
|
||||||
|
@@ -38,11 +38,16 @@ static bool compare_pass_order(const Pass& a, const Pass& b)
|
|||||||
|
|
||||||
void Pass::add(PassType type, vector<Pass>& passes)
|
void Pass::add(PassType type, vector<Pass>& passes)
|
||||||
{
|
{
|
||||||
|
foreach(Pass& existing_pass, passes)
|
||||||
|
if(existing_pass.type == type)
|
||||||
|
return;
|
||||||
|
|
||||||
Pass pass;
|
Pass pass;
|
||||||
|
|
||||||
pass.type = type;
|
pass.type = type;
|
||||||
pass.filter = true;
|
pass.filter = true;
|
||||||
pass.exposure = false;
|
pass.exposure = false;
|
||||||
|
pass.divide_type = PASS_NONE;
|
||||||
|
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case PASS_NONE:
|
case PASS_NONE:
|
||||||
@@ -82,26 +87,32 @@ void Pass::add(PassType type, vector<Pass>& passes)
|
|||||||
case PASS_DIFFUSE_INDIRECT:
|
case PASS_DIFFUSE_INDIRECT:
|
||||||
pass.components = 4;
|
pass.components = 4;
|
||||||
pass.exposure = true;
|
pass.exposure = true;
|
||||||
|
pass.divide_type = PASS_DIFFUSE_COLOR;
|
||||||
break;
|
break;
|
||||||
case PASS_GLOSSY_INDIRECT:
|
case PASS_GLOSSY_INDIRECT:
|
||||||
pass.components = 4;
|
pass.components = 4;
|
||||||
pass.exposure = true;
|
pass.exposure = true;
|
||||||
|
pass.divide_type = PASS_GLOSSY_COLOR;
|
||||||
break;
|
break;
|
||||||
case PASS_TRANSMISSION_INDIRECT:
|
case PASS_TRANSMISSION_INDIRECT:
|
||||||
pass.components = 4;
|
pass.components = 4;
|
||||||
pass.exposure = true;
|
pass.exposure = true;
|
||||||
|
pass.divide_type = PASS_TRANSMISSION_COLOR;
|
||||||
break;
|
break;
|
||||||
case PASS_DIFFUSE_DIRECT:
|
case PASS_DIFFUSE_DIRECT:
|
||||||
pass.components = 4;
|
pass.components = 4;
|
||||||
pass.exposure = true;
|
pass.exposure = true;
|
||||||
|
pass.divide_type = PASS_DIFFUSE_COLOR;
|
||||||
break;
|
break;
|
||||||
case PASS_GLOSSY_DIRECT:
|
case PASS_GLOSSY_DIRECT:
|
||||||
pass.components = 4;
|
pass.components = 4;
|
||||||
pass.exposure = true;
|
pass.exposure = true;
|
||||||
|
pass.divide_type = PASS_GLOSSY_COLOR;
|
||||||
break;
|
break;
|
||||||
case PASS_TRANSMISSION_DIRECT:
|
case PASS_TRANSMISSION_DIRECT:
|
||||||
pass.components = 4;
|
pass.components = 4;
|
||||||
pass.exposure = true;
|
pass.exposure = true;
|
||||||
|
pass.divide_type = PASS_TRANSMISSION_COLOR;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PASS_EMISSION:
|
case PASS_EMISSION:
|
||||||
@@ -127,6 +138,9 @@ void Pass::add(PassType type, vector<Pass>& passes)
|
|||||||
/* order from by components, to ensure alignment so passes with size 4
|
/* order from by components, to ensure alignment so passes with size 4
|
||||||
come first and then passes with size 1 */
|
come first and then passes with size 1 */
|
||||||
sort(passes.begin(), passes.end(), compare_pass_order);
|
sort(passes.begin(), passes.end(), compare_pass_order);
|
||||||
|
|
||||||
|
if(pass.divide_type != PASS_NONE)
|
||||||
|
Pass::add(pass.divide_type, passes);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Pass::equals(const vector<Pass>& A, const vector<Pass>& B)
|
bool Pass::equals(const vector<Pass>& A, const vector<Pass>& B)
|
||||||
|
@@ -36,6 +36,7 @@ public:
|
|||||||
int components;
|
int components;
|
||||||
bool filter;
|
bool filter;
|
||||||
bool exposure;
|
bool exposure;
|
||||||
|
PassType divide_type;
|
||||||
|
|
||||||
static void add(PassType type, vector<Pass>& passes);
|
static void add(PassType type, vector<Pass>& passes);
|
||||||
static bool equals(const vector<Pass>& A, const vector<Pass>& B);
|
static bool equals(const vector<Pass>& A, const vector<Pass>& B);
|
||||||
|
@@ -799,6 +799,19 @@ __device_inline void make_orthonormals(const float3 N, float3 *a, float3 *b)
|
|||||||
*b = cross(N, *a);
|
*b = cross(N, *a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Color division */
|
||||||
|
|
||||||
|
__device_inline float3 safe_divide_color(float3 a, float3 b)
|
||||||
|
{
|
||||||
|
float x, y, z;
|
||||||
|
|
||||||
|
x = (b.x != 0.0f)? a.x/b.x: 0.0f;
|
||||||
|
y = (b.y != 0.0f)? a.y/b.y: 0.0f;
|
||||||
|
z = (b.z != 0.0f)? a.z/b.z: 0.0f;
|
||||||
|
|
||||||
|
return make_float3(x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
CCL_NAMESPACE_END
|
CCL_NAMESPACE_END
|
||||||
|
|
||||||
#endif /* __UTIL_MATH_H__ */
|
#endif /* __UTIL_MATH_H__ */
|
||||||
|
Reference in New Issue
Block a user