You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用顶点和片段着色器实现2D纹理凹凸效果并移除指定像素

实现方案

核心逻辑基于纹理UV坐标的范围判断,配合伪随机函数实现不规则边缘裁剪/凹凸效果,无需修改现有顶点着色器,仅调整片段着色器即可,天然支持四个侧边独立配置效果,适配OpenGL ES 2.0标准。

1. 新增伪随机函数

OpenGL ES 2.0无内置随机能力,先在片段着色器中新增轻量伪随机函数,用于生成边缘不规则阈值:

float random(vec2 st) {
    return fract(sin(dot(st.xy + u_randomSeed, vec2(12.9898,78.233))) * 43758.5453123);
}

2. 完整修改后的片段着色器代码

#ifdef GL_ES
#define PRECISION mediump
precision PRECISION float;
precision PRECISION int;
#else
#define PRECISION
#endif

varying vec4 v_color;
varying vec2 v_texCoords;

uniform sampler2D u_texture;
uniform sampler2D u_other;
// 新增配置参数:四个侧边的裁剪范围(比例值,0为不处理)
uniform float u_edgeCutTop;
uniform float u_edgeCutBottom;
uniform float u_edgeCutLeft;
uniform float u_edgeCutRight;
// 随机种子,修改即可生成不同的边缘样式
uniform float u_randomSeed;

float random(vec2 st) {
    return fract(sin(dot(st.xy + u_randomSeed, vec2(12.9898,78.233))) * 43758.5453123);
}

void main() {
    vec4 color = texture2D(u_texture, v_texCoords);
    vec4 other_colors = texture2D(u_other, v_texCoords);
    float alpha = 1.0;

    // 顶部裁剪逻辑
    if(u_edgeCutTop > 0.0 && v_texCoords.y > (1.0 - u_edgeCutTop)) {
        float cutProgress = (v_texCoords.y - (1.0 - u_edgeCutTop)) / u_edgeCutTop;
        float cutThreshold = random(v_texCoords);
        if(cutProgress > cutThreshold) alpha = 0.0;
    }
    // 底部裁剪逻辑
    else if(u_edgeCutBottom > 0.0 && v_texCoords.y < u_edgeCutBottom) {
        float cutProgress = (u_edgeCutBottom - v_texCoords.y) / u_edgeCutBottom;
        float cutThreshold = random(v_texCoords);
        if(cutProgress > cutThreshold) alpha = 0.0;
    }
    // 左侧裁剪逻辑
    else if(u_edgeCutLeft > 0.0 && v_texCoords.x < u_edgeCutLeft) {
        float cutProgress = (u_edgeCutLeft - v_texCoords.x) / u_edgeCutLeft;
        float cutThreshold = random(v_texCoords);
        if(cutProgress > cutThreshold) alpha = 0.0;
    }
    // 右侧裁剪逻辑
    else if(u_edgeCutRight > 0.0 && v_texCoords.x > (1.0 - u_edgeCutRight)) {
        float cutProgress = (v_texCoords.x - (1.0 - u_edgeCutRight)) / u_edgeCutRight;
        float cutThreshold = random(v_texCoords);
        if(cutProgress > cutThreshold) alpha = 0.0;
    }

    other_colors.a *= alpha;
    gl_FragColor = other_colors * v_color;
}

如果不需要alpha混合,也可以把alpha = 0.0的逻辑替换为discard,直接丢弃对应片段,性能表现相近。

3. libGDX侧参数传入

在渲染前给着色器传入对应参数即可控制边缘效果:

// 着色器初始化后绑定
shaderProgram.bind();
// 示例:顶部裁剪10%区域,左侧裁剪5%区域,其余边不处理
shaderProgram.setUniformf("u_edgeCutTop", 0.1f);
shaderProgram.setUniformf("u_edgeCutBottom", 0f);
shaderProgram.setUniformf("u_edgeCutLeft", 0.05f);
shaderProgram.setUniformf("u_edgeCutRight", 0f);
// 随机种子,修改数值即可生成完全不同的边缘凹凸样式
shaderProgram.setUniformf("u_randomSeed", 234.567f);

记得开启alpha混合:

Gdx.gl.glEnable(GL20.GL_BLEND);
Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);

4. 自定义边缘规则扩展

如果需要完全自定义边缘形状而非随机效果,可以新增uniform sampler2D u_edgeMask参数,用提前制作的遮罩纹理灰度值替代随机函数的返回值作为裁剪阈值,即可实现任意自定义的边缘凹凸/粗糙效果。


内容的提问来源于stack exchange,提问作者mantasarm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.16 23:36:04