[英]How to draw 3 rectangles with WebGL2
I am able to write out by hand the full boilerplate to WebGL2 pretty much, and have this much working. 我可以手工将完整的样板写到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)
However, there are 3 comments in there. 但是,其中有3条评论。
gl.createVertexArray
and gl.bindVertexArray
are. gl.createVertexArray
和gl.bindVertexArray
的目的是什么。 vertexArray
. vertexArray
构造顶点。 indexArray
. indexArray
构造索引。 I've gone through many tutorials but they usually gloss over the creation and definition of the the vertices/indices. 我已经看过很多教程,但是它们通常掩盖了顶点/索引的创建和定义。 They don't really explain how they designed them or structured them or why it's like that, so I haven't really been able to reconstruct it on my own yet.
他们并没有真正解释他们是如何设计或构造它们的,或者为什么是这样,所以我还不能真正重建它。 I would like to use
drawElements
with the indices instead of drawArrays
. 我想用
drawElements
与指数的,而不是drawArrays
。
Wondering if one could show how to draw 3 rectangles each with a different color (which gets passed in through the vertexArray
). 想知道是否可以显示如何绘制3个矩形,每个矩形具有不同的颜色(通过
vertexArray
传递)。 I was imagining interleaving the positions/colors in the vertexArray
, but I don't know how to do that properly, and also don't know how to associate the data with the indexArray
. 我正在想象将
vertexArray
的位置/颜色交织vertexArray
,但是我不知道如何正确地做到这一点,也不知道如何将数据与indexArray
。 By "properly", I mean I don't understand intuitively yet what goes into the Float32Array
for vertices and the Uint32Array
for indices. 所谓“正确”,我的意思是我不明白直观又怎样进入
Float32Array
为顶点和Uint32Array
的指标。 If it is x, y
, or x, y, r, g, b, a
in this case, or what. 如果是
x, y
或x, y, r, g, b, a
在这种情况下为a)或其他值。 I don't understand how the rectangle closes and its "surface" gets colored. 我不了解矩形是如何闭合的,其“表面”是彩色的。 Wondering if one could help explain and demonstrate this drawing of 3 rectangles of different colors.
想知道是否可以帮助解释和演示这张由3种不同颜色的矩形组成的图。 That would help solidify how to draw in WebGL!
这将有助于巩固如何绘制WebGL!
My attempt at drawing them is this: 我尝试绘制它们的方法是:
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
]
But it doesn't do anything. 但是它什么也没做。
The key to this is the are the last 2 parameters of gl.vertexAttribPointer
. 关键是
gl.vertexAttribPointer
的最后两个参数。
The 5th parameter specifies the byte offset between the sets of consecutive generic vertex attributes. 第5个参数指定连续的通用顶点属性集之间的字节偏移。 In your case each set of attributes consists of 6 values (xyrgba) with type float .
在您的情况下,每组属性都由6个类型为float的值(xyrgba)组成。 So the byte offset is 6*4 = 24.
因此字节偏移为6 * 4 = 24。
The 6th parameter specifies the byte offset of the first component of the first generic vertex attribute in the array (In case when a named array buffer object is bound). 第6个参数指定数组中第一个通用顶点属性的第一个组件的字节偏移量(如果绑定了命名数组缓冲区对象)。
The offset for the vertex coordinates is 0, since this are the first 2 values. 顶点坐标的偏移为0,因为这是前2个值。
The offset for the color attribute is 2*4 = 8, since the color attribute starts at the 3rd position. 颜色属性的偏移量为2 * 4 = 8,因为颜色属性从第3个位置开始。
So the specification of the vertex array has to be: 因此,顶点数组的规范必须为:
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)
You want to draw 2 triangles: 您要绘制2个三角形:
2 0
+--------+ 0: (1, 1)
| /| 1: (0, 1)
| / | 2: (1, 0)
| / | 3: (0, 0)
+ -------+
3 1
each triangle consists of 3 indices, so the array of indices has to be: 每个三角形由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)
If you draw this using the primitive type TRIANGLES
, 如果使用基本类型
TRIANGLES
绘制此TRIANGLES
,
gl.drawElements(gl.TRIANGLES, indexArray.length, gl.UNSIGNED_SHORT, 0)
then this forms the 2 triangles with the coordinates: 那么这将形成两个具有坐标的三角形:
1st : (1, 1) -> (1, 0) -> (0, 0)
2nd : (1, 1) -> (0, 0) -> (0, 1)
Of course it is possible to draw a triangles strip ( TRIANGLE_STRIP
) or triangle fan ( TRIANGLE_FAN
) instead: 当然,可以绘制三角形带(
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, // xyrgba 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>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.