module Shaders exposing (..) import WebGL {-| This shader uses Spherical Environment Mapping (SEM). Here are some relevant links: - [very cool demo](https://www.clicktorelease.com/code/spherical-normal-mapping/#) - - -} reflectionVert = [glsl| attribute vec3 position; attribute vec3 normal; uniform mat4 mvMat; uniform mat4 camera; varying vec3 vNormal; void main() { vec4 vertex4 = mvMat * vec4(position, 1.0); vNormal = vec3(mvMat * vec4(normal, 0.0)); vec3 nm_z = normalize(vec3(vertex4)); vec3 nm_x = cross(nm_z, vec3(0.0, 1.0, 0.0)); vec3 nm_y = cross(nm_x, nm_z); vNormal = vec3(dot(vNormal, nm_x), dot(vNormal, nm_y), dot(vNormal, nm_z)); gl_Position = camera * vertex4; } |] reflectionFrag = [glsl| precision mediump float; uniform sampler2D texture; varying vec3 vNormal; void main() { vec2 texCoord = vec2(0.5 * vNormal.x + 0.5, - 0.5 * vNormal.y - 0.5); vec4 fragColor = texture2D(texture, texCoord); fragColor.a = 1.0; gl_FragColor = fragColor; } |] {-| normal mapping according to: -} normalVert = [glsl| attribute vec3 position; attribute vec3 normal; attribute vec2 texCoord; attribute vec4 tangent; varying vec2 vTexCoord; varying vec3 vLightDirection; varying vec3 vViewDirection; uniform mat4 modelViewProjectionMatrix; uniform mat4 modelMatrix; uniform vec3 lightPosition; uniform vec3 viewPosition; mat3 transpose(mat3 m) { return mat3(m[0][0], m[1][0], m[2][0], m[0][1], m[1][1], m[2][1], m[0][2], m[1][2], m[2][2]); } void main() { vec4 pos = vec4(position, 1.0 ); vec3 posWorld = (modelMatrix * pos).xyz; // Tangent, Bitangent, Normal space matrix TBN // this isn't entirely correct, it should use the normal matrix // In this special case it works out well, // since my model matrix does not contain any rotation or translation. // http://www.lighthouse3d.com/tutorials/glsl-12-tutorial/the-normal-matrix/ vec3 n = normalize((modelMatrix * vec4(normal, 0.0)).xyz); vec3 t = normalize((modelMatrix * vec4(tangent.xyz, 0.0)).xyz); vec3 b = normalize((modelMatrix * vec4((cross(normal, tangent.xyz) * tangent.w), 0.0)).xyz); mat3 tbn = transpose(mat3(t, b, n)); vLightDirection = tbn*(lightPosition - posWorld); vViewDirection = tbn*(viewPosition - posWorld); vTexCoord = texCoord; gl_Position = modelViewProjectionMatrix * pos; } |] normalFrag = [glsl| precision mediump float; uniform sampler2D textureDiff; uniform sampler2D textureNorm; varying vec2 vTexCoord; varying vec3 vLightDirection; varying vec3 vViewDirection; void main() { vec3 lightDir = normalize(vLightDirection); // Local normal, in tangent space vec3 pixelNormal = normalize(texture2D(textureNorm, vTexCoord).rgb*2.0 - 1.0); float lambert = max(dot(pixelNormal, lightDir), 0.0); // diffuse + lambert vec3 lightIntensities = vec3(1.5, 1.0, 1.0); vec3 diffuseColor = texture2D(textureDiff, vTexCoord).rgb; vec3 diffuse = lambert * diffuseColor * lightIntensities; // ambient vec3 ambient = 0.3 * diffuseColor; // specular float shininess = 32.0; vec3 viewDir = normalize(vViewDirection); vec3 reflectDir = reflect(-lightDir, pixelNormal); vec3 halfwayDir = normalize(lightDir + viewDir); float spec = pow(max(dot(pixelNormal, halfwayDir), 0.0), shininess); vec3 specular = vec3(0.2) * spec * lightIntensities; // attenuation float lightAttenuation = 0.3; float attenuation = 1.0 / (1.0 + lightAttenuation * pow(length(vLightDirection), 2.0)); vec3 final_color = ambient + (diffuse + specular) * attenuation; gl_FragColor = vec4(final_color, 1.0); } |] {-| same as the normal mapping shader, but without deforming normals. -} noNormalVert = [glsl| attribute vec3 position; attribute vec3 normal; attribute vec2 texCoord; varying vec2 vTexCoord; varying vec3 vLightDirection; varying vec3 vViewDirection; varying vec3 vNormal; uniform mat4 modelViewProjectionMatrix; uniform mat4 modelMatrix; uniform vec3 lightPosition; uniform vec3 viewPosition; void main() { vec4 pos = vec4(position, 1.0 ); vec3 posWorld = (modelMatrix * pos).xyz; vLightDirection = lightPosition - posWorld; vViewDirection = viewPosition - posWorld; vTexCoord = texCoord; // this is incorrect, it should use the normal matrix vNormal = mat3(modelMatrix) * normal; gl_Position = modelViewProjectionMatrix * pos; } |] noNormalFrag = [glsl| precision mediump float; uniform sampler2D textureDiff; varying vec2 vTexCoord; varying vec3 vLightDirection; varying vec3 vViewDirection; varying vec3 vNormal; void main() { vec3 lightDir = normalize(vLightDirection); // lambert vec3 pixelNormal = normalize(vNormal); float lambert = max(dot(pixelNormal, lightDir), 0.0); // diffuse + lambert vec3 lightIntensities = vec3(1.5, 1.0, 1.0); vec3 diffuseColor = texture2D(textureDiff, vTexCoord).rgb; vec3 diffuse = lambert * diffuseColor * lightIntensities; // ambient vec3 ambient = 0.3 * diffuseColor; // specular float shininess = 32.0; vec3 viewDir = normalize(vViewDirection); vec3 reflectDir = reflect(-lightDir, pixelNormal); vec3 halfwayDir = normalize(lightDir + viewDir); float spec = pow(max(dot(pixelNormal, halfwayDir), 0.0), shininess); vec3 specular = vec3(0.2) * spec * lightIntensities; // attenuation float lightAttenuation = 0.3; float attenuation = 1.0 / (1.0 + lightAttenuation * pow(length(vLightDirection), 2.0)); vec3 final_color = ambient + (diffuse + specular) * attenuation; gl_FragColor = vec4(final_color, 1.0); } |] {-| same as above, but without any textures. -} simpleVert = [glsl| attribute vec3 position; attribute vec3 normal; varying vec3 vLightDirection; varying vec3 vViewDirection; varying vec3 vNormal; uniform mat4 modelViewProjectionMatrix; uniform mat4 modelMatrix; uniform vec3 lightPosition; uniform vec3 viewPosition; void main() { vec4 pos = vec4(position, 1.0 ); vec3 posWorld = (modelMatrix * pos).xyz; vLightDirection = lightPosition - posWorld; vViewDirection = viewPosition - posWorld; // this is incorrect, it should use the normal matrix, like this: // vNormal = mat3(normalMatrix) * normal; // it works in this case, since the modelMatrix is the identity matrix vNormal = normal; gl_Position = modelViewProjectionMatrix * pos; } |] simpleFrag = [glsl| precision mediump float; varying vec3 vLightDirection; varying vec3 vViewDirection; varying vec3 vNormal; void main() { vec3 lightDir = normalize(vLightDirection); // lambert vec3 pixelNormal = normalize(vNormal); float lambert = max(dot(pixelNormal, lightDir), 0.0); // diffuse + lambert vec3 lightIntensities = vec3(1.5, 1.0, 1.0); vec3 diffuseColor = vec3(0.3, 0.2, 0.95); vec3 diffuse = lambert * diffuseColor * lightIntensities; // ambient vec3 ambient = 0.2 * diffuseColor; // specular float shininess = 32.0; vec3 viewDir = normalize(vViewDirection); vec3 reflectDir = reflect(-lightDir, pixelNormal); vec3 halfwayDir = normalize(lightDir + viewDir); float spec = pow(max(dot(pixelNormal, halfwayDir), 0.0), shininess); vec3 specular = vec3(0.2) * spec * lightIntensities; // attenuation float lightAttenuation = 0.3; float attenuation = 1.0 / (1.0 + lightAttenuation * pow(length(vLightDirection), 2.0)); vec3 final_color = ambient + (diffuse + specular) * attenuation; gl_FragColor = vec4(final_color, 1.0); } |]