首页 > 解决方案 > 如何在 GLSL 中平滑淡化 2 个没有 alpha 的纹理?

问题描述

我正在做一个着色器以在使用 ThreeJS 生成的地形块上应用动态纹理。tilemap 用于定义每个纹理应该发生的位置。

例如使用的瓷砖:

图像

这是实际的渲染:

着色器的实际渲染

现在我需要将它们混合在一起以获得每个纹理之间的平滑过渡。这是我想要实现的渲染:

预期结果

知道如何在没有 alpha 通道的情况下实现这一点吗?

我的顶点着色器:

uniform sampler2D heightCH1;
uniform sampler2D heightCH2;
uniform sampler2D tile;
uniform float bumpScale;

varying float vAmount;
varying float vColor;
varying vec2 vUV;

void main() 
{
    vUV = uv;
    vec4 bumpData = texture2D(heightCH2, uv);
    vec4 tileData = texture2D(tile, uv);

    vAmount = bumpData.r;
    vColor = tileData.r;

    vec3 newPosition = position + normal * bumpScale * vAmount;

    gl_Position = projectionMatrix * modelViewMatrix * vec4(newPosition, 1.0);
}

还有我的片段着色器:

uniform sampler2D tile;
uniform sampler2D heightCH1;
uniform sampler2D texture1;
uniform sampler2D texture2;
uniform sampler2D texture3;
uniform sampler2D texture4;
uniform sampler2D texture5;
uniform sampler2D texture6;
uniform sampler2D texture7;
uniform sampler2D texture8;
uniform sampler2D texture9;
uniform sampler2D texture10;
uniform sampler2D texture11;
uniform sampler2D texture12;
uniform sampler2D texture13;
uniform sampler2D texture14;
uniform sampler2D texture15;
uniform float mapping[15];

varying vec2 vUV;
out vec4 FragColor;

int getNearestColorIndex(float tileColor)
{
    int nearestIndex = 0;
    float diff = abs(tileColor - mapping[nearestIndex]);
    for (int i = 1; i < mapping.length(); i++)
    {
        float tempDiff = abs(tileColor - mapping[i]);
        if (tempDiff <= diff)
        {
            diff = tempDiff;
            nearestIndex = i;
        }
    }
    return nearestIndex;
}

vec4 getTexelForColorIndex(int index)
{
    vec4 t0;

    if (index == 0) t0 = texture2D(texture1, vUV * 40.0);
    else if (index == 1) t0 = texture2D(texture2, vUV * 40.0);
    else if (index == 2) t0 = texture2D(texture3, vUV * 40.0);
    else if (index == 3) t0 = texture2D(texture4, vUV * 40.0);
    else if (index == 4) t0 = texture2D(texture5, vUV * 40.0);
    else if (index == 5) t0 = texture2D(texture6, vUV * 40.0);
    else if (index == 6) t0 = texture2D(texture7, vUV * 40.0);
    else if (index == 7) t0 = texture2D(texture8, vUV * 40.0);
    else if (index == 8) t0 = texture2D(texture9, vUV * 40.0);
    else if (index == 9) t0 = texture2D(texture10, vUV * 40.0);
    else if (index == 10) t0 = texture2D(texture11, vUV * 40.0);
    else if (index == 11) t0 = texture2D(texture12, vUV * 40.0);
    else if (index == 12) t0 = texture2D(texture13, vUV * 40.0);
    else if (index == 13) t0 = texture2D(texture14, vUV * 40.0);
    else if (index == 14) t0 = texture2D(texture15, vUV * 40.0);

    return t0;
}

void main() 
{
    vec4 tileColors = texture2D(tile, vUV);
    int nearestIndex = getNearestColorIndex(tileColors.r);
    vec4 colorToApply = getTexelForColorIndex(nearestIndex);
    
    FragColor = vec4(0.0, 0.0, 0.0, 1.0) + colorToApply;
}

预先感谢您的帮助

标签: three.jsmappingglslshadertextures

解决方案


推荐阅读