orthographic scaling opengl viewport - c

I found this code sample that does what I would like to do with modern opengl.
I am trying to figure out how to do this with my code but I am having a really difficult time.
/*
* GL03Viewport.cpp: Clipping-area and Viewport
* Implementing reshape to ensure same aspect ratio between the
* clipping-area and the viewport.
*/
#include <GL/glut.h> // GLUT, include glu.h and gl.h
/* Initialize OpenGL Graphics */
void initGL() {
// Set "clearing" or background color
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Black and opaque
}
void display() {
glClear(GL_COLOR_BUFFER_BIT); // Clear the color buffer with current clearing color
// Define shapes enclosed within a pair of glBegin and glEnd
glBegin(GL_QUADS); // Each set of 4 vertices form a quad
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex2f(-0.8f, 0.1f); // Define vertices in counter-clockwise (CCW) order
glVertex2f(-0.2f, 0.1f); // so that the normal (front-face) is facing you
glVertex2f(-0.2f, 0.7f);
glVertex2f(-0.8f, 0.7f);
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex2f(-0.7f, -0.6f);
glVertex2f(-0.1f, -0.6f);
glVertex2f(-0.1f, 0.0f);
glVertex2f(-0.7f, 0.0f);
glColor3f(0.2f, 0.2f, 0.2f); // Dark Gray
glVertex2f(-0.9f, -0.7f);
glColor3f(1.0f, 1.0f, 1.0f); // White
glVertex2f(-0.5f, -0.7f);
glColor3f(0.2f, 0.2f, 0.2f); // Dark Gray
glVertex2f(-0.5f, -0.3f);
glColor3f(1.0f, 1.0f, 1.0f); // White
glVertex2f(-0.9f, -0.3f);
glEnd();
glBegin(GL_TRIANGLES); // Each set of 3 vertices form a triangle
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex2f(0.1f, -0.6f);
glVertex2f(0.7f, -0.6f);
glVertex2f(0.4f, -0.1f);
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex2f(0.3f, -0.4f);
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex2f(0.9f, -0.4f);
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex2f(0.6f, -0.9f);
glEnd();
glBegin(GL_POLYGON); // These vertices form a closed polygon
glColor3f(1.0f, 1.0f, 0.0f); // Yellow
glVertex2f(0.4f, 0.2f);
glVertex2f(0.6f, 0.2f);
glVertex2f(0.7f, 0.4f);
glVertex2f(0.6f, 0.6f);
glVertex2f(0.4f, 0.6f);
glVertex2f(0.3f, 0.4f);
glEnd();
glFlush(); // Render now
}
/* Handler for window re-size event. Called back when the window first appears and
whenever the window is re-sized with its new width and height */
void reshape(GLsizei width, GLsizei height) { // GLsizei for non-negative integer
// Compute aspect ratio of the new window
if (height == 0) height = 1; // To prevent divide by 0
GLfloat aspect = (GLfloat)width / (GLfloat)height;
// Set the viewport to cover the new window
glViewport(0, 0, width, height);
// Set the aspect ratio of the clipping area to match the viewport
glMatrixMode(GL_PROJECTION); // To operate on the Projection matrix
glLoadIdentity(); // Reset the projection matrix
if (width >= height) {
// aspect >= 1, set the height from -1 to 1, with larger width
gluOrtho2D(-1.0 * aspect, 1.0 * aspect, -1.0, 1.0);
} else {
// aspect < 1, set the width to -1 to 1, with larger height
gluOrtho2D(-1.0, 1.0, -1.0 / aspect, 1.0 / aspect);
}
}
/* Main function: GLUT runs as a console application starting at main() */
int main(int argc, char** argv) {
glutInit(&argc, argv); // Initialize GLUT
//glutInitWindowSize(640, 480); // Set the window's initial width & height - non-square
glutInitWindowSize(1024, 720); // Set the window's initial width & height - non-square
glutInitWindowPosition(50, 50); // Position the window's initial top-left corner
glutCreateWindow("Viewport Transform"); // Create window with the given title
glutDisplayFunc(display); // Register callback handler for window re-paint event
glutReshapeFunc(reshape); // Register callback handler for window re-size event
initGL(); // Our own OpenGL initialization
glutMainLoop(); // Enter the infinite event-processing loop
return 0;
}
There are a few chances that I made to my code for two reasons.
1) I'd like to have 0,0 be the lower left corner and width, height be the upper right hand corner.
2) The second and more confusing part is how do I maintain my pixel coordinates. The example code uses points in the range of -1.0 to 1.0 but I would like to be able to say my quad is 50px by 50px.
currently I create my viewport and projections like this.
point3 eye, center;
vec3 up;
vmathP3MakeFromElems(&eye, 0, 0, 0);
vmathP3MakeFromElems(&center, 0, 0, -1);
vmathV3MakeFromElems(&up, 0, 1, 0);
vmathM4MakeLookAt(&v_mat, &eye, &center, &up);
vec3 trans;
vmathV3MakeFromElems(&trans, 0, 0, -20);
vmathM4MakeTranslation(&v_mat, &trans);
glViewport(0, 0, width, height);
vmathM4MakeOrthographic(&p_mat, 0, width, 0, height, 1, 100);
I am currently drawing 1 quad that's defined like this:
//3 position, 4 color, 2 texture coordinates
float v_data[] = {-1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f,
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f,
1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f,
1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f};
short i_data[] = {0, 1, 2, 0, 2, 3};
and I setup it's model matrix like this:
vmathV3MakeFromElems(&out->scale, texture->width * 0.5f, texture->height * 0.5f, 1);
vmathM4SetElem(&out->model_mat, 0, 0, out->scale.x);
vmathM4SetElem(&out->model_mat, 1, 1, out->scale.y);
vmathM4SetElem(&out->model_mat, 2, 2, 1);
vmathM4SetElem(&out->model_mat, 3, 3, 1);
vmathM4SetElem(&out->model_mat, 3, 0, (out->scale.x) - (x));
vmathM4SetElem(&out->model_mat, 3, 1, (out->scale.y) + (y));
so how can I achieve viewport scaling like in the sample code but being able to use pixels [this might be the wrong approach, i am unsure].
this sample code at the top can be copy pasted and built with this command.
gcc -lglut -lGLU -lGL -o glsample glsample.c && ./glsample

vmathM4MakeOrthographic(&p_mat, 0, width, 0, height, 1, 100);
Let's say, that after this line p_mat will hold a matrix like this:
|1/width | -> p_mat[0][0]
| 1/height | -> p_mat[1][1]
| .... |
| |
This should ensure, that if width and height are in pixels, you'll keep your pixel-perfect scale.
The first sample you provided, however, uses
gluOrtho2D(-1.0 * aspect, 1.0 * aspect, -1.0, 1.0);
Which doesn't consider screen width and height (only the aspect ratio between them), and you will have a uniform unit scale.
Basically, by dividing or multiplying those two components (by the same number to keep aspect) in the projection matrix (p_mat[0][0] & p_mat[1][1]) you can scale your viewport. To achieve pixel-perfect scale, simply set them to 1/width and 1/height.

Related

Clarification on glVertexAttribPointer index paramter

I have a very simple program to display a 3D triangle in OpenGL. hat value I put in, it does not display correctly. I put in the following array into the vertex buffer
float triangle[] = {
// x y z r g b a
0.2f, -0.2f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f,
-0.2f, -0.2f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f,
-0.2f, 0.2f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
0.0f, -0.2f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f
};
And I use the following to pass them to the vertex shader
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 7, 0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 7, 0);
But the output triangle has a strange blue area, even though the positions are correct, which doesn't make sense since the input colours should be black. I have seen some use the index as sizeof(float) * 3 and sizeof(float) * 4, but that makes the triangle green and makes the positions wrong. The docs.gl entry is pretty vague, and doesn't provide any examples. Here are my shaders
Fragment Shader
#version 330 core
out vec4 color;
in vec4 outColor;
void main() {
out vec4 outColor;
uniform mat4 transform;
void main() {
gl_Position = transform * inPos;
outColor = inColor;
};
What is wrong here?
If a named buffer object is bound, then the last argument of glVertexAttribPointer is treated as a byte offset in the buffers data store.
The offset of the color attribute is 3*sizeof(float) bytes:
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 7, 0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 7,
(void*)(sizeof(float) * 3)); // <--- byte offset
The attribute consists of 7 components (x, y, z, r, g, b, a). The offset of the vertex coordinate is 0, because this are the first 3 components in the tuple. The offset of the color is 3*sizeof(float), because this are the components from 4 to 7.

Why does this cube in openGL rotate differently when using a perspective matrix?

I was just getting into OpenGL and learning about projection matrices using cglm (math library) and glfw. I have 3 matrices : model, view, and projection. In the render loop
while (!glfwWindowShouldClose(window)) {
/* Render here */
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glm_rotate(model, 0.001f, (vec3) { 0.0f, 1.0f, 0.0f });
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, model);
glBindVertexArray(vao1);
glDrawElements(GL_TRIANGLES, 12, GL_UNSIGNED_INT, NULL);
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
I am rotating my model about the y-axis, and it rotates about the y axis just fine. But then I add a projection matrix and instead of rotating, it just moves around. Here is a gif of it https://imgur.com/7KSaMdt
glm_perspective(0.785f, 740 / 580, 0.0f, 100.0f, projection);
Why is this happening? Shouldn't it just look farther away?
This is my vertex shader
#version 330 core
layout(location = 0) in vec4 InPos;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main() {
gl_Position = projection * view * model * InPos;
};
And here are my vertexes and indices:
float triangle1[] = {
//Coordinates x y z
0.9f, -0.5f, -5.0f,
-0.5f, -0.5f, -5.0f,
-0.5f, 0.5f, -5.0f,
0.0f, 0.0f, -4.0f
};
unsigned int indices[] = {
0, 1, 2,
2, 0, 3,
1, 2, 3,
1, 3, 0
};
the view matrix is just an identity matrix.
EDIT : the code initializing matrixes
mat4 model = GLM_MAT4_IDENTITY_INIT, view = GLM_MAT4_IDENTITY_INIT, projection = GLM_MAT4_IDENTITY_INIT;
glm_perspective(0.785f, 740 / 580, 1.0f, 100.0f, projection);
unsigned int modelLoc = glGetUniformLocation(shader, "model");
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, model);
unsigned int viewLoc = glGetUniformLocation(shader, "view");
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, view);
unsigned int projectionLoc = glGetUniformLocation(shader, "projection");
glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, projection);
glClearColor(0.5f, 0.1f, 0.9f, 1.0f);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window)) {
....
}
The issue seems to be the line
glm_perspective(0.785f, 740 / 580, 0.0f, 100.0f, projection);
the projection matrix defines a 3 dimensional space (clip space) which is projected on the 2 dimensional viewport. At Perspective projection, this space is a frustum (Viewing frustum).
In your example the near plane is 0.0. That causes an undefined behavior. The value for the near plane and the far plane have to be greater than 0.0 and the far plane has to be greater then the near plane:
0 < near < far
When you draw the geometry, the you have to ensure, that the geometry is in between then near and the far plane (in clip space respectively in the viewing volume), else the geometry is clipped.
Change the value for the near plane. For instance:
glm_perspective(0.785f, 740.0f / 580.0f, 0.1f, 100.0f, projection);

identifier "Image" is unidentified

I have been trying to load 6 images onto each face of the cube, and I tried to search for a way to do it, and found out that using SOIL I can load the texture images. Currently I want to load an array of images (6), and use that to set the textures of each of the cube's sides to one of those textures.
Here is my code so far, it loads a cube, and keeps on rotating it without the textures if you comment the LoadGLTextures() function:
#include <windows.h> // for MS Windows
#include <GL/glut.h> // GLUT, include glu.h and gl.h
#include "SOIL.h""
#include <fstream>
#include <stdlib.h>
#include <stdio.h>
#include <Imagehlp.h>
#include <image_DXT.h>
using namespace std;
/* Global variables */
char title[] = "3D Shapes";
float _angle = 0.0;
GLuint texture[6];
/* Initialize OpenGL Graphics */
void initGL() {
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set background color to black and opaque
glClearDepth(1.0f); // Set background depth to farthest
glEnable(GL_DEPTH_TEST); // Enable depth testing for z-culling
glDepthFunc(GL_LEQUAL); // Set the type of depth-test
glShadeModel(GL_SMOOTH); // Enable smooth shading
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Nice perspective corrections
GLuint tex;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
float color[] = { 1.0f, 0.0f, 0.0f, 1.0f };
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color);
}
void LoadGLTextures() {
// Load Texture
Image *image[6]; //PROBLEM HERE
int i;
for (i = 0; i<6; i++){
// allocate space for texture
image[i] = (Image *)malloc(sizeof(Image));
if (image[i] == NULL) {
printf("Error allocating space for image");
exit(0);
}
}
if ((!ImageLoad("1.png", image[0])) || (!ImageLoad("2.png", image[1])) || (!ImageLoad("3.png", image[2])) || (!ImageLoad("4.png", image[3])) || (!ImageLoad("5.png", image[4])) || (!ImageLoad("6.png", image[5]))) {
exit(1);
}
for (i = 0; i<6; i++){
// Create Texture
glGenTextures(1, &texture[i]);
glBindTexture(GL_TEXTURE_2D, texture[i]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // scale linearly when image bigger than texture
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // scale linearly when image smalled than texture
glTexImage2D(GL_TEXTURE_2D, 0, 3, image[i]->sizeX, image[i]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, image[i]->data);
}
};
/* Handler for window-repaint event. Called back when the window first appears and
whenever the window needs to be re-painted. */
void display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear color and depth buffers
glMatrixMode(GL_MODELVIEW); // To operate on model-view matrix
// Render a color-cube consisting of 6 quads with different colors
glLoadIdentity(); // Reset the model-view matrix
glTranslatef(1.5f, 0.0f, -7.0f); // Move right and into the screen
//Rotates, making sure it rotates around the center of the cube
glTranslatef(0.5, 1.0, 0.0);
glRotatef(_angle, 1.0, 1.0, 1.0);
glTranslatef(-0.5, -1.0, 0.0);
glBegin(GL_QUADS); // Begin drawing the color cube with 6 quads
// Top face (y = 1.0f)
// Define vertices in counter-clockwise (CCW) order with normal pointing out
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex3f(1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(1.0f, 1.0f, 1.0f);
// Bottom face (y = -1.0f)
glColor3f(1.0f, 0.5f, 0.0f); // Orange
glVertex3f(1.0f, -1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f(1.0f, -1.0f, -1.0f);
// Front face (z = 1.0f)
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex3f(1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f(1.0f, -1.0f, 1.0f);
// Back face (z = -1.0f)
glColor3f(1.0f, 1.0f, 0.0f); // Yellow
glVertex3f(1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f(1.0f, 1.0f, -1.0f);
// Left face (x = -1.0f)
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
// Right face (x = 1.0f)
glColor3f(1.0f, 0.0f, 1.0f); // Magenta
glVertex3f(1.0f, 1.0f, -1.0f);
glVertex3f(1.0f, 1.0f, 1.0f);
glVertex3f(1.0f, -1.0f, 1.0f);
glVertex3f(1.0f, -1.0f, -1.0f);
// Black/white checkerboard
float pixels[] = {
0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f
};
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_FLOAT, pixels);
glEnd(); // End of drawing color-cube
//// Render a pyramid consists of 4 triangles
//glLoadIdentity(); // Reset the model-view matrix
//glTranslatef(-1.5f, 0.0f, -6.0f); // Move left and into the screen
//glBegin(GL_TRIANGLES); // Begin drawing the pyramid with 4 triangles
//// Front
//glColor3f(1.0f, 0.0f, 0.0f); // Red
//glVertex3f(0.0f, 1.0f, 0.0f);
//glColor3f(0.0f, 1.0f, 0.0f); // Green
//glVertex3f(-1.0f, -1.0f, 1.0f);
//glColor3f(0.0f, 0.0f, 1.0f); // Blue
//glVertex3f(1.0f, -1.0f, 1.0f);
//// Right
//glColor3f(1.0f, 0.0f, 0.0f); // Red
//glVertex3f(0.0f, 1.0f, 0.0f);
//glColor3f(0.0f, 0.0f, 1.0f); // Blue
//glVertex3f(1.0f, -1.0f, 1.0f);
//glColor3f(0.0f, 1.0f, 0.0f); // Green
//glVertex3f(1.0f, -1.0f, -1.0f);
//// Back
//glColor3f(1.0f, 0.0f, 0.0f); // Red
//glVertex3f(0.0f, 1.0f, 0.0f);
//glColor3f(0.0f, 1.0f, 0.0f); // Green
//glVertex3f(1.0f, -1.0f, -1.0f);
//glColor3f(0.0f, 0.0f, 1.0f); // Blue
//glVertex3f(-1.0f, -1.0f, -1.0f);
//// Left
//glColor3f(1.0f, 0.0f, 0.0f); // Red
//glVertex3f(0.0f, 1.0f, 0.0f);
//glColor3f(0.0f, 0.0f, 1.0f); // Blue
//glVertex3f(-1.0f, -1.0f, -1.0f);
//glColor3f(0.0f, 1.0f, 0.0f); // Green
//glVertex3f(-1.0f, -1.0f, 1.0f);
//glEnd(); // Done drawing the pyramid
glutSwapBuffers(); // Swap the front and back frame buffers (double buffering)
}
/* Handler for window re-size event. Called back when the window first appears and
whenever the window is re-sized with its new width and height */
void reshape(GLsizei width, GLsizei height) { // GLsizei for non-negative integer
// Compute aspect ratio of the new window
if (height == 0) height = 1; // To prevent divide by 0
GLfloat aspect = (GLfloat)width / (GLfloat)height;
// Set the viewport to cover the new window
glViewport(0, 0, width, height);
// Set the aspect ratio of the clipping volume to match the viewport
glMatrixMode(GL_PROJECTION); // To operate on the Projection matrix
glLoadIdentity(); // Reset
// Enable perspective projection with fovy, aspect, zNear and zFar
gluPerspective(45.0f, aspect, 0.1f, 100.0f);
}
void update(int value) { //function for increasing the angle variable smoothly, keeps it <=360
_angle += 1.0f;
if (_angle > 360) {
_angle -= 360;
}
glutPostRedisplay();
glutTimerFunc(25, update, 0);
}
/* Main function: GLUT runs as a console application starting at main() */
int main(int argc, char** argv) {
glutInit(&argc, argv); // Initialize GLUT
glutInitDisplayMode(GLUT_DOUBLE); // Enable double buffered mode
glutInitWindowSize(640, 480); // Set the window's initial width & height
glutInitWindowPosition(50, 50); // Position the window's initial top-left corner
glutCreateWindow(title); // Create window with the given title
glutDisplayFunc(display); // Register callback handler for window re-paint event
glutReshapeFunc(reshape); // Register callback handler for window re-size event
initGL(); // Our own OpenGL initialization
glutTimerFunc(25, update, 0); //Add a timer
glutMainLoop(); // Enter the infinite event-processing loop
return 0;
}

OpenGL: smudges drawn on image surfaces

I am trying to code an interface to a rubik's cube.
However when I draw it there are smudges on the faces of the cube:
Here is the well-commented code. Can someone please help me and perhaps run the code and tell me where I might be going wrong?
#include <GL/glut.h>
#include <stdlib.h>
#include <stdio.h>
void init() {
glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
glEnable(GL_DEPTH_TEST);
}
static float x_degs = 0.0f;
static float y_degs = 0.0f;
void keyboard(unsigned char key, int x, int y) {
switch (key) {
case 'q':
exit(EXIT_SUCCESS);
case 'h':
y_degs -= 1.0f;
glutPostRedisplay();
glutSwapBuffers();
break;
case 'j':
x_degs -= 1.0f;
glutPostRedisplay();
glutSwapBuffers();
break;
case 'k':
x_degs += 1.0f;
glutPostRedisplay();
glutSwapBuffers();
break;
case 'l':
y_degs += 1.0f;
glutPostRedisplay();
glutSwapBuffers();
break;
}
}
// half the length of one card
static const float card_half_size = 1.0f;
// half the space between cards
static const float space_half_size = 0.1f;
// number of cards per face
static const int NUM_CARDS_PER_FACE = 4;
/*
// start position of center of top left card
const float start = - 3 * (card_half_size + space_half_size);
// increment between center of cards
const float incr = 2 * (card_half_size + space_half_size);
// half the size of a cube face
const float cube_half_size = 4 * (card_half_size + space_half_size);
*/
// draw a card centered at the origin
void draw_card() {
glBegin(GL_QUADS);
glVertex3f(- card_half_size, - card_half_size, 0.0f);
glVertex3f(- card_half_size, card_half_size, 0.0f);
glVertex3f(card_half_size, card_half_size, 0.0f);
glVertex3f(card_half_size, - card_half_size, 0.0f);
glEnd();
}
// draw a cube face made up of cards
void draw_card_face() {
const float cube_half_size = 4 * (card_half_size + space_half_size);
const float start = - 3 * (card_half_size + space_half_size);
const float incr = 2 * (card_half_size + space_half_size);
glColor3f(0.0f, 1.0f, 1.0f);
glBegin(GL_QUADS);
glVertex3f(- cube_half_size, - cube_half_size, -0.001f);
glVertex3f(- cube_half_size, cube_half_size, -0.001f);
glVertex3f(cube_half_size, cube_half_size, -0.001f);
glVertex3f(cube_half_size, - cube_half_size, -0.001f);
glEnd();
glColor3f(1.0f, 1.0f, 1.0f);
for (int i = 0; i < NUM_CARDS_PER_FACE; i++)
for (int j = 0; j < NUM_CARDS_PER_FACE; j++) {
glPushMatrix();
glTranslatef(start + i * incr, start + j * incr, 0.0f);
draw_card();
glPopMatrix();
}
}
// draw a cube made up of cards
void draw_card_cube() {
const float cube_half_size = 4 * (card_half_size + space_half_size);
// front face
glPushMatrix();
glTranslatef(0.0f, 0.0f, cube_half_size);
draw_card_face();
glPopMatrix();
// back face
glPushMatrix();
glTranslatef(0.0f, 0.0f, - cube_half_size);
glRotatef(180.0f, 0.0f, 1.0f, 0.0f);
draw_card_face();
glPopMatrix();
// right face
glPushMatrix();
glTranslatef(cube_half_size, 0.0f, 0.0f);
glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
draw_card_face();
glPopMatrix();
// left face
glPushMatrix();
glTranslatef(- cube_half_size, 0.0f, 0.0f);
glRotatef(- 90.0f, 0.0f, 1.0f, 0.0f);
draw_card_face();
glPopMatrix();
// top face
glPushMatrix();
glTranslatef(0.0f, cube_half_size, 0.0f);
glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
draw_card_face();
glPopMatrix();
// bottom face
glPushMatrix();
glTranslatef(0.0f, - cube_half_size, 0.0f);
glRotatef(- 90.0f, 1.0f, 0.0f, 0.0f);
draw_card_face();
glPopMatrix();
}
void display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glRotatef(x_degs, 1.0f, 0.0f, 0.0f);
glRotatef(y_degs, 0.0f, 1.0f, 0.0f);
gluLookAt(-0.6f, 0.6f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
draw_card_cube();
glutSwapBuffers();
}
void reshape(int w, int h) {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-15.0f, 15.0f, -15.0f, 15.0f, -15.0f, 15.0f);
glViewport(0, 0, w, h);
glMatrixMode(GL_MODELVIEW);
}
int main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutCreateWindow(argv[0]);
init();
glutKeyboardFunc(keyboard);
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
OK, I have revised the code so that I draw th cyan rectangles 0.01f units behind instead of 0.001f units behind and this seems to have fixed the z-fighting. However I would have liked to use glPolygonOffset(factor, units) to fix this problem but I was unable to do it, for the following
reasons:
I don't know how to set facor and units (I've tried 1.0 for both).
I've tried different values to no outcome.
Here is the code without the bleeding/stitching/z-fighting:
#include <GL/glut.h>
#include <stdlib.h>
#include <stdio.h>
void init() {
glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
glEnable(GL_DEPTH_TEST);
}
static float x_degs = 0.0f;
static float y_degs = 0.0f;
void keyboard(unsigned char key, int x, int y) {
switch (key) {
case 'q':
exit(EXIT_SUCCESS);
case 'h':
y_degs -= 1.0f;
glutPostRedisplay();
glutSwapBuffers();
break;
case 'j':
x_degs -= 1.0f;
glutPostRedisplay();
glutSwapBuffers();
break;
case 'k':
x_degs += 1.0f;
glutPostRedisplay();
glutSwapBuffers();
break;
case 'l':
y_degs += 1.0f;
glutPostRedisplay();
glutSwapBuffers();
break;
}
}
// half the length of one card
static const float card_half_size = 1.0f;
// half the space between cards
static const float space_half_size = 0.1f;
// number of cards per face
static const int NUM_CARDS_PER_FACE = 4;
/*
// start position of center of top left card
const float start = - 3 * (card_half_size + space_half_size);
// increment between center of cards
const float incr = 2 * (card_half_size + space_half_size);
// half the size of a cube face
const float cube_half_size = 4 * (card_half_size + space_half_size);
*/
// draw a card centered at the origin
void draw_card() {
glBegin(GL_QUADS);
glVertex3f(- card_half_size, - card_half_size, 0.0f);
glVertex3f(- card_half_size, card_half_size, 0.0f);
glVertex3f(card_half_size, card_half_size, 0.0f);
glVertex3f(card_half_size, - card_half_size, 0.0f);
glEnd();
}
// draw a cube face made up of cards
void draw_card_face() {
const float cube_half_size = 4 * (card_half_size + space_half_size);
const float start = - 3 * (card_half_size + space_half_size);
const float incr = 2 * (card_half_size + space_half_size);
glColor3f(0.0f, 1.0f, 1.0f);
glBegin(GL_QUADS);
glVertex3f(- cube_half_size, - cube_half_size, -0.001f);
glVertex3f(- cube_half_size, cube_half_size, -0.001f);
glVertex3f(cube_half_size, cube_half_size, -0.001f);
glVertex3f(cube_half_size, - cube_half_size, -0.001f);
glEnd();
glColor3f(1.0f, 1.0f, 1.0f);
for (int i = 0; i < NUM_CARDS_PER_FACE; i++)
for (int j = 0; j < NUM_CARDS_PER_FACE; j++) {
glPushMatrix();
glTranslatef(start + i * incr, start + j * incr, 0.0f);
draw_card();
glPopMatrix();
}
}
// draw a cube made up of cards
void draw_card_cube() {
const float cube_half_size = 4 * (card_half_size + space_half_size);
// front face
glPushMatrix();
glTranslatef(0.0f, 0.0f, cube_half_size);
draw_card_face();
glPopMatrix();
// back face
glPushMatrix();
glTranslatef(0.0f, 0.0f, - cube_half_size);
glRotatef(180.0f, 0.0f, 1.0f, 0.0f);
draw_card_face();
glPopMatrix();
// right face
glPushMatrix();
glTranslatef(cube_half_size, 0.0f, 0.0f);
glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
draw_card_face();
glPopMatrix();
// left face
glPushMatrix();
glTranslatef(- cube_half_size, 0.0f, 0.0f);
glRotatef(- 90.0f, 0.0f, 1.0f, 0.0f);
draw_card_face();
glPopMatrix();
// top face
glPushMatrix();
glTranslatef(0.0f, cube_half_size, 0.0f);
glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
draw_card_face();
glPopMatrix();
// bottom face
glPushMatrix();
glTranslatef(0.0f, - cube_half_size, 0.0f);
glRotatef(- 90.0f, 1.0f, 0.0f, 0.0f);
draw_card_face();
glPopMatrix();
}
void display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glRotatef(x_degs, 1.0f, 0.0f, 0.0f);
glRotatef(y_degs, 0.0f, 1.0f, 0.0f);
gluLookAt(-0.6f, 0.6f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
draw_card_cube();
glutSwapBuffers();
}
void reshape(int w, int h) {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-15.0f, 15.0f, -15.0f, 15.0f, -15.0f, 15.0f);
glViewport(0, 0, w, h);
glMatrixMode(GL_MODELVIEW);
}
int main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutCreateWindow(argv[0]);
init();
glutKeyboardFunc(keyboard);
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
I think you're drawing your checkers as coplanar quads of the faces of your main cube ; if this is the case, the problem you encounter is called "z fighting".
You can take a look at point 12.040 Depth buffering seems to work, but polygons seem to bleed through polygons that are in front of them. What's going on? here :
http://www.opengl.org/resources/faq/technical/depthbuffer.htm
Basically, your depth buffer does not have enough precision to resolve which quad to display for each pixel, causing the problem.
You can either manually add an offset to your checker quads, to move them away from the cube ; or use depth bias through glPolygonOffset to solve the issue.
I think you're trying to do coplanar rendering. Look into glPolygonOffset() instead of using small Z offsets like you do.
This is what I get from your code, compiled with gcc -std=c99 -lGL -lGLU -lglut a.c: no smudges. Can you post yours? (Ubuntu 11.10, Intel GPU)

C - GLFW window doesn't open on Debian

I'm trying to get started with GLFW on Debian, I've tried compiling and running an example program but it refuses to run. With the help of a couple of printf statements I've found that when the program tries to open a GLFW window it fails, then exits - but I don't know why. Any help would be amazing.
#include <stdlib.h> // For malloc() etc.
#include <stdio.h> // For printf(), fopen() etc.
#include <math.h> // For sin(), cos() etc.
#include <GL/glfw.h> // For GLFW, OpenGL and GLU
//----------------------------------------------------------------------
// Draw() - Main OpenGL drawing function that is called each frame
//----------------------------------------------------------------------
void Draw( void )
{
int width, height; // Window dimensions
double t; // Time (in seconds)
int k; // Loop counter
// Get current time
t = glfwGetTime();
// Get window size
glfwGetWindowSize( &width, &height );
// Make sure that height is non-zero to avoid division by zero
height = height < 1 ? 1 : height;
// Set viewport
glViewport( 0, 0, width, height );
// Clear color and depht buffers
glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
// Set up projection matrix
glMatrixMode( GL_PROJECTION ); // Select projection matrix
glLoadIdentity(); // Start with an identity matrix
gluPerspective( // Set perspective view
65.0, // Field of view = 65 degrees
(double)width/(double)height, // Window aspect (assumes square pixels)
1.0, // Near Z clipping plane
100.0 // Far Z clippling plane
);
// Set up modelview matrix
glMatrixMode( GL_MODELVIEW ); // Select modelview matrix
glLoadIdentity(); // Start with an identity matrix
gluLookAt( // Set camera position and orientation
0.0, 0.0, 10.0, // Camera position (x,y,z)
0.0, 0.0, 0.0, // View point (x,y,z)
0.0, 1.0, 0.0 // Up-vector (x,y,z)
);
// **** Draw a circle of points ***
// Save the current modelview matrix on the stack
glPushMatrix();
// Translate (move) the points to the upper left of the display
glTranslatef( -4.0f, 3.0f, 0.0f );
// Rotate the points about the z-axis and the x-axis
glRotatef( 35.0f * (float)t, 0.0f, 0.0f, 1.0f );
glRotatef( 60.0f * (float)t, 1.0f, 0.0f, 0.0f );
// Now draw the points - we use a for-loop to build a circle
glColor3f( 1.0f, 1.0f, 1.0f );
glBegin( GL_POINTS );
for( k = 0; k < 20; k ++ )
{
glVertex3f( 2.0f * (float)cos( 0.31416 * (double)k ),
2.0f * (float)sin( 0.31416 * (double)k ),
0.0f );
}
glEnd();
// Restore modelview matrix
glPopMatrix();
// **** Draw a circle of lines ***
// Save the current modelview matrix on the stack
glPushMatrix();
// Translate (move) the lines to the upper right of the display
glTranslatef( 4.0f, 3.0f, 0.0f );
// Rotate the points about the z-axis and the x-axis
glRotatef( 45.0f * (float)t, 0.0f, 0.0f, 1.0f );
glRotatef( 55.0f * (float)t, 1.0f, 0.0f, 0.0f );
// Now draw the lines - we use a for-loop to build a circle
glBegin( GL_LINE_LOOP );
for( k = 0; k < 20; k ++ )
{
glColor3f( 1.0f, 0.05f * (float)k, 0.0f );
glVertex3f( 2.0f * (float)cos( 0.31416 * (double)k ),
2.0f * (float)sin( 0.31416 * (double)k ),
0.0f );
}
glEnd();
// Restore modelview matrix
glPopMatrix();
// **** Draw a disc using trinagles ***
// Save the current modelview matrix on the stack
glPushMatrix();
// Translate (move) the triangles to the lower left of the display
glTranslatef( -4.0f, -3.0f, 0.0f );
// Rotate the triangles about the z-axis and the x-axis
glRotatef( 25.0f * (float)t, 0.0f, 0.0f, 1.0f );
glRotatef( 75.0f * (float)t, 1.0f, 0.0f, 0.0f );
// Now draw the triangles - we use a for-loop to build a disc
// Since we are building a triangle fan, we also specify a first
// vertex for the centre point of the disc.
glBegin( GL_TRIANGLE_FAN );
glColor3f( 0.0f, 0.5f, 1.0f );
glVertex3f( 0.0f, 0.0f, 0.0f );
for( k = 0; k < 21; k ++ )
{
glColor3f( 0.0f, 0.05f * (float)k, 1.0f );
glVertex3f( 2.0f * (float)cos( 0.31416 * (double)k ),
2.0f * (float)sin( 0.31416 * (double)k ),
0.0f );
}
glEnd();
// Restore modelview matrix
glPopMatrix();
// **** Draw a disc using a polygon ***
// Save the current modelview matrix on the stack
glPushMatrix();
// Translate (move) the polygon to the lower right of the display
glTranslatef( 4.0f, -3.0f, 0.0f );
// Rotate the polygon about the z-axis and the x-axis
glRotatef( 65.0f * (float)t, 0.0f, 0.0f, 1.0f );
glRotatef( -35.0f * (float)t, 1.0f, 0.0f, 0.0f );
// Now draw the polygon - we use a for-loop to build a disc
glBegin( GL_POLYGON );
for( k = 0; k < 20; k ++ )
{
glColor3f( 1.0f, 0.0f, 0.05f * (float)k );
glVertex3f( 2.0f * (float)cos( 0.31416 * (double)k ),
2.0f * (float)sin( 0.31416 * (double)k ),
0.0f );
}
glEnd();
// Restore modelview matrix
glPopMatrix();
// **** Draw a single quad ***
// Save the current modelview matrix on the stack
glPushMatrix();
// Rotate the quad about the y-axis
glRotatef( 60.0f * (float)t, 0.0f, 1.0f, 0.0f );
// Now draw the quad
glBegin( GL_QUADS );
glColor3f( 1.0f, 0.0f, 0.0f );
glVertex3f( -1.5f, -1.5f, 0.0f );
glColor3f( 1.0f, 1.0f, 0.0f );
glVertex3f( 1.5f, -1.5f, 0.0f );
glColor3f( 1.0f, 0.0f, 1.0f );
glVertex3f( 1.5f, 1.5f, 0.0f );
glColor3f( 0.0f, 0.0f, 1.0f );
glVertex3f( -1.5f, 1.5f, 0.0f );
glEnd();
// Restore modelview matrix
glPopMatrix();
}
//----------------------------------------------------------------------
// main() - Program entry point
//----------------------------------------------------------------------
int main( int argc, char **argv )
{
int ok; // Flag telling if the window was opened
int running; // Flag telling if the program is running
// Initialize GLFW
glfwInit();
// Open window
ok = glfwOpenWindow(
100, 100, // Width and height of window
8, 8, 8, // Number of red, green, and blue bits for color buffer
8, // Number of bits for alpha buffer
24, // Number of bits for depth buffer (Z-buffer)
0, // Number of bits for stencil buffer
GLFW_WINDOW // We want a desktop window (could be GLFW_FULLSCREEN)
);
printf("here");
// If we could not open a window, exit now
if( !ok )
{
glfwTerminate();
return 0;
}
printf("not here");
// Set window title
glfwSetWindowTitle( "My OpenGL program" );
// Enable sticky keys
glfwEnable( GLFW_STICKY_KEYS );
// Main rendering loop
do
{
// Call our rendering function
Draw();
// Swap front and back buffers (we use a double buffered display)
glfwSwapBuffers();
// Check if the escape key was pressed, or if the window was closed
running = !glfwGetKey( GLFW_KEY_ESC ) &&
glfwGetWindowParam( GLFW_OPENED );
}
while( running );
// Terminate GLFW
glfwTerminate();
// Exit program
return 0;
}
You're sure it's glfwOpenWindow that's failing? I don't know why that might be, perhaps you're using too many bits for your z-buffer? That's the only thing I can think of.
Try this
GLFWvidmode dvm;
glfwGetDesktopMode(&dvm);
glfwOpenWindow(winWidth, winHeight, dvm.RedBits, dvm.GreenBits, dvm.BlueBits, 0, 0, 0, GLFW_WINDOW);
And see if it still fails.

Resources