PDA

View Full Version : Drawing a cube and a triangle in different positions



many-as-one
02-10-2014, 04:25 PM
Hello,

I'm learning OpenGL and I have a (potentially stupid) question. My main objective is to draw a cube and a triangle in different locations by using two separated arrays, two MVP (Model, View and Projection) matrices and one vertex shader. If I draw my cube alone it works, and the same with my triangle, but when I try to draw both of them at the same time I don't get the desired result :dejection:

This is my C++ code:


#define GLEW_STATIC
#include <GL\glew.h>
#include <GLFW\glfw3.h>
#include <glm\glm.hpp>
#include <glm\gtx\transform.hpp>
#include <glm\gtc\matrix_transform.hpp>
#include <vector>
#include <iostream>

#include "ShaderFile.hpp" //My own shader wrapper

//Using the OpenGL 4.1 version
#define OPENGL_MAJOR 4
#define OPENGL_MINOR 1

//#define FULLSCREEN

#define WINDOW_TITLE "Color Cube and The Lone Triangle"
#ifdef FULLSCREEN
#define SCREEN_WIDTH 1366
#define SCREEN_HEIGHT 768
#else
#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 600
#endif

///My cube
static const GLfloat vertex_buffer_array[] = {
-1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f
};

//Colors for my cube
static const GLfloat color_buffer_data[] = {
0.583f, 0.771f, 0.014f,
0.609f, 0.115f, 0.436f,
0.327f, 0.483f, 0.844f,
0.822f, 0.569f, 0.201f,
0.435f, 0.602f, 0.223f,
0.310f, 0.747f, 0.185f,
0.597f, 0.770f, 0.761f,
0.559f, 0.436f, 0.730f,
0.359f, 0.583f, 0.152f,
0.483f, 0.596f, 0.789f,
0.559f, 0.861f, 0.639f,
0.195f, 0.548f, 0.859f,
0.014f, 0.184f, 0.576f,
0.771f, 0.328f, 0.970f,
0.406f, 0.615f, 0.116f,
0.676f, 0.977f, 0.133f,
0.971f, 0.572f, 0.833f,
0.140f, 0.616f, 0.489f,
0.997f, 0.513f, 0.064f,
0.945f, 0.719f, 0.592f,
0.543f, 0.021f, 0.978f,
0.279f, 0.317f, 0.505f,
0.167f, 0.620f, 0.077f,
0.347f, 0.857f, 0.137f,
0.055f, 0.953f, 0.042f,
0.714f, 0.505f, 0.345f,
0.783f, 0.290f, 0.734f,
0.722f, 0.645f, 0.174f,
0.302f, 0.455f, 0.848f,
0.225f, 0.587f, 0.040f,
0.517f, 0.713f, 0.338f,
0.053f, 0.959f, 0.120f,
0.393f, 0.621f, 0.362f,
0.673f, 0.211f, 0.457f,
0.820f, 0.883f, 0.371f,
0.982f, 0.099f, 0.879f
};

//The triangle
static const GLfloat triangle_data_array[] = {
-1.0F, -1.0F, 0.0F,
1.0F, -1.0F, 0.0F,
0.0F, 1.0F, 0.0F
};


//////////////////////////////////////////////////////////////////////////
// Functions prototypes
//////////////////////////////////////////////////////////////////////////

//It creates the main UI window
GLFWwindow* createContext(void);

//It configures OpenGL and the context
void configureGLFWWindow(void);

//Vertex Array Object: It stores all of the links between the attributes
//and your Vertex Buffer Objects with raw vertex data
GLuint inline createVAO(void);

//It draws the vertex data
void inline draw(GLuint&, GLuint&);
void inline drawTriangle(GLuint&);

//It creates the shader program
GLuint createProgram(void);

//This function compile the referenced shader ID with the shader file string.
void compileShader(GLuint&, const GLchar* const);

//It shows information about the render and the OpenGL version
void showInfo(void);

//It computes and returns the Model, View and Projection matrix
glm::mat4 createMVPMatrix(bool is_triangle = false);
glm::mat4 createModelMatrix(void);
glm::mat4 createModelMatrixForTriangle(void);


int main()
{
auto window = createContext();

if (window == nullptr) return EXIT_FAILURE;

showInfo(); //Show info about the rendered and the OpenGL version
GLuint programID = createProgram(); //Create the shader program

//Get a handle for our "MVP" uniform.
GLuint MVPmatrixID = glGetUniformLocation(programID, "MVP");
glm::mat4 MVPmatrix = createMVPMatrix();

//The MVP for the triangle
GLuint MPVtriangleID = glGetUniformLocation(programID, "MVP_triangle");
glm::mat4 MVPmatrix_triangle = createMVPMatrix(true); //true for the triangle!

//The color of the background when you clear the screen
glClearColor(0.2f, 0.1f, 0.3f, 0.0f);

//The Z-Buffer
glEnable(GL_DEPTH_TEST); //Enable depth test
glDepthFunc(GL_LESS); //Accept fragment if it closer to the camera than the former one

//Create the Vertex Array Object
auto VAO_id = createVAO();

//Create the buffers: vertices
GLuint vertexBuffer;
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_buffer_array),
vertex_buffer_array, GL_STATIC_DRAW);

//Create the buffers: colors
GLuint colorBuffer;
glGenBuffers(1, &colorBuffer);
glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(color_buffer_data),
color_buffer_data, GL_STATIC_DRAW);

//The Lone Triangle
GLuint triangleBuffer;
glGenBuffers(1, &triangleBuffer);
glBindBuffer(GL_ARRAY_BUFFER, triangleBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(triangle_data_array),
triangle_data_array, GL_STATIC_DRAW);

//The main loop!
while (!glfwWindowShouldClose(window)) {
//Tell GLFW to retrieve window events...
glfwSwapBuffers(window);
glfwPollEvents();

//Clear the screen
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

//Use the shader program!
glUseProgram(programID);

//Send our transformation to the currently bound shader
glUniformMatrix4fv(MVPmatrixID, 1, GL_FALSE, &MVPmatrix[0][0]);
draw(vertexBuffer, colorBuffer);

//Draw the triangle!
glUniformMatrix4fv(MPVtriangleID, 1, GL_FALSE, &MVPmatrix_triangle[0][0]);
drawTriangle(triangleBuffer);

//If you press escape key, break the loop and finish execution
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
}

// Cleanup VBO and shader
glDeleteBuffers(1, &vertexBuffer);
glDeleteBuffers(1, &colorBuffer);
glDeleteBuffers(1, &triangleBuffer);
glDeleteProgram(programID);
glDeleteVertexArrays(1, &VAO_id);
glfwTerminate();

return 0;
}

//////////////////////////////////////////////////////////////////////////
// Prototypes implementation
//////////////////////////////////////////////////////////////////////////
GLFWwindow* createContext(void)
{
if (!glfwInit()) {
std::cerr << "Failed to initialize GLFW =(" << std::endl;
return nullptr;
}

configureGLFWWindow();

GLFWwindow* window;

#ifdef FULLSCREEN
window = glfwCreateWindow(SCREEN_WIDTH, SCREEN_HEIGHT, WINDOW_TITLE,
glfwGetPrimaryMonitor(), nullptr);
#else
window = glfwCreateWindow(SCREEN_WIDTH, SCREEN_HEIGHT, WINDOW_TITLE,
nullptr, nullptr);
#endif

glfwMakeContextCurrent(window);

//Prepare GLEW
glewExperimental = GL_TRUE;

if (glewInit() != GLEW_OK) {
std::cerr << "Failed to initialize GLEW =(" << std::endl;
return nullptr;
}

return window;
}

void configureGLFWWindow(void)
{
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, OPENGL_MAJOR);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, OPENGL_MINOR);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
}

GLuint inline createVAO(void)
{
GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
return VertexArrayID;
}

void inline draw(GLuint& vertex, GLuint& colors)
{
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertex);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);

//Second buffer attributes: the colors
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, colors);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, nullptr);

//Draw: 12 * 3 indices starting at 0 -> 12 triangles -> 6 squares
glDrawArrays(GL_TRIANGLES, 0, 12 * 3);

glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
}

void inline drawTriangle(GLuint& buffer)
{
glEnableVertexAttribArray(3);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(3);
}

GLuint createProgram(void)
{
//Create and compile the shaders
GLuint vertexID = glCreateShader(GL_VERTEX_SHADER);
compileShader(vertexID, "shader.vert");
GLuint fragmentID = glCreateShader(GL_FRAGMENT_SHADER);
compileShader(fragmentID, "shader.frag");

//Link the program with the shaders
std::cout << "--> Linking the program..." << std::endl;
GLuint programID = glCreateProgram();
glAttachShader(programID, vertexID);
glAttachShader(programID, fragmentID);
glLinkProgram(programID);

//Check the program for any error
GLint result = GL_FALSE;
GLint infoLogLength;
glGetProgramiv(programID, GL_LINK_STATUS, &result);

if (result == GL_TRUE)
std::cout << "\tProgram #" << programID << " OK!" << std::endl;
else {
glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &infoLogLength);
std::vector<char> programInfoMsg(infoLogLength);
glGetProgramInfoLog(programID, infoLogLength, nullptr,
&programInfoMsg[0]);

std::cout << "\tProgram #" << programID << " info log:\n"
<< &programInfoMsg[0] << std::endl;
}

glDeleteShader(vertexID);
glDeleteShader(fragmentID);

return programID;
}

void compileShader(GLuint& shaderID, const GLchar* const shaderFile)
{
Utils::ShaderFile shader(shaderFile);

//Get the vertex shader source and compile it
std::string shaderString = shader.getShaderStringSource();
const GLchar* vertSrc = const_cast<GLchar*>(shaderString.c_str());
std::cout << "--> Compiling Shader #"
<< shaderID << "... " << std::endl;
glShaderSource(shaderID, 1, &vertSrc, nullptr);
glCompileShader(shaderID);

//Check the vertex shader compilation
GLint result = GL_FALSE;
int infoLogLength;
glGetShaderiv(shaderID, GL_COMPILE_STATUS, &result);

if (result == GL_TRUE)
std::cout << "\tShader #" << shaderID << " OK!" << std::endl;
else {
glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &infoLogLength);
std::vector<GLchar> vertexShaderInfoMsg(infoLogLength);
glGetShaderInfoLog(shaderID, infoLogLength, nullptr,
&vertexShaderInfoMsg[0]);

std::cout << "\tShader #" << shaderID << " info log:\n"
<< &vertexShaderInfoMsg[0] << std::endl;
}
}

void showInfo(void)
{
std::cout << "Renderer: " << glGetString(GL_RENDERER) << std::endl;
std::cout << "OpenGL version: " << glGetString(GL_VERSION) << std::endl;
}

glm::mat4 createMVPMatrix(bool is_triangle)
{
//Projection matrix: 45 Field of View, 4:3 ratio
glm::mat4 projection = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.0f);

//View matrix
glm::mat4 view = glm::lookAt(glm::vec3(4, 3, -3), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));

//Model matrix
glm::mat4 model = is_triangle ? createModelMatrixForTriangle() : createModelMatrix();

//Return the Model-View-Projection matrix
return projection * view * model;
}

//The cube is in the upper right corner
glm::mat4 createModelMatrix(void)
{
glm::mat4 translation = glm::translate(glm::vec3(-3.3F, 0.0F, 0.0F));
glm::mat4 scaling = glm::mat4(1.0F);
glm::mat4 rotation = glm::mat4(1.0F);
return translation * rotation * scaling;
}

//The triangle is in the lower left corner
glm::mat4 createModelMatrixForTriangle(void)
{
glm::mat4 translation = glm::translate(glm::vec3(1.3F, 0.0F, 0.0F));
glm::mat4 scaling = glm::mat4(1.0F);
glm::mat4 rotation = glm::mat4(1.0F);
return translation * rotation * scaling;
}


And my vertex shader code where (I think) I have the problem:


#version 410 core

layout(location = 0) in vec3 cube_position;
layout(location = 1) in vec3 vertexColor;
layout(location = 3) in vec3 triangle_position;

out vec3 fragmentColor;

uniform mat4 MVP; //Model-View-Projection
uniform mat4 MVP_triangle;

void main() {
vec4 cube_pos = (MVP * vec4(cube_position, 1));
vec4 triangle_pos = (MVP_triangle * vec4(triangle_position, 1));
gl_Position = triangle_pos;// * cube_pos; ????

// The color of each vertex will be interpolated to produce the color of each fragment
fragmentColor = vertexColor;
}


I don't know if this is the right way... Can someone give me a hand?

Thank you =)

tonyo_au
02-10-2014, 07:41 PM
You seem very confused about how a vertex shader works. It takes 1 vertex and applies the transformation to it. Therefore you should have only 1 input vertex and 1 MVP in the shader.
your sequence is basically

1) load the shader porgram
2) bind the cube vertex buffer
3) set the MVP in the shader to the cube matrix
4) do draw of cube
5) bind the triangle buffer
6) set the MVP in the shader to the triangle matrix
7) do draw triangle

many-as-one
02-11-2014, 12:33 PM
Thank you very much for your reply, I got it! :)