diff options
| author | Ethan Morgan <ethan@gweithio.com> | 2026-02-14 16:44:06 +0000 |
|---|---|---|
| committer | Ethan Morgan <ethan@gweithio.com> | 2026-02-14 16:44:06 +0000 |
| commit | 54409423f767d8b1cf30cb7d0efca6b4ca138823 (patch) | |
| tree | d915ac7828703ce4b963efdd9728a1777ba18c1e /apps/openmb/resources/shaders | |
Diffstat (limited to 'apps/openmb/resources/shaders')
19 files changed, 487 insertions, 0 deletions
diff --git a/apps/openmb/resources/shaders/.gitkeep b/apps/openmb/resources/shaders/.gitkeep new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/apps/openmb/resources/shaders/.gitkeep diff --git a/apps/openmb/resources/shaders/cube.frag b/apps/openmb/resources/shaders/cube.frag new file mode 100644 index 0000000..cb15430 --- /dev/null +++ b/apps/openmb/resources/shaders/cube.frag @@ -0,0 +1,21 @@ +#version 330 core +out vec4 FragColor; +uniform vec3 color; +in vec3 vFragPos; +uniform vec3 cameraPos; +uniform vec3 fogColor; +uniform float fogDensity; +uniform float fogAmount; + +void main() +{ + // Basic color with fog applied + vec3 base = color; + + // vFragPos provided by vertex shader + float dist = length(vFragPos - cameraPos); + float fogFactor = 1.0 - exp(-fogDensity * dist); + fogFactor = clamp(fogFactor * fogAmount, 0.0, 1.0); + vec3 finalColor = mix(base, fogColor, fogFactor); + FragColor = vec4(finalColor, 1.0); +} diff --git a/apps/openmb/resources/shaders/cube.vert b/apps/openmb/resources/shaders/cube.vert new file mode 100644 index 0000000..805c883 --- /dev/null +++ b/apps/openmb/resources/shaders/cube.vert @@ -0,0 +1,11 @@ +#version 330 core +layout(location = 0) in vec3 aPos; +uniform mat4 model; +uniform mat4 view; +uniform mat4 proj; +out vec3 vFragPos; +void main() +{ + vFragPos = vec3(model * vec4(aPos, 1.0)); + gl_Position = proj * view * model * vec4(aPos, 1.0); +} diff --git a/apps/openmb/resources/shaders/depth.frag b/apps/openmb/resources/shaders/depth.frag new file mode 100644 index 0000000..f6ba8e2 --- /dev/null +++ b/apps/openmb/resources/shaders/depth.frag @@ -0,0 +1,5 @@ +#version 330 core +void main() +{ + +} diff --git a/apps/openmb/resources/shaders/depth.vert b/apps/openmb/resources/shaders/depth.vert new file mode 100644 index 0000000..e80ee01 --- /dev/null +++ b/apps/openmb/resources/shaders/depth.vert @@ -0,0 +1,10 @@ +#version 330 core +layout(location = 0) in vec3 aPos; + +uniform mat4 model; +uniform mat4 lightSpace; + +void main() +{ + gl_Position = lightSpace * model * vec4(aPos, 1.0); +} diff --git a/apps/openmb/resources/shaders/gbuffer.frag b/apps/openmb/resources/shaders/gbuffer.frag new file mode 100644 index 0000000..f6ddb45 --- /dev/null +++ b/apps/openmb/resources/shaders/gbuffer.frag @@ -0,0 +1,10 @@ +#version 330 core +in vec2 vUV; +in vec3 vNormalView; +layout(location = 0) out vec3 gNormal; + +void main() +{ + vec3 n = normalize(vNormalView); + gNormal = n * 0.5 + 0.5; +} diff --git a/apps/openmb/resources/shaders/gbuffer.vert b/apps/openmb/resources/shaders/gbuffer.vert new file mode 100644 index 0000000..c9e677c --- /dev/null +++ b/apps/openmb/resources/shaders/gbuffer.vert @@ -0,0 +1,19 @@ +#version 330 core +layout(location = 0) in vec3 aPos; +layout(location = 1) in vec2 aUV; +layout(location = 2) in vec3 aNormal; + +uniform mat4 model; +uniform mat4 view; +uniform mat4 proj; + +out vec2 vUV; +out vec3 vNormalView; + +void main() +{ + vUV = aUV; + vec4 viewPos = view * model * vec4(aPos, 1.0); + vNormalView = mat3(transpose(inverse(view * model))) * aNormal; + gl_Position = proj * viewPos; +} diff --git a/apps/openmb/resources/shaders/godrays_quad.vert b/apps/openmb/resources/shaders/godrays_quad.vert new file mode 100644 index 0000000..6a33825 --- /dev/null +++ b/apps/openmb/resources/shaders/godrays_quad.vert @@ -0,0 +1,11 @@ +#version 330 core +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec2 aTex; + +out vec2 vTex; + +void main() +{ + vTex = aTex; + gl_Position = vec4(aPos, 1.0); +} diff --git a/apps/openmb/resources/shaders/godrays_radial.frag b/apps/openmb/resources/shaders/godrays_radial.frag new file mode 100644 index 0000000..3dfac87 --- /dev/null +++ b/apps/openmb/resources/shaders/godrays_radial.frag @@ -0,0 +1,44 @@ +#version 330 core +in vec2 vTex; +out vec4 FragColor; + +uniform sampler2D occlusionTex; +uniform vec2 lightScreenPos; // in [0,1] +uniform vec3 sunColor; +uniform float sunIntensity; +uniform float globalIntensity; +uniform int samples; +uniform float density; +uniform float weight; +uniform float decay; + +void main() +{ + vec2 texCoord = vTex; + // vector from current pixel to light + vec2 delta = lightScreenPos - texCoord; + float dist = length(delta); + vec2 stepv = delta * (1.0 / float(samples)) * density; + + vec3 illumination = vec3(0.0); + float illumDecay = 1.0; + + vec2 coord = texCoord; + for (int i = 0; i < samples; ++i) + { + coord += stepv; + vec3 sample = texture(occlusionTex, coord).rgb; + // occlusion tex stores white where geometry present + float occ = sample.r; + illumination += occ * illumDecay * weight; + illumDecay *= decay; + } + + vec3 result = illumination * sunColor * sunIntensity * globalIntensity; + // tone-map / clamp to avoid extreme brightness + result = clamp(result, vec3(0.0), vec3(1.0)); + // use luminance as alpha so we can composite less aggressively + float lum = dot(result, vec3(0.299, 0.587, 0.114)); + float alpha = clamp(lum, 0.0, 1.0); + FragColor = vec4(result, alpha); +} diff --git a/apps/openmb/resources/shaders/occlusion.frag b/apps/openmb/resources/shaders/occlusion.frag new file mode 100644 index 0000000..02a0732 --- /dev/null +++ b/apps/openmb/resources/shaders/occlusion.frag @@ -0,0 +1,8 @@ +#version 330 core +out vec4 FragColor; + +void main() +{ + // Solid white occluder + FragColor = vec4(1.0); +} diff --git a/apps/openmb/resources/shaders/occlusion.vert b/apps/openmb/resources/shaders/occlusion.vert new file mode 100644 index 0000000..9d95f3a --- /dev/null +++ b/apps/openmb/resources/shaders/occlusion.vert @@ -0,0 +1,11 @@ +#version 330 core +layout (location = 0) in vec3 aPos; + +uniform mat4 model; +uniform mat4 view; +uniform mat4 proj; + +void main() +{ + gl_Position = proj * view * model * vec4(aPos, 1.0); +} diff --git a/apps/openmb/resources/shaders/skybox.frag b/apps/openmb/resources/shaders/skybox.frag new file mode 100644 index 0000000..f9e41eb --- /dev/null +++ b/apps/openmb/resources/shaders/skybox.frag @@ -0,0 +1,8 @@ +#version 330 core +in vec3 TexCoords; +out vec4 FragColor; +uniform samplerCube skybox; +void main() +{ + FragColor = texture(skybox, TexCoords); +} diff --git a/apps/openmb/resources/shaders/skybox.vert b/apps/openmb/resources/shaders/skybox.vert new file mode 100644 index 0000000..8e66a99 --- /dev/null +++ b/apps/openmb/resources/shaders/skybox.vert @@ -0,0 +1,10 @@ +#version 330 core +layout(location = 0) in vec3 aPos; +out vec3 TexCoords; +uniform mat4 view; +uniform mat4 proj; +void main() +{ + TexCoords = aPos; + gl_Position = proj * view * vec4(aPos, 1.0); +} diff --git a/apps/openmb/resources/shaders/ssao.frag b/apps/openmb/resources/shaders/ssao.frag new file mode 100644 index 0000000..60479f2 --- /dev/null +++ b/apps/openmb/resources/shaders/ssao.frag @@ -0,0 +1,76 @@ +#version 330 core +in vec2 vUV; +out float FragColor; + +uniform sampler2D gDepth; +uniform sampler2D gNormal; +uniform sampler2D texNoise; + +uniform vec3 samples[64]; +uniform mat4 proj; +uniform mat4 invProj; +uniform float radius; +uniform float bias; +uniform float noiseScale; + +uniform int kernelSize; +uniform float power; + +vec3 getViewPos(vec2 uv) +{ + float depth = texture(gDepth, uv).r; + if (depth == 1.0) return vec3(0.0); + float z = depth * 2.0 - 1.0; + vec4 clip = vec4(uv * 2.0 - 1.0, z, 1.0); + vec4 viewPos = invProj * clip; + viewPos /= viewPos.w; + return viewPos.xyz; +} + +void main() +{ + vec3 fragPos = getViewPos(vUV); + if (fragPos == vec3(0.0)) + { + FragColor = 1.0; + return; + } + + vec3 normal = texture(gNormal, vUV).rgb; + normal = normalize(normal * 2.0 - 1.0); + + vec3 randomVec = normalize(texture(texNoise, vUV * noiseScale).xyz * 2.0 - 1.0); + + + vec3 tangent = normalize(randomVec - normal * dot(randomVec, normal)); + vec3 bitangent = cross(normal, tangent); + mat3 TBN = mat3(tangent, bitangent, normal); + + float occlusion = 0.0; + for (int i = 0; i < kernelSize; ++i) + { + vec3 sample = TBN * samples[i]; + sample = fragPos + sample * radius; + + + vec4 offset = proj * vec4(sample, 1.0); + offset.xyz /= offset.w; + vec2 sampleUV = offset.xy * 0.5 + 0.5; + + if (sampleUV.x < 0.0 || sampleUV.x > 1.0 || sampleUV.y < 0.0 || sampleUV.y > 1.0) + continue; + + vec3 samplePos = getViewPos(sampleUV); + if (samplePos == vec3(0.0)) + continue; + + float rangeCheck = smoothstep(0.0, 1.0, radius / abs(fragPos.z - samplePos.z)); + float diff = samplePos.z - sample.z; + if (diff > bias) + occlusion += rangeCheck; + } + + occlusion = 1.0 - (occlusion / float(kernelSize)); + occlusion = pow(occlusion, power); + FragColor = occlusion; +} diff --git a/apps/openmb/resources/shaders/ssao.vert b/apps/openmb/resources/shaders/ssao.vert new file mode 100644 index 0000000..5afd1d3 --- /dev/null +++ b/apps/openmb/resources/shaders/ssao.vert @@ -0,0 +1,9 @@ +#version 330 core +layout(location = 0) in vec2 aPos; +layout(location = 1) in vec2 aUV; +out vec2 vUV; +void main() +{ + vUV = aUV; + gl_Position = vec4(aPos, 0.0, 1.0); +} diff --git a/apps/openmb/resources/shaders/ssao_blur.frag b/apps/openmb/resources/shaders/ssao_blur.frag new file mode 100644 index 0000000..e093eff --- /dev/null +++ b/apps/openmb/resources/shaders/ssao_blur.frag @@ -0,0 +1,45 @@ +#version 330 core +in vec2 vUV; +out float FragColor; + +uniform sampler2D ssaoInput; +uniform vec2 texelSize; +uniform int horizontal; + + +const float w0 = 0.2270270270; +const float w1 = 0.1945945946; +const float w2 = 0.1216216216; +const float w3 = 0.0540540541; +const float w4 = 0.0162162162; + +void main() +{ + float result = 0.0; + if (horizontal == 1) + { + result += texture(ssaoInput, vUV).r * w0; + result += texture(ssaoInput, vUV + vec2(texelSize.x, 0.0)).r * w1; + result += texture(ssaoInput, vUV - vec2(texelSize.x, 0.0)).r * w1; + result += texture(ssaoInput, vUV + vec2(2.0 * texelSize.x, 0.0)).r * w2; + result += texture(ssaoInput, vUV - vec2(2.0 * texelSize.x, 0.0)).r * w2; + result += texture(ssaoInput, vUV + vec2(3.0 * texelSize.x, 0.0)).r * w3; + result += texture(ssaoInput, vUV - vec2(3.0 * texelSize.x, 0.0)).r * w3; + result += texture(ssaoInput, vUV + vec2(4.0 * texelSize.x, 0.0)).r * w4; + result += texture(ssaoInput, vUV - vec2(4.0 * texelSize.x, 0.0)).r * w4; + } + else + { + result += texture(ssaoInput, vUV).r * w0; + result += texture(ssaoInput, vUV + vec2(0.0, texelSize.y)).r * w1; + result += texture(ssaoInput, vUV - vec2(0.0, texelSize.y)).r * w1; + result += texture(ssaoInput, vUV + vec2(0.0, 2.0 * texelSize.y)).r * w2; + result += texture(ssaoInput, vUV - vec2(0.0, 2.0 * texelSize.y)).r * w2; + result += texture(ssaoInput, vUV + vec2(0.0, 3.0 * texelSize.y)).r * w3; + result += texture(ssaoInput, vUV - vec2(0.0, 3.0 * texelSize.y)).r * w3; + result += texture(ssaoInput, vUV + vec2(0.0, 4.0 * texelSize.y)).r * w4; + result += texture(ssaoInput, vUV - vec2(0.0, 4.0 * texelSize.y)).r * w4; + } + + FragColor = result; +} diff --git a/apps/openmb/resources/shaders/textured.frag b/apps/openmb/resources/shaders/textured.frag new file mode 100644 index 0000000..ea5e207 --- /dev/null +++ b/apps/openmb/resources/shaders/textured.frag @@ -0,0 +1,45 @@ +#version 330 core + +in vec2 vUV; +out vec4 FragColor; + +uniform sampler2D albedo; +uniform sampler2D normalMap; +uniform int normalEnabled; +uniform float normalStrength; +uniform vec3 tint; +uniform int radialEnabled; +uniform float radialInner; +uniform float radialOuter; + +void main() +{ + vec4 tex = texture(albedo, vUV); + vec3 color = tex.rgb * tint; + float alpha = tex.a; + vec3 finalNormal = vec3(0.0, 0.0, 1.0); + if (normalEnabled == 1) + { + vec3 n = texture(normalMap, vUV).rgb; + n = n * 2.0 - 1.0; + finalNormal = normalize(vec3(n.x * normalStrength, n.y * normalStrength, 1.0)); + } + if (radialEnabled == 1) + { + + float dist = distance(vUV, vec2(0.5, 0.5)); + + float mask = 1.0 - smoothstep(radialInner, radialOuter, dist); + alpha *= mask; + } + + if (normalEnabled == 1) + { + vec3 lightDir = normalize(vec3(0.3, 1.0, 0.5)); + float l = max(dot(normalize(finalNormal), lightDir), 0.0); + + color *= (0.4 + 0.6 * l); + } + + FragColor = vec4(color, alpha); +} diff --git a/apps/openmb/resources/shaders/textured.vert b/apps/openmb/resources/shaders/textured.vert new file mode 100644 index 0000000..f71f407 --- /dev/null +++ b/apps/openmb/resources/shaders/textured.vert @@ -0,0 +1,23 @@ +#version 330 core +layout(location = 0) in vec3 aPos; +layout(location = 1) in vec2 aUV; +layout(location = 2) in vec3 aNormal; + +uniform mat4 model; +uniform mat4 view; +uniform mat4 proj; +uniform mat4 lightSpace; + +out vec2 vUV; +out vec3 vNormal; +out vec3 vFragPos; +out vec4 vFragPosLightSpace; + +void main() +{ + vUV = aUV; + vFragPos = vec3(model * vec4(aPos, 1.0)); + vNormal = mat3(transpose(inverse(model))) * aNormal; + vFragPosLightSpace = lightSpace * vec4(vFragPos, 1.0); + gl_Position = proj * view * model * vec4(aPos, 1.0); +} diff --git a/apps/openmb/resources/shaders/textured_lit.frag b/apps/openmb/resources/shaders/textured_lit.frag new file mode 100644 index 0000000..58c71f7 --- /dev/null +++ b/apps/openmb/resources/shaders/textured_lit.frag @@ -0,0 +1,121 @@ +#version 330 core + +in vec2 vUV; +in vec3 vNormal; +in vec3 vFragPos; +in vec4 vFragPosLightSpace; +out vec4 FragColor; + +uniform sampler2D albedo; +uniform sampler2D normalMap; +uniform int normalEnabled; +uniform float normalStrength; +uniform vec3 tint; +uniform int radialEnabled; +uniform float radialInner; +uniform float radialOuter; + +struct DirectionalLight +{ + vec3 direction; + vec3 color; + float intensity; +}; + +uniform DirectionalLight dirLight; +uniform vec3 ambientColor = vec3(0.15, 0.15, 0.15); +uniform sampler2D shadowMap; +uniform float shadowBiasMin; +uniform float shadowBiasScale; +uniform int pcfRadius; +uniform sampler2D ssao; +uniform float aoStrength; +uniform float screenWidth; +uniform float screenHeight; + +// Fog +uniform vec3 cameraPos; +uniform vec3 fogColor; +uniform float fogDensity; // e.g. 0.02 +uniform float fogAmount; // 0..1 blend factor +float ShadowCalculation(vec4 fragPosLightSpace, vec3 normal, vec3 lightDir) +{ + + vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w; + + projCoords = projCoords * 0.5 + 0.5; + + if (projCoords.z > 1.0) + return 0.0; + + + float currentDepth = projCoords.z; + + float bias = max(shadowBiasScale * (1.0 - max(dot(normal, lightDir), 0.0)), shadowBiasMin); + + + ivec2 texSize = textureSize(shadowMap, 0); + vec2 texelSize = 1.0 / vec2(texSize); + float vis = 0.0; + int samples = 0; + for (int x = -pcfRadius; x <= pcfRadius; ++x) + { + for (int y = -pcfRadius; y <= pcfRadius; ++y) + { + vec2 offset = vec2(x, y) * texelSize; + float depthSample = texture(shadowMap, projCoords.xy + offset).r; + // texture returns stored light-space depth. If our fragment's depth (minus bias) + // is less than or equal to the sampled depth, it's visible to the light. + vis += (currentDepth - bias <= depthSample) ? 1.0 : 0.0; + samples++; + } + } + float visibility = vis / float(samples); + float shadow = 1.0 - visibility; + return shadow; +} + +void main() +{ + vec4 tex = texture(albedo, vUV); + vec3 color = tex.rgb * tint; + float alpha = tex.a; + vec3 finalNormal = vec3(0.0, 0.0, 1.0); + if (normalEnabled == 1) + { + vec3 n = texture(normalMap, vUV).rgb; + n = n * 2.0 - 1.0; + finalNormal = normalize(vec3(n.x * normalStrength, n.y * normalStrength, 1.0)); + } + if (radialEnabled == 1) + { + float dist = distance(vUV, vec2(0.5, 0.5)); + float mask = 1.0 - smoothstep(radialInner, radialOuter, dist); + alpha *= mask; + } + + + vec3 N = normalize(finalNormal); + vec3 L = normalize(dirLight.direction); + float diff = max(dot(N, L), 0.0); + vec3 diffuse = dirLight.color * dirLight.intensity * diff; + + float shadow = ShadowCalculation(vFragPosLightSpace, N, L); + float shadowFactor = 1.0 - shadow * 0.9; + float ao = 1.0; + if (aoStrength > 0.0) + { + vec2 ssaoUV = gl_FragCoord.xy / vec2(screenWidth, screenHeight); + ao = texture(ssao, ssaoUV).r; + } + float aoFactor = mix(1.0, ao, aoStrength); + vec3 result = color * (ambientColor * aoFactor + diffuse * shadowFactor); + + // Compute fog based on distance from camera + float dist = length(vFragPos - cameraPos); + float fogFactor = 1.0 - exp(-fogDensity * dist); + fogFactor = clamp(fogFactor * fogAmount, 0.0, 1.0); + vec3 finalColor = mix(result, fogColor, fogFactor); + + FragColor = vec4(finalColor, alpha); +} |