diff options
Diffstat (limited to 'source/blender/gpu/shaders/gpu_shader_material.glsl')
-rw-r--r-- | source/blender/gpu/shaders/gpu_shader_material.glsl | 87 |
1 files changed, 50 insertions, 37 deletions
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index 5c52b7fd153..3dbecc58a7e 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -2621,29 +2621,26 @@ void node_bsdf_toon(vec4 color, float size, float tsmooth, vec3 N, out vec4 resu 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_gloss, 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 vec4 result) { /* ambient light */ // TODO: set ambient light to an appropriate value - vec3 L = vec3(mix(0.1, 0.03, metallic)) * base_color.rgb; + 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 = -normalize(I); + 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 - Tangent = vec3(1.0, 0.0, 0.0); - if (N.x != 0.0 || N.y != 0.0) { - vec3 N_xz = normalize(vec3(N.x, 0.0, N.z)); - - vec3 axis = normalize(cross(vec3(0.0, 0.0, 1.0), N_xz)); - float angle = acos(dot(vec3(0.0, 0.0, 1.0), N_xz)); - - Tangent = normalize(rotate_vector(vec3(1.0, 0.0, 0.0), axis, angle)); + 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 } } @@ -2663,10 +2660,11 @@ 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 = normalize(gl_NormalMatrix * light_position_world); + 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); @@ -2711,8 +2709,9 @@ void node_bsdf_principled(vec4 base_color, float subsurface, vec3 subsurface_rad // sheen vec3 Fsheen = schlick_fresnel(LdotH) * sheen * Csheen; - diffuse_and_specular_bsdf = (M_1_PI * mix(Fd, ss, subsurface) * base_color.rgb + Fsheen) - * (1.0 - metallic) + Gs * Fs * Ds; + 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); @@ -2725,15 +2724,15 @@ void node_bsdf_principled(vec4 base_color, float subsurface, vec3 subsurface_rad //float FH = schlick_fresnel(LdotH); // clearcoat (ior = 1.5 -> F0 = 0.04) - float Dr = GTR1(CNdotH, mix(0.1, 0.001, clearcoat_gloss)); + 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); - clearcoat_bsdf = clearcoat * Gr * Fr * Dr * vec3(0.25); + clearcoat_bsdf = clearcoat * Gr * Fr * Dr * vec3(0.25) * light_specular; } clearcoat_bsdf *= max(CNdotL, 0.0); - L += light_specular * (diffuse_and_specular_bsdf + clearcoat_bsdf); + L += diffuse_and_specular_bsdf + clearcoat_bsdf; } result = vec4(L, 1.0); @@ -3032,10 +3031,10 @@ vec2 calc_brick_texture(vec3 p, float mortar_size, float mortar_smooth, float bi float tint = clamp((integer_noise((rownum << 16) + (bricknum & 0xFFFF)) + bias), 0.0, 1.0); float min_dist = min(min(x, y), min(brick_width - x, row_height - y)); - if(min_dist >= mortar_size) { + if (min_dist >= mortar_size) { return vec2(tint, 0.0); } - else if(mortar_smooth == 0.0) { + else if (mortar_smooth == 0.0) { return vec2(tint, 1.0); } else { @@ -3117,15 +3116,17 @@ void node_tex_image(vec3 co, sampler2D ima, out vec4 color, out float alpha) } void node_tex_image_box(vec3 texco, - vec3 nob, + vec3 N, sampler2D ima, float blend, out vec4 color, out float alpha) { + vec3 signed_N = N; + /* project from direction vector to barycentric coordinates in triangles */ - nob = vec3(abs(nob.x), abs(nob.y), abs(nob.z)); - nob /= (nob.x + nob.y + nob.z); + N = vec3(abs(N.x), abs(N.y), abs(N.z)); + N /= (N.x + N.y + N.z); /* basic idea is to think of this as a triangle, each corner representing * one of the 3 faces of the cube. in the corners we have single textures, @@ -3141,37 +3142,37 @@ void node_tex_image_box(vec3 texco, float limit = 0.5 * (1.0 + blend); /* first test for corners with single texture */ - if (nob.x > limit * (nob.x + nob.y) && nob.x > limit * (nob.x + nob.z)) { + if (N.x > limit * (N.x + N.y) && N.x > limit * (N.x + N.z)) { weight.x = 1.0; } - else if (nob.y > limit * (nob.x + nob.y) && nob.y > limit * (nob.y + nob.z)) { + else if (N.y > limit * (N.x + N.y) && N.y > limit * (N.y + N.z)) { weight.y = 1.0; } - else if (nob.z > limit * (nob.x + nob.z) && nob.z > limit * (nob.y + nob.z)) { + else if (N.z > limit * (N.x + N.z) && N.z > limit * (N.y + N.z)) { weight.z = 1.0; } else if (blend > 0.0) { /* in case of blending, test for mixes between two textures */ - if (nob.z < (1.0 - limit) * (nob.y + nob.x)) { - weight.x = nob.x / (nob.x + nob.y); + if (N.z < (1.0 - limit) * (N.y + N.x)) { + weight.x = N.x / (N.x + N.y); weight.x = clamp((weight.x - 0.5 * (1.0 - blend)) / blend, 0.0, 1.0); weight.y = 1.0 - weight.x; } - else if (nob.x < (1.0 - limit) * (nob.y + nob.z)) { - weight.y = nob.y / (nob.y + nob.z); + else if (N.x < (1.0 - limit) * (N.y + N.z)) { + weight.y = N.y / (N.y + N.z); weight.y = clamp((weight.y - 0.5 * (1.0 - blend)) / blend, 0.0, 1.0); weight.z = 1.0 - weight.y; } - else if (nob.y < (1.0 - limit) * (nob.x + nob.z)) { - weight.x = nob.x / (nob.x + nob.z); + else if (N.y < (1.0 - limit) * (N.x + N.z)) { + weight.x = N.x / (N.x + N.z); weight.x = clamp((weight.x - 0.5 * (1.0 - blend)) / blend, 0.0, 1.0); weight.z = 1.0 - weight.x; } else { /* last case, we have a mix between three */ - weight.x = ((2.0 - limit) * nob.x + (limit - 1.0)) / (2.0 * limit - 1.0); - weight.y = ((2.0 - limit) * nob.y + (limit - 1.0)) / (2.0 * limit - 1.0); - weight.z = ((2.0 - limit) * nob.z + (limit - 1.0)) / (2.0 * limit - 1.0); + weight.x = ((2.0 - limit) * N.x + (limit - 1.0)) / (2.0 * limit - 1.0); + weight.y = ((2.0 - limit) * N.y + (limit - 1.0)) / (2.0 * limit - 1.0); + weight.z = ((2.0 - limit) * N.z + (limit - 1.0)) / (2.0 * limit - 1.0); } } else { @@ -3180,13 +3181,25 @@ void node_tex_image_box(vec3 texco, } color = vec4(0); if (weight.x > 0.0) { - color += weight.x * texture2D(ima, texco.yz); + vec2 uv = texco.yz; + if(signed_N.x < 0.0) { + uv.x = 1.0 - uv.x; + } + color += weight.x * texture2D(ima, uv); } if (weight.y > 0.0) { - color += weight.y * texture2D(ima, texco.xz); + vec2 uv = texco.xz; + if(signed_N.y > 0.0) { + uv.x = 1.0 - uv.x; + } + color += weight.y * texture2D(ima, uv); } if (weight.z > 0.0) { - color += weight.z * texture2D(ima, texco.yx); + vec2 uv = texco.yx; + if(signed_N.z > 0.0) { + uv.x = 1.0 - uv.x; + } + color += weight.z * texture2D(ima, uv); } alpha = color.a; |