/* * 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 /* Sky texture */ __device float sky_angle_between(float thetav, float phiv, float theta, float phi) { float cospsi = sinf(thetav)*sinf(theta)*cosf(phi - phiv) + cosf(thetav)*cosf(theta); return safe_acosf(cospsi); } /* * "A Practical Analytic Model for Daylight" * A. J. Preetham, Peter Shirley, Brian Smits */ __device float sky_perez_function(float *lam, float theta, float gamma) { float ctheta = cosf(theta); float cgamma = cosf(gamma); return (1.0f + lam[0]*expf(lam[1]/ctheta)) * (1.0f + lam[2]*expf(lam[3]*gamma) + lam[4]*cgamma*cgamma); } __device float3 sky_radiance_old(KernelGlobals *kg, float3 dir, float sunphi, float suntheta, float radiance_x, float radiance_y, float radiance_z, float *config_x, float *config_y, float *config_z) { /* convert vector to spherical coordinates */ float2 spherical = direction_to_spherical(dir); float theta = spherical.x; float phi = spherical.y; /* angle between sun direction and dir */ float gamma = sky_angle_between(theta, phi, suntheta, sunphi); /* clamp theta to horizon */ theta = min(theta, M_PI_2_F - 0.001f); /* compute xyY color space values */ float x = radiance_y * sky_perez_function(config_y, theta, gamma); float y = radiance_z * sky_perez_function(config_z, theta, gamma); float Y = radiance_x * sky_perez_function(config_x, theta, gamma); /* convert to RGB */ float3 xyz = xyY_to_xyz(x, y, Y); return xyz_to_rgb(xyz.x, xyz.y, xyz.z); } /* * "An Analytic Model for Full Spectral Sky-Dome Radiance" * Lukas Hosek, Alexander Wilkie */ __device float sky_radiance_internal(float *configuration, float theta, float gamma) { float ctheta = cosf(theta); float cgamma = cosf(gamma); float expM = expf(configuration[4] * gamma); float rayM = cgamma * cgamma; float mieM = (1.0f + rayM) / powf((1.0f + configuration[8]*configuration[8] - 2.0f*configuration[8]*cgamma), 1.5f); float zenith = sqrt(ctheta); return (1.0f + configuration[0] * expf(configuration[1] / (ctheta + 0.01f))) * (configuration[2] + configuration[3] * expM + configuration[5] * rayM + configuration[6] * mieM + configuration[7] * zenith); } __device float3 sky_radiance_new(KernelGlobals *kg, float3 dir, float sunphi, float suntheta, float radiance_x, float radiance_y, float radiance_z, float *config_x, float *config_y, float *config_z) { /* convert vector to spherical coordinates */ float2 spherical = direction_to_spherical(dir); float theta = spherical.x; float phi = spherical.y; /* angle between sun direction and dir */ float gamma = sky_angle_between(theta, phi, suntheta, sunphi); /* clamp theta to horizon */ theta = min(theta, M_PI_2_F - 0.001f); /* compute xyz color space values */ float x = sky_radiance_internal(config_x, theta, gamma) * radiance_x; float y = sky_radiance_internal(config_y, theta, gamma) * radiance_y; float z = sky_radiance_internal(config_z, theta, gamma) * radiance_z; /* convert to RGB and adjust strength */ return xyz_to_rgb(x, y, z) * (M_2PI_F/683); } __device void svm_node_tex_sky(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset) { /* Define variables */ float sunphi, suntheta, radiance_x, radiance_y, radiance_z; float config_x[9], config_y[9], config_z[9]; /* Load data */ uint dir_offset = node.y; uint out_offset = node.z; int sky_model = node.w; float4 data = read_node_float(kg, offset); sunphi = data.x; suntheta = data.y; radiance_x = data.z; radiance_y = data.w; data = read_node_float(kg, offset); radiance_z = data.x; config_x[0] = data.y; config_x[1] = data.z; config_x[2] = data.w; data = read_node_float(kg, offset); config_x[3] = data.x; config_x[4] = data.y; config_x[5] = data.z; config_x[6] = data.w; data = read_node_float(kg, offset); config_x[7] = data.x; config_x[8] = data.y; config_y[0] = data.z; config_y[1] = data.w; data = read_node_float(kg, offset); config_y[2] = data.x; config_y[3] = data.y; config_y[4] = data.z; config_y[5] = data.w; data = read_node_float(kg, offset); config_y[6] = data.x; config_y[7] = data.y; config_y[8] = data.z; config_z[0] = data.w; data = read_node_float(kg, offset); config_z[1] = data.x; config_z[2] = data.y; config_z[3] = data.z; config_z[4] = data.w; data = read_node_float(kg, offset); config_z[5] = data.x; config_z[6] = data.y; config_z[7] = data.z; config_z[8] = data.w; float3 dir = stack_load_float3(stack, dir_offset); float3 f; /* Compute Sky */ if(sky_model == 0) f = sky_radiance_old(kg, dir, sunphi, suntheta, radiance_x, radiance_y, radiance_z, config_x, config_y, config_z); else f = sky_radiance_new(kg, dir, sunphi, suntheta, radiance_x, radiance_y, radiance_z, config_x, config_y, config_z); stack_store_float3(stack, out_offset, f); } CCL_NAMESPACE_END