Displaying multiple cubes in OpenGL with shaders - opengl

I'm new to OpenGL and shaders. I have a project that involves using shaders to display cubes.
So basically I'm supposed to display eight cubes using a perspective projection at (+-10,+-10,+-10) from the origin each in a different color. In other words, there would be a cube centered at (10, 10, 10), another centered at (10, 10, -10) and so on. There are 8 combinations in (+-10, +-10, +-10). And then I'm supposed to provide a key command 'c' that changes the color of all the cubes each time the key is pressed.
So far I was able to make one cube at the origin. I know I should use this cube and translate it to create the eight cubes but I'm not sure how I would do that. Does anyone know how I would go about with this?

That question is, as mentioned, too broad. But you said that you managed to draw one cube so I can assume that you can set up camera and your window. That leaves us whit how to render 8 cubes. There are many ways to do this, but I'll mention 2 very different ones.
Classic:
You make function that takes 2 parameters - center of cube, and size. Whit these 2 you can build up cube the same way you're doing it now, but instead of fixed values you will use those variables. For example, front face would be:
glBegin(GL_TRIANGLE_STRIP);
glVertex3f(center.x-size/2, center.y-size/2, center.z+size/2);
glVertex3f(center.x+size/2, center.y-size/2, center.z+size/2);
glVertex3f(center.x-size/2, center.y+size/2, center.z+size/2);
glVertex3f(center.x+size/2, center.y+size/2, center.z+size/2);
glEnd();
This is just for showcase how to make it from variables, you can do it the same way you're doing it now.
Now, you mentioned you want to use shaders. Shader topic is very broad, just like openGL itself, but I can tell you the idea. In openGL 3.2 special shaders called geometry were added. Their purpose is to work with geometry as whole - on contrary that vertex shaders works whit just 1 vertex at time or that fragment shaders work just whit one fragment at time - geometry shaders work whit one geometry piece at time. If you're rendering triangles, you get all info about single triangle that is just passing through shaders. This wouldn't be anything serious, but these shaders doesn't only modify these geometries, they can create new ones! So I'm doing in one of my shader programs, where I render points, but when they pass through geometry shader, these points are converted to circles. Similarly you can render just points, but inside geometry shader you can render whole cubes. The point position would work as center for these cubes and you should pass size of cubes in uniform. If size of cubes may vary, you need to make vertex shader also that will pass the size from attribute to variable, which can be read in geometry shader.
As for color problem, if you don't implement fragment shaders, only thing you need to do is call glColor3f before rendering cubes. It takes 3 parameters - red, green and blue values. Note that these values doesn't range from 0 to 255, but from 0 to 1. You can get confused that you cubes aren't rendered if you use white background and think that when you set colors to 200,10,10 you should see red cubes but you don't see anything. That's because in fact you render white cubes. To avoid such errors, I recommend to set background to something like grey whit glClearColor.

Related

Opengl draw cube edges

I'm able to draw a simple cube with modern opengl, but I would like to be able to draw a line cube from the same data I draw my current cube with (vertices):
currently I'm drawing a cube and using glPolygonMode to draw the lines, but I would like to get rid of the lines going though each quad face (essentially just drawing the edges of the cube)
I wasn't able to get any further than this, I don't know how to tackle this topic (shaders, or some other opengl method)
how can I draw a cube in such a way?
Easiest way is to still use glPolygonMOde(...) while rendering QUADS instead of TRIANGLES. This however requires change in your data ...
In case your meshes will be always composed from QUADS and triangulated so the 2 consequent triangles always form a QUAD but you are unwilling to switch to QUADS then you can write a Geometry shader taking in 6 Vertexes and outputting 4 lines which will be still more or less "fast" however note that Geometry shaders where not very reliable in past...
If those are not an option you can modify this:
Silhouette-Outlined shader
To render fragments near sharp normal changes. However this will hide back sides so in order to have them too you have to do this in 2 passes one with glFrontFace(GL_CW); and the other with glFrontFace(GL_CCW); combining their outputs. This also allows you to set different color to the hidden edges ...
So I see it like this:
glFrontFace(GL_CW);
render_mesh_to_trexture(); // using normal instead of color
render_siluete_from_texture(); // using texture from previous line
glFrontFace(GL_CCW);
render_mesh_to_trexture(); // using normal instead of color
render_siluete_from_texture(); // using texture from previous line
However this will be a lot slower and requires consistent winding rule...
Another option is to just compile list of edges from your mesh on CPU side and remove all that have duplicates. Its simple and fast however will create new VBO/VAO data and no longer complies with your requirement to use the same data (however the new VBO might be just integer indices so 2 ints per edge).

How to colour vertices as a grid (like wireframe mode) using shaders?

I've created a plane with six vertices per square that form a terrain.
I colour each vertex using the terrain height value in the pixel shader.
I'm looking for a way to colour pixels between vertexes black, while keeping everything else the same to create a grid effect. The same effect you get from wireframe mode, except for the diagonal line, and the transparent part should be the normal colour.
My terrain, and how it looks in wireframe mode:
How would one go about doing this in pixel shader, or otherwise?
See "Solid Wireframe" - NVIDIA paper from a few years ago.
The idea is basically this: include a geometry shader that generates barycentric coordinates as a varying for each vertex. In your fragment / pixel shader, check the value of the bary components. If they are below a certain threshold, you color the pixel however you'd like your wireframe to be colored. Otherwise, light it as you normally would.
Given a face with vertices A,B,C, you'd generate barycentric values of:
A: 1,0,0
B: 0,1,0
C: 0,0,1
In your fragment shader, see if any component of the bary for that fragment is less than, say, 0.1. If so, it means that it's close to one of the edges of the face. (Which component is below the threshold will also tell you which edge, if you want to get fancy.)
I'll see if I can find a link and update here in a few.
Note that the paper is also ~10 years old. There are ways to get bary coordinates without the geometry shader these days in some situations, and I'm sure there are other workarounds. (Geometry shaders have their place, but are not the greatest friend of performance.)
Also, while geom shaders come with a perf hit, they're significantly faster than a second pass to draw a wireframe. Drawing in wireframe mode in GL (or DX) carries a significant performance penalty because you're asking the rasterizer to simulate Bresenham's line algorithm. That's not how rasterizers work, and it is freaking slow.
This approach also solves any z-fighting issues that you may encounter with two passes.
If your mesh were a single triangle, you could skip the geometry shader and just pack the needed values into a vertex buffer. But, since vertices are shared between faces in any model other than a single triangle, things get a little complicated.
Or, for fun: do this as a post processing step. Look for high ddx()/ddy() (or dFdx()/dFdy(), depending on your API) values in your fragment shader. That also lets you make some interesting effects.
Given that you have a vertex buffer containing all the vertices of your grid, make an index buffer that utilizes the vertex buffer but instead of making groups of 3 for triangles, use pairs of 2 for line segments. This will be a Line List and should contain all the pairs that make up the squares of the grid. You could generate this list automatically in your program.
Rough algorithm for rendering:
Render your terrain as normal
Switch your primitive topology to Line List
Assign the new index buffer
Disable Depth Culling (or add a small height value to each point in the vertex shader so the grid appears above the terrain)
Render the Line List
This should produce the effect you are looking for of the terrain drawn and shaded with a square grid on top of it. You will need to put a switch (via a constant buffer) in your pixel shader that tells it when it is rendering the grid so it can draw the grid black instead of using the height values.

Opengl: coloring a world map?

Here is a task that every GIS application can do: given some polygons, fill each polygon with a chosen color. Like this: image
What is the best way of doing this repeatedly in Opengl? That is, the polygons do not change, and I want to vary the data for coloring to produce difference renderings.
Redrawing polygons for each rendering is the most straightforward solution, but it seems to be a waste, since the geometries do not change at all.
Or is it better to create a stencil for each polygon, and stencil print the entire map? If there are too many polygons, will doing hundreds or thousands of rendering passes create a problem?
For each vertex of a polygon, map a certain color.That means when you send the data to the shaders, with each call the vertex array object sends 2 parameters: a vector which is needed in the vertex shader and a vector which will be used as the fragment color.That is the simplest way.
For example think of a triangle drawn in opengl . if you send its vertices to the vertex shader and set a color in the fragment shader everytime when a vertex enters the shader pipeline it will be positioned accordingly and on the screen set with the given color from the fragment shader.
The technique which I poorly explained ( sry I am not the best at explanations) , is used in the colored triangle example in which colors interpolate.Red maped to a corner , Green maped to another , and Blue to the last. If you set it so the red color maps to every corner you get your colored triangle.That is the basic principle.Oh and you draw the minimum count of triangles and you need one pair of shaders .
Note : a polygon is made out of N triangles and you need to map the same color to every vertex of each triangle drawn in that polygon.
I think a bigger issue will be that OpenGL doesn't support polygons or vector drawing in general, but there are libraries for this. You'll have to use an existing solution for vector drawing, or failing that, you'll have to convert from your GIS data (usually a list of points for a polygon) to triangles. This is likely the biggest obstacle.
The fact that the geometry doesn't change isn't really an issue, you would generally store geometry into one or more buffers, then create logic to only draw what is visible inside your view point area, perhaps even go as far to only generate the geometry for the visible area.
See also this question and it's answers.
Rendering Vector Graphics in OpenGL?

Draw multiple shapes in one vbo

I want to render multiple 3D cubes from one vbo. Each cube has a uniform color.
At this time, I create a vbo where each vertex has a color information.
Is it posible to upload only one color for a one shape (list of verticies)?
I'm also want to mix GL_TRIANGLES and GL_LINES in the glDrawElements-method of the same shader. Is it posible?
//Edit : I only have OpenGL 2.1. Later I want to build this project on Android.
//Edit 2:
I want to render a large count of cubes (up to 150.000). One cube has 24 verticies of geometry and color and 34 indices. Now my idea is to create some vbo's (maybe 50) and share out the cubes to the vbo's. I hope that this minimizes the overhead.
Drawing lots of cubes
Yes, if you want to draw a bunch of cubes, you can specify the color for each cube once.
Create a VBO containing the vertexes for one cube.
// cube = 36 vertexes with glDrawArrays(GL_TRIANGLES)
vbo1 = [v1] [v2] [v3] ... [v36]
Create another VBO with the view matrix and color for each cube, and use an attribute divisor of 1. (You can use the same vbo, but I would use a separate one.)
vbo2 = [cube 1 mat, color] [cube 2 mat, color] ... [cube N mat, color]
Call glDrawElementsInstanced() or glDrawArraysInstanced(). This will draw the cube over and over again.
Alternatively, you can use glUniform() for each cube, but this will limit the number of cubes you can draw. The above method will let you draw thousands, easily.
Mixing GL_TRIANGLES and GL_LINES
You will have to call glDraw????() once for each type of primitive. You can use the same shader for both times, if you like.
Regarding your questions :
Is it possible to upload only one color for one shape ?
Yes , you can use a uniform instead of a vertex attribute(ofc this means changes in more places). However, you will need to set the uniform for each shape, and have a different drawcall for each differently colored shape .
Is it possible to mix GL_TRIANGLES and GL_LINES in the glDrawElements ?
Yes and no. Yes , but you will need a new drawcall (which is obvious). You cannot do on the same drawcall some shapes with GL_TRIANGLES and some shapes with GL_LINES.
In pseudocode this will look like this :
draw shapes 1,2,10 from the vbo using color red and GL_TRIANGLES
draw shapes 3,4,6 from the vbo using color blue and GL_LINES
draw shapes 7,8,9 from the vb using color blue and GL_TRIANGLES
With OpenGL 2.1, I don't think there's a reasonable way of specifying the color only once per cube, and still draw everything in a single draw call.
The most direct approach is that, instead of having the color attribute in a VBO, you specify it directly before the draw call. Assuming that you're using generic vertex attributes, where you would currently have:
glEnableVertexAttribArray(colorLoc);
glVertexAttripPointer(colorLoc, ...);
you do this:
glDisableVertexAttribArray(colorLoc);
glVertexAttrib3f(colorLoc, r, g, b);
where glDisableVertexAttribArray() is only needed if the array was previously enabled for the location.
The big disadvantage is that you can only draw cubes with the same color in one draw call. In the extreme case, that's one draw call per cube. Of course if you have multiple cubes with the same color, you could still batch those into a single draw call.
You wonder whether this is more efficient than having a color for each vertex in the VBO? Impossible to say in general. You'll always get the same answer in cases like this: Try both, and benchmark. I'm skeptical that you will find it beneficial. In my experience, it's fairly rare for fetching vertex data to be a major performance bottleneck. So cutting out one attribute will likely no give you much of a gain. On the other hand, making many small draw calls absolutely can (and often will) hurt performance.
There is one option you can use that is sort of a hybrid. I'm not necessarily recommending it, but just in the interest of brainstorming. If you use a fairly limited number of colors, you can use a single scalar attribute in the VBO that encodes a "color index". Then in the vertex shader, you can use a texture lookup to translate the "color index" to the actual color.
The really good options are beyond OpenGL 2.1. #DietrichEpp nicely explained instanced rendering, which is an elegant solution for cases like this.
And no, you can not have lines and triangles in the same draw call. Even the most flexible draw calls in OpenGL 4.x, like glDrawElementsIndirect(), still take only one primitive type.

What is the best way to specify the colors of different squares while drawing a chess board?

What is the best way to specify the colors of different squares while drawing a chess board?
Suppose I want a 2 by 2 board with colors like this:
*-----*-----*
|black|white|
*-----*-----*
|white|black|
*-----*-----*
I can now have 9 vertices and draw the board with GL_QUADS primitive. As I understand filling a square with some color means specifying a color of each vertex with that color.
But filling every square with a different color means duplicating 5 vertices
*-----**----*
|black|white|
**-----**----**
|white|black|
*-----**----*
Is it the simplest way to do this? And is it actually allowed in OpenGL to have vertices with equal coordinates and different colors?
If you really want to draw a quad for each field, duplicating the vertices is the way to go. There are no problems with different vertices having the same coordinates. The GL's rasterization rules will make sure that there are a) no gaps at such shared edges and b) there is also no overdraw, so you will be fine.
However, you can also draw the whole field as one quad and use texturing. All you would need is a 2x2 sized texture with the black and white colors and can use the GL_NEAREST filtering mode so get a nice and sharp checkerboard pattern.
With that approach, you can also dynamically change the number of fields without changing the texture at all, just by using the GL_REPEAT mode and only changing the texcoords.
In modern shader based GL, you can also procedurally generate the checkerboard pattern directly in the fragment shader.