Working on the night mode

This commit is contained in:
Vladislav Khorev committed 2026-06-04 13:27:52 +03:00
1 parent e6bfe85e2e
commit 442d3a7945
18 files changed
+1060 -2

No files matched your search

+22
View File
@@ -0,0 +1,22 @@
attribute vec3 vPosition;
attribute vec2 vTexCoord;
attribute vec3 vNormal;
varying vec2 texCoord;
varying float fogDistance;
varying vec3 fragViewPos;
varying vec3 fragNormal;
uniform mat4 ProjectionModelViewMatrix;
uniform mat4 ModelViewMatrix;
uniform vec3 uPlayerEyePos;
void main()
{
vec4 eyePos = ModelViewMatrix * vec4(vPosition.xyz, 1.0);
fogDistance = length(eyePos.xyz - uPlayerEyePos);
gl_Position = ProjectionModelViewMatrix * vec4(vPosition.xyz, 1.0);
texCoord = vTexCoord;
fragViewPos = eyePos.xyz;
fragNormal = mat3(ModelViewMatrix) * vNormal;
}
@@ -0,0 +1,56 @@
uniform sampler2D Texture;
uniform float uAlpha;
uniform int uPointLightCount;
uniform vec3 uPointLightPos[4];
uniform vec3 uPointLightDir[4];
uniform vec3 uPointLightColor[4];
varying vec2 texCoord;
varying float fogDistance;
varying vec3 fragViewPos;
varying vec3 fragNormal;
// cos(45 deg) = half-angle for a 90-degree full-angle spotlight
const float SPOT_COS_OUTER = 0.7071;
const float SPOT_COS_INNER = 0.82; // slightly tighter inner cone for smooth edge
void main()
{
vec4 color = texture2D(Texture, texCoord);
if (color.a < 0.1)
discard;
float ambient = 0.37;
vec3 lighting = vec3(ambient);
bool hasNormal = dot(fragNormal, fragNormal) > 0.001;
vec3 N = hasNormal ? normalize(fragNormal) : vec3(0.0);
for (int i = 0; i < 4; i++)
{
if (i >= uPointLightCount) break;
vec3 lightVec = uPointLightPos[i] - fragViewPos;
float dist = length(lightVec);
vec3 lightDir = normalize(lightVec);
// Spotlight cone: angle between the cone axis and the ray from light to fragment
float cosTheta = dot(-lightDir, normalize(uPointLightDir[i]));
float spotAtten = smoothstep(SPOT_COS_OUTER, SPOT_COS_INNER, cosTheta);
if (spotAtten <= 0.0) continue;
float atten = 1.0 / (1.0 + 0.35 * dist + 0.15 * dist * dist);
float diff = hasNormal ? max(dot(N, lightDir), 0.0) : 1.0;
lighting += uPointLightColor[i] * diff * atten * spotAtten;
}
color.rgb *= lighting;
vec3 fogColor = vec3(0.01, 0.01, 0.05);
float fogFactor = clamp((fogDistance - 15.0) / 8.0, 0.0, 1.0);
color.rgb = mix(color.rgb, fogColor, fogFactor);
gl_FragColor = vec4(color.rgb, color.a * uAlpha);
}
+25
View File
@@ -0,0 +1,25 @@
attribute vec3 vPosition;
attribute vec2 vTexCoord;
attribute vec3 vNormal;
varying vec2 texCoord;
varying vec4 fragPosLightSpace;
varying vec3 fragNormal;
varying float fogDistance;
varying vec3 fragViewPos;
uniform mat4 ProjectionModelViewMatrix;
uniform mat4 ModelViewMatrix;
uniform mat4 uLightFromCamera;
uniform vec3 uPlayerEyePos;
void main()
{
vec4 eyePos = ModelViewMatrix * vec4(vPosition, 1.0);
fogDistance = length(eyePos.xyz - uPlayerEyePos);
gl_Position = ProjectionModelViewMatrix * vec4(vPosition, 1.0);
texCoord = vTexCoord;
fragViewPos = eyePos.xyz;
fragNormal = mat3(ModelViewMatrix) * vNormal;
fragPosLightSpace = uLightFromCamera * eyePos;
}
@@ -0,0 +1,95 @@
uniform sampler2D Texture;
uniform sampler2D uShadowMap;
uniform vec3 uLightDir;
uniform float uAlpha;
uniform int uPointLightCount;
uniform vec3 uPointLightPos[4];
uniform vec3 uPointLightDir[4];
uniform vec3 uPointLightColor[4];
varying vec2 texCoord;
varying vec4 fragPosLightSpace;
varying vec3 fragNormal;
varying float fogDistance;
varying vec3 fragViewPos;
const float SPOT_COS_OUTER = 0.7071;
const float SPOT_COS_INNER = 0.82;
float computeShadow(vec4 lightSpacePos, vec3 normal)
{
vec3 projCoords = lightSpacePos.xyz / lightSpacePos.w;
projCoords = projCoords * 0.5 + 0.5;
if (projCoords.x < 0.0 || projCoords.x > 1.0 ||
projCoords.y < 0.0 || projCoords.y > 1.0 ||
projCoords.z > 1.0)
{
return 0.0;
}
float currentDepth = projCoords.z;
float bias = 0.0004;
if (dot(normal, normal) > 0.001)
{
float cosTheta = dot(normalize(normal), -normalize(uLightDir));
bias = max(0.002 * (1.0 - cosTheta), 0.0002);
}
float shadow = 0.0;
float texelSize = 1.0 / 2048.0;
for (int x = -1; x <= 1; x++)
{
for (int y = -1; y <= 1; y++)
{
float pcfDepth = texture2D(uShadowMap, projCoords.xy + vec2(float(x), float(y)) * texelSize).r;
shadow += currentDepth - bias > pcfDepth ? 1.0 : 0.0;
}
}
shadow /= 9.0;
return shadow;
}
void main()
{
vec4 color = texture2D(Texture, texCoord);
if (color.a < 0.1)
discard;
float ambient = 0.37;
vec3 lighting = vec3(ambient);
bool hasNormal = dot(fragNormal, fragNormal) > 0.001;
vec3 N = hasNormal ? normalize(fragNormal) : vec3(0.0);
float shadow = computeShadow(fragPosLightSpace, fragNormal);
for (int i = 0; i < 4; i++)
{
if (i >= uPointLightCount) break;
vec3 lightVec = uPointLightPos[i] - fragViewPos;
float dist = length(lightVec);
vec3 lightDir = normalize(lightVec);
float cosTheta = dot(-lightDir, normalize(uPointLightDir[i]));
float spotAtten = smoothstep(SPOT_COS_OUTER, SPOT_COS_INNER, cosTheta);
if (spotAtten <= 0.0) continue;
float atten = 1.0 / (1.0 + 0.35 * dist + 0.15 * dist * dist);
float diff = hasNormal ? max(dot(N, lightDir), 0.0) : 1.0;
lighting += uPointLightColor[i] * diff * atten * spotAtten * (1.0 - shadow);
}
color.rgb *= lighting;
vec3 fogColor = vec3(0.01, 0.01, 0.05);
float fogFactor = clamp((fogDistance - 15.0) / 8.0, 0.0, 1.0);
color.rgb = mix(color.rgb, fogColor, fogFactor);
gl_FragColor = vec4(color.rgb, color.a * uAlpha);
}
@@ -0,0 +1,97 @@
precision mediump float;
uniform sampler2D Texture;
uniform sampler2D uShadowMap;
uniform vec3 uLightDir;
uniform float uAlpha;
uniform int uPointLightCount;
uniform vec3 uPointLightPos[4];
uniform vec3 uPointLightDir[4];
uniform vec3 uPointLightColor[4];
varying vec2 texCoord;
varying vec4 fragPosLightSpace;
varying vec3 fragNormal;
varying float fogDistance;
varying vec3 fragViewPos;
const float SPOT_COS_OUTER = 0.7071;
const float SPOT_COS_INNER = 0.82;
float computeShadow(vec4 lightSpacePos, vec3 normal)
{
vec3 projCoords = lightSpacePos.xyz / lightSpacePos.w;
projCoords = projCoords * 0.5 + 0.5;
if (projCoords.x < 0.0 || projCoords.x > 1.0 ||
projCoords.y < 0.0 || projCoords.y > 1.0 ||
projCoords.z > 1.0)
{
return 0.0;
}
float currentDepth = projCoords.z;
float bias = 0.0004;
if (dot(normal, normal) > 0.001)
{
float cosTheta = dot(normalize(normal), -normalize(uLightDir));
bias = max(0.002 * (1.0 - cosTheta), 0.0002);
}
float shadow = 0.0;
float texelSize = 1.0 / 2048.0;
for (int x = -1; x <= 1; x++)
{
for (int y = -1; y <= 1; y++)
{
float pcfDepth = texture2D(uShadowMap, projCoords.xy + vec2(float(x), float(y)) * texelSize).r;
shadow += currentDepth - bias > pcfDepth ? 1.0 : 0.0;
}
}
shadow /= 9.0;
return shadow;
}
void main()
{
vec4 color = texture2D(Texture, texCoord);
if (color.a < 0.1)
discard;
float ambient = 0.37;
vec3 lighting = vec3(ambient);
bool hasNormal = dot(fragNormal, fragNormal) > 0.001;
vec3 N = hasNormal ? normalize(fragNormal) : vec3(0.0);
float shadow = computeShadow(fragPosLightSpace, fragNormal);
for (int i = 0; i < 4; i++)
{
if (i >= uPointLightCount) break;
vec3 lightVec = uPointLightPos[i] - fragViewPos;
float dist = length(lightVec);
vec3 lightDir = normalize(lightVec);
float cosTheta = dot(-lightDir, normalize(uPointLightDir[i]));
float spotAtten = smoothstep(SPOT_COS_OUTER, SPOT_COS_INNER, cosTheta);
if (spotAtten <= 0.0) continue;
float atten = 1.0 / (1.0 + 0.35 * dist + 0.15 * dist * dist);
float diff = hasNormal ? max(dot(N, lightDir), 0.0) : 1.0;
lighting += uPointLightColor[i] * diff * atten * spotAtten * (1.0 - shadow);
}
color.rgb *= lighting;
vec3 fogColor = vec3(0.01, 0.01, 0.05);
float fogFactor = clamp((fogDistance - 15.0) / 8.0, 0.0, 1.0);
color.rgb = mix(color.rgb, fogColor, fogFactor);
gl_FragColor = vec4(color.rgb, color.a * uAlpha);
}
@@ -0,0 +1,68 @@
attribute vec3 vPosition;
attribute vec2 vTexCoord;
attribute vec3 vNormal;
attribute vec4 aBoneIndices0;
attribute vec2 aBoneIndices1;
attribute vec4 aBoneWeights0;
attribute vec2 aBoneWeights1;
varying vec2 texCoord;
varying float fogDistance;
varying vec3 fragViewPos;
varying vec3 fragNormal;
uniform mat4 ProjectionModelViewMatrix;
uniform mat4 ModelViewMatrix;
uniform mat4 uBoneMatrices[64];
uniform vec3 uPlayerEyePos;
void main()
{
vec4 skinnedPos = vec4(0.0, 0.0, 0.0, 0.0);
vec3 skinnedNormal = vec3(0.0, 0.0, 0.0);
vec4 originalPos = vec4(vPosition, 1.0);
float totalWeight = 0.0;
if (aBoneWeights0.x > 0.0) {
skinnedPos += uBoneMatrices[int(aBoneIndices0.x)] * originalPos * aBoneWeights0.x;
skinnedNormal += mat3(uBoneMatrices[int(aBoneIndices0.x)]) * vNormal * aBoneWeights0.x;
totalWeight += aBoneWeights0.x;
}
if (aBoneWeights0.y > 0.0) {
skinnedPos += uBoneMatrices[int(aBoneIndices0.y)] * originalPos * aBoneWeights0.y;
skinnedNormal += mat3(uBoneMatrices[int(aBoneIndices0.y)]) * vNormal * aBoneWeights0.y;
totalWeight += aBoneWeights0.y;
}
if (aBoneWeights0.z > 0.0) {
skinnedPos += uBoneMatrices[int(aBoneIndices0.z)] * originalPos * aBoneWeights0.z;
skinnedNormal += mat3(uBoneMatrices[int(aBoneIndices0.z)]) * vNormal * aBoneWeights0.z;
totalWeight += aBoneWeights0.z;
}
if (aBoneWeights0.w > 0.0) {
skinnedPos += uBoneMatrices[int(aBoneIndices0.w)] * originalPos * aBoneWeights0.w;
skinnedNormal += mat3(uBoneMatrices[int(aBoneIndices0.w)]) * vNormal * aBoneWeights0.w;
totalWeight += aBoneWeights0.w;
}
if (aBoneWeights1.x > 0.0) {
skinnedPos += uBoneMatrices[int(aBoneIndices1.x)] * originalPos * aBoneWeights1.x;
skinnedNormal += mat3(uBoneMatrices[int(aBoneIndices1.x)]) * vNormal * aBoneWeights1.x;
totalWeight += aBoneWeights1.x;
}
if (aBoneWeights1.y > 0.0) {
skinnedPos += uBoneMatrices[int(aBoneIndices1.y)] * originalPos * aBoneWeights1.y;
skinnedNormal += mat3(uBoneMatrices[int(aBoneIndices1.y)]) * vNormal * aBoneWeights1.y;
totalWeight += aBoneWeights1.y;
}
if (totalWeight < 0.001) {
skinnedPos = originalPos;
skinnedNormal = vNormal;
}
vec4 eyePos = ModelViewMatrix * skinnedPos;
fogDistance = length(eyePos.xyz - uPlayerEyePos);
gl_Position = ProjectionModelViewMatrix * skinnedPos;
texCoord = vTexCoord;
fragViewPos = eyePos.xyz;
fragNormal = mat3(ModelViewMatrix) * skinnedNormal;
}
@@ -0,0 +1,71 @@
attribute vec3 vPosition;
attribute vec2 vTexCoord;
attribute vec3 vNormal;
attribute vec4 aBoneIndices0;
attribute vec2 aBoneIndices1;
attribute vec4 aBoneWeights0;
attribute vec2 aBoneWeights1;
varying vec2 texCoord;
varying vec4 fragPosLightSpace;
varying vec3 fragNormal;
varying float fogDistance;
varying vec3 fragViewPos;
uniform mat4 ProjectionModelViewMatrix;
uniform mat4 ModelViewMatrix;
uniform mat4 uLightFromCamera;
uniform mat4 uBoneMatrices[64];
uniform vec3 uPlayerEyePos;
void main()
{
vec4 skinnedPos = vec4(0.0, 0.0, 0.0, 0.0);
vec3 skinnedNormal = vec3(0.0, 0.0, 0.0);
vec4 originalPos = vec4(vPosition, 1.0);
float totalWeight = 0.0;
if (aBoneWeights0.x > 0.0) {
skinnedPos += uBoneMatrices[int(aBoneIndices0.x)] * originalPos * aBoneWeights0.x;
skinnedNormal += mat3(uBoneMatrices[int(aBoneIndices0.x)]) * vNormal * aBoneWeights0.x;
totalWeight += aBoneWeights0.x;
}
if (aBoneWeights0.y > 0.0) {
skinnedPos += uBoneMatrices[int(aBoneIndices0.y)] * originalPos * aBoneWeights0.y;
skinnedNormal += mat3(uBoneMatrices[int(aBoneIndices0.y)]) * vNormal * aBoneWeights0.y;
totalWeight += aBoneWeights0.y;
}
if (aBoneWeights0.z > 0.0) {
skinnedPos += uBoneMatrices[int(aBoneIndices0.z)] * originalPos * aBoneWeights0.z;
skinnedNormal += mat3(uBoneMatrices[int(aBoneIndices0.z)]) * vNormal * aBoneWeights0.z;
totalWeight += aBoneWeights0.z;
}
if (aBoneWeights0.w > 0.0) {
skinnedPos += uBoneMatrices[int(aBoneIndices0.w)] * originalPos * aBoneWeights0.w;
skinnedNormal += mat3(uBoneMatrices[int(aBoneIndices0.w)]) * vNormal * aBoneWeights0.w;
totalWeight += aBoneWeights0.w;
}
if (aBoneWeights1.x > 0.0) {
skinnedPos += uBoneMatrices[int(aBoneIndices1.x)] * originalPos * aBoneWeights1.x;
skinnedNormal += mat3(uBoneMatrices[int(aBoneIndices1.x)]) * vNormal * aBoneWeights1.x;
totalWeight += aBoneWeights1.x;
}
if (aBoneWeights1.y > 0.0) {
skinnedPos += uBoneMatrices[int(aBoneIndices1.y)] * originalPos * aBoneWeights1.y;
skinnedNormal += mat3(uBoneMatrices[int(aBoneIndices1.y)]) * vNormal * aBoneWeights1.y;
totalWeight += aBoneWeights1.y;
}
if (totalWeight < 0.001) {
skinnedPos = originalPos;
skinnedNormal = vNormal;
}
vec4 eyePos = ModelViewMatrix * skinnedPos;
fogDistance = length(eyePos.xyz - uPlayerEyePos);
gl_Position = ProjectionModelViewMatrix * skinnedPos;
texCoord = vTexCoord;
fragViewPos = eyePos.xyz;
fragNormal = mat3(ModelViewMatrix) * skinnedNormal;
fragPosLightSpace = uLightFromCamera * eyePos;
}
+58
View File
@@ -0,0 +1,58 @@
precision mediump float;
uniform sampler2D Texture;
uniform float uAlpha;
uniform int uPointLightCount;
uniform vec3 uPointLightPos[4];
uniform vec3 uPointLightDir[4];
uniform vec3 uPointLightColor[4];
varying vec2 texCoord;
varying float fogDistance;
varying vec3 fragViewPos;
varying vec3 fragNormal;
// cos(45 deg) = half-angle for a 90-degree full-angle spotlight
const float SPOT_COS_OUTER = 0.7071;
const float SPOT_COS_INNER = 0.82; // slightly tighter inner cone for smooth edge
void main()
{
vec4 color = texture2D(Texture, texCoord);
if (color.a < 0.1)
discard;
float ambient = 0.37;
vec3 lighting = vec3(ambient);
bool hasNormal = dot(fragNormal, fragNormal) > 0.001;
vec3 N = hasNormal ? normalize(fragNormal) : vec3(0.0);
for (int i = 0; i < 4; i++)
{
if (i >= uPointLightCount) break;
vec3 lightVec = uPointLightPos[i] - fragViewPos;
float dist = length(lightVec);
vec3 lightDir = normalize(lightVec);
// Spotlight cone: angle between the cone axis and the ray from light to fragment
float cosTheta = dot(-lightDir, normalize(uPointLightDir[i]));
float spotAtten = smoothstep(SPOT_COS_OUTER, SPOT_COS_INNER, cosTheta);
if (spotAtten <= 0.0) continue;
float atten = 1.0 / (1.0 + 0.35 * dist + 0.15 * dist * dist);
float diff = hasNormal ? max(dot(N, lightDir), 0.0) : 1.0;
lighting += uPointLightColor[i] * diff * atten * spotAtten;
}
color.rgb *= lighting;
vec3 fogColor = vec3(0.01, 0.01, 0.05);
float fogFactor = clamp((fogDistance - 15.0) / 8.0, 0.0, 1.0);
color.rgb = mix(color.rgb, fogColor, fogFactor);
gl_FragColor = vec4(color.rgb, color.a * uAlpha);
}