Related
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.
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(¢er, 0, 0, -1);
vmathV3MakeFromElems(&up, 0, 1, 0);
vmathM4MakeLookAt(&v_mat, &eye, ¢er, &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.
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;
}
When I draw a cube with this code
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(
x, y, z,
x+xp, y+yp, z+zp,
0.0f, 1.0f, 0.0f);
glBegin(GL_QUADS);
glColor3f(0.0f,1.0f,0.0f);
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);
glColor3f(1.0f,0.5,0.0f);
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);
glColor3f(1.0f,0.0f,0.0f);
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);
glColor3f(1.0f,1.0f,0.0f);
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);
glColor3f(0.0f,0.0f,1.0f);
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);
glColor3f(1.0f,0.0f,1.0f);
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);
glEnd();
I get an odd cude drawing:
and
Even without gluLookAt() I still end up with an odd drawing.
The weird thing is I used the exact same code in a python OpenGL project and had no trouble with it. So it seems to be a C error?
It also seems like the first 2 quads (green and orange) are not being drawn at all.
Just solved my own problem by adding:
glEnable(GL_DEPTH_TEST);
to my code.
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)