[英]WebGL2 draw multiple textures in one draw call
我在查找代碼中的錯誤時遇到了一些麻煩。 我希望你能告訴我尋找解決方案的方向。
我嘗試在一次繪制調用中使用 2+ 紋理。 為了測試,我使用 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.