请问大佬关于小游戏webgl渲染中uniform3fv参数的问题
- 当前 Bug 的表现(可附上截图) 使用webgl渲染时,调用 gl.uniform3fv, gl.uniform4fv 等接口设置shader参数时发现以下问题: 以 gl.uniform3fv(dest, v) 为例,如果 v = Float32Array([1,2,3]).subarray(1,2) ,即输入的参数是一个byteoffset != 0 的TypeArray,那么实际运行时该参数的设置结果是错误的,导致游戏显示出现各种问题。 - 预期表现 - 复现路径 我们还试过华为,三星的多款Android的手机,均有这个问题。 - 提供一个最简复现 Demo 测试代码: let ctx = canvas.getContext('webgl') let HEAP32 = new Int32Array(1024 * 1024 * 8) let global_time = 0; var aspectRatio; var vertexArray; var vertexBuffer; var vertexNumComponents; var vertexCount; var uScalingFactor; var uGlobalColor; var uRotationVector; var aVertexPosition; var previousTime = 0.0; var degreesPerSecond = 90.0; var HEAP = new Float32Array(16); var currentRotation = 8; var currentScale = 10; var currentAngle = 0; var shaderProgram = null; var rotationRate = 0; function compileShader(code, type) { let gl = ctx; var shader = gl.createShader(type); gl.shaderSource(shader, code); gl.compileShader(shader); if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { console.log(`Error compiling ${type === gl.VERTEX_SHADER ? "vertex" : "fragment"} shader:`); console.log(gl.getShaderInfoLog(shader)); } return shader; } function animateScene() { let gl = ctx; gl.viewport(0, 0, 320, 528); gl.clearColor(0.8, 0.9, 1.0, 1.0); gl.clear(gl.COLOR_BUFFER_BIT); var radians = currentAngle * Math.PI / 180.0; HEAP[currentRotation] = Math.sin(radians); HEAP[currentRotation + 1] = Math.cos(radians); gl.useProgram(shaderProgram); uScalingFactor = gl.getUniformLocation(shaderProgram, "uScalingFactor"); uGlobalColor = gl.getUniformLocation(shaderProgram, "uGlobalColor"); uRotationVector = gl.getUniformLocation(shaderProgram, "uRotationVector"); gl.uniform2fv(uScalingFactor, HEAP.subarray(currentScale, currentScale + 2)); gl.uniform2fv(uRotationVector, HEAP.subarray(currentRotation, currentRotation + 2)); var rot = gl.getUniform(shaderProgram, uRotationVector); if (rot[0] != HEAP[currentRotation] || rot[1] != HEAP[currentRotation + 1]) console.log("buggy"); else console.log("ok"); gl.uniform4fv(uGlobalColor, [0.1, 0.7, 0.2, 1.0]); gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); aVertexPosition = gl.getAttribLocation(shaderProgram, "aVertexPosition"); gl.enableVertexAttribArray(aVertexPosition); gl.vertexAttribPointer(aVertexPosition, vertexNumComponents, gl.FLOAT, false, 0, 0); gl.drawArrays(gl.TRIANGLES, 0, vertexCount); window.requestAnimationFrame(function (currentTime) { var deltaAngle = ((currentTime - previousTime) / 1000.0) * degreesPerSecond; currentAngle = (currentAngle + deltaAngle) % 360; previousTime = currentTime; animateScene(); }); } /** * 游戏主函数 */ export default class Main { constructor() { // 维护当前requestAnimationFrame的id this.aniId = 0 console.log("start !!!!!") this.startup(); } startup() { let gl = ctx; var shaderSet = [ { type: gl.VERTEX_SHADER, code: "attribute vec2 aVertexPosition;" + "uniform vec2 uScalingFactor;" + "uniform vec2 uRotationVector;" + "void main() {" + "vec2 rotatedPosition = vec2(aVertexPosition.x * uRotationVector.y + aVertexPosition.y * uRotationVector.x," + "aVertexPosition.y * uRotationVector.y - aVertexPosition.x * uRotationVector.x);" + "gl_Position = vec4(rotatedPosition * uScalingFactor, 0.0, 1.0);" + "}" }, { type: gl.FRAGMENT_SHADER, code: "precision highp float;" + "uniform vec4 uGlobalColor;" + "void main() { gl_FragColor = uGlobalColor; }" } ]; shaderProgram = this.buildShaderProgram(shaderSet); aspectRatio = 320 / 528; HEAP[currentRotation] = 0; HEAP[currentRotation + 1] = 1; HEAP[currentScale] = 1; HEAP[currentScale + 1] = aspectRatio; vertexArray = new Float32Array([ -0.5, 0.5, 0.5, 0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, -0.5, -0.5 ]); vertexBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); gl.bufferData(gl.ARRAY_BUFFER, vertexArray, gl.STATIC_DRAW); vertexNumComponents = 2; vertexCount = vertexArray.length / vertexNumComponents; currentAngle = 0.0; rotationRate = 6; animateScene(); } buildShaderProgram(shaderInfo) { let gl = ctx; var program = gl.createProgram(); shaderInfo.forEach(function (desc) { var shader = compileShader(desc.code, desc.type); if (shader) gl.attachShader(program, shader); }); gl.linkProgram(program) if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { console.log("Error linking shader program:"); console.log(gl.getProgramInfoLog(program)); } return program; } // 实现游戏帧循环 }