简体   繁体   English

如何使用WebGL2绘制3个矩形

[英]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条评论。

  1. I don't know what the purpose of gl.createVertexArray and gl.bindVertexArray are. 我不知道gl.createVertexArraygl.bindVertexArray的目的是什么。 This explains it. 解释了它。
  2. Don't know how to structure the vertices in vertexArray . 不知道如何在vertexArray构造顶点。
  3. Don't know how to structure the indices in 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, yx, 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM