#define ATTENUATION //#define HQ_ATTENUATION varying vec2 texCoord; uniform sampler2D m_DiffuseData; uniform sampler2D m_SpecularData; uniform sampler2D m_NormalData; uniform sampler2D m_DepthData; uniform vec3 m_FrustumCorner; uniform vec2 m_FrustumNearFar; uniform vec4 g_LightColor; uniform vec4 g_LightPosition; uniform vec3 g_CameraPosition; uniform mat4 m_ViewProjectionMatrixInverse; #ifdef COLORRAMP uniform sampler2D m_ColorRamp; #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){ //#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(dot(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 wvPos, in vec3 wvNorm, in vec3 wvViewDir, in vec4 wvLightDir, in float shiny){ float diffuseFactor = lightComputeDiffuse(wvNorm, wvLightDir.xyz, wvViewDir); float specularFactor = lightComputeSpecular(wvNorm, wvViewDir, wvLightDir.xyz, shiny); return vec2(diffuseFactor, specularFactor) * vec2(wvLightDir.w); } vec3 decodeNormal(in vec4 enc){ vec4 nn = enc * vec4(2.0,2.0,0.0,0.0) + vec4(-1.0,-1.0,1.0,-1.0); float l = dot(nn.xyz, -nn.xyw); nn.z = l; nn.xy *= sqrt(l); return nn.xyz * vec3(2.0) + vec3(0.0,0.0,-1.0); } vec3 getPosition(in vec2 newTexCoord){ //Reconstruction from depth float depth = texture2D(m_DepthData, newTexCoord).r; //if (depth == 1.0) // return vec3(0.0, 0.0, 2.0); //depth = (2.0 * m_FrustumNearFar.x) /// (m_FrustumNearFar.y + m_FrustumNearFar.x - depth * (m_FrustumNearFar.y-m_FrustumNearFar.x)); //one frustum corner method //float x = mix(-m_FrustumCorner.x, m_FrustumCorner.x, newTexCoord.x); //float y = mix(-m_FrustumCorner.y, m_FrustumCorner.y, newTexCoord.y); //return depth * vec3(x, y, m_FrustumCorner.z); vec4 pos; pos.xy = (newTexCoord * vec2(2.0)) - vec2(1.0); pos.z = depth; pos.w = 1.0; pos = m_ViewProjectionMatrixInverse * pos; //pos /= pos.w; return pos.xyz; } // JME3 lights in world space void lightComputeDir(in vec3 worldPos, in vec4 color, in vec4 position, out vec4 lightDir){ #ifdef DIR_LIGHT lightDir.xyz = -position.xyz; #else lightDir.xyz = position.xyz - worldPos.xyz; float dist = length(lightDir.xyz); lightDir.w = clamp(1.0 - position.w * dist, 0.0, 1.0); lightDir.xyz /= dist; #endif /* float posLight = step(0.5, color.w); vec3 tempVec = position.xyz * sign(posLight - 0.5) - (worldPos * posLight); #ifdef ATTENUATION float dist = length(tempVec); lightDir.w = clamp(1.0 - position.w * dist * posLight, 0.0, 1.0); lightDir.xyz = tempVec / vec3(dist); #ifdef HQ_ATTENUATION lightVec = tempVec; #endif #else lightDir = vec4(normalize(tempVec), 1.0); #endif */ } void main(){ vec2 newTexCoord = texCoord; vec4 diffuseColor = texture2D(m_DiffuseData, newTexCoord); if (diffuseColor.a == 0.0) discard; vec4 specularColor = texture2D(m_SpecularData, newTexCoord); vec3 worldPosition = getPosition(newTexCoord); vec3 viewDir = normalize(g_CameraPosition - worldPosition); vec4 normalInfo = vec4(texture2D(m_NormalData, newTexCoord).rg, 0.0, 0.0); vec3 normal = decodeNormal(normalInfo); vec4 lightDir; lightComputeDir(worldPosition, g_LightColor, g_LightPosition, lightDir); vec2 light = computeLighting(worldPosition, normal, viewDir, lightDir, specularColor.w*128.0); #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 gl_FragColor = vec4(light.x * diffuseColor.xyz + light.y * specularColor.xyz, 1.0); gl_FragColor.xyz *= g_LightColor.xyz; }