three.js - 基于世界空间的 GLSL 片段着色器 UV 置换

标签 three.js glsl shader fragment-shader

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

这是我的片段着色器。

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);

}

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

example

如何在不必传入统一值的情况下对 uv 偏移进行归一化?

最佳答案

传入偏移量等更多信息是正常的

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 中调整它。例如

  const uniforms = {
    offset1:  { value: 0 },
    offset2:  { value: 0 },
    ...
  };

  ...

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

如果是我,我可能会这样做

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 ; 
}

并设置它们

  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;

举个不那么硬编码的例子。我什至可以使用纹理矩阵而不是偏移量,这将允许旋转和缩放每个 channel 并将它们与允许交换 channel 的矩阵组合。

关于three.js - 基于世界空间的 GLSL 片段着色器 UV 置换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57676918/

相关文章:

ios - 向 scenekit 着色器发送额外信息?

opengl-es - Cocos2d 3(模糊)着色器

javascript - 如何在 Three.js 中围绕立方体旋转球体

javascript - 如何在 ar js/three.js 中禁用 fps 显示?

javascript - Three.js - 在另一个之上的几何

c++ - GLM + STL : operator == missing

C++ OpenGL 段错误(核心转储)运行时错误

java - 尝试使用 jogl 加载并初始化着色器

javascript - Three.js 上的平滑相机控制开关

opengl - GBUFFER 贴花投影和缩放