forked from bartvdbraak/blender
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:
parent
adb87dd080
commit
41e49d7ece
@ -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
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user