【问题标题】:GLSL Shader - Shadow between 2 textures on a planeGLSL Shader - 平面上 2 个纹理之间的阴影
【发布时间】:2014-06-19 17:55:18
【问题描述】:

我正在使用 AGK(App Game Kit)编写游戏,我想用着色器制作一些阴影。 (AGK 目前只支持 GLSL 1.20)

在我的游戏中,我有一个平面对象,其中有 2 个纹理。第一个纹理是背景纹理,第二个是前景纹理,有一条透明的路径,我们可以在其中看到背景纹理(它们就像墙壁),我有一个指针灯。

这是一个例子(左边是我拥有的,右边是我想要的):

这里是代码:

attribute vec3 position;
attribute vec3 normal;
attribute vec2 uv;

varying vec2 uvVarying;
varying vec3 normalVarying;
varying vec3 posVarying;

uniform vec4 uvBounds0;

uniform mat4 agk_World;
uniform mat4 agk_ViewProj;
uniform mat3 agk_WorldNormal;

void main()
{
    vec4 pos = agk_World * vec4(position,1);
    gl_Position = agk_ViewProj * pos;
    vec3 norm = agk_WorldNormal * normal;
    posVarying = pos.xyz;
    normalVarying = norm;
    uvVarying = uv * uvBounds0.xy + uvBounds0.zw;
}

还有:

uniform sampler2D texture0;
uniform sampler2D texture1;

varying vec2 uvVarying;
varying vec3 normalVarying;
varying vec3 posVarying;

uniform vec2 playerPos;
uniform vec2 agk_resolution;
uniform vec4 agk_PLightPos;
uniform vec4 agk_PLightColor;
uniform vec4 agk_ObjColor;

void main (void)
{
    vec4 lightPos = agk_PLightPos;
    lightPos.x = playerPos.x;
    lightPos.y = playerPos.y;


    vec3 dir = vec3(lightPos.x - posVarying.x, lightPos.y + posVarying.y, lightPos.z - posVarying.z);
    vec3 norm = normalize(normalVarying);
    float atten = dot(dir,dir);
    atten = clamp(lightPos.w/atten,0.0,1.0);
    float intensity = dot(normalize(dir),norm);
    intensity = clamp(intensity,0.0,1.0);
    vec3 color = agk_PLightColor.rgb * intensity * atten;

    if (texture2D(texture0, uvVarying).a == 0) {
        gl_FragColor = texture2D(texture1, uvVarying) * vec4(color,1) * agk_ObjColor;
    }
    else {
        gl_FragColor = texture2D(texture0, uvVarying) * agk_ObjColor;
    }
}

所以,我放第一个纹理,计算光照,然后检查第二个纹理,如果片段是透明的,我放背景纹理和光照,如果不透明,我只放第二个纹理。

所以,代码执行了图像的左侧示例,我想知道,是否可以计算光线,使其在穿过第二个纹理的不透明片段时停止?所以它确实喜欢图像的正确示例。

我搜索了很多,我只找到了带有 3D 对象的着色器的阴影示例,如何创建阴影贴图等...但是你能在同一个对象的 2 个纹理之间计算吗?

【问题讨论】:

    标签: opengl textures glsl shadow plane


    【解决方案1】:

    我会采用以下想法:对于光线范围内的每个像素,您都需要跟踪光源的原点并测试路径上是否没有黑色像素。它看起来或多或少是这样的:

    bool inTheShadow = false;
    //Check if you're in the light range
    if (intensity>0){
      vec2 delta = dir.xy / numSamples; //You can either use constant number of samples, or base it on the distance to the light source
      vec2 currentPointer = vec2(posVarying.x,posVarying.y);
      for (int i=0; i<numSamples ; i++){
        xxx //Calculate uv for currentPointer
        if(texture2D(texture0, YOUR_NEW_UV).a > 0){
          inTheShadow = true;
          break;
        }
        currentPointer += delta;
      }
    }
    

    它应该可以解决问题。您只需要在标有“xxx”的行中计算 YOUR_NEW_UV 即可。我希望你能理解这个想法。您基本上需要测试当前像素和光源之间的可见 UV,并检查整个过程中墙壁纹理是否为空。

    【讨论】:

      猜你喜欢
      • 2017-01-13
      • 2016-05-05
      • 1970-01-01
      • 2015-03-31
      • 1970-01-01
      • 1970-01-01
      • 2018-09-10
      • 2014-08-10
      • 1970-01-01
      相关资源
      最近更新 更多