【问题标题】:WebGL texture on top of texture纹理之上的 WebGL 纹理
【发布时间】:2016-08-28 11:09:09
【问题描述】:

我正在开展一个项目,将网络摄像头流合并到球形几何体中。由于我是着色器的新手并且想了解它是如何工作的,因此我想在静态背景图像之上使用相对正常的大小将网络摄像头投影到球体中。

因此网络摄像头视频必须只覆盖球体的一小部分,但背景图像必须覆盖整个球体。

目前我的网络摄像头图像如下所示: current situation

但我希望它看起来像这样: desired situation

我有以下顶点着色器:

            uniform mat4 projectionMat;
        uniform mat4 modelViewMat;
        attribute vec3 position;
        attribute vec2 texCoord;
        attribute vec2 texVideoCoord;
        varying vec2 vTexCoord;
        varying vec2 vTexVideoCoord;

        void main() {
          vTexCoord = texCoord;
          vTexVideoCoord = texVideoCoord;
          gl_Position = projectionMat * modelViewMat * vec4( position, 1.0 );
        }

还有下面的片段着色器,它当前绘制的是网络摄像头流的“视频”。

        precision mediump float;

        // Textures
        uniform sampler2D u_background;
        uniform sampler2D u_video;

        varying vec2 vTexCoord;
        varying vec2 vTexVideoCoord;

        void main() {
          vec4 background = texture2D(u_background, vTexCoord);
          vec4 video = texture2D(u_video, vTexVideoCoord);
          gl_FragColor = video;
        }

而我的渲染功能设置如下:

    this.program.use();

    //setup attributes
    //setup uniforms
    context.gl.uniformMatrix4fv(this.program.uniform.projectionMat, false, projectionMat);
    context.gl.uniformMatrix4fv(this.program.uniform.modelViewMat, false, modelViewMat);

    context.gl.bindBuffer(context.gl.ARRAY_BUFFER, this.vertBuffer);
    context.gl.bindBuffer(context.gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);

    context.gl.enableVertexAttribArray(this.program.attrib.position);
    context.gl.enableVertexAttribArray(this.program.attrib.texCoord);
    context.gl.enableVertexAttribArray(this.program.attrib.texVideoCoord);

    context.gl.vertexAttribPointer(this.program.attrib.position, 3, context.gl.FLOAT, false, 20, 0);
    context.gl.vertexAttribPointer(this.program.attrib.texCoord, 2, context.gl.FLOAT, false, 20, 12);
    context.gl.vertexAttribPointer(this.program.attrib.texVideoCoord, 2, context.gl.FLOAT, false, 20, 12);

    var u_backgroundLocation = context.gl.getUniformLocation(this.program.program, "u_background");
    var u_videoLocation = context.gl.getUniformLocation(this.program.program, "u_video");
    context.gl.uniform1i(u_backgroundLocation, 0);
    context.gl.uniform1i(u_videoLocation, 1);

    //activetexture/bind
    context.gl.activeTexture(context.gl.TEXTURE0);
    context.gl.bindTexture(context.gl.TEXTURE_2D, self.textureBackground);
    context.gl.texImage2D(context.gl.TEXTURE_2D, 0, context.gl.RGBA, context.gl.RGBA, context.gl.UNSIGNED_BYTE, self.canvasElement);
    context.gl.activeTexture(context.gl.TEXTURE1);
    context.gl.bindTexture(context.gl.TEXTURE_2D, self.textureVideo);
    context.gl.texImage2D(context.gl.TEXTURE_2D, 0, context.gl.RGBA, context.gl.RGBA, context.gl.UNSIGNED_BYTE, self.videoElement);

    //drawarrays/drawelements
    context.gl.drawElements(context.gl.TRIANGLES, this.indexCount, context.gl.UNSIGNED_SHORT, 0);

我不知道如何继续使网络摄像头显示为按比例缩放并成为球体的一部分,而不是在其上拉伸。网络摄像头是一个 100 度的摄像头,因此应该在球体内定位。

【问题讨论】:

    标签: javascript glsl webgl


    【解决方案1】:

    如果您的 UV 穿过球体,您可以将其全部用于背景图像采样,并将其较小部分用于采样视频纹理。

    vec2 vid_uv_start = vec2(0.2, 0.3);
    vec2 vid_uv_end = vec2(0.6, 0.7);
    
    uniform sampler2D u_background;
    uniform sampler2D u_video;
    
    varying vec2 vTexCoord;
    
    void main()
    {
        vec4 col = texture(u_background, vTexCoord);
        if((vTexCoord.x>=vid_uv_start.x && vTexCoord.x<=vid_uv_end.x)
            && (vTexCoord.y>=vid_uv_start.y && vTexCoord.y<=vid_uv_end.y))
        {
            vec2 adjustedUV = (vTexCoord-vid_uv_start)/(vid_uv_end-vid_uv_start);
            col = texture(u_video, adjustedUV);
        }
        gl_FragColor = col;
    }
    

    编辑:

    这是工作着色器玩具:https://www.shadertoy.com/view/MsdSWs

    【讨论】:

    • 很好,工作正常。显然纹理(应该变成纹理2D(但这很好用。谢谢。
    【解决方案2】:

    另一种方法是设置视频 UV 坐标,使 01 范围代表您想要观看视频的区域

    换句话说,背景的 UV 消失了

    0,0       0.3    0.7    1.0
        +------+------+------+
        |      |      |      |
        |      |      |      |
        |      |      |      |
    0.3 +------+------+------+
        |      |      |      |
        |      |      |      |
        |      |      |      |
    0.7 +------+------+------+
        |      |      |      |
        |      |      |      |
        |      |      |      |
    1.0 +------+------+------+
    

    但是视频 UV 消失了

    -1,-1      0      1      2
        +------+------+------+
        |      |      |      |
        |      |      |      |
        |      |      |      |
      0 +------+------+------+
        |      |......|      |
        |      |......|      |
        |      |......|      |
      1 +------+------+------+
        |      |      |      |
        |      |      |      |
        |      |      |      |
      2 +------+------+------+
    

    这使得 ...... 部分成为 0 和 1 之间的部分

    那么你的着色器将是

       precision mediump float;
    
        // Textures
        uniform sampler2D u_background;
        uniform sampler2D u_video;
    
        varying vec2 vTexCoord;
        varying vec2 vTexVideoCoord;
    
        void main() {
          vec4 background = texture2D(u_background, vTexCoord);
          vec4 video = texture2D(u_video, vTexVideoCoord);
          vec2 m = step(vec2(0), vTexVideoCoord) * step(vTexVideoCoord, vec2(1));
          gl_FragColor = mix(background, video, m.x * m.y);
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-21
      • 2013-11-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-31
      • 2013-09-23
      相关资源
      最近更新 更多