diff options
Diffstat (limited to 'source/blender/gpu/shaders/gpu_shader_material.glsl')
-rw-r--r-- | source/blender/gpu/shaders/gpu_shader_material.glsl | 2396 |
1 files changed, 538 insertions, 1858 deletions
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index ce9e82b34f8..3affacf5203 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -1,12 +1,18 @@ + +uniform mat4 ModelMatrix; +uniform mat4 ModelViewMatrix; +uniform mat4 ModelViewMatrixInverse; +uniform mat3 NormalMatrix; + +#ifndef ATTRIB +uniform mat4 ModelMatrixInverse; +#endif + /* 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; -#else - return (color.r + color.g + color.b) / 3.0; -#endif + return dot(color.rgb, vec3(0.2126, 0.7152, 0.0722)); } float exp_blender(float f) @@ -53,7 +59,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,56 +161,15 @@ 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); -} - -void uv_attribute(vec2 attuv, out vec3 uv) -{ - uv = vec3(attuv * 2.0 - vec2(1.0, 1.0), 0.0); -} - -void geom( - vec3 co, vec3 nor, mat4 viewinvmat, vec3 attorco, vec2 attuv, vec4 attvcol, - out vec3 global, out vec3 local, out vec3 view, out vec3 orco, out vec3 uv, - 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); - global = (viewinvmat * vec4(local, 1.0)).xyz; - orco = attorco; - uv_attribute(attuv, uv); - normal = -normalize(nor); /* blender render normal is negated */ - vcol_attribute(attvcol, vcol); - srgb_to_linearrgb(vcol, vcol); - vcol_alpha = attvcol.a; - frontback = (gl_FrontFacing) ? 1.0 : 0.0; -} - -void particle_info( - vec4 sprops, vec4 loc, vec3 vel, vec3 avel, - out float index, out float random, out float age, - out float life_time, out vec3 location, - out float size, out vec3 velocity, out vec3 angular_velocity) -{ - index = sprops.x; - random = loc.w; - age = sprops.y; - life_time = sprops.z; - size = sprops.w; - - location = loc.xyz; - velocity = vel; - angular_velocity = avel; -} - void vect_normalize(vec3 vin, out vec3 vout) { vout = normalize(vin); @@ -272,17 +237,6 @@ void camera(vec3 co, out vec3 outview, out float outdepth, out float outdist) outview = normalize(co); } -void lamp( - vec4 col, float energy, vec3 lv, float dist, vec3 shadow, float visifac, - out vec4 outcol, out vec3 outlv, out float outdist, out vec4 outshadow, out float outvisifac) -{ - outcol = col * energy; - outlv = lv; - outdist = dist; - outshadow = vec4(shadow, 1.0); - outvisifac = visifac; -} - void math_add(float val1, float val2, out float outval) { outval = val1 + val2; @@ -426,13 +380,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) @@ -448,7 +402,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); } @@ -490,9 +444,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)); @@ -501,9 +455,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)); @@ -823,22 +777,19 @@ 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; -#else - outval = color.r * 0.35 + color.g * 0.45 + color.b * 0.2; /* keep these factors in sync with texture.h:RGBTOBW */ -#endif + vec3 factors = vec3(0.2126, 0.7152, 0.0722); + 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,56 +867,6 @@ void output_node(vec4 rgb, float alpha, out vec4 outrgb) /*********** TEXTURES ***************/ -void texture_flip_blend(vec3 vec, out vec3 outvec) -{ - outvec = vec.yxz; -} - -void texture_blend_lin(vec3 vec, out float outval) -{ - outval = (1.0 + vec.x) / 2.0; -} - -void texture_blend_quad(vec3 vec, out float outval) -{ - outval = max((1.0 + vec.x) / 2.0, 0.0); - outval *= outval; -} - -void texture_wood_sin(vec3 vec, out float value, out vec4 color, out vec3 normal) -{ - float a = sqrt(vec.x * vec.x + vec.y * vec.y + vec.z * vec.z) * 20.0; - float wi = 0.5 + 0.5 * sin(a); - - value = wi; - color = vec4(wi, wi, wi, 1.0); - normal = vec3(0.0, 0.0, 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); - value = color.a; - - normal.x = 2.0 * (color.r - 0.5); - normal.y = 2.0 * (0.5 - color.g); - normal.z = 2.0 * (color.b - 0.5); -} - -/************* MTEX *****************/ - -void texco_orco(vec3 attorco, out vec3 orco) -{ - orco = attorco; -} - -void texco_uv(vec2 attuv, out vec3 uv) -{ - /* disabled for now, works together with leaving out mtex_2d_mapping */ - // uv = vec3(attuv*2.0 - vec2(1.0, 1.0), 0.0); */ - uv = vec3(attuv, 0.0); -} - void texco_norm(vec3 normal, out vec3 outnormal) { /* corresponds to shi->orn, which is negated so cancels @@ -973,436 +874,11 @@ void texco_norm(vec3 normal, out vec3 outnormal) outnormal = normalize(normal); } -void texco_tangent(vec4 tangent, out vec3 outtangent) -{ - outtangent = normalize(tangent.xyz); -} - -void texco_global(mat4 viewinvmat, vec3 co, out vec3 global) -{ - global = (viewinvmat * vec4(co, 1.0)).xyz; -} - -void texco_object(mat4 viewinvmat, mat4 obinvmat, vec3 co, out vec3 object) -{ - object = (obinvmat * (viewinvmat * vec4(co, 1.0))).xyz; -} - -void texco_refl(vec3 vn, vec3 view, out vec3 ref) -{ - ref = view - 2.0 * dot(vn, view) * vn; -} - -void shade_norm(vec3 normal, out vec3 outnormal) -{ - /* blender render normal is negated */ - outnormal = -normalize(normal); -} - -void mtex_mirror(vec3 tcol, vec4 refcol, float tin, float colmirfac, out vec4 outrefcol) -{ - outrefcol = mix(refcol, vec4(1.0, tcol), tin * colmirfac); -} - -void mtex_rgb_blend(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) -{ - float facm; - - fact *= facg; - facm = 1.0 - fact; - - incol = fact * texcol + facm * outcol; -} - -void mtex_rgb_mul(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) -{ - float facm; - - fact *= facg; - facm = 1.0 - fact; - - incol = (facm + fact * texcol) * outcol; -} - -void mtex_rgb_screen(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) -{ - float facm; - - fact *= facg; - facm = 1.0 - fact; - - incol = vec3(1.0) - (vec3(facm) + fact * (vec3(1.0) - texcol)) * (vec3(1.0) - outcol); -} - -void mtex_rgb_overlay(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) -{ - float facm; - - fact *= facg; - facm = 1.0 - fact; - - if (outcol.r < 0.5) - incol.r = outcol.r * (facm + 2.0 * fact * texcol.r); - else - incol.r = 1.0 - (facm + 2.0 * fact * (1.0 - texcol.r)) * (1.0 - outcol.r); - - if (outcol.g < 0.5) - incol.g = outcol.g * (facm + 2.0 * fact * texcol.g); - else - incol.g = 1.0 - (facm + 2.0 * fact * (1.0 - texcol.g)) * (1.0 - outcol.g); - - if (outcol.b < 0.5) - incol.b = outcol.b * (facm + 2.0 * fact * texcol.b); - else - incol.b = 1.0 - (facm + 2.0 * fact * (1.0 - texcol.b)) * (1.0 - outcol.b); -} - -void mtex_rgb_sub(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) -{ - incol = -fact * facg * texcol + outcol; -} - -void mtex_rgb_add(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) -{ - incol = fact * facg * texcol + outcol; -} - -void mtex_rgb_div(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) -{ - float facm; - - fact *= facg; - facm = 1.0 - fact; - - if (texcol.r != 0.0) incol.r = facm * outcol.r + fact * outcol.r / texcol.r; - if (texcol.g != 0.0) incol.g = facm * outcol.g + fact * outcol.g / texcol.g; - if (texcol.b != 0.0) incol.b = facm * outcol.b + fact * outcol.b / texcol.b; -} - -void mtex_rgb_diff(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) -{ - float facm; - - fact *= facg; - facm = 1.0 - fact; - - incol = facm * outcol + fact * abs(texcol - outcol); -} - -void mtex_rgb_dark(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) -{ - float facm, col; - - fact *= facg; - facm = 1.0 - fact; - - incol.r = min(outcol.r, texcol.r) * fact + outcol.r * facm; - incol.g = min(outcol.g, texcol.g) * fact + outcol.g * facm; - incol.b = min(outcol.b, texcol.b) * fact + outcol.b * facm; -} - -void mtex_rgb_light(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) -{ - float facm, col; - - fact *= facg; - - col = fact * texcol.r; - if (col > outcol.r) incol.r = col; else incol.r = outcol.r; - col = fact * texcol.g; - if (col > outcol.g) incol.g = col; else incol.g = outcol.g; - col = fact * texcol.b; - if (col > outcol.b) incol.b = col; else incol.b = outcol.b; -} - -void mtex_rgb_hue(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) -{ - vec4 col; - - mix_hue(fact * facg, vec4(outcol, 1.0), vec4(texcol, 1.0), col); - incol.rgb = col.rgb; -} - -void mtex_rgb_sat(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) -{ - vec4 col; - - mix_sat(fact * facg, vec4(outcol, 1.0), vec4(texcol, 1.0), col); - incol.rgb = col.rgb; -} - -void mtex_rgb_val(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) -{ - vec4 col; - - mix_val(fact * facg, vec4(outcol, 1.0), vec4(texcol, 1.0), col); - incol.rgb = col.rgb; -} - -void mtex_rgb_color(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) -{ - vec4 col; - - mix_color(fact * facg, vec4(outcol, 1.0), vec4(texcol, 1.0), col); - incol.rgb = col.rgb; -} - -void mtex_rgb_soft(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) -{ - vec4 col; - - mix_soft(fact * facg, vec4(outcol, 1.0), vec4(texcol, 1.0), col); - incol.rgb = col.rgb; -} - -void mtex_rgb_linear(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) -{ - fact *= facg; - - if (texcol.r > 0.5) - incol.r = outcol.r + fact * (2.0 * (texcol.r - 0.5)); - else - incol.r = outcol.r + fact * (2.0 * (texcol.r) - 1.0); - - if (texcol.g > 0.5) - incol.g = outcol.g + fact * (2.0 * (texcol.g - 0.5)); - else - incol.g = outcol.g + fact * (2.0 * (texcol.g) - 1.0); - - if (texcol.b > 0.5) - incol.b = outcol.b + fact * (2.0 * (texcol.b - 0.5)); - else - incol.b = outcol.b + fact * (2.0 * (texcol.b) - 1.0); -} - -void mtex_value_vars(inout float fact, float facg, out float facm) -{ - fact *= abs(facg); - facm = 1.0 - fact; - - if (facg < 0.0) { - float tmp = fact; - fact = facm; - facm = tmp; - } -} - -void mtex_value_blend(float outcol, float texcol, float fact, float facg, out float incol) -{ - float facm; - mtex_value_vars(fact, facg, facm); - - incol = fact * texcol + facm * outcol; -} - -void mtex_value_mul(float outcol, float texcol, float fact, float facg, out float incol) -{ - float facm; - mtex_value_vars(fact, facg, facm); - - facm = 1.0 - facg; - incol = (facm + fact * texcol) * outcol; -} - -void mtex_value_screen(float outcol, float texcol, float fact, float facg, out float incol) -{ - float facm; - mtex_value_vars(fact, facg, facm); - - facm = 1.0 - facg; - incol = 1.0 - (facm + fact * (1.0 - texcol)) * (1.0 - outcol); -} - -void mtex_value_sub(float outcol, float texcol, float fact, float facg, out float incol) -{ - float facm; - mtex_value_vars(fact, facg, facm); - - fact = -fact; - incol = fact * texcol + outcol; -} - -void mtex_value_add(float outcol, float texcol, float fact, float facg, out float incol) -{ - float facm; - mtex_value_vars(fact, facg, facm); - - fact = fact; - incol = fact * texcol + outcol; -} - -void mtex_value_div(float outcol, float texcol, float fact, float facg, out float incol) -{ - float facm; - mtex_value_vars(fact, facg, facm); - - if (texcol != 0.0) - incol = facm * outcol + fact * outcol / texcol; - else - incol = 0.0; -} - -void mtex_value_diff(float outcol, float texcol, float fact, float facg, out float incol) -{ - float facm; - mtex_value_vars(fact, facg, facm); - - incol = facm * outcol + fact * abs(texcol - outcol); -} - -void mtex_value_dark(float outcol, float texcol, float fact, float facg, out float incol) -{ - float facm; - mtex_value_vars(fact, facg, facm); - - incol = facm * outcol + fact * min(outcol, texcol); -} - -void mtex_value_light(float outcol, float texcol, float fact, float facg, out float incol) -{ - float facm; - mtex_value_vars(fact, facg, facm); - - float col = fact * texcol; - if (col > outcol) incol = col; else incol = outcol; -} - -void mtex_value_clamp_positive(float fac, out float outfac) -{ - outfac = max(fac, 0.0); -} - -void mtex_value_clamp(float fac, out float outfac) -{ - outfac = clamp(fac, 0.0, 1.0); -} - -void mtex_har_divide(float har, out float outhar) -{ - outhar = har / 128.0; -} - -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; -} - -void mtex_alpha_from_col(vec4 col, out float alpha) -{ - alpha = col.a; -} - -void mtex_alpha_to_col(vec4 col, float alpha, out vec4 outcol) -{ - outcol = vec4(col.rgb, alpha); -} - -void mtex_alpha_multiply_value(vec4 col, float value, out vec4 outcol) -{ - outcol = vec4(col.rgb, col.a * value); -} - -void mtex_rgbtoint(vec4 rgb, out float intensity) -{ - intensity = dot(vec3(0.35, 0.45, 0.2), rgb.rgb); -} - -void mtex_value_invert(float invalue, out float outvalue) -{ - outvalue = 1.0 - invalue; -} - -void mtex_rgb_invert(vec4 inrgb, out vec4 outrgb) -{ - outrgb = vec4(vec3(1.0) - inrgb.rgb, inrgb.a); -} - -void mtex_value_stencil(float stencil, float intensity, out float outstencil, out float outintensity) -{ - float fact = intensity; - outintensity = intensity * stencil; - outstencil = stencil * fact; -} - -void mtex_rgb_stencil(float stencil, vec4 rgb, out float outstencil, out vec4 outrgb) -{ - float fact = rgb.a; - outrgb = vec4(rgb.rgb, rgb.a * stencil); - outstencil = stencil * fact; -} - -void mtex_mapping_ofs(vec3 texco, vec3 ofs, out vec3 outtexco) -{ - outtexco = texco + ofs; -} - -void mtex_mapping_size(vec3 texco, vec3 size, out vec3 outtexco) -{ - outtexco = size * texco; -} - -void mtex_2d_mapping(vec3 vec, out vec3 outvec) -{ - outvec = vec3(vec.xy * 0.5 + vec2(0.5), vec.z); -} - vec3 mtex_2d_mapping(vec3 vec) { return vec3(vec.xy * 0.5 + vec2(0.5), vec.z); } -void mtex_cube_map(vec3 co, samplerCube ima, out float value, out vec4 color) -{ - color = textureCube(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); - value = color.a; -} - -void mtex_cube_map_refl( - samplerCube ima, vec3 vp, vec3 vn, mat4 viewmatrixinverse, mat4 viewmatrix, - out float value, out vec4 color) -{ - 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); - value = 1.0; -} - -void mtex_image(vec3 texco, sampler2D ima, out float value, out vec4 color) -{ - color = texture2D(ima, texco.xy); - value = 1.0; -} - -void mtex_normal(vec3 texco, sampler2D ima, out vec3 normal) -{ - // The invert of the red channel is to make - // the normal map compliant with the outside world. - // 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); - normal = 2.0 * (vec3(-color.r, color.g, color.b) - vec3(-0.5, 0.5, 0.5)); -} - -void mtex_bump_normals_init(vec3 vN, out vec3 vNorg, out vec3 vNacc, out float fPrevMagnitude) -{ - vNorg = vN; - vNacc = vN; - fPrevMagnitude = 1.0; -} - /** helper method to extract the upper left 3x3 matrix from a 4x4 matrix */ mat3 to_mat3(mat4 m4) { @@ -1413,976 +889,6 @@ mat3 to_mat3(mat4 m4) return m3; } -void mtex_bump_init_objspace( - vec3 surf_pos, vec3 surf_norm, - mat4 mView, mat4 mViewInv, mat4 mObj, mat4 mObjInv, - float fPrevMagnitude_in, vec3 vNacc_in, - 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); - - vec3 vSigmaS = view2obj * dFdx(surf_pos); - vec3 vSigmaT = view2obj * dFdy(surf_pos); - vec3 vN = normalize(surf_norm * obj2view); - - vR1 = cross(vSigmaT, vN); - vR2 = cross(vN, vSigmaS); - fDet = dot(vSigmaS, vR1); - - /* pretransform vNacc (in mtex_bump_apply) using the inverse transposed */ - vR1 = vR1 * view2obj; - vR2 = vR2 * view2obj; - vN = vN * view2obj; - - float fMagnitude = abs(fDet) * length(vN); - vNacc_out = vNacc_in * (fMagnitude / fPrevMagnitude_in); - fPrevMagnitude_out = fMagnitude; -} - -void mtex_bump_init_texturespace( - vec3 surf_pos, vec3 surf_norm, - float fPrevMagnitude_in, vec3 vNacc_in, - out float fPrevMagnitude_out, out vec3 vNacc_out, - out vec3 vR1, out vec3 vR2, out float fDet) -{ - vec3 vSigmaS = dFdx(surf_pos); - vec3 vSigmaT = dFdy(surf_pos); - vec3 vN = surf_norm; /* normalized interpolated vertex normal */ - - vR1 = normalize(cross(vSigmaT, vN)); - vR2 = normalize(cross(vN, vSigmaS)); - fDet = sign(dot(vSigmaS, vR1)); - - float fMagnitude = abs(fDet); - vNacc_out = vNacc_in * (fMagnitude / fPrevMagnitude_in); - fPrevMagnitude_out = fMagnitude; -} - -void mtex_bump_init_viewspace( - vec3 surf_pos, vec3 surf_norm, - float fPrevMagnitude_in, vec3 vNacc_in, - out float fPrevMagnitude_out, out vec3 vNacc_out, - out vec3 vR1, out vec3 vR2, out float fDet) -{ - vec3 vSigmaS = dFdx(surf_pos); - vec3 vSigmaT = dFdy(surf_pos); - vec3 vN = surf_norm; /* normalized interpolated vertex normal */ - - vR1 = cross(vSigmaT, vN); - vR2 = cross(vN, vSigmaS); - fDet = dot(vSigmaS, vR1); - - float fMagnitude = abs(fDet); - vNacc_out = vNacc_in * (fMagnitude / fPrevMagnitude_in); - fPrevMagnitude_out = fMagnitude; -} - -void mtex_bump_tap3( - vec3 texco, sampler2D ima, float hScale, - out float dBs, out float dBt) -{ - vec2 STll = texco.xy; - vec2 STlr = texco.xy + dFdx(texco.xy); - 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); - - dBs = hScale * (Hlr - Hll); - dBt = hScale * (Hul - Hll); -} - -#ifdef BUMP_BICUBIC - -void mtex_bump_bicubic( - vec3 texco, sampler2D ima, float hScale, - out float dBs, out float dBt ) -{ - float Hl; - float Hr; - float Hd; - float Hu; - - vec2 TexDx = dFdx(texco.xy); - vec2 TexDy = dFdy(texco.xy); - - vec2 STl = texco.xy - 0.5 * TexDx; - vec2 STr = texco.xy + 0.5 * TexDx; - 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); - - vec2 dHdxy = vec2(Hr - Hl, Hu - Hd); - float fBlend = clamp(1.0 - textureQueryLOD(ima, texco.xy).x, 0.0, 1.0); - if (fBlend != 0.0) { - // the derivative of the bicubic sampling of level 0 - ivec2 vDim; - vDim = textureSize(ima, 0); - - // taking the fract part of the texture coordinate is a hardcoded wrap mode. - // this is acceptable as textures use wrap mode exclusively in 3D view elsewhere in blender. - // this is done so that we can still get a valid texel with uvs outside the 0,1 range - // by texelFetch below, as coordinates are clamped when using this function. - vec2 fTexLoc = vDim * fract(texco.xy) - vec2(0.5, 0.5); - ivec2 iTexLoc = ivec2(floor(fTexLoc)); - vec2 t = clamp(fTexLoc - iTexLoc, 0.0, 1.0); // sat just to be pedantic - -/******************************************************************************************* - * This block will replace the one below when one channel textures are properly supported. * - ******************************************************************************************* - vec4 vSamplesUL = textureGather(ima, (iTexLoc+ivec2(-1,-1) + vec2(0.5,0.5))/vDim); - vec4 vSamplesUR = textureGather(ima, (iTexLoc+ivec2(1,-1) + vec2(0.5,0.5))/vDim); - vec4 vSamplesLL = textureGather(ima, (iTexLoc+ivec2(-1,1) + vec2(0.5,0.5))/vDim); - vec4 vSamplesLR = textureGather(ima, (iTexLoc+ivec2(1,1) + vec2(0.5,0.5))/vDim); - - mat4 H = mat4(vSamplesUL.w, vSamplesUL.x, vSamplesLL.w, vSamplesLL.x, - vSamplesUL.z, vSamplesUL.y, vSamplesLL.z, vSamplesLL.y, - vSamplesUR.w, vSamplesUR.x, vSamplesLR.w, vSamplesLR.x, - vSamplesUR.z, vSamplesUR.y, vSamplesLR.z, vSamplesLR.y); - */ - ivec2 iTexLocMod = iTexLoc + ivec2(-1, -1); - - mat4 H; - - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - ivec2 iTexTmp = iTexLocMod + ivec2(i, j); - - // wrap texture coordinates manually for texelFetch to work on uvs oitside the 0,1 range. - // this is guaranteed to work since we take the fractional part of the uv above. - iTexTmp.x = (iTexTmp.x < 0) ? iTexTmp.x + vDim.x : ((iTexTmp.x >= vDim.x) ? iTexTmp.x - vDim.x : iTexTmp.x); - iTexTmp.y = (iTexTmp.y < 0) ? iTexTmp.y + vDim.y : ((iTexTmp.y >= vDim.y) ? iTexTmp.y - vDim.y : iTexTmp.y); - - rgbtobw(texelFetch(ima, iTexTmp, 0), H[i][j]); - } - } - - float x = t.x, y = t.y; - float x2 = x * x, x3 = x2 * x, y2 = y * y, y3 = y2 * y; - - vec4 X = vec4(-0.5 * (x3 + x) + x2, 1.5 * x3 - 2.5 * x2 + 1, -1.5 * x3 + 2 * x2 + 0.5 * x, 0.5 * (x3 - x2)); - vec4 Y = vec4(-0.5 * (y3 + y) + y2, 1.5 * y3 - 2.5 * y2 + 1, -1.5 * y3 + 2 * y2 + 0.5 * y, 0.5 * (y3 - y2)); - vec4 dX = vec4(-1.5 * x2 + 2 * x - 0.5, 4.5 * x2 - 5 * x, -4.5 * x2 + 4 * x + 0.5, 1.5 * x2 - x); - vec4 dY = vec4(-1.5 * y2 + 2 * y - 0.5, 4.5 * y2 - 5 * y, -4.5 * y2 + 4 * y + 0.5, 1.5 * y2 - y); - - // complete derivative in normalized coordinates (mul by vDim) - vec2 dHdST = vDim * vec2(dot(Y, H * dX), dot(dY, H * X)); - - // transform derivative to screen-space - vec2 dHdxy_bicubic = vec2(dHdST.x * TexDx.x + dHdST.y * TexDx.y, - dHdST.x * TexDy.x + dHdST.y * TexDy.y); - - // blend between the two - dHdxy = dHdxy * (1 - fBlend) + dHdxy_bicubic * fBlend; - } - - dBs = hScale * dHdxy.x; - dBt = hScale * dHdxy.y; -} - -#endif - -void mtex_bump_tap5( - vec3 texco, sampler2D ima, float hScale, - out float dBs, out float dBt) -{ - vec2 TexDx = dFdx(texco.xy); - vec2 TexDy = dFdy(texco.xy); - - vec2 STc = texco.xy; - vec2 STl = texco.xy - 0.5 * TexDx; - vec2 STr = texco.xy + 0.5 * TexDx; - vec2 STd = texco.xy - 0.5 * TexDy; - 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); - - dBs = hScale * (Hr - Hl); - dBt = hScale * (Hu - Hd); -} - -void mtex_bump_deriv( - vec3 texco, sampler2D ima, float ima_x, float ima_y, float hScale, - out float dBs, out float dBt) -{ - float s = 1.0; // negate this if flipped texture coordinate - vec2 TexDx = dFdx(texco.xy); - vec2 TexDy = dFdy(texco.xy); - - // 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); - - dBs = dBduv.x * TexDx.x + s * dBduv.y * TexDx.y; - dBt = dBduv.x * TexDy.x + s * dBduv.y * TexDy.y; -} - -void mtex_bump_apply( - float fDet, float dBs, float dBt, vec3 vR1, vec3 vR2, vec3 vNacc_in, - out vec3 vNacc_out, out vec3 perturbed_norm) -{ - vec3 vSurfGrad = sign(fDet) * (dBs * vR1 + dBt * vR2); - - vNacc_out = vNacc_in - vSurfGrad; - perturbed_norm = normalize(vNacc_out); -} - -void mtex_bump_apply_texspace( - float fDet, float dBs, float dBt, vec3 vR1, vec3 vR2, - sampler2D ima, vec3 texco, float ima_x, float ima_y, vec3 vNacc_in, - out vec3 vNacc_out, out vec3 perturbed_norm) -{ - vec2 TexDx = dFdx(texco.xy); - vec2 TexDy = dFdy(texco.xy); - - vec3 vSurfGrad = sign(fDet) * ( - dBs / length(vec2(ima_x * TexDx.x, ima_y * TexDx.y)) * vR1 + - dBt / length(vec2(ima_x * TexDy.x, ima_y * TexDy.y)) * vR2); - - vNacc_out = vNacc_in - vSurfGrad; - perturbed_norm = normalize(vNacc_out); -} - -void mtex_negate_texnormal(vec3 normal, out vec3 outnormal) -{ - outnormal = vec3(-normal.x, -normal.y, normal.z); -} - -void mtex_nspace_tangent(vec4 tangent, vec3 normal, vec3 texnormal, out vec3 outnormal) -{ - vec3 B = tangent.w * cross(normal, tangent.xyz); - - outnormal = texnormal.x * tangent.xyz + texnormal.y * B + texnormal.z * normal; - outnormal = normalize(outnormal); -} - -void mtex_nspace_world(mat4 viewmat, vec3 texnormal, out vec3 outnormal) -{ - outnormal = normalize((viewmat * vec4(texnormal, 0.0)).xyz); -} - -void mtex_nspace_object(vec3 texnormal, out vec3 outnormal) -{ - outnormal = normalize(gl_NormalMatrix * texnormal); -} - -void mtex_blend_normal(float norfac, vec3 normal, vec3 newnormal, out vec3 outnormal) -{ - outnormal = (1.0 - norfac) * normal + norfac * newnormal; - outnormal = normalize(outnormal); -} - -/******* MATERIAL *********/ - -void lamp_visibility_sun_hemi(vec3 lampvec, out vec3 lv, out float dist, out float visifac) -{ - lv = lampvec; - dist = 1.0; - visifac = 1.0; -} - -void lamp_visibility_other(vec3 co, vec3 lampco, out vec3 lv, out float dist, out float visifac) -{ - lv = co - lampco; - dist = length(lv); - lv = normalize(lv); - visifac = 1.0; -} - -void lamp_falloff_invlinear(float lampdist, float dist, out float visifac) -{ - visifac = lampdist / (lampdist + dist); -} - -void lamp_falloff_invsquare(float lampdist, float dist, out float visifac) -{ - visifac = lampdist / (lampdist + dist * dist); -} - -void lamp_falloff_sliders(float lampdist, float ld1, float ld2, float dist, out float visifac) -{ - float lampdistkw = lampdist * lampdist; - - visifac = lampdist / (lampdist + ld1 * dist); - visifac *= lampdistkw / (lampdistkw + ld2 * dist * dist); -} - -void lamp_falloff_invcoefficients(float coeff_const, float coeff_lin, float coeff_quad, float dist, out float visifac) -{ - vec3 coeff = vec3(coeff_const, coeff_lin, coeff_quad); - vec3 d_coeff = vec3(1.0, dist, dist * dist); - float visifac_r = dot(coeff, d_coeff); - if (visifac_r > 0.0) - visifac = 1.0 / visifac_r; - else - visifac = 0.0; -} - -void lamp_falloff_curve(float lampdist, sampler2D curvemap, float dist, out float visifac) -{ - visifac = texture2D(curvemap, vec2(dist / lampdist, 0.0)).x; -} - -void lamp_visibility_sphere(float lampdist, float dist, float visifac, out float outvisifac) -{ - float t = lampdist - dist; - - outvisifac = visifac * max(t, 0.0) / lampdist; -} - -void lamp_visibility_spot_square(vec3 lampvec, mat4 lampimat, vec2 scale, vec3 lv, out float inpr) -{ - if (dot(lv, lampvec) > 0.0) { - vec3 lvrot = (lampimat * vec4(lv, 0.0)).xyz; - /* without clever non-uniform scale, we could do: */ - // float x = max(abs(lvrot.x / lvrot.z), abs(lvrot.y / lvrot.z)); - float x = max(abs((lvrot.x / scale.x) / lvrot.z), abs((lvrot.y / scale.y) / lvrot.z)); - - inpr = 1.0 / sqrt(1.0 + x * x); - } - else - inpr = 0.0; -} - -void lamp_visibility_spot_circle(vec3 lampvec, mat4 lampimat, vec2 scale, vec3 lv, out float inpr) -{ - /* without clever non-uniform scale, we could do: */ - // inpr = dot(lv, lampvec); - if (dot(lv, lampvec) > 0.0) { - vec3 lvrot = (lampimat * vec4(lv, 0.0)).xyz; - float x = abs(lvrot.x / lvrot.z); - float y = abs(lvrot.y / lvrot.z); - - float ellipse = abs((x * x) / (scale.x * scale.x) + (y * y) / (scale.y * scale.y)); - - inpr = 1.0 / sqrt(1.0 + ellipse); - } - else - inpr = 0.0; -} - -void lamp_visibility_spot(float spotsi, float spotbl, float inpr, float visifac, out float outvisifac) -{ - float t = spotsi; - - if (inpr <= t) { - outvisifac = 0.0; - } - else { - t = inpr - t; - - /* soft area */ - if (spotbl != 0.0) - inpr *= smoothstep(0.0, 1.0, t / spotbl); - - outvisifac = visifac * inpr; - } -} - -void lamp_visibility_clamp(float visifac, out float outvisifac) -{ - outvisifac = (visifac < 0.001) ? 0.0 : visifac; -} - -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); -} - -void world_zen_mapping(vec3 view, float zenup, float zendown, out float zenfac) -{ - if (view.z >= 0.0) - zenfac = zenup; - else - zenfac = zendown; -} - -void world_blend_paper_real(vec3 vec, out float blend) -{ - blend = abs(vec.y); -} - -void world_blend_paper(vec3 vec, out float blend) -{ - blend = (vec.y + 1.0) * 0.5; -} - -void world_blend_real(vec3 vec, out float blend) -{ - blend = abs(normalize(vec).z); -} - -void world_blend(vec3 vec, out float blend) -{ - blend = (normalize(vec).z + 1) * 0.5; -} - -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); -} - -void shade_tangent_v(vec3 lv, vec3 tang, out vec3 vn) -{ - vec3 c = cross(lv, tang); - vec3 vnor = cross(c, tang); - - vn = -normalize(vnor); -} - -void shade_inp(vec3 vn, vec3 lv, out float inp) -{ - inp = dot(vn, lv); -} - -void shade_is_no_diffuse(out float is) -{ - is = 0.0; -} - -void shade_is_hemi(float inp, out float is) -{ - is = 0.5 * inp + 0.5; -} - -float area_lamp_energy(mat4 area, vec3 co, vec3 vn) -{ - vec3 vec[4], c[4]; - float rad[4], fac; - - vec[0] = normalize(co - area[0].xyz); - vec[1] = normalize(co - area[1].xyz); - vec[2] = normalize(co - area[2].xyz); - vec[3] = normalize(co - area[3].xyz); - - c[0] = normalize(cross(vec[0], vec[1])); - c[1] = normalize(cross(vec[1], vec[2])); - c[2] = normalize(cross(vec[2], vec[3])); - c[3] = normalize(cross(vec[3], vec[0])); - - rad[0] = acos(dot(vec[0], vec[1])); - rad[1] = acos(dot(vec[1], vec[2])); - rad[2] = acos(dot(vec[2], vec[3])); - rad[3] = acos(dot(vec[3], vec[0])); - - fac = rad[0] * dot(vn, c[0]); - fac += rad[1] * dot(vn, c[1]); - fac += rad[2] * dot(vn, c[2]); - fac += rad[3] * dot(vn, c[3]); - - return max(fac, 0.0); -} - -void shade_inp_area( - vec3 position, vec3 lampco, vec3 lampvec, vec3 vn, mat4 area, float areasize, float k, - out float inp) -{ - vec3 co = position; - vec3 vec = co - lampco; - - if (dot(vec, lampvec) < 0.0) { - inp = 0.0; - } - else { - float intens = area_lamp_energy(area, co, vn); - - inp = pow(intens * areasize, k); - } -} - -void shade_diffuse_oren_nayer(float nl, vec3 n, vec3 l, vec3 v, float rough, out float is) -{ - vec3 h = normalize(v + l); - float nh = max(dot(n, h), 0.0); - float nv = max(dot(n, v), 0.0); - float realnl = dot(n, l); - - if (realnl < 0.0) { - is = 0.0; - } - else if (nl < 0.0) { - is = 0.0; - } - else { - float vh = max(dot(v, h), 0.0); - float Lit_A = acos(realnl); - float View_A = acos(nv); - - vec3 Lit_B = normalize(l - realnl * n); - vec3 View_B = normalize(v - nv * n); - - float t = max(dot(Lit_B, View_B), 0.0); - - float a, b; - - if (Lit_A > View_A) { - a = Lit_A; - b = View_A; - } - else { - a = View_A; - b = Lit_A; - } - - float A = 1.0 - (0.5 * ((rough * rough) / ((rough * rough) + 0.33))); - float B = 0.45 * ((rough * rough) / ((rough * rough) + 0.09)); - - b *= 0.95; - is = nl * (A + (B * t * sin(a) * tan(b))); - } -} - -void shade_diffuse_toon(vec3 n, vec3 l, vec3 v, float size, float tsmooth, out float is) -{ - float rslt = dot(n, l); - float ang = acos(rslt); - - if (ang < size) is = 1.0; - else if (ang > (size + tsmooth) || tsmooth == 0.0) is = 0.0; - else is = 1.0 - ((ang - size) / tsmooth); -} - -void shade_diffuse_minnaert(float nl, vec3 n, vec3 v, float darkness, out float is) -{ - if (nl <= 0.0) { - is = 0.0; - } - else { - float nv = max(dot(n, v), 0.0); - - if (darkness <= 1.0) - is = nl * pow(max(nv * nl, 0.1), darkness - 1.0); - else - is = nl * pow(1.0001 - nv, darkness - 1.0); - } -} - -float fresnel_fac(vec3 view, vec3 vn, float grad, float fac) -{ - float t1, t2; - float ffac; - - if (fac == 0.0) { - ffac = 1.0; - } - else { - t1 = dot(view, vn); - if (t1 > 0.0) t2 = 1.0 + t1; - else t2 = 1.0 - t1; - - t2 = grad + (1.0 - grad) * pow(t2, fac); - - if (t2 < 0.0) ffac = 0.0; - else if (t2 > 1.0) ffac = 1.0; - else ffac = t2; - } - - return ffac; -} - -void shade_diffuse_fresnel(vec3 vn, vec3 lv, vec3 view, float fac_i, float fac, out float is) -{ - is = fresnel_fac(lv, vn, fac_i, fac); -} - -void shade_cubic(float is, out float outis) -{ - if (is > 0.0 && is < 1.0) - outis = smoothstep(0.0, 1.0, is); - else - outis = is; -} - -void shade_visifac(float i, float visifac, float refl, out float outi) -{ - /*if (i > 0.0)*/ - outi = max(i * visifac * refl, 0.0); - /*else - outi = i;*/ -} - -void shade_tangent_v_spec(vec3 tang, out vec3 vn) -{ - vn = tang; -} - -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); -} - -void shade_hemi_spec(vec3 vn, vec3 lv, vec3 view, float spec, float hard, float visifac, out float t) -{ - lv += view; - lv = normalize(lv); - - t = dot(vn, lv); - t = 0.5 * t + 0.5; - - t = visifac * spec * pow(t, hard); -} - -void shade_phong_spec(vec3 n, vec3 l, vec3 v, float hard, out float specfac) -{ - vec3 h = normalize(l + v); - float rslt = max(dot(h, n), 0.0); - - specfac = pow(rslt, hard); -} - -void shade_cooktorr_spec(vec3 n, vec3 l, vec3 v, float hard, out float specfac) -{ - vec3 h = normalize(v + l); - float nh = dot(n, h); - - if (nh < 0.0) { - specfac = 0.0; - } - else { - float nv = max(dot(n, v), 0.0); - float i = pow(nh, hard); - - i = i / (0.1 + nv); - specfac = i; - } -} - -void shade_blinn_spec(vec3 n, vec3 l, vec3 v, float refrac, float spec_power, out float specfac) -{ - if (refrac < 1.0) { - specfac = 0.0; - } - else if (spec_power == 0.0) { - specfac = 0.0; - } - else { - if (spec_power < 100.0) - spec_power = sqrt(1.0 / spec_power); - else - spec_power = 10.0 / spec_power; - - vec3 h = normalize(v + l); - float nh = dot(n, h); - if (nh < 0.0) { - specfac = 0.0; - } - else { - float nv = max(dot(n, v), 0.01); - float nl = dot(n, l); - if (nl <= 0.01) { - specfac = 0.0; - } - else { - float vh = max(dot(v, h), 0.01); - - float a = 1.0; - float b = (2.0 * nh * nv) / vh; - float c = (2.0 * nh * nl) / vh; - - float g = 0.0; - - if (a < b && a < c) g = a; - else if (b < a && b < c) g = b; - else if (c < a && c < b) g = c; - - float p = sqrt(((refrac * refrac) + (vh * vh) - 1.0)); - float f = ((((p - vh) * (p - vh)) / ((p + vh) * (p + vh))) * - (1.0 + ((((vh * (p + vh)) - 1.0) * ((vh * (p + vh)) - 1.0)) / - (((vh * (p - vh)) + 1.0) * ((vh * (p - vh)) + 1.0))))); - float ang = acos(nh); - - specfac = max(f * g * exp_blender((-(ang * ang) / (2.0 * spec_power * spec_power))), 0.0); - } - } - } -} - -void shade_wardiso_spec(vec3 n, vec3 l, vec3 v, float rms, out float specfac) -{ - vec3 h = normalize(l + v); - float nh = max(dot(n, h), 0.001); - float nv = max(dot(n, v), 0.001); - float nl = max(dot(n, l), 0.001); - float angle = tan(acos(nh)); - float alpha = max(rms, 0.001); - - specfac = nl * (1.0 / (4.0 * M_PI * alpha * alpha)) * (exp_blender(-(angle * angle) / (alpha * alpha)) / (sqrt(nv * nl))); -} - -void shade_toon_spec(vec3 n, vec3 l, vec3 v, float size, float tsmooth, out float specfac) -{ - vec3 h = normalize(l + v); - float rslt = dot(h, n); - float ang = acos(rslt); - - if (ang < size) rslt = 1.0; - else if (ang >= (size + tsmooth) || tsmooth == 0.0) rslt = 0.0; - else rslt = 1.0 - ((ang - size) / tsmooth); - - specfac = rslt; -} - -void shade_spec_area_inp(float specfac, float inp, out float outspecfac) -{ - outspecfac = specfac * inp; -} - -void shade_spec_t(float shadfac, float spec, float visifac, float specfac, out float t) -{ - t = shadfac * spec * visifac * specfac; -} - -void shade_add_spec(float t, vec3 lampcol, vec3 speccol, out vec3 outcol) -{ - outcol = t * lampcol * speccol; -} - -void shade_add_mirror(vec3 mir, vec4 refcol, vec3 combined, out vec3 result) -{ - result = mir * refcol.gba + (vec3(1.0) - mir * refcol.rrr) * combined; -} - -void alpha_spec_correction(vec3 spec, float spectra, float alpha, out float outalpha) -{ - if (spectra > 0.0) { - float t = clamp(max(max(spec.r, spec.g), spec.b) * spectra, 0.0, 1.0); - outalpha = (1.0 - t) * alpha + t; - } - else { - outalpha = alpha; - } -} - -void shade_add(vec4 col1, vec4 col2, out vec4 outcol) -{ - outcol = col1 + col2; -} - -void shade_madd(vec4 col, vec4 col1, vec4 col2, out vec4 outcol) -{ - outcol = col + col1 * col2; -} - -void shade_add_clamped(vec4 col1, vec4 col2, out vec4 outcol) -{ - outcol = col1 + max(col2, vec4(0.0, 0.0, 0.0, 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)); -} - -void env_apply(vec4 col, vec3 hor, vec3 zen, vec4 f, mat4 vm, vec3 vn, out vec4 outcol) -{ - vec3 vv = normalize(vm[2].xyz); - float skyfac = 0.5 * (1.0 + dot(vn, -vv)); - outcol = col + f * vec4(mix(hor, zen, skyfac), 0); -} - -void shade_maddf(vec4 col, float f, vec4 col1, out vec4 outcol) -{ - outcol = col + f * col1; -} - -void shade_mul(vec4 col1, vec4 col2, out vec4 outcol) -{ - outcol = col1 * col2; -} - -void shade_mul_value(float fac, vec4 col, out vec4 outcol) -{ - outcol = col * fac; -} - -void shade_mul_value_v3(float fac, vec3 col, out vec3 outcol) -{ - outcol = col * fac; -} - -void shade_obcolor(vec4 col, vec4 obcol, out vec4 outcol) -{ - outcol = vec4(col.rgb * obcol.rgb, col.a); -} - -void ramp_rgbtobw(vec3 color, out float outval) -{ - outval = color.r * 0.3 + color.g * 0.58 + color.b * 0.12; -} - -void shade_only_shadow(float i, float shadfac, float energy, vec3 shadcol, out vec3 outshadrgb) -{ - outshadrgb = i * energy * (1.0 - shadfac) * (vec3(1.0) - shadcol); -} - -void shade_only_shadow_diffuse(vec3 shadrgb, vec3 rgb, vec4 diff, out vec4 outdiff) -{ - outdiff = diff - vec4(rgb * shadrgb, 0.0); -} - -void shade_only_shadow_specular(vec3 shadrgb, vec3 specrgb, vec4 spec, out vec4 outspec) -{ - outspec = spec - vec4(specrgb * shadrgb, 0.0); -} - -void shade_clamp_positive(vec4 col, out vec4 outcol) -{ - outcol = max(col, vec4(0.0)); -} - -void test_shadowbuf( - vec3 rco, sampler2DShadow shadowmap, mat4 shadowpersmat, float shadowbias, float inp, - out float result) -{ - if (inp <= 0.0) { - result = 0.0; - } - else { - vec4 co = shadowpersmat * vec4(rco, 1.0); - - //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 - result = 1.0; - } -} - -void test_shadowbuf_vsm( - vec3 rco, sampler2D shadowmap, mat4 shadowpersmat, float shadowbias, float bleedbias, float inp, - out float result) -{ - if (inp <= 0.0) { - result = 0.0; - } - 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; - float dist = co.z / co.w; - float p = 0.0; - - if (dist <= moments.x) - p = 1.0; - - float variance = moments.y - (moments.x * moments.x); - variance = max(variance, shadowbias / 10.0); - - float d = moments.x - dist; - float p_max = variance / (variance + d * d); - - // Now reduce light-bleeding by removing the [0, x] tail and linearly rescaling (x, 1] - p_max = clamp((p_max - bleedbias) / (1.0 - bleedbias), 0.0, 1.0); - - result = max(p, p_max); - } - else { - result = 1.0; - } - } -} - -void shadows_only( - vec3 rco, sampler2DShadow shadowmap, mat4 shadowpersmat, - float shadowbias, vec3 shadowcolor, float inp, - out vec3 result) -{ - result = vec3(1.0); - - if (inp > 0.0) { - float shadfac; - - test_shadowbuf(rco, shadowmap, shadowpersmat, shadowbias, inp, shadfac); - result -= (1.0 - shadfac) * (vec3(1.0) - shadowcolor); - } -} - -void shadows_only_vsm( - vec3 rco, sampler2D shadowmap, mat4 shadowpersmat, - float shadowbias, float bleedbias, vec3 shadowcolor, float inp, - out vec3 result) -{ - result = vec3(1.0); - - if (inp > 0.0) { - float shadfac; - - test_shadowbuf_vsm(rco, shadowmap, shadowpersmat, shadowbias, bleedbias, inp, shadfac); - result -= (1.0 - shadfac) * (vec3(1.0) - shadowcolor); - } -} - -void shade_light_texture(vec3 rco, sampler2D cookie, mat4 shadowpersmat, out vec4 result) -{ - - vec4 co = shadowpersmat * vec4(rco, 1.0); - - result = texture2DProj(cookie, co); -} - -void shade_exposure_correct(vec3 col, float linfac, float logfac, out vec3 outcol) -{ - outcol = linfac * (1.0 - exp(col * logfac)); -} - -void shade_mist_factor( - vec3 co, float enable, float miststa, float mistdist, float misttype, float misi, - out float outfac) -{ - if (enable == 1.0) { - float fac, zcor; - - zcor = (gl_ProjectionMatrix[3][3] == 0.0) ? length(co) : -co[2]; - - fac = clamp((zcor - miststa) / mistdist, 0.0, 1.0); - if (misttype == 0.0) fac *= fac; - else if (misttype == 1.0) ; - else fac = sqrt(fac); - - outfac = 1.0 - (1.0 - fac) * (1.0 - misi); - } - else { - outfac = 0.0; - } -} - -void shade_world_mix(vec3 hor, vec4 col, out vec4 outcol) -{ - float fac = clamp(col.a, 0.0, 1.0); - outcol = vec4(mix(hor, col.rgb, fac), col.a); -} - -void shade_alpha_opaque(vec4 col, out vec4 outcol) -{ - outcol = vec4(col.rgb, 1.0); -} - -void shade_alpha_obcolor(vec4 col, vec4 obcol, out vec4 outcol) -{ - outcol = vec4(col.rgb, col.a * obcol.a); -} - /*********** NEW SHADER UTILITIES **************/ float fresnel_dielectric_0(float eta) @@ -2428,7 +934,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) @@ -2441,7 +955,6 @@ int quick_floor(float x) return int(x) - ((x < 0) ? 1 : 0); } -#ifdef BIT_OPERATIONS float integer_noise(int n) { int nn; @@ -2505,7 +1018,6 @@ vec3 cellnoise_color(vec3 p) return vec3(r, g, b); } -#endif // BIT_OPERATIONS float floorfrac(float x, out int i) { @@ -2513,317 +1025,346 @@ float floorfrac(float x, out int i) return x - i; } +/* bsdfs */ -/* Principled BSDF operations */ - -float sqr(float a) +void convert_metallic_to_specular_tinted( + vec3 basecol, float metallic, float specular_fac, float specular_tint, + out vec3 diffuse, out vec3 f0) { - return a*a; + 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); } -float schlick_fresnel(float u) +#ifndef VOLUMETRICS +void node_bsdf_diffuse(vec4 color, float roughness, vec3 N, out Closure result) { - float m = clamp(1.0 - u, 0.0, 1.0); - float m2 = m * m; - return m2 * m2 * m; // pow(m,5) + 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; } -float GTR1(float NdotH, float a) +void node_bsdf_glossy(vec4 color, float roughness, vec3 N, float ssr_id, out Closure result) { - if (a >= 1.0) { - return M_1_PI; - } - - a = max(a, 0.001); - float a2 = a*a; - float t = 1.0 + (a2 - 1.0) * NdotH*NdotH; - return (a2 - 1.0) / (M_PI * log(a2) * t); + vec3 out_spec, ssr_spec; + 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); } -float GTR2(float NdotH, float a) +void node_bsdf_anisotropic( + vec4 color, float roughness, float anisotropy, float rotation, vec3 N, vec3 T, + out Closure result) { - float a2 = a*a; - float t = 1.0 + (a2 - 1.0) * NdotH*NdotH; - return a2 / (M_PI * t*t); + node_bsdf_diffuse(color, 0.0, N, result); } -float GTR2_aniso(float NdotH, float HdotX, float HdotY, float ax, float ay) +void node_bsdf_glass(vec4 color, float roughness, float ior, vec3 N, float ssr_id, out Closure result) { - return 1.0 / (M_PI * ax*ay * sqr(sqr(HdotX / ax) + sqr(HdotY / ay) + NdotH*NdotH)); + vec3 out_spec, out_refr, ssr_spec; + 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); } -float smithG_GGX(float NdotV, float alphaG) +void node_bsdf_toon(vec4 color, float size, float tsmooth, vec3 N, out Closure result) { - float a = alphaG*alphaG; - float b = NdotV*NdotV; - return 1.0 / (NdotV + sqrt(a + b - a * b)); + node_bsdf_diffuse(color, 0.0, N, result); } -vec3 rotate_vector(vec3 p, vec3 n, float theta) { - return ( - p * cos(theta) + cross(n, p) * - sin(theta) + n * dot(p, n) * - (1.0 - cos(theta)) - ); -} +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) +{ + 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); -/*********** NEW SHADER NODES ***************/ + transmission *= 1.0 - metallic; + subsurface *= 1.0 - metallic; -#define NUM_LIGHTS 3 + clearcoat *= 0.25; + clearcoat *= 1.0 - transmission; -/* bsdfs */ +#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 +} -void node_bsdf_diffuse(vec4 color, float roughness, vec3 N, out vec4 result) +void node_bsdf_translucent(vec4 color, vec3 N, out Closure result) { - /* 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; - - float bsdf = max(dot(N, light_position), 0.0); - L += light_diffuse * bsdf; - } - - result = vec4(L * color.rgb, 1.0); + node_bsdf_diffuse(color, 0.0, -N, result); } -void node_bsdf_glossy(vec4 color, float roughness, vec3 N, out vec4 result) +void node_bsdf_transparent(vec4 color, out Closure result) { - /* 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 H = gl_LightSource[i].halfVector.xyz; - vec3 light_diffuse = gl_LightSource[i].diffuse.rgb; - vec3 light_specular = gl_LightSource[i].specular.rgb; - - /* we mix in some diffuse so low roughness still shows up */ - float r2 = roughness * roughness; - float bsdf = 0.5 * pow(max(dot(N, H), 0.0), 1.0 / r2); - bsdf += 0.5 * max(dot(N, light_position), 0.0); - L += light_specular * bsdf; - } - - result = vec4(L * color.rgb, 1.0); + /* this isn't right */ + result = CLOSURE_DEFAULT; + result.radiance = vec3(0.0); + result.opacity = 0.0; + result.ssr_id = TRANSPARENT_CLOSURE_FLAG; } -void node_bsdf_anisotropic( - vec4 color, float roughness, float anisotropy, float rotation, vec3 N, vec3 T, - 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_bsdf_glass(vec4 color, float roughness, float ior, vec3 N, out vec4 result) -{ +void node_subsurface_scattering( + vec4 color, float scale, vec3 radius, float sharpen, float texture_blur, vec3 N, float sss_id, + out Closure result) +{ +#if 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_toon(vec4 color, float size, float tsmooth, vec3 N, out vec4 result) +void node_bsdf_refraction(vec4 color, float roughness, float ior, vec3 N, out Closure result) { - node_bsdf_diffuse(color, 0.0, N, result); + vec3 out_refr; + color.rgb *= (refractionDepth > 0.0) ? color.rgb : vec3(1.0); /* Simulate 2 absorption event. */ + eevee_closure_refraction(N, roughness, ior, out_refr); + vec3 vN = normalize(mat3(ViewMatrix) * N); + result = CLOSURE_DEFAULT; + result.ssr_normal = normal_encode(vN, viewCameraVec); + result.radiance = out_refr * color.rgb; + result.ssr_id = REFRACT_CLOSURE_FLAG; } -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) +void node_ambient_occlusion(vec4 color, float distance, vec3 normal, out vec4 result_color, out float result_ao) { - /* 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)); - - 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); - - /* fresnel normalization parameters */ - float F0 = fresnel_dielectric_0(eta); - float F0_norm = 1.0 / (1.0 - F0); - - /* directional lights */ - for (int i = 0; i < NUM_LIGHTS; i++) { - vec3 light_position_world = gl_LightSource[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; - - float NdotL = dot(N, light_position); - float NdotV = dot(N, V); - float LdotH = dot(light_position, H); - - vec3 diffuse_and_specular_bsdf = vec3(0.0); - 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. - - 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); - vec3 Csheen = mix(vec3(1.0), Ctint, sheen_tint); - - // Diffuse fresnel - go from 1 at normal incidence to .5 at grazing - // and mix in diffuse retro-reflection based on roughness - - float FL = schlick_fresnel(NdotL), FV = schlick_fresnel(NdotV); - float Fd90 = 0.5 + 2.0 * LdotH*LdotH * roughness; - float Fd = mix(1.0, Fd90, FL) * mix(1.0, Fd90, FV); - - // Based on Hanrahan-Krueger brdf approximation of isotropic bssrdf - // 1.25 scale is used to (roughly) preserve albedo - // Fss90 used to "flatten" retroreflection based on roughness - float Fss90 = LdotH*LdotH * roughness; - float Fss = mix(1.0, Fss90, FL) * mix(1.0, Fss90, FV); - 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); - float roughg = sqr(roughness * 0.5 + 0.5); - float Gs = smithG_GGX(NdotL, roughg) * smithG_GGX(NdotV, roughg); - - // sheen - vec3 Fsheen = schlick_fresnel(LdotH) * sheen * Csheen; - - vec3 diffuse_bsdf = (mix(Fd * base_color.rgb, ss * subsurface_color.rgb, subsurface) + Fsheen) * light_diffuse; - vec3 specular_bsdf = Gs * Fs * Ds * light_specular; - diffuse_and_specular_bsdf = diffuse_bsdf * (1.0 - metallic) + specular_bsdf; - } - diffuse_and_specular_bsdf *= max(NdotL, 0.0); + vec3 bent_normal; + vec4 rand = texelFetch(utilTex, ivec3(ivec2(gl_FragCoord.xy) % LUT_SIZE, 2.0), 0); + result_ao = occlusion_compute(normalize(normal), viewPosition, 1.0, rand, bent_normal); + result_color = result_ao * color; +} - float CNdotL = dot(CN, light_position); - float CNdotV = dot(CN, V); +#endif /* VOLUMETRICS */ - vec3 clearcoat_bsdf = vec3(0.0); - if (CNdotL >= 0.0 && CNdotV >= 0.0 && clearcoat > 0.0) { - float CNdotH = dot(CN, H); - //float FH = schlick_fresnel(LdotH); +/* emission */ - // clearcoat (ior = 1.5 -> F0 = 0.04) - float Dr = GTR1(CNdotH, sqr(clearcoat_roughness)); - float Fr = fresnel_dielectric_cos(LdotH, 1.5); //mix(0.04, 1.0, FH); - float Gr = smithG_GGX(CNdotL, 0.25) * smithG_GGX(CNdotV, 0.25); +void node_emission(vec4 color, float strength, vec3 vN, out Closure result) +{ +#ifndef VOLUMETRICS + color *= strength; + result = CLOSURE_DEFAULT; + result.radiance = color.rgb; + result.opacity = color.a; + result.ssr_normal = normal_encode(vN, viewCameraVec); +#else + result = Closure(vec3(0.0), vec3(0.0), color.rgb * strength, 0.0); +#endif +} - clearcoat_bsdf = clearcoat * Gr * Fr * Dr * vec3(0.25) * light_specular; - } - clearcoat_bsdf *= max(CNdotL, 0.0); +/* background */ - L += diffuse_and_specular_bsdf + clearcoat_bsdf; - } +void background_transform_to_world(vec3 viewvec, out vec3 worldvec) +{ + 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); - result = vec4(L, 1.0); + vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0); +#if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE) + worldvec = (ViewMatrixInverse * co).xyz; +#else + worldvec = (ModelViewMatrixInverse * co).xyz; +#endif } -void node_bsdf_translucent(vec4 color, vec3 N, out vec4 result) +void node_background(vec4 color, float strength, out Closure result) { - node_bsdf_diffuse(color, 0.0, N, result); +#ifndef VOLUMETRICS + color *= strength; + result = CLOSURE_DEFAULT; + result.radiance = color.rgb; + result.opacity = color.a; +#else + result = CLOSURE_DEFAULT; +#endif } -void node_bsdf_transparent(vec4 color, out vec4 result) -{ - /* this isn't right */ - result.r = color.r; - result.g = color.g; - result.b = color.b; - result.a = 0.0; -} +/* volumes */ -void node_bsdf_velvet(vec4 color, float sigma, vec3 N, out vec4 result) +void node_volume_scatter(vec4 color, float density, float anisotropy, out Closure result) { - node_bsdf_diffuse(color, 0.0, N, result); +#ifdef VOLUMETRICS + result = Closure(vec3(0.0), color.rgb * density, vec3(0.0), anisotropy); +#else + result = CLOSURE_DEFAULT; +#endif } -void node_subsurface_scattering( - vec4 color, float scale, vec3 radius, float sharpen, float texture_blur, vec3 N, - out vec4 result) +void node_volume_absorption(vec4 color, float density, out Closure result) { - node_bsdf_diffuse(color, 0.0, N, result); +#ifdef VOLUMETRICS + result = Closure((1.0 - color.rgb) * density, vec3(0.0), vec3(0.0), 0.0); +#else + result = CLOSURE_DEFAULT; +#endif } -void node_bsdf_hair(vec4 color, float offset, float roughnessu, float roughnessv, vec3 tangent, out vec4 result) +void node_blackbody(float temperature, sampler2D spectrummap, out vec4 color) { - result = color; + if(temperature >= 12000.0) { + color = vec4(0.826270103, 0.994478524, 1.56626022, 1.0); + } + else if(temperature < 965.0) { + color = vec4(4.70366907, 0.0, 0.0, 1.0); + } + else { + float t = (temperature - 965.0) / (12000.0 - 965.0); + color = vec4(texture(spectrummap, vec2(t, 0.0)).rgb, 1.0); + } } -void node_bsdf_refraction(vec4 color, float roughness, float ior, vec3 N, out vec4 result) +void node_volume_principled( + vec4 color, + float density, + float anisotropy, + vec4 absorption_color, + float emission_strength, + vec4 emission_color, + float blackbody_intensity, + vec4 blackbody_tint, + float temperature, + float density_attribute, + vec4 color_attribute, + float temperature_attribute, + sampler2D spectrummap, + out Closure result) { - node_bsdf_diffuse(color, 0.0, N, result); -} +#ifdef VOLUMETRICS + vec3 absorption_coeff = vec3(0.0); + vec3 scatter_coeff = vec3(0.0); + vec3 emission_coeff = vec3(0.0); -void node_ambient_occlusion(vec4 color, float distance, vec3 normal, out vec4 result_color, out float result_ao) -{ - result_color = color; - result_ao = 1.0; -} + /* Compute density. */ + density = max(density, 0.0); -/* emission */ + if(density > 1e-5) { + density = max(density * density_attribute, 0.0); + } -void node_emission(vec4 color, float strength, vec3 N, out vec4 result) -{ - result = color * strength; -} + if(density > 1e-5) { + /* Compute scattering and absorption coefficients. */ + vec3 scatter_color = color.rgb * color_attribute.rgb; -/* background */ + scatter_coeff = scatter_color * density; + absorption_color.rgb = sqrt(max(absorption_color.rgb, 0.0)); + absorption_coeff = max(1.0 - scatter_color, 0.0) * max(1.0 - absorption_color.rgb, 0.0) * density; + } -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); + /* Compute emission. */ + emission_strength = max(emission_strength, 0.0); - vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0); - worldvec = (gl_ModelViewMatrixInverse * co).xyz; -} + if(emission_strength > 1e-5) { + emission_coeff += emission_strength * emission_color.rgb; + } -void node_background(vec4 color, float strength, vec3 N, out vec4 result) -{ - result = color * strength; + if(blackbody_intensity > 1e-3) { + /* Add temperature from attribute. */ + float T = max(temperature * max(temperature_attribute, 0.0), 0.0); + + /* Stefan-Boltzman law. */ + float T4 = (T * T) * (T * T); + float sigma = 5.670373e-8 * 1e-6 / M_PI; + float intensity = sigma * mix(1.0, T4, blackbody_intensity); + + if(intensity > 1e-5) { + vec4 bb; + node_blackbody(T, spectrummap, bb); + emission_coeff += bb.rgb * blackbody_tint.rgb * intensity; + } + } + + result = Closure(absorption_coeff, scatter_coeff, emission_coeff, anisotropy); +#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 */ @@ -2831,7 +1372,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); @@ -2843,7 +1384,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); @@ -2873,11 +1414,67 @@ 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(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(MESH_SHADER) && defined(VOLUMETRICS) + vec3 cos = volumeObjectLocalCoord; +#else + vec3 cos = vec3(0.0); +#endif + + vec4 value = texture(tex, cos).rgba; + /* Density is premultiplied for interpolation, divide it out here. */ + if (value.a > 1e-8) + value.rgb /= value.a; + + outvec = value.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(MESH_SHADER) && defined(VOLUMETRICS) + vec3 cos = volumeObjectLocalCoord; +#else + vec3 cos = vec3(0.0); +#endif + outf = texture(tex, cos).r; + outvec = vec3(outf, outf, outf); + outcol = vec4(outf, outf, outf, 1.0); +} + +void node_attribute_volume_temperature(sampler3D tex, vec2 temperature, out vec4 outcol, out vec3 outvec, out float outf) +{ +#if defined(MESH_SHADER) && defined(VOLUMETRICS) + vec3 cos = volumeObjectLocalCoord; +#else + vec3 cos = vec3(0.0); +#endif + float flame = texture(tex, cos).r; + + outf = (flame > 0.01) ? temperature.x + flame * (temperature.y - temperature.x): 0.0; + outvec = vec3(outf, outf, outf); + outcol = vec4(outf, outf, outf, 1.0); +} + 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) @@ -2885,19 +1482,47 @@ 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) { - position = (toworld * vec4(I, 1.0)).xyz; + position = worldPosition; 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); @@ -2911,16 +1536,15 @@ 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; - shade_view(I, shade_I); + vec3 shade_I = (ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0); vec3 view_reflection = reflect(shade_I, normalize(N)); reflection = (viewinvmat * vec4(view_reflection, 0.0)).xyz; } @@ -2931,13 +1555,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; @@ -2945,13 +1574,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) @@ -3021,7 +1654,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, @@ -3057,7 +1689,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, @@ -3068,7 +1699,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, @@ -3082,10 +1712,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) @@ -3100,7 +1726,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) @@ -3116,7 +1750,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) @@ -3126,7 +1760,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; } @@ -3200,21 +1834,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; @@ -3287,7 +1921,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); @@ -3362,10 +1995,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); @@ -3375,7 +2007,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); @@ -3390,11 +2022,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) { @@ -3410,15 +2040,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 @@ -3434,9 +2057,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; @@ -3462,9 +2084,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; @@ -3490,13 +2111,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; @@ -3525,13 +2145,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; @@ -3562,14 +2181,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)); @@ -3591,19 +2209,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, @@ -3616,7 +2233,6 @@ void node_tex_musgrave(vec3 co, out vec4 color, out float fac) { -#ifdef BIT_OPERATIONS fac = svm_musgrave(int(type), dimension, lacunarity, @@ -3625,9 +2241,6 @@ void node_tex_musgrave(vec3 co, 1.0, gain, co * scale); -#else - fac = 1.0; -#endif color = vec4(fac, fac, fac, 1.0); } @@ -3639,7 +2252,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]; @@ -3704,13 +2316,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; @@ -3732,22 +2339,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 */ @@ -3767,13 +2368,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; @@ -3836,6 +2445,23 @@ void node_bevel(float radius, vec3 N, out vec3 result) result = N; } +void node_hair_info(out float is_strand, out float intercept, out float thickness, out vec3 tangent, out float random) +{ +#ifdef HAIR_SHADER + is_strand = 1.0; + intercept = hairTime; + thickness = hairThickness; + tangent = normalize(hairTangent); + random = wang_hash_noise(uint(hairStrandID)); /* TODO: could be precomputed per strand instead. */ +#else + is_strand = 0.0; + intercept = 0.0; + thickness = 0.0; + tangent = vec3(1.0); + random = 0.0; +#endif +} + void node_displacement_object(float height, float midlevel, float scale, vec3 N, mat4 obmat, out vec3 result) { N = (vec4(N, 0.0) * obmat).xyz; @@ -3872,37 +2498,91 @@ void node_vector_displacement_world(vec4 vector, float midlevel, float scale, ou /* output */ -void node_output_material(vec4 surface, vec4 volume, vec3 displacement, out vec4 result) +void node_output_material(Closure surface, Closure volume, vec3 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 + result.radiance = surface.radiance; + result.opacity = backgroundAlpha; +#else + result = volume; +#endif /* VOLUMETRICS */ } -/* ********************** matcap style render ******************** */ - -void material_preview_matcap(vec4 color, sampler2D ima, vec4 N, vec4 mask, out vec4 result) +#ifndef VOLUMETRICS +/* TODO : clean this ifdef mess */ +/* EEVEE output */ +void world_normals_get(out vec3 N) { - 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; +#ifdef HAIR_SHADER + vec3 B = normalize(cross(worldNormal, hairTangent)); + float cos_theta; + if (hairThicknessRes == 1) { + vec4 rand = texelFetch(utilTex, ivec3(ivec2(gl_FragCoord.xy) % LUT_SIZE, 2.0), 0); + /* Random cosine normal distribution on the hair surface. */ + cos_theta = rand.x * 2.0 - 1.0; + } + else { + /* Shade as a cylinder. */ + cos_theta = hairThickTime / hairThickness; } - normal = normalize(normal); + float sin_theta = sqrt(max(0.0, 1.0f - cos_theta*cos_theta));; + N = normalize(worldNormal * sin_theta + B * cos_theta); #else - normal = inpt.v.normal; - mask = vec4(1.0, 1.0, 1.0, 1.0); + N = gl_FrontFacing ? worldNormal : -worldNormal; #endif +} - tex.x = 0.5 + 0.49 * normal.x; - tex.y = 0.5 + 0.49 * normal.y; - result = texture2D(ima, tex) * mask; +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); } + +void node_shader_to_rgba(Closure cl, out vec4 outcol, out float outalpha) +{ + vec4 spec_accum = vec4(0.0); + if (ssrToggle && cl.ssr_id == outputSsrId) { + vec3 V = cameraVec; + vec3 vN = normal_decode(cl.ssr_normal, viewCameraVec); + vec3 N = transform_direction(ViewMatrixInverse, vN); + float roughness = cl.ssr_data.a; + float roughnessSquared = max(1e-3, roughness * roughness); + fallback_cubemap(N, V, worldPosition, viewPosition, roughness, roughnessSquared, spec_accum); + } + + outalpha = cl.opacity; + outcol = vec4((spec_accum.rgb * cl.ssr_data.rgb) + cl.radiance, 1.0); + +# ifdef USE_SSS +# ifdef USE_SSS_ALBEDO + outcol.rgb += cl.sss_data.rgb * cl.sss_albedo; +# else + outcol.rgb += cl.sss_data.rgb; +# endif +# endif +} + +#endif /* VOLUMETRICS */ |