Changeset View
Changeset View
Standalone View
Standalone View
intern/cycles/kernel/closure/bsdf_microfacet.h
| Show First 20 Lines • Show All 170 Lines • ▼ Show 20 Lines | |||||
| } | } | ||||
| /* Beckmann and GGX microfacet importance sampling from: | /* Beckmann and GGX microfacet importance sampling from: | ||||
| * | * | ||||
| * Importance Sampling Microfacet-Based BSDFs using the Distribution of Visible Normals. | * Importance Sampling Microfacet-Based BSDFs using the Distribution of Visible Normals. | ||||
| * E. Heitz and E. d'Eon, EGSR 2014 */ | * E. Heitz and E. d'Eon, EGSR 2014 */ | ||||
| ccl_device_inline void microfacet_beckmann_sample_slopes( | ccl_device_inline void microfacet_beckmann_sample_slopes( | ||||
| KernelGlobals *kg, | |||||
| const float cos_theta_i, const float sin_theta_i, | const float cos_theta_i, const float sin_theta_i, | ||||
| const float alpha_x, const float alpha_y, | |||||
| float randu, float randv, float *slope_x, float *slope_y, | float randu, float randv, float *slope_x, float *slope_y, | ||||
| float *G1i) | float *G1i) | ||||
| { | { | ||||
| /* special case (normal incidence) */ | /* special case (normal incidence) */ | ||||
| if(cos_theta_i >= 0.99999f) { | if(cos_theta_i >= 0.99999f) { | ||||
| const float r = sqrtf(-logf(randu)); | const float r = sqrtf(-logf(randu)); | ||||
| const float phi = M_2PI_F * randv; | const float phi = M_2PI_F * randv; | ||||
| *slope_x = r * cosf(phi); | *slope_x = r * cosf(phi); | ||||
| *slope_y = r * sinf(phi); | *slope_y = r * sinf(phi); | ||||
| *G1i = 1.0f; | *G1i = 1.0f; | ||||
| return; | return; | ||||
| } | } | ||||
| /* precomputations */ | /* precomputations */ | ||||
| const float tan_theta_i = sin_theta_i/cos_theta_i; | const float tan_theta_i = sin_theta_i/cos_theta_i; | ||||
| const float inv_a = tan_theta_i; | const float inv_a = tan_theta_i; | ||||
| const float a = 1.0f/inv_a; | const float a = 1.0f/inv_a; | ||||
| const float erf_a = approx_erff(a); | const float erf_a = approx_erff(a); | ||||
| const float exp_a2 = expf(-a*a); | const float exp_a2 = expf(-a*a); | ||||
| const float SQRT_PI_INV = 0.56418958354f; | const float SQRT_PI_INV = 0.56418958354f; | ||||
| const float Lambda = 0.5f*(erf_a - 1.0f) + (0.5f*SQRT_PI_INV)*(exp_a2*inv_a); | const float Lambda = 0.5f*(erf_a - 1.0f) + (0.5f*SQRT_PI_INV)*(exp_a2*inv_a); | ||||
| const float G1 = 1.0f/(1.0f + Lambda); /* masking */ | const float G1 = 1.0f/(1.0f + Lambda); /* masking */ | ||||
| const float C = 1.0f - G1 * erf_a; | |||||
| *G1i = G1; | *G1i = G1; | ||||
| #if 0 | |||||
| const float C = 1.0f - G1 * erf_a; | |||||
| /* sample slope X */ | /* sample slope X */ | ||||
| if(randu < C) { | if(randu < C) { | ||||
| /* rescale randu */ | /* rescale randu */ | ||||
| randu = randu / C; | randu = randu / C; | ||||
| const float w_1 = 0.5f * SQRT_PI_INV * sin_theta_i * exp_a2; | const float w_1 = 0.5f * SQRT_PI_INV * sin_theta_i * exp_a2; | ||||
| const float w_2 = cos_theta_i * (0.5f - 0.5f*erf_a); | const float w_2 = cos_theta_i * (0.5f - 0.5f*erf_a); | ||||
| const float p = w_1 / (w_1 + w_2); | const float p = w_1 / (w_1 + w_2); | ||||
| Show All 18 Lines | if(randv > p) { | ||||
| randv = (randv - p) / (1.0f - p); | randv = (randv - p) / (1.0f - p); | ||||
| } | } | ||||
| else | else | ||||
| randv = randv / p; | randv = randv / p; | ||||
| } | } | ||||
| /* sample slope Y */ | /* sample slope Y */ | ||||
| *slope_y = approx_erfinvf(2.0f*randv - 1.0f); | *slope_y = approx_erfinvf(2.0f*randv - 1.0f); | ||||
| #else | |||||
| /* use precomputed table, because it better preserves stratification | |||||
| * of the random number pattern */ | |||||
| int beckmann_table_offset = kernel_data.tables.beckmann_offset; | |||||
| *slope_x = lookup_table_read_2D(kg, randu, cos_theta_i, | |||||
| beckmann_table_offset, BECKMANN_TABLE_SIZE, BECKMANN_TABLE_SIZE); | |||||
| *slope_y = approx_erfinvf(2.0f*randv - 1.0f); | |||||
| #endif | |||||
| } | } | ||||
| ccl_device_inline void microfacet_ggx_sample_slopes( | ccl_device_inline void microfacet_ggx_sample_slopes( | ||||
| const float cos_theta_i, const float sin_theta_i, | const float cos_theta_i, const float sin_theta_i, | ||||
| const float alpha_x, const float alpha_y, | |||||
| float randu, float randv, float *slope_x, float *slope_y, | float randu, float randv, float *slope_x, float *slope_y, | ||||
| float *G1i) | float *G1i) | ||||
| { | { | ||||
| /* special case (normal incidence) */ | /* special case (normal incidence) */ | ||||
| if(cos_theta_i >= 0.99999f) { | if(cos_theta_i >= 0.99999f) { | ||||
| const float r = sqrtf(randu/(1.0f - randu)); | const float r = sqrtf(randu/(1.0f - randu)); | ||||
| const float phi = M_2PI_F * randv; | const float phi = M_2PI_F * randv; | ||||
| *slope_x = r * cosf(phi); | *slope_x = r * cosf(phi); | ||||
| Show All 31 Lines | else { | ||||
| S = -1.0f; | S = -1.0f; | ||||
| randv = 2.0f*(0.5f - randv); | randv = 2.0f*(0.5f - randv); | ||||
| } | } | ||||
| const float z = (randv*(randv*(randv*0.27385f - 0.73369f) + 0.46341f)) / (randv*(randv*(randv*0.093073f + 0.309420f) - 1.000000f) + 0.597999f); | const float z = (randv*(randv*(randv*0.27385f - 0.73369f) + 0.46341f)) / (randv*(randv*(randv*0.093073f + 0.309420f) - 1.000000f) + 0.597999f); | ||||
| *slope_y = S * z * safe_sqrtf(1.0f + (*slope_x)*(*slope_x)); | *slope_y = S * z * safe_sqrtf(1.0f + (*slope_x)*(*slope_x)); | ||||
| } | } | ||||
| ccl_device_inline float3 microfacet_sample_stretched(const float3 omega_i, | ccl_device_inline float3 microfacet_sample_stretched( | ||||
| KernelGlobals *kg, const float3 omega_i, | |||||
| const float alpha_x, const float alpha_y, | const float alpha_x, const float alpha_y, | ||||
| const float randu, const float randv, | const float randu, const float randv, | ||||
| bool beckmann, float *G1i) | bool beckmann, float *G1i) | ||||
| { | { | ||||
| /* 1. stretch omega_i */ | /* 1. stretch omega_i */ | ||||
| float3 omega_i_ = make_float3(alpha_x * omega_i.x, alpha_y * omega_i.y, omega_i.z); | float3 omega_i_ = make_float3(alpha_x * omega_i.x, alpha_y * omega_i.y, omega_i.z); | ||||
| omega_i_ = normalize(omega_i_); | omega_i_ = normalize(omega_i_); | ||||
| Show All 10 Lines | if(omega_i_.z < 0.99999f) { | ||||
| float invlen = 1.0f/sintheta_; | float invlen = 1.0f/sintheta_; | ||||
| cosphi_ = omega_i_.x * invlen; | cosphi_ = omega_i_.x * invlen; | ||||
| sinphi_ = omega_i_.y * invlen; | sinphi_ = omega_i_.y * invlen; | ||||
| } | } | ||||
| /* 2. sample P22_{omega_i}(x_slope, y_slope, 1, 1) */ | /* 2. sample P22_{omega_i}(x_slope, y_slope, 1, 1) */ | ||||
| float slope_x, slope_y; | float slope_x, slope_y; | ||||
| if(beckmann) | if(beckmann) { | ||||
| microfacet_beckmann_sample_slopes(costheta_, sintheta_, | microfacet_beckmann_sample_slopes(kg, costheta_, sintheta_, | ||||
| alpha_x, alpha_y, randu, randv, &slope_x, &slope_y, G1i); | randu, randv, &slope_x, &slope_y, G1i); | ||||
| else | } | ||||
| else { | |||||
| microfacet_ggx_sample_slopes(costheta_, sintheta_, | microfacet_ggx_sample_slopes(costheta_, sintheta_, | ||||
| alpha_x, alpha_y, randu, randv, &slope_x, &slope_y, G1i); | randu, randv, &slope_x, &slope_y, G1i); | ||||
| } | |||||
| /* 3. rotate */ | /* 3. rotate */ | ||||
| float tmp = cosphi_*slope_x - sinphi_*slope_y; | float tmp = cosphi_*slope_x - sinphi_*slope_y; | ||||
| slope_y = sinphi_*slope_x + cosphi_*slope_y; | slope_y = sinphi_*slope_x + cosphi_*slope_y; | ||||
| slope_x = tmp; | slope_x = tmp; | ||||
| /* 4. unstretch */ | /* 4. unstretch */ | ||||
| slope_x = alpha_x * slope_x; | slope_x = alpha_x * slope_x; | ||||
| ▲ Show 20 Lines • Show All 191 Lines • ▼ Show 20 Lines | ccl_device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) | ||||
| * pdf = pm * (m_eta * m_eta) * fabsf(cosHI) / Ht2 */ | * pdf = pm * (m_eta * m_eta) * fabsf(cosHI) / Ht2 */ | ||||
| float common = D * (m_eta * m_eta) / (cosNO * Ht2); | float common = D * (m_eta * m_eta) / (cosNO * Ht2); | ||||
| float out = G * fabsf(cosHI * cosHO) * common; | float out = G * fabsf(cosHI * cosHO) * common; | ||||
| *pdf = G1o * cosHO * fabsf(cosHI) * common; | *pdf = G1o * cosHO * fabsf(cosHI) * common; | ||||
| return make_float3(out, out, out); | return make_float3(out, out, out); | ||||
| } | } | ||||
| ccl_device int bsdf_microfacet_ggx_sample(const ShaderClosure *sc, float3 Ng, 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) | ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg, const ShaderClosure *sc, float3 Ng, 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) | ||||
| { | { | ||||
| float alpha_x = sc->data0; | float alpha_x = sc->data0; | ||||
| float alpha_y = sc->data1; | float alpha_y = sc->data1; | ||||
| int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID; | int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID; | ||||
| float3 N = sc->N; | float3 N = sc->N; | ||||
| float cosNO = dot(N, I); | float cosNO = dot(N, I); | ||||
| if(cosNO > 0) { | if(cosNO > 0) { | ||||
| float3 X, Y, Z = N; | float3 X, Y, Z = N; | ||||
| if(alpha_x == alpha_y) | if(alpha_x == alpha_y) | ||||
| make_orthonormals(Z, &X, &Y); | make_orthonormals(Z, &X, &Y); | ||||
| else | else | ||||
| make_orthonormals_tangent(Z, sc->T, &X, &Y); | make_orthonormals_tangent(Z, sc->T, &X, &Y); | ||||
| /* importance sampling with distribution of visible normals. vectors are | /* importance sampling with distribution of visible normals. vectors are | ||||
| * transformed to local space before and after */ | * transformed to local space before and after */ | ||||
| float3 local_I = make_float3(dot(X, I), dot(Y, I), cosNO); | float3 local_I = make_float3(dot(X, I), dot(Y, I), cosNO); | ||||
| float3 local_m; | float3 local_m; | ||||
| float G1o; | float G1o; | ||||
| local_m = microfacet_sample_stretched(local_I, alpha_x, alpha_y, | local_m = microfacet_sample_stretched(kg, local_I, alpha_x, alpha_y, | ||||
| randu, randv, false, &G1o); | randu, randv, false, &G1o); | ||||
| float3 m = X*local_m.x + Y*local_m.y + Z*local_m.z; | float3 m = X*local_m.x + Y*local_m.y + Z*local_m.z; | ||||
| float cosThetaM = local_m.z; | float cosThetaM = local_m.z; | ||||
| /* reflection or refraction? */ | /* reflection or refraction? */ | ||||
| if(!m_refractive) { | if(!m_refractive) { | ||||
| float cosMO = dot(m, I); | float cosMO = dot(m, I); | ||||
| ▲ Show 20 Lines • Show All 309 Lines • ▼ Show 20 Lines | ccl_device float3 bsdf_microfacet_beckmann_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) | ||||
| * pdf = pm * (m_eta * m_eta) * fabsf(cosHI) / Ht2 */ | * pdf = pm * (m_eta * m_eta) * fabsf(cosHI) / Ht2 */ | ||||
| float common = D * (m_eta * m_eta) / (cosNO * Ht2); | float common = D * (m_eta * m_eta) / (cosNO * Ht2); | ||||
| float out = G * fabsf(cosHI * cosHO) * common; | float out = G * fabsf(cosHI * cosHO) * common; | ||||
| *pdf = G1o * cosHO * fabsf(cosHI) * common; | *pdf = G1o * cosHO * fabsf(cosHI) * common; | ||||
| return make_float3(out, out, out); | return make_float3(out, out, out); | ||||
| } | } | ||||
| ccl_device int bsdf_microfacet_beckmann_sample(const ShaderClosure *sc, float3 Ng, 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) | ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals *kg, const ShaderClosure *sc, float3 Ng, 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) | ||||
| { | { | ||||
| float alpha_x = sc->data0; | float alpha_x = sc->data0; | ||||
| float alpha_y = sc->data1; | float alpha_y = sc->data1; | ||||
| int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID; | int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID; | ||||
| float3 N = sc->N; | float3 N = sc->N; | ||||
| float cosNO = dot(N, I); | float cosNO = dot(N, I); | ||||
| if(cosNO > 0) { | if(cosNO > 0) { | ||||
| float3 X, Y, Z = N; | float3 X, Y, Z = N; | ||||
| if(alpha_x == alpha_y) | if(alpha_x == alpha_y) | ||||
| make_orthonormals(Z, &X, &Y); | make_orthonormals(Z, &X, &Y); | ||||
| else | else | ||||
| make_orthonormals_tangent(Z, sc->T, &X, &Y); | make_orthonormals_tangent(Z, sc->T, &X, &Y); | ||||
| /* importance sampling with distribution of visible normals. vectors are | /* importance sampling with distribution of visible normals. vectors are | ||||
| * transformed to local space before and after */ | * transformed to local space before and after */ | ||||
| float3 local_I = make_float3(dot(X, I), dot(Y, I), cosNO); | float3 local_I = make_float3(dot(X, I), dot(Y, I), cosNO); | ||||
| float3 local_m; | float3 local_m; | ||||
| float G1o; | float G1o; | ||||
| local_m = microfacet_sample_stretched(local_I, alpha_x, alpha_x, | local_m = microfacet_sample_stretched(kg, local_I, alpha_x, alpha_x, | ||||
| randu, randv, true, &G1o); | randu, randv, true, &G1o); | ||||
| float3 m = X*local_m.x + Y*local_m.y + Z*local_m.z; | float3 m = X*local_m.x + Y*local_m.y + Z*local_m.z; | ||||
| float cosThetaM = local_m.z; | float cosThetaM = local_m.z; | ||||
| /* reflection or refraction? */ | /* reflection or refraction? */ | ||||
| if(!m_refractive) { | if(!m_refractive) { | ||||
| float cosMO = dot(m, I); | float cosMO = dot(m, I); | ||||
| ▲ Show 20 Lines • Show All 141 Lines • Show Last 20 Lines | |||||