首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >基于世界空间的GLSL破片着色器紫外位移

基于世界空间的GLSL破片着色器紫外位移
EN

Stack Overflow用户
提问于 2019-08-27 14:28:59
回答 3查看 2.3K关注 0票数 2

我正试图为网站上的图像创建一个rgb偏移效果。我有基本的功能,但问题是通道是抵消了uv的纹理。因此,如果图像大小不同,则每个图像的偏移量在视觉上并不相同。

这是我的碎片着色器。

代码语言:javascript
复制
uniform sampler2D texture;
varying vec2 vUv; // vertex uv


void main() {
    vec2 uv = vUv;

    float red = texture2D(texture, vec2(uv.x, uv.y - .1)).r;
    float green = texture2D(texture, uv).g;
    float blue = texture2D(texture, vec2(uv.x, uv.y + .1)).b;
    float alpha = texture2D(texture, uv).a;

    gl_FragColor = vec4(vec3(red, green, blue), alpha);

}

以及它呈现到页面上的方式。

我将如何在不需要传递一个统一的值的情况下,对uv偏移量进行标准化?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-08-28 04:40:07

传递更多的信息,比如偏移量,这是正常的。

代码语言:javascript
复制
uniform float offset1;
uniform float offset2;
uniform sampler2D texture;
varying vec2 vUv; // vertex uv


void main() {
    vec2 uv = vUv;

    float red = texture2D(texture, vec2(uv.x, uv.y + offset1)).r;
    float green = texture2D(texture, uv).g;
    float blue = texture2D(texture, vec2(uv.x, uv.y + offset2)).b;
    float alpha = texture2D(texture, uv).a;

    gl_FragColor = vec4(vec3(red, green, blue), alpha);

}

然后,您可以在JavaScript中调整这一点。例如

代码语言:javascript
复制
  const uniforms = {
    offset1:  { value: 0 },
    offset2:  { value: 0 },
    ...
  };

  ...

  uniforms.offset1.value =  2 / textureHeight;
  uniforms.offset2.value = -2 / textureHeight;

如果是我,我会做得更像这样

代码语言:javascript
复制
uniform vec2 channelOffsets[4];
uniform vec4 channelMult[4];
uniform sampler2D texture;
varying vec2 vUv; // vertex uv


void main() {
    vec2 uv = vUv;

    vec4 channel0 = texture2D(texture, uv + channelOffset[0]);
    vec4 channel1 = texture2D(texture, uv + channelOffset[1]);
    vec4 channel2 = texture2D(texture, uv + channelOffset[2]);
    vec4 channel3 = texture2D(texture, uv + channelOffset[3]);

    gl_FragColor = 
        channelMult[0] * channel0 +
        channelMult[1] * channel1 +
        channelMult[2] * channel2 +
        channelMult[3] * channel3 ; 
}

并设置它们

代码语言:javascript
复制
  const uniforms = {
    channelOffsets:  { value: [
      new THREE.Vector2(),
      new THREE.Vector2(),
      new THREE.Vector2(),
      new THREE.Vector2(),
    ]},
    channelMults: { value: [
      new THREE.Vector4(1, 0, 0, 0),
      new THREE.Vector4(0, 1, 0, 0),
      new THREE.Vector4(0, 0, 1, 0),
      new THREE.Vector4(0, 0, 0, 1),
    ]},
    ....
  }

...

  uniforms.channelOffsets.value[0].y = -2 / textureHeight;
  uniforms.channelOffsets.value[2].y =  2 / textureHeight;

一个不太硬编码的例子。我甚至可以使用纹理矩阵代替允许旋转和缩放每个通道的偏移,并将它们与允许交换通道的矩阵组合起来。

票数 5
EN

Stack Overflow用户

发布于 2019-08-27 16:02:19

如果要使用WebGL 2.0上下文(参见如何使用WebGL2),则可以使用textureSize获取纹理的大小。例如:

代码语言:javascript
复制
#version 300 es

uniform sampler2D tex;
in      vec2      vUv;
out     vec4      color;

void main() {
    vec2 uv = vUv;

    vec2  size   = vec2(textureSize(tex, 0));
    float pixel  = 10.0;
    float offset = pixel / size.y;

    float red   = texture(tex, vec2(uv.x, uv.y - offset)).r;
    float green = texture(tex, uv).g;
    float blue  = texture(tex, vec2(uv.x, uv.y + offset)).b;
    float alpha = texture(tex, uv).a;

    color = vec4(red, green, blue, alpha);
}

注意,您必须更改纹理取样器制服的名称

票数 3
EN

Stack Overflow用户

发布于 2019-08-27 17:29:38

如果你需要知道你在屏幕空间(不是3D世界空间)上的哪个像素,你可以使用gl_FragCoord。例如,在1080 p的显示器中,gl_FragCoord.x从左边的0开始,在屏幕的右边增加到1920。gl_FragCoord.y的范围将比0,1080短一点。您可以在分段着色器中提取这些坐标,如下所示:

代码语言:javascript
复制
vec2 coord = gl_FragCoord.xy;

这样你就可以知道你在屏幕空间的哪个像素,而不必穿另一件制服。有关更多细节,请参见此处:

FragCoord.xhtml

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57676918

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档