我能够手动写出完整的样板文件到WebGL2,并且有这么多工作。
const canvas = document.createElement('canvas')
document.body.appendChild(canvas)
const gl = canvas.getContext('webgl2', { antialias: true })
const width = 800
const height = 500
canvas.width = width
canvas.height = height
const vertexShader = gl.createShader(gl.VERTEX_SHADER)
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER)
gl.shaderSource(vertexShader, `#version 300 es
in vec3 position;
in vec4 color;
out vec4 thecolor;
void
main() {
gl_Position = vec4(position, 1.0);
thecolor = color;
}
`)
gl.shaderSource(fragmentShader, `#version 300 es
precision mediump float;
in vec4 thecolor;
out vec4 color;
void
main() {
color = thecolor;
}
`)
gl.compileShader(vertexShader)
var success = gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)
if (!success) throw new Error(gl.getShaderInfoLog(vertexShader))
gl.compileShader(fragmentShader)
var success = gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)
if (!success) throw new Error(gl.getShaderInfoLog(fragmentShader))
const program = gl.createProgram()
gl.attachShader(program, vertexShader)
gl.attachShader(program, fragmentShader)
gl.linkProgram(program)
gl.useProgram(program)
const positionAttribute = gl.getAttribLocation(program, 'position')
const colorAttribute = gl.getAttribLocation(program, 'color')
gl.viewport(0, 0, width, height)
gl.clearColor(0, 0, 0, 0)
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
// I don't know what the purpose of this is.
const positionVAO = gl.createVertexArray()
gl.bindVertexArray(positionVAO)
const vertexBuffer = gl.createBuffer()
const indexBuffer = gl.createBuffer()
const vertexArray = [
// don't know how to structure this on my own.
]
const indexArray = [
// don't know how to structure this either.
]
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer)
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexArray), gl.DYNAMIC_DRAW)
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer)
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indexArray), gl.STATIC_DRAW)
gl.enableVertexAttribArray(positionAttribute)
gl.vertexAttribPointer(positionAttribute, 2, gl.FLOAT, false, 0, 0)
gl.enableVertexAttribArray(colorAttribute)
gl.vertexAttribPointer(colorAttribute, 4, gl.FLOAT, false, 0, 0)
gl.drawElements(gl.TRIANGLES, indexArray.length, gl.UNSIGNED_SHORT, 0)
但是,有3条评论。
gl.createVertexArray
和gl.bindVertexArray
的目的是什么。
This解释说。vertexArray
中构造顶点。indexArray
中构建指数。我经历了很多教程,但他们通常会忽略顶点/索引的创建和定义。他们并没有真正解释他们是如何设计或构建它们的,或者为什么会这样,所以我还没有真正能够自己重建它。我想使用drawElements
与索引而不是drawArrays
。
想知道是否可以展示如何绘制3个矩形,每个矩形具有不同的颜色(通过vertexArray
传入)。我想象插入vertexArray
中的位置/颜色,但我不知道如何正确地做到这一点,也不知道如何将数据与indexArray
相关联。通过“正确”,我的意思是我不直观地理解什么进入Float32Array
的顶点和Uint32Array
的索引。如果是x, y
,或x, y, r, g, b, a
在这种情况下,或什么。我不明白矩形如何关闭,其“表面”变色。想知道是否可以帮助解释和演示这种不同颜色的3个矩形的绘图。这将有助于巩固如何在WebGL中绘制!
我尝试绘制它们是这样的:
const vertexArray = [
1, 1, 1, 1, 1, 1, // x y r g b a
0, 1, 1, 1, 1, 1,
1, 0, 1, 1, 1, 1,
0, 0, 1, 1, 1, 1
]
const indexArray = [
1,
2,
3,
4
]
但它没有做任何事情。
关键是gl.vertexAttribPointer
的最后2个参数。
第5个参数指定连续通用顶点属性集之间的字节偏移量。在您的情况下,每组属性由6个值(x y r g b a)组成,类型为float。所以字节偏移量是6 * 4 = 24。
第6个参数指定数组中第一个通用顶点属性的第一个组件的字节偏移量(如果绑定了命名数组缓冲区对象)。 顶点坐标的偏移量为0,因为这是前2个值。 颜色属性的偏移量为2 * 4 = 8,因为颜色属性从第3个位置开始。
所以顶点数组的规范必须是:
const vertexArray = [
1, 1, 1, 1, 1, 1, // x y r g b a
0, 1, 1, 1, 1, 1,
1, 0, 1, 1, 1, 1,
0, 0, 1, 1, 1, 1
]
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer)
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexArray), gl.DYNAMIC_DRAW)
gl.enableVertexAttribArray(positionAttribute)
gl.vertexAttribPointer(positionAttribute, 2, gl.FLOAT, false, 6*4, 0)
gl.enableVertexAttribArray(colorAttribute)
gl.vertexAttribPointer(colorAttribute, 4, gl.FLOAT, false, 6*4, 2*4)
你想绘制2个三角形:
2 0
+--------+ 0: (1, 1)
| /| 1: (0, 1)
| / | 2: (1, 0)
| / | 3: (0, 0)
+ -------+
3 1
每个三角形由3个索引组成,因此索引数组必须是:
const indexArray = [ 0, 2, 3, 0, 3, 1 ]
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer)
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indexArray), gl.STATIC_DRAW)
如果你使用primitive类型TRIANGLES
绘制,
gl.drawElements(gl.TRIANGLES, indexArray.length, gl.UNSIGNED_SHORT, 0)
然后这形成了带坐标的2个三角形:
1st : (1, 1) -> (1, 0) -> (0, 0)
2nd : (1, 1) -> (0, 0) -> (0, 1)
当然可以绘制三角形条(TRIANGLE_STRIP
)或三角形扇形(TRIANGLE_FAN
):
const indexArray = [ 2, 0, 3, 1 ]
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer)
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indexArray), gl.STATIC_DRAW)
gl.drawElements(gl.TRIANGLE_STRIP, indexArray.length, gl.UNSIGNED_SHORT, 0)
const indexArray = [ 0, 2, 3, 1 ]
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer)
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indexArray), gl.STATIC_DRAW)
gl.drawElements(gl.TRIANGLE_FAN, indexArray.length, gl.UNSIGNED_SHORT, 0)
var canvas = document.getElementById('my_canvas');
const gl = canvas.getContext('webgl2', { antialias: true })
const width = 800
const height = 500
canvas.width = width
canvas.height = height
const vertexShader = gl.createShader(gl.VERTEX_SHADER)
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER)
gl.shaderSource(vertexShader, `#version 300 es
in vec3 position;
in vec4 color;
out vec4 thecolor;
void
main() {
gl_Position = vec4(position, 1.0);
thecolor = color;
}
`)
gl.shaderSource(fragmentShader, `#version 300 es
precision mediump float;
in vec4 thecolor;
out vec4 color;
void
main() {
color = thecolor;
}
`)
gl.compileShader(vertexShader)
var success = gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)
if (!success) throw new Error(gl.getShaderInfoLog(vertexShader))
gl.compileShader(fragmentShader)
var success = gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)
if (!success) throw new Error(gl.getShaderInfoLog(fragmentShader))
const program = gl.createProgram()
gl.attachShader(program, vertexShader)
gl.attachShader(program, fragmentShader)
gl.linkProgram(program)
gl.useProgram(program)
const positionAttribute = gl.getAttribLocation(program, 'position')
const colorAttribute = gl.getAttribLocation(program, 'color')
gl.viewport(0, 0, width, height)
gl.clearColor(0, 0, 0, 0)
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
// I don't know what the purpose of this is.
const positionVAO = gl.createVertexArray()
gl.bindVertexArray(positionVAO)
const vertexBuffer = gl.createBuffer()
const indexBuffer = gl.createBuffer()
const vertexArray = [
1, 1, 1, 1, 0, 1, // x y r g b a
0, 1, 1, 0, 1, 1,
1, 0, 0, 1, 1, 1,
0, 0, 1, 1, 0, 1
]
const indexArray = [0, 2, 3, 0, 3, 1]
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer)
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexArray), gl.DYNAMIC_DRAW)
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer)
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indexArray), gl.STATIC_DRAW)
gl.enableVertexAttribArray(positionAttribute)
gl.vertexAttribPointer(positionAttribute, 2, gl.FLOAT, false, 6*4, 0)
gl.enableVertexAttribArray(colorAttribute)
gl.vertexAttribPointer(colorAttribute, 4, gl.FLOAT, false, 6*4, 2*4)
gl.drawElements(gl.TRIANGLES, indexArray.length, gl.UNSIGNED_SHORT, 0)
<canvas id="my_canvas"></canvas>