Refactor: group multiple floats to float2 or float3

Multiple random numbers were passed around separately, making some
argument lists unnecessarily long.
No functional changes expected.

Pull Request: https://projects.blender.org/blender/blender/pulls/108236
This commit is contained in:
Weizhen Huang 2023-05-24 18:56:58 +02:00 committed by Weizhen Huang
parent adb87dd080
commit 41e49d7ece
35 changed files with 290 additions and 420 deletions

@ -12,19 +12,19 @@ CCL_NAMESPACE_BEGIN
/* Perspective Camera */
ccl_device float2 camera_sample_aperture(ccl_constant KernelCamera *cam, float u, float v)
ccl_device float2 camera_sample_aperture(ccl_constant KernelCamera *cam, const float2 rand)
{
float blades = cam->blades;
float2 bokeh;
if (blades == 0.0f) {
/* sample disk */
bokeh = concentric_sample_disk(u, v);
bokeh = concentric_sample_disk(rand);
}
else {
/* sample polygon */
float rotation = cam->bladesrotation;
bokeh = regular_polygon_sample(blades, rotation, u, v);
bokeh = regular_polygon_sample(blades, rotation, rand);
}
/* anamorphic lens bokeh */
@ -34,15 +34,13 @@ ccl_device float2 camera_sample_aperture(ccl_constant KernelCamera *cam, float u
}
ccl_device void camera_sample_perspective(KernelGlobals kg,
float raster_x,
float raster_y,
float lens_u,
float lens_v,
const float2 raster_xy,
const float2 rand_lens,
ccl_private Ray *ray)
{
/* create ray form raster position */
ProjectionTransform rastertocamera = kernel_data.cam.rastertocamera;
float3 raster = make_float3(raster_x, raster_y, 0.0f);
const float3 raster = float2_to_float3(raster_xy);
float3 Pcamera = transform_perspective(&rastertocamera, raster);
if (kernel_data.cam.have_perspective_motion) {
@ -71,14 +69,14 @@ ccl_device void camera_sample_perspective(KernelGlobals kg,
if (aperturesize > 0.0f) {
/* sample point on aperture */
float2 lensuv = camera_sample_aperture(&kernel_data.cam, lens_u, lens_v) * aperturesize;
float2 lens_uv = camera_sample_aperture(&kernel_data.cam, rand_lens) * aperturesize;
/* compute point on plane of focus */
float ft = kernel_data.cam.focaldistance / D.z;
float3 Pfocus = D * ft;
/* update ray for effect of lens */
P = make_float3(lensuv.x, lensuv.y, 0.0f);
P = float2_to_float3(lens_uv);
D = normalize(Pfocus - P);
}
@ -133,7 +131,7 @@ ccl_device void camera_sample_perspective(KernelGlobals kg,
float3 Px = Pnostereo;
float3 Dx = transform_perspective(&rastertocamera,
make_float3(raster_x + 1.0f, raster_y, 0.0f));
make_float3(raster.x + 1.0f, raster.y, 0.0f));
Dx = normalize(transform_direction(&cameratoworld, Dx));
spherical_stereo_transform(&kernel_data.cam, &Px, &Dx);
@ -144,7 +142,7 @@ ccl_device void camera_sample_perspective(KernelGlobals kg,
float3 Py = Pnostereo;
float3 Dy = transform_perspective(&rastertocamera,
make_float3(raster_x, raster_y + 1.0f, 0.0f));
make_float3(raster.x, raster.y + 1.0f, 0.0f));
Dy = normalize(transform_direction(&cameratoworld, Dy));
spherical_stereo_transform(&kernel_data.cam, &Py, &Dy);
@ -166,15 +164,13 @@ ccl_device void camera_sample_perspective(KernelGlobals kg,
/* Orthographic Camera */
ccl_device void camera_sample_orthographic(KernelGlobals kg,
float raster_x,
float raster_y,
float lens_u,
float lens_v,
const float2 raster_xy,
const float2 rand_lens,
ccl_private Ray *ray)
{
/* create ray form raster position */
ProjectionTransform rastertocamera = kernel_data.cam.rastertocamera;
float3 Pcamera = transform_perspective(&rastertocamera, make_float3(raster_x, raster_y, 0.0f));
float3 Pcamera = transform_perspective(&rastertocamera, float2_to_float3(raster_xy));
float3 P;
float3 D = make_float3(0.0f, 0.0f, 1.0f);
@ -184,15 +180,15 @@ ccl_device void camera_sample_orthographic(KernelGlobals kg,
if (aperturesize > 0.0f) {
/* sample point on aperture */
float2 lensuv = camera_sample_aperture(&kernel_data.cam, lens_u, lens_v) * aperturesize;
float2 lens_uv = camera_sample_aperture(&kernel_data.cam, rand_lens) * aperturesize;
/* compute point on plane of focus */
float3 Pfocus = D * kernel_data.cam.focaldistance;
/* update ray for effect of lens */
float3 lensuvw = make_float3(lensuv.x, lensuv.y, 0.0f);
P = Pcamera + lensuvw;
D = normalize(Pfocus - lensuvw);
float3 lens_uvw = float2_to_float3(lens_uv);
P = Pcamera + lens_uvw;
D = normalize(Pfocus - lens_uvw);
}
else {
P = Pcamera;
@ -229,14 +225,12 @@ ccl_device void camera_sample_orthographic(KernelGlobals kg,
ccl_device_inline void camera_sample_panorama(ccl_constant KernelCamera *cam,
ccl_global const DecomposedTransform *cam_motion,
float raster_x,
float raster_y,
float lens_u,
float lens_v,
const float2 raster,
const float2 rand_lens,
ccl_private Ray *ray)
{
ProjectionTransform rastertocamera = cam->rastertocamera;
float3 Pcamera = transform_perspective(&rastertocamera, make_float3(raster_x, raster_y, 0.0f));
float3 Pcamera = transform_perspective(&rastertocamera, float2_to_float3(raster));
/* create ray form raster position */
float3 P = zero_float3();
@ -253,7 +247,7 @@ ccl_device_inline void camera_sample_panorama(ccl_constant KernelCamera *cam,
if (aperturesize > 0.0f) {
/* sample point on aperture */
float2 lensuv = camera_sample_aperture(cam, lens_u, lens_v) * aperturesize;
float2 lens_uv = camera_sample_aperture(cam, rand_lens) * aperturesize;
/* compute point on plane of focus */
float3 Dfocus = normalize(D);
@ -265,7 +259,7 @@ ccl_device_inline void camera_sample_panorama(ccl_constant KernelCamera *cam,
V = normalize(cross(Dfocus, U));
/* update ray for effect of lens */
P = U * lensuv.x + V * lensuv.y;
P = U * lens_uv.x + V * lens_uv.y;
D = normalize(Pfocus - P);
}
@ -302,7 +296,7 @@ ccl_device_inline void camera_sample_panorama(ccl_constant KernelCamera *cam,
Pcenter = transform_point(&cameratoworld, Pcenter);
Dcenter = normalize(transform_direction(&cameratoworld, Dcenter));
float3 Px = transform_perspective(&rastertocamera, make_float3(raster_x + 1.0f, raster_y, 0.0f));
float3 Px = transform_perspective(&rastertocamera, make_float3(raster.x + 1.0f, raster.y, 0.0f));
float3 Dx = panorama_to_direction(cam, Px.x, Px.y);
if (use_stereo) {
spherical_stereo_transform(cam, &Px, &Dx);
@ -314,7 +308,7 @@ ccl_device_inline void camera_sample_panorama(ccl_constant KernelCamera *cam,
dP.dx = Px - Pcenter;
dD.dx = Dx - Dcenter;
float3 Py = transform_perspective(&rastertocamera, make_float3(raster_x, raster_y + 1.0f, 0.0f));
float3 Py = transform_perspective(&rastertocamera, make_float3(raster.x, raster.y + 1.0f, 0.0f));
float3 Dy = panorama_to_direction(cam, Py.x, Py.y);
if (use_stereo) {
spherical_stereo_transform(cam, &Py, &Dy);
@ -341,17 +335,16 @@ ccl_device_inline void camera_sample_panorama(ccl_constant KernelCamera *cam,
ccl_device_inline void camera_sample(KernelGlobals kg,
int x,
int y,
float filter_u,
float filter_v,
float lens_u,
float lens_v,
float time,
const float2 filter_uv,
const float time,
const float2 lens_uv,
ccl_private Ray *ray)
{
/* pixel filter */
int filter_table_offset = kernel_data.tables.filter_table_offset;
float raster_x = x + lookup_table_read(kg, filter_u, filter_table_offset, FILTER_TABLE_SIZE);
float raster_y = y + lookup_table_read(kg, filter_v, filter_table_offset, FILTER_TABLE_SIZE);
const float2 raster = make_float2(
x + lookup_table_read(kg, filter_uv.x, filter_table_offset, FILTER_TABLE_SIZE),
y + lookup_table_read(kg, filter_uv.y, filter_table_offset, FILTER_TABLE_SIZE));
/* motion blur */
if (kernel_data.cam.shuttertime == -1.0f) {
@ -393,14 +386,14 @@ ccl_device_inline void camera_sample(KernelGlobals kg,
/* sample */
if (kernel_data.cam.type == CAMERA_PERSPECTIVE) {
camera_sample_perspective(kg, raster_x, raster_y, lens_u, lens_v, ray);
camera_sample_perspective(kg, raster, lens_uv, ray);
}
else if (kernel_data.cam.type == CAMERA_ORTHOGRAPHIC) {
camera_sample_orthographic(kg, raster_x, raster_y, lens_u, lens_v, ray);
camera_sample_orthographic(kg, raster, lens_uv, ray);
}
else {
ccl_global const DecomposedTransform *cam_motion = kernel_data_array(camera_motion);
camera_sample_panorama(&kernel_data.cam, cam_motion, raster_x, raster_y, lens_u, lens_v, ray);
camera_sample_panorama(&kernel_data.cam, cam_motion, raster, lens_uv, ray);
}
}

@ -122,73 +122,53 @@ ccl_device_inline int bsdf_sample(KernelGlobals kg,
*pdf = 0.f;
int label = LABEL_NONE;
const float3 Ng = (sd->type & PRIMITIVE_CURVE) ? sc->N : sd->Ng;
const float2 rand_xy = float3_to_float2(rand);
switch (sc->type) {
case CLOSURE_BSDF_DIFFUSE_ID:
label = bsdf_diffuse_sample(sc, Ng, sd->wi, rand.x, rand.y, eval, wo, pdf);
label = bsdf_diffuse_sample(sc, Ng, sd->wi, rand_xy, eval, wo, pdf);
*sampled_roughness = one_float2();
*eta = 1.0f;
break;
#if defined(__SVM__) || defined(__OSL__)
case CLOSURE_BSDF_OREN_NAYAR_ID:
label = bsdf_oren_nayar_sample(sc, Ng, sd->wi, rand.x, rand.y, eval, wo, pdf);
label = bsdf_oren_nayar_sample(sc, Ng, sd->wi, rand_xy, eval, wo, pdf);
*sampled_roughness = one_float2();
*eta = 1.0f;
break;
# ifdef __OSL__
case CLOSURE_BSDF_PHONG_RAMP_ID:
label = bsdf_phong_ramp_sample(
sc, Ng, sd->wi, rand.x, rand.y, eval, wo, pdf, sampled_roughness);
label = bsdf_phong_ramp_sample(sc, Ng, sd->wi, rand_xy, eval, wo, pdf, sampled_roughness);
*eta = 1.0f;
break;
case CLOSURE_BSDF_DIFFUSE_RAMP_ID:
label = bsdf_diffuse_ramp_sample(sc, Ng, sd->wi, rand.x, rand.y, eval, wo, pdf);
label = bsdf_diffuse_ramp_sample(sc, Ng, sd->wi, rand_xy, eval, wo, pdf);
*sampled_roughness = one_float2();
*eta = 1.0f;
break;
# endif
case CLOSURE_BSDF_TRANSLUCENT_ID:
label = bsdf_translucent_sample(sc, Ng, sd->wi, rand.x, rand.y, eval, wo, pdf);
label = bsdf_translucent_sample(sc, Ng, sd->wi, rand_xy, eval, wo, pdf);
*sampled_roughness = one_float2();
*eta = 1.0f;
break;
case CLOSURE_BSDF_TRANSPARENT_ID:
label = bsdf_transparent_sample(sc, Ng, sd->wi, rand.x, rand.y, eval, wo, pdf);
label = bsdf_transparent_sample(sc, Ng, sd->wi, eval, wo, pdf);
*sampled_roughness = zero_float2();
*eta = 1.0f;
break;
case CLOSURE_BSDF_REFLECTION_ID:
case CLOSURE_BSDF_REFRACTION_ID:
case CLOSURE_BSDF_SHARP_GLASS_ID:
label = bsdf_microfacet_sharp_sample(sc,
path_flag,
Ng,
sd->wi,
rand.x,
rand.y,
rand.z,
eval,
wo,
pdf,
sampled_roughness,
eta);
label = bsdf_microfacet_sharp_sample(
sc, path_flag, Ng, sd->wi, rand, eval, wo, pdf, sampled_roughness, eta);
break;
case CLOSURE_BSDF_MICROFACET_GGX_ID:
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
case CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID:
label = bsdf_microfacet_ggx_sample(sc,
path_flag,
Ng,
sd->wi,
rand.x,
rand.y,
rand.z,
eval,
wo,
pdf,
sampled_roughness,
eta);
label = bsdf_microfacet_ggx_sample(
sc, path_flag, Ng, sd->wi, rand, eval, wo, pdf, sampled_roughness, eta);
break;
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
label = bsdf_microfacet_multi_ggx_sample(kg,
@ -221,61 +201,50 @@ ccl_device_inline int bsdf_sample(KernelGlobals kg,
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID:
label = bsdf_microfacet_beckmann_sample(sc,
path_flag,
Ng,
sd->wi,
rand.x,
rand.y,
rand.z,
eval,
wo,
pdf,
sampled_roughness,
eta);
label = bsdf_microfacet_beckmann_sample(
sc, path_flag, Ng, sd->wi, rand, eval, wo, pdf, sampled_roughness, eta);
break;
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
label = bsdf_ashikhmin_shirley_sample(
sc, Ng, sd->wi, rand.x, rand.y, eval, wo, pdf, sampled_roughness);
sc, Ng, sd->wi, rand_xy, eval, wo, pdf, sampled_roughness);
*eta = 1.0f;
break;
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
label = bsdf_ashikhmin_velvet_sample(sc, Ng, sd->wi, rand.x, rand.y, eval, wo, pdf);
label = bsdf_ashikhmin_velvet_sample(sc, Ng, sd->wi, rand_xy, eval, wo, pdf);
*sampled_roughness = one_float2();
*eta = 1.0f;
break;
case CLOSURE_BSDF_DIFFUSE_TOON_ID:
label = bsdf_diffuse_toon_sample(sc, Ng, sd->wi, rand.x, rand.y, eval, wo, pdf);
label = bsdf_diffuse_toon_sample(sc, Ng, sd->wi, rand_xy, eval, wo, pdf);
*sampled_roughness = one_float2();
*eta = 1.0f;
break;
case CLOSURE_BSDF_GLOSSY_TOON_ID:
label = bsdf_glossy_toon_sample(sc, Ng, sd->wi, rand.x, rand.y, eval, wo, pdf);
label = bsdf_glossy_toon_sample(sc, Ng, sd->wi, rand_xy, eval, wo, pdf);
// double check if this is valid
*sampled_roughness = one_float2();
*eta = 1.0f;
break;
case CLOSURE_BSDF_HAIR_REFLECTION_ID:
label = bsdf_hair_reflection_sample(
sc, Ng, sd->wi, rand.x, rand.y, eval, wo, pdf, sampled_roughness);
sc, Ng, sd->wi, rand_xy, eval, wo, pdf, sampled_roughness);
*eta = 1.0f;
break;
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
label = bsdf_hair_transmission_sample(
sc, Ng, sd->wi, rand.x, rand.y, eval, wo, pdf, sampled_roughness);
sc, Ng, sd->wi, rand_xy, eval, wo, pdf, sampled_roughness);
*eta = 1.0f;
break;
case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
label = bsdf_principled_hair_sample(
kg, sc, sd, rand.x, rand.y, rand.z, eval, wo, pdf, sampled_roughness, eta);
label = bsdf_principled_hair_sample(kg, sc, sd, rand, eval, wo, pdf, sampled_roughness, eta);
break;
case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
label = bsdf_principled_diffuse_sample(sc, Ng, sd->wi, rand.x, rand.y, eval, wo, pdf);
label = bsdf_principled_diffuse_sample(sc, Ng, sd->wi, rand_xy, eval, wo, pdf);
*sampled_roughness = one_float2();
*eta = 1.0f;
break;
case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
label = bsdf_principled_sheen_sample(sc, Ng, sd->wi, rand.x, rand.y, eval, wo, pdf);
label = bsdf_principled_sheen_sample(sc, Ng, sd->wi, rand_xy, eval, wo, pdf);
*sampled_roughness = one_float2();
*eta = 1.0f;
break;

@ -111,24 +111,19 @@ ccl_device_forceinline Spectrum bsdf_ashikhmin_shirley_eval(ccl_private const Sh
return make_spectrum(out);
}
ccl_device_inline void bsdf_ashikhmin_shirley_sample_first_quadrant(float n_x,
float n_y,
float randu,
float randv,
ccl_private float *phi,
ccl_private float *cos_theta)
ccl_device_inline void bsdf_ashikhmin_shirley_sample_first_quadrant(
float n_x, float n_y, const float2 rand, ccl_private float *phi, ccl_private float *cos_theta)
{
*phi = atanf(sqrtf((n_x + 1.0f) / (n_y + 1.0f)) * tanf(M_PI_2_F * randu));
*phi = atanf(sqrtf((n_x + 1.0f) / (n_y + 1.0f)) * tanf(M_PI_2_F * rand.x));
float cos_phi = cosf(*phi);
float sin_phi = sinf(*phi);
*cos_theta = powf(randv, 1.0f / (n_x * cos_phi * cos_phi + n_y * sin_phi * sin_phi + 1.0f));
*cos_theta = powf(rand.y, 1.0f / (n_x * cos_phi * cos_phi + n_y * sin_phi * sin_phi + 1.0f));
}
ccl_device int bsdf_ashikhmin_shirley_sample(ccl_private const ShaderClosure *sc,
float3 Ng,
float3 wi,
float randu,
float randv,
float2 rand,
ccl_private Spectrum *eval,
ccl_private float3 *wo,
ccl_private float *pdf,
@ -162,32 +157,28 @@ ccl_device int bsdf_ashikhmin_shirley_sample(ccl_private const ShaderClosure *sc
float cos_theta;
if (n_x == n_y) {
/* isotropic sampling */
phi = M_2PI_F * randu;
cos_theta = powf(randv, 1.0f / (n_x + 1.0f));
phi = M_2PI_F * rand.x;
cos_theta = powf(rand.y, 1.0f / (n_x + 1.0f));
}
else {
/* anisotropic sampling */
if (randu < 0.25f) { /* first quadrant */
float remapped_randu = 4.0f * randu;
bsdf_ashikhmin_shirley_sample_first_quadrant(
n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
if (rand.x < 0.25f) { /* first quadrant */
rand.x *= 4.0f;
bsdf_ashikhmin_shirley_sample_first_quadrant(n_x, n_y, rand, &phi, &cos_theta);
}
else if (randu < 0.5f) { /* second quadrant */
float remapped_randu = 4.0f * (.5f - randu);
bsdf_ashikhmin_shirley_sample_first_quadrant(
n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
else if (rand.x < 0.5f) { /* second quadrant */
rand.x = 4.0f * (0.5f - rand.x);
bsdf_ashikhmin_shirley_sample_first_quadrant(n_x, n_y, rand, &phi, &cos_theta);
phi = M_PI_F - phi;
}
else if (randu < 0.75f) { /* third quadrant */
float remapped_randu = 4.0f * (randu - 0.5f);
bsdf_ashikhmin_shirley_sample_first_quadrant(
n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
else if (rand.x < 0.75f) { /* third quadrant */
rand.x = 4.0f * (rand.x - 0.5f);
bsdf_ashikhmin_shirley_sample_first_quadrant(n_x, n_y, rand, &phi, &cos_theta);
phi = M_PI_F + phi;
}
else { /* fourth quadrant */
float remapped_randu = 4.0f * (1.0f - randu);
bsdf_ashikhmin_shirley_sample_first_quadrant(
n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
rand.x = 4.0f * (1.0f - rand.x);
bsdf_ashikhmin_shirley_sample_first_quadrant(n_x, n_y, rand, &phi, &cos_theta);
phi = 2.0f * M_PI_F - phi;
}
}

@ -78,8 +78,7 @@ ccl_device Spectrum bsdf_ashikhmin_velvet_eval(ccl_private const ShaderClosure *
ccl_device int bsdf_ashikhmin_velvet_sample(ccl_private const ShaderClosure *sc,
float3 Ng,
float3 wi,
float randu,
float randv,
const float2 rand,
ccl_private Spectrum *eval,
ccl_private float3 *wo,
ccl_private float *pdf)
@ -90,7 +89,7 @@ ccl_device int bsdf_ashikhmin_velvet_sample(ccl_private const ShaderClosure *sc,
// we are viewing the surface from above - send a ray out with uniform
// distribution over the hemisphere
sample_uniform_hemisphere(N, randu, randv, wo, pdf);
sample_uniform_hemisphere(N, rand, wo, pdf);
if (!(dot(Ng, *wo) > 0)) {
*pdf = 0.0f;

@ -42,8 +42,7 @@ ccl_device Spectrum bsdf_diffuse_eval(ccl_private const ShaderClosure *sc,
ccl_device int bsdf_diffuse_sample(ccl_private const ShaderClosure *sc,
float3 Ng,
float3 wi,
float randu,
float randv,
float2 rand,
ccl_private Spectrum *eval,
ccl_private float3 *wo,
ccl_private float *pdf)
@ -52,7 +51,7 @@ ccl_device int bsdf_diffuse_sample(ccl_private const ShaderClosure *sc,
float3 N = bsdf->N;
// distribution over the hemisphere
sample_cos_hemisphere(N, randu, randv, wo, pdf);
sample_cos_hemisphere(N, rand, wo, pdf);
if (dot(Ng, *wo) > 0.0f) {
*eval = make_spectrum(*pdf);
@ -88,8 +87,7 @@ ccl_device Spectrum bsdf_translucent_eval(ccl_private const ShaderClosure *sc,
ccl_device int bsdf_translucent_sample(ccl_private const ShaderClosure *sc,
float3 Ng,
float3 wi,
float randu,
float randv,
float2 rand,
ccl_private Spectrum *eval,
ccl_private float3 *wo,
ccl_private float *pdf)
@ -99,7 +97,7 @@ ccl_device int bsdf_translucent_sample(ccl_private const ShaderClosure *sc,
// we are viewing the surface from the right side - send a ray out with cosine
// distribution over the hemisphere
sample_cos_hemisphere(-N, randu, randv, wo, pdf);
sample_cos_hemisphere(-N, rand, wo, pdf);
if (dot(Ng, *wo) < 0) {
*eval = make_spectrum(*pdf);
}

@ -67,8 +67,7 @@ ccl_device Spectrum bsdf_diffuse_ramp_eval(ccl_private const ShaderClosure *sc,
ccl_device int bsdf_diffuse_ramp_sample(ccl_private const ShaderClosure *sc,
float3 Ng,
float3 wi,
float randu,
float randv,
float2 rand,
ccl_private Spectrum *eval,
ccl_private float3 *wo,
ccl_private float *pdf)
@ -77,7 +76,7 @@ ccl_device int bsdf_diffuse_ramp_sample(ccl_private const ShaderClosure *sc,
float3 N = bsdf->N;
// distribution over the hemisphere
sample_cos_hemisphere(N, randu, randv, wo, pdf);
sample_cos_hemisphere(N, rand, wo, pdf);
if (dot(Ng, *wo) > 0.0f) {
*eval = rgb_to_spectrum(bsdf_diffuse_ramp_get_color(bsdf->colors, *pdf * M_PI_F) * M_1_PI_F);

@ -143,8 +143,7 @@ ccl_device Spectrum bsdf_hair_transmission_eval(ccl_private const ShaderClosure
ccl_device int bsdf_hair_reflection_sample(ccl_private const ShaderClosure *sc,
float3 Ng,
float3 wi,
float randu,
float randv,
float2 rand,
ccl_private Spectrum *eval,
ccl_private float3 *wo,
ccl_private float *pdf,
@ -165,7 +164,7 @@ ccl_device int bsdf_hair_reflection_sample(ccl_private const ShaderClosure *sc,
float a_R = fast_atan2f(((M_PI_2_F + theta_r) * 0.5f - offset) * roughness1_inv, 1.0f);
float b_R = fast_atan2f(((-M_PI_2_F + theta_r) * 0.5f - offset) * roughness1_inv, 1.0f);
float t = roughness1 * tanf(randu * (a_R - b_R) + b_R);
float t = roughness1 * tanf(rand.x * (a_R - b_R) + b_R);
float theta_h = t + offset;
float theta_i = 2 * theta_h - theta_r;
@ -173,7 +172,7 @@ ccl_device int bsdf_hair_reflection_sample(ccl_private const ShaderClosure *sc,
float costheta_i, sintheta_i;
fast_sincosf(theta_i, &sintheta_i, &costheta_i);
float phi = 2 * safe_asinf(1 - 2 * randv) * roughness2;
float phi = 2 * safe_asinf(1 - 2 * rand.y) * roughness2;
float phi_pdf = fast_cosf(phi * 0.5f) * 0.25f / roughness2;
@ -196,8 +195,7 @@ ccl_device int bsdf_hair_reflection_sample(ccl_private const ShaderClosure *sc,
ccl_device int bsdf_hair_transmission_sample(ccl_private const ShaderClosure *sc,
float3 Ng,
float3 wi,
float randu,
float randv,
float2 rand,
ccl_private Spectrum *eval,
ccl_private float3 *wo,
ccl_private float *pdf,
@ -219,7 +217,7 @@ ccl_device int bsdf_hair_transmission_sample(ccl_private const ShaderClosure *sc
float b_TT = fast_atan2f(((-M_PI_2_F + theta_r) / 2 - offset) * roughness1_inv, 1.0f);
float c_TT = 2 * fast_atan2f(M_PI_2_F / roughness2, 1.0f);
float t = roughness1 * tanf(randu * (a_TT - b_TT) + b_TT);
float t = roughness1 * tanf(rand.x * (a_TT - b_TT) + b_TT);
float theta_h = t + offset;
float theta_i = 2 * theta_h - theta_r;
@ -227,7 +225,7 @@ ccl_device int bsdf_hair_transmission_sample(ccl_private const ShaderClosure *sc
float costheta_i, sintheta_i;
fast_sincosf(theta_i, &sintheta_i, &costheta_i);
float p = roughness2 * tanf(c_TT * (randv - 0.5f));
float p = roughness2 * tanf(c_TT * (rand.y - 0.5f));
float phi = p + M_PI_F;
float theta_pdf = roughness1 /
(2 * (t * t + roughness1 * roughness1) * (a_TT - b_TT) * costheta_i);

@ -336,9 +336,7 @@ ccl_device Spectrum bsdf_principled_hair_eval(KernelGlobals kg,
ccl_device int bsdf_principled_hair_sample(KernelGlobals kg,
ccl_private const ShaderClosure *sc,
ccl_private ShaderData *sd,
float randu,
float randv,
float randw,
float3 rand,
ccl_private Spectrum *eval,
ccl_private float3 *wo,
ccl_private float *pdf,
@ -381,12 +379,12 @@ ccl_device int bsdf_principled_hair_sample(KernelGlobals kg,
int p = 0;
for (; p < 3; p++) {
if (randw < Ap_energy[p]) {
if (rand.z < Ap_energy[p]) {
break;
}
randw -= Ap_energy[p];
rand.z -= Ap_energy[p];
}
randw /= Ap_energy[p];
rand.z /= Ap_energy[p];
float v = bsdf->v;
if (p == 1) {
@ -396,9 +394,10 @@ ccl_device int bsdf_principled_hair_sample(KernelGlobals kg,
v *= 4.0f;
}
randw = max(randw, 1e-5f);
const float fac = 1.0f + v * logf(randw + (1.0f - randw) * expf(-2.0f / v));
float sin_theta_i = -fac * sin_theta_o + cos_from_sin(fac) * cosf(M_2PI_F * randv) * cos_theta_o;
rand.z = max(rand.z, 1e-5f);
const float fac = 1.0f + v * logf(rand.z + (1.0f - rand.z) * expf(-2.0f / v));
float sin_theta_i = -fac * sin_theta_o +
cos_from_sin(fac) * cosf(M_2PI_F * rand.y) * cos_theta_o;
float cos_theta_i = cos_from_sin(sin_theta_i);
float angles[6];
@ -410,10 +409,10 @@ ccl_device int bsdf_principled_hair_sample(KernelGlobals kg,
float phi;
if (p < 3) {
phi = delta_phi(p, gamma_o, gamma_t) + sample_trimmed_logistic(randu, bsdf->s);
phi = delta_phi(p, gamma_o, gamma_t) + sample_trimmed_logistic(rand.x, bsdf->s);
}
else {
phi = M_2PI_F * randu;
phi = M_2PI_F * rand.x;
}
const float phi_i = phi_o + phi;

@ -76,8 +76,7 @@ static_assert(sizeof(ShaderClosure) >= sizeof(MicrofacetBsdf), "MicrofacetBsdf i
ccl_device_forceinline float3 microfacet_beckmann_sample_vndf(const float3 wi,
const float alpha_x,
const float alpha_y,
const float randu,
const float randv)
const float2 rand)
{
/* 1. stretch wi */
float3 wi_ = make_float3(alpha_x * wi.x, alpha_y * wi.y, wi.z);
@ -90,8 +89,8 @@ ccl_device_forceinline float3 microfacet_beckmann_sample_vndf(const float3 wi,
if (wi_.z >= 0.99999f) {
/* Special case (normal incidence). */
const float r = sqrtf(-logf(randu));
const float phi = M_2PI_F * randv;
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);
}
@ -125,8 +124,8 @@ ccl_device_forceinline float3 microfacet_beckmann_sample_vndf(const float3 wi,
* solve y = 1 + b + K * (1 - b * b)
*/
const float K = tan_theta_i * SQRT_PI_INV;
const float y_approx = randu * (1.0f + erf_a + K * (1 - erf_a * erf_a));
const float y_exact = randu * (1.0f + erf_a + K * exp_a2);
const float y_approx = rand.x * (1.0f + erf_a + K * (1 - erf_a * erf_a));
const float y_exact = rand.x * (1.0f + erf_a + K * exp_a2);
float b = K > 0 ? (0.5f - sqrtf(K * (K - y_approx + 1.0f) + 0.25f)) / K : y_approx - 1.0f;
float inv_erf = fast_ierff(b);
@ -155,7 +154,7 @@ ccl_device_forceinline float3 microfacet_beckmann_sample_vndf(const float3 wi,
}
slope_x = inv_erf;
slope_y = fast_ierff(2.0f * randv - 1.0f);
slope_y = fast_ierff(2.0f * rand.y - 1.0f);
}
/* 3. rotate */
@ -178,8 +177,7 @@ ccl_device_forceinline float3 microfacet_beckmann_sample_vndf(const float3 wi,
ccl_device_forceinline float3 microfacet_ggx_sample_vndf(const float3 wi,
const float alpha_x,
const float alpha_y,
const float randu,
const float randv)
const float2 rand)
{
/* Section 3.2: Transforming the view direction to the hemisphere configuration. */
float3 wi_ = normalize(make_float3(alpha_x * wi.x, alpha_y * wi.y, wi.z));
@ -198,7 +196,7 @@ ccl_device_forceinline float3 microfacet_ggx_sample_vndf(const float3 wi,
}
/* Section 4.2: Parameterization of the projected area. */
float2 t = concentric_sample_disk(randu, randv);
float2 t = concentric_sample_disk(rand);
t.y = mix(safe_sqrtf(1.0f - sqr(t.x)), t.y, 0.5f * (1.0f + wi_.z));
/* Section 4.3: Reprojection onto hemisphere. */
@ -467,9 +465,7 @@ ccl_device int bsdf_microfacet_sample(ccl_private const ShaderClosure *sc,
const int path_flag,
float3 Ng,
float3 wi,
float randu,
float randv,
float randw,
const float3 rand,
ccl_private Spectrum *eval,
ccl_private float3 *wo,
ccl_private float *pdf,
@ -513,11 +509,11 @@ ccl_device int bsdf_microfacet_sample(ccl_private const ShaderClosure *sc,
* space before and after sampling. */
local_I = make_float3(dot(X, wi), dot(Y, wi), cos_NI);
if (m_type == MicrofacetType::GGX) {
local_H = microfacet_ggx_sample_vndf(local_I, alpha_x, alpha_y, randu, randv);
local_H = microfacet_ggx_sample_vndf(local_I, alpha_x, alpha_y, float3_to_float2(rand));
}
else {
/* m_type == MicrofacetType::BECKMANN */
local_H = microfacet_beckmann_sample_vndf(local_I, alpha_x, alpha_y, randu, randv);
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;
@ -545,7 +541,7 @@ ccl_device int bsdf_microfacet_sample(ccl_private const ShaderClosure *sc,
* excessive noise for reflection highlights. */
float reflect_pdf = (path_flag & PATH_RAY_CAMERA) ? clamp(fresnel, 0.125f, 0.875f) :
fresnel;
do_refract = (randw >= reflect_pdf);
do_refract = (rand.z >= reflect_pdf);
lobe_pdf = do_refract ? (1.0f - reflect_pdf) : reflect_pdf;
}
}
@ -764,9 +760,7 @@ ccl_device int bsdf_microfacet_ggx_sample(ccl_private const ShaderClosure *sc,
const int path_flag,
float3 Ng,
float3 wi,
float randu,
float randv,
float randw,
const float3 rand,
ccl_private Spectrum *eval,
ccl_private float3 *wo,
ccl_private float *pdf,
@ -774,7 +768,7 @@ ccl_device int bsdf_microfacet_ggx_sample(ccl_private const ShaderClosure *sc,
ccl_private float *eta)
{
return bsdf_microfacet_sample<MicrofacetType::GGX>(
sc, path_flag, Ng, wi, randu, randv, randw, eval, wo, pdf, sampled_roughness, eta);
sc, path_flag, Ng, wi, rand, eval, wo, pdf, sampled_roughness, eta);
}
/* Beckmann microfacet with Smith shadow-masking from:
@ -833,9 +827,7 @@ ccl_device int bsdf_microfacet_beckmann_sample(ccl_private const ShaderClosure *
const int path_flag,
float3 Ng,
float3 wi,
float randu,
float randv,
float randw,
const float3 rand,
ccl_private Spectrum *eval,
ccl_private float3 *wo,
ccl_private float *pdf,
@ -843,7 +835,7 @@ ccl_device int bsdf_microfacet_beckmann_sample(ccl_private const ShaderClosure *
ccl_private float *eta)
{
return bsdf_microfacet_sample<MicrofacetType::BECKMANN>(
sc, path_flag, Ng, wi, randu, randv, randw, eval, wo, pdf, sampled_roughness, eta);
sc, path_flag, Ng, wi, rand, eval, wo, pdf, sampled_roughness, eta);
}
/* Specular interface, not really a microfacet model but close enough that sharing code makes
@ -889,9 +881,7 @@ ccl_device int bsdf_microfacet_sharp_sample(ccl_private const ShaderClosure *sc,
const int path_flag,
float3 Ng,
float3 wi,
float randu,
float randv,
float randw,
const float3 rand,
ccl_private Spectrum *eval,
ccl_private float3 *wo,
ccl_private float *pdf,
@ -899,7 +889,7 @@ ccl_device int bsdf_microfacet_sharp_sample(ccl_private const ShaderClosure *sc,
ccl_private float *eta)
{
return bsdf_microfacet_sample<MicrofacetType::SHARP>(
sc, path_flag, Ng, wi, randu, randv, randw, eval, wo, pdf, sampled_roughness, eta);
sc, path_flag, Ng, wi, rand, eval, wo, pdf, sampled_roughness, eta);
}
CCL_NAMESPACE_END

@ -66,14 +66,13 @@ ccl_device Spectrum bsdf_oren_nayar_eval(ccl_private const ShaderClosure *sc,
ccl_device int bsdf_oren_nayar_sample(ccl_private const ShaderClosure *sc,
float3 Ng,
float3 wi,
float randu,
float randv,
float2 rand,
ccl_private Spectrum *eval,
ccl_private float3 *wo,
ccl_private float *pdf)
{
ccl_private const OrenNayarBsdf *bsdf = (ccl_private const OrenNayarBsdf *)sc;
sample_uniform_hemisphere(bsdf->N, randu, randv, wo, pdf);
sample_uniform_hemisphere(bsdf->N, rand, wo, pdf);
if (dot(Ng, *wo) > 0.0f) {
*eval = bsdf_oren_nayar_get_intensity(sc, bsdf->N, wi, *wo);

@ -78,8 +78,7 @@ ccl_device_inline float phong_ramp_exponent_to_roughness(float exponent)
ccl_device int bsdf_phong_ramp_sample(ccl_private const ShaderClosure *sc,
float3 Ng,
float3 wi,
float randu,
float randv,
const float2 rand,
ccl_private Spectrum *eval,
ccl_private float3 *wo,
ccl_private float *pdf,
@ -96,8 +95,8 @@ ccl_device int bsdf_phong_ramp_sample(ccl_private const ShaderClosure *sc,
float3 R = (2 * cosNI) * bsdf->N - wi;
float3 T, B;
make_orthonormals(R, &T, &B);
float phi = M_2PI_F * randu;
float cosTheta = powf(randv, 1 / (m_exponent + 1));
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;

@ -132,8 +132,7 @@ ccl_device Spectrum bsdf_principled_diffuse_eval(ccl_private const ShaderClosure
ccl_device int bsdf_principled_diffuse_sample(ccl_private const ShaderClosure *sc,
float3 Ng,
float3 wi,
float randu,
float randv,
float2 rand,
ccl_private Spectrum *eval,
ccl_private float3 *wo,
ccl_private float *pdf)
@ -142,7 +141,7 @@ ccl_device int bsdf_principled_diffuse_sample(ccl_private const ShaderClosure *s
float3 N = bsdf->N;
sample_cos_hemisphere(N, randu, randv, wo, pdf);
sample_cos_hemisphere(N, rand, wo, pdf);
if (dot(Ng, *wo) > 0) {
*eval = bsdf_principled_diffuse_compute_brdf(bsdf, N, wi, *wo, pdf);

@ -84,8 +84,7 @@ ccl_device Spectrum bsdf_principled_sheen_eval(ccl_private const ShaderClosure *
ccl_device int bsdf_principled_sheen_sample(ccl_private const ShaderClosure *sc,
float3 Ng,
float3 wi,
float randu,
float randv,
float2 rand,
ccl_private Spectrum *eval,
ccl_private float3 *wo,
ccl_private float *pdf)
@ -94,7 +93,7 @@ ccl_device int bsdf_principled_sheen_sample(ccl_private const ShaderClosure *sc,
float3 N = bsdf->N;
sample_cos_hemisphere(N, randu, randv, wo, pdf);
sample_cos_hemisphere(N, rand, wo, pdf);
if (dot(Ng, *wo) > 0) {
float3 H = normalize(wi + *wo);

@ -79,8 +79,7 @@ ccl_device Spectrum bsdf_diffuse_toon_eval(ccl_private const ShaderClosure *sc,
ccl_device int bsdf_diffuse_toon_sample(ccl_private const ShaderClosure *sc,
float3 Ng,
float3 wi,
float randu,
float randv,
float2 rand,
ccl_private Spectrum *eval,
ccl_private float3 *wo,
ccl_private float *pdf)
@ -89,10 +88,10 @@ ccl_device int bsdf_diffuse_toon_sample(ccl_private const ShaderClosure *sc,
float max_angle = bsdf->size * M_PI_2_F;
float smooth = bsdf->smooth * M_PI_2_F;
float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
float angle = sample_angle * randu;
float angle = sample_angle * rand.x;
if (sample_angle > 0.0f) {
sample_uniform_cone(bsdf->N, sample_angle, randu, randv, wo, pdf);
sample_uniform_cone(bsdf->N, sample_angle, rand, wo, pdf);
if (dot(Ng, *wo) > 0.0f) {
*eval = make_spectrum(*pdf * bsdf_toon_get_intensity(max_angle, smooth, angle));
@ -152,8 +151,7 @@ ccl_device Spectrum bsdf_glossy_toon_eval(ccl_private const ShaderClosure *sc,
ccl_device int bsdf_glossy_toon_sample(ccl_private const ShaderClosure *sc,
float3 Ng,
float3 wi,
float randu,
float randv,
float2 rand,
ccl_private Spectrum *eval,
ccl_private float3 *wo,
ccl_private float *pdf)
@ -168,9 +166,9 @@ ccl_device int bsdf_glossy_toon_sample(ccl_private const ShaderClosure *sc,
float3 R = (2 * cosNI) * bsdf->N - wi;
float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
float angle = sample_angle * randu;
float angle = sample_angle * rand.x;
sample_uniform_cone(R, sample_angle, randu, randv, wo, pdf);
sample_uniform_cone(R, sample_angle, rand, wo, pdf);
if (dot(Ng, *wo) > 0.0f) {
float cosNO = dot(bsdf->N, *wo);

@ -71,8 +71,6 @@ ccl_device Spectrum bsdf_transparent_eval(ccl_private const ShaderClosure *sc,
ccl_device int bsdf_transparent_sample(ccl_private const ShaderClosure *sc,
float3 Ng,
float3 wi,
float randu,
float randv,
ccl_private Spectrum *eval,
ccl_private float3 *wo,
ccl_private float *pdf)

@ -67,21 +67,20 @@ ccl_device Spectrum volume_henyey_greenstein_eval_phase(ccl_private const Shader
return make_spectrum(*pdf);
}
ccl_device float3
henyey_greenstrein_sample(float3 D, float g, float randu, float randv, ccl_private float *pdf)
ccl_device float3 henyey_greenstrein_sample(float3 D, float g, float2 rand, ccl_private float *pdf)
{
/* match pdf for small g */
float cos_theta;
bool isotropic = fabsf(g) < 1e-3f;
if (isotropic) {
cos_theta = (1.0f - 2.0f * randu);
cos_theta = (1.0f - 2.0f * rand.x);
if (pdf) {
*pdf = M_1_PI_F * 0.25f;
}
}
else {
float k = (1.0f - g * g) / (1.0f - g + 2.0f * g * randu);
float k = (1.0f - g * g) / (1.0f - g + 2.0f * g * rand.x);
cos_theta = (1.0f + g * g - k * k) / (2.0f * g);
if (pdf) {
*pdf = single_peaked_henyey_greenstein(cos_theta, g);
@ -89,7 +88,7 @@ henyey_greenstrein_sample(float3 D, float g, float randu, float randv, ccl_priva
}
float sin_theta = sin_from_cos(cos_theta);
float phi = M_2PI_F * randv;
float phi = M_2PI_F * rand.y;
float3 dir = make_float3(sin_theta * cosf(phi), sin_theta * sinf(phi), cos_theta);
float3 T, B;
@ -101,8 +100,7 @@ henyey_greenstrein_sample(float3 D, float g, float randu, float randv, ccl_priva
ccl_device int volume_henyey_greenstein_sample(ccl_private const ShaderVolumeClosure *svc,
float3 wi,
float randu,
float randv,
float2 rand,
ccl_private Spectrum *eval,
ccl_private float3 *wo,
ccl_private float *pdf)
@ -110,7 +108,7 @@ ccl_device int volume_henyey_greenstein_sample(ccl_private const ShaderVolumeClo
float g = svc->g;
/* note that wi points towards the viewer and so is used negated */
*wo = henyey_greenstrein_sample(-wi, g, randu, randv, pdf);
*wo = henyey_greenstrein_sample(-wi, g, rand, pdf);
*eval = make_spectrum(*pdf); /* perfect importance sampling */
return LABEL_VOLUME_SCATTER;
@ -128,13 +126,12 @@ ccl_device Spectrum volume_phase_eval(ccl_private const ShaderData *sd,
ccl_device int volume_phase_sample(ccl_private const ShaderData *sd,
ccl_private const ShaderVolumeClosure *svc,
float randu,
float randv,
float2 rand,
ccl_private Spectrum *eval,
ccl_private float3 *wo,
ccl_private float *pdf)
{
return volume_henyey_greenstein_sample(svc, sd->wi, randu, randv, eval, wo, pdf);
return volume_henyey_greenstein_sample(svc, sd->wi, rand, eval, wo, pdf);
}
/* Volume sampling utilities. */

@ -32,16 +32,11 @@ ccl_device_inline void integrate_camera_sample(KernelGlobals kg,
path_rng_3D(kg, rng_hash, sample, PRNG_LENS_TIME) :
zero_float3();
const float rand_time = rand_time_lens.x;
const float2 rand_lens = make_float2(rand_time_lens.y, rand_time_lens.z);
/* Generate camera ray. */
camera_sample(kg,
x,
y,
rand_filter.x,
rand_filter.y,
rand_time_lens.y,
rand_time_lens.z,
rand_time_lens.x,
ray);
camera_sample(kg, x, y, rand_filter, rand_time, rand_lens, ray);
}
/* Return false to indicate that this pixel is finished.

@ -254,9 +254,7 @@ ccl_device_forceinline void integrate_surface_direct_light(KernelGlobals kg,
if (!light_sample_from_position(kg,
rng_state,
rand_light.z,
rand_light.x,
rand_light.y,
rand_light,
sd->time,
sd->P,
sd->N,
@ -576,7 +574,7 @@ ccl_device_forceinline void integrate_surface_ao(KernelGlobals kg,
float3 ao_D;
float ao_pdf;
sample_cos_hemisphere(ao_N, rand_bsdf.x, rand_bsdf.y, &ao_D, &ao_pdf);
sample_cos_hemisphere(ao_N, rand_bsdf, &ao_D, &ao_pdf);
bool skip_self = true;

@ -710,9 +710,7 @@ ccl_device_forceinline bool integrate_volume_equiangular_sample_light(
LightSample ls ccl_optional_struct_init;
if (!light_sample_from_volume_segment(kg,
rand_light.z,
rand_light.x,
rand_light.y,
rand_light,
sd->time,
sd->P,
ray->D,
@ -776,9 +774,7 @@ ccl_device_forceinline void integrate_volume_direct_light(
if (!light_sample_from_position(kg,
rng_state,
rand_light.z,
rand_light.x,
rand_light.y,
rand_light,
sd->time,
P,
zero_float3(),

@ -180,7 +180,7 @@ ccl_device_inline bool subsurface_random_walk(KernelGlobals kg,
/* Sample diffuse surface scatter into the object. */
float3 D;
float pdf;
sample_cos_hemisphere(-N, rand_bsdf.x, rand_bsdf.y, &D, &pdf);
sample_cos_hemisphere(-N, rand_bsdf, &D, &pdf);
if (dot(-Ng, D) <= 0.0f) {
return false;
}
@ -326,8 +326,7 @@ ccl_device_inline bool subsurface_random_walk(KernelGlobals kg,
ray.D = newD;
}
else {
float3 newD = henyey_greenstrein_sample(
ray.D, anisotropy, rand_scatter.x, rand_scatter.y, &hg_pdf);
float3 newD = henyey_greenstrein_sample(ray.D, anisotropy, rand_scatter, &hg_pdf);
cos_theta = dot(newD, N);
ray.D = newD;
}

@ -317,8 +317,7 @@ ccl_device int volume_shader_phase_guided_sample(KernelGlobals kg,
else {
/* Sample phase. */
*phase_pdf = 0.0f;
label = volume_phase_sample(
sd, svc, rand_phase.x, rand_phase.y, &eval, wo, unguided_phase_pdf);
label = volume_phase_sample(sd, svc, rand_phase, &eval, wo, unguided_phase_pdf);
if (*unguided_phase_pdf != 0.0f) {
bsdf_eval_init(phase_eval, CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID, eval);
@ -357,7 +356,7 @@ ccl_device int volume_shader_phase_sample(KernelGlobals kg,
Spectrum eval = zero_spectrum();
*pdf = 0.0f;
int label = volume_phase_sample(sd, svc, rand_phase.x, rand_phase.y, &eval, wo, pdf);
int label = volume_phase_sample(sd, svc, rand_phase, &eval, wo, pdf);
if (*pdf != 0.0f) {
bsdf_eval_init(phase_eval, CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID, eval);

@ -19,8 +19,7 @@ ccl_device_inline float area_light_rect_sample(float3 P,
const float len_u,
const float3 axis_v,
const float len_v,
float randu,
float randv,
const float2 rand,
bool sample_coord)
{
/* In our name system we're using P for the center, which is o in the paper. */
@ -59,7 +58,7 @@ ccl_device_inline float area_light_rect_sample(float3 P,
if (sample_coord) {
/* Compute cu. */
float au = randu * S + k;
float au = rand.x * S + k;
float fu = (cosf(au) * b0 - b1) / sinf(au);
float cu = 1.0f / sqrtf(fu * fu + b0sq) * (fu > 0.0f ? 1.0f : -1.0f);
cu = clamp(cu, -1.0f, 1.0f);
@ -73,7 +72,7 @@ ccl_device_inline float area_light_rect_sample(float3 P,
float d = sqrtf(xu * xu + z0sq);
float h0 = y0 / sqrtf(d * d + y0sq);
float h1 = y1 / sqrtf(d * d + y1sq);
float hv = h0 + randv * (h1 - h0), hv2 = hv * hv;
float hv = h0 + rand.y * (h1 - h0), hv2 = hv * hv;
float yv = (hv2 < 1.0f - 1e-6f) ? (hv * d) / sqrtf(1.0f - hv2) : y1;
/* Transform (xu, yv, z0) to world coords. */
@ -233,8 +232,7 @@ ccl_device_inline bool area_light_eval(const ccl_global KernelLight *klight,
const float3 ray_P,
ccl_private float3 *light_P,
ccl_private LightSample *ccl_restrict ls,
float randu,
float randv,
const float2 rand,
bool sample_coord)
{
float3 axis_u = klight->area.axis_u;
@ -250,9 +248,8 @@ ccl_device_inline bool area_light_eval(const ccl_global KernelLight *klight,
if (in_volume_segment) {
light_P_new += sample_rectangle ?
rectangle_sample(
axis_u * len_u * 0.5f, axis_v * len_v * 0.5f, randu, randv) :
ellipse_sample(axis_u * len_u * 0.5f, axis_v * len_v * 0.5f, randu, randv);
rectangle_sample(axis_u * len_u * 0.5f, axis_v * len_v * 0.5f, rand) :
ellipse_sample(axis_u * len_u * 0.5f, axis_v * len_v * 0.5f, rand);
ls->pdf = invarea;
}
else {
@ -273,7 +270,7 @@ ccl_device_inline bool area_light_eval(const ccl_global KernelLight *klight,
if (sample_rectangle) {
ls->pdf = area_light_rect_sample(
ray_P, &light_P_new, axis_u, len_u, axis_v, len_v, randu, randv, sample_coord);
ray_P, &light_P_new, axis_u, len_u, axis_v, len_v, rand, sample_coord);
}
else {
if (klight->area.tan_half_spread == 0.0f) {
@ -281,8 +278,7 @@ ccl_device_inline bool area_light_eval(const ccl_global KernelLight *klight,
}
else {
if (sample_coord) {
light_P_new += ellipse_sample(
axis_u * len_u * 0.5f, axis_v * len_v * 0.5f, randu, randv);
light_P_new += ellipse_sample(axis_u * len_u * 0.5f, axis_v * len_v * 0.5f, rand);
}
ls->pdf = 4.0f * M_1_PI_F / (len_u * len_v);
}
@ -311,8 +307,7 @@ ccl_device_inline bool area_light_eval(const ccl_global KernelLight *klight,
template<bool in_volume_segment>
ccl_device_inline bool area_light_sample(const ccl_global KernelLight *klight,
const float randu,
const float randv,
const float2 rand,
const float3 P,
ccl_private LightSample *ls)
{
@ -325,7 +320,7 @@ ccl_device_inline bool area_light_sample(const ccl_global KernelLight *klight,
}
}
if (!area_light_eval<in_volume_segment>(klight, P, &ls->P, ls, randu, randv, true)) {
if (!area_light_eval<in_volume_segment>(klight, P, &ls->P, ls, rand, true)) {
return false;
}
@ -358,11 +353,11 @@ ccl_device_forceinline void area_light_update_position(const ccl_global KernelLi
{
if (klight->area.tan_half_spread == 0) {
/* Update position on the light to keep the direction fixed. */
area_light_eval<false>(klight, P, &ls->P, ls, 0, 0, true);
area_light_eval<false>(klight, P, &ls->P, ls, zero_float2(), true);
}
else {
ls->D = normalize_len(ls->P - P, &ls->t);
area_light_eval<false>(klight, P, &ls->P, ls, 0, 0, false);
area_light_eval<false>(klight, P, &ls->P, ls, zero_float2(), false);
/* Convert pdf to be in area measure. */
ls->pdf /= lamp_light_pdf(ls->Ng, -ls->D, ls->t);
}
@ -421,7 +416,7 @@ ccl_device_inline bool area_light_sample_from_intersection(
ls->Ng = klight->area.dir;
float3 light_P = klight->co;
return area_light_eval<false>(klight, ray_P, &light_P, ls, 0, 0, false);
return area_light_eval<false>(klight, ray_P, &light_P, ls, zero_float2(), false);
}
template<bool in_volume_segment>

@ -10,10 +10,7 @@ CCL_NAMESPACE_BEGIN
/* Background Light */
ccl_device float3 background_map_sample(KernelGlobals kg,
float randu,
float randv,
ccl_private float *pdf)
ccl_device float3 background_map_sample(KernelGlobals kg, float2 rand, ccl_private float *pdf)
{
/* for the following, the CDF values are actually a pair of floats, with the
* function value as X and the actual CDF as Y. The last entry's function
@ -30,7 +27,7 @@ ccl_device float3 background_map_sample(KernelGlobals kg,
int step = count >> 1;
int middle = first + step;
if (kernel_data_fetch(light_background_marginal_cdf, middle).y < randv) {
if (kernel_data_fetch(light_background_marginal_cdf, middle).y < rand.y) {
first = middle + 1;
count -= step + 1;
}
@ -46,7 +43,7 @@ ccl_device float3 background_map_sample(KernelGlobals kg,
float2 cdf_last_v = kernel_data_fetch(light_background_marginal_cdf, res_y);
/* importance-sampled V direction */
float dv = inverse_lerp(cdf_v.y, cdf_next_v.y, randv);
float dv = inverse_lerp(cdf_v.y, cdf_next_v.y, rand.y);
float v = (index_v + dv) / res_y;
/* This is basically std::lower_bound as used by PBRT. */
@ -57,7 +54,8 @@ ccl_device float3 background_map_sample(KernelGlobals kg,
int middle = first + step;
if (kernel_data_fetch(light_background_conditional_cdf, index_v * cdf_width + middle).y <
randu) {
rand.x)
{
first = middle + 1;
count -= step + 1;
}
@ -76,7 +74,7 @@ ccl_device float3 background_map_sample(KernelGlobals kg,
index_v * cdf_width + res_x);
/* importance-sampled U direction */
float du = inverse_lerp(cdf_u.y, cdf_next_u.y, randu);
float du = inverse_lerp(cdf_u.y, cdf_next_u.y, rand.x);
float u = (index_u + du) / res_x;
/* compute pdf */
@ -198,7 +196,7 @@ ccl_device_inline float background_portal_pdf(
}
else {
portal_pdf += area_light_rect_sample(
P, &lightpos, axis_u, len_u, axis_v, len_v, 0.0f, 0.0f, false);
P, &lightpos, axis_u, len_u, axis_v, len_v, zero_float2(), false);
}
}
@ -223,16 +221,15 @@ ccl_device int background_num_possible_portals(KernelGlobals kg, float3 P)
ccl_device float3 background_portal_sample(KernelGlobals kg,
float3 P,
float randu,
float randv,
float2 rand,
int num_possible,
ccl_private int *sampled_portal,
ccl_private float *pdf)
{
/* Pick a portal, then re-normalize randv. */
randv *= num_possible;
int portal = (int)randv;
randv -= portal;
/* Pick a portal, then re-normalize rand.y. */
rand.y *= num_possible;
int portal = (int)rand.y;
rand.y -= portal;
/* TODO(sergey): Some smarter way of finding portal to sample
* is welcome.
@ -255,14 +252,13 @@ ccl_device float3 background_portal_sample(KernelGlobals kg,
float3 D;
if (is_round) {
lightpos += ellipse_sample(axis_u * len_u * 0.5f, axis_v * len_v * 0.5f, randu, randv);
lightpos += ellipse_sample(axis_u * len_u * 0.5f, axis_v * len_v * 0.5f, rand);
float t;
D = normalize_len(lightpos - P, &t);
*pdf = fabsf(klight->area.invarea) * lamp_light_pdf(dir, -D, t);
}
else {
*pdf = area_light_rect_sample(
P, &lightpos, axis_u, len_u, axis_v, len_v, randu, randv, true);
*pdf = area_light_rect_sample(P, &lightpos, axis_u, len_u, axis_v, len_v, rand, true);
D = normalize(lightpos - P);
}
@ -278,14 +274,13 @@ ccl_device float3 background_portal_sample(KernelGlobals kg,
}
ccl_device_inline float3 background_sun_sample(KernelGlobals kg,
float randu,
float randv,
float2 rand,
ccl_private float *pdf)
{
float3 D;
const float3 N = float4_to_float3(kernel_data.background.sun);
const float angle = kernel_data.background.sun.w;
sample_uniform_cone(N, angle, randu, randv, &D, pdf);
sample_uniform_cone(N, angle, rand, &D, pdf);
return D;
}
@ -296,8 +291,10 @@ ccl_device_inline float background_sun_pdf(KernelGlobals kg, float3 D)
return pdf_uniform_cone(N, D, angle);
}
ccl_device_inline float3 background_light_sample(
KernelGlobals kg, float3 P, float randu, float randv, ccl_private float *pdf)
ccl_device_inline float3 background_light_sample(KernelGlobals kg,
float3 P,
float2 rand,
ccl_private float *pdf)
{
float portal_method_pdf = kernel_data.background.portal_weight;
float sun_method_pdf = kernel_data.background.sun_weight;
@ -316,7 +313,7 @@ ccl_device_inline float3 background_light_sample(
if (pdf_fac == 0.0f) {
/* Use uniform as a fallback if we can't use any strategy. */
*pdf = 1.0f / M_4PI_F;
return sample_uniform_sphere(randu, randv);
return sample_uniform_sphere(rand);
}
pdf_fac = 1.0f / pdf_fac;
@ -325,23 +322,23 @@ ccl_device_inline float3 background_light_sample(
map_method_pdf *= pdf_fac;
/* We have 100% in total and split it between the three categories.
* Therefore, we pick portals if randu is between 0 and portal_method_pdf,
* sun if randu is between portal_method_pdf and (portal_method_pdf + sun_method_pdf)
* and map if randu is between (portal_method_pdf + sun_method_pdf) and 1. */
* Therefore, we pick portals if rand.x is between 0 and portal_method_pdf,
* sun if rand.x is between portal_method_pdf and (portal_method_pdf + sun_method_pdf)
* and map if rand.x is between (portal_method_pdf + sun_method_pdf) and 1. */
float sun_method_cdf = portal_method_pdf + sun_method_pdf;
int method = 0;
float3 D;
if (randu < portal_method_pdf) {
if (rand.x < portal_method_pdf) {
method = 0;
/* Rescale randu. */
/* Rescale rand.x. */
if (portal_method_pdf != 1.0f) {
randu /= portal_method_pdf;
rand.x /= portal_method_pdf;
}
/* Sample a portal. */
int portal;
D = background_portal_sample(kg, P, randu, randv, num_portals, &portal, pdf);
D = background_portal_sample(kg, P, rand, num_portals, &portal, pdf);
if (num_portals > 1) {
/* Ignore the chosen portal, its pdf is already included. */
*pdf += background_portal_pdf(kg, P, D, portal, NULL);
@ -353,14 +350,14 @@ ccl_device_inline float3 background_light_sample(
}
*pdf *= portal_method_pdf;
}
else if (randu < sun_method_cdf) {
else if (rand.x < sun_method_cdf) {
method = 1;
/* Rescale randu. */
/* Rescale rand.x. */
if (sun_method_pdf != 1.0f) {
randu = (randu - portal_method_pdf) / sun_method_pdf;
rand.x = (rand.x - portal_method_pdf) / sun_method_pdf;
}
D = background_sun_sample(kg, randu, randv, pdf);
D = background_sun_sample(kg, rand, pdf);
/* Skip MIS if this is the only method. */
if (sun_method_pdf == 1.0f) {
@ -370,12 +367,12 @@ ccl_device_inline float3 background_light_sample(
}
else {
method = 2;
/* Rescale randu. */
/* Rescale rand.x. */
if (map_method_pdf != 1.0f) {
randu = (randu - sun_method_cdf) / map_method_pdf;
rand.x = (rand.x - sun_method_cdf) / map_method_pdf;
}
D = background_map_sample(kg, randu, randv, pdf);
D = background_map_sample(kg, rand, pdf);
/* Skip MIS if this is the only method. */
if (map_method_pdf == 1.0f) {

@ -28,24 +28,24 @@ typedef struct LightSample {
/* Utilities */
ccl_device_inline float3 ellipse_sample(float3 ru, float3 rv, float randu, float randv)
ccl_device_inline float3 ellipse_sample(float3 ru, float3 rv, float2 rand)
{
const float2 rand = concentric_sample_disk(randu, randv);
return ru * rand.x + rv * rand.y;
const float2 uv = concentric_sample_disk(rand);
return ru * uv.x + rv * uv.y;
}
ccl_device_inline float3 rectangle_sample(float3 ru, float3 rv, float randu, float randv)
ccl_device_inline float3 rectangle_sample(float3 ru, float3 rv, float2 rand)
{
return ru * (2.0f * randu - 1.0f) + rv * (2.0f * randv - 1.0f);
return ru * (2.0f * rand.x - 1.0f) + rv * (2.0f * rand.y - 1.0f);
}
ccl_device float3 disk_light_sample(float3 v, float randu, float randv)
ccl_device float3 disk_light_sample(float3 n, float2 rand)
{
float3 ru, rv;
make_orthonormals(v, &ru, &rv);
make_orthonormals(n, &ru, &rv);
return ellipse_sample(ru, rv, randu, randv);
return ellipse_sample(ru, rv, rand);
}
ccl_device float lamp_light_pdf(const float3 Ng, const float3 I, float t)

@ -10,8 +10,7 @@
CCL_NAMESPACE_BEGIN
ccl_device_inline bool distant_light_sample(const ccl_global KernelLight *klight,
const float randu,
const float randv,
const float2 rand,
ccl_private LightSample *ls)
{
/* distant light */
@ -21,7 +20,7 @@ ccl_device_inline bool distant_light_sample(const ccl_global KernelLight *klight
float invarea = klight->distant.invarea;
if (radius > 0.0f) {
D = normalize(D + disk_light_sample(D, randu, randv) * radius);
D = normalize(D + disk_light_sample(D, rand) * radius);
}
ls->P = D;

@ -11,7 +11,7 @@ CCL_NAMESPACE_BEGIN
/* Simple CDF based sampling over all lights in the scene, without taking into
* account shading position or normal. */
ccl_device int light_distribution_sample(KernelGlobals kg, const float randn)
ccl_device int light_distribution_sample(KernelGlobals kg, const float rand)
{
/* This is basically std::upper_bound as used by PBRT, to find a point light or
* triangle to emit from, proportional to area. a good improvement would be to
@ -19,13 +19,12 @@ ccl_device int light_distribution_sample(KernelGlobals kg, const float randn)
* arbitrary shaders. */
int first = 0;
int len = kernel_data.integrator.num_distribution + 1;
float r = randn;
do {
int half_len = len >> 1;
int middle = first + half_len;
if (r < kernel_data_fetch(light_distribution, middle).totarea) {
if (rand < kernel_data_fetch(light_distribution, middle).totarea) {
len = half_len;
}
else {
@ -43,9 +42,7 @@ ccl_device int light_distribution_sample(KernelGlobals kg, const float randn)
template<bool in_volume_segment>
ccl_device_noinline bool light_distribution_sample(KernelGlobals kg,
const float randn,
const float randu,
const float randv,
const float3 rand,
const float time,
const float3 P,
const int object_receiver,
@ -54,10 +51,12 @@ ccl_device_noinline bool light_distribution_sample(KernelGlobals kg,
ccl_private LightSample *ls)
{
/* Sample light index from distribution. */
const int index = light_distribution_sample(kg, randn);
/* The first two dimensions of the Sobol sequence have better stratification. */
const int index = light_distribution_sample(kg, rand.z);
const float pdf_selection = kernel_data.integrator.distribution_pdf_lights;
const float2 rand_uv = float3_to_float2(rand);
return light_sample<in_volume_segment>(
kg, randu, randv, time, P, object_receiver, bounce, path_flag, index, 0, pdf_selection, ls);
kg, rand_uv, time, P, object_receiver, bounce, path_flag, index, 0, pdf_selection, ls);
}
ccl_device_inline float light_distribution_pdf_lamp(KernelGlobals kg)

@ -93,8 +93,7 @@ ccl_device_inline bool light_link_object_match(KernelGlobals kg,
template<bool in_volume_segment>
ccl_device_inline bool light_sample(KernelGlobals kg,
const int lamp,
const float randu,
const float randv,
const float2 rand,
const float3 P,
const uint32_t path_flag,
ccl_private LightSample *ls)
@ -112,8 +111,8 @@ ccl_device_inline bool light_sample(KernelGlobals kg,
ls->object = PRIM_NONE;
ls->prim = PRIM_NONE;
ls->lamp = lamp;
ls->u = randu;
ls->v = randv;
ls->u = rand.x;
ls->v = rand.y;
ls->group = lamp_lightgroup(kg, lamp);
if (in_volume_segment && (type == LIGHT_DISTANT || type == LIGHT_BACKGROUND)) {
@ -130,13 +129,13 @@ ccl_device_inline bool light_sample(KernelGlobals kg,
}
if (type == LIGHT_DISTANT) {
if (!distant_light_sample(klight, randu, randv, ls)) {
if (!distant_light_sample(klight, rand, ls)) {
return false;
}
}
else if (type == LIGHT_BACKGROUND) {
/* infinite area light (e.g. light dome or env light) */
float3 D = -background_light_sample(kg, P, randu, randv, &ls->pdf);
float3 D = -background_light_sample(kg, P, rand, &ls->pdf);
ls->P = D;
ls->Ng = D;
@ -145,18 +144,18 @@ ccl_device_inline bool light_sample(KernelGlobals kg,
ls->eval_fac = 1.0f;
}
else if (type == LIGHT_SPOT) {
if (!spot_light_sample<in_volume_segment>(klight, randu, randv, P, ls)) {
if (!spot_light_sample<in_volume_segment>(klight, rand, P, ls)) {
return false;
}
}
else if (type == LIGHT_POINT) {
if (!point_light_sample<in_volume_segment>(klight, randu, randv, P, ls)) {
if (!point_light_sample<in_volume_segment>(klight, rand, P, ls)) {
return false;
}
}
else {
/* area light */
if (!area_light_sample<in_volume_segment>(klight, randu, randv, P, ls)) {
if (!area_light_sample<in_volume_segment>(klight, rand, P, ls)) {
return false;
}
}
@ -168,8 +167,7 @@ ccl_device_inline bool light_sample(KernelGlobals kg,
template<bool in_volume_segment>
ccl_device_noinline bool light_sample(KernelGlobals kg,
const float randu,
const float randv,
const float2 rand,
const float time,
const float3 P,
const int object_receiver,
@ -218,7 +216,7 @@ ccl_device_noinline bool light_sample(KernelGlobals kg,
}
const int shader_flag = mesh_light.shader_flag;
if (!triangle_light_sample<in_volume_segment>(kg, prim, object, randu, randv, time, ls, P)) {
if (!triangle_light_sample<in_volume_segment>(kg, prim, object, rand, time, ls, P)) {
return false;
}
ls->shader |= shader_flag;
@ -234,7 +232,7 @@ ccl_device_noinline bool light_sample(KernelGlobals kg,
return false;
}
if (!light_sample<in_volume_segment>(kg, light, randu, randv, P, path_flag, ls)) {
if (!light_sample<in_volume_segment>(kg, light, rand, P, path_flag, ls)) {
return false;
}
}

@ -9,8 +9,7 @@ CCL_NAMESPACE_BEGIN
template<bool in_volume_segment>
ccl_device_inline bool point_light_sample(const ccl_global KernelLight *klight,
const float randu,
const float randv,
const float2 rand,
const float3 P,
ccl_private LightSample *ls)
{
@ -21,7 +20,7 @@ ccl_device_inline bool point_light_sample(const ccl_global KernelLight *klight,
ls->P = center;
if (radius > 0.0f) {
ls->P += disk_light_sample(lightN, randu, randv) * radius;
ls->P += disk_light_sample(lightN, rand) * radius;
}
ls->pdf = klight->spot.invarea;

@ -318,9 +318,7 @@ ccl_device_inline float light_sample_mis_weight_nee(KernelGlobals kg,
* Uses either a flat distribution or light tree. */
ccl_device_inline bool light_sample_from_volume_segment(KernelGlobals kg,
const float randn,
const float randu,
const float randv,
const float3 rand,
const float time,
const float3 P,
const float3 D,
@ -332,33 +330,20 @@ ccl_device_inline bool light_sample_from_volume_segment(KernelGlobals kg,
{
#ifdef __LIGHT_TREE__
if (kernel_data.integrator.use_light_tree) {
return light_tree_sample<true>(kg,
randn,
randu,
randv,
time,
P,
D,
t,
object_receiver,
SD_BSDF_HAS_TRANSMISSION,
bounce,
path_flag,
ls);
return light_tree_sample<true>(
kg, rand, time, P, D, t, object_receiver, SD_BSDF_HAS_TRANSMISSION, bounce, path_flag, ls);
}
else
#endif
{
return light_distribution_sample<true>(
kg, randn, randu, randv, time, P, object_receiver, bounce, path_flag, ls);
kg, rand, time, P, object_receiver, bounce, path_flag, ls);
}
}
ccl_device bool light_sample_from_position(KernelGlobals kg,
ccl_private const RNGState *rng_state,
const float randn,
const float randu,
const float randv,
const float3 rand,
const float time,
const float3 P,
const float3 N,
@ -370,25 +355,14 @@ ccl_device bool light_sample_from_position(KernelGlobals kg,
{
#ifdef __LIGHT_TREE__
if (kernel_data.integrator.use_light_tree) {
return light_tree_sample<false>(kg,
randn,
randu,
randv,
time,
P,
N,
0.0f,
object_receiver,
shader_flags,
bounce,
path_flag,
ls);
return light_tree_sample<false>(
kg, rand, time, P, N, 0.0f, object_receiver, shader_flags, bounce, path_flag, ls);
}
else
#endif
{
return light_distribution_sample<false>(
kg, randn, randu, randv, time, P, object_receiver, bounce, path_flag, ls);
kg, rand, time, P, object_receiver, bounce, path_flag, ls);
}
}

@ -18,8 +18,7 @@ ccl_device float spot_light_attenuation(const ccl_global KernelSpotLight *spot,
template<bool in_volume_segment>
ccl_device_inline bool spot_light_sample(const ccl_global KernelLight *klight,
const float randu,
const float randv,
const float2 rand,
const float3 P,
ccl_private LightSample *ls)
{
@ -33,7 +32,7 @@ ccl_device_inline bool spot_light_sample(const ccl_global KernelLight *klight,
if (radius > 0.0f) {
/* disk light */
ls->P += disk_light_sample(lightN, randu, randv) * radius;
ls->P += disk_light_sample(lightN, rand) * radius;
}
const float invarea = klight->spot.invarea;

@ -671,9 +671,7 @@ ccl_device int light_tree_root_node_index(KernelGlobals kg, const int object_rec
template<bool in_volume_segment>
ccl_device_noinline bool light_tree_sample(KernelGlobals kg,
float randn,
const float randu,
const float randv,
const float3 rand,
const float time,
const float3 P,
float3 N_or_D,
@ -694,6 +692,8 @@ ccl_device_noinline bool light_tree_sample(KernelGlobals kg,
int selected_emitter = -1;
int object_emitter = 0;
int node_index = light_tree_root_node_index(kg, object_receiver);
/* The first two dimensions of the Sobol sequence have better stratification. */
float rand_selection = rand.z;
float3 local_P = P;
@ -704,7 +704,7 @@ ccl_device_noinline bool light_tree_sample(KernelGlobals kg,
if (is_leaf(knode)) {
/* At a leaf node, we pick an emitter. */
selected_emitter = light_tree_cluster_select_emitter<in_volume_segment>(
kg, randn, local_P, N_or_D, t, has_transmission, &node_index, &pdf_selection);
kg, rand_selection, local_P, N_or_D, t, has_transmission, &node_index, &pdf_selection);
if (node_index < 0) {
break;
@ -730,7 +730,8 @@ ccl_device_noinline bool light_tree_sample(KernelGlobals kg,
float discard;
float total_prob = left_prob;
node_index = left_index;
sample_resevoir(right_index, 1.0f - left_prob, node_index, discard, total_prob, randn);
sample_resevoir(
right_index, 1.0f - left_prob, node_index, discard, total_prob, rand_selection);
pdf_leaf *= (node_index == left_index) ? left_prob : (1.0f - left_prob);
}
@ -741,8 +742,7 @@ ccl_device_noinline bool light_tree_sample(KernelGlobals kg,
pdf_selection *= pdf_leaf;
return light_sample<in_volume_segment>(kg,
randu,
randv,
float3_to_float2(rand),
time,
P,
object_receiver,

@ -122,8 +122,7 @@ template<bool in_volume_segment>
ccl_device_forceinline bool triangle_light_sample(KernelGlobals kg,
int prim,
int object,
float randu,
float randv,
const float2 rand,
float time,
ccl_private LightSample *ls,
const float3 P)
@ -191,14 +190,14 @@ ccl_device_forceinline bool triangle_light_sample(KernelGlobals kg,
/* precompute a few things
* these could be re-used to take several samples
* as they are independent of randu/randv */
* as they are independent of `rand` */
const float cos_c = dot(A, B);
const float sin_alpha = fast_sinf(alpha);
const float product = sin_alpha * cos_c;
/* Select a random sub-area of the spherical triangle
* and calculate the third vertex C_ of that new triangle */
const float phi = randu * solid_angle - alpha;
const float phi = rand.x * solid_angle - alpha;
float s, t;
fast_sincosf(phi, &s, &t);
const float u = t - cos_alpha;
@ -217,7 +216,7 @@ ccl_device_forceinline bool triangle_light_sample(KernelGlobals kg,
/* Finally, select a random point along the edge of the new triangle
* That point on the spherical triangle is the sampled ray direction */
const float z = 1.0f - randv * (1.0f - dot(C_, B));
const float z = 1.0f - rand.y * (1.0f - dot(C_, B));
ls->D = z * B + sin_from_cos(z) * safe_normalize(C_ - dot(C_, B) * B);
/* calculate intersection with the planar triangle */
@ -246,8 +245,8 @@ ccl_device_forceinline bool triangle_light_sample(KernelGlobals kg,
/* compute random point in triangle. From Eric Heitz's "A Low-Distortion Map Between Triangle
* and Square" */
float u = randu;
float v = randv;
float u = rand.x;
float v = rand.y;
if (v > u) {
u *= 0.5f;
v -= u;

@ -11,13 +11,13 @@
CCL_NAMESPACE_BEGIN
/* distribute uniform xy on [0,1] over unit disk [-1,1] */
ccl_device void to_unit_disk(ccl_private float *x, ccl_private float *y)
ccl_device void to_unit_disk(ccl_private float2 *rand)
{
float phi = M_2PI_F * (*x);
float r = sqrtf(*y);
float phi = M_2PI_F * rand->x;
float r = sqrtf(rand->y);
*x = r * cosf(phi);
*y = r * sinf(phi);
rand->x = r * cosf(phi);
rand->y = r * sinf(phi);
}
/* return an orthogonal tangent and bitangent given a normal and tangent that
@ -32,24 +32,29 @@ ccl_device void make_orthonormals_tangent(const float3 N,
}
/* sample direction with cosine weighted distributed in hemisphere */
ccl_device_inline void sample_cos_hemisphere(
const float3 N, float randu, float randv, ccl_private float3 *wo, ccl_private float *pdf)
ccl_device_inline void sample_cos_hemisphere(const float3 N,
float2 rand,
ccl_private float3 *wo,
ccl_private float *pdf)
{
to_unit_disk(&randu, &randv);
float costheta = sqrtf(max(1.0f - randu * randu - randv * randv, 0.0f));
to_unit_disk(&rand);
float costheta = safe_sqrtf(1.0f - len_squared(rand));
float3 T, B;
make_orthonormals(N, &T, &B);
*wo = randu * T + randv * B + costheta * N;
*wo = rand.x * T + rand.y * B + costheta * N;
*pdf = costheta * M_1_PI_F;
}
/* sample direction uniformly distributed in hemisphere */
ccl_device_inline void sample_uniform_hemisphere(
const float3 N, float randu, float randv, ccl_private float3 *wo, ccl_private float *pdf)
ccl_device_inline void sample_uniform_hemisphere(const float3 N,
const float2 rand,
ccl_private float3 *wo,
ccl_private float *pdf)
{
float z = randu;
float r = sqrtf(max(0.0f, 1.0f - z * z));
float phi = M_2PI_F * randv;
float z = 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);
@ -60,17 +65,13 @@ ccl_device_inline void sample_uniform_hemisphere(
}
/* sample direction uniformly distributed in cone */
ccl_device_inline void sample_uniform_cone(const float3 N,
float angle,
float randu,
float randv,
ccl_private float3 *wo,
ccl_private float *pdf)
ccl_device_inline void sample_uniform_cone(
const float3 N, float angle, const float2 rand, ccl_private float3 *wo, ccl_private float *pdf)
{
const float cosThetaMin = cosf(angle);
const float cosTheta = mix(cosThetaMin, 1.0f, randu);
const float cosTheta = mix(cosThetaMin, 1.0f, rand.x);
const float sinTheta = sin_from_cos(cosTheta);
const float phi = M_2PI_F * randv;
const float phi = M_2PI_F * rand.y;
const float x = sinTheta * cosf(phi);
const float y = sinTheta * sinf(phi);
const float z = cosTheta;
@ -92,11 +93,11 @@ ccl_device_inline float pdf_uniform_cone(const float3 N, float3 D, float angle)
}
/* sample uniform point on the surface of a sphere */
ccl_device float3 sample_uniform_sphere(float u1, float u2)
ccl_device float3 sample_uniform_sphere(const float2 rand)
{
float z = 1.0f - 2.0f * u1;
float r = sqrtf(fmaxf(0.0f, 1.0f - z * z));
float phi = M_2PI_F * u2;
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);
@ -105,11 +106,11 @@ ccl_device float3 sample_uniform_sphere(float u1, float u2)
/* distribute uniform xy on [0,1] over unit disk [-1,1], with concentric mapping
* to better preserve stratification for some RNG sequences */
ccl_device float2 concentric_sample_disk(float u1, float u2)
ccl_device float2 concentric_sample_disk(const float2 rand)
{
float phi, r;
float a = 2.0f * u1 - 1.0f;
float b = 2.0f * u2 - 1.0f;
float a = 2.0f * rand.x - 1.0f;
float b = 2.0f * rand.y - 1.0f;
if (a == 0.0f && b == 0.0f) {
return zero_float2();
@ -127,8 +128,10 @@ ccl_device float2 concentric_sample_disk(float u1, float u2)
}
/* sample point in unit polygon with given number of corners and rotation */
ccl_device float2 regular_polygon_sample(float corners, float rotation, float u, float v)
ccl_device float2 regular_polygon_sample(float corners, float rotation, const float2 rand)
{
float u = rand.x, v = rand.y;
/* sample corner number and reuse u */
float corner = floorf(u * corners);
u = u * corners - corner;

@ -52,7 +52,7 @@ ccl_device float svm_ao(
const float2 rand_disk = path_branched_rng_2D(
kg, &rng_state, sample, num_samples, PRNG_SURFACE_AO);
float2 d = concentric_sample_disk(rand_disk.x, rand_disk.y);
float2 d = concentric_sample_disk(rand_disk);
float3 D = make_float3(d.x, d.y, safe_sqrtf(1.0f - dot(d, d)));
/* Create ray. */

@ -752,19 +752,15 @@ float Camera::world_to_raster_size(float3 P)
/* No differentials, just use from directly ahead. */
camera_sample_panorama(&kernel_camera,
kernel_camera_motion.data(),
0.5f * full_width,
0.5f * full_height,
0.0f,
0.0f,
0.5f * make_float2(full_width, full_height),
zero_float2(),
&ray);
}
#else
camera_sample_panorama(&kernel_camera,
kernel_camera_motion.data(),
0.5f * full_width,
0.5f * full_height,
0.0f,
0.0f,
0.5f * make_float2(full_width, full_height),
zero_float2(),
&ray);
#endif