Files
test2/source/blender/gpu/shaders/gpu_shader_codegen_lib.glsl
Jeroen Bakker 9bcba25bc2 Fix #128282: EEVEE: Unable to compile displacement
When using vertex displacement EEVEE didn't compile the generated
functions into the vertex shader. This could result in errors when
compiling materials.

**Notes**

- Should be back-ported to Blender 4.2

Pull Request: https://projects.blender.org/blender/blender/pulls/128525
2024-10-10 12:16:28 +02:00

371 lines
8.3 KiB
GLSL

/* SPDX-FileCopyrightText: 2020-2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
vec3 calc_barycentric_distances(vec3 pos0, vec3 pos1, vec3 pos2)
{
vec3 edge21 = pos2 - pos1;
vec3 edge10 = pos1 - pos0;
vec3 edge02 = pos0 - pos2;
vec3 d21 = normalize(edge21);
vec3 d10 = normalize(edge10);
vec3 d02 = normalize(edge02);
vec3 dists;
float d = dot(d21, edge02);
dists.x = sqrt(dot(edge02, edge02) - d * d);
d = dot(d02, edge10);
dists.y = sqrt(dot(edge10, edge10) - d * d);
d = dot(d10, edge21);
dists.z = sqrt(dot(edge21, edge21) - d * d);
return dists;
}
vec2 calc_barycentric_co(int vertid)
{
vec2 bary;
bary.x = float((vertid % 3) == 0);
bary.y = float((vertid % 3) == 1);
return bary;
}
#ifdef HAIR_SHADER
/* Hairs uv and col attributes are passed by bufferTextures. */
# define DEFINE_ATTR(type, attr) uniform samplerBuffer attr
# define GET_ATTR(type, attr) hair_get_customdata_##type(attr)
# define barycentric_get() hair_get_barycentric()
# define barycentric_resolve(bary) hair_resolve_barycentric(bary)
vec3 orco_get(vec3 local_pos, mat4 modelmatinv, vec4 orco_madd[2], const samplerBuffer orco_samp)
{
/* TODO: fix ORCO with modifiers. */
vec3 orco = (modelmatinv * vec4(local_pos, 1.0)).xyz;
return orco_madd[0].xyz + orco * orco_madd[1].xyz;
}
float hair_len_get(int id, const samplerBuffer len)
{
return texelFetch(len, id).x;
}
vec4 tangent_get(const samplerBuffer attr, mat3 normalmat)
{
/* Unsupported */
return vec4(0.0);
}
#else /* MESH_SHADER */
# define DEFINE_ATTR(type, attr) in type attr
# define GET_ATTR(type, attr) attr
/* Calculated in geom shader later with calc_barycentric_co. */
# define barycentric_get() vec2(0)
# define barycentric_resolve(bary) bary
vec3 orco_get(vec3 local_pos, mat4 modelmatinv, vec4 orco_madd[2], vec4 orco)
{
/* If the object does not have any deformation, the orco layer calculation is done on the fly
* using the orco_madd factors.
* We know when there is no orco layer when orco.w is 1.0 because it uses the generic vertex
* attribute (which is [0,0,0,1]). */
if (orco.w == 0.0) {
return orco.xyz * 0.5 + 0.5;
}
else {
return orco_madd[0].xyz + local_pos * orco_madd[1].xyz;
}
}
float hair_len_get(int id, const float len)
{
return len;
}
vec4 tangent_get(vec4 attr, mat3 normalmat)
{
vec4 tangent;
tangent.xyz = normalmat * attr.xyz;
tangent.w = attr.w;
float len_sqr = dot(tangent.xyz, tangent.xyz);
/* Normalize only if vector is not null. */
if (len_sqr > 0.0) {
tangent.xyz *= inversesqrt(len_sqr);
}
return tangent;
}
#endif
/* Assumes GPU_VEC4 is color data. So converting to luminance like cycles. */
#define float_from_vec4(v) dot(v.rgb, vec3(0.2126, 0.7152, 0.0722))
#define float_from_vec3(v) ((v.r + v.g + v.b) * (1.0 / 3.0))
#define float_from_vec2(v) v.r
#define vec2_from_vec4(v) vec2(((v.r + v.g + v.b) * (1.0 / 3.0)), v.a)
#define vec2_from_vec3(v) vec2(((v.r + v.g + v.b) * (1.0 / 3.0)), 1.0)
#define vec2_from_float(v) vec2(v)
#define vec3_from_vec4(v) v.rgb
#define vec3_from_vec2(v) v.rrr
#define vec3_from_float(v) vec3(v)
#define vec4_from_vec3(v) vec4(v, 1.0)
#define vec4_from_vec2(v) v.rrrg
#define vec4_from_float(v) vec4(vec3(v), 1.0)
/* TODO: Move to shader_shared. */
#define RAY_TYPE_CAMERA 0
#define RAY_TYPE_SHADOW 1
#define RAY_TYPE_DIFFUSE 2
#define RAY_TYPE_GLOSSY 3
#ifdef GPU_FRAGMENT_SHADER
# define FrontFacing gl_FrontFacing
#else
# define FrontFacing true
#endif
/* Can't use enum here because not a header file. But would be great to do. */
#define ClosureType uint
#define CLOSURE_NONE_ID 0u
/* Diffuse */
#define CLOSURE_BSDF_DIFFUSE_ID 1u
#define CLOSURE_BSDF_OREN_NAYAR_ID 2u /* TODO */
#define CLOSURE_BSDF_SHEEN_ID 4u /* TODO */
#define CLOSURE_BSDF_DIFFUSE_TOON_ID 5u /* TODO */
#define CLOSURE_BSDF_TRANSLUCENT_ID 6u
/* Glossy */
#define CLOSURE_BSDF_MICROFACET_GGX_REFLECTION_ID 7u
#define CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID 8u /* TODO */
#define CLOSURE_BSDF_ASHIKHMIN_VELVET_ID 9u /* TODO */
#define CLOSURE_BSDF_GLOSSY_TOON_ID 10u /* TODO */
#define CLOSURE_BSDF_HAIR_REFLECTION_ID 11u /* TODO */
/* Transmission */
#define CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID 12u
/* Glass */
#define CLOSURE_BSDF_HAIR_HUANG_ID 13u /* TODO */
/* BSSRDF */
#define CLOSURE_BSSRDF_BURLEY_ID 14u
struct ClosureUndetermined {
vec3 color;
float weight;
vec3 N;
ClosureType type;
/* Additional data different for each closure type. */
vec4 data;
};
ClosureUndetermined closure_new(ClosureType type)
{
ClosureUndetermined cl;
cl.type = type;
return cl;
}
struct ClosureOcclusion {
vec3 N;
};
struct ClosureDiffuse {
float weight;
vec3 color;
vec3 N;
};
struct ClosureSubsurface {
float weight;
vec3 color;
vec3 N;
vec3 sss_radius;
};
struct ClosureTranslucent {
float weight;
vec3 color;
vec3 N;
};
struct ClosureReflection {
float weight;
vec3 color;
vec3 N;
float roughness;
};
struct ClosureRefraction {
float weight;
vec3 color;
vec3 N;
float roughness;
float ior;
};
struct ClosureHair {
float weight;
vec3 color;
float offset;
vec2 roughness;
vec3 T;
};
struct ClosureVolumeScatter {
float weight;
vec3 scattering;
float anisotropy;
};
struct ClosureVolumeAbsorption {
float weight;
vec3 absorption;
};
struct ClosureEmission {
float weight;
vec3 emission;
};
struct ClosureTransparency {
float weight;
vec3 transmittance;
float holdout;
};
ClosureDiffuse to_closure_diffuse(ClosureUndetermined cl)
{
ClosureDiffuse closure;
closure.N = cl.N;
closure.color = cl.color;
return closure;
}
ClosureSubsurface to_closure_subsurface(ClosureUndetermined cl)
{
ClosureSubsurface closure;
closure.N = cl.N;
closure.color = cl.color;
closure.sss_radius = cl.data.xyz;
return closure;
}
ClosureTranslucent to_closure_translucent(ClosureUndetermined cl)
{
ClosureTranslucent closure;
closure.N = cl.N;
closure.color = cl.color;
return closure;
}
ClosureReflection to_closure_reflection(ClosureUndetermined cl)
{
ClosureReflection closure;
closure.N = cl.N;
closure.color = cl.color;
closure.roughness = cl.data.x;
return closure;
}
ClosureRefraction to_closure_refraction(ClosureUndetermined cl)
{
ClosureRefraction closure;
closure.N = cl.N;
closure.color = cl.color;
closure.roughness = cl.data.x;
closure.ior = cl.data.y;
return closure;
}
struct GlobalData {
/** World position. */
vec3 P;
/** Surface Normal. Normalized, overridden by bump displacement. */
vec3 N;
/** Raw interpolated normal (non-normalized) data. */
vec3 Ni;
/** Geometric Normal. */
vec3 Ng;
/** Curve Tangent Space. */
vec3 curve_T, curve_B, curve_N;
/** Barycentric coordinates. */
vec2 barycentric_coords;
vec3 barycentric_dists;
/** Ray properties (approximation). */
int ray_type;
float ray_depth;
float ray_length;
/** Hair time along hair length. 0 at base 1 at tip. */
float hair_time;
/** Hair time along width of the hair. */
float hair_time_width;
/** Hair thickness in world space. */
float hair_thickness;
/** Index of the strand for per strand effects. */
int hair_strand_id;
/** Is hair. */
bool is_strand;
};
GlobalData g_data;
#ifndef GPU_FRAGMENT_SHADER
/* Stubs. */
# define dF_impl(a) (vec3(0.0))
# define dF_branch(a, b) (b = vec2(0.0))
# define dF_branch_incomplete(a, b) (b = vec2(0.0))
#elif defined(GPU_FAST_DERIVATIVE) /* TODO(@fclem): User Option? */
/* Fast derivatives */
vec3 dF_impl(vec3 v)
{
return vec3(0.0);
}
void dF_branch(float fn, out vec2 result)
{
result.x = DFDX_SIGN * dFdx(fn);
result.y = DFDY_SIGN * dFdy(fn);
}
#else
/* Precise derivatives */
int g_derivative_flag = 0;
vec3 dF_impl(vec3 v)
{
if (g_derivative_flag > 0) {
return DFDX_SIGN * dFdx(v);
}
else if (g_derivative_flag < 0) {
return DFDY_SIGN * dFdy(v);
}
return vec3(0.0);
}
# define dF_branch(fn, result) \
if (true) { \
g_derivative_flag = 1; \
result.x = (fn); \
g_derivative_flag = -1; \
result.y = (fn); \
g_derivative_flag = 0; \
result -= vec2((fn)); \
}
/* Used when the non-offset value is already computed elsewhere */
# define dF_branch_incomplete(fn, result) \
if (true) { \
g_derivative_flag = 1; \
result.x = (fn); \
g_derivative_flag = -1; \
result.y = (fn); \
g_derivative_flag = 0; \
}
#endif
/* TODO(fclem): Remove. */
#define CODEGEN_LIB