【问题标题】:GLSL Check texture alpha between 2 vectorsGLSL 检查 2 个向量之间的纹理 alpha
【发布时间】:2014-07-23 11:24:10
【问题描述】:

我正在努力学习如何制作着色器,不久前,我在这里发布了一个问题:GLSL Shader - Shadow between 2 textures on a plane

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

所以这里是代码:

顶点着色器:

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,我使用 uvVarying 来获取当前片段(如果我没记错的话),但要得到光的距离,我必须计算 posVarying 和 lightPos 之间的长度,而不是 uvVarying 和 lightPos 之间的长度(我做了一个测试,我离光越远,它变得越红,而使用 posVarying,它使我变成了一个圆圈我的播放器周围有渐变(lightPos),但是当我使用 uvVarying 时,圆圈只有一种颜色,当我将播放器靠近屏幕中心时,它或多或少是红色)。

谢谢和最好的问候,

最大

【问题讨论】:

    标签: opengl-es textures glsl shader shadow


    【解决方案1】:

    当您通过texture2D() 访问纹理时,您使用的是标准化坐标。 IE。从 (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 视频下):forum.thegamecreators.com/?m=forum_view&t=201508&b=41 也许我可以使用 agk_Ortho 或 agk_WorldOrtho,但我不太确定如何使用它们......会看看这个
    • 抱歉,invert() 仅适用于 es 3.0。如果你使用正交投影,你可以做这样的事情,假设你的纹理覆盖了整个屏幕并且不移动: uvShadow /= screenResolution;紫外线阴影 += 0.5; uvShadow *= 0.5;
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-29
    相关资源
    最近更新 更多