#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; | |
} |