基于顶点绑定多个纹理

时间:2014-10-13 00:40:18

标签: javascript textures webgl

我的问题是我试图通过从文本文件中检索verticies来将某个纹理设置到三角形上。基本上我希望能够遍历每个矩阵并为我想要设置的纹理设置一个值。现在我把它设置为只有1个纹理的字面上的一切。我从一个例子中得到这个,但这是直接webgl没有库或任何我严格用于解构和学习目的。必须有一种方法可以做到这一点,我正在为x,y,z坐标和纹理坐标这样做。

    gl.activeTexture(gl.TEXTURE0);
    gl.bindTexture(gl.TEXTURE_2D, rockTexture);
    gl.uniform1i(shaderProgram.samplerUniform, 0);

我查了一些文档,你不能像绑定bindBuffer一样将数组绑定到纹理,基本上我只是试图从文本文件中获取一个值来确定我希望它是哪个纹理。一些帮助,甚至是朝着正确方向迈出一步并做出一些解释都会产生奇迹。

我如何使用坐标执行此操作的示例:

(文本文件示例)

// Floor 1
-25.0  0.0 -25.0 0.0 25.0
-25.0  0.0  25.0 0.0 0.0
 25.0  0.0  25.0 25.0 0.0

-25.0  0.0 -25.0 0.0 25.0
 25.0  0.0 -25.0 25.0 25.0
 25.0  0.0  25.0 25.0 0.0

// Ceiling 1
-25.0  4.0 -25.0 0.0 24.0
-25.0  4.0  25.0 0.0 0.0
 25.0  4.0  25.0 24.0 0.0
-25.0  4.0 -25.0 0.0 24.0
 25.0  4.0 -25.0 24.0 24.0
 25.0  4.0  25.0 24.0 0.0

然后它通过这里解析并连接它:

var lines = data.split("\n");
        var vertexCount = 0;
        var vertexPositions = [];
        var vertexTextureCoords = [];
        for (var i in lines) {
            var vals = lines[i].replace(/^\s+/, "").split(/\s+/);
            if (vals.length == 6 && vals[0] != "//") {
                // It is a line describing a vertex; get X, Y and Z first
                vertexPositions.push(parseFloat(vals[0]));
                vertexPositions.push(parseFloat(vals[1]));
                vertexPositions.push(parseFloat(vals[2]));

                // And then the texture coords
                vertexTextureCoords.push(parseFloat(vals[3]));
                vertexTextureCoords.push(parseFloat(vals[4]));

                vertexCount += 1;
            }
        }

        worldVertexPositionBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, worldVertexPositionBuffer);
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexPositions), gl.STATIC_DRAW);
        worldVertexPositionBuffer.itemSize = 3;
        worldVertexPositionBuffer.numItems = vertexCount;

        worldVertexTextureCoordBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, worldVertexTextureCoordBuffer);
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexTextureCoords), gl.STATIC_DRAW);
        worldVertexTextureCoordBuffer.itemSize = 2;
        worldVertexTextureCoordBuffer.numItems = vertexCount;

所以基本上我只是想这样做来告诉程序我想要使用哪种纹理。

1 个答案:

答案 0 :(得分:0)

通常,如果您想在同一模型上使用2个或更多纹理,则将它们合并为texture atlas。你可以看到a live example as the last example on this page

否则,如果你真的想要使用2个或更多纹理(提示:除了特殊情况,大多数程序都不这样做),那么你

  1. 制作纹理

    // for each texture
    var tex1 = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, tex1);
    gl.texImage2D(....);
    
  2. 在着色器中引用多个纹理

    uniform sampler2D u_tex1;
    uniform sampler2D u_tex2;
    
  3. 决定如何在着色器中选择1或其他纹理。

    vec4 color1 = texture2D(u_tex1, v_coordsForTex1);
    vec4 color2 = texture2D(u_tex2, v_coordsForTex2);
    vec4 color =  mix(color1, color2, mixAmount);
    

    由您来决定如何设置mixAmount。它可以是uniform,一个公式,它可以来自属性的varying,因此每个顶点都可以选择纹理等......

  4. 在渲染时间

    1. 将纹理绑定到纹理单元

      gl.activeTexture(gl.TEXTURE0 + unitForTexture1);
      gl.bindTexture(gl.TEXTURE_2D, tex1);
      gl.activeTexture(gl.TEXTURE0 + unitForTexture2);
      gl.bindTexture(gl.TEXTURE_2D, tex2);
      
    2. 告诉着色器将纹理放在哪个单位

      gl.uniform1f(locationOfUTex1, unitForTexture1);
      gl.uniform1f(locationOfUTex2, unitForTexture2);
      
  5. 注意:为了澄清,许多程序在绘制时使用多个纹理,但通常这些纹理是颜色贴图,法线贴图,可能是辉光贴图,环境贴图,环境遮挡贴图等。但很少有程序使用单个绘图的多个颜色贴图。相反,他们使用纹理图集。

    我所知道的一个常见例外是地形渲染,有时他们会说泥土,草和雪纹理并在它们之间融合。它通常比使用纹理图集的手绘过渡更加丑陋。它主要用于21世纪初,当时4meg的vram很常见。现在大多数GPU都至少有32倍。