多纹理 webgl 片段着色器问题

时间:2021-02-16 15:37:48

标签: fragment glsl shader webgl curtains.js

我在我的网络项目中使用curves.js。 我告诉你这个是因为我试图在关于这个主题的 stackoverflow 上找到类似的问题,但由于窗帘的制作方式,我无法重现答案。窗帘.js 对 html 的 DOM 中的对象非常具体。 考虑到这一点,我想提出以下问题:

有没有办法让我的代码更漂亮?目前我有这个:

export default [...]

varying vec2 vTextureCoord; 
varying vec2 vDisplacedTextureCoord;
varying vec2 vDistortionEffect;

// custom uniforms
uniform float uDisplacementStrength;
uniform float uVideoQueue;

// our textures samplers
uniform sampler2D displacementTexture2;
uniform sampler2D sourceVideo0;
uniform sampler2D sourceVideo1;
uniform sampler2D sourceVideo2;
uniform sampler2D sourceVideo3;
uniform sampler2D sourceVideo4;
uniform sampler2D sourceVideo5;
uniform sampler2D sourceVideo6;
uniform sampler2D sourceVideo7;
uniform sampler2D sourceVideo8;
uniform sampler2D sourceVideo9;
uniform sampler2D canvasTexture;

void main (void) {
    vec2 textureCoords = vTextureCoord;
    
    vec4 mouseEffect = texture2D(canvasTexture, textureCoords);
    vec4 mapEffect = texture2D(displacementTexture2, textureCoords);
    
    vec4 colorEffect = texture2D(sourceVideo0, textureCoords);
    vec4 finalColor = texture2D(sourceVideo0, vDisplacedTextureCoord + vec2(mapEffect.r * mouseEffect.r * colorEffect.r, 0.0));

    if (uVideoQueue == 1.0) {
        colorEffect = texture2D(sourceVideo1, textureCoords);
        finalColor = texture2D(sourceVideo1, vDisplacedTextureCoord + vec2(mapEffect.r * mouseEffect.r * colorEffect.r, 0.0));
    } else if (uVideoQueue == 2.0) {
        colorEffect = texture2D(sourceVideo2, textureCoords);
        finalColor = texture2D(sourceVideo2, vDisplacedTextureCoord + vec2(mapEffect.r * mouseEffect.r * colorEffect.r, 0.0));
    } else if (uVideoQueue == 3.0) {
        colorEffect = texture2D(sourceVideo3, textureCoords);
        finalColor = texture2D(sourceVideo3, vDisplacedTextureCoord + vec2(mapEffect.r * mouseEffect.r * colorEffect.r, 0.0));
    } else if (uVideoQueue == 4.0) {
        colorEffect = texture2D(sourceVideo4, textureCoords);
        finalColor = texture2D(sourceVideo4, vDisplacedTextureCoord + vec2(mapEffect.r * mouseEffect.r * colorEffect.r, 0.0));
    } else if (uVideoQueue == 5.0) {
        colorEffect = texture2D(sourceVideo5, textureCoords);
        finalColor = texture2D(sourceVideo5, vDisplacedTextureCoord + vec2(mapEffect.r * mouseEffect.r * colorEffect.r, 0.0));
    } else if (uVideoQueue == 6.0) {
        colorEffect = texture2D(sourceVideo6, textureCoords);
        finalColor = texture2D(sourceVideo6, vDisplacedTextureCoord + vec2(mapEffect.r * mouseEffect.r * colorEffect.r, 0.0));
    } else if (uVideoQueue == 7.0) {
        colorEffect = texture2D(sourceVideo7, textureCoords);
        finalColor = texture2D(sourceVideo7, vDisplacedTextureCoord + vec2(mapEffect.r * mouseEffect.r * colorEffect.r, 0.0));
    } else if (uVideoQueue == 8.0) {
        colorEffect = texture2D(sourceVideo8, textureCoords);
        finalColor = texture2D(sourceVideo8, vDisplacedTextureCoord + vec2(mapEffect.r * mouseEffect.r * colorEffect.r, 0.0));
    } else if (uVideoQueue == 9.0) {
        colorEffect = texture2D(sourceVideo9, textureCoords);
        finalColor = texture2D(sourceVideo9, vDisplacedTextureCoord + vec2(mapEffect.r * mouseEffect.r * colorEffect.r, 0.0));
    } 
        
    gl_FragColor = finalColor;

[...]

在我的主脚本中有一个uniform,它不断更新以告诉着色器它应该用于输出的纹理(uVideoQueue),范围从0-9(当前数字是特定视频的编号)

sampler2D uniforms(0-9)是DOM中需要绘制的视频。

正如您在代码中看到的,在着色器中每次绘制调用时,该函数都必须检查它需要添加片段着色器的 sourceVideo sampler2D 统一变量。

如您所见:每个 if/else if 代码行都与顶部的相同,但只有 sampler2D 统一的名称不同。一定有办法拥有这样的东西

vec4 colorEffect = texture2D(sourceVideo **+ i**, textureCoords);
vec4 finalColor = texture2D(sourceVideo **+ i**, [...]);

其中 i 是 uVideoQueue 的编号。

代码工作正常,但我认为与只需要 2 行代码的更优雅的解决方案相比,所有 if/else if 语句的处理器强度更高......

谢谢!

2 个答案:

答案 0 :(得分:1)

根据官方文档 slideshow example code,您应该使用额外的 activeTexture 纹理并随时更新其来源。

然后您的片段着色器将变得更容易编写,只需使用统一的 uActiveTexture 采样器。

这是一个演示该概念的最小代码和框:https://codepen.io/martinlaxenaire/pen/YzpVYLE

干杯,

答案 1 :(得分:0)

感谢您的回复!

这是我的新 FS:

void main (void) {
vec2 textureCoords = vTextureCoord;

vec4 mouseEffect = texture2D(canvasTexture, vDisplacedTextureCoord);
vec4 mapEffect = texture2D(displacementTexture2, vDisplacedTextureCoord);

vec4 colorEffect = texture2D(activeVideo, vDisplacedTextureCoord);
vec4 finalColor = texture2D(activeVideo, vDisplacedTextureCoord + vec2(mapEffect.r * mouseEffect.r * colorEffect.r * 0.2, 0.0));

gl_FragColor = finalColor;

在我的主脚本中,我创建了一个新纹理:

welcomeobj.mouseEffect.activeTexture = welcomeobj.mouseEffect.curtains.planes[0].createTexture({
            sampler: "activeVideo",
        });

当上一个视频结束时,主脚本会为纹理设置一个新源:

welcomeobj.mouseEffect.activeTexture.setSource(loaderobj.xhrarray[m].video);