簡體   English   中英

WebGL2 在一次繪制調用中繪制多個紋理

[英]WebGL2 draw multiple textures in one draw call

我在查找代碼中的錯誤時遇到了一些麻煩。 我希望你能告訴我尋找解決方案的方向。

我嘗試在一次繪制調用中使用 2+ 紋理。 為了測試,我使用 2 個紋理。

  1. 頂點着色器的第一個紋理 - 保存為紋理的矩陣
  2. 渲染為圖像的第二個紋理

當我嘗試渲染場景時,第一個紋理(名稱:“dataTexture”)為空,第二個紋理(名稱:“u_image0”)可用並且工作正常。

這是一個包含兩種紋理的制服

myUniform = [
...
{
    name: "dataTexture",
    type: "TEXTURE_2D",
    variableLocation: WebGLUniformLocation,
    valueToPass: WebGLTexture
},
{
    name: "u_image0",
    type: "TEXTURE_2D",
    variableLocation: WebGLUniformLocation,
    valueToPass: WebGLTexture
}
];

然后我用一個單獨的 function 來渲染這些紋理 看起來像這樣

// For textures
// Using 2 or more textures
textureID = 0; // textureID = 0, 1, 2, ... (int)
let len = myUniforms.length;
for (i = 0; i < len; i++) {
    ...
    if (type == "TEXTURE_2D") { 
        // Set which texture units to render with
        if (variableLocation != null){
            console.log("Location exist");
            
            gl.uniform1i(variableLocation, textureID); // textureID = 0, 1, 2, ...
    
            textureID++;
        }
        else {console.log("No location");}
    
        // Set each texture unit to use a particular texture
        gl.activeTexture(gl.TEXTURE0 + textureID);
        // Bind texture image
        gl.bindTexture(gl.TEXTURE_2D, valueToPass);
    }
}
...
// Render
gl.drawArrays(primitiveType, offsetArray, count);

這是着色器

vertexShaderSource = [
    "#version 300 es",
    // Attributes
    // An attribute is an input (in) to a vertex shader.
    // It will receive data from a buffer
    "in vec2 a_position;",
    // Texture coordinates
    "in vec2 a_texCoord;",
    // Data indices in texture
    "in float a_matrixIndices;",
    
    // Uniforms
    // Data texture
    "uniform sampler2D dataTexture;",
    // Clip space matrix
    "uniform mat3 clipSpaceMatrix;",
    
    // Vareable to pass to fragment shader
    // Color
    "out vec3 color;",
    // Texture coordinates
    "out vec2 v_texCoord;",
    // Texture for use in the current instance
    "out float textureID;",

    // Read data from texture
    "vec4 getValueByIndexFromTexture(sampler2D tex, int index) {",
        "int texWidth = textureSize(tex, 0).x;",
        "int col = index % texWidth;",
        "int row = index / texWidth;",
        "return texelFetch(tex, ivec2(col, row), 0);",
    "}",
    
    "void main() {",
        // Index to read data from texture
        "int index = int(a_matrixIndices);",
        "vec3 data = getValueByIndexFromTexture(dataTexture, index).xyz;",

        // Object type
        "int objectType = int(data.x);",
        // Matrix to convert from object space to world space
        "mat3 matrixWorld = mat3(.0);",
        
        "if (objectType == 0) {",
            // Obect type = RasterImage
            "matrixWorld[0][0] = data.y;",
            "matrixWorld[0][1] = data.z;",

            "data = getValueByIndexFromTexture(dataTexture, index + 1).xyz,",
            "matrixWorld[0][2] = data.x;",
            "matrixWorld[1][0] = data.y;",
            "matrixWorld[1][1] = data.z;",
            "data = getValueByIndexFromTexture(dataTexture, index + 2).xyz,",
            "matrixWorld[1][2] = data.x;",
            "matrixWorld[2][0] = data.y;",
            "matrixWorld[2][1] = data.z;",

            "data = getValueByIndexFromTexture(dataTexture, index + 3).xyz,",
            "matrixWorld[2][2] = data.x;",
            
            // Texture ID
            // Texture for use in the current instance
            "textureID = data.y;",
        "}",
        // Multiply the position by the matrix
        "vec3 position = clipSpaceMatrix * matrixWorld * vec3(a_position.xy, 1);",
        
        "gl_Position = vec4(position, 1);",
        // Send color to fragment shader
        "color = vec3(.1, 0.7, 0.3);",
        // Pass the texCoord to the fragment shader
        "v_texCoord = a_texCoord;",
    "}"
].join("\n");

fragmentShaderSource = [
    // WebGL2 version
    "#version 300 es",
    // Fragment shaders don't have a default precision so we need
    // to pick one. highp is a good default. It means "high precision"
    "precision highp float;",

    // Uniforms
    // Textures
    "uniform sampler2D u_image0;",
    //"uniform sampler2D u_image1;",

    // Passed in from the vertex shader.
    //"uniform vec3 foo;",
    "in vec3 color;",
    // Texture coordinates
    // The GPU will interpolate this value between points
    "in vec2 v_texCoord;",
    // Texture for use in the current instance
    "in float textureID;",

    // We need to declare an output for the fragment shader
    "out vec4 outColor;",

    "void main() {",
        "vec4 fragmentColor = vec4(1.0, 0.0, 1.0, 1.0);",
        "if (textureID == 0.0) {",
            "fragmentColor = texture(u_image0, v_texCoord);",
        "}",
        //"else if (textureID == 1.0) {",
        //  "fragmentColor = texture(u_image1, v_texCoord);",
        //"}",

        // Set color
        "outColor = fragmentColor;",
    "}"
].join("\n");

謝謝大家。 這段代碼是正確的。 你可以隨心所欲地使用它。 像往常一樣,一個破壞一切的錯誤:發送無效數據以創建 dataTexture。 混淆push()concat()

對於 push() 方法:

dataTexture = dataTexture.push(data0, data1, ...); // This is wrong (returns array length)
dataTexture.push(data0, data1, ...); // Correct (returns changed array)

對於 conact() 方法

dataTexture = dataTexture.concat(Array[data0, data1, ...], ...); // Correct way (returns changed array)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM