1#define ATTENUATION
2//#define HQ_ATTENUATION
3
4varying vec2 texCoord;
5
6uniform sampler2D m_DiffuseData;
7uniform sampler2D m_SpecularData;
8uniform sampler2D m_NormalData;
9uniform sampler2D m_DepthData;
10
11uniform vec3 m_FrustumCorner;
12uniform vec2 m_FrustumNearFar;
13
14uniform vec4 g_LightColor;
15uniform vec4 g_LightPosition;
16uniform vec3 g_CameraPosition;
17
18uniform mat4 m_ViewProjectionMatrixInverse;
19
20#ifdef COLORRAMP
21  uniform sampler2D m_ColorRamp;
22#endif
23
24float lightComputeDiffuse(in vec3 norm, in vec3 lightdir, in vec3 viewdir){
25    #ifdef MINNAERT
26        float NdotL = max(0.0, dot(norm, lightdir));
27        float NdotV = max(0.0, dot(norm, viewdir));
28        return NdotL * pow(max(NdotL * NdotV, 0.1), -1.0) * 0.5;
29    #else
30        return max(0.0, dot(norm, lightdir));
31    #endif
32}
33
34float lightComputeSpecular(in vec3 norm, in vec3 viewdir, in vec3 lightdir, in float shiny){
35//#ifdef LOW_QUALITY
36       // Blinn-Phong
37       // Note: preferably, H should be computed in the vertex shader
38       vec3 H = (viewdir + lightdir) * vec3(0.5);
39       return pow(max(dot(H, norm), 0.0), shiny);
40/*
41    #elif defined(WARDISO)
42        // Isotropic Ward
43        vec3 halfVec = normalize(viewdir + lightdir);
44        float NdotH  = max(0.001, tangDot(norm, halfVec));
45        float NdotV  = max(0.001, tangDot(norm, viewdir));
46        float NdotL  = max(0.001, tangDot(norm, lightdir));
47        float a      = tan(acos(NdotH));
48        float p      = max(shiny/128.0, 0.001);
49        return NdotL * (1.0 / (4.0*3.14159265*p*p)) * (exp(-(a*a)/(p*p)) / (sqrt(NdotV * NdotL)));
50    #else
51       // Standard Phong
52       vec3 R = reflect(-lightdir, norm);
53       return pow(max(tangDot(R, viewdir), 0.0), shiny);
54    #endif
55*/
56}
57
58vec2 computeLighting(in vec3 wvPos, in vec3 wvNorm, in vec3 wvViewDir, in vec4 wvLightDir, in float shiny){
59   float diffuseFactor  = lightComputeDiffuse(wvNorm, wvLightDir.xyz, wvViewDir);
60   float specularFactor = lightComputeSpecular(wvNorm, wvViewDir, wvLightDir.xyz, shiny);
61   return vec2(diffuseFactor, specularFactor) * vec2(wvLightDir.w);
62}
63
64vec3 decodeNormal(in vec4 enc){
65    vec4 nn = enc * vec4(2.0,2.0,0.0,0.0) + vec4(-1.0,-1.0,1.0,-1.0);
66    float l = dot(nn.xyz, -nn.xyw);
67    nn.z = l;
68    nn.xy *= sqrt(l);
69    return nn.xyz * vec3(2.0) + vec3(0.0,0.0,-1.0);
70}
71
72vec3 getPosition(in vec2 newTexCoord){
73  //Reconstruction from depth
74  float depth = texture2D(m_DepthData, newTexCoord).r;
75  //if (depth == 1.0)
76  //  return vec3(0.0, 0.0, 2.0);
77  //depth = (2.0 * m_FrustumNearFar.x)
78  /// (m_FrustumNearFar.y + m_FrustumNearFar.x - depth * (m_FrustumNearFar.y-m_FrustumNearFar.x));
79
80  //one frustum corner method
81  //float x = mix(-m_FrustumCorner.x, m_FrustumCorner.x, newTexCoord.x);
82  //float y = mix(-m_FrustumCorner.y, m_FrustumCorner.y, newTexCoord.y);
83
84  //return depth * vec3(x, y, m_FrustumCorner.z);
85  vec4 pos;
86  pos.xy = (newTexCoord * vec2(2.0)) - vec2(1.0);
87  pos.z  = depth;
88  pos.w  = 1.0;
89  pos    = m_ViewProjectionMatrixInverse * pos;
90  //pos   /= pos.w;
91  return pos.xyz;
92}
93
94// JME3 lights in world space
95void lightComputeDir(in vec3 worldPos, in vec4 color, in vec4 position, out vec4 lightDir){
96    #ifdef DIR_LIGHT
97        lightDir.xyz = -position.xyz;
98    #else
99        lightDir.xyz = position.xyz - worldPos.xyz;
100        float dist = length(lightDir.xyz);
101        lightDir.w = clamp(1.0 - position.w * dist, 0.0, 1.0);
102        lightDir.xyz /= dist;
103    #endif
104
105/*
106    float posLight = step(0.5, color.w);
107    vec3 tempVec = position.xyz * sign(posLight - 0.5) - (worldPos * posLight);
108    #ifdef ATTENUATION
109     float dist = length(tempVec);
110     lightDir.w = clamp(1.0 - position.w * dist * posLight, 0.0, 1.0);
111     lightDir.xyz = tempVec / vec3(dist);
112     #ifdef HQ_ATTENUATION
113       lightVec = tempVec;
114     #endif
115    #else
116     lightDir = vec4(normalize(tempVec), 1.0);
117    #endif
118*/
119}
120
121void main(){
122    vec2 newTexCoord = texCoord;
123    vec4 diffuseColor = texture2D(m_DiffuseData,  newTexCoord);
124    if (diffuseColor.a == 0.0)
125        discard;
126
127    vec4 specularColor = texture2D(m_SpecularData, newTexCoord);
128    vec3 worldPosition = getPosition(newTexCoord);
129    vec3 viewDir  = normalize(g_CameraPosition - worldPosition);
130
131    vec4 normalInfo = vec4(texture2D(m_NormalData, newTexCoord).rg, 0.0, 0.0);
132    vec3 normal = decodeNormal(normalInfo);
133
134    vec4 lightDir;
135    lightComputeDir(worldPosition, g_LightColor, g_LightPosition, lightDir);
136
137    vec2 light = computeLighting(worldPosition, normal, viewDir, lightDir, specularColor.w*128.0);
138
139    #ifdef COLORRAMP
140        diffuseColor.rgb  *= texture2D(m_ColorRamp, vec2(light.x, 0.0)).rgb;
141        specularColor.rgb *= texture2D(m_ColorRamp, vec2(light.y, 0.0)).rgb;
142    #endif
143
144    gl_FragColor = vec4(light.x * diffuseColor.xyz + light.y * specularColor.xyz, 1.0);
145    gl_FragColor.xyz *= g_LightColor.xyz;
146}
147