Opengl es GLSL检查两个向量之间的纹理alpha

Opengl es GLSL检查两个向量之间的纹理alpha,opengl-es,textures,glsl,shader,shadow,Opengl Es,Textures,Glsl,Shader,Shadow,我正在尝试学习如何制作着色器,不久前,我在这里发布了一个问题: 所以,答案给了我正确的方向,但是我在检查当前碎片和灯光位置之间是否存在不透明的碎片时遇到了一些麻烦 下面是代码: 顶点着色器: attribute vec3 position; attribute vec3 normal; attribute vec2 uv; varying vec2 uvVarying; varying vec3 normalVarying; varying vec3 posVarying; uniform

我正在尝试学习如何制作着色器,不久前,我在这里发布了一个问题:

所以,答案给了我正确的方向,但是我在检查当前碎片和灯光位置之间是否存在不透明的碎片时遇到了一些麻烦

下面是代码:

顶点着色器:

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;
}
和片段着色器:

#ifdef GL_ES
   #ifdef GL_FRAGMENT_PRECISION_HIGH   
      precision highp float;
   #else
      precision mediump float;
   #endif
#endif

uniform sampler2D texture0;
uniform sampler2D texture1;

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

uniform vec4 uvBounds0;
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 lightColor = agk_PLightColor.rgb * intensity * atten;
    vec3 shadowColor = agk_PLightColor.rgb * 0;

    bool inTheShadow = false;

    if (intensity * atten > 0.05) {
        float distanceToLight = length(posVarying.xy - lightPos.xy);

        for (float i = distanceToLight; i > 0.0; i -= 0.1) {

            vec2 uvShadow = ???

            if (texture2D(texture0, uvShadow).a > 0) {
                inTheShadow = true;

                break;
            }
        }
    }

    if (texture2D(texture0, uvVarying).a == 0) {
        if (inTheShadow == true) {
            gl_FragColor = texture2D(texture1, uvVarying) * vec4(shadowColor, 1) * agk_ObjColor;
        }
        else {
            gl_FragColor = texture2D(texture1, uvVarying) * vec4(lightColor, 1) * agk_ObjColor;
        }
    }
    else {
        gl_FragColor = texture2D(texture0, uvVarying) * agk_ObjColor;
    }
}
所以,这是我遇到一些麻烦的部分:

bool inTheShadow = false;

    if (intensity * atten > 0.05) {
        float distanceToLight = length(posVarying.xy - lightPos.xy);

        for (float i = distanceToLight; i > 0.0; i -= 0.1) {

            vec2 uvShadow = ???

            if (texture2D(texture0, uvShadow).a > 0) {
                inTheShadow = true;

                break;
            }
        }
    }
我首先检查我是否在强度*atten>0.05的光线半径内

然后我得到当前碎片到灯光位置的距离

然后,我做一个for循环,检查当前片段和灯光位置之间的每个片段。我尝试了一些计算来获得当前片段,但没有成功

那么,你知道如何计算循环中的uvShadow吗

我希望我也使用了好的变量,因为在我的代码的最后一部分,我使用gl_FragColor,我使用uvvaring来获得当前片段(如果我没有弄错的话),但是为了获得光距离,我必须计算posvaring和lightPos之间的长度,而不是uvvaring和lightPos之间的长度(我做了一个测试,我离灯光越远,它就变得越红,通过位置变化,它在我的播放器(lightPos)周围形成了一个带有渐变的圆圈,但当我使用UVVariable时,圆圈只有一种颜色,当我接近我的播放器到屏幕中心时,它或多或少是红色的)

谢谢并致以最良好的祝愿


Max

当您通过
texture2D()
访问纹理时,您使用归一化坐标。即从(0.0,0.0)到(1.0,1.0)的数字。因此,您需要将世界位置转换为该归一化空间。例如:

vec2 uvShadow = posVarying.xy + ((distanceToLight / 0.1) * i * (posVarying.xy - lightPos.xy));
// Take uvShadow from world space to view space, this is -1.0 to 1.0
uvShadow *= mat2(inverse(agk_View)); // This could be optimized if you are using orthographic projection
// Now take it to texture space
uvShadow += 0.5;
uvShadow *= 0.5;

谢谢,现在我更了解了它的工作原理:)遗憾的是,在OpenGL ES 2.0中似乎没有反函数,对于正交投影,我看了一下,发现了一个可以使用的常数列表:(在第一个youtube视频下):也许我可以使用agk_Ortho或agk_WorldOrtho,但我不太确定如何使用它们。。。我来看看这个oops道歉倒置()仅是es 3.0。如果您使用的是正交投影,您可以这样做,假设您的纹理覆盖整个屏幕并且不移动:uvShadow/=屏幕分辨率;uvShadow+=0.5;uvShadow*=0.5;