diff options
Diffstat (limited to 'source/blender/gpu/shaders/gpu_shader_material.glsl')
-rw-r--r-- | source/blender/gpu/shaders/gpu_shader_material.glsl | 817 |
1 files changed, 589 insertions, 228 deletions
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index f98d7b9f5bb..07c3b1e782b 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -1,11 +1,57 @@ + +uniform mat4 ModelViewMatrix; +#ifndef EEVEE_ENGINE +uniform mat4 ProjectionMatrix; +uniform mat4 ViewMatrixInverse; +uniform mat4 ViewMatrix; +#endif +uniform mat4 ModelMatrix; +uniform mat4 ModelMatrixInverse; +uniform mat4 ModelViewMatrixInverse; +uniform mat4 ProjectionMatrixInverse; +uniform mat3 NormalMatrix; +uniform vec4 CameraTexCoFactors; + +/* Old glsl mode compat. */ + +#ifndef CLOSURE_DEFAULT + +struct Closure { + vec3 radiance; + float opacity; +}; + +#define CLOSURE_DEFAULT Closure(vec3(0.0), 1.0) + +Closure closure_mix(Closure cl1, Closure cl2, float fac) +{ + Closure cl; + cl.radiance = mix(cl1.radiance, cl2.radiance, fac); + cl.opacity = mix(cl1.opacity, cl2.opacity, fac); + return cl; +} + +Closure closure_add(Closure cl1, Closure cl2) +{ + Closure cl; + cl.radiance = cl1.radiance + cl2.radiance; + cl.opacity = cl1.opacity + cl2.opacity; + return cl; +} + +Closure nodetree_exec(void); /* Prototype */ + +#endif /* CLOSURE_DEFAULT */ + + /* Converters */ float convert_rgba_to_float(vec4 color) { #ifdef USE_NEW_SHADING - return color.r * 0.2126 + color.g * 0.7152 + color.b * 0.0722; + return dot(color.rgb, vec3(0.2126, 0.7152, 0.0722)); #else - return (color.r + color.g + color.b) / 3.0; + return (color.r + color.g + color.b) * 0.333333; #endif } @@ -53,7 +99,7 @@ void rgb_to_hsv(vec4 rgb, out vec4 outcol) h = 0.0; } else { - c = (vec3(cmax, cmax, cmax) - rgb.xyz) / cdelta; + c = (vec3(cmax) - rgb.xyz) / cdelta; if (rgb.x == cmax) h = c[2] - c[1]; else if (rgb.y == cmax) h = 2.0 + c[0] - c[2]; @@ -155,15 +201,18 @@ void color_to_blender_normal_new_shading(vec3 color, out vec3 normal) normal.y = -2.0 * ((color.g) - 0.5); normal.z = -2.0 * ((color.b) - 0.5); } - +#ifndef M_PI #define M_PI 3.14159265358979323846 -#define M_1_PI 0.31830988618379069 +#endif +#ifndef M_1_PI +#define M_1_PI 0.318309886183790671538 +#endif /*********** SHADER NODES ***************/ void vcol_attribute(vec4 attvcol, out vec4 vcol) { - vcol = vec4(attvcol.x, attvcol.y, attvcol.z, 1.0); + vcol = vec4(attvcol.xyz, 1.0); } void uv_attribute(vec2 attuv, out vec3 uv) @@ -177,7 +226,7 @@ void geom( out vec3 normal, out vec4 vcol, out float vcol_alpha, out float frontback) { local = co; - view = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(local) : vec3(0.0, 0.0, -1.0); + view = (ProjectionMatrix[3][3] == 0.0) ? normalize(local) : vec3(0.0, 0.0, -1.0); global = (viewinvmat * vec4(local, 1.0)).xyz; orco = attorco; uv_attribute(attuv, uv); @@ -419,13 +468,13 @@ void squeeze(float val, float width, float center, out float outval) void vec_math_add(vec3 v1, vec3 v2, out vec3 outvec, out float outval) { outvec = v1 + v2; - outval = (abs(outvec[0]) + abs(outvec[1]) + abs(outvec[2])) / 3.0; + outval = (abs(outvec[0]) + abs(outvec[1]) + abs(outvec[2])) * 0.333333; } void vec_math_sub(vec3 v1, vec3 v2, out vec3 outvec, out float outval) { outvec = v1 - v2; - outval = (abs(outvec[0]) + abs(outvec[1]) + abs(outvec[2])) / 3.0; + outval = (abs(outvec[0]) + abs(outvec[1]) + abs(outvec[2])) * 0.333333; } void vec_math_average(vec3 v1, vec3 v2, out vec3 outvec, out float outval) @@ -441,7 +490,7 @@ void vec_math_mix(float strength, vec3 v1, vec3 v2, out vec3 outvec) void vec_math_dot(vec3 v1, vec3 v2, out vec3 outvec, out float outval) { - outvec = vec3(0, 0, 0); + outvec = vec3(0); outval = dot(v1, v2); } @@ -483,9 +532,9 @@ void normal_new_shading(vec3 dir, vec3 nor, out vec3 outnor, out float outdot) void curves_vec(float fac, vec3 vec, sampler2D curvemap, out vec3 outvec) { - outvec.x = texture2D(curvemap, vec2((vec.x + 1.0) * 0.5, 0.0)).x; - outvec.y = texture2D(curvemap, vec2((vec.y + 1.0) * 0.5, 0.0)).y; - outvec.z = texture2D(curvemap, vec2((vec.z + 1.0) * 0.5, 0.0)).z; + outvec.x = texture(curvemap, vec2((vec.x + 1.0) * 0.5, 0.0)).x; + outvec.y = texture(curvemap, vec2((vec.y + 1.0) * 0.5, 0.0)).y; + outvec.z = texture(curvemap, vec2((vec.z + 1.0) * 0.5, 0.0)).z; if (fac != 1.0) outvec = (outvec * fac) + (vec * (1.0 - fac)); @@ -494,9 +543,9 @@ void curves_vec(float fac, vec3 vec, sampler2D curvemap, out vec3 outvec) void curves_rgb(float fac, vec4 col, sampler2D curvemap, out vec4 outcol) { - outcol.r = texture2D(curvemap, vec2(texture2D(curvemap, vec2(col.r, 0.0)).a, 0.0)).r; - outcol.g = texture2D(curvemap, vec2(texture2D(curvemap, vec2(col.g, 0.0)).a, 0.0)).g; - outcol.b = texture2D(curvemap, vec2(texture2D(curvemap, vec2(col.b, 0.0)).a, 0.0)).b; + outcol.r = texture(curvemap, vec2(texture(curvemap, vec2(col.r, 0.0)).a, 0.0)).r; + outcol.g = texture(curvemap, vec2(texture(curvemap, vec2(col.g, 0.0)).a, 0.0)).g; + outcol.b = texture(curvemap, vec2(texture(curvemap, vec2(col.b, 0.0)).a, 0.0)).b; if (fac != 1.0) outcol = (outcol * fac) + (col * (1.0 - fac)); @@ -816,22 +865,23 @@ void mix_linear(float fac, vec4 col1, vec4 col2, out vec4 outcol) void valtorgb(float fac, sampler2D colormap, out vec4 outcol, out float outalpha) { - outcol = texture2D(colormap, vec2(fac, 0.0)); + outcol = texture(colormap, vec2(fac, 0.0)); outalpha = outcol.a; } void rgbtobw(vec4 color, out float outval) { #ifdef USE_NEW_SHADING - outval = color.r * 0.2126 + color.g * 0.7152 + color.b * 0.0722; + vec3 factors = vec3(0.2126, 0.7152, 0.0722); #else - outval = color.r * 0.35 + color.g * 0.45 + color.b * 0.2; /* keep these factors in sync with texture.h:RGBTOBW */ + vec3 factors = vec3(0.35, 0.45, 0.2); /* keep these factors in sync with texture.h:RGBTOBW */ #endif + outval = dot(color.rgb, factors); } void invert(float fac, vec4 col, out vec4 outcol) { - outcol.xyz = mix(col.xyz, vec3(1.0, 1.0, 1.0) - col.xyz, fac); + outcol.xyz = mix(col.xyz, vec3(1.0) - col.xyz, fac); outcol.w = col.w; } @@ -916,12 +966,12 @@ void texture_flip_blend(vec3 vec, out vec3 outvec) void texture_blend_lin(vec3 vec, out float outval) { - outval = (1.0 + vec.x) / 2.0; + outval = (1.0 + vec.x) * 0.5; } void texture_blend_quad(vec3 vec, out float outval) { - outval = max((1.0 + vec.x) / 2.0, 0.0); + outval = max((1.0 + vec.x) * 0.5, 0.0); outval *= outval; } @@ -932,12 +982,12 @@ void texture_wood_sin(vec3 vec, out float value, out vec4 color, out vec3 normal value = wi; color = vec4(wi, wi, wi, 1.0); - normal = vec3(0.0, 0.0, 0.0); + normal = vec3(0.0); } void texture_image(vec3 vec, sampler2D ima, out float value, out vec4 color, out vec3 normal) { - color = texture2D(ima, (vec.xy + vec2(1.0, 1.0)) * 0.5); + color = texture(ima, (vec.xy + vec2(1.0)) * 0.5); value = color.a; normal.x = 2.0 * (color.r - 0.5); @@ -1277,11 +1327,7 @@ void mtex_har_divide(float har, out float outhar) void mtex_har_multiply_clamp(float har, out float outhar) { - har *= 128.0; - - if (har < 1.0) outhar = 1.0; - else if (har > 511.0) outhar = 511.0; - else outhar = har; + outhar = clamp(har * 128.0, 1.0, 511.0); } void mtex_alpha_from_col(vec4 col, out float alpha) @@ -1350,14 +1396,14 @@ vec3 mtex_2d_mapping(vec3 vec) void mtex_cube_map(vec3 co, samplerCube ima, out float value, out vec4 color) { - color = textureCube(ima, co); + color = texture(ima, co); value = 1.0; } void mtex_cube_map_refl_from_refldir( samplerCube ima, vec3 reflecteddirection, out float value, out vec4 color) { - color = textureCube(ima, reflecteddirection); + color = texture(ima, reflecteddirection); value = color.a; } @@ -1368,13 +1414,13 @@ void mtex_cube_map_refl( vec3 viewdirection = vec3(viewmatrixinverse * vec4(vp, 0.0)); vec3 normaldirection = normalize(vec3(vec4(vn, 0.0) * viewmatrix)); vec3 reflecteddirection = reflect(viewdirection, normaldirection); - color = textureCube(ima, reflecteddirection); + color = texture(ima, reflecteddirection); value = 1.0; } void mtex_image(vec3 texco, sampler2D ima, out float value, out vec4 color) { - color = texture2D(ima, texco.xy); + color = texture(ima, texco.xy); value = 1.0; } @@ -1385,7 +1431,7 @@ void mtex_normal(vec3 texco, sampler2D ima, out vec3 normal) // It needs to be done because in Blender // the normal used points inward. // Should this ever change this negate must be removed. - vec4 color = texture2D(ima, texco.xy); + vec4 color = texture(ima, texco.xy); normal = 2.0 * (vec3(-color.r, color.g, color.b) - vec3(-0.5, 0.5, 0.5)); } @@ -1413,8 +1459,8 @@ void mtex_bump_init_objspace( out float fPrevMagnitude_out, out vec3 vNacc_out, out vec3 vR1, out vec3 vR2, out float fDet) { - mat3 obj2view = to_mat3(gl_ModelViewMatrix); - mat3 view2obj = to_mat3(gl_ModelViewMatrixInverse); + mat3 obj2view = to_mat3(ModelViewMatrix); + mat3 view2obj = to_mat3(ModelViewMatrixInverse); vec3 vSigmaS = view2obj * dFdx(surf_pos); vec3 vSigmaT = view2obj * dFdy(surf_pos); @@ -1481,9 +1527,9 @@ void mtex_bump_tap3( vec2 STul = texco.xy + dFdy(texco.xy); float Hll, Hlr, Hul; - rgbtobw(texture2D(ima, STll), Hll); - rgbtobw(texture2D(ima, STlr), Hlr); - rgbtobw(texture2D(ima, STul), Hul); + rgbtobw(texture(ima, STll), Hll); + rgbtobw(texture(ima, STlr), Hlr); + rgbtobw(texture(ima, STul), Hul); dBs = hScale * (Hlr - Hll); dBt = hScale * (Hul - Hll); @@ -1508,10 +1554,10 @@ void mtex_bump_bicubic( vec2 STd = texco.xy - 0.5 * TexDy; vec2 STu = texco.xy + 0.5 * TexDy; - rgbtobw(texture2D(ima, STl), Hl); - rgbtobw(texture2D(ima, STr), Hr); - rgbtobw(texture2D(ima, STd), Hd); - rgbtobw(texture2D(ima, STu), Hu); + rgbtobw(texture(ima, STl), Hl); + rgbtobw(texture(ima, STr), Hr); + rgbtobw(texture(ima, STd), Hd); + rgbtobw(texture(ima, STu), Hu); vec2 dHdxy = vec2(Hr - Hl, Hu - Hd); float fBlend = clamp(1.0 - textureQueryLOD(ima, texco.xy).x, 0.0, 1.0); @@ -1597,11 +1643,11 @@ void mtex_bump_tap5( vec2 STu = texco.xy + 0.5 * TexDy; float Hc, Hl, Hr, Hd, Hu; - rgbtobw(texture2D(ima, STc), Hc); - rgbtobw(texture2D(ima, STl), Hl); - rgbtobw(texture2D(ima, STr), Hr); - rgbtobw(texture2D(ima, STd), Hd); - rgbtobw(texture2D(ima, STu), Hu); + rgbtobw(texture(ima, STc), Hc); + rgbtobw(texture(ima, STl), Hl); + rgbtobw(texture(ima, STr), Hr); + rgbtobw(texture(ima, STd), Hd); + rgbtobw(texture(ima, STu), Hu); dBs = hScale * (Hr - Hl); dBt = hScale * (Hu - Hd); @@ -1618,7 +1664,7 @@ void mtex_bump_deriv( // this variant using a derivative map is described here // http://mmikkelsen3d.blogspot.com/2011/07/derivative-maps.html vec2 dim = vec2(ima_x, ima_y); - vec2 dBduv = hScale * dim * (2.0 * texture2D(ima, texco.xy).xy - 1.0); + vec2 dBduv = hScale * dim * (2.0 * texture(ima, texco.xy).xy - 1.0); dBs = dBduv.x * TexDx.x + s * dBduv.y * TexDx.y; dBt = dBduv.x * TexDy.x + s * dBduv.y * TexDy.y; @@ -1670,7 +1716,7 @@ void mtex_nspace_world(mat4 viewmat, vec3 texnormal, out vec3 outnormal) void mtex_nspace_object(vec3 texnormal, out vec3 outnormal) { - outnormal = normalize(gl_NormalMatrix * texnormal); + outnormal = normalize(NormalMatrix * texnormal); } void mtex_blend_normal(float norfac, vec3 normal, vec3 newnormal, out vec3 outnormal) @@ -1727,7 +1773,7 @@ void lamp_falloff_invcoefficients(float coeff_const, float coeff_lin, float coef void lamp_falloff_curve(float lampdist, sampler2D curvemap, float dist, out float visifac) { - visifac = texture2D(curvemap, vec2(dist / lampdist, 0.0)).x; + visifac = texture(curvemap, vec2(dist / lampdist, 0.0)).x; } void lamp_visibility_sphere(float lampdist, float dist, float visifac, out float outvisifac) @@ -1794,7 +1840,7 @@ void lamp_visibility_clamp(float visifac, out float outvisifac) void world_paper_view(vec3 vec, out vec3 outvec) { vec3 nvec = normalize(vec); - outvec = (gl_ProjectionMatrix[3][3] == 0.0) ? vec3(nvec.x, 0.0, nvec.y) : vec3(0.0, 0.0, -1.0); + outvec = (ProjectionMatrix[3][3] == 0.0) ? vec3(nvec.x, 0.0, nvec.y) : vec3(0.0, 0.0, -1.0); } void world_zen_mapping(vec3 view, float zenup, float zendown, out float zenfac) @@ -1828,7 +1874,7 @@ void world_blend(vec3 vec, out float blend) void shade_view(vec3 co, out vec3 view) { /* handle perspective/orthographic */ - view = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(co) : vec3(0.0, 0.0, -1.0); + view = (ProjectionMatrix[3][3] == 0.0) ? normalize(co) : vec3(0.0, 0.0, -1.0); } void shade_tangent_v(vec3 lv, vec3 tang, out vec3 vn) @@ -2020,7 +2066,7 @@ void shade_add_to_diffuse(float i, vec3 lampcol, vec3 col, out vec3 outcol) if (i > 0.0) outcol = i * lampcol * col; else - outcol = vec3(0.0, 0.0, 0.0); + outcol = vec3(0.0); } void shade_hemi_spec(vec3 vn, vec3 lv, vec3 view, float spec, float hard, float visifac, out float t) @@ -2177,12 +2223,12 @@ void shade_madd(vec4 col, vec4 col1, vec4 col2, out vec4 outcol) void shade_add_clamped(vec4 col1, vec4 col2, out vec4 outcol) { - outcol = col1 + max(col2, vec4(0.0, 0.0, 0.0, 0.0)); + outcol = col1 + max(col2, vec4(0.0)); } void shade_madd_clamped(vec4 col, vec4 col1, vec4 col2, out vec4 outcol) { - outcol = col + max(col1 * col2, vec4(0.0, 0.0, 0.0, 0.0)); + outcol = col + max(col1 * col2, vec4(0.0)); } void env_apply(vec4 col, vec3 hor, vec3 zen, vec4 f, mat4 vm, vec3 vn, out vec4 outcol) @@ -2219,7 +2265,7 @@ void shade_obcolor(vec4 col, vec4 obcol, out vec4 outcol) void ramp_rgbtobw(vec3 color, out float outval) { - outval = color.r * 0.3 + color.g * 0.58 + color.b * 0.12; + outval = dot(color, vec3(0.3, 0.58, 0.12)); } void shade_only_shadow(float i, float shadfac, float energy, vec3 shadcol, out vec3 outshadrgb) @@ -2255,10 +2301,12 @@ void test_shadowbuf( //float bias = (1.5 - inp*inp)*shadowbias; co.z -= shadowbias * co.w; - if (co.w > 0.0 && co.x > 0.0 && co.x / co.w < 1.0 && co.y > 0.0 && co.y / co.w < 1.0) - result = shadow2DProj(shadowmap, co).x; - else + if (co.w > 0.0 && co.x > 0.0 && co.x / co.w < 1.0 && co.y > 0.0 && co.y / co.w < 1.0) { + result = textureProj(shadowmap, co); + } + else { result = 1.0; + } } } @@ -2272,7 +2320,7 @@ void test_shadowbuf_vsm( else { vec4 co = shadowpersmat * vec4(rco, 1.0); if (co.w > 0.0 && co.x > 0.0 && co.x / co.w < 1.0 && co.y > 0.0 && co.y / co.w < 1.0) { - vec2 moments = texture2DProj(shadowmap, co).rg; + vec2 moments = textureProj(shadowmap, co).rg; float dist = co.z / co.w; float p = 0.0; @@ -2331,7 +2379,7 @@ void shade_light_texture(vec3 rco, sampler2D cookie, mat4 shadowpersmat, out vec vec4 co = shadowpersmat * vec4(rco, 1.0); - result = texture2DProj(cookie, co); + result = textureProj(cookie, co); } void shade_exposure_correct(vec3 col, float linfac, float logfac, out vec3 outcol) @@ -2346,7 +2394,7 @@ void shade_mist_factor( if (enable == 1.0) { float fac, zcor; - zcor = (gl_ProjectionMatrix[3][3] == 0.0) ? length(co) : -co[2]; + zcor = (ProjectionMatrix[3][3] == 0.0) ? length(co) : -co[2]; fac = clamp((zcor - miststa) / mistdist, 0.0, 1.0); if (misttype == 0.0) fac *= fac; @@ -2421,7 +2469,15 @@ float hypot(float x, float y) void generated_from_orco(vec3 orco, out vec3 generated) { - generated = orco * 0.5 + vec3(0.5); +#ifdef VOLUMETRICS +#ifdef MESH_SHADER + generated = volumeObjectLocalCoord; +#else + generated = worldPosition; +#endif +#else + generated = orco; +#endif } int floor_to_int(float x) @@ -2434,7 +2490,6 @@ int quick_floor(float x) return int(x) - ((x < 0) ? 1 : 0); } -#ifdef BIT_OPERATIONS float integer_noise(int n) { int nn; @@ -2499,7 +2554,6 @@ vec3 cellnoise_color(vec3 p) return vec3(r, g, b); } -#endif // BIT_OPERATIONS float floorfrac(float x, out int i) { @@ -2561,41 +2615,107 @@ vec3 rotate_vector(vec3 p, vec3 n, float theta) { ); } +void prepare_tangent( + float anisotropic, float anisotropic_rotation, float roughness, vec3 N, vec3 T, + out vec3 X, out vec3 Y, out float ax, out float ay) +{ + /* rotate tangent */ + if (anisotropic_rotation != 0.0) { + T = rotate_vector(T, N, anisotropic_rotation * 2.0 * M_PI); + } + + Y = normalize(cross(T, N)); + + float aspect = sqrt(1.0 - anisotropic * 0.9); + float a = sqr(roughness); + ax = max(0.001, a / aspect); + ay = max(0.001, a * aspect); +} + +void convert_metallic_to_specular(vec3 basecol, float metallic, float specular_fac, out vec3 diffuse, out vec3 f0) +{ + vec3 dielectric = vec3(0.034) * specular_fac * 2.0; + diffuse = mix(basecol, vec3(0.0), metallic); + f0 = mix(dielectric, basecol, metallic); +} + +void convert_metallic_to_specular_tinted( + vec3 basecol, float metallic, float specular_fac, float specular_tint, + out vec3 diffuse, out vec3 f0) +{ + vec3 dielectric = vec3(0.034) * specular_fac * 2.0; + float lum = dot(basecol, vec3(0.3, 0.6, 0.1)); /* luminance approx. */ + vec3 tint = lum > 0 ? basecol / lum : vec3(1.0); /* normalize lum. to isolate hue+sat */ + f0 = mix(dielectric * mix(vec3(1.0), tint, specular_tint), basecol, metallic); + diffuse = mix(basecol, vec3(0.0), metallic); +} /*********** NEW SHADER NODES ***************/ #define NUM_LIGHTS 3 -/* bsdfs */ +struct glLight { + vec4 position; + vec4 diffuse; + vec4 specular; + vec4 halfVector; +}; -void node_bsdf_diffuse(vec4 color, float roughness, vec3 N, out vec4 result) -{ +layout(std140) uniform lightSource { + glLight glLightSource[NUM_LIGHTS]; +}; + +#ifndef VOLUMETRICS +/* bsdfs */ +void node_bsdf_diffuse(vec4 color, float roughness, vec3 N, out Closure result) +{ +#ifdef EEVEE_ENGINE + vec3 vN = normalize(mat3(ViewMatrix) * N); + result = CLOSURE_DEFAULT; + result.ssr_normal = normal_encode(vN, viewCameraVec); + eevee_closure_diffuse(N, color.rgb, 1.0, result.radiance); + result.radiance *= color.rgb; +#else /* ambient light */ vec3 L = vec3(0.2); /* directional lights */ for (int i = 0; i < NUM_LIGHTS; i++) { - vec3 light_position = gl_LightSource[i].position.xyz; - vec3 light_diffuse = gl_LightSource[i].diffuse.rgb; + vec3 light_position = glLightSource[i].position.xyz; + vec3 light_diffuse = glLightSource[i].diffuse.rgb; float bsdf = max(dot(N, light_position), 0.0); L += light_diffuse * bsdf; } - result = vec4(L * color.rgb, 1.0); + result = Closure(L * color.rgb, 1.0); +#endif } -void node_bsdf_glossy(vec4 color, float roughness, vec3 N, out vec4 result) +void node_bsdf_glossy(vec4 color, float roughness, vec3 N, float ssr_id, out Closure result) { +#ifdef EEVEE_ENGINE + vec3 out_spec, ssr_spec; + roughness = sqrt(roughness); + eevee_closure_glossy(N, vec3(1.0), int(ssr_id), roughness, 1.0, out_spec, ssr_spec); + vec3 vN = normalize(mat3(ViewMatrix) * N); + result = CLOSURE_DEFAULT; + result.radiance = out_spec * color.rgb; + result.ssr_data = vec4(ssr_spec * color.rgb, roughness); + result.ssr_normal = normal_encode(vN, viewCameraVec); + result.ssr_id = int(ssr_id); +#else /* ambient light */ vec3 L = vec3(0.2); + direction_transform_m4v3(N, ViewMatrix, N); + /* directional lights */ for (int i = 0; i < NUM_LIGHTS; i++) { - vec3 light_position = gl_LightSource[i].position.xyz; - vec3 H = gl_LightSource[i].halfVector.xyz; - vec3 light_diffuse = gl_LightSource[i].diffuse.rgb; - vec3 light_specular = gl_LightSource[i].specular.rgb; + vec3 light_position = glLightSource[i].position.xyz; + vec3 H = glLightSource[i].halfVector.xyz; + vec3 light_diffuse = glLightSource[i].diffuse.rgb; + vec3 light_specular = glLightSource[i].specular.rgb; /* we mix in some diffuse so low roughness still shows up */ float bsdf = 0.5 * pow(max(dot(N, H), 0.0), 1.0 / roughness); @@ -2603,30 +2723,52 @@ void node_bsdf_glossy(vec4 color, float roughness, vec3 N, out vec4 result) L += light_specular * bsdf; } - result = vec4(L * color.rgb, 1.0); + result = Closure(L * color.rgb, 1.0); +#endif } void node_bsdf_anisotropic( vec4 color, float roughness, float anisotropy, float rotation, vec3 N, vec3 T, - out vec4 result) + out Closure result) { node_bsdf_diffuse(color, 0.0, N, result); } -void node_bsdf_glass(vec4 color, float roughness, float ior, vec3 N, out vec4 result) -{ +void node_bsdf_glass(vec4 color, float roughness, float ior, vec3 N, float ssr_id, out Closure result) +{ +#ifdef EEVEE_ENGINE + vec3 out_spec, out_refr, ssr_spec; + roughness = sqrt(roughness); + vec3 refr_color = (refractionDepth > 0.0) ? color.rgb * color.rgb : color.rgb; /* Simulate 2 transmission event */ + eevee_closure_glass(N, vec3(1.0), int(ssr_id), roughness, 1.0, ior, out_spec, out_refr, ssr_spec); + out_refr *= refr_color; + out_spec *= color.rgb; + float fresnel = F_eta(ior, dot(N, cameraVec)); + vec3 vN = normalize(mat3(ViewMatrix) * N); + result = CLOSURE_DEFAULT; + result.radiance = mix(out_refr, out_spec, fresnel); + result.ssr_data = vec4(ssr_spec * color.rgb * fresnel, roughness); + result.ssr_normal = normal_encode(vN, viewCameraVec); + result.ssr_id = int(ssr_id); +#else node_bsdf_diffuse(color, 0.0, N, result); +#endif } -void node_bsdf_toon(vec4 color, float size, float tsmooth, vec3 N, out vec4 result) +void node_bsdf_toon(vec4 color, float size, float tsmooth, vec3 N, out Closure result) { node_bsdf_diffuse(color, 0.0, N, result); } +#ifndef EEVEE_ENGINE void node_bsdf_principled(vec4 base_color, float subsurface, vec3 subsurface_radius, vec4 subsurface_color, float metallic, float specular, float specular_tint, float roughness, float anisotropic, float anisotropic_rotation, float sheen, float sheen_tint, float clearcoat, - float clearcoat_roughness, float ior, float transmission, float transmission_roughness, vec3 N, vec3 CN, vec3 T, vec3 I, out vec4 result) + float clearcoat_roughness, float ior, float transmission, float transmission_roughness, vec3 N, vec3 CN, vec3 T, vec3 I, out Closure result) { + vec3 X, Y; + float ax, ay; + prepare_tangent(anisotropic, anisotropic_rotation, roughness, N, T, X, Y, ax, ay); + /* ambient light */ // TODO: set ambient light to an appropriate value vec3 L = mix(0.1, 0.03, metallic) * mix(base_color.rgb, subsurface_color.rgb, subsurface * (1.0 - metallic)); @@ -2634,28 +2776,7 @@ void node_bsdf_principled(vec4 base_color, float subsurface, vec3 subsurface_rad float eta = (2.0 / (1.0 - sqrt(0.08 * specular))) - 1.0; /* set the viewing vector */ - vec3 V = (gl_ProjectionMatrix[3][3] == 0.0) ? -normalize(I) : vec3(0.0, 0.0, 1.0); - - /* get the tangent */ - vec3 Tangent = T; - if (T == vec3(0.0)) { - // if no tangent is set, use a default tangent - if(N.x != N.y || N.x != N.z) { - Tangent = vec3(N.z-N.y, N.x-N.z, N.y-N.x); // (1,1,1) x N - } - else { - Tangent = vec3(N.z-N.y, N.x+N.z, -N.y-N.x); // (-1,1,1) x N - } - } - - /* rotate tangent */ - if (anisotropic_rotation != 0.0) { - Tangent = rotate_vector(Tangent, N, anisotropic_rotation * 2.0 * M_PI); - } - - /* calculate the tangent and bitangent */ - vec3 Y = normalize(cross(N, Tangent)); - vec3 X = cross(Y, N); + vec3 V = (ProjectionMatrix[3][3] == 0.0) ? -normalize(I) : vec3(0.0, 0.0, 1.0); /* fresnel normalization parameters */ float F0 = fresnel_dielectric_0(eta); @@ -2663,13 +2784,13 @@ void node_bsdf_principled(vec4 base_color, float subsurface, vec3 subsurface_rad /* directional lights */ for (int i = 0; i < NUM_LIGHTS; i++) { - vec3 light_position_world = gl_LightSource[i].position.xyz; + vec3 light_position_world = glLightSource[i].position.xyz; vec3 light_position = normalize(light_position_world); vec3 H = normalize(light_position + V); - vec3 light_diffuse = gl_LightSource[i].diffuse.rgb; - vec3 light_specular = gl_LightSource[i].specular.rgb; + vec3 light_diffuse = glLightSource[i].diffuse.rgb; + vec3 light_specular = glLightSource[i].specular.rgb; float NdotL = dot(N, light_position); float NdotV = dot(N, V); @@ -2679,7 +2800,7 @@ void node_bsdf_principled(vec4 base_color, float subsurface, vec3 subsurface_rad if (NdotL >= 0.0 && NdotV >= 0.0) { float NdotH = dot(N, H); - float Cdlum = 0.3 * base_color.r + 0.6 * base_color.g + 0.1 * base_color.b; // luminance approx. + float Cdlum = dot(base_color.rgb, vec3(0.3, 0.6, 0.1)); // luminance approx. vec3 Ctint = Cdlum > 0 ? base_color.rgb / Cdlum : vec3(1.0); // normalize lum. to isolate hue+sat vec3 Cspec0 = mix(specular * 0.08 * mix(vec3(1.0), Ctint, specular_tint), base_color.rgb, metallic); @@ -2700,10 +2821,6 @@ void node_bsdf_principled(vec4 base_color, float subsurface, vec3 subsurface_rad float ss = 1.25 * (Fss * (1.0 / (NdotL + NdotV) - 0.5) + 0.5); // specular - float aspect = sqrt(1.0 - anisotropic * 0.9); - float a = sqr(roughness); - float ax = max(0.001, a / aspect); - float ay = max(0.001, a * aspect); float Ds = GTR2_aniso(NdotH, dot(H, X), dot(H, Y), ax, ay); //GTR2(NdotH, a); float FH = (fresnel_dielectric_cos(LdotH, eta) - F0) * F0_norm; vec3 Fs = mix(Cspec0, vec3(1.0), FH); @@ -2739,83 +2856,232 @@ void node_bsdf_principled(vec4 base_color, float subsurface, vec3 subsurface_rad L += diffuse_and_specular_bsdf + clearcoat_bsdf; } - result = vec4(L, 1.0); + result = Closure(L, 1.0); } +#endif -void node_bsdf_translucent(vec4 color, vec3 N, out vec4 result) +void node_bsdf_principled_clearcoat(vec4 base_color, float subsurface, vec3 subsurface_radius, vec4 subsurface_color, float metallic, float specular, + float specular_tint, float roughness, float anisotropic, float anisotropic_rotation, float sheen, float sheen_tint, float clearcoat, + float clearcoat_roughness, float ior, float transmission, float transmission_roughness, vec3 N, vec3 CN, vec3 T, vec3 I, float ssr_id, + float sss_id, vec3 sss_scale, out Closure result) { - node_bsdf_diffuse(color, 0.0, N, result); +#ifdef EEVEE_ENGINE + metallic = saturate(metallic); + transmission = saturate(transmission); + + vec3 diffuse, f0, out_diff, out_spec, out_trans, out_refr, ssr_spec; + convert_metallic_to_specular_tinted(base_color.rgb, metallic, specular, specular_tint, diffuse, f0); + + transmission *= 1.0 - metallic; + subsurface *= 1.0 - metallic; + + clearcoat *= 0.25; + clearcoat *= 1.0 - transmission; + +#ifdef USE_SSS + diffuse = mix(diffuse, vec3(0.0), subsurface); +#else + diffuse = mix(diffuse, subsurface_color.rgb, subsurface); +#endif + f0 = mix(f0, vec3(1.0), transmission); + + float sss_scalef = dot(sss_scale, vec3(1.0 / 3.0)); + eevee_closure_principled(N, diffuse, f0, int(ssr_id), roughness, + CN, clearcoat, clearcoat_roughness, 1.0, sss_scalef, ior, + out_diff, out_trans, out_spec, out_refr, ssr_spec); + + vec3 refr_color = base_color.rgb; + refr_color *= (refractionDepth > 0.0) ? refr_color : vec3(1.0); /* Simulate 2 transmission event */ + + float fresnel = F_eta(ior, dot(N, cameraVec)); + vec3 refr_spec_color = base_color.rgb * fresnel; + /* This bit maybe innacurate. */ + out_refr = out_refr * refr_color * (1.0 - fresnel) + out_spec * refr_spec_color; + + ssr_spec = mix(ssr_spec, refr_spec_color, transmission); + + vec3 vN = normalize(mat3(ViewMatrix) * N); + result = CLOSURE_DEFAULT; + result.radiance = out_spec + out_diff * diffuse; + result.radiance = mix(result.radiance, out_refr, transmission); + result.ssr_data = vec4(ssr_spec, roughness); + result.ssr_normal = normal_encode(vN, viewCameraVec); + result.ssr_id = int(ssr_id); +#ifdef USE_SSS + result.sss_data.a = sss_scalef; + result.sss_data.rgb = out_diff + out_trans; +#ifdef USE_SSS_ALBEDO + result.sss_albedo.rgb = mix(vec3(0.0), subsurface_color.rgb, subsurface); +#else + result.sss_data.rgb *= mix(vec3(0.0), subsurface_color.rgb, subsurface); +#endif + result.sss_data.rgb *= (1.0 - transmission); +#endif + +#else + node_bsdf_principled(base_color, subsurface, subsurface_radius, subsurface_color, metallic, specular, + specular_tint, roughness, anisotropic, anisotropic_rotation, sheen, sheen_tint, clearcoat, + clearcoat_roughness, ior, transmission, transmission_roughness, N, CN, T, I, result); +#endif +} + +void node_bsdf_translucent(vec4 color, vec3 N, out Closure result) +{ + node_bsdf_diffuse(color, 0.0, -N, result); } -void node_bsdf_transparent(vec4 color, out vec4 result) +void node_bsdf_transparent(vec4 color, out Closure result) { /* this isn't right */ - result.r = color.r; - result.g = color.g; - result.b = color.b; - result.a = 0.0; + result = CLOSURE_DEFAULT; + result.radiance = vec3(0.0); + result.opacity = 0.0; +#ifdef EEVEE_ENGINE + result.ssr_id = TRANSPARENT_CLOSURE_FLAG; +#endif } -void node_bsdf_velvet(vec4 color, float sigma, vec3 N, out vec4 result) +void node_bsdf_velvet(vec4 color, float sigma, vec3 N, out Closure result) { node_bsdf_diffuse(color, 0.0, N, result); } void node_subsurface_scattering( - vec4 color, float scale, vec3 radius, float sharpen, float texture_blur, vec3 N, - out vec4 result) -{ + vec4 color, float scale, vec3 radius, float sharpen, float texture_blur, vec3 N, float sss_id, + out Closure result) +{ +#if defined(EEVEE_ENGINE) && defined(USE_SSS) + vec3 out_diff, out_trans; + vec3 vN = normalize(mat3(ViewMatrix) * N); + result = CLOSURE_DEFAULT; + result.ssr_data = vec4(0.0); + result.ssr_normal = normal_encode(vN, viewCameraVec); + result.ssr_id = -1; + result.sss_data.a = scale; + eevee_closure_subsurface(N, color.rgb, 1.0, scale, out_diff, out_trans); + result.sss_data.rgb = out_diff + out_trans; +#ifdef USE_SSS_ALBEDO + /* Not perfect for texture_blur not exaclty equal to 0.0 or 1.0. */ + result.sss_albedo.rgb = mix(color.rgb, vec3(1.0), texture_blur); + result.sss_data.rgb *= mix(vec3(1.0), color.rgb, texture_blur); +#else + result.sss_data.rgb *= color.rgb; +#endif +#else node_bsdf_diffuse(color, 0.0, N, result); +#endif } -void node_bsdf_hair(vec4 color, float offset, float roughnessu, float roughnessv, vec3 tangent, out vec4 result) +void node_bsdf_refraction(vec4 color, float roughness, float ior, vec3 N, out Closure result) { - result = color; +#ifdef EEVEE_ENGINE + vec3 out_refr; + color.rgb *= (refractionDepth > 0.0) ? color.rgb : vec3(1.0); /* Simulate 2 absorption event. */ + roughness = sqrt(roughness); + eevee_closure_refraction(N, roughness, ior, out_refr); + result = CLOSURE_DEFAULT; + result.radiance = out_refr * color.rgb; + result.ssr_id = REFRACT_CLOSURE_FLAG; +#else + node_bsdf_diffuse(color, 0.0, N, result); +#endif /* EEVEE_ENGINE */ } -void node_bsdf_refraction(vec4 color, float roughness, float ior, vec3 N, out vec4 result) +/* Unsupported for now */ +#ifndef EEVEE_ENGINE +void node_bsdf_hair(vec4 color, float offset, float roughnessu, float roughnessv, vec3 tangent, out Closure result) { - node_bsdf_diffuse(color, 0.0, N, result); + result = Closure(color.rgb, color.a); } -void node_ambient_occlusion(vec4 color, out vec4 result) +void node_ambient_occlusion(vec4 color, out Closure result) { - result = color; + result = Closure(color.rgb, color.a); } +#endif /* EEVEE_ENGINE */ + +#endif /* VOLUMETRICS */ /* emission */ -void node_emission(vec4 color, float strength, vec3 N, out vec4 result) +void node_emission(vec4 color, float strength, vec3 N, out Closure result) { - result = color * strength; +#ifndef VOLUMETRICS + color *= strength; +#ifdef EEVEE_ENGINE + result = CLOSURE_DEFAULT; + result.radiance = color.rgb; + result.opacity = color.a; + result.ssr_normal = normal_encode(N, viewCameraVec); +#else + result = Closure(color.rgb, color.a); +#endif +#else + result = Closure(vec3(0.0), vec3(0.0), color.rgb * strength, 0.0); +#endif } /* background */ void background_transform_to_world(vec3 viewvec, out vec3 worldvec) { - vec4 v = (gl_ProjectionMatrix[3][3] == 0.0) ? vec4(viewvec, 1.0) : vec4(0.0, 0.0, 1.0, 1.0); - vec4 co_homogenous = (gl_ProjectionMatrixInverse * v); + vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(viewvec, 1.0) : vec4(0.0, 0.0, 1.0, 1.0); + vec4 co_homogenous = (ProjectionMatrixInverse * v); vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0); - worldvec = (gl_ModelViewMatrixInverse * co).xyz; +#if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE) + worldvec = (ViewMatrixInverse * co).xyz; +#else + worldvec = (ModelViewMatrixInverse * co).xyz; +#endif +} + +void node_background(vec4 color, float strength, out Closure result) +{ +#ifndef VOLUMETRICS + color *= strength; +#ifdef EEVEE_ENGINE + result = CLOSURE_DEFAULT; + result.radiance = color.rgb; + result.opacity = color.a; +#else + result = Closure(color.rgb, color.a); +#endif +#else + result = CLOSURE_DEFAULT; +#endif +} + +/* volumes */ + +void node_volume_scatter(vec4 color, float density, float anisotropy, out Closure result) +{ +#ifdef VOLUMETRICS + result = Closure(vec3(0.0), color.rgb * density, vec3(0.0), anisotropy); +#else + result = CLOSURE_DEFAULT; +#endif } -void node_background(vec4 color, float strength, vec3 N, out vec4 result) +void node_volume_absorption(vec4 color, float density, out Closure result) { - result = color * strength; +#ifdef VOLUMETRICS + result = Closure((1.0 - color.rgb) * density, vec3(0.0), vec3(0.0), 0.0); +#else + result = CLOSURE_DEFAULT; +#endif } /* closures */ -void node_mix_shader(float fac, vec4 shader1, vec4 shader2, out vec4 shader) +void node_mix_shader(float fac, Closure shader1, Closure shader2, out Closure shader) { - shader = mix(shader1, shader2, fac); + shader = closure_mix(shader1, shader2, fac); } -void node_add_shader(vec4 shader1, vec4 shader2, out vec4 shader) +void node_add_shader(Closure shader1, Closure shader2, out Closure shader) { - shader = shader1 + shader2; + shader = closure_add(shader1, shader2); } /* fresnel */ @@ -2823,7 +3089,7 @@ void node_add_shader(vec4 shader1, vec4 shader2, out vec4 shader) void node_fresnel(float ior, vec3 N, vec3 I, out float result) { /* handle perspective/orthographic */ - vec3 I_view = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0); + vec3 I_view = (ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0); float eta = max(ior, 0.00001); result = fresnel_dielectric(I_view, N, (gl_FrontFacing) ? eta : 1.0 / eta); @@ -2835,7 +3101,7 @@ void node_layer_weight(float blend, vec3 N, vec3 I, out float fresnel, out float { /* fresnel */ float eta = max(1.0 - blend, 0.00001); - vec3 I_view = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0); + vec3 I_view = (ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0); fresnel = fresnel_dielectric(I_view, N, (gl_FrontFacing) ? 1.0 / eta : eta); @@ -2865,11 +3131,47 @@ void node_gamma(vec4 col, float gamma, out vec4 outcol) /* geometry */ +void node_attribute_volume_density(sampler3D tex, out vec4 outcol, out vec3 outvec, out float outf) +{ +#if defined(EEVEE_ENGINE) && defined(MESH_SHADER) && defined(VOLUMETRICS) + vec3 cos = volumeObjectLocalCoord; +#else + vec3 cos = vec3(0.0); +#endif + outvec = texture(tex, cos).aaa; + outcol = vec4(outvec, 1.0); + outf = dot(vec3(1.0 / 3.0), outvec); +} + +void node_attribute_volume_color(sampler3D tex, out vec4 outcol, out vec3 outvec, out float outf) +{ +#if defined(EEVEE_ENGINE) && defined(MESH_SHADER) && defined(VOLUMETRICS) + vec3 cos = volumeObjectLocalCoord; +#else + vec3 cos = vec3(0.0); +#endif + outvec = texture(tex, cos).rgb; + outcol = vec4(outvec, 1.0); + outf = dot(vec3(1.0 / 3.0), outvec); +} + +void node_attribute_volume_flame(sampler3D tex, out vec4 outcol, out vec3 outvec, out float outf) +{ +#if defined(EEVEE_ENGINE) && defined(MESH_SHADER) && defined(VOLUMETRICS) + vec3 cos = volumeObjectLocalCoord; +#else + vec3 cos = vec3(0.0); +#endif + outvec = texture(tex, cos).rrr; + outcol = vec4(outvec, 1.0); + outf = dot(vec3(1.0 / 3.0), outvec); +} + void node_attribute(vec3 attr, out vec4 outcol, out vec3 outvec, out float outf) { outcol = vec4(attr, 1.0); outvec = attr; - outf = (attr.x + attr.y + attr.z) / 3.0; + outf = dot(vec3(1.0 / 3.0), attr); } void node_uvmap(vec3 attr_uv, out vec3 outvec) @@ -2877,19 +3179,51 @@ void node_uvmap(vec3 attr_uv, out vec3 outvec) outvec = attr_uv; } +void tangent_orco_x(vec3 orco_in, out vec3 orco_out) +{ + orco_out = vec3(0.0, (orco_in.z - 0.5) * -0.5, (orco_in.y - 0.5) * 0.5); +} + +void tangent_orco_y(vec3 orco_in, out vec3 orco_out) +{ + orco_out = vec3((orco_in.z - 0.5) * -0.5, 0.0, (orco_in.x - 0.5) * 0.5); +} + +void tangent_orco_z(vec3 orco_in, out vec3 orco_out) +{ + orco_out = vec3((orco_in.y - 0.5) * -0.5, (orco_in.x - 0.5) * 0.5, 0.0); +} + +void node_tangentmap(vec4 attr_tangent, mat4 toworld, out vec3 tangent) +{ + tangent = (toworld * vec4(attr_tangent.xyz, 0.0)).xyz; +} + +void node_tangent(vec3 N, vec3 orco, mat4 objmat, mat4 toworld, out vec3 T) +{ + N = (toworld * vec4(N, 0.0)).xyz; + T = (objmat * vec4(orco, 0.0)).xyz; + T = cross(N, normalize(cross(T, N))); +} + void node_geometry( - vec3 I, vec3 N, mat4 toworld, + vec3 I, vec3 N, vec3 orco, mat4 objmat, mat4 toworld, out vec3 position, out vec3 normal, out vec3 tangent, out vec3 true_normal, out vec3 incoming, out vec3 parametric, out float backfacing, out float pointiness) { +#ifdef EEVEE_ENGINE + position = worldPosition; +#else position = (toworld * vec4(I, 1.0)).xyz; +#endif normal = (toworld * vec4(N, 0.0)).xyz; - tangent = vec3(0.0); + tangent_orco_z(orco, orco); + node_tangent(N, orco, objmat, toworld, tangent); true_normal = normal; /* handle perspective/orthographic */ - vec3 I_view = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0); + vec3 I_view = (ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0); incoming = -(toworld * vec4(I_view, 0.0)).xyz; parametric = vec3(0.0); @@ -2903,12 +3237,12 @@ void node_tex_coord( out vec3 generated, out vec3 normal, out vec3 uv, out vec3 object, out vec3 camera, out vec3 window, out vec3 reflection) { - generated = attr_orco * 0.5 + vec3(0.5); + generated = attr_orco; normal = normalize((obinvmat * (viewinvmat * vec4(N, 0.0))).xyz); uv = attr_uv; object = (obinvmat * (viewinvmat * vec4(I, 1.0))).xyz; camera = vec3(I.xy, -I.z); - vec4 projvec = gl_ProjectionMatrix * vec4(I, 1.0); + vec4 projvec = ProjectionMatrix * vec4(I, 1.0); window = vec3(mtex_2d_mapping(projvec.xyz / projvec.w).xy * camerafac.xy + camerafac.zw, 0.0); vec3 shade_I; @@ -2923,13 +3257,18 @@ void node_tex_coord_background( out vec3 generated, out vec3 normal, out vec3 uv, out vec3 object, out vec3 camera, out vec3 window, out vec3 reflection) { - vec4 v = (gl_ProjectionMatrix[3][3] == 0.0) ? vec4(I, 1.0) : vec4(0.0, 0.0, 1.0, 1.0); - vec4 co_homogenous = (gl_ProjectionMatrixInverse * v); + vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(I, 1.0) : vec4(0.0, 0.0, 1.0, 1.0); + vec4 co_homogenous = (ProjectionMatrixInverse * v); vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0); co = normalize(co); - vec3 coords = (gl_ModelViewMatrixInverse * co).xyz; + +#if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE) + vec3 coords = (ViewMatrixInverse * co).xyz; +#else + vec3 coords = (ModelViewMatrixInverse * co).xyz; +#endif generated = coords; normal = -coords; @@ -2937,13 +3276,17 @@ void node_tex_coord_background( object = coords; camera = vec3(co.xy, -co.z); - window = (gl_ProjectionMatrix[3][3] == 0.0) ? + window = (ProjectionMatrix[3][3] == 0.0) ? vec3(mtex_2d_mapping(I).xy * camerafac.xy + camerafac.zw, 0.0) : vec3(vec2(0.5) * camerafac.xy + camerafac.zw, 0.0); reflection = -coords; } +#if defined(WORLD_BACKGROUND) || (defined(PROBE_CAPTURE) && !defined(MESH_SHADER)) +#define node_tex_coord node_tex_coord_background +#endif + /* textures */ float calc_gradient(vec3 p, int gradient_type) @@ -3013,7 +3356,6 @@ void node_tex_checker(vec3 co, vec4 color1, vec4 color2, float scale, out vec4 c fac = check ? 1.0 : 0.0; } -#ifdef BIT_OPERATIONS vec2 calc_brick_texture(vec3 p, float mortar_size, float mortar_smooth, float bias, float brick_width, float row_height, float offset_amount, int offset_frequency, @@ -3049,7 +3391,6 @@ vec2 calc_brick_texture(vec3 p, float mortar_size, float mortar_smooth, float bi return vec2(tint, smoothstep(0.0, mortar_smooth, min_dist)); } } -#endif void node_tex_brick(vec3 co, vec4 color1, vec4 color2, @@ -3060,7 +3401,6 @@ void node_tex_brick(vec3 co, float squash_amount, float squash_frequency, out vec4 color, out float fac) { -#ifdef BIT_OPERATIONS vec2 f2 = calc_brick_texture(co * scale, mortar_size, mortar_smooth, bias, brick_width, row_height, @@ -3074,10 +3414,6 @@ void node_tex_brick(vec3 co, } color = mix(color1, mortar, f); fac = f; -#else - color = vec4(1.0); - fac = 1.0; -#endif } void node_tex_clouds(vec3 co, float size, out vec4 color, out float fac) @@ -3092,7 +3428,15 @@ void node_tex_environment_equirectangular(vec3 co, sampler2D ima, out vec4 color float u = -atan(nco.y, nco.x) / (2.0 * M_PI) + 0.5; float v = atan(nco.z, hypot(nco.x, nco.y)) / M_PI + 0.5; - color = texture2D(ima, vec2(u, v)); + /* Fix pole bleeding */ + float half_width = 0.5 / float(textureSize(ima, 0).x); + v = clamp(v, half_width, 1.0 - half_width); + + /* Fix u = 0 seam */ + /* This is caused by texture filtering, since uv don't have smooth derivatives + * at u = 0 or 2PI, hardware filtering is using the smallest mipmap for certain + * texels. So we force the highest mipmap and don't do anisotropic filtering. */ + color = textureLod(ima, vec2(u, v), 0.0); } void node_tex_environment_mirror_ball(vec3 co, sampler2D ima, out vec4 color) @@ -3108,7 +3452,7 @@ void node_tex_environment_mirror_ball(vec3 co, sampler2D ima, out vec4 color) float u = 0.5 * (nco.x + 1.0); float v = 0.5 * (nco.z + 1.0); - color = texture2D(ima, vec2(u, v)); + color = texture(ima, vec2(u, v)); } void node_tex_environment_empty(vec3 co, out vec4 color) @@ -3118,7 +3462,7 @@ void node_tex_environment_empty(vec3 co, out vec4 color) void node_tex_image(vec3 co, sampler2D ima, out vec4 color, out float alpha) { - color = texture2D(ima, co.xy); + color = texture(ima, co.xy); alpha = color.a; } @@ -3192,21 +3536,21 @@ void node_tex_image_box(vec3 texco, if(signed_N.x < 0.0) { uv.x = 1.0 - uv.x; } - color += weight.x * texture2D(ima, uv); + color += weight.x * texture(ima, uv); } if (weight.y > 0.0) { vec2 uv = texco.xz; if(signed_N.y > 0.0) { uv.x = 1.0 - uv.x; } - color += weight.y * texture2D(ima, uv); + color += weight.y * texture(ima, uv); } if (weight.z > 0.0) { vec2 uv = texco.yx; if(signed_N.z > 0.0) { uv.x = 1.0 - uv.x; } - color += weight.z * texture2D(ima, uv); + color += weight.z * texture(ima, uv); } alpha = color.a; @@ -3279,7 +3623,6 @@ void node_tex_magic(vec3 co, float scale, float distortion, float depth, out vec fac = (color.x + color.y + color.z) / 3.0; } -#ifdef BIT_OPERATIONS float noise_fade(float t) { return t * t * t * (t * (t * 6.0 - 15.0) + 10.0); @@ -3342,10 +3685,9 @@ float noise_turbulence(vec3 p, float octaves, int hard) float fscale = 1.0; float amp = 1.0; float sum = 0.0; - int i, n; octaves = clamp(octaves, 0.0, 16.0); - n = int(octaves); - for (i = 0; i <= n; i++) { + int n = int(octaves); + for (int i = 0; i <= n; i++) { float t = noise(fscale * p); if (hard != 0) { t = abs(2.0 * t - 1.0); @@ -3355,7 +3697,7 @@ float noise_turbulence(vec3 p, float octaves, int hard) fscale *= 2.0; } float rmd = octaves - floor(octaves); - if (rmd != 0.0) { + if (rmd != 0.0) { float t = noise(fscale * p); if (hard != 0) { t = abs(2.0 * t - 1.0); @@ -3370,11 +3712,9 @@ float noise_turbulence(vec3 p, float octaves, int hard) return sum; } } -#endif // BIT_OPERATIONS void node_tex_noise(vec3 co, float scale, float detail, float distortion, out vec4 color, out float fac) { -#ifdef BIT_OPERATIONS vec3 p = co * scale; int hard = 0; if (distortion != 0.0) { @@ -3390,15 +3730,8 @@ void node_tex_noise(vec3 co, float scale, float detail, float distortion, out ve noise_turbulence(vec3(p.y, p.x, p.z), detail, hard), noise_turbulence(vec3(p.y, p.z, p.x), detail, hard), 1); -#else // BIT_OPERATIONS - color = vec4(1.0); - fac = 1.0; -#endif // BIT_OPERATIONS } - -#ifdef BIT_OPERATIONS - /* Musgrave fBm * * H: fractal increment parameter @@ -3414,9 +3747,8 @@ float noise_musgrave_fBm(vec3 p, float H, float lacunarity, float octaves) float value = 0.0; float pwr = 1.0; float pwHL = pow(lacunarity, -H); - int i; - for (i = 0; i < int(octaves); i++) { + for (int i = 0; i < int(octaves); i++) { value += snoise(p) * pwr; pwr *= pwHL; p *= lacunarity; @@ -3442,9 +3774,8 @@ float noise_musgrave_multi_fractal(vec3 p, float H, float lacunarity, float octa float value = 1.0; float pwr = 1.0; float pwHL = pow(lacunarity, -H); - int i; - for (i = 0; i < int(octaves); i++) { + for (int i = 0; i < int(octaves); i++) { value *= (pwr * snoise(p) + 1.0); pwr *= pwHL; p *= lacunarity; @@ -3470,13 +3801,12 @@ float noise_musgrave_hetero_terrain(vec3 p, float H, float lacunarity, float oct float value, increment, rmd; float pwHL = pow(lacunarity, -H); float pwr = pwHL; - int i; /* first unscaled octave of function; later octaves are scaled */ value = offset + snoise(p); p *= lacunarity; - for (i = 1; i < int(octaves); i++) { + for (int i = 1; i < int(octaves); i++) { increment = (snoise(p) + offset) * pwr * value; value += increment; pwr *= pwHL; @@ -3505,13 +3835,12 @@ float noise_musgrave_hybrid_multi_fractal(vec3 p, float H, float lacunarity, flo float result, signal, weight, rmd; float pwHL = pow(lacunarity, -H); float pwr = pwHL; - int i; result = snoise(p) + offset; weight = gain * result; p *= lacunarity; - for (i = 1; (weight > 0.001f) && (i < int(octaves)); i++) { + for (int i = 1; (weight > 0.001f) && (i < int(octaves)); i++) { if (weight > 1.0) weight = 1.0; @@ -3542,14 +3871,13 @@ float noise_musgrave_ridged_multi_fractal(vec3 p, float H, float lacunarity, flo float result, signal, weight; float pwHL = pow(lacunarity, -H); float pwr = pwHL; - int i; signal = offset - abs(snoise(p)); signal *= signal; result = signal; weight = 1.0; - for (i = 1; i < int(octaves); i++) { + for (int i = 1; i < int(octaves); i++) { p *= lacunarity; weight = clamp(signal * gain, 0.0, 1.0); signal = offset - abs(snoise(p)); @@ -3571,19 +3899,18 @@ float svm_musgrave(int type, float gain, vec3 p) { - if (type == 0 /*NODE_MUSGRAVE_MULTIFRACTAL*/) + if (type == 0 /* NODE_MUSGRAVE_MULTIFRACTAL */) return intensity * noise_musgrave_multi_fractal(p, dimension, lacunarity, octaves); - else if (type == 1 /*NODE_MUSGRAVE_FBM*/) + else if (type == 1 /* NODE_MUSGRAVE_FBM */) return intensity * noise_musgrave_fBm(p, dimension, lacunarity, octaves); - else if (type == 2 /*NODE_MUSGRAVE_HYBRID_MULTIFRACTAL*/) + else if (type == 2 /* NODE_MUSGRAVE_HYBRID_MULTIFRACTAL */) return intensity * noise_musgrave_hybrid_multi_fractal(p, dimension, lacunarity, octaves, offset, gain); - else if (type == 3 /*NODE_MUSGRAVE_RIDGED_MULTIFRACTAL*/) + else if (type == 3 /* NODE_MUSGRAVE_RIDGED_MULTIFRACTAL */) return intensity * noise_musgrave_ridged_multi_fractal(p, dimension, lacunarity, octaves, offset, gain); - else if (type == 4 /*NODE_MUSGRAVE_HETERO_TERRAIN*/) + else if (type == 4 /* NODE_MUSGRAVE_HETERO_TERRAIN */) return intensity * noise_musgrave_hetero_terrain(p, dimension, lacunarity, octaves, offset); return 0.0; } -#endif // #ifdef BIT_OPERATIONS void node_tex_musgrave(vec3 co, float scale, @@ -3596,7 +3923,6 @@ void node_tex_musgrave(vec3 co, out vec4 color, out float fac) { -#ifdef BIT_OPERATIONS fac = svm_musgrave(int(type), dimension, lacunarity, @@ -3605,9 +3931,6 @@ void node_tex_musgrave(vec3 co, 1.0, gain, co * scale); -#else - fac = 1.0; -#endif color = vec4(fac, fac, fac, 1.0); } @@ -3619,7 +3942,6 @@ void node_tex_sky(vec3 co, out vec4 color) void node_tex_voronoi(vec3 co, float scale, float coloring, out vec4 color, out float fac) { -#ifdef BIT_OPERATIONS vec3 p = co * scale; int xx, yy, zz, xi, yi, zi; float da[4]; @@ -3684,13 +4006,8 @@ void node_tex_voronoi(vec3 co, float scale, float coloring, out vec4 color, out color = vec4(cellnoise_color(pa[0]), 1); fac = (color.x + color.y + color.z) * (1.0 / 3.0); } -#else // BIT_OPERATIONS - color = vec4(1.0); - fac = 1.0; -#endif // BIT_OPERATIONS } -#ifdef BIT_OPERATIONS float calc_wave(vec3 p, float distortion, float detail, float detail_scale, int wave_type, int wave_profile) { float n; @@ -3712,22 +4029,16 @@ float calc_wave(vec3 p, float distortion, float detail, float detail_scale, int return (n < 0.0) ? n + 1.0 : n; } } -#endif // BIT_OPERATIONS void node_tex_wave( vec3 co, float scale, float distortion, float detail, float detail_scale, float wave_type, float wave_profile, out vec4 color, out float fac) { -#ifdef BIT_OPERATIONS float f; f = calc_wave(co * scale, distortion, detail, detail_scale, int(wave_type), int(wave_profile)); color = vec4(f, f, f, 1.0); fac = f; -#else // BIT_OPERATIONS - color = vec4(1.0); - fac = 1; -#endif // BIT_OPERATIONS } /* light path */ @@ -3747,13 +4058,21 @@ void node_light_path( out float transparent_depth, out float transmission_depth) { +#ifndef PROBE_CAPTURE is_camera_ray = 1.0; - is_shadow_ray = 0.0; - is_diffuse_ray = 0.0; is_glossy_ray = 0.0; - is_singular_ray = 0.0; + is_diffuse_ray = 0.0; is_reflection_ray = 0.0; is_transmission_ray = 0.0; +#else + is_camera_ray = 0.0; + is_glossy_ray = 1.0; + is_diffuse_ray = 1.0; + is_reflection_ray = 1.0; + is_transmission_ray = 1.0; +#endif + is_shadow_ray = 0.0; + is_singular_ray = 0.0; ray_length = 1.0; ray_depth = 1.0; diffuse_depth = 1.0; @@ -3818,37 +4137,79 @@ void node_bevel(float radius, vec3 N, out vec3 result) /* output */ -void node_output_material(vec4 surface, vec4 volume, float displacement, out vec4 result) +void node_output_material(Closure surface, Closure volume, float displacement, out Closure result) { +#ifdef VOLUMETRICS + result = volume; +#else result = surface; +#endif } -void node_output_world(vec4 surface, vec4 volume, out vec4 result) +uniform float backgroundAlpha; + +void node_output_world(Closure surface, Closure volume, out Closure result) { - result = surface; +#ifndef VOLUMETRICS +#ifdef EEVEE_ENGINE + result.radiance = surface.radiance; + result.opacity = backgroundAlpha; +#else + result = Closure(surface.radiance, backgroundAlpha); +#endif +#else + result = volume; +#endif /* VOLUMETRICS */ +} + +#ifndef VOLUMETRICS +/* TODO : clean this ifdef mess */ +/* EEVEE output */ +#ifdef EEVEE_ENGINE +void world_normals_get(out vec3 N) +{ + N = gl_FrontFacing ? worldNormal : -worldNormal; +} + +void node_eevee_specular( + vec4 diffuse, vec4 specular, float roughness, vec4 emissive, float transp, vec3 normal, + float clearcoat, float clearcoat_roughness, vec3 clearcoat_normal, + float occlusion, float ssr_id, out Closure result) +{ + vec3 out_diff, out_spec, ssr_spec; + eevee_closure_default(normal, diffuse.rgb, specular.rgb, int(ssr_id), roughness, occlusion, + out_diff, out_spec, ssr_spec); + + vec3 vN = normalize(mat3(ViewMatrix) * normal); + result = CLOSURE_DEFAULT; + result.radiance = out_diff * diffuse.rgb + out_spec + emissive.rgb; + result.opacity = 1.0 - transp; + result.ssr_data = vec4(ssr_spec, roughness); + result.ssr_normal = normal_encode(vN, viewCameraVec); + result.ssr_id = int(ssr_id); } +#endif /* EEVEE_ENGINE */ +#endif /* VOLUMETRICS */ + /* ********************** matcap style render ******************** */ void material_preview_matcap(vec4 color, sampler2D ima, vec4 N, vec4 mask, out vec4 result) { vec3 normal; - vec2 tex; #ifndef USE_OPENSUBDIV /* remap to 0.0 - 1.0 range. This is done because OpenGL 2.0 clamps colors * between shader stages and we want the full range of the normal */ - normal = vec3(2.0, 2.0, 2.0) * vec3(N.x, N.y, N.z) - vec3(1.0, 1.0, 1.0); - if (normal.z < 0.0) { - normal.z = 0.0; - } + normal = 2.0 * N.xyz - vec3(1.0); + normal.z = max(normal.z, 0.0); normal = normalize(normal); #else normal = inpt.v.normal; - mask = vec4(1.0, 1.0, 1.0, 1.0); + mask = vec4(1.0); #endif - tex.x = 0.5 + 0.49 * normal.x; - tex.y = 0.5 + 0.49 * normal.y; - result = texture2D(ima, tex) * mask; + vec2 tex = 0.49 * normal.xy + vec2(0.5); + + result = texture(ima, tex) * mask; } |