GOOENGINE: Principled bsdf versioning
Increase max parameters to 38 and version the old and new principled bsdf for eevee legacy Version vector math length squared function. A hacky solution but will look for a proper fix later
This commit is contained in:
@@ -62,8 +62,8 @@ GPU_SHADER_CREATE_INFO(eevee_legacy_lights_lib)
|
||||
.sampler(8, ImageType::SHADOW_2D_ARRAY, "shadowCubeTexture")
|
||||
.sampler(9, ImageType::SHADOW_2D_ARRAY, "shadowCascadeTexture")
|
||||
/* GooEngine: Use slots 15,16 as others are already taken. */
|
||||
.sampler(15, ImageType::UINT_2D_ARRAY, "shadowCubeIDTexture")
|
||||
.sampler(16, ImageType::UINT_2D_ARRAY, "shadowCascadeIDTexture");
|
||||
.sampler(23, ImageType::UINT_2D_ARRAY, "shadowCubeIDTexture")
|
||||
.sampler(24, ImageType::UINT_2D_ARRAY, "shadowCascadeIDTexture");
|
||||
|
||||
/* Hair lib. */
|
||||
GPU_SHADER_CREATE_INFO(eevee_legacy_hair_lib)
|
||||
|
||||
@@ -84,6 +84,13 @@ enum eGPUMaterialFlag {
|
||||
|
||||
GPU_MATFLAG_BARYCENTRIC = (1 << 20),
|
||||
|
||||
/* Optimization to only add the branches of the principled shader that are necessary. */
|
||||
GPU_MATFLAG_PRINCIPLED_COAT = (1 << 21),
|
||||
GPU_MATFLAG_PRINCIPLED_METALLIC = (1 << 22),
|
||||
GPU_MATFLAG_PRINCIPLED_DIELECTRIC = (1 << 23),
|
||||
GPU_MATFLAG_PRINCIPLED_GLASS = (1 << 24),
|
||||
GPU_MATFLAG_PRINCIPLED_ANY = (1 << 25),
|
||||
|
||||
/* Tells the render engine the material was just compiled or updated. */
|
||||
GPU_MATFLAG_UPDATED = (1 << 29),
|
||||
|
||||
@@ -220,6 +227,10 @@ char *GPU_material_split_sub_function(GPUMaterial *material,
|
||||
GPUNodeLink **link);
|
||||
|
||||
bool GPU_material_sss_profile_create(GPUMaterial *material, float radii[3]);
|
||||
GPUUniformBuf *GPU_material_sss_profile_get(GPUMaterial *material,
|
||||
int sample_len,
|
||||
GPUTexture **tex_profile);
|
||||
|
||||
/**
|
||||
* High level functions to create and use GPU materials.
|
||||
*/
|
||||
|
||||
@@ -397,6 +397,24 @@ void GPUCodegen::generate_resources()
|
||||
{
|
||||
GPUCodegenCreateInfo &info = *create_info;
|
||||
|
||||
/* Ref. #98190: Defines are optimizations for old compilers.
|
||||
* Might become unnecessary with EEVEE-Next. */
|
||||
if (GPU_material_flag_get(&mat, GPU_MATFLAG_PRINCIPLED_COAT)) {
|
||||
info.define("PRINCIPLED_COAT");
|
||||
}
|
||||
if (GPU_material_flag_get(&mat, GPU_MATFLAG_PRINCIPLED_METALLIC)) {
|
||||
info.define("PRINCIPLED_METALLIC");
|
||||
}
|
||||
if (GPU_material_flag_get(&mat, GPU_MATFLAG_PRINCIPLED_DIELECTRIC)) {
|
||||
info.define("PRINCIPLED_DIELECTRIC");
|
||||
}
|
||||
if (GPU_material_flag_get(&mat, GPU_MATFLAG_PRINCIPLED_GLASS)) {
|
||||
info.define("PRINCIPLED_GLASS");
|
||||
}
|
||||
if (GPU_material_flag_get(&mat, GPU_MATFLAG_PRINCIPLED_ANY)) {
|
||||
info.define("PRINCIPLED_ANY");
|
||||
}
|
||||
|
||||
std::stringstream ss;
|
||||
|
||||
/* Textures. */
|
||||
@@ -944,6 +962,7 @@ bool GPU_pass_async_compilation_try_finalize(GPUPass *pass)
|
||||
bool GPU_pass_compile(GPUPass *pass, const char *shname)
|
||||
{
|
||||
BLI_mutex_lock(&pass->shader_creation_mutex);
|
||||
|
||||
bool success = true;
|
||||
if (pass->async_compilation_handle > 0) {
|
||||
/* We're trying to compile this pass synchronously, but there's a pending asynchronous
|
||||
@@ -955,6 +974,7 @@ bool GPU_pass_compile(GPUPass *pass, const char *shname)
|
||||
GPUShader *shader = GPU_shader_create_from_info(info);
|
||||
success = GPU_pass_finalize_compilation(pass, shader);
|
||||
}
|
||||
|
||||
BLI_mutex_unlock(&pass->shader_creation_mutex);
|
||||
return success;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include "GPU_material.hh"
|
||||
|
||||
#define MAX_FUNCTION_NAME 64
|
||||
#define MAX_PARAMETER 36
|
||||
#define MAX_PARAMETER 38
|
||||
|
||||
struct GSet;
|
||||
|
||||
|
||||
@@ -58,7 +58,11 @@ void node_bsdf_principled(vec4 base_color,
|
||||
float emission_strength,
|
||||
float thin_film_thickness,
|
||||
float thin_film_ior,
|
||||
const float do_diffuse,
|
||||
const float do_coat,
|
||||
const float do_refraction,
|
||||
const float do_multiscatter,
|
||||
const float do_sss,
|
||||
out Closure result)
|
||||
{
|
||||
/* Match cycles. */
|
||||
@@ -91,6 +95,198 @@ void node_bsdf_principled(vec4 base_color,
|
||||
vec3 V = coordinate_incoming(g_data.P);
|
||||
float NV = dot(N, V);
|
||||
|
||||
#ifdef GPU_SHADER_EEVEE_LEGACY_DEFINES
|
||||
ClosureTransparency transparency_data;
|
||||
transparency_data.weight = weight;
|
||||
transparency_data.transmittance = vec3(1.0 - alpha);
|
||||
transparency_data.holdout = 0.0;
|
||||
weight *= alpha;
|
||||
|
||||
/* First layer: Sheen */
|
||||
vec3 sheen_data_color = vec3(0.0);
|
||||
if (sheen_weight > 0.0) {
|
||||
/* TODO: Maybe sheen_weight should be specular. */
|
||||
vec3 sheen_color = sheen_weight * sheen_tint.rgb * principled_sheen(NV, sheen_roughness);
|
||||
sheen_data_color = weight * sheen_color;
|
||||
/* Attenuate lower layers */
|
||||
weight *= max((1.0 - math_reduce_max(sheen_color)), 0.0);
|
||||
}
|
||||
|
||||
/* Second layer: Coat */
|
||||
ClosureReflection coat_data;
|
||||
coat_data.N = CN;
|
||||
coat_data.roughness = coat_roughness;
|
||||
coat_data.color = vec3(1.0);
|
||||
|
||||
if (coat_weight > 0.0) {
|
||||
float coat_NV = dot(coat_data.N, V);
|
||||
float reflectance = bsdf_lut(coat_NV, coat_data.roughness, coat_ior, false).x;
|
||||
coat_data.weight = weight * coat_weight * reflectance;
|
||||
/* Attenuate lower layers */
|
||||
weight *= max((1.0 - reflectance * coat_weight), 0.0);
|
||||
|
||||
if (!all(equal(coat_tint.rgb, vec3(1.0)))) {
|
||||
float coat_neta = 1.0 / coat_ior;
|
||||
float NT = sqrt_fast(1.0 - coat_neta * coat_neta * (1 - NV * NV));
|
||||
/* Tint lower layers. */
|
||||
coat_tint.rgb = mix(vec3(1.0), pow(coat_tint.rgb, vec3(1.0 / NT)), saturate(coat_weight));
|
||||
}
|
||||
}
|
||||
else {
|
||||
coat_tint.rgb = vec3(1.0);
|
||||
coat_data.weight = 0.0;
|
||||
}
|
||||
|
||||
/* Attenuated by sheen and coat. */
|
||||
ClosureEmission emission_data;
|
||||
emission_data.weight = weight;
|
||||
emission_data.emission = coat_tint.rgb * emission.rgb * emission_strength;
|
||||
|
||||
/* Metallic component */
|
||||
ClosureReflection reflection_data;
|
||||
reflection_data.N = N;
|
||||
reflection_data.roughness = roughness;
|
||||
vec3 reflection_tint = specular_tint.rgb;
|
||||
if (metallic > 0.0) {
|
||||
vec3 F0 = clamped_base_color.rgb;
|
||||
vec3 F82 = min(reflection_tint, vec3(1.0));
|
||||
vec3 metallic_brdf;
|
||||
brdf_f82_tint_lut(F0, F82, NV, roughness, do_multiscatter != 0.0, metallic_brdf);
|
||||
reflection_data.color = weight * metallic * metallic_brdf;
|
||||
/* Attenuate lower layers */
|
||||
weight *= max((1.0 - metallic), 0.0);
|
||||
}
|
||||
else {
|
||||
reflection_data.color = vec3(0.0);
|
||||
}
|
||||
|
||||
/* Transmission component */
|
||||
ClosureRefraction refraction_data;
|
||||
refraction_data.N = N;
|
||||
refraction_data.roughness = roughness;
|
||||
refraction_data.ior = ior;
|
||||
if (transmission_weight > 0.0) {
|
||||
vec3 F0 = vec3(F0_from_ior(ior)) * reflection_tint;
|
||||
vec3 F90 = vec3(1.0);
|
||||
vec3 reflectance, transmittance;
|
||||
bsdf_lut(F0,
|
||||
F90,
|
||||
clamped_base_color.rgb,
|
||||
NV,
|
||||
roughness,
|
||||
ior,
|
||||
do_multiscatter != 0.0,
|
||||
reflectance,
|
||||
transmittance);
|
||||
|
||||
reflection_data.color += weight * transmission_weight * reflectance;
|
||||
|
||||
refraction_data.weight = weight * transmission_weight;
|
||||
refraction_data.color = transmittance * coat_tint.rgb;
|
||||
/* Attenuate lower layers */
|
||||
weight *= max((1.0 - transmission_weight), 0.0);
|
||||
}
|
||||
else {
|
||||
refraction_data.weight = 0.0;
|
||||
refraction_data.color = vec3(0.0);
|
||||
}
|
||||
|
||||
/* Specular component */
|
||||
if (true) {
|
||||
float eta = ior;
|
||||
float f0 = F0_from_ior(eta);
|
||||
if (specular_ior_level != 0.5) {
|
||||
f0 *= 2.0 * specular_ior_level;
|
||||
eta = ior_from_F0(f0);
|
||||
if (ior < 1.0) {
|
||||
eta = 1.0 / eta;
|
||||
}
|
||||
}
|
||||
|
||||
vec3 F0 = vec3(f0) * reflection_tint;
|
||||
F0 = clamp(F0, vec3(0.0), vec3(1.0));
|
||||
vec3 F90 = vec3(1.0);
|
||||
vec3 reflectance, unused;
|
||||
bsdf_lut(F0, F90, vec3(0.0), NV, roughness, eta, do_multiscatter != 0.0, reflectance, unused);
|
||||
|
||||
reflection_data.color += weight * reflectance;
|
||||
/* Adjust the weight of picking the closure. */
|
||||
reflection_data.color *= coat_tint.rgb;
|
||||
reflection_data.weight = math_average(reflection_data.color);
|
||||
reflection_data.color *= safe_rcp(reflection_data.weight);
|
||||
|
||||
/* Attenuate lower layers */
|
||||
weight *= max((1.0 - math_reduce_max(reflectance)), 0.0);
|
||||
}
|
||||
|
||||
/* EEVEE Legacy evaluates the subsurface as a diffuse closure.
|
||||
* So this has no performance penalty. However, using a separate closure for subsurface
|
||||
* (just like for EEVEE-Next) would induce a huge performance hit. */
|
||||
ClosureSubsurface diffuse_data;
|
||||
/* Flag subsurface as disabled by default. */
|
||||
diffuse_data.sss_radius.b = -1.0;
|
||||
diffuse_data.N = N;
|
||||
|
||||
subsurface_radius = max(subsurface_radius * subsurface_scale, vec3(0.0));
|
||||
|
||||
/* Subsurface component */
|
||||
if (subsurface_weight > 0.0) {
|
||||
/* For Legacy EEVEE, Subsurface is just part of the diffuse. Just evaluate the mixed color. */
|
||||
/* Subsurface Scattering materials behave unpredictably with values greater than 1.0 in
|
||||
* Cycles. So it's clamped there and we clamp here for consistency with Cycles. */
|
||||
base_color = mix(base_color, clamped_base_color, subsurface_weight);
|
||||
if (do_sss != 0.0) {
|
||||
diffuse_data.sss_radius = subsurface_weight * subsurface_radius;
|
||||
}
|
||||
}
|
||||
|
||||
/* Diffuse component */
|
||||
if (true) {
|
||||
diffuse_data.color = weight * base_color.rgb * coat_tint.rgb;
|
||||
/* Add energy of the sheen layer until we have proper sheen BSDF. */
|
||||
diffuse_data.color += sheen_data_color;
|
||||
|
||||
diffuse_data.weight = math_average(diffuse_data.color);
|
||||
diffuse_data.color *= safe_rcp(diffuse_data.weight);
|
||||
}
|
||||
|
||||
/* Ref. #98190: Defines are optimizations for old compilers.
|
||||
* Might become unnecessary with EEVEE-Next. */
|
||||
if (do_diffuse == 0.0 && do_refraction == 0.0 && do_coat != 0.0) {
|
||||
#ifdef PRINCIPLED_COAT
|
||||
/* Metallic & Coat case. */
|
||||
result = closure_eval(reflection_data, coat_data);
|
||||
#endif
|
||||
}
|
||||
else if (do_diffuse == 0.0 && do_refraction == 0.0 && do_coat == 0.0) {
|
||||
#ifdef PRINCIPLED_METALLIC
|
||||
/* Metallic case. */
|
||||
result = closure_eval(reflection_data);
|
||||
#endif
|
||||
}
|
||||
else if (do_diffuse != 0.0 && do_refraction == 0.0 && do_coat == 0.0) {
|
||||
#ifdef PRINCIPLED_DIELECTRIC
|
||||
/* Dielectric case. */
|
||||
result = closure_eval(diffuse_data, reflection_data);
|
||||
#endif
|
||||
}
|
||||
else if (do_diffuse == 0.0 && do_refraction != 0.0 && do_coat == 0.0) {
|
||||
#ifdef PRINCIPLED_GLASS
|
||||
/* Glass case. */
|
||||
result = closure_eval(reflection_data, refraction_data);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
#ifdef PRINCIPLED_ANY
|
||||
/* Un-optimized case. */
|
||||
result = closure_eval(diffuse_data, reflection_data, coat_data, refraction_data);
|
||||
#endif
|
||||
}
|
||||
Closure emission_cl = closure_eval(emission_data);
|
||||
Closure transparency_cl = closure_eval(transparency_data);
|
||||
result = closure_add(result, emission_cl);
|
||||
result = closure_add(result, transparency_cl);
|
||||
#else
|
||||
/* Transparency component. */
|
||||
if (true) {
|
||||
ClosureTransparency transparency_data;
|
||||
@@ -251,4 +447,5 @@ void node_bsdf_principled(vec4 base_color,
|
||||
}
|
||||
|
||||
result = Closure(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -4,10 +4,23 @@
|
||||
|
||||
#pragma BLENDER_REQUIRE(gpu_shader_common_math_utils.glsl)
|
||||
|
||||
float len_sqred(vec2 a)
|
||||
{
|
||||
return dot(a, a);
|
||||
}
|
||||
float len_sqred(vec3 a)
|
||||
{
|
||||
return dot(a, a);
|
||||
}
|
||||
float len_sqred(vec4 a)
|
||||
{
|
||||
return dot(a, a);
|
||||
}
|
||||
|
||||
vec3 vector_math_safe_normalize(vec3 a)
|
||||
{
|
||||
/* Match the safe normalize function in Cycles by defaulting to vec3(0.0) */
|
||||
float length_sqr = length_squared(a);
|
||||
float length_sqr = len_sqred(a);
|
||||
return (length_sqr > 1e-35f) ? a * inversesqrt(length_sqr) : vec3(0.0);
|
||||
}
|
||||
|
||||
|
||||
@@ -343,6 +343,24 @@ static int node_shader_gpu_bsdf_principled(GPUMaterial *mat,
|
||||
flag |= GPU_MATFLAG_COAT;
|
||||
}
|
||||
|
||||
/* Ref. #98190: Defines are optimizations for old compilers.
|
||||
* Might become unnecessary with EEVEE-Next. */
|
||||
if (use_diffuse == false && use_refract == false && use_coat == true) {
|
||||
flag |= GPU_MATFLAG_PRINCIPLED_COAT;
|
||||
}
|
||||
else if (use_diffuse == false && use_refract == false && use_coat == false) {
|
||||
flag |= GPU_MATFLAG_PRINCIPLED_METALLIC;
|
||||
}
|
||||
else if (use_diffuse == true && use_refract == false && use_coat == false) {
|
||||
flag |= GPU_MATFLAG_PRINCIPLED_DIELECTRIC;
|
||||
}
|
||||
else if (use_diffuse == false && use_refract == true && use_coat == false) {
|
||||
flag |= GPU_MATFLAG_PRINCIPLED_GLASS;
|
||||
}
|
||||
else {
|
||||
flag |= GPU_MATFLAG_PRINCIPLED_ANY;
|
||||
}
|
||||
|
||||
if (use_subsurf) {
|
||||
bNodeSocket *socket = (bNodeSocket *)BLI_findlink(&node->runtime->original->inputs,
|
||||
SOCK_SUBSURFACE_RADIUS_ID);
|
||||
@@ -352,11 +370,23 @@ static int node_shader_gpu_bsdf_principled(GPUMaterial *mat,
|
||||
}
|
||||
|
||||
float use_multi_scatter = (node->custom1 == SHD_GLOSSY_MULTI_GGX) ? 1.0f : 0.0f;
|
||||
float use_sss = (use_subsurf) ? 1.0f : 0.0f;
|
||||
float use_diffuse_f = (use_diffuse) ? 1.0f : 0.0f;
|
||||
float use_coat_f = (use_coat) ? 1.0f : 0.0f;
|
||||
float use_refract_f = (use_refract) ? 1.0f : 0.0f;
|
||||
|
||||
GPU_material_flag_set(mat, flag);
|
||||
|
||||
return GPU_stack_link(
|
||||
mat, node, "node_bsdf_principled", in, out, GPU_constant(&use_multi_scatter));
|
||||
return GPU_stack_link(mat,
|
||||
node,
|
||||
"node_bsdf_principled",
|
||||
in,
|
||||
out,
|
||||
GPU_constant(&use_diffuse_f),
|
||||
GPU_constant(&use_coat_f),
|
||||
GPU_constant(&use_refract_f),
|
||||
GPU_constant(&use_multi_scatter),
|
||||
GPU_constant(&use_sss));
|
||||
}
|
||||
|
||||
static void node_shader_update_principled(bNodeTree *ntree, bNode *node)
|
||||
|
||||
Reference in New Issue
Block a user