| @ -0,0 +1,86 @@ | |||
| #version 100 | |||
| precision mediump float; | |||
| // This shader is based on the basic lighting shader | |||
| // This only supports one light, which is directional, and it (of course) supports shadows | |||
| // Input vertex attributes (from vertex shader) | |||
| varying vec3 fragPosition; | |||
| varying vec2 fragTexCoord; | |||
| //varying in vec4 fragColor; | |||
| varying vec3 fragNormal; | |||
| // Input uniform values | |||
| uniform sampler2D texture0; | |||
| uniform vec4 colDiffuse; | |||
| // Input lighting values | |||
| uniform vec3 lightDir; | |||
| uniform vec4 lightColor; | |||
| uniform vec4 ambient; | |||
| uniform vec3 viewPos; | |||
| // Input shadowmapping values | |||
| uniform mat4 lightVP; // Light source view-projection matrix | |||
| uniform sampler2D shadowMap; | |||
| uniform int shadowMapResolution; | |||
| void main() | |||
| { | |||
| // Texel color fetching from texture sampler | |||
| vec4 texelColor = texture2D(texture0, fragTexCoord); | |||
| vec3 lightDot = vec3(0.0); | |||
| vec3 normal = normalize(fragNormal); | |||
| vec3 viewD = normalize(viewPos - fragPosition); | |||
| vec3 specular = vec3(0.0); | |||
| vec3 l = -lightDir; | |||
| float NdotL = max(dot(normal, l), 0.0); | |||
| lightDot += lightColor.rgb*NdotL; | |||
| float specCo = 0.0; | |||
| if (NdotL > 0.0) specCo = pow(max(0.0, dot(viewD, reflect(-(l), normal))), 16.0); // 16 refers to shine | |||
| specular += specCo; | |||
| vec4 finalColor = (texelColor*((colDiffuse + vec4(specular, 1.0))*vec4(lightDot, 1.0))); | |||
| // Shadow calculations | |||
| vec4 fragPosLightSpace = lightVP*vec4(fragPosition, 1); | |||
| fragPosLightSpace.xyz /= fragPosLightSpace.w; // Perform the perspective division | |||
| fragPosLightSpace.xyz = (fragPosLightSpace.xyz + 1.0)/2.0; // Transform from [-1, 1] range to [0, 1] range | |||
| vec2 sampleCoords = fragPosLightSpace.xy; | |||
| float curDepth = fragPosLightSpace.z; | |||
| // Slope-scale depth bias: depth biasing reduces "shadow acne" artifacts, where dark stripes appear all over the scene | |||
| // The solution is adding a small bias to the depth | |||
| // In this case, the bias is proportional to the slope of the surface, relative to the light | |||
| float bias = max(0.0008*(1.0 - dot(normal, l)), 0.00008); | |||
| int shadowCounter = 0; | |||
| const int numSamples = 9; | |||
| // PCF (percentage-closer filtering) algorithm: | |||
| // Instead of testing if just one point is closer to the current point, | |||
| // we test the surrounding points as well | |||
| // This blurs shadow edges, hiding aliasing artifacts | |||
| vec2 texelSize = vec2(1.0/float(shadowMapResolution)); | |||
| for (int x = -1; x <= 1; x++) | |||
| { | |||
| for (int y = -1; y <= 1; y++) | |||
| { | |||
| float sampleDepth = texture2D(shadowMap, sampleCoords + texelSize*vec2(x, y)).r; | |||
| if (curDepth - bias > sampleDepth) shadowCounter++; | |||
| } | |||
| } | |||
| finalColor = mix(finalColor, vec4(0, 0, 0, 1), float(shadowCounter)/float(numSamples)); | |||
| // Add ambient lighting whether in shadow or not | |||
| finalColor += texelColor*(ambient/10.0)*colDiffuse; | |||
| // Gamma correction | |||
| finalColor = pow(finalColor, vec4(1.0/2.2)); | |||
| gl_FragColor = finalColor; | |||
| } | |||
| @ -0,0 +1,32 @@ | |||
| #version 100 | |||
| // Input vertex attributes | |||
| attribute vec3 vertexPosition; | |||
| attribute vec2 vertexTexCoord; | |||
| attribute vec3 vertexNormal; | |||
| attribute vec4 vertexColor; | |||
| // Input uniform values | |||
| uniform mat4 mvp; | |||
| uniform mat4 matModel; | |||
| uniform mat4 matNormal; | |||
| // Output vertex attributes (to fragment shader) | |||
| varying vec3 fragPosition; | |||
| varying vec2 fragTexCoord; | |||
| varying vec4 fragColor; | |||
| varying vec3 fragNormal; | |||
| // NOTE: Add your custom variables here | |||
| void main() | |||
| { | |||
| // Send vertex attributes to fragment shader | |||
| fragPosition = vec3(matModel*vec4(vertexPosition, 1.0)); | |||
| fragTexCoord = vertexTexCoord; | |||
| fragColor = vertexColor; | |||
| fragNormal = normalize(vec3(matNormal*vec4(vertexNormal, 1.0))); | |||
| // Calculate final vertex position | |||
| gl_Position = mvp*vec4(vertexPosition, 1.0); | |||
| } | |||
| @ -0,0 +1,24 @@ | |||
| #version 120 | |||
| // Input vertex attributes (from vertex shader) | |||
| varying vec2 fragTexCoord; | |||
| varying vec4 fragColor; | |||
| // Input uniform values | |||
| uniform sampler2D texture0; | |||
| uniform sampler2D texture1; | |||
| uniform vec4 colDiffuse; | |||
| uniform float divider; | |||
| void main() | |||
| { | |||
| // Texel color fetching from texture sampler | |||
| vec4 texelColor0 = texture2D(texture0, fragTexCoord); | |||
| vec4 texelColor1 = texture2D(texture1, fragTexCoord); | |||
| float x = fract(fragTexCoord.s); | |||
| float final = smoothstep(divider - 0.1, divider + 0.1, x); | |||
| gl_FragColor = mix(texelColor0, texelColor1, final); | |||
| } | |||
| @ -0,0 +1,58 @@ | |||
| #version 120 | |||
| // Input vertex attributes (from vertex shader) | |||
| varying vec2 fragTexCoord; | |||
| varying vec4 fragColor; | |||
| // Custom variables | |||
| const float PI = 3.14159265358979323846; | |||
| uniform float uTime; | |||
| float divisions = 5.0; | |||
| float angle = 0.0; | |||
| vec2 VectorRotateTime(vec2 v, float speed) | |||
| { | |||
| float time = uTime*speed; | |||
| float localTime = fract(time); // The time domain this works on is 1 sec | |||
| if ((localTime >= 0.0) && (localTime < 0.25)) angle = 0.0; | |||
| else if ((localTime >= 0.25) && (localTime < 0.50)) angle = PI/4.0*sin(2.0*PI*localTime - PI/2.0); | |||
| else if ((localTime >= 0.50) && (localTime < 0.75)) angle = PI*0.25; | |||
| else if ((localTime >= 0.75) && (localTime < 1.00)) angle = PI/4.0*sin(2.0*PI*localTime); | |||
| // Rotate vector by angle | |||
| v -= 0.5; | |||
| v = mat2(cos(angle), -sin(angle), sin(angle), cos(angle))*v; | |||
| v += 0.5; | |||
| return v; | |||
| } | |||
| float Rectangle(in vec2 st, in float size, in float fill) | |||
| { | |||
| float roundSize = 0.5 - size/2.0; | |||
| float left = step(roundSize, st.x); | |||
| float top = step(roundSize, st.y); | |||
| float bottom = step(roundSize, 1.0 - st.y); | |||
| float right = step(roundSize, 1.0 - st.x); | |||
| return (left*bottom*right*top)*fill; | |||
| } | |||
| void main() | |||
| { | |||
| vec2 fragPos = fragTexCoord; | |||
| fragPos.xy += uTime/9.0; | |||
| fragPos *= divisions; | |||
| vec2 ipos = floor(fragPos); // Get the integer coords | |||
| vec2 fpos = fract(fragPos); // Get the fractional coords | |||
| fpos = VectorRotateTime(fpos, 0.2); | |||
| float alpha = Rectangle(fpos, 0.216, 1.0); | |||
| vec3 color = vec3(0.3, 0.3, 0.3); | |||
| gl_FragColor = vec4(color, alpha); | |||
| } | |||
| @ -0,0 +1,57 @@ | |||
| #version 120 | |||
| // Input vertex attributes (from vertex shader) | |||
| varying vec2 fragTexCoord; | |||
| varying vec4 fragColor; | |||
| // Input uniform values | |||
| uniform sampler2D gPosition; | |||
| uniform sampler2D gNormal; | |||
| uniform sampler2D gAlbedoSpec; | |||
| struct Light { | |||
| int enabled; | |||
| int type; // Unused in this demo | |||
| vec3 position; | |||
| vec3 target; // Unused in this demo | |||
| vec4 color; | |||
| }; | |||
| const int NR_LIGHTS = 4; | |||
| uniform Light lights[NR_LIGHTS]; | |||
| uniform vec3 viewPosition; | |||
| const float QUADRATIC = 0.032; | |||
| const float LINEAR = 0.09; | |||
| void main() | |||
| { | |||
| vec3 fragPosition = texture2D(gPosition, fragTexCoord).rgb; | |||
| vec3 normal = texture2D(gNormal, fragTexCoord).rgb; | |||
| vec3 albedo = texture2D(gAlbedoSpec, fragTexCoord).rgb; | |||
| float specular = texture2D(gAlbedoSpec, fragTexCoord).a; | |||
| vec3 ambient = albedo*vec3(0.1); | |||
| vec3 viewDirection = normalize(viewPosition - fragPosition); | |||
| for (int i = 0; i < NR_LIGHTS; ++i) | |||
| { | |||
| if (lights[i].enabled == 0) continue; | |||
| vec3 lightDirection = lights[i].position - fragPosition; | |||
| vec3 diffuse = max(dot(normal, lightDirection), 0.0)*albedo*lights[i].color.xyz; | |||
| vec3 halfwayDirection = normalize(lightDirection + viewDirection); | |||
| float spec = pow(max(dot(normal, halfwayDirection), 0.0), 32.0); | |||
| vec3 specular = specular*spec*lights[i].color.xyz; | |||
| // Attenuation | |||
| float distance = length(lights[i].position - fragPosition); | |||
| float attenuation = 1.0/(1.0 + LINEAR*distance + QUADRATIC*distance*distance); | |||
| diffuse *= attenuation; | |||
| specular *= attenuation; | |||
| ambient += diffuse + specular; | |||
| } | |||
| gl_FragColor = vec4(ambient, 1.0); | |||
| } | |||
| @ -0,0 +1,16 @@ | |||
| #version 120 | |||
| // Input vertex attributes | |||
| attribute vec3 vertexPosition; | |||
| attribute vec2 vertexTexCoord; | |||
| // Output vertex attributes (to fragment shader) | |||
| varying vec2 fragTexCoord; | |||
| void main() | |||
| { | |||
| fragTexCoord = vertexTexCoord; | |||
| // Calculate final vertex position | |||
| gl_Position = vec4(vertexPosition, 1.0); | |||
| } | |||
| @ -0,0 +1,58 @@ | |||
| #version 120 | |||
| /************************************************************************************* | |||
| The Sieve of Eratosthenes -- a simple shader by ProfJski | |||
| An early prime number sieve: https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes | |||
| The screen is divided into a square grid of boxes, each representing an integer value | |||
| Each integer is tested to see if it is a prime number. Primes are colored white | |||
| Non-primes are colored with a color that indicates the smallest factor which evenly divdes our integer | |||
| You can change the scale variable to make a larger or smaller grid | |||
| Total number of integers displayed = scale squared, so scale = 100 tests the first 10,000 integers | |||
| WARNING: If you make scale too large, your GPU may bog down! | |||
| ***************************************************************************************/ | |||
| // Input vertex attributes (from vertex shader) | |||
| varying vec2 fragTexCoord; | |||
| varying vec4 fragColor; | |||
| // Make a nice spectrum of colors based on counter and maxSize | |||
| vec4 Colorizer(float counter, float maxSize) | |||
| { | |||
| float red = 0.0, green = 0.0, blue = 0.0; | |||
| float normsize = counter/maxSize; | |||
| red = smoothstep(0.3, 0.7, normsize); | |||
| green = sin(3.14159*normsize); | |||
| blue = 1.0 - smoothstep(0.0, 0.4, normsize); | |||
| return vec4(0.8*red, 0.8*green, 0.8*blue, 1.0); | |||
| } | |||
| void main() | |||
| { | |||
| vec4 color = vec4(1.0); | |||
| float scale = 1000.0; // Makes 100x100 square grid. Change this variable to make a smaller or larger grid | |||
| float value = scale*floor(fragTexCoord.y*scale) + floor(fragTexCoord.x*scale); // Group pixels into boxes representing integer values | |||
| int valuei = int(value); | |||
| //if ((valuei == 0) || (valuei == 1) || (valuei == 2)) gl_FragColor = vec4(1.0); | |||
| //else | |||
| { | |||
| //for (int i = 2; (i < int(max(2.0, sqrt(value) + 1.0))); i++) | |||
| // NOTE: On GLSL 100 for loops are restricted and loop condition must be a constant | |||
| // Tested on RPI, it seems loops are limited around 60 iteractions | |||
| for (int i = 2; i < 48; i++) | |||
| { | |||
| if ((value - float(i)*floor(value/float(i))) <= 0.0) | |||
| { | |||
| gl_FragColor = Colorizer(float(i), scale); | |||
| //break; // Uncomment to color by the largest factor instead | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,34 @@ | |||
| #version 120 | |||
| // Input vertex attributes (from vertex shader) | |||
| varying vec3 fragPosition; | |||
| varying vec2 fragTexCoord; | |||
| varying vec3 fragNormal; | |||
| varying vec4 fragColor; | |||
| // TODO: Is there some alternative for GLSL100 | |||
| //layout (location = 0) out vec3 gPosition; | |||
| //layout (location = 1) out vec3 gNormal; | |||
| //layout (location = 2) out vec4 gAlbedoSpec; | |||
| //uniform vec3 gPosition; | |||
| //uniform vec3 gNormal; | |||
| //uniform vec4 gAlbedoSpec; | |||
| // Input uniform values | |||
| uniform sampler2D texture0; // Diffuse texture | |||
| uniform sampler2D specularTexture; | |||
| void main() | |||
| { | |||
| // Store the fragment position vector in the first gbuffer texture | |||
| //gPosition = fragPosition; | |||
| // Store the per-fragment normals into the gbuffer | |||
| //gNormal = normalize(fragNormal); | |||
| // Store the diffuse per-fragment color | |||
| gl_FragColor.rgb = texture2D(texture0, fragTexCoord).rgb; | |||
| // Store specular intensity in gAlbedoSpec's alpha component | |||
| gl_FragColor.a = texture2D(specularTexture, fragTexCoord).r; | |||
| } | |||
| @ -0,0 +1,60 @@ | |||
| #version 120 | |||
| // Input vertex attributes | |||
| attribute vec3 vertexPosition; | |||
| attribute vec2 vertexTexCoord; | |||
| attribute vec3 vertexNormal; | |||
| attribute vec4 vertexColor; | |||
| // Input uniform values | |||
| uniform mat4 matModel; | |||
| uniform mat4 matView; | |||
| uniform mat4 matProjection; | |||
| // Output vertex attributes (to fragment shader) | |||
| varying vec3 fragPosition; | |||
| varying vec2 fragTexCoord; | |||
| varying vec3 fragNormal; | |||
| varying vec4 fragColor; | |||
| // https://github.com/glslify/glsl-inverse | |||
| mat3 inverse(mat3 m) | |||
| { | |||
| float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2]; | |||
| float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2]; | |||
| float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2]; | |||
| float b01 = a22*a11 - a12*a21; | |||
| float b11 = -a22*a10 + a12*a20; | |||
| float b21 = a21*a10 - a11*a20; | |||
| float det = a00*b01 + a01*b11 + a02*b21; | |||
| return mat3(b01, (-a22*a01 + a02*a21), (a12*a01 - a02*a11), | |||
| b11, (a22*a00 - a02*a20), (-a12*a00 + a02*a10), | |||
| b21, (-a21*a00 + a01*a20), (a11*a00 - a01*a10))/det; | |||
| } | |||
| // https://github.com/glslify/glsl-transpose | |||
| 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() | |||
| { | |||
| // Calculate vertex attributes for fragment shader | |||
| vec4 worldPos = matModel*vec4(vertexPosition, 1.0); | |||
| fragPosition = worldPos.xyz; | |||
| fragTexCoord = vertexTexCoord; | |||
| fragColor = vertexColor; | |||
| mat3 normalMatrix = transpose(inverse(mat3(matModel))); | |||
| fragNormal = normalMatrix*vertexNormal; | |||
| // Calculate final vertex position | |||
| gl_Position = matProjection*matView*worldPos; | |||
| } | |||
| @ -0,0 +1,17 @@ | |||
| #version 120 | |||
| #extension GL_EXT_frag_depth : enable // Extension required for writing depth | |||
| varying vec2 fragTexCoord; | |||
| varying vec4 fragColor; | |||
| uniform sampler2D texture0; | |||
| uniform vec4 colDiffuse; | |||
| void main() | |||
| { | |||
| vec4 texelColor = texture2D(texture0, fragTexCoord); | |||
| gl_FragColor = texelColor*colDiffuse*fragColor; | |||
| gl_FragDepthEXT = gl_FragCoord.z; | |||
| } | |||
| @ -0,0 +1,291 @@ | |||
| #version 120 | |||
| #extension GL_EXT_frag_depth : enable //Extension required for writing depth | |||
| #extension GL_OES_standard_derivatives : enable //Extension used for fwidth() | |||
| // Input vertex attributes (from vertex shader) | |||
| varying vec2 fragTexCoord; | |||
| varying vec4 fragColor; | |||
| // Input uniform values | |||
| uniform sampler2D texture0; | |||
| uniform vec4 colDiffuse; | |||
| // Custom Input Uniform | |||
| uniform vec3 camPos; | |||
| uniform vec3 camDir; | |||
| uniform vec2 screenCenter; | |||
| #define ZERO 0 | |||
| // SRC: https://learnopengl.com/Advanced-OpenGL/Depth-testing | |||
| float CalcDepth(in vec3 rd, in float Idist) | |||
| { | |||
| float local_z = dot(normalize(camDir),rd)*Idist; | |||
| return (1.0/(local_z) - 1.0/0.01)/(1.0/1000.0 -1.0/0.01); | |||
| } | |||
| // SRC: https://iquilezles.org/articles/distfunctions/ | |||
| float sdHorseshoe(in vec3 p, in vec2 c, in float r, in float le, vec2 w) | |||
| { | |||
| p.x = abs(p.x); | |||
| float l = length(p.xy); | |||
| p.xy = mat2(-c.x, c.y, | |||
| c.y, c.x)*p.xy; | |||
| p.xy = vec2((p.y>0.0 || p.x>0.0)?p.x:l*sign(-c.x), | |||
| (p.x>0.0)?p.y:l); | |||
| p.xy = vec2(p.x,abs(p.y-r))-vec2(le,0.0); | |||
| vec2 q = vec2(length(max(p.xy,0.0)) + min(0.0,max(p.x,p.y)),p.z); | |||
| vec2 d = abs(q) - w; | |||
| return min(max(d.x,d.y),0.0) + length(max(d,0.0)); | |||
| } | |||
| // r = sphere's radius | |||
| // h = cutting's plane's position | |||
| // t = thickness | |||
| float sdSixWayCutHollowSphere(vec3 p, float r, float h, float t) | |||
| { | |||
| // Six way symetry Transformation | |||
| vec3 ap = abs(p); | |||
| if (ap.x < max(ap.y, ap.z)){ | |||
| if (ap.y < ap.z) ap.xz = ap.zx; | |||
| else ap.xy = ap.yx; | |||
| } | |||
| vec2 q = vec2(length(ap.yz), ap.x); | |||
| float w = sqrt(r*r-h*h); | |||
| return ((h*q.x<w*q.y) ? length(q-vec2(w,h)) : abs(length(q)-r)) - t; | |||
| } | |||
| // SRC: https://iquilezles.org/articles/boxfunctions | |||
| vec2 iBox(in vec3 ro, in vec3 rd, in vec3 rad) | |||
| { | |||
| vec3 m = 1.0/rd; | |||
| vec3 n = m*ro; | |||
| vec3 k = abs(m)*rad; | |||
| vec3 t1 = -n - k; | |||
| vec3 t2 = -n + k; | |||
| return vec2(max(max(t1.x, t1.y), t1.z), | |||
| min(min(t2.x, t2.y), t2.z)); | |||
| } | |||
| vec2 opU(vec2 d1, vec2 d2) | |||
| { | |||
| return (d1.x<d2.x) ? d1 : d2; | |||
| } | |||
| vec2 map(in vec3 pos) | |||
| { | |||
| vec2 res = vec2(sdHorseshoe(pos-vec3(-1.0,0.08, 1.0), vec2(cos(1.3),sin(1.3)), 0.2, 0.3, vec2(0.03,0.5)), 11.5) ; | |||
| res = opU(res, vec2(sdSixWayCutHollowSphere(pos-vec3(0.0, 1.0, 0.0), 4.0, 3.5, 0.5), 4.5)) ; | |||
| return res; | |||
| } | |||
| // SRC: https://www.shadertoy.com/view/Xds3zN | |||
| vec2 raycast(in vec3 ro, in vec3 rd) | |||
| { | |||
| vec2 res = vec2(-1.0,-1.0); | |||
| float tmin = 1.0; | |||
| float tmax = 20.0; | |||
| // Raytrace floor plane | |||
| float tp1 = (-ro.y)/rd.y; | |||
| if (tp1>0.0) | |||
| { | |||
| tmax = min(tmax, tp1); | |||
| res = vec2(tp1, 1.0); | |||
| } | |||
| float t = tmin; | |||
| for (int i=0; i<70 ; i++) | |||
| { | |||
| if (t>tmax) break; | |||
| vec2 h = map(ro+rd*t); | |||
| if (abs(h.x) < (0.0001*t)) | |||
| { | |||
| res = vec2(t,h.y); | |||
| break; | |||
| } | |||
| t += h.x; | |||
| } | |||
| return res; | |||
| } | |||
| // https://iquilezles.org/articles/rmshadows | |||
| float calcSoftshadow(in vec3 ro, in vec3 rd, in float mint, in float tmax) | |||
| { | |||
| // bounding volume | |||
| float tp = (0.8-ro.y)/rd.y; if (tp>0.0) tmax = min(tmax, tp); | |||
| float res = 1.0; | |||
| float t = mint; | |||
| for (int i=ZERO; i<24; i++) | |||
| { | |||
| float h = map(ro + rd*t).x; | |||
| float s = clamp(8.0*h/t,0.0,1.0); | |||
| res = min(res, s); | |||
| t += clamp(h, 0.01, 0.2); | |||
| if (res<0.004 || t>tmax) break; | |||
| } | |||
| res = clamp(res, 0.0, 1.0); | |||
| return res*res*(3.0-2.0*res); | |||
| } | |||
| // https://iquilezles.org/articles/normalsSDF | |||
| vec3 calcNormal(in vec3 pos) | |||
| { | |||
| vec2 e = vec2(1.0, -1.0)*0.5773*0.0005; | |||
| return normalize(e.xyy*map(pos + e.xyy).x + | |||
| e.yyx*map(pos + e.yyx).x + | |||
| e.yxy*map(pos + e.yxy).x + | |||
| e.xxx*map(pos + e.xxx).x); | |||
| } | |||
| // https://iquilezles.org/articles/nvscene2008/rwwtt.pdf | |||
| float calcAO(in vec3 pos, in vec3 nor) | |||
| { | |||
| float occ = 0.0; | |||
| float sca = 1.0; | |||
| for (int i=ZERO; i<5; i++) | |||
| { | |||
| float h = 0.01 + 0.12*float(i)/4.0; | |||
| float d = map(pos + h*nor).x; | |||
| occ += (h-d)*sca; | |||
| sca *= 0.95; | |||
| if (occ>0.35) break; | |||
| } | |||
| return clamp(1.0 - 3.0*occ, 0.0, 1.0)*(0.5+0.5*nor.y); | |||
| } | |||
| // https://iquilezles.org/articles/checkerfiltering | |||
| float checkersGradBox(in vec2 p) | |||
| { | |||
| // filter kernel | |||
| vec2 w = fwidth(p) + 0.001; | |||
| // analytical integral (box filter) | |||
| vec2 i = 2.0*(abs(fract((p-0.5*w)*0.5)-0.5)-abs(fract((p+0.5*w)*0.5)-0.5))/w; | |||
| // xor pattern | |||
| return 0.5 - 0.5*i.x*i.y; | |||
| } | |||
| // https://www.shadertoy.com/view/tdS3DG | |||
| vec4 render(in vec3 ro, in vec3 rd) | |||
| { | |||
| // background | |||
| vec3 col = vec3(0.7, 0.7, 0.9) - max(rd.y,0.0)*0.3; | |||
| // raycast scene | |||
| vec2 res = raycast(ro,rd); | |||
| float t = res.x; | |||
| float m = res.y; | |||
| if (m>-0.5) | |||
| { | |||
| vec3 pos = ro + t*rd; | |||
| vec3 nor = (m<1.5) ? vec3(0.0,1.0,0.0) : calcNormal(pos); | |||
| vec3 ref = reflect(rd, nor); | |||
| // material | |||
| col = 0.2 + 0.2*sin(m*2.0 + vec3(0.0,1.0,2.0)); | |||
| float ks = 1.0; | |||
| if (m<1.5) | |||
| { | |||
| float f = checkersGradBox(3.0*pos.xz); | |||
| col = 0.15 + f*vec3(0.05); | |||
| ks = 0.4; | |||
| } | |||
| // lighting | |||
| float occ = calcAO(pos, nor); | |||
| vec3 lin = vec3(0.0); | |||
| // sun | |||
| { | |||
| vec3 lig = normalize(vec3(-0.5, 0.4, -0.6)); | |||
| vec3 hal = normalize(lig-rd); | |||
| float dif = clamp(dot(nor, lig), 0.0, 1.0); | |||
| //if (dif>0.0001) | |||
| dif *= calcSoftshadow(pos, lig, 0.02, 2.5); | |||
| float spe = pow(clamp(dot(nor, hal), 0.0, 1.0),16.0); | |||
| spe *= dif; | |||
| spe *= 0.04+0.96*pow(clamp(1.0-dot(hal,lig),0.0,1.0),5.0); | |||
| //spe *= 0.04+0.96*pow(clamp(1.0-sqrt(0.5*(1.0-dot(rd,lig))),0.0,1.0),5.0); | |||
| lin += col*2.20*dif*vec3(1.30,1.00,0.70); | |||
| lin += 5.00*spe*vec3(1.30,1.00,0.70)*ks; | |||
| } | |||
| // sky | |||
| { | |||
| float dif = sqrt(clamp(0.5+0.5*nor.y, 0.0, 1.0)); | |||
| dif *= occ; | |||
| float spe = smoothstep(-0.2, 0.2, ref.y); | |||
| spe *= dif; | |||
| spe *= 0.04+0.96*pow(clamp(1.0+dot(nor,rd),0.0,1.0), 5.0); | |||
| //if (spe>0.001) | |||
| spe *= calcSoftshadow(pos, ref, 0.02, 2.5); | |||
| lin += col*0.60*dif*vec3(0.40,0.60,1.15); | |||
| lin += 2.00*spe*vec3(0.40,0.60,1.30)*ks; | |||
| } | |||
| // back | |||
| { | |||
| float dif = clamp(dot(nor, normalize(vec3(0.5,0.0,0.6))), 0.0, 1.0)*clamp(1.0-pos.y,0.0,1.0); | |||
| dif *= occ; | |||
| lin += col*0.55*dif*vec3(0.25,0.25,0.25); | |||
| } | |||
| // sss | |||
| { | |||
| float dif = pow(clamp(1.0+dot(nor,rd),0.0,1.0),2.0); | |||
| dif *= occ; | |||
| lin += col*0.25*dif*vec3(1.00,1.00,1.00); | |||
| } | |||
| col = lin; | |||
| col = mix(col, vec3(0.7,0.7,0.9), 1.0-exp(-0.0001*t*t*t)); | |||
| } | |||
| return vec4(vec3(clamp(col,0.0,1.0)),t); | |||
| } | |||
| vec3 CalcRayDir(vec2 nCoord){ | |||
| vec3 horizontal = normalize(cross(camDir,vec3(.0 , 1.0, .0))); | |||
| vec3 vertical = normalize(cross(horizontal,camDir)); | |||
| return normalize(camDir + horizontal*nCoord.x + vertical*nCoord.y); | |||
| } | |||
| mat3 setCamera() | |||
| { | |||
| vec3 cw = normalize(camDir); | |||
| vec3 cp = vec3(0.0, 1.0 ,0.0); | |||
| vec3 cu = normalize(cross(cw,cp)); | |||
| vec3 cv = (cross(cu,cw)); | |||
| return mat3(cu, cv, cw); | |||
| } | |||
| void main() | |||
| { | |||
| vec2 nCoord = (gl_FragCoord.xy - screenCenter.xy)/screenCenter.y; | |||
| mat3 ca = setCamera(); | |||
| // focal length | |||
| float fl = length(camDir); | |||
| vec3 rd = ca*normalize(vec3(nCoord,fl)); | |||
| vec3 color = vec3(nCoord/2.0 + 0.5, 0.0); | |||
| float depth = gl_FragCoord.z; | |||
| { | |||
| vec4 res = render(camPos - vec3(0.0, 0.0, 0.0) , rd); | |||
| color = res.xyz; | |||
| depth = CalcDepth(rd,res.w); | |||
| } | |||
| gl_FragColor = vec4(color , 1.0); | |||
| gl_FragDepthEXT = depth; | |||
| } | |||
| @ -0,0 +1,80 @@ | |||
| #version 120 | |||
| // Input vertex attributes (from vertex shader) | |||
| varying vec2 fragTexCoord; | |||
| varying vec4 fragColor; | |||
| uniform vec2 c; // c.x = real, c.y = imaginary component. Equation done is z^2 + c | |||
| uniform vec2 offset; // Offset of the scale | |||
| uniform float zoom; // Zoom of the scale | |||
| // NOTE: Maximum number of shader for-loop iterations depend on GPU, | |||
| // for example, on RasperryPi for this examply only supports up to 60 | |||
| const int maxIterations = 48; // Max iterations to do | |||
| const float colorCycles = 1.0; // Number of times the color palette repeats | |||
| // Square a complex number | |||
| vec2 ComplexSquare(vec2 z) | |||
| { | |||
| return vec2(z.x*z.x - z.y*z.y, z.x*z.y*2.0); | |||
| } | |||
| // Convert Hue Saturation Value (HSV) color into RGB | |||
| vec3 Hsv2rgb(vec3 c) | |||
| { | |||
| vec4 K = vec4(1.0, 2.0/3.0, 1.0/3.0, 3.0); | |||
| vec3 p = abs(fract(c.xxx + K.xyz)*6.0 - K.www); | |||
| return c.z*mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); | |||
| } | |||
| void main() | |||
| { | |||
| /********************************************************************************************** | |||
| Julia sets use a function z^2 + c, where c is a constant | |||
| This function is iterated until the nature of the point is determined | |||
| If the magnitude of the number becomes greater than 2, then from that point onward | |||
| the number will get bigger and bigger, and will never get smaller (tends towards infinity) | |||
| 2^2 = 4, 4^2 = 8 and so on | |||
| So at 2 we stop iterating | |||
| If the number is below 2, we keep iterating | |||
| But when do we stop iterating if the number is always below 2 (it converges)? | |||
| That is what maxIterations is for | |||
| Then we can divide the iterations by the maxIterations value to get a normalized value | |||
| that we can then map to a color | |||
| We use dot product (z.x*z.x + z.y*z.y) to determine the magnitude (length) squared | |||
| And once the magnitude squared is > 4, then magnitude > 2 is also true (saves computational power) | |||
| *************************************************************************************************/ | |||
| // The pixel coordinates are scaled so they are on the mandelbrot scale | |||
| // NOTE: fragTexCoord already comes as normalized screen coordinates but offset must be normalized before scaling and zoom | |||
| vec2 z = vec2((fragTexCoord.x - 0.5)*2.5, (fragTexCoord.y - 0.5)*1.5)/zoom; | |||
| z.x += offset.x; | |||
| z.y += offset.y; | |||
| int iter = 0; | |||
| for (int iterations = 0; iterations < 60; iterations++) | |||
| { | |||
| z = ComplexSquare(z) + c; // Iterate function | |||
| if (dot(z, z) > 4.0) break; | |||
| iter = iterations; | |||
| } | |||
| // Another few iterations decreases errors in the smoothing calculation | |||
| // See http://linas.org/art-gallery/escape/escape.html for more information | |||
| z = ComplexSquare(z) + c; | |||
| z = ComplexSquare(z) + c; | |||
| // This last part smooths the color (again see link above) | |||
| float smoothVal = float(iter) + 1.0 - (log(log(length(z)))/log(2.0)); | |||
| // Normalize the value so it is between 0 and 1 | |||
| float norm = smoothVal/float(maxIterations); | |||
| // If in set, color black. 0.999 allows for some float accuracy error | |||
| if (norm > 0.999) gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); | |||
| else gl_FragColor = vec4(Hsv2rgb(vec3(norm*colorCycles, 1.0, 1.0)), 1.0); | |||
| } | |||
| @ -0,0 +1,36 @@ | |||
| #version 120 | |||
| // Input vertex attributes | |||
| attribute vec3 vertexPosition; | |||
| attribute vec2 vertexTexCoord; | |||
| attribute vec3 vertexNormal; | |||
| attribute vec4 vertexColor; | |||
| attribute mat4 instanceTransform; | |||
| // Input uniform values | |||
| uniform mat4 mvp; | |||
| uniform mat4 matNormal; | |||
| // Output vertex attributes (to fragment shader) | |||
| varying vec3 fragPosition; | |||
| varying vec2 fragTexCoord; | |||
| varying vec4 fragColor; | |||
| varying vec3 fragNormal; | |||
| // NOTE: Add your custom variables here | |||
| void main() | |||
| { | |||
| // Compute MVP for current instance | |||
| mat4 mvpi = mvp*instanceTransform; | |||
| // Send vertex attributes to fragment shader | |||
| fragPosition = vec3(mvpi*vec4(vertexPosition, 1.0)); | |||
| fragTexCoord = vertexTexCoord; | |||
| fragColor = vertexColor; | |||
| fragNormal = normalize(vec3(matNormal*vec4(vertexNormal, 1.0))); | |||
| // Calculate final vertex position | |||
| gl_Position = mvpi*vec4(vertexPosition, 1.0); | |||
| } | |||
| @ -0,0 +1,22 @@ | |||
| #version 120 | |||
| // Input vertex attributes (from vertex shader) | |||
| varying vec2 fragTexCoord; | |||
| varying vec4 fragColor; | |||
| // Input uniform values | |||
| uniform sampler2D texture0; | |||
| uniform sampler2D mask; | |||
| uniform vec4 colDiffuse; | |||
| uniform int frame; | |||
| // NOTE: Add your custom variables here | |||
| void main() | |||
| { | |||
| vec4 maskColour = texture2D(mask, fragTexCoord + vec2(sin(-float(frame)/150.0)/10.0, cos(-float(frame)/170.0)/10.0)); | |||
| if (maskColour.r < 0.25) discard; | |||
| vec4 texelColor = texture2D(texture0, fragTexCoord + vec2(sin(float(frame)/90.0)/8.0, cos(float(frame)/60.0)/8.0)); | |||
| gl_FragColor = texelColor*maskColour; | |||
| } | |||
| @ -0,0 +1,32 @@ | |||
| #version 120 | |||
| // Input vertex attributes (from vertex shader) | |||
| varying vec2 fragTexCoord; | |||
| varying vec4 fragColor; | |||
| // Input uniform values | |||
| uniform sampler2D texture0; | |||
| uniform vec4 colDiffuse; | |||
| uniform vec2 textureSize; | |||
| uniform float outlineSize; | |||
| uniform vec4 outlineColor; | |||
| void main() | |||
| { | |||
| vec4 texel = texture2D(texture0, fragTexCoord); // Get texel color | |||
| vec2 texelScale = vec2(0.0); | |||
| texelScale.x = outlineSize/textureSize.x; | |||
| texelScale.y = outlineSize/textureSize.y; | |||
| // We sample four corner texels, but only for the alpha channel (this is for the outline) | |||
| vec4 corners = vec4(0.0); | |||
| corners.x = texture2D(texture0, fragTexCoord + vec2(texelScale.x, texelScale.y)).a; | |||
| corners.y = texture2D(texture0, fragTexCoord + vec2(texelScale.x, -texelScale.y)).a; | |||
| corners.z = texture2D(texture0, fragTexCoord + vec2(-texelScale.x, texelScale.y)).a; | |||
| corners.w = texture2D(texture0, fragTexCoord + vec2(-texelScale.x, -texelScale.y)).a; | |||
| float outline = min(dot(corners, vec4(1.0)), 1.0); | |||
| vec4 color = mix(vec4(0.0), outlineColor, outline); | |||
| gl_FragColor = mix(color, texel, texel.a); | |||
| } | |||
| @ -0,0 +1,37 @@ | |||
| #version 120 | |||
| // Input vertex attributes (from vertex shader) | |||
| varying vec2 fragTexCoord; // Texture coordinates (sampler2D) | |||
| varying vec4 fragColor; // Tint color | |||
| // Uniform inputs | |||
| uniform vec2 resolution; // Viewport resolution (in pixels) | |||
| uniform vec2 mouse; // Mouse pixel xy coordinates | |||
| uniform float time; // Total run time (in secods) | |||
| // Draw circle | |||
| vec4 DrawCircle(vec2 fragCoord, vec2 position, float radius, vec3 color) | |||
| { | |||
| float d = length(position - fragCoord) - radius; | |||
| float t = clamp(d, 0.0, 1.0); | |||
| return vec4(color, 1.0 - t); | |||
| } | |||
| void main() | |||
| { | |||
| vec2 fragCoord = gl_FragCoord.xy; | |||
| vec2 position = vec2(mouse.x, resolution.y - mouse.y); | |||
| float radius = 40.0; | |||
| // Draw background layer | |||
| vec4 colorA = vec4(0.2,0.2,0.8, 1.0); | |||
| vec4 colorB = vec4(1.0,0.7,0.2, 1.0); | |||
| vec4 layer1 = mix(colorA, colorB, abs(sin(time*0.1))); | |||
| // Draw circle layer | |||
| vec3 color = vec3(0.9, 0.16, 0.21); | |||
| vec4 layer2 = DrawCircle(fragCoord, position, radius, color); | |||
| // Blend the two layers | |||
| gl_FragColor = mix(layer1, layer2, layer2.a); | |||
| } | |||
| @ -0,0 +1,75 @@ | |||
| #version 120 | |||
| #define MAX_SPOTS 3 | |||
| struct Spot { | |||
| vec2 pos; // window coords of spot | |||
| float inner; // inner fully transparent centre radius | |||
| float radius; // alpha fades out to this radius | |||
| }; | |||
| uniform Spot spots[MAX_SPOTS]; // Spotlight positions array | |||
| uniform float screenWidth; // Width of the screen | |||
| void main() | |||
| { | |||
| float alpha = 1.0; | |||
| // Get the position of the current fragment (screen coordinates!) | |||
| vec2 pos = vec2(gl_FragCoord.x, gl_FragCoord.y); | |||
| // Find out which spotlight is nearest | |||
| float d = 65000.0; // some high value | |||
| int fi = -1; // found index | |||
| for (int i = 0; i < MAX_SPOTS; i++) | |||
| { | |||
| for (int j = 0; j < MAX_SPOTS; j++) | |||
| { | |||
| float dj = distance(pos, spots[j].pos) - spots[j].radius + spots[i].radius; | |||
| if (d > dj) | |||
| { | |||
| d = dj; | |||
| fi = i; | |||
| } | |||
| } | |||
| } | |||
| // d now equals distance to nearest spot... | |||
| // allowing for the different radii of all spotlights | |||
| if (fi == 0) | |||
| { | |||
| if (d > spots[0].radius) alpha = 1.0; | |||
| else | |||
| { | |||
| if (d < spots[0].inner) alpha = 0.0; | |||
| else alpha = (d - spots[0].inner)/(spots[0].radius - spots[0].inner); | |||
| } | |||
| } | |||
| else if (fi == 1) | |||
| { | |||
| if (d > spots[1].radius) alpha = 1.0; | |||
| else | |||
| { | |||
| if (d < spots[1].inner) alpha = 0.0; | |||
| else alpha = (d - spots[1].inner)/(spots[1].radius - spots[1].inner); | |||
| } | |||
| } | |||
| else if (fi == 2) | |||
| { | |||
| if (d > spots[2].radius) alpha = 1.0; | |||
| else | |||
| { | |||
| if (d < spots[2].inner) alpha = 0.0; | |||
| else alpha = (d - spots[2].inner)/(spots[2].radius - spots[2].inner); | |||
| } | |||
| } | |||
| // Right hand side of screen is dimly lit, | |||
| // could make the threshold value user definable | |||
| if ((pos.x > screenWidth/2.0) && (alpha > 0.9)) alpha = 0.9; | |||
| // could make the black out colour user definable... | |||
| gl_FragColor = vec4(0, 0, 0, alpha); | |||
| } | |||
| @ -0,0 +1,19 @@ | |||
| #version 120 | |||
| // Input vertex attributes (from vertex shader) | |||
| varying vec2 fragTexCoord; | |||
| varying vec4 fragColor; | |||
| // Input uniform values | |||
| uniform sampler2D texture0; | |||
| uniform vec4 colDiffuse; | |||
| // NOTE: Add your custom variables here | |||
| uniform vec2 tiling; | |||
| void main() | |||
| { | |||
| vec2 texCoord = fragTexCoord*tiling; | |||
| gl_FragColor = texture2D(texture0, texCoord)*colDiffuse; | |||
| } | |||
| @ -0,0 +1,15 @@ | |||
| #version 120 | |||
| // Input vertex attributes (from fragment shader) | |||
| varying vec2 fragTexCoord; | |||
| varying float height; | |||
| void main() | |||
| { | |||
| vec4 darkblue = vec4(0.0, 0.13, 0.18, 1.0); | |||
| vec4 lightblue = vec4(1.0, 1.0, 1.0, 1.0); | |||
| // Interpolate between two colors based on height | |||
| vec4 finalColor = mix(darkblue, lightblue, height); | |||
| gl_FragColor = finalColor; | |||
| } | |||
| @ -0,0 +1,43 @@ | |||
| #version 120 | |||
| attribute vec3 vertexPosition; | |||
| attribute vec2 vertexTexCoord; | |||
| attribute vec3 vertexNormal; | |||
| attribute vec4 vertexColor; | |||
| uniform mat4 mvp; | |||
| uniform mat4 matModel; | |||
| uniform mat4 matNormal; | |||
| uniform float time; | |||
| uniform sampler2D perlinNoiseMap; | |||
| varying vec3 fragPosition; | |||
| varying vec2 fragTexCoord; | |||
| varying vec3 fragNormal; | |||
| varying float height; | |||
| void main() | |||
| { | |||
| // Calculate animated texture coordinates based on time and vertex position | |||
| vec2 animatedTexCoord = sin(vertexTexCoord + vec2(sin(time + vertexPosition.x*0.1), cos(time + vertexPosition.z*0.1))*0.3); | |||
| // Normalize animated texture coordinates to range [0, 1] | |||
| animatedTexCoord = animatedTexCoord*0.5 + 0.5; | |||
| // Fetch displacement from the perlin noise map | |||
| float displacement = texture2D(perlinNoiseMap, animatedTexCoord).r*7.0; // Amplified displacement | |||
| // Displace vertex position | |||
| vec3 displacedPosition = vertexPosition + vec3(0.0, displacement, 0.0); | |||
| // Send vertex attributes to fragment shader | |||
| fragPosition = vec3(matModel*vec4(displacedPosition, 1.0)); | |||
| fragTexCoord = vertexTexCoord; | |||
| fragNormal = normalize(vec3(matNormal*vec4(vertexNormal, 1.0))); | |||
| height = displacedPosition.y*0.2; // send height to fragment shader for coloring | |||
| // Calculate final vertex position | |||
| gl_Position = mvp*vec4(displacedPosition, 1.0); | |||
| } | |||
| @ -0,0 +1,32 @@ | |||
| #version 120 | |||
| // Input vertex attributes (from vertex shader) | |||
| varying vec2 fragTexCoord; | |||
| varying vec4 fragColor; | |||
| // Input uniform values | |||
| uniform sampler2D texture0; | |||
| uniform vec4 colDiffuse; | |||
| uniform float seconds; | |||
| uniform vec2 size; | |||
| uniform float freqX; | |||
| uniform float freqY; | |||
| uniform float ampX; | |||
| uniform float ampY; | |||
| uniform float speedX; | |||
| uniform float speedY; | |||
| void main() { | |||
| float pixelWidth = 1.0/size.x; | |||
| float pixelHeight = 1.0/size.y; | |||
| float aspect = pixelHeight/pixelWidth; | |||
| float boxLeft = 0.0; | |||
| float boxTop = 0.0; | |||
| vec2 p = fragTexCoord; | |||
| p.x += cos((fragTexCoord.y - boxTop)*freqX/(pixelWidth*750.0) + (seconds*speedX))*ampX*pixelWidth; | |||
| p.y += sin((fragTexCoord.x - boxLeft)*freqY*aspect/(pixelHeight*750.0) + (seconds*speedY))*ampY*pixelHeight; | |||
| gl_FragColor = texture2D(texture0, p)*colDiffuse*fragColor; | |||
| } | |||
| @ -0,0 +1,17 @@ | |||
| #version 100 | |||
| #extension GL_EXT_frag_depth : enable | |||
| varying vec2 fragTexCoord; | |||
| varying vec4 fragColor; | |||
| uniform sampler2D texture0; | |||
| uniform vec4 colDiffuse; | |||
| void main() | |||
| { | |||
| vec4 texelColor = texture2D(texture0, fragTexCoord); | |||
| gl_FragColor = texelColor*colDiffuse*fragColor; | |||
| gl_FragDepthEXT = 1.0 - gl_FragCoord.z; | |||
| } | |||