WebGL使用drawArraysInstanced时纹理无法显示的求助
OpenGL实例化绘制纹理异常问题
我正在开发一款浏览器小游戏学习OpenGL,尝试用drawArraysInstanced做实例化绘制渲染纹理。现有一张85×44带透明通道的PNG纹理,单次绘制时显示正常,但切换到实例化绘制后无法正常显示。调整片段着色器的alpha阈值后,画布对应位置只会出现白色块(如图)。尝试调整glBindTexture调用顺序,绘制内容会在白色和黑色间切换,但不确定方向是否正确。

片段着色器(FS)
// #version 300 es // #pragma vscode_glsllint_stage: frag precision mediump float; // our texture uniform sampler2D u_image; // the texCoords passed in from the vertex shader. varying vec2 v_texCoord; void main() { gl_FragColor = texture2D(u_image, v_texCoord); if(gl_FragColor.a < 0.9) discard; }
顶点着色器(VS)
// #version 300 es // #pragma vscode_glsllint_stage: vert attribute vec2 a_Position; uniform mat3 u_matrix; varying vec2 v_texCoord; void main() { gl_Position = vec4(u_matrix * vec3(a_Position, 1), 1); // because we're using a unit quad we can just use // the same data for our texcoords. v_texCoord = a_Position; }
initVertexBuffer.ts
import { ProgramInfo } from "../../../compileShaders"; export function initVertexBuffers({ gl, programInfo, array, rgba, // note not in use in this file texture, // note not in use in this file }: { gl: WebGL2RenderingContext; programInfo: ProgramInfo; array: number[]; rgba: [number, number, number, number] | number[]; texture: WebGLTexture; }) { const dim = 2; const vertices = new Float32Array(array); // Assign the vertices in buffer object to a_Position variable // let positionLocation = gl.getAttribLocation(program, "a_position"); const a_Position = gl.getAttribLocation(programInfo.program, "a_Position"); const u_imageLoc = gl.getUniformLocation(programInfo.program, "u_image"); const u_matrixLoc = gl.getUniformLocation(programInfo.program, "u_matrix"); const vertexBuffer = gl.createBuffer(); if (!vertexBuffer) { console.log("Failed to create the buffer object"); return { n: -1 }; } gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW); if (a_Position < 0) { console.log("Failed to get the storage location of a_Position"); return { n: -2 }; } gl.enableVertexAttribArray(a_Position); gl.vertexAttribPointer(a_Position, dim, gl.FLOAT, false, 0, 0); // use texture gl.activeTexture(gl.TEXTURE0); // Return number of vertices return { n: vertices.length / dim, u_imageLoc, u_matrixLoc }; }
createRect.ts
export const createRect = ({ array, gl, position, size, cameraLoc, color = [], }: { gl: WebGL2RenderingContext; array: number[]; position: XY; size: Dimensions; cameraLoc: XY; color?: number[] | [number, number, number, number]; }) => { const { width: canvasWidth, height: canvasHeight } = gl.canvas; const { x, y } = position; const { width, height } = size; const { x: cameraX, y: cameraY } = cameraLoc; const clipX = ((x - cameraX) / canvasWidth) * 2 - 1; const clipY = ((y - cameraY) / canvasHeight) * -2 + 1; const clipWidth = width / canvasWidth; const clipHeight = height / canvasHeight; // minimum of 12 numbers per rect array.push( // first triangle clipX, clipY, clipX + clipWidth, clipY, clipX, clipY - clipHeight, // second triangle clipX + clipWidth, clipY, clipX, clipY - clipHeight, clipX + clipWidth, clipY - clipHeight, ...color ); };
draw.ts
import { RootState } from "../../../../store"; import { glBindTexture } from "../../shaders/textures/terrain/grass1/glBindTexture"; import { ProgramInfo } from "../../shaders/compileShaders"; import { initVertexBuffers } from "../../shaders/textures/terrain/grass1/initVertexBuffers"; import { gray } from "../../colors"; import { createRect } from "../../shaders/textures/terrain/grass1/createRect"; interface Props { gl: WebGL2RenderingContext; state: RootState; shaders: { grass1Shader: ProgramInfo; }; } const images = {} as Record<string, HTMLImageElement>; export const terrain = ({ gl, state, shaders: { grass1Shader } }: Props) => { if (!grass1Shader) return; const cameras = state.game.cameras["main"].position; if (!images["grass1.png"]) { const img = document.getElementById("grass1.png") as HTMLImageElement; if (!img) return; images["grass1.png"] = img; } images["grass1.png"].width = 85; images["grass1.png"].height = 40; if (!images["grass1.png"]) return; const array = [] as number[]; createRect({ array, gl, position: { x: 0, y: 0, }, cameraLoc: cameras, size: { width: 85, height: 44, }, }); createRect({ array, gl, position: { x: 100, y: 100, }, cameraLoc: cameras, size: { width: 85, height: 44, }, }); gl.useProgram(grass1Shader.program); gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); const texture = glBindTexture(gl, grass1Shader, images["grass1.png"]); const { n, u_matrixLoc } = initVertexBuffers({ gl, programInfo: grass1Shader, array, rgba: gray, texture, }); if (n < 0) { console.log(n); console.log("Failed to set the positions of the vertices"); return; } // identity matrix spanning full screen gl.uniformMatrix3fv(u_matrixLoc, false, [1, 0, 0, 0, 1, 0, 0, 0, 1]); // console.log(n, array.length / 12); gl.drawArraysInstanced(gl.TRIANGLES, 0, n, array.length / 12); // gl.drawElementsInstanced(gl.TRIANGLES, n, gl.UNSIGNED_SHORT, 0, 1); gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); };
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

