Clarification on glVertexAttribPointer index paramter - c

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.

Related

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);

orthographic scaling opengl viewport

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.

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;
}

Coord texture array does not works correctly with glDrawElements

the purpose of my program is to load and display a simple cube with the same texture on each face. But the problem is that the output is not very good (just 4 faces are textured correctly).I tried lots of combinations of coordinates in the textures array but most of the time it's worse. Is it possible to set textures correctly with the function glDrawElements or not?
#define OFFSET_BUFFER(bytes) ((GLfloat *)NULL + bytes)
GLfloat vertices[] =
{
-1.0, -1.0, -1.0,
1.0, -1.0, -1.0,
1.0, 1.0, -1.0,
-1.0, 1.0, -1.0,
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, 1.0, 1.0,
-1.0, 1.0, 1.0,
};
GLubyte indices[] =
{
0, 1, 2, 3,
4, 7, 6, 5,
0, 4, 5, 1,
3, 2, 6, 7,
0, 3, 7, 4,
1, 5, 6, 2
};
GLfloat textures[] =
{
0,0, 1,0, 1,1, 0,1,
0,1, 1,1, 1,0, 0,0,
/*//0,0, 1,0, 1,1, 0,1,
//0,0, 1,0, 1,1, 0,1,
0,1, 1,1, 1,0, 0,0,
0,1, 1,1, 1,0, 0,0,
//0,0, 1,0, 1,1, 0,1*/
};
int main(int argc, char *argv[])
{
SDL_Init(SDL_INIT_VIDEO);
SDL_WM_SetCaption("Texture Mapping",NULL);
SDL_SetVideoMode(500, 500, 32, SDL_OPENGL);
bool continuer = true;
SDL_Event event;
GLuint texCube;
glClearDepth(1.0f);
glClearColor(0.1f, 0.1f, 0.1f, 0.1f);
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(70.0f, (float)500.0f / (float)500.0f, 1.0f, 3000.0f);
glewInit();
texCube = loadTexture("caisse.jpg");
glBindTexture(GL_TEXTURE_2D, texCube);
glEnable(GL_TEXTURE_2D);
while (continuer)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
SDL_WaitEvent(&event);
switch(event.type)
{
case SDL_QUIT:
continuer = false;
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0f, 0.0f, 3.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
//Draw Cube ---------------------------------------
glPushMatrix();
glRotatef(45.0f, 1.0f, 1.0f, 0.0f);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertices);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 0, textures);
glDrawElements(GL_QUADS, 24, GL_UNSIGNED_BYTE, indices);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
//-------------------------------------------------
glPopMatrix();
glFlush();
SDL_GL_SwapBuffers();
}
glDisable(GL_TEXTURE_2D);
SDL_Quit();
return 0;
}
You are trying to use only 8 vertices. To get correct texturing you must use 12 separate triangles, each of them with the "correct" texture coordinates. The thing is when you're trying to do the planar map onto something homeomorphic to the sphere (e.g., a cube in your case), you will get "troubles" like this.
So, split the cube into 12 triangles (yes, they will share coordinates) and calculate the texture coordinates with one of the mapping methods.
See here for mapping details:
http://local.wasp.uwa.edu.au/~pbourke/texture_colour/texturemap/
The answer to your question "Is it possible to set textures correctly with the function glDrawElements or not?" is "Yes, but you have to change the arrays' layout".
Even more, there's a solution already written down on this site:
Problems texturing a cube
Detailed layout of the vertices and texture coordinates goes here: http://blogs.msdn.com/b/dawate/archive/2011/01/20/constructing-drawing-and-texturing-a-cube-with-vertices-in-xna-on-windows-phone-7.aspx

VertexBuffer from Vertices

I need to create a vertex buffer out of vertices. This tutorial in MSDN is splendid.
But this one holds good for DirectX10+. I am using DirectX9. How to accomplish the same here?
Thanks.
//Definitions
LPDIRECT3DVERTEXBUFFER9 v_buffer = NULL;
struct SimpleVertexCombined{
D3DXVECTOR3 Pos;
SimpleVertexCombined(FLOAT X, FLOAT Y, FLOAT Z):Pos(X, Y, Z){}
};
d3ddev->CreateVertexBuffer(8*sizeof(SimpleVertexCombined),
0,
0,
D3DPOOL_MANAGED,
&v_buffer,
NULL);
SimpleVertexCombined* cube = 0;
v_buffer->Lock(0, 0, (void**)&cube, 0);
cube[0] = SimpleVertexCombined(-1.0f, -1.0f, -1.0f);
cube[1] = SimpleVertexCombined(-1.0f, 1.0f, -1.0f);
cube[2] = SimpleVertexCombined( 1.0f, 1.0f, -1.0f);
cube[3] = SimpleVertexCombined( 1.0f, -1.0f, -1.0f);
cube[4] = SimpleVertexCombined(-1.0f, -1.0f, 1.0f);
cube[5] = SimpleVertexCombined(-1.0f, 1.0f, 1.0f);
cube[6] = SimpleVertexCombined( 1.0f, 1.0f, 1.0f);
cube[7] = SimpleVertexCombined( 1.0f, -1.0f, 1.0f);
v_buffer->Unlock();
I think this should work, First we create the v_buffer using CreateVertexBuffer(), the first value is its size so remember to change that number if you're adding more vertices, and then we use the pointer cube to transfer data to the buffer. You can also use memcpy() between the lock and unlock if you want to transfer data from a pre-existing array, like this:
SimpleVertexCombined verticesCombo[] = {
D3DXVECTOR3( 0.0f, 0.5f, 0.5f ),
D3DXVECTOR3( 0.0f, 0.0f, 0.5f ),
D3DXVECTOR3( 0.5f, -0.5f, 0.5f ),
D3DXVECTOR3( 0.5f, 0.0f, 0.0f ),
D3DXVECTOR3( -0.5f, -0.5f, 0.5f ),
D3DXVECTOR3( 0.0f, 0.5f, 0.0f ),
};
VOID* pVoid;
v_buffer->Lock(0, 0, (void**)&cube, 0);
memcpy(pVoid, verticesCombo, sizeof(verticesCombo));
v_buffer->Unlock();
All of this is done without colour, if you want colour you have to add it to the constructor, also if you want to render you have to create a D3DVERTEXELEMENT9 and a declaration to it.

Resources