diff options
author | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2013-12-28 04:54:44 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2013-12-28 19:57:02 +0400 |
commit | a35db17cee5a9b47dc9624f7dfcb41f5fc185b33 (patch) | |
tree | ef23032da73b9b202490307f865e2afd4e2e7e76 /intern/cycles/kernel/closure/volume.h | |
parent | a06c9c277a8577f7ef473fffaf2258d2a3a6ab80 (diff) |
Cycles Volume Render: work on nodes and closures.
* Henyey-Greenstein scattering closure implementation.
* Rename transparent to absorption node and isotropic to scatter node.
* Volume density is folded into the closure weights.
* OSL support for volume closures and nodes.
* This commit has no user visible changes, there is no volume render code yet.
This is work by "storm", Stuart Broadfoot, Thomas Dinges and myself.
Diffstat (limited to 'intern/cycles/kernel/closure/volume.h')
-rw-r--r-- | intern/cycles/kernel/closure/volume.h | 114 |
1 files changed, 91 insertions, 23 deletions
diff --git a/intern/cycles/kernel/closure/volume.h b/intern/cycles/kernel/closure/volume.h index f4932568c1f..dae24fb03fd 100644 --- a/intern/cycles/kernel/closure/volume.h +++ b/intern/cycles/kernel/closure/volume.h @@ -14,53 +14,102 @@ * limitations under the License */ +#ifndef __VOLUME_H__ +#define __VOLUME_H__ + CCL_NAMESPACE_BEGIN -/* note: the interfaces here are just as an example, need to figure - * out the right functions and parameters to use */ +/* HENYEY-GREENSTEIN CLOSURE */ -/* ISOTROPIC VOLUME CLOSURE */ +/* Given cosine between rays, return probability density that a photon bounces + * to that direction. The g parameter controls how different it is from the + * uniform sphere. g=0 uniform diffuse-like, g=1 close to sharp single ray. */ +ccl_device float single_peaked_henyey_greenstein(float cos_theta, float g) +{ + if(fabsf(g) < 1e-3f) + return M_1_PI_F * 0.25f; + + return ((1.0f - g * g) / safe_powf(1.0f + g * g - 2.0f * g * cos_theta, 1.5f)) * (M_1_PI_F * 0.25f); +}; -ccl_device int volume_isotropic_setup(ShaderClosure *sc, float density) +ccl_device int volume_henyey_greenstein_setup(ShaderClosure *sc) { - sc->type = CLOSURE_VOLUME_ISOTROPIC_ID; - sc->data0 = density; + sc->type = CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID; + + /* clamp anisotropy to avoid delta function */ + sc->data0 = signf(sc->data0) * min(fabsf(sc->data0), 1.0f - 1e-3f); - return SD_VOLUME; + return SD_BSDF|SD_BSDF_HAS_EVAL; } -ccl_device float3 volume_isotropic_eval_phase(const ShaderClosure *sc, const float3 omega_in, const float3 omega_out) +ccl_device float3 volume_henyey_greenstein_eval_phase(const ShaderClosure *sc, const float3 I, float3 omega_in, float *pdf) { - return make_float3(1.0f, 1.0f, 1.0f); -} + float g = sc->data0; -/* TRANSPARENT VOLUME CLOSURE */ + /* note that I points towards the viewer */ + float cos_theta = dot(-I, omega_in); -ccl_device int volume_transparent_setup(ShaderClosure *sc, float density) + *pdf = single_peaked_henyey_greenstein(cos_theta, g); + + return make_float3(*pdf, *pdf, *pdf); +} + +ccl_device int volume_henyey_greenstein_sample(const ShaderClosure *sc, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, + float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) { - sc->type = CLOSURE_VOLUME_TRANSPARENT_ID; - sc->data0 = density; + float g = sc->data0; + float cos_phi, sin_phi, cos_theta; - return SD_VOLUME; + /* match pdf for small g */ + if(fabsf(g) < 1e-3f) { + cos_theta = (1.0f - 2.0f * randu); + } + else { + float k = (1.0f - g * g) / (1.0f - g + 2.0f * g * randu); + cos_theta = (1.0f + g * g - k * k) / (2.0f * g); + } + + float sin_theta = safe_sqrtf(1.0f - cos_theta * cos_theta); + + float phi = M_2PI_F * randv; + cos_phi = cosf(phi); + sin_phi = sinf(phi); + + /* note that I points towards the viewer and so is used negated */ + float3 T, B; + make_orthonormals(-I, &T, &B); + *omega_in = sin_theta * cos_phi * T + sin_theta * sin_phi * B + cos_theta * (-I); + + *pdf = single_peaked_henyey_greenstein(cos_theta, g); + *eval = make_float3(*pdf, *pdf, *pdf); /* perfect importance sampling */ + +#ifdef __RAY_DIFFERENTIALS__ + /* todo: implement ray differential estimation */ + *domega_in_dx = make_float3(0.0f, 0.0f, 0.0f); + *domega_in_dy = make_float3(0.0f, 0.0f, 0.0f); +#endif + + return LABEL_VOLUME_SCATTER; } -ccl_device float3 volume_transparent_eval_phase(const ShaderClosure *sc, const float3 omega_in, const float3 omega_out) +/* ABSORPTION VOLUME CLOSURE */ + +ccl_device int volume_absorption_setup(ShaderClosure *sc) { - return make_float3(1.0f, 1.0f, 1.0f); + sc->type = CLOSURE_VOLUME_ABSORPTION_ID; + + return SD_VOLUME; } /* VOLUME CLOSURE */ -ccl_device float3 volume_eval_phase(KernelGlobals *kg, const ShaderClosure *sc, const float3 omega_in, const float3 omega_out) +ccl_device float3 volume_eval_phase(const ShaderClosure *sc, const float3 I, float3 omega_in, float *pdf) { float3 eval; switch(sc->type) { - case CLOSURE_VOLUME_ISOTROPIC_ID: - eval = volume_isotropic_eval_phase(sc, omega_in, omega_out); - break; - case CLOSURE_VOLUME_TRANSPARENT_ID: - eval = volume_transparent_eval_phase(sc, omega_in, omega_out); + case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID: + eval = volume_henyey_greenstein_eval_phase(sc, I, omega_in, pdf); break; default: eval = make_float3(0.0f, 0.0f, 0.0f); @@ -70,5 +119,24 @@ ccl_device float3 volume_eval_phase(KernelGlobals *kg, const ShaderClosure *sc, return eval; } +ccl_device int volume_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, + float randv, float3 *eval, float3 *omega_in, differential3 *domega_in, float *pdf) +{ + int label; + + switch(sc->type) { + case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID: + label = volume_henyey_greenstein_sample(sc, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + break; + default: + *eval = make_float3(0.0f, 0.0f, 0.0f); + label = LABEL_NONE; + break; + } + + return label; +} + CCL_NAMESPACE_END +#endif |