多纹理webgl frag shader问题

Multiple textures webgl frag shader problem

我正在为我的网络项目使用 curtains.js。 我告诉你这个是因为我试图在 Whosebug 上找到关于这个主题的类似问题,但由于窗帘的制作方式,我无法重现答案。 curtains.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;

[...]

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

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

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

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

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

其中 i 是 uVideoQueue 的编号。

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

谢谢!

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

您的片段着色器将变得更容易编写,仅使用 uActiveTexture 采样器制服。

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

干杯,

感谢您的回复!

这是我的新 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);