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

Shadertoy圆角矩形着色器移植到Godot 4.0后无效果问题求助

问题:Godot 4.0中转换Shadertoy圆角矩形着色器无效果

我在Shadertoy的评论里找到一个生成圆角矩形的着色器:

float udRoundBox( vec2 p, vec2 b, float r )
{
  return length(max(abs(p)-b+r,0.0))-r;
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    float f = udRoundBox( fragCoord-iResolution.xy/2.0, iResolution.xy/2.0, 64.0);
    f = (f>0.0) ? 1.0 : 0.0;
    fragColor = vec4(f,1.0,f,1.0);
}

我尝试转换成Godot 4.0的CanvasItem着色器:

shader_type canvas_item;

float udRoundBox( vec2 p, vec2 b, float r )
{
    return length(max(abs(p)-b+r,0.0))-r;
}

void fragment()
{
    // Vague idea of how to translate these:
    vec2  iResolution = SCREEN_PIXEL_SIZE;
    vec2  fragCoord = FRAGCOORD.xy;
    vec4  fragColor = COLOR;
    
    vec2  p = fragCoord-iResolution.xy/2.0;
    vec2  b = iResolution.xy/2.0;
    float r = 64.0;
    
    float f = udRoundBox(p, b, r);
    f = (f>0.0) ? 1.0 : 0.0;
    fragColor = vec4(f,1.0,f,1.0);
}

将这个着色器材质加到带GradientTexture1D的TextureRect后,纹理完全没变化,调整参数r也没用,问题出在哪?


问题分析与修复

你的着色器没生效的核心问题是坐标系统理解错误,以及对Godot CanvasItem着色器的变量使用不当,具体问题和修复方法如下:

1. 错误的分辨率/坐标变量

  • Shadertoy的iResolution是画布的像素尺寸,但你用的SCREEN_PIXEL_SIZE是单个屏幕像素的大小(比如1920x1080屏幕下是vec2(1/1920, 1/1080)),二者完全不是同一概念。
  • Godot的FRAGCOORD是当前片段在纹理/控件上的绝对像素坐标,直接使用会导致圆角矩形尺寸和屏幕绑定,而非和TextureRect的尺寸绑定。

正确做法是使用UV坐标(范围0到1)做相对定位,或用TEXTURE_SIZE获取当前纹理的像素尺寸。

2. 未结合原有纹理

你直接覆盖了fragColor,完全忽略了TextureRect上的GradientTexture1D。如果要保留原有纹理,需要将圆角矩形作为遮罩与原纹理混合。

修复后的着色器代码

shader_type canvas_item;

float udRoundBox(vec2 p, vec2 b, float r) {
    return length(max(abs(p) - b + r, 0.0)) - r;
}

void fragment() {
    // UV坐标范围(0,0)到(1,1),中心在(0.5,0.5)
    vec2 uv = UV - 0.5;
    // 修正UV的宽高比,避免圆角矩形拉伸变形
    vec2 aspect = vec2(1.0, TEXTURE_SIZE.y / TEXTURE_SIZE.x);
    vec2 p = uv * aspect;
    
    // 用相对值定义矩形大小和圆角半径,适配不同尺寸的控件
    vec2 b = vec2(0.4);
    float r = 0.1;
    
    float f = udRoundBox(p, b, r);
    // smoothstep实现抗锯齿,避免边缘出现锯齿感
    float mask = smoothstep(0.0, fwidth(f), -f);
    
    // 结合原纹理颜色与圆角遮罩
    COLOR = texture(TEXTURE, UV) * vec4(1.0, 1.0, 1.0, mask);
}

额外说明

  • 如果需要用绝对像素作为圆角半径,可以这样计算:
    float pixel_radius = 64.0;
    float r = pixel_radius / min(TEXTURE_SIZE.x, TEXTURE_SIZE.y) * 0.5;
    
    这样能保证在不同尺寸的TextureRect上,圆角半径始终为64像素。
  • fwidth(f)会根据当前片段的像素密度自动计算平滑范围,让抗锯齿效果适配不同分辨率。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 19:31:25