Related
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;
}
So, I'm a beginner learning graphics programmer. I'm working on a program for camera movement. I think there's something wrong with the vertex shader. The program runs with no errors but the screen is completely blank. Here is the vertex shader I'm using:
#version 330
in vec4 vPosition;
out vec4 vColor;
uniform mat4 model_view;
uniform mat4 projection;
void main()
{
vec4 pos = projection * model_view * vPosition / vPosition.w;
gl_Position = pos;
vColor = vPosition;
}
If I switch the shader back to basic version:
#version 330
in vec4 vPosition;
out vec4 vColor;
void
main()
{
gl_Position = vPosition;
vColor = vPosition;
}
The program runs and renders a triangle successfully. So, I'm pretty sure the error is with the shader.
The shader is called in the initialize function:
void initialize(void)
{
glClearColor(1.0, 1.0, 1.0, 1.0); // white background
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// Create and initialize a buffer object
GLuint buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);
// Load shaders and use the resulting shader program
GLuint program = InitShader("res/shaders/vshader21.glsl", "res/shaders/fshader21.glsl");
model_view = glGetUniformLocation(program, "model_view");
projection = glGetUniformLocation(program, "projection");
glUseProgram(program);
// Initialize the vertex position attribute from the vertex shader
GLuint loc = glGetAttribLocation(program, "vPosition");
glEnableVertexAttribArray(loc);
glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
}
the 'points' in glBufferData is as follows:
const int WIDTH = 500, HEIGHT = 500;
/* Positions */
vec4 points[] = {
vec4(0.5,0.5, 1, 1),
vec4(-0.5,0.5, 1, 1),
vec4(0.5,-0.5, 1, 1) ,
vec4(-0.5,-0.5, 1, 1)
};
model_view and projection are of GLuint type in main application and global.
I set the uniform variables (position, model_view) in the display functions.
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT); // clear the window
glPointSize(20.0);
// Projection transformation parameters
GLfloat left = -1.0, right = 1.0;
GLfloat bottom = -1.0, top = 1.0;
GLfloat zNear = 0, zFar = 3.0;
mat4 p = Ortho(left, right, bottom, top, zNear, zFar);
glUniformMatrix4fv(projection, 1, GL_TRUE, p);
vec4 eye(0.0, 0.0, -1.0, 1.0);
vec4 at(0.0, 0.0, 0.0, 1.0);
vec4 up(0.0, 1.0, 0.0, 0.0);
mat4 mv = LookAt(eye, at, up);
glUniformMatrix4fv(model_view, 1, GL_TRUE, mv);
glDrawArrays(GL_TRIANGLES, 0, 3); // draw the points
glFlush();
}
What could possibly be going wrong?
The explicit division by the .w component is superfluous.
vec4 pos = projection * model_view * vPosition / vPosition.w;
vec4 pos = projection * model_view * vPosition;
Note, the Perspective divide is automatically performed after clipping.
Since the vector is multiplied to the uniforms form the right, you do not have to transpose the matrices:
glUniformMatrix4fv(projection, 1, GL_TRUE, p);
glUniformMatrix4fv(projection, 1, GL_FALSE, p);
glUniformMatrix4fv(model_view, 1, GL_TRUE, mv);
glUniformMatrix4fv(model_view, 1, GL_FALSE, mv);
See GLSL Programming/Vector and Matrix Operations
So I'm following LearnOpenGL tutorials for the camera. I am trying to render a cube (definied with the vector of verts) and just circle around the cube to make sure it has rendered properly. I can render the front face of the cube just fine, but as soon as I switch the shader to use MVP nothing renders
void GraphicsProgram::run_program()
{
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
state = RUNNING;
// TODO: Move these into their respective classes
// Hardcoded for some testing
// ----------------------------------------------
const char *vertexShaderPath = "vertex_shader.vs";
const char *fragmentShaderPath = "fragment_shader.fs";
Shader firstShader = Shader(vertexShaderPath, fragmentShaderPath);
std::vector<Vertex> verts;
Vertex v1, v2, v3, v4, v5, v6, v7, v8;
v1.position = { -0.5, -0.5, +0.5 };
v2.position = { +0.5, -0.5, +0.5 };
v3.position = { +0.5, +0.5, +0.5 };
v4.position = { -0.5, +0.5, +0.5 };
v5.position = { +0.5, -0.5, -0.5 };
v6.position = { +0.5, +0.5, -0.5 };
v7.position = { -0.5, +0.5, -0.5 };
v8.position = { -0.5, -0.5, -0.5 };
verts.push_back(v1);
verts.push_back(v2);
verts.push_back(v3);
verts.push_back(v4);
verts.push_back(v5);
verts.push_back(v6);
verts.push_back(v7);
verts.push_back(v8);
std::vector<unsigned int> indicies = {
0, 1, 2, 0, 2, 3, // front
1, 4, 5, 1, 5, 2, // right
4, 7, 6, 4, 6, 7, // back
7, 0, 3, 7, 3, 6, // left
3, 2, 5, 3, 5, 6, // top
7, 4, 1, 7, 1, 0 // bottom
};
unsigned int VBO, VAO, EBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, verts.size() * sizeof(Vertex), &verts[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicies.size() * sizeof(unsigned int), &indicies[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glUseProgram(firstShader.shaderID);
glm::mat4 projection = glm::perspective(glm::radians(45.0f), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
firstShader.set_mat4("projection", projection);
while (state == RUNNING) {
currentFrame = (float)SDL_GetTicks() / 1000;
deltaTime = lastFrame - currentFrame;
lastFrame = currentFrame;
process_input();
glUseProgram(firstShader.shaderID);
glm::mat4 view;
float radius = 10.0f;
float camX = sin((float)SDL_GetTicks() / 1000) * radius;
float camZ = cos((float)SDL_GetTicks() / 1000) * radius;
view = glm::lookAt(glm::vec3(camX, 0.0f, camZ), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
firstShader.set_mat4("view", view);
glBindVertexArray(VAO);
glm::mat4 model;
model = glm::translate(model, glm::vec3(0.0, 0.0, 0.0));
float angle = 0.0;
model = glm::rotate(model, glm::radians(angle), glm::vec3(0,0,0));
firstShader.set_mat4("model", model);
glDrawElements(GL_TRIANGLES, 24, GL_UNSIGNED_INT, 0);
SDL_GL_SwapWindow(window);
}
shutdown_program();
}
Vertex struct:
struct Vertex {
glm::vec3 position;
glm::vec3 normal;
glm::vec2 texCoord;
};
Vertex Shader code:
#version 330 core
layout (location = 0) in vec3 aPos;
out vec4 vertexColor;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main() {
gl_Position = projection * view * model * vec4(aPos, 1.0f);
vertexColor = vec4(abs(aPos.x), abs(aPos.y), abs(aPos.z), 1.0);
}
Fragment Shader:
#version 330 core
in vec4 vertexColor;
out vec4 fragColor;
void main() {
fragColor = vertexColor;
}
The vertex shader I used originally just took in the vertex positions.
You have to initialize the matrix variables glm::mat4 model and glm::mat4 view.
The glm API documentation refers to The OpenGL Shading Language specification 4.20.
5.4.2 Vector and Matrix Constructors
If there is a single scalar parameter to a vector constructor, it is used to initialize all components of the constructed vector to that scalar’s value. If there is a single scalar parameter to a matrix constructor, it is used to initialize all the components on the matrix’s diagonal, with the remaining components initialized to 0.0.
This means, that an identity matrix can be initialized by the single parameter 1.0:
glm::mat4 model(1.0f);
....
glm::mat4 view(1.0f);
You missed to set a proper rotation axis in the glm::rotate:
model = glm::rotate(model, glm::radians(angle),
glm::vec3(1.0,0,0)); // e.g. (1, 0, 0) instead of (0, 0, 0)
You have to clear the default farmebuffer before every frame (glClear):
glClearColor(0.0, 0.0, 0.0, 1.0);
while (state == RUNNING)
{
glClear(GL_COLOR_BUFFER_BIT);
.....
You should enable the Depth Test and clear the depth buffer too:
glEnable(GL_DEPTH_TEST);
glClearColor(0.0, 0.0, 0.0, 1.0);
while (state == RUNNING)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
.....
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);
.....
}
I created a sphere floating above a ground. The sphere is centered around (0,0,0). I have set up a camera with a twist, elevation, azimuth as well as moving in closer and farther from the sphere. The problem I have is that the sphere is always drawn on top of the ground. For example, if I move the camera below the ground I should see the ground be drawn on top of the sphere but that's not the case. Here are my ground and draw functions.
void init_ground()
{
GLfloat x = -static_cast<GLfloat>(NUM_GROUND_LINES/2);
GLfloat z = -static_cast<GLfloat>(NUM_GROUND_LINES/2);
for(int i=0; i<NUM_GROUND_LINES*2; i += 2)
{
GLfloat x = NUM_GROUND_LINES/2;
glm::vec3 vertex1 = glm::vec3(-x, -4.0, z);
glm::vec3 vertex2 = glm::vec3(x, -4.0, z);
ground[i] = vertex1;
ground[i+1] = vertex2;
z += 1.0;
}
for(int i=NUM_GROUND_LINES*2; i<NUM_GROUND_LINES*4; i += 2)
{
GLfloat z = NUM_GROUND_LINES/2;
glm::vec3 vertex1 = glm::vec3(x, -4.0, -z);
glm::vec3 vertex2 = glm::vec3(x, -4.0, z);
ground[i] = vertex1;
ground[i+1] = vertex2;
x += 1.0;
}
}
glm::vec3 cameraPos = glm::vec3(0.0, 0.0, 3.0);
glm::vec3 cameraFront = glm::vec3(0.0f, 0.0f, -1.0f);
glm::vec3 cameraUp = glm::vec3(0.0f, 1.0f, 0.0f);
void draw()
{
glm::mat4 view;
glm::mat4 projection;
glm::mat4 model;
view = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp);
view = glm::rotate(view, glm::radians(GLfloat(twist)), glm::vec3(0.0, 0.0, 1.0));
view = glm::rotate(view, glm::radians(GLfloat(elevation)), glm::vec3(1.0, 0.0, 0.0));
view = glm::rotate(view, glm::radians(GLfloat(azimuth)), glm::vec3(0.0, 0.0, 1.0));
projection = glm::perspective(45.0f, (GLfloat)WIDTH/(GLfloat)HEIGHT, 0.1f, 100.0f);
glUseProgram(program_ground);
GLint ground_proj_loc = glGetUniformLocation(program_ground, "projection");
GLint ground_view_loc = glGetUniformLocation(program_ground, "view");
GLint ground_model_loc = glGetUniformLocation(program_ground, "model");
glUniformMatrix4fv(ground_proj_loc, 1, GL_FALSE, glm::value_ptr(projection));
glUniformMatrix4fv(ground_view_loc, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(ground_model_loc, 1, GL_FALSE, glm::value_ptr(model));
glBindVertexArray(vao_ground);
glDrawArrays(GL_LINES, 0, NUM_GROUND_LINES*2*4);
glBindVertexArray(0);
glUseProgram(program_sphere);
GLint sphere_model_loc = glGetUniformLocation(program_sphere, "model");
GLint sphere_view_loc = glGetUniformLocation(program_sphere, "view");
GLint sphere_proj_loc = glGetUniformLocation(program_sphere, "projection");
glUniformMatrix4fv(sphere_view_loc, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(sphere_proj_loc, 1, GL_FALSE, glm::value_ptr(projection));
glUniformMatrix4fv(sphere_model_loc, 1, GL_FALSE, glm::value_ptr(model));
glBindVertexArray(vao_sphere);
glDrawArrays(GL_LINE_LOOP, 0, 342);
glBindVertexArray(0);
glfwSwapBuffers(window);
}
To be able to remove hidden superficies, you need to enable the Depth Test.
To do that, first you must ask, at the context creation time, a buffer to store the relative z positional value of a vertex, in relation to the camera. If you are using GLFW library, this creation is done automatically.
The second step is to enable the depth test itself. To do that, you need to call:
glEnable(GL_DEPTH_TEST);
somewhere before you call your draw functions.
And, at last, at every frame draw, you must clear you depth buffer, calling:
glClear(GL_DEPTH_BUFFER_BIT);
but usually it is called as:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
to clear the color buffer as well.