blender/intern/cycles/kernel/closure/bsdf_util.h
OmarSquircleArt 613b37bc2c Shading: Add More Features To The Voronoi Node.
This patch allows the Voronoi node to operate in 1D, 2D, and 4D space.
It also adds a Randomness input to control the randomness of the texture.
Additionally, it adds three new modes of operation:

- Smooth F1: A smooth version of F1 Voronoi with no discontinuities.
- Distance To Edge: Returns the distance to the edges of the cells.
- N-Sphere Radius: Returns the radius of the n-sphere inscribed in
the cells. In other words, it is half the distance between the
closest feature point and the feature point closest to it.

And it removes the following three modes of operation:

- F3.
- F4.
- Cracks.

The Distance metric is now called Euclidean, and it computes the actual
euclidean distance as opposed to the old method of computing the squared
euclidean distance.

This breaks backward compatibility in many ways, including the base case.

Reviewers: brecht, JacquesLucke

Differential Revision: https://developer.blender.org/D5743
2019-09-12 13:09:31 +02:00

155 lines
5.5 KiB
C

/*
* Adapted from Open Shading Language with this license:
*
* Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
* All Rights Reserved.
*
* Modifications Copyright 2011, Blender Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Sony Pictures Imageworks nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __BSDF_UTIL_H__
#define __BSDF_UTIL_H__
CCL_NAMESPACE_BEGIN
ccl_device float fresnel_dielectric(float eta,
const float3 N,
const float3 I,
float3 *R,
float3 *T,
#ifdef __RAY_DIFFERENTIALS__
const float3 dIdx,
const float3 dIdy,
float3 *dRdx,
float3 *dRdy,
float3 *dTdx,
float3 *dTdy,
#endif
bool *is_inside)
{
float cos = dot(N, I), neta;
float3 Nn;
// check which side of the surface we are on
if (cos > 0) {
// we are on the outside of the surface, going in
neta = 1 / eta;
Nn = N;
*is_inside = false;
}
else {
// we are inside the surface
cos = -cos;
neta = eta;
Nn = -N;
*is_inside = true;
}
// compute reflection
*R = (2 * cos) * Nn - I;
#ifdef __RAY_DIFFERENTIALS__
*dRdx = (2 * dot(Nn, dIdx)) * Nn - dIdx;
*dRdy = (2 * dot(Nn, dIdy)) * Nn - dIdy;
#endif
float arg = 1 - (neta * neta * (1 - (cos * cos)));
if (arg < 0) {
*T = make_float3(0.0f, 0.0f, 0.0f);
#ifdef __RAY_DIFFERENTIALS__
*dTdx = make_float3(0.0f, 0.0f, 0.0f);
*dTdy = make_float3(0.0f, 0.0f, 0.0f);
#endif
return 1; // total internal reflection
}
else {
float dnp = max(sqrtf(arg), 1e-7f);
float nK = (neta * cos) - dnp;
*T = -(neta * I) + (nK * Nn);
#ifdef __RAY_DIFFERENTIALS__
*dTdx = -(neta * dIdx) + ((neta - neta * neta * cos / dnp) * dot(dIdx, Nn)) * Nn;
*dTdy = -(neta * dIdy) + ((neta - neta * neta * cos / dnp) * dot(dIdy, Nn)) * Nn;
#endif
// compute Fresnel terms
float cosTheta1 = cos; // N.R
float cosTheta2 = -dot(Nn, *T);
float pPara = (cosTheta1 - eta * cosTheta2) / (cosTheta1 + eta * cosTheta2);
float pPerp = (eta * cosTheta1 - cosTheta2) / (eta * cosTheta1 + cosTheta2);
return 0.5f * (pPara * pPara + pPerp * pPerp);
}
}
ccl_device float fresnel_dielectric_cos(float cosi, float eta)
{
// compute fresnel reflectance without explicitly computing
// the refracted direction
float c = fabsf(cosi);
float g = eta * eta - 1 + c * c;
if (g > 0) {
g = sqrtf(g);
float A = (g - c) / (g + c);
float B = (c * (g + c) - 1) / (c * (g - c) + 1);
return 0.5f * A * A * (1 + B * B);
}
return 1.0f; // TIR(no refracted component)
}
ccl_device float3 fresnel_conductor(float cosi, const float3 eta, const float3 k)
{
float3 cosi2 = make_float3(cosi * cosi, cosi * cosi, cosi * cosi);
float3 one = make_float3(1.0f, 1.0f, 1.0f);
float3 tmp_f = eta * eta + k * k;
float3 tmp = tmp_f * cosi2;
float3 Rparl2 = (tmp - (2.0f * eta * cosi) + one) / (tmp + (2.0f * eta * cosi) + one);
float3 Rperp2 = (tmp_f - (2.0f * eta * cosi) + cosi2) / (tmp_f + (2.0f * eta * cosi) + cosi2);
return (Rparl2 + Rperp2) * 0.5f;
}
ccl_device float schlick_fresnel(float u)
{
float m = clamp(1.0f - u, 0.0f, 1.0f);
float m2 = m * m;
return m2 * m2 * m; // pow(m, 5)
}
/* Calculate the fresnel color which is a blend between white and the F0 color (cspec0) */
ccl_device_forceinline float3
interpolate_fresnel_color(float3 L, float3 H, float ior, float F0, float3 cspec0)
{
/* Calculate the fresnel interpolation factor
* The value from fresnel_dielectric_cos(...) has to be normalized because
* the cspec0 keeps the F0 color
*/
float F0_norm = 1.0f / (1.0f - F0);
float FH = (fresnel_dielectric_cos(dot(L, H), ior) - F0) * F0_norm;
/* Blend between white and a specular color with respect to the fresnel */
return cspec0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH;
}
CCL_NAMESPACE_END
#endif /* __BSDF_UTIL_H__ */