在 WebGL2 中使用 mat4 属性
Using mat4 attribute in WebGL2
我正在尝试将 4x4 矩阵作为属性传递给 WebGL2 顶点着色器。在密切关注 之后,我一直在思考为什么我无法成功渲染并在我的控制台中收到 glDrawArrays: attempt to access out of range vertices in attribute 0
错误。
据我了解,mat4 在 WebGL 中表示为 4 乘以 vec4。当我在 GPU 上查询 a_modelMatrix
位置时,我可以看到它占据了从 0 到 3 的位置,所以这看起来没问题。我将作业分成 4 个部分,如下所示:
for (let i = 0; i < 4; ++i) {
gl.enableVertexAttribArray(a_modelMatrix + i)
gl.vertexAttribPointer(a_modelMatrix + i, 4, gl.FLOAT, false, 64, i * 16)
}
但是还是报错
这是我的代码:
console.clear()
const canvas = document.createElement('canvas')
const gl = canvas.getContext('webgl')
document.body.appendChild(canvas)
canvas.width = 500
canvas.height = 500
gl.viewport(0, 0, 500, 500)
const vertexShaderSrc = `
attribute mat4 a_modelMatrix;
attribute vec4 a_pos;
void main () {
gl_Position = a_modelMatrix * a_pos;
}
`
const fragmentShaderSrc = `
precision highp float;
void main () {
gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
}
`
const vShader = makeShader(gl.VERTEX_SHADER, vertexShaderSrc)
const fShader = makeShader(gl.FRAGMENT_SHADER, fragmentShaderSrc)
const program = makeProgram(vShader, fShader)
gl.useProgram(program)
const modelMatrix = mat4.create()
const scale = vec3.create()
vec3.set(scale, 2, 2, 2)
mat4.scale(modelMatrix, modelMatrix, scale)
const a_pos = gl.getAttribLocation(program, 'a_pos')
const a_modelMatrix = gl.getAttribLocation(program, 'a_modelMatrix')
const posBuffer = gl.createBuffer()
const modelMatrixBuffer = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, posBuffer)
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ -0.1, 0.1, 0.1, 0.1, 0.0, 0.0 ]), gl.STATIC_DRAW)
gl.vertexAttribPointer(a_pos, 2, gl.FLOAT, false, 0, 0)
gl.enableVertexAttribArray(a_pos)
gl.bindBuffer(gl.ARRAY_BUFFER, modelMatrixBuffer)
gl.bufferData(gl.ARRAY_BUFFER, modelMatrix, gl.STATIC_DRAW)
for (let i = 0; i < 4; ++i) {
gl.enableVertexAttribArray(a_modelMatrix + i)
gl.vertexAttribPointer(a_modelMatrix + i, 4, gl.FLOAT, false, 64, i * 16)
}
gl.drawArrays(gl.LINE_LOOP, 0, 3)
function makeShader (type, src) {
const shader = gl.createShader(type)
gl.shaderSource(shader, src)
gl.compileShader(shader)
if (gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
return shader
}
console.log(gl.getShaderInfoLog(shader))
}
function makeProgram (vShader, fShader) {
const program = gl.createProgram()
gl.attachShader(program, vShader)
gl.attachShader(program, fShader)
gl.linkProgram(program)
if (gl.getProgramParameter(program, gl.LINK_STATUS)) {
return program
}
console.log(gl.getProgramInfoLog(shader))
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.8.1/gl-matrix-min.js"></script>
您必须为每个顶点坐标指定 1 个属性。顶点不能共享 1 个矩阵属性。每个顶点坐标必须有自己的模型矩阵属性:
at_array = new Float32Array(16*no_of_vertices)
for (let i = 0; i < no_of_vertices; i ++)
mat_array.set(modelMatrix, 16*i)
gl.bufferData(gl.ARRAY_BUFFER, mat_array, gl.STATIC_DRAW)
console.clear()
const canvas = document.createElement('canvas')
const gl = canvas.getContext('webgl')
document.body.appendChild(canvas)
canvas.width = 300
canvas.height = 300
gl.viewport(0, 0, 300, 300)
const vertexShaderSrc = `
attribute mat4 a_modelMatrix;
attribute vec4 a_pos;
void main () {
gl_Position = a_modelMatrix * a_pos;
}
`
const fragmentShaderSrc = `
precision highp float;
void main () {
gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
}
`
const vShader = makeShader(gl.VERTEX_SHADER, vertexShaderSrc)
const fShader = makeShader(gl.FRAGMENT_SHADER, fragmentShaderSrc)
const program = makeProgram(vShader, fShader)
gl.useProgram(program)
const modelMatrix = mat4.create()
const scale = vec3.create()
vec3.set(scale, 2, 2, 2)
mat4.scale(modelMatrix, modelMatrix, scale)
const a_pos = gl.getAttribLocation(program, 'a_pos')
const a_modelMatrix = gl.getAttribLocation(program, 'a_modelMatrix')
const posBuffer = gl.createBuffer()
const modelMatrixBuffer = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, posBuffer)
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ -0.3, 0.3, 0.3, 0.3, 0.0, 0.0 ]), gl.STATIC_DRAW)
gl.vertexAttribPointer(a_pos, 2, gl.FLOAT, false, 0, 0)
gl.enableVertexAttribArray(a_pos)
gl.bindBuffer(gl.ARRAY_BUFFER, modelMatrixBuffer)
let mat_array = new Float32Array(16*3)
for (let i = 0; i < 3; i ++) mat_array.set(modelMatrix, 16*i)
gl.bufferData(gl.ARRAY_BUFFER, mat_array, gl.STATIC_DRAW)
for (let i = 0; i < 4; ++i) {
gl.enableVertexAttribArray(a_modelMatrix + i)
gl.vertexAttribPointer(a_modelMatrix + i, 4, gl.FLOAT, false, 64, i * 16)
}
gl.drawArrays(gl.LINE_LOOP, 0, 3)
function makeShader (type, src) {
const shader = gl.createShader(type)
gl.shaderSource(shader, src)
gl.compileShader(shader)
if (gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
return shader
}
console.log(gl.getShaderInfoLog(shader))
}
function makeProgram (vShader, fShader) {
const program = gl.createProgram()
gl.attachShader(program, vShader)
gl.attachShader(program, fShader)
gl.linkProgram(program)
if (gl.getProgramParameter(program, gl.LINK_STATUS)) {
return program
}
console.log(gl.getProgramInfoLog(shader))
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.8.1/gl-matrix-min.js"></script>
如果使用 WebGL 1.0, I recommend to use a Uniform 变量而不是矩阵属性。一个uniform是全局Shader变量:
attribute vec4 a_pos;
uniform mat4 u_modelMatrix;
void main () {
gl_Position = u_modelMatrix * a_pos;
}
const u_modelMatrix = gl.getUniformLocation(program, 'u_modelMatrix')
// [...]
gl.uniformMatrix4fv(u_modelMatrix, false, modelMatrix)
console.clear()
const canvas = document.createElement('canvas')
const gl = canvas.getContext('webgl')
document.body.appendChild(canvas)
canvas.width = 300
canvas.height = 300
gl.viewport(0, 0, 300, 300)
const vertexShaderSrc = `
attribute vec4 a_pos;
uniform mat4 u_modelMatrix;
void main () {
gl_Position = u_modelMatrix * a_pos;
}
`
const fragmentShaderSrc = `
precision highp float;
void main () {
gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
}
`
const vShader = makeShader(gl.VERTEX_SHADER, vertexShaderSrc)
const fShader = makeShader(gl.FRAGMENT_SHADER, fragmentShaderSrc)
const program = makeProgram(vShader, fShader)
gl.useProgram(program)
const modelMatrix = mat4.create()
const scale = vec3.create()
vec3.set(scale, 2, 2, 2)
mat4.scale(modelMatrix, modelMatrix, scale)
const a_pos = gl.getAttribLocation(program, 'a_pos')
const u_modelMatrix = gl.getUniformLocation(program, 'u_modelMatrix')
const posBuffer = gl.createBuffer()
const modelMatrixBuffer = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, posBuffer)
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ -0.3, 0.3, 0.3, 0.3, 0.0, 0.0 ]), gl.STATIC_DRAW)
gl.vertexAttribPointer(a_pos, 2, gl.FLOAT, false, 0, 0)
gl.enableVertexAttribArray(a_pos)
gl.uniformMatrix4fv(u_modelMatrix, false, modelMatrix)
gl.drawArrays(gl.LINE_LOOP, 0, 3)
function makeShader (type, src) {
const shader = gl.createShader(type)
gl.shaderSource(shader, src)
gl.compileShader(shader)
if (gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
return shader
}
console.log(gl.getShaderInfoLog(shader))
}
function makeProgram (vShader, fShader) {
const program = gl.createProgram()
gl.attachShader(program, vShader)
gl.attachShader(program, fShader)
gl.linkProgram(program)
if (gl.getProgramParameter(program, gl.LINK_STATUS)) {
return program
}
console.log(gl.getProgramInfoLog(shader))
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.8.1/gl-matrix-min.js"></script>
但是,如果您创建 WebGL 2.0 上下文:
const gl = canvas.getContext('webgl')
const gl = canvas.getContext('webgl2')
和一个顶点数组对象:
const vao = gl.createVertexArray();
gl.bindVertexArray(vao);
您可以使用 Instancing。 matix属性是一个实例属性:
gl.bindBuffer(gl.ARRAY_BUFFER, modelMatrixBuffer)
gl.bufferData(gl.ARRAY_BUFFER, modelMatrix, gl.STATIC_DRAW)
for (let i = 0; i < 4; ++i) {
gl.enableVertexAttribArray(a_modelMatrix + i)
gl.vertexAttribPointer(a_modelMatrix + i, 4, gl.FLOAT, false, 64, i * 16)
gl.vertexAttribDivisor(a_modelMatrix + i, 1)
}
gl.drawArrays(gl.LINE_LOOP, 0, 3)
gl.drawArraysInstanced(gl.LINE_LOOP, 0, 3, 1)
console.clear()
const canvas = document.createElement('canvas')
const gl = canvas.getContext('webgl2')
document.body.appendChild(canvas)
canvas.width = 300
canvas.height = 300
gl.viewport(0, 0, 300, 300)
const vertexShaderSrc = `
attribute mat4 a_modelMatrix;
attribute vec4 a_pos;
void main () {
gl_Position = a_modelMatrix * a_pos;
}
`
const fragmentShaderSrc = `
precision highp float;
void main () {
gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
}
`
const vShader = makeShader(gl.VERTEX_SHADER, vertexShaderSrc)
const fShader = makeShader(gl.FRAGMENT_SHADER, fragmentShaderSrc)
const program = makeProgram(vShader, fShader)
gl.useProgram(program)
const modelMatrix = mat4.create()
const scale = vec3.create()
vec3.set(scale, 2, 2, 2)
mat4.scale(modelMatrix, modelMatrix, scale)
const vao = gl.createVertexArray();
gl.bindVertexArray(vao);
const a_pos = gl.getAttribLocation(program, 'a_pos')
const a_modelMatrix = gl.getAttribLocation(program, 'a_modelMatrix')
const posBuffer = gl.createBuffer()
const modelMatrixBuffer = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, posBuffer)
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ -0.3, 0.3, 0.3, 0.3, 0.0, 0.0 ]), gl.STATIC_DRAW)
gl.vertexAttribPointer(a_pos, 2, gl.FLOAT, false, 0, 0)
gl.enableVertexAttribArray(a_pos)
gl.bindBuffer(gl.ARRAY_BUFFER, modelMatrixBuffer)
gl.bufferData(gl.ARRAY_BUFFER, modelMatrix, gl.STATIC_DRAW)
for (let i = 0; i < 4; ++i) {
gl.enableVertexAttribArray(a_modelMatrix + i)
gl.vertexAttribPointer(a_modelMatrix + i, 4, gl.FLOAT, false, 64, i * 16)
gl.vertexAttribDivisor(a_modelMatrix + i, 1)
}
//gl.drawArrays(gl.LINE_LOOP, 0, 3)
gl.drawArraysInstanced(gl.LINE_LOOP, 0, 3, 1)
function makeShader (type, src) {
const shader = gl.createShader(type)
gl.shaderSource(shader, src)
gl.compileShader(shader)
if (gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
return shader
}
console.log(gl.getShaderInfoLog(shader))
}
function makeProgram (vShader, fShader) {
const program = gl.createProgram()
gl.attachShader(program, vShader)
gl.attachShader(program, fShader)
gl.linkProgram(program)
if (gl.getProgramParameter(program, gl.LINK_STATUS)) {
return program
}
console.log(gl.getProgramInfoLog(shader))
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.8.1/gl-matrix-min.js"></script>
我正在尝试将 4x4 矩阵作为属性传递给 WebGL2 顶点着色器。在密切关注 glDrawArrays: attempt to access out of range vertices in attribute 0
错误。
据我了解,mat4 在 WebGL 中表示为 4 乘以 vec4。当我在 GPU 上查询 a_modelMatrix
位置时,我可以看到它占据了从 0 到 3 的位置,所以这看起来没问题。我将作业分成 4 个部分,如下所示:
for (let i = 0; i < 4; ++i) {
gl.enableVertexAttribArray(a_modelMatrix + i)
gl.vertexAttribPointer(a_modelMatrix + i, 4, gl.FLOAT, false, 64, i * 16)
}
但是还是报错
这是我的代码:
console.clear()
const canvas = document.createElement('canvas')
const gl = canvas.getContext('webgl')
document.body.appendChild(canvas)
canvas.width = 500
canvas.height = 500
gl.viewport(0, 0, 500, 500)
const vertexShaderSrc = `
attribute mat4 a_modelMatrix;
attribute vec4 a_pos;
void main () {
gl_Position = a_modelMatrix * a_pos;
}
`
const fragmentShaderSrc = `
precision highp float;
void main () {
gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
}
`
const vShader = makeShader(gl.VERTEX_SHADER, vertexShaderSrc)
const fShader = makeShader(gl.FRAGMENT_SHADER, fragmentShaderSrc)
const program = makeProgram(vShader, fShader)
gl.useProgram(program)
const modelMatrix = mat4.create()
const scale = vec3.create()
vec3.set(scale, 2, 2, 2)
mat4.scale(modelMatrix, modelMatrix, scale)
const a_pos = gl.getAttribLocation(program, 'a_pos')
const a_modelMatrix = gl.getAttribLocation(program, 'a_modelMatrix')
const posBuffer = gl.createBuffer()
const modelMatrixBuffer = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, posBuffer)
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ -0.1, 0.1, 0.1, 0.1, 0.0, 0.0 ]), gl.STATIC_DRAW)
gl.vertexAttribPointer(a_pos, 2, gl.FLOAT, false, 0, 0)
gl.enableVertexAttribArray(a_pos)
gl.bindBuffer(gl.ARRAY_BUFFER, modelMatrixBuffer)
gl.bufferData(gl.ARRAY_BUFFER, modelMatrix, gl.STATIC_DRAW)
for (let i = 0; i < 4; ++i) {
gl.enableVertexAttribArray(a_modelMatrix + i)
gl.vertexAttribPointer(a_modelMatrix + i, 4, gl.FLOAT, false, 64, i * 16)
}
gl.drawArrays(gl.LINE_LOOP, 0, 3)
function makeShader (type, src) {
const shader = gl.createShader(type)
gl.shaderSource(shader, src)
gl.compileShader(shader)
if (gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
return shader
}
console.log(gl.getShaderInfoLog(shader))
}
function makeProgram (vShader, fShader) {
const program = gl.createProgram()
gl.attachShader(program, vShader)
gl.attachShader(program, fShader)
gl.linkProgram(program)
if (gl.getProgramParameter(program, gl.LINK_STATUS)) {
return program
}
console.log(gl.getProgramInfoLog(shader))
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.8.1/gl-matrix-min.js"></script>
您必须为每个顶点坐标指定 1 个属性。顶点不能共享 1 个矩阵属性。每个顶点坐标必须有自己的模型矩阵属性:
at_array = new Float32Array(16*no_of_vertices)
for (let i = 0; i < no_of_vertices; i ++)
mat_array.set(modelMatrix, 16*i)
gl.bufferData(gl.ARRAY_BUFFER, mat_array, gl.STATIC_DRAW)
console.clear()
const canvas = document.createElement('canvas')
const gl = canvas.getContext('webgl')
document.body.appendChild(canvas)
canvas.width = 300
canvas.height = 300
gl.viewport(0, 0, 300, 300)
const vertexShaderSrc = `
attribute mat4 a_modelMatrix;
attribute vec4 a_pos;
void main () {
gl_Position = a_modelMatrix * a_pos;
}
`
const fragmentShaderSrc = `
precision highp float;
void main () {
gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
}
`
const vShader = makeShader(gl.VERTEX_SHADER, vertexShaderSrc)
const fShader = makeShader(gl.FRAGMENT_SHADER, fragmentShaderSrc)
const program = makeProgram(vShader, fShader)
gl.useProgram(program)
const modelMatrix = mat4.create()
const scale = vec3.create()
vec3.set(scale, 2, 2, 2)
mat4.scale(modelMatrix, modelMatrix, scale)
const a_pos = gl.getAttribLocation(program, 'a_pos')
const a_modelMatrix = gl.getAttribLocation(program, 'a_modelMatrix')
const posBuffer = gl.createBuffer()
const modelMatrixBuffer = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, posBuffer)
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ -0.3, 0.3, 0.3, 0.3, 0.0, 0.0 ]), gl.STATIC_DRAW)
gl.vertexAttribPointer(a_pos, 2, gl.FLOAT, false, 0, 0)
gl.enableVertexAttribArray(a_pos)
gl.bindBuffer(gl.ARRAY_BUFFER, modelMatrixBuffer)
let mat_array = new Float32Array(16*3)
for (let i = 0; i < 3; i ++) mat_array.set(modelMatrix, 16*i)
gl.bufferData(gl.ARRAY_BUFFER, mat_array, gl.STATIC_DRAW)
for (let i = 0; i < 4; ++i) {
gl.enableVertexAttribArray(a_modelMatrix + i)
gl.vertexAttribPointer(a_modelMatrix + i, 4, gl.FLOAT, false, 64, i * 16)
}
gl.drawArrays(gl.LINE_LOOP, 0, 3)
function makeShader (type, src) {
const shader = gl.createShader(type)
gl.shaderSource(shader, src)
gl.compileShader(shader)
if (gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
return shader
}
console.log(gl.getShaderInfoLog(shader))
}
function makeProgram (vShader, fShader) {
const program = gl.createProgram()
gl.attachShader(program, vShader)
gl.attachShader(program, fShader)
gl.linkProgram(program)
if (gl.getProgramParameter(program, gl.LINK_STATUS)) {
return program
}
console.log(gl.getProgramInfoLog(shader))
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.8.1/gl-matrix-min.js"></script>
如果使用 WebGL 1.0, I recommend to use a Uniform 变量而不是矩阵属性。一个uniform是全局Shader变量:
attribute vec4 a_pos;
uniform mat4 u_modelMatrix;
void main () {
gl_Position = u_modelMatrix * a_pos;
}
const u_modelMatrix = gl.getUniformLocation(program, 'u_modelMatrix')
// [...]
gl.uniformMatrix4fv(u_modelMatrix, false, modelMatrix)
console.clear()
const canvas = document.createElement('canvas')
const gl = canvas.getContext('webgl')
document.body.appendChild(canvas)
canvas.width = 300
canvas.height = 300
gl.viewport(0, 0, 300, 300)
const vertexShaderSrc = `
attribute vec4 a_pos;
uniform mat4 u_modelMatrix;
void main () {
gl_Position = u_modelMatrix * a_pos;
}
`
const fragmentShaderSrc = `
precision highp float;
void main () {
gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
}
`
const vShader = makeShader(gl.VERTEX_SHADER, vertexShaderSrc)
const fShader = makeShader(gl.FRAGMENT_SHADER, fragmentShaderSrc)
const program = makeProgram(vShader, fShader)
gl.useProgram(program)
const modelMatrix = mat4.create()
const scale = vec3.create()
vec3.set(scale, 2, 2, 2)
mat4.scale(modelMatrix, modelMatrix, scale)
const a_pos = gl.getAttribLocation(program, 'a_pos')
const u_modelMatrix = gl.getUniformLocation(program, 'u_modelMatrix')
const posBuffer = gl.createBuffer()
const modelMatrixBuffer = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, posBuffer)
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ -0.3, 0.3, 0.3, 0.3, 0.0, 0.0 ]), gl.STATIC_DRAW)
gl.vertexAttribPointer(a_pos, 2, gl.FLOAT, false, 0, 0)
gl.enableVertexAttribArray(a_pos)
gl.uniformMatrix4fv(u_modelMatrix, false, modelMatrix)
gl.drawArrays(gl.LINE_LOOP, 0, 3)
function makeShader (type, src) {
const shader = gl.createShader(type)
gl.shaderSource(shader, src)
gl.compileShader(shader)
if (gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
return shader
}
console.log(gl.getShaderInfoLog(shader))
}
function makeProgram (vShader, fShader) {
const program = gl.createProgram()
gl.attachShader(program, vShader)
gl.attachShader(program, fShader)
gl.linkProgram(program)
if (gl.getProgramParameter(program, gl.LINK_STATUS)) {
return program
}
console.log(gl.getProgramInfoLog(shader))
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.8.1/gl-matrix-min.js"></script>
但是,如果您创建 WebGL 2.0 上下文:
const gl = canvas.getContext('webgl')
const gl = canvas.getContext('webgl2')
和一个顶点数组对象:
const vao = gl.createVertexArray();
gl.bindVertexArray(vao);
您可以使用 Instancing。 matix属性是一个实例属性:
gl.bindBuffer(gl.ARRAY_BUFFER, modelMatrixBuffer)
gl.bufferData(gl.ARRAY_BUFFER, modelMatrix, gl.STATIC_DRAW)
for (let i = 0; i < 4; ++i) {
gl.enableVertexAttribArray(a_modelMatrix + i)
gl.vertexAttribPointer(a_modelMatrix + i, 4, gl.FLOAT, false, 64, i * 16)
gl.vertexAttribDivisor(a_modelMatrix + i, 1)
}
gl.drawArrays(gl.LINE_LOOP, 0, 3)
gl.drawArraysInstanced(gl.LINE_LOOP, 0, 3, 1)
console.clear()
const canvas = document.createElement('canvas')
const gl = canvas.getContext('webgl2')
document.body.appendChild(canvas)
canvas.width = 300
canvas.height = 300
gl.viewport(0, 0, 300, 300)
const vertexShaderSrc = `
attribute mat4 a_modelMatrix;
attribute vec4 a_pos;
void main () {
gl_Position = a_modelMatrix * a_pos;
}
`
const fragmentShaderSrc = `
precision highp float;
void main () {
gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
}
`
const vShader = makeShader(gl.VERTEX_SHADER, vertexShaderSrc)
const fShader = makeShader(gl.FRAGMENT_SHADER, fragmentShaderSrc)
const program = makeProgram(vShader, fShader)
gl.useProgram(program)
const modelMatrix = mat4.create()
const scale = vec3.create()
vec3.set(scale, 2, 2, 2)
mat4.scale(modelMatrix, modelMatrix, scale)
const vao = gl.createVertexArray();
gl.bindVertexArray(vao);
const a_pos = gl.getAttribLocation(program, 'a_pos')
const a_modelMatrix = gl.getAttribLocation(program, 'a_modelMatrix')
const posBuffer = gl.createBuffer()
const modelMatrixBuffer = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, posBuffer)
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ -0.3, 0.3, 0.3, 0.3, 0.0, 0.0 ]), gl.STATIC_DRAW)
gl.vertexAttribPointer(a_pos, 2, gl.FLOAT, false, 0, 0)
gl.enableVertexAttribArray(a_pos)
gl.bindBuffer(gl.ARRAY_BUFFER, modelMatrixBuffer)
gl.bufferData(gl.ARRAY_BUFFER, modelMatrix, gl.STATIC_DRAW)
for (let i = 0; i < 4; ++i) {
gl.enableVertexAttribArray(a_modelMatrix + i)
gl.vertexAttribPointer(a_modelMatrix + i, 4, gl.FLOAT, false, 64, i * 16)
gl.vertexAttribDivisor(a_modelMatrix + i, 1)
}
//gl.drawArrays(gl.LINE_LOOP, 0, 3)
gl.drawArraysInstanced(gl.LINE_LOOP, 0, 3, 1)
function makeShader (type, src) {
const shader = gl.createShader(type)
gl.shaderSource(shader, src)
gl.compileShader(shader)
if (gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
return shader
}
console.log(gl.getShaderInfoLog(shader))
}
function makeProgram (vShader, fShader) {
const program = gl.createProgram()
gl.attachShader(program, vShader)
gl.attachShader(program, fShader)
gl.linkProgram(program)
if (gl.getProgramParameter(program, gl.LINK_STATUS)) {
return program
}
console.log(gl.getProgramInfoLog(shader))
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.8.1/gl-matrix-min.js"></script>