WebGL无报错但无法渲染三角形问题求助
WebGL三角形无法渲染问题排查与修复
我尝试用WebGL绘制三角形,程序没有报错,但三角形始终显示不出来。我试过调整输入顺序、重写着色器代码,以下是相关代码片段:
顶点着色器
attribute vec4 a_position; attribute vec4 a_color; varying vec4 v_color; void main() { v_color = a_color; gl_Position = a_position; }
片元着色器(初始错误版本)
attribute vec4 a_position; attribute vec4 a_color; varying vec4 v_color; void main() { v_color = a_color; gl_Position = a_position; }
绘制函数
function drawTri(x1,y1,x2,y2,x3,y3){ const a_position = new Float32Array([x1,y1,0,1,x2,y2,0,1,x3,y3,0,1]); const a_color = new Float32Array([ testColor[0],testColor[1],testColor[2],testColor[3], testColor[0],testColor[1],testColor[2],testColor[3], testColor[0],testColor[1],testColor[2],testColor[3] ]); gl.useProgram(myShaders.untextured.ProgramInf.program); gl.viewport(0, 0, 630, 360); // Bind Positional Data gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer); gl.bufferData(gl.ARRAY_BUFFER, a_position, gl.STATIC_DRAW); gl.enableVertexAttribArray(a_position_Location); gl.vertexAttribPointer(a_position_Location, 4, gl.FLOAT, false, 0, 0); // Bind Color Data gl.bindBuffer(gl.ARRAY_BUFFER,colorBuffer); gl.bufferData(gl.ARRAY_BUFFER, a_color, gl.STATIC_DRAW); gl.enableVertexAttribArray(a_color_Location); gl.vertexAttribPointer(a_color_Location, 4, gl.FLOAT, false, 0, 0); gl.drawArrays(gl.TRIANGLES, 0, 3); }
testColor 定义
const testColor = [0,0,1,1];
完整示例代码
const canvas = document.createElement("canvas"); const gl = canvas.getContext("webgl2") || canvas.getContext("experimental-webgl") || canvas.getContext("webgl"); canvas.width = 480; canvas.height = 360; gl.clearColor(0, 0, 0, 1); gl.clear(gl.COLOR_BUFFER_BIT); //Get Shaders const myShaders = { untextured: { Shaders: { vert: ` precision highp float; attribute vec4 a_position; attribute vec4 a_color; varying vec4 v_color; void main() { v_color = a_color; gl_Position = a_position; } `, frag: ` precision highp float; varying vec4 v_color; void main() { gl_FragColor = vec4(0,0,1,1); } `, }, ProgramInf: null, }, createAndCompileShaders: (vert, frag) => { // compile vertex Shader const vertShader = gl.createShader(gl.VERTEX_SHADER); try { gl.shaderSource(vertShader, vert.trim()); gl.compileShader(vertShader); if (!gl.getShaderParameter(vertShader, gl.COMPILE_STATUS)) { throw gl.getShaderInfoLog(vertShader); } } catch (error) { console.error(error); } // compile fragment Shader const fragShader = gl.createShader(gl.FRAGMENT_SHADER); try { gl.shaderSource(fragShader, frag.trim()); gl.compileShader(fragShader); if (!gl.getShaderParameter(fragShader, gl.COMPILE_STATUS)) { throw gl.getShaderInfoLog(fragShader); } } catch (error) { console.error(error); } // compile program const program = gl.createProgram(); try { gl.attachShader(program, vertShader); gl.attachShader(program, fragShader); gl.linkProgram(program); if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { throw gl.getProgramInfoLog(program); } gl.validateProgram(program); if (!gl.getProgramParameter(program, gl.VALIDATE_STATUS)) { throw gl.getProgramInfoLog(program); } } catch (error) { console.error(error); } return { program: program, vert: vertShader, frag: fragShader, }; }, }; myShaders.untextured.ProgramInf = myShaders.createAndCompileShaders( myShaders.untextured.Shaders.vert, myShaders.untextured.Shaders.frag ); const a_position_Location = gl.getAttribLocation( myShaders.untextured.ProgramInf.program, "a_position" ); const a_color_Location = gl.getAttribLocation( myShaders.untextured.ProgramInf.program, "a_color" ); console.log(a_position_Location, a_color_Location); document.body.appendChild(canvas); const positionBuffer = gl.createBuffer(); //predefine penColor's postion so we don't have to call it as much. const penColor = [0, 0, 1, 1]; const drawTri = (x1, y1, x2, y2, x3, y3) => { const a_position = new Float32Array([ x1, y1, 1, 1, penColor[0], penColor[1], penColor[2], penColor[3], x2, y2, 1, 1, penColor[0], penColor[1], penColor[2], penColor[3], x3, y3, 1, 1, penColor[0], penColor[1], penColor[2], penColor[3], ]); gl.useProgram(myShaders.untextured.ProgramInf.program); gl.viewport(0, 0, 480, 360); // Bind Positional Data gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); gl.bufferData( gl.ARRAY_BUFFER, a_position, gl.STATIC_DRAW ); gl.vertexAttribPointer( a_position_Location, 4, gl.FLOAT, false, 4 * Float32Array.BYTES_PER_ELEMENT, 0 ); gl.vertexAttribPointer( a_color_Location, 4, gl.FLOAT, false, 4 * Float32Array.BYTES_PER_ELEMENT, 4 * Float32Array.BYTES_PER_ELEMENT ); gl.enableVertexAttribArray(a_position_Location); gl.enableVertexAttribArray(a_color_Location); gl.useProgram(myShaders.untextured.ProgramInf.program); console.log( gl.getProgramInfoLog(myShaders.untextured.ProgramInf.program) ); gl.drawArrays(gl.TRIANGLES, 0, 3); }; drawTri(0, 0, 0.5, 0.5, 0, 0.5);
问题排查与修复
片元着色器初始错误:你最初提供的片元着色器复制了顶点着色器代码,片元着色器不允许使用
attribute变量或赋值gl_Position,不过完整代码中已修正此问题,这不是当前渲染失败的原因。顶点数据步长(stride)错误:在完整代码的
drawTri函数中,你将位置和颜色数据交错存储(每个顶点占8个float:4个位置+4个颜色),但vertexAttribPointer的stride参数设置为4 * Float32Array.BYTES_PER_ELEMENT,导致WebGL读取顶点属性时跳过的字节数不足,无法正确解析每个顶点的完整数据。修正后的
vertexAttribPointer调用:const vertexSize = 8 * Float32Array.BYTES_PER_ELEMENT; // 每个顶点的总字节数 gl.vertexAttribPointer( a_position_Location, 4, gl.FLOAT, false, vertexSize, 0 ); gl.vertexAttribPointer( a_color_Location, 4, gl.FLOAT, false, vertexSize, 4 * Float32Array.BYTES_PER_ELEMENT );顶点坐标适配裁剪空间:WebGL裁剪空间的x轴范围是-1(左)到1(右),y轴范围是-1(下)到1(上)。你当前使用的
(0,0)、(0.5,0.5)、(0,0.5)仅在画布右半区域可见,若想让三角形居中,可调整为(-0.5,-0.5)、(0.5,0.5)、(-0.5,0.5)这类坐标。冗余代码清理:
drawTri中重复调用gl.useProgram无意义,第一次调用已激活目标程序。
修复后的drawTri函数
const drawTri = (x1, y1, x2, y2, x3, y3) => { const vertexData = new Float32Array([ x1, y1, 0, 1, penColor[0], penColor[1], penColor[2], penColor[3], x2, y2, 0, 1, penColor[0], penColor[1], penColor[2], penColor[3], x3, y3, 0, 1, penColor[0], penColor[1], penColor[2], penColor[3], ]); gl.useProgram(myShaders.untextured.ProgramInf.program); gl.viewport(0, 0, canvas.width, canvas.height); // 使用画布实际尺寸 gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); gl.bufferData(gl.ARRAY_BUFFER, vertexData, gl.STATIC_DRAW); const vertexSize = 8 * Float32Array.BYTES_PER_ELEMENT; gl.vertexAttribPointer(a_position_Location, 4, gl.FLOAT, false, vertexSize, 0); gl.vertexAttribPointer(a_color_Location, 4, gl.FLOAT, false, vertexSize, 4 * Float32Array.BYTES_PER_ELEMENT); gl.enableVertexAttribArray(a_position_Location); gl.enableVertexAttribArray(a_color_Location); gl.drawArrays(gl.TRIANGLES, 0, 3); }; // 调用时使用裁剪空间内的居中坐标 drawTri(-0.5, -0.5, 0.5, 0.5, -0.5, 0.5);
内容的提问来源于stack exchange,提问作者ObviousAlexC.
相关产品推荐
相关产品推荐

