如何使用顶点和片段着色器实现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
相关产品推荐
相关产品推荐

