From b8d0bef3b4a3583467eea973baf67bf09b450ad9 Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Mon, 7 Oct 2024 02:18:49 +0200 Subject: [PATCH] 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 --- intern/cycles/kernel/camera/projection.h | 56 ++++++------------- .../kernel/closure/bsdf_ashikhmin_shirley.h | 7 +-- .../cycles/kernel/closure/bsdf_microfacet.h | 23 ++++---- .../cycles/kernel/closure/bsdf_phong_ramp.h | 4 +- .../closure/bsdf_principled_hair_chiang.h | 9 ++- .../closure/bsdf_principled_hair_huang.h | 23 ++------ intern/cycles/kernel/closure/bsdf_sheen.h | 4 +- intern/cycles/kernel/closure/volume_util.h | 7 +-- intern/cycles/kernel/integrator/subsurface.h | 2 +- .../kernel/integrator/subsurface_disk.h | 2 +- .../integrator/subsurface_random_walk.h | 5 +- intern/cycles/kernel/sample/mapping.h | 6 +- intern/cycles/kernel/svm/ao.h | 2 +- intern/cycles/kernel/svm/bevel.h | 2 +- intern/cycles/kernel/svm/gabor.h | 16 ++---- intern/cycles/kernel/svm/sky.h | 18 ++---- intern/cycles/kernel/svm/tex_coord.h | 2 +- intern/cycles/scene/shader.cpp | 2 +- .../test/kernel_camera_projection_test.cpp | 4 +- intern/cycles/util/math.h | 5 ++ intern/cycles/util/projection.h | 53 ++++++++++++++++++ 21 files changed, 125 insertions(+), 127 deletions(-) diff --git a/intern/cycles/kernel/camera/projection.h b/intern/cycles/kernel/camera/projection.h index 22e221d0aea..9c6bd21bfc5 100644 --- a/intern/cycles/kernel/camera/projection.h +++ b/intern/cycles/kernel/camera/projection.h @@ -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, diff --git a/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h b/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h index 0377e31eaf7..323b6651339 100644 --- a/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h +++ b/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h @@ -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; diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h index 5e8c4c02650..d7d3e2850ec 100644 --- a/intern/cycles/kernel/closure/bsdf_microfacet.h +++ b/intern/cycles/kernel/closure/bsdf_microfacet.h @@ -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); diff --git a/intern/cycles/kernel/closure/bsdf_phong_ramp.h b/intern/cycles/kernel/closure/bsdf_phong_ramp.h index 2933b8f310c..9863d939e7a 100644 --- a/intern/cycles/kernel/closure/bsdf_phong_ramp.h +++ b/intern/cycles/kernel/closure/bsdf_phong_ramp.h @@ -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); diff --git a/intern/cycles/kernel/closure/bsdf_principled_hair_chiang.h b/intern/cycles/kernel/closure/bsdf_principled_hair_chiang.h index 3b4183f7b02..94612b8a931 100644 --- a/intern/cycles/kernel/closure/bsdf_principled_hair_chiang.h +++ b/intern/cycles/kernel/closure/bsdf_principled_hair_chiang.h @@ -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); } diff --git a/intern/cycles/kernel/closure/bsdf_principled_hair_huang.h b/intern/cycles/kernel/closure/bsdf_principled_hair_huang.h index 72334fdc1e8..4dbe44dfafa 100644 --- a/intern/cycles/kernel/closure/bsdf_principled_hair_huang.h +++ b/intern/cycles/kernel/closure/bsdf_principled_hair_huang.h @@ -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; diff --git a/intern/cycles/kernel/closure/bsdf_sheen.h b/intern/cycles/kernel/closure/bsdf_sheen.h index b66bce6fd34..5e2b2388b38 100644 --- a/intern/cycles/kernel/closure/bsdf_sheen.h +++ b/intern/cycles/kernel/closure/bsdf_sheen.h @@ -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(); diff --git a/intern/cycles/kernel/closure/volume_util.h b/intern/cycles/kernel/closure/volume_util.h index 4e97271a956..7cb7799b5e0 100644 --- a/intern/cycles/kernel/closure/volume_util.h +++ b/intern/cycles/kernel/closure/volume_util.h @@ -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 diff --git a/intern/cycles/kernel/integrator/subsurface.h b/intern/cycles/kernel/integrator/subsurface.h index cb3f307ddd1..2d6b5750699 100644 --- a/intern/cycles/kernel/integrator/subsurface.h +++ b/intern/cycles/kernel/integrator/subsurface.h @@ -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))); diff --git a/intern/cycles/kernel/integrator/subsurface_disk.h b/intern/cycles/kernel/integrator/subsurface_disk.h index df5f437ad01..2603761e805 100644 --- a/intern/cycles/kernel/integrator/subsurface_disk.h +++ b/intern/cycles/kernel/integrator/subsurface_disk.h @@ -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; diff --git a/intern/cycles/kernel/integrator/subsurface_random_walk.h b/intern/cycles/kernel/integrator/subsurface_random_walk.h index eb85fb23d2f..68cf48a9083 100644 --- a/intern/cycles/kernel/integrator/subsurface_random_walk.h +++ b/intern/cycles/kernel/integrator/subsurface_random_walk.h @@ -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, diff --git a/intern/cycles/kernel/sample/mapping.h b/intern/cycles/kernel/sample/mapping.h index a759de920ff..cd9b0029d27 100644 --- a/intern/cycles/kernel/sample/mapping.h +++ b/intern/cycles/kernel/sample/mapping.h @@ -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 */ diff --git a/intern/cycles/kernel/svm/ao.h b/intern/cycles/kernel/svm/ao.h index 263aa081c01..c9a0e06c0fe 100644 --- a/intern/cycles/kernel/svm/ao.h +++ b/intern/cycles/kernel/svm/ao.h @@ -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; diff --git a/intern/cycles/kernel/svm/bevel.h b/intern/cycles/kernel/svm/bevel.h index fa718336fd0..9007b67c6dc 100644 --- a/intern/cycles/kernel/svm/bevel.h +++ b/intern/cycles/kernel/svm/bevel.h @@ -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; diff --git a/intern/cycles/kernel/svm/gabor.h b/intern/cycles/kernel/svm/gabor.h index b7279f0bd72..e8b9eeda8a6 100644 --- a/intern/cycles/kernel/svm/gabor.h +++ b/intern/cycles/kernel/svm/gabor.h @@ -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( diff --git a/intern/cycles/kernel/svm/sky.h b/intern/cycles/kernel/svm/sky.h index bafbcadec3a..8adf6e6a00b 100644 --- a/intern/cycles/kernel/svm/sky.h +++ b/intern/cycles/kernel/svm/sky.h @@ -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; } } diff --git a/intern/cycles/kernel/svm/tex_coord.h b/intern/cycles/kernel/svm/tex_coord.h index fc5da61cd85..1a56dfb763a 100644 --- a/intern/cycles/kernel/svm/tex_coord.h +++ b/intern/cycles/kernel/svm/tex_coord.h @@ -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); diff --git a/intern/cycles/scene/shader.cpp b/intern/cycles/scene/shader.cpp index 3ba12587a9f..e7b04db4f39 100644 --- a/intern/cycles/scene/shader.cpp +++ b/intern/cycles/scene/shader.cpp @@ -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) diff --git a/intern/cycles/test/kernel_camera_projection_test.cpp b/intern/cycles/test/kernel_camera_projection_test.cpp index 89f1d636451..d911675a397 100644 --- a/intern/cycles/test/kernel_camera_projection_test.cpp +++ b/intern/cycles/test/kernel_camera_projection_test.cpp @@ -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); } }; diff --git a/intern/cycles/util/math.h b/intern/cycles/util/math.h index 077993c1ea9..0b2ac9c1a44 100644 --- a/intern/cycles/util/math.h +++ b/intern/cycles/util/math.h @@ -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); diff --git a/intern/cycles/util/projection.h b/intern/cycles/util/projection.h index 848e91d3a8e..1efe7e891c5 100644 --- a/intern/cycles/util/projection.h +++ b/intern/cycles/util/projection.h @@ -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 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 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 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 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 {