blender/intern/cycles/kernel/kernel_displace.h

338 lines
8.5 KiB
C
Raw Normal View History

/*
* Copyright 2011-2013 Blender Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
CCL_NAMESPACE_BEGIN
ccl_device void compute_light_pass(KernelGlobals *kg, ShaderData *sd, PathRadiance *L, RNG rng, bool is_ao)
{
int samples = kernel_data.integrator.aa_samples;
/* initialize master radiance accumulator */
kernel_assert(kernel_data.film.use_light_pass);
path_radiance_init(L, kernel_data.film.use_light_pass);
/* take multiple samples */
for(int sample = 0; sample < samples; sample++) {
PathRadiance L_sample;
PathState state;
Ray ray;
float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
/* init radiance */
path_radiance_init(&L_sample, kernel_data.film.use_light_pass);
/* init path state */
path_state_init(kg, &state, &rng, sample);
state.num_samples = samples;
/* evaluate surface shader */
float rbsdf = path_state_rng_1D(kg, &rng, &state, PRNG_BSDF);
shader_eval_surface(kg, sd, rbsdf, state.flag, SHADER_CONTEXT_MAIN);
/* sample ambient occlusion */
if(is_ao) {
kernel_path_ao(kg, sd, &L_sample, &state, &rng, throughput);
}
/* sample light and BSDF */
else if(kernel_path_integrate_lighting(kg, &rng, sd, &throughput, &state, &L_sample, &ray)) {
#ifdef __LAMP_MIS__
state.ray_t = 0.0f;
#endif
/* compute indirect light */
kernel_path_indirect(kg, &rng, ray, throughput, state.num_samples, state, &L_sample);
/* sum and reset indirect light pass variables for the next samples */
path_radiance_sum_indirect(&L_sample);
path_radiance_reset_indirect(&L_sample);
}
/* accumulate into master L */
path_radiance_accum_sample(L, &L_sample, samples);
}
}
ccl_device bool is_light_pass(ShaderEvalType type)
{
switch (type) {
case SHADER_EVAL_AO:
case SHADER_EVAL_COMBINED:
case SHADER_EVAL_SHADOW:
case SHADER_EVAL_DIFFUSE_DIRECT:
case SHADER_EVAL_GLOSSY_DIRECT:
case SHADER_EVAL_TRANSMISSION_DIRECT:
case SHADER_EVAL_SUBSURFACE_DIRECT:
case SHADER_EVAL_DIFFUSE_INDIRECT:
case SHADER_EVAL_GLOSSY_INDIRECT:
case SHADER_EVAL_TRANSMISSION_INDIRECT:
case SHADER_EVAL_SUBSURFACE_INDIRECT:
return true;
default:
return false;
}
}
ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input, ccl_global float4 *output, ShaderEvalType type, int i)
{
ShaderData sd;
uint4 in = input[i];
float3 out;
int object = in.x;
int prim = in.y;
if(prim == -1)
return;
float u = __uint_as_float(in.z);
float v = __uint_as_float(in.w);
int shader;
float3 P, Ng;
triangle_point_normal(kg, prim, u, v, &P, &Ng, &shader);
/* dummy initilizations copied from SHADER_EVAL_DISPLACE */
float3 I = Ng;
float t = 0.0f;
float time = TIME_INVALID;
int bounce = 0;
int transparent_bounce = 0;
/* light passes */
PathRadiance L;
/* TODO, disable the closures we won't need */
shader_setup_from_sample(kg, &sd, P, Ng, I, shader, object, prim, u, v, t, time, bounce, transparent_bounce);
if(is_light_pass(type)){
RNG rng = cmj_hash(i, 0);
compute_light_pass(kg, &sd, &L, rng, (type == SHADER_EVAL_AO));
}
switch (type) {
/* data passes */
case SHADER_EVAL_NORMAL:
{
/* compression: normal = (2 * color) - 1 */
out = sd.N * 0.5f + make_float3(0.5f, 0.5f, 0.5f);
break;
}
case SHADER_EVAL_UV:
{
out = primitive_uv(kg, &sd);
break;
}
case SHADER_EVAL_DIFFUSE_COLOR:
{
shader_eval_surface(kg, &sd, 0.f, 0, SHADER_CONTEXT_MAIN);
out = shader_bsdf_diffuse(kg, &sd);
break;
}
case SHADER_EVAL_GLOSSY_COLOR:
{
shader_eval_surface(kg, &sd, 0.f, 0, SHADER_CONTEXT_MAIN);
out = shader_bsdf_glossy(kg, &sd);
break;
}
case SHADER_EVAL_TRANSMISSION_COLOR:
{
shader_eval_surface(kg, &sd, 0.f, 0, SHADER_CONTEXT_MAIN);
out = shader_bsdf_transmission(kg, &sd);
break;
}
case SHADER_EVAL_SUBSURFACE_COLOR:
{
#ifdef __SUBSURFACE__
shader_eval_surface(kg, &sd, 0.f, 0, SHADER_CONTEXT_MAIN);
out = shader_bsdf_subsurface(kg, &sd);
#endif
break;
}
case SHADER_EVAL_EMISSION:
{
shader_eval_surface(kg, &sd, 0.f, 0, SHADER_CONTEXT_EMISSION);
out = shader_emissive_eval(kg, &sd);
break;
}
/* light passes */
case SHADER_EVAL_AO:
{
out = L.ao;
break;
}
case SHADER_EVAL_COMBINED:
{
out = path_radiance_clamp_and_sum(kg, &L);
break;
}
case SHADER_EVAL_SHADOW:
{
out = make_float3(L.shadow.x, L.shadow.y, L.shadow.z);
break;
}
case SHADER_EVAL_DIFFUSE_DIRECT:
{
shader_eval_surface(kg, &sd, 0.f, 0, SHADER_CONTEXT_MAIN);
out = safe_divide_color(L.direct_diffuse, shader_bsdf_diffuse(kg, &sd));
break;
}
case SHADER_EVAL_GLOSSY_DIRECT:
{
shader_eval_surface(kg, &sd, 0.f, 0, SHADER_CONTEXT_MAIN);
out = safe_divide_color(L.direct_glossy, shader_bsdf_glossy(kg, &sd));
break;
}
case SHADER_EVAL_TRANSMISSION_DIRECT:
{
shader_eval_surface(kg, &sd, 0.f, 0, SHADER_CONTEXT_MAIN);
out = safe_divide_color(L.direct_transmission, shader_bsdf_transmission(kg, &sd));
break;
}
case SHADER_EVAL_SUBSURFACE_DIRECT:
{
#ifdef __SUBSURFACE__
shader_eval_surface(kg, &sd, 0.f, 0, SHADER_CONTEXT_MAIN);
out = safe_divide_color(L.direct_subsurface, shader_bsdf_subsurface(kg, &sd));
#endif
break;
}
case SHADER_EVAL_DIFFUSE_INDIRECT:
{
shader_eval_surface(kg, &sd, 0.f, 0, SHADER_CONTEXT_MAIN);
out = safe_divide_color(L.indirect_diffuse, shader_bsdf_diffuse(kg, &sd));
break;
}
case SHADER_EVAL_GLOSSY_INDIRECT:
{
shader_eval_surface(kg, &sd, 0.f, 0, SHADER_CONTEXT_MAIN);
out = safe_divide_color(L.indirect_glossy, shader_bsdf_glossy(kg, &sd));
break;
}
case SHADER_EVAL_TRANSMISSION_INDIRECT:
{
shader_eval_surface(kg, &sd, 0.f, 0, SHADER_CONTEXT_MAIN);
out = safe_divide_color(L.indirect_transmission, shader_bsdf_transmission(kg, &sd));
break;
}
case SHADER_EVAL_SUBSURFACE_INDIRECT:
{
#ifdef __SUBSURFACE__
shader_eval_surface(kg, &sd, 0.f, 0, SHADER_CONTEXT_MAIN);
out = safe_divide_color(L.indirect_subsurface, shader_bsdf_subsurface(kg, &sd));
#endif
break;
}
/* extra */
case SHADER_EVAL_ENVIRONMENT:
{
/* setup ray */
Ray ray;
ray.P = make_float3(0.0f, 0.0f, 0.0f);
ray.D = normalize(P);
ray.t = 0.0f;
#ifdef __CAMERA_MOTION__
ray.time = 0.5f;
#endif
#ifdef __RAY_DIFFERENTIALS__
ray.dD = differential3_zero();
ray.dP = differential3_zero();
#endif
/* setup shader data */
shader_setup_from_background(kg, &sd, &ray, 0, 0);
/* evaluate */
int flag = 0; /* we can't know which type of BSDF this is for */
out = shader_eval_background(kg, &sd, flag, SHADER_CONTEXT_MAIN);
break;
}
default:
{
/* no real shader, returning the position of the verts for debugging */
out = normalize(P);
break;
}
}
/* write output */
output[i] = make_float4(out.x, out.y, out.z, 1.0f);
return;
}
ccl_device void kernel_shader_evaluate(KernelGlobals *kg, ccl_global uint4 *input, ccl_global float4 *output, ShaderEvalType type, int i)
{
if(type >= SHADER_EVAL_BAKE) {
kernel_bake_evaluate(kg, input, output, type, i);
return;
}
ShaderData sd;
uint4 in = input[i];
float3 out;
if(type == SHADER_EVAL_DISPLACE) {
/* setup shader data */
int object = in.x;
int prim = in.y;
float u = __uint_as_float(in.z);
float v = __uint_as_float(in.w);
shader_setup_from_displace(kg, &sd, object, prim, u, v);
/* evaluate */
float3 P = sd.P;
shader_eval_displacement(kg, &sd, SHADER_CONTEXT_MAIN);
out = sd.P - P;
}
else { // SHADER_EVAL_BACKGROUND
/* setup ray */
Ray ray;
float u = __uint_as_float(in.x);
float v = __uint_as_float(in.y);
ray.P = make_float3(0.0f, 0.0f, 0.0f);
ray.D = equirectangular_to_direction(u, v);
ray.t = 0.0f;
#ifdef __CAMERA_MOTION__
ray.time = 0.5f;
#endif
#ifdef __RAY_DIFFERENTIALS__
ray.dD = differential3_zero();
ray.dP = differential3_zero();
#endif
/* setup shader data */
shader_setup_from_background(kg, &sd, &ray, 0, 0);
/* evaluate */
int flag = 0; /* we can't know which type of BSDF this is for */
out = shader_eval_background(kg, &sd, flag, SHADER_CONTEXT_MAIN);
}
/* write output */
output[i] = make_float4(out.x, out.y, out.z, 0.0f);
}
CCL_NAMESPACE_END