I am trying to create six sides for a cylinder using OpenGL and two triangles for each side. I am currently using wireframe mode, so I can see the triangles that are being used. I finished by code for the cylinderVertices array and the cylinderIndices array, but whenever I run the program, the base comes out perfectly, but the sides are messed up. Is there something wrong with the angles that I am using for the sine and cosine coordinates in my cylinderVertices array or do my indices need fixing in my cylinderIndices array? Maybe someone can help me give the right coordinates. Here is my code:
#include <GL\glew.h>
#include <GLFW\glfw3.h>
#include <iostream>
// GLM library
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
using namespace std;
int width, height;
const double PI = 3.14159;
const float toRadians = PI / 180.0f;
// Draw Primitive(s)
void draw() {
GLenum mode = GL_TRIANGLES;
GLsizei indices = 63;
glDrawElements(mode, indices, GL_UNSIGNED_BYTE, nullptr);
}
// Create and Compile Shaders
static GLuint CompileShader(const string& source, GLuint shaderType) {
// Create Shader Object
GLuint shaderID = glCreateShader(shaderType);
const char* src = source.c_str();
// Attach source code to Shader object
glShaderSource(shaderID, 1, &src, nullptr);
// Compile Shader
glCompileShader(shaderID);
// Return ID of Compiled shader
return shaderID;
}
// Create Program Object
static GLuint CreateShaderProgram(const string& vertexShader, const string& fragmentShader) {
// Compile vertex shader
GLuint vertexShaderComp = CompileShader(vertexShader, GL_VERTEX_SHADER);
// Compile fragment shader
GLuint fragmentShaderComp = CompileShader(fragmentShader, GL_FRAGMENT_SHADER);
// Create program object
GLuint shaderProgram = glCreateProgram();
// Attch vertex and fragment shaders to program object
glAttachShader(shaderProgram, vertexShaderComp);
glAttachShader(shaderProgram, fragmentShaderComp);
// Link shaders to create executable
glLinkProgram(shaderProgram);
// Delete compiled vertex and fragment shaders
glDeleteShader(vertexShaderComp);
glDeleteShader(fragmentShaderComp);
// Return Shader Program
return shaderProgram;
}
int main(void) {
width = 640; height = 480;
GLFWwindow* window;
// Initialize the library
if (!glfwInit())
return -1;
// Create a windowed mode window and its OpenGL context
window = glfwCreateWindow(width, height, "Main Window", NULL, NULL);
if (!window) {
glfwTerminate();
return -1;
}
// Make the window's context current
glfwMakeContextCurrent(window);
// Initialize GLEW
if (glewInit() != GLEW_OK)
cout << "Error!" << endl;
GLfloat cylinderVertices[] = {
// Base of the cylinder
// Triangle One // Color
0.0, 0.0, 0.0, 1.0, 0.0, 0.0, // Vertex 0 red
cos( 0 * toRadians), sin( 0 * toRadians), 0.0, 0.0, 1.0, 0.0, // Vertex 1 green
cos( 60 * toRadians), sin( 60 * toRadians), 0.0, 0.0, 0.0, 1.0, // Vertex 2 blue
// Part of Triangle Two
cos(120 * toRadians), sin(120 * toRadians), 0.0, 1.0, 0.0, 1.0, // Vertex 3 purple
// Part of Triangle Three
cos(180 * toRadians), sin(180 * toRadians), 0.0, 0.0, 1.0, 0.0, // Vertex 4 greem
// Part of Triangle Four
cos(240 * toRadians), sin(240 * toRadians), 0.0, 0.0, 0.0, 1.0, // Vertex 5 blue
// Part of Triangle Five
cos(300 * toRadians), sin(300 * toRadians), 0.0, 1.0, 0.0, 1.0, // Vertex 6 purple
// Part of Triangle Six
cos(360 * toRadians), sin(360 * toRadians), 0.0, 0.0, 1.0, 0.0, // Vertex 7 green
// Sides of the cylinder
// Part of Triangle Seven
cos( 0 * toRadians), sin( 0 * toRadians), 2.0, 1.0, 0.0, 0.0, // Vertex 8 red
// Part of Triangle Eight
cos( 45 * toRadians), sin( 45 * toRadians), 2.0, 0.0, 1.0, 0.0, // Vertex 9 green
// Part of Triangle Nine
cos( 60 * toRadians), sin( 60 * toRadians), 2.0, 0.0, 0.0, 1.0, // Vertex 10 blue
// Part of Triangle Ten
cos( 105 * toRadians), sin( 105 * toRadians), 2.0, 1.0, 0.0, 1.0, // Vertex 11 purple
// Part of Triangle Eleven
cos( 120 * toRadians), sin( 120 * toRadians), 2.0, 1.0, 0.0, 0.0, // Vertex 12 red
// Part of Triangle Twelve
cos( 165 * toRadians), sin( 165 * toRadians), 2.0, 0.0, 1.0, 0.0, // Vertex 13 green
// Part of Triangle Thirteen
cos( 180 * toRadians), sin( 180 * toRadians), 2.0, 0.0, 0.0, 1.0, // Vertex 14 blue
// Part of Triangle Fourteen
cos( 225 * toRadians), sin( 225 * toRadians), 2.0, 1,0, 0.0, 1.0, // Vertex 15 purple
// Part of Triangle Fifteen
cos( 240 * toRadians), sin( 240 * toRadians), 2.0, 1.0, 0.0, 0.0 // Vertex 16 red
};
// Define element indices
GLubyte cylinderIndices[] = {
0,1,2,
0,2,3,
0,3,4,
0,4,5,
0,5,6,
0,6,7,
1,2,8,
2,8,9,
3,2,10,
2,9,10,
3,10,11,
3,4,11,
4,11,12,
4,5,12,
5,12,13,
5,6,13,
6,13,14,
5,6,14,
5,6,15,
6,1,15,
1,6,8
};
// Enable Depth Buffer
glEnable(GL_DEPTH_TEST);
// Wireframe mode
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
GLuint VBO, EBO, VAO;
glGenBuffers(1, &VBO); // Create VBO and returns ID
glGenBuffers(1, &EBO); // Create EBO
glGenVertexArrays(1, &VAO); // Create VAO
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO); // Select VBO and activate buffer
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); // Select EBO
glBufferData(GL_ARRAY_BUFFER, sizeof(cylinderVertices), cylinderVertices, GL_STATIC_DRAW); // Load vertex attributes
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(cylinderIndices), cylinderIndices, GL_STATIC_DRAW); // Load indices attributes
// Specify attributes location and layout to GPU
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
// Color attribute location and layout
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
glBindVertexArray(0);
// Vertex shader source code
string vertexShaderSource =
"#version 330 core\n"
"layout(location = 0) in vec4 vPosition;"
"layout(location = 1) in vec4 aColor;"
"out vec4 oColor;"
"uniform mat4 model;"
"uniform mat4 view;"
"uniform mat4 projection;"
"void main()\n"
"{\n"
"gl_Position = projection * view * model * vPosition;"
"oColor = aColor;"
"}\n";
// Fragment shader source code
string fragmentShaderSource =
"#version 330 core\n"
"in vec4 oColor;"
"out vec4 fragColor;"
"void main()\n"
"{\n"
"fragColor = oColor;"
"}\n";
// Creating Shader Program
GLuint shaderProgram = CreateShaderProgram(vertexShaderSource, fragmentShaderSource);
while (!glfwWindowShouldClose(window)) {
// Resize window and graphics simultaneously
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
// Render here
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Use Shader Program exe and select VAO before drawing
glUseProgram(shaderProgram); // Call Shader per-frame when updating attributes
// Declare identity matrix
glm::mat4 modelMatrix(1.0f);
glm::mat4 viewMatrix(1.0f);
glm::mat4 projectionMatrix(1.0f);
// Initialize transforms
modelMatrix = glm::scale(modelMatrix, glm::vec3(0.5f, 0.5f, 0.5f));
// I increased the third argument from -3.0f to -6.0f to make the object smaller
viewMatrix = glm::translate(viewMatrix, glm::vec3(0.0f, 0.0f, -6.0f));
// I changed up somme of the arguments, so the object would tilt left instead of toward me
viewMatrix = glm::rotate(viewMatrix, 45.0f * toRadians, glm::vec3(-0.5f, 1.0f, 1.5f));
projectionMatrix = glm::perspective(45.0f * toRadians, (GLfloat)width / (GLfloat)height, 0.1f, 100.0f);
// Select uniform shader and variable
GLuint modelLoc = glGetUniformLocation(shaderProgram, "model");
GLuint viewLoc = glGetUniformLocation(shaderProgram, "view");
GLuint projectionLoc = glGetUniformLocation(shaderProgram, "projection");
// Pass transform to Shader
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(viewMatrix));
glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projectionMatrix));
glBindVertexArray(VAO); // User-defined VAO must be called before draw
for (GLuint i = 0; i < 4; i++) {
glm::mat4 modelMatrix(1.0f);
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(modelMatrix));
// Draw primitive(s)
draw();
}
// Unbind Shader exe and VOA after drawing per frame
glBindVertexArray(0); // In case different VAO will be used after
glUseProgram(0); // In case different shader will be used after
glBindVertexArray(VAO);
// Swap front and back buffers
glfwSwapBuffers(window);
// Poll for and process events
glfwPollEvents();
}
glfwTerminate();
return 0;
}
This fixed the problem:
GLfloat cylinderVertices[] = {
// Base of the cylinder
// Triangle One // Color
0.0, 0.0, 0.0, 1.0, 0.0, 0.0, // Vertex 0 red
cos( 0 * toRadians), sin( 0 * toRadians), 0.0, 0.0, 1.0, 0.0, // Vertex 1 green
cos( 60 * toRadians), sin( 60 * toRadians), 0.0, 0.0, 0.0, 1.0, // Vertex 2 blue
// Part of Triangle Two
cos(120 * toRadians), sin(120 * toRadians), 0.0, 1.0, 0.0, 1.0, // Vertex 3 purple
// Part of Triangle Three
cos(180 * toRadians), sin(180 * toRadians), 0.0, 0.0, 1.0, 0.0, // Vertex 4 greem
// Part of Triangle Four
cos(240 * toRadians), sin(240 * toRadians), 0.0, 0.0, 0.0, 1.0, // Vertex 5 blue
// Part of Triangle Five
cos(300 * toRadians), sin(300 * toRadians), 0.0, 1.0, 0.0, 1.0, // Vertex 6 purple
// Part of Triangle Six
cos(360 * toRadians), sin(360 * toRadians), 0.0, 0.0, 1.0, 0.0, // Vertex 7 green
// Sides of the cylinder
// Part of Triangle Seven
cos( 0 * toRadians), sin( 0 * toRadians), 2.0, 1.0, 0.0, 0.0, // Vertex 8 red
// Part of Triangle Eight
cos( 60 * toRadians), sin( 60 * toRadians), 2.0, 0.0, 1.0, 0.0, // Vertex 9 green
// Part of Triangle Nine
cos( 120 * toRadians), sin( 120 * toRadians), 2.0, 0.0, 0.0, 1.0, // Vertex 10 blue
// Part of Triangle Ten
cos( 180 * toRadians), sin( 180 * toRadians), 2.0, 1.0, 0.0, 1.0, // Vertex 11 purple
// Part of Triangle Eleven
cos( 240 * toRadians), sin( 240 * toRadians), 2.0, 1.0, 0.0, 0.0, // Vertex 12 red
// Part of Triangle Twelve
cos( 300 * toRadians), sin( 300 * toRadians), 2.0, 0.0, 1.0, 0.0, // Vertex 13 green
};
// Define element indices
GLubyte cylinderIndices[] = {
// Bottom base
0,1,2,
0,2,3,
0,3,4,
0,4,5,
0,5,6,
0,6,7,
// Sides
1,2,8,
2,9,8,
2,3,9,
3,10,9,
3,4,10,
4,11,10,
5,11,4,
5,12,11,
5,6,12,
6,13,12,
6,1,13,
1,8,13
};
Related
I am trying to create a cylinder and plane to put underneath cylinder. Before I created a new vertex buffer object for the plane, the cylinder was rendering just fine. But for some reason, neither the cylinder or the plane are rendering when I run the program. I have created an EBO for the cylinder, but I am still getting a black window. I don't know if I need to create an EBO for each shape and a VAO for each shape or if there is something wrong with my draw function. Can someone point out what may be the problem? Here is my code:
#include <GL\glew.h>
#include <GLFW\glfw3.h>
#include <iostream>
// GLM library
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
using namespace std;
int width, height;
const double PI = 3.14159;
const float toRadians = PI / 180.0f;
// Draw Primitive(s)
void draw() {
GLenum mode = GL_TRIANGLES;
GLsizei indices = 60;
glDrawElements(mode, indices, GL_UNSIGNED_BYTE, nullptr);
}
// Create and Compile Shaders
static GLuint CompileShader(const string& source, GLuint shaderType) {
// Create Shader Object
GLuint shaderID = glCreateShader(shaderType);
const char* src = source.c_str();
// Attach source code to Shader object
glShaderSource(shaderID, 1, &src, nullptr);
// Compile Shader
glCompileShader(shaderID);
// Return ID of Compiled shader
return shaderID;
}
// Create Program Object
static GLuint CreateShaderProgram(const string& vertexShader, const string& fragmentShader) {
// Compile vertex shader
GLuint vertexShaderComp = CompileShader(vertexShader, GL_VERTEX_SHADER);
// Compile fragment shader
GLuint fragmentShaderComp = CompileShader(fragmentShader, GL_FRAGMENT_SHADER);
// Create program object
GLuint shaderProgram = glCreateProgram();
// Attch vertex and fragment shaders to program object
glAttachShader(shaderProgram, vertexShaderComp);
glAttachShader(shaderProgram, fragmentShaderComp);
// Link shaders to create executable
glLinkProgram(shaderProgram);
// Delete compiled vertex and fragment shaders
glDeleteShader(vertexShaderComp);
glDeleteShader(fragmentShaderComp);
// Return Shader Program
return shaderProgram;
}
int main(void) {
width = 640; height = 480;
GLFWwindow* window;
// Initialize the library
if (!glfwInit())
return -1;
// Create a windowed mode window and its OpenGL context
window = glfwCreateWindow(width, height, "Main Window", NULL, NULL);
if (!window) {
glfwTerminate();
return -1;
}
// Make the window's context current
glfwMakeContextCurrent(window);
// Initialize GLEW
if (glewInit() != GLEW_OK)
cout << "Error!" << endl;
GLfloat cylinderVertices[] = {
// Base of the cylinder
// Triangle One // Color
0.0, 0.0, 0.0, 1.0, 0.0, 0.0, // Vertex 0 red
cos(0 * toRadians), sin(0 * toRadians), 0.0, 0.0, 1.0, 0.0, // Vertex 1 green
cos(60 * toRadians), sin(60 * toRadians), 0.0, 0.0, 0.0, 1.0, // Vertex 2 blue
// Part of Triangle Two
cos(120 * toRadians), sin(120 * toRadians), 0.0, 1.0, 0.0, 1.0, // Vertex 3 purple
// Part of Triangle Three
cos(180 * toRadians), sin(180 * toRadians), 0.0, 0.0, 1.0, 0.0, // Vertex 4 greem
// Part of Triangle Four
cos(240 * toRadians), sin(240 * toRadians), 0.0, 0.0, 0.0, 1.0, // Vertex 5 blue
// Part of Triangle Five
cos(300 * toRadians), sin(300 * toRadians), 0.0, 1.0, 0.0, 1.0, // Vertex 6 purple
// Part of Triangle Six
cos(360 * toRadians), sin(360 * toRadians), 0.0, 0.0, 1.0, 0.0, // Vertex 7 green
// Sides of the cylinder
// Part of Triangle Seven
cos(0 * toRadians), sin(0 * toRadians), 2.0, 1.0, 0.0, 0.0, // Vertex 8 red
// Part of Triangle Eight
cos(60 * toRadians), sin(60 * toRadians), 2.0, 0.0, 1.0, 0.0, // Vertex 9 green
// Part of Triangle Nine
cos(120 * toRadians), sin(120 * toRadians), 2.0, 0.0, 0.0, 1.0, // Vertex 10 blue
// Part of Triangle Ten
cos(180 * toRadians), sin(180 * toRadians), 2.0, 1.0, 0.0, 1.0, // Vertex 11 purple
// Part of Triangle Eleven
cos(240 * toRadians), sin(240 * toRadians), 2.0, 1.0, 0.0, 0.0, // Vertex 12 red
// Part of Triangle Twelve
cos(300 * toRadians), sin(300 * toRadians), 2.0, 0.0, 1.0, 0.0, // Vertex 13 green
};
// Define element indices
GLubyte cylinderIndices[] = {
// Bottom base
0,1,2,
0,2,3,
0,3,4,
0,4,5,
0,5,6,
0,6,7,
// Sides
1,2,8,
2,9,8,
2,3,9,
3,10,9,
3,4,10,
4,11,10,
5,11,4,
5,12,11,
5,6,12,
6,13,12,
6,1,13,
1,8,13
};
GLfloat planeVertices[] = {
// positon attributes (x,y,z)
0.0f, 0.0f, 0.0f, // vert 14
0.0f, 1.0f, 0.0f, // red
0.0f, 0.866f, 0.0f, // vert 15
0.0f, 1.0f, 0.0f, // green
1.0f, 0.0f, 0.0f, // vert 16
0.0f, 1.0f, 0.0f, // blue
1.0f, 0.866f, 0.0f, // vert 17
1.0f, 0.0f, 1.0f // purple
};
// Define element indices
GLubyte planeIndices[] = {
14,16,15,
16,17,15
};
// Enable Depth Buffer
glEnable(GL_DEPTH_TEST);
// Wireframe mode
// glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
GLuint cylinderVBO, planeVBO, EBO, VAO;
glGenBuffers(1, &cylinderVBO); // Create VBO and returns ID
glGenBuffers(1, &planeVBO);
glGenBuffers(1, &EBO); // Create EBO
glGenVertexArrays(1, &VAO); // Create VAO
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, cylinderVBO); // Select VBO and activate buffer
glBindBuffer(GL_ARRAY_BUFFER, planeVBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); // Select EBO
glBufferData(GL_ARRAY_BUFFER, sizeof(cylinderVertices), cylinderVertices, GL_STATIC_DRAW); // Load vertex attributes
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(cylinderIndices), cylinderIndices, GL_STATIC_DRAW); // Load indices attributes
glBufferData(GL_ARRAY_BUFFER, sizeof(planeVertices), planeVertices, GL_STATIC_DRAW); // Load vertex attributes
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(planeIndices), planeIndices, GL_STATIC_DRAW); // Load indices attributes
// Specify attributes location and layout to GPU
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
// Color attribute location and layout
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
glBindVertexArray(0);
// Vertex shader source code
string vertexShaderSource =
"#version 330 core\n"
"layout(location = 0) in vec4 vPosition;"
"layout(location = 1) in vec4 aColor;"
"out vec4 oColor;"
"uniform mat4 model;"
"uniform mat4 view;"
"uniform mat4 projection;"
"void main()\n"
"{\n"
"gl_Position = projection * view * model * vPosition;"
"oColor = aColor;"
"}\n";
// Fragment shader source code
string fragmentShaderSource =
"#version 330 core\n"
"in vec4 oColor;"
"out vec4 fragColor;"
"void main()\n"
"{\n"
"fragColor = oColor;"
"}\n";
// Creating Shader Program
GLuint shaderProgram = CreateShaderProgram(vertexShaderSource, fragmentShaderSource);
while (!glfwWindowShouldClose(window)) {
// Resize window and graphics simultaneously
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
// Render here
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Use Shader Program exe and select VAO before drawing
glUseProgram(shaderProgram); // Call Shader per-frame when updating attributes
// Declare identity matrix
glm::mat4 modelMatrix(1.0f);
glm::mat4 viewMatrix(1.0f);
glm::mat4 projectionMatrix(1.0f);
// Initialize transforms
modelMatrix = glm::scale(modelMatrix, glm::vec3(0.5f, 0.5f, 0.5f));
// I increased the third argument from -3.0f to -6.0f to make the object smaller
// Moved the cup to the right by increasing the x coordinate
viewMatrix = glm::translate(viewMatrix, glm::vec3(0.5f, 0.0f, -6.0f));
// I changed up somme of the arguments, so the object would tilt right instead of toward me
viewMatrix = glm::rotate(viewMatrix, 45.0f * toRadians, glm::vec3(-0.5f, 1.0f, 1.5f));
projectionMatrix = glm::perspective(45.0f * toRadians, (GLfloat)width / (GLfloat)height, 0.1f, 100.0f);
// Select uniform shader and variable
GLuint modelLoc = glGetUniformLocation(shaderProgram, "model");
GLuint viewLoc = glGetUniformLocation(shaderProgram, "view");
GLuint projectionLoc = glGetUniformLocation(shaderProgram, "projection");
// Pass transform to Shader
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(viewMatrix));
glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projectionMatrix));
glBindVertexArray(VAO); // User-defined VAO must be called before draw
for (GLuint i = 0; i < 4; i++) {
glm::mat4 modelMatrix(1.0f);
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(modelMatrix));
// Draw primitive(s)
draw();
}
// Unbind Shader exe and VOA after drawing per frame
glBindVertexArray(0); // In case different VAO will be used after
glUseProgram(0); // In case different shader will be used after
glBindVertexArray(VAO);
// Swap front and back buffers
glfwSwapBuffers(window);
// Poll for and process events
glfwPollEvents();
}
glfwTerminate();
return 0;
}
Ok, so there is a bit of a structural problem with your plane & cylinder buffer layouts (ind indexing).
Vertex Buffers
First, let's start with the vertex data and associated buffers (we'll worry about indexing later).
You have 2 choices for how to send the data to the GPU.
Seperate vertex buffers for each shape. i.e. specify a cylinderVBO (with all cylinder vertices) and a planeVBO (with all plane vertices).
Combine both sets of vertices into a single vertex buffer.
If you are specifying the buffers separately, then setup EACH buffer in turn.
// do the cylinder buffer first!
glGenBuffers(1, &cylinderVBO);
glBindBuffer(GL_ARRAY_BUFFER, cylinderVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(cylinderVertices), cylinderVertices, GL_STATIC_DRAW); // Load vertex attributes
// NOW do the plane buffer!
glGenBuffers(1, &planeVBO);
glBindBuffer(GL_ARRAY_BUFFER, planeVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(planeVertices), planeVertices, GL_STATIC_DRAW); // Load vertex attributes
If you want to combine the buffers into one big blob, then generate one big array:
GLfloat allVertices[] = {
// ------------- cylinderVertices[]
// Base of the cylinder
// Triangle One // Color
0.0, 0.0, 0.0, 1.0, 0.0, 0.0, // Vertex 0 red
cos(0 * toRadians), sin(0 * toRadians), 0.0, 0.0, 1.0, 0.0, // Vertex 1 green
cos(60 * toRadians), sin(60 * toRadians), 0.0, 0.0, 0.0, 1.0, // Vertex 2 blue
// Part of Triangle Two
cos(120 * toRadians), sin(120 * toRadians), 0.0, 1.0, 0.0, 1.0, // Vertex 3 purple
// Part of Triangle Three
cos(180 * toRadians), sin(180 * toRadians), 0.0, 0.0, 1.0, 0.0, // Vertex 4 greem
// Part of Triangle Four
cos(240 * toRadians), sin(240 * toRadians), 0.0, 0.0, 0.0, 1.0, // Vertex 5 blue
// Part of Triangle Five
cos(300 * toRadians), sin(300 * toRadians), 0.0, 1.0, 0.0, 1.0, // Vertex 6 purple
// Part of Triangle Six
cos(360 * toRadians), sin(360 * toRadians), 0.0, 0.0, 1.0, 0.0, // Vertex 7 green
// Sides of the cylinder
// Part of Triangle Seven
cos(0 * toRadians), sin(0 * toRadians), 2.0, 1.0, 0.0, 0.0, // Vertex 8 red
// Part of Triangle Eight
cos(60 * toRadians), sin(60 * toRadians), 2.0, 0.0, 1.0, 0.0, // Vertex 9 green
// Part of Triangle Nine
cos(120 * toRadians), sin(120 * toRadians), 2.0, 0.0, 0.0, 1.0, // Vertex 10 blue
// Part of Triangle Ten
cos(180 * toRadians), sin(180 * toRadians), 2.0, 1.0, 0.0, 1.0, // Vertex 11 purple
// Part of Triangle Eleven
cos(240 * toRadians), sin(240 * toRadians), 2.0, 1.0, 0.0, 0.0, // Vertex 12 red
// Part of Triangle Twelve
cos(300 * toRadians), sin(300 * toRadians), 2.0, 0.0, 1.0, 0.0, // Vertex 13 green
// ------------- planeVertices[]
// positon attributes (x,y,z)
0.0f, 0.0f, 0.0f, // vert 14
0.0f, 1.0f, 0.0f, // red
0.0f, 0.866f, 0.0f, // vert 15
0.0f, 1.0f, 0.0f, // green
1.0f, 0.0f, 0.0f, // vert 16
0.0f, 1.0f, 0.0f, // blue
1.0f, 0.866f, 0.0f, // vert 17
1.0f, 0.0f, 1.0f // purple
};
// Now generate a vertex buffer with all vertex data in one buffer
GLuint allVerticesVBO;
glGenBuffers(1, & allVerticesVBO);
glBindBuffer(GL_ARRAY_BUFFER, allVerticesVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(allVertices), allVertices, GL_STATIC_DRAW); // Load vertex attributes
Index Buffers
Now, depending on how you set the vertex buffers up previously, you will have to do one (but not both!) of the following.
If you have separated your vertex buffers (one for cylinder, one for the plane), then you will need separate index buffers as well.
// we need two index buffers, one for the plane, one for the cylinder
GLuint cylinderIBO, planeIBO;
//--------------------
// cylinder
//--------------------
// Define element indices
GLubyte cylinderIndices[] = {
// Bottom base
0,1,2,
0,2,3,
0,3,4,
0,4,5,
0,5,6,
0,6,7,
// Sides
1,2,8,
2,9,8,
2,3,9,
3,10,9,
3,4,10,
4,11,10,
5,11,4,
5,12,11,
5,6,12,
6,13,12,
6,1,13,
1,8,13
};
glGenBuffers(1, &cylinderIBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cylinderIBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(cylinderIndices), cylinderIndices, GL_STATIC_DRAW); // Load indices attributes
//--------------------
// plane
//--------------------
GLubyte planeIndices[] = {
0,2,1, //< NOTE: These must start at ZERO in this case!
2,3,1
};
glGenBuffers(1, &planeIBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, planeIBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(planeIndices), planeIndices, GL_STATIC_DRAW); // Load indices attributes
If however you wish to combine both shapes into a single buffer, then instead do this:
// we need one index buffer!
GLuint allIndicesIBO;
// Define element indices
GLubyte allIndices[] = {
//--------------------
// cylinder
//--------------------
// Bottom base
0,1,2,
0,2,3,
0,3,4,
0,4,5,
0,5,6,
0,6,7,
// Sides
1,2,8,
2,9,8,
2,3,9,
3,10,9,
3,4,10,
4,11,10,
5,11,4,
5,12,11,
5,6,12,
6,13,12,
6,1,13,
1,8,13,
//--------------------
// plane
//--------------------
14,16,15, //< NOTE: these now start at 14!
16,17,15
};
glGenBuffers(1, &allIndicesIBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, allIndicesIBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(allIndices), allIndices, GL_STATIC_DRAW); // Load indices attributes
Vertex Buffer Objects
If you have set up separate buffers for each shape, then you have two choices in how you set up the VAOs.
1.1 Create two VAO's, one for each shape.
GLuint cylinderVAO, planeVAO;
// generate a bind new VAO for the cylinder
glGenVertexArrays(1, & cylinderVAO);
glBindVertexArray(cylinderVAO);
// specify which buffers the current VAO should use
glBindBuffer(GL_ARRAY_BUFFER, cylinderVBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cylinderIBO);
// Specify attributes location and layout to GPU
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
// Color attribute location and layout
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
// generate a bind new VAO for the plane
glGenVertexArrays(1, &planeVAO);
glBindVertexArray(planeVAO);
// specify which buffers the current VAO should use
glBindBuffer(GL_ARRAY_BUFFER, planeVBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, planeIBO);
// Specify attributes location and layout to GPU
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
// Color attribute location and layout
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
To render the data like this, you'll need 2 draw calls, one for each shape.
glBindVertexArray(cylinderVAO);
glDrawElements(mode, 54, GL_UNSIGNED_BYTE, nullptr);
glBindVertexArray(planeVAO);
glDrawElements(mode, 6, GL_UNSIGNED_BYTE, nullptr);
1.2 Setup 1 VAO, but rebind the vertex & index buffers on the fly.
GLuint sharedVAO;
// generate a bind new VAO for the cylinder
glGenVertexArrays(1, & sharedVAO);
glBindVertexArray(sharedVAO);
// Specify attributes location and layout to GPU
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
// Color attribute location and layout
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
To render the data like this, you'll need 2 draw calls, one for each shape.
// specify the shared vertex format
glBindVertexArray(sharedVAO);
// specify data sources for cylinder, and render
glBindBuffer(GL_ARRAY_BUFFER, cylinderVBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cylinderIBO);
glDrawElements(mode, 54, GL_UNSIGNED_BYTE, nullptr);
// specify data sources for plane, and render
glBindBuffer(GL_ARRAY_BUFFER, planeVBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, planeIBO);
glDrawElements(mode, 6, GL_UNSIGNED_BYTE, nullptr);
If however you have specified all of the data in a single vertex buffer, and a single index buffer, then instead you can do:
GLuint sharedVAO;
// generate a bind new VAO for the cylinder
glGenVertexArrays(1, & sharedVAO);
glBindVertexArray(sharedVAO);
// specify data sources for the VAO
glBindBuffer(GL_ARRAY_BUFFER, allVerticesVBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, allIndicesIBO);
// Specify attributes location and layout to GPU
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
// Color attribute location and layout
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
To render the data like this, you'll need 1 draw call.
// render both shapes in one draw call
glBindVertexArray(sharedVAO);
glDrawElements(mode, 60, GL_UNSIGNED_BYTE, nullptr);
And that's it.
I am trying to create a lamp or light source in OpenGL in the form of a cube. My current code renders a cylinder sitting on a plane with textures whenever I run the program. I have defined planePositions and planeRotations and I have used those variables in a for loop to form a cube that will be my shining lamp. But for some reason, a lamp is not rendering at all. Is there a way to incorporate my current plane into the for loop or is there a better way to create a lamp? Here is my code:
#include <GL\glew.h>
#include <GLFW\glfw3.h>
#include <iostream>
// GLM library
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <SOIL2.h>
using namespace std;
int width, height;
const double PI = 3.14159;
const float toRadians = PI / 180.0f;
// Input Function prototypes
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods);
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
void cursor_position_callback(GLFWwindow* window, double xpos, double ypos);
void mouse_button_callback(GLFWwindow* window, int button, int action, int mods);
// Initialize FOV
GLfloat fov = 45.f;
double cameraSpeedPerSecond = 2.5;
// Define Camera Attributes
glm::vec3 cameraPosition;
glm::vec3 target;
glm::vec3 cameraDirection;
glm::vec3 worldUp;
glm::vec3 cameraRight;
glm::vec3 cameraUp;
// Declare target prototype
glm::vec3 getTarget();
// Camera transformation prototype
void TransformCamera();
// Boolean for keys and mouse buttons
bool keys[1024], mouseButtons[3];
// Boolean to check camera transformations
bool isPanning = false, isOrbiting = false;
bool projectionIsPerspective = true;
// Radius, Pitch, and Yaw
GLfloat radius = 3.f, rawYaw = 0.f, rawPitch = 0.f, degYaw, degPitch;
GLfloat deltaTime = 0.f, lastFrame = 0.f;
GLfloat lastX = 400, lastY = 300, xChange, yChange;
bool firstMouseMove = true; // Detect inititial mouse movement
// Light source position
glm::vec3 lightPosition(1.0f, 1.0f, 1.0f);
void initCamera();
void UProcessInput(GLFWwindow* window);
// Draw Primitive(s)
void draw() {
GLenum mode = GL_TRIANGLES;
GLsizei indices = 62;
glDrawElements(mode, indices, GL_UNSIGNED_BYTE, nullptr);
}
// Create and Compile Shaders
static GLuint CompileShader(const string& source, GLuint shaderType) {
// Create Shader Object
GLuint shaderID = glCreateShader(shaderType);
const char* src = source.c_str();
// Attach source code to Shader object
glShaderSource(shaderID, 1, &src, nullptr);
// Compile Shader
glCompileShader(shaderID);
// Return ID of Compiled shader
return shaderID;
}
// Create Program Object
static GLuint CreateShaderProgram(const string& vertexShader, const string& fragmentShader) {
// Compile vertex shader
GLuint vertexShaderComp = CompileShader(vertexShader, GL_VERTEX_SHADER);
// Compile fragment shader
GLuint fragmentShaderComp = CompileShader(fragmentShader, GL_FRAGMENT_SHADER);
// Create program object
GLuint shaderProgram = glCreateProgram();
// Attch vertex and fragment shaders to program object
glAttachShader(shaderProgram, vertexShaderComp);
glAttachShader(shaderProgram, fragmentShaderComp);
// Link shaders to create executable
glLinkProgram(shaderProgram);
// Delete compiled vertex and fragment shaders
glDeleteShader(vertexShaderComp);
glDeleteShader(fragmentShaderComp);
// Return Shader Program
return shaderProgram;
}
int main(void) {
width = 640; height = 480;
GLFWwindow* window;
// Initialize the library
if (!glfwInit())
return -1;
// Create a windowed mode window and its OpenGL context
window = glfwCreateWindow(width, height, "Main Window", NULL, NULL);
if (!window) {
glfwTerminate();
return -1;
}
glfwSetScrollCallback(window, scroll_callback);
glfwSetCursorPosCallback(window, cursor_position_callback);
glfwSetKeyCallback(window, key_callback);
// Make the window's context current
glfwMakeContextCurrent(window);
// Initialize GLEW
if (glewInit() != GLEW_OK)
cout << "Error!" << endl;
initCamera();
GLfloat cylinderVertices[] = {
// Base of the cylinder
// Triangle One // Color
// Vertex 0 // Red // UV
0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.5, 0.0,
// Vertex 1 // Green // UV
cos(0 * toRadians), sin(0 * toRadians), 0.0, 0.0, 1.0, 0.0, 1.0, 0.0,
// Vertex 2 // Blue // UV
cos(60 * toRadians), sin(60 * toRadians), 0.0, 0.0, 0.0, 1.0, 1.0, 0.0,
// Part of Triangle Two
// Vertex 3 // Purple // UV
cos(120 * toRadians), sin(120 * toRadians), 0.0, 1.0, 0.0, 1.0, 1.0, 0.0,
// Part of Triangle Three
// Vertex 4 // Green // UV
cos(180 * toRadians), sin(180 * toRadians), 0.0, 0.0, 1.0, 0.0, 1.0, 0.0,
// Part of Triangle Four
// Vertex 5 // Blue // UV
cos(240 * toRadians), sin(240 * toRadians), 0.0, 0.0, 0.0, 1.0, 0.0, 0.0,
// Part of Triangle Five
// Vertex 6 // Purple // UV
cos(300 * toRadians), sin(300 * toRadians), 0.0, 1.0, 0.0, 1.0, 0.0, 0.0,
// Part of Triangle Six
// Vertex 7 // Green // UV
cos(360 * toRadians), sin(360 * toRadians), 0.0, 0.0, 1.0, 0.0, 0.0, 0.0,
// Sides of the cylinder
// Part of Triangle Seven
// Vertex 8 // Red // UV
cos(0 * toRadians), sin(0 * toRadians), 2.0, 1.0, 0.0, 0.0, 1.0, 1.0,
// Part of Triangle Eight
// Vertex 9 // Green // UV
cos(60 * toRadians), sin(60 * toRadians), 2.0, 0.0, 1.0, 0.0, 1.0, 1.0,
// Part of Triangle Nine
// Vertex 10 // Blue // UV
cos(120 * toRadians), sin(120 * toRadians), 2.0, 0.0, 0.0, 1.0, 1.0, 1.0,
// Part of Triangle Ten
// Vertex 11 // Purple // UV
cos(180 * toRadians), sin(180 * toRadians), 2.0, 1.0, 0.0, 1.0, 0.0, 1.0,
// Part of Triangle Eleven
// Vertex 12 // Red // UV
cos(240 * toRadians), sin(240 * toRadians), 2.0, 1.0, 0.0, 0.0, 0.0, 1.0,
// Part of Triangle Twelve
// Vertex 13 // Green // UV
cos(300 * toRadians), sin(300 * toRadians), 2.0, 0.0, 1.0, 0.0, 0.0, 1.0
};
// we need two index buffers, one for the plane, one for the cylinder
GLuint cylinderIBO, planeIBO, lampIBO;
// Define element indices
GLubyte cylinderIndices[] = {
// Bottom base
0,1,2,
0,2,3,
0,3,4,
0,4,5,
0,5,6,
0,6,7,
// Sides
1,2,8,
2,9,8,
2,3,9,
3,10,9,
3,4,10,
4,11,10,
5,11,4,
5,12,11,
5,6,12,
6,13,12,
6,1,13,
1,8,13
};
glGenBuffers(1, &cylinderIBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cylinderIBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(cylinderIndices), cylinderIndices, GL_STATIC_DRAW); // Load indices attributes
GLfloat planeVertices[] = {
// positon attributes (x,y,z)
-2.0f, 2.0f, 0.0f, // plane vertex 0
0.0f, 1.0f, 1.0f, // cyan
0.0f, 0.0, // UV
2.0f, 1.0f, -0.2f, // plane vertex 1
1.0f, 1.0f, 0.0f, // yellow
0.0f, 1.0f, // UV
-3.0f, 0.0f, 0.0f, // plane vertex 2
1.0f, 1.0f, 0.0f, // yellow
1.0f, 0.0, // UV
1.0f, -1.0f, -0.2f, // plane vertex 3
0.0f, 1.0f, 1.0f, // cyan
1.0f, 1.0f // UV
};
// Define element indicesd
GLubyte planeIndices[] = {
0,2,1,
2,3,1
};
// Plane Transforms
glm::vec3 planePositions[] = {
glm::vec3(0.0f, 0.0f, 0.5f),
glm::vec3(0.5f, 0.0f, 0.0f),
glm::vec3(0.0f, 0.0f, -0.5f),
glm::vec3(-0.5f, 0.0f, 0.0f),
glm::vec3(0.0f, 0.5f, 0.0f),
glm::vec3(0.0f, -0.5f, 0.0f)
};
glm::float32 planeRotations[] = {
0.0f, 90.0f, 0.0f, 50.0f, 90.0f, 90.0f
};
glGenBuffers(1, &planeIBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, planeIBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(planeIndices), planeIndices, GL_STATIC_DRAW); // Load indices attributes
GLfloat lampVertices[] = {
-0.5, -0.5, 0.0, // index 0
-0.5, 0.5, 0.0, // index 1
0.5, -0.5, 0.0, // index 2
0.5, 0.5, 0.0 // index 3
};
GLubyte lampIndices[] = {
0, 1, 2,
1, 2, 3
};
glGenBuffers(1, &lampIBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, lampIBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(lampIndices), lampIndices, GL_STATIC_DRAW); // Load indices attributes
// Enable Depth Buffer
glEnable(GL_DEPTH_TEST);
// Wireframe mode
// glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
GLuint cylinderVBO, planeVBO, EBO, lampVBO, lampEBO;
glGenBuffers(1, &cylinderVBO); // Create VBO and returns ID
glBindBuffer(GL_ARRAY_BUFFER, cylinderVBO); // Select VBO and activate buffer
glBufferData(GL_ARRAY_BUFFER, sizeof(cylinderVertices), cylinderVertices, GL_STATIC_DRAW); // Load vertex attributes
glGenBuffers(1, &planeVBO); // Create VBO and returns ID
glBindBuffer(GL_ARRAY_BUFFER, planeVBO); // Select VBO and activate buffer
glBufferData(GL_ARRAY_BUFFER, sizeof(planeVertices), planeVertices, GL_STATIC_DRAW); // Load vertex attributes
glGenBuffers(1, &EBO); // Create EBO
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); // Select EBO
glGenBuffers(1, &lampVBO); // Creat VBO and returns ID
glBindBuffer(GL_ARRAY_BUFFER, lampVBO); // Select VBO and activate buffer
glBufferData(GL_ARRAY_BUFFER, sizeof(lampVertices), lampVertices, GL_STATIC_DRAW); // Load vertex attributes
glGenBuffers(1, &lampEBO); // Create EBO
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, lampEBO); // Select EBO
GLuint cylinderVAO, planeVAO, lampVAO;
// generate a bind new VAO for the cylinder
glGenVertexArrays(1, &cylinderVAO);
glBindVertexArray(cylinderVAO);
// specify which buffers the current VAO should use
glBindBuffer(GL_ARRAY_BUFFER, cylinderVBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cylinderIBO);
// Specify attributes location and layout to GPU
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
// Color attribute location and layout
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
glEnableVertexAttribArray(2);
// generate a bind new VAO for the plane
glGenVertexArrays(1, &planeVAO);
glBindVertexArray(planeVAO);
// specify which buffers the current VAO should use
glBindBuffer(GL_ARRAY_BUFFER, planeVBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, planeIBO);
// Specify attributes location and layout to GPU
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
// Color attribute location and layout
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
glEnableVertexAttribArray(2);
glBindVertexArray(0);
// generate a bind new VAO for the lamp
glGenVertexArrays(1, &lampVAO);
glBindVertexArray(lampVAO);
// specify which buffers the current VAO should use
glBindBuffer(GL_ARRAY_BUFFER, lampVBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, lampIBO);
// Specify attributes location and layout to GPU
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
glBindVertexArray(0);
glBindVertexArray(cylinderVAO);
glDrawElements(GL_TRIANGLES, 54, GL_UNSIGNED_BYTE, nullptr);
glBindVertexArray(planeVAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, nullptr);
glBindVertexArray(lampVAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, nullptr);
// Load textures
int crateTexWidth, crateTexHeight, gridTexWidth, gridTexHeight;
unsigned char* crateImage = SOIL_load_image("crate.png", &crateTexWidth, &crateTexHeight, 0, SOIL_LOAD_RGB);
unsigned char* gridImage = SOIL_load_image("grid.png", &gridTexWidth, &gridTexHeight, 0, SOIL_LOAD_RGB);
// Generate Textures
GLuint crateTexture;
glGenTextures(1, &crateTexture);
glBindTexture(GL_TEXTURE_2D, crateTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, crateTexWidth, crateTexHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, crateImage);
glGenerateMipmap(GL_TEXTURE_2D);
SOIL_free_image_data(crateImage);
glBindTexture(GL_TEXTURE_2D, 0);
GLuint gridTexture;
glGenTextures(1, &gridTexture);
glBindTexture(GL_TEXTURE_2D, gridTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, gridTexWidth, gridTexHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, gridImage);
glGenerateMipmap(GL_TEXTURE_2D);
SOIL_free_image_data(gridImage);
glBindTexture(GL_TEXTURE_2D, 0);
// Vertex shader source code
string vertexShaderSource =
"#version 330 core\n"
"layout(location = 0) in vec3 vPosition;"
"layout(location = 1) in vec3 aColor;"
"layout(location = 2) in vec2 texCoord;"
"out vec3 oColor;"
"out vec2 oTexCoord;"
"uniform mat4 model;"
"uniform mat4 view;"
"uniform mat4 projection;"
"void main()\n"
"{\n"
"gl_Position = projection * view * model * vec4(vPosition.x, vPosition.y, vPosition.z, 1.0);"
"oColor = aColor;"
"oTexCoord = texCoord;"
"}\n";
// Fragment shader source code
string fragmentShaderSource =
"#version 330 core\n"
"in vec3 oColor;"
"in vec2 oTexCoord;"
"out vec4 fragColor;"
"uniform sampler2D myTexture;"
"uniform vec3 objectColor;"
"uniform vec3 lightColor;"
"uniform vec3 lightPos;"
"void main()\n"
"{\n"
"fragColor = texture(myTexture, oTexCoord) * vec4(objectColor * lightColor, 1.0f);"
"}\n";
// Lamp Vertex shader source code
string lampVertexShaderSource =
"#version 330 core\n"
"layout(location = 0) in vec3 vPosition;"
"uniform mat4 model;"
"uniform mat4 view;"
"uniform mat4 projection;"
"void main()\n"
"{\n"
"gl_Position = projection * view * model * vec4(vPosition.x, vPosition.y, vPosition.z, 1.0);"
"}\n";
// Lamp Fragment shader source code
string lampFragmentShaderSource =
"#version 330 core\n"
"out vec4 fragColor;"
"void main()\n"
"{\n"
"fragColor = vec4(1.0f);"
"}\n";
// Creating Shader Program
GLuint shaderProgram = CreateShaderProgram(vertexShaderSource, fragmentShaderSource);
GLuint lampShaderProgram = CreateShaderProgram(lampVertexShaderSource, lampFragmentShaderSource);
double currentTime = glfwGetTime();
// loop until th euser closes window
while (!glfwWindowShouldClose(window)) {
double newTime = glfwGetTime();
deltaTime = newTime - currentTime;
currentTime = newTime;
// Resize window and graphics simultaneously
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
// Render here
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
UProcessInput(window);
// Use Shader Program exe and select VAO before drawing
glUseProgram(shaderProgram); // Call Shader per-frame when updating attributes
// Declare identity matrix
glm::mat4 modelMatrix(1.0f);
glm::mat4 viewMatrix(1.0f);
glm::mat4 projectionMatrix(1.0f);
// Initialize transforms
modelMatrix = glm::scale(modelMatrix, glm::vec3(0.5f, 0.5f, 0.5f));
// I increased the third argument from -3.0f to -6.0f to make the object smaller
// Moved the cup to the right by increasing the x coordinate
//viewMatrix = glm::translate(viewMatrix, glm::vec3(0.5f, 0.0f, -6.0f));
// I changed up somme of the arguments, so the object would tilt right instead of toward me
//viewMatrix = glm::rotate(viewMatrix, 45.0f * toRadians, glm::vec3(-0.5f, 1.0f, 1.5f));
//
// Transforms the camera: move the camera back (z axis)
viewMatrix = glm::lookAt(cameraPosition, cameraPosition + cameraDirection, worldUp);
if (projectionIsPerspective) {
projectionMatrix = glm::perspective(45.0f * toRadians, (GLfloat)width / (GLfloat)height, 0.1f, 100.0f);
}
else
projectionMatrix = glm::ortho(-10.f, 10.f, -10.f * ((GLfloat)height / width), 10.f * ((GLfloat)height / width), 0.1f, 100.0f);
// Get matrix's uniform location and set matrix
// Select uniform shader and variable
GLuint modelLoc = glGetUniformLocation(shaderProgram, "model");
GLuint viewLoc = glGetUniformLocation(shaderProgram, "view");
GLuint projectionLoc = glGetUniformLocation(shaderProgram, "projection");
// Get light and object color, and light position location
GLint objectColorLoc = glGetUniformLocation(shaderProgram, "objectColor");
GLint lightColorLoc = glGetUniformLocation(shaderProgram, "lightColor");
GLint lightPosLoc = glGetUniformLocation(shaderProgram, "lightPos");
// Assign Light and Object Colors
glUniform3f(objectColorLoc, 0.46f, 0.36f, 0.25f);
glUniform3f(lightColorLoc, 1.0f, 1.0f, 1.0f);
// Set light position
glUniform3f(lightColorLoc, lightPosition.x, lightPosition.y, lightPosition.z);
// Pass transform to Shader
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(viewMatrix));
glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projectionMatrix));
glBindTexture(GL_TEXTURE_2D, crateTexture);
glBindVertexArray(cylinderVAO);
glDrawElements(GL_TRIANGLES, 54, GL_UNSIGNED_BYTE, nullptr);
glBindTexture(GL_TEXTURE_2D, gridTexture);
glBindVertexArray(planeVAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, nullptr); // User-defined VAO must be called before draw
for (GLuint i = 0; i < 4; i++) {
glm::mat4 modelMatrix(1.0f);
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(modelMatrix));
// Draw primitive(s)
draw();
}
// Unbind Shader exe and VOA after drawing per frame
glBindVertexArray(0); // In case different VAO will be used after
glUseProgram(0); // In case different shader will be used after
glUseProgram(lampShaderProgram);
// Get matrix's uniform location and set matrix
// Select uniform shader and variable
GLuint lampModelLoc = glGetUniformLocation(lampShaderProgram, "model");
GLuint lampViewLoc = glGetUniformLocation(lampShaderProgram, "view");
GLuint lampProjectionLoc = glGetUniformLocation(lampShaderProgram, "projection");
glUniformMatrix4fv(lampViewLoc, 1, GL_FALSE, glm::value_ptr(viewMatrix));
glUniformMatrix4fv(lampProjectionLoc, 1, GL_FALSE, glm::value_ptr(projectionMatrix));
glBindVertexArray(lampVAO); // Calls lamp VAO
// Transform planes to form cube
for (GLuint i = 0; i < 6; i++) {
glm::mat4 modelMatrix;
modelMatrix = glm::translate(modelMatrix, planePositions[i] / glm::vec3(8.,8.,8.) + lightPosition);
modelMatrix = glm::rotate(modelMatrix, planeRotations[i] * toRadians, glm::vec3(0.0f, 1.0f, 0.0f));
modelMatrix = glm::scale(modelMatrix, glm::vec3(.125f, .125f, .125f));
if (i >= 4)
modelMatrix = glm::rotate(modelMatrix, planeRotations[i] * toRadians, glm::vec3(1.0f, 0.0f, 0.0f));
glUniformMatrix4fv(lampModelLoc, 1, GL_FALSE, glm::value_ptr(modelMatrix));
// Draw primitive(s)
draw();
}
glBindVertexArray(0); // Deactivates vertex array object
glUseProgram(0); // In case different shader will be used after
// Swap front and back buffers
glfwSwapBuffers(window);
// Poll for and process events
glfwPollEvents();
}
glfwTerminate();
return 0;
}
// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
void UProcessInput(GLFWwindow* window) {
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
float cameraSpeed = cameraSpeedPerSecond * deltaTime;
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
cameraPosition += cameraSpeed * cameraDirection;
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
cameraPosition -= cameraSpeed * cameraDirection;
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
cameraPosition -= glm::normalize(glm::cross(cameraDirection, cameraUp)) * cameraSpeed;
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
cameraPosition += glm::normalize(glm::cross(cameraDirection, cameraUp)) * cameraSpeed;
if (glfwGetKey(window, GLFW_KEY_Q) == GLFW_PRESS)
cameraPosition -= cameraSpeed * cameraUp;
if (glfwGetKey(window, GLFW_KEY_E) == GLFW_PRESS)
cameraPosition += cameraSpeed * cameraUp;
}
// Define Input Callback functions
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
if (action == GLFW_PRESS)
{
keys[key] = true;
if (key == GLFW_KEY_P) {
projectionIsPerspective = !projectionIsPerspective;
}
}
else if (action == GLFW_RELEASE)
keys[key] = false;
}
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) {
cameraSpeedPerSecond += yoffset;
if (cameraSpeedPerSecond < 0) {
cameraSpeedPerSecond = 0;
}
}
double oldXPos = 0;
double oldYPos = 0;
void cursor_position_callback(GLFWwindow* window, double xpos, double ypos) {
int state = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT);
if (state == GLFW_PRESS)
{
float horizontalRotation = (xpos - oldXPos) * 0.01f;
float verticalRotation = (ypos - oldYPos) * -0.01f;
glm::mat4 rotationMat(1);
rotationMat = glm::rotate(rotationMat, horizontalRotation, cameraUp);
rotationMat = glm::rotate(rotationMat, verticalRotation, cameraRight);
cameraDirection = glm::vec3(rotationMat * glm::vec4(cameraDirection, 1.0));
cameraUp = glm::vec3(rotationMat * glm::vec4(cameraUp, 1.0));
cameraRight = glm::vec3(rotationMat * glm::vec4(cameraRight, 1.0));
}
oldXPos = xpos;
oldYPos = ypos;
}
void initCamera() {
cameraPosition = glm::vec3(6.f, 6.f, 6.f);
target = glm::vec3(1.f, 0.f, 0.f);
cameraDirection = glm::normalize(target - cameraPosition);
worldUp = glm::vec3(-1.f, -1.f, 0.f);
cameraRight = glm::normalize(glm::cross(worldUp, cameraDirection));
cameraUp = glm::normalize(glm::cross(cameraDirection, cameraRight));
cameraSpeedPerSecond = 2.5;
}
I'm new to OpenGl and I was working on texturing. I want to draw one image on three sides and another image on other three sides of cube. I'm unable to do it. I want to know at what point in my code is cube being drawn on window?
This is my code:
#include "06_texturing.hpp"
#include "texture.hpp"
GLuint shaderProgram;
GLuint vbo[2], vao[2];
GLuint tex;
glm::mat4 rotation_matrix;
glm::mat4 projection_matrix;
glm::mat4 c_rotation_matrix;
glm::mat4 lookat_matrix;
glm::mat4 model_matrix;
glm::mat4 view_matrix;
glm::mat4 modelview_matrix;
glm::mat3 normal_matrix;
GLuint uModelViewMatrix;
GLuint viewMatrix;
GLuint normalMatrix;
//-----------------------------------------------------------------
//6 faces, 2 triangles/face, 3 vertices/triangle
const int num_vertices = 36;
glm::vec4 texCoordinates[8];
//Eight vertices in homogenous coordinates
glm::vec4 positions[8] = {
glm::vec4(-0.5, -0.5, 0.5, 1.0),
glm::vec4(-0.5, 0.5, 0.5, 1.0),
glm::vec4(0.5, 0.5, 0.5, 1.0),
glm::vec4(0.5, -0.5, 0.5, 1.0),
glm::vec4(-0.5, -0.5, -0.5, 1.0),
glm::vec4(-0.5, 0.5, -0.5, 1.0),
glm::vec4(0.5, 0.5, -0.5, 1.0),
glm::vec4(0.5, -0.5, -0.5, 1.0)
};
glm::vec4 normals[8] = {
glm::vec4(-0.5, -0.5, 0.5, 1.0),
glm::vec4(-0.5, 0.5, 0.5, 1.0),
glm::vec4(0.5, 0.5, 0.5, 1.0),
glm::vec4(0.5, -0.5, 0.5, 1.0),
glm::vec4(-0.5, -0.5, -0.5, 1.0),
glm::vec4(-0.5, 0.5, -0.5, 1.0),
glm::vec4(0.5, 0.5, -0.5, 1.0),
glm::vec4(0.5, -0.5, -0.5, 1.0)
};
//RGBA colors
glm::vec4 colors[8] = {
glm::vec4(0.0, 0.0, 0.0, 1.0),
glm::vec4(1.0, 0.0, 0.0, 1.0),
glm::vec4(1.0, 1.0, 0.0, 1.0),
glm::vec4(0.0, 1.0, 0.0, 1.0),
glm::vec4(0.0, 0.0, 1.0, 1.0),
glm::vec4(1.0, 0.0, 1.0, 1.0),
glm::vec4(1.0, 1.0, 1.0, 1.0),
glm::vec4(0.0, 1.0, 1.0, 1.0)
};
glm::vec2 t_coords[4] = {
glm::vec2( 0.0, 0.0),
glm::vec2( 0.0, 1.0),
glm::vec2( 1.0, 0.0),
glm::vec2( 1.0, 1.0)
};
glm::vec4 color(0.6, 0.6, 0.6, 1.0);
glm::vec4 black(0.1, 0.1, 0.1, 1.0);
glm::vec4 white(0.2, 0.7, 0.7, 1.0);
glm::vec4 red(1.0, 0.2, 0.2, 1.0);
glm::vec4 yellow(0.8, 0.8, 0.0, 1.0);
glm::vec4 green(0.2, 0.7, 0.2, 1.0);
glm::vec4 blue(0.2, 0.2, 0.7, 1.0);
int tri_idx=0;
glm::vec4 v_positions[num_vertices];
glm::vec4 v_colors[num_vertices];
glm::vec4 v_normals[num_vertices];
glm::vec2 tex_coords[num_vertices];
// quad generates two triangles for each face and assigns colors to the vertices
void quad(int a, int b, int c, int d, glm::vec4 color)
{
v_colors[tri_idx] = color; v_positions[tri_idx] = positions[a];
v_normals[tri_idx] = normals[a];
tex_coords[tri_idx] = t_coords[1];
tri_idx++;
v_colors[tri_idx] = color; v_positions[tri_idx] = positions[b];
v_normals[tri_idx] = normals[b];
tex_coords[tri_idx] = t_coords[0];
tri_idx++;
v_colors[tri_idx] = color; v_positions[tri_idx] = positions[c];
v_normals[tri_idx] = normals[c];
tex_coords[tri_idx] = t_coords[2];
tri_idx++;
v_colors[tri_idx] = color; v_positions[tri_idx] = positions[a];
v_normals[tri_idx] = normals[a];
tex_coords[tri_idx] = t_coords[1];
tri_idx++;
v_colors[tri_idx] = color; v_positions[tri_idx] = positions[c];
v_normals[tri_idx] = normals[c];
tex_coords[tri_idx] = t_coords[2];
tri_idx++;
v_colors[tri_idx] = color; v_positions[tri_idx] = positions[d];
v_normals[tri_idx] = normals[d];
tex_coords[tri_idx] = t_coords[3];
tri_idx++;
}
// generate 12 triangles: 36 vertices and 36 colors
void colorcube(void)
{
quad( 1, 0, 3, 2, red);
quad( 2, 3, 7, 6, green);
quad( 3, 0, 4, 7, white);
quad( 6, 5, 1, 2, yellow);
quad( 4, 5, 6, 7, black);
quad( 5, 4, 0, 1, blue);
}
//-----------------------------------------------------------------
void initBuffersGL(void)
{
// Load shaders and use the resulting shader program
std::string vertex_shader_file("06_vshader.glsl");
std::string fragment_shader_file("06_fshader.glsl");
std::vector<GLuint> shaderList;
shaderList.push_back(csX75::LoadShaderGL(GL_VERTEX_SHADER, vertex_shader_file));
shaderList.push_back(csX75::LoadShaderGL(GL_FRAGMENT_SHADER, fragment_shader_file));
shaderProgram = csX75::CreateProgramGL(shaderList);
glUseProgram( shaderProgram );
// getting the attributes from the shader program
GLuint vPosition = glGetAttribLocation( shaderProgram, "vPosition" );
GLuint vColor = glGetAttribLocation( shaderProgram, "vColor" );
GLuint vNormal = glGetAttribLocation( shaderProgram, "vNormal" );
GLuint texCoord = glGetAttribLocation( shaderProgram, "texCoord" );
uModelViewMatrix = glGetUniformLocation( shaderProgram, "uModelViewMatrix");
normalMatrix = glGetUniformLocation( shaderProgram, "normalMatrix");
viewMatrix = glGetUniformLocation( shaderProgram, "viewMatrix");
// Load Textures
GLuint tex=LoadTexture("images/all1.bmp",256,256);
GLuint tex2=LoadTexture("images/another.bmp",256,256);
glBindTexture(GL_TEXTURE_2D, tex);
//Ask GL for two Vertex Attribute Objects (vao) , one for the sphere and one for the wireframe
glGenVertexArrays (2, vao);
//Ask GL for two Vertex Buffer Object (vbo)
glGenBuffers (2, vbo);
//Set 0 as the current array to be used by binding it
glBindVertexArray (vao[0]);
//Set 0 as the current buffer to be used by binding it
glBindBuffer (GL_ARRAY_BUFFER, vbo[0]);
colorcube();
//Copy the points into the current buffer
glBufferData (GL_ARRAY_BUFFER, sizeof (v_positions) + sizeof(tex_coords) + sizeof(v_normals), NULL, GL_STATIC_DRAW);
glBufferSubData( GL_ARRAY_BUFFER, 0, sizeof(v_positions), v_positions );
glBufferSubData( GL_ARRAY_BUFFER, sizeof(v_positions), sizeof(tex_coords), tex_coords);
glBufferSubData( GL_ARRAY_BUFFER, sizeof(tex_coords)+sizeof(v_positions), sizeof(v_normals), v_normals );
// set up vertex array
//Position
glEnableVertexAttribArray( vPosition );
glVertexAttribPointer( vPosition, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0) );
//Textures
glEnableVertexAttribArray( texCoord );
glVertexAttribPointer( texCoord, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(sizeof(v_positions)) );
//Normal
glEnableVertexAttribArray( vNormal );
glVertexAttribPointer( vNormal, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(sizeof(v_positions)+sizeof(tex_coords)) );
}
void renderGL(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
rotation_matrix = glm::rotate(glm::mat4(1.0f), glm::radians(xrot), glm::vec3(1.0f,0.0f,0.0f));
rotation_matrix = glm::rotate(rotation_matrix, glm::radians(yrot), glm::vec3(0.0f,1.0f,0.0f));
rotation_matrix = glm::rotate(rotation_matrix, glm::radians(zrot), glm::vec3(0.0f,0.0f,1.0f));
model_matrix = rotation_matrix;
//Creating the lookat and the up vectors for the camera
c_rotation_matrix = glm::rotate(glm::mat4(1.0f), glm::radians(c_xrot), glm::vec3(1.0f,0.0f,0.0f));
c_rotation_matrix = glm::rotate(c_rotation_matrix, glm::radians(c_yrot), glm::vec3(0.0f,1.0f,0.0f));
c_rotation_matrix = glm::rotate(c_rotation_matrix, glm::radians(c_zrot), glm::vec3(0.0f,0.0f,1.0f));
glm::vec4 c_pos = glm::vec4(c_xpos,c_ypos,c_zpos, 1.0)*c_rotation_matrix;
glm::vec4 c_up = glm::vec4(c_up_x,c_up_y,c_up_z, 1.0)*c_rotation_matrix;
//Creating the lookat matrix
lookat_matrix = glm::lookAt(glm::vec3(c_pos),glm::vec3(0.0),glm::vec3(c_up));
//creating the projection matrix
projection_matrix = glm::frustum(-1.0, 1.0, -1.0, 1.0, 1.0, 5.0);
view_matrix = projection_matrix*lookat_matrix;
glUniformMatrix4fv(viewMatrix, 1, GL_FALSE, glm::value_ptr(view_matrix));
// Draw the sphere
modelview_matrix = view_matrix*model_matrix;
glUniformMatrix4fv(uModelViewMatrix, 1, GL_FALSE, glm::value_ptr(modelview_matrix));
normal_matrix = glm::transpose (glm::inverse(glm::mat3(modelview_matrix)));
glUniformMatrix3fv(normalMatrix, 1, GL_FALSE, glm::value_ptr(normal_matrix));
// glBindTexture(GL_TEXTURE_2D, tex);
glBindVertexArray (vao[0]);
glDrawArrays(GL_TRIANGLES, 0, num_vertices);
}
int main(int argc, char** argv)
{
//! The pointer to the GLFW window
GLFWwindow* window;
//! Setting up the GLFW Error callback
glfwSetErrorCallback(csX75::error_callback);
//! Initialize GLFW
if (!glfwInit())
return -1;
//We want OpenGL 4.0
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
//This is for MacOSX - can be omitted otherwise
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
//We don't want the old OpenGL
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
//! Create a windowed mode window and its OpenGL context
window = glfwCreateWindow(512, 512, "CS475/CS675 Tutorial 6: Texturing a cube", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
//! Make the window's context current
glfwMakeContextCurrent(window);
//Initialize GLEW
//Turn this on to get Shader based OpenGL
glewExperimental = GL_TRUE;
GLenum err = glewInit();
if (GLEW_OK != err)
{
//Problem: glewInit failed, something is seriously wrong.
std::cerr<<"GLEW Init Failed : %s"<<std::endl;
}
//Keyboard Callback
glfwSetKeyCallback(window, csX75::key_callback);
//Framebuffer resize callback
glfwSetFramebufferSizeCallback(window, csX75::framebuffer_size_callback);
// Ensure we can capture the escape key being pressed below
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
//Initialize GL state
csX75::initGL();
initBuffersGL();
// Loop until the user closes the window
while (glfwWindowShouldClose(window) == 0)
{
// Render here
renderGL();
// Swap front and back buffers
glfwSwapBuffers(window);
// Poll for and process events
glfwPollEvents();
}
glfwTerminate();
return 0;
}
I want to change in it to render different images on different sides.
If you want to use 2 completely different textures, in the fragment shader, then you have to bind the textures to 2 different texture units. The texture unit can be set by glActiveTexture:
GLuint tex=LoadTexture("images/all1.bmp",256,256);
GLuint tex2=LoadTexture("images/another.bmp",256,256);
int unit_tex0 = 0; // texture unit 0 and binding point 0
int unit_tex1 = 1; // texture unit 1 and binding point 1
glActiveTexture( GL_TEXTURE0 + unit_tex0 );
glBindTexture(GL_TEXTURE_2D, tex);
glActiveTexture( GL_TEXTURE0 + unit_tex1 );
glBindTexture(GL_TEXTURE_2D, tex2);
Further you have to declare 2 texture samplers in the fragment shader. The texture samplers have to be associated to the texture units. Since GLSL version 4.2 this can be done in the fragment shader by specifying binding points:
#version 420
layout (binding = 0) uniform sampler2D u_texture0;
layout (binding = 1) uniform sampler2D u_texture1;
Alternatively you can assign the texture unit index, to the texture sampler uniform by glUniform1i:
uniform sampler2D u_texture0;
uniform sampler2D u_texture1;
GLuint location_tex0 = glGetUniformLocation( shaderProgram, "u_texture0" );
GLuint location_tex1 = glGetUniformLocation( shaderProgram, "u_texture1" );
glUniform1i( location_tex0, unit_tex0 );
glUniform1i( location_tex1, unit_tex1 );
To distinguish between the sides of the cubes, you can use the built in vertex shader variable gl_VertexID.
Create a flat out variable of type int in the vertex shader and pass the vertex id to the fragment shader:
flat out int vertex_id;
void main()
{
.....
vertex_id = gl_VertexID;
.....
}
In the fragment shader yo can decide which texture you want to use by the id corresponding to the vertex coordinate. Note, you have 36 coordinates, the first 3 sides have the ids form 0 to 17 and the other the ids form 18 to 35:
flat in int vertex_id;
void main()
{
.....
if ( vertex_id < 18 )
fragColor = texture(u_texture0, vertUV);
else
fragColor = texture(u_texture1, vertUV);
.....
}
was following the OpenGL RedBook and was able to use a Uniform for a frustrum or translate matrix. I have become a little lost trying to use both at the same time.
//Declarations
GLfloat frustum[4][4] = {
{((2.0*frusZNe //Etc...
GLfloat translate[4][4] = {
{1.0, 0.0, //Etc...
And then I use it in Init:
GLuint uboIndex;
GLint uboSize;
GLuint ubo;
GLvoid *buffer;
uboIndex = glGetUniformBlockIndex(program, "frustumUniform");
glGetActiveUniformBlockiv(program, uboIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &uboSize);
buffer = malloc(uboSize);
const char* frustumName[1] = {"frustum"};
GLuint indices[1];
GLint size[1];
GLint offset[1];
GLint type[1];
glGetUniformIndices(program, 1, frustumName, indices);
glGetActiveUniformsiv(program, 1, indices, GL_UNIFORM_OFFSET, offset);
glGetActiveUniformsiv(program, 1, indices, GL_UNIFORM_SIZE, size);
glGetActiveUniformsiv(program, 1, indices, GL_UNIFORM_TYPE, type);
//memcpy(&buffer + 0, &frustum, sizeof(frustum));
glGenBuffers(1, &ubo);
glBindBuffer(GL_UNIFORM_BUFFER, ubo);
glBufferData(GL_UNIFORM_BUFFER, uboSize, &frustum, GL_STATIC_DRAW);
glBindBufferBase(GL_UNIFORM_BUFFER, uboIndex, ubo);
Immediately afterwards, I do the same thing for the translate one but change some of the values, such as: glGetUniformBlockIndex(program, "translateUniform");
///Translate Uniform, same 20 statements as above, with alterations
GLuint uboIndex2;
GLint uboSize2;
GLuint ubo2;
GLvoid *buffer2;
uboIndex2 = glGetUniformBlockIndex(program, "translateUniform");
glGetActiveUniformBlockiv(program, uboIndex2, GL_UNIFORM_BLOCK_DATA_SIZE, &uboSize2);
buffer2 = malloc(uboSize2);
string offsetString = iToS(uboIndex2);
debugMsg(offsetString + "Index2, 1:");
const char* translateName[1] = {"translate"};
GLuint indices2[1];
GLint size2[1];
GLint offset2[1];
GLint type2[1];
glGetUniformIndices(program, 1, translateName, indices2);
glGetActiveUniformsiv(program, 1, indices2, GL_UNIFORM_OFFSET, offset2);
glGetActiveUniformsiv(program, 1, indices2, GL_UNIFORM_SIZE, size2);
glGetActiveUniformsiv(program, 1, indices2, GL_UNIFORM_TYPE, type2);
//memcpy(&buffer + 0, &frustum, sizeof(frustum));
glGenBuffers(1, &ubo2);
glBindBuffer(GL_UNIFORM_BUFFER, ubo2);
glBufferData(GL_UNIFORM_BUFFER, uboSize2, &translate, GL_STATIC_DRAW);
glBindBufferBase(GL_UNIFORM_BUFFER, uboIndex2, ubo2);
string uboIndex2S = iToS(uboIndex2);
debugMsg("Index 2: " + uboIndex2S);
string uboSizeS, uboSizeS2, uboIndexS, uboIndexS2;
uboSizeS = iToS(uboSize);
uboSizeS2 = iToS(uboSize2);
uboIndexS = iToS(uboIndex);
uboIndexS2 = iToS(uboIndex2);
debugMsg(uboSizeS + " ," + uboSizeS2 + " ," + uboIndexS + " , " + uboIndexS2);
Vertex shader:
#version 430 core
uniform frustumUniform {
mat4 frustum;
};
uniform translateUniform {
mat4 translate;
};
layout(location = 0) in vec4 vPosition;
void
main()
{
vec3 trans = vec3(.2, 0, 0);
mat4 view = mat4(1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, -200.0, 1.0);
mat4 rotate = mat4(0.2, 0.0, 0.3, 0.0,
0.0, 1.0, 0.0, 0.0,
-0.3, 0.0, 0.2, 0.0,
0.0, 0.0, 20.0, 1.0);
mat4 translateOld = mat4(1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0);
gl_Position = frustum * translate * view * vPosition;
}
It compiles, but the second Uniform no longer works. Any ideas?
I'm having troubles with the implementation of shadow mapping in my OpenGL graphic engine.
At first stage, I render the shadow map into a frame buffer object (with a depth texture attached to it) from the light point of view:
Vector3f lightPosition = Vector3f(mainLight->getPosition().x, mainLight->getPosition().y, mainLight->getPosition().z);
shadowMapFBO->BindForWriting();
glUseProgramObjectARB(0);
glViewport(0, 0, screenWidth * SHADOW_Q, screenHeight * SHADOW_Q);
glClear(GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK); //Avoid self shadowing
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-20, 20, -20, 20, 0.0f, +300.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(lightPosition.X, lightPosition.Y, lightPosition.Z, 0, 0, 0, 0, 1, 0);
drawSceneTree();
setTextureMatrix();
I draw all the scene by using the function drawSceneTree(), and I store the light matrix into the OpenGL TEXTURE7 using the function setTextureMatrix(), which content is this:
static double modelView[16];
static double projection[16];
const GLdouble bias[16] = {
0.5, 0.0, 0.0, 0.0,
0.0, 0.5, 0.0, 0.0,
0.0, 0.0, 0.5, 0.0,
0.5, 0.5, 0.5, 1.0
};
// Grab modelview and transformation matrices
glGetDoublev(GL_MODELVIEW_MATRIX, modelView);
glGetDoublev(GL_PROJECTION_MATRIX, projection);
glActiveTextureARB(GL_TEXTURE7);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glLoadMatrixd(bias);
// concatating all matrice into one.
glMultMatrixd(projection);
glMultMatrixd(modelView);
// Go back to normal matrix mode
glMatrixMode(GL_MODELVIEW);
Then I render the scene from the camera point of view, and using a shader for rendering the shadows:
glViewport(0, 0, screenWidth, screenHeight);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
// Clear previous frame values
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_LIGHTING);
//Using the shadow shader
glUseProgram(shadowMapFBO->getShader());
glUniform1iARB(shadowMapFBO->getShadowMapUniform(), 7);
glUniform1iARB(shadowMapFBO->getTextureUniform(), 0);
shadowMapFBO->BindForReading(7);
setupMatrices(0, 4, -13, 0, 5, 0);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
drawSceneTree();
The setupMatrices() function set the projection and modelview matrix. I bind the shadowMapFBO into the OpenGL TEXTURE7, using the function BindForReading(7), which content is:
glActiveTexture(GL_TEXTURE0 + TextureUnit);
glBindTexture(GL_TEXTURE_2D, depthTextureId);
Finally, the vertex and fragment shaders are these:
Vertex:
varying vec4 ShadowCoord;
varying vec3 normal;
varying vec3 vertex_to_light_vector;
varying vec2 texture_coordinate;
void main()
{
ShadowCoord = gl_TextureMatrix[7] * gl_Vertex;
gl_Position = ftransform();
gl_FrontColor = gl_Color;
normal = gl_NormalMatrix * gl_Normal;
vec4 vertex_in_modelview_space = gl_ModelViewMatrix * gl_Vertex;
vertex_to_light_vector = vec3(gl_LightSource[0].position -vertex_in_modelview_space);
texture_coordinate = vec2(gl_MultiTexCoord0);
}
Fragment:
uniform sampler2D ShadowMap;
uniform sampler2D Texture;
varying vec4 ShadowCoord;
varying vec3 normal;
varying vec3 vertex_to_light_vector;
varying vec2 texture_coordinate;
void main()
{
const vec4 AmbientColor = vec4(0.7, 0.7, 0.7, 1.0);
const vec4 DiffuseColor = vec4(0.5, 0.5, 0.5, 1.0);
vec3 normalized_normal = normalize(normal);
vec3 normalized_vertex_to_light_vector = normalize(vertex_to_light_vector);
float DiffuseTerm = clamp(dot(normal, vertex_to_light_vector), 0.0, 1.0);
vec4 shadowCoordinateWdivide = ShadowCoord / ShadowCoord.w ;
// Used to lower moiré pattern and self-shadowing
shadowCoordinateWdivide.z += 0.0005;
float distanceFromLight = texture2D(ShadowMap,shadowCoordinateWdivide.st).z;
float shadow = 1.0;
if (ShadowCoord.w > 0.0)
shadow = distanceFromLight < shadowCoordinateWdivide.z ? 0.5 : 1.0 ;
gl_FragColor = texture2D(Texture, texture_coordinate) * shadow * (AmbientColor + DiffuseColor * DiffuseTerm);
gl_FragColor.a = 1.0;
}
And I'm getting the shadow of the game's character projected in all objects of the scene. I've recorded it in a gif:
https://dl.dropboxusercontent.com/u/658766/captura.gif
P.S: The shadow map is also rendered on screen for debug purposes, at the right upper corner.
Your shadow coordinate has to be processed by ModelWold matrix (without projection nor view matrices). In my shaders, I compute it with this:
ShadowCoord = gl_TextureMatrix[7] * inverse(modelView) * gl_ModelViewMatrix * gl_Vertex;
But you may pass it to your shader as an uniform. This is the transformation matrix applied to each individual objects in your scene after the ModelViewProjectionMatrix has been set to look at origin. (there is surely a smarter way for handling this, but I've not dig much).