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

如何在Godot着色器中采样任意UI控件的COLOR像素?

Godot画布项着色器:通用UI元素波浪效果实现问题

问题描述

在Godot画布项片段着色器中,我梳理了以下特性:

  • COLOR 存储当前画布项的像素颜色(例如白色文本的像素为白色)
  • TEXTURE 对应控件的纹理,但带文本的默认按钮这类控件未设置该值(显示为纯白色)
  • hint_screen_texture 对应的屏幕纹理仅包含已渲染元素,当前着色器正在处理的内容尚未写入,且会包含下方元素,不符合需求

我编写了一段实现波浪按钮效果的着色器代码:

shader_type canvas_item;
uniform float wave_speed: hint_range(0.0, 5.0, 0.01) = 0.1;
uniform float wave_count: hint_range(0.0, 25.0, 1.0) = 10.0;
uniform float wave_size: hint_range(0.0, 1.0, 0.01) = 0.1;


void fragment() {
    // shrink by wave_size so we have space for the effect
    float remainingSize = 1.0 - wave_size;
    vec2 newUV = UV / vec2(remainingSize, 1.0) - vec2(wave_size, 0.0);
    
    // actual wave effect
    float halfWaveSize = wave_size * 0.5;
    newUV += vec2(sin((UV.y + TIME * wave_speed) * PI * wave_count) * halfWaveSize + halfWaveSize, 0.0);
    COLOR = newUV.x < 0.0 || newUV.x > 1.0 ? vec4(0.0) : texture(TEXTURE, newUV);
}

这段代码在TextureRect上可正常工作,但在默认按钮上仅显示波浪状白块。请问是否存在方法,能对任意UI元素(纹理、文本、形状等)的指定UV坐标采样COLOR?

解决方案

核心问题分析

你的着色器依赖TEXTURE采样像素,但默认按钮这类复杂UI控件的视觉内容(文本、背景)并非通过自身的TEXTURE绑定实现,而是通过Godot的样式系统或子节点绘制,直接采样TEXTURE只能得到纯白结果。

可靠实现方案:SubViewport预渲染

要让着色器作用于整个UI元素的完整视觉内容,最有效的方式是先将UI元素预渲染为纹理,再对该纹理应用波浪效果:

  1. 创建SubViewport,设置其尺寸与目标UI元素匹配(或开启Size Flags自适应)。
  2. 将目标UI元素(如默认按钮)作为SubViewport的子节点。
  3. 创建TextureRect,将其Texture属性设置为SubViewport的GetTexture()返回值。
  4. 给TextureRect应用你的波浪着色器。

这种方式下,TextureRect的TEXTURE就是整个UI元素的完整渲染结果,着色器能正常采样到包含文本、背景的所有像素,实现预期的波浪效果。

兼容无纹理控件的着色器修改(局限性大)

若不想使用预渲染,可修改着色器兼容无纹理控件,但仅适用于纯色或单一形状的控件,无法处理包含子节点(如按钮文本)的复杂UI:

shader_type canvas_item;
uniform float wave_speed: hint_range(0.0, 5.0, 0.01) = 0.1;
uniform float wave_count: hint_range(0.0, 25.0, 1.0) = 10.0;
uniform float wave_size: hint_range(0.0, 1.0, 0.01) = 0.1;

void fragment() {
    float remainingSize = 1.0 - wave_size;
    vec2 newUV = UV / vec2(remainingSize, 1.0) - vec2(wave_size, 0.0);
    
    float halfWaveSize = wave_size * 0.5;
    newUV += vec2(sin((UV.y + TIME * wave_speed) * PI * wave_count) * halfWaveSize + halfWaveSize, 0.0);
    
    if (newUV.x < 0.0 || newUV.x > 1.0 || newUV.y < 0.0 || newUV.y > 1.0) {
        COLOR = vec4(0.0);
    } else {
        vec4 texColor = texture(TEXTURE, newUV);
        // 检测是否为无纹理的纯白状态
        bool isDefaultTexture = texColor.r == 1.0 && texColor.g == 1.0 && texColor.b == 1.0 && texColor.a == 1.0;
        COLOR = isDefaultTexture ? COLOR : texColor * COLOR;
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 03:59:49