【问题标题】:Multiple textures webgl frag shader problem多个纹理 webgl frag 着色器问题
【发布时间】:2021-02-16 15:37:48
【问题描述】:

我正在为我的网络项目使用窗帘.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;

[...]

在我的主脚本中有一个不断更新的制服,以告诉着色器它应该使用哪个纹理用于​​输出(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 语句的处理器强度更高...

谢谢!

【问题讨论】:

  • 既然这个制服只在draw call之间改变,你就不能改变绑定的纹理吗?
  • 使用数组,将uVideoQueue转为int,然后从数组中得到你需要的。
  • @ZachSaucier GLSL 1.0 不允许使用非常数索引到数组中。

标签: fragment glsl shader webgl curtains.js


【解决方案1】:

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

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

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

干杯,

【讨论】:

    【解决方案2】:

    感谢您的回复!

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-26
      相关资源
      最近更新 更多