Opengl: 使用glsl 将纹理处理成圆角的几种思路

在GLSL中实现纹理圆角效果可以通过多种方法,这些方法各有其优缺点和适用场景。以下是几种常见的实现方法:

1. 使用距离函数

最常见的方法是计算像素到中心的距离,并使用该距离来决定像素是否显示。

#version 330 core

in vec2 TexCoord;
out vec4 FragColor;

uniform sampler2D texture1;
uniform vec2 resolution;
uniform float radius;

void main()
{
    vec2 center = vec2(0.5, 0.5); // 中心位置
    vec2 uv = TexCoord; // 当前纹理坐标

    float dist = length(uv - center); // 计算距离
    float alpha = smoothstep(radius, radius + 0.01, dist); // 创建圆角掩码

    vec4 color = texture(texture1, TexCoord);
    FragColor = vec4(color.rgb, color.a * (1.0 - alpha)); // 应用掩码
}

2. 使用圆形遮罩纹理

你可以创建一个圆形遮罩纹理,用于在片段着色器中结合原始纹理。这个方法有时更灵活,尤其是在处理多个不同的形状时。

#version 330 core

in vec2 TexCoord;
out vec4 FragColor;

uniform sampler2D texture1;
uniform sampler2D maskTexture; // 圆形遮罩纹理

void main()
{
    vec4 texColor = texture(texture1, TexCoord);
    float maskAlpha = texture(maskTexture, TexCoord).r; // 从遮罩纹理中取样
    FragColor = vec4(texColor.rgb, texColor.a * maskAlpha); // 应用遮罩
}

3. 利用discard语句

你可以在片段着色器中使用discard语句来完全丢弃不在圆角区域内的像素。

#version 330 core

in vec2 TexCoord;
out vec4 FragColor;

uniform sampler2D texture1;
uniform float radius;

void main()
{
    vec2 center = vec2(0.5, 0.5); // 中心位置
    vec2 uv = TexCoord; // 当前纹理坐标

    float dist = length(uv - center); // 计算距离
    if (dist > radius) {
        discard; // 丢弃超出圆角区域的像素
    }

    vec4 color = texture(texture1, TexCoord);
    FragColor = color; // 输出纹理颜色
}

4. 利用Shader中的数学函数

在一些情况下,你可能需要创建更复杂的圆角效果,结合其他数学函数来实现。例如,可以结合高斯模糊函数或其他形状的遮罩来创建柔和的边缘效果。

#version 330 core

in vec2 TexCoord;
out vec4 FragColor;

uniform sampler2D texture1;
uniform vec2 resolution;
uniform float radius;

void main()
{
    vec2 center = vec2(0.5, 0.5); // 中心位置
    vec2 uv = TexCoord; // 当前纹理坐标

    float dist = length(uv - center); // 计算距离
    float alpha = 1.0 - smoothstep(radius - 0.01, radius, dist); // 更柔和的圆角

    vec4 color = texture(texture1, TexCoord);
    FragColor = vec4(color.rgb, color.a * alpha); // 应用圆角
}

5. 使用Alpha测试

你可以先将纹理的透明度设置为圆形区域,然后在渲染管线的早期阶段进行Alpha测试来丢弃不需要的像素。

#version 330 core

in vec2 TexCoord;
out vec4 FragColor;

uniform sampler2D texture1;
uniform float radius;

void main()
{
    vec2 center = vec2(0.5, 0.5); // 中心位置
    vec2 uv = TexCoord; // 当前纹理坐标

    float dist = length(uv - center); // 计算距离
    float alpha = smoothstep(radius, radius + 0.01, dist); // 圆角掩码

    vec4 color = texture(texture1, TexCoord);
    if (color.a * (1.0 - alpha) < 0.1) {
        discard; // 根据透明度决定是否丢弃
    }

    FragColor = color; // 输出纹理颜色
}

总结

这些方法各有其特点和应用场景。选择合适的方法取决于具体的需求和性能考虑。例如,使用discard语句可能对性能有影响,但非常直观;而使用遮罩纹理或距离函数则可能更灵活,适用于不同的场景.

                                                           

posted @ 2024-08-09 17:30  连山In17  阅读(289)  评论(0)    收藏  举报