Related
I've spent 2 weeks trying to get OpenGL to draw a cube in 3D, but no matter what I do, it never actually drew a cube. If I enable the depth test with glEnable(DEPTH_TEST), it simply does not render anything. If I comment out that function, it renders all the vertices as if the z-values were all 0. I'm completely stuck and have no idea what i've done wrong.
Here's my main file: https://pastebin.com/D8cEcJ4g
#include "Dependencies\glew\glew.h"
#include "Dependencies\freeglut\freeglut.h"
#include "Dependencies\soil\SOIL.h"
#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"
#include "glm/gtc/type_ptr.hpp"
#include <iostream>
#include "ShaderLoader.h";
#include "Camera.h"
#define BUTTON_UP 0
#define BUTTON_DOWN 1
GLuint program;
GLuint vao, vbo, ebo;
GLuint texture, texture2;
unsigned char keyState[255];
glm::vec3 vPosTrans = glm::vec3(-0.50f, -0.50f, 0.0f);//source
glm::vec3 vPosInit = vPosTrans;
glm::vec3 vPosDest = glm::vec3(0.50f, 0.50f, 0.0f);//destination
glm::vec3 vCurrentPos = vPosTrans;
bool Dest1or2 = true;
const GLfloat WIDTH = 800.0f, HEIGHT = 600.0f;
Camera* camera;
void init(){
camera = new Camera(180.0f, WIDTH, HEIGHT, 0.0f, 100.0f);
ShaderLoader shaderLoader;
program = shaderLoader.CreateProgram("CoordSystem_Texture_QUAD.vs", "CoordSystem_Texture_QUAD.fs");
glEnable(GL_DEPTH_TEST);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
// Set up vertex data (and buffer(s)) and attribute pointers
GLfloat vertices[] = {
//position //color //texture coord //Normals
-1.01f, -1.01f, -1.01f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
-1.01f, 1.01f, -1.01f, 0.0f, 1.0f, -0.0f, 0.0f, 0.0f,
1.01f, 1.01f, -1.01f, 1.0f, 0.0f, -0.0f, 1.0f, 0.0f,
1.01f, -1.01f, -1.01f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f,
// Fill in the back face vertex data.
-1.01f, -1.01f, 1.01f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f,
1.01f, -1.01f, 1.01f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f,
1.01f, 1.01f, 1.01f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f,
-1.01f, 1.01f, 1.01f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f,
// Fill in the top face vertex data.
-1.01f, 1.01f, -1.01f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
-1.01f, 1.01f, 1.01f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f,
1.01f, 1.01f, 1.01f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f,
1.01f, 1.01f, -1.01f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
// Fill in the bottom face vertex data.
-1.01f, -1.01f, -1.01f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
1.01f, -1.01f, -1.01f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
1.01f, -1.01f, 1.01f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
-1.01f, -1.01f, 1.01f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f,
// Fill in the left face vertex data.
-1.01f, -1.01f, 1.01f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
-1.01f, 1.01f, 1.01f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f,
-1.01f, 1.01f, -1.01f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
-1.01f, -1.01f, -1.01f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
// Fill in the right face vertex data.
1.01f, -1.01f, -1.01f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
1.01f, 1.01f, -1.01f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
1.01f, 1.01f, 1.01f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
1.01f, -1.01f, 1.01f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f,
};
GLuint indices[] = {
// front
0, 1, 2,
0, 2, 3,
// top
4, 5, 6,
4, 6, 7,
// back
8, 9, 10,
8, 10, 11,
// bottom
12, 13, 14,
12, 14, 15,
// left
16, 17, 18,
16, 18, 19,
// right
20, 21, 22,
20, 22, 23,
};
//** VAO **
// Generate vertex arrow object
glGenVertexArrays(1, &vao);
// Bind the Vertex Array Object to openGl context
glBindVertexArray(vao);//otherwise glVertexAttribPointer
//** VBO **
// Then bind and set vertex buffer(s).
// First paramter is how many buffers we have to create
glGenBuffers(1, &vbo);
// bind VBO to binding point, here it is GL_ARRAY_BUFFER
// there are other binding points
glBindBuffer(GL_ARRAY_BUFFER, vbo);//bind to context
glBufferData(GL_ARRAY_BUFFER,
sizeof(vertices),// GPU need to know how much memory needs to be allocated
vertices,//copy data to GPU
GL_STATIC_DRAW);// How to use the buffer - buffer is created and modified once
//** EBO **
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
sizeof(indices),
indices,
GL_STATIC_DRAW);
// ** Attributes **
//** Vertex Attribute **
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
//** Color Attribute **
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
//** TexCoord attribute **
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
glEnableVertexAttribArray(2);
// It's always a good thing to unbind any buffer/array to prevent strange bugs
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
//** Load and bind texture 1
//--------------------------
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
//** loadImage and create texture
// Load image, create texture and generate mipmaps
int width, height;
unsigned char* image = SOIL_load_image("wall.jpg", &width, &height, 0, SOIL_LOAD_RGB);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
glGenerateMipmap(GL_TEXTURE_2D);
SOIL_free_image_data(image);
glBindTexture(GL_TEXTURE_2D, 0);
// ** Load and Bind Texture 2
//---------------------------
glGenTextures(1, &texture2);
glBindTexture(GL_TEXTURE_2D, texture2);
//** loadImage and create texture
// Load image, create texture and generate mipmaps
unsigned char* image2 = SOIL_load_image("awesomeface.png", &width, &height, 0, SOIL_LOAD_RGB);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image2);
glGenerateMipmap(GL_TEXTURE_2D);
SOIL_free_image_data(image2);
glBindTexture(GL_TEXTURE_2D, 0);
// Set texture wrapping to GL_REPEAT (usually basic wrapping method)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// Set texture filtering parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
void render(){
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Draw our first triangle
glUseProgram(program);
//bind
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glUniform1i(glGetUniformLocation(program, "Texture"), 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture2);
glUniform1i(glGetUniformLocation(program, "Texture2"), 1);
glBindVertexArray(vao);
// Draw Elements intead of vertex array
glDrawArrays(GL_QUADS, 0, 24);
//glDrawElements(GL_TRIANGLES, 24, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
glutSwapBuffers();
}
void update(){
GLfloat cameraSpeed = 0.05f;
camera->setCameraSpeed(cameraSpeed);
//currentTime uniform
GLfloat currentTime = glutGet(GLUT_ELAPSED_TIME);
currentTime = currentTime / 1000;
GLint currentTimeLocation = glGetUniformLocation(program, "currentTime");
glUniform1f(currentTimeLocation, currentTime);
//transforms
glm::mat4 transform = glm::mat4(1.0f);
glm::vec3 vScaleVec = glm::vec3(0.51f, 0.51f, 0.0f);
glm::mat4 model = glm::mat4(1.0);
if (keyState[(unsigned char)'w'] == BUTTON_DOWN) {
camera->moveForward();
std::cout << "e";
}
if (keyState[(unsigned char)'s'] == BUTTON_DOWN) {
camera->moveBack();
std::cout << "A";
}
camera->Update();
//glm::mat4 projection = glm::perspective(45.0f, (GLfloat)WIDTH / (GLfloat)HEIGHT, 0.1f, 100.0f);
glm::mat4 projection = camera->getProjectionMatrix();
glm::mat4 view = glm::lookAt(camera->getCameraPos(), camera->getCameraPos() + camera->getCameraFront(), camera->getCameraUp());
//glm::mat4 view = glm::lookAt(glm::vec3(1, 1, 0), glm::vec3(0, 1, 0), glm::vec3(0, 0, 1));
GLfloat radius = 3.5f;
GLfloat camX = sin(currentTime) * radius;
GLfloat camZ = cos(currentTime) * radius;
//glm::mat4 view = glm::lookAt(
// glm::vec3(camX, 0.0, camZ),
// glm::vec3(0.0, 0.0, 0.0),
// glm::vec3(0.0, 1.0, 0.0));
transform = glm::scale(transform, vScaleVec);
glm::vec3(0.65f, 0.65f, 0.65f);
//transform = glm::rotate(transform, 90.0f, glm::vec3(0.0, 0.0, 1.0));
if (vCurrentPos == vPosDest && Dest1or2 == true )
{
Dest1or2 = false;
}
else if (vCurrentPos == vPosTrans && Dest1or2 == false)
{
Dest1or2 = true;
}
if(Dest1or2)
vCurrentPos = glm::mix(vCurrentPos, vPosDest, currentTime * 0.01f);
else
vCurrentPos = glm::mix(vCurrentPos, vPosTrans, currentTime*0.01f);
//transform = glm::translate(transform, vCurrentPos);
//transform = glm::translate(transform, glm::vec3(-0.51f, -0.51f, 0.0f));
//transform = glm::rotate(transform, ((GLfloat)currentTime / 100) * 90.0f, glm::vec3(0.0f, 0.0f, 1.0f));
// RTS
GLuint transformLoc = glGetUniformLocation(program, "transform");
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(transform));
GLint modelLoc = glGetUniformLocation(program, "model");
GLint viewLoc = glGetUniformLocation(program, "view");
GLint projLoc = glGetUniformLocation(program, "projection");
// Pass them to the shaders
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(camera->getViewMatrix()));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(camera->getProjectionMatrix()));
//glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
//glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
glutPostRedisplay();
}
void keyboard(unsigned char key, int x, int y) {
keyState[key] = BUTTON_DOWN;
//printf("key pressed: %d \n", key);
}
void keyboard_up(unsigned char key, int x, int y) {
keyState[key] = BUTTON_UP;
}
int main(int argc, char **argv){
// init glut
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(300, 200);
glutInitWindowSize(800, 600);
glutCreateWindow("QUAD EBO");
//init GLEW
glewInit();
init();
//clear
glClearColor(1.0, 0.0, 0.0, 1.0);//clear red
// register callbacks
glutDisplayFunc(render);
glutKeyboardFunc(keyboard);
glutKeyboardUpFunc(keyboard_up);
glutIdleFunc(update);
glutMainLoop();
return 0;
}
RAW Paste Data
#include "Dependencies\glew\glew.h"
#include "Dependencies\freeglut\freeglut.h"
#include "Dependencies\soil\SOIL.h"
#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"
#include "glm/gtc/type_ptr.hpp"
#include <iostream>
#include "ShaderLoader.h";
#include "Camera.h"
#define BUTTON_UP 0
#define BUTTON_DOWN 1
GLuint program;
GLuint vao, vbo, ebo;
GLuint texture, texture2;
unsigned char keyState[255];
glm::vec3 vPosTrans = glm::vec3(-0.50f, -0.50f, 0.0f);//source
glm::vec3 vPosInit = vPosTrans;
glm::vec3 vPosDest = glm::vec3(0.50f, 0.50f, 0.0f);//destination
glm::vec3 vCurrentPos = vPosTrans;
bool Dest1or2 = true;
const GLfloat WIDTH = 800.0f, HEIGHT = 600.0f;
Camera* camera;
void init(){
camera = new Camera(180.0f, WIDTH, HEIGHT, 0.0f, 100.0f);
ShaderLoader shaderLoader;
program = shaderLoader.CreateProgram("CoordSystem_Texture_QUAD.vs", "CoordSystem_Texture_QUAD.fs");
glEnable(GL_DEPTH_TEST);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
// Set up vertex data (and buffer(s)) and attribute pointers
GLfloat vertices[] = {
//position //color //texture coord //Normals
-1.01f, -1.01f, -1.01f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
-1.01f, 1.01f, -1.01f, 0.0f, 1.0f, -0.0f, 0.0f, 0.0f,
1.01f, 1.01f, -1.01f, 1.0f, 0.0f, -0.0f, 1.0f, 0.0f,
1.01f, -1.01f, -1.01f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f,
// Fill in the back face vertex data.
-1.01f, -1.01f, 1.01f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f,
1.01f, -1.01f, 1.01f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f,
1.01f, 1.01f, 1.01f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f,
-1.01f, 1.01f, 1.01f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f,
// Fill in the top face vertex data.
-1.01f, 1.01f, -1.01f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
-1.01f, 1.01f, 1.01f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f,
1.01f, 1.01f, 1.01f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f,
1.01f, 1.01f, -1.01f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
// Fill in the bottom face vertex data.
-1.01f, -1.01f, -1.01f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
1.01f, -1.01f, -1.01f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
1.01f, -1.01f, 1.01f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
-1.01f, -1.01f, 1.01f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f,
// Fill in the left face vertex data.
-1.01f, -1.01f, 1.01f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
-1.01f, 1.01f, 1.01f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f,
-1.01f, 1.01f, -1.01f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
-1.01f, -1.01f, -1.01f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
// Fill in the right face vertex data.
1.01f, -1.01f, -1.01f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
1.01f, 1.01f, -1.01f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
1.01f, 1.01f, 1.01f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
1.01f, -1.01f, 1.01f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f,
};
GLuint indices[] = {
// front
0, 1, 2,
0, 2, 3,
// top
4, 5, 6,
4, 6, 7,
// back
8, 9, 10,
8, 10, 11,
// bottom
12, 13, 14,
12, 14, 15,
// left
16, 17, 18,
16, 18, 19,
// right
20, 21, 22,
20, 22, 23,
};
//** VAO **
// Generate vertex arrow object
glGenVertexArrays(1, &vao);
// Bind the Vertex Array Object to openGl context
glBindVertexArray(vao);//otherwise glVertexAttribPointer
//** VBO **
// Then bind and set vertex buffer(s).
// First paramter is how many buffers we have to create
glGenBuffers(1, &vbo);
// bind VBO to binding point, here it is GL_ARRAY_BUFFER
// there are other binding points
glBindBuffer(GL_ARRAY_BUFFER, vbo);//bind to context
glBufferData(GL_ARRAY_BUFFER,
sizeof(vertices),// GPU need to know how much memory needs to be allocated
vertices,//copy data to GPU
GL_STATIC_DRAW);// How to use the buffer - buffer is created and modified once
//** EBO **
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
sizeof(indices),
indices,
GL_STATIC_DRAW);
// ** Attributes **
//** Vertex Attribute **
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
//** Color Attribute **
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
//** TexCoord attribute **
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
glEnableVertexAttribArray(2);
// It's always a good thing to unbind any buffer/array to prevent strange bugs
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
//** Load and bind texture 1
//--------------------------
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
//** loadImage and create texture
// Load image, create texture and generate mipmaps
int width, height;
unsigned char* image = SOIL_load_image("wall.jpg", &width, &height, 0, SOIL_LOAD_RGB);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
glGenerateMipmap(GL_TEXTURE_2D);
SOIL_free_image_data(image);
glBindTexture(GL_TEXTURE_2D, 0);
// ** Load and Bind Texture 2
//---------------------------
glGenTextures(1, &texture2);
glBindTexture(GL_TEXTURE_2D, texture2);
//** loadImage and create texture
// Load image, create texture and generate mipmaps
unsigned char* image2 = SOIL_load_image("awesomeface.png", &width, &height, 0, SOIL_LOAD_RGB);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image2);
glGenerateMipmap(GL_TEXTURE_2D);
SOIL_free_image_data(image2);
glBindTexture(GL_TEXTURE_2D, 0);
// Set texture wrapping to GL_REPEAT (usually basic wrapping method)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// Set texture filtering parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
void render(){
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Draw our first triangle
glUseProgram(program);
//bind
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glUniform1i(glGetUniformLocation(program, "Texture"), 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture2);
glUniform1i(glGetUniformLocation(program, "Texture2"), 1);
glBindVertexArray(vao);
// Draw Elements intead of vertex array
glDrawArrays(GL_QUADS, 0, 24);
//glDrawElements(GL_TRIANGLES, 24, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
glutSwapBuffers();
}
void update(){
GLfloat cameraSpeed = 0.05f;
camera->setCameraSpeed(cameraSpeed);
//currentTime uniform
GLfloat currentTime = glutGet(GLUT_ELAPSED_TIME);
currentTime = currentTime / 1000;
GLint currentTimeLocation = glGetUniformLocation(program, "currentTime");
glUniform1f(currentTimeLocation, currentTime);
//transforms
glm::mat4 transform = glm::mat4(1.0f);
glm::vec3 vScaleVec = glm::vec3(0.51f, 0.51f, 0.0f);
glm::mat4 model = glm::mat4(1.0);
if (keyState[(unsigned char)'w'] == BUTTON_DOWN) {
camera->moveForward();
std::cout << "e";
}
if (keyState[(unsigned char)'s'] == BUTTON_DOWN) {
camera->moveBack();
std::cout << "A";
}
camera->Update();
//glm::mat4 projection = glm::perspective(45.0f, (GLfloat)WIDTH / (GLfloat)HEIGHT, 0.1f, 100.0f);
glm::mat4 projection = camera->getProjectionMatrix();
glm::mat4 view = glm::lookAt(camera->getCameraPos(), camera->getCameraPos() + camera->getCameraFront(), camera->getCameraUp());
//glm::mat4 view = glm::lookAt(glm::vec3(1, 1, 0), glm::vec3(0, 1, 0), glm::vec3(0, 0, 1));
GLfloat radius = 3.5f;
GLfloat camX = sin(currentTime) * radius;
GLfloat camZ = cos(currentTime) * radius;
//glm::mat4 view = glm::lookAt(
// glm::vec3(camX, 0.0, camZ),
// glm::vec3(0.0, 0.0, 0.0),
// glm::vec3(0.0, 1.0, 0.0));
transform = glm::scale(transform, vScaleVec);
glm::vec3(0.65f, 0.65f, 0.65f);
//transform = glm::rotate(transform, 90.0f, glm::vec3(0.0, 0.0, 1.0));
if (vCurrentPos == vPosDest && Dest1or2 == true )
{
Dest1or2 = false;
}
else if (vCurrentPos == vPosTrans && Dest1or2 == false)
{
Dest1or2 = true;
}
if(Dest1or2)
vCurrentPos = glm::mix(vCurrentPos, vPosDest, currentTime * 0.01f);
else
vCurrentPos = glm::mix(vCurrentPos, vPosTrans, currentTime*0.01f);
//transform = glm::translate(transform, vCurrentPos);
//transform = glm::translate(transform, glm::vec3(-0.51f, -0.51f, 0.0f));
//transform = glm::rotate(transform, ((GLfloat)currentTime / 100) * 90.0f, glm::vec3(0.0f, 0.0f, 1.0f));
// RTS
GLuint transformLoc = glGetUniformLocation(program, "transform");
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(transform));
GLint modelLoc = glGetUniformLocation(program, "model");
GLint viewLoc = glGetUniformLocation(program, "view");
GLint projLoc = glGetUniformLocation(program, "projection");
// Pass them to the shaders
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(camera->getViewMatrix()));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(camera->getProjectionMatrix()));
//glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
//glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
glutPostRedisplay();
}
void keyboard(unsigned char key, int x, int y) {
keyState[key] = BUTTON_DOWN;
//printf("key pressed: %d \n", key);
}
void keyboard_up(unsigned char key, int x, int y) {
keyState[key] = BUTTON_UP;
}
int main(int argc, char **argv){
// init glut
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(300, 200);
glutInitWindowSize(800, 600);
glutCreateWindow("QUAD EBO");
//init GLEW
glewInit();
init();
//clear
glClearColor(1.0, 0.0, 0.0, 1.0);//clear red
// register callbacks
glutDisplayFunc(render);
glutKeyboardFunc(keyboard);
glutKeyboardUpFunc(keyboard_up);
glutIdleFunc(update);
glutMainLoop();
return 0;
}
Fragment Shader:
#version 430 core
in vec3 outColor;
in vec2 TexCoord;
out vec4 color;
uniform sampler2D Texture;
uniform sampler2D Texture2;
uniform float currentTime;
void main()
{
//vec3 colorTemp = outColor * abs(sin(currentTime));
//color = vec4(colorTemp, 1.0f) ;
//color = texture(ourTexture, TexCoord) * vec4(outColor, 1.0f) * abs(sin(currentTime)) ;
color = mix(texture(Texture, TexCoord), texture(Texture2, TexCoord), 0.2) * vec4(outColor, 1.0f) * abs(sin(currentTime));
}
Vertex shader:
#version 430 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 color;
layout (location = 2) in vec2 texCoord;
out vec3 outColor;
out vec2 TexCoord;
uniform mat4 transform;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main(void)
{
gl_Position = projection * view * model * transform * vec4(position, 1.0);
outColor = color;
TexCoord = vec2(texCoord.x, 1.0 - texCoord.y);
}
If I comment out that function, it renders all the vertices as if the z-values were all 0
Well, that's because ... they are:
glm::vec3 vScaleVec = glm::vec3(0.51f, 0.51f, 0.0f);
[...]
transform = glm::scale(transform, vScaleVec);
[...]
gl_Position = projection * view * model * transform * vec4(position, 1.0);
You scale with z=0, which means you move all vertices into the z = 0 plane. So it is already flat after your first transformation step (which also means transform is a singular matrix with the third row and column being all zeros). The additional transform steps you have commented out in the code, as well as all the other matrices applied in the shader, won't change any of that, the object is still a flat plane, no matter what other matrices you pre- or post-multiply to it, they just move that plane around.
I don't know which amount of scaling you want, but scaling by 0 is almost never a good idea, and 1 is the neutral element for scaling operations.
Also, why do you have model and transform as separate matrices in the shader? In 3d computer graphics, the model matrix typically contains all the transformations required for mapping the object from it's own local model space to the world space. Even if you need to track separate parts of the transformation internally, you typically don't need these during actual rendering on the gpu, and should multiply all of these together on the CPU, and just send the accumulated transformation as the model matrix to the shader.
I have this OpenGL code the draws a cube and pyramid. However, this program rotates the pyramid and cube together. I am tasked with only making the cube itself move not both objects at the same time. I know for this to happen I have to implement shaders for both. I'm not sure how to go about implementing both of the shaders at once. Any tips?
/*
This program demonstrates simple lighting.
A pyramid is lighted by a point light and can be rotated by mouse.
Ying Zhu
Georgia State University
October 2016
*/
// GLEW header
#include <GL/glew.h> // This must appear before freeglut.h
// Freeglut header
#include <GL/freeglut.h>
// GLM header files
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
// #include <glm/gtx/transform2.hpp>
#include <glm/gtc/matrix_access.hpp>
// #include <glm/gtx/projection.hpp>
#include <glm/gtc/matrix_inverse.hpp>
#include <glm/gtc/type_ptr.hpp>
// C++ header files
#include <iostream>
using namespace std;
using namespace glm;
#define BUFFER_OFFSET(offset) ((GLvoid *) offset)
// VBO buffer IDs
GLuint vertexArrayBufferID = 0;
GLuint normalArrayBufferID = 0;
GLuint cubePosition = 0;
GLuint cubeElements = 0;
GLuint program; // shader program ID
// Shader variable IDs
GLint vPos; // vertex attribute: position
GLint normalID; // vertex attribute: normal
GLint mvpMatrixID; // uniform variable: model, view, projection matrix
GLint modelMatrixID; // uniform variable: model, view matrix
GLint normalMatrixID; // uniform variable: normal matrix for transforming normals
GLint lightSourcePositionID; // uniform variable: for lighting calculation
GLint diffuseLightProductID; // uniform variable: for lighting calculation
GLint ambientID;
GLint attenuationAID;
GLint attenuationBID;
GLint attenuationCID;
// Transformation matrices
mat4 projMatrix;
mat4 mvpMatrix;
mat4 modelMatrix;
mat4 viewMatrix;
mat3 normalMatrix; // Normal matrix for transforming normals
// Light parameters
vec4 lightSourcePosition = vec4(0.0f, 4.0f, 0.0f, 1.0f);
vec4 diffuseMaterial = vec4(0.5f, 0.5f, 0.0f, 1.0f);
vec4 diffuseLightIntensity = vec4(1.0f, 1.0f, 1.0f, 1.0f);
vec4 ambient = vec4(0.2f, 0.2f, 0.2f, 1.0f);
float attenuationA = 1.0f;
float attenuationB = 0.2f;
float attenuationC = 0.0f;
vec4 diffuseLightProduct;
// Camera parameters
vec3 eyePosition = vec3(0.0f, 0.0f, 4.0f);
vec3 lookAtCenter = vec3(0.0f, 0.0f, 0.0f);
vec3 upVector = vec3(0.0f, 1.0f, 0.0f);
float fieldOfView = 30.0f;
float nearPlane = 0.1f;
float farPlane = 1000.0f;
// Mouse controlled rotation angles
float rotateX = 0;
float rotateY = 0;
struct VertexData {
GLfloat vertex[3];
VertexData(GLfloat x, GLfloat y, GLfloat z) {
vertex[0] = x; vertex[1] = y; vertex[2] = z;
}
};
//---------------------------------------------------------------
// Initialize vertex arrays and VBOs
void prepareVBOs() {
// Define a 3D pyramid.
GLfloat vertices[][4] = {
{1.0f, -1.0f, 1.0f, 1.0f}, // face 1
{-1.0f, -1.0f, -1.0f, 1.0f},
{1.0f, -1.0f, -1.0f, 1.0f},
{ 1.0f, -1.0f, -1.0f, 1.0f }, // face 2
{0.0f, 1.0f, 0.0f, 1.0f},
{ 1.0f, -1.0f, 1.0f, 1.0f },
{ 1.0f, -1.0f, 1.0f, 1.0f }, // face 3
{ 0.0f, 1.0f, 0.0f, 1.0f },
{-1.0f, -1.0f, 1.0f, 1.0f},
{ -1.0f, -1.0f, 1.0f, 1.0f }, // face 4
{ 0.0f, 1.0f, 0.0f, 1.0f },
{ -1.0f, -1.0f, -1.0f, 1.0f },
{ 0.0f, 1.0f, 0.0f, 1.0f }, // face 5
{ 1.0f, -1.0f, -1.0f, 1.0f },
{ -1.0f, -1.0f, -1.0f, 1.0f },
{ 1.0f, -1.0f, 1.0f, 1.0f }, // face 6
{ -1.0f, -1.0f, 1.0f, 1.0f },
{ -1.0f, -1.0f, -1.0f, 1.0f }
};
GLfloat normals[][4] = {
{0.0f, -1.0f, 0.0f, 1.0f}, // normal 1
{0.0f, -1.0f, 0.0f, 1.0f },
{0.0f, -1.0f, 0.0f, 1.0f },
{0.8944f, 0.4472f, 0.0f, 1.0f}, // normal 2
{ 0.8944f, 0.4472f, 0.0f, 1.0f },
{ 0.8944f, 0.4472f, 0.0f, 1.0f },
{-0.0f, 0.4472f, 0.8944f, 1.0f}, // normal 3
{ -0.0f, 0.4472f, 0.8944f, 1.0f },
{ -0.0f, 0.4472f, 0.8944f, 1.0f },
{-0.8944f, 0.4472f, 0.0f, 1.0f}, // normal 4
{ -0.8944f, 0.4472f, 0.0f, 1.0f },
{ -0.8944f, 0.4472f, 0.0f, 1.0f },
{0.0f, 0.4472f, -0.8944f, 1.0f}, // normal 5
{ 0.0f, 0.4472f, -0.8944f, 1.0f },
{ 0.0f, 0.4472f, -0.8944f, 1.0f },
{ 0.0f, -1.0f, 0.0f, 1.0f }, // normal 6
{ 0.0f, -1.0f, 0.0f, 1.0f },
{ 0.0f, -1.0f, 0.0f, 1.0f }
};
// Cube positioins
VertexData vertexData[] = {
VertexData(0.0, 0.0, 0.0), /* Index 0 */
VertexData(0.0, 0.0, 1.0), /* Index 1 */
VertexData(0.0, 1.0, 0.0), /* Index 2 */
VertexData(0.0, 1.0, 1.0), /* Index 3 */
VertexData(1.0, 0.0, 0.0), /* Index 4 */
VertexData(1.0, 0.0, 1.0), /* Index 5 */
VertexData(1.0, 1.0, 0.0), /* Index 6 */
VertexData(1.0, 1.0, 1.0), /* Index 7 */
};
// Cube elements
GLubyte indices[] = {
4, 5, 7, // +X face
4, 7, 6,
0, 2, 3, // ‐X face
0, 3, 1,
2, 6, 7, // +Y face
2, 7, 3,
0, 1, 5, // ‐Y face
0, 5, 4,
0, 4, 6, // +Z face
0, 6, 2,
1, 3, 7, // ‐Z face
1, 7, 5
};
// Get an unused buffer object name. Required after OpenGL 3.1.
glGenBuffers(1, &vertexArrayBufferID);
// If it's the first time the buffer object name is used, create that buffer.
glBindBuffer(GL_ARRAY_BUFFER, vertexArrayBufferID);
// Allocate memory for the active buffer object.
// 1. Allocate memory on the graphics card for the amount specified by the 2nd parameter.
// 2. Copy the data referenced by the third parameter (a pointer) from the main memory to the
// memory on the graphics card.
// 3. If you want to dynamically load the data, then set the third parameter to be NULL.
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glGenBuffers(1, &normalArrayBufferID);
glBindBuffer(GL_ARRAY_BUFFER, normalArrayBufferID);
glBufferData(GL_ARRAY_BUFFER, sizeof(normals), normals, GL_STATIC_DRAW);
glGenBuffers(1, &cubePosition);
glBindBuffer(GL_ARRAY_BUFFER, cubePosition);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData),
vertexData, GL_STATIC_DRAW);
glGenBuffers(1, &cubeElements);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cubeElements);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices),
indices, GL_STATIC_DRAW);
}
//---------------------------------------------------------------
// Print out the output of the shader compiler
void printLog(GLuint obj)
{
int infologLength = 0;
char infoLog[1024];
if (glIsShader(obj)) {
glGetShaderInfoLog(obj, 1024, &infologLength, infoLog);
}
else {
glGetProgramInfoLog(obj, 1024, &infologLength, infoLog);
}
if (infologLength > 0) {
cout << infoLog;
}
}
//-------------------------------------------------------------------
void prepareShaders() {
// Vertex shader source code
// A point light source is implemented.
// For simplicity, only the ambient and diffuse components are implemented.
// The lighting is calculated in world space, not in camera space.
const char* vSource = {
"#version 330\n"
"in vec4 vPos;"
"in vec4 normal;"
"uniform mat4x4 mvpMatrix;"
"uniform mat4x4 modelMatrix;"
"uniform mat3x3 normalMatrix;"
"uniform vec4 lightSourcePosition;"
"uniform vec4 diffuseLightProduct;"
"uniform vec4 ambient;"
"uniform float attenuationA;"
"uniform float attenuationB;"
"uniform float attenuationC;"
"out vec4 color;"
"void main() {"
" gl_Position = mvpMatrix * vPos;"
// Transform the vertex position to the world space.
" vec4 transformedVertex = modelMatrix * vPos;"
// Transform the normal vector to the world space.
" vec3 transformedNormal = normalize(normalMatrix * normal.xyz);"
// Light direction
" vec3 lightVector = normalize(transformedVertex.xyz - lightSourcePosition.xyz);"
// Distance between the light source and vertex
" float dist = distance(lightSourcePosition.xyz, transformedVertex.xyz);"
// Attenuation factor
" float attenuation = 1.0f / (attenuationA + (attenuationB * dist) + (attenuationC * dist * dist));"
// Calculate the diffuse component of the lighting equation.
" vec4 diffuse = attenuation * (max(dot(transformedNormal, lightVector), 0.0) * diffuseLightProduct);"
// Combine the ambient component and diffuse component.
" color = ambient + diffuse;"
"}"
};
// Fragment shader source code
const char* fSource = {
"#version 330\n"
"in vec4 color;"
"out vec4 fragColor;"
"void main() {"
" fragColor = color;"
"}"
};
// Declare shader IDs
GLuint vShader, fShader;
// Create empty shader objects
vShader = glCreateShader(GL_VERTEX_SHADER);
fShader = glCreateShader(GL_FRAGMENT_SHADER);
// Attach shader source code the shader objects
glShaderSource(vShader, 1, &vSource, NULL);
glShaderSource(fShader, 1, &fSource, NULL);
// Compile shader objects
glCompileShader(vShader);
printLog(vShader);
glCompileShader(fShader);
printLog(fShader);
// Create an empty shader program object
program = glCreateProgram();
// Attach vertex and fragment shaders to the shader program
glAttachShader(program, vShader);
glAttachShader(program, fShader);
// Link the shader program
glLinkProgram(program);
printLog(program);
}
//---------------------------------------------------------------
// Retrieve the IDs of the shader variables. Later we will
// use these IDs to pass data to the shaders.
void getShaderVariableLocations(GLuint shaderProgram) {
// Retrieve the ID of a vertex attribute, i.e. position
vPos = glGetAttribLocation(shaderProgram, "vPos");
normalID = glGetAttribLocation(shaderProgram, "normal");
mvpMatrixID = glGetUniformLocation(shaderProgram, "mvpMatrix");
modelMatrixID = glGetUniformLocation(shaderProgram, "modelMatrix");
normalMatrixID = glGetUniformLocation(shaderProgram, "normalMatrix");
lightSourcePositionID = glGetUniformLocation(shaderProgram, "lightSourcePosition");
diffuseLightProductID = glGetUniformLocation(shaderProgram, "diffuseLightProduct");
ambientID = glGetUniformLocation(shaderProgram, "ambient");
attenuationAID = glGetUniformLocation(shaderProgram, "attenuationA");
attenuationBID = glGetUniformLocation(shaderProgram, "attenuationB");
attenuationCID = glGetUniformLocation(shaderProgram, "attenuationC");
}
//---------------------------------------------------------------
void setShaderVariables() {
// value_ptr is a glm function
glUniformMatrix4fv(mvpMatrixID, 1, GL_FALSE, value_ptr(mvpMatrix));
glUniformMatrix4fv(modelMatrixID, 1, GL_FALSE, value_ptr(modelMatrix));
glUniformMatrix3fv(normalMatrixID, 1, GL_FALSE, value_ptr(normalMatrix));
glUniform4fv(lightSourcePositionID, 1, value_ptr(lightSourcePosition));
glUniform4fv(diffuseLightProductID, 1, value_ptr(diffuseLightProduct));
glUniform4fv(ambientID, 1, value_ptr(ambient));
glUniform1f(attenuationAID, attenuationA);
glUniform1f(attenuationBID, attenuationB);
glUniform1f(attenuationCID, attenuationC);
}
//---------------------------------------------------------------
// Set lighting related parameters
void setLightingParam() {
diffuseLightProduct = diffuseMaterial * diffuseLightIntensity;
}
//---------------------------------------------------------------
// Build the model matrix. This matrix will transform the 3D object to the proper place.
mat4 buildModelMatrix() {
mat4 rotationXMatrix = rotate(mat4(1.0f), radians(rotateX), vec3(1.0f, 0.0f, 0.0f));
mat4 rotationYMatrix = rotate(mat4(1.0f), radians(rotateY), vec3(0.0f, 1.0f, 0.0f));
mat4 matrix = rotationYMatrix * rotationXMatrix;
return matrix;
}
//---------------------------------------------------------------
void buildMatrices() {
modelMatrix = buildModelMatrix();
mvpMatrix = projMatrix * viewMatrix * modelMatrix;
normalMatrix = column(normalMatrix, 0, vec3(modelMatrix[0][0], modelMatrix[0][1], modelMatrix[0][2]));
normalMatrix = column(normalMatrix, 1, vec3(modelMatrix[1][0], modelMatrix[1][1], modelMatrix[1][2]));
normalMatrix = column(normalMatrix, 2, vec3(modelMatrix[2][0], modelMatrix[2][1], modelMatrix[2][2]));
// Use glm::inverseTranspose() to create a normal matrix, which is used to transform normal vectors.
normalMatrix = inverseTranspose(normalMatrix);
}
//---------------------------------------------------------------
// Handles the display event
void display()
{
// Clear the window with the background color
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
buildMatrices();
setShaderVariables();
// Activate the shader program
glUseProgram(program);
// If the buffer object already exists, make that buffer the current active one.
// If the buffer object name is 0, disable buffer objects.
glBindBuffer(GL_ARRAY_BUFFER, vertexArrayBufferID);
// Associate the vertex array in the buffer object with the vertex attribute: "position"
glVertexAttribPointer(vPos, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
// Enable the vertex attribute: "position"
glEnableVertexAttribArray(vPos);
glBindBuffer(GL_ARRAY_BUFFER, normalArrayBufferID);
glVertexAttribPointer(normalID, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
glEnableVertexAttribArray(normalID);
// Start the shader program. Draw the object. The third parameter is the number of triangles.
glDrawArrays(GL_TRIANGLES, 0, 18);
glBindBuffer(GL_ARRAY_BUFFER, cubePosition);
glVertexAttribPointer(vPos, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
glEnableVertexAttribArray(vPos);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cubeElements);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, BUFFER_OFFSET(0));
// Refresh the window
glutSwapBuffers();
}
//---------------------------------------------------------------
// Handles the reshape event
void reshape(int width, int height)
{
// Specify the width and height of the picture within the window
glViewport(0, 0, width, height);
projMatrix = perspective(fieldOfView, (float)width / (float)height, nearPlane, farPlane);
viewMatrix = lookAt(eyePosition, lookAtCenter, upVector);
}
//---------------------------------------------------------------
// Read mouse motion data and convert them to rotation angles.
void passiveMotion(int x, int y) {
rotateY = (float)x * -0.8f;
rotateX = (float)y * -0.8f;
// Generate a dislay event to force refreshing the window.
glutPostRedisplay();
}
//-----------------------------------------------------------------
void init() {
prepareVBOs();
prepareShaders();
getShaderVariableLocations(program);
setLightingParam();
// Specify the background color
glClearColor(1, 1, 1, 1);
glEnable(GL_DEPTH_TEST);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
}
//---------------------------------------------------------------
void main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutCreateWindow("Lighting Demo");
glutReshapeWindow(800, 800);
glewInit();
init();
// Register the display callback function
glutDisplayFunc(display);
// Register the reshape callback function
glutReshapeFunc(reshape);
// Register the passive mouse motion call back function
// This function is called when the mouse moves within the window
// while no mouse buttons are pressed.
glutPassiveMotionFunc(passiveMotion);
// Start the event loop
glutMainLoop();
}
Well, the most obvious culprit here would be setting a single ModelMatrix for both - I can't see any logic in your code to set them independently for each object you're rendering.
Since each object has a different rotation (and presumably, unless you're planning to draw one on top of the other, a different translation), you would want to be generating / loading a different model matrix for each draw call.
You dont need to use different shaders, you just need to use different model matricies. Say you have two objects in you scene something like this:
while (!myWindow(shouldClose))
{
myShader.use();
glBindVertexArray(myVao1);
glDrawArrays(GL_TRIANGLES, 0, x); // Draw pyramid
glBindVertaxArray(myVao2);
glDrawArrays(GL_TRIANGLES, 0, x); // Draw cube
}
Say you want only the second model to rotate on the y axis, you could do something like this:
float rotationDegree = 0;
while (!myWindow(shouldClose))
{
myShader.use();
myShader.setMat4(glm::mat4(1.0f)) // Make sure to set it to normal matrix for the pyrmamid
glBindVertexArray(myVao1);
glDrawArrays(GL_TRIANGLES, 0, x); // Draw pyramid
glBindVertaxArray(myVao2);
glm::mat4 model = glm::mat4(1.0f);
glm::rotate(model, glm::radians(rotationDegree), glm::vec3(0.0f, 1.0f, 0.0f));
rotateionDegree += 0.01;
myShader.setMat4("model", model); // Set you model matrix in your shader.
glDrawArrays(GL_TRIANGLES, 0, x); // Draw cube
}
I have been using this tutorial to create a skybox but sampling the texture returns black. If I use my texture coordinates as colour then I get sensible looking coloured skybox so I presume the problem is with the texture sampling! Could it be a problem with my graphics card or openGL version?
Here is my code:
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#include "utils.h"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#define CUSTOM_PI 3.1415926535897931
/*
*
* Include files for Windows, Linux and OSX
* __APPLE is defined if OSX, otherwise Windows and Linux.
*
*/
#ifdef __APPLE__
#define GLFW_INCLUDE_GLCOREARB 1
#include <GLFW/glfw3.h>
#else
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#endif
struct Vertex {
GLfloat position[3];
};
float aspectRatio;
// Position of camera in world space
glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 200.0f);
// Camera Orientation in view space
glm::vec3 cameraOrientation = glm::vec3(0.0f, 1.0f, 0.0f);
/* yaw is initialized to -90.0 degrees since a yaw of 0.0 results in a direction
* vector pointing to the right so we initially rotate a bit to the left. */
float yaw = -90.0f;
float pitch = 0.0f;
float yawPitchStep = 2.0f;
float cameraSpeed = 0.0f;
float cameraAccelerationStep = 0.025f;
float cameraDecelerationStep = 0.05f;
bool left = false;
bool right = false;
bool page_up = false;
bool page_down = false;
bool up = false;
bool down = false;
GLuint shaderProgram;
unsigned int skyboxVAO, skyboxVBO;
unsigned int cubemapTexture;
/* Whenever the window size changed (by OS or user resize) this callback
* function executes */
void framebuffer_size_callback(GLFWwindow *window, int width, int height) {
/* Make sure the viewport matches the new window dimensions; note that width
* and height will be significantly larger than specified on retina
* displays. */
if (!(width == 0 || height == 0)) {
aspectRatio = (float)width / (float)height;
glViewport(0, 0, width, height);
}
}
static void key_callback(GLFWwindow *window, int key, int scancode, int action,
int mods) {
if ((key == GLFW_KEY_ESCAPE || key == GLFW_KEY_Q) && action == GLFW_PRESS) {
glfwSetWindowShouldClose(window, GL_TRUE);
}
if (key == GLFW_KEY_LEFT) {
if (action == GLFW_PRESS)
left = true;
if (action == GLFW_RELEASE)
left = false;
}
if (key == GLFW_KEY_RIGHT) {
if (action == GLFW_PRESS)
right = true;
if (action == GLFW_RELEASE)
right = false;
}
if (key == GLFW_KEY_PAGE_UP) {
if (action == GLFW_PRESS)
page_up = true;
if (action == GLFW_RELEASE)
page_up = false;
}
if (key == GLFW_KEY_PAGE_DOWN) {
if (action == GLFW_PRESS)
page_down = true;
if (action == GLFW_RELEASE)
page_down = false;
}
if (key == GLFW_KEY_UP) {
if (action == GLFW_PRESS)
up = true;
if (action == GLFW_RELEASE)
up = false;
}
if (key == GLFW_KEY_DOWN) {
if (action == GLFW_PRESS)
down = true;
if (action == GLFW_RELEASE)
down = false;
}
}
// loads a cubemap texture from 6 individual texture faces
// order:
// +X (right)
// -X (left)
// +Y (top)
// -Y (bottom)
// +Z (front)
// -Z (back)
// -------------------------------------------------------
unsigned int loadCubemap(std::vector<std::string> faces) {
unsigned int textureID;
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_CUBE_MAP, textureID);
int width, height, nrChannels;
for (unsigned int i = 0; i < faces.size(); i++) {
unsigned char *data =
stbi_load(faces[i].c_str(), &width, &height, &nrChannels, 0);
if (data) {
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, width,
height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
stbi_image_free(data);
} else {
std::cout << "Cubemap texture failed to load at path: " << faces[i]
<< std::endl;
stbi_image_free(data);
}
}
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
return textureID;
}
void setup() {
// These pointers will receive the contents of our shader source code files
GLchar *vertexSource, *fragmentSource;
// These are handles used to reference the shaders
GLuint vertexShader, fragmentShader;
/* Read our shaders into the appropriate buffers */
vertexSource = fileToBuf("./skyboxShader.vert");
fragmentSource = fileToBuf("./skyboxShader.frag");
/* Assign our handles a "name" to new shader objects */
vertexShader = glCreateShader(GL_VERTEX_SHADER);
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
/* Associate the source code buffers with each handle */
glShaderSource(vertexShader, 1, (const GLchar **)&vertexSource, 0);
glShaderSource(fragmentShader, 1, (const GLchar **)&fragmentSource, 0);
/* Compile our shader objects */
glCompileShader(vertexShader);
glCompileShader(fragmentShader);
/* Assign our program handle a "name" */
shaderProgram = glCreateProgram();
// Attach our shaders to our program
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glBindAttribLocation(shaderProgram, 0, "in_Position");
// Link our program, and set it as being actively used
glLinkProgram(shaderProgram);
checkShader(shaderProgram, "Basic Shader");
glUseProgram(shaderProgram);
GLuint cubemapTexture;
glGenTextures(1, &cubemapTexture);
glBindTexture(GL_TEXTURE_CUBE_MAP, cubemapTexture);
float skyboxVertices[] = {
// positions
-1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f,
1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f};
// skybox VAO
glGenVertexArrays(1, &skyboxVAO);
glGenBuffers(1, &skyboxVBO);
glBindVertexArray(skyboxVAO);
glBindBuffer(GL_ARRAY_BUFFER, skyboxVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), &skyboxVertices,
GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float),
(void *)0);
// load textures
// -------------
std::vector<std::string> faces{
"./textures/skybox/right.jpg", "./textures/skybox/left.jpg",
"./textures/skybox/top.jpg", "./textures/skybox/bottom.jpg",
"./textures/skybox/front.jpg", "./textures/skybox/back.jpg"};
cubemapTexture = loadCubemap(faces);
// shader configuration
// --------------------
glUniform1i(glGetUniformLocation(shaderProgram, "skybox"), 0);
}
void render(float time, glm::mat4 projection, glm::mat4 view) {
// draw skybox as last
glDepthFunc(GL_LEQUAL); // change depth function so depth test passes when
// values are equal to depth buffer's content
glUseProgram(shaderProgram);
view =
glm::mat4(glm::mat3(view)); // remove translation from the view matrix
glm::mat4 VP = projection * view;
// Bind Model, View, Perspective transformation matrix to be a uniform
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "vpmatrix"), 1,
GL_FALSE, glm::value_ptr(VP));
// skybox cube
glBindVertexArray(skyboxVAO);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_CUBE_MAP, cubemapTexture);
glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(0);
glDepthFunc(GL_LESS); // set depth function back to default
}
int main(void) {
int k = 0;
float time = 0;
GLFWwindow *window;
if (!glfwInit()) {
printf("Failed to start GLFW\n");
exit(EXIT_FAILURE);
}
#ifdef __APPLE__
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#endif
window = glfwCreateWindow(800, 800, "Graphics Test", NULL, NULL);
aspectRatio = 1.0f;
if (!window) {
glfwTerminate();
printf("GLFW Failed to start\n");
return -1;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
#ifndef __APPLE__
glewExperimental = GL_TRUE;
int err = glewInit();
if (GLEW_OK != err) {
/* Problem: glewInit failed, something is seriously wrong. */
fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
}
#endif
glfwSetKeyCallback(window, key_callback);
fprintf(stderr, "GL INFO %s\n", glGetString(GL_VERSION));
glEnable(GL_DEPTH_TEST);
setup();
printf("Ready to render\n");
while (!glfwWindowShouldClose(window)) { // Main loop
time = glfwGetTime();
// Make our blue to ensure skybox is working.
glClearColor(0.0, 1.0, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
/* Defines the projection:
* With 45 degree field of view
* With A given aspect ratio
* Cliping everything closer than 0.1 to the camera
* Cliping everything further than 1000 from the camera */
glm::mat4 Projection =
glm::perspective(45.0f, aspectRatio, 0.1f, 1000.0f);
if (left) {
yaw -= yawPitchStep;
}
if (right) {
yaw += yawPitchStep;
}
if (page_up) {
pitch += yawPitchStep;
}
if (page_down) {
pitch -= yawPitchStep;
}
if (up) {
cameraSpeed += cameraAccelerationStep;
printf("Camera Speed = %f\n", cameraSpeed);
}
if (down) {
cameraSpeed -= cameraDecelerationStep;
if (cameraSpeed < 0) {
cameraSpeed = 0;
}
printf("Camera Speed = %f\n", cameraSpeed);
}
glm::vec3 front;
front.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch));
front.y = sin(glm::radians(pitch));
front.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch));
glm::vec3 cameraDirection = glm::normalize(front);
cameraPos += cameraSpeed * cameraDirection;
glm::mat4 View = glm::lookAt(cameraPos, cameraPos + cameraDirection,
cameraOrientation);
render(time, Projection, View);
k++;
glfwSwapBuffers(window); // Swap front and back rendering buffers
glfwPollEvents(); // Poll for events.
}
glfwTerminate(); // Close window and terminate GLFW
exit(EXIT_SUCCESS); // Exit program
}
And my vertex shader:
#version 400
precision highp float;
// Position of vertex
in vec3 in_Position;
// The model, view, and projection matrices which needs to be applied to every vertex
uniform mat4 vpmatrix;
// Texture coordinates passed on to fragment shader
out vec3 TexCoords;
void main(void) {
TexCoords = in_Position;
vec4 pos = vpmatrix * vec4(in_Position, 1.0);
gl_Position = pos.xyww;
}
And my fragment shader:
#version 400
precision highp float;
in vec3 TexCoords;
out vec4 FragColor;
uniform samplerCube skybox;
void main()
{
FragColor = texture(skybox, TexCoords);
// FragColor = vec4(TexCoords, 1.0f);
}
The global variable unsigned int cubemapTexture;, which is used in the function render is never set, because there is a 2nd (local) variable named cubemapTexture in the function setup.
Remove the local variable cubemapTexture from the function setup to solve the issue:
unsigned int cubemapTexture;
void setup() {
.....
GLuint cubemapTexture; // delete this part of the
glGenTextures(1, &cubemapTexture); //
glBindTexture(GL_TEXTURE_CUBE_MAP, cubemapTexture); //
.....
cubemapTexture = loadCubemap(faces);
.....
}
void render(float time, glm::mat4 projection, glm::mat4 view) {
.....
glBindTexture(GL_TEXTURE_CUBE_MAP, cubemapTexture);
.....
}
I am making an empty room with 4 walls, 1 floor and 1 ceiling.
I have added an array of uniform variables in the fragment shader for each wall/floor/ceiling.
I'm adjusting this section of code (below), and trying to get the far wall to appear red but nothing is changing after I execute. It stays blue. Why is that?
static void init(GLFWwindow* window)
{
...
// Wall 1 (Far)
g_materialProperties_plane[1].ambient = glm::vec4(1.0f, 0.0f, 0.0f, 1.0f);
g_materialProperties_plane[1].diffuse = glm::vec4(1.0f, 0.0f, 0.0f, 1.0f);
g_materialProperties_plane[1].specular = glm::vec4(0.2f, 0.7f, 1.0f, 1.0f);
...
}
Full program
#define MAX_MATERIALS 6
// struct for lighting properties
struct LightProperties
{
vec4 position;
vec4 ambient;
vec4 diffuse;
vec4 specular;
float shininess;
vec3 attenuation;
float cutoffAngle;
vec3 direction;
};
// struct for material properties
struct MaterialProperties
{
vec4 ambient;
vec4 diffuse;
vec4 specular;
};
LightProperties g_lightProperties;
MaterialProperties g_materialProperties_plane[6];
// struct for vertex attributes
struct Vertex_plane
{
GLfloat position[3];
GLfloat normal[3];
};
GLuint g_VBO; // vertex buffer object identifier
GLuint g_VAO = 0; // vertex array object identifier
GLuint g_shaderProgramID = 0; // shader program identifier
// locations in shader
GLuint g_MVP_Index;
GLuint g_M_Index = 0;
GLuint g_viewPointIndex = 0;
GLuint g_lightPositionIndex = 0;
GLuint g_lightAmbientIndex = 0;
GLuint g_lightDiffuseIndex = 0;
GLuint g_lightSpecularIndex = 0;
GLuint g_lightShininessIndex = 0;
GLuint g_lightAttenuationIndex = 0;
GLuint g_lightCutoffAngleIndex = 0;
GLuint g_lightDirectionIndex = 0;
GLuint g_materialAmbientIndex[MAX_MATERIALS];
GLuint g_materialDiffuseIndex[MAX_MATERIALS];
GLuint g_materialSpecularIndex[MAX_MATERIALS];
glm::mat4 g_modelMatrix_plane[6]; // object's model matrix (4 walls + 1 ceiling + 1 floor)
glm::mat4 g_viewMatrix; // view matrix
glm::mat4 g_projectionMatrix; // projection matrix
glm::vec3 g_viewPoint; // view point
Camera g_camera; // camera
GLuint g_windowWidth = 1200; // window dimensions
GLuint g_windowHeight = 1000;
bool g_wireFrame = false; // wireframe on or off
static void init(GLFWwindow* window)
{
glEnable(GL_DEPTH_TEST); // enable depth buffer test
// create and compile our GLSL program from the shader files
g_shaderProgramID = loadShaders("PerFragLightingVS.vert", "PerFragLightingFS.frag");
// find the location of shader variables
GLuint positionIndex = glGetAttribLocation(g_shaderProgramID, "aPosition");
GLuint normalIndex = glGetAttribLocation(g_shaderProgramID, "aNormal");
g_MVP_Index = glGetUniformLocation(g_shaderProgramID, "uModelViewProjectionMatrix");
g_M_Index = glGetUniformLocation(g_shaderProgramID, "uModelMatrix");
g_viewPointIndex = glGetUniformLocation(g_shaderProgramID, "uViewPoint");
// Material
g_materialAmbientIndex[0] = glGetUniformLocation(g_shaderProgramID, "uMaterialProperties[0].ambient");
g_materialDiffuseIndex[0] = glGetUniformLocation(g_shaderProgramID, "uMaterialProperties[0].diffuse");
g_materialSpecularIndex[0] = glGetUniformLocation(g_shaderProgramID, "uMaterialProperties[0].specular");
g_materialAmbientIndex[1] = glGetUniformLocation(g_shaderProgramID, "uMaterialProperties[1].ambient");
g_materialDiffuseIndex[1] = glGetUniformLocation(g_shaderProgramID, "uMaterialProperties[1].diffuse");
g_materialSpecularIndex[1] = glGetUniformLocation(g_shaderProgramID, "uMaterialProperties[1].specular");
g_materialAmbientIndex[2] = glGetUniformLocation(g_shaderProgramID, "uMaterialProperties[2].ambient");
g_materialDiffuseIndex[2] = glGetUniformLocation(g_shaderProgramID, "uMaterialProperties[2].diffuse");
g_materialSpecularIndex[2] = glGetUniformLocation(g_shaderProgramID, "uMaterialProperties[2].specular");
g_materialAmbientIndex[3] = glGetUniformLocation(g_shaderProgramID, "uMaterialProperties[3].ambient");
g_materialDiffuseIndex[3] = glGetUniformLocation(g_shaderProgramID, "uMaterialProperties[3].diffuse");
g_materialSpecularIndex[3] = glGetUniformLocation(g_shaderProgramID, "uMaterialProperties[3].specular");
g_materialAmbientIndex[4] = glGetUniformLocation(g_shaderProgramID, "uMaterialProperties[4].ambient");
g_materialDiffuseIndex[4] = glGetUniformLocation(g_shaderProgramID, "uMaterialProperties[4].diffuse");
g_materialSpecularIndex[4] = glGetUniformLocation(g_shaderProgramID, "uMaterialProperties[4].specular");
g_materialAmbientIndex[5] = glGetUniformLocation(g_shaderProgramID, "uMaterialProperties[5].ambient");
g_materialDiffuseIndex[5] = glGetUniformLocation(g_shaderProgramID, "uMaterialProperties[5].diffuse");
g_materialSpecularIndex[5] = glGetUniformLocation(g_shaderProgramID, "uMaterialProperties[5].specular");
// initialise model matrix to the identity matrix
g_modelMatrix_plane[0] = g_modelMatrix_plane[1] = g_modelMatrix_plane[2] = g_modelMatrix_plane[3]
= g_modelMatrix_plane[4] = g_modelMatrix_plane[5] = g_modelMatrix_plane[6] = glm::mat4(1.0f);
...
// Material Properties - Planes
// Floor
g_materialProperties_plane[0].ambient = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f);
g_materialProperties_plane[0].diffuse = glm::vec4(0.2f, 0.7f, 1.0f, 1.0f);
g_materialProperties_plane[0].specular = glm::vec4(0.2f, 0.7f, 1.0f, 1.0f);
// Wall 1 (Far)
g_materialProperties_plane[1].ambient = glm::vec4(1.0f, 0.0f, 0.0f, 1.0f);
g_materialProperties_plane[1].diffuse = glm::vec4(1.0f, 0.0f, 0.0f, 1.0f);
g_materialProperties_plane[1].specular = glm::vec4(0.2f, 0.7f, 1.0f, 1.0f);
// Wall 2 (Left)
g_materialProperties_plane[2].ambient = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f);
g_materialProperties_plane[2].diffuse = glm::vec4(0.2f, 0.7f, 1.0f, 1.0f);
g_materialProperties_plane[2].specular = glm::vec4(0.2f, 0.7f, 1.0f, 1.0f);
// Wall 3 (Right)
g_materialProperties_plane[3].ambient = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f);
g_materialProperties_plane[3].diffuse = glm::vec4(0.2f, 0.7f, 1.0f, 1.0f);
g_materialProperties_plane[3].specular = glm::vec4(0.2f, 0.7f, 1.0f, 1.0f);
// Wall 4 (Near)
g_materialProperties_plane[4].ambient = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f);
g_materialProperties_plane[4].diffuse = glm::vec4(0.2f, 0.7f, 1.0f, 1.0f);
g_materialProperties_plane[4].specular = glm::vec4(0.2f, 0.7f, 1.0f, 1.0f);
// Ceiling
g_materialProperties_plane[5].ambient = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f);
g_materialProperties_plane[5].diffuse = glm::vec4(0.2f, 0.7f, 1.0f, 1.0f);
g_materialProperties_plane[5].specular = glm::vec4(0.2f, 0.7f, 1.0f, 1.0f);
// generate identifier for VBOs and copy data to GPU
glGenBuffers(1, &g_VBO);
glBindBuffer(GL_ARRAY_BUFFER, g_VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertices_plane), g_vertices_plane, GL_STATIC_DRAW);
// generate identifiers for VAO
glGenVertexArrays(1, &g_VAO);
// create VAO and specify VBO data
glBindVertexArray(g_VAO);
glBindBuffer(GL_ARRAY_BUFFER, g_VBO);
glVertexAttribPointer(positionIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex_plane), reinterpret_cast<void*>(offsetof(Vertex_plane, position)));
glVertexAttribPointer(normalIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex_plane), reinterpret_cast<void*>(offsetof(Vertex_plane, normal)));
glEnableVertexAttribArray(positionIndex); // enable vertex attributes
glEnableVertexAttribArray(normalIndex);
}
// function used to render the scene
static void render_scene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear colour buffer and depth buffer
glUseProgram(g_shaderProgramID); // use the shaders associated with the shader program
glBindVertexArray(g_VAO); // make VAO active
// set uniform shader variables
glm::mat4 MVP = glm::mat4(1.0f);
// Floor
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix_plane[0];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glUniformMatrix4fv(g_M_Index, 1, GL_FALSE, &g_modelMatrix_plane[0][0][0]);
glUniform3fv(g_viewPointIndex, 1, &g_viewPoint[0]);
glDrawArrays(GL_TRIANGLES, 0, 6);
// Wall 1 (Far wall)
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix_plane[1];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glUniformMatrix4fv(g_M_Index, 1, GL_FALSE, &g_modelMatrix_plane[1][0][0]);
glUniform3fv(g_viewPointIndex, 1, &g_viewPoint[0]);
glDrawArrays(GL_TRIANGLES, 0, 6);
// Wall 2 (Left wall)
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix_plane[2];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glUniformMatrix4fv(g_M_Index, 1, GL_FALSE, &g_modelMatrix_plane[2][0][0]);
glUniform3fv(g_viewPointIndex, 1, &g_viewPoint[0]);
glDrawArrays(GL_TRIANGLES, 0, 6);
// Wall 3 (Right wall)
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix_plane[3];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glUniformMatrix4fv(g_M_Index, 1, GL_FALSE, &g_modelMatrix_plane[3][0][0]);
glUniform3fv(g_viewPointIndex, 1, &g_viewPoint[0]);
glDrawArrays(GL_TRIANGLES, 0, 6);
// Wall 4 (Near wall)
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix_plane[4];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glUniformMatrix4fv(g_M_Index, 1, GL_FALSE, &g_modelMatrix_plane[4][0][0]);
glUniform3fv(g_viewPointIndex, 1, &g_viewPoint[0]);
glDrawArrays(GL_TRIANGLES, 0, 6);
// Ceiling
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix_plane[5];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glUniformMatrix4fv(g_M_Index, 1, GL_FALSE, &g_modelMatrix_plane[5][0][0]);
glUniform3fv(g_viewPointIndex, 1, &g_viewPoint[0]);
glDrawArrays(GL_TRIANGLES, 0, 6);
glUniform4fv(g_lightPositionIndex, 1, &g_lightProperties.position[0]);
glUniform4fv(g_lightAmbientIndex, 1, &g_lightProperties.ambient[0]);
glUniform4fv(g_lightDiffuseIndex, 1, &g_lightProperties.diffuse[0]);
glUniform4fv(g_lightSpecularIndex, 1, &g_lightProperties.specular[0]);
glUniform1fv(g_lightShininessIndex, 1, &g_lightProperties.shininess);
glUniform3fv(g_lightAttenuationIndex, 1, &g_lightProperties.attenuation[0]);
glUniform1fv(g_lightCutoffAngleIndex, 1, &g_lightProperties.cutoffAngle);
glUniform3fv(g_lightDirectionIndex, 1, &g_lightProperties.direction[0]);
// Material Properties - Planes
// Floor
glUniform4fv(g_materialAmbientIndex[0], 1, &g_materialProperties_plane[0].ambient[0]);
glUniform4fv(g_materialDiffuseIndex[0], 1, &g_materialProperties_plane[0].diffuse[0]);
glUniform4fv(g_materialSpecularIndex[0], 1, &g_materialProperties_plane[0].specular[0]);
// Wall 1 (Far)
glUniform4fv(g_materialAmbientIndex[1], 1, &g_materialProperties_plane[1].ambient[0]);
glUniform4fv(g_materialDiffuseIndex[1], 1, &g_materialProperties_plane[1].diffuse[0]);
glUniform4fv(g_materialSpecularIndex[1], 1, &g_materialProperties_plane[1].specular[0]);
// Wall 2 (Left)
glUniform4fv(g_materialAmbientIndex[2], 1, &g_materialProperties_plane[2].ambient[0]);
glUniform4fv(g_materialDiffuseIndex[2], 1, &g_materialProperties_plane[2].diffuse[0]);
glUniform4fv(g_materialSpecularIndex[2], 1, &g_materialProperties_plane[2].specular[0]);
// Wall 3 (Right)
glUniform4fv(g_materialAmbientIndex[3], 1, &g_materialProperties_plane[3].ambient[0]);
glUniform4fv(g_materialDiffuseIndex[3], 1, &g_materialProperties_plane[3].diffuse[0]);
glUniform4fv(g_materialSpecularIndex[3], 1, &g_materialProperties_plane[3].specular[0]);
// Wall 4 (Near)
glUniform4fv(g_materialAmbientIndex[4], 1, &g_materialProperties_plane[4].ambient[0]);
glUniform4fv(g_materialDiffuseIndex[4], 1, &g_materialProperties_plane[4].diffuse[0]);
glUniform4fv(g_materialSpecularIndex[4], 1, &g_materialProperties_plane[4].specular[0]);
// Ceiling
glUniform4fv(g_materialAmbientIndex[5], 1, &g_materialProperties_plane[5].ambient[0]);
glUniform4fv(g_materialDiffuseIndex[5], 1, &g_materialProperties_plane[5].diffuse[0]);
glUniform4fv(g_materialSpecularIndex[5], 1, &g_materialProperties_plane[5].specular[0]);
glFlush(); // flush the pipeline
}
int main(void)
{
GLFWwindow* window = NULL; // pointer to a GLFW window handle
TwBar *TweakBar; // pointer to a tweak bar
glfwSetErrorCallback(error_callback); // set error callback function
// initialise GLFW
if (!glfwInit())
{
// if failed to initialise GLFW
exit(EXIT_FAILURE);
}
// minimum OpenGL version 3.3
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
// create a window and its OpenGL context
window = glfwCreateWindow(g_windowWidth, g_windowHeight, "Tutorial", NULL, NULL);
// if failed to create window
if (window == NULL)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window); // set window context as the current context
glfwSwapInterval(1); // swap buffer interval
// initialise GLEW
if (glewInit() != GLEW_OK)
{
// if failed to initialise GLEW
cerr << "GLEW initialisation failed" << endl;
exit(EXIT_FAILURE);
}
// set key callback function
glfwSetKeyCallback(window, key_callback);
glfwSetCursorPosCallback(window, cursor_position_callback);
glfwSetMouseButtonCallback(window, mouse_button_callback);
// use sticky mode to avoid missing state changes from polling
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
// use mouse to move camera, hence use disable cursor mode
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
// initialise AntTweakBar
TwInit(TW_OPENGL_CORE, NULL);
// give tweak bar the size of graphics window
TwWindowSize(g_windowWidth, g_windowHeight);
TwDefine(" TW_HELP visible=false "); // disable help menu
TwDefine(" GLOBAL fontsize=3 "); // set large font size
// create a tweak bar
TweakBar = TwNewBar("Main");
TwDefine(" Main label='Controls' refresh=0.02 text=light size='220 200' ");
// create display entries
TwAddVarRW(TweakBar, "Wireframe", TW_TYPE_BOOLCPP, &g_wireFrame, " group='Display' ");
// display a separator
TwAddSeparator(TweakBar, NULL, NULL);
// create spotlight entries
TwAddVarRW(TweakBar, "Cutoff", TW_TYPE_FLOAT, &g_lightProperties.cutoffAngle, " group='Spotlight' min=-180.0 max=180.0 step=1.0 ");
TwAddVarRW(TweakBar, "Direction: x", TW_TYPE_FLOAT, &g_lightProperties.direction[0], " group='Spotlight' min=-1.0 max=1.0 step=0.1");
TwAddVarRW(TweakBar, "Direction: y", TW_TYPE_FLOAT, &g_lightProperties.direction[1], " group='Spotlight' min=-1.0 max=1.0 step=0.1");
TwAddVarRW(TweakBar, "Direction: z", TW_TYPE_FLOAT, &g_lightProperties.direction[2], " group='Spotlight' min=-1.0 max=1.0 step=0.1");
// initialise rendering states
init(window);
// the rendering loop
while (!glfwWindowShouldClose(window))
{
g_camera.update(window); // update camera
if (g_wireFrame)
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
render_scene(); // render the scene
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
TwDraw(); // draw tweak bar(s)
glfwSwapBuffers(window); // swap buffers
glfwPollEvents(); // poll for events
}
// clean up
glDeleteProgram(g_shaderProgramID);
glDeleteBuffers(1, &g_VBO);
glDeleteVertexArrays(1, &g_VAO);
// uninitialise tweak bar
TwTerminate();
// close the window and terminate GLFW
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}
Fragment Shader
#version 330 core
#define MAX_MATERIALS 6
// interpolated values from the vertex shaders
in vec3 vNormal;
in vec3 vPosition;
// uniform input data
struct LightProperties
{
vec4 position;
vec4 ambient;
vec4 diffuse;
vec4 specular;
float shininess;
vec3 attenuation;
float cutoffAngle;
vec3 direction;
};
struct MaterialProperties
{
vec4 ambient;
vec4 diffuse;
vec4 specular;
};
uniform LightProperties uLightingProperties;
uniform MaterialProperties uMaterialProperties[MAX_MATERIALS];
uniform vec3 uViewPoint;
// output data
out vec3 fColor;
void main()
{
// calculate vectors for lighting
vec3 N = normalize(vNormal);
vec3 L;
float attenuation = 1.0f;
// calculate the attenuation based on distance
L = (uLightingProperties.position).xyz - vPosition;
float distance = length(L);
L = normalize(L);
attenuation = 1/(uLightingProperties.attenuation.x
+ uLightingProperties.attenuation.y * distance
+ uLightingProperties.attenuation.z * distance * distance);
vec3 V = normalize(uViewPoint - vPosition);
vec3 R = reflect(-L, N);
// the direction of the spotlight
vec3 direction = normalize(uLightingProperties.direction);
// the angle between the vector from the light to the fragment’s position and the spotlight’s direction
float angle = degrees(acos(dot(-L, direction)));
vec3 colour = vec3(0.0f, 0.0f, 0.0f);
// only compute if angle is less than the cutoff angle
if(angle <= uLightingProperties.cutoffAngle)
{
for(int i = 0; i < MAX_MATERIALS; i++){
// calculate Phong lighting
vec4 ambient = uLightingProperties.ambient * uMaterialProperties[i].ambient;
vec4 diffuse = uLightingProperties.diffuse * uMaterialProperties[i].diffuse * max(dot(L, N), 0.0);
vec4 specular = vec4(0.0f, 0.0f, 0.0f, 1.0f);
if(dot(L, N) > 0.0f)
{
specular = uLightingProperties.specular * uMaterialProperties[i].specular
* pow(max(dot(V, R), 0.0), uLightingProperties.shininess);
}
colour = (attenuation * (diffuse + specular)).rgb + ambient.rgb;
// fade the spotlight's intensity linearly with angle
colour *= 1.0f - angle/uLightingProperties.cutoffAngle;
}
}
// set output color
fColor = colour;
}
The issue is inside the Fragment shader:
for(int i = 0; i < MAX_MATERIALS; i++){
....
colour = (attenuation * (diffuse + specular)).rgb + ambient.rgb;
// fade the spotlight's intensity linearly with angle
colour *= 1.0f - angle/uLightingProperties.cutoffAngle;
}
In each iteration of the for loop assign the variable color.
At the end the content of color os the was calculated in the last iteration of the loop (i=5).
You don't need a loop, but you have to set the appropriate material index to a uniform variable before you draw a mesh.
// The index of the material which should be applied to the mesh,
// which is currently drawn.
uniform int uMaterialIndex;
.....
void main()
{
.....
vec3 colour = vec3(0.0f, 0.0f, 0.0f);
if (angle <= uLightingProperties.cutoffAngle)
{
int i = uMaterialIndex;
// calculate Phong lighting
vec4 ambient = uLightingProperties.ambient * uMaterialProperties[i].ambient;
vec4 diffuse = uLightingProperties.diffuse * uMaterialProperties[i].diffuse * max(dot(L, N), 0.0);
vec4 specular = vec4(0.0f, 0.0f, 0.0f, 1.0f);
if (dot(L, N) > 0.0f)
{
specular = uLightingProperties.specular * uMaterialProperties[i].specular
* pow(max(dot(V, R), 0.0), uLightingProperties.shininess);
}
colour = (attenuation * (diffuse + specular)).rgb + ambient.rgb;
// fade the spotlight's intensity linearly with angle
colour *= 1.0f - angle/uLightingProperties.cutoffAngle;
}
.....
}
When you draw a mesh, you need to update the uniform variable:
GLuint g_materialIndex;
g_materialIndex = glGetUniformLocation(g_shaderProgramID, "uMaterialIndex");
glUniform1i(g_materialIndex, materialIndex); // materialIndex in range 0 to 5
glDrawArrays(GL_TRIANGLES, 0, 6);
I'm trying to work with 2D array textures in qt with QOpenGLTextures, I want to send multiple images to the shader to do some processing between each frame. this is what I have so far and for debugging I'm just working with first two images:
std::vector< QImage* > vtextureImgs;
vtextureImgs.resize(2);
QImage *textures0 = new QImage(m_dataPath + "/" +fileslist[0]);
m_width = textures0->width();
m_height = textures0->height();
m_QImgFormat = textures0->format();
vtextureImgs[0] = textures0;
QImage *textures1 = new QImage(m_dataPath + "/" +fileslist[1]);
vtextureImgs[1] = textures1;
GLsizei layerCount = 1;
GLsizei mipLevelCount = 1;
SAFE_DELETE(m_GLTexture);
m_GLTexture = new QOpenGLTexture(QOpenGLTexture::Target::Target2DArray);
m_GLTexture->destroy();
m_GLTexture->create();
m_GLTexture->bind();
m_GLTexture->setMinificationFilter(QOpenGLTexture::Nearest);
m_GLTexture->setMagnificationFilter(QOpenGLTexture::Nearest);
m_GLTexture->setLayers(layerCount);
// m_GLTexture->setSize(m_width,m_height,1 );
m_GLTexture->setWrapMode(QOpenGLTexture::ClampToEdge);
m_GLTexture->setData(0, 0, QOpenGLTexture::RGB, QOpenGLTexture::UInt16, vtextureImgs[0]);
m_GLTexture->bind(0);
if(m_ShaderProgram!=nullptr)
{
m_ShaderProgram->bind();
m_ShaderProgram->setUniformValue("bgTexSampler",0);
m_ShaderProgram->setUniformValue("rows",1);
m_ShaderProgram->setUniformValue("cols",2);
m_ShaderProgram->release();
}
but it gives me segmentation error when I call glTexSubImage3D . any idea on what is wrong here? and also how to set uniform value for this type of texture? My class is inherited from QOpenGLWidget class.
Edit: the segmentation fault is fixed with inheriting from QOpenGLFunctions. strange that I didn't have this problem with simple 2D textures.
now I only get a black screen instead of the texture that I sent to the shader. Here is how my paintGL looks like:
QMatrix4x4 projectionMatrix, modelMatrix, viewMatrix;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
projectionMatrix.ortho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f);
modelMatrix.setToIdentity();
viewMatrix.setToIdentity();
makeCurrent();
m_ShaderProgram->bind();
if(m_GLTexture->isCreated())
{
m_GLTexture->bind();
m_ShaderProgram->setUniformValue("projectionMatrix", projectionMatrix);
m_ShaderProgram->setUniformValue("ModelMatrix", modelMatrix);
m_ShaderProgram->setUniformValue("viewMatrix", viewMatrix);
m_ShaderProgram->setUniformValue("cameraPositionX",(float)m_vfCameraPosition.x());
m_ShaderProgram->setUniformValue("cameraPositionY",(float)m_vfCameraPosition.y());
const QVector3D vertices[4] = {
QVector3D(-1.0f, -1.0f, 0.0f),
QVector3D(-1.0f, 1.0f, 0.0f),
QVector3D( 1.0f, 1.0f, 0.0f),
QVector3D( 1.0f, -1.0f, 0.0f)
};
const QVector2D texcoords[4] = {
QVector2D(0.0f, 1.0f),
QVector2D(0.0f, 0.0f),
QVector2D(1.0f, 0.0f),
QVector2D(1.0f, 1.0f)
};
const unsigned int indices[4] = { 0, 1, 2, 3 };
m_ShaderProgram->enableAttributeArray("vertices");
m_ShaderProgram->enableAttributeArray("vTexCoords");
m_ShaderProgram->setAttributeArray("vertices", vertices);
m_ShaderProgram->setAttributeArray("vTexCoords", texcoords);
glDrawElements(GL_QUADS, 4, GL_UNSIGNED_INT, indices);
m_ShaderProgram->disableAttributeArray("vertices");
m_ShaderProgram->disableAttributeArray("vTexCoords");
m_GLTexture->bind(0);
}
m_ShaderProgram->release();
and my shader:
uniform sampler2DArray bgTexSampler;
uniform int rows;
uniform int cols;
uniform float cameraPositionX;
uniform float cameraPositionY;
smooth in vec2 FragTexCoord;
out vec4 fragColor;
void main(void)
{
vec4 color = texture(bgTexSampler, vec3(FragTexCoord, 0));
fragColor = vec4(color.rgb, 1.0);
}