How do you render primitives as wireframes in OpenGL? - opengl

How do you render primitives as wireframes in OpenGL?

glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
to switch on,
glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
to go back to normal.
Note that things like texture-mapping and lighting will still be applied to the wireframe lines if they're enabled, which can look weird.

From http://cone3d.gamedev.net/cgi-bin/index.pl?page=tutorials/ogladv/tut5
// Turn on wireframe mode
glPolygonMode(GL_FRONT, GL_LINE);
glPolygonMode(GL_BACK, GL_LINE);
// Draw the box
DrawBox();
// Turn off wireframe mode
glPolygonMode(GL_FRONT, GL_FILL);
glPolygonMode(GL_BACK, GL_FILL);

Assuming a forward-compatible context in OpenGL 3 and up, you can either use glPolygonMode as mentioned before, but note that lines with thickness more than 1px are now deprecated. So while you can draw triangles as wire-frame, they need to be very thin. In OpenGL ES, you can use GL_LINES with the same limitation.
In OpenGL it is possible to use geometry shaders to take incoming triangles, disassemble them and send them for rasterization as quads (pairs of triangles really) emulating thick lines. Pretty simple, really, except that geometry shaders are notorious for poor performance scaling.
What you can do instead, and what will also work in OpenGL ES is to employ fragment shader. Think of applying a texture of wire-frame triangle to the triangle. Except that no texture is needed, it can be generated procedurally. But enough talk, let's code. Fragment shader:
in vec3 v_barycentric; // barycentric coordinate inside the triangle
uniform float f_thickness; // thickness of the rendered lines
void main()
{
float f_closest_edge = min(v_barycentric.x,
min(v_barycentric.y, v_barycentric.z)); // see to which edge this pixel is the closest
float f_width = fwidth(f_closest_edge); // calculate derivative (divide f_thickness by this to have the line width constant in screen-space)
float f_alpha = smoothstep(f_thickness, f_thickness + f_width, f_closest_edge); // calculate alpha
gl_FragColor = vec4(vec3(.0), f_alpha);
}
And vertex shader:
in vec4 v_pos; // position of the vertices
in vec3 v_bc; // barycentric coordinate inside the triangle
out vec3 v_barycentric; // barycentric coordinate inside the triangle
uniform mat4 t_mvp; // modeview-projection matrix
void main()
{
gl_Position = t_mvp * v_pos;
v_barycentric = v_bc; // just pass it on
}
Here, the barycentric coordinates are simply (1, 0, 0), (0, 1, 0) and (0, 0, 1) for the three triangle vertices (the order does not really matter, which makes packing into triangle strips potentially easier).
The obvious disadvantage of this approach is that it will eat some texture coordinates and you need to modify your vertex array. Could be solved with a very simple geometry shader but I'd still suspect it will be slower than just feeding the GPU with more data.

In Modern OpenGL(OpenGL 3.2 and higher), you could use a Geometry Shader for this :
#version 330
layout (triangles) in;
layout (line_strip /*for lines, use "points" for points*/, max_vertices=3) out;
in vec2 texcoords_pass[]; //Texcoords from Vertex Shader
in vec3 normals_pass[]; //Normals from Vertex Shader
out vec3 normals; //Normals for Fragment Shader
out vec2 texcoords; //Texcoords for Fragment Shader
void main(void)
{
int i;
for (i = 0; i < gl_in.length(); i++)
{
texcoords=texcoords_pass[i]; //Pass through
normals=normals_pass[i]; //Pass through
gl_Position = gl_in[i].gl_Position; //Pass through
EmitVertex();
}
EndPrimitive();
}
Notices :
for points, change layout (line_strip, max_vertices=3) out; to layout (points, max_vertices=3) out;
Read more about Geometry Shaders

If you are using the fixed pipeline (OpenGL < 3.3) or the compatibility profile you can use
//Turn on wireframe mode
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
//Draw the scene with polygons as lines (wireframe)
renderScene();
//Turn off wireframe mode
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
In this case you can change the line width by calling glLineWidth
Otherwise you need to change the polygon mode inside your draw method (glDrawElements, glDrawArrays, etc) and you may end up with some rough results because your vertex data is for triangles and you are outputting lines. For best results consider using a Geometry shader or creating new data for the wireframe.

The easiest way is to draw the primitives as GL_LINE_STRIP.
glBegin(GL_LINE_STRIP);
/* Draw vertices here */
glEnd();

You can use glut libraries like this:
for a sphere:
glutWireSphere(radius,20,20);
for a Cylinder:
GLUquadric *quadratic = gluNewQuadric();
gluQuadricDrawStyle(quadratic,GLU_LINE);
gluCylinder(quadratic,1,1,1,12,1);
for a Cube:
glutWireCube(1.5);

Use this function:
void glPolygonMode(GLenum face, GLenum mode);
face: Specifies the polygon faces that mode applies to. Can be GL_FRONT for the front side of the polygon, GL_BACK for the back and GL_FRONT_AND_BACK for both.
mode: Three modes are defined.
GL_POINT: Polygon vertices that are marked as the start of a boundary edge are drawn as points.
GL_LINE: Boundary edges of the polygon are drawn as line segments. (your target)
GL_FILL: The interior of the polygon is filled.
P.S: glPolygonMode controls the interpretation of polygons for rasterization in the graphics pipeline.
For more information look at the OpenGL reference pages in khronos group.

If it's OpenGL ES 2.0 you're dealing with, you can choose one of draw mode constants from
GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES, to draw lines,
GL_POINTS (if you need to draw only vertices), or
GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, and GL_TRIANGLES to draw filled triangles
as first argument to your
glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid * indices)
or
glDrawArrays(GLenum mode, GLint first, GLsizei count) calls.

A good and simple way of drawing anti-aliased lines on a non anti-aliased render target is to draw rectangles of 4 pixel width with an 1x4 texture, with alpha channel values of {0.,1.,1.,0.}, and use linear filtering with mip-mapping off. This will make the lines 2 pixels thick, but you can change the texture for different thicknesses.
This is faster and easier than barymetric calculations.

Related

Drawing a cube for each vertex

I have a list of 3D vertices which I can easily render as a pointcloud by passing the whole list to my vertex shader, setting gl_Position = pos, then setting FragColor = vec4(1.0, 1.0, 1.0, 1.0)and use GL_POINTS in the drawing function.
I would now like to render an actual cube at that vertex position, with the vertex being the center of the cube and some given width. How can I achieve this in the most easy and performant way? Looping through all vertices, loading a cube into a buffer and then passing the vertex position to the vertex shader to draw each cube individually does not seem to be feasible to me, or is that the way to go?

OpenGL how to render background

Hi I am doing an assignment and can't figure out how to render a background.
I've drawn the triangles and every thing renders to the screen ok but it always becomes the foreground and blocks everything else from view.
Here is my code for rendering the back ground.
void render(){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(bgShaderID);
glBindVertexArray(bgArrayID);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
// draw everything else
glutSwapBuffers();
glFlush();
}
In my vertex shader I have the following:
in vec3 a_vertex;
in vec3 a_colour;
out vec3 fragmentColor;
void main(){
gl_Position = vec4(a_vertex.xy, 0.0 ,1);
fragmentColor = a_colour;
}
It seems like you have the GL_DEPTH_TEST enabled. I don't know what projection matrix and z values you use for drawing your foreground objects, but
gl_Position = vec4(a_vertex.xy, 0.0 ,1);
is setting clip space z of the background to 0. Assuming a perspecitve projection, this is redicolously close to the front plane. Assuming some prthographic projection, this is still in the middle of the depth range.
You could of course try to set z=1.0 to set it to the far plane in the shader. However, since you draw the background first, you might be better off just disabling the GL_DEPTH_TEST (or disabling depth writes via glDepthMask(GL_FALSE)) temporarily during drawing of your backgorund.

Opengl GLSL render to texture

I'm trying to render to texture with OpenGL + GLSL shaders. For start I'm trying to fill every pixel of 30x30 texture with white color. I'm passing to vertex shader index from 0 to 899, representing each pixel of texture. Is this correct?
Vertex shader:
flat in int index;
void main(void) {
gl_Position = vec4((index % 30) / 15 - 1, floor(index / 30) / 15 - 1, 0, 1);
}
Fragment shader:
out vec4 color;
void main(void) {
color = vec4(1, 1, 1, 1);
}
You are trying to render 900 vertices, with one vertex per pixel? Why are you doing that? What primitive type are you using. It would only make sense if you were using points, but then you would need some slight modification of the output coordinates to actually hit the fragment centers.
The usual way for this is to render just a quad (easily represented as a triangle strip with just 4 vertices) which is filling the whole framebuffer. To achieve this, you just need to setup the viewport to the full frambeuffer and render are quad from (-1,-1) to (1,1).
Note that in both approaches, you don't need vertex attributes. You could just use gl_VertexID (directly as replacement for index in your approach, or as aan index to a const array of 4 vertex coords for the quad).

Drawing round points using modern OpenGL

I know how to draw round points using fixed pipeline. However I need to do the same using modern OpenGL. Is it possible, or should I use point sprites and textures?
For the interested.Here is how it is done with fixed pipeline:
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_NOTEQUAL, 0);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable( GL_POINT_SMOOTH );
glPointSize( 8.0 );
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(myMatrix);
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(myAnotherMatrix);
glBegin(GL_POINTS);
glColor3f(1,1,1);
glVertex3fv(position);
glEnd();
glDisable(GL_POINT_SMOOTH);
glBlendFunc(GL_NONE, GL_NONE);
glDisable(GL_BLEND);
One way would be to draw point sprites with a circle-texture and a self-made alpha test in the fragment shader:
uniform sampler2D circle;
void main()
{
if(texture(circle, gl_PointCoord).r < 0.5)
discard;
...
}
But in fact you don't even need a texture for this, since a circle is a pretty well-defined mathematical concept. So just check the gl_PointCoord only, which says in which part of the [0,1] square representing the whole point your current fragment is:
vec2 coord = gl_PointCoord - vec2(0.5); //from [0,1] to [-0.5,0.5]
if(length(coord) > 0.5) //outside of circle radius?
discard;
Drawing circle with shader.
OpenGL ES shader sphere.

OpenGL issue: cannot render geometry on screen

My program was meant to draw a simple textured cube on screen, however, I cannot get it to render anything other than the clear color. This is my draw function:
void testRender() {
glClearColor(.25f, 0.35f, 0.15f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUniformMatrix4fv(resources.uniforms.m4ModelViewProjection, 1, GL_FALSE, (const GLfloat*)resources.modelviewProjection.modelViewProjection);
glEnableVertexAttribArray(resources.attributes.vTexCoord);
glEnableVertexAttribArray(resources.attributes.vVertex);
//deal with vTexCoord first
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,resources.hiBuffer);
glBindBuffer(GL_ARRAY_BUFFER, resources.htcBuffer);
glVertexAttribPointer(resources.attributes.vTexCoord,2,GL_FLOAT,GL_FALSE,sizeof(GLfloat)*2,(void*)0);
//now the other one
glBindBuffer(GL_ARRAY_BUFFER,resources.hvBuffer);
glVertexAttribPointer(resources.attributes.vVertex,3,GL_FLOAT,GL_FALSE,sizeof(GLfloat)*3,(void*)0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, resources.htextures[0]);
glUniform1i(resources.uniforms.colorMap, 0);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, (void*)0);
//clean up a bit
};
In addition, here is the vertex shader:
#version 330
in vec3 vVertex;
in vec2 vTexCoord;
uniform mat4 m4ModelViewProjection;
smooth out vec2 vVarryingTexCoord;
void main(void) {
vVarryingTexCoord = vTexCoord;
gl_Position = m4ModelViewProjection * vec4(vVertex, 1.0);
};
and the fragment shader (I have given up on textures for now):
#version 330
uniform sampler2D colorMap;
in vec2 vVarryingTexCoord;
out vec4 vVaryingFragColor;
void main(void) {
vVaryingFragColor = texture(colorMap, vVarryingTexCoord);
vVaryingFragColor = vec4(1.0,1.0,1.0,1.0);
};
the vertex array buffer for the position coordinates make a simple cube (with all coordinates a signed 0.25) while the modelview projection is just the inverse camera matrix (moved back by a factor of two) applied to a perspective matrix. However, even without the matrix transformation, I am unable to see anything onscreen. Originally, I had two different buffers that needed two different element index lists, but now both buffers (containing the vertex and texture coordinate data) are the same length and in order. The code itself is derived from the Durian Software Tutorial and the latest OpenGL Superbible. The rest of the code is here.
By this point, I have tried nearly everything I can think of. Is this code even remotely close? If so, why can't I get anything to render onscreen?
You're looking pretty good so far.
The only thing that I see right now is that you've got DEPTH_TEST enabled, but you don't clear the depth buffer. Even if the buffer initialized to a good value, you would be drawing empty scenes on every frame after the first one, because the depth buffer's not being cleared.
If that does not help, can you make sure that you have no glGetError() errors? You may have to clean up your unused texturing attributes/uniforms to get the errors to be clean, but that would be my next step.