I have seen a lot of videos on youtube regarding this and I've visited these sites:
Most of these sources are similar but I just can't get the gist of it.
I been working with webgl for 4 months and I've made triangles, rectangles, spheres, cubes and also I've written some cool fragment shaders.
But displaying multiple objects is being a large obstacle for me.
I don't know where to start or how I should change my existing code.
Am I supposed to create more buffers or create more vertex arrays or create more programs ?
How should I get with this?
I'm currently trying to make multiple spheres for a project. The spheres will act as electrons orbiting a nucleus of an atom. Basically I'm trying to make a 3d model of an atom.
I know that libraries like three.js and babylon.js can be of good use here but I really really want to do this without any external libraries.
There's a lot of ways to handle this.
Buffers define geometry, and shader programs define how that geometry makes it to the screen. It's up to you how to put those together to get what you want.
The short version is that when you call a gl.draw*()
function, the bound shader program is executed with what ever buffers and uniforms you told it to use. And you can do that as many times as with different buffers, shaders, or inputs to the shader as you need to to finish that frame.
Let's say you had a cube, a sphere. They are the same color and style (meaning they use the same shader). Let's say that shader takes vertex positions as attribute vec3 aVert
and a color as uniform vec4 uColor
.
You would probably create a buffer for each object with the vertex data for that shape. Then to render:
uColor
uniform on the shader to [1,0,0,1]
(red)aVert
attributegl.drawArrays(gl.TRIANGLES, 0, vertexCount)
aVert
attributegl.drawArrays(gl.TRIANGLES, 0, vertexCount)
In this example, you draw two different buffers with the same shader using two draw calls.
Now let's say you had multiple cubes, that you want to render with different colors (same shader, but different uniforms). Let's say your shader also takes a uniform vec3 aPos
value that positions the center of the cube.
aVert
attributeuColor
uniform on the shader to [1,0,0,1]
(red)uPos
uniform to [0,0,0]
gl.drawArrays(gl.TRIANGLES, 0, vertexCount)
uColor
uniform on the shader to [0,0,1,1]
(blue)uPos
uniform to [10,0,0]
gl.drawArrays(gl.TRIANGLES, 0, vertexCount)
In this example you draw one buffer with one shader as two object with two different draw calls, with different uniform values in that shader for each draw call.
Am I supposed to create more buffers or create more vertex arrays or create more programs?
Yes, or both, as needed. Do you have different geometry to draw? Then you need more buffers. Do you have different ways to render that geometry? Then you need more shaders. Buffers define a blank canvas, and the shader is your paint and paintbrush. Maybe you paint multiple objects with the same brush and the same paint, or maybe you don't. It's up to you.
I'm currently trying to make multiple spheres for a project. The spheres will act as electrons orbiting a nucleus of an atom. Basically I'm trying to make a 3d model of an atom.
A simple version of this one buffer (a sphere) and one shader. The shader would define:
attribute vec3 aVert;
uniform vec4 uColor;
uniform float uRadius; // radius of sphere
uniform float uOrbitRadius; // radius of orbit distance
uniform fload uOrbitAngle; // radians around the orbit
This shader would have a vertex shader that scaled the sphere according to uRadius
, and then moved the sphere into orbit with some trigonometry on uOrbitAngle
and uOrbitRadius
.
And it would have a fragment shader that did shading/lighting/whatever and tinted the result by uColor
.
Then you render a hydrogen atom by:
aVert
attribute in the shaderuColor
to [0.5,0.5,0.5,1]
(gray)uRadius
to 10
uOrbitRadius
to 0
uOrbitAngle
to 0
gl.drawArrays()
uColor
to [1,0,1,1]
(megenta)uRadius
to 1
uOrbitRadius
to 20
uOrbitAngle
to an increasing amount every framegl.drawArrays()
Then you could add more electrons by repeating the electron render, changing only the uOrbitAngle
.
But this really depends on how you want the two objects to look, which will dictate how you structure this.