Cleanup: Cycles: Consolidate coordinate system conversions

- Deduplicate Fisheye projection code
- Replace spherical/cartesian conversions with shared helpers
- Replace transforms from/to local coordinate systems with shared helpers

The main type of repeated transform that's not covered here is `to/from_coords`, but with separate values for xy and z (e.g. BSDFs that already computed `dot(wi, N)` earlier, so they only need `dot(wi, X)` and `dot(wi, Y)` later). Could also be replaced, but it would feel weirdly specific for a helper function.

Pull Request: https://projects.blender.org/blender/blender/pulls/125999
This commit is contained in:
Lukas Stockner
2024-10-07 02:18:49 +02:00
committed by Lukas Stockner
parent 6d5d3ce975
commit b8d0bef3b4
21 changed files with 125 additions and 127 deletions

View File

@@ -12,22 +12,6 @@
CCL_NAMESPACE_BEGIN
/* Spherical coordinates <-> Cartesian direction. */
ccl_device float2 direction_to_spherical(float3 dir)
{
float theta = safe_acosf(dir.z);
float phi = atan2f(dir.x, dir.y);
return make_float2(theta, phi);
}
ccl_device float3 spherical_to_direction(float theta, float phi)
{
float sin_theta = sinf(theta);
return make_float3(sin_theta * sinf(phi), sin_theta * cosf(phi), cosf(theta));
}
/* Equirectangular coordinates <-> Cartesian direction */
ccl_device float2 direction_to_equirectangular_range(float3 dir, float4 range)
@@ -45,8 +29,7 @@ ccl_device float3 equirectangular_range_to_direction(float u, float v, float4 ra
{
float phi = range.x * u + range.y;
float theta = range.z * v + range.w;
float sin_theta = sinf(theta);
return make_float3(sin_theta * cosf(phi), sin_theta * sinf(phi), cosf(theta));
return spherical_to_direction(theta, phi);
}
ccl_device float2 direction_to_equirectangular(float3 dir)
@@ -77,14 +60,24 @@ ccl_device float3 central_cylindrical_to_direction(float u, float v, float4 rang
/* Fisheye <-> Cartesian direction */
ccl_device float2 direction_to_fisheye(float3 dir, float fov)
ccl_device_inline float3 fisheye_to_direction(float theta, float u, float v, float r)
{
float phi = safe_acosf(safe_divide(u, r));
if (v < 0.0f) {
phi = -phi;
}
return make_float3(cosf(theta), -cosf(phi) * sinf(theta), sinf(phi) * sinf(theta));
}
ccl_device float2 direction_to_fisheye_equidistant(float3 dir, float fov)
{
const float r = atan2f(len(make_float2(dir.y, dir.z)), dir.x) / fov;
const float2 uv = r * safe_normalize(make_float2(dir.y, dir.z));
return make_float2(0.5f - uv.x, uv.y + 0.5f);
}
ccl_device float3 fisheye_to_direction(float u, float v, float fov)
ccl_device float3 fisheye_equidistant_to_direction(float u, float v, float fov)
{
u = (u - 0.5f) * 2.0f;
v = (v - 0.5f) * 2.0f;
@@ -94,13 +87,9 @@ ccl_device float3 fisheye_to_direction(float u, float v, float fov)
if (r > 1.0f)
return zero_float3();
float phi = safe_acosf((r != 0.0f) ? u / r : 0.0f);
float theta = r * fov * 0.5f;
if (v < 0.0f)
phi = -phi;
return make_float3(cosf(theta), -cosf(phi) * sinf(theta), sinf(phi) * sinf(theta));
return fisheye_to_direction(theta, u, v, r);
}
ccl_device float2 direction_to_fisheye_equisolid(float3 dir, float lens, float width, float height)
@@ -124,13 +113,9 @@ fisheye_equisolid_to_direction(float u, float v, float lens, float fov, float wi
if (r > rmax)
return zero_float3();
float phi = safe_acosf((r != 0.0f) ? u / r : 0.0f);
float theta = 2.0f * asinf(r / (2.0f * lens));
if (v < 0.0f)
phi = -phi;
return make_float3(cosf(theta), -cosf(phi) * sinf(theta), sinf(phi) * sinf(theta));
return fisheye_to_direction(theta, u, v, r);
}
ccl_device_inline float3 fisheye_lens_polynomial_to_direction(
@@ -147,12 +132,7 @@ ccl_device_inline float3 fisheye_lens_polynomial_to_direction(
if (fabsf(theta) > 0.5f * fov)
return zero_float3();
float phi = safe_acosf((r != 0.0f) ? u / r : 0.0f);
if (v < 0.0f)
phi = -phi;
return make_float3(cosf(theta), -cosf(phi) * sinf(theta), sinf(phi) * sinf(theta));
return fisheye_to_direction(theta, u, v, r);
}
ccl_device float2 direction_to_fisheye_lens_polynomial(
@@ -258,7 +238,7 @@ ccl_device_inline float3 panorama_to_direction(ccl_constant KernelCamera *cam, f
case PANORAMA_MIRRORBALL:
return mirrorball_to_direction(u, v);
case PANORAMA_FISHEYE_EQUIDISTANT:
return fisheye_to_direction(u, v, cam->fisheye_fov);
return fisheye_equidistant_to_direction(u, v, cam->fisheye_fov);
case PANORAMA_FISHEYE_LENS_POLYNOMIAL:
return fisheye_lens_polynomial_to_direction(u,
v,
@@ -286,7 +266,7 @@ ccl_device_inline float2 direction_to_panorama(ccl_constant KernelCamera *cam, f
case PANORAMA_MIRRORBALL:
return direction_to_mirrorball(dir);
case PANORAMA_FISHEYE_EQUIDISTANT:
return direction_to_fisheye(dir, cam->fisheye_fov);
return direction_to_fisheye_equidistant(dir, cam->fisheye_fov);
case PANORAMA_FISHEYE_LENS_POLYNOMIAL:
return direction_to_fisheye_lens_polynomial(dir,
cam->fisheye_lens_polynomial_bias,

View File

@@ -185,13 +185,10 @@ ccl_device int bsdf_ashikhmin_shirley_sample(ccl_private const ShaderClosure *sc
}
/* get half vector in tangent space */
float sin_theta = sqrtf(fmaxf(0.0f, 1.0f - cos_theta * cos_theta));
float cos_phi = cosf(phi);
float sin_phi = sinf(phi); /* No `sqrt(1-cos^2)` here because it causes artifacts. */
float3 h = make_float3(sin_theta * cos_phi, sin_theta * sin_phi, cos_theta);
float3 h = spherical_cos_to_direction(cos_theta, phi);
/* half vector to world space */
float3 H = h.x * X + h.y * Y + h.z * N;
float3 H = to_global(h, X, Y, N);
float HdotI = dot(H, wi);
if (HdotI < 0.0f)
H = -H;

View File

@@ -99,7 +99,7 @@ ccl_device_forceinline float3 microfacet_beckmann_sample_vndf(const float3 wi,
wi_ = normalize(wi_);
/* 2. sample P22_{wi}(x_slope, y_slope, 1, 1) */
float slope_x, slope_y;
float2 slope;
float cos_phi_i = 1.0f;
float sin_phi_i = 0.0f;
@@ -107,8 +107,7 @@ ccl_device_forceinline float3 microfacet_beckmann_sample_vndf(const float3 wi,
/* Special case (normal incidence). */
const float r = sqrtf(-logf(rand.x));
const float phi = M_2PI_F * rand.y;
slope_x = r * cosf(phi);
slope_y = r * sinf(phi);
slope = polar_to_cartesian(r, phi);
}
else {
/* Precomputations. */
@@ -169,21 +168,19 @@ ccl_device_forceinline float3 microfacet_beckmann_sample_vndf(const float3 wi,
current.y = 1.0f + current.x + K * expf(-sqr(inv_erf)) - y_exact;
}
slope_x = inv_erf;
slope_y = fast_ierff(2.0f * rand.y - 1.0f);
slope.x = inv_erf;
slope.y = fast_ierff(2.0f * rand.y - 1.0f);
}
/* 3. rotate */
float tmp = cos_phi_i * slope_x - sin_phi_i * slope_y;
slope_y = sin_phi_i * slope_x + cos_phi_i * slope_y;
slope_x = tmp;
slope = make_float2(cos_phi_i * slope.x - sin_phi_i * slope.y,
sin_phi_i * slope.x + cos_phi_i * slope.y);
/* 4. unstretch */
slope_x = alpha_x * slope_x;
slope_y = alpha_y * slope_y;
slope *= make_float2(alpha_x, alpha_y);
/* 5. compute normal */
return normalize(make_float3(-slope_x, -slope_y, 1.0f));
return normalize(make_float3(-slope.x, -slope.y, 1.0f));
}
/* GGX VNDF importance sampling algorithm from:
@@ -216,7 +213,7 @@ ccl_device_forceinline float3 microfacet_ggx_sample_vndf(const float3 wi,
t.y = mix(safe_sqrtf(1.0f - sqr(t.x)), t.y, 0.5f * (1.0f + wi_.z));
/* Section 4.3: Reprojection onto hemisphere. */
float3 H_ = t.x * T1 + t.y * T2 + safe_sqrtf(1.0f - len_squared(t)) * wi_;
float3 H_ = to_global(disk_to_hemisphere(t), T1, T2, wi_);
/* Section 3.4: Transforming the normal back to the ellipsoid configuration. */
return normalize(make_float3(alpha_x * H_.x, alpha_y * H_.y, max(0.0f, H_.z)));
@@ -686,7 +683,7 @@ ccl_device int bsdf_microfacet_sample(KernelGlobals kg,
local_H = microfacet_beckmann_sample_vndf(local_I, alpha_x, alpha_y, float3_to_float2(rand));
}
H = X * local_H.x + Y * local_H.y + N * local_H.z;
H = to_global(local_H, X, Y, N);
}
const float cos_HI = dot(H, wi);

View File

@@ -96,9 +96,7 @@ ccl_device int bsdf_phong_ramp_sample(ccl_private const ShaderClosure *sc,
make_orthonormals(R, &T, &B);
float phi = M_2PI_F * rand.x;
float cosTheta = powf(rand.y, 1 / (m_exponent + 1));
float sinTheta2 = 1 - cosTheta * cosTheta;
float sinTheta = sinTheta2 > 0 ? sqrtf(sinTheta2) : 0;
*wo = (cosf(phi) * sinTheta) * T + (sinf(phi) * sinTheta) * B + (cosTheta)*R;
*wo = to_global(spherical_cos_to_direction(cosTheta, phi), T, B, R);
if (dot(Ng, *wo) > 0.0f) {
// common terms for pdf and eval
float cosNO = dot(bsdf->N, *wo);

View File

@@ -264,8 +264,8 @@ ccl_device Spectrum bsdf_hair_chiang_eval(KernelGlobals kg,
const float3 Z = safe_normalize(cross(X, Y));
/* local_I is the illumination direction. */
const float3 local_O = make_float3(dot(sd->wi, X), dot(sd->wi, Y), dot(sd->wi, Z));
const float3 local_I = make_float3(dot(wo, X), dot(wo, Y), dot(wo, Z));
const float3 local_O = to_local(sd->wi, X, Y, Z);
const float3 local_I = to_local(wo, X, Y, Z);
const float sin_theta_o = local_O.x;
const float cos_theta_o = cos_from_sin(sin_theta_o);
@@ -350,7 +350,7 @@ ccl_device int bsdf_hair_chiang_sample(KernelGlobals kg,
const float3 Z = safe_normalize(cross(X, Y));
/* `wo` in PBRT. */
const float3 local_O = make_float3(dot(sd->wi, X), dot(sd->wi, Y), dot(sd->wi, Z));
const float3 local_O = to_local(sd->wi, X, Y, Z);
const float sin_theta_o = local_O.x;
const float cos_theta_o = cos_from_sin(sin_theta_o);
@@ -443,8 +443,7 @@ ccl_device int bsdf_hair_chiang_sample(KernelGlobals kg,
*eval = F;
*pdf = F_energy;
*wo = X * sin_theta_i + Y * cos_theta_i * cosf(phi_i) + Z * cos_theta_i * sinf(phi_i);
*wo = to_global(spherical_cos_to_direction(sin_theta_i, phi_i), Y, Z, X);
return LABEL_GLOSSY | ((p == 0) ? LABEL_REFLECT : LABEL_TRANSMIT);
}

View File

@@ -243,8 +243,7 @@ ccl_device int bsdf_hair_huang_setup(ccl_private ShaderData *sd,
bsdf->extra->Z = safe_normalize(cross(bsdf->N, sd->dPdu));
}
const float3 I = make_float3(
dot(sd->wi, bsdf->N), dot(sd->wi, bsdf->extra->Y), dot(sd->wi, bsdf->extra->Z));
const float3 I = to_local(sd->wi, bsdf->N, bsdf->extra->Y, bsdf->extra->Z);
bsdf->extra->wi = I;
bsdf->extra->e2 = 1.0f - sqr(bsdf->aspect_ratio);
bsdf->extra->radius = bsdf->extra->e2 == 0 ?
@@ -286,11 +285,9 @@ ccl_device_inline float3 sample_wh(
float3 s, t;
make_orthonormals(wm, &s, &t);
const float3 wi_wm = make_float3(dot(wi, s), dot(wi, t), dot(wi, wm));
const float3 wi_wm = to_local(wi, s, t, wm);
const float3 wh_wm = microfacet_ggx_sample_vndf(wi_wm, roughness, roughness, rand);
const float3 wh = wh_wm.x * s + wh_wm.y * t + wh_wm.z * wm;
const float3 wh = to_global(wh_wm, s, t, wm);
return wh;
}
@@ -769,13 +766,8 @@ ccl_device int bsdf_hair_huang_sample(const KernelGlobals kg,
*eval = TRRT / trrt * make_spectrum(total_energy);
}
/* Get local coordinate system. */
const float3 X = bsdf->N;
const float3 Y = bsdf->extra->Y;
const float3 Z = bsdf->extra->Z;
/* Transform `wo` to global coordinate system. */
*wo = local_O.x * X + local_O.y * Y + local_O.z * Z;
*wo = to_global(local_O, bsdf->N, bsdf->extra->Y, bsdf->extra->Z);
/* Ensure the same pdf is returned for BSDF and emitter sampling. The importance sampling pdf is
* already factored in the value so this value is only used for MIS. */
@@ -794,14 +786,9 @@ ccl_device Spectrum bsdf_hair_huang_eval(KernelGlobals kg,
kernel_assert(fabsf(bsdf->h) < bsdf->extra->radius);
/* Get local coordinate system. */
const float3 X = bsdf->N;
const float3 Y = bsdf->extra->Y;
const float3 Z = bsdf->extra->Z;
/* Transform `wi`/`wo` from global coordinate system to local. */
const float3 local_I = bsdf->extra->wi;
const float3 local_O = make_float3(dot(wo, X), dot(wo, Y), dot(wo, Z));
const float3 local_O = to_local(wo, bsdf->N, bsdf->extra->Y, bsdf->extra->Z);
/* TODO: better estimation of the pdf */
*pdf = 1.0f;

View File

@@ -64,7 +64,7 @@ ccl_device Spectrum bsdf_sheen_eval(ccl_private const ShaderClosure *sc,
return zero_spectrum();
}
float3 localO = make_float3(dot(T, wo), dot(B, wo), dot(N, wo));
float3 localO = to_local(wo, T, B, N);
if (localO.z <= 0.0f) {
*pdf = 0.0f;
return zero_spectrum();
@@ -93,7 +93,7 @@ ccl_device int bsdf_sheen_sample(ccl_private const ShaderClosure *sc,
float diskZ = safe_sqrtf(1.0f - dot(disk, disk));
float3 localO = normalize(make_float3((disk.x - diskZ * b), disk.y, diskZ * a));
*wo = localO.x * T + localO.y * B + localO.z * N;
*wo = to_global(localO, T, B, N);
if (dot(Ng, *wo) <= 0) {
*eval = zero_spectrum();

View File

@@ -9,15 +9,12 @@ CCL_NAMESPACE_BEGIN
/* Given a random number, sample a direction that makes an angle of theta with direction D. */
ccl_device float3 phase_sample_direction(float3 D, float cos_theta, float rand)
{
float sin_theta = sin_from_cos(cos_theta);
float phi = M_2PI_F * rand;
float3 dir = make_float3(sin_theta * cosf(phi), sin_theta * sinf(phi), cos_theta);
float3 dir = spherical_cos_to_direction(cos_theta, phi);
float3 T, B;
make_orthonormals(D, &T, &B);
dir = dir.x * T + dir.y * B + dir.z * D;
return dir;
return to_global(dir, T, B, D);
}
/* Given cosine between rays, return probability density that a photon bounces

View File

@@ -57,7 +57,7 @@ ccl_device_inline bool subsurface_entry_bounce(KernelGlobals kg,
/* Sample microfacet normal by transforming to/from local coordinates. */
const float3 local_I = make_float3(dot(X, sd->wi), dot(Y, sd->wi), cos_NI);
const float3 local_H = microfacet_ggx_sample_vndf(local_I, alpha, alpha, rand_bsdf);
const float3 H = X * local_H.x + Y * local_H.y + Z * local_H.z;
const float3 H = to_global(local_H, X, Y, Z);
const float cos_HI = dot(H, sd->wi);
const float arg = 1.0f - (sqr(neta) * (1.0f - sqr(cos_HI)));

View File

@@ -81,7 +81,7 @@ ccl_device_inline bool subsurface_disk(KernelGlobals kg,
bssrdf_sample(radius, rand_disk.x, &disk_r, &disk_height);
float3 disk_P = (disk_r * cosf(phi)) * disk_T + (disk_r * sinf(phi)) * disk_B;
float3 disk_P = to_global(polar_to_cartesian(disk_r, phi), disk_T, disk_B);
/* Create ray. */
ray.P = P + disk_N * disk_height + disk_P;

View File

@@ -139,13 +139,12 @@ ccl_device_forceinline float diffusion_length_dwivedi(float alpha)
ccl_device_forceinline float3 direction_from_cosine(float3 D, float cos_theta, float randv)
{
float sin_theta = sin_from_cos(cos_theta);
float phi = M_2PI_F * randv;
float3 dir = make_float3(sin_theta * cosf(phi), sin_theta * sinf(phi), cos_theta);
float3 dir = spherical_cos_to_direction(cos_theta, phi);
float3 T, B;
make_orthonormals(D, &T, &B);
return dir.x * T + dir.y * B + dir.z * D;
return to_global(dir, T, B, D);
}
ccl_device_forceinline Spectrum subsurface_random_walk_pdf(Spectrum sigma_t,

View File

@@ -29,7 +29,7 @@ ccl_device float2 sample_uniform_disk(const float2 rand)
phi = M_PI_2_F - M_PI_4_F * (a / b);
}
return make_float2(r * cosf(phi), r * sinf(phi));
return polar_to_cartesian(r, phi);
}
/* return an orthogonal tangent and bitangent given a normal and tangent that
@@ -168,10 +168,8 @@ ccl_device float3 sample_uniform_sphere(const float2 rand)
float z = 1.0f - 2.0f * rand.x;
float r = sin_from_cos(z);
float phi = M_2PI_F * rand.y;
float x = r * cosf(phi);
float y = r * sinf(phi);
return make_float3(x, y, z);
return float2_to_float3(polar_to_cartesian(r, phi), z);
}
/* sample point in unit polygon with given number of corners and rotation */

View File

@@ -59,7 +59,7 @@ ccl_device float svm_ao(
/* Create ray. */
Ray ray;
ray.P = sd->P;
ray.D = D.x * T + D.y * B + D.z * N;
ray.D = to_global(D, T, B, N);
ray.tmin = 0.0f;
ray.tmax = max_dist;
ray.time = sd->time;

View File

@@ -176,7 +176,7 @@ ccl_device float3 svm_bevel(
/* Perhaps find something better than Cubic BSSRDF, but happens to work well. */
svm_bevel_cubic_sample(radius, disk_r, &disk_r, &disk_height);
float3 disk_P = (disk_r * cosf(phi)) * disk_T + (disk_r * sinf(phi)) * disk_B;
float3 disk_P = to_global(polar_to_cartesian(disk_r, phi), disk_T, disk_B);
/* Create ray. */
Ray ray ccl_optional_struct_init;

View File

@@ -62,11 +62,8 @@ ccl_device float2 compute_2d_gabor_kernel(float2 position, float frequency, floa
float gaussian_envelop = expf(-M_PI_F * distance_squared);
float windowed_gaussian_envelope = gaussian_envelop * hann_window;
float2 frequency_vector = frequency * make_float2(cosf(orientation), sinf(orientation));
float angle = 2.0f * M_PI_F * dot(position, frequency_vector);
float2 phasor = make_float2(cosf(angle), sinf(angle));
return windowed_gaussian_envelope * phasor;
float angle = 2.0f * M_PI_F * dot(position, polar_to_cartesian(frequency, orientation));
return polar_to_cartesian(windowed_gaussian_envelope, angle);
}
/* Computes the approximate standard deviation of the zero mean normal distribution representing
@@ -181,9 +178,7 @@ ccl_device float2 compute_3d_gabor_kernel(float3 position, float frequency, floa
float3 frequency_vector = frequency * orientation;
float angle = 2.0f * M_PI_F * dot(position, frequency_vector);
float2 phasor = make_float2(cosf(angle), sinf(angle));
return windowed_gaussian_envelope * phasor;
return polar_to_cartesian(windowed_gaussian_envelope, angle);
}
/* Identical to compute_2d_gabor_standard_deviation except we do triple integration in 3D. The only
@@ -219,9 +214,8 @@ ccl_device float3 compute_3d_orientation(float3 orientation, float isotropy, flo
inclination += random_angles.x * isotropy;
azimuth += random_angles.y * isotropy;
/* Convert back to Cartesian coordinates, */
return make_float3(
sinf(inclination) * cosf(azimuth), sinf(inclination) * sinf(azimuth), cosf(inclination));
/* Convert back to Cartesian coordinates. */
return spherical_to_direction(inclination, azimuth);
}
ccl_device float2 compute_3d_gabor_noise_cell(

View File

@@ -41,7 +41,7 @@ ccl_device float3 sky_radiance_preetham(KernelGlobals kg,
/* convert vector to spherical coordinates */
float2 spherical = direction_to_spherical(dir);
float theta = spherical.x;
float phi = spherical.y;
float phi = -spherical.y + M_PI_2_F;
/* angle between sun direction and dir */
float gamma = sky_angle_between(theta, phi, suntheta, sunphi);
@@ -94,7 +94,7 @@ ccl_device float3 sky_radiance_hosek(KernelGlobals kg,
/* convert vector to spherical coordinates */
float2 spherical = direction_to_spherical(dir);
float theta = spherical.x;
float phi = spherical.y;
float phi = -spherical.y + M_PI_2_F;
/* angle between sun direction and dir */
float gamma = sky_angle_between(theta, phi, suntheta, sunphi);
@@ -114,7 +114,7 @@ ccl_device float3 sky_radiance_hosek(KernelGlobals kg,
/* Nishita improved sky model */
ccl_device float3 geographical_to_direction(float lat, float lon)
{
return make_float3(cosf(lat) * cosf(lon), cosf(lat) * sinf(lon), sinf(lat));
return spherical_to_direction(lat - M_PI_2_F, lon - M_PI_2_F);
}
ccl_device float3 sky_radiance_nishita(KernelGlobals kg,
@@ -137,7 +137,7 @@ ccl_device float3 sky_radiance_nishita(KernelGlobals kg,
/* render above the horizon */
if (dir.z >= 0.0f) {
/* definitions */
float3 sun_dir = geographical_to_direction(sun_elevation, sun_rotation + M_PI_2_F);
float3 sun_dir = geographical_to_direction(sun_elevation, sun_rotation);
float sun_dir_angle = precise_angle(dir, sun_dir);
float half_angular = angular_diameter * 0.5f;
float dir_elevation = M_PI_2_F - direction.x;
@@ -171,12 +171,9 @@ ccl_device float3 sky_radiance_nishita(KernelGlobals kg,
/* sky */
else {
/* sky interpolation */
float x = (direction.y + M_PI_F + sun_rotation) / M_2PI_F;
float x = fractf((-direction.y - M_PI_2_F + sun_rotation) / M_2PI_F);
/* more pixels toward horizon compensation */
float y = safe_sqrtf(dir_elevation / M_PI_2_F);
if (x > 1.0f) {
x -= 1.0f;
}
xyz = float4_to_float3(kernel_tex_image_interp(kg, texture_id, x, y));
}
}
@@ -190,10 +187,7 @@ ccl_device float3 sky_radiance_nishita(KernelGlobals kg,
float fade = 1.0f + dir.z * 2.5f;
fade = sqr(fade) * fade;
/* interpolation */
float x = (direction.y + M_PI_F + sun_rotation) / M_2PI_F;
if (x > 1.0f) {
x -= 1.0f;
}
float x = fractf((-direction.y - M_PI_2_F + sun_rotation) / M_2PI_F);
xyz = float4_to_float3(kernel_tex_image_interp(kg, texture_id, x, -0.5)) * fade;
}
}

View File

@@ -320,7 +320,7 @@ ccl_device_noinline void svm_node_normal_map(KernelGlobals kg,
/* apply normal map */
float3 B = sign * cross(normal, tangent);
N = safe_normalize(color.x * tangent + color.y * B + color.z * normal);
N = safe_normalize(to_global(color, tangent, B, normal));
/* transform to world space */
object_normal_transform(kg, sd, &N);

View File

@@ -813,7 +813,7 @@ float ShaderManager::linear_rgb_to_gray(float3 c)
float3 ShaderManager::rec709_to_scene_linear(float3 c)
{
return make_float3(dot(rec709_to_r, c), dot(rec709_to_g, c), dot(rec709_to_b, c));
return to_local(c, rec709_to_r, rec709_to_g, rec709_to_b);
}
string ShaderManager::get_cryptomatte_materials(Scene *scene)

View File

@@ -284,14 +284,14 @@ struct FisheyeEquidistant : public CommonValues {
float const width,
float const height)
{
return direction_to_fisheye(dir, fov);
return direction_to_fisheye_equidistant(dir, fov);
}
static float3 sensor_to_direction(float2 const &sensor,
float const fov,
float const width,
float const height)
{
return fisheye_to_direction(sensor.x, sensor.y, fov);
return fisheye_equidistant_to_direction(sensor.x, sensor.y, fov);
}
};

View File

@@ -527,6 +527,11 @@ ccl_device_inline float3 float2_to_float3(const float2 a)
return make_float3(a.x, a.y, 0.0f);
}
ccl_device_inline float3 float2_to_float3(const float2 a, const float z)
{
return make_float3(a.x, a.y, z);
}
ccl_device_inline float2 float3_to_float2(const float3 a)
{
return make_float2(a.x, a.y);

View File

@@ -9,6 +9,59 @@
CCL_NAMESPACE_BEGIN
ccl_device float2 direction_to_spherical(float3 dir)
{
float theta = safe_acosf(dir.z);
float phi = atan2f(dir.y, dir.x);
return make_float2(theta, phi);
}
ccl_device float3 spherical_to_direction(float theta, float phi)
{
return make_float3(sinf(theta) * cosf(phi), sinf(theta) * sinf(phi), cosf(theta));
}
ccl_device float3 spherical_cos_to_direction(float cos_theta, float phi)
{
const float sin_theta = sin_from_cos(cos_theta);
return make_float3(sin_theta * cosf(phi), sin_theta * sinf(phi), cos_theta);
}
ccl_device_inline float2 polar_to_cartesian(float r, float phi)
{
return make_float2(r * cosf(phi), r * sinf(phi));
}
/* Transform p from a local coordinate system (spanned by X and Y) into global coordinates. */
template<class T> ccl_device_inline T to_global(const float2 p, const T X, const T Y)
{
return p.x * X + p.y * Y;
}
/* Transform p from a local coordinate system (spanned by X, Y and Z) into global coordinates. */
template<class T> ccl_device_inline T to_global(const float3 p, const T X, const T Y, const T Z)
{
return p.x * X + p.y * Y + p.z * Z;
}
/* Transform p from global coordinates into a local coordinate system (spanned by X and Y). */
template<class T> ccl_device_inline float2 to_local(const T p, const T X, const T Y)
{
return make_float2(dot(p, X), dot(p, Y));
}
/* Transform p from global coordinates into a local coordinate system (spanned by X, Y and Z). */
template<class T> ccl_device_inline float3 to_local(const T p, const T X, const T Y, const T Z)
{
return make_float3(dot(p, X), dot(p, Y), dot(p, Z));
}
ccl_device_inline float3 disk_to_hemisphere(const float2 p)
{
return make_float3(p.x, p.y, safe_sqrtf(1.0f - len_squared(p)));
}
/* 4x4 projection matrix, perspective or orthographic. */
typedef struct ProjectionTransform {