首页 > 解决方案 > 在片段着色器中应用变换

问题描述

我知道我可以在顶点着色器中执行转换(旋转、缩放)。但是我想知道我是否可以在fragment着色器中做类似的事情。

shadertoy.com - transformation_in_fragment_shade

我试图通过乘以在片段着色器中应用转换,uv但被结果弄糊涂了。

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    // Normalized pixel coordinates (from 0 to 1)
    vec2 uv = fragCoord/iResolution.xy;
    uv = fract(uv * 2.);
    vec4 img = texture(iChannel0, uv);
    
    // Output to screen
    fragColor = img;
}

结果

我预计图像会被缩放2倍而不是缩小,我也对fract这里的含义感到困惑,为什么应用这个功能可以将图像分成4块。

所以问题是,我可以在这里的片段着色器中应用旋转或缩放吗?我应该使用不同的方法来进行旋转,在这里缩放吗?

标签: glslshaderwebglfragment-shader

解决方案


纹理坐标在 [0.0, 1.0] 范围内。(0, 0) 是左下角, (1, 1) 是右上角。在texture特定坐标处查找纹理并从该坐标返回颜色。如果将纹理坐标乘以 2,则坐标将在 [0.0, 2.0] 范围内。从 1.0 到 2.0 的坐标不在纹理上,并固定为 1.0。
fract函数跳过积分部分。例如,1.5 变为 0.5。因此uv = fract(uv * 2.)将坐标从区间 [0.0, 1.0] 映射到 2 个区间 [0.0, 1.0], [0.0, 1.0]。
如果要放大 (2x) 到中心,则需要在视图中的坐标 (0.25, 0.25) 和 (0.75, 0.75) 之间投影纹理:

uv = uv / 2.0 + 0.25; // maps [0.0, 1.0] to [0.25, 0.75]

您可以对 3x3 矩阵执行相同操作:

mat3 zoom = mat3(
    vec3(0.5, 0.0, 0.0),
    vec3(0.0, 0.5, 0.0),
    vec3(0.25, 0.25, 1.0));

uv = (zoom * vec3(uv, 1.0)).xy;

推荐阅读