HLSL中Clip函数的使用
在 HLSL(High - Level Shading Language)中,clip()函数用于在片元着色器(Pixel Shader)中丢弃特定片元,实现裁剪效果,常用于透明物体剔除、遮罩渲染等场景。
核心作用
- 丢弃片元:若输入参数 小于 0,则丢弃当前片元(不进行渲染)
- 语法格式:
clip(float4/int4 value),通常用标量(如单通道的值)来判断,例如:clip(v.color.a - 0.5); // 透明度小于0.5的片元被丢弃
等价于:
if (v.color.a < 0.5) discard;
注1:与discard的区别:clip()是封装好的条件判断,更简洁;discard需手动编写分支逻辑
注2:OpenGL中,没有Clip函数,只有discard关键字
案例 1:基于透明度(Alpha 通道)的裁剪
渲染半透明物体时,剔除透明度低于阈值的像素(如玻璃、布料的镂空效果)
float4 PixelShader(V2F input) : SV_TARGET { // 采样纹理并获取颜色(包含Alpha通道) float4 texColor = tex2D(_MainTex, input.uv); // 裁剪条件:Alpha值小于0.5的像素被丢弃 clip(texColor.a - 0.5); // 返回颜色(仅保留半透明以上的像素) return texColor; }
注1:原图中 Alpha < 0.5 的区域(如灰色部分)被完全剔除,仅显示半透明及以上区域
注2:常用于实现带透明通道的纹理渲染(如树叶、栅栏)
案例 2:使用遮罩纹理(Mask Texture)裁剪形状
通过黑白遮罩图控制显示区域(如 UI 圆形头像、镂空图案)
步骤:
① 在材质中导入一张遮罩图(白色区域保留,黑色区域裁剪)
② 片元着色器中采样遮罩图并判断阈值。
sampler2D _MaskTex; // 遮罩纹理(黑白图) float _MaskThreshold; // 阈值(默认0.5,可在材质面板调整) float4 PixelShader(V2F input) : SV_TARGET { // 采样遮罩图的单通道值(通常用R通道) float mask = tex2D(_MaskTex, input.uv).r; // 裁剪条件:遮罩值小于阈值的区域被丢弃 clip(mask - _MaskThreshold); // 返回颜色(仅显示遮罩允许的区域) return _MainColor; // 主颜色可自定义 }
注1:若遮罩图为圆形黑白图,最终渲染结果会呈现圆形区域,其余部分被裁剪
注2:适用于 UI 界面异形显示、角色装备镂空花纹等场景
案例 3:几何裁剪(自定义形状裁剪)
根据顶点坐标偏移量,在片元阶段动态裁剪出不规则形状(如雷达扫描效果、动态遮罩)
float _CutoffX; // X轴裁剪位置(可通过动画动态修改) float _CutoffY; // Y轴裁剪位置(可通过动画动态修改) float4 PixelShader(V2F input) : SV_TARGET { // 获取片元在屏幕空间的坐标([-1,1]范围) float2 screenUV = input.screenPos.xy / input.screenPos.w * 2 - 1; // 裁剪条件:片元位于(_CutoffX, _CutoffY)左下方时保留 clip(screenUV.x - _CutoffX); // X轴右侧超出裁剪位置的像素被丢弃 clip(screenUV.y - _CutoffY); // Y轴上侧超出裁剪位置的像素被丢弃 // 返回颜色(仅显示裁剪区域内的像素) return float4(1, 0.5, 0, 1); // 橙色 }
注1:通过动态修改
_CutoffX 和 _CutoffY,可实现矩形区域的实时裁剪(如地图迷雾逐渐揭开的效果)注2:结合正弦函数等数学运算,可实现波浪形、圆形扩张等动态裁剪效果
案例 4:多条件组合裁剪(复杂遮罩)
同时使用透明度和遮罩纹理进行双重裁剪(如带透明效果的镂空花纹)
float4 PixelShader(V2F input) : SV_TARGET { // 采样主纹理(含Alpha通道) float4 mainColor = tex2D(_MainTex, input.uv); // 采样遮罩纹理(单通道) float mask = tex2D(_MaskTex, input.uv).r; // 组合裁剪条件:Alpha<0.3 **且** 遮罩值<0.5的像素被丢弃 clip(mainColor.a - 0.3); clip(mask - 0.5); // 返回颜色(仅保留同时满足条件的像素) return mainColor * mask; // 颜色与遮罩相乘,增强对比 }
注:仅同时满足透明度和遮罩值的区域会被渲染,适用于多层叠加的复杂遮罩场景(如雕花玻璃)
注意事项
- 性能优化:避免在同一个片元着色器中使用过多
clip()语句,可合并条件(如clip(a && b)改为clip(a + b - 2)) - 精度问题:建议使用浮点类型(如
float)作为裁剪条件,避免整数运算导致边缘锯齿 - 调试技巧:可暂时将
clip()替换为return float4(1,0,0,1)(红色),直观查看裁剪区域是否符合预期 - 触发
clip()会导致片元着色器提前终止,合理使用可优化渲染效率 - 避免在循环或分支中频繁调用,可能增加 GPU 开销
浙公网安备 33010602011771号