I am trying to integrate 2 programs together.
One has a planet system (with moving cubes)
The other has code for a moving camera. It can also pan around
I have managed to put both of them together. The view of the planet system can be toggled to show
Perspective view (when '1' is pressed)
Top-view (when '2' is pressed)
I am having problems with my top-view (when 2 is pressed). It is not pointing at the planet system. It is right above the planets but not looking downwards. I want to point the camera downwards such that it looks like this
I have unsuccessfully been playing with this section of code (below) to get the camera to look down. More specifically, the coordinates in the g_camera.setViewMatrix function.
// render from top view
else if (key == GLFW_KEY_2 && action == GLFW_PRESS) {
cout << "Top-View" << endl << endl;
// set camera's view matrix
g_camera.setViewMatrix(glm::vec3(0, 15, 0), glm::vec3(0, 0, 0), glm::vec3(1, 0, 0));
//g_viewMatrix = glm::lookAt(glm::vec3(0, 15, 0), glm::vec3(0, 0, 0), glm::vec3(1, 0, 0));
render_scene();
}
Before I integrated the camera code, I used this look at function.
g_viewMatrix = glm::lookAt(glm::vec3(0, 15, 0), glm::vec3(0, 0, 0), glm::vec3(1, 0, 0));
However, when I plugged these same vectors for the g_camera.setViewMatrix function, it did not point in the same direction.
Another problem I have:
The red oval is actually a circle. How do I get it to appear as a circle instead of an oval? I integrated the code for the circle from another program. In that program, it was a perfect circle.
Here is my code
#include <cstdio> // for C++ i/o
#include <iostream>
#include <string>
#include <cstddef>
using namespace std; // to avoid having to use std::
#define GLEW_STATIC // include GLEW as a static library
#include <GLEW/glew.h> // include GLEW
#include <GLFW/glfw3.h> // include GLFW (which includes the OpenGL header)
#include <glm/glm.hpp> // include GLM (ideally should only use the GLM headers that are actually used)
#include <glm/gtx/transform.hpp>
using namespace glm; // to avoid having to use glm::
#include "shader.h"
#include "camera.h"
#define PI 3.14159265
#define MAX_SLICES 50
#define MIN_SLICES 8
#define MAX_VERTICES (MAX_SLICES+2)*3 // a triangle fan should have a minimum of 3 vertices
#define CIRCLE_RADIUS 3.0
#define WINDOW_WIDTH 1500
#define WINDOW_HEIGHT 800
// struct for vertex attributes
struct Vertex
{
GLfloat position[3];
GLfloat color[3];
};
// global variables
GLfloat g_vertices_circle[MAX_VERTICES] = {
0.0f, 0.0f, 0.0f, // try adjusting this value to get rid of red line
0.0f, 0.0f, 0.0f
};
GLfloat g_colors_circle[MAX_VERTICES] = {
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f
};
GLuint g_slices = MAX_SLICES; // number of circle slices
Vertex g_vertices[] = {
// vertex 1
-0.5f, 0.5f, 0.5f, // position
1.0f, 0.0f, 1.0f, // colour
// vertex 2
-0.5f, -0.5f, 0.5f, // position
1.0f, 0.0f, 0.0f, // colour
// vertex 3
0.5f, 0.5f, 0.5f, // position
1.0f, 1.0f, 1.0f, // colour
// vertex 4
0.5f, -0.5f, 0.5f, // position
1.0f, 1.0f, 0.0f, // colour
// vertex 5
-0.5f, 0.5f, -0.5f, // position
0.0f, 0.0f, 1.0f, // colour
// vertex 6
-0.5f, -0.5f, -0.5f,// position
0.0f, 0.0f, 0.0f, // colour
// vertex 7
0.5f, 0.5f, -0.5f, // position
0.0f, 1.0f, 1.0f, // colour
// vertex 8
0.5f, -0.5f, -0.5f, // position
0.0f, 1.0f, 0.0f, // colour
};
GLuint g_indices[] = {
0, 1, 2, // triangle 1
2, 1, 3, // triangle 2
4, 5, 0, // triangle 3
0, 5, 1, // ...
2, 3, 6,
6, 3, 7,
4, 0, 6,
6, 0, 2,
1, 5, 3,
3, 5, 7,
5, 4, 7,
7, 4, 6, // triangle 12
};
GLuint g_IBO = 0; // index buffer object identifier
GLuint g_VBO[3]; // vertex buffer object identifier
GLuint g_VAO[2]; // vertex array object identifier
GLuint g_shaderProgramID = 0; // shader program identifier
GLuint g_MVP_Index = 0; // location in shader
glm::mat4 g_modelMatrix[5]; // planets object model matrices
glm::mat4 g_modelMatrixCircle[5];// circle model matrices
glm::mat4 g_modelMatrixSubPlanets[5];// object matrices for sub-planets (moon, disc etc)
glm::mat4 g_viewMatrix; // view matrix
glm::mat4 g_projectionMatrix; // projection matrix
Camera g_camera; // camera
float g_orbitSpeed[5] = { 0.3f, 1.0f, 0.7f, 0.9f, 1.2f }; // for speed of rotation around sun
float g_rotationSpeed[5] = { 0.07f, 0.7f, 3.0f, 5.0f, 1.0f }; // for speed of rotation on own axis
float g_scaleSize[5] = { 0.5f, 0.5f, 0.5f, 0.5f, 0.5f }; // for scaling the orbiting planets
float g_axisOfRotation[5] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, }; // for offsetting the axis of rotation
void generate_circle()
{
float angle = PI * 2 / static_cast<float>(g_slices); // used to generate x and y coordinates
float scale_factor = static_cast<float>(WINDOW_HEIGHT) / WINDOW_WIDTH; // scale to make it a circle instead of an elipse
int index = 0; // vertex index
g_vertices_circle[3] = CIRCLE_RADIUS * scale_factor; // set x coordinate of vertex 1
// generate vertex coordinates for triangle fan
for (int i = 2; i < g_slices + 2; i++)
{
// multiply by 3 because a vertex has x, y, z coordinates
index = i * 3;
g_vertices_circle[index] = CIRCLE_RADIUS * cos(angle) * scale_factor;
g_vertices_circle[index + 1] = CIRCLE_RADIUS * sin(angle);
g_vertices_circle[index + 2] = 0.0f;
//Color for edges. See stackoverflow
g_colors_circle[index] = 1.0f;
g_colors_circle[index + 1] = 0.0f;
g_colors_circle[index + 2] = 0.0f;
// update to next angle
angle += PI * 2 / static_cast<float>(g_slices);
}
// Gets rid of line from middle of circle
g_vertices_circle[0] = g_vertices_circle[3];
g_vertices_circle[1] = g_vertices_circle[4];
g_vertices_circle[2] = g_vertices_circle[5];
}
static void init(GLFWwindow* window)
{
glClearColor(0.0, 0.0, 0.0, 1.0); // set clear background colour
glEnable(GL_DEPTH_TEST); // enable depth buffer test
// create and compile our GLSL program from the shader files
g_shaderProgramID = loadShaders("MVP_VS.vert", "ColorFS.frag");
// find the location of shader variables
GLuint positionIndex = glGetAttribLocation(g_shaderProgramID, "aPosition");
GLuint colorIndex = glGetAttribLocation(g_shaderProgramID, "aColor");
g_MVP_Index = glGetUniformLocation(g_shaderProgramID, "uModelViewProjectionMatrix");
// initialise model matrix to the identity matrix
g_modelMatrix[0] = g_modelMatrix[1] = g_modelMatrix[2] = g_modelMatrix[3] = g_modelMatrix[4] = glm::mat4(1.0f);
g_modelMatrixCircle[0] = g_modelMatrixCircle[1] = glm::mat4(1.0f);
g_modelMatrixSubPlanets[3] = glm::mat4(1.0f);;
// initialise view matrix
//g_viewMatrix = glm::lookAt(glm::vec3(10, 3, 8), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0)); //perspective
// set camera's view matrix
//g_camera.setViewMatrix(glm::vec3(10, 3, 8), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
g_camera.setViewMatrix(glm::vec3(0, 3, 14), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
int width, height;
glfwGetFramebufferSize(window, &width, &height);
float aspectRatio = static_cast<float>(width) / height;
// set camera's projection matrix
g_camera.setProjectionMatrix(glm::perspective(45.0f, aspectRatio, 0.1f, 100.0f));
// initialise projection matrix
g_projectionMatrix = glm::perspective(45.0f, aspectRatio, 0.1f, 100.0f);
// generate identifier for VBO and copy data to GPU
glGenBuffers(1, &g_VBO[0]);
glBindBuffer(GL_ARRAY_BUFFER, g_VBO[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertices), g_vertices, GL_STATIC_DRAW);
// generate identifier for IBO and copy data to GPU
glGenBuffers(1, &g_IBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(g_indices), g_indices, GL_STATIC_DRAW);
// generate identifiers for VAO
glGenVertexArrays(1, &g_VAO[0]);
// create VAO and specify VBO data
glBindVertexArray(g_VAO[0]);
glBindBuffer(GL_ARRAY_BUFFER, g_VBO[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_IBO);
// interleaved attributes
glVertexAttribPointer(positionIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, position)));
glVertexAttribPointer(colorIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, color)));
glEnableVertexAttribArray(positionIndex); // enable vertex attributes
glEnableVertexAttribArray(colorIndex);
/*------------------------Circle----------------------*/
// generate vertices of triangle fan
generate_circle();
// create VBO and buffer the data
glGenBuffers(1, &g_VBO[1]);
glBindBuffer(GL_ARRAY_BUFFER, g_VBO[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * (g_slices + 2), g_vertices_circle, GL_STATIC_DRAW);
glGenBuffers(1, &g_VBO[2]);
glBindBuffer(GL_ARRAY_BUFFER, g_VBO[2]);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * (g_slices + 2), g_colors_circle, GL_STATIC_DRAW);
// create VAO and specify VBO data
glGenVertexArrays(1, &g_VAO[1]);
glBindVertexArray(g_VAO[1]);
glBindBuffer(GL_ARRAY_BUFFER, g_VBO[1]);
glVertexAttribPointer(positionIndex, 3, GL_FLOAT, GL_FALSE, 0, 0); // specify the form of the data
glBindBuffer(GL_ARRAY_BUFFER, g_VBO[2]);
glVertexAttribPointer(colorIndex, 3, GL_FLOAT, GL_FALSE, 0, 0); // specify the form of the data
/*----------------------------------------------------*/
glEnableVertexAttribArray(positionIndex); // enable vertex attributes
glEnableVertexAttribArray(colorIndex);
}
//Generates a random value between 0.1 and 0.9
double generateRandomFloat(float min, float max)
{
return min + static_cast <float> (rand()) / (static_cast <float> (RAND_MAX / (max - min)));
}
// function used to update the scene
static void update_scene()
{
// static variables for rotation angles
static float orbitAngle[5] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, };
static float rotationAngle[5] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
float scaleFactor = 0.05;
orbitAngle[0] += g_orbitSpeed[0] * scaleFactor;
orbitAngle[1] += g_orbitSpeed[1] * scaleFactor;
orbitAngle[2] += g_orbitSpeed[2] * scaleFactor;
orbitAngle[3] += g_orbitSpeed[3] * scaleFactor;
orbitAngle[4] += g_orbitSpeed[4] * scaleFactor;
// update rotation angles
rotationAngle[0] += g_rotationSpeed[0] * scaleFactor;
rotationAngle[1] += g_rotationSpeed[1] * scaleFactor;
rotationAngle[2] += g_rotationSpeed[2] * scaleFactor;
rotationAngle[3] += g_rotationSpeed[3] * scaleFactor;
rotationAngle[4] += g_rotationSpeed[4] * scaleFactor;
// update model matrix (planets)
g_modelMatrix[0] = glm::rotate(rotationAngle[0], glm::vec3(0.0f, 1.0f, 0.0f));
g_modelMatrix[1] = glm::translate(glm::vec3(g_axisOfRotation[1], 0.0f, 0.0f)) //moves the axis of rotation along x-axis
* glm::rotate(orbitAngle[1], glm::vec3(0.0f, 1.0f, 0.0f))
* glm::translate(glm::vec3(2.0f, 0.0f, 0.0f))
* glm::rotate(rotationAngle[1], glm::vec3(0.0f, -1.0f, 0.0f)) //enables rotation on own axis. try comment
* glm::rotate(glm::radians(45.0f), glm::vec3(1.0f, 0.0f, 0.0f)) //rotates into a diamond shape
* glm::rotate(glm::radians(45.0f), glm::vec3(0.0f, 0.0f, 1.0f)) //rotates into a diamond shape
* glm::scale(glm::vec3(g_scaleSize[1], g_scaleSize[1], g_scaleSize[1]));
g_modelMatrix[2] = glm::translate(glm::vec3(g_axisOfRotation[2], 0.0f, 0.0f))
* glm::rotate(orbitAngle[2], glm::vec3(0.0f, -1.0f, 0.0f))
* glm::translate(glm::vec3(4.0f, 0.0f, 0.0f))
* glm::rotate(rotationAngle[2], glm::vec3(0.0f, 1.0f, 0.0f))
* glm::scale(glm::vec3(g_scaleSize[2], g_scaleSize[2], g_scaleSize[2]));
g_modelMatrix[3] = glm::translate(glm::vec3(g_axisOfRotation[3], 0.0f, 0.0f))
* glm::rotate(orbitAngle[3], glm::vec3(0.0f, 1.0f, 0.0f))
* glm::translate(glm::vec3(6.0f, 0.0f, 0.0f))
* glm::rotate(rotationAngle[3], glm::vec3(0.0f, 1.0f, 0.0f))
* glm::scale(glm::vec3(g_scaleSize[3], g_scaleSize[3], g_scaleSize[3]));
g_modelMatrix[4] = glm::translate(glm::vec3(g_axisOfRotation[4], 0.0f, 0.0f))
* glm::rotate(orbitAngle[4], glm::vec3(0.0f, -1.0f, 0.0f)) // -y changes orbit to clock-wise
* glm::translate(glm::vec3(8.0f, 0.0f, 0.0f))
* glm::rotate(rotationAngle[4], glm::vec3(0.0f, -1.0f, 0.0f))
* glm::scale(glm::vec3(g_scaleSize[4], g_scaleSize[4], g_scaleSize[4]));
// update model matrix (orbit paths ie.circles)
g_modelMatrixCircle[1] = glm::rotate(glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f));
// update model matrix (mini planets eg. moon)
g_modelMatrixSubPlanets[3] = glm::translate(glm::vec3(g_axisOfRotation[3], 0.0f, 0.0f))
* glm::rotate(orbitAngle[3], glm::vec3(0.0f, 1.0f, 0.0f))
* glm::translate(glm::vec3(6.0f, 0.0f, 0.0f))
* glm::rotate(rotationAngle[3], glm::vec3(0.0f, 1.0f, 0.0f))
* glm::scale(glm::vec3(g_scaleSize[3], g_scaleSize[3], g_scaleSize[3]));
}
// 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
glm::mat4 MVP = glm::mat4(1.0f); //ModelViewProjection matrix to be shared. Initialized to identity
//Circle 1
//MVP = g_projectionMatrix * g_viewMatrix * g_modelMatrixCircle[1];
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrixCircle[1];
//MVP = g_camera.getViewMatrix() * g_modelMatrixCircle[1];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glBindVertexArray(g_VAO[1]); // make VAO active
glDrawArrays(GL_LINE_LOOP, 0, g_slices + 2); // display the vertices based on the primitive type
glBindVertexArray(g_VAO[0]); // make VAO active
// Object 1
//MVP = g_projectionMatrix * g_viewMatrix * g_modelMatrix[0];
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix[0];
// set uniform model transformation matrix
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
// Object 2
//MVP = g_projectionMatrix * g_viewMatrix * g_modelMatrix[1];
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix[1];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
// Object 3
//MVP = g_projectionMatrix * g_viewMatrix * g_modelMatrix[2];
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix[2];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
// Object 4
//MVP = g_projectionMatrix * g_viewMatrix * g_modelMatrix[3];
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix[3];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
// Object 5
//MVP = g_projectionMatrix * g_viewMatrix * g_modelMatrix[4];
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix[4];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
// Moon for Object 3
//MVP = g_projectionMatrix * g_viewMatrix * g_modelMatrixSubPlanets[3] * g_modelMatrix[4];
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrixSubPlanets[3] * g_modelMatrix[4];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
glFlush(); // flush the pipeline
}
static void cursor_position_callback(GLFWwindow* window, double xpos, double ypos)
{
// variables to store mouse cursor coordinates
static double previous_xpos = xpos;
static double previous_ypos = ypos;
double delta_x = xpos - previous_xpos;
double delta_y = ypos - previous_ypos;
// pass mouse movement to camera class
g_camera.updateYaw(delta_x);
g_camera.updatePitch(delta_y);
// update previous mouse coordinates
previous_xpos = xpos;
previous_ypos = ypos;
}
// key press or release callback function
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
// quit if the ESCAPE key was press
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
{
// set flag to close the window
glfwSetWindowShouldClose(window, GL_TRUE);
return;
}
// render in perspective view
else if (key == GLFW_KEY_1 && action == GLFW_PRESS) {
cout << "Perspective-View" << endl << endl;
// set camera's view matrix
g_camera.setViewMatrix(glm::vec3(0, 3, 14), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
//g_viewMatrix = glm::lookAt(glm::vec3(10, 3, 8), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
render_scene();
}
// render from top view
else if (key == GLFW_KEY_2 && action == GLFW_PRESS) {
cout << "Top-View" << endl << endl;
// set camera's view matrix
g_camera.setViewMatrix(glm::vec3(0, 15, 0), glm::vec3(0, 0, 0), glm::vec3(1, 0, 0));
//g_viewMatrix = glm::lookAt(glm::vec3(0, 15, 0), glm::vec3(0, 0, 0), glm::vec3(1, 0, 0));
render_scene();
}
// render from eye-level view
else if (key == GLFW_KEY_3 && action == GLFW_PRESS) {
cout << "Eye-level View" << endl << endl;
// set camera's view matrix
g_camera.setViewMatrix(glm::vec3(0, 0, 10), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
//g_viewMatrix = glm::lookAt(glm::vec3(0, 0, 10), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
render_scene();
}
// Randomize size, orbit speed, axis rotation speed of planets
else if (key == GLFW_KEY_R && action == GLFW_PRESS) {
// Randomize planet size
g_scaleSize[1] = generateRandomFloat(0.1, 0.75);
g_scaleSize[2] = generateRandomFloat(0.1, 0.75);
g_scaleSize[3] = generateRandomFloat(0.1, 0.75);
g_scaleSize[4] = generateRandomFloat(0.1, 0.75);
// Randomize speed of rotation (on planets own axis)
g_rotationSpeed[1] = generateRandomFloat(0.1, 10.0);
g_rotationSpeed[2] = generateRandomFloat(0.1, 10.0);
g_rotationSpeed[3] = generateRandomFloat(0.1, 10.0);
g_rotationSpeed[4] = generateRandomFloat(0.1, 10.0);
// Randomize speed of rotation around sun
g_orbitSpeed[1] = generateRandomFloat(0.1, 1.2);
g_orbitSpeed[2] = generateRandomFloat(0.1, 1.2);
g_orbitSpeed[3] = generateRandomFloat(0.1, 1.2);
g_orbitSpeed[4] = generateRandomFloat(0.1, 1.2);
// Randomize offset for axis of rotation
g_axisOfRotation[1] = generateRandomFloat(-0.5, 0.5);
g_axisOfRotation[2] = generateRandomFloat(-0.5, 0.5);
g_axisOfRotation[3] = generateRandomFloat(-0.5, 0.5);
g_axisOfRotation[4] = generateRandomFloat(-0.5, 0.5);
// Display info for each planet
cout << "PLANET 1 - \tSize: " << g_scaleSize[1] << "\tSpeed: " << g_rotationSpeed[1]
<< "\tOrbit Speed: " << g_orbitSpeed[1] << "\tAxis offset: " << g_axisOfRotation[1] << endl;
cout << "PLANET 2 - \tSize: " << g_scaleSize[2] << "\tSpeed: " << g_rotationSpeed[2]
<< "\tOrbit Speed: " << g_orbitSpeed[2] << "\tAxis offset: " << g_axisOfRotation[2] << endl;
cout << "PLANET 3 - \tSize: " << g_scaleSize[3] << "\tSpeed: " << g_rotationSpeed[3]
<< "\tOrbit Speed: " << g_orbitSpeed[3] << "\tAxis offset: " << g_axisOfRotation[3] << endl;
cout << "PLANET 4 - \tSize: " << g_scaleSize[4] << "\tSpeed: " << g_rotationSpeed[4]
<< "\tOrbit Speed: " << g_orbitSpeed[4] << "\tAxis offset: " << g_axisOfRotation[4] << endl;
cout << endl;
render_scene();
}
}
// error callback function
static void error_callback(int error, const char* description)
{
cerr << description << endl; // output error description
}
int main(void)
{
GLFWwindow* window = NULL; // pointer to a GLFW window handle
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(1500, 1000, "Assignment 2", 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);
// 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_DISABLED);
// initialise rendering states
init(window);
// variables for simple time management
float lastUpdateTime = glfwGetTime();
float currentTime = lastUpdateTime;
// the rendering loop
while (!glfwWindowShouldClose(window))
{
currentTime = glfwGetTime();
g_camera.update(window); // update camera
// only update if more than 0.02 seconds since last update
if (currentTime - lastUpdateTime > 0.02)
{
update_scene(); // update the scene
render_scene(); // render the scene
glfwSwapBuffers(window); // swap buffers
glfwPollEvents(); // poll for events
lastUpdateTime = currentTime; // update last update time
}
}
// clean up
glDeleteProgram(g_shaderProgramID);
glDeleteBuffers(1, &g_IBO);
glDeleteBuffers(1, &g_VBO[0]);
glDeleteBuffers(1, &g_VBO[1]);
glDeleteVertexArrays(1, &g_VAO[0]);
glDeleteVertexArrays(1, &g_VAO[1]);
// close the window and terminate GLFW
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}
Camera.cpp
#include "Camera.h"
Camera::Camera()
{
// initialise camera member variables
mPosition = glm::vec3(0.0f, 0.0f, 1.0f);
mLookAt = glm::vec3(0.0f, 0.0f, 0.0f);
mUp = glm::vec3(0.0f, 1.0f, 0.0f);
mYaw = 0.0f;
mPitch = 0.0f;
mViewMatrix = glm::lookAt(mPosition, mLookAt, mUp);
mProjectionMatrix = glm::perspective(45.0f, 1.5f, 0.1f, 100.0f);
}
Camera::~Camera()
{}
void Camera::update(GLFWwindow* window)
{
// variables to store forward/back and strafe movement
float moveForward = 0;
float strafeRight = 0;
// update variables based on keyboard input
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
moveForward += MOVEMENT_SENSITIVITY;
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
moveForward -= MOVEMENT_SENSITIVITY;
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
strafeRight -= MOVEMENT_SENSITIVITY;
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
strafeRight += MOVEMENT_SENSITIVITY;
// rotate the respective unit vectors about the y-axis
glm::vec3 rotatedForwardVec = glm::rotateY(glm::vec3(0.0f, 0.0f, -1.0f), mYaw);
glm::vec3 rotatedRightVec = glm::rotateY(glm::vec3(1.0f, 0.0f, 0.0f), mYaw);
// rotate the rotated forward vector about the rotated right vector
rotatedForwardVec = glm::vec3(glm::rotate(mPitch, rotatedRightVec)*glm::vec4(rotatedForwardVec, 0.0f));
// update position, look-at and up vectors
mPosition += rotatedForwardVec * moveForward + rotatedRightVec * strafeRight;
mLookAt = mPosition + rotatedForwardVec;
mUp = glm::cross(rotatedRightVec, rotatedForwardVec);
// compute the new view matrix
mViewMatrix = glm::lookAt(mPosition, mLookAt, mUp);
}
void Camera::updateYaw(float yaw)
{
mYaw -= yaw * ROTATION_SENSITIVITY;
}
void Camera::updatePitch(float pitch)
{
mPitch -= pitch * ROTATION_SENSITIVITY;
}
void Camera::setViewMatrix(glm::vec3 position, glm::vec3 lookAt, glm::vec3 up)
{
mPosition = position;
mLookAt = lookAt;
mUp = up;
mViewMatrix = glm::lookAt(mPosition, mLookAt, mUp);
}
void Camera::setProjectionMatrix(glm::mat4& matrix)
{
mProjectionMatrix = matrix;
}
glm::mat4 Camera::getViewMatrix()
{
return mViewMatrix;
}
glm::mat4 Camera::getProjectionMatrix()
{
return mProjectionMatrix;
}
Camera.h
#ifndef __CAMERA_H
#define __CAMERA_H
#include <GLFW/glfw3.h> // include GLFW (which includes the OpenGL header)
#include <glm/glm.hpp> // include GLM (ideally should only use the GLM headers that are actually used)
#include <glm/gtx/transform.hpp>
#include <glm/gtx/rotate_vector.hpp>
using namespace glm; // to avoid having to use glm::
#define MOVEMENT_SENSITIVITY 0.0005f // camera movement sensitivity
#define ROTATION_SENSITIVITY 0.001f // camera rotation sensitivity
class Camera {
public:
Camera();
~Camera();
void update(GLFWwindow* window);
void updateYaw(float yaw);
void updatePitch(float pitch);
void setViewMatrix(glm::vec3 position, glm::vec3 lookAt, glm::vec3 up);
void setProjectionMatrix(glm::mat4& matrix);
glm::mat4 getViewMatrix();
glm::mat4 getProjectionMatrix();
private:
float mYaw;
float mPitch;
glm::vec3 mPosition;
glm::vec3 mLookAt;
glm::vec3 mUp;
glm::mat4 mViewMatrix;
glm::mat4 mProjectionMatrix;
};
#endif
Vertex shader
#version 330 core
// input data (different for all executions of this shader)
in vec3 aPosition;
in vec3 aColor;
// ModelViewProjection matrix
uniform mat4 uModelViewProjectionMatrix;
// output data (will be interpolated for each fragment)
out vec3 vColor;
void main()
{
// set vertex position
gl_Position = uModelViewProjectionMatrix * vec4(aPosition, 1.0);
// the color of each vertex will be interpolated
// to produce the color of each fragment
vColor = aColor;
}
You have to map from world coordinates to viewport cooordinates
x y z
--------
1 0 0 | x' = x
0 0 1 | y' = z
0 -1 0 | z' = -y
Use this to see the scene from above:
g_camera.setViewMatrix(glm::vec3(0, 15.0f, 0), glm::vec3(0, 0, 0), glm::vec3(0, 0, -1.0f));
To pane, zoom and orbit the view you have to set up translation and rotation matrices and you have to concatenate (multiply)
them with the view matrix.
Add members to the class Camerato store the translation and rotation angles:
glm::vec3 _move;
float _angX;
float _angY;
Adapt the method Camera::update to sum up the translation and rotation angles:
#define MOVEMENT_SENSITIVITY 0.01f
#define ZOOM_SENSITIVITY 0.1f
#define ROTATION_SENSITIVITY 1.0f
void Camera::update(GLFWwindow* window)
{
if ( glfwGetKey( window, GLFW_KEY_A ) == GLFW_PRESS ) _move[0] -= MOVEMENT_SENSITIVITY;
if ( glfwGetKey( window, GLFW_KEY_D ) == GLFW_PRESS ) _move[0] += MOVEMENT_SENSITIVITY;
if ( glfwGetKey( window, GLFW_KEY_S ) == GLFW_PRESS ) _move[1] -= MOVEMENT_SENSITIVITY;
if ( glfwGetKey( window, GLFW_KEY_W ) == GLFW_PRESS ) _move[1] += MOVEMENT_SENSITIVITY;
if ( glfwGetKey( window, GLFW_KEY_PAGE_DOWN ) == GLFW_PRESS ) _move[2] -= ZOOM_SENSITIVITY;
if ( glfwGetKey( window, GLFW_KEY_PAGE_UP ) == GLFW_PRESS ) _move[2] += ZOOM_SENSITIVITY;
if ( glfwGetKey( window, GLFW_KEY_UP ) == GLFW_PRESS ) _angX -= ROTATION_SENSITIVITY;
if ( glfwGetKey( window, GLFW_KEY_DOWN ) == GLFW_PRESS ) _angX += ROTATION_SENSITIVITY;
if ( glfwGetKey( window, GLFW_KEY_RIGHT ) == GLFW_PRESS ) _angY -= ROTATION_SENSITIVITY;
if ( glfwGetKey( window, GLFW_KEY_LEFT ) == GLFW_PRESS ) _angY += ROTATION_SENSITIVITY;
}
Note, you have to adjust the sensitivity and the buttons or even other kinds of input to your needs. To get a clearly defined behavior you should execute the update method in a time discrete process.
Set up the translation matrix and the rotation matrices in the methode Camera::getViewMatrix and concatenate them to the view matrix:
glm::mat4 Camera::getViewMatrix()
{
glm::mat4 rotX = glm::rotate( _angX * (float)PI / 180.0f, glm::vec3( mViewMatrix[0] ) );
glm::mat4 rotY = glm::rotate( _angY * (float)PI / 180.0f, glm::vec3( mViewMatrix[1] ) );
glm::mat4 trans = glm::translate( glm::mat4( 1.0 ), _move );
return trans * mViewMatrix * rotX * rotY;
}
Related
When running the program, the camera seems to work fine and I can manipulate the clear colour but the cube itself will not render.
Here's my code:
(The camera and renderer objects are both declared in their respective header files along with their methods)
Main.cpp
#include <GL/glew.h>
#include "Shapes.h"
#include "Renderer.h"
#include "Camera.h"
int main()
{
Renderer* renderer = new Renderer(800, 800, (const char*)"OpenGL Sample Test", glm::vec4(0.0f, 0.0f, 0.0f, 1.0f));
GLFWwindow* window = renderer->getWindow();
Block* cube = new Block(renderer);
cube->setColourTint(glm::vec4(0.3f, 0.0f, 0.4f, 1.0f));
while (!glfwWindowShouldClose(window))
{
renderer->updateRender();
cube->rotate((float)glfwGetTime() * glm::radians(50.0f), glm::vec3(0.5f, 0.5f, 0.0f));
}
delete renderer;
return 0;
}
Renderer.cpp
#include "Renderer.h"
#include "Shapes.h"
Renderer::Renderer(int Window_X, int Window_Y, const char* Window_Title, glm::vec4 ClearColour)
{
Renderer::renderList = new std::vector<Shape*>;
Renderer::clearColour = ClearColour;
Renderer::WINDOW_X = Window_X;
Renderer::WINDOW_Y = Window_Y;
Renderer::WINDOW_TITLE = Window_Title;
createWindow();
std::cout << "Running OpenGL extension checks... ";
GLenum glewTest = glewInit();
if (GLEW_OK != glewTest)
{
std::cout << "FAILED";
std::cout << (const char*)glewGetErrorString(glewTest) << std::endl;
glfwDestroyWindow(window);
}
else
{
std::cout << "OK" << std::endl;
glfwMakeContextCurrent(window);
}
//OPENGL//
glEnable(GL_DEPTH_TEST);
glViewport(0, 0, Window_X, Window_Y);
Renderer::shader = new Shader("Vertex.glsl", "Fragment.glsl"); //Create the shaders
Renderer::camera = new Camera(Window_X, Window_Y, glm::vec3(0.0f, 0.0f, 2.0f));
Renderer::modelMatrixShaderLocation = glGetUniformLocation(shader->ID, "model"); //Grab the name of the uniform of the model matrix
Renderer::fragmentColourTintLocation = glGetUniformLocation(shader->ID, "colourTint");
glCheckError();
}
void Renderer::createWindow()
{
//Define OpenGL Version | Create Window
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
std::cout << "Creating GLFW Window... ";
Renderer::window = glfwCreateWindow(WINDOW_X, WINDOW_Y, WINDOW_TITLE, NULL, NULL);
if (window == NULL)
{
std::cout << "ERROR: GLFW WINDOW FAILED TO INSTANTIATE" << std::endl;
glfwTerminate();
}
else
{
std::cout << "OK" << std::endl;
glfwMakeContextCurrent(window);
//Key Callbacks
glfwSetKeyCallback(window, key_callback);
glfwSetWindowCloseCallback(window, close_callback);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
}
}
bool Renderer::updateRender()
{
glClearColor(clearColour.r, clearColour.g, clearColour.b, clearColour.a); //Add background color
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //Clear the color and depth back buffers
shader->use(); //Bind to the shader program
for (int i = 0; i < renderList->size(); i++)
{
Shape* current = renderList->at(i);
current->clearMatrix();
}
//Refresh the projection matrix
//projection = glm::mat4(1.0f);
//projection = glm::perspective(glm::radians(45.0f), (float)WINDOW_X / (float)WINDOW_Y, 0.1f, 100.0f);
//shader->setMat4("projection", projection);
glCheckError();
for (int i = 0; i < renderList->size(); i++) //Update matrix of each renderable object
{
Shape* current = renderList->at(i);
glUniformMatrix4fv(modelMatrixShaderLocation, 1, GL_FALSE, glm::value_ptr(current->getPosition()));
glUniform4f(fragmentColourTintLocation, current->getColourTint().r, current->getColourTint().g, current->getColourTint().b, current->getColourTint().a);
glBindVertexArray(current->getVAO());
std::cout << "Drawing: " << current << " : " << current->getVAO() << std::endl;
glDrawElements(GL_TRIANGLES, current->getIndicesStride(), GL_UNSIGNED_INT, 0);
glCheckError();
}
camera->Inputs(window); //Process camera input
//Camera Matrix updating
camera->Matrix(45.0f, 0.1f, 100.0f, shader, "camMatrix");
glfwSwapBuffers(window);
glfwPollEvents();
if (glCheckError() != NULL)
{
return true;
}
else
{
return false;
}
}
Renderer::~Renderer()
{
for (int i = 0; i < renderList->size(); i++)
{
Shape* current = renderList->at(i);
glDeleteVertexArrays(1, current->getVAOAddress());
glDeleteBuffers(1, current->getVBOAddress());
glDeleteBuffers(1, current->getEBOAddress());
delete current;
}
glfwDestroyWindow(window);
glfwTerminate();
glDeleteProgram(shader->ID);
delete renderList;
delete shader;
delete camera;
}
GLFWwindow* Renderer::getWindow()
{
return window;
}
void Renderer::push_Renderer(Shape* Renderable_Object)
{
renderList->push_back(Renderable_Object);
}
void Renderer::updateClearColour(glm::vec4 ClearColour)
{
clearColour = ClearColour;
}
Camera.cpp
#include "Camera.h"
Camera::Camera(int width, int height, glm::vec3 position)
{
Camera::width = width;
Camera::height = height;
Position = position;
}
void Camera::Matrix(float FOVdeg, float nearPlane, float farPlane, Shader* shader, const char* uniform)
{
//Matrix Magic
glm::mat4 view = glm::mat4(1.0f);
glm::mat4 projection = glm::mat4(1.0f);
view = glm::lookAt(Position, Position + Orientation, Up);
projection = glm::perspective(glm::radians(FOVdeg), (float)(width / height), nearPlane, farPlane);
//std::cout << "XYZ: " << Position.x << " : " << Position.y << " : " << Position.z << std::endl;
glUniformMatrix4fv(glGetUniformLocation(shader->ID, uniform), 1, GL_FALSE, glm::value_ptr(projection * view));
}
void Camera::Inputs(GLFWwindow* window)
{
//Basic Camera Controls
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
{
Position += speed * Orientation;
}
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
{
Position += speed * -glm::normalize(glm::cross(Orientation, Up));
}
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
{
Position += speed * -Orientation;
}
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
{
Position += speed * glm::normalize(glm::cross(Orientation, Up));
}
if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS)
{
Position += speed * Up;
}
if (glfwGetKey(window, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS)
{
Position += speed * -Up;
}
if (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS)
{
speed = 0.4f;
}
if (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_RELEASE)
{
speed = 0.1f;
}
//Mouse Control
if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS) //Hide cursor when left mouse button is pressed
{
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
double MouseX;
double MouseY;
glfwGetCursorPos(window, &MouseX, &MouseY);
float rotX = sensitivity * (float)(MouseY - (height / 2)) / height;
float rotY = sensitivity * (float)(MouseX - (height / 2)) / height;
glm::vec3 newOrientation = glm::rotate(Orientation, glm::radians(-rotX), glm::normalize(glm::cross(Orientation, Up)));
if (!((glm::angle(newOrientation, Up) <= glm::radians(5.0f)) or (glm::angle(newOrientation, -Up) <= glm::radians(5.0f))))
{
Orientation = newOrientation;
}
Orientation = glm::rotate(Orientation, glm::radians(-rotY), Up);
glfwSetCursorPos(window, (width / 2), (height / 2));
}
if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_RELEASE) //Show cursor when left mouse button is released
{
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
}
}
Shapes.h
#pragma once
#ifndef SHAPES_H
#define SHAPES_H
#include "Renderer.h"
#include <GL/glew.h>
#include <glm.hpp>
#include <gtc/type_ptr.hpp>
#include <gtx/rotate_vector.hpp>
#include <gtx/vector_angle.hpp>
inline void GeneralVao(GLuint &VAO, GLuint &VBO, GLuint &EBO, GLint* indices, GLfloat* vertices, GLsizeiptr sizeofidef, GLsizeiptr sizeofvdef)
{
//bind the Vertex Array Object first, then bind and set vertex buffer, and then configure vertex attributes(s).
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
//EBO
glGenBuffers(1, &EBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeofidef, indices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeofvdef, vertices, GL_STATIC_DRAW);
//Position Attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (void*)0);
glEnableVertexAttribArray(0);
//Colour Attribute
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
//unbind
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
class Shape
{
protected:
GLfloat* vertices = NULL;
GLint* indices = NULL;
virtual void constructVao() = 0;
GLuint VAO = NULL, VBO = NULL, EBO = NULL;
glm::mat4 ModelMatrix = glm::mat4(1.0f);
glm::vec4 colourTint = glm::vec4(1.0f);
public:
GLuint getVAO()
{
return VAO;
}
glm::vec4 getColourTint()
{
return colourTint;
}
void setColourTint(glm::vec4 Colour)
{
colourTint = Colour;
}
//Addresses
GLuint* getVAOAddress()
{
return &VAO;
}
GLuint* getVBOAddress()
{
return &VBO;
}
GLuint* getEBOAddress()
{
return &EBO;
}
//
void setPosition(glm::mat4 Matrix)
{
ModelMatrix = Matrix;
}
void rotate(glm::f32 angle, glm::vec3 axis) //Rotates by an angle (floating point) and an axis (vector3)
{
ModelMatrix = glm::rotate(ModelMatrix, angle, axis);
}
void scale(glm::vec3 ScaleFactor3)
{
ModelMatrix = glm::scale(ModelMatrix, ScaleFactor3);
}
void move(glm::vec3 Vector)
{
ModelMatrix = glm::translate(ModelMatrix, Vector);
}
void clearMatrix()
{
ModelMatrix = glm::mat4(1.0f);
}
virtual GLsizei getIndicesStride() = 0;
glm::mat4 getPosition()
{
return ModelMatrix;
}
virtual ~Shape()
{
}
};
class Pyramid : public Shape
{
private:
GLfloat vdef[30] = {
//Position Colour
-0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, //Front Bottom Left | 0
0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 0.0f, //Front Bottom Right | 1
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, //Back Bottom Left | 2
0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.0f, //Back Bottom Right | 3
0.0f, 0.5f, 0.0f, 1.0f, 1.0f, 1.0f //Top | 4
};
GLint idef[18] = {
//Bottom
0, 2, 3,
3, 1, 0,
//Front
1, 4, 0 ,
//Left
0, 4, 2,
//Right
1, 4, 3,
//Back
3, 4, 2
};
public:
Pyramid(Renderer* renderer)
{
indices = idef;
vertices = vdef;
constructVao();
renderer->push_Renderer(this);
}
void constructVao()
{
GeneralVao(VAO, VBO, EBO, idef, vdef, sizeof(idef), sizeof(vdef));
}
GLsizei getIndicesStride()
{
return sizeof(idef) / sizeof(GLint);
}
virtual ~Pyramid()
{
}
};
class Block : public Shape
{
private:
GLfloat vdef[48] = {
//Position Colour
-0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, //Front Bottom Left | 0
0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 0.0f, //Front Bottom Right | 1
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, //Back Bottom Left | 2
0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.0f, //Back Bottom Right | 3
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, //Front Top Left | 4
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, //Front Top Right | 5
-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, //Back Top Left | 6
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f, //Back Top Right | 7
};
GLint idef[36] = {
//Bottom
0, 1, 3,
3, 2, 0,
//Front
1, 0, 4,
4, 5, 1,
//Left
0, 2, 6,
6, 4, 0,
//Right
1, 3, 7,
7, 5, 1,
//Top
4, 5, 7,
7, 6, 4,
//Back
2, 3, 5,
5, 5, 2
};
public:
Block(Renderer* renderer)
{
indices = idef;
vertices = vdef;
setColourTint(glm::vec4(0.3, 0.0, 1.0, 1.0));
constructVao();
renderer->push_Renderer(this);
}
void constructVao()
{
GeneralVao(VAO, VBO, EBO, idef, vdef, (GLsizeiptr)sizeof(idef), (GLsizeiptr)sizeof(vdef));
}
GLsizei getIndicesStride()
{
return sizeof(idef) / sizeof(GLint);
}
virtual ~Block()
{
}
};
#endif
Vertex.glsl
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
uniform mat4 model;
uniform mat4 camMatrix;
out vec3 ourColor;
void main()
{
gl_Position = camMatrix * model * vec4(aPos, 1.0);
ourColor = aColor;
}
Fragment.glsl
#version 330 core
out vec4 FragColor;
in vec3 ourColor;
uniform vec4 colourTint;
void main()
{
FragColor.a = colourTint.a;
FragColor.rgb = ((FragColor.rgb - colourTint.rgb) / FragColor.rgb) * 100;
}
I found the issue.
Turns out it worked, just the cube was unexpectedly black along with the clearcolor.
Ran the code and no errors. A blank screen appear. Can't see where I went wrong after I edited this section of the code.
Trying to integrate a planet system of 4 planets and 1 sun. The program was running and showing the system, but once I edited this section of the code. It became blank screen.
planetsystem.cpp
#include <string>
using namespace std; // to avoid having to use std::
#define GLEW_STATIC // include GLEW as a static library
#include <GLEW/glew.h> // include GLEW
#include <GLFW/glfw3.h> // include GLFW (which includes the OpenGL header)
#include <glm/glm.hpp> // include GLM (ideally should only use the GLM headers that are actually used)
#include <glm/gtx/transform.hpp>
using namespace glm; // to avoid having to use glm::
#include "shader.h"
#include "camera.h"
#define PI 3.14159265
#define MAX_SLICES 50
#define MIN_SLICES 8
#define MAX_VERTICES (MAX_SLICES+2)*3 // a triangle fan should have a minimum of 3 vertices
#define CIRCLE_RADIUS 3.0
#define WINDOW_WIDTH 1000
#define WINDOW_HEIGHT 1000
// struct for vertex attributes
struct Vertex
{
GLfloat position[3];
GLfloat color[3];
};
// global variables
GLfloat g_vertices_circle[MAX_VERTICES] = {
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f
};
GLfloat g_colors_circle[MAX_VERTICES] = {
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f
};
GLuint g_slices = MAX_SLICES; // number of circle slices
Vertex g_vertices[] = {
// vertex 1
-0.5f, 0.5f, 0.5f, // position
1.0f, 0.0f, 1.0f, // colour
// vertex 2
-0.5f, -0.5f, 0.5f, // position
1.0f, 0.0f, 0.0f, // colour
// vertex 3
0.5f, 0.5f, 0.5f, // position
1.0f, 1.0f, 1.0f, // colour
// vertex 4
0.5f, -0.5f, 0.5f, // position
1.0f, 1.0f, 0.0f, // colour
// vertex 5
-0.5f, 0.5f, -0.5f, // position
0.0f, 0.0f, 1.0f, // colour
// vertex 6
-0.5f, -0.5f, -0.5f,// position
0.0f, 0.0f, 0.0f, // colour
// vertex 7
0.5f, 0.5f, -0.5f, // position
0.0f, 1.0f, 1.0f, // colour
// vertex 8
0.5f, -0.5f, -0.5f, // position
0.0f, 1.0f, 0.0f, // colour
};
GLuint g_indices[] = {
0, 1, 2, // triangle 1
2, 1, 3, // triangle 2
4, 5, 0, // triangle 3
0, 5, 1, // ...
2, 3, 6,
6, 3, 7,
4, 0, 6,
6, 0, 2,
1, 5, 3,
3, 5, 7,
5, 4, 7,
7, 4, 6, // triangle 12
};
GLuint g_IBO = 0; // index buffer object identifier
GLuint g_VBO[3]; // vertex buffer object identifier
GLuint g_VAO[2]; // vertex array object identifier
GLuint g_shaderProgramID = 0; // shader program identifier
GLuint g_MVP_Index = 0; // location in shader
GLuint g_alphaIndex; // for transparency of 4th planet
glm::mat4 g_modelMatrix[5]; // planets object model matrices
glm::mat4 g_modelMatrixCircle[5];// circle model matrices
glm::mat4 g_modelMatrixSubPlanets[5];// object matrices for sub-planets (moon, disc etc)
glm::mat4 g_viewMatrix; // view matrix
glm::mat4 g_projectionMatrix; // projection matrix
Camera g_camera; // camera
float g_orbitSpeed[5] = { 0.3f, 0.5f, 0.4f, 0.2f, 0.1f }; // for speed of rotation around sun
float g_rotationSpeed[5] = { 0.07f, 0.7f, 3.0f, 5.0f, 1.0f }; // for speed of rotation on own axis
float g_scaleSize[5] = { 0.5f, 0.5f, 0.5f, 0.5f, 0.5f }; // for scaling the orbiting planets
float g_axisOfRotation[5] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, }; // for offsetting the axis of rotation
float g_alpha = 0.5f; // transparency of 4th planet
bool g_enableAnimation = true;
void generate_circle()
{
float angle = PI * 2 / static_cast<float>(g_slices); // used to generate x and y coordinates
float scale_factor = static_cast<float>(WINDOW_HEIGHT) / WINDOW_WIDTH; // scale to make it a circle instead of an elipse
int index = 0; // vertex index
g_vertices_circle[3] = CIRCLE_RADIUS * scale_factor; // set x coordinate of vertex 1
// generate vertex coordinates for triangle fan
for (int i = 2; i < g_slices + 2; i++)
{
// multiply by 3 because a vertex has x, y, z coordinates
index = i * 3;
g_vertices_circle[index] = CIRCLE_RADIUS * cos(angle) * scale_factor;
g_vertices_circle[index + 1] = CIRCLE_RADIUS * sin(angle);
g_vertices_circle[index + 2] = 0.0f;
//Color for edges. See stackoverflow
g_colors_circle[index] = 1.0f;
g_colors_circle[index + 1] = 0.0f;
g_colors_circle[index + 2] = 0.0f;
// update to next angle
angle += PI * 2 / static_cast<float>(g_slices);
}
// Gets rid of line from middle of circle
g_vertices_circle[0] = g_vertices_circle[3];
g_vertices_circle[1] = g_vertices_circle[4];
g_vertices_circle[2] = g_vertices_circle[5];
}
static void init(GLFWwindow* window)
{
glClearColor(0.0, 0.0, 0.0, 1.0); // set clear background colour
glEnable(GL_DEPTH_TEST); // enable depth buffer test
glEnable(GL_BLEND);
glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
// create and compile our GLSL program from the shader files
g_shaderProgramID = loadShaders("MVP_VS.vert", "ColorFS.frag");
// find the location of shader variables
GLuint positionIndex = glGetAttribLocation(g_shaderProgramID, "aPosition");
GLuint colorIndex = glGetAttribLocation(g_shaderProgramID, "aColor");
g_MVP_Index = glGetUniformLocation(g_shaderProgramID, "uModelViewProjectionMatrix");
g_alphaIndex = glGetUniformLocation(g_shaderProgramID, "uAlpha");
// initialise model matrix to the identity matrix
g_modelMatrix[0] = g_modelMatrix[1] = g_modelMatrix[2] = g_modelMatrix[3] = g_modelMatrix[4] = glm::mat4(1.0f);
g_modelMatrixCircle[0] = g_modelMatrixCircle[1] = g_modelMatrixCircle[2] = g_modelMatrixCircle[3] = g_modelMatrixCircle[4] = glm::mat4(1.0f);
g_modelMatrixSubPlanets[2] = g_modelMatrixSubPlanets[3] = glm::mat4(1.0f);;
// set camera's view matrix
g_camera.setViewMatrix(glm::vec3(0, 3, 14), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
int width, height;
glfwGetFramebufferSize(window, &width, &height);
float aspectRatio = static_cast<float>(width) / height;
// set camera's projection matrix
g_camera.setProjectionMatrix(g_projectionMatrix);
// initialise projection matrix
g_projectionMatrix = glm::perspective(45.0f, aspectRatio, 0.1f, 100.0f);
// generate identifier for VBO and copy data to GPU
glGenBuffers(1, &g_VBO[0]);
glBindBuffer(GL_ARRAY_BUFFER, g_VBO[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertices), g_vertices, GL_STATIC_DRAW);
// generate identifier for IBO and copy data to GPU
glGenBuffers(1, &g_IBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(g_indices), g_indices, GL_STATIC_DRAW);
// generate identifiers for VAO
glGenVertexArrays(1, &g_VAO[0]);
// create VAO and specify VBO data
glBindVertexArray(g_VAO[0]);
glBindBuffer(GL_ARRAY_BUFFER, g_VBO[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_IBO);
// interleaved attributes
glVertexAttribPointer(positionIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, position)));
glVertexAttribPointer(colorIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, color)));
glEnableVertexAttribArray(positionIndex); // enable vertex attributes
glEnableVertexAttribArray(colorIndex);
/*------------------------Circle----------------------*/
// generate vertices of triangle fan
generate_circle();
// create VBO and buffer the data
glGenBuffers(1, &g_VBO[1]);
glBindBuffer(GL_ARRAY_BUFFER, g_VBO[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * (g_slices + 2), g_vertices_circle, GL_STATIC_DRAW);
glGenBuffers(1, &g_VBO[2]);
glBindBuffer(GL_ARRAY_BUFFER, g_VBO[2]);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * (g_slices + 2), g_colors_circle, GL_STATIC_DRAW);
// create VAO and specify VBO data
glGenVertexArrays(1, &g_VAO[1]);
glBindVertexArray(g_VAO[1]);
glBindBuffer(GL_ARRAY_BUFFER, g_VBO[1]);
glVertexAttribPointer(positionIndex, 3, GL_FLOAT, GL_FALSE, 0, 0); // specify the form of the data
glBindBuffer(GL_ARRAY_BUFFER, g_VBO[2]);
glVertexAttribPointer(colorIndex, 3, GL_FLOAT, GL_FALSE, 0, 0); // specify the form of the data
glEnableVertexAttribArray(positionIndex); // enable vertex attributes
glEnableVertexAttribArray(colorIndex);
/*----------------------------------------------------*/
}
//Generates a random value between 0.1 and 0.9
double generateRandomFloat(float min, float max)
{
return min + static_cast <float> (rand()) / (static_cast <float> (RAND_MAX / (max - min)));
}
// function used to update the scene
static void update_scene()
{
// static variables for rotation angles
static float orbitAngle[5] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, };
static float rotationAngle[5] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
float scaleFactor = 0.05;
orbitAngle[0] += g_orbitSpeed[0] * scaleFactor;
orbitAngle[1] += g_orbitSpeed[1] * scaleFactor;
orbitAngle[2] += g_orbitSpeed[2] * scaleFactor;
orbitAngle[3] += g_orbitSpeed[3] * scaleFactor;
orbitAngle[4] += g_orbitSpeed[4] * scaleFactor;
// update rotation angles
rotationAngle[0] += g_rotationSpeed[0] * scaleFactor;
rotationAngle[1] += g_rotationSpeed[1] * scaleFactor;
rotationAngle[2] += g_rotationSpeed[2] * scaleFactor;
rotationAngle[3] += g_rotationSpeed[3] * scaleFactor;
rotationAngle[4] += g_rotationSpeed[4] * scaleFactor;
// update model matrix (planets)
g_modelMatrix[0] = glm::rotate(rotationAngle[0], glm::vec3(0.0f, 1.0f, 0.0f));
g_modelMatrix[1] = glm::translate(glm::vec3(g_axisOfRotation[1], 0.0f, 0.0f)) //moves the axis of rotation along x-axis
* glm::rotate(orbitAngle[1], glm::vec3(0.0f, 1.0f, 0.0f))
* glm::translate(glm::vec3(2.0f, 0.0f, 0.0f))
* glm::rotate(rotationAngle[1], glm::vec3(0.0f, -1.0f, 0.0f)) //enables rotation on own axis. try comment
* glm::rotate(glm::radians(45.0f), glm::vec3(1.0f, 0.0f, 0.0f)) //rotates into a diamond shape
* glm::rotate(glm::radians(45.0f), glm::vec3(0.0f, 0.0f, 1.0f)) //rotates into a diamond shape
* glm::scale(glm::vec3(g_scaleSize[1], g_scaleSize[1], g_scaleSize[1]));
g_modelMatrix[2] = glm::translate(glm::vec3(g_axisOfRotation[2], 0.0f, 0.0f))
* glm::rotate(orbitAngle[2], glm::vec3(0.0f, -1.0f, 0.0f))
* glm::translate(glm::vec3(4.0f, 0.0f, 0.0f))
* glm::rotate(rotationAngle[2], glm::vec3(0.0f, 1.0f, 0.0f))
* glm::scale(glm::vec3(g_scaleSize[2], g_scaleSize[2], g_scaleSize[2]));
g_modelMatrix[3] = glm::translate(glm::vec3(g_axisOfRotation[3], 0.0f, 0.0f))
* glm::rotate(orbitAngle[3], glm::vec3(0.0f, 1.0f, 0.0f))
* glm::translate(glm::vec3(6.0f, 0.0f, 0.0f))
* glm::rotate(rotationAngle[3], glm::vec3(0.0f, 1.0f, 0.0f))
* glm::scale(glm::vec3(g_scaleSize[3], g_scaleSize[3], g_scaleSize[3]));
g_modelMatrix[4] = glm::translate(glm::vec3(g_axisOfRotation[4], 0.0f, 0.0f))
* glm::rotate(orbitAngle[4], glm::vec3(0.0f, -1.0f, 0.0f)) // -y changes orbit to clock-wise
* glm::translate(glm::vec3(8.0f, 0.0f, 0.0f))
* glm::rotate(rotationAngle[4], glm::vec3(0.0f, -1.0f, 0.0f))
* glm::scale(glm::vec3(g_scaleSize[4], g_scaleSize[4], g_scaleSize[4]));
// update model matrix (orbit paths ie.circles)
g_modelMatrixCircle[1] = glm::translate(glm::vec3(g_axisOfRotation[1], 0.0f, 0.0f)) * glm::scale(glm::vec3(0.68f, 0.68f, 0.68f)) * glm::rotate(glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f));
g_modelMatrixCircle[2] = glm::translate(glm::vec3(g_axisOfRotation[2], 0.0f, 0.0f)) * glm::scale(glm::vec3(1.35f, 1.35f, 1.35f)) * glm::rotate(glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f));
g_modelMatrixCircle[3] = glm::translate(glm::vec3(g_axisOfRotation[3], 0.0f, 0.0f)) * glm::scale(glm::vec3(2.0f, 2.0f, 2.0f)) * glm::rotate(glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f));
g_modelMatrixCircle[4] = glm::translate(glm::vec3(g_axisOfRotation[4], 0.0f, 0.0f)) * glm::scale(glm::vec3(2.7f, 2.7f, 2.7f)) * glm::rotate(glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f));
// update model matrix (mini planets eg. moon)
g_modelMatrixSubPlanets[2] = glm::translate(glm::vec3(g_axisOfRotation[1], 0.0f, 0.0f))
* glm::scale(glm::vec3(0.35f, 0.35f, 0.35f))
* glm::rotate(glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f));
g_modelMatrixSubPlanets[3] = glm::translate(glm::vec3(g_axisOfRotation[3], 0.0f, 0.0f))
* glm::rotate(orbitAngle[3], glm::vec3(0.0f, 1.0f, 0.0f))
* glm::translate(glm::vec3(6.0f, 0.0f, 0.0f))
* glm::rotate(rotationAngle[3], glm::vec3(0.0f, 1.0f, 0.0f))
* glm::scale(glm::vec3(g_scaleSize[3], g_scaleSize[3], g_scaleSize[3]));
}
// 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
glm::mat4 MVP = glm::mat4(1.0f); //ModelViewProjection matrix to be shared. Initialized to identity
//Circle 1
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrixCircle[1];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glBindVertexArray(g_VAO[1]); // make VAO active
glDrawArrays(GL_LINE_LOOP, 0, g_slices + 2); // display the vertices based on the primitive type
//Circle 2
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrixCircle[2];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawArrays(GL_LINE_LOOP, 0, g_slices + 2); // display the vertices based on the primitive type
//Circle 3
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrixCircle[3];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawArrays(GL_LINE_LOOP, 0, g_slices + 2); // display the vertices based on the primitive type
//Circle 4
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrixCircle[4];;
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawArrays(GL_LINE_LOOP, 0, g_slices + 2); // display the vertices based on the primitive type
// Circle for Object 2
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix[2] * g_modelMatrixSubPlanets[2];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawArrays(GL_TRIANGLE_FAN, 0, g_slices + 2); // display the vertices based on the primitive type
glBindVertexArray(g_VAO[0]); // make VAO active
// Object 1
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix[0];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
// Object 2
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix[1];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
// Object 3
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix[2];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
// Object 4
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix[3];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glUniform1fv(g_alphaIndex,1, &g_alpha);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
// Object 5
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix[4];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
// Moon for Object 3
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrixSubPlanets[3] * g_modelMatrix[4];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
glFlush(); // flush the pipeline
}
static void cursor_position_callback(GLFWwindow* window, double xpos, double ypos)
{
// variables to store mouse cursor coordinates
static double previous_xpos = xpos;
static double previous_ypos = ypos;
double delta_x = xpos - previous_xpos;
double delta_y = ypos - previous_ypos;
// pass mouse movement to camera class
g_camera.updateYaw(delta_x);
g_camera.updatePitch(delta_y);
// update previous mouse coordinates
previous_xpos = xpos;
previous_ypos = ypos;
}
// key press or release callback function
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
// quit if the ESCAPE key was press
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
{
// set flag to close the window
glfwSetWindowShouldClose(window, GL_TRUE);
return;
}
// toggle animation
else if (key == GLFW_KEY_P && action == GLFW_PRESS) {
static int count = 1;
if (count % 2 == 0)
g_enableAnimation = true;
else
g_enableAnimation = false;
count++;
}
// render in perspective view
else if (key == GLFW_KEY_1 && action == GLFW_PRESS) {
cout << "Perspective-View" << endl << endl;
// set camera's view matrix
g_camera.setViewMatrix(glm::vec3(0, 3, 14), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
render_scene();
}
// render from top view
else if (key == GLFW_KEY_2 && action == GLFW_PRESS) {
cout << "Top-View" << endl << endl;
// set camera's view matrix
g_camera.setViewMatrix(glm::vec3(0, 15, 0), glm::vec3(0, 0, 0), glm::vec3(0, 0,-1));
render_scene();
}
// Randomize size, orbit speed, axis rotation speed of planets
else if (key == GLFW_KEY_R && action == GLFW_PRESS) {
// Randomize planet size
g_scaleSize[1] = generateRandomFloat(0.1, 0.75);
g_scaleSize[2] = generateRandomFloat(0.1, 0.75);
g_scaleSize[3] = generateRandomFloat(0.1, 0.75);
g_scaleSize[4] = generateRandomFloat(0.1, 0.75);
// Randomize speed of rotation (on planets own axis)
g_rotationSpeed[1] = generateRandomFloat(0.1, 2.0);
g_rotationSpeed[2] = generateRandomFloat(0.1, 2.0);
g_rotationSpeed[3] = generateRandomFloat(0.1, 2.0);
g_rotationSpeed[4] = generateRandomFloat(0.1, 2.0);
// Randomize speed of rotation around sun
g_orbitSpeed[1] = generateRandomFloat(0.1, 0.7);
g_orbitSpeed[2] = generateRandomFloat(0.1, 0.7);
g_orbitSpeed[3] = generateRandomFloat(0.1, 0.7);
g_orbitSpeed[4] = generateRandomFloat(0.1, 0.7);
// Randomize offset for axis of rotation
g_axisOfRotation[1] = generateRandomFloat(-0.5, 0.5);
g_axisOfRotation[2] = generateRandomFloat(-0.5, 0.5);
g_axisOfRotation[3] = generateRandomFloat(-0.5, 0.5);
g_axisOfRotation[4] = generateRandomFloat(-0.5, 0.5);
// Display info for each planet
cout << "PLANET 1 - \tSize: " << g_scaleSize[1] << "\tSpeed: " << g_rotationSpeed[1]
<< "\tOrbit Speed: " << g_orbitSpeed[1] << "\tAxis offset: " << g_axisOfRotation[1] << endl;
cout << "PLANET 2 - \tSize: " << g_scaleSize[2] << "\tSpeed: " << g_rotationSpeed[2]
<< "\tOrbit Speed: " << g_orbitSpeed[2] << "\tAxis offset: " << g_axisOfRotation[2] << endl;
cout << "PLANET 3 - \tSize: " << g_scaleSize[3] << "\tSpeed: " << g_rotationSpeed[3]
<< "\tOrbit Speed: " << g_orbitSpeed[3] << "\tAxis offset: " << g_axisOfRotation[3] << endl;
cout << "PLANET 4 - \tSize: " << g_scaleSize[4] << "\tSpeed: " << g_rotationSpeed[4]
<< "\tOrbit Speed: " << g_orbitSpeed[4] << "\tAxis offset: " << g_axisOfRotation[4] << endl;
cout << endl;
render_scene();
}
}
// error callback function
static void error_callback(int error, const char* description)
{
cerr << description << endl; // output error description
}
int main(void)
{
GLFWwindow* window = NULL; // pointer to a GLFW window handle
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(1000, 1000, "Assessment 1", 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);
// 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_DISABLED);
// initialise rendering states
init(window);
// variables for simple time management
float lastUpdateTime = glfwGetTime();
float currentTime = lastUpdateTime;
// the rendering loop
while (!glfwWindowShouldClose(window))
{
currentTime = glfwGetTime();
g_camera.update(window); // update camera
// only update if more than 0.02 seconds since last update
if (currentTime - lastUpdateTime > 0.02)
{
if (g_enableAnimation) { update_scene(); } // update the scene
render_scene(); // render the scene
glfwSwapBuffers(window); // swap buffers
glfwPollEvents(); // poll for events
lastUpdateTime = currentTime; // update last update time
}
}
// clean up
glDeleteProgram(g_shaderProgramID);
glDeleteBuffers(1, &g_IBO);
glDeleteBuffers(1, &g_VBO[0]);
glDeleteBuffers(1, &g_VBO[1]);
glDeleteVertexArrays(1, &g_VAO[0]);
glDeleteVertexArrays(1, &g_VAO[1]);
// close the window and terminate GLFW
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}
color.frag
#version 330 core
// interpolated values from the vertex shaders
in vec3 vColor;
// uniform input data
uniform vec3 uAlpha;
// output data
out vec4 fColor;
void main()
{
// set output color
fColor = vec4(uAlpha,1);
}
There are 3 issues. The 1st one is a copy/past issue. g_projectionMatrix has to be set before it is passed to Camera::setProjectionMatrix:
// initialise projection matrix
g_projectionMatrix = glm::perspective(glm::radians(45.0f), aspectRatio, 0.1f, 100.0f);
// set camera's projection matrix
g_camera.setProjectionMatrix(g_projectionMatrix);
The 2nd issue is a logical issue. The index buffer (ELEMENT_ARRAY_BUFFER) binding is stored within the Vertex Array Object. So the Vertex Array Object has to be bound before the index buffer:
// generate identifier for VBO and copy data to GPU
glGenBuffers(1, &g_VBO[0]);
glBindBuffer(GL_ARRAY_BUFFER, g_VBO[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertices), g_vertices, GL_STATIC_DRAW);
# Bind vertex array object before element array buffer!
// generate identifiers for VAO
glGenVertexArrays(1, &g_VAO[0]);
// create VAO and specify VBO data
glBindVertexArray(g_VAO[0]);
// generate identifier for IBO and copy data to GPU
glGenBuffers(1, &g_IBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(g_indices), g_indices, GL_STATIC_DRAW);
// interleaved attributes
glVertexAttribPointer(positionIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, position)));
glVertexAttribPointer(colorIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, color)));
glEnableVertexAttribArray(positionIndex); // enable vertex attributes
glEnableVertexAttribArray(colorIndex);
Note, in compare to the index buffer, the array buffer binding is a global state.
Each attribute which is stated in the VAOs state vector may refer to a different ARRAY_BUFFER. This reference is stored when glVertexAttribPointer is called. Then the buffer which is currently bound to the target ARRAY_BUFFER is associated to the attribute and the name (value) of the object is stored in the state vector of the VAO.
But the index buffer is a state of the VAO. When a buffer is bound to the target ELEMENT_ARRAY_BUFFER, then this buffer is associated to the vertex array object which is currently bound.
Furthermore, I suppose the type of uAlpha ahs to be float, because it is set by glUniform1fv. The final color is fColor = vec4(vColor, uAlpha);:
Fragment shader
#version 330 core
// interpolated values from the vertex shaders
in vec3 vColor;
// uniform input data
uniform float uAlpha;
// output data
out vec4 fColor;
void main()
{
// set output color
fColor = vec4(vColor, uAlpha);
}
I am trying to combine 2 programs
One is an empty room with a table and 2 chairs
The other draws a mesh of a Taurus
I have combined both and this was the result I got
Some of the surfaces of the table and chairs have disappeared. Can someone tell me why? I have already made an additional VBO and VAO to hold the vertice data of the meshes. However it seems to be affecting the surfaces of the cubes.
Here is my program
#define MAX_CUBES 6
#define MAX_PLANES 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;
// struct for vertex attributes
struct Vertex
{
GLfloat position[3];
GLfloat normal[3];
};
...
Vertex g_vertices_cube[] = {
// vertex 1
-0.5f, 0.5f, 0.5f, // position
1.0f, 1.0f, 1.0f, // normal
// vertex 2
-0.5f, -0.5f, 0.5f, // position
1.0f, 1.0f, 1.0f, // normal
// vertex 3
0.5f, 0.5f, 0.5f, // position
1.0f, 1.0f, 1.0f, // normal
// vertex 4
0.5f, -0.5f, 0.5f, // position
1.0f, 1.0f, 1.0f, // normal
// vertex 5
-0.5f, 0.5f, -0.5f, // position
1.0f, 1.0f, 1.0f, // normal
// vertex 6
-0.5f, -0.5f, -0.5f,// position
1.0f, 1.0f, 1.0f, // normal
// vertex 7
0.5f, 0.5f, -0.5f, // position
1.0f, 1.0f, 1.0f, // normal
// vertex 8
0.5f, -0.5f, -0.5f, // position
1.0f, 1.0f, 1.0f, // normal
};
GLuint g_indices_cube[] = {
0, 1, 2, // triangle 1
2, 1, 3, // triangle 2
4, 5, 0, // triangle 3
0, 5, 1, // ...
2, 3, 6,
6, 3, 7,
4, 0, 6,
6, 0, 2,
1, 5, 3,
3, 5, 7,
5, 4, 7,
7, 4, 6, // triangle 12
};
// Meshes
Vertex* g_pMeshVertices = NULL; // pointer to mesh vertices
GLint g_numberOfVertices = 0; // number of vertices in the mesh
GLint* g_pMeshIndices = NULL; // pointer to mesh indices
GLint g_numberOfFaces = 0; // number of faces in the mesh
/*
g_VBO[0] - Planes ie. walls, ceiling
g_VBO[1] - Cubes ie. table, stools
g_VBO[2] - Meshes (Taurus)
*/
GLuint g_IBO[2]; // index buffer object identifier
GLuint g_VBO[3]; // vertex buffer object identifier
GLuint g_VAO[3]; // 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 = 0;
GLuint g_materialDiffuseIndex = 0;
GLuint g_materialSpecularIndex = 0;
glm::mat4 g_modelMatrix_plane[MAX_PLANES]; // object's model matrix (4 walls + 1 ceiling + 1 floor)
glm::mat4 g_modelMatrix_cube[MAX_CUBES];// cube for table
glm::mat4 g_modelMatrix_mesh; // for meshes
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 = 1600; // window dimensions
GLuint g_windowHeight = 1000;
bool g_wireFrame = false; // wireframe on or off
bool load_mesh(const char* fileName)
{
// load file with assimp
const aiScene* pScene = aiImportFile(fileName, aiProcess_Triangulate
| aiProcess_GenSmoothNormals | aiProcess_JoinIdenticalVertices);
// check whether scene was loaded
if (!pScene)
{
cout << "Could not load mesh." << endl;
return false;
}
// get pointer to mesh 0
const aiMesh* pMesh = pScene->mMeshes[0];
// store number of mesh vertices
g_numberOfVertices = pMesh->mNumVertices;
// if mesh contains vertex coordinates
if (pMesh->HasPositions())
{
// allocate memory for vertices
g_pMeshVertices = new Vertex[pMesh->mNumVertices];
// read vertex coordinates and store in the array
for (int i = 0; i < pMesh->mNumVertices; i++)
{
const aiVector3D* pVertexPos = &(pMesh->mVertices[i]);
g_pMeshVertices[i].position[0] = (GLfloat)pVertexPos->x;
g_pMeshVertices[i].position[1] = (GLfloat)pVertexPos->y;
g_pMeshVertices[i].position[2] = (GLfloat)pVertexPos->z;
}
}
// if mesh contains normals
if (pMesh->HasNormals())
{
// read normals and store in the array
for (int i = 0; i < pMesh->mNumVertices; i++)
{
const aiVector3D* pVertexNormal = &(pMesh->mNormals[i]);
g_pMeshVertices[i].normal[0] = (GLfloat)pVertexNormal->x;
g_pMeshVertices[i].normal[1] = (GLfloat)pVertexNormal->y;
g_pMeshVertices[i].normal[2] = (GLfloat)pVertexNormal->z;
}
}
// if mesh contains faces
if (pMesh->HasFaces())
{
// store number of mesh faces
g_numberOfFaces = pMesh->mNumFaces;
// allocate memory for vertices
g_pMeshIndices = new GLint[pMesh->mNumFaces * 3];
// read normals and store in the array
for (int i = 0; i < pMesh->mNumFaces; i++)
{
const aiFace* pFace = &(pMesh->mFaces[i]);
g_pMeshIndices[i * 3] = (GLint)pFace->mIndices[0];
g_pMeshIndices[i * 3 + 1] = (GLint)pFace->mIndices[1];
g_pMeshIndices[i * 3 + 2] = (GLint)pFace->mIndices[2];
}
}
// release the scene
aiReleaseImport(pScene);
return true;
}
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");
g_lightPositionIndex = glGetUniformLocation(g_shaderProgramID, "uLightingProperties.position");
g_lightAmbientIndex = glGetUniformLocation(g_shaderProgramID, "uLightingProperties.ambient");
g_lightDiffuseIndex = glGetUniformLocation(g_shaderProgramID, "uLightingProperties.diffuse");
g_lightSpecularIndex = glGetUniformLocation(g_shaderProgramID, "uLightingProperties.specular");
g_lightShininessIndex = glGetUniformLocation(g_shaderProgramID, "uLightingProperties.shininess");
g_lightAttenuationIndex = glGetUniformLocation(g_shaderProgramID, "uLightingProperties.attenuation");
g_lightCutoffAngleIndex = glGetUniformLocation(g_shaderProgramID, "uLightingProperties.cutoffAngle");
g_lightDirectionIndex = glGetUniformLocation(g_shaderProgramID, "uLightingProperties.direction");
g_materialAmbientIndex = glGetUniformLocation(g_shaderProgramID, "uMaterialProperties.ambient");
g_materialDiffuseIndex = glGetUniformLocation(g_shaderProgramID, "uMaterialProperties.diffuse");
g_materialSpecularIndex = glGetUniformLocation(g_shaderProgramID, "uMaterialProperties.specular");
// initialise model matrix to the identity matrix
for (int i = 0; i < MAX_PLANES; i++) { g_modelMatrix_plane[i] = glm::mat4(1.0f); }
for (int i = 0; i < MAX_CUBES; i++) { g_modelMatrix_cube[i] = glm::mat4(1.0f); }
g_modelMatrix_mesh = glm::mat4(1.0f);
...
// Model Matrices - Cubes
// Table-top
g_modelMatrix_cube[0] = glm::scale(glm::vec3(1.4f, 0.2f, 1.4f));
// Table Leg 1
g_modelMatrix_cube[1] = glm::translate(glm::vec3(-0.5f, -0.55f, 0.5f))
* glm::scale(glm::vec3(0.2f, 1.2f, 0.2f));
// Table Leg 2
g_modelMatrix_cube[2] = glm::translate(glm::vec3(0.5f, -0.55f, 0.5f))
* glm::scale(glm::vec3(0.2f, 1.2f, 0.2f));
// Table Leg 3
g_modelMatrix_cube[3] = glm::translate(glm::vec3(-0.5f, -0.55f, -0.5f))
* glm::scale(glm::vec3(0.2f, 1.2f, 0.2f));
// Table Leg 4
g_modelMatrix_cube[4] = glm::translate(glm::vec3(0.5f, -0.55f, -0.5f))
* glm::scale(glm::vec3(0.2f, 1.2f, 0.2f));
// Chair back-rest (note: chair is a table but scaled down. And add a backrest)
g_modelMatrix_cube[5] = glm::translate(glm::vec3(0.5f, 0.5f, 0.0f))
* glm::scale(glm::vec3(0.2f, 1.2f, 1.35f));
// Model Matrices - Mesh
g_modelMatrix_mesh = glm::scale(glm::vec3(0.3f, 0.3f, 0.3f));
// set camera's view matrix
g_camera.setViewMatrix(glm::vec3(0, 0, 3), glm::vec3(0, 0, 2), glm::vec3(0, 1, 0));
int width, height;
glfwGetFramebufferSize(window, &width, &height);
float aspectRatio = static_cast<float>(width) / height;
// set camera's projection matrix
g_camera.setProjectionMatrix(glm::perspective(45.0f, aspectRatio, 0.1f, 100.0f));
// load mesh
load_mesh("models/WusonOBJ.obj");
//load_mesh("models/suzanne.obj");
// initialise light and material properties
g_lightProperties.position = glm::vec4(0.0f, 2.0f, 0.0f, 1.0f);
g_lightProperties.ambient = glm::vec4(0.2f, 0.2f, 0.2f, 1.0f);
g_lightProperties.diffuse = glm::vec4(0.0f, 0.5f, 1.0f, 1.0f);
g_lightProperties.specular = glm::vec4(0.0f, 0.5f, 1.0f, 1.0f);
g_lightProperties.shininess = 10.0f;
g_lightProperties.attenuation = glm::vec3(1.0f, 0.0f, 0.0f);
//g_lightProperties.cutoffAngle = 45.0f;
g_lightProperties.cutoffAngle = 180.0f;
g_lightProperties.direction = glm::vec3(0.0f, -1.0f, 0.0f);
// Material Properties - Planes
// Floor
g_materialProperties.ambient = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f);
g_materialProperties.diffuse = glm::vec4(0.2f, 0.7f, 1.0f, 1.0f);
g_materialProperties.specular = glm::vec4(0.2f, 0.7f, 1.0f, 1.0f);
...
// Cube
// generate identifier for VBOs and copy data to GPU
glGenBuffers(1, &g_VBO[1]);
glBindBuffer(GL_ARRAY_BUFFER, g_VBO[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertices_cube), g_vertices_cube, GL_STATIC_DRAW);
// generate identifier for IBO and copy data to GPU
glGenBuffers(1, &g_IBO[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_IBO[0]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(g_indices_cube), g_indices_cube, GL_STATIC_DRAW);
// generate identifiers for VAO
glGenVertexArrays(1, &g_VAO[1]);
// create VAO and specify VBO data
glBindVertexArray(g_VAO[1]);
glBindBuffer(GL_ARRAY_BUFFER, g_VBO[1]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_IBO[0]);
glVertexAttribPointer(positionIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, position)));
glVertexAttribPointer(normalIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, normal)));
glEnableVertexAttribArray(positionIndex); // enable vertex attributes
glEnableVertexAttribArray(normalIndex);
// Meshes
// generate identifier for VBOs and copy data to GPU
glGenBuffers(1, &g_VBO[2]);
glBindBuffer(GL_ARRAY_BUFFER, g_VBO[2]);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex)*g_numberOfVertices, g_pMeshVertices, GL_STATIC_DRAW);
// generate identifier for IBO and copy data to GPU
glGenBuffers(1, &g_IBO[1]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_IBO[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLint) * 3 * g_numberOfFaces, g_pMeshIndices, GL_STATIC_DRAW);
// generate identifiers for VAO
glGenVertexArrays(1, &g_VAO[2]);
// create VAO and specify VBO data
glBindVertexArray(g_VAO[2]);
glBindBuffer(GL_ARRAY_BUFFER, g_VBO[2]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_IBO[1]);
glVertexAttribPointer(positionIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, position)));
glVertexAttribPointer(normalIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, 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[0]); // make VAO active
// Material Properties - Planes
glUniform4fv(g_materialAmbientIndex, 1, &g_materialProperties.ambient[0]);
glUniform4fv(g_materialDiffuseIndex, 1, &g_materialProperties.diffuse[0]);
glUniform4fv(g_materialSpecularIndex, 1, &g_materialProperties.specular[0]);
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]);
// set uniform shader variables
glm::mat4 MVP = glm::mat4(1.0f);
// Draw Planes
for (int i = 0; i < MAX_PLANES; i++)
{
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix_plane[i];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glUniformMatrix4fv(g_M_Index, 1, GL_FALSE, &g_modelMatrix_plane[i][0][0]);
glUniform3fv(g_viewPointIndex, 1, &g_viewPoint[0]);
glDrawArrays(GL_TRIANGLES, 0, 6);
}
glBindVertexArray(g_VAO[1]); // make VAO active
// Draw Cubes
// Table top + 4 Table legs
for (int i = 0; i < (MAX_CUBES - 1); i++)
{
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix_cube[i];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glUniformMatrix4fv(g_M_Index, 1, GL_FALSE, &g_modelMatrix_cube[i][0][0]);
glUniform3fv(g_viewPointIndex, 1, &g_viewPoint[0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
}
// Chair (Right)
for (int i = 0; i < MAX_CUBES; i++)
{
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix()
* glm::translate(glm::vec3(1.5f, -0.2f, 0.0f)) * glm::scale(glm::vec3(0.7f, 0.7f, 0.7f)) * g_modelMatrix_cube[i];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glUniformMatrix4fv(g_M_Index, 1, GL_FALSE, &g_modelMatrix_cube[i][0][0]);
glUniform3fv(g_viewPointIndex, 1, &g_viewPoint[0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
}
// Chair (Left)
for (int i = 0; i < MAX_CUBES; i++)
{
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix()
* glm::rotate(glm::radians(180.0f), glm::vec3(0.0f, 1.0f, 0.0f))
* glm::translate(glm::vec3(1.5f, -0.2f, 0.0f)) * glm::scale(glm::vec3(0.7f, 0.7f, 0.7f)) * g_modelMatrix_cube[i];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glUniformMatrix4fv(g_M_Index, 1, GL_FALSE, &g_modelMatrix_cube[i][0][0]);
glUniform3fv(g_viewPointIndex, 1, &g_viewPoint[0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
}
glBindVertexArray(g_VAO[2]); // make VAO active
// Draw Meshes
// Taurus
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix_mesh;
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glUniformMatrix4fv(g_M_Index, 1, GL_FALSE, &g_modelMatrix_mesh[0][0]);
glUniform3fv(g_viewPointIndex, 1, &g_viewPoint[0]);
glDrawElements(GL_TRIANGLES, g_numberOfFaces * 3, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
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
if (g_pMeshVertices)
delete[] g_pMeshVertices;
if (g_pMeshIndices)
delete[] g_pMeshIndices;
glDeleteProgram(g_shaderProgramID);
glDeleteBuffers(1, &g_VBO[0]);
glDeleteVertexArrays(1, &g_VAO[0]);
// uninitialise tweak bar
TwTerminate();
// close the window and terminate GLFW
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}
Fragment shader
#version 330 core
// 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;
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)
{
// calculate Phong lighting
vec4 ambient = uLightingProperties.ambient * uMaterialProperties.ambient;
vec4 diffuse = uLightingProperties.diffuse * uMaterialProperties.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.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;
}
You are overriding the index buffer of g_VAO[1]. Since you don't unbind the VAO after it its initialization has finished, glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_IBO[1]); will modify it.
To solve your problem: Unbind VAOs before binding any buffers that are not related to them.
I am trying to integrate 2 programs together.
One displays a 2D hollow red circle
Another is a 3D "planet system". (There are cubes moving/orbiting around a "sun")
I want to get the red circle to display in the "planet system". It is not supposed to move. I have tried integrating the code, but the circle does not appear as I want it to.
I noticed that when I uncomment these sections of code (below), the circle appears, but it moves around just like a planet.
static void init(GLFWwindow* window){
/*------------------------Circle----------------------*/
//// generate vertices of triangle fan
//generate_circle();
//// create VBO and buffer the data
//glGenBuffers(1, &g_VBO[1]);
//glBindBuffer(GL_ARRAY_BUFFER, g_VBO[1]);
//glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * (g_slices + 2), g_vertices_circle, GL_STATIC_DRAW);
//glGenBuffers(1, &g_VBO[2]);
//glBindBuffer(GL_ARRAY_BUFFER, g_VBO[2]);
//glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * (g_slices + 2), g_colors_circle, GL_STATIC_DRAW);
//// create VAO and specify VBO data
//glGenVertexArrays(1, &g_VAO[1]);
//glBindVertexArray(g_VAO[1]);
//glBindBuffer(GL_ARRAY_BUFFER, g_VBO[1]);
//glVertexAttribPointer(positionIndex, 3, GL_FLOAT, GL_FALSE, 0, 0); // specify the form of the data
//glBindBuffer(GL_ARRAY_BUFFER, g_VBO[2]);
//glVertexAttribPointer(colorIndex, 3, GL_FLOAT, GL_FALSE, 0, 0); // specify the form of the data
/*----------------------------------------------------*/
}
static void render_scene(){
// glBindVertexArray(g_VAO[1]); // make VAO active
//
////Circle 1
// glDrawArrays(GL_LINE_LOOP, 0, g_slices + 2); // display the vertices based on the primitive type
//
// glBindVertexArray(g_VAO[0]); // make VAO active
}
And also, my planet system disappears. I'm pretty sure this has something to do with my vertices being multiplied by the matrix in the vertex shader. How can I place the circle without it moving and making my "planets" disappear?
Here is my vertex shader
#version 330 core
// input data (different for all executions of this shader)
in vec3 aPosition;
in vec3 aColor;
// ModelViewProjection matrix
uniform mat4 uModelViewProjectionMatrix;
// output data (will be interpolated for each fragment)
out vec3 vColor;
void main()
{
// set vertex position
gl_Position = uModelViewProjectionMatrix * vec4(aPosition, 1.0);
// the color of each vertex will be interpolated
// to produce the color of each fragment
vColor = aColor;
}
Here is my main program:
#include <cstdio> // for C++ i/o
#include <iostream>
#include <string>
#include <cstddef>
using namespace std; // to avoid having to use std::
#define GLEW_STATIC // include GLEW as a static library
#include <GLEW/glew.h> // include GLEW
#include <GLFW/glfw3.h> // include GLFW (which includes the OpenGL header)
#include <glm/glm.hpp> // include GLM (ideally should only use the GLM headers that are actually used)
#include <glm/gtx/transform.hpp>
using namespace glm; // to avoid having to use glm::
#include "shader.h"
#define PI 3.14159265
#define MAX_SLICES 50
#define MIN_SLICES 8
#define MAX_VERTICES (MAX_SLICES+2)*3 // a triangle fan should have a minimum of 3 vertices
#define CIRCLE_RADIUS 1.0
#define WINDOW_WIDTH 1500
#define WINDOW_HEIGHT 800
// struct for vertex attributes
struct Vertex
{
GLfloat position[3];
GLfloat color[3];
};
// global variables
GLfloat g_vertices_circle[MAX_VERTICES] = {
0.0f, 0.0f, 0.0f, // try adjusting this value to get rid of red line
0.0f, 0.0f, 0.0f
};
GLfloat g_colors_circle[MAX_VERTICES] = {
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f
};
GLuint g_slices = MAX_SLICES; // number of circle slices
Vertex g_vertices[] = {
// vertex 1
-0.5f, 0.5f, 0.5f, // position
1.0f, 0.0f, 1.0f, // colour
// vertex 2
-0.5f, -0.5f, 0.5f, // position
1.0f, 0.0f, 0.0f, // colour
// vertex 3
0.5f, 0.5f, 0.5f, // position
1.0f, 1.0f, 1.0f, // colour
// vertex 4
0.5f, -0.5f, 0.5f, // position
1.0f, 1.0f, 0.0f, // colour
// vertex 5
-0.5f, 0.5f, -0.5f, // position
0.0f, 0.0f, 1.0f, // colour
// vertex 6
-0.5f, -0.5f, -0.5f,// position
0.0f, 0.0f, 0.0f, // colour
// vertex 7
0.5f, 0.5f, -0.5f, // position
0.0f, 1.0f, 1.0f, // colour
// vertex 8
0.5f, -0.5f, -0.5f, // position
0.0f, 1.0f, 0.0f, // colour
};
GLuint g_indices[] = {
0, 1, 2, // triangle 1
2, 1, 3, // triangle 2
4, 5, 0, // triangle 3
0, 5, 1, // ...
2, 3, 6,
6, 3, 7,
4, 0, 6,
6, 0, 2,
1, 5, 3,
3, 5, 7,
5, 4, 7,
7, 4, 6, // triangle 12
};
GLuint g_IBO = 0; // index buffer object identifier
GLuint g_VBO[3]; // vertex buffer object identifier
GLuint g_VAO[2]; // vertex array object identifier
GLuint g_shaderProgramID = 0; // shader program identifier
GLuint g_MVP_Index = 0; // location in shader
glm::mat4 g_modelMatrix[5]; // object model matrices
glm::mat4 g_viewMatrix; // view matrix
glm::mat4 g_projectionMatrix; // projection matrix
float g_orbitSpeed[5] = { 0.3f, 1.0f, 0.7f, 0.9f, 1.2f }; // for speed of rotation around sun
float g_rotationSpeed[5] = { 0.07f, 0.7f, 3.0f, 5.0f, 1.0f }; // for speed of rotation on own axis
float g_scaleSize[5] = { 0.5f, 0.5f, 0.5f, 0.5f, 0.5f }; // for scaling the orbiting planets
float g_axisOfRotation[5] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, }; // for offsetting the axis of rotation
void generate_circle()
{
float angle = PI * 2 / static_cast<float>(g_slices); // used to generate x and y coordinates
float scale_factor = static_cast<float>(WINDOW_HEIGHT) / WINDOW_WIDTH; // scale to make it a circle instead of an elipse
int index = 0; // vertex index
g_vertices_circle[3] = CIRCLE_RADIUS * scale_factor; // set x coordinate of vertex 1
// generate vertex coordinates for triangle fan
for (int i = 2; i < g_slices + 2; i++)
{
// multiply by 3 because a vertex has x, y, z coordinates
index = i * 3;
g_vertices_circle[index] = CIRCLE_RADIUS * cos(angle) * scale_factor;
g_vertices_circle[index + 1] = CIRCLE_RADIUS * sin(angle);
g_vertices_circle[index + 2] = 0.0f;
//Color for edges. See stackoverflow
g_colors_circle[index] = 1.0f;
g_colors_circle[index + 1] = 0.0f;
g_colors_circle[index + 2] = 0.0f;
// update to next angle
angle += PI * 2 / static_cast<float>(g_slices);
}
// Gets rid of line from middle of circle
g_vertices_circle[0] = g_vertices_circle[3];
g_vertices_circle[1] = g_vertices_circle[4];
g_vertices_circle[2] = g_vertices_circle[5];
}
static void init(GLFWwindow* window)
{
glClearColor(0.0, 0.0, 0.0, 1.0); // set clear background colour
glEnable(GL_DEPTH_TEST); // enable depth buffer test
// create and compile our GLSL program from the shader files
g_shaderProgramID = loadShaders("MVP_VS.vert", "ColorFS.frag");
// enable point size
glEnable(GL_PROGRAM_POINT_SIZE);
// set line width
glLineWidth(5.0);
// find the location of shader variables
GLuint positionIndex = glGetAttribLocation(g_shaderProgramID, "aPosition");
GLuint colorIndex = glGetAttribLocation(g_shaderProgramID, "aColor");
g_MVP_Index = glGetUniformLocation(g_shaderProgramID, "uModelViewProjectionMatrix");
// initialise model matrix to the identity matrix
g_modelMatrix[0] = g_modelMatrix[1] = g_modelMatrix[2] = g_modelMatrix[3] = g_modelMatrix[4] = glm::mat4(1.0f);
// initialise view matrix
g_viewMatrix = glm::lookAt(glm::vec3(10, 3, 8), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0)); //perspective
int width, height;
glfwGetFramebufferSize(window, &width, &height);
float aspectRatio = static_cast<float>(width) / height;
// initialise projection matrix
g_projectionMatrix = glm::perspective(45.0f, aspectRatio, 0.1f, 100.0f);
// generate identifier for VBO and copy data to GPU
glGenBuffers(1, &g_VBO[0]);
glBindBuffer(GL_ARRAY_BUFFER, g_VBO[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertices), g_vertices, GL_STATIC_DRAW);
// generate identifier for IBO and copy data to GPU
glGenBuffers(1, &g_IBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(g_indices), g_indices, GL_STATIC_DRAW);
// generate identifiers for VAO
glGenVertexArrays(1, &g_VAO[0]);
// create VAO and specify VBO data
glBindVertexArray(g_VAO[0]);
glBindBuffer(GL_ARRAY_BUFFER, g_VBO[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_IBO);
// interleaved attributes
glVertexAttribPointer(positionIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, position)));
glVertexAttribPointer(colorIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, color)));
/*------------------------Circle----------------------*/
//// generate vertices of triangle fan
//generate_circle();
//// create VBO and buffer the data
//glGenBuffers(1, &g_VBO[1]);
//glBindBuffer(GL_ARRAY_BUFFER, g_VBO[1]);
//glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * (g_slices + 2), g_vertices_circle, GL_STATIC_DRAW);
//glGenBuffers(1, &g_VBO[2]);
//glBindBuffer(GL_ARRAY_BUFFER, g_VBO[2]);
//glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * (g_slices + 2), g_colors_circle, GL_STATIC_DRAW);
//// create VAO and specify VBO data
//glGenVertexArrays(1, &g_VAO[1]);
//glBindVertexArray(g_VAO[1]);
//glBindBuffer(GL_ARRAY_BUFFER, g_VBO[1]);
//glVertexAttribPointer(positionIndex, 3, GL_FLOAT, GL_FALSE, 0, 0); // specify the form of the data
//glBindBuffer(GL_ARRAY_BUFFER, g_VBO[2]);
//glVertexAttribPointer(colorIndex, 3, GL_FLOAT, GL_FALSE, 0, 0); // specify the form of the data
/*----------------------------------------------------*/
glEnableVertexAttribArray(positionIndex); // enable vertex attributes
glEnableVertexAttribArray(colorIndex);
}
//Generates a random value between 0.1 and 0.9
double generateRandomFloat(float min, float max)
{
return min + static_cast <float> (rand()) / (static_cast <float> (RAND_MAX / (max - min)));
}
// function used to update the scene
static void update_scene()
{
// static variables for rotation angles
static float orbitAngle[5] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, };
static float rotationAngle[5] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
float scaleFactor = 0.05;
orbitAngle[0] += g_orbitSpeed[0] * scaleFactor;
orbitAngle[1] += g_orbitSpeed[1] * scaleFactor;
orbitAngle[2] += g_orbitSpeed[2] * scaleFactor;
orbitAngle[3] += g_orbitSpeed[3] * scaleFactor;
orbitAngle[4] += g_orbitSpeed[4] * scaleFactor;
// update rotation angles
rotationAngle[0] += g_rotationSpeed[0] * scaleFactor;
rotationAngle[1] += g_rotationSpeed[1] * scaleFactor;
rotationAngle[2] += g_rotationSpeed[2] * scaleFactor;
rotationAngle[3] += g_rotationSpeed[3] * scaleFactor;
rotationAngle[4] += g_rotationSpeed[4] * scaleFactor;
// update model matrix
g_modelMatrix[0] = glm::rotate(rotationAngle[0], glm::vec3(0.0f, 1.0f, 0.0f));
g_modelMatrix[1] = glm::translate(glm::vec3(g_axisOfRotation[1], 0.0f, 0.0f)) //moves the axis of rotation along x-axis
* glm::rotate(orbitAngle[1], glm::vec3(0.0f, 1.0f, 0.0f))
* glm::translate(glm::vec3(2.0f, 0.0f, 0.0f))
* glm::rotate(rotationAngle[1], glm::vec3(0.0f, -1.0f, 0.0f)) //enables rotation on own axis. try comment
* glm::rotate(glm::radians(45.0f), glm::vec3(1.0f, 0.0f, 0.0f)) //rotates into a diamond shape
* glm::rotate(glm::radians(45.0f), glm::vec3(0.0f, 0.0f, 1.0f)) //rotates into a diamond shape
* glm::scale(glm::vec3(g_scaleSize[1], g_scaleSize[1], g_scaleSize[1]));
g_modelMatrix[2] = glm::translate(glm::vec3(g_axisOfRotation[2], 0.0f, 0.0f))
* glm::rotate(orbitAngle[2], glm::vec3(0.0f, -1.0f, 0.0f))
* glm::translate(glm::vec3(4.0f, 0.0f, 0.0f))
* glm::rotate(rotationAngle[2], glm::vec3(0.0f, 1.0f, 0.0f))
* glm::scale(glm::vec3(g_scaleSize[2], g_scaleSize[2], g_scaleSize[2]));
g_modelMatrix[3] = glm::translate(glm::vec3(g_axisOfRotation[3], 0.0f, 0.0f))
* glm::rotate(orbitAngle[3], glm::vec3(0.0f, 1.0f, 0.0f))
* glm::translate(glm::vec3(6.0f, 0.0f, 0.0f))
* glm::rotate(rotationAngle[3], glm::vec3(0.0f, 1.0f, 0.0f))
* glm::scale(glm::vec3(g_scaleSize[3], g_scaleSize[3], g_scaleSize[3]));
g_modelMatrix[4] = glm::translate(glm::vec3(g_axisOfRotation[4], 0.0f, 0.0f))
* glm::rotate(orbitAngle[4], glm::vec3(0.0f, -1.0f, 0.0f)) // -y changes orbit to clock-wise
* glm::translate(glm::vec3(8.0f, 0.0f, 0.0f))
* glm::rotate(rotationAngle[4], glm::vec3(0.0f, -1.0f, 0.0f))
* glm::scale(glm::vec3(g_scaleSize[4], g_scaleSize[4], g_scaleSize[4]));
}
// 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[1]); // make VAO active
//
////Circle 1
// glDrawArrays(GL_LINE_LOOP, 0, g_slices + 2); // display the vertices based on the primitive type
//
// glBindVertexArray(g_VAO[0]); // make VAO active
// Object 1
glm::mat4 MVP = g_projectionMatrix * g_viewMatrix * g_modelMatrix[0];
// set uniform model transformation matrix
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
// Object 2
MVP = g_projectionMatrix * g_viewMatrix * g_modelMatrix[1];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
// Object 3
MVP = g_projectionMatrix * g_viewMatrix * g_modelMatrix[2];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
// Object 4
MVP = g_projectionMatrix * g_viewMatrix * g_modelMatrix[3];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
// Object 5
MVP = g_projectionMatrix * g_viewMatrix * g_modelMatrix[4];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
glFlush(); // flush the pipeline
}
int main(void)
{
GLFWwindow* window = NULL; // pointer to a GLFW window handle
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(1500, 1000, "Assignment 2", 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);
// initialise rendering states
init(window);
// variables for simple time management
float lastUpdateTime = glfwGetTime();
float currentTime = lastUpdateTime;
// the rendering loop
while (!glfwWindowShouldClose(window))
{
currentTime = glfwGetTime();
// only update if more than 0.02 seconds since last update
if (currentTime - lastUpdateTime > 0.02)
{
update_scene(); // update the scene
render_scene(); // render the scene
glfwSwapBuffers(window); // swap buffers
glfwPollEvents(); // poll for events
lastUpdateTime = currentTime; // update last update time
}
}
// clean up
glDeleteProgram(g_shaderProgramID);
glDeleteBuffers(1, &g_IBO);
glDeleteBuffers(1, &g_VBO[0]);
glDeleteBuffers(1, &g_VBO[1]);
glDeleteVertexArrays(1, &g_VAO[0]);
glDeleteVertexArrays(1, &g_VAO[1]);
// close the window and terminate GLFW
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}
You have to set the uniform variable uModelViewProjectionMatrix before you draw the circle.
For all other objects you set a proper model view projection matrix, but you don't do so for the circle.
Since the circle does not move and has no other location data you only need the projection matrix and the view matrix.
In this case the model matrix is the identity matrix, so you can skip it.
glm::mat4 MVP = g_projectionMatrix * g_viewMatrix;
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glBindVertexArray(g_VAO[1]);
glDrawArrays(GL_LINE_LOOP, 0, g_slices + 2);
If you want to place the circle to another position in the scene you have to set up a model matrix for the circle and you have to concatenate the model matrix of the circle with the view matrix and the projection matrix.
glm::vec3 circlePos = ....;
glm::mat4 circleModelMat = glm::translate(glm::mat4(1.0f), circlePos);
glm::mat4 MVP = g_projectionMatrix * g_viewMatrix * circleModelMat;
Extension to the answer:
However, my cubes are still missing. All I can see is a static circle.
Do you know how I can get the cubes to appear as well?
You have to enable the vertex attributes vor both vertex array objects:
glBindVertexArray(g_VAO[0]);
// ... bind buffer and set vetex attribute pointer
glEnableVertexAttribArray(positionIndex); // enable vertex attributes
glEnableVertexAttribArray(colorIndex);
/*------------------------Circle----------------------*/
// ...
glBindVertexArray(g_VAO[1]);
// ... bind buffer and set vetex attribute pointer
glEnableVertexAttribArray(positionIndex); // enable vertex attributes
glEnableVertexAttribArray(colorIndex);
My program is a moving "planet system".
I want to get the furthest planet (cube) to "fade" alternately from transparent to fully opaque.
I understand that this has to do with adjusting the alpha values of vertices. However, I am unfamiliar with blending and transparency.
I was given some code that could alter the alpha values of an object. I have integrated it into my program but now my program keeps crashing. Can someone tell me why it is crashing and how I can change my code to get the planet to fade in and out?
Here is the code I added to my program
GLuint g_alphaIndex; // for transparency of 4th planet
float g_alpha = 0.5f; // transparency of 4th planet
static void init(GLFWwindow* window)
{
....
glEnable(GL_BLEND);
glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
.....
.....
g_alphaIndex = glGetUniformLocation(g_shaderProgramID, "uAlpha");
....
}
static void render_scene()
{
......
// Object 4
glUniform1fv(g_alphaIndex, 2, &g_alpha);
......
}
/*
In Fragment shader
*/
uniform float uAlpha;
void main()
{
// set output color
fColor = vec4(vColor, uAlpha);
}
Here is my full program
#include <cstdio> // for C++ i/o
#include <iostream>
#include <string>
#include <cstddef>
using namespace std; // to avoid having to use std::
#define GLEW_STATIC // include GLEW as a static library
#include <GLEW/glew.h> // include GLEW
#include <GLFW/glfw3.h> // include GLFW (which includes the OpenGL header)
#include <glm/glm.hpp> // include GLM (ideally should only use the GLM headers that are actually used)
#include <glm/gtx/transform.hpp>
using namespace glm; // to avoid having to use glm::
#include "shader.h"
#include "camera.h"
#define PI 3.14159265
#define MAX_SLICES 50
#define MIN_SLICES 8
#define MAX_VERTICES (MAX_SLICES+2)*3 // a triangle fan should have a minimum of 3 vertices
#define CIRCLE_RADIUS 3.0
#define WINDOW_WIDTH 1000
#define WINDOW_HEIGHT 1000
// struct for vertex attributes
struct Vertex
{
GLfloat position[3];
GLfloat color[3];
};
// global variables
GLfloat g_vertices_circle[MAX_VERTICES] = {
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f
};
GLfloat g_colors_circle[MAX_VERTICES] = {
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f
};
GLuint g_slices = MAX_SLICES; // number of circle slices
Vertex g_vertices[] = {
// vertex 1
-0.5f, 0.5f, 0.5f, // position
1.0f, 0.0f, 1.0f, // colour
// vertex 2
-0.5f, -0.5f, 0.5f, // position
1.0f, 0.0f, 0.0f, // colour
// vertex 3
0.5f, 0.5f, 0.5f, // position
1.0f, 1.0f, 1.0f, // colour
// vertex 4
0.5f, -0.5f, 0.5f, // position
1.0f, 1.0f, 0.0f, // colour
// vertex 5
-0.5f, 0.5f, -0.5f, // position
0.0f, 0.0f, 1.0f, // colour
// vertex 6
-0.5f, -0.5f, -0.5f,// position
0.0f, 0.0f, 0.0f, // colour
// vertex 7
0.5f, 0.5f, -0.5f, // position
0.0f, 1.0f, 1.0f, // colour
// vertex 8
0.5f, -0.5f, -0.5f, // position
0.0f, 1.0f, 0.0f, // colour
};
GLuint g_indices[] = {
0, 1, 2, // triangle 1
2, 1, 3, // triangle 2
4, 5, 0, // triangle 3
0, 5, 1, // ...
2, 3, 6,
6, 3, 7,
4, 0, 6,
6, 0, 2,
1, 5, 3,
3, 5, 7,
5, 4, 7,
7, 4, 6, // triangle 12
};
GLuint g_IBO = 0; // index buffer object identifier
GLuint g_VBO[3]; // vertex buffer object identifier
GLuint g_VAO[2]; // vertex array object identifier
GLuint g_shaderProgramID = 0; // shader program identifier
GLuint g_MVP_Index = 0; // location in shader
GLuint g_alphaIndex; // for transparency of 4th planet
glm::mat4 g_modelMatrix[5]; // planets object model matrices
glm::mat4 g_modelMatrixCircle[5];// circle model matrices
glm::mat4 g_modelMatrixSubPlanets[5];// object matrices for sub-planets (moon, disc etc)
glm::mat4 g_viewMatrix; // view matrix
glm::mat4 g_projectionMatrix; // projection matrix
Camera g_camera; // camera
float g_orbitSpeed[5] = { 0.3f, 0.5f, 0.4f, 0.2f, 0.1f }; // for speed of rotation around sun
float g_rotationSpeed[5] = { 0.07f, 0.7f, 3.0f, 5.0f, 1.0f }; // for speed of rotation on own axis
float g_scaleSize[5] = { 0.5f, 0.5f, 0.5f, 0.5f, 0.5f }; // for scaling the orbiting planets
float g_axisOfRotation[5] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, }; // for offsetting the axis of rotation
float g_alpha = 0.5f; // transparency of 4th planet
bool g_enableAnimation = true;
void generate_circle()
{
float angle = PI * 2 / static_cast<float>(g_slices); // used to generate x and y coordinates
float scale_factor = static_cast<float>(WINDOW_HEIGHT) / WINDOW_WIDTH; // scale to make it a circle instead of an elipse
int index = 0; // vertex index
g_vertices_circle[3] = CIRCLE_RADIUS * scale_factor; // set x coordinate of vertex 1
// generate vertex coordinates for triangle fan
for (int i = 2; i < g_slices + 2; i++)
{
// multiply by 3 because a vertex has x, y, z coordinates
index = i * 3;
g_vertices_circle[index] = CIRCLE_RADIUS * cos(angle) * scale_factor;
g_vertices_circle[index + 1] = CIRCLE_RADIUS * sin(angle);
g_vertices_circle[index + 2] = 0.0f;
//Color for edges. See stackoverflow
g_colors_circle[index] = 1.0f;
g_colors_circle[index + 1] = 0.0f;
g_colors_circle[index + 2] = 0.0f;
// update to next angle
angle += PI * 2 / static_cast<float>(g_slices);
}
// Gets rid of line from middle of circle
g_vertices_circle[0] = g_vertices_circle[3];
g_vertices_circle[1] = g_vertices_circle[4];
g_vertices_circle[2] = g_vertices_circle[5];
}
static void init(GLFWwindow* window)
{
glClearColor(0.0, 0.0, 0.0, 1.0); // set clear background colour
glEnable(GL_DEPTH_TEST); // enable depth buffer test
glEnable(GL_BLEND);
glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
// create and compile our GLSL program from the shader files
g_shaderProgramID = loadShaders("MVP_VS.vert", "ColorFS.frag");
// find the location of shader variables
GLuint positionIndex = glGetAttribLocation(g_shaderProgramID, "aPosition");
GLuint colorIndex = glGetAttribLocation(g_shaderProgramID, "aColor");
g_MVP_Index = glGetUniformLocation(g_shaderProgramID, "uModelViewProjectionMatrix");
g_alphaIndex = glGetUniformLocation(g_shaderProgramID, "uAlpha");
// initialise model matrix to the identity matrix
g_modelMatrix[0] = g_modelMatrix[1] = g_modelMatrix[2] = g_modelMatrix[3] = g_modelMatrix[4] = glm::mat4(1.0f);
g_modelMatrixCircle[0] = g_modelMatrixCircle[1] = g_modelMatrixCircle[2] = g_modelMatrixCircle[3] = g_modelMatrixCircle[4] = glm::mat4(1.0f);
g_modelMatrixSubPlanets[2] = g_modelMatrixSubPlanets[3] = glm::mat4(1.0f);;
// set camera's view matrix
g_camera.setViewMatrix(glm::vec3(0, 3, 14), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
int width, height;
glfwGetFramebufferSize(window, &width, &height);
float aspectRatio = static_cast<float>(width) / height;
// set camera's projection matrix
g_camera.setProjectionMatrix(glm::perspective(45.0f, aspectRatio, 0.1f, 100.0f));
// initialise projection matrix
g_projectionMatrix = glm::perspective(45.0f, aspectRatio, 0.1f, 100.0f);
// generate identifier for VBO and copy data to GPU
glGenBuffers(1, &g_VBO[0]);
glBindBuffer(GL_ARRAY_BUFFER, g_VBO[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertices), g_vertices, GL_STATIC_DRAW);
// generate identifier for IBO and copy data to GPU
glGenBuffers(1, &g_IBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(g_indices), g_indices, GL_STATIC_DRAW);
// generate identifiers for VAO
glGenVertexArrays(1, &g_VAO[0]);
// create VAO and specify VBO data
glBindVertexArray(g_VAO[0]);
glBindBuffer(GL_ARRAY_BUFFER, g_VBO[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_IBO);
// interleaved attributes
glVertexAttribPointer(positionIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, position)));
glVertexAttribPointer(colorIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, color)));
glEnableVertexAttribArray(positionIndex); // enable vertex attributes
glEnableVertexAttribArray(colorIndex);
/*------------------------Circle----------------------*/
// generate vertices of triangle fan
generate_circle();
// create VBO and buffer the data
glGenBuffers(1, &g_VBO[1]);
glBindBuffer(GL_ARRAY_BUFFER, g_VBO[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * (g_slices + 2), g_vertices_circle, GL_STATIC_DRAW);
glGenBuffers(1, &g_VBO[2]);
glBindBuffer(GL_ARRAY_BUFFER, g_VBO[2]);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * (g_slices + 2), g_colors_circle, GL_STATIC_DRAW);
// create VAO and specify VBO data
glGenVertexArrays(1, &g_VAO[1]);
glBindVertexArray(g_VAO[1]);
glBindBuffer(GL_ARRAY_BUFFER, g_VBO[1]);
glVertexAttribPointer(positionIndex, 3, GL_FLOAT, GL_FALSE, 0, 0); // specify the form of the data
glBindBuffer(GL_ARRAY_BUFFER, g_VBO[2]);
glVertexAttribPointer(colorIndex, 3, GL_FLOAT, GL_FALSE, 0, 0); // specify the form of the data
glEnableVertexAttribArray(positionIndex); // enable vertex attributes
glEnableVertexAttribArray(colorIndex);
/*----------------------------------------------------*/
}
//Generates a random value between 0.1 and 0.9
double generateRandomFloat(float min, float max)
{
return min + static_cast <float> (rand()) / (static_cast <float> (RAND_MAX / (max - min)));
}
// function used to update the scene
static void update_scene()
{
// static variables for rotation angles
static float orbitAngle[5] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, };
static float rotationAngle[5] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
float scaleFactor = 0.05;
orbitAngle[0] += g_orbitSpeed[0] * scaleFactor;
orbitAngle[1] += g_orbitSpeed[1] * scaleFactor;
orbitAngle[2] += g_orbitSpeed[2] * scaleFactor;
orbitAngle[3] += g_orbitSpeed[3] * scaleFactor;
orbitAngle[4] += g_orbitSpeed[4] * scaleFactor;
// update rotation angles
rotationAngle[0] += g_rotationSpeed[0] * scaleFactor;
rotationAngle[1] += g_rotationSpeed[1] * scaleFactor;
rotationAngle[2] += g_rotationSpeed[2] * scaleFactor;
rotationAngle[3] += g_rotationSpeed[3] * scaleFactor;
rotationAngle[4] += g_rotationSpeed[4] * scaleFactor;
// update model matrix (planets)
g_modelMatrix[0] = glm::rotate(rotationAngle[0], glm::vec3(0.0f, 1.0f, 0.0f));
g_modelMatrix[1] = glm::translate(glm::vec3(g_axisOfRotation[1], 0.0f, 0.0f)) //moves the axis of rotation along x-axis
* glm::rotate(orbitAngle[1], glm::vec3(0.0f, 1.0f, 0.0f))
* glm::translate(glm::vec3(2.0f, 0.0f, 0.0f))
* glm::rotate(rotationAngle[1], glm::vec3(0.0f, -1.0f, 0.0f)) //enables rotation on own axis. try comment
* glm::rotate(glm::radians(45.0f), glm::vec3(1.0f, 0.0f, 0.0f)) //rotates into a diamond shape
* glm::rotate(glm::radians(45.0f), glm::vec3(0.0f, 0.0f, 1.0f)) //rotates into a diamond shape
* glm::scale(glm::vec3(g_scaleSize[1], g_scaleSize[1], g_scaleSize[1]));
g_modelMatrix[2] = glm::translate(glm::vec3(g_axisOfRotation[2], 0.0f, 0.0f))
* glm::rotate(orbitAngle[2], glm::vec3(0.0f, -1.0f, 0.0f))
* glm::translate(glm::vec3(4.0f, 0.0f, 0.0f))
* glm::rotate(rotationAngle[2], glm::vec3(0.0f, 1.0f, 0.0f))
* glm::scale(glm::vec3(g_scaleSize[2], g_scaleSize[2], g_scaleSize[2]));
g_modelMatrix[3] = glm::translate(glm::vec3(g_axisOfRotation[3], 0.0f, 0.0f))
* glm::rotate(orbitAngle[3], glm::vec3(0.0f, 1.0f, 0.0f))
* glm::translate(glm::vec3(6.0f, 0.0f, 0.0f))
* glm::rotate(rotationAngle[3], glm::vec3(0.0f, 1.0f, 0.0f))
* glm::scale(glm::vec3(g_scaleSize[3], g_scaleSize[3], g_scaleSize[3]));
g_modelMatrix[4] = glm::translate(glm::vec3(g_axisOfRotation[4], 0.0f, 0.0f))
* glm::rotate(orbitAngle[4], glm::vec3(0.0f, -1.0f, 0.0f)) // -y changes orbit to clock-wise
* glm::translate(glm::vec3(8.0f, 0.0f, 0.0f))
* glm::rotate(rotationAngle[4], glm::vec3(0.0f, -1.0f, 0.0f))
* glm::scale(glm::vec3(g_scaleSize[4], g_scaleSize[4], g_scaleSize[4]));
// update model matrix (orbit paths ie.circles)
g_modelMatrixCircle[1] = glm::translate(glm::vec3(g_axisOfRotation[1], 0.0f, 0.0f)) * glm::scale(glm::vec3(0.68f, 0.68f, 0.68f)) * glm::rotate(glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f));
g_modelMatrixCircle[2] = glm::translate(glm::vec3(g_axisOfRotation[2], 0.0f, 0.0f)) * glm::scale(glm::vec3(1.35f, 1.35f, 1.35f)) * glm::rotate(glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f));
g_modelMatrixCircle[3] = glm::translate(glm::vec3(g_axisOfRotation[3], 0.0f, 0.0f)) * glm::scale(glm::vec3(2.0f, 2.0f, 2.0f)) * glm::rotate(glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f));
g_modelMatrixCircle[4] = glm::translate(glm::vec3(g_axisOfRotation[4], 0.0f, 0.0f)) * glm::scale(glm::vec3(2.7f, 2.7f, 2.7f)) * glm::rotate(glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f));
// update model matrix (mini planets eg. moon)
g_modelMatrixSubPlanets[2] = glm::translate(glm::vec3(g_axisOfRotation[1], 0.0f, 0.0f))
* glm::scale(glm::vec3(0.35f, 0.35f, 0.35f))
* glm::rotate(glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f));
g_modelMatrixSubPlanets[3] = glm::translate(glm::vec3(g_axisOfRotation[3], 0.0f, 0.0f))
* glm::rotate(orbitAngle[3], glm::vec3(0.0f, 1.0f, 0.0f))
* glm::translate(glm::vec3(6.0f, 0.0f, 0.0f))
* glm::rotate(rotationAngle[3], glm::vec3(0.0f, 1.0f, 0.0f))
* glm::scale(glm::vec3(g_scaleSize[3], g_scaleSize[3], g_scaleSize[3]));
}
// 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
glm::mat4 MVP = glm::mat4(1.0f); //ModelViewProjection matrix to be shared. Initialized to identity
//Circle 1
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrixCircle[1];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glBindVertexArray(g_VAO[1]); // make VAO active
glDrawArrays(GL_LINE_LOOP, 0, g_slices + 2); // display the vertices based on the primitive type
//Circle 2
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrixCircle[2];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawArrays(GL_LINE_LOOP, 0, g_slices + 2); // display the vertices based on the primitive type
//Circle 3
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrixCircle[3];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawArrays(GL_LINE_LOOP, 0, g_slices + 2); // display the vertices based on the primitive type
//Circle 4
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrixCircle[4];;
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawArrays(GL_LINE_LOOP, 0, g_slices + 2); // display the vertices based on the primitive type
// Circle for Object 2
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix[2] * g_modelMatrixSubPlanets[2];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawArrays(GL_TRIANGLE_FAN, 0, g_slices + 2); // display the vertices based on the primitive type
glBindVertexArray(g_VAO[0]); // make VAO active
// Object 1
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix[0];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
// Object 2
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix[1];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
// Object 3
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix[2];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
// Object 4
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix[3];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glUniform1fv(g_alphaIndex, 2, &g_alpha);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
// Object 5
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix[4];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
// Moon for Object 3
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrixSubPlanets[3] * g_modelMatrix[4];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
glFlush(); // flush the pipeline
}
static void cursor_position_callback(GLFWwindow* window, double xpos, double ypos)
{
// variables to store mouse cursor coordinates
static double previous_xpos = xpos;
static double previous_ypos = ypos;
double delta_x = xpos - previous_xpos;
double delta_y = ypos - previous_ypos;
// pass mouse movement to camera class
g_camera.updateYaw(delta_x);
g_camera.updatePitch(delta_y);
// update previous mouse coordinates
previous_xpos = xpos;
previous_ypos = ypos;
}
// key press or release callback function
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
// quit if the ESCAPE key was press
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
{
// set flag to close the window
glfwSetWindowShouldClose(window, GL_TRUE);
return;
}
// toggle animation
else if (key == GLFW_KEY_P && action == GLFW_PRESS) {
static int count = 1;
if(count % 2 == 0)
g_enableAnimation = true;
else
g_enableAnimation = false;
count++;
}
// render in perspective view
else if (key == GLFW_KEY_1 && action == GLFW_PRESS) {
cout << "Perspective-View" << endl << endl;
// set camera's view matrix
g_camera.setViewMatrix(glm::vec3(0, 3, 14), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
render_scene();
}
// render from top view
else if (key == GLFW_KEY_2 && action == GLFW_PRESS) {
cout << "Top-View" << endl << endl;
// set camera's view matrix
g_camera.setViewMatrix(glm::vec3(0, 15.0f, 0), glm::vec3(0, 0, 0), glm::vec3(0, 0, -1.0f));
render_scene();
}
// render from eye-level view
else if (key == GLFW_KEY_3 && action == GLFW_PRESS) {
cout << "Eye-level View" << endl << endl;
// set camera's view matrix
g_camera.setViewMatrix(glm::vec3(0, 0, 10), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
render_scene();
}
// Randomize size, orbit speed, axis rotation speed of planets
else if (key == GLFW_KEY_R && action == GLFW_PRESS) {
// Randomize planet size
g_scaleSize[1] = generateRandomFloat(0.1, 0.75);
g_scaleSize[2] = generateRandomFloat(0.1, 0.75);
g_scaleSize[3] = generateRandomFloat(0.1, 0.75);
g_scaleSize[4] = generateRandomFloat(0.1, 0.75);
// Randomize speed of rotation (on planets own axis)
g_rotationSpeed[1] = generateRandomFloat(0.1, 2.0);
g_rotationSpeed[2] = generateRandomFloat(0.1, 2.0);
g_rotationSpeed[3] = generateRandomFloat(0.1, 2.0);
g_rotationSpeed[4] = generateRandomFloat(0.1, 2.0);
// Randomize speed of rotation around sun
g_orbitSpeed[1] = generateRandomFloat(0.1, 0.7);
g_orbitSpeed[2] = generateRandomFloat(0.1, 0.7);
g_orbitSpeed[3] = generateRandomFloat(0.1, 0.7);
g_orbitSpeed[4] = generateRandomFloat(0.1, 0.7);
// Randomize offset for axis of rotation
g_axisOfRotation[1] = generateRandomFloat(-0.5, 0.5);
g_axisOfRotation[2] = generateRandomFloat(-0.5, 0.5);
g_axisOfRotation[3] = generateRandomFloat(-0.5, 0.5);
g_axisOfRotation[4] = generateRandomFloat(-0.5, 0.5);
// Display info for each planet
cout << "PLANET 1 - \tSize: " << g_scaleSize[1] << "\tSpeed: " << g_rotationSpeed[1]
<< "\tOrbit Speed: " << g_orbitSpeed[1] << "\tAxis offset: " << g_axisOfRotation[1] << endl;
cout << "PLANET 2 - \tSize: " << g_scaleSize[2] << "\tSpeed: " << g_rotationSpeed[2]
<< "\tOrbit Speed: " << g_orbitSpeed[2] << "\tAxis offset: " << g_axisOfRotation[2] << endl;
cout << "PLANET 3 - \tSize: " << g_scaleSize[3] << "\tSpeed: " << g_rotationSpeed[3]
<< "\tOrbit Speed: " << g_orbitSpeed[3] << "\tAxis offset: " << g_axisOfRotation[3] << endl;
cout << "PLANET 4 - \tSize: " << g_scaleSize[4] << "\tSpeed: " << g_rotationSpeed[4]
<< "\tOrbit Speed: " << g_orbitSpeed[4] << "\tAxis offset: " << g_axisOfRotation[4] << endl;
cout << endl;
render_scene();
}
}
// error callback function
static void error_callback(int error, const char* description)
{
cerr << description << endl; // output error description
}
int main(void)
{
GLFWwindow* window = NULL; // pointer to a GLFW window handle
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(1500, 1000, "Assignment 2", 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);
// 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_DISABLED);
// initialise rendering states
init(window);
// variables for simple time management
float lastUpdateTime = glfwGetTime();
float currentTime = lastUpdateTime;
// the rendering loop
while (!glfwWindowShouldClose(window))
{
currentTime = glfwGetTime();
g_camera.update(window); // update camera
// only update if more than 0.02 seconds since last update
if (currentTime - lastUpdateTime > 0.02)
{
if (g_enableAnimation) { update_scene(); } // update the scene
render_scene(); // render the scene
glfwSwapBuffers(window); // swap buffers
glfwPollEvents(); // poll for events
lastUpdateTime = currentTime; // update last update time
}
}
// clean up
glDeleteProgram(g_shaderProgramID);
glDeleteBuffers(1, &g_IBO);
glDeleteBuffers(1, &g_VBO[0]);
glDeleteBuffers(1, &g_VBO[1]);
glDeleteVertexArrays(1, &g_VAO[0]);
glDeleteVertexArrays(1, &g_VAO[1]);
// close the window and terminate GLFW
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}
Fragment Shader
#version 330 core
// interpolated values from the vertex shaders
in vec3 vColor;
// uniform input data
uniform float uAlpha;
// output data
out vec3 fColor;
void main()
{
// set output color
fColor = vec4(vColor, uAlpha);
}
Vertex Shader
#version 330 core
// input data (different for all executions of this shader)
in vec3 aPosition;
in vec3 aColor;
// ModelViewProjection matrix
uniform mat4 uModelViewProjectionMatrix;
// output data (will be interpolated for each fragment)
out vec3 vColor;
void main()
{
// set vertex position
gl_Position = uModelViewProjectionMatrix * vec4(aPosition, 1.0);
// the color of each vertex will be interpolated
// to produce the color of each fragment
vColor = aColor;
}
In the vertex shader program you have declared the uniform uAlpha with type float.
uniform float uAlpha;
You correctly read the uniform location index of uAlpha:
g_alphaIndex = glGetUniformLocation(g_shaderProgramID, "uAlpha");
Your mistake is when specifying the value of a uniform variable:
glUniform1fv(g_alphaIndex, 2, &g_alpha);
Note, the second paramter of glUniform1fv is the number of elements.
The OpenGL Reference page
of Khronos Group clearly says about the 2nd parameter count:
For the vector (glUniform*v) commands, specifies the number of elements that are to be modified.
This should be 1 if the targeted uniform variable is not an array, and 1 or more if it is an array.
Note, you try to set the 1st and the 2nd element of an uniform array with type of float,
but you only declared a single uniform variable of type float.
This is an undefined behavior and may cause a crash.
Change your code somehow like that:
glUniform1fv(g_alphaIndex, 1, &g_alpha);
In your fragment shader, out color is "vec3" while you asign it with "vec4".
There are sevral ways to debug the opengl code and shaders, which might help you.
0.after compiling or linking shaders, you can get compile result or link result via glGetShaderInfoLog()
1.use glGetError() to fetch the error code, witch contains specific error information if error exists.Once you call this function, the error state in the context will be cleared.
2.out put intermediate result in shader, to see if there is something wrong in the shading calculations