Index: binaries/data/mods/public/art/materials/basic_trans_ao.xml =================================================================== --- binaries/data/mods/public/art/materials/basic_trans_ao.xml +++ binaries/data/mods/public/art/materials/basic_trans_ao.xml @@ -7,5 +7,5 @@ - + Index: binaries/data/mods/public/art/materials/basic_trans_ao_parallax_spec.xml =================================================================== --- binaries/data/mods/public/art/materials/basic_trans_ao_parallax_spec.xml +++ binaries/data/mods/public/art/materials/basic_trans_ao_parallax_spec.xml @@ -10,5 +10,5 @@ - + Index: binaries/data/mods/public/art/materials/basic_trans_ao_spec.xml =================================================================== --- binaries/data/mods/public/art/materials/basic_trans_ao_spec.xml +++ binaries/data/mods/public/art/materials/basic_trans_ao_spec.xml @@ -7,5 +7,5 @@ - + Index: binaries/data/mods/public/art/materials/basic_trans_parallax_spec.xml =================================================================== --- binaries/data/mods/public/art/materials/basic_trans_parallax_spec.xml +++ binaries/data/mods/public/art/materials/basic_trans_parallax_spec.xml @@ -9,5 +9,5 @@ - + Index: binaries/data/mods/public/art/materials/basic_trans_spec.xml =================================================================== --- binaries/data/mods/public/art/materials/basic_trans_spec.xml +++ binaries/data/mods/public/art/materials/basic_trans_spec.xml @@ -7,5 +7,5 @@ - + Index: binaries/data/mods/public/art/materials/no_trans_ao.xml =================================================================== --- binaries/data/mods/public/art/materials/no_trans_ao.xml +++ binaries/data/mods/public/art/materials/no_trans_ao.xml @@ -4,5 +4,5 @@ - + Index: binaries/data/mods/public/art/materials/no_trans_ao_parallax_spec.xml =================================================================== --- binaries/data/mods/public/art/materials/no_trans_ao_parallax_spec.xml +++ binaries/data/mods/public/art/materials/no_trans_ao_parallax_spec.xml @@ -7,5 +7,5 @@ - + Index: binaries/data/mods/public/art/materials/no_trans_ao_spec.xml =================================================================== --- binaries/data/mods/public/art/materials/no_trans_ao_spec.xml +++ binaries/data/mods/public/art/materials/no_trans_ao_spec.xml @@ -5,5 +5,5 @@ - + Index: binaries/data/mods/public/art/materials/player_trans_ao.xml =================================================================== --- binaries/data/mods/public/art/materials/player_trans_ao.xml +++ binaries/data/mods/public/art/materials/player_trans_ao.xml @@ -5,5 +5,5 @@ - + Index: binaries/data/mods/public/art/materials/player_trans_ao_parallax.xml =================================================================== --- binaries/data/mods/public/art/materials/player_trans_ao_parallax.xml +++ binaries/data/mods/public/art/materials/player_trans_ao_parallax.xml @@ -7,5 +7,5 @@ - + Index: binaries/data/mods/public/art/materials/player_trans_ao_parallax_spec.xml =================================================================== --- binaries/data/mods/public/art/materials/player_trans_ao_parallax_spec.xml +++ binaries/data/mods/public/art/materials/player_trans_ao_parallax_spec.xml @@ -8,5 +8,5 @@ - + Index: binaries/data/mods/public/art/materials/player_trans_ao_spec.xml =================================================================== --- binaries/data/mods/public/art/materials/player_trans_ao_spec.xml +++ binaries/data/mods/public/art/materials/player_trans_ao_spec.xml @@ -7,5 +7,5 @@ - + Index: binaries/data/mods/public/art/materials/player_trans_parallax.xml =================================================================== --- binaries/data/mods/public/art/materials/player_trans_parallax.xml +++ binaries/data/mods/public/art/materials/player_trans_parallax.xml @@ -5,5 +5,5 @@ - + Index: binaries/data/mods/public/art/materials/player_trans_parallax_spec.xml =================================================================== --- binaries/data/mods/public/art/materials/player_trans_parallax_spec.xml +++ binaries/data/mods/public/art/materials/player_trans_parallax_spec.xml @@ -7,5 +7,5 @@ - + Index: binaries/data/mods/public/art/materials/player_trans_spec.xml =================================================================== --- binaries/data/mods/public/art/materials/player_trans_spec.xml +++ binaries/data/mods/public/art/materials/player_trans_spec.xml @@ -5,5 +5,5 @@ - + Index: binaries/data/mods/public/art/materials/rock_norm_spec.xml =================================================================== --- binaries/data/mods/public/art/materials/rock_norm_spec.xml +++ binaries/data/mods/public/art/materials/rock_norm_spec.xml @@ -8,5 +8,5 @@ - + Index: binaries/data/mods/public/art/materials/rock_norm_spec_ao.xml =================================================================== --- binaries/data/mods/public/art/materials/rock_norm_spec_ao.xml +++ binaries/data/mods/public/art/materials/rock_norm_spec_ao.xml @@ -8,5 +8,5 @@ - + Index: binaries/data/mods/public/shaders/glsl/model_common.fs =================================================================== --- binaries/data/mods/public/shaders/glsl/model_common.fs +++ binaries/data/mods/public/shaders/glsl/model_common.fs @@ -25,36 +25,144 @@ varying vec4 v_lighting; varying vec2 v_tex; -#if (USE_INSTANCING || USE_GPU_SKINNING) && USE_AO +#if USE_AO varying vec2 v_tex2; #endif #if USE_SPECULAR uniform float specularPower; - uniform vec3 specularColor; + uniform vec3 specularColor; // Will be zeroed; only tex accepted. #endif #if USE_NORMAL_MAP || USE_SPECULAR_MAP || USE_PARALLAX || USE_AO uniform vec4 effectSettings; #endif -#if USE_SPECULAR || USE_NORMAL_MAP || USE_SPECULAR_MAP || USE_PARALLAX - varying vec4 v_normal; - #if (USE_INSTANCING || USE_GPU_SKINNING) && (USE_NORMAL_MAP || USE_PARALLAX) - varying vec4 v_tangent; - //varying vec3 v_bitangent; - #endif - #if USE_SPECULAR || USE_SPECULAR_MAP - varying vec3 v_half; - #endif - #if (USE_INSTANCING || USE_GPU_SKINNING) && USE_PARALLAX - varying vec3 v_eyeVec; - #endif -#endif +varying vec4 v_normal; +varying vec3 v_eyeVec; +varying vec3 v_half; +varying vec4 v_tangent; +varying vec3 v_bitangent; + +float metal_detect_hack( vec3 diffuse, vec3 specular ) +{ + float result = dot(diffuse,diffuse); + result *= clamp(1.0-100.0*(diffuse.g-diffuse.r),0.0,1.0); + result *= clamp(1.0-100.0*(diffuse.b-diffuse.g),0.0,1.0); + result *= max(max(specular.r,specular.g),specular.b); + result -= (diffuse.b*0.475); + result = smoothstep(0.10,0.15,result); + return result; +} + +float skin_detect_hack( vec3 diff ) +{ + float r = diff.r; + float g = diff.g; + float b = diff.b; + float skin = clamp((1.0-abs(r-2.0*b))*(1.0-abs(r+b-2.0*g))*(1.0-abs(r+g+b-2.2))+0.5,0.0,1.0); + skin = skin * skin + 0.05; + skin = skin * skin + 0.05; + skin = skin * skin + 0.05; + return skin * skin; +} + +vec3 anisotropic_ambient_hack( vec3 ambientcolor, vec3 normal ) +{ + float up = normal.y; + vec3 up_bias = vec3(up,up,up); + up_bias += vec3(4.5,3.0,1.9); + up_bias *= vec3(0.2,0.3,0.5); + return ambientcolor * up_bias; +} + +float vector_hits_the_ground( vec3 vector, float specpwr ) +{ + float blur = 1.0/sqrt(specpwr); + return smoothstep( -blur, +blur, -vector.y ); +} + +float reflection_unobstructed( vec3 viewvec, vec3 normvec, float AO ) +{ + float cos_halfangle = 1.0 - AO; + float cos_fullangle = cos_halfangle*cos_halfangle; // Approx 4 small angles; works well. + float cos_view = max( 0.0, dot(viewvec, normvec) ); + return smoothstep(cos_fullangle, cos_halfangle, cos_view ); +} + +vec3 incident_specular_light +( + vec3 normal, + vec3 groundColor, + vec3 diffuse_col, + vec3 ao, + vec3 ambient, + float matspecpwr, + float refl_ground +) +{ + vec3 eyevec = normalize(v_eyeVec); + vec3 refl_view = -reflect( eyevec, normal ); + vec3 hafvec = normalize(v_half); + float spec_pwr = max(1.0, matspecpwr); + float unblocked_specular = reflection_unobstructed(eyevec, normal, ao.r); + float point_is_in_shadow = 1.0-getShadow(); + float refl_view_dot_sun = dot(refl_view, sunDir); + float blocker_in_sun = 0.5 + (refl_view_dot_sun * 0.5); // Just a likelihood... + blocker_in_sun = blocker_in_sun * (1.0-pow( max(0.0,refl_view_dot_sun),spec_pwr)); // We are shadowing blocker! + float Phong_coefficient = pow( max(0.0, dot(normal, hafvec)), spec_pwr ); + float brightness_adj = 0.5 / ( 1.0 - pow(0.5, (1.0/spec_pwr)) ); // Sharper reflections do look brighter. + vec3 light_on_blocker = mix( ambient*ao*ao, sunColor, blocker_in_sun*blocker_in_sun ); + vec3 spec_blocker_color = diffuse_col * light_on_blocker; // Assuming blocker's same material as this. + vec3 spec_from_sun = mix( sunColor * brightness_adj, spec_blocker_color, 0.0*point_is_in_shadow ); + vec3 spec_from_env = mix( spec_blocker_color, ambient, unblocked_specular ); + spec_from_env = mix( spec_from_env, ambient * groundColor, refl_ground ); + return mix( spec_from_env, spec_from_sun, Phong_coefficient); +} + +vec3 SchlickApproximateReflectionCoefficient( float is_metal, float rayDotNormal, float From_IOR, float To_IOR ) +{ + float R0 = (To_IOR - From_IOR) / (From_IOR + To_IOR); + float angle_part = pow( 0.9*(1.0-rayDotNormal), 5.0 ); + R0 = R0 * R0; + float RC = R0 + (1.0 - R0) * angle_part; + RC = RC * (1.0 - is_metal); + return vec3(RC, RC, RC); // Returns Fresnel refl coeff as gray-scale color. +} + +vec3 specularly_reflected_light( vec3 mspeccol, vec3 fresnelcolor, float is_metal, vec3 incident_light ) +{ + vec3 final_specular_color = mix(fresnelcolor, mspeccol, is_metal); + return final_specular_color * incident_light; +} + +vec3 incident_diffuse_light +( + vec3 groundColor, + vec3 fresnelcolor, + vec3 ao, + vec3 ambientcolor, + float normal_hits_ground, + float ray_dot_normal +) +{ + vec3 FresnelRefractFactor = vec3(1.0) - fresnelcolor; + FresnelRefractFactor = FresnelRefractFactor*FresnelRefractFactor; // In and out. + vec3 incident_ambient = ao * mix( ambientcolor, groundColor, normal_hits_ground ); + vec3 incident_direct = vec3(ray_dot_normal*getShadow()) * sunColor * FresnelRefractFactor; + return incident_ambient + incident_direct; +} + +vec3 diffusely_reflected_light( vec3 diffuse, vec3 incident_diff_light ) +{ + return diffuse * incident_diff_light; +} void main() { vec2 coord = v_tex; + float up; + vec3 up_bias; #if (USE_INSTANCING || USE_GPU_SKINNING) && (USE_PARALLAX || USE_NORMAL_MAP) vec3 bitangent = vec3(v_normal.w, v_tangent.w, v_lighting.w); @@ -74,28 +182,32 @@ int iter = int(min(20.0, 25.0 - dist/10.0)); - if (iter > 0) - { - float s = 1.0/float(iter); - float t = s; - move = vec2(-eyeDir.x, eyeDir.y) * scale / (eyeDir.z * float(iter)); - vec2 nil = vec2(0.0); - - for (int i = 0; i < iter; ++i) { - height -= t; - t = (h < height) ? s : 0.0; - vec2 temp = (h < height) ? move : nil; - coord += temp; - h = texture2D(normTex, coord).a; - } - - // Move back to where we collided with the surface. - // This assumes the surface is linear between the sample point before we - // intersect the surface and after we intersect the surface - float hp = texture2D(normTex, coord - move).a; - coord -= move * ((h - height) / (s + h - hp)); - } + if (iter > 0) + { + float s = 1.0/float(iter); + float t = s; + move = vec2(-eyeDir.x, eyeDir.y) * scale / (eyeDir.z * float(iter)); + vec2 nil = vec2(0.0); + + for (int i = 0; i < iter; ++i) + { + height -= t; + t = (h < height) ? s : 0.0; + vec2 temp = (h < height) ? move : nil; + coord += temp; + h = texture2D(normTex, coord).a; + } + + // Move back to where we collided with the surface. + // This assumes the surface is linear between the sample point before we + // intersect the surface and after we intersect the surface. + float hp = texture2D(normTex, coord - move).a; + coord -= move * ((h - height) / (s + h - hp)); + } } + + #else + vec3 eyeDir = normalize(v_eyeVec); #endif vec4 tex = texture2D(baseTex, coord); @@ -123,9 +235,7 @@ #endif #endif - #if USE_SPECULAR || USE_SPECULAR_MAP || USE_NORMAL_MAP - vec3 normal = v_normal.xyz; - #endif + vec3 normal = normalize(v_normal.xyz); #if (USE_INSTANCING || USE_GPU_SKINNING) && USE_NORMAL_MAP vec3 ntex = texture2D(normTex, coord).rgb * 2.0 - 1.0; @@ -147,32 +257,66 @@ specular.a = s.a; specPow = effectSettings.y; #else - specCol = specularColor; + specCol = vec3(0.0,0.0,0.0); // If not from texture; zero it. specPow = specularPower; #endif - specular.rgb = sunColor * specCol * pow(max(0.0, dot(normalize(normal), v_half)), specPow); + #else + vec3 specCol = vec3(0.0,0.0,0.0); + float specPow = 4.20; #endif + specPow = clamp(16.0*(specCol.r+specCol.g+specCol.b),1.0,100.0); + up = normal.y; - vec3 color = (texdiffuse * sundiffuse + specular.rgb) * getShadow(); - vec3 ambColor = texdiffuse * ambient; - - #if (USE_INSTANCING || USE_GPU_SKINNING) && USE_AO - vec3 ao = texture2D(aoTex, v_tex2).rrr; - ao = mix(vec3(1.0), ao * 2.0, effectSettings.w); - ambColor *= ao; + //inject common sense: + vec3 ZERO = vec3(0.0); + float maxdiffuse = max(texdiffuse.r,max(texdiffuse.g,texdiffuse.b)); + float speclimit = 1.0-maxdiffuse; + vec3 speclimitcol = vec3(speclimit,speclimit,speclimit); + specCol = clamp(specCol,ZERO,speclimitcol); // Better metal detect with this on. + + //metal detection hack: + float is_metal = metal_detect_hack(texdiffuse, specCol); + //metal representation hack: + vec3 metal_specCol = sqrt(texdiffuse); + vec3 metal_diffCol = texdiffuse*texdiffuse*texdiffuse; + specCol = mix(vec3(0.0),metal_specCol,is_metal); + texdiffuse = mix(texdiffuse,metal_diffCol,is_metal); + //end of metal representation hack. + + float rayDotNormal = max( 0.0, dot( -sunDir, normal ) ); + + //skin detection hack + float is_skin = skin_detect_hack( texdiffuse ); + float IndexOfRefraction = mix(1.0,1.5,is_skin); + specPow = mix( specPow, 17.0, is_skin ); + + #if USE_AO + float AO = texture2D(aoTex, v_tex2).r; + vec3 ao_color = mix(vec3(0.5), vec3(AO), effectSettings.w); + #else + float AO = 0.5; + vec3 ao_color = vec3(0.5); #endif - color += ambColor; + // Main algorithm begins. + vec3 ground_col = vec3( 0.2, 0.3, 0.2 ); + vec3 eyeVec = normalize( v_eyeVec ); + float eyeDotNormal = max( 0.0, dot( eyeVec, normal ) ); + vec3 aniso_amb = anisotropic_ambient_hack( ambient, normal ); + float normal_hits_the_ground = vector_hits_the_ground(normal, specPow); + vec3 refl_view = -reflect( eyeVec, normal ); + float reflecting_ground = vector_hits_the_ground(refl_view, specPow); + vec3 incident_spec = incident_specular_light(normal,ground_col,texdiffuse,ao_color,aniso_amb,specPow,reflecting_ground ); + vec3 fresnel_refl_color = SchlickApproximateReflectionCoefficient( is_metal, eyeDotNormal, 1.0, IndexOfRefraction ); + vec3 incident_diff = incident_diffuse_light(ground_col,fresnel_refl_color,ao_color,aniso_amb,normal_hits_the_ground,rayDotNormal); + vec3 color = specularly_reflected_light( specCol, fresnel_refl_color, is_metal, incident_spec ); + color = color + diffusely_reflected_light( texdiffuse, incident_diff ); + // Main algorithm ends. #if USE_SPECULAR_MAP && USE_SELF_LIGHT color = mix(texdiffuse, color, specular.a); #endif - color = applyFog(color); - color *= getLOS(); - - color *= shadingColor; - - gl_FragColor.rgb = color; + gl_FragColor.rgb = mix(color,sqrt(color),1.0/3.0); // Re-gamma implicit de-gamma. } Index: binaries/data/mods/public/shaders/glsl/model_common.vs =================================================================== --- binaries/data/mods/public/shaders/glsl/model_common.vs +++ binaries/data/mods/public/shaders/glsl/model_common.vs @@ -22,22 +22,18 @@ varying vec4 v_lighting; varying vec2 v_tex; -#if (USE_INSTANCING || USE_GPU_SKINNING) && USE_AO +#if USE_AO varying vec2 v_tex2; #endif +varying vec4 v_normal; +varying vec3 v_eyeVec; +varying vec3 v_half; #if USE_SPECULAR || USE_NORMAL_MAP || USE_SPECULAR_MAP || USE_PARALLAX - varying vec4 v_normal; #if (USE_INSTANCING || USE_GPU_SKINNING) && (USE_NORMAL_MAP || USE_PARALLAX) varying vec4 v_tangent; //varying vec3 v_bitangent; #endif - #if USE_SPECULAR || USE_SPECULAR_MAP - varying vec3 v_half; - #endif - #if (USE_INSTANCING || USE_GPU_SKINNING) && USE_PARALLAX - varying vec3 v_eyeVec; - #endif #endif attribute vec3 a_vertex; @@ -84,17 +80,17 @@ vec3 tangent = normalMatrix * a_tangent.xyz; #endif #else - #if (USE_INSTANCING) - vec4 position = instancingTransform * vec4(a_vertex, 1.0); - mat3 normalMatrix = mat3(instancingTransform[0].xyz, instancingTransform[1].xyz, instancingTransform[2].xyz); - vec3 normal = normalMatrix * a_normal; - #if (USE_NORMAL_MAP || USE_PARALLAX) - vec3 tangent = normalMatrix * a_tangent.xyz; + #if (USE_INSTANCING) + vec4 position = instancingTransform * vec4(a_vertex, 1.0); + mat3 normalMatrix = mat3(instancingTransform[0].xyz, instancingTransform[1].xyz, instancingTransform[2].xyz); + vec3 normal = normalMatrix * a_normal; + #if (USE_NORMAL_MAP || USE_PARALLAX) + vec3 tangent = normalMatrix * a_tangent.xyz; + #endif + #else + vec4 position = vec4(a_vertex, 1.0); + vec3 normal = a_normal; #endif - #else - vec4 position = vec4(a_vertex, 1.0); - vec3 normal = a_normal; - #endif #endif @@ -134,9 +130,13 @@ gl_Position = transform * position; - #if USE_SPECULAR || USE_NORMAL_MAP || USE_SPECULAR_MAP || USE_PARALLAX - v_normal.xyz = normal; + vec3 eyeVec = cameraPos.xyz - position.xyz; + vec3 sunVec = -sunDir; + v_normal.xyz = normal; + v_eyeVec = eyeVec; + v_half = normalize(normalize(sunVec) + normalize(eyeVec)); + #if USE_SPECULAR || USE_NORMAL_MAP || USE_SPECULAR_MAP || USE_PARALLAX #if (USE_INSTANCING || USE_GPU_SKINNING) && (USE_NORMAL_MAP || USE_PARALLAX) v_tangent.xyz = tangent; vec3 bitangent = cross(v_normal.xyz, v_tangent.xyz) * a_tangent.w; @@ -144,24 +144,13 @@ v_tangent.w = bitangent.y; v_lighting.w = bitangent.z; #endif - - #if USE_SPECULAR || USE_SPECULAR_MAP || USE_PARALLAX - vec3 eyeVec = cameraPos.xyz - position.xyz; - #if USE_SPECULAR || USE_SPECULAR_MAP - vec3 sunVec = -sunDir; - v_half = normalize(sunVec + normalize(eyeVec)); - #endif - #if (USE_INSTANCING || USE_GPU_SKINNING) && USE_PARALLAX - v_eyeVec = eyeVec; - #endif - #endif #endif v_lighting.xyz = max(0.0, dot(normal, -sunDir)) * sunColor; v_tex = a_uv0; - #if (USE_INSTANCING || USE_GPU_SKINNING) && USE_AO + #if USE_AO v_tex2 = a_uv1; #endif Index: binaries/data/mods/public/shaders/glsl/terrain_common.fs =================================================================== --- binaries/data/mods/public/shaders/glsl/terrain_common.fs +++ binaries/data/mods/public/shaders/glsl/terrain_common.fs @@ -42,9 +42,6 @@ varying vec4 v_tangent; varying vec3 v_bitangent; #endif - #if USE_SPECULAR || USE_SPECULAR_MAP - varying vec3 v_half; - #endif #endif #if USE_TRIPLANAR @@ -98,8 +95,26 @@ } #endif +float get_needed_white_dimming_factor(vec3 rgbColor) +{ + float r = rgbColor[0]; + float g = rgbColor[1]; + float b = rgbColor[2]; + float colorMax = max(max(r,g), b); + float colorMin = min(min(r,g), b); + float saturation = 0.0; + if (colorMax != 0.0) + saturation = (colorMax - colorMin ) / colorMax; + float grayness = 1.0-saturation; + float mul_factor; + mul_factor = (1.0 - (grayness * colorMax)); + return mul_factor * mul_factor * mul_factor; +} + void main() { + vec3 up_bias; + float up; #if BLEND // Use alpha from blend texture gl_FragColor.a = 1.0 - texture2D(blendTex, v_blend).a; @@ -129,6 +144,7 @@ #endif vec3 texdiffuse = tex.rgb; + texdiffuse = mix( texdiffuse*texdiffuse*vec3(0.75), texdiffuse, get_needed_white_dimming_factor(texdiffuse)); #if USE_SPECULAR || USE_SPECULAR_MAP || USE_NORMAL_MAP vec3 normal = v_normal; @@ -149,31 +165,17 @@ vec3 sundiffuse = v_lighting; #endif - vec4 specular = vec4(0.0); - #if USE_SPECULAR || USE_SPECULAR_MAP - vec3 specCol; - float specPow; - #if USE_SPECULAR_MAP - #if USE_TRIPLANAR - vec4 s = triplanar(specTex, v_tex); - #else - vec4 s = texture2D(specTex, v_tex); - #endif - specCol = s.rgb; - specular.a = s.a; - specPow = effectSettings.y; - #else - specCol = specularColor; - specPow = specularPower; - #endif - specular.rgb = sunColor * specCol * pow(max(0.0, dot(normalize(normal), v_half)), specPow); - #endif - - vec3 color = (texdiffuse * sundiffuse + specular.rgb) * getShadowOnLandscape() + texdiffuse * ambient; - #if USE_SPECULAR_MAP && USE_SELF_LIGHT - color = mix(texdiffuse, color, specular.a); + #if USE_SPECULAR || USE_SPECULAR_MAP || USE_NORMAL_MAP + up = normal.y; + #else + up = v_normal.y; #endif + up_bias = vec3(up,up,up); + up_bias += vec3(4.5,3.0,1.9); + up_bias *= vec3(0.2,0.3,0.5); + + vec3 color = (texdiffuse * sundiffuse) * getShadowOnLandscape() + texdiffuse * ambient * up_bias; color = applyFog(color);