333 lines
11 KiB
GLSL
333 lines
11 KiB
GLSL
#import "Common/ShaderLib/Parallax.glsllib"
|
|
#import "Common/ShaderLib/Optics.glsllib"
|
|
#define ATTENUATION
|
|
//#define HQ_ATTENUATION
|
|
|
|
#import "MatDefs/FragScattering.glsllib"
|
|
|
|
varying vec2 texCoord;
|
|
#ifdef SEPARATE_TEXCOORD
|
|
varying vec2 texCoord2;
|
|
#endif
|
|
|
|
varying vec3 AmbientSum;
|
|
varying vec4 DiffuseSum;
|
|
varying vec3 SpecularSum;
|
|
|
|
varying float z;
|
|
|
|
#ifndef VERTEX_LIGHTING
|
|
uniform vec4 g_LightDirection;
|
|
//varying vec3 vPosition;
|
|
varying vec3 vViewDir;
|
|
varying vec4 vLightDir;
|
|
varying vec3 lightVec;
|
|
#else
|
|
varying vec2 vertexLightValues;
|
|
#endif
|
|
|
|
#ifdef DIFFUSEMAP
|
|
uniform sampler2D m_DiffuseMap;
|
|
uniform sampler2D m_BackgroundDiffuseMap;
|
|
uniform sampler2D m_NoiseMap;
|
|
#endif
|
|
|
|
#ifdef SPECULARMAP
|
|
uniform sampler2D m_SpecularMap;
|
|
#endif
|
|
|
|
#ifdef PARALLAXMAP
|
|
uniform sampler2D m_ParallaxMap;
|
|
#endif
|
|
#if (defined(PARALLAXMAP) || (defined(NORMALMAP_PARALLAX) && defined(NORMALMAP))) && !defined(VERTEX_LIGHTING)
|
|
uniform float m_ParallaxHeight;
|
|
#endif
|
|
|
|
#ifdef LIGHTMAP
|
|
uniform sampler2D m_LightMap;
|
|
#endif
|
|
|
|
#ifdef NORMALMAP
|
|
uniform sampler2D m_NormalMap;
|
|
#else
|
|
varying vec3 vNormal;
|
|
#endif
|
|
|
|
#ifdef ALPHAMAP
|
|
uniform sampler2D m_AlphaMap;
|
|
#endif
|
|
|
|
#ifdef COLORRAMP
|
|
uniform sampler2D m_ColorRamp;
|
|
#endif
|
|
|
|
uniform float m_AlphaDiscardThreshold;
|
|
|
|
#ifndef VERTEX_LIGHTING
|
|
uniform float m_Shininess;
|
|
|
|
#ifdef HQ_ATTENUATION
|
|
uniform vec4 g_LightPosition;
|
|
#endif
|
|
|
|
#ifdef USE_REFLECTION
|
|
uniform float m_ReflectionPower;
|
|
uniform float m_ReflectionIntensity;
|
|
varying vec4 refVec;
|
|
|
|
uniform ENVMAP m_EnvMap;
|
|
#endif
|
|
|
|
float tangDot(in vec3 v1, in vec3 v2){
|
|
float d = dot(v1,v2);
|
|
#ifdef V_TANGENT
|
|
d = 1.0 - d*d;
|
|
return step(0.0, d) * sqrt(d);
|
|
#else
|
|
return d;
|
|
#endif
|
|
}
|
|
|
|
float lightComputeDiffuse(in vec3 norm, in vec3 lightdir, in vec3 viewdir){
|
|
#ifdef MINNAERT
|
|
float NdotL = max(0.0, dot(norm, lightdir));
|
|
float NdotV = max(0.0, dot(norm, viewdir));
|
|
return NdotL * pow(max(NdotL * NdotV, 0.1), -1.0) * 0.5;
|
|
#else
|
|
return max(0.0, dot(norm, lightdir));
|
|
#endif
|
|
}
|
|
|
|
float lightComputeSpecular(in vec3 norm, in vec3 viewdir, in vec3 lightdir, in float shiny){
|
|
// NOTE: check for shiny <= 1 removed since shininess is now
|
|
// 1.0 by default (uses matdefs default vals)
|
|
#ifdef LOW_QUALITY
|
|
// Blinn-Phong
|
|
// Note: preferably, H should be computed in the vertex shader
|
|
vec3 H = (viewdir + lightdir) * vec3(0.5);
|
|
return pow(max(tangDot(H, norm), 0.0), shiny);
|
|
#elif defined(WARDISO)
|
|
// Isotropic Ward
|
|
vec3 halfVec = normalize(viewdir + lightdir);
|
|
float NdotH = max(0.001, tangDot(norm, halfVec));
|
|
float NdotV = max(0.001, tangDot(norm, viewdir));
|
|
float NdotL = max(0.001, tangDot(norm, lightdir));
|
|
float a = tan(acos(NdotH));
|
|
float p = max(shiny/128.0, 0.001);
|
|
return NdotL * (1.0 / (4.0*3.14159265*p*p)) * (exp(-(a*a)/(p*p)) / (sqrt(NdotV * NdotL)));
|
|
#else
|
|
// Standard Phong
|
|
vec3 R = reflect(-lightdir, norm);
|
|
return pow(max(tangDot(R, viewdir), 0.0), shiny);
|
|
#endif
|
|
}
|
|
|
|
vec2 computeLighting(in vec3 wvNorm, in vec3 wvViewDir, in vec3 wvLightDir){
|
|
float diffuseFactor = lightComputeDiffuse(wvNorm, wvLightDir, wvViewDir);
|
|
float specularFactor = lightComputeSpecular(wvNorm, wvViewDir, wvLightDir, m_Shininess);
|
|
|
|
#ifdef HQ_ATTENUATION
|
|
float att = clamp(1.0 - g_LightPosition.w * length(lightVec), 0.0, 1.0);
|
|
#else
|
|
float att = vLightDir.w;
|
|
#endif
|
|
|
|
if (m_Shininess <= 1.0) {
|
|
specularFactor = 0.0; // should be one instruction on most cards ..
|
|
}
|
|
|
|
specularFactor *= diffuseFactor;
|
|
|
|
return vec2(diffuseFactor, specularFactor) * vec2(att);
|
|
}
|
|
#endif
|
|
|
|
vec4 getColor( in sampler2D diffuseMap, in sampler2D diffuseMap2,
|
|
in sampler2D normalMap, in vec2 tc, in float distMix,
|
|
out vec3 normal ) {
|
|
|
|
vec2 tcOffset;
|
|
tcOffset = texture2D(m_NoiseMap, tc * 0.01).xy * 6.0 - 3.0;
|
|
vec4 diffuseColor = texture2D(diffuseMap, (tc + tcOffset) * 0.75);
|
|
|
|
tcOffset = (texture2D(m_NoiseMap, tc * 0.01).xy * 6.0) - 3.0;
|
|
vec4 subColor = texture2D(diffuseMap2, ((tc + tcOffset) * 1.0) * 0.1 );
|
|
diffuseColor = mix(diffuseColor, subColor, distMix);
|
|
|
|
#ifdef NORMALMAP
|
|
vec4 normalHeight = texture2D(normalMap, tc);
|
|
normal = normalize((normalHeight.xyz * vec3(2.0) - vec3(1.0)));
|
|
#else
|
|
normal = vec3(0.0, 1.0, 0.0);
|
|
#endif
|
|
|
|
return diffuseColor;
|
|
}
|
|
|
|
|
|
void main(){
|
|
vec2 newTexCoord;
|
|
|
|
#if (defined(PARALLAXMAP) || (defined(NORMALMAP_PARALLAX) && defined(NORMALMAP))) && !defined(VERTEX_LIGHTING)
|
|
|
|
#ifdef STEEP_PARALLAX
|
|
#ifdef NORMALMAP_PARALLAX
|
|
//parallax map is stored in the alpha channel of the normal map
|
|
newTexCoord = steepParallaxOffset(m_NormalMap, vViewDir, texCoord, m_ParallaxHeight);
|
|
#else
|
|
//parallax map is a texture
|
|
newTexCoord = steepParallaxOffset(m_ParallaxMap, vViewDir, texCoord, m_ParallaxHeight);
|
|
#endif
|
|
#else
|
|
#ifdef NORMALMAP_PARALLAX
|
|
//parallax map is stored in the alpha channel of the normal map
|
|
newTexCoord = classicParallaxOffset(m_NormalMap, vViewDir, texCoord, m_ParallaxHeight);
|
|
#else
|
|
//parallax map is a texture
|
|
newTexCoord = classicParallaxOffset(m_ParallaxMap, vViewDir, texCoord, m_ParallaxHeight);
|
|
#endif
|
|
#endif
|
|
#else
|
|
newTexCoord = texCoord;
|
|
#endif
|
|
|
|
float distMix = z / 32.0;
|
|
distMix = clamp(distMix, 0.4, 1.0);
|
|
|
|
#ifdef DIFFUSEMAP
|
|
vec3 newNormal;
|
|
#ifdef NORMALMAP
|
|
vec4 diffuseColor = getColor(m_DiffuseMap, m_BackgroundDiffuseMap,
|
|
m_NormalMap, texCoord, distMix, newNormal);
|
|
#else
|
|
vec4 diffuseColor = getColor(m_DiffuseMap, m_BackgroundDiffuseMap,
|
|
m_DiffuseMap, texCoord, distMix, newNormal);
|
|
#endif
|
|
#else
|
|
vec4 diffuseColor = vec4(1.0);
|
|
vec3 newNormal = vec3(0.0, 1.0, 0.0);
|
|
#endif
|
|
|
|
float alpha = DiffuseSum.a * diffuseColor.a;
|
|
#ifdef ALPHAMAP
|
|
alpha = alpha * texture2D(m_AlphaMap, newTexCoord).r;
|
|
#endif
|
|
if(alpha < m_AlphaDiscardThreshold){
|
|
discard;
|
|
}
|
|
|
|
#ifndef VERTEX_LIGHTING
|
|
float spotFallOff = 1.0;
|
|
|
|
#if __VERSION__ >= 110
|
|
// allow use of control flow
|
|
if(g_LightDirection.w != 0.0){
|
|
#endif
|
|
|
|
vec3 L = normalize(lightVec.xyz);
|
|
vec3 spotdir = normalize(g_LightDirection.xyz);
|
|
float curAngleCos = dot(-L, spotdir);
|
|
float innerAngleCos = floor(g_LightDirection.w) * 0.001;
|
|
float outerAngleCos = fract(g_LightDirection.w);
|
|
float innerMinusOuter = innerAngleCos - outerAngleCos;
|
|
spotFallOff = (curAngleCos - outerAngleCos) / innerMinusOuter;
|
|
|
|
#if __VERSION__ >= 110
|
|
if(spotFallOff <= 0.0){
|
|
gl_FragColor.rgb = AmbientSum * diffuseColor.rgb;
|
|
gl_FragColor.a = alpha;
|
|
return;
|
|
}else{
|
|
spotFallOff = clamp(spotFallOff, 0.0, 1.0);
|
|
}
|
|
}
|
|
#else
|
|
spotFallOff = clamp(spotFallOff, step(g_LightDirection.w, 0.001), 1.0);
|
|
#endif
|
|
#endif
|
|
|
|
// ***********************
|
|
// Read from textures
|
|
// ***********************
|
|
#if defined(NORMALMAP) && !defined(VERTEX_LIGHTING)
|
|
vec3 normal = newNormal;
|
|
#elif !defined(VERTEX_LIGHTING)
|
|
vec3 normal = vNormal;
|
|
#if !defined(LOW_QUALITY) && !defined(V_TANGENT)
|
|
normal = normalize(normal);
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef SPECULARMAP
|
|
vec4 specularColor = texture2D(m_SpecularMap, newTexCoord);
|
|
#else
|
|
vec4 specularColor = vec4(1.0);
|
|
#endif
|
|
|
|
#ifdef LIGHTMAP
|
|
vec3 lightMapColor;
|
|
#ifdef SEPARATE_TEXCOORD
|
|
lightMapColor = texture2D(m_LightMap, texCoord2).rgb;
|
|
#else
|
|
lightMapColor = texture2D(m_LightMap, texCoord).rgb;
|
|
#endif
|
|
specularColor.rgb *= lightMapColor;
|
|
diffuseColor.rgb *= lightMapColor;
|
|
#endif
|
|
|
|
#ifdef VERTEX_LIGHTING
|
|
vec2 light = vertexLightValues.xy;
|
|
#ifdef COLORRAMP
|
|
light.x = texture2D(m_ColorRamp, vec2(light.x, 0.0)).r;
|
|
light.y = texture2D(m_ColorRamp, vec2(light.y, 0.0)).r;
|
|
#endif
|
|
|
|
#ifndef USE_SCATTERING
|
|
gl_FragColor.rgb = AmbientSum * diffuseColor.rgb +
|
|
DiffuseSum.rgb * diffuseColor.rgb * vec3(light.x) +
|
|
SpecularSum * specularColor.rgb * vec3(light.y);
|
|
#else
|
|
vec3 color = AmbientSum * diffuseColor.rgb +
|
|
DiffuseSum.rgb * diffuseColor.rgb * vec3(light.x) +
|
|
SpecularSum * specularColor.rgb * vec3(light.y);
|
|
gl_FragColor.rgb = calculateGroundColor(vec4(color, 1.0)).rgb;
|
|
#endif
|
|
#else
|
|
vec4 lightDir = vLightDir;
|
|
lightDir.xyz = normalize(lightDir.xyz);
|
|
vec3 viewDir = normalize(vViewDir);
|
|
|
|
vec2 light = computeLighting(normal, viewDir, lightDir.xyz) * spotFallOff;
|
|
#ifdef COLORRAMP
|
|
diffuseColor.rgb *= texture2D(m_ColorRamp, vec2(light.x, 0.0)).rgb;
|
|
specularColor.rgb *= texture2D(m_ColorRamp, vec2(light.y, 0.0)).rgb;
|
|
#endif
|
|
|
|
// Workaround, since it is not possible to modify varying variables
|
|
vec4 SpecularSum2 = vec4(SpecularSum, 1.0);
|
|
#ifdef USE_REFLECTION
|
|
vec4 refColor = Optics_GetEnvColor(m_EnvMap, refVec.xyz);
|
|
|
|
// Interpolate light specularity toward reflection color
|
|
// Multiply result by specular map
|
|
specularColor = mix(SpecularSum2 * light.y, refColor, refVec.w) * specularColor;
|
|
|
|
SpecularSum2 = vec4(1.0);
|
|
light.y = 1.0;
|
|
#endif
|
|
|
|
#ifndef USE_SCATTERING
|
|
gl_FragColor.rgb = AmbientSum * diffuseColor.rgb +
|
|
DiffuseSum.rgb * diffuseColor.rgb * vec3(light.x) +
|
|
SpecularSum * specularColor.rgb * vec3(light.y);
|
|
#else
|
|
vec3 color = AmbientSum * diffuseColor.rgb +
|
|
DiffuseSum.rgb * diffuseColor.rgb * vec3(light.x) +
|
|
SpecularSum * specularColor.rgb * vec3(light.y);
|
|
gl_FragColor.rgb = calculateGroundColor(vec4(color, 1.0)).rgb;
|
|
#endif
|
|
|
|
#endif
|
|
gl_FragColor.a = alpha;
|
|
}
|