GLSL Shader-平面上2个纹理之间的阴影 [英] GLSL Shader - Shadow between 2 textures on a plane

查看:183
本文介绍了GLSL Shader-平面上2个纹理之间的阴影的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用AGK(应用游戏套件)编写游戏,我想用着色器制作一些阴影. (AGK目前仅支持GLSL 1.20)

I'm writting a game with AGK (App Game Kit) and I wanted to make some shadows with shaders. (AGK only support GLSL 1.20 at the moment)

在我的游戏中,我有一个平面对象,其中有2个纹理.第一个纹理是背景纹理,第二个纹理是前景纹理,具有透明的路径,在该路径中我们可以看到背景纹理(它们就像墙壁一样),并且我有一个指示器灯.

On my game, I have a plane object, where I have 2 textures. The first texture is the background texture, and the second, is the foreground texture, with a transparent path where we see the background texture (they are like the walls) and I have a pointer light.

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

Here is an example (left is what I have, right is what I want) :

这是代码:

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;
    }
}

因此,我先放置第一个纹理,然后计算光照,然后检查第二个纹理,如果片段是透明的,则放置背景纹理和灯光,如果不透明,则放置第二个纹理.

So, i put the first texture, calculate the light, then I check the secondtexture, if the fragment is transparent, I put the background texture and the light, if it's not transparent, i just put the second texture.

那么,代码做了图像的左例,我想知道,是否有可能计算光,如果它穿过第二个纹理的非透明片段,它就停止了吗?因此,它确实类似于该图像的正确示例.

So, the code does the left example of the image, and I wanted to know, if it's possible to calculate the light so it stop if it goes through a non-transparent fragment of the second texture ? So it does like the right example of the image.

我进行了很多搜索,只发现了带有带有3D对象的着色器的阴影示例,如何创建阴影贴图等...但是您可以在同一对象的2个纹理之间计算出这一点吗?

I searched a lot and I only found examples of shadows with shaders with 3D objects, how to create a shadow map etc... but can you calculate this between 2 textures on the same object ?

推荐答案

我会寻求以下想法:对于您的照明范围内的每个像素,您都希望对光源进行跟踪并测试是否存在路径上没有黑色像素.看起来或多或少是这样的:

I would go for the following idea: for each pixel in the range of your light yo will want to do a trace to the light origin and test if there is no black pixel on the path. It will look more or less like that:

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,并检查墙的纹理在整个过程中是否为空.

It should do the trick. You only need to calculate YOUR_NEW_UV in the line marked with "xxx". I hope that you understand this idea. You basically need to test visible UVs between the current pixel and the light origin and check if the wall texture is enpty along the whole way.

这篇关于GLSL Shader-平面上2个纹理之间的阴影的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆