57 lines
1.6 KiB
Plaintext
57 lines
1.6 KiB
Plaintext
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);
|
|
}
|