【问题标题】:GLSL: How to include alpha blending into a fragment shader with lightingGLSL:如何将 alpha 混合包含到带照明的片段着色器中
【发布时间】:2020-11-09 16:04:11
【问题描述】:

我设法使用以下片段着色器使用 OpenGL(OpenTK,因为我使用 C# 和 Winforms)创建了一个光线充足的场景:

#version 420 core

in vec3 FragPos;
in vec3 Normal;
in vec2 texCoord;

out vec4 FragColor;

uniform sampler2D texture0;
uniform sampler2D texture1;

struct Material {
    sampler2D diffuse;
    sampler2D specular;
    float     shininess;
};
struct Light {
    vec3 position;
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
};

uniform Material material;
uniform Light light;
uniform vec3 viewPos;

void main()
{
    // Ambient
    vec3 ambient = light.ambient * vec3(texture(material.diffuse, texCoord));

    // Diffuse 
    vec3 norm = normalize(Normal);
    vec3 lightDir = normalize(vec3(light.position - FragPos));
    float diff = max(dot(norm, lightDir), 0.0);
    vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, texCoord));

    // Specular
    vec3 viewDir = normalize(viewPos - FragPos);
    vec3 reflectDir = reflect(-lightDir, norm);
    float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
    vec3 specular = light.specular * spec * vec3(texture(material.specular, texCoord));

    vec3 result = ambient + diffuse + specular;    
    FragColor = vec4(result, 1.0);
}

不幸的是,这个解决方案似乎没有考虑纹理的 Alpha 通道。这导致了这样的场景:

计划是,左边的球体是云层。纹理包含一个 Alpha 通道,这应该会产生一个带有可见云的透明球体。不要混淆:当一切恢复正常时,云球将移回地球上方。

在实现环境光、漫反射光和镜面光之前,我使用了以下片段着色器:

#version 420 core

in vec2 texCoord;

out vec4 FragColor;

uniform sampler2D texture0;
uniform sampler2D texture1;

void main()
{
    vec4 outputColor = mix(texture(texture0, texCoord), texture(texture1, texCoord), 0.2);
    if(outputColor.a < 0.1)
        discard;

    FragColor = outputColor;
}

此着色器考虑了 Alpha 通道,它确实按预期工作。重要的是,云和地球是独立的球体对象。旧着色器中的 texture1 根本没有使用。所以唯一相关的纹理是纹理0。

所以“目标”应该是将 alpha 通道添加到新的着色器(带有照明的着色器)中。

抱歉,如果您觉得这个问题很愚蠢。我是 OpenGL 的新手,还在学习。 提前致谢!

【问题讨论】:

    标签: c# winforms opengl glsl opentk


    【解决方案1】:

    您必须mix 依赖于云层的 Alpha 通道的纹理。假设“texture1”是云层:

    vec4 groundColor = texture(texture0, texCoord);
    vec4 cloudColor  = texture(texture1, texCoord);
    vec4 outputColor = vec4(mix(grundColor.rgb, cloudColor.rgb, cloudColor.a), 1.0);
    
    FragColor = outputColor;
    

    【讨论】:

    • 您好,谢谢您的回答。我忘了在解释中提到一些东西(我现在将添加):云和地球是独立的球体对象。旧着色器中的 texture1 根本没有使用。所以唯一相关的纹理是纹理0。
    • @BanditBloodwyn 我很困惑,不知道你想要什么。您有 2 个通行证,一个用于地球,一个用于云?您是否对两个通道使用相同的着色器?在着色器程序中没有实现混合。混合是一个阶段,必须启用。阅读Blening
    • 为了简单起见:我很确定我的着色器(这里的第一个)不支持 alpha 混合,因为不考虑 alpha 通道。我看到旧着色器和新着色器之间的重要区别:旧着色器为 FragColor 提供 vec4 (RGBA),新着色器为 vec3 (RGB) + 1.0,作为第四个用于制作 vec4。所以问题是:如何重新包含第四个通道(alpha)而不是只使用 1.0?我希望现在可以理解了
    【解决方案2】:

    我自己找到了解决方案。这里是固定着色器:

    #version 420 core
    
    in vec3 FragPos;
    in vec3 Normal;
    in vec2 texCoord;
    
    out vec4 FragColor;
    
    struct Material {
        sampler2D diffuse;
        sampler2D specular;
        float     shininess;
    };
    struct Light {
        vec3 position;
        vec3 ambient;
        vec3 diffuse;
        vec3 specular;
    };
    
    uniform Material material;
    uniform Light light;
    uniform vec3 viewPos;
    
    void main()
    {
        // Ambient
        vec4 ambient = vec4(light.ambient, 1.0) * texture(material.diffuse, texCoord);
    
        // Diffuse 
        vec3 norm = normalize(Normal);
        vec3 lightDir = normalize(vec3(light.position - FragPos));
        float diff = max(dot(norm, lightDir), 0.0);
        vec4 diffuse = vec4(light.diffuse, 1.0) * diff * texture(material.diffuse, texCoord);
    
        // Specular
        vec3 viewDir = normalize(viewPos - FragPos);
        vec3 reflectDir = reflect(-lightDir, norm);
        float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
        vec4 specular = vec4(light.specular, 1.0) * spec * texture(material.specular, texCoord);
    
        vec4 result = ambient + diffuse + specular;   
    
        if(result.a < 0.1)
            discard;    
        
        FragColor = result;
    }
    

    如果您有更好的想法,我很乐意尝试:)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-03
      • 1970-01-01
      • 1970-01-01
      • 2017-04-12
      • 1970-01-01
      相关资源
      最近更新 更多