@ -0,0 +1,161 @@ | |||||
#version 100 | |||||
precision mediump float; | |||||
varying vec3 fragPosition; | |||||
varying vec2 fragTexCoord; | |||||
varying vec4 fragColor; | |||||
varying vec3 fragNormal; | |||||
uniform sampler2D texture0; | |||||
uniform sampler2D texture1; | |||||
uniform sampler2D texture2; | |||||
uniform vec4 colAmbient; | |||||
uniform vec4 colDiffuse; | |||||
uniform vec4 colSpecular; | |||||
uniform float glossiness; | |||||
uniform int useNormal; | |||||
uniform int useSpecular; | |||||
uniform mat4 modelMatrix; | |||||
uniform vec3 viewDir; | |||||
struct Light { | |||||
int enabled; | |||||
int type; | |||||
vec3 position; | |||||
vec3 direction; | |||||
vec4 diffuse; | |||||
float intensity; | |||||
float radius; | |||||
float coneAngle; | |||||
}; | |||||
const int maxLights = 8; | |||||
uniform Light lights[maxLights]; | |||||
vec3 ComputeLightPoint(Light l, vec3 n, vec3 v, float s) | |||||
{ | |||||
/* | |||||
vec3 surfacePos = vec3(modelMatrix*vec4(fragPosition, 1.0)); | |||||
vec3 surfaceToLight = l.position - surfacePos; | |||||
// Diffuse shading | |||||
float brightness = clamp(float(dot(n, surfaceToLight)/(length(surfaceToLight)*length(n))), 0.0, 1.0); | |||||
float diff = 1.0/dot(surfaceToLight/l.radius, surfaceToLight/l.radius)*brightness*l.intensity; | |||||
// Specular shading | |||||
float spec = 0.0; | |||||
if (diff > 0.0) | |||||
{ | |||||
vec3 h = normalize(-l.direction + v); | |||||
spec = pow(dot(n, h), 3.0 + glossiness)*s; | |||||
} | |||||
return (diff*l.diffuse.rgb + spec*colSpecular.rgb); | |||||
*/ | |||||
return vec3(0.5); | |||||
} | |||||
vec3 ComputeLightDirectional(Light l, vec3 n, vec3 v, float s) | |||||
{ | |||||
/* | |||||
vec3 lightDir = normalize(-l.direction); | |||||
// Diffuse shading | |||||
float diff = clamp(float(dot(n, lightDir)), 0.0, 1.0)*l.intensity; | |||||
// Specular shading | |||||
float spec = 0.0; | |||||
if (diff > 0.0) | |||||
{ | |||||
vec3 h = normalize(lightDir + v); | |||||
spec = pow(dot(n, h), 3.0 + glossiness)*s; | |||||
} | |||||
// Combine results | |||||
return (diff*l.intensity*l.diffuse.rgb + spec*colSpecular.rgb); | |||||
*/ | |||||
return vec3(0.5); | |||||
} | |||||
vec3 ComputeLightSpot(Light l, vec3 n, vec3 v, float s) | |||||
{ | |||||
/* | |||||
vec3 surfacePos = vec3(modelMatrix*vec4(fragPosition, 1)); | |||||
vec3 lightToSurface = normalize(surfacePos - l.position); | |||||
vec3 lightDir = normalize(-l.direction); | |||||
// Diffuse shading | |||||
float diff = clamp(float(dot(n, lightDir)), 0.0, 1.0)*l.intensity; | |||||
// Spot attenuation | |||||
float attenuation = clamp(float(dot(n, lightToSurface)), 0.0, 1.0); | |||||
attenuation = dot(lightToSurface, -lightDir); | |||||
float lightToSurfaceAngle = degrees(acos(attenuation)); | |||||
if (lightToSurfaceAngle > l.coneAngle) attenuation = 0.0; | |||||
float falloff = (l.coneAngle - lightToSurfaceAngle)/l.coneAngle; | |||||
// Combine diffuse and attenuation | |||||
float diffAttenuation = diff*attenuation; | |||||
// Specular shading | |||||
float spec = 0.0; | |||||
if (diffAttenuation > 0.0) | |||||
{ | |||||
vec3 h = normalize(lightDir + v); | |||||
spec = pow(dot(n, h), 3.0 + glossiness)*s; | |||||
} | |||||
return (falloff*(diffAttenuation*l.diffuse.rgb + spec*colSpecular.rgb)); | |||||
*/ | |||||
return vec3(0.5); | |||||
} | |||||
void main() | |||||
{ | |||||
// Calculate fragment normal in screen space | |||||
// NOTE: important to multiply model matrix by fragment normal to apply model transformation (rotation and scale) | |||||
mat3 normalMatrix = mat3(modelMatrix); | |||||
vec3 normal = normalize(normalMatrix*fragNormal); | |||||
// Normalize normal and view direction vectors | |||||
vec3 n = normalize(normal); | |||||
vec3 v = normalize(viewDir); | |||||
// Calculate diffuse texture color fetching | |||||
vec4 texelColor = texture2D(texture0, fragTexCoord); | |||||
vec3 lighting = colAmbient.rgb; | |||||
// Calculate normal texture color fetching or set to maximum normal value by default | |||||
if (useNormal == 1) | |||||
{ | |||||
n *= texture2D(texture1, fragTexCoord).rgb; | |||||
n = normalize(n); | |||||
} | |||||
// Calculate specular texture color fetching or set to maximum specular value by default | |||||
float spec = 1.0; | |||||
if (useSpecular == 1) spec *= normalize(texture2D(texture2, fragTexCoord).r); | |||||
for (int i = 0; i < maxLights; i++) | |||||
{ | |||||
// Check if light is enabled | |||||
if (lights[i].enabled == 1) | |||||
{ | |||||
// Calculate lighting based on light type | |||||
if(lights[i].type == 0) lighting += ComputeLightPoint(lights[i], n, v, spec); | |||||
else if(lights[i].type == 1) lighting += ComputeLightDirectional(lights[i], n, v, spec); | |||||
else if(lights[i].type == 2) lighting += ComputeLightSpot(lights[i], n, v, spec); | |||||
// NOTE: It seems that too many ComputeLight*() operations inside for loop breaks the shader on RPI | |||||
} | |||||
} | |||||
// Calculate final fragment color | |||||
gl_FragColor = vec4(texelColor.rgb*lighting*colDiffuse.rgb, texelColor.a*colDiffuse.a); | |||||
} |
@ -0,0 +1,23 @@ | |||||
#version 100 | |||||
attribute vec3 vertexPosition; | |||||
attribute vec3 vertexNormal; | |||||
attribute vec2 vertexTexCoord; | |||||
attribute vec4 vertexColor; | |||||
varying vec3 fragPosition; | |||||
varying vec2 fragTexCoord; | |||||
varying vec4 fragColor; | |||||
varying vec3 fragNormal; | |||||
uniform mat4 mvpMatrix; | |||||
void main() | |||||
{ | |||||
fragPosition = vertexPosition; | |||||
fragTexCoord = vertexTexCoord; | |||||
fragColor = vertexColor; | |||||
fragNormal = vertexNormal; | |||||
gl_Position = mvpMatrix*vec4(vertexPosition, 1.0); | |||||
} |
@ -0,0 +1,150 @@ | |||||
#version 330 | |||||
in vec3 fragPosition; | |||||
in vec2 fragTexCoord; | |||||
in vec4 fragColor; | |||||
in vec3 fragNormal; | |||||
out vec4 finalColor; | |||||
uniform sampler2D texture0; | |||||
uniform sampler2D texture1; | |||||
uniform sampler2D texture2; | |||||
uniform vec4 colAmbient; | |||||
uniform vec4 colDiffuse; | |||||
uniform vec4 colSpecular; | |||||
uniform float glossiness; | |||||
uniform int useNormal; | |||||
uniform int useSpecular; | |||||
uniform mat4 modelMatrix; | |||||
uniform vec3 viewDir; | |||||
struct Light { | |||||
int enabled; | |||||
int type; | |||||
vec3 position; | |||||
vec3 direction; | |||||
vec4 diffuse; | |||||
float intensity; | |||||
float radius; | |||||
float coneAngle; | |||||
}; | |||||
const int maxLights = 8; | |||||
uniform Light lights[maxLights]; | |||||
vec3 ComputeLightPoint(Light l, vec3 n, vec3 v, float s) | |||||
{ | |||||
vec3 surfacePos = vec3(modelMatrix*vec4(fragPosition, 1)); | |||||
vec3 surfaceToLight = l.position - surfacePos; | |||||
// Diffuse shading | |||||
float brightness = clamp(float(dot(n, surfaceToLight)/(length(surfaceToLight)*length(n))), 0.0, 1.0); | |||||
float diff = 1.0/dot(surfaceToLight/l.radius, surfaceToLight/l.radius)*brightness*l.intensity; | |||||
// Specular shading | |||||
float spec = 0.0; | |||||
if (diff > 0.0) | |||||
{ | |||||
vec3 h = normalize(-l.direction + v); | |||||
spec = pow(dot(n, h), 3.0 + glossiness)*s; | |||||
} | |||||
return (diff*l.diffuse.rgb + spec*colSpecular.rgb); | |||||
} | |||||
vec3 ComputeLightDirectional(Light l, vec3 n, vec3 v, float s) | |||||
{ | |||||
vec3 lightDir = normalize(-l.direction); | |||||
// Diffuse shading | |||||
float diff = clamp(float(dot(n, lightDir)), 0.0, 1.0)*l.intensity; | |||||
// Specular shading | |||||
float spec = 0.0; | |||||
if (diff > 0.0) | |||||
{ | |||||
vec3 h = normalize(lightDir + v); | |||||
spec = pow(dot(n, h), 3.0 + glossiness)*s; | |||||
} | |||||
// Combine results | |||||
return (diff*l.intensity*l.diffuse.rgb + spec*colSpecular.rgb); | |||||
} | |||||
vec3 ComputeLightSpot(Light l, vec3 n, vec3 v, float s) | |||||
{ | |||||
vec3 surfacePos = vec3(modelMatrix*vec4(fragPosition, 1)); | |||||
vec3 lightToSurface = normalize(surfacePos - l.position); | |||||
vec3 lightDir = normalize(-l.direction); | |||||
// Diffuse shading | |||||
float diff = clamp(float(dot(n, lightDir)), 0.0, 1.0)*l.intensity; | |||||
// Spot attenuation | |||||
float attenuation = clamp(float(dot(n, lightToSurface)), 0.0, 1.0); | |||||
attenuation = dot(lightToSurface, -lightDir); | |||||
float lightToSurfaceAngle = degrees(acos(attenuation)); | |||||
if (lightToSurfaceAngle > l.coneAngle) attenuation = 0.0; | |||||
float falloff = (l.coneAngle - lightToSurfaceAngle)/l.coneAngle; | |||||
// Combine diffuse and attenuation | |||||
float diffAttenuation = diff*attenuation; | |||||
// Specular shading | |||||
float spec = 0.0; | |||||
if (diffAttenuation > 0.0) | |||||
{ | |||||
vec3 h = normalize(lightDir + v); | |||||
spec = pow(dot(n, h), 3.0 + glossiness)*s; | |||||
} | |||||
return (falloff*(diffAttenuation*l.diffuse.rgb + spec*colSpecular.rgb)); | |||||
} | |||||
void main() | |||||
{ | |||||
// Calculate fragment normal in screen space | |||||
// NOTE: important to multiply model matrix by fragment normal to apply model transformation (rotation and scale) | |||||
mat3 normalMatrix = mat3(modelMatrix); | |||||
vec3 normal = normalize(normalMatrix*fragNormal); | |||||
// Normalize normal and view direction vectors | |||||
vec3 n = normalize(normal); | |||||
vec3 v = normalize(viewDir); | |||||
// Calculate diffuse texture color fetching | |||||
vec4 texelColor = texture(texture0, fragTexCoord); | |||||
vec3 lighting = colAmbient.rgb; | |||||
// Calculate normal texture color fetching or set to maximum normal value by default | |||||
if (useNormal == 1) | |||||
{ | |||||
n *= texture(texture1, fragTexCoord).rgb; | |||||
n = normalize(n); | |||||
} | |||||
// Calculate specular texture color fetching or set to maximum specular value by default | |||||
float spec = 1.0; | |||||
if (useSpecular == 1) spec *= normalize(texture(texture2, fragTexCoord).r); | |||||
for (int i = 0; i < maxLights; i++) | |||||
{ | |||||
// Check if light is enabled | |||||
if (lights[i].enabled == 1) | |||||
{ | |||||
// Calculate lighting based on light type | |||||
if (lights[i].type == 0) lighting += ComputeLightPoint(lights[i], n, v, spec); | |||||
else if (lights[i].type == 1) lighting += ComputeLightDirectional(lights[i], n, v, spec); | |||||
else if (lights[i].type == 2) lighting += ComputeLightSpot(lights[i], n, v, spec); | |||||
} | |||||
} | |||||
// Calculate final fragment color | |||||
finalColor = vec4(texelColor.rgb*lighting*colDiffuse.rgb, texelColor.a*colDiffuse.a); | |||||
} |
@ -0,0 +1,23 @@ | |||||
#version 330 | |||||
in vec3 vertexPosition; | |||||
in vec3 vertexNormal; | |||||
in vec2 vertexTexCoord; | |||||
in vec4 vertexColor; | |||||
out vec3 fragPosition; | |||||
out vec2 fragTexCoord; | |||||
out vec4 fragColor; | |||||
out vec3 fragNormal; | |||||
uniform mat4 mvpMatrix; | |||||
void main() | |||||
{ | |||||
fragPosition = vertexPosition; | |||||
fragTexCoord = vertexTexCoord; | |||||
fragColor = vertexColor; | |||||
fragNormal = vertexNormal; | |||||
gl_Position = mvpMatrix*vec4(vertexPosition, 1.0); | |||||
} |