Я пытаюсь создать 2D-рендерер в OpenGL со светом и тенями, и свет работает довольно хорошо. Но тени не являются конусами, они проецируют объект таким, какой он есть, на объект с более низким z-положением. Вот изображение того, как это выглядит: тень. Я не могу понять, как сделать теневые конусы, отходящие от источника света. Это мой фрагментный шейдер:
#version 330 core
out vec4 FragColor;
in vec2 TexCoord;
in vec3 FragPos;
uniform sampler2D texture1;
uniform vec4 ourColor;
struct Light {
vec3 position;
float innerRadius;
float outerRadius;
vec4 color;
float intensity;
bool castsShadows;
};
#define MAX_LIGHTS 10
uniform int numLights;
uniform Light lights[MAX_LIGHTS];
// Global light
uniform vec4 globalLightColor;
// Shadow casting structures
struct ShadowCaster {
vec3 position;
vec2 size;
float angle;
bool isFlipped;
};
#define MAX_SHADOW_CASTERS 10
uniform int numShadowCasters;
uniform ShadowCaster shadowCasters[MAX_SHADOW_CASTERS];
uniform sampler2D shadowCasterTextures[MAX_SHADOW_CASTERS];
float pixelInShadow(vec3 fragPos, vec3 lightPos, vec3 objPos, vec2 objSize, float objAngle, sampler2D shadowTex, bool isFlipped) {
vec3 lightToObj = objPos - lightPos;
vec3 fragToObj = objPos - fragPos;
vec3 projFragPos = vec3(fragPos.xy, objPos.z);
vec2 offset = projFragPos.xy - objPos.xy;
float cosAngle = cos(objAngle);
float sinAngle = sin(objAngle);
vec2 rotatedOffset = vec2(
cosAngle * offset.x - sinAngle * offset.y,
sinAngle * offset.x + cosAngle * offset.y
);
vec2 rotatedPos = objPos.xy + rotatedOffset;
bool inBounds = rotatedPos.x > objPos.x - objSize.x * 0.5 &&
rotatedPos.x < objPos.x + objSize.x * 0.5 &&
rotatedPos.y > objPos.y - objSize.y * 0.5 &&
rotatedPos.y < objPos.y + objSize.y * 0.5;
if (inBounds) {
// Calculate texture coordinates
vec2 texCoord = (rotatedPos - (objPos.xy - objSize * 0.5)) / objSize;
if (isFlipped) {
texCoord.x = 1.0 - texCoord.x; // Flip the texture coordinates in the x-axis
}
float alpha = texture(shadowTex, texCoord).a;
return 1.0 - alpha;
} else {
return 1.0;
}
}
void main()
{
vec4 texColor = texture(texture1, TexCoord);
vec4 finalColor = texColor * ourColor;
vec3 totalLight = vec3(0.0);
for (int i = 0; i < numLights; i++)
{
Light light = lights;
float distance = length(light.position - FragPos);
if (distance < light.outerRadius)
{
float intensity = light.intensity;
if (distance > light.innerRadius)
{
intensity *= 1.0 - (distance - light.innerRadius) / (light.outerRadius - light.innerRadius);
}
// Calculate shadow
float shadowFactor = 1.0;
if (light.castsShadows) {
for (int j = 0; j < numShadowCasters; j++) {
ShadowCaster caster = shadowCasters[j];
shadowFactor *= pixelInShadow(FragPos, light.position, caster.position, caster.size, caster.angle, shadowCasterTextures[j], caster.isFlipped);
}
}
totalLight += light.color.rgb * intensity * shadowFactor;
}
}
// Apply global light color
totalLight += globalLightColor.rgb;
// Combine finalColor with total light contribution
finalColor.rgb *= totalLight;
// Clamp final color
finalColor.rgb = clamp(finalColor.rgb, 0.0, 1.0);
// Output the final color
FragColor = finalColor;
}
Подробнее здесь: https://stackoverflow.com/questions/786 ... ent-shader
Как создать 2D-теневые конусы во фрагментном шейдере GLSL? ⇐ C++
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение