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 */ /* 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; float blades = cam->blades;
float2 bokeh; float2 bokeh;
if (blades == 0.0f) { if (blades == 0.0f) {
/* sample disk */ /* sample disk */
bokeh = concentric_sample_disk(u, v); bokeh = concentric_sample_disk(rand);
} }
else { else {
/* sample polygon */ /* sample polygon */
float rotation = cam->bladesrotation; float rotation = cam->bladesrotation;
bokeh = regular_polygon_sample(blades, rotation, u, v); bokeh = regular_polygon_sample(blades, rotation, rand);
} }
/* anamorphic lens bokeh */ /* 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, ccl_device void camera_sample_perspective(KernelGlobals kg,
float raster_x, const float2 raster_xy,
float raster_y, const float2 rand_lens,
float lens_u,
float lens_v,
ccl_private Ray *ray) ccl_private Ray *ray)
{ {
/* create ray form raster position */ /* create ray form raster position */
ProjectionTransform rastertocamera = kernel_data.cam.rastertocamera; 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); float3 Pcamera = transform_perspective(&rastertocamera, raster);
if (kernel_data.cam.have_perspective_motion) { if (kernel_data.cam.have_perspective_motion) {
@ -71,14 +69,14 @@ ccl_device void camera_sample_perspective(KernelGlobals kg,
if (aperturesize > 0.0f) { if (aperturesize > 0.0f) {
/* sample point on aperture */ /* 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 */ /* compute point on plane of focus */
float ft = kernel_data.cam.focaldistance / D.z; float ft = kernel_data.cam.focaldistance / D.z;
float3 Pfocus = D * ft; float3 Pfocus = D * ft;
/* update ray for effect of lens */ /* 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); D = normalize(Pfocus - P);
} }
@ -133,7 +131,7 @@ ccl_device void camera_sample_perspective(KernelGlobals kg,
float3 Px = Pnostereo; float3 Px = Pnostereo;
float3 Dx = transform_perspective(&rastertocamera, 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)); Dx = normalize(transform_direction(&cameratoworld, Dx));
spherical_stereo_transform(&kernel_data.cam, &Px, &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 Py = Pnostereo;
float3 Dy = transform_perspective(&rastertocamera, 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)); Dy = normalize(transform_direction(&cameratoworld, Dy));
spherical_stereo_transform(&kernel_data.cam, &Py, &Dy); spherical_stereo_transform(&kernel_data.cam, &Py, &Dy);
@ -166,15 +164,13 @@ ccl_device void camera_sample_perspective(KernelGlobals kg,
/* Orthographic Camera */ /* Orthographic Camera */
ccl_device void camera_sample_orthographic(KernelGlobals kg, ccl_device void camera_sample_orthographic(KernelGlobals kg,
float raster_x, const float2 raster_xy,
float raster_y, const float2 rand_lens,
float lens_u,
float lens_v,
ccl_private Ray *ray) ccl_private Ray *ray)
{ {
/* create ray form raster position */ /* create ray form raster position */
ProjectionTransform rastertocamera = kernel_data.cam.rastertocamera; 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 P;
float3 D = make_float3(0.0f, 0.0f, 1.0f); 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) { if (aperturesize > 0.0f) {
/* sample point on aperture */ /* 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 */ /* compute point on plane of focus */
float3 Pfocus = D * kernel_data.cam.focaldistance; float3 Pfocus = D * kernel_data.cam.focaldistance;
/* update ray for effect of lens */ /* update ray for effect of lens */
float3 lensuvw = make_float3(lensuv.x, lensuv.y, 0.0f); float3 lens_uvw = float2_to_float3(lens_uv);
P = Pcamera + lensuvw; P = Pcamera + lens_uvw;
D = normalize(Pfocus - lensuvw); D = normalize(Pfocus - lens_uvw);
} }
else { else {
P = Pcamera; 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_device_inline void camera_sample_panorama(ccl_constant KernelCamera *cam,
ccl_global const DecomposedTransform *cam_motion, ccl_global const DecomposedTransform *cam_motion,
float raster_x, const float2 raster,
float raster_y, const float2 rand_lens,
float lens_u,
float lens_v,
ccl_private Ray *ray) ccl_private Ray *ray)
{ {
ProjectionTransform rastertocamera = cam->rastertocamera; 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 */ /* create ray form raster position */
float3 P = zero_float3(); float3 P = zero_float3();
@ -253,7 +247,7 @@ ccl_device_inline void camera_sample_panorama(ccl_constant KernelCamera *cam,
if (aperturesize > 0.0f) { if (aperturesize > 0.0f) {
/* sample point on aperture */ /* 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 */ /* compute point on plane of focus */
float3 Dfocus = normalize(D); float3 Dfocus = normalize(D);
@ -265,7 +259,7 @@ ccl_device_inline void camera_sample_panorama(ccl_constant KernelCamera *cam,
V = normalize(cross(Dfocus, U)); V = normalize(cross(Dfocus, U));
/* update ray for effect of lens */ /* 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); D = normalize(Pfocus - P);
} }
@ -302,7 +296,7 @@ ccl_device_inline void camera_sample_panorama(ccl_constant KernelCamera *cam,
Pcenter = transform_point(&cameratoworld, Pcenter); Pcenter = transform_point(&cameratoworld, Pcenter);
Dcenter = normalize(transform_direction(&cameratoworld, Dcenter)); 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); float3 Dx = panorama_to_direction(cam, Px.x, Px.y);
if (use_stereo) { if (use_stereo) {
spherical_stereo_transform(cam, &Px, &Dx); 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; dP.dx = Px - Pcenter;
dD.dx = Dx - Dcenter; 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); float3 Dy = panorama_to_direction(cam, Py.x, Py.y);
if (use_stereo) { if (use_stereo) {
spherical_stereo_transform(cam, &Py, &Dy); 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, ccl_device_inline void camera_sample(KernelGlobals kg,
int x, int x,
int y, int y,
float filter_u, const float2 filter_uv,
float filter_v, const float time,
float lens_u, const float2 lens_uv,
float lens_v,
float time,
ccl_private Ray *ray) ccl_private Ray *ray)
{ {
/* pixel filter */ /* pixel filter */
int filter_table_offset = kernel_data.tables.filter_table_offset; 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); const float2 raster = make_float2(
float raster_y = y + lookup_table_read(kg, filter_v, filter_table_offset, FILTER_TABLE_SIZE); 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 */ /* motion blur */
if (kernel_data.cam.shuttertime == -1.0f) { if (kernel_data.cam.shuttertime == -1.0f) {
@ -393,14 +386,14 @@ ccl_device_inline void camera_sample(KernelGlobals kg,
/* sample */ /* sample */
if (kernel_data.cam.type == CAMERA_PERSPECTIVE) { 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) { 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 { else {
ccl_global const DecomposedTransform *cam_motion = kernel_data_array(camera_motion); 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; *pdf = 0.f;
int label = LABEL_NONE; int label = LABEL_NONE;
const float3 Ng = (sd->type & PRIMITIVE_CURVE) ? sc->N : sd->Ng; const float3 Ng = (sd->type & PRIMITIVE_CURVE) ? sc->N : sd->Ng;
const float2 rand_xy = float3_to_float2(rand);
switch (sc->type) { switch (sc->type) {
case CLOSURE_BSDF_DIFFUSE_ID: 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(); *sampled_roughness = one_float2();
*eta = 1.0f; *eta = 1.0f;
break; break;
#if defined(__SVM__) || defined(__OSL__) #if defined(__SVM__) || defined(__OSL__)
case CLOSURE_BSDF_OREN_NAYAR_ID: 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(); *sampled_roughness = one_float2();
*eta = 1.0f; *eta = 1.0f;
break; break;
# ifdef __OSL__ # ifdef __OSL__
case CLOSURE_BSDF_PHONG_RAMP_ID: case CLOSURE_BSDF_PHONG_RAMP_ID:
label = bsdf_phong_ramp_sample( label = bsdf_phong_ramp_sample(sc, Ng, sd->wi, rand_xy, eval, wo, pdf, sampled_roughness);
sc, Ng, sd->wi, rand.x, rand.y, eval, wo, pdf, sampled_roughness);
*eta = 1.0f; *eta = 1.0f;
break; break;
case CLOSURE_BSDF_DIFFUSE_RAMP_ID: 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(); *sampled_roughness = one_float2();
*eta = 1.0f; *eta = 1.0f;
break; break;
# endif # endif
case CLOSURE_BSDF_TRANSLUCENT_ID: 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(); *sampled_roughness = one_float2();
*eta = 1.0f; *eta = 1.0f;
break; break;
case CLOSURE_BSDF_TRANSPARENT_ID: 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(); *sampled_roughness = zero_float2();
*eta = 1.0f; *eta = 1.0f;
break; break;
case CLOSURE_BSDF_REFLECTION_ID: case CLOSURE_BSDF_REFLECTION_ID:
case CLOSURE_BSDF_REFRACTION_ID: case CLOSURE_BSDF_REFRACTION_ID:
case CLOSURE_BSDF_SHARP_GLASS_ID: case CLOSURE_BSDF_SHARP_GLASS_ID:
label = bsdf_microfacet_sharp_sample(sc, label = bsdf_microfacet_sharp_sample(
path_flag, sc, path_flag, Ng, sd->wi, rand, eval, wo, pdf, sampled_roughness, eta);
Ng,
sd->wi,
rand.x,
rand.y,
rand.z,
eval,
wo,
pdf,
sampled_roughness,
eta);
break; break;
case CLOSURE_BSDF_MICROFACET_GGX_ID: case CLOSURE_BSDF_MICROFACET_GGX_ID:
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID: case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID: case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
case CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID: case CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID:
label = bsdf_microfacet_ggx_sample(sc, label = bsdf_microfacet_ggx_sample(
path_flag, sc, path_flag, Ng, sd->wi, rand, eval, wo, pdf, sampled_roughness, eta);
Ng,
sd->wi,
rand.x,
rand.y,
rand.z,
eval,
wo,
pdf,
sampled_roughness,
eta);
break; break;
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID: case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
label = bsdf_microfacet_multi_ggx_sample(kg, 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_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID: case CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID:
label = bsdf_microfacet_beckmann_sample(sc, label = bsdf_microfacet_beckmann_sample(
path_flag, sc, path_flag, Ng, sd->wi, rand, eval, wo, pdf, sampled_roughness, eta);
Ng,
sd->wi,
rand.x,
rand.y,
rand.z,
eval,
wo,
pdf,
sampled_roughness,
eta);
break; break;
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID: case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
label = bsdf_ashikhmin_shirley_sample( 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; *eta = 1.0f;
break; break;
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: 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(); *sampled_roughness = one_float2();
*eta = 1.0f; *eta = 1.0f;
break; break;
case CLOSURE_BSDF_DIFFUSE_TOON_ID: 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(); *sampled_roughness = one_float2();
*eta = 1.0f; *eta = 1.0f;
break; break;
case CLOSURE_BSDF_GLOSSY_TOON_ID: 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 // double check if this is valid
*sampled_roughness = one_float2(); *sampled_roughness = one_float2();
*eta = 1.0f; *eta = 1.0f;
break; break;
case CLOSURE_BSDF_HAIR_REFLECTION_ID: case CLOSURE_BSDF_HAIR_REFLECTION_ID:
label = bsdf_hair_reflection_sample( 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; *eta = 1.0f;
break; break;
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID: case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
label = bsdf_hair_transmission_sample( 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; *eta = 1.0f;
break; break;
case CLOSURE_BSDF_HAIR_PRINCIPLED_ID: case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
label = bsdf_principled_hair_sample( label = bsdf_principled_hair_sample(kg, sc, sd, rand, eval, wo, pdf, sampled_roughness, eta);
kg, sc, sd, rand.x, rand.y, rand.z, eval, wo, pdf, sampled_roughness, eta);
break; break;
case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID: 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(); *sampled_roughness = one_float2();
*eta = 1.0f; *eta = 1.0f;
break; break;
case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID: 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(); *sampled_roughness = one_float2();
*eta = 1.0f; *eta = 1.0f;
break; break;

@ -111,24 +111,19 @@ ccl_device_forceinline Spectrum bsdf_ashikhmin_shirley_eval(ccl_private const Sh
return make_spectrum(out); return make_spectrum(out);
} }
ccl_device_inline void bsdf_ashikhmin_shirley_sample_first_quadrant(float n_x, ccl_device_inline void bsdf_ashikhmin_shirley_sample_first_quadrant(
float n_y, float n_x, float n_y, const float2 rand, ccl_private float *phi, ccl_private float *cos_theta)
float randu,
float randv,
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 cos_phi = cosf(*phi);
float sin_phi = sinf(*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, ccl_device int bsdf_ashikhmin_shirley_sample(ccl_private const ShaderClosure *sc,
float3 Ng, float3 Ng,
float3 wi, float3 wi,
float randu, float2 rand,
float randv,
ccl_private Spectrum *eval, ccl_private Spectrum *eval,
ccl_private float3 *wo, ccl_private float3 *wo,
ccl_private float *pdf, ccl_private float *pdf,
@ -162,32 +157,28 @@ ccl_device int bsdf_ashikhmin_shirley_sample(ccl_private const ShaderClosure *sc
float cos_theta; float cos_theta;
if (n_x == n_y) { if (n_x == n_y) {
/* isotropic sampling */ /* isotropic sampling */
phi = M_2PI_F * randu; phi = M_2PI_F * rand.x;
cos_theta = powf(randv, 1.0f / (n_x + 1.0f)); cos_theta = powf(rand.y, 1.0f / (n_x + 1.0f));
} }
else { else {
/* anisotropic sampling */ /* anisotropic sampling */
if (randu < 0.25f) { /* first quadrant */ if (rand.x < 0.25f) { /* first quadrant */
float remapped_randu = 4.0f * randu; rand.x *= 4.0f;
bsdf_ashikhmin_shirley_sample_first_quadrant( bsdf_ashikhmin_shirley_sample_first_quadrant(n_x, n_y, rand, &phi, &cos_theta);
n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
} }
else if (randu < 0.5f) { /* second quadrant */ else if (rand.x < 0.5f) { /* second quadrant */
float remapped_randu = 4.0f * (.5f - randu); rand.x = 4.0f * (0.5f - rand.x);
bsdf_ashikhmin_shirley_sample_first_quadrant( bsdf_ashikhmin_shirley_sample_first_quadrant(n_x, n_y, rand, &phi, &cos_theta);
n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
phi = M_PI_F - phi; phi = M_PI_F - phi;
} }
else if (randu < 0.75f) { /* third quadrant */ else if (rand.x < 0.75f) { /* third quadrant */
float remapped_randu = 4.0f * (randu - 0.5f); rand.x = 4.0f * (rand.x - 0.5f);
bsdf_ashikhmin_shirley_sample_first_quadrant( bsdf_ashikhmin_shirley_sample_first_quadrant(n_x, n_y, rand, &phi, &cos_theta);
n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
phi = M_PI_F + phi; phi = M_PI_F + phi;
} }
else { /* fourth quadrant */ else { /* fourth quadrant */
float remapped_randu = 4.0f * (1.0f - randu); rand.x = 4.0f * (1.0f - rand.x);
bsdf_ashikhmin_shirley_sample_first_quadrant( bsdf_ashikhmin_shirley_sample_first_quadrant(n_x, n_y, rand, &phi, &cos_theta);
n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
phi = 2.0f * M_PI_F - phi; 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, ccl_device int bsdf_ashikhmin_velvet_sample(ccl_private const ShaderClosure *sc,
float3 Ng, float3 Ng,
float3 wi, float3 wi,
float randu, const float2 rand,
float randv,
ccl_private Spectrum *eval, ccl_private Spectrum *eval,
ccl_private float3 *wo, ccl_private float3 *wo,
ccl_private float *pdf) 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 // we are viewing the surface from above - send a ray out with uniform
// distribution over the hemisphere // distribution over the hemisphere
sample_uniform_hemisphere(N, randu, randv, wo, pdf); sample_uniform_hemisphere(N, rand, wo, pdf);
if (!(dot(Ng, *wo) > 0)) { if (!(dot(Ng, *wo) > 0)) {
*pdf = 0.0f; *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, ccl_device int bsdf_diffuse_sample(ccl_private const ShaderClosure *sc,
float3 Ng, float3 Ng,
float3 wi, float3 wi,
float randu, float2 rand,
float randv,
ccl_private Spectrum *eval, ccl_private Spectrum *eval,
ccl_private float3 *wo, ccl_private float3 *wo,
ccl_private float *pdf) ccl_private float *pdf)
@ -52,7 +51,7 @@ ccl_device int bsdf_diffuse_sample(ccl_private const ShaderClosure *sc,
float3 N = bsdf->N; float3 N = bsdf->N;
// distribution over the hemisphere // 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) { if (dot(Ng, *wo) > 0.0f) {
*eval = make_spectrum(*pdf); *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, ccl_device int bsdf_translucent_sample(ccl_private const ShaderClosure *sc,
float3 Ng, float3 Ng,
float3 wi, float3 wi,
float randu, float2 rand,
float randv,
ccl_private Spectrum *eval, ccl_private Spectrum *eval,
ccl_private float3 *wo, ccl_private float3 *wo,
ccl_private float *pdf) 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 // we are viewing the surface from the right side - send a ray out with cosine
// distribution over the hemisphere // distribution over the hemisphere
sample_cos_hemisphere(-N, randu, randv, wo, pdf); sample_cos_hemisphere(-N, rand, wo, pdf);
if (dot(Ng, *wo) < 0) { if (dot(Ng, *wo) < 0) {
*eval = make_spectrum(*pdf); *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, ccl_device int bsdf_diffuse_ramp_sample(ccl_private const ShaderClosure *sc,
float3 Ng, float3 Ng,
float3 wi, float3 wi,
float randu, float2 rand,
float randv,
ccl_private Spectrum *eval, ccl_private Spectrum *eval,
ccl_private float3 *wo, ccl_private float3 *wo,
ccl_private float *pdf) ccl_private float *pdf)
@ -77,7 +76,7 @@ ccl_device int bsdf_diffuse_ramp_sample(ccl_private const ShaderClosure *sc,
float3 N = bsdf->N; float3 N = bsdf->N;
// distribution over the hemisphere // 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) { 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); *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, ccl_device int bsdf_hair_reflection_sample(ccl_private const ShaderClosure *sc,
float3 Ng, float3 Ng,
float3 wi, float3 wi,
float randu, float2 rand,
float randv,
ccl_private Spectrum *eval, ccl_private Spectrum *eval,
ccl_private float3 *wo, ccl_private float3 *wo,
ccl_private float *pdf, 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 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 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_h = t + offset;
float theta_i = 2 * theta_h - theta_r; 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; float costheta_i, sintheta_i;
fast_sincosf(theta_i, &sintheta_i, &costheta_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; 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, ccl_device int bsdf_hair_transmission_sample(ccl_private const ShaderClosure *sc,
float3 Ng, float3 Ng,
float3 wi, float3 wi,
float randu, float2 rand,
float randv,
ccl_private Spectrum *eval, ccl_private Spectrum *eval,
ccl_private float3 *wo, ccl_private float3 *wo,
ccl_private float *pdf, 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 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 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_h = t + offset;
float theta_i = 2 * theta_h - theta_r; 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; float costheta_i, sintheta_i;
fast_sincosf(theta_i, &sintheta_i, &costheta_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 phi = p + M_PI_F;
float theta_pdf = roughness1 / float theta_pdf = roughness1 /
(2 * (t * t + roughness1 * roughness1) * (a_TT - b_TT) * costheta_i); (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_device int bsdf_principled_hair_sample(KernelGlobals kg,
ccl_private const ShaderClosure *sc, ccl_private const ShaderClosure *sc,
ccl_private ShaderData *sd, ccl_private ShaderData *sd,
float randu, float3 rand,
float randv,
float randw,
ccl_private Spectrum *eval, ccl_private Spectrum *eval,
ccl_private float3 *wo, ccl_private float3 *wo,
ccl_private float *pdf, ccl_private float *pdf,
@ -381,12 +379,12 @@ ccl_device int bsdf_principled_hair_sample(KernelGlobals kg,
int p = 0; int p = 0;
for (; p < 3; p++) { for (; p < 3; p++) {
if (randw < Ap_energy[p]) { if (rand.z < Ap_energy[p]) {
break; break;
} }
randw -= Ap_energy[p]; rand.z -= Ap_energy[p];
} }
randw /= Ap_energy[p]; rand.z /= Ap_energy[p];
float v = bsdf->v; float v = bsdf->v;
if (p == 1) { if (p == 1) {
@ -396,9 +394,10 @@ ccl_device int bsdf_principled_hair_sample(KernelGlobals kg,
v *= 4.0f; v *= 4.0f;
} }
randw = max(randw, 1e-5f); rand.z = max(rand.z, 1e-5f);
const float fac = 1.0f + v * logf(randw + (1.0f - randw) * expf(-2.0f / v)); 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 * randv) * cos_theta_o; 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 cos_theta_i = cos_from_sin(sin_theta_i);
float angles[6]; float angles[6];
@ -410,10 +409,10 @@ ccl_device int bsdf_principled_hair_sample(KernelGlobals kg,
float phi; float phi;
if (p < 3) { 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 { else {
phi = M_2PI_F * randu; phi = M_2PI_F * rand.x;
} }
const float phi_i = phi_o + phi; 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, ccl_device_forceinline float3 microfacet_beckmann_sample_vndf(const float3 wi,
const float alpha_x, const float alpha_x,
const float alpha_y, const float alpha_y,
const float randu, const float2 rand)
const float randv)
{ {
/* 1. stretch wi */ /* 1. stretch wi */
float3 wi_ = make_float3(alpha_x * wi.x, alpha_y * wi.y, wi.z); 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) { if (wi_.z >= 0.99999f) {
/* Special case (normal incidence). */ /* Special case (normal incidence). */
const float r = sqrtf(-logf(randu)); const float r = sqrtf(-logf(rand.x));
const float phi = M_2PI_F * randv; const float phi = M_2PI_F * rand.y;
slope_x = r * cosf(phi); slope_x = r * cosf(phi);
slope_y = r * sinf(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) * solve y = 1 + b + K * (1 - b * b)
*/ */
const float K = tan_theta_i * SQRT_PI_INV; 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_approx = rand.x * (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_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 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); 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_x = inv_erf;
slope_y = fast_ierff(2.0f * randv - 1.0f); slope_y = fast_ierff(2.0f * rand.y - 1.0f);
} }
/* 3. rotate */ /* 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, ccl_device_forceinline float3 microfacet_ggx_sample_vndf(const float3 wi,
const float alpha_x, const float alpha_x,
const float alpha_y, const float alpha_y,
const float randu, const float2 rand)
const float randv)
{ {
/* Section 3.2: Transforming the view direction to the hemisphere configuration. */ /* 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)); 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. */ /* 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)); t.y = mix(safe_sqrtf(1.0f - sqr(t.x)), t.y, 0.5f * (1.0f + wi_.z));
/* Section 4.3: Reprojection onto hemisphere. */ /* 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, const int path_flag,
float3 Ng, float3 Ng,
float3 wi, float3 wi,
float randu, const float3 rand,
float randv,
float randw,
ccl_private Spectrum *eval, ccl_private Spectrum *eval,
ccl_private float3 *wo, ccl_private float3 *wo,
ccl_private float *pdf, ccl_private float *pdf,
@ -513,11 +509,11 @@ ccl_device int bsdf_microfacet_sample(ccl_private const ShaderClosure *sc,
* space before and after sampling. */ * space before and after sampling. */
local_I = make_float3(dot(X, wi), dot(Y, wi), cos_NI); local_I = make_float3(dot(X, wi), dot(Y, wi), cos_NI);
if (m_type == MicrofacetType::GGX) { 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 { else {
/* m_type == MicrofacetType::BECKMANN */ /* 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; 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. */ * excessive noise for reflection highlights. */
float reflect_pdf = (path_flag & PATH_RAY_CAMERA) ? clamp(fresnel, 0.125f, 0.875f) : float reflect_pdf = (path_flag & PATH_RAY_CAMERA) ? clamp(fresnel, 0.125f, 0.875f) :
fresnel; fresnel;
do_refract = (randw >= reflect_pdf); do_refract = (rand.z >= reflect_pdf);
lobe_pdf = do_refract ? (1.0f - reflect_pdf) : 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, const int path_flag,
float3 Ng, float3 Ng,
float3 wi, float3 wi,
float randu, const float3 rand,
float randv,
float randw,
ccl_private Spectrum *eval, ccl_private Spectrum *eval,
ccl_private float3 *wo, ccl_private float3 *wo,
ccl_private float *pdf, ccl_private float *pdf,
@ -774,7 +768,7 @@ ccl_device int bsdf_microfacet_ggx_sample(ccl_private const ShaderClosure *sc,
ccl_private float *eta) ccl_private float *eta)
{ {
return bsdf_microfacet_sample<MicrofacetType::GGX>( 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: /* 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, const int path_flag,
float3 Ng, float3 Ng,
float3 wi, float3 wi,
float randu, const float3 rand,
float randv,
float randw,
ccl_private Spectrum *eval, ccl_private Spectrum *eval,
ccl_private float3 *wo, ccl_private float3 *wo,
ccl_private float *pdf, ccl_private float *pdf,
@ -843,7 +835,7 @@ ccl_device int bsdf_microfacet_beckmann_sample(ccl_private const ShaderClosure *
ccl_private float *eta) ccl_private float *eta)
{ {
return bsdf_microfacet_sample<MicrofacetType::BECKMANN>( 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 /* 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, const int path_flag,
float3 Ng, float3 Ng,
float3 wi, float3 wi,
float randu, const float3 rand,
float randv,
float randw,
ccl_private Spectrum *eval, ccl_private Spectrum *eval,
ccl_private float3 *wo, ccl_private float3 *wo,
ccl_private float *pdf, ccl_private float *pdf,
@ -899,7 +889,7 @@ ccl_device int bsdf_microfacet_sharp_sample(ccl_private const ShaderClosure *sc,
ccl_private float *eta) ccl_private float *eta)
{ {
return bsdf_microfacet_sample<MicrofacetType::SHARP>( 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 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, ccl_device int bsdf_oren_nayar_sample(ccl_private const ShaderClosure *sc,
float3 Ng, float3 Ng,
float3 wi, float3 wi,
float randu, float2 rand,
float randv,
ccl_private Spectrum *eval, ccl_private Spectrum *eval,
ccl_private float3 *wo, ccl_private float3 *wo,
ccl_private float *pdf) ccl_private float *pdf)
{ {
ccl_private const OrenNayarBsdf *bsdf = (ccl_private const OrenNayarBsdf *)sc; 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) { if (dot(Ng, *wo) > 0.0f) {
*eval = bsdf_oren_nayar_get_intensity(sc, bsdf->N, wi, *wo); *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, ccl_device int bsdf_phong_ramp_sample(ccl_private const ShaderClosure *sc,
float3 Ng, float3 Ng,
float3 wi, float3 wi,
float randu, const float2 rand,
float randv,
ccl_private Spectrum *eval, ccl_private Spectrum *eval,
ccl_private float3 *wo, ccl_private float3 *wo,
ccl_private float *pdf, 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 R = (2 * cosNI) * bsdf->N - wi;
float3 T, B; float3 T, B;
make_orthonormals(R, &T, &B); make_orthonormals(R, &T, &B);
float phi = M_2PI_F * randu; float phi = M_2PI_F * rand.x;
float cosTheta = powf(randv, 1 / (m_exponent + 1)); float cosTheta = powf(rand.y, 1 / (m_exponent + 1));
float sinTheta2 = 1 - cosTheta * cosTheta; float sinTheta2 = 1 - cosTheta * cosTheta;
float sinTheta = sinTheta2 > 0 ? sqrtf(sinTheta2) : 0; float sinTheta = sinTheta2 > 0 ? sqrtf(sinTheta2) : 0;
*wo = (cosf(phi) * sinTheta) * T + (sinf(phi) * sinTheta) * B + (cosTheta)*R; *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, ccl_device int bsdf_principled_diffuse_sample(ccl_private const ShaderClosure *sc,
float3 Ng, float3 Ng,
float3 wi, float3 wi,
float randu, float2 rand,
float randv,
ccl_private Spectrum *eval, ccl_private Spectrum *eval,
ccl_private float3 *wo, ccl_private float3 *wo,
ccl_private float *pdf) ccl_private float *pdf)
@ -142,7 +141,7 @@ ccl_device int bsdf_principled_diffuse_sample(ccl_private const ShaderClosure *s
float3 N = bsdf->N; float3 N = bsdf->N;
sample_cos_hemisphere(N, randu, randv, wo, pdf); sample_cos_hemisphere(N, rand, wo, pdf);
if (dot(Ng, *wo) > 0) { if (dot(Ng, *wo) > 0) {
*eval = bsdf_principled_diffuse_compute_brdf(bsdf, N, wi, *wo, pdf); *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, ccl_device int bsdf_principled_sheen_sample(ccl_private const ShaderClosure *sc,
float3 Ng, float3 Ng,
float3 wi, float3 wi,
float randu, float2 rand,
float randv,
ccl_private Spectrum *eval, ccl_private Spectrum *eval,
ccl_private float3 *wo, ccl_private float3 *wo,
ccl_private float *pdf) ccl_private float *pdf)
@ -94,7 +93,7 @@ ccl_device int bsdf_principled_sheen_sample(ccl_private const ShaderClosure *sc,
float3 N = bsdf->N; float3 N = bsdf->N;
sample_cos_hemisphere(N, randu, randv, wo, pdf); sample_cos_hemisphere(N, rand, wo, pdf);
if (dot(Ng, *wo) > 0) { if (dot(Ng, *wo) > 0) {
float3 H = normalize(wi + *wo); 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, ccl_device int bsdf_diffuse_toon_sample(ccl_private const ShaderClosure *sc,
float3 Ng, float3 Ng,
float3 wi, float3 wi,
float randu, float2 rand,
float randv,
ccl_private Spectrum *eval, ccl_private Spectrum *eval,
ccl_private float3 *wo, ccl_private float3 *wo,
ccl_private float *pdf) 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 max_angle = bsdf->size * M_PI_2_F;
float smooth = bsdf->smooth * M_PI_2_F; float smooth = bsdf->smooth * M_PI_2_F;
float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth); 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) { 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) { if (dot(Ng, *wo) > 0.0f) {
*eval = make_spectrum(*pdf * bsdf_toon_get_intensity(max_angle, smooth, angle)); *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, ccl_device int bsdf_glossy_toon_sample(ccl_private const ShaderClosure *sc,
float3 Ng, float3 Ng,
float3 wi, float3 wi,
float randu, float2 rand,
float randv,
ccl_private Spectrum *eval, ccl_private Spectrum *eval,
ccl_private float3 *wo, ccl_private float3 *wo,
ccl_private float *pdf) 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; float3 R = (2 * cosNI) * bsdf->N - wi;
float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth); 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) { if (dot(Ng, *wo) > 0.0f) {
float cosNO = dot(bsdf->N, *wo); 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, ccl_device int bsdf_transparent_sample(ccl_private const ShaderClosure *sc,
float3 Ng, float3 Ng,
float3 wi, float3 wi,
float randu,
float randv,
ccl_private Spectrum *eval, ccl_private Spectrum *eval,
ccl_private float3 *wo, ccl_private float3 *wo,
ccl_private float *pdf) ccl_private float *pdf)

@ -67,21 +67,20 @@ ccl_device Spectrum volume_henyey_greenstein_eval_phase(ccl_private const Shader
return make_spectrum(*pdf); return make_spectrum(*pdf);
} }
ccl_device float3 ccl_device float3 henyey_greenstrein_sample(float3 D, float g, float2 rand, ccl_private float *pdf)
henyey_greenstrein_sample(float3 D, float g, float randu, float randv, ccl_private float *pdf)
{ {
/* match pdf for small g */ /* match pdf for small g */
float cos_theta; float cos_theta;
bool isotropic = fabsf(g) < 1e-3f; bool isotropic = fabsf(g) < 1e-3f;
if (isotropic) { if (isotropic) {
cos_theta = (1.0f - 2.0f * randu); cos_theta = (1.0f - 2.0f * rand.x);
if (pdf) { if (pdf) {
*pdf = M_1_PI_F * 0.25f; *pdf = M_1_PI_F * 0.25f;
} }
} }
else { 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); cos_theta = (1.0f + g * g - k * k) / (2.0f * g);
if (pdf) { if (pdf) {
*pdf = single_peaked_henyey_greenstein(cos_theta, g); *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 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 dir = make_float3(sin_theta * cosf(phi), sin_theta * sinf(phi), cos_theta);
float3 T, B; 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, ccl_device int volume_henyey_greenstein_sample(ccl_private const ShaderVolumeClosure *svc,
float3 wi, float3 wi,
float randu, float2 rand,
float randv,
ccl_private Spectrum *eval, ccl_private Spectrum *eval,
ccl_private float3 *wo, ccl_private float3 *wo,
ccl_private float *pdf) ccl_private float *pdf)
@ -110,7 +108,7 @@ ccl_device int volume_henyey_greenstein_sample(ccl_private const ShaderVolumeClo
float g = svc->g; float g = svc->g;
/* note that wi points towards the viewer and so is used negated */ /* 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 */ *eval = make_spectrum(*pdf); /* perfect importance sampling */
return LABEL_VOLUME_SCATTER; 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_device int volume_phase_sample(ccl_private const ShaderData *sd,
ccl_private const ShaderVolumeClosure *svc, ccl_private const ShaderVolumeClosure *svc,
float randu, float2 rand,
float randv,
ccl_private Spectrum *eval, ccl_private Spectrum *eval,
ccl_private float3 *wo, ccl_private float3 *wo,
ccl_private float *pdf) 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. */ /* 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) : path_rng_3D(kg, rng_hash, sample, PRNG_LENS_TIME) :
zero_float3(); 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. */ /* Generate camera ray. */
camera_sample(kg, camera_sample(kg, x, y, rand_filter, rand_time, rand_lens, ray);
x,
y,
rand_filter.x,
rand_filter.y,
rand_time_lens.y,
rand_time_lens.z,
rand_time_lens.x,
ray);
} }
/* Return false to indicate that this pixel is finished. /* 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, if (!light_sample_from_position(kg,
rng_state, rng_state,
rand_light.z, rand_light,
rand_light.x,
rand_light.y,
sd->time, sd->time,
sd->P, sd->P,
sd->N, sd->N,
@ -576,7 +574,7 @@ ccl_device_forceinline void integrate_surface_ao(KernelGlobals kg,
float3 ao_D; float3 ao_D;
float ao_pdf; 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; bool skip_self = true;

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

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

@ -317,8 +317,7 @@ ccl_device int volume_shader_phase_guided_sample(KernelGlobals kg,
else { else {
/* Sample phase. */ /* Sample phase. */
*phase_pdf = 0.0f; *phase_pdf = 0.0f;
label = volume_phase_sample( label = volume_phase_sample(sd, svc, rand_phase, &eval, wo, unguided_phase_pdf);
sd, svc, rand_phase.x, rand_phase.y, &eval, wo, unguided_phase_pdf);
if (*unguided_phase_pdf != 0.0f) { if (*unguided_phase_pdf != 0.0f) {
bsdf_eval_init(phase_eval, CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID, eval); 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(); Spectrum eval = zero_spectrum();
*pdf = 0.0f; *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) { if (*pdf != 0.0f) {
bsdf_eval_init(phase_eval, CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID, eval); 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 float len_u,
const float3 axis_v, const float3 axis_v,
const float len_v, const float len_v,
float randu, const float2 rand,
float randv,
bool sample_coord) bool sample_coord)
{ {
/* In our name system we're using P for the center, which is o in the paper. */ /* 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) { if (sample_coord) {
/* Compute cu. */ /* Compute cu. */
float au = randu * S + k; float au = rand.x * S + k;
float fu = (cosf(au) * b0 - b1) / sinf(au); float fu = (cosf(au) * b0 - b1) / sinf(au);
float cu = 1.0f / sqrtf(fu * fu + b0sq) * (fu > 0.0f ? 1.0f : -1.0f); float cu = 1.0f / sqrtf(fu * fu + b0sq) * (fu > 0.0f ? 1.0f : -1.0f);
cu = clamp(cu, -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 d = sqrtf(xu * xu + z0sq);
float h0 = y0 / sqrtf(d * d + y0sq); float h0 = y0 / sqrtf(d * d + y0sq);
float h1 = y1 / sqrtf(d * d + y1sq); 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; float yv = (hv2 < 1.0f - 1e-6f) ? (hv * d) / sqrtf(1.0f - hv2) : y1;
/* Transform (xu, yv, z0) to world coords. */ /* 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, const float3 ray_P,
ccl_private float3 *light_P, ccl_private float3 *light_P,
ccl_private LightSample *ccl_restrict ls, ccl_private LightSample *ccl_restrict ls,
float randu, const float2 rand,
float randv,
bool sample_coord) bool sample_coord)
{ {
float3 axis_u = klight->area.axis_u; 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) { if (in_volume_segment) {
light_P_new += sample_rectangle ? light_P_new += sample_rectangle ?
rectangle_sample( rectangle_sample(axis_u * len_u * 0.5f, axis_v * len_v * 0.5f, rand) :
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, rand);
ellipse_sample(axis_u * len_u * 0.5f, axis_v * len_v * 0.5f, randu, randv);
ls->pdf = invarea; ls->pdf = invarea;
} }
else { else {
@ -273,7 +270,7 @@ ccl_device_inline bool area_light_eval(const ccl_global KernelLight *klight,
if (sample_rectangle) { if (sample_rectangle) {
ls->pdf = area_light_rect_sample( 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 { else {
if (klight->area.tan_half_spread == 0.0f) { 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 { else {
if (sample_coord) { if (sample_coord) {
light_P_new += ellipse_sample( light_P_new += ellipse_sample(axis_u * len_u * 0.5f, axis_v * len_v * 0.5f, rand);
axis_u * len_u * 0.5f, axis_v * len_v * 0.5f, randu, randv);
} }
ls->pdf = 4.0f * M_1_PI_F / (len_u * len_v); 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> template<bool in_volume_segment>
ccl_device_inline bool area_light_sample(const ccl_global KernelLight *klight, ccl_device_inline bool area_light_sample(const ccl_global KernelLight *klight,
const float randu, const float2 rand,
const float randv,
const float3 P, const float3 P,
ccl_private LightSample *ls) 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; 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) { if (klight->area.tan_half_spread == 0) {
/* Update position on the light to keep the direction fixed. */ /* 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 { else {
ls->D = normalize_len(ls->P - P, &ls->t); 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. */ /* Convert pdf to be in area measure. */
ls->pdf /= lamp_light_pdf(ls->Ng, -ls->D, ls->t); 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; ls->Ng = klight->area.dir;
float3 light_P = klight->co; 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> template<bool in_volume_segment>

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

@ -28,24 +28,24 @@ typedef struct LightSample {
/* Utilities */ /* 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); const float2 uv = concentric_sample_disk(rand);
return ru * rand.x + rv * rand.y; 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; 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) ccl_device float lamp_light_pdf(const float3 Ng, const float3 I, float t)

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

@ -11,7 +11,7 @@ CCL_NAMESPACE_BEGIN
/* Simple CDF based sampling over all lights in the scene, without taking into /* Simple CDF based sampling over all lights in the scene, without taking into
* account shading position or normal. */ * 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 /* 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 * 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. */ * arbitrary shaders. */
int first = 0; int first = 0;
int len = kernel_data.integrator.num_distribution + 1; int len = kernel_data.integrator.num_distribution + 1;
float r = randn;
do { do {
int half_len = len >> 1; int half_len = len >> 1;
int middle = first + half_len; 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; len = half_len;
} }
else { else {
@ -43,9 +42,7 @@ ccl_device int light_distribution_sample(KernelGlobals kg, const float randn)
template<bool in_volume_segment> template<bool in_volume_segment>
ccl_device_noinline bool light_distribution_sample(KernelGlobals kg, ccl_device_noinline bool light_distribution_sample(KernelGlobals kg,
const float randn, const float3 rand,
const float randu,
const float randv,
const float time, const float time,
const float3 P, const float3 P,
const int object_receiver, const int object_receiver,
@ -54,10 +51,12 @@ ccl_device_noinline bool light_distribution_sample(KernelGlobals kg,
ccl_private LightSample *ls) ccl_private LightSample *ls)
{ {
/* Sample light index from distribution. */ /* 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 float pdf_selection = kernel_data.integrator.distribution_pdf_lights;
const float2 rand_uv = float3_to_float2(rand);
return light_sample<in_volume_segment>( 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) 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> template<bool in_volume_segment>
ccl_device_inline bool light_sample(KernelGlobals kg, ccl_device_inline bool light_sample(KernelGlobals kg,
const int lamp, const int lamp,
const float randu, const float2 rand,
const float randv,
const float3 P, const float3 P,
const uint32_t path_flag, const uint32_t path_flag,
ccl_private LightSample *ls) ccl_private LightSample *ls)
@ -112,8 +111,8 @@ ccl_device_inline bool light_sample(KernelGlobals kg,
ls->object = PRIM_NONE; ls->object = PRIM_NONE;
ls->prim = PRIM_NONE; ls->prim = PRIM_NONE;
ls->lamp = lamp; ls->lamp = lamp;
ls->u = randu; ls->u = rand.x;
ls->v = randv; ls->v = rand.y;
ls->group = lamp_lightgroup(kg, lamp); ls->group = lamp_lightgroup(kg, lamp);
if (in_volume_segment && (type == LIGHT_DISTANT || type == LIGHT_BACKGROUND)) { 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 (type == LIGHT_DISTANT) {
if (!distant_light_sample(klight, randu, randv, ls)) { if (!distant_light_sample(klight, rand, ls)) {
return false; return false;
} }
} }
else if (type == LIGHT_BACKGROUND) { else if (type == LIGHT_BACKGROUND) {
/* infinite area light (e.g. light dome or env light) */ /* 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->P = D;
ls->Ng = D; ls->Ng = D;
@ -145,18 +144,18 @@ ccl_device_inline bool light_sample(KernelGlobals kg,
ls->eval_fac = 1.0f; ls->eval_fac = 1.0f;
} }
else if (type == LIGHT_SPOT) { 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; return false;
} }
} }
else if (type == LIGHT_POINT) { 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; return false;
} }
} }
else { else {
/* area light */ /* 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; return false;
} }
} }
@ -168,8 +167,7 @@ ccl_device_inline bool light_sample(KernelGlobals kg,
template<bool in_volume_segment> template<bool in_volume_segment>
ccl_device_noinline bool light_sample(KernelGlobals kg, ccl_device_noinline bool light_sample(KernelGlobals kg,
const float randu, const float2 rand,
const float randv,
const float time, const float time,
const float3 P, const float3 P,
const int object_receiver, const int object_receiver,
@ -218,7 +216,7 @@ ccl_device_noinline bool light_sample(KernelGlobals kg,
} }
const int shader_flag = mesh_light.shader_flag; 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; return false;
} }
ls->shader |= shader_flag; ls->shader |= shader_flag;
@ -234,7 +232,7 @@ ccl_device_noinline bool light_sample(KernelGlobals kg,
return false; 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; return false;
} }
} }

@ -9,8 +9,7 @@ CCL_NAMESPACE_BEGIN
template<bool in_volume_segment> template<bool in_volume_segment>
ccl_device_inline bool point_light_sample(const ccl_global KernelLight *klight, ccl_device_inline bool point_light_sample(const ccl_global KernelLight *klight,
const float randu, const float2 rand,
const float randv,
const float3 P, const float3 P,
ccl_private LightSample *ls) ccl_private LightSample *ls)
{ {
@ -21,7 +20,7 @@ ccl_device_inline bool point_light_sample(const ccl_global KernelLight *klight,
ls->P = center; ls->P = center;
if (radius > 0.0f) { 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; 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. */ * Uses either a flat distribution or light tree. */
ccl_device_inline bool light_sample_from_volume_segment(KernelGlobals kg, ccl_device_inline bool light_sample_from_volume_segment(KernelGlobals kg,
const float randn, const float3 rand,
const float randu,
const float randv,
const float time, const float time,
const float3 P, const float3 P,
const float3 D, const float3 D,
@ -332,33 +330,20 @@ ccl_device_inline bool light_sample_from_volume_segment(KernelGlobals kg,
{ {
#ifdef __LIGHT_TREE__ #ifdef __LIGHT_TREE__
if (kernel_data.integrator.use_light_tree) { if (kernel_data.integrator.use_light_tree) {
return light_tree_sample<true>(kg, return light_tree_sample<true>(
randn, kg, rand, time, P, D, t, object_receiver, SD_BSDF_HAS_TRANSMISSION, bounce, path_flag, ls);
randu,
randv,
time,
P,
D,
t,
object_receiver,
SD_BSDF_HAS_TRANSMISSION,
bounce,
path_flag,
ls);
} }
else else
#endif #endif
{ {
return light_distribution_sample<true>( 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_device bool light_sample_from_position(KernelGlobals kg,
ccl_private const RNGState *rng_state, ccl_private const RNGState *rng_state,
const float randn, const float3 rand,
const float randu,
const float randv,
const float time, const float time,
const float3 P, const float3 P,
const float3 N, const float3 N,
@ -370,25 +355,14 @@ ccl_device bool light_sample_from_position(KernelGlobals kg,
{ {
#ifdef __LIGHT_TREE__ #ifdef __LIGHT_TREE__
if (kernel_data.integrator.use_light_tree) { if (kernel_data.integrator.use_light_tree) {
return light_tree_sample<false>(kg, return light_tree_sample<false>(
randn, kg, rand, time, P, N, 0.0f, object_receiver, shader_flags, bounce, path_flag, ls);
randu,
randv,
time,
P,
N,
0.0f,
object_receiver,
shader_flags,
bounce,
path_flag,
ls);
} }
else else
#endif #endif
{ {
return light_distribution_sample<false>( 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> template<bool in_volume_segment>
ccl_device_inline bool spot_light_sample(const ccl_global KernelLight *klight, ccl_device_inline bool spot_light_sample(const ccl_global KernelLight *klight,
const float randu, const float2 rand,
const float randv,
const float3 P, const float3 P,
ccl_private LightSample *ls) ccl_private LightSample *ls)
{ {
@ -33,7 +32,7 @@ ccl_device_inline bool spot_light_sample(const ccl_global KernelLight *klight,
if (radius > 0.0f) { if (radius > 0.0f) {
/* disk light */ /* 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; 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> template<bool in_volume_segment>
ccl_device_noinline bool light_tree_sample(KernelGlobals kg, ccl_device_noinline bool light_tree_sample(KernelGlobals kg,
float randn, const float3 rand,
const float randu,
const float randv,
const float time, const float time,
const float3 P, const float3 P,
float3 N_or_D, float3 N_or_D,
@ -694,6 +692,8 @@ ccl_device_noinline bool light_tree_sample(KernelGlobals kg,
int selected_emitter = -1; int selected_emitter = -1;
int object_emitter = 0; int object_emitter = 0;
int node_index = light_tree_root_node_index(kg, object_receiver); 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; float3 local_P = P;
@ -704,7 +704,7 @@ ccl_device_noinline bool light_tree_sample(KernelGlobals kg,
if (is_leaf(knode)) { if (is_leaf(knode)) {
/* At a leaf node, we pick an emitter. */ /* At a leaf node, we pick an emitter. */
selected_emitter = light_tree_cluster_select_emitter<in_volume_segment>( 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) { if (node_index < 0) {
break; break;
@ -730,7 +730,8 @@ ccl_device_noinline bool light_tree_sample(KernelGlobals kg,
float discard; float discard;
float total_prob = left_prob; float total_prob = left_prob;
node_index = left_index; 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); 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; pdf_selection *= pdf_leaf;
return light_sample<in_volume_segment>(kg, return light_sample<in_volume_segment>(kg,
randu, float3_to_float2(rand),
randv,
time, time,
P, P,
object_receiver, object_receiver,

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

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

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

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