Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/cycles/kernel/kernel_shader.h')
-rw-r--r--intern/cycles/kernel/kernel_shader.h232
1 files changed, 167 insertions, 65 deletions
diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h
index c66f52255f0..695d4fc380a 100644
--- a/intern/cycles/kernel/kernel_shader.h
+++ b/intern/cycles/kernel/kernel_shader.h
@@ -66,8 +66,8 @@ ccl_device_noinline void shader_setup_from_ray(KernelGlobals *kg,
/* matrices and time */
#ifdef __OBJECT_MOTION__
shader_setup_object_transforms(kg, sd, ray->time);
- sd->time = ray->time;
#endif
+ sd->time = ray->time;
sd->prim = kernel_tex_fetch(__prim_index, isect->prim);
sd->ray_length = isect->t;
@@ -83,7 +83,7 @@ ccl_device_noinline void shader_setup_from_ray(KernelGlobals *kg,
float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
sd->shader = __float_as_int(curvedata.z);
- sd->P = bvh_curve_refine(kg, sd, isect, ray);
+ sd->P = curve_refine(kg, sd, isect, ray);
}
else
#endif
@@ -271,17 +271,17 @@ ccl_device_inline void shader_setup_from_sample(KernelGlobals *kg,
sd->u = u;
sd->v = v;
#endif
+ sd->time = time;
sd->ray_length = t;
sd->flag = kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*SHADER_SIZE);
sd->object_flag = 0;
if(sd->object != OBJECT_NONE) {
sd->object_flag |= kernel_tex_fetch(__object_flag,
- sd->object);
+ sd->object);
#ifdef __OBJECT_MOTION__
shader_setup_object_transforms(kg, sd, time);
- sd->time = time;
}
else if(lamp != LAMP_NONE) {
sd->ob_tfm = lamp_fetch_transform(kg, lamp, false);
@@ -385,9 +385,7 @@ ccl_device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderDat
sd->shader = kernel_data.background.surface_shader;
sd->flag = kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*SHADER_SIZE);
sd->object_flag = 0;
-#ifdef __OBJECT_MOTION__
sd->time = ray->time;
-#endif
sd->ray_length = 0.0f;
#ifdef __INSTANCING__
@@ -427,9 +425,7 @@ ccl_device_inline void shader_setup_from_volume(KernelGlobals *kg, ShaderData *s
sd->shader = SHADER_NONE;
sd->flag = 0;
sd->object_flag = 0;
-#ifdef __OBJECT_MOTION__
sd->time = ray->time;
-#endif
sd->ray_length = 0.0f; /* todo: can we set this to some useful value? */
#ifdef __INSTANCING__
@@ -498,20 +494,45 @@ ccl_device_inline void shader_merge_closures(ShaderData *sd)
}
#endif
+/* Defensive sampling. */
+
+ccl_device_inline void shader_prepare_closures(ShaderData *sd,
+ ccl_addr_space PathState *state)
+{
+ /* We can likely also do defensive sampling at deeper bounces, particularly
+ * for cases like a perfect mirror but possibly also others. This will need
+ * a good heuristic. */
+ if(state->bounce + state->transparent_bounce == 0 && sd->num_closure > 1) {
+ float sum = 0.0f;
+
+ for(int i = 0; i < sd->num_closure; i++) {
+ ShaderClosure *sc = &sd->closure[i];
+ if(CLOSURE_IS_BSDF_OR_BSSRDF(sc->type)) {
+ sum += sc->sample_weight;
+ }
+ }
+
+ for(int i = 0; i < sd->num_closure; i++) {
+ ShaderClosure *sc = &sd->closure[i];
+ if(CLOSURE_IS_BSDF_OR_BSSRDF(sc->type)) {
+ sc->sample_weight = max(sc->sample_weight, 0.125f * sum);
+ }
+ }
+ }
+}
+
+
/* BSDF */
ccl_device_inline void _shader_bsdf_multi_eval(KernelGlobals *kg, ShaderData *sd, const float3 omega_in, float *pdf,
- int skip_bsdf, BsdfEval *result_eval, float sum_pdf, float sum_sample_weight)
+ const ShaderClosure *skip_sc, BsdfEval *result_eval, float sum_pdf, float sum_sample_weight)
{
/* this is the veach one-sample model with balance heuristic, some pdf
* factors drop out when using balance heuristic weighting */
for(int i = 0; i < sd->num_closure; i++) {
- if(i == skip_bsdf)
- continue;
-
const ShaderClosure *sc = &sd->closure[i];
- if(CLOSURE_IS_BSDF(sc->type)) {
+ if(sc != skip_sc && CLOSURE_IS_BSDF(sc->type)) {
float bsdf_pdf = 0.0f;
float3 eval = bsdf_eval(kg, sd, sc, omega_in, &bsdf_pdf);
@@ -574,7 +595,7 @@ void shader_bsdf_eval(KernelGlobals *kg,
#endif
{
float pdf;
- _shader_bsdf_multi_eval(kg, sd, omega_in, &pdf, -1, eval, 0.0f, 0.0f);
+ _shader_bsdf_multi_eval(kg, sd, omega_in, &pdf, NULL, eval, 0.0f, 0.0f);
if(use_mis) {
float weight = power_heuristic(light_pdf, pdf);
bsdf_eval_mis(eval, weight);
@@ -582,48 +603,120 @@ void shader_bsdf_eval(KernelGlobals *kg,
}
}
-ccl_device_inline int shader_bsdf_sample(KernelGlobals *kg,
- ShaderData *sd,
- float randu, float randv,
- BsdfEval *bsdf_eval,
- float3 *omega_in,
- differential3 *domega_in,
- float *pdf)
+ccl_device_inline const ShaderClosure *shader_bsdf_pick(ShaderData *sd,
+ float *randu)
{
int sampled = 0;
if(sd->num_closure > 1) {
- /* pick a BSDF closure based on sample weights */
+ /* Pick a BSDF or based on sample weights. */
float sum = 0.0f;
- for(sampled = 0; sampled < sd->num_closure; sampled++) {
- const ShaderClosure *sc = &sd->closure[sampled];
-
- if(CLOSURE_IS_BSDF(sc->type))
+ for(int i = 0; i < sd->num_closure; i++) {
+ const ShaderClosure *sc = &sd->closure[i];
+
+ if(CLOSURE_IS_BSDF(sc->type)) {
sum += sc->sample_weight;
+ }
}
- float r = sd->randb_closure*sum;
- sum = 0.0f;
+ float r = (*randu)*sum;
+ float partial_sum = 0.0f;
+
+ for(int i = 0; i < sd->num_closure; i++) {
+ const ShaderClosure *sc = &sd->closure[i];
- for(sampled = 0; sampled < sd->num_closure; sampled++) {
- const ShaderClosure *sc = &sd->closure[sampled];
-
if(CLOSURE_IS_BSDF(sc->type)) {
- sum += sc->sample_weight;
+ float next_sum = partial_sum + sc->sample_weight;
+
+ if(r < next_sum) {
+ sampled = i;
- if(r <= sum)
+ /* Rescale to reuse for direction sample, to better
+ * preserve stratifaction. */
+ *randu = (r - partial_sum) / sc->sample_weight;
break;
+ }
+
+ partial_sum = next_sum;
}
}
+ }
- if(sampled == sd->num_closure) {
- *pdf = 0.0f;
- return LABEL_NONE;
+ return &sd->closure[sampled];
+}
+
+ccl_device_inline const ShaderClosure *shader_bssrdf_pick(ShaderData *sd,
+ ccl_addr_space float3 *throughput,
+ float *randu)
+{
+ int sampled = 0;
+
+ if(sd->num_closure > 1) {
+ /* Pick a BSDF or BSSRDF or based on sample weights. */
+ float sum_bsdf = 0.0f;
+ float sum_bssrdf = 0.0f;
+
+ for(int i = 0; i < sd->num_closure; i++) {
+ const ShaderClosure *sc = &sd->closure[i];
+
+ if(CLOSURE_IS_BSDF(sc->type)) {
+ sum_bsdf += sc->sample_weight;
+ }
+ else if(CLOSURE_IS_BSSRDF(sc->type)) {
+ sum_bssrdf += sc->sample_weight;
+ }
+ }
+
+ float r = (*randu)*(sum_bsdf + sum_bssrdf);
+ float partial_sum = 0.0f;
+
+ for(int i = 0; i < sd->num_closure; i++) {
+ const ShaderClosure *sc = &sd->closure[i];
+
+ if(CLOSURE_IS_BSDF_OR_BSSRDF(sc->type)) {
+ float next_sum = partial_sum + sc->sample_weight;
+
+ if(r < next_sum) {
+ if(CLOSURE_IS_BSDF(sc->type)) {
+ *throughput *= (sum_bsdf + sum_bssrdf) / sum_bsdf;
+ return NULL;
+ }
+ else {
+ *throughput *= (sum_bsdf + sum_bssrdf) / sum_bssrdf;
+ sampled = i;
+
+ /* Rescale to reuse for direction sample, to better
+ * preserve stratifaction. */
+ *randu = (r - partial_sum) / sc->sample_weight;
+ break;
+ }
+ }
+
+ partial_sum = next_sum;
+ }
}
}
- const ShaderClosure *sc = &sd->closure[sampled];
+ return &sd->closure[sampled];
+}
+
+ccl_device_inline int shader_bsdf_sample(KernelGlobals *kg,
+ ShaderData *sd,
+ float randu, float randv,
+ BsdfEval *bsdf_eval,
+ float3 *omega_in,
+ differential3 *domega_in,
+ float *pdf)
+{
+ const ShaderClosure *sc = shader_bsdf_pick(sd, &randu);
+ if(sc == NULL) {
+ *pdf = 0.0f;
+ return LABEL_NONE;
+ }
+
+ /* BSSRDF should already have been handled elsewhere. */
+ kernel_assert(CLOSURE_IS_BSDF(sc->type));
int label;
float3 eval;
@@ -636,7 +729,7 @@ ccl_device_inline int shader_bsdf_sample(KernelGlobals *kg,
if(sd->num_closure > 1) {
float sweight = sc->sample_weight;
- _shader_bsdf_multi_eval(kg, sd, *omega_in, pdf, sampled, bsdf_eval, *pdf*sweight, sweight);
+ _shader_bsdf_multi_eval(kg, sd, *omega_in, pdf, sc, bsdf_eval, *pdf*sweight, sweight);
}
}
@@ -669,7 +762,7 @@ ccl_device void shader_bsdf_blur(KernelGlobals *kg, ShaderData *sd, float roughn
}
}
-ccl_device float3 shader_bsdf_transparency(KernelGlobals *kg, ShaderData *sd)
+ccl_device float3 shader_bsdf_transparency(KernelGlobals *kg, const ShaderData *sd)
{
if(sd->flag & SD_HAS_ONLY_VOLUME)
return make_float3(1.0f, 1.0f, 1.0f);
@@ -677,7 +770,7 @@ ccl_device float3 shader_bsdf_transparency(KernelGlobals *kg, ShaderData *sd)
float3 eval = make_float3(0.0f, 0.0f, 0.0f);
for(int i = 0; i < sd->num_closure; i++) {
- ShaderClosure *sc = &sd->closure[i];
+ const ShaderClosure *sc = &sd->closure[i];
if(sc->type == CLOSURE_BSDF_TRANSPARENT_ID) // todo: make this work for osl
eval += sc->weight;
@@ -764,6 +857,19 @@ ccl_device float3 shader_bsdf_subsurface(KernelGlobals *kg, ShaderData *sd)
return eval;
}
+ccl_device float3 shader_bsdf_average_normal(KernelGlobals *kg, ShaderData *sd)
+{
+ float3 N = make_float3(0.0f, 0.0f, 0.0f);
+
+ for(int i = 0; i < sd->num_closure; i++) {
+ ShaderClosure *sc = &sd->closure[i];
+ if(CLOSURE_IS_BSDF_OR_BSSRDF(sc->type))
+ N += sc->N*average(sc->weight);
+ }
+
+ return (is_zero(N))? sd->N : normalize(N);
+}
+
ccl_device float3 shader_bsdf_ao(KernelGlobals *kg, ShaderData *sd, float ao_factor, float3 *N_)
{
float3 eval = make_float3(0.0f, 0.0f, 0.0f);
@@ -783,12 +889,7 @@ ccl_device float3 shader_bsdf_ao(KernelGlobals *kg, ShaderData *sd, float ao_fac
}
}
- if(is_zero(N))
- N = sd->N;
- else
- N = normalize(N);
-
- *N_ = N;
+ *N_ = (is_zero(N))? sd->N : normalize(N);
return eval;
}
@@ -863,16 +964,15 @@ ccl_device float3 shader_holdout_eval(KernelGlobals *kg, ShaderData *sd)
/* Surface Evaluation */
-ccl_device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd, RNG *rng,
- ccl_addr_space PathState *state, float randb, int path_flag, ShaderContext ctx)
+ccl_device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd,
+ ccl_addr_space PathState *state, int path_flag)
{
sd->num_closure = 0;
sd->num_closure_extra = 0;
- sd->randb_closure = randb;
#ifdef __OSL__
if(kg->osl)
- OSLShader::eval_surface(kg, sd, state, path_flag, ctx);
+ OSLShader::eval_surface(kg, sd, state, path_flag);
else
#endif
{
@@ -887,24 +987,23 @@ ccl_device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd, RNG *rng,
#endif
}
- if(rng && (sd->flag & SD_BSDF_NEEDS_LCG)) {
- sd->lcg_state = lcg_state_init(rng, state->rng_offset, state->sample, 0xb4bc3953);
+ if(sd->flag & SD_BSDF_NEEDS_LCG) {
+ sd->lcg_state = lcg_state_init_addrspace(state, 0xb4bc3953);
}
}
/* Background Evaluation */
ccl_device float3 shader_eval_background(KernelGlobals *kg, ShaderData *sd,
- ccl_addr_space PathState *state, int path_flag, ShaderContext ctx)
+ ccl_addr_space PathState *state, int path_flag)
{
sd->num_closure = 0;
sd->num_closure_extra = 0;
- sd->randb_closure = 0.0f;
#ifdef __SVM__
#ifdef __OSL__
if(kg->osl) {
- OSLShader::eval_background(kg, sd, state, path_flag, ctx);
+ OSLShader::eval_background(kg, sd, state, path_flag);
}
else
#endif
@@ -981,17 +1080,22 @@ ccl_device int shader_volume_phase_sample(KernelGlobals *kg, const ShaderData *s
sum += sc->sample_weight;
}
- float r = sd->randb_closure*sum;
- sum = 0.0f;
+ float r = randu*sum;
+ float partial_sum = 0.0f;
for(sampled = 0; sampled < sd->num_closure; sampled++) {
const ShaderClosure *sc = &sd->closure[sampled];
if(CLOSURE_IS_PHASE(sc->type)) {
- sum += sc->sample_weight;
+ float next_sum = partial_sum + sc->sample_weight;
- if(r <= sum)
+ if(r <= next_sum) {
+ /* Rescale to reuse for BSDF direction sample. */
+ randu = (r - partial_sum) / sc->sample_weight;
break;
+ }
+
+ partial_sum = next_sum;
}
}
@@ -1039,8 +1143,7 @@ ccl_device_inline void shader_eval_volume(KernelGlobals *kg,
ShaderData *sd,
ccl_addr_space PathState *state,
ccl_addr_space VolumeStack *stack,
- int path_flag,
- ShaderContext ctx)
+ int path_flag)
{
/* reset closures once at the start, we will be accumulating the closures
* for all volumes in the stack into a single array of closures */
@@ -1073,7 +1176,7 @@ ccl_device_inline void shader_eval_volume(KernelGlobals *kg,
#ifdef __SVM__
# ifdef __OSL__
if(kg->osl) {
- OSLShader::eval_volume(kg, sd, state, path_flag, ctx);
+ OSLShader::eval_volume(kg, sd, state, path_flag);
}
else
# endif
@@ -1092,17 +1195,16 @@ ccl_device_inline void shader_eval_volume(KernelGlobals *kg,
/* Displacement Evaluation */
-ccl_device void shader_eval_displacement(KernelGlobals *kg, ShaderData *sd, ccl_addr_space PathState *state, ShaderContext ctx)
+ccl_device void shader_eval_displacement(KernelGlobals *kg, ShaderData *sd, ccl_addr_space PathState *state)
{
sd->num_closure = 0;
sd->num_closure_extra = 0;
- sd->randb_closure = 0.0f;
/* this will modify sd->P */
#ifdef __SVM__
# ifdef __OSL__
if(kg->osl)
- OSLShader::eval_displacement(kg, sd, ctx);
+ OSLShader::eval_displacement(kg, sd, state);
else
# endif
{