diff --git a/CMakeLists.txt b/CMakeLists.txt index 4ad625e9..b545bd0e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -84,6 +84,9 @@ set(SOURCES sources/Component/Animator/AnimatorComponent.hpp sources/System/Animator/AnimatorSystem.cpp sources/System/Animator/AnimatorSystem.hpp + sources/Component/Shaders/ShaderComponent.cpp + sources/Component/Shaders/ShaderComponent.hpp + sources/Component/Tag/TagComponent.hpp sources/Component/Music/MusicComponent.cpp sources/Component/Music/MusicComponent.hpp sources/Component/Sound/SoundComponent.hpp @@ -95,6 +98,7 @@ set(SOURCES sources/System/Music/MusicSystem.hpp sources/System/Music/MusicSystem.cpp ) + add_executable(bomberman sources/main.cpp ${SOURCES} @@ -105,6 +109,7 @@ target_link_libraries(bomberman PUBLIC wal ray) add_executable(unit_tests EXCLUDE_FROM_ALL ${SOURCES} + tests/CacheTest.cpp tests/EntityTests.cpp tests/MainTest.cpp tests/EngineTests.cpp @@ -112,7 +117,7 @@ add_executable(unit_tests EXCLUDE_FROM_ALL tests/MoveTests.cpp tests/ViewTest.cpp tests/CollisionTest.cpp - ) +) target_include_directories(unit_tests PUBLIC sources) target_link_libraries(unit_tests PUBLIC wal ray) diff --git a/assets/map/bumper.png b/assets/map/bumper.png index a86b67f2..63632844 100644 Binary files a/assets/map/bumper.png and b/assets/map/bumper.png differ diff --git a/assets/shaders/basic_shader.fs b/assets/shaders/basic_shader.fs new file mode 100644 index 00000000..241d07a7 --- /dev/null +++ b/assets/shaders/basic_shader.fs @@ -0,0 +1,33 @@ +#version 330 +precision highp float; +precision highp int; + +varying float noise; + +//uniform float brightness; + +float random( vec3 scale, float seed ) { + return fract( sin( dot( gl_FragCoord.xyz + seed, scale ) ) * 43758.5453 + seed ) ; +} + +vec3 mult(vec3 a, vec3 b){ + return vec3(a.r *b.r, a.g * b.g, a.b * b.b); +} + +void main() { + + brightness = 0.86080327; + // get a random offset + float offset = .01 * random( vec3( 12.9898, 78.233, 0151.7182 ), 0.0 ); + + // not quite depth, but how bright the sphere is (higher is dimmer) + float depth = 0.25; + + // lookup vertically in the texture, using noise and offset + // to get the right RGB colour + vec2 tPos = vec2( 0, ( brightness + depth ) * noise + offset ); + // vec4 color = texture2D( tExplosion, ( brightness - depth ) - tPos ); + vec3 color = mult(vec3(0, 1, 0), vec3( ( brightness - depth ) - tPos.y )); + gl_FragColor = vec4( color, 1.0 ); + +} diff --git a/assets/shaders/basic_shader.vs b/assets/shaders/basic_shader.vs new file mode 100644 index 00000000..6a7846d8 --- /dev/null +++ b/assets/shaders/basic_shader.vs @@ -0,0 +1,218 @@ +#version 330 +precision highp float; +precision highp int; + +//uniform mat4 modelMatrix; +uniform mat4 view; +uniform mat4 projection; +uniform mat4 viewMatrix; +//uniform mat3 matNormal; + +attribute vec3 vertexPosition; +attribute vec3 vertexNormal; +//attribute vec2 uv; +//attribute vec2 uv2; + +varying float noise; +uniform float time; +uniform float fireSpeed; +uniform float pulseHeight; +uniform float displacementHeight; +uniform float turbulenceDetail; + +// +// GLSL textureless classic 3D noise "cnoise", +// with an RSL-style periodic variant "pnoise". +// Author: Stefan Gustavson (stefan.gustavson@liu.se) +// Version: 2011-10-11 +// +// Many thanks to Ian McEwan of Ashima Arts for the +// ideas for permutation and gradient selection. +// +// Copyright (c) 2011 Stefan Gustavson. All rights reserved. +// Distributed under the MIT license. See LICENSE file. +// https://github.com/ashima/webgl-noise +// + +vec3 mod289(vec3 x) { + return x - floor(x * (1.0 / 289.0)) * 289.0; +} + +vec4 mod289(vec4 x) { + return x - floor(x * (1.0 / 289.0)) * 289.0; +} + +vec4 permute(vec4 x) { + return mod289(((x*34.0)+1.0)*x); +} + +vec4 taylorInvSqrt(vec4 r) { + return 1.79284291400159 - 0.85373472095314 * r; +} + +vec3 fade(vec3 t) { + return t*t*t*(t*(t*6.0-15.0)+10.0); +} + +// Classic Perlin noise +float cnoise(vec3 P) { + vec3 Pi0 = floor(P); // Integer part for indexing + vec3 Pi1 = Pi0 + vec3(1.0); // Integer part + 1 + Pi0 = mod289(Pi0); + Pi1 = mod289(Pi1); + vec3 Pf0 = fract(P); // Fractional part for interpolation + vec3 Pf1 = Pf0 - vec3(1.0); // Fractional part - 1.0 + vec4 ix = vec4(Pi0.x, Pi1.x, Pi0.x, Pi1.x); + vec4 iy = vec4(Pi0.yy, Pi1.yy); + vec4 iz0 = Pi0.zzzz; + vec4 iz1 = Pi1.zzzz; + + vec4 ixy = permute(permute(ix) + iy); + vec4 ixy0 = permute(ixy + iz0); + vec4 ixy1 = permute(ixy + iz1); + + vec4 gx0 = ixy0 * (1.0 / 7.0); + vec4 gy0 = fract(floor(gx0) * (1.0 / 7.0)) - 0.5; + gx0 = fract(gx0); + vec4 gz0 = vec4(0.5) - abs(gx0) - abs(gy0); + vec4 sz0 = step(gz0, vec4(0.0)); + gx0 -= sz0 * (step(0.0, gx0) - 0.5); + gy0 -= sz0 * (step(0.0, gy0) - 0.5); + + vec4 gx1 = ixy1 * (1.0 / 7.0); + vec4 gy1 = fract(floor(gx1) * (1.0 / 7.0)) - 0.5; + gx1 = fract(gx1); + vec4 gz1 = vec4(0.5) - abs(gx1) - abs(gy1); + vec4 sz1 = step(gz1, vec4(0.0)); + gx1 -= sz1 * (step(0.0, gx1) - 0.5); + gy1 -= sz1 * (step(0.0, gy1) - 0.5); + + vec3 g000 = vec3(gx0.x,gy0.x,gz0.x); + vec3 g100 = vec3(gx0.y,gy0.y,gz0.y); + vec3 g010 = vec3(gx0.z,gy0.z,gz0.z); + vec3 g110 = vec3(gx0.w,gy0.w,gz0.w); + vec3 g001 = vec3(gx1.x,gy1.x,gz1.x); + vec3 g101 = vec3(gx1.y,gy1.y,gz1.y); + vec3 g011 = vec3(gx1.z,gy1.z,gz1.z); + vec3 g111 = vec3(gx1.w,gy1.w,gz1.w); + + vec4 norm0 = taylorInvSqrt(vec4(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110))); + g000 *= norm0.x; + g010 *= norm0.y; + g100 *= norm0.z; + g110 *= norm0.w; + vec4 norm1 = taylorInvSqrt(vec4(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111))); + g001 *= norm1.x; + g011 *= norm1.y; + g101 *= norm1.z; + g111 *= norm1.w; + + float n000 = dot(g000, Pf0); + float n100 = dot(g100, vec3(Pf1.x, Pf0.yz)); + float n010 = dot(g010, vec3(Pf0.x, Pf1.y, Pf0.z)); + float n110 = dot(g110, vec3(Pf1.xy, Pf0.z)); + float n001 = dot(g001, vec3(Pf0.xy, Pf1.z)); + float n101 = dot(g101, vec3(Pf1.x, Pf0.y, Pf1.z)); + float n011 = dot(g011, vec3(Pf0.x, Pf1.yz)); + float n111 = dot(g111, Pf1); + + vec3 fade_xyz = fade(Pf0); + vec4 n_z = mix(vec4(n000, n100, n010, n110), vec4(n001, n101, n011, n111), fade_xyz.z); + vec2 n_yz = mix(n_z.xy, n_z.zw, fade_xyz.y); + float n_xyz = mix(n_yz.x, n_yz.y, fade_xyz.x); + return 2.2 * n_xyz; +} + +// Classic Perlin noise, periodic variant +float pnoise(vec3 P, vec3 rep) { + vec3 Pi0 = mod(floor(P), rep); // Integer part, modulo period + vec3 Pi1 = mod(Pi0 + vec3(1.0), rep); // Integer part + 1, mod period + Pi0 = mod289(Pi0); + Pi1 = mod289(Pi1); + vec3 Pf0 = fract(P); // Fractional part for interpolation + vec3 Pf1 = Pf0 - vec3(1.0); // Fractional part - 1.0 + vec4 ix = vec4(Pi0.x, Pi1.x, Pi0.x, Pi1.x); + vec4 iy = vec4(Pi0.yy, Pi1.yy); + vec4 iz0 = Pi0.zzzz; + vec4 iz1 = Pi1.zzzz; + + vec4 ixy = permute(permute(ix) + iy); + vec4 ixy0 = permute(ixy + iz0); + vec4 ixy1 = permute(ixy + iz1); + + vec4 gx0 = ixy0 * (1.0 / 7.0); + vec4 gy0 = fract(floor(gx0) * (1.0 / 7.0)) - 0.5; + gx0 = fract(gx0); + vec4 gz0 = vec4(0.5) - abs(gx0) - abs(gy0); + vec4 sz0 = step(gz0, vec4(0.0)); + gx0 -= sz0 * (step(0.0, gx0) - 0.5); + gy0 -= sz0 * (step(0.0, gy0) - 0.5); + + vec4 gx1 = ixy1 * (1.0 / 7.0); + vec4 gy1 = fract(floor(gx1) * (1.0 / 7.0)) - 0.5; + gx1 = fract(gx1); + vec4 gz1 = vec4(0.5) - abs(gx1) - abs(gy1); + vec4 sz1 = step(gz1, vec4(0.0)); + gx1 -= sz1 * (step(0.0, gx1) - 0.5); + gy1 -= sz1 * (step(0.0, gy1) - 0.5); + + vec3 g000 = vec3(gx0.x,gy0.x,gz0.x); + vec3 g100 = vec3(gx0.y,gy0.y,gz0.y); + vec3 g010 = vec3(gx0.z,gy0.z,gz0.z); + vec3 g110 = vec3(gx0.w,gy0.w,gz0.w); + vec3 g001 = vec3(gx1.x,gy1.x,gz1.x); + vec3 g101 = vec3(gx1.y,gy1.y,gz1.y); + vec3 g011 = vec3(gx1.z,gy1.z,gz1.z); + vec3 g111 = vec3(gx1.w,gy1.w,gz1.w); + + vec4 norm0 = taylorInvSqrt(vec4(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110))); + g000 *= norm0.x; + g010 *= norm0.y; + g100 *= norm0.z; + g110 *= norm0.w; + vec4 norm1 = taylorInvSqrt(vec4(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111))); + g001 *= norm1.x; + g011 *= norm1.y; + g101 *= norm1.z; + g111 *= norm1.w; + + float n000 = dot(g000, Pf0); + float n100 = dot(g100, vec3(Pf1.x, Pf0.yz)); + float n010 = dot(g010, vec3(Pf0.x, Pf1.y, Pf0.z)); + float n110 = dot(g110, vec3(Pf1.xy, Pf0.z)); + float n001 = dot(g001, vec3(Pf0.xy, Pf1.z)); + float n101 = dot(g101, vec3(Pf1.x, Pf0.y, Pf1.z)); + float n011 = dot(g011, vec3(Pf0.x, Pf1.yz)); + float n111 = dot(g111, Pf1); + + vec3 fade_xyz = fade(Pf0); + vec4 n_z = mix(vec4(n000, n100, n010, n110), vec4(n001, n101, n011, n111), fade_xyz.z); + vec2 n_yz = mix(n_z.xy, n_z.zw, fade_xyz.y); + float n_xyz = mix(n_yz.x, n_yz.y, fade_xyz.x); + return 2.2 * n_xyz; +} + +// Include the Ashima code here! + +float turbulence( vec3 p ) { + float t = -0.5; + for (float f = 1.0 ; f <= 10.0 ; f++ ){ + float power = pow( 2.0, f ); + t += abs( pnoise( vec3( power * p ), vec3( 10.0, 10.0, 10.0 ) ) / power ); + } + return t; +} + +void main() { + + noise = -1.1 * turbulence( turbulenceDetail * vertexNormal + ( time * fireSpeed ) ); + + float b = pulseHeight * pnoise( + 0.05 * vertexPosition + vec3( 1.0 * time ), vec3( 100.0 ) + ); + float displacement = ( 0.0 - displacementHeight ) * noise + b; + + vec3 newvertexPosition = vertexPosition + vertexNormal * displacement; + gl_vertexPosition = projection * view * vec4( newvertexPosition, 1.0 ); + +} \ No newline at end of file diff --git a/assets/shaders/glsl100/base.fs b/assets/shaders/glsl100/base.fs new file mode 100644 index 00000000..c1126423 --- /dev/null +++ b/assets/shaders/glsl100/base.fs @@ -0,0 +1,23 @@ +#version 100 + +precision mediump float; + +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +// NOTE: Add here your custom variables + +void main() +{ + // Texel color fetching from texture sampler + vec4 texelColor = texture2D(texture0, fragTexCoord); + + // NOTE: Implement here your fragment shader code + + gl_FragColor = texelColor*colDiffuse; +} \ No newline at end of file diff --git a/assets/shaders/glsl100/base.vs b/assets/shaders/glsl100/base.vs new file mode 100644 index 00000000..4be76b9e --- /dev/null +++ b/assets/shaders/glsl100/base.vs @@ -0,0 +1,26 @@ +#version 100 + +// Input vertex attributes +attribute vec3 vertexPosition; +attribute vec2 vertexTexCoord; +attribute vec3 vertexNormal; +attribute vec4 vertexColor; + +// Input uniform values +uniform mat4 mvp; + +// Output vertex attributes (to fragment shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; + +// NOTE: Add here your custom variables + +void main() +{ + // Send vertex attributes to fragment shader + fragTexCoord = vertexTexCoord; + fragColor = vertexColor; + + // Calculate final vertex position + gl_Position = mvp*vec4(vertexPosition, 1.0); +} \ No newline at end of file diff --git a/assets/shaders/glsl100/base_lighting.vs b/assets/shaders/glsl100/base_lighting.vs new file mode 100644 index 00000000..5245c615 --- /dev/null +++ b/assets/shaders/glsl100/base_lighting.vs @@ -0,0 +1,59 @@ +#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; + +// Output vertex attributes (to fragment shader) +varying vec3 fragPosition; +varying vec2 fragTexCoord; +varying vec4 fragColor; +varying vec3 fragNormal; + +// NOTE: Add here your custom variables + +// 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() +{ + // Send vertex attributes to fragment shader + fragPosition = vec3(matModel*vec4(vertexPosition, 1.0)); + fragTexCoord = vertexTexCoord; + fragColor = vertexColor; + + mat3 normalMatrix = transpose(inverse(mat3(matModel))); + fragNormal = normalize(normalMatrix*vertexNormal); + + // Calculate final vertex position + gl_Position = mvp*vec4(vertexPosition, 1.0); +} diff --git a/assets/shaders/glsl100/base_lighting_instanced.vs b/assets/shaders/glsl100/base_lighting_instanced.vs new file mode 100644 index 00000000..c8e25607 --- /dev/null +++ b/assets/shaders/glsl100/base_lighting_instanced.vs @@ -0,0 +1,62 @@ +#version 100 + +// Input vertex attributes +attribute vec3 vertexPosition; +attribute vec2 vertexTexCoord; +attribute vec3 vertexNormal; +attribute vec4 vertexColor; + +attribute mat4 instance; + +// Input uniform values +uniform mat4 mvp; + +// Output vertex attributes (to fragment shader) +varying vec3 fragPosition; +varying vec2 fragTexCoord; +varying vec4 fragColor; +varying vec3 fragNormal; + +// NOTE: Add here your custom variables + +// 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() +{ + // Send vertex attributes to fragment shader + fragPosition = vec3(instance*vec4(vertexPosition, 1.0)); + fragTexCoord = vertexTexCoord; + fragColor = vertexColor; + + mat3 normalMatrix = transpose(inverse(mat3(instance))); + fragNormal = normalize(normalMatrix*vertexNormal); + + mat4 mvpi = mvp*instance; + + // Calculate final vertex position + gl_Position = mvpi*vec4(vertexPosition, 1.0); +} diff --git a/assets/shaders/glsl100/bloom.fs b/assets/shaders/glsl100/bloom.fs new file mode 100644 index 00000000..673e0116 --- /dev/null +++ b/assets/shaders/glsl100/bloom.fs @@ -0,0 +1,39 @@ +#version 100 + +precision mediump float; + +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +// NOTE: Add here your custom variables + +const vec2 size = vec2(800, 450); // render size +const float samples = 5.0; // pixels per axis; higher = bigger glow, worse performance +const float quality = 2.5; // lower = smaller glow, better quality + +void main() +{ + vec4 sum = vec4(0); + vec2 sizeFactor = vec2(1)/size*quality; + + // Texel color fetching from texture sampler + vec4 source = texture2D(texture0, fragTexCoord); + + const int range = 2; // should be = (samples - 1)/2; + + for (int x = -range; x <= range; x++) + { + for (int y = -range; y <= range; y++) + { + sum += texture2D(texture0, fragTexCoord + vec2(x, y)*sizeFactor); + } + } + + // Calculate final fragment color + gl_FragColor = ((sum/(samples*samples)) + source)*colDiffuse; +} \ No newline at end of file diff --git a/assets/shaders/glsl100/blur.fs b/assets/shaders/glsl100/blur.fs new file mode 100644 index 00000000..96f780e1 --- /dev/null +++ b/assets/shaders/glsl100/blur.fs @@ -0,0 +1,34 @@ +#version 100 + +precision mediump float; + +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +// NOTE: Add here your custom variables + +// NOTE: Render size values must be passed from code +const float renderWidth = 800.0; +const float renderHeight = 450.0; + +vec3 offset = vec3(0.0, 1.3846153846, 3.2307692308); +vec3 weight = vec3(0.2270270270, 0.3162162162, 0.0702702703); + +void main() +{ + // Texel color fetching from texture sampler + vec3 tc = texture2D(texture0, fragTexCoord).rgb*weight.x; + + tc += texture2D(texture0, fragTexCoord + vec2(offset.y)/renderWidth, 0.0).rgb*weight.y; + tc += texture2D(texture0, fragTexCoord - vec2(offset.y)/renderWidth, 0.0).rgb*weight.y; + + tc += texture2D(texture0, fragTexCoord + vec2(offset.z)/renderWidth, 0.0).rgb*weight.z; + tc += texture2D(texture0, fragTexCoord - vec2(offset.z)/renderWidth, 0.0).rgb*weight.z; + + gl_FragColor = vec4(tc, 1.0); +} \ No newline at end of file diff --git a/assets/shaders/glsl100/color_mix.fs b/assets/shaders/glsl100/color_mix.fs new file mode 100644 index 00000000..c5c0cb70 --- /dev/null +++ b/assets/shaders/glsl100/color_mix.fs @@ -0,0 +1,26 @@ +#version 100 + +precision mediump float; + +// 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); +} diff --git a/assets/shaders/glsl100/cross_hatching.fs b/assets/shaders/glsl100/cross_hatching.fs new file mode 100644 index 00000000..7d63b0a5 --- /dev/null +++ b/assets/shaders/glsl100/cross_hatching.fs @@ -0,0 +1,47 @@ +# version 100 + +precision mediump float; + +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +// NOTE: Add here your custom variables + +float hatchOffsetY = 5.0; +float lumThreshold01 = 0.9; +float lumThreshold02 = 0.7; +float lumThreshold03 = 0.5; +float lumThreshold04 = 0.3; + +void main() +{ + vec3 tc = vec3(1.0, 1.0, 1.0); + float lum = length(texture2D(texture0, fragTexCoord).rgb); + + if (lum < lumThreshold01) + { + if (mod(gl_FragCoord.x + gl_FragCoord.y, 10.0) == 0.0) tc = vec3(0.0, 0.0, 0.0); + } + + if (lum < lumThreshold02) + { + if (mod(gl_FragCoord .x - gl_FragCoord .y, 10.0) == 0.0) tc = vec3(0.0, 0.0, 0.0); + } + + if (lum < lumThreshold03) + { + if (mod(gl_FragCoord .x + gl_FragCoord .y - hatchOffsetY, 10.0) == 0.0) tc = vec3(0.0, 0.0, 0.0); + } + + if (lum < lumThreshold04) + { + if (mod(gl_FragCoord .x - gl_FragCoord .y - hatchOffsetY, 10.0) == 0.0) tc = vec3(0.0, 0.0, 0.0); + } + + gl_FragColor = vec4(tc, 1.0); +} \ No newline at end of file diff --git a/assets/shaders/glsl100/cross_stitching.fs b/assets/shaders/glsl100/cross_stitching.fs new file mode 100644 index 00000000..de6d4f40 --- /dev/null +++ b/assets/shaders/glsl100/cross_stitching.fs @@ -0,0 +1,57 @@ +# version 100 + +precision mediump float; + +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +// NOTE: Add here your custom variables + +// NOTE: Render size values must be passed from code +const float renderWidth = 800.0; +const float renderHeight = 450.0; + +float stitchingSize = 6.0; +int invert = 0; + +vec4 PostFX(sampler2D tex, vec2 uv) +{ + vec4 c = vec4(0.0); + float size = stitchingSize; + vec2 cPos = uv * vec2(renderWidth, renderHeight); + vec2 tlPos = floor(cPos / vec2(size, size)); + tlPos *= size; + + int remX = int(mod(cPos.x, size)); + int remY = int(mod(cPos.y, size)); + + if (remX == 0 && remY == 0) tlPos = cPos; + + vec2 blPos = tlPos; + blPos.y += (size - 1.0); + + if ((remX == remY) || (((int(cPos.x) - int(blPos.x)) == (int(blPos.y) - int(cPos.y))))) + { + if (invert == 1) c = vec4(0.2, 0.15, 0.05, 1.0); + else c = texture2D(tex, tlPos * vec2(1.0/renderWidth, 1.0/renderHeight)) * 1.4; + } + else + { + if (invert == 1) c = texture2D(tex, tlPos * vec2(1.0/renderWidth, 1.0/renderHeight)) * 1.4; + else c = vec4(0.0, 0.0, 0.0, 1.0); + } + + return c; +} + +void main() +{ + vec3 tc = PostFX(texture0, fragTexCoord).rgb; + + gl_FragColor = vec4(tc, 1.0); +} \ No newline at end of file diff --git a/assets/shaders/glsl100/cubes_panning.fs b/assets/shaders/glsl100/cubes_panning.fs new file mode 100644 index 00000000..108f0579 --- /dev/null +++ b/assets/shaders/glsl100/cubes_panning.fs @@ -0,0 +1,60 @@ +#version 100 + +precision mediump float; + +// 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); +} \ No newline at end of file diff --git a/assets/shaders/glsl100/depth.fs b/assets/shaders/glsl100/depth.fs new file mode 100644 index 00000000..f6a14eb2 --- /dev/null +++ b/assets/shaders/glsl100/depth.fs @@ -0,0 +1,26 @@ +#version 100 + +precision mediump float; + +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; // Depth texture +uniform vec4 colDiffuse; + +// NOTE: Add here your custom variables + +void main() +{ + float zNear = 0.01; // camera z near + float zFar = 10.0; // camera z far + float z = texture2D(texture0, fragTexCoord).x; + + // Linearize depth value + float depth = (2.0*zNear)/(zFar + zNear - z*(zFar - zNear)); + + // Calculate final fragment color + gl_FragColor = vec4(depth, depth, depth, 1.0f); +} \ No newline at end of file diff --git a/assets/shaders/glsl100/distortion.fs b/assets/shaders/glsl100/distortion.fs new file mode 100644 index 00000000..50116ce0 --- /dev/null +++ b/assets/shaders/glsl100/distortion.fs @@ -0,0 +1,54 @@ +#version 100 + +precision mediump float; + +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; + +// Input uniform values +uniform sampler2D texture0; + +// NOTE: Default parameters for Oculus Rift DK2 device +const vec2 LeftLensCenter = vec2(0.2863248, 0.5); +const vec2 RightLensCenter = vec2(0.7136753, 0.5); +const vec2 LeftScreenCenter = vec2(0.25, 0.5); +const vec2 RightScreenCenter = vec2(0.75, 0.5); +const vec2 Scale = vec2(0.25, 0.45); +const vec2 ScaleIn = vec2(4.0, 2.5); +const vec4 HmdWarpParam = vec4(1.0, 0.22, 0.24, 0.0); +const vec4 ChromaAbParam = vec4(0.996, -0.004, 1.014, 0.0); + +void main() +{ + // The following two variables need to be set per eye + vec2 LensCenter = fragTexCoord.x < 0.5 ? LeftLensCenter : RightLensCenter; + vec2 ScreenCenter = fragTexCoord.x < 0.5 ? LeftScreenCenter : RightScreenCenter; + + // Scales input texture coordinates for distortion: vec2 HmdWarp(vec2 fragTexCoord, vec2 LensCenter) + vec2 theta = (fragTexCoord - LensCenter)*ScaleIn; // Scales to [-1, 1] + float rSq = theta.x*theta.x + theta.y*theta.y; + vec2 theta1 = theta*(HmdWarpParam.x + HmdWarpParam.y*rSq + HmdWarpParam.z*rSq*rSq + HmdWarpParam.w*rSq*rSq*rSq); + //vec2 tc = LensCenter + Scale*theta1; + + // Detect whether blue texture coordinates are out of range since these will scaled out the furthest + vec2 thetaBlue = theta1*(ChromaAbParam.z + ChromaAbParam.w*rSq); + vec2 tcBlue = LensCenter + Scale*thetaBlue; + + if (any(bvec2(clamp(tcBlue, ScreenCenter - vec2(0.25, 0.5), ScreenCenter + vec2(0.25, 0.5)) - tcBlue))) gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); + else + { + // Do blue texture lookup + float blue = texture2D(texture0, tcBlue).b; + + // Do green lookup (no scaling) + vec2 tcGreen = LensCenter + Scale*theta1; + float green = texture2D(texture0, tcGreen).g; + + // Do red scale and lookup + vec2 thetaRed = theta1*(ChromaAbParam.x + ChromaAbParam.y*rSq); + vec2 tcRed = LensCenter + Scale*thetaRed; + float red = texture2D(texture0, tcRed).r; + + gl_FragColor = vec4(red, green, blue, 1.0); + } +} diff --git a/assets/shaders/glsl100/dream_vision.fs b/assets/shaders/glsl100/dream_vision.fs new file mode 100644 index 00000000..7014b592 --- /dev/null +++ b/assets/shaders/glsl100/dream_vision.fs @@ -0,0 +1,37 @@ +#version 100 + +precision mediump float; + +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +// NOTE: Add here your custom variables + +void main() +{ + vec4 color = texture2D(texture0, fragTexCoord); + + color += texture2D(texture0, fragTexCoord + 0.001); + color += texture2D(texture0, fragTexCoord + 0.003); + color += texture2D(texture0, fragTexCoord + 0.005); + color += texture2D(texture0, fragTexCoord + 0.007); + color += texture2D(texture0, fragTexCoord + 0.009); + color += texture2D(texture0, fragTexCoord + 0.011); + + color += texture2D(texture0, fragTexCoord - 0.001); + color += texture2D(texture0, fragTexCoord - 0.003); + color += texture2D(texture0, fragTexCoord - 0.005); + color += texture2D(texture0, fragTexCoord - 0.007); + color += texture2D(texture0, fragTexCoord - 0.009); + color += texture2D(texture0, fragTexCoord - 0.011); + + color.rgb = vec3((color.r + color.g + color.b)/3.0); + color = color/9.5; + + gl_FragColor = color; +} \ No newline at end of file diff --git a/assets/shaders/glsl100/eratosthenes.fs b/assets/shaders/glsl100/eratosthenes.fs new file mode 100644 index 00000000..ba6de891 --- /dev/null +++ b/assets/shaders/glsl100/eratosthenes.fs @@ -0,0 +1,60 @@ +#version 100 + +precision mediump float; + +/************************************************************************************* + + 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 + } + } + } +} diff --git a/assets/shaders/glsl100/fisheye.fs b/assets/shaders/glsl100/fisheye.fs new file mode 100644 index 00000000..8beb3d4a --- /dev/null +++ b/assets/shaders/glsl100/fisheye.fs @@ -0,0 +1,43 @@ +#version 100 + +precision mediump float; + +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +// NOTE: Add here your custom variables + +const float PI = 3.1415926535; + +void main() +{ + float aperture = 178.0; + float apertureHalf = 0.5 * aperture * (PI / 180.0); + float maxFactor = sin(apertureHalf); + + vec2 uv = vec2(0.0); + vec2 xy = 2.0 * fragTexCoord.xy - 1.0; + float d = length(xy); + + if (d < (2.0 - maxFactor)) + { + d = length(xy * maxFactor); + float z = sqrt(1.0 - d * d); + float r = atan(d, z) / PI; + float phi = atan(xy.y, xy.x); + + uv.x = r * cos(phi) + 0.5; + uv.y = r * sin(phi) + 0.5; + } + else + { + uv = fragTexCoord.xy; + } + + gl_FragColor = texture2D(texture0, uv); +} \ No newline at end of file diff --git a/assets/shaders/glsl100/fog.fs b/assets/shaders/glsl100/fog.fs new file mode 100644 index 00000000..eeb2150f --- /dev/null +++ b/assets/shaders/glsl100/fog.fs @@ -0,0 +1,94 @@ +#version 100 + +precision mediump float; + +// Input vertex attributes (from vertex shader) +varying vec3 fragPosition; +varying vec2 fragTexCoord; +varying vec4 fragColor; +varying vec3 fragNormal; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +// NOTE: Add here your custom variables + +#define MAX_LIGHTS 4 +#define LIGHT_DIRECTIONAL 0 +#define LIGHT_POINT 1 + +struct MaterialProperty { + vec3 color; + int useSampler; + sampler2D sampler; +}; + +struct Light { + int enabled; + int type; + vec3 position; + vec3 target; + vec4 color; +}; + +// Input lighting values +uniform Light lights[MAX_LIGHTS]; +uniform vec4 ambient; +uniform vec3 viewPos; +uniform float fogDensity; + +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); + + // NOTE: Implement here your fragment shader code + + for (int i = 0; i < MAX_LIGHTS; i++) + { + if (lights[i].enabled == 1) + { + vec3 light = vec3(0.0); + + if (lights[i].type == LIGHT_DIRECTIONAL) light = -normalize(lights[i].target - lights[i].position); + if (lights[i].type == LIGHT_POINT) light = normalize(lights[i].position - fragPosition); + + float NdotL = max(dot(normal, light), 0.0); + lightDot += lights[i].color.rgb*NdotL; + + float specCo = 0.0; + if (NdotL > 0.0) specCo = pow(max(0.0, dot(viewD, reflect(-(light), normal))), 16.0); // Shine: 16.0 + specular += specCo; + } + } + + vec4 finalColor = (texelColor*((colDiffuse + vec4(specular,1))*vec4(lightDot, 1.0))); + finalColor += texelColor*(ambient/10.0); + + // Gamma correction + finalColor = pow(finalColor, vec4(1.0/2.2)); + + // Fog calculation + float dist = length(viewPos - fragPosition); + + // these could be parameters... + const vec4 fogColor = vec4(0.5, 0.5, 0.5, 1.0); + //const float fogDensity = 0.16; + + // Exponential fog + float fogFactor = 1.0/exp((dist*fogDensity)*(dist*fogDensity)); + + // Linear fog (less nice) + //const float fogStart = 2.0; + //const float fogEnd = 10.0; + //float fogFactor = (fogEnd - dist)/(fogEnd - fogStart); + + fogFactor = clamp(fogFactor, 0.0, 1.0); + + gl_FragColor = mix(fogColor, finalColor, fogFactor); +} diff --git a/assets/shaders/glsl100/grayscale.fs b/assets/shaders/glsl100/grayscale.fs new file mode 100644 index 00000000..15174ea5 --- /dev/null +++ b/assets/shaders/glsl100/grayscale.fs @@ -0,0 +1,25 @@ +#version 100 + +precision mediump float; + +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +// NOTE: Add here your custom variables + +void main() +{ + // Texel color fetching from texture sampler + vec4 texelColor = texture2D(texture0, fragTexCoord)*colDiffuse*fragColor; + + // Convert texel color to grayscale using NTSC conversion weights + float gray = dot(texelColor.rgb, vec3(0.299, 0.587, 0.114)); + + // Calculate final fragment color + gl_FragColor = vec4(gray, gray, gray, texelColor.a); +} \ No newline at end of file diff --git a/assets/shaders/glsl100/julia_set.fs b/assets/shaders/glsl100/julia_set.fs new file mode 100644 index 00000000..bce25db1 --- /dev/null +++ b/assets/shaders/glsl100/julia_set.fs @@ -0,0 +1,83 @@ +#version 100 + +precision mediump float; + +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; + +uniform vec2 screenDims; // Dimensions of the screen +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 MAX_ITERATIONS = 48; // Max iterations to do + +// 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 MAX_ITERATIONS is for. + Then we can divide the iterations by the MAX_ITERATIONS 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 + offset.x/screenDims.x)*2.5/zoom, (fragTexCoord.y + offset.y/screenDims.y)*1.5/zoom); + + 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(MAX_ITERATIONS); + + // 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, 1.0, 1.0)), 1.0); +} diff --git a/assets/shaders/glsl100/lighting.fs b/assets/shaders/glsl100/lighting.fs new file mode 100644 index 00000000..5e4ff64c --- /dev/null +++ b/assets/shaders/glsl100/lighting.fs @@ -0,0 +1,81 @@ +#version 100 + +precision mediump float; + +// Input vertex attributes (from vertex shader) +varying vec3 fragPosition; +varying vec2 fragTexCoord; +varying vec4 fragColor; +varying vec3 fragNormal; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +// NOTE: Add here your custom variables + +#define MAX_LIGHTS 4 +#define LIGHT_DIRECTIONAL 0 +#define LIGHT_POINT 1 + +struct MaterialProperty { + vec3 color; + int useSampler; + sampler2D sampler; +}; + +struct Light { + int enabled; + int type; + vec3 position; + vec3 target; + vec4 color; +}; + +// Input lighting values +uniform Light lights[MAX_LIGHTS]; +uniform vec4 ambient; +uniform vec3 viewPos; + +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); + + // NOTE: Implement here your fragment shader code + + for (int i = 0; i < MAX_LIGHTS; i++) + { + if (lights[i].enabled == 1) + { + vec3 light = vec3(0.0); + + if (lights[i].type == LIGHT_DIRECTIONAL) + { + light = -normalize(lights[i].target - lights[i].position); + } + + if (lights[i].type == LIGHT_POINT) + { + light = normalize(lights[i].position - fragPosition); + } + + float NdotL = max(dot(normal, light), 0.0); + lightDot += lights[i].color.rgb*NdotL; + + float specCo = 0.0; + if (NdotL > 0.0) specCo = pow(max(0.0, dot(viewD, reflect(-(light), normal))), 16.0); // 16 refers to shine + specular += specCo; + } + } + + vec4 finalColor = (texelColor*((colDiffuse + vec4(specular, 1.0))*vec4(lightDot, 1.0))); + finalColor += texelColor*(ambient/10.0); + + // Gamma correction + gl_FragColor = pow(finalColor, vec4(1.0/2.2)); +} diff --git a/assets/shaders/glsl100/mask.fs b/assets/shaders/glsl100/mask.fs new file mode 100644 index 00000000..20710620 --- /dev/null +++ b/assets/shaders/glsl100/mask.fs @@ -0,0 +1,24 @@ +#version 100 + +precision mediump float; + +// 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 here your custom variables + +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; +} diff --git a/assets/shaders/glsl100/palette_switch.fs b/assets/shaders/glsl100/palette_switch.fs new file mode 100644 index 00000000..e5b038d6 --- /dev/null +++ b/assets/shaders/glsl100/palette_switch.fs @@ -0,0 +1,41 @@ +#version 100 + +precision mediump float; + +const int colors = 8; + +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform ivec3 palette[colors]; + +void main() +{ + // Texel color fetching from texture sampler + vec4 texelColor = texture2D(texture0, fragTexCoord)*fragColor; + + // Convert the (normalized) texel color RED component (GB would work, too) + // to the palette index by scaling up from [0, 1] to [0, 255]. + int index = int(texelColor.r*255.0); + + ivec3 color = ivec3(0); + + // NOTE: On GLSL 100 we are not allowed to index a uniform array by a variable value, + // a constantmust be used, so this logic... + if (index == 0) color = palette[0]; + else if (index == 1) color = palette[1]; + else if (index == 2) color = palette[2]; + else if (index == 3) color = palette[3]; + else if (index == 4) color = palette[4]; + else if (index == 5) color = palette[5]; + else if (index == 6) color = palette[6]; + else if (index == 7) color = palette[7]; + + // Calculate final fragment color. Note that the palette color components + // are defined in the range [0, 255] and need to be normalized to [0, 1] + // for OpenGL to work. + gl_FragColor = vec4(float(color.x)/255.0, float(color.y)/255.0, float(color.z)/255.0, texelColor.a); +} diff --git a/assets/shaders/glsl100/pixelizer.fs b/assets/shaders/glsl100/pixelizer.fs new file mode 100644 index 00000000..44fb0ca2 --- /dev/null +++ b/assets/shaders/glsl100/pixelizer.fs @@ -0,0 +1,32 @@ +#version 100 + +precision mediump float; + +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +// NOTE: Add here your custom variables + +// NOTE: Render size values must be passed from code +const float renderWidth = 800.0; +const float renderHeight = 450.0; + +float pixelWidth = 5.0; +float pixelHeight = 5.0; + +void main() +{ + float dx = pixelWidth*(1.0/renderWidth); + float dy = pixelHeight*(1.0/renderHeight); + + vec2 coord = vec2(dx*floor(fragTexCoord.x/dx), dy*floor(fragTexCoord.y/dy)); + + vec3 tc = texture2D(texture0, coord).rgb; + + gl_FragColor = vec4(tc, 1.0); +} \ No newline at end of file diff --git a/assets/shaders/glsl100/posterization.fs b/assets/shaders/glsl100/posterization.fs new file mode 100644 index 00000000..a7942c82 --- /dev/null +++ b/assets/shaders/glsl100/posterization.fs @@ -0,0 +1,29 @@ +#version 100 + +precision mediump float; + +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +// NOTE: Add here your custom variables + +float gamma = 0.6; +float numColors = 8.0; + +void main() +{ + vec3 color = texture2D(texture0, fragTexCoord.xy).rgb; + + color = pow(color, vec3(gamma, gamma, gamma)); + color = color*numColors; + color = floor(color); + color = color/numColors; + color = pow(color, vec3(1.0/gamma)); + + gl_FragColor = vec4(color, 1.0); +} \ No newline at end of file diff --git a/assets/shaders/glsl100/predator.fs b/assets/shaders/glsl100/predator.fs new file mode 100644 index 00000000..37dc0bdf --- /dev/null +++ b/assets/shaders/glsl100/predator.fs @@ -0,0 +1,31 @@ +#version 100 + +precision mediump float; + +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +// NOTE: Add here your custom variables + +void main() +{ + vec3 color = texture2D(texture0, fragTexCoord).rgb; + vec3 colors[3]; + colors[0] = vec3(0.0, 0.0, 1.0); + colors[1] = vec3(1.0, 1.0, 0.0); + colors[2] = vec3(1.0, 0.0, 0.0); + + float lum = (color.r + color.g + color.b)/3.0; + + vec3 tc = vec3(0.0, 0.0, 0.0); + + if (lum < 0.5) tc = mix(colors[0], colors[1], lum/0.5); + else tc = mix(colors[1], colors[2], (lum - 0.5)/0.5); + + gl_FragColor = vec4(tc, 1.0); +} \ No newline at end of file diff --git a/assets/shaders/glsl100/raymarching.fs b/assets/shaders/glsl100/raymarching.fs new file mode 100644 index 00000000..7535086b --- /dev/null +++ b/assets/shaders/glsl100/raymarching.fs @@ -0,0 +1,429 @@ +#version 100 + +precision mediump float; + +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; + +uniform vec3 viewEye; +uniform vec3 viewCenter; +uniform float runTime; +uniform vec2 resolution; + +// The MIT License +// Copyright © 2013 Inigo Quilez +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +// A list of useful distance function to simple primitives, and an example on how to +// do some interesting boolean operations, repetition and displacement. +// +// More info here: http://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm + +#define AA 1 // make this 1 is your machine is too slow + +//------------------------------------------------------------------ + +float sdPlane( vec3 p ) +{ + return p.y; +} + +float sdSphere( vec3 p, float s ) +{ + return length(p)-s; +} + +float sdBox( vec3 p, vec3 b ) +{ + vec3 d = abs(p) - b; + return min(max(d.x,max(d.y,d.z)),0.0) + length(max(d,0.0)); +} + +float sdEllipsoid( in vec3 p, in vec3 r ) +{ + return (length( p/r ) - 1.0) * min(min(r.x,r.y),r.z); +} + +float udRoundBox( vec3 p, vec3 b, float r ) +{ + return length(max(abs(p)-b,0.0))-r; +} + +float sdTorus( vec3 p, vec2 t ) +{ + return length( vec2(length(p.xz)-t.x,p.y) )-t.y; +} + +float sdHexPrism( vec3 p, vec2 h ) +{ + vec3 q = abs(p); +#if 0 + return max(q.z-h.y,max((q.x*0.866025+q.y*0.5),q.y)-h.x); +#else + float d1 = q.z-h.y; + float d2 = max((q.x*0.866025+q.y*0.5),q.y)-h.x; + return length(max(vec2(d1,d2),0.0)) + min(max(d1,d2), 0.); +#endif +} + +float sdCapsule( vec3 p, vec3 a, vec3 b, float r ) +{ + vec3 pa = p-a, ba = b-a; + float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 ); + return length( pa - ba*h ) - r; +} + +float sdEquilateralTriangle( in vec2 p ) +{ + const float k = sqrt(3.0); + p.x = abs(p.x) - 1.0; + p.y = p.y + 1.0/k; + if( p.x + k*p.y > 0.0 ) p = vec2( p.x - k*p.y, -k*p.x - p.y )/2.0; + p.x += 2.0 - 2.0*clamp( (p.x+2.0)/2.0, 0.0, 1.0 ); + return -length(p)*sign(p.y); +} + +float sdTriPrism( vec3 p, vec2 h ) +{ + vec3 q = abs(p); + float d1 = q.z-h.y; +#if 1 + // distance bound + float d2 = max(q.x*0.866025+p.y*0.5,-p.y)-h.x*0.5; +#else + // correct distance + h.x *= 0.866025; + float d2 = sdEquilateralTriangle(p.xy/h.x)*h.x; +#endif + return length(max(vec2(d1,d2),0.0)) + min(max(d1,d2), 0.); +} + +float sdCylinder( vec3 p, vec2 h ) +{ + vec2 d = abs(vec2(length(p.xz),p.y)) - h; + return min(max(d.x,d.y),0.0) + length(max(d,0.0)); +} + +float sdCone( in vec3 p, in vec3 c ) +{ + vec2 q = vec2( length(p.xz), p.y ); + float d1 = -q.y-c.z; + float d2 = max( dot(q,c.xy), q.y); + return length(max(vec2(d1,d2),0.0)) + min(max(d1,d2), 0.); +} + +float sdConeSection( in vec3 p, in float h, in float r1, in float r2 ) +{ + float d1 = -p.y - h; + float q = p.y - h; + float si = 0.5*(r1-r2)/h; + float d2 = max( sqrt( dot(p.xz,p.xz)*(1.0-si*si)) + q*si - r2, q ); + return length(max(vec2(d1,d2),0.0)) + min(max(d1,d2), 0.); +} + +float sdPryamid4(vec3 p, vec3 h ) // h = { cos a, sin a, height } +{ + // Tetrahedron = Octahedron - Cube + float box = sdBox( p - vec3(0,-2.0*h.z,0), vec3(2.0*h.z) ); + + float d = 0.0; + d = max( d, abs( dot(p, vec3( -h.x, h.y, 0 )) )); + d = max( d, abs( dot(p, vec3( h.x, h.y, 0 )) )); + d = max( d, abs( dot(p, vec3( 0, h.y, h.x )) )); + d = max( d, abs( dot(p, vec3( 0, h.y,-h.x )) )); + float octa = d - h.z; + return max(-box,octa); // Subtraction + } + +float length2( vec2 p ) +{ + return sqrt( p.x*p.x + p.y*p.y ); +} + +float length6( vec2 p ) +{ + p = p*p*p; p = p*p; + return pow( p.x + p.y, 1.0/6.0 ); +} + +float length8( vec2 p ) +{ + p = p*p; p = p*p; p = p*p; + return pow( p.x + p.y, 1.0/8.0 ); +} + +float sdTorus82( vec3 p, vec2 t ) +{ + vec2 q = vec2(length2(p.xz)-t.x,p.y); + return length8(q)-t.y; +} + +float sdTorus88( vec3 p, vec2 t ) +{ + vec2 q = vec2(length8(p.xz)-t.x,p.y); + return length8(q)-t.y; +} + +float sdCylinder6( vec3 p, vec2 h ) +{ + return max( length6(p.xz)-h.x, abs(p.y)-h.y ); +} + +//------------------------------------------------------------------ + +float opS( float d1, float d2 ) +{ + return max(-d2,d1); +} + +vec2 opU( vec2 d1, vec2 d2 ) +{ + return (d1.x0.0 ) tmax = min( tmax, tp1 ); + float tp2 = (1.6-ro.y)/rd.y; if( tp2>0.0 ) { if( ro.y>1.6 ) tmin = max( tmin, tp2 ); + else tmax = min( tmax, tp2 ); } +#endif + + float t = tmin; + float m = -1.0; + for( int i=0; i<64; i++ ) + { + float precis = 0.0005*t; + vec2 res = map( ro+rd*t ); + if( res.xtmax ) break; + t += res.x; + m = res.y; + } + + if( t>tmax ) m=-1.0; + return vec2( t, m ); +} + + +float calcSoftshadow( in vec3 ro, in vec3 rd, in float mint, in float tmax ) +{ + float res = 1.0; + float t = mint; + for( int i=0; i<16; i++ ) + { + float h = map( ro + rd*t ).x; + res = min( res, 8.0*h/t ); + t += clamp( h, 0.02, 0.10 ); + if( h<0.001 || t>tmax ) break; + } + return clamp( res, 0.0, 1.0 ); +} + +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 ); + /* + vec3 eps = vec3( 0.0005, 0.0, 0.0 ); + vec3 nor = vec3( + map(pos+eps.xyy).x - map(pos-eps.xyy).x, + map(pos+eps.yxy).x - map(pos-eps.yxy).x, + map(pos+eps.yyx).x - map(pos-eps.yyx).x ); + return normalize(nor); + */ +} + +float calcAO( in vec3 pos, in vec3 nor ) +{ + float occ = 0.0; + float sca = 1.0; + for( int i=0; i<5; i++ ) + { + float hr = 0.01 + 0.12*float(i)/4.0; + vec3 aopos = nor * hr + pos; + float dd = map( aopos ).x; + occ += -(dd-hr)*sca; + sca *= 0.95; + } + return clamp( 1.0 - 3.0*occ, 0.0, 1.0 ); +} + +// http://iquilezles.org/www/articles/checkerfiltering/checkerfiltering.htm +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; +} + +vec3 render( in vec3 ro, in vec3 rd ) +{ + vec3 col = vec3(0.7, 0.9, 1.0) +rd.y*0.8; + vec2 res = castRay(ro,rd); + float t = res.x; + float m = res.y; + if( m>-0.5 ) + { + vec3 pos = ro + t*rd; + vec3 nor = calcNormal( pos ); + vec3 ref = reflect( rd, nor ); + + // material + col = 0.45 + 0.35*sin( vec3(0.05,0.08,0.10)*(m-1.0) ); + if( m<1.5 ) + { + + float f = checkersGradBox( 5.0*pos.xz ); + col = 0.3 + f*vec3(0.1); + } + + // lighting + float occ = calcAO( pos, nor ); + vec3 lig = normalize( vec3(cos(-0.4 * runTime), sin(0.7 * runTime), -0.6) ); + vec3 hal = normalize( lig-rd ); + float amb = clamp( 0.5+0.5*nor.y, 0.0, 1.0 ); + float dif = clamp( dot( nor, lig ), 0.0, 1.0 ); + float bac = clamp( dot( nor, normalize(vec3(-lig.x,0.0,-lig.z))), 0.0, 1.0 )*clamp( 1.0-pos.y,0.0,1.0); + float dom = smoothstep( -0.1, 0.1, ref.y ); + float fre = pow( clamp(1.0+dot(nor,rd),0.0,1.0), 2.0 ); + + dif *= calcSoftshadow( pos, lig, 0.02, 2.5 ); + dom *= calcSoftshadow( pos, ref, 0.02, 2.5 ); + + float spe = pow( clamp( dot( nor, hal ), 0.0, 1.0 ),16.0)* + dif * + (0.04 + 0.96*pow( clamp(1.0+dot(hal,rd),0.0,1.0), 5.0 )); + + vec3 lin = vec3(0.0); + lin += 1.30*dif*vec3(1.00,0.80,0.55); + lin += 0.40*amb*vec3(0.40,0.60,1.00)*occ; + lin += 0.50*dom*vec3(0.40,0.60,1.00)*occ; + lin += 0.50*bac*vec3(0.25,0.25,0.25)*occ; + lin += 0.25*fre*vec3(1.00,1.00,1.00)*occ; + col = col*lin; + col += 10.00*spe*vec3(1.00,0.90,0.70); + + col = mix( col, vec3(0.8,0.9,1.0), 1.0-exp( -0.0002*t*t*t ) ); + } + + return vec3( clamp(col,0.0,1.0) ); +} + +mat3 setCamera( in vec3 ro, in vec3 ta, float cr ) +{ + vec3 cw = normalize(ta-ro); + vec3 cp = vec3(sin(cr), cos(cr),0.0); + vec3 cu = normalize( cross(cw,cp) ); + vec3 cv = normalize( cross(cu,cw) ); + return mat3( cu, cv, cw ); +} + +void main() +{ + vec3 tot = vec3(0.0); +#if AA>1 + for( int m=0; m1 + } + tot /= float(AA*AA); +#endif + + gl_FragColor = vec4( tot, 1.0 ); +} diff --git a/assets/shaders/glsl100/reload.fs b/assets/shaders/glsl100/reload.fs new file mode 100644 index 00000000..eda00ae3 --- /dev/null +++ b/assets/shaders/glsl100/reload.fs @@ -0,0 +1,39 @@ +#version 100 + +precision mediump float; + +// 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); +} diff --git a/assets/shaders/glsl100/scanlines.fs b/assets/shaders/glsl100/scanlines.fs new file mode 100644 index 00000000..ce649e1a --- /dev/null +++ b/assets/shaders/glsl100/scanlines.fs @@ -0,0 +1,44 @@ +#version 100 + +precision mediump float; + +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +// NOTE: Add here your custom variables + +float offset = 0.0; +float frequency = 450.0/3.0; + +uniform float time; + +void main() +{ +/* + // Scanlines method 1 + float tval = 0; //time + vec2 uv = 0.5 + (fragTexCoord - 0.5)*(0.9 + 0.01*sin(0.5*tval)); + + vec4 color = texture2D(texture0, fragTexCoord); + + color = clamp(color*0.5 + 0.5*color*color*1.2, 0.0, 1.0); + color *= 0.5 + 0.5*16.0*uv.x*uv.y*(1.0 - uv.x)*(1.0 - uv.y); + color *= vec4(0.8, 1.0, 0.7, 1); + color *= 0.9 + 0.1*sin(10.0*tval + uv.y*1000.0); + color *= 0.97 + 0.03*sin(110.0*tval); + + fragColor = color; +*/ + // Scanlines method 2 + float globalPos = (fragTexCoord.y + offset) * frequency; + float wavePos = cos((fract(globalPos) - 0.5)*3.14); + + vec4 color = texture2D(texture0, fragTexCoord); + + gl_FragColor = mix(vec4(0.0, 0.3, 0.0, 0.0), color, wavePos); +} \ No newline at end of file diff --git a/assets/shaders/glsl100/sobel.fs b/assets/shaders/glsl100/sobel.fs new file mode 100644 index 00000000..3e5c22dd --- /dev/null +++ b/assets/shaders/glsl100/sobel.fs @@ -0,0 +1,40 @@ +#version 100 + +precision mediump float; + +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +// NOTE: Add here your custom variables +vec2 resolution = vec2(800.0, 450.0); + +void main() +{ + float x = 1.0/resolution.x; + float y = 1.0/resolution.y; + + vec4 horizEdge = vec4(0.0); + horizEdge -= texture2D(texture0, vec2(fragTexCoord.x - x, fragTexCoord.y - y))*1.0; + horizEdge -= texture2D(texture0, vec2(fragTexCoord.x - x, fragTexCoord.y ))*2.0; + horizEdge -= texture2D(texture0, vec2(fragTexCoord.x - x, fragTexCoord.y + y))*1.0; + horizEdge += texture2D(texture0, vec2(fragTexCoord.x + x, fragTexCoord.y - y))*1.0; + horizEdge += texture2D(texture0, vec2(fragTexCoord.x + x, fragTexCoord.y ))*2.0; + horizEdge += texture2D(texture0, vec2(fragTexCoord.x + x, fragTexCoord.y + y))*1.0; + + vec4 vertEdge = vec4(0.0); + vertEdge -= texture2D(texture0, vec2(fragTexCoord.x - x, fragTexCoord.y - y))*1.0; + vertEdge -= texture2D(texture0, vec2(fragTexCoord.x , fragTexCoord.y - y))*2.0; + vertEdge -= texture2D(texture0, vec2(fragTexCoord.x + x, fragTexCoord.y - y))*1.0; + vertEdge += texture2D(texture0, vec2(fragTexCoord.x - x, fragTexCoord.y + y))*1.0; + vertEdge += texture2D(texture0, vec2(fragTexCoord.x , fragTexCoord.y + y))*2.0; + vertEdge += texture2D(texture0, vec2(fragTexCoord.x + x, fragTexCoord.y + y))*1.0; + + vec3 edge = sqrt((horizEdge.rgb*horizEdge.rgb) + (vertEdge.rgb*vertEdge.rgb)); + + gl_FragColor = vec4(edge, texture2D(texture0, fragTexCoord).a); +} \ No newline at end of file diff --git a/assets/shaders/glsl100/spotlight.fs b/assets/shaders/glsl100/spotlight.fs new file mode 100644 index 00000000..c8d83038 --- /dev/null +++ b/assets/shaders/glsl100/spotlight.fs @@ -0,0 +1,77 @@ +#version 100 + +precision mediump float; + +#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); +} diff --git a/assets/shaders/glsl100/swirl.fs b/assets/shaders/glsl100/swirl.fs new file mode 100644 index 00000000..7807b807 --- /dev/null +++ b/assets/shaders/glsl100/swirl.fs @@ -0,0 +1,46 @@ +#version 100 + +precision mediump float; + +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +// NOTE: Add here your custom variables + +// NOTE: Render size values should be passed from code +const float renderWidth = 800.0; +const float renderHeight = 450.0; + +float radius = 250.0; +float angle = 0.8; + +uniform vec2 center; + +void main() +{ + vec2 texSize = vec2(renderWidth, renderHeight); + vec2 tc = fragTexCoord*texSize; + tc -= center; + + float dist = length(tc); + + if (dist < radius) + { + float percent = (radius - dist)/radius; + float theta = percent*percent*angle*8.0; + float s = sin(theta); + float c = cos(theta); + + tc = vec2(dot(tc, vec2(c, -s)), dot(tc, vec2(s, c))); + } + + tc += center; + vec4 color = texture2D(texture0, tc/texSize)*colDiffuse*fragColor;; + + gl_FragColor = vec4(color.rgb, 1.0);; +} diff --git a/assets/shaders/glsl100/wave.fs b/assets/shaders/glsl100/wave.fs new file mode 100644 index 00000000..50c4e02f --- /dev/null +++ b/assets/shaders/glsl100/wave.fs @@ -0,0 +1,36 @@ +#version 100 + +precision mediump float; + +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +uniform float secondes; + +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) + (secondes * speedX)) * ampX * pixelWidth; + p.y += sin((fragTexCoord.x - boxLeft) * freqY * aspect / ( pixelHeight * 750.0) + (secondes * speedY)) * ampY * pixelHeight; + + gl_FragColor = texture2D(texture0, p)*colDiffuse*fragColor; +} diff --git a/assets/shaders/glsl120/base.fs b/assets/shaders/glsl120/base.fs new file mode 100644 index 00000000..18799f95 --- /dev/null +++ b/assets/shaders/glsl120/base.fs @@ -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 vec4 colDiffuse; + +// NOTE: Add here your custom variables +uniform vec2 resolution = vec2(800, 450); + +void main() +{ + // Texel color fetching from texture sampler + vec4 texelColor = texture2D(texture0, fragTexCoord); + + // NOTE: Implement here your fragment shader code + + gl_FragColor = texelColor*colDiffuse; +} \ No newline at end of file diff --git a/assets/shaders/glsl120/base.vs b/assets/shaders/glsl120/base.vs new file mode 100644 index 00000000..674153d8 --- /dev/null +++ b/assets/shaders/glsl120/base.vs @@ -0,0 +1,26 @@ +#version 120 + +// Input vertex attributes +attribute vec3 vertexPosition; +attribute vec2 vertexTexCoord; +attribute vec3 vertexNormal; +attribute vec4 vertexColor; + +// Input uniform values +uniform mat4 mvp; + +// Output vertex attributes (to fragment shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; + +// NOTE: Add here your custom variables + +void main() +{ + // Send vertex attributes to fragment shader + fragTexCoord = vertexTexCoord; + fragColor = vertexColor; + + // Calculate final vertex position + gl_Position = mvp*vec4(vertexPosition, 1.0); +} \ No newline at end of file diff --git a/assets/shaders/glsl120/base_lighting.vs b/assets/shaders/glsl120/base_lighting.vs new file mode 100644 index 00000000..678c60e9 --- /dev/null +++ b/assets/shaders/glsl120/base_lighting.vs @@ -0,0 +1,59 @@ +#version 120 + +// Input vertex attributes +attribute vec3 vertexPosition; +attribute vec2 vertexTexCoord; +attribute vec3 vertexNormal; +attribute vec4 vertexColor; + +// Input uniform values +uniform mat4 mvp; +uniform mat4 matModel; + +// Output vertex attributes (to fragment shader) +varying vec3 fragPosition; +varying vec2 fragTexCoord; +varying vec4 fragColor; +varying vec3 fragNormal; + +// NOTE: Add here your custom variables + +// 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() +{ + // Send vertex attributes to fragment shader + fragPosition = vec3(matModel*vec4(vertexPosition, 1.0)); + fragTexCoord = vertexTexCoord; + fragColor = vertexColor; + + mat3 normalMatrix = transpose(inverse(mat3(matModel))); + fragNormal = normalize(normalMatrix*vertexNormal); + + // Calculate final vertex position + gl_Position = mvp*vec4(vertexPosition, 1.0); +} diff --git a/assets/shaders/glsl120/bloom.fs b/assets/shaders/glsl120/bloom.fs new file mode 100644 index 00000000..f97c18ed --- /dev/null +++ b/assets/shaders/glsl120/bloom.fs @@ -0,0 +1,37 @@ +#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 here your custom variables + +const vec2 size = vec2(800, 450); // render size +const float samples = 5.0; // pixels per axis; higher = bigger glow, worse performance +const float quality = 2.5; // lower = smaller glow, better quality + +void main() +{ + vec4 sum = vec4(0); + vec2 sizeFactor = vec2(1)/size*quality; + + // Texel color fetching from texture sampler + vec4 source = texture2D(texture0, fragTexCoord); + + const int range = 2; // should be = (samples - 1)/2; + + for (int x = -range; x <= range; x++) + { + for (int y = -range; y <= range; y++) + { + sum += texture2D(texture0, fragTexCoord + vec2(x, y)*sizeFactor); + } + } + + // Calculate final fragment color + gl_FragColor = ((sum/(samples*samples)) + source)*colDiffuse; +} \ No newline at end of file diff --git a/assets/shaders/glsl120/blur.fs b/assets/shaders/glsl120/blur.fs new file mode 100644 index 00000000..99cddfc9 --- /dev/null +++ b/assets/shaders/glsl120/blur.fs @@ -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; + +// NOTE: Add here your custom variables + +// NOTE: Render size values must be passed from code +const float renderWidth = 800.0; +const float renderHeight = 450.0; + +vec3 offset = vec3(0.0, 1.3846153846, 3.2307692308); +vec3 weight = vec3(0.2270270270, 0.3162162162, 0.0702702703); + +void main() +{ + // Texel color fetching from texture sampler + vec3 tc = texture2D(texture0, fragTexCoord).rgb*weight.x; + + tc += texture2D(texture0, fragTexCoord + vec2(offset.y)/renderWidth, 0.0).rgb*weight.y; + tc += texture2D(texture0, fragTexCoord - vec2(offset.y)/renderWidth, 0.0).rgb*weight.y; + + tc += texture2D(texture0, fragTexCoord + vec2(offset.z)/renderWidth, 0.0).rgb*weight.z; + tc += texture2D(texture0, fragTexCoord - vec2(offset.z)/renderWidth, 0.0).rgb*weight.z; + + gl_FragColor = vec4(tc, 1.0); +} \ No newline at end of file diff --git a/assets/shaders/glsl120/cross_hatching.fs b/assets/shaders/glsl120/cross_hatching.fs new file mode 100644 index 00000000..46514120 --- /dev/null +++ b/assets/shaders/glsl120/cross_hatching.fs @@ -0,0 +1,45 @@ +# 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 here your custom variables + +float hatchOffsetY = 5.0; +float lumThreshold01 = 0.9; +float lumThreshold02 = 0.7; +float lumThreshold03 = 0.5; +float lumThreshold04 = 0.3; + +void main() +{ + vec3 tc = vec3(1.0, 1.0, 1.0); + float lum = length(texture2D(texture0, fragTexCoord).rgb); + + if (lum < lumThreshold01) + { + if (mod(gl_FragCoord.x + gl_FragCoord.y, 10.0) == 0.0) tc = vec3(0.0, 0.0, 0.0); + } + + if (lum < lumThreshold02) + { + if (mod(gl_FragCoord .x - gl_FragCoord .y, 10.0) == 0.0) tc = vec3(0.0, 0.0, 0.0); + } + + if (lum < lumThreshold03) + { + if (mod(gl_FragCoord .x + gl_FragCoord .y - hatchOffsetY, 10.0) == 0.0) tc = vec3(0.0, 0.0, 0.0); + } + + if (lum < lumThreshold04) + { + if (mod(gl_FragCoord .x - gl_FragCoord .y - hatchOffsetY, 10.0) == 0.0) tc = vec3(0.0, 0.0, 0.0); + } + + gl_FragColor = vec4(tc, 1.0); +} \ No newline at end of file diff --git a/assets/shaders/glsl120/cross_stitching.fs b/assets/shaders/glsl120/cross_stitching.fs new file mode 100644 index 00000000..dee4617e --- /dev/null +++ b/assets/shaders/glsl120/cross_stitching.fs @@ -0,0 +1,55 @@ +# 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 here your custom variables + +// NOTE: Render size values must be passed from code +const float renderWidth = 800.0; +const float renderHeight = 450.0; + +float stitchingSize = 6.0; +int invert = 0; + +vec4 PostFX(sampler2D tex, vec2 uv) +{ + vec4 c = vec4(0.0); + float size = stitchingSize; + vec2 cPos = uv * vec2(renderWidth, renderHeight); + vec2 tlPos = floor(cPos / vec2(size, size)); + tlPos *= size; + + int remX = int(mod(cPos.x, size)); + int remY = int(mod(cPos.y, size)); + + if (remX == 0 && remY == 0) tlPos = cPos; + + vec2 blPos = tlPos; + blPos.y += (size - 1.0); + + if ((remX == remY) || (((int(cPos.x) - int(blPos.x)) == (int(blPos.y) - int(cPos.y))))) + { + if (invert == 1) c = vec4(0.2, 0.15, 0.05, 1.0); + else c = texture2D(tex, tlPos * vec2(1.0/renderWidth, 1.0/renderHeight)) * 1.4; + } + else + { + if (invert == 1) c = texture2D(tex, tlPos * vec2(1.0/renderWidth, 1.0/renderHeight)) * 1.4; + else c = vec4(0.0, 0.0, 0.0, 1.0); + } + + return c; +} + +void main() +{ + vec3 tc = PostFX(texture0, fragTexCoord).rgb; + + gl_FragColor = vec4(tc, 1.0); +} \ No newline at end of file diff --git a/assets/shaders/glsl120/distortion.fs b/assets/shaders/glsl120/distortion.fs new file mode 100644 index 00000000..f9d7f1e5 --- /dev/null +++ b/assets/shaders/glsl120/distortion.fs @@ -0,0 +1,52 @@ +#version 120 + +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; + +// Input uniform values +uniform sampler2D texture0; + +// NOTE: Default parameters for Oculus Rift DK2 device +const vec2 LeftLensCenter = vec2(0.2863248, 0.5); +const vec2 RightLensCenter = vec2(0.7136753, 0.5); +const vec2 LeftScreenCenter = vec2(0.25, 0.5); +const vec2 RightScreenCenter = vec2(0.75, 0.5); +const vec2 Scale = vec2(0.25, 0.45); +const vec2 ScaleIn = vec2(4.0, 2.5); +const vec4 HmdWarpParam = vec4(1.0, 0.22, 0.24, 0.0); +const vec4 ChromaAbParam = vec4(0.996, -0.004, 1.014, 0.0); + +void main() +{ + // The following two variables need to be set per eye + vec2 LensCenter = fragTexCoord.x < 0.5 ? LeftLensCenter : RightLensCenter; + vec2 ScreenCenter = fragTexCoord.x < 0.5 ? LeftScreenCenter : RightScreenCenter; + + // Scales input texture coordinates for distortion: vec2 HmdWarp(vec2 fragTexCoord, vec2 LensCenter) + vec2 theta = (fragTexCoord - LensCenter)*ScaleIn; // Scales to [-1, 1] + float rSq = theta.x*theta.x + theta.y*theta.y; + vec2 theta1 = theta*(HmdWarpParam.x + HmdWarpParam.y*rSq + HmdWarpParam.z*rSq*rSq + HmdWarpParam.w*rSq*rSq*rSq); + //vec2 tc = LensCenter + Scale*theta1; + + // Detect whether blue texture coordinates are out of range since these will scaled out the furthest + vec2 thetaBlue = theta1*(ChromaAbParam.z + ChromaAbParam.w*rSq); + vec2 tcBlue = LensCenter + Scale*thetaBlue; + + if (any(bvec2(clamp(tcBlue, ScreenCenter - vec2(0.25, 0.5), ScreenCenter + vec2(0.25, 0.5)) - tcBlue))) gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); + else + { + // Do blue texture lookup + float blue = texture2D(texture0, tcBlue).b; + + // Do green lookup (no scaling) + vec2 tcGreen = LensCenter + Scale*theta1; + float green = texture2D(texture0, tcGreen).g; + + // Do red scale and lookup + vec2 thetaRed = theta1*(ChromaAbParam.x + ChromaAbParam.y*rSq); + vec2 tcRed = LensCenter + Scale*thetaRed; + float red = texture2D(texture0, tcRed).r; + + gl_FragColor = vec4(red, green, blue, 1.0); + } +} diff --git a/assets/shaders/glsl120/dream_vision.fs b/assets/shaders/glsl120/dream_vision.fs new file mode 100644 index 00000000..cb97b2bd --- /dev/null +++ b/assets/shaders/glsl120/dream_vision.fs @@ -0,0 +1,35 @@ +#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 here your custom variables + +void main() +{ + vec4 color = texture2D(texture0, fragTexCoord); + + color += texture2D(texture0, fragTexCoord + 0.001); + color += texture2D(texture0, fragTexCoord + 0.003); + color += texture2D(texture0, fragTexCoord + 0.005); + color += texture2D(texture0, fragTexCoord + 0.007); + color += texture2D(texture0, fragTexCoord + 0.009); + color += texture2D(texture0, fragTexCoord + 0.011); + + color += texture2D(texture0, fragTexCoord - 0.001); + color += texture2D(texture0, fragTexCoord - 0.003); + color += texture2D(texture0, fragTexCoord - 0.005); + color += texture2D(texture0, fragTexCoord - 0.007); + color += texture2D(texture0, fragTexCoord - 0.009); + color += texture2D(texture0, fragTexCoord - 0.011); + + color.rgb = vec3((color.r + color.g + color.b)/3.0); + color = color/9.5; + + gl_FragColor = color; +} \ No newline at end of file diff --git a/assets/shaders/glsl120/fisheye.fs b/assets/shaders/glsl120/fisheye.fs new file mode 100644 index 00000000..6f376ba3 --- /dev/null +++ b/assets/shaders/glsl120/fisheye.fs @@ -0,0 +1,41 @@ +#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 here your custom variables + +const float PI = 3.1415926535; + +void main() +{ + float aperture = 178.0; + float apertureHalf = 0.5 * aperture * (PI / 180.0); + float maxFactor = sin(apertureHalf); + + vec2 uv = vec2(0.0); + vec2 xy = 2.0 * fragTexCoord.xy - 1.0; + float d = length(xy); + + if (d < (2.0 - maxFactor)) + { + d = length(xy * maxFactor); + float z = sqrt(1.0 - d * d); + float r = atan(d, z) / PI; + float phi = atan(xy.y, xy.x); + + uv.x = r * cos(phi) + 0.5; + uv.y = r * sin(phi) + 0.5; + } + else + { + uv = fragTexCoord.xy; + } + + gl_FragColor = texture2D(texture0, uv); +} \ No newline at end of file diff --git a/assets/shaders/glsl120/fog.fs b/assets/shaders/glsl120/fog.fs new file mode 100644 index 00000000..fcd6ef95 --- /dev/null +++ b/assets/shaders/glsl120/fog.fs @@ -0,0 +1,92 @@ +#version 120 + +// Input vertex attributes (from vertex shader) +varying vec3 fragPosition; +varying vec2 fragTexCoord; +varying vec4 fragColor; +varying vec3 fragNormal; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +// NOTE: Add here your custom variables + +#define MAX_LIGHTS 4 +#define LIGHT_DIRECTIONAL 0 +#define LIGHT_POINT 1 + +struct MaterialProperty { + vec3 color; + int useSampler; + sampler2D sampler; +}; + +struct Light { + int enabled; + int type; + vec3 position; + vec3 target; + vec4 color; +}; + +// Input lighting values +uniform Light lights[MAX_LIGHTS]; +uniform vec4 ambient; +uniform vec3 viewPos; +uniform float fogDensity; + +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); + + // NOTE: Implement here your fragment shader code + + for (int i = 0; i < MAX_LIGHTS; i++) + { + if (lights[i].enabled == 1) + { + vec3 light = vec3(0.0); + + if (lights[i].type == LIGHT_DIRECTIONAL) light = -normalize(lights[i].target - lights[i].position); + if (lights[i].type == LIGHT_POINT) light = normalize(lights[i].position - fragPosition); + + float NdotL = max(dot(normal, light), 0.0); + lightDot += lights[i].color.rgb*NdotL; + + float specCo = 0.0; + if (NdotL > 0.0) specCo = pow(max(0.0, dot(viewD, reflect(-(light), normal))), 16.0); // Shine: 16.0 + specular += specCo; + } + } + + vec4 finalColor = (texelColor*((colDiffuse + vec4(specular,1))*vec4(lightDot, 1.0))); + finalColor += texelColor*(ambient/10.0); + + // Gamma correction + finalColor = pow(finalColor, vec4(1.0/2.2)); + + // Fog calculation + float dist = length(viewPos - fragPosition); + + // these could be parameters... + const vec4 fogColor = vec4(0.5, 0.5, 0.5, 1.0); + //const float fogDensity = 0.16; + + // Exponential fog + float fogFactor = 1.0/exp((dist*fogDensity)*(dist*fogDensity)); + + // Linear fog (less nice) + //const float fogStart = 2.0; + //const float fogEnd = 10.0; + //float fogFactor = (fogEnd - dist)/(fogEnd - fogStart); + + fogFactor = clamp(fogFactor, 0.0, 1.0); + + gl_FragColor = mix(fogColor, finalColor, fogFactor); +} diff --git a/assets/shaders/glsl120/grayscale.fs b/assets/shaders/glsl120/grayscale.fs new file mode 100644 index 00000000..4de60d22 --- /dev/null +++ b/assets/shaders/glsl120/grayscale.fs @@ -0,0 +1,23 @@ +#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 here your custom variables + +void main() +{ + // Texel color fetching from texture sampler + vec4 texelColor = texture2D(texture0, fragTexCoord)*colDiffuse*fragColor; + + // Convert texel color to grayscale using NTSC conversion weights + float gray = dot(texelColor.rgb, vec3(0.299, 0.587, 0.114)); + + // Calculate final fragment color + gl_FragColor = vec4(gray, gray, gray, texelColor.a); +} \ No newline at end of file diff --git a/assets/shaders/glsl120/palette_switch.fs b/assets/shaders/glsl120/palette_switch.fs new file mode 100644 index 00000000..ab3f79c7 --- /dev/null +++ b/assets/shaders/glsl120/palette_switch.fs @@ -0,0 +1,27 @@ +#version 120 + +const int colors = 8; + +// Input fragment attributes (from fragment shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform ivec3 palette[colors]; + +void main() +{ + // Texel color fetching from texture sampler + vec4 texelColor = texture(texture0, fragTexCoord) * fragColor; + + // Convert the (normalized) texel color RED component (GB would work, too) + // to the palette index by scaling up from [0, 1] to [0, 255]. + int index = int(texelColor.r * 255.0); + ivec3 color = palette[index]; + + // Calculate final fragment color. Note that the palette color components + // are defined in the range [0, 255] and need to be normalized to [0, 1] + // for OpenGL to work. + gl_FragColor = vec4(color / 255.0, texelColor.a); +} diff --git a/assets/shaders/glsl120/pixelizer.fs b/assets/shaders/glsl120/pixelizer.fs new file mode 100644 index 00000000..6f741faf --- /dev/null +++ b/assets/shaders/glsl120/pixelizer.fs @@ -0,0 +1,30 @@ +#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 here your custom variables + +// NOTE: Render size values must be passed from code +const float renderWidth = 800.0; +const float renderHeight = 450.0; + +float pixelWidth = 5.0; +float pixelHeight = 5.0; + +void main() +{ + float dx = pixelWidth*(1.0/renderWidth); + float dy = pixelHeight*(1.0/renderHeight); + + vec2 coord = vec2(dx*floor(fragTexCoord.x/dx), dy*floor(fragTexCoord.y/dy)); + + vec3 tc = texture2D(texture0, coord).rgb; + + gl_FragColor = vec4(tc, 1.0); +} \ No newline at end of file diff --git a/assets/shaders/glsl120/posterization.fs b/assets/shaders/glsl120/posterization.fs new file mode 100644 index 00000000..475b93a1 --- /dev/null +++ b/assets/shaders/glsl120/posterization.fs @@ -0,0 +1,27 @@ +#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 here your custom variables + +float gamma = 0.6; +float numColors = 8.0; + +void main() +{ + vec3 color = texture2D(texture0, fragTexCoord.xy).rgb; + + color = pow(color, vec3(gamma, gamma, gamma)); + color = color*numColors; + color = floor(color); + color = color/numColors; + color = pow(color, vec3(1.0/gamma)); + + gl_FragColor = vec4(color, 1.0); +} \ No newline at end of file diff --git a/assets/shaders/glsl120/predator.fs b/assets/shaders/glsl120/predator.fs new file mode 100644 index 00000000..2999cc8d --- /dev/null +++ b/assets/shaders/glsl120/predator.fs @@ -0,0 +1,29 @@ +#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 here your custom variables + +void main() +{ + vec3 color = texture2D(texture0, fragTexCoord).rgb; + vec3 colors[3]; + colors[0] = vec3(0.0, 0.0, 1.0); + colors[1] = vec3(1.0, 1.0, 0.0); + colors[2] = vec3(1.0, 0.0, 0.0); + + float lum = (color.r + color.g + color.b)/3.0; + + vec3 tc = vec3(0.0, 0.0, 0.0); + + if (lum < 0.5) tc = mix(colors[0], colors[1], lum/0.5); + else tc = mix(colors[1], colors[2], (lum - 0.5)/0.5); + + gl_FragColor = vec4(tc, 1.0); +} \ No newline at end of file diff --git a/assets/shaders/glsl120/scanlines.fs b/assets/shaders/glsl120/scanlines.fs new file mode 100644 index 00000000..929c79eb --- /dev/null +++ b/assets/shaders/glsl120/scanlines.fs @@ -0,0 +1,42 @@ +#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 here your custom variables + +float offset = 0.0; +float frequency = 450.0/3.0; + +uniform float time; + +void main() +{ +/* + // Scanlines method 1 + float tval = 0; //time + vec2 uv = 0.5 + (fragTexCoord - 0.5)*(0.9 + 0.01*sin(0.5*tval)); + + vec4 color = texture2D(texture0, fragTexCoord); + + color = clamp(color*0.5 + 0.5*color*color*1.2, 0.0, 1.0); + color *= 0.5 + 0.5*16.0*uv.x*uv.y*(1.0 - uv.x)*(1.0 - uv.y); + color *= vec4(0.8, 1.0, 0.7, 1); + color *= 0.9 + 0.1*sin(10.0*tval + uv.y*1000.0); + color *= 0.97 + 0.03*sin(110.0*tval); + + fragColor = color; +*/ + // Scanlines method 2 + float globalPos = (fragTexCoord.y + offset) * frequency; + float wavePos = cos((fract(globalPos) - 0.5)*3.14); + + vec4 color = texture2D(texture0, fragTexCoord); + + gl_FragColor = mix(vec4(0.0, 0.3, 0.0, 0.0), color, wavePos); +} \ No newline at end of file diff --git a/assets/shaders/glsl120/sobel.fs b/assets/shaders/glsl120/sobel.fs new file mode 100644 index 00000000..73e72703 --- /dev/null +++ b/assets/shaders/glsl120/sobel.fs @@ -0,0 +1,38 @@ +#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 here your custom variables +vec2 resolution = vec2(800.0, 450.0); + +void main() +{ + float x = 1.0/resolution.x; + float y = 1.0/resolution.y; + + vec4 horizEdge = vec4(0.0); + horizEdge -= texture2D(texture0, vec2(fragTexCoord.x - x, fragTexCoord.y - y))*1.0; + horizEdge -= texture2D(texture0, vec2(fragTexCoord.x - x, fragTexCoord.y ))*2.0; + horizEdge -= texture2D(texture0, vec2(fragTexCoord.x - x, fragTexCoord.y + y))*1.0; + horizEdge += texture2D(texture0, vec2(fragTexCoord.x + x, fragTexCoord.y - y))*1.0; + horizEdge += texture2D(texture0, vec2(fragTexCoord.x + x, fragTexCoord.y ))*2.0; + horizEdge += texture2D(texture0, vec2(fragTexCoord.x + x, fragTexCoord.y + y))*1.0; + + vec4 vertEdge = vec4(0.0); + vertEdge -= texture2D(texture0, vec2(fragTexCoord.x - x, fragTexCoord.y - y))*1.0; + vertEdge -= texture2D(texture0, vec2(fragTexCoord.x , fragTexCoord.y - y))*2.0; + vertEdge -= texture2D(texture0, vec2(fragTexCoord.x + x, fragTexCoord.y - y))*1.0; + vertEdge += texture2D(texture0, vec2(fragTexCoord.x - x, fragTexCoord.y + y))*1.0; + vertEdge += texture2D(texture0, vec2(fragTexCoord.x , fragTexCoord.y + y))*2.0; + vertEdge += texture2D(texture0, vec2(fragTexCoord.x + x, fragTexCoord.y + y))*1.0; + + vec3 edge = sqrt((horizEdge.rgb*horizEdge.rgb) + (vertEdge.rgb*vertEdge.rgb)); + + gl_FragColor = vec4(edge, texture2D(texture0, fragTexCoord).a); +} \ No newline at end of file diff --git a/assets/shaders/glsl120/swirl.fs b/assets/shaders/glsl120/swirl.fs new file mode 100644 index 00000000..0618e013 --- /dev/null +++ b/assets/shaders/glsl120/swirl.fs @@ -0,0 +1,44 @@ +#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 here your custom variables + +// NOTE: Render size values should be passed from code +const float renderWidth = 800; +const float renderHeight = 450; + +float radius = 250.0; +float angle = 0.8; + +uniform vec2 center; + +void main() +{ + vec2 texSize = vec2(renderWidth, renderHeight); + vec2 tc = fragTexCoord*texSize; + tc -= center; + + float dist = length(tc); + + if (dist < radius) + { + float percent = (radius - dist)/radius; + float theta = percent*percent*angle*8.0; + float s = sin(theta); + float c = cos(theta); + + tc = vec2(dot(tc, vec2(c, -s)), dot(tc, vec2(s, c))); + } + + tc += center; + vec4 color = texture2D(texture0, tc/texSize)*colDiffuse*fragColor;; + + gl_FragColor = vec4(color.rgb, 1.0);; +} \ No newline at end of file diff --git a/assets/shaders/glsl330/base.fs b/assets/shaders/glsl330/base.fs new file mode 100644 index 00000000..f1418df1 --- /dev/null +++ b/assets/shaders/glsl330/base.fs @@ -0,0 +1,25 @@ +#version 330 + +// Input vertex attributes (from vertex shader) +in vec2 fragTexCoord; +in vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +// Output fragment color +out vec4 finalColor; + +// NOTE: Add here your custom variables + +void main() +{ + // Texel color fetching from texture sampler + vec4 texelColor = texture(texture0, fragTexCoord); + + // NOTE: Implement here your fragment shader code + + finalColor = texelColor*colDiffuse; +} + diff --git a/assets/shaders/glsl330/base.vs b/assets/shaders/glsl330/base.vs new file mode 100644 index 00000000..f3099e82 --- /dev/null +++ b/assets/shaders/glsl330/base.vs @@ -0,0 +1,26 @@ +#version 330 + +// Input vertex attributes +in vec3 vertexPosition; +in vec2 vertexTexCoord; +in vec3 vertexNormal; +in vec4 vertexColor; + +// Input uniform values +uniform mat4 mvp; + +// Output vertex attributes (to fragment shader) +out vec2 fragTexCoord; +out vec4 fragColor; + +// NOTE: Add here your custom variables + +void main() +{ + // Send vertex attributes to fragment shader + fragTexCoord = vertexTexCoord; + fragColor = vertexColor; + + // Calculate final vertex position + gl_Position = mvp*vec4(vertexPosition, 1.0); +} \ No newline at end of file diff --git a/assets/shaders/glsl330/base_lighting.vs b/assets/shaders/glsl330/base_lighting.vs new file mode 100644 index 00000000..f8ec45f1 --- /dev/null +++ b/assets/shaders/glsl330/base_lighting.vs @@ -0,0 +1,32 @@ +#version 330 + +// Input vertex attributes +in vec3 vertexPosition; +in vec2 vertexTexCoord; +in vec3 vertexNormal; +in vec4 vertexColor; + +// Input uniform values +uniform mat4 mvp; +uniform mat4 matModel; +uniform mat4 matNormal; + +// Output vertex attributes (to fragment shader) +out vec3 fragPosition; +out vec2 fragTexCoord; +out vec4 fragColor; +out vec3 fragNormal; + +// NOTE: Add here your custom variables + +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); +} diff --git a/assets/shaders/glsl330/base_lighting_instanced.vs b/assets/shaders/glsl330/base_lighting_instanced.vs new file mode 100644 index 00000000..d198efe1 --- /dev/null +++ b/assets/shaders/glsl330/base_lighting_instanced.vs @@ -0,0 +1,36 @@ +#version 330 + +// Input vertex attributes +in vec3 vertexPosition; +in vec2 vertexTexCoord; +in vec3 vertexNormal; +in vec4 vertexColor; + +in mat4 instanceTransform; + +// Input uniform values +uniform mat4 mvp; +uniform mat4 matNormal; + +// Output vertex attributes (to fragment shader) +out vec3 fragPosition; +out vec2 fragTexCoord; +out vec4 fragColor; +out vec3 fragNormal; + +// NOTE: Add here your custom variables + +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); +} diff --git a/assets/shaders/glsl330/bloom.fs b/assets/shaders/glsl330/bloom.fs new file mode 100644 index 00000000..549cde8f --- /dev/null +++ b/assets/shaders/glsl330/bloom.fs @@ -0,0 +1,40 @@ +#version 330 + +// Input vertex attributes (from vertex shader) +in vec2 fragTexCoord; +in vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +// Output fragment color +out vec4 finalColor; + +// NOTE: Add here your custom variables + +const vec2 size = vec2(800, 450); // render size +const float samples = 5.0; // pixels per axis; higher = bigger glow, worse performance +const float quality = 2.5; // lower = smaller glow, better quality + +void main() +{ + vec4 sum = vec4(0); + vec2 sizeFactor = vec2(1)/size*quality; + + // Texel color fetching from texture sampler + vec4 source = texture(texture0, fragTexCoord); + + const int range = 2; // should be = (samples - 1)/2; + + for (int x = -range; x <= range; x++) + { + for (int y = -range; y <= range; y++) + { + sum += texture(texture0, fragTexCoord + vec2(x, y)*sizeFactor); + } + } + + // Calculate final fragment color + finalColor = ((sum/(samples*samples)) + source)*colDiffuse; +} \ No newline at end of file diff --git a/assets/shaders/glsl330/blur.fs b/assets/shaders/glsl330/blur.fs new file mode 100644 index 00000000..e4df406d --- /dev/null +++ b/assets/shaders/glsl330/blur.fs @@ -0,0 +1,35 @@ +#version 330 + +// Input vertex attributes (from vertex shader) +in vec2 fragTexCoord; +in vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +// Output fragment color +out vec4 finalColor; + +// NOTE: Add here your custom variables + +// NOTE: Render size values must be passed from code +const float renderWidth = 800; +const float renderHeight = 450; + +float offset[3] = float[](0.0, 1.3846153846, 3.2307692308); +float weight[3] = float[](0.2270270270, 0.3162162162, 0.0702702703); + +void main() +{ + // Texel color fetching from texture sampler + vec3 texelColor = texture(texture0, fragTexCoord).rgb*weight[0]; + + for (int i = 1; i < 3; i++) + { + texelColor += texture(texture0, fragTexCoord + vec2(offset[i])/renderWidth, 0.0).rgb*weight[i]; + texelColor += texture(texture0, fragTexCoord - vec2(offset[i])/renderWidth, 0.0).rgb*weight[i]; + } + + finalColor = vec4(texelColor, 1.0); +} \ No newline at end of file diff --git a/assets/shaders/glsl330/color_mix.fs b/assets/shaders/glsl330/color_mix.fs new file mode 100644 index 00000000..761b3464 --- /dev/null +++ b/assets/shaders/glsl330/color_mix.fs @@ -0,0 +1,27 @@ +#version 330 + +// Input vertex attributes (from vertex shader) +in vec3 vertexPos; +in vec2 fragTexCoord; +in vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform sampler2D texture1; +uniform vec4 colDiffuse; + +uniform float divider = 0.5; + +out vec4 finalColor; + +void main() +{ + // Texel color fetching from texture sampler + vec4 texelColor0 = texture(texture0, fragTexCoord); + vec4 texelColor1 = texture(texture1, fragTexCoord); + + float x = fract(fragTexCoord.s); + float final = smoothstep(divider - 0.1, divider + 0.1, x); + + finalColor = mix(texelColor0, texelColor1, final); +} \ No newline at end of file diff --git a/assets/shaders/glsl330/cross_hatching.fs b/assets/shaders/glsl330/cross_hatching.fs new file mode 100644 index 00000000..ffa5a41a --- /dev/null +++ b/assets/shaders/glsl330/cross_hatching.fs @@ -0,0 +1,49 @@ +#version 330 + +// Input vertex attributes (from vertex shader) +in vec2 fragTexCoord; +in vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +// Output fragment color +out vec4 finalColor; + +// NOTE: Add here your custom variables + +float hatchOffsetY = 5.0; +float lumThreshold01 = 0.9; +float lumThreshold02 = 0.7; +float lumThreshold03 = 0.5; +float lumThreshold04 = 0.3; + +void main() +{ + vec3 tc = vec3(1.0, 1.0, 1.0); + float lum = length(texture(texture0, fragTexCoord).rgb); + float a = texture(texture0, fragTexCoord).a; + + if (lum < lumThreshold01) + { + if (mod(gl_FragCoord.x + gl_FragCoord.y, 10.0) == 0.0) tc = vec3(0.0, 0.0, 0.0); + } + + if (lum < lumThreshold02) + { + if (mod(gl_FragCoord.x - gl_FragCoord.y, 10.0) == 0.0) tc = vec3(0.0, 0.0, 0.0); + } + + if (lum < lumThreshold03) + { + if (mod(gl_FragCoord.x + gl_FragCoord.y - hatchOffsetY, 10.0) == 0.0) tc = vec3(0.0, 0.0, 0.0); + } + + if (lum < lumThreshold04) + { + if (mod(gl_FragCoord.x - gl_FragCoord.y - hatchOffsetY, 10.0) == 0.0) tc = vec3(0.0, 0.0, 0.0); + } + + finalColor = vec4(tc, a); +} \ No newline at end of file diff --git a/assets/shaders/glsl330/cross_stitching.fs b/assets/shaders/glsl330/cross_stitching.fs new file mode 100644 index 00000000..a50e085d --- /dev/null +++ b/assets/shaders/glsl330/cross_stitching.fs @@ -0,0 +1,60 @@ +#version 330 + +// Input vertex attributes (from vertex shader) +in vec2 fragTexCoord; +in vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +// Output fragment color +out vec4 finalColor; + +// NOTE: Add here your custom variables + +// NOTE: Render size values must be passed from code +const float renderWidth = 800.0; +const float renderHeight = 450.0; + +float stitchingSize = 6.0; + +uniform int invert = 0; + +vec4 PostFX(sampler2D tex, vec2 uv) +{ + vec4 c = vec4(0.0); + float size = stitchingSize; + vec2 cPos = uv * vec2(renderWidth, renderHeight); + vec2 tlPos = floor(cPos / vec2(size, size)); + tlPos *= size; + + int remX = int(mod(cPos.x, size)); + int remY = int(mod(cPos.y, size)); + + if (remX == 0 && remY == 0) tlPos = cPos; + + vec2 blPos = tlPos; + blPos.y += (size - 1.0); + + if ((remX == remY) || (((int(cPos.x) - int(blPos.x)) == (int(blPos.y) - int(cPos.y))))) + { + if (invert == 1) c = vec4(0.2, 0.15, 0.05, 1.0); + else c = texture(tex, tlPos * vec2(1.0/renderWidth, 1.0/renderHeight)) * 1.4; + } + else + { + if (invert == 1) c = texture(tex, tlPos * vec2(1.0/renderWidth, 1.0/renderHeight)) * 1.4; + else c = vec4(0.0, 0.0, 0.0, 1.0); + } + + return c; +} + +void main() +{ + vec3 tc = PostFX(texture0, fragTexCoord).rgb; + float a = texture(texture0, fragTexCoord).a; + + finalColor = vec4(tc, a); +} \ No newline at end of file diff --git a/assets/shaders/glsl330/cubes_panning.fs b/assets/shaders/glsl330/cubes_panning.fs new file mode 100644 index 00000000..c92418a4 --- /dev/null +++ b/assets/shaders/glsl330/cubes_panning.fs @@ -0,0 +1,61 @@ +#version 330 + +// Input vertex attributes (from vertex shader) +in vec2 fragTexCoord; +in vec4 fragColor; + +// Output fragment color +out vec4 finalColor; + +// Custom variables +#define PI 3.14159265358979323846 +uniform float uTime = 0.0; + +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*sin(2*PI*localTime - PI/2); + else if ((localTime >= 0.50) && (localTime < 0.75)) angle = PI*0.25; + else if ((localTime >= 0.75) && (localTime < 1.00)) angle = PI/4*sin(2*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); + + finalColor = vec4(color, alpha); +} \ No newline at end of file diff --git a/assets/shaders/glsl330/depth.fs b/assets/shaders/glsl330/depth.fs new file mode 100644 index 00000000..2422f390 --- /dev/null +++ b/assets/shaders/glsl330/depth.fs @@ -0,0 +1,27 @@ +#version 330 + +// Input vertex attributes (from vertex shader) +in vec2 fragTexCoord; +in vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; // Depth texture +uniform vec4 colDiffuse; + +// Output fragment color +out vec4 finalColor; + +// NOTE: Add here your custom variables + +void main() +{ + float zNear = 0.01; // camera z near + float zFar = 10.0; // camera z far + float z = texture(texture0, fragTexCoord).x; + + // Linearize depth value + float depth = (2.0*zNear)/(zFar + zNear - z*(zFar - zNear)); + + // Calculate final fragment color + finalColor = vec4(depth, depth, depth, 1.0f); +} \ No newline at end of file diff --git a/assets/shaders/glsl330/distortion.fs b/assets/shaders/glsl330/distortion.fs new file mode 100644 index 00000000..cb4be8fc --- /dev/null +++ b/assets/shaders/glsl330/distortion.fs @@ -0,0 +1,56 @@ +#version 330 + +// Input vertex attributes (from vertex shader) +in vec2 fragTexCoord; + +// Input uniform values +uniform sampler2D texture0; + +// Output fragment color +out vec4 finalColor; + +// NOTE: Default parameters for Oculus Rift DK2 device +const vec2 LeftLensCenter = vec2(0.2863248, 0.5); +const vec2 RightLensCenter = vec2(0.7136753, 0.5); +const vec2 LeftScreenCenter = vec2(0.25, 0.5); +const vec2 RightScreenCenter = vec2(0.75, 0.5); +const vec2 Scale = vec2(0.25, 0.45); +const vec2 ScaleIn = vec2(4.0, 2.5); +const vec4 HmdWarpParam = vec4(1.0, 0.22, 0.24, 0.0); +const vec4 ChromaAbParam = vec4(0.996, -0.004, 1.014, 0.0); + +void main() +{ + // The following two variables need to be set per eye + vec2 LensCenter = fragTexCoord.x < 0.5 ? LeftLensCenter : RightLensCenter; + vec2 ScreenCenter = fragTexCoord.x < 0.5 ? LeftScreenCenter : RightScreenCenter; + + // Scales input texture coordinates for distortion: vec2 HmdWarp(vec2 fragTexCoord, vec2 LensCenter) + vec2 theta = (fragTexCoord - LensCenter)*ScaleIn; // Scales to [-1, 1] + float rSq = theta.x*theta.x + theta.y*theta.y; + vec2 theta1 = theta*(HmdWarpParam.x + HmdWarpParam.y*rSq + HmdWarpParam.z*rSq*rSq + HmdWarpParam.w*rSq*rSq*rSq); + //vec2 tc = LensCenter + Scale*theta1; + + // Detect whether blue texture coordinates are out of range since these will scaled out the furthest + vec2 thetaBlue = theta1*(ChromaAbParam.z + ChromaAbParam.w*rSq); + vec2 tcBlue = LensCenter + Scale*thetaBlue; + + if (any(bvec2(clamp(tcBlue, ScreenCenter - vec2(0.25, 0.5), ScreenCenter + vec2(0.25, 0.5)) - tcBlue))) finalColor = vec4(0.0, 0.0, 0.0, 1.0); + else + { + // Do blue texture lookup + float blue = texture(texture0, tcBlue).b; + + // Do green lookup (no scaling) + vec2 tcGreen = LensCenter + Scale*theta1; + float green = texture(texture0, tcGreen).g; + + // Do red scale and lookup + vec2 thetaRed = theta1*(ChromaAbParam.x + ChromaAbParam.y*rSq); + vec2 tcRed = LensCenter + Scale*thetaRed; + float red = texture(texture0, tcRed).r; + + finalColor = vec4(red, green, blue, 1.0); + } +} + diff --git a/assets/shaders/glsl330/dream_vision.fs b/assets/shaders/glsl330/dream_vision.fs new file mode 100644 index 00000000..31d3fd2f --- /dev/null +++ b/assets/shaders/glsl330/dream_vision.fs @@ -0,0 +1,34 @@ +#version 330 + +in vec2 fragTexCoord; + +out vec4 fragColor; + +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +// NOTE: Add here your custom variables + +void main() +{ + vec4 color = texture(texture0, fragTexCoord); + + color += texture(texture0, fragTexCoord + 0.001); + color += texture(texture0, fragTexCoord + 0.003); + color += texture(texture0, fragTexCoord + 0.005); + color += texture(texture0, fragTexCoord + 0.007); + color += texture(texture0, fragTexCoord + 0.009); + color += texture(texture0, fragTexCoord + 0.011); + + color += texture(texture0, fragTexCoord - 0.001); + color += texture(texture0, fragTexCoord - 0.003); + color += texture(texture0, fragTexCoord - 0.005); + color += texture(texture0, fragTexCoord - 0.007); + color += texture(texture0, fragTexCoord - 0.009); + color += texture(texture0, fragTexCoord - 0.011); + + color.rgb = vec3((color.r + color.g + color.b)/3.0); + color = color/9.5; + + fragColor = color; +} \ No newline at end of file diff --git a/assets/shaders/glsl330/eratosthenes.fs b/assets/shaders/glsl330/eratosthenes.fs new file mode 100644 index 00000000..14711222 --- /dev/null +++ b/assets/shaders/glsl330/eratosthenes.fs @@ -0,0 +1,59 @@ +#version 330 + +/************************************************************************************* + + 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) +in vec2 fragTexCoord; +in vec4 fragColor; + +// Output fragment color +out vec4 finalColor; + +// 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. + int value = int(scale*floor(fragTexCoord.y*scale)+floor(fragTexCoord.x*scale)); // Group pixels into boxes representing integer values + + if ((value == 0) || (value == 1) || (value == 2)) finalColor = vec4(1.0); + else + { + for (int i = 2; (i < max(2, sqrt(value) + 1)); i++) + { + if ((value - i*floor(float(value)/float(i))) == 0) + { + color = Colorizer(float(i), scale); + //break; // Uncomment to color by the largest factor instead + } + } + + finalColor = color; + } +} diff --git a/assets/shaders/glsl330/fisheye.fs b/assets/shaders/glsl330/fisheye.fs new file mode 100644 index 00000000..e85d7c9d --- /dev/null +++ b/assets/shaders/glsl330/fisheye.fs @@ -0,0 +1,40 @@ +#version 330 + +in vec2 fragTexCoord; + +out vec4 fragColor; + +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +// NOTE: Add here your custom variables + +const float PI = 3.1415926535; + +void main() +{ + float aperture = 178.0; + float apertureHalf = 0.5 * aperture * (PI / 180.0); + float maxFactor = sin(apertureHalf); + + vec2 uv = vec2(0); + vec2 xy = 2.0 * fragTexCoord.xy - 1.0; + float d = length(xy); + + if (d < (2.0 - maxFactor)) + { + d = length(xy * maxFactor); + float z = sqrt(1.0 - d * d); + float r = atan(d, z) / PI; + float phi = atan(xy.y, xy.x); + + uv.x = r * cos(phi) + 0.5; + uv.y = r * sin(phi) + 0.5; + } + else + { + uv = fragTexCoord.xy; + } + + fragColor = texture(texture0, uv); +} \ No newline at end of file diff --git a/assets/shaders/glsl330/fog.fs b/assets/shaders/glsl330/fog.fs new file mode 100644 index 00000000..2160f31b --- /dev/null +++ b/assets/shaders/glsl330/fog.fs @@ -0,0 +1,95 @@ +#version 330 + +// Input vertex attributes (from vertex shader) +in vec2 fragTexCoord; +in vec4 fragColor; +in vec3 fragPosition; +in vec3 fragNormal; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +// Output fragment color +out vec4 finalColor; + +// NOTE: Add here your custom variables + +#define MAX_LIGHTS 4 +#define LIGHT_DIRECTIONAL 0 +#define LIGHT_POINT 1 + +struct MaterialProperty { + vec3 color; + int useSampler; + sampler2D sampler; +}; + +struct Light { + int enabled; + int type; + vec3 position; + vec3 target; + vec4 color; +}; + +// Input lighting values +uniform Light lights[MAX_LIGHTS]; +uniform vec4 ambient; +uniform vec3 viewPos; +uniform float fogDensity; + +void main() +{ + // Texel color fetching from texture sampler + vec4 texelColor = texture(texture0, fragTexCoord); + vec3 lightDot = vec3(0.0); + vec3 normal = normalize(fragNormal); + vec3 viewD = normalize(viewPos - fragPosition); + vec3 specular = vec3(0.0); + + // NOTE: Implement here your fragment shader code + + for (int i = 0; i < MAX_LIGHTS; i++) + { + if (lights[i].enabled == 1) + { + vec3 light = vec3(0.0); + + if (lights[i].type == LIGHT_DIRECTIONAL) light = -normalize(lights[i].target - lights[i].position); + if (lights[i].type == LIGHT_POINT) light = normalize(lights[i].position - fragPosition); + + float NdotL = max(dot(normal, light), 0.0); + lightDot += lights[i].color.rgb*NdotL; + + float specCo = 0.0; + if (NdotL > 0.0) specCo = pow(max(0.0, dot(viewD, reflect(-(light), normal))), 16.0); // Shine: 16.0 + specular += specCo; + } + } + + finalColor = (texelColor*((colDiffuse + vec4(specular,1))*vec4(lightDot, 1.0))); + finalColor += texelColor*(ambient/10.0); + + // Gamma correction + finalColor = pow(finalColor, vec4(1.0/2.2)); + + // Fog calculation + float dist = length(viewPos - fragPosition); + + // these could be parameters... + const vec4 fogColor = vec4(0.5, 0.5, 0.5, 1.0); + //const float fogDensity = 0.16; + + // Exponential fog + float fogFactor = 1.0/exp((dist*fogDensity)*(dist*fogDensity)); + + // Linear fog (less nice) + //const float fogStart = 2.0; + //const float fogEnd = 10.0; + //float fogFactor = (fogEnd - dist)/(fogEnd - fogStart); + + fogFactor = clamp(fogFactor, 0.0, 1.0); + + finalColor = mix(fogColor, finalColor, fogFactor); +} diff --git a/assets/shaders/glsl330/grayscale.fs b/assets/shaders/glsl330/grayscale.fs new file mode 100644 index 00000000..5b3e11be --- /dev/null +++ b/assets/shaders/glsl330/grayscale.fs @@ -0,0 +1,26 @@ +#version 330 + +// Input vertex attributes (from vertex shader) +in vec2 fragTexCoord; +in vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +// Output fragment color +out vec4 finalColor; + +// NOTE: Add here your custom variables + +void main() +{ + // Texel color fetching from texture sampler + vec4 texelColor = texture(texture0, fragTexCoord)*colDiffuse*fragColor; + + // Convert texel color to grayscale using NTSC conversion weights + float gray = dot(texelColor.rgb, vec3(0.299, 0.587, 0.114)); + + // Calculate final fragment color + finalColor = vec4(gray, gray, gray, texelColor.a); +} \ No newline at end of file diff --git a/assets/shaders/glsl330/julia_set.fs b/assets/shaders/glsl330/julia_set.fs new file mode 100644 index 00000000..f68367ea --- /dev/null +++ b/assets/shaders/glsl330/julia_set.fs @@ -0,0 +1,81 @@ +#version 330 + +// Input vertex attributes (from vertex shader) +in vec2 fragTexCoord; +in vec4 fragColor; + +// Output fragment color +out vec4 finalColor; + +uniform vec2 screenDims; // Dimensions of the screen +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. + +const int MAX_ITERATIONS = 255; // Max iterations to do. + +// 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 MAX_ITERATIONS is for. + Then we can divide the iterations by the MAX_ITERATIONS 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 + offset.x/screenDims.x)*2.5/zoom, (fragTexCoord.y + offset.y/screenDims.y)*1.5/zoom); + + int iterations = 0; + for (iterations = 0; iterations < MAX_ITERATIONS; iterations++) + { + z = ComplexSquare(z) + c; // Iterate function + + if (dot(z, z) > 4.0) break; + } + + // 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(iterations) + 1.0 - (log(log(length(z)))/log(2.0)); + + // Normalize the value so it is between 0 and 1. + float norm = smoothVal/float(MAX_ITERATIONS); + + // If in set, color black. 0.999 allows for some float accuracy error. + if (norm > 0.999) finalColor = vec4(0.0, 0.0, 0.0, 1.0); + else finalColor = vec4(Hsv2rgb(vec3(norm, 1.0, 1.0)), 1.0); +} diff --git a/assets/shaders/glsl330/lighting.fs b/assets/shaders/glsl330/lighting.fs new file mode 100644 index 00000000..6877c1c7 --- /dev/null +++ b/assets/shaders/glsl330/lighting.fs @@ -0,0 +1,82 @@ +#version 330 + +// Input vertex attributes (from vertex shader) +in vec3 fragPosition; +in vec2 fragTexCoord; +in vec4 fragColor; +in vec3 fragNormal; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +// Output fragment color +out vec4 finalColor; + +// NOTE: Add here your custom variables + +#define MAX_LIGHTS 4 +#define LIGHT_DIRECTIONAL 0 +#define LIGHT_POINT 1 + +struct MaterialProperty { + vec3 color; + int useSampler; + sampler2D sampler; +}; + +struct Light { + int enabled; + int type; + vec3 position; + vec3 target; + vec4 color; +}; + +// Input lighting values +uniform Light lights[MAX_LIGHTS]; +uniform vec4 ambient; +uniform vec3 viewPos; + +void main() +{ + // Texel color fetching from texture sampler + vec4 texelColor = texture(texture0, fragTexCoord); + vec3 lightDot = vec3(0.0); + vec3 normal = normalize(fragNormal); + vec3 viewD = normalize(viewPos - fragPosition); + vec3 specular = vec3(0.0); + + // NOTE: Implement here your fragment shader code + + for (int i = 0; i < MAX_LIGHTS; i++) + { + if (lights[i].enabled == 1) + { + vec3 light = vec3(0.0); + + if (lights[i].type == LIGHT_DIRECTIONAL) + { + light = -normalize(lights[i].target - lights[i].position); + } + + if (lights[i].type == LIGHT_POINT) + { + light = normalize(lights[i].position - fragPosition); + } + + float NdotL = max(dot(normal, light), 0.0); + lightDot += lights[i].color.rgb*NdotL; + + float specCo = 0.0; + if (NdotL > 0.0) specCo = pow(max(0.0, dot(viewD, reflect(-(light), normal))), 16.0); // 16 refers to shine + specular += specCo; + } + } + + finalColor = (texelColor*((colDiffuse + vec4(specular, 1.0))*vec4(lightDot, 1.0))); + finalColor += texelColor*(ambient/10.0)*colDiffuse; + + // Gamma correction + finalColor = pow(finalColor, vec4(1.0/2.2)); +} diff --git a/assets/shaders/glsl330/mask.fs b/assets/shaders/glsl330/mask.fs new file mode 100644 index 00000000..a93bed07 --- /dev/null +++ b/assets/shaders/glsl330/mask.fs @@ -0,0 +1,22 @@ +#version 330 + +// Input vertex attributes (from vertex shader) +in vec2 fragTexCoord; +in vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform sampler2D mask; +uniform int frame; + +// Output fragment color +out vec4 finalColor; + +void main() +{ + vec4 maskColour = texture(mask, fragTexCoord + vec2(sin(-frame/150.0)/10.0, cos(-frame/170.0)/10.0)); + if (maskColour.r < 0.25) discard; + vec4 texelColor = texture(texture0, fragTexCoord + vec2(sin(frame/90.0)/8.0, cos(frame/60.0)/8.0)); + + finalColor = texelColor*maskColour; +} diff --git a/assets/shaders/glsl330/overdraw.fs b/assets/shaders/glsl330/overdraw.fs new file mode 100644 index 00000000..435217c3 --- /dev/null +++ b/assets/shaders/glsl330/overdraw.fs @@ -0,0 +1,26 @@ +#version 330 + +// Input vertex attributes (from vertex shader) +in vec2 fragTexCoord; +in vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +// Output fragment color +out vec4 finalColor; + +// NOTE: Add here your custom variables + +void main() +{ + // To show overdraw, we just render all the fragments + // with a solid color and some transparency + + // NOTE: This is not a postpro render, + // it will only render all screen texture in a plain color + + finalColor = vec4(1.0, 0.0, 0.0, 0.2); +} + diff --git a/assets/shaders/glsl330/palette_switch.fs b/assets/shaders/glsl330/palette_switch.fs new file mode 100644 index 00000000..7c8a488c --- /dev/null +++ b/assets/shaders/glsl330/palette_switch.fs @@ -0,0 +1,30 @@ +#version 330 + +const int colors = 8; + +// Input fragment attributes (from fragment shader) +in vec2 fragTexCoord; +in vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform ivec3 palette[colors]; + +// Output fragment color +out vec4 finalColor; + +void main() +{ + // Texel color fetching from texture sampler + vec4 texelColor = texture(texture0, fragTexCoord)*fragColor; + + // Convert the (normalized) texel color RED component (GB would work, too) + // to the palette index by scaling up from [0, 1] to [0, 255]. + int index = int(texelColor.r*255.0); + ivec3 color = palette[index]; + + // Calculate final fragment color. Note that the palette color components + // are defined in the range [0, 255] and need to be normalized to [0, 1] + // for OpenGL to work. + finalColor = vec4(color/255.0, texelColor.a); +} diff --git a/assets/shaders/glsl330/pixelizer.fs b/assets/shaders/glsl330/pixelizer.fs new file mode 100644 index 00000000..6a386c20 --- /dev/null +++ b/assets/shaders/glsl330/pixelizer.fs @@ -0,0 +1,33 @@ +#version 330 + +// Input vertex attributes (from vertex shader) +in vec2 fragTexCoord; +in vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +// Output fragment color +out vec4 finalColor; + +// NOTE: Add here your custom variables + +// NOTE: Render size values must be passed from code +const float renderWidth = 800; +const float renderHeight = 450; + +uniform float pixelWidth = 5.0; +uniform float pixelHeight = 5.0; + +void main() +{ + float dx = pixelWidth*(1.0/renderWidth); + float dy = pixelHeight*(1.0/renderHeight); + + vec2 coord = vec2(dx*floor(fragTexCoord.x/dx), dy*floor(fragTexCoord.y/dy)); + + vec4 tc = texture(texture0, coord).rgba; + + finalColor = tc; +} \ No newline at end of file diff --git a/assets/shaders/glsl330/posterization.fs b/assets/shaders/glsl330/posterization.fs new file mode 100644 index 00000000..94197b01 --- /dev/null +++ b/assets/shaders/glsl330/posterization.fs @@ -0,0 +1,32 @@ +#version 330 + +// Input vertex attributes (from vertex shader) +in vec2 fragTexCoord; +in vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +// Output fragment color +out vec4 finalColor; + +// NOTE: Add here your custom variables + +float gamma = 0.6; +float numColors = 8.0; + +void main() +{ + // Texel color fetching from texture sampler + vec3 texelColor = texture(texture0, fragTexCoord.xy).rgb; + float a = texture(texture0, fragTexCoord.xy).a; + + texelColor = pow(texelColor, vec3(gamma, gamma, gamma)); + texelColor = texelColor*numColors; + texelColor = floor(texelColor); + texelColor = texelColor/numColors; + texelColor = pow(texelColor, vec3(1.0/gamma)); + + finalColor = vec4(texelColor, a); +} \ No newline at end of file diff --git a/assets/shaders/glsl330/predator.fs b/assets/shaders/glsl330/predator.fs new file mode 100644 index 00000000..fb983996 --- /dev/null +++ b/assets/shaders/glsl330/predator.fs @@ -0,0 +1,32 @@ +#version 330 + +// Input vertex attributes (from vertex shader) +in vec2 fragTexCoord; +in vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +// Output fragment color +out vec4 finalColor; + +// NOTE: Add here your custom variables + +void main() +{ + // Texel color fetching from texture sampler + vec4 texelColor = texture(texture0, fragTexCoord).rgba; + vec3 colors[3]; + colors[0] = vec3(0.0, 0.0, 1.0); + colors[1] = vec3(1.0, 1.0, 0.0); + colors[2] = vec3(1.0, 0.0, 0.0); + + float lum = (texelColor.r + texelColor.g + texelColor.b)/3.0; + + int ix = (lum < 0.5)? 0:1; + + vec3 tc = mix(colors[ix], colors[ix + 1], (lum - float(ix)*0.5)/0.5); + + finalColor = vec4(tc, texelColor.a); +} \ No newline at end of file diff --git a/assets/shaders/glsl330/raymarching.fs b/assets/shaders/glsl330/raymarching.fs new file mode 100644 index 00000000..5b0caa65 --- /dev/null +++ b/assets/shaders/glsl330/raymarching.fs @@ -0,0 +1,430 @@ +#version 330 + +// Input vertex attributes (from vertex shader) +in vec2 fragTexCoord; +in vec4 fragColor; + +// Output fragment color +out vec4 finalColor; + +uniform vec3 viewEye; +uniform vec3 viewCenter; +uniform float runTime; +uniform vec2 resolution; + +// The MIT License +// Copyright © 2013 Inigo Quilez +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +// A list of useful distance function to simple primitives, and an example on how to +// do some interesting boolean operations, repetition and displacement. +// +// More info here: http://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm + +#define AA 1 // make this 1 is your machine is too slow + +//------------------------------------------------------------------ + +float sdPlane( vec3 p ) +{ + return p.y; +} + +float sdSphere( vec3 p, float s ) +{ + return length(p)-s; +} + +float sdBox( vec3 p, vec3 b ) +{ + vec3 d = abs(p) - b; + return min(max(d.x,max(d.y,d.z)),0.0) + length(max(d,0.0)); +} + +float sdEllipsoid( in vec3 p, in vec3 r ) +{ + return (length( p/r ) - 1.0) * min(min(r.x,r.y),r.z); +} + +float udRoundBox( vec3 p, vec3 b, float r ) +{ + return length(max(abs(p)-b,0.0))-r; +} + +float sdTorus( vec3 p, vec2 t ) +{ + return length( vec2(length(p.xz)-t.x,p.y) )-t.y; +} + +float sdHexPrism( vec3 p, vec2 h ) +{ + vec3 q = abs(p); +#if 0 + return max(q.z-h.y,max((q.x*0.866025+q.y*0.5),q.y)-h.x); +#else + float d1 = q.z-h.y; + float d2 = max((q.x*0.866025+q.y*0.5),q.y)-h.x; + return length(max(vec2(d1,d2),0.0)) + min(max(d1,d2), 0.); +#endif +} + +float sdCapsule( vec3 p, vec3 a, vec3 b, float r ) +{ + vec3 pa = p-a, ba = b-a; + float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 ); + return length( pa - ba*h ) - r; +} + +float sdEquilateralTriangle( in vec2 p ) +{ + const float k = sqrt(3.0); + p.x = abs(p.x) - 1.0; + p.y = p.y + 1.0/k; + if( p.x + k*p.y > 0.0 ) p = vec2( p.x - k*p.y, -k*p.x - p.y )/2.0; + p.x += 2.0 - 2.0*clamp( (p.x+2.0)/2.0, 0.0, 1.0 ); + return -length(p)*sign(p.y); +} + +float sdTriPrism( vec3 p, vec2 h ) +{ + vec3 q = abs(p); + float d1 = q.z-h.y; +#if 1 + // distance bound + float d2 = max(q.x*0.866025+p.y*0.5,-p.y)-h.x*0.5; +#else + // correct distance + h.x *= 0.866025; + float d2 = sdEquilateralTriangle(p.xy/h.x)*h.x; +#endif + return length(max(vec2(d1,d2),0.0)) + min(max(d1,d2), 0.); +} + +float sdCylinder( vec3 p, vec2 h ) +{ + vec2 d = abs(vec2(length(p.xz),p.y)) - h; + return min(max(d.x,d.y),0.0) + length(max(d,0.0)); +} + +float sdCone( in vec3 p, in vec3 c ) +{ + vec2 q = vec2( length(p.xz), p.y ); + float d1 = -q.y-c.z; + float d2 = max( dot(q,c.xy), q.y); + return length(max(vec2(d1,d2),0.0)) + min(max(d1,d2), 0.); +} + +float sdConeSection( in vec3 p, in float h, in float r1, in float r2 ) +{ + float d1 = -p.y - h; + float q = p.y - h; + float si = 0.5*(r1-r2)/h; + float d2 = max( sqrt( dot(p.xz,p.xz)*(1.0-si*si)) + q*si - r2, q ); + return length(max(vec2(d1,d2),0.0)) + min(max(d1,d2), 0.); +} + +float sdPryamid4(vec3 p, vec3 h ) // h = { cos a, sin a, height } +{ + // Tetrahedron = Octahedron - Cube + float box = sdBox( p - vec3(0,-2.0*h.z,0), vec3(2.0*h.z) ); + + float d = 0.0; + d = max( d, abs( dot(p, vec3( -h.x, h.y, 0 )) )); + d = max( d, abs( dot(p, vec3( h.x, h.y, 0 )) )); + d = max( d, abs( dot(p, vec3( 0, h.y, h.x )) )); + d = max( d, abs( dot(p, vec3( 0, h.y,-h.x )) )); + float octa = d - h.z; + return max(-box,octa); // Subtraction + } + +float length2( vec2 p ) +{ + return sqrt( p.x*p.x + p.y*p.y ); +} + +float length6( vec2 p ) +{ + p = p*p*p; p = p*p; + return pow( p.x + p.y, 1.0/6.0 ); +} + +float length8( vec2 p ) +{ + p = p*p; p = p*p; p = p*p; + return pow( p.x + p.y, 1.0/8.0 ); +} + +float sdTorus82( vec3 p, vec2 t ) +{ + vec2 q = vec2(length2(p.xz)-t.x,p.y); + return length8(q)-t.y; +} + +float sdTorus88( vec3 p, vec2 t ) +{ + vec2 q = vec2(length8(p.xz)-t.x,p.y); + return length8(q)-t.y; +} + +float sdCylinder6( vec3 p, vec2 h ) +{ + return max( length6(p.xz)-h.x, abs(p.y)-h.y ); +} + +//------------------------------------------------------------------ + +float opS( float d1, float d2 ) +{ + return max(-d2,d1); +} + +vec2 opU( vec2 d1, vec2 d2 ) +{ + return (d1.x0.0 ) tmax = min( tmax, tp1 ); + float tp2 = (1.6-ro.y)/rd.y; if( tp2>0.0 ) { if( ro.y>1.6 ) tmin = max( tmin, tp2 ); + else tmax = min( tmax, tp2 ); } +#endif + + float t = tmin; + float m = -1.0; + for( int i=0; i<64; i++ ) + { + float precis = 0.0005*t; + vec2 res = map( ro+rd*t ); + if( res.xtmax ) break; + t += res.x; + m = res.y; + } + + if( t>tmax ) m=-1.0; + return vec2( t, m ); +} + + +float calcSoftshadow( in vec3 ro, in vec3 rd, in float mint, in float tmax ) +{ + float res = 1.0; + float t = mint; + for( int i=0; i<16; i++ ) + { + float h = map( ro + rd*t ).x; + res = min( res, 8.0*h/t ); + t += clamp( h, 0.02, 0.10 ); + if( h<0.001 || t>tmax ) break; + } + return clamp( res, 0.0, 1.0 ); +} + +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 ); + /* + vec3 eps = vec3( 0.0005, 0.0, 0.0 ); + vec3 nor = vec3( + map(pos+eps.xyy).x - map(pos-eps.xyy).x, + map(pos+eps.yxy).x - map(pos-eps.yxy).x, + map(pos+eps.yyx).x - map(pos-eps.yyx).x ); + return normalize(nor); + */ +} + +float calcAO( in vec3 pos, in vec3 nor ) +{ + float occ = 0.0; + float sca = 1.0; + for( int i=0; i<5; i++ ) + { + float hr = 0.01 + 0.12*float(i)/4.0; + vec3 aopos = nor * hr + pos; + float dd = map( aopos ).x; + occ += -(dd-hr)*sca; + sca *= 0.95; + } + return clamp( 1.0 - 3.0*occ, 0.0, 1.0 ); +} + +// http://iquilezles.org/www/articles/checkerfiltering/checkerfiltering.htm +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; +} + +vec3 render( in vec3 ro, in vec3 rd ) +{ + vec3 col = vec3(0.7, 0.9, 1.0) +rd.y*0.8; + vec2 res = castRay(ro,rd); + float t = res.x; + float m = res.y; + if( m>-0.5 ) + { + vec3 pos = ro + t*rd; + vec3 nor = calcNormal( pos ); + vec3 ref = reflect( rd, nor ); + + // material + col = 0.45 + 0.35*sin( vec3(0.05,0.08,0.10)*(m-1.0) ); + if( m<1.5 ) + { + + float f = checkersGradBox( 5.0*pos.xz ); + col = 0.3 + f*vec3(0.1); + } + + // lighting + float occ = calcAO( pos, nor ); + vec3 lig = normalize( vec3(cos(-0.4 * runTime), sin(0.7 * runTime), -0.6) ); + vec3 hal = normalize( lig-rd ); + float amb = clamp( 0.5+0.5*nor.y, 0.0, 1.0 ); + float dif = clamp( dot( nor, lig ), 0.0, 1.0 ); + float bac = clamp( dot( nor, normalize(vec3(-lig.x,0.0,-lig.z))), 0.0, 1.0 )*clamp( 1.0-pos.y,0.0,1.0); + float dom = smoothstep( -0.1, 0.1, ref.y ); + float fre = pow( clamp(1.0+dot(nor,rd),0.0,1.0), 2.0 ); + + dif *= calcSoftshadow( pos, lig, 0.02, 2.5 ); + dom *= calcSoftshadow( pos, ref, 0.02, 2.5 ); + + float spe = pow( clamp( dot( nor, hal ), 0.0, 1.0 ),16.0)* + dif * + (0.04 + 0.96*pow( clamp(1.0+dot(hal,rd),0.0,1.0), 5.0 )); + + vec3 lin = vec3(0.0); + lin += 1.30*dif*vec3(1.00,0.80,0.55); + lin += 0.40*amb*vec3(0.40,0.60,1.00)*occ; + lin += 0.50*dom*vec3(0.40,0.60,1.00)*occ; + lin += 0.50*bac*vec3(0.25,0.25,0.25)*occ; + lin += 0.25*fre*vec3(1.00,1.00,1.00)*occ; + col = col*lin; + col += 10.00*spe*vec3(1.00,0.90,0.70); + + col = mix( col, vec3(0.8,0.9,1.0), 1.0-exp( -0.0002*t*t*t ) ); + } + + return vec3( clamp(col,0.0,1.0) ); +} + +mat3 setCamera( in vec3 ro, in vec3 ta, float cr ) +{ + vec3 cw = normalize(ta-ro); + vec3 cp = vec3(sin(cr), cos(cr),0.0); + vec3 cu = normalize( cross(cw,cp) ); + vec3 cv = normalize( cross(cu,cw) ); + return mat3( cu, cv, cw ); +} + +void main() +{ + vec3 tot = vec3(0.0); +#if AA>1 + for( int m=0; m1 + } + tot /= float(AA*AA); +#endif + + finalColor = vec4( tot, 1.0 ); +} diff --git a/assets/shaders/glsl330/reload.fs b/assets/shaders/glsl330/reload.fs new file mode 100644 index 00000000..21ce18e0 --- /dev/null +++ b/assets/shaders/glsl330/reload.fs @@ -0,0 +1,40 @@ +#version 330 + +// Input vertex attributes (from vertex shader) +in vec2 fragTexCoord; // Texture coordinates (sampler2D) +in vec4 fragColor; // Tint color + +// Output fragment color +out vec4 finalColor; // Output fragment 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 + finalColor = mix(layer1, layer2, layer2.a); +} diff --git a/assets/shaders/glsl330/scanlines.fs b/assets/shaders/glsl330/scanlines.fs new file mode 100644 index 00000000..22dc9cd5 --- /dev/null +++ b/assets/shaders/glsl330/scanlines.fs @@ -0,0 +1,49 @@ +#version 330 + +// Input vertex attributes (from vertex shader) +in vec2 fragTexCoord; +in vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +// Output fragment color +out vec4 finalColor; + +// NOTE: Add here your custom variables + +// NOTE: Render size values must be passed from code +const float renderWidth = 800; +const float renderHeight = 450; +float offset = 0.0; + +uniform float time; + +void main() +{ + float frequency = renderHeight/3.0; +/* + // Scanlines method 1 + float tval = 0; //time + vec2 uv = 0.5 + (fragTexCoord - 0.5)*(0.9 + 0.01*sin(0.5*tval)); + + vec4 color = texture(texture0, fragTexCoord); + + color = clamp(color*0.5 + 0.5*color*color*1.2, 0.0, 1.0); + color *= 0.5 + 0.5*16.0*uv.x*uv.y*(1.0 - uv.x)*(1.0 - uv.y); + color *= vec4(0.8, 1.0, 0.7, 1); + color *= 0.9 + 0.1*sin(10.0*tval + uv.y*1000.0); + color *= 0.97 + 0.03*sin(110.0*tval); + + fragColor = color; +*/ + // Scanlines method 2 + float globalPos = (fragTexCoord.y + offset) * frequency; + float wavePos = cos((fract(globalPos) - 0.5)*3.14); + + // Texel color fetching from texture sampler + vec4 texelColor = texture(texture0, fragTexCoord); + + finalColor = mix(vec4(0.0, 0.3, 0.0, 0.0), texelColor, wavePos); +} \ No newline at end of file diff --git a/assets/shaders/glsl330/sobel.fs b/assets/shaders/glsl330/sobel.fs new file mode 100644 index 00000000..60fe56e4 --- /dev/null +++ b/assets/shaders/glsl330/sobel.fs @@ -0,0 +1,41 @@ +#version 330 + +// Input vertex attributes (from vertex shader) +in vec2 fragTexCoord; +in vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +// Output fragment color +out vec4 finalColor; + +// NOTE: Add here your custom variables +uniform vec2 resolution = vec2(800 * 2, 450 * 2); + +void main() +{ + float x = 1.0/resolution.x; + float y = 1.0/resolution.y; + + vec4 horizEdge = vec4(0.0); + horizEdge -= texture2D(texture0, vec2(fragTexCoord.x - x, fragTexCoord.y - y))*1.0; + horizEdge -= texture2D(texture0, vec2(fragTexCoord.x - x, fragTexCoord.y ))*2.0; + horizEdge -= texture2D(texture0, vec2(fragTexCoord.x - x, fragTexCoord.y + y))*1.0; + horizEdge += texture2D(texture0, vec2(fragTexCoord.x + x, fragTexCoord.y - y))*1.0; + horizEdge += texture2D(texture0, vec2(fragTexCoord.x + x, fragTexCoord.y ))*2.0; + horizEdge += texture2D(texture0, vec2(fragTexCoord.x + x, fragTexCoord.y + y))*1.0; + + vec4 vertEdge = vec4(0.0); + vertEdge -= texture2D(texture0, vec2(fragTexCoord.x - x, fragTexCoord.y - y))*1.0; + vertEdge -= texture2D(texture0, vec2(fragTexCoord.x , fragTexCoord.y - y))*2.0; + vertEdge -= texture2D(texture0, vec2(fragTexCoord.x + x, fragTexCoord.y - y))*1.0; + vertEdge += texture2D(texture0, vec2(fragTexCoord.x - x, fragTexCoord.y + y))*1.0; + vertEdge += texture2D(texture0, vec2(fragTexCoord.x , fragTexCoord.y + y))*2.0; + vertEdge += texture2D(texture0, vec2(fragTexCoord.x + x, fragTexCoord.y + y))*1.0; + + vec3 edge = sqrt((horizEdge.rgb*horizEdge.rgb) + (vertEdge.rgb*vertEdge.rgb)); + + finalColor = vec4(edge, texture2D(texture0, fragTexCoord).a); +} \ No newline at end of file diff --git a/assets/shaders/glsl330/spotlight.fs b/assets/shaders/glsl330/spotlight.fs new file mode 100644 index 00000000..c573be8f --- /dev/null +++ b/assets/shaders/glsl330/spotlight.fs @@ -0,0 +1,65 @@ +#version 330 + +// Input vertex attributes (from vertex shader) +in vec2 fragTexCoord; +in vec4 fragColor; + +// Output fragment color +out vec4 finalColor; + +// NOTE: Add here your custom variables + +#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; // 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 != -1) + { + if (d > spots[fi].radius) alpha = 1.0; + else + { + if (d < spots[fi].inner) alpha = 0.0; + else alpha = (d - spots[fi].inner) / (spots[fi].radius - spots[fi].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; + + finalColor = vec4(0, 0, 0, alpha); +} diff --git a/assets/shaders/glsl330/swirl.fs b/assets/shaders/glsl330/swirl.fs new file mode 100644 index 00000000..4741e597 --- /dev/null +++ b/assets/shaders/glsl330/swirl.fs @@ -0,0 +1,47 @@ +#version 330 + +// Input vertex attributes (from vertex shader) +in vec2 fragTexCoord; +in vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +// Output fragment color +out vec4 finalColor; + +// NOTE: Add here your custom variables + +// NOTE: Render size values should be passed from code +const float renderWidth = 800; +const float renderHeight = 450; + +float radius = 250.0; +float angle = 0.8; + +uniform vec2 center = vec2(200.0, 200.0); + +void main() +{ + vec2 texSize = vec2(renderWidth, renderHeight); + vec2 tc = fragTexCoord*texSize; + tc -= center; + + float dist = length(tc); + + if (dist < radius) + { + float percent = (radius - dist)/radius; + float theta = percent*percent*angle*8.0; + float s = sin(theta); + float c = cos(theta); + + tc = vec2(dot(tc, vec2(c, -s)), dot(tc, vec2(s, c))); + } + + tc += center; + vec4 color = texture2D(texture0, tc/texSize)*colDiffuse*fragColor;; + + finalColor = vec4(color.rgb, 1.0);; +} \ No newline at end of file diff --git a/assets/shaders/glsl330/wave.fs b/assets/shaders/glsl330/wave.fs new file mode 100644 index 00000000..43efee23 --- /dev/null +++ b/assets/shaders/glsl330/wave.fs @@ -0,0 +1,37 @@ +#version 330 + +// Input vertex attributes (from vertex shader) +in vec2 fragTexCoord; +in vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +// Output fragment color +out vec4 finalColor; + +uniform float secondes; + +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) + (secondes * speedX)) * ampX * pixelWidth; + p.y += sin((fragTexCoord.x - boxLeft) * freqY * aspect / ( pixelHeight * 750.0) + (secondes * speedY)) * ampY * pixelHeight; + + finalColor = texture(texture0, p)*colDiffuse*fragColor; +} diff --git a/lib/Ray/CMakeLists.txt b/lib/Ray/CMakeLists.txt index d713eb1e..9a55f6be 100644 --- a/lib/Ray/CMakeLists.txt +++ b/lib/Ray/CMakeLists.txt @@ -97,7 +97,7 @@ set(SRC sources/Model/ModelAnimations.cpp sources/Vector/Vector2.cpp sources/Vector/Vector3.cpp -) + sources/Shaders/Shaders.cpp sources/Shaders/Shaders.hpp) find_package(raylib QUIET) if (NOT raylib_FOUND) diff --git a/lib/Ray/sources/Audio/Music.cpp b/lib/Ray/sources/Audio/Music.cpp index f58921bc..0a9b2660 100644 --- a/lib/Ray/sources/Audio/Music.cpp +++ b/lib/Ray/sources/Audio/Music.cpp @@ -10,8 +10,8 @@ RAY::Cache<::Music> RAY::Audio::Music::_musicsCache(LoadMusicStream, UnloadMusicStream); -RAY::Audio::Music::Music(const std::string &path): - _music(this->_musicsCache.fetch(path.c_str())) +RAY::Audio::Music::Music(const std::string &path, bool lonely): + _music(this->_musicsCache.fetch(path, lonely)) { } diff --git a/lib/Ray/sources/Audio/Music.hpp b/lib/Ray/sources/Audio/Music.hpp index 66ab0162..1aca0cc3 100644 --- a/lib/Ray/sources/Audio/Music.hpp +++ b/lib/Ray/sources/Audio/Music.hpp @@ -19,7 +19,8 @@ namespace RAY::Audio public: //! @brief Load Music stream from file - Music(const std::string &path); + //! @param lonely: should be set to true if the entity's loaded data must be independant from others + Music(const std::string &path, bool lonely = false); //! @brief Default destructor ~Music() = default; diff --git a/lib/Ray/sources/Audio/Sound.cpp b/lib/Ray/sources/Audio/Sound.cpp index da8df7ba..de1002bc 100644 --- a/lib/Ray/sources/Audio/Sound.cpp +++ b/lib/Ray/sources/Audio/Sound.cpp @@ -9,8 +9,8 @@ RAY::Cache<::Sound> RAY::Audio::Sound::_soundsCache(LoadSound, UnloadSound); -RAY::Audio::Sound::Sound(const std::string &path): - _sound(_soundsCache.fetch(path.c_str())) +RAY::Audio::Sound::Sound(const std::string &path, bool lonely): + _sound(_soundsCache.fetch(path, lonely)) { } diff --git a/lib/Ray/sources/Audio/Sound.hpp b/lib/Ray/sources/Audio/Sound.hpp index 00ba3ddc..0f7a7ff5 100644 --- a/lib/Ray/sources/Audio/Sound.hpp +++ b/lib/Ray/sources/Audio/Sound.hpp @@ -20,7 +20,8 @@ namespace RAY::Audio public: //! @brief Load Sound stream from file - Sound(const std::string &path); + //! @param lonely: should be set to true if the entity's loaded data must be independant from others + Sound(const std::string &path, bool lonely = false); //! @brief Default destructor ~Sound() = default; diff --git a/lib/Ray/sources/Drawables/Image.cpp b/lib/Ray/sources/Drawables/Image.cpp index 353986d3..a95246be 100644 --- a/lib/Ray/sources/Drawables/Image.cpp +++ b/lib/Ray/sources/Drawables/Image.cpp @@ -13,9 +13,9 @@ namespace RAY { Cache<::Image> Image::_imagesCache(LoadImage, UnloadImage); - Image::Image(const std::string &filename): + Image::Image(const std::string &filename, bool lonely): Rectangle(Vector2(0, 0), Vector2(0, 0), WHITE), - _image(_imagesCache.fetch(filename)), + _image(_imagesCache.fetch(filename, lonely)), _ressourcePath(filename) { this->_dimensions = Vector2(this->_image->width, this->_image->height); diff --git a/lib/Ray/sources/Drawables/Image.hpp b/lib/Ray/sources/Drawables/Image.hpp index 1f01e9fa..7963328d 100644 --- a/lib/Ray/sources/Drawables/Image.hpp +++ b/lib/Ray/sources/Drawables/Image.hpp @@ -21,7 +21,8 @@ namespace RAY public: //! @brief Create an image, loading a file //! @param filename: path to file to load - Image(const std::string &filename); + //! @param lonely: should be set to true if the entity's loaded data must be independant from others + Image(const std::string &filename, bool lonely = false); //! @brief A default copy constructor Image(const Image &image) = default; diff --git a/lib/Ray/sources/Drawables/Texture.cpp b/lib/Ray/sources/Drawables/Texture.cpp index 40a11fb3..dfdf1213 100644 --- a/lib/Ray/sources/Drawables/Texture.cpp +++ b/lib/Ray/sources/Drawables/Texture.cpp @@ -13,9 +13,9 @@ namespace RAY { Cache<::Texture> Texture::_texturesCache(LoadTexture, UnloadTexture); - Texture::Texture(const std::string &filename): + Texture::Texture(const std::string &filename, bool lonely): Rectangle(Vector2(0, 0), Vector2(0, 0), WHITE), - _texture(_texturesCache.fetch(filename)), + _texture(_texturesCache.fetch(filename, lonely)), _resourcePath(filename) { this->_dimensions = Vector2(this->_texture->width, this->_texture->height); diff --git a/lib/Ray/sources/Drawables/Texture.hpp b/lib/Ray/sources/Drawables/Texture.hpp index 03cd0dc6..931699e2 100644 --- a/lib/Ray/sources/Drawables/Texture.hpp +++ b/lib/Ray/sources/Drawables/Texture.hpp @@ -20,7 +20,8 @@ namespace RAY public: //! @brief Create an texture, loading a file //! @param filename: path to file to load - Texture(const std::string &filename); + //! @param lonely: should be set to true if the entity's loaded data must be independant from others + Texture(const std::string &filename, bool lonely = false); //! @brief A texture is copy constructable Texture(const Texture &) = default; diff --git a/lib/Ray/sources/Exceptions/RayError.cpp b/lib/Ray/sources/Exceptions/RayError.cpp index bc2ba888..a4de1200 100644 --- a/lib/Ray/sources/Exceptions/RayError.cpp +++ b/lib/Ray/sources/Exceptions/RayError.cpp @@ -21,3 +21,8 @@ RAY::Exception::NotCompatibleError::NotCompatibleError(const std::string &expect RayError(expectionMessage) { } + +RAY::Exception::WrongInputError::WrongInputError(const std::string &what): + RayError(what) +{ +} diff --git a/lib/Ray/sources/Exceptions/RayError.hpp b/lib/Ray/sources/Exceptions/RayError.hpp index f700ac17..158640d6 100644 --- a/lib/Ray/sources/Exceptions/RayError.hpp +++ b/lib/Ray/sources/Exceptions/RayError.hpp @@ -59,6 +59,23 @@ namespace RAY::Exception { //! @brief A default assignment operator NotSupportedError &operator=(const NotSupportedError &) = default; }; + + + //! @brief exception used when an non-supported operation is done + class WrongInputError: public RayError { + public: + //! @brief Create a new exception instance + explicit WrongInputError(const std::string &what = "The input can't be proceed"); + + //! @brief A default destructor + ~WrongInputError() override = default; + + //! @brief An exception is copy constructable + WrongInputError(const WrongInputError &) = default; + + //! @brief A default assignment operator + WrongInputError &operator=(const WrongInputError &) = default; + }; } #endif /* !RAYERROR_HPP_ */ diff --git a/lib/Ray/sources/Font.cpp b/lib/Ray/sources/Font.cpp index c4288463..89bf9517 100644 --- a/lib/Ray/sources/Font.cpp +++ b/lib/Ray/sources/Font.cpp @@ -9,8 +9,8 @@ RAY::Cache<::Font> RAY::Font::_fontsCache(LoadFont, UnloadFont); -RAY::Font::Font(const std::string &filename): - _font(_fontsCache.fetch(filename)) +RAY::Font::Font(const std::string &filename, bool lonely): + _font(_fontsCache.fetch(filename, lonely)) { } diff --git a/lib/Ray/sources/Font.hpp b/lib/Ray/sources/Font.hpp index a403dcb3..1aaeb173 100644 --- a/lib/Ray/sources/Font.hpp +++ b/lib/Ray/sources/Font.hpp @@ -19,7 +19,8 @@ namespace RAY public: //! @brief Create an font, loading a file //! @param filename: path to file to load - Font(const std::string &filename); + //! @param lonely: should be set to true if the entity's loaded data must be independant from others + Font(const std::string &filename, bool lonely = false); //! @brief A default copy constructor Font(const Font &) = default; diff --git a/lib/Ray/sources/Model/Model.cpp b/lib/Ray/sources/Model/Model.cpp index aab5fdc6..0a0bad2b 100644 --- a/lib/Ray/sources/Model/Model.cpp +++ b/lib/Ray/sources/Model/Model.cpp @@ -19,9 +19,9 @@ namespace RAY::Drawables::Drawables3D { const RAY::Vector3 &scale, const RAY::Vector3 &position, const RAY::Vector3 &rotationAxis, - float rotationAngle) + float rotationAngle, bool lonely) : ADrawable3D(position, WHITE), - _model(_modelsCache.fetch(filename)), + _model(_modelsCache.fetch(filename, lonely)), _rotationAxis(rotationAxis), _rotationAngle(rotationAngle), _scale(scale) @@ -106,4 +106,15 @@ namespace RAY::Drawables::Drawables3D { { DrawModelEx(*this->_model, this->_position, this->_rotationAxis, this->_rotationAngle, this->_scale, this->_color); } + + void Model::setShader(const RAY::Shader &shader) + { + this->_originalShader = this->_model->materials[0].shader; + this->_model->materials[0].shader = *shader.getShaderPtr(); + } + + void Model::resetShader() + { + this->_model->materials[0].shader = this->_originalShader; + } } \ No newline at end of file diff --git a/lib/Ray/sources/Model/Model.hpp b/lib/Ray/sources/Model/Model.hpp index 7a7e3fdf..8742a3e3 100644 --- a/lib/Ray/sources/Model/Model.hpp +++ b/lib/Ray/sources/Model/Model.hpp @@ -11,6 +11,7 @@ #include "Drawables/Texture.hpp" #include "Drawables/ADrawable3D.hpp" #include "Model/ModelAnimation.hpp" +#include "Shaders/Shaders.hpp" #include #include #include @@ -25,12 +26,13 @@ namespace RAY::Drawables::Drawables3D { //! @brief Create an model, loading a file //! @param filePath: path to file to load + //! @param lonely: should be set to true if the entity's loaded data must be independant from others Model(const std::string &filePath, std::optional> texture = std::nullopt, const RAY::Vector3 &scale = RAY::Vector3(1, 1, 1), const RAY::Vector3 &position = {0, 0, 0}, const RAY::Vector3 &rotationAxis = RAY::Vector3(0, 1, 0), - float rotationAngle = 0); + float rotationAngle = 0, bool lonely = false); //! @brief Create an model, loading a file //! @param mesh: mesh to load @@ -77,6 +79,12 @@ namespace RAY::Drawables::Drawables3D { //! @return Scale const RAY::Vector3 & getScale(void); + //! @brief Set a shader on the model + void setShader(const RAY::Shader &shader); + + //! @brief Set the original shader (used to disable a shader) + void resetShader(); + void drawOn(RAY::Window &) override; private: @@ -90,6 +98,8 @@ namespace RAY::Drawables::Drawables3D { float _rotationAngle; //! @brief Scale of the shape RAY::Vector3 _scale; + //! @brief The original shaderId used to disable a shader effect + ::Shader _originalShader = {}; static RAY::Cache<::Model> _modelsCache; diff --git a/lib/Ray/sources/Shaders/Shaders.cpp b/lib/Ray/sources/Shaders/Shaders.cpp new file mode 100644 index 00000000..435b4f72 --- /dev/null +++ b/lib/Ray/sources/Shaders/Shaders.cpp @@ -0,0 +1,49 @@ +// +// Created by cbihan on 04/06/2021. +// + +#include "Shaders.hpp" + +#include +#include "Exceptions/RayError.hpp" + +namespace RAY +{ + Cache<::Shader> Shader::_shadersCache(LoadShader, UnloadShader); + + + Shader::Shader(const std::string &vertexFile, const std::string &fragmentFile) + : _vertexFile(vertexFile), + _fragmentFile(fragmentFile), + _rayLibShader(_shadersCache.fetch(vertexFile, fragmentFile)) + { + } + + const std::shared_ptr<::Shader> &Shader::getShaderPtr() const + { + return this->_rayLibShader; + } + + void Shader::setShaderUniformVar(const std::string &varName, float value) + { + if (this->_shaderIndexVars.find(varName) == this->_shaderIndexVars.end()) { + int varShaderIndex = GetShaderLocation(*this->_rayLibShader, varName.c_str()); + + if (varShaderIndex < 0) { + throw Exception::WrongInputError("The loaded shader doesn't have a variable called: " + varName); + } + this->_shaderIndexVars[varName] = varShaderIndex; + } + SetShaderValue(*this->_rayLibShader, this->_shaderIndexVars[varName], &value, SHADER_UNIFORM_FLOAT); + } + + void Shader::BeginUsingCustomShader(Shader &shader) + { + BeginShaderMode(*shader.getShaderPtr()); + } + + void Shader::EndUsingCustomShader() + { + EndShaderMode(); + } +} \ No newline at end of file diff --git a/lib/Ray/sources/Shaders/Shaders.hpp b/lib/Ray/sources/Shaders/Shaders.hpp new file mode 100644 index 00000000..529eea64 --- /dev/null +++ b/lib/Ray/sources/Shaders/Shaders.hpp @@ -0,0 +1,55 @@ +// +// Created by cbihan on 04/06/2021. +// + +#pragma once + +#include +#include +#include +#include +#include "Utils/Cache.hpp" + +namespace RAY +{ + class Shader + { + private: + //! @brief The vertex file of the shader + std::string _vertexFile; + //! @brief The fragment file of the shader + std::string _fragmentFile; + + //! @brief Raylib shader struct + std::shared_ptr<::Shader> _rayLibShader; + + //! @brief Fetch and cache the index of the shader variable on the first set of the var + std::map _shaderIndexVars = {}; + + static Cache<::Shader> _shadersCache; + public: + //INTERNAL: + const std::shared_ptr<::Shader> &getShaderPtr() const; + + public: + + //! @brief start using a custom shader when drawing + static void BeginUsingCustomShader(RAY::Shader &shader); + //! @brief stop using the custom shader + static void EndUsingCustomShader(); + + //! @brief The set var for float values + //! @note Throw if the var is not found + void setShaderUniformVar(const std::string &varName, float value); + + //! @brief ctor if no vertexfile in needed set it to nullptr + Shader(const std::string &vertexFile, const std::string &fragmentFile); + //! @brief Default copy ctor + Shader(const Shader &) = default; + //! @brief dtor + ~Shader() = default; + //! @brief Assignment operator + Shader &operator=(const Shader &) = default; + }; + +} \ No newline at end of file diff --git a/lib/Ray/sources/Utils/Cache.hpp b/lib/Ray/sources/Utils/Cache.hpp index 653933f5..73e6a8b6 100644 --- a/lib/Ray/sources/Utils/Cache.hpp +++ b/lib/Ray/sources/Utils/Cache.hpp @@ -9,7 +9,13 @@ #include #include #include +#include #include +#include "Exceptions/RayError.hpp" +#include +#include +#include +#include namespace RAY { //! @brief A templated class used to cache ressources, indexed with a string @@ -31,16 +37,28 @@ namespace RAY { Cache &operator=(const Cache &) = default; //! @param path path of the file - //! @return a newly loaded ressource if it hasn't be previously loaded, or one from cache - std::shared_ptrfetch(const std::string &path) + //! @param lonely: should be set to true if the loaded data must be held by no other active entites + //! @return a newly loaded ressource if it hasn't be previously loaded, or one from cache + std::shared_ptrfetch(const std::string &path, bool lonely = false) { - if (this->_cache.find(path) == this->_cache.end()) - this->_cache.emplace(path, std::shared_ptr( - new T(this->_dataLoader(path.c_str())), [this](T *p) { - this->_dataUnloader(*p); - delete p; - })); - return _cache[path]; + if (!this->_cache.contains(path)) + this->_cache.emplace(path, std::vector>()); + std::vector> &matchingDataVector = this->_cache.at(path); + + if (matchingDataVector.size()) { + for (std::shared_ptr &i: matchingDataVector) { + if (!lonely) + return i; + if (lonely && i.use_count() == 1) + return i; + } + } + matchingDataVector.push_back(std::shared_ptr( + new T(this->_dataLoader(path.c_str())), [this](T *p) { + this->_dataUnloader(*p); + delete p; + })); + return matchingDataVector.back(); }; private: //! @brief function to call to load data @@ -50,14 +68,14 @@ namespace RAY { std::function _dataUnloader; //! @brief map storing shared ptr of caches - std::unordered_map> _cache; + std::unordered_map>> _cache; }; template<> class Cache<::ModelAnimation> { public: Cache(std::function<::ModelAnimation *(const char *, int *)> dataLoader, std::functiondataUnloader): - _dataLoader(dataLoader), _dataUnloader(dataUnloader) + _dataLoader(std::move(dataLoader)), _dataUnloader(std::move(dataUnloader)) {}; std::shared_ptr<::ModelAnimation> fetch(const std::string &path, int *counter) { @@ -83,4 +101,42 @@ namespace RAY { //! @brief map storing shared ptr of caches std::unordered_map> _cache; }; + + template<> + class Cache<::Shader> + { + public: + Cache(std::function<::Shader(const char *, const char *)> dataLoader, + std::function dataUnloader) : + _dataLoader(std::move(dataLoader)), _dataUnloader(std::move(dataUnloader)) + {}; + + std::shared_ptr<::Shader> fetch(const std::string &vertexFile, const std::string &fragmentFile) + { + const std::string index = vertexFile + fragmentFile; + + if (vertexFile.empty() && fragmentFile.empty()) { + throw RAY::Exception::WrongInputError(); + } + if (this->_cache.find(index) != this->_cache.end()) + return this->_cache[index]; + + this->_cache.emplace(index, std::shared_ptr<::Shader>( + new ::Shader( + this->_dataLoader(vertexFile.empty() ? nullptr : vertexFile.c_str(), fragmentFile.c_str())), + [this](::Shader *p) { + this->_dataUnloader(*p); + })); + return this->_cache[index]; + }; + private: + //! @brief function to call to load data + std::function<::Shader(const char *, const char *)> _dataLoader; + + //! @brief function to call when the ray data will be unloaded + std::function _dataUnloader; + + //! @brief map storing shared ptr of caches + std::unordered_map> _cache; + }; } diff --git a/lib/wal/sources/Entity/Entity.hpp b/lib/wal/sources/Entity/Entity.hpp index c4d00aad..5cffcc5f 100644 --- a/lib/wal/sources/Entity/Entity.hpp +++ b/lib/wal/sources/Entity/Entity.hpp @@ -44,6 +44,7 @@ namespace WAL void _componentRemoved(const std::type_index &type); friend Scene; + friend class Wal; protected: public: //! @brief A reference to the ECS. diff --git a/lib/wal/sources/Scene/Scene.cpp b/lib/wal/sources/Scene/Scene.cpp index 2e51f577..aab82e82 100644 --- a/lib/wal/sources/Scene/Scene.cpp +++ b/lib/wal/sources/Scene/Scene.cpp @@ -67,6 +67,8 @@ namespace WAL this->_entities.remove_if([this](auto &entity) { if (!entity.shouldDelete()) return false; + for (auto &cmp : entity._components) + cmp.second->onStop(); this->_entityRemoved(entity); return true; }); @@ -79,6 +81,8 @@ namespace WAL view->emplace_back(entity); } entity._notifyScene = true; + for (auto &cmp : entity._components) + cmp.second->onStart(); } this->_entities.splice(this->_entities.end(), this->_newEntities); } diff --git a/lib/wal/sources/Scene/Scene.hpp b/lib/wal/sources/Scene/Scene.hpp index 5482948f..e0aad880 100644 --- a/lib/wal/sources/Scene/Scene.hpp +++ b/lib/wal/sources/Scene/Scene.hpp @@ -40,6 +40,9 @@ namespace WAL //! @param entity The entity to remove. void _entityRemoved(const Entity &entity); public: + //! @brief Get the ID of this scene. + int getID() const; + //! @brief Get the list of entities. std::list &getEntities(); @@ -66,8 +69,6 @@ namespace WAL return *view; } - //! @return ID of the scene - int getID() const; //! @brief Delete entities marked as deleted and create scheduled entities. void applyChanges(); diff --git a/lib/wal/sources/System/System.hpp b/lib/wal/sources/System/System.hpp index 58f49970..88a1c73b 100644 --- a/lib/wal/sources/System/System.hpp +++ b/lib/wal/sources/System/System.hpp @@ -30,7 +30,7 @@ namespace WAL //! @brief Get a view of all entities containing every dependencies of this system. View &getView() override { - return this->_wal.scene->template view(); + return this->_wal.getScene()->template view(); } //! @brief Update the corresponding component of the given entity diff --git a/lib/wal/sources/Wal.hpp b/lib/wal/sources/Wal.hpp index 4748e84e..4c5dc064 100644 --- a/lib/wal/sources/Wal.hpp +++ b/lib/wal/sources/Wal.hpp @@ -5,6 +5,7 @@ #pragma once +#include #include #include #include @@ -29,6 +30,9 @@ namespace WAL //! @brief The list of registered systems std::vector> _systems = {}; + //! @brief The scene that contains entities. + std::shared_ptr _scene; + //! @brief Start the game loop //! @param callback A callback called after each update of the game. It allow you to update the engine based on a specific game state. (you can also update the game state here) //! @param state An initial game state. If not specified, it will be defaulted. @@ -52,7 +56,7 @@ namespace WAL } for (auto &system : this->_systems) system->update(dtime); - this->scene->applyChanges(); + this->_scene->applyChanges(); callback(*this, state); } } @@ -76,18 +80,38 @@ namespace WAL } for (auto &system : wal._systems) system->update(dtime); - wal.scene->applyChanges(); + wal._scene->applyChanges(); callback(wal, state); } #endif public: - //! @brief The scene that contains entities. - std::shared_ptr scene; //! @brief True if the engine should close after the end of the current tick. bool shouldClose = false; //! @brief The time between each fixed update. static constexpr std::chrono::nanoseconds timestep = std::chrono::milliseconds(32); + //! @brief Retrieve the current scene + std::shared_ptr getScene() const + { + return this->_scene; + } + + //! @brief Change the current scene + void changeScene(std::shared_ptr newScene) + { + if (this->_scene) { + for (auto &entity : this->_scene->getEntities()) { + for (auto &cmp : entity._components) + cmp.second->onStop(); + } + } + this->_scene = std::move(newScene); + for (auto &entity : this->_scene->getEntities()) { + for (auto &cmp : entity._components) + cmp.second->onStart(); + } + } + //! @brief Create a new system in place. //! @return The wal instance used to call this function is returned. This allow method chaining. template diff --git a/sources/Component/Shaders/ShaderComponent.cpp b/sources/Component/Shaders/ShaderComponent.cpp new file mode 100644 index 00000000..0320864e --- /dev/null +++ b/sources/Component/Shaders/ShaderComponent.cpp @@ -0,0 +1,57 @@ +// +// Created by cbihan on 03/06/2021. +// + +#include "ShaderComponent.hpp" + +#include +#include + +namespace BBM +{ + WAL::Component *ShaderComponent::clone(WAL::Entity &entity) const + { + return new ShaderComponent(*this); + } + + RAY::Shader &ShaderComponent::getShader() + { + return this->_shader; + } + + ShaderComponent::ShaderComponent(WAL::Entity &entity, const std::string &fragmentFilePath, const std::string &vertexFilePath) + : WAL::Component(entity), + _shader(vertexFilePath, fragmentFilePath), + _fragmentFilePath(fragmentFilePath), + _vertexFilePath(vertexFilePath) + { + } + + std::string ShaderComponent::getFragmentFilePath() const + { + return this->_fragmentFilePath; + } + + std::string ShaderComponent::getVertexFilePath() const + { + return this->_vertexFilePath; + } + + ShaderComponentModel::ShaderComponentModel(WAL::Entity &entity, std::string fragmentFilePath, std::string vertexFilePath) + : ShaderComponent(entity, std::move(fragmentFilePath), std::move(vertexFilePath)) + { + } + + void ShaderComponentModel::onStart() + { + auto &drawable = this->_entity.getComponent(); + this->model = dynamic_cast(drawable.drawable.get()); + if (!this->model) + throw std::runtime_error("No model available with a shader model component. This is unsupported."); + } + + ShaderComponentDrawable2D::ShaderComponentDrawable2D(WAL::Entity &entity, std::string fragmentFilePath, std::string vertexFilePath) + : ShaderComponent(entity, std::move(fragmentFilePath), std::move(vertexFilePath)) + { + } +} \ No newline at end of file diff --git a/sources/Component/Shaders/ShaderComponent.hpp b/sources/Component/Shaders/ShaderComponent.hpp new file mode 100644 index 00000000..51428de2 --- /dev/null +++ b/sources/Component/Shaders/ShaderComponent.hpp @@ -0,0 +1,80 @@ +// +// Created by cbihan on 03/06/2021. +// + +#pragma once + +#include +#include +#include +#include +#include + +namespace BBM +{ + class ShaderComponent : public WAL::Component + { + private: + //! @brief The shader to be applied + RAY::Shader _shader; + //! @brief The path to the fragment file + std::string _fragmentFilePath; + //! @brief The path to the vertex file + std::string _vertexFilePath; + public: + //! @brief getter for _shader + RAY::Shader &getShader(); + + //! @inherit + WAL::Component *clone(WAL::Entity &entity) const override; + + //! @brief get the fragment file path + std::string getFragmentFilePath() const; + + + //! @brief get the fragment file path + std::string getVertexFilePath() const; + + //! @brief ctor + //! @note use empty string to omit a file + ShaderComponent(WAL::Entity &entity, const std::string& fragmentFilePath, const std::string& vertexFilePath = ""); + //! @brief Default copy ctor + ShaderComponent(const ShaderComponent &) = default; + //! @brief Default dtor + ~ShaderComponent() override = default; + //! @brief Default assignment operator + ShaderComponent &operator=(const ShaderComponent &) = delete; + }; + + class ShaderComponentModel : public ShaderComponent + { + public: + RAY::Drawables::Drawables3D::Model *model = nullptr; + + void onStart() override; + + //! @brief ctor + //! @note use empty string to omit a file + ShaderComponentModel(WAL::Entity &entity, std::string fragmentFilePath, std::string vertexFilePath = ""); + //! @brief Default copy ctor + ShaderComponentModel(const ShaderComponentModel &) = default; + //! @brief Default dtor + ~ShaderComponentModel() override = default; + //! @brief Default assignment operator + ShaderComponentModel &operator=(const ShaderComponentModel &) = delete; + }; + + class ShaderComponentDrawable2D : public ShaderComponent + { + public: + //! @brief ctor + //! @note use empty string to omit a file + ShaderComponentDrawable2D(WAL::Entity &entity, std::string fragmentFilePath, std::string vertexFilePath = ""); + //! @brief Default copy ctor + ShaderComponentDrawable2D(const ShaderComponentDrawable2D &) = default; + //! @brief Default dtor + ~ShaderComponentDrawable2D() override = default; + //! @brief Default assignment operator + ShaderComponentDrawable2D &operator=(const ShaderComponentDrawable2D &) = delete; + }; +} \ No newline at end of file diff --git a/sources/Component/Sound/SoundComponent.cpp b/sources/Component/Sound/SoundComponent.cpp index 6396ff54..038b58e1 100644 --- a/sources/Component/Sound/SoundComponent.cpp +++ b/sources/Component/Sound/SoundComponent.cpp @@ -11,10 +11,12 @@ namespace BBM float SoundComponent::volume = 0.75; SoundComponent::SoundComponent(WAL::Entity &entity, - const std::map &soundPath) + const std::map &soundPath, + bool isLonely) : WAL::Component(entity), _soundIndex(IDLE), - _soundPath(soundPath) + _soundPath(soundPath), + _isLonely(isLonely) { for (int i = 0; i <= DEATH; i++) { this->_isSoundLoad[static_cast(i)] = false; @@ -22,7 +24,7 @@ namespace BBM for (auto &soundPath : soundPath) { this->_isSoundLoad[soundPath.first] = true; - this->_soundList[soundPath.first] = std::make_unique(soundPath.second); + this->_soundList[soundPath.first] = std::make_unique(soundPath.second, this->_isLonely); } } diff --git a/sources/Component/Sound/SoundComponent.hpp b/sources/Component/Sound/SoundComponent.hpp index 64a217d5..ec42fd24 100644 --- a/sources/Component/Sound/SoundComponent.hpp +++ b/sources/Component/Sound/SoundComponent.hpp @@ -59,7 +59,9 @@ namespace BBM //! @inherit WAL::Component *clone(WAL::Entity &entity) const override; //! @brief Create a new SoundComponent at a certain Sound - explicit SoundComponent(WAL::Entity &entity, const std::map &); + explicit SoundComponent(WAL::Entity &entity, + const std::map &, + bool isLonely = false); //! @brief A Sound component is copy constructable SoundComponent(const SoundComponent &) = default; //! @brief A default destructor @@ -74,6 +76,8 @@ namespace BBM std::map> _soundList; //! @brief map to know if sound is loaded std::map _isSoundLoad; + //! @brief to know if cache is needed + bool _isLonely; //! @brief All sounds path const std::map _soundPath; //! SoundIndex diff --git a/sources/Component/Tag/TagComponent.hpp b/sources/Component/Tag/TagComponent.hpp new file mode 100644 index 00000000..00fa27d5 --- /dev/null +++ b/sources/Component/Tag/TagComponent.hpp @@ -0,0 +1,54 @@ +// +// Created by Zoe Roux on 6/9/21. +// + +#pragma once + +#include +#include + +namespace BBM +{ + template + struct StringLiteral + { + public: + char value[I]; + + //! @brief Implicitly convert an array of char to a string literal. + constexpr StringLiteral(const char (&str)[I]) // NOLINT(google-explicit-constructor) + : value() + { + std::copy_n(str, I, value); + } + //! @brief A string literal is copy constructable. + constexpr StringLiteral(const StringLiteral &) = default; + //! @brief A default destructor + constexpr ~StringLiteral() = default; + //! @brief A string literal is assignable. + constexpr StringLiteral &operator=(const StringLiteral &) = default; + }; + + template + class TagComponent : public WAL::Component + { + public: + Component *clone(WAL::Entity &entity) const override + { + return new TagComponent(entity); + } + + //! @brief Create a new empty tag component. + explicit TagComponent(WAL::Entity &entity) + : WAL::Component(entity) + {} + //! @brief A default copy constructor. + TagComponent(const TagComponent &) = default; + //! @brief A default destructor + ~TagComponent() override = default; + //! @brief A tag component is not assignable. + TagComponent &operator=(const TagComponent &) = delete; + }; + + constexpr const char Blowable[] = "Blowable"; +} diff --git a/sources/Map/Map.cpp b/sources/Map/Map.cpp index 5e8a9a2e..e9af839f 100644 --- a/sources/Map/Map.cpp +++ b/sources/Map/Map.cpp @@ -6,7 +6,7 @@ #include "Component/Collision/CollisionComponent.hpp" #include "System/Collision/CollisionSystem.hpp" #include "Map.hpp" -#include +#include namespace RAY3D = RAY::Drawables::Drawables3D; @@ -23,7 +23,7 @@ namespace BBM if (collidedAxis & CollisionComponent::CollidedAxis::X) mov->_velocity.x = 0; if (collidedAxis & CollisionComponent::CollidedAxis::Y) - mov->_velocity.x = 0; + mov->_velocity.y = 0; if (collidedAxis & CollisionComponent::CollidedAxis::Z) mov->_velocity.z = 0; } @@ -56,6 +56,7 @@ namespace BBM if (!(i % 2) && !(j % 2)) { scene->addEntity("Unbreakable Wall") .addComponent(i, 0, j) + .addComponent>() .addComponent( WAL::Callback(), &MapGenerator::wallCollide, 0.25, .75) @@ -73,25 +74,28 @@ namespace BBM scene->addEntity("Bottom Wall") .addComponent(Vector3f((width + 1) / 2, 0, -1)) + .addComponent>() .addComponent( WAL::Callback(), - &MapGenerator::wallCollide, 0.25, .75) + &MapGenerator::wallCollide, Vector3f(-(width + 1) / 2 , 0.25, 0.25), Vector3f(width + 1, 2, 0.75)) .addComponent(unbreakableObj, std::make_pair(MAP_DIFFUSE, unbreakablePnj), RAY::Vector3(width + 3, 1, 1)); scene->addEntity("Upper Wall") .addComponent(Vector3f((width + 1) / 2, 0, height + 1)) + .addComponent>() .addComponent( WAL::Callback(), - &MapGenerator::wallCollide, 0.25, .75) + &MapGenerator::wallCollide, Vector3f(-(width + 1) / 2 , 0.25, 0.25), Vector3f(width + 1, 2, 0.75)) .addComponent(unbreakableObj, std::make_pair(MAP_DIFFUSE, unbreakablePnj), RAY::Vector3(width + 3, 1, 1)); scene->addEntity("Left Wall") .addComponent(Vector3f(width + 1, 0, height / 2)) + .addComponent>() .addComponent( WAL::Callback(), - &MapGenerator::wallCollide, 0.25, .75) + &MapGenerator::wallCollide, Vector3f(0.25, 0.25, -(height + 1) / 2 ), Vector3f(0.75, 2, height + 1)) .addComponent(unbreakableObj, std::make_pair(MAP_DIFFUSE, unbreakablePnj), RAY::Vector3(1, 1, height + 1)); @@ -99,7 +103,7 @@ namespace BBM .addComponent(Vector3f(-1, 0, height / 2)) .addComponent( WAL::Callback(), - &MapGenerator::wallCollide, 0.25, .75) + &MapGenerator::wallCollide, Vector3f(0.25, 0.25, -(height + 1) / 2 ), Vector3f(0.75, 2, height + 1)) .addComponent(unbreakableObj, std::make_pair(MAP_DIFFUSE, unbreakablePnj), RAY::Vector3(1, 1, height + 1)); @@ -129,16 +133,13 @@ namespace BBM {HOLE, &createHole}, {FLOOR, &createFloor}, {BUMPER, &createBumper}, - {STAIRS, &createStairs}, {UPPERFLOOR, &createUpperFloor}, }; - try { - auto element = elements.at(blockType); - element(coords, scene); - } catch (std::exception const &err) { + if (blockType == NOTHING || blockType == SPAWNER) return; - } + auto element = elements.at(blockType); + element(coords, std::move(scene)); } void MapGenerator::createBreakable(Vector3f coords, std::shared_ptr scene) @@ -148,6 +149,7 @@ namespace BBM scene->addEntity("Breakable Block") .addComponent(coords) + .addComponent>() .addComponent(1, &MapGenerator::wallDestroyed) .addComponent( WAL::Callback(), @@ -184,6 +186,7 @@ namespace BBM scene->addEntity("Unbreakable Block") .addComponent(coords) + .addComponent>() .addComponent( WAL::Callback(), &MapGenerator::wallCollide, 0.25, .75) @@ -231,17 +234,6 @@ namespace BBM }); */ } - void MapGenerator::createStairs(Vector3f coords, std::shared_ptr scene) - { - static const std::string stairsObj = stairsPath + objExtension; - static const std::string stairsPng = stairsPath + imageExtension; - - scene->addEntity("Stairs Block") - .addComponent(coords) - //.addComponent(1) - .addComponent(stairsObj, std::make_pair(MAP_DIFFUSE, stairsPng)); - } - bool MapGenerator::isCloseToBlockType(std::map, BlockType> map, int x, int y, int z, BlockType blockType) { @@ -273,10 +265,10 @@ namespace BBM map[std::make_tuple(i, 1, 0)] = map[std::make_tuple(i, 0, 0)]; map[std::make_tuple(i, 0, 0)] = UPPERFLOOR; } - map[std::make_tuple(0, 0, height - 1)] = STAIRS; - map[std::make_tuple(0, 0, 1)] = STAIRS; - map[std::make_tuple(width, 0, height - 1)] = STAIRS; - map[std::make_tuple(width, 0, 1)] = STAIRS; + map[std::make_tuple(0, -1, height - 1)] = BUMPER; + map[std::make_tuple(0, -1, 1)] = BUMPER; + map[std::make_tuple(width, -1, height - 1)] = BUMPER; + map[std::make_tuple(width, -1, 1)] = BUMPER; map[std::make_tuple(width / 2, -1, height - 1)] = BUMPER; map[std::make_tuple(width / 2, -1, 1)] = BUMPER; } @@ -289,10 +281,10 @@ namespace BBM map[std::make_tuple(i, 0, j)] = UPPERFLOOR; } } - map[std::make_tuple(width / 2 - width / 8, 0, height / 2 + height / 4 + 1)] = STAIRS; - map[std::make_tuple(width / 2 + width / 8, 0, height / 2 - height / 4 - 1)] = STAIRS; - map[std::make_tuple(width / 2 - width / 4 - 1, 0, height / 2 - height / 8)] = STAIRS; - map[std::make_tuple(width / 2 + width / 4 + 1, 0, height / 2 + height / 8)] = STAIRS; + map[std::make_tuple(width / 2 - width / 8, -1, height / 2 + height / 4 + 1)] = BUMPER; + map[std::make_tuple(width / 2 + width / 8, -1, height / 2 - height / 4 - 1)] = BUMPER; + map[std::make_tuple(width / 2 - width / 4 - 1, -1, height / 2 - height / 8)] = BUMPER; + map[std::make_tuple(width / 2 + width / 4 + 1, -1, height / 2 + height / 8)] = BUMPER; } return map; } @@ -311,8 +303,6 @@ namespace BBM { for (int i = 0; i < width + 1; i++) for (int j = 0; j < height; j++) { - if (map[std::make_tuple(i, 0, j)] == BREAKABLE && isCloseToBlockType(map, i, 0, j, STAIRS)) - map[std::make_tuple(i, 0, j)] = NOTHING; if (map[std::make_tuple(i, 0, j)] == BREAKABLE && map[std::make_tuple(i, -1, j)] == BUMPER) map[std::make_tuple(i, 0, j)] = NOTHING; } diff --git a/sources/Map/Map.hpp b/sources/Map/Map.hpp index 4a961cbc..f99fd550 100644 --- a/sources/Map/Map.hpp +++ b/sources/Map/Map.hpp @@ -37,7 +37,6 @@ namespace BBM UPPERFLOOR, FLOOR, BUMPER, - STAIRS, SPAWNER, UNBREAKABLE }; @@ -109,12 +108,6 @@ namespace BBM //! @brief Create upper floor of the map static void createUpperFloor(Vector3f coords, std::shared_ptr scene); - - //! @param coords coords of the element - //! @param scene Scene where the map is instanced - //! @brief Create stair of the map - static void createStairs(Vector3f coords, std::shared_ptr scene); - //! @param map Map to load with block declared inside //! @param width Width of the map //! @param height Height of the map diff --git a/sources/Models/Vector3.hpp b/sources/Models/Vector3.hpp index d4ba7337..a2266e07 100644 --- a/sources/Models/Vector3.hpp +++ b/sources/Models/Vector3.hpp @@ -168,6 +168,11 @@ namespace BBM return (point * this) / std::pow(this->magnitude(), 2) * this; } + Vector3 round() const requires(std::is_floating_point_v) + { + return Vector3(std::round(this->x), std::round(this->y), std::round(this->z)); + } + operator RAY::Vector3() const requires(std::is_same_v) { return RAY::Vector3(this->x, this->y, this->z); diff --git a/sources/Runner/Runner.cpp b/sources/Runner/Runner.cpp index e4cde34b..6d6b36cb 100644 --- a/sources/Runner/Runner.cpp +++ b/sources/Runner/Runner.cpp @@ -12,6 +12,7 @@ #include #include