LibGDX 重叠二维阴影
LibGDX Overlapping 2D Shadows
我正在为一款 2D 俯视游戏制作阴影。现在,阴影只是在瓷砖上方的图层上绘制的颜色为 (0,0,0,0.1) 的精灵。
问题:当许多实体或树木聚集在一起时,阴影重叠,形成看起来不自然的暗区。
我试过将阴影绘制到帧缓冲区并使用简单的着色器来防止重叠,但这会导致其他问题,包括分层问题。
是否可以为阴影启用某种混合功能以防止 "stacking",或者使用着色器的更好方法?
在禁用混合的情况下将阴影绘制到 fbo。
绘制背景,例如草
从 fbo 绘制阴影纹理
绘制所有其他精灵
如果您不想处理排序问题,我认为您可以使用着色器来完成。但是每个对象都必须受或不受阴影影响。所以高大的树可以被标记为不接收阴影,而地面、草地和角色将被标记为接收阴影。
首先制作一个清晰的白色帧缓冲区。把你所有的影子都画成纯黑色。
然后制作一个阴影贴图着色器来绘制你世界中的一切。这取决于您不需要精灵颜色的所有四个通道,因为我们需要这些通道之一来将每个精灵标记为是否接收阴影。例如,如果您不使用 RGB 为精灵着色,我们可以使用 R 通道。或者,如果您不让它们淡入淡出,我们可以使用 A。我在这里假设后者:
顶点着色器:
attribute vec4 a_position;
attribute vec4 a_color;
attribute vec2 a_texCoord0;
varying vec2 v_texCoords;
varying vec2 v_texCoordsShadowmap;
varying vec4 v_color;
uniform mat4 u_projTrans;
void main()
{
v_texCoords = a_texCoord0;
v_color = a_color;
v_color.a = v_color.a * (255.0/254.0); //this is a correction due to color float precision (see SpriteBatch's default shader)
vec3 screenPosition = u_projTrans * a_position;
v_texCoordsShadowmap = (screenPosition.xy * 0.5) + 0.5;
gl_Position = screenPosition;
}
片段着色器:
#ifdef GL_ES
precision mediump float;
#endif
varying vec2 v_texCoords;
varying vec2 v_texCoordsShadowmap;
varying vec4 v_color;
uniform sampler2D u_texture;
uniform sampler2D u_textureShadowmap;
void main()
{
vec4 textureColor = texture2D(u_texture, v_texCoords);
float shadowColor = texture2D(u_textureShadowmap, v_texCoordsShadowmap).r;
shadowColor = mix(shadowColor, 1.0, v_color.a);
textureColor.rgb *= shadowColor * v_color.rgb;
gl_FragColor = textureColor;
}
这些完全未经测试,可能存在错误。确保将帧缓冲区的颜色纹理分配给 "u_textureShadowmap"。对于所有精灵,根据您希望它们投射在它们身上的阴影量来设置它们颜色的 alpha,通常始终为 0 或 0.1(基于您之前使用的亮度)。
我正在为一款 2D 俯视游戏制作阴影。现在,阴影只是在瓷砖上方的图层上绘制的颜色为 (0,0,0,0.1) 的精灵。
问题:当许多实体或树木聚集在一起时,阴影重叠,形成看起来不自然的暗区。
我试过将阴影绘制到帧缓冲区并使用简单的着色器来防止重叠,但这会导致其他问题,包括分层问题。 是否可以为阴影启用某种混合功能以防止 "stacking",或者使用着色器的更好方法?
在禁用混合的情况下将阴影绘制到 fbo。
绘制背景,例如草 从 fbo 绘制阴影纹理 绘制所有其他精灵
如果您不想处理排序问题,我认为您可以使用着色器来完成。但是每个对象都必须受或不受阴影影响。所以高大的树可以被标记为不接收阴影,而地面、草地和角色将被标记为接收阴影。
首先制作一个清晰的白色帧缓冲区。把你所有的影子都画成纯黑色。
然后制作一个阴影贴图着色器来绘制你世界中的一切。这取决于您不需要精灵颜色的所有四个通道,因为我们需要这些通道之一来将每个精灵标记为是否接收阴影。例如,如果您不使用 RGB 为精灵着色,我们可以使用 R 通道。或者,如果您不让它们淡入淡出,我们可以使用 A。我在这里假设后者:
顶点着色器:
attribute vec4 a_position;
attribute vec4 a_color;
attribute vec2 a_texCoord0;
varying vec2 v_texCoords;
varying vec2 v_texCoordsShadowmap;
varying vec4 v_color;
uniform mat4 u_projTrans;
void main()
{
v_texCoords = a_texCoord0;
v_color = a_color;
v_color.a = v_color.a * (255.0/254.0); //this is a correction due to color float precision (see SpriteBatch's default shader)
vec3 screenPosition = u_projTrans * a_position;
v_texCoordsShadowmap = (screenPosition.xy * 0.5) + 0.5;
gl_Position = screenPosition;
}
片段着色器:
#ifdef GL_ES
precision mediump float;
#endif
varying vec2 v_texCoords;
varying vec2 v_texCoordsShadowmap;
varying vec4 v_color;
uniform sampler2D u_texture;
uniform sampler2D u_textureShadowmap;
void main()
{
vec4 textureColor = texture2D(u_texture, v_texCoords);
float shadowColor = texture2D(u_textureShadowmap, v_texCoordsShadowmap).r;
shadowColor = mix(shadowColor, 1.0, v_color.a);
textureColor.rgb *= shadowColor * v_color.rgb;
gl_FragColor = textureColor;
}
这些完全未经测试,可能存在错误。确保将帧缓冲区的颜色纹理分配给 "u_textureShadowmap"。对于所有精灵,根据您希望它们投射在它们身上的阴影量来设置它们颜色的 alpha,通常始终为 0 或 0.1(基于您之前使用的亮度)。