WebGL绘制可刷新变色八边形:颜色缓冲区问题求助
WebGL八边形颜色缓冲区问题修复
我是WebGL新手,正在开发一个刷新时会变色的八边形,但在颜色缓冲区及颜色相关处理上遇到了问题。如果直接在HTML文件中手动设置gl_FragColor,八边形可以正常显示。
原始HTML文件
<!DOCTYPE html> <html> <head> <script id="vertex-shader" type="x-shader/x-vertex"> attribute vec4 vPosition; attribute vec4 aColor; varying vec4 vColor; void main() { gl_Position = vPosition; vColor = aColor; } </script> <script id="fragment-shader" type="x-shader/x-fragment"> precision mediump float; varying vec4 vColor; void main() { gl_FragColor = vColor; } </script> <script type="text/javascript" src="webgl-utils.js"></script> <script type="text/javascript" src="initShaders.js"></script> <script type="text/javascript" src="MV.js"></script> <script type="text/javascript" src="octagon.js"></script> </head> <body> <canvas id="gl-canvas" width="512" height="512"> Oops ... your browser doesn't support the HTML5 canvas element </canvas> </body> </html>
原始JavaScript文件
var gl; var points; var pi = 3.1415; var rad = 2*pi/360; var r = 0.5; var colors = []; var vertices = []; window.onload = function init() { var canvas = document.getElementById( "gl-canvas" ); gl = WebGLUtils.setupWebGL( canvas ); if ( !gl ) { alert( "WebGL isn't available" ); } vertices.push(0.0); vertices.push(0.0); colors.push(1.0); colors.push(0.0); colors.push(0.0); colors.push(1.0); for(var theta = 0; theta <= 360; theta+=45) { vertices.push(r*Math.cos(rad*theta)); vertices.push(r*Math.sin(rad*theta)); colors.push(1.0); colors.push(0.0); colors.push(0.0); colors.push(1.0); } // Configure WebGL gl.viewport( 0, 0, canvas.width, canvas.height); gl.clearColor( 1.0, 1.0, 1.0, 1.0 ); // Load shaders and initialize attribute buffers var program = initShaders( gl, "vertex-shader", "fragment-shader" ); gl.useProgram( program ); // Load the data into the GPU var bufferId = gl.createBuffer(); gl.bindBuffer( gl.ARRAY_BUFFER, bufferId ); gl.bufferData( gl.ARRAY_BUFFER,new Float32Array(vertices), gl.STATIC_DRAW ); // Associate out shader variables with our data buffer var vPosition = gl.getAttribLocation( program, "vPosition" ); gl.vertexAttribPointer( vPosition, 2, gl.FLOAT, false, 0, 0 ); gl.enableVertexAttribArray( vPosition ); var colorBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW); var aColor = g1.getAttribLocation(program, "aColor"); // 此处存在笔误 gl.vertexAttribPointer( aColor, 4, gl.FLOAT, false, 0, 0 ); gl.enableVertexAttribArray(aColor); render(); }; function render() { gl.clear( gl.COLOR_BUFFER_BIT ); gl.drawArrays( gl.TRIANGLE_FAN, 0, 10 ); }
问题修复与变色功能实现
1. 修复核心笔误
代码中g1.getAttribLocation是拼写错误,必须改为gl.getAttribLocation,否则无法正确获取颜色属性aColor的位置,导致颜色数据无法传递到着色器。
2. 实现刷新变色逻辑
如果要让八边形每次刷新时变色,推荐两种高效实现方式:
方式一:更新Attribute颜色缓冲区(适合顶点颜色不同的场景)
修改init和render函数,每次渲染时生成随机颜色并更新缓冲区:
var gl; var pi = 3.1415; var rad = 2*pi/360; var r = 0.5; var vertices = []; var colorBuffer; var aColorLocation; window.onload = function init() { var canvas = document.getElementById( "gl-canvas" ); gl = WebGLUtils.setupWebGL( canvas ); if ( !gl ) { alert( "WebGL isn't available" ); } // 生成八边形顶点数据 vertices.push(0.0); vertices.push(0.0); for(var theta = 0; theta <= 360; theta+=45) { vertices.push(r*Math.cos(rad*theta)); vertices.push(r*Math.sin(rad*theta)); } gl.viewport( 0, 0, canvas.width, canvas.height); gl.clearColor( 1.0, 1.0, 1.0, 1.0 ); var program = initShaders( gl, "vertex-shader", "fragment-shader" ); gl.useProgram( program ); // 顶点缓冲区设置 var bufferId = gl.createBuffer(); gl.bindBuffer( gl.ARRAY_BUFFER, bufferId ); gl.bufferData( gl.ARRAY_BUFFER,new Float32Array(vertices), gl.STATIC_DRAW ); var vPosition = gl.getAttribLocation( program, "vPosition" ); gl.vertexAttribPointer( vPosition, 2, gl.FLOAT, false, 0, 0 ); gl.enableVertexAttribArray( vPosition ); // 初始化颜色缓冲区(数据在render中动态更新) colorBuffer = gl.createBuffer(); aColorLocation = gl.getAttribLocation(program, "aColor"); gl.enableVertexAttribArray(aColorLocation); // 开启循环渲染 requestAnimationFrame(render); }; function render() { // 生成随机RGBA颜色 var randR = Math.random(); var randG = Math.random(); var randB = Math.random(); var alpha = 1.0; // 为10个顶点生成相同颜色 var colors = []; for(var i=0; i<10; i++){ colors.push(randR, randG, randB, alpha); } // 更新颜色缓冲区数据 gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.DYNAMIC_DRAW); gl.vertexAttribPointer( aColorLocation, 4, gl.FLOAT, false, 0, 0 ); gl.clear( gl.COLOR_BUFFER_BIT ); gl.drawArrays( gl.TRIANGLE_FAN, 0, 10 ); // 持续渲染下一帧 requestAnimationFrame(render); }
方式二:使用Uniform变量(适合所有顶点颜色相同的场景,性能更优)
无需颜色缓冲区,直接通过uniform变量传递全局颜色:
修改着色器代码:
<script id="vertex-shader" type="x-shader/x-vertex"> attribute vec4 vPosition; uniform vec4 uColor; varying vec4 vColor; void main() { gl_Position = vPosition; vColor = uColor; } </script> <script id="fragment-shader" type="x-shader/x-fragment"> precision mediump float; varying vec4 vColor; void main() { gl_FragColor = vColor; } </script>
修改JavaScript代码:
var gl; var pi = 3.1415; var rad = 2*pi/360; var r = 0.5; var vertices = []; var uColorLocation; window.onload = function init() { var canvas = document.getElementById( "gl-canvas" ); gl = WebGLUtils.setupWebGL( canvas ); if ( !gl ) { alert( "WebGL isn't available" ); } // 生成八边形顶点数据 vertices.push(0.0); vertices.push(0.0); for(var theta = 0; theta <= 360; theta+=45) { vertices.push(r*Math.cos(rad*theta)); vertices.push(r*Math.sin(rad*theta)); } gl.viewport( 0, 0, canvas.width, canvas.height); gl.clearColor( 1.0, 1.0, 1.0, 1.0 ); var program = initShaders( gl, "vertex-shader", "fragment-shader" ); gl.useProgram( program ); // 顶点缓冲区设置 var bufferId = gl.createBuffer(); gl.bindBuffer( gl.ARRAY_BUFFER, bufferId ); gl.bufferData( gl.ARRAY_BUFFER,new Float32Array(vertices), gl.STATIC_DRAW ); var vPosition = gl.getAttribLocation( program, "vPosition" ); gl.vertexAttribPointer( vPosition, 2, gl.FLOAT, false, 0, 0 ); gl.enableVertexAttribArray( vPosition ); // 获取uniform颜色变量位置 uColorLocation = gl.getUniformLocation(program, "uColor"); // 开启循环渲染 requestAnimationFrame(render); }; function render() { // 生成随机RGBA颜色 var randR = Math.random(); var randG = Math.random(); var randB = Math.random(); var alpha = 1.0; // 设置全局颜色 gl.uniform4f(uColorLocation, randR, randG, randB, alpha); gl.clear( gl.COLOR_BUFFER_BIT ); gl.drawArrays( gl.TRIANGLE_FAN, 0, 10 ); // 持续渲染下一帧 requestAnimationFrame(render); }
内容的提问来源于stack exchange,提问作者daCornchipe
相关产品推荐
相关产品推荐

