I want to be able to pan, zoom, and orbit the cube. I would like to know why the cube appears fully zoomed on the screen such that I have to move backwards to view the whole cube. I would also like to change the zooming controls to alt and right mouse button for both zooming and orbiting but I cant get it to work. Any assistance would be appreciated.
/*/header inclusions*/
#include <iostream> // Includes C++ i/o stream
#include <GL/glew.h> // Includes glew header
#include <GL/freeglut.h> // Includes freeglut header
// GLM Math inclusions
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include<glm/gtc/type_ptr.hpp>
using namespace std; // Uses the standard namespace
#define WINDOW_TITLE "Modern OpenGL" // Macro for window title
//Vertex and fragment shader
#ifndef GLSL
#define GLSL(Version, source) "#version " #Version "\n" #source
#endif
// Variables for window width and height
GLint ShaderProgram, WindowWidth = 800, WindowHeight = 600;
GLuint VBO, VAO;
GLfloat cameraSpeed = 0.0005f;
GLchar currentKey;
GLfloat lastMouseX = 400, lastMouseY = 300;
GLfloat mouseXOffset, mouseYOffset, yaw = 0.0f, pitch = 0.0f;
GLfloat sensitivity = 0.5f;
bool mouseDetected = true;
//global vectors declaration
glm::vec3 cameraPosition = glm::vec3(0.0f,0.0f,0.0f);
glm::vec3 CameraUpY = glm::vec3(0.0f,1.0f,0.0f);
glm::vec3 CameraForwardZ = glm::vec3(0.0f,0.0f,-1.0f);
glm::vec3 front;
/* User-defined Function prototypes to:*/
void UResizeWindow(int,int);
void URenderGraphics(void);
void UCreateShader(void);
void UCreateBuffers(void);
void UKeyboard(unsigned char key, int x, int y);
void UKeyReleased(unsigned char key, int x, int y);
void UMouseMove(int x, int y);
/*Vertex shader source code*/
const GLchar * vertexShaderSource = GLSL(330,
layout(location=0) in vec3 position;
layout(location=1) in vec3 color;
out vec3 mobileColor; //declare a vec 4 variable
//Global variables for the transform matrices
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main(){
gl_Position = projection * view * model * vec4(position, 1.0f);//transform vertices
mobileColor = color;
}
);
/*Fragment shader program source code*/
const GLchar * fragmentShaderSource = GLSL(330,
in vec3 mobileColor;
out vec4 gpuColor;//out vertex_Color;
void main(){
gpuColor = vec4 (mobileColor, 1.0);
}
);
//main program
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowSize(WindowWidth, WindowHeight);
glutCreateWindow(WINDOW_TITLE);
glutReshapeFunc(UResizeWindow);
glewExperimental = GL_TRUE;
if (glewInit()!= GLEW_OK)
{
std::cout << "Failed to initialize GLEW" << std::endl;
return -1;
}
UCreateShader();
UCreateBuffers();
// Use the Shader program
glUseProgram(ShaderProgram);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set background color
glutDisplayFunc(URenderGraphics);
glutKeyboardFunc(UKeyboard);
glutKeyboardUpFunc(UKeyReleased);
glutPassiveMotionFunc(UMouseMove);
glutMainLoop();
// Destroys Buffer objects once used
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
return 0;
}
/* Resizes the window*/
void UResizeWindow(int w, int h)
{
WindowWidth = w;
WindowHeight = h;
glViewport(0, 0, WindowWidth, WindowHeight);
}
/* Renders graphics */
void URenderGraphics(void)
{
glEnable(GL_DEPTH_TEST); // Enable z-depth
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clears the screen
glBindVertexArray(VAO); // Activate the Vertex Array Object before rendering and transforming them
//camera movement logic
if(currentKey == 'w')
cameraPosition += cameraSpeed * CameraForwardZ;
if(currentKey == 's')
cameraPosition -= cameraSpeed * CameraForwardZ;
if(currentKey == 'a')
cameraPosition -= glm::normalize(glm::cross(CameraForwardZ, CameraUpY)) * cameraSpeed;
if(currentKey == 'd')
cameraPosition += glm::normalize(glm::cross(CameraForwardZ, CameraUpY)) * cameraSpeed;
CameraForwardZ = front;
// Transforms the object
glm::mat4 model;
model = glm::translate(model, glm::vec3(0.0, 0.0f, 0.0f)); // Place the object at the center of the 7i,p9rA
model = glm::rotate(model, 45.0f, glm::vec3(1.0, 1.0f, 1.0f)); // Rotate the object 45 degrees on the XYZ
model = glm::scale(model, glm::vec3(1.0f, 1.0f, -1.0f)); // Increase the object size by a scale of 2
// Transforms the camera
glm::mat4 view;
view = glm::lookAt(cameraPosition, cameraPosition + CameraForwardZ, CameraUpY); //Moves the world 0.5 units on X and -5 units in Z
// Creates a perspective projection
glm::mat4 projection;
projection = glm::perspective(45.0f, (GLfloat)WindowWidth / (GLfloat)WindowHeight, 0.1f, 100.0f);
// Retrieves and passes transform matrices to the Shader program
GLint modelLoc = glGetUniformLocation(ShaderProgram, "model");
GLint viewLoc = glGetUniformLocation(ShaderProgram, "view");
GLint projLoc = glGetUniformLocation(ShaderProgram, "projection");
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
glutPostRedisplay();
// Draws the triangles
glDrawArrays(GL_TRIANGLES,0, 36);
glBindVertexArray(0); // Deactivate the Vertex Array Object
glutSwapBuffers(); // Flips the the back buffer with the front buffer every frame. Similar to GL FLush
}
/*Creates the Shader program*/
void UCreateShader()
{
// Vertex shader
GLint vertexShader = glCreateShader(GL_VERTEX_SHADER); // Creates the Vertex Shader
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); // Attaches the Vertex Shader to the source code
glCompileShader(vertexShader); // Compiles the Vertex Shader
// Fragment Shader
GLint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); // Creates the Fragment Shader
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);// Attaches the Fragment Shader to the source code
glCompileShader(fragmentShader); // Compiles the Fragment Shader
// Shader program
ShaderProgram = glCreateProgram(); // Creates the Shader program and returns an id
glAttachShader(ShaderProgram, vertexShader); // Attach Vertex Shader to the Shader program
glAttachShader(ShaderProgram, fragmentShader);; // Attach Fragment Shader to the Shader program
glLinkProgram(ShaderProgram); //Link Vertex and Fragment shader, to Shader program
// Delete the Vertex and Fragment shaders once linked
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
}
/*creates the buffer and array object*/
void UCreateBuffers()
{
//position and color data
GLfloat vertices[] = {
//vertex positions and colors
-0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f,
0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.0f,
0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 1.0f,
};
//Generate buffer id,
glGenVertexArrays(1, &VAO);
glGenBuffers(1,&VBO);
// Activate the Vertex Array Object before binding and setting any VB0s and Vertex Attribute Pointers.
glBindVertexArray(VAO);
// Activate the VBO
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); //Copy vertices to VBO
// Set attribute pointer 0 to hold Position data
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0); // Enables vertex attribute
// Set attribute pointer 1 to hold Color data
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1); // Enables vertex attribute
glBindVertexArray(0); // Deactivates the VAC, which is good practice
}
//implement the UKeyboard function
void UKeyboard(unsigned char key, GLint x, GLint y)
{
switch(key){
case 'w':
currentKey = key;
cout<<"You Pressed W"<<endl;
break;
case 's':
currentKey = key;
cout<<"You Pressed S"<<endl;
break;
case 'a':
currentKey = key;
cout<<"You Pressed A"<<endl;
break;
case 'd':
currentKey = key;
cout<<"You Pressed D"<<endl;
break;
default:
cout<<"Press a key!"<<endl;
}
}
//implement the UKeyReleased function
void UKeyReleased(unsigned char key, GLint x, GLint y)
{
cout<<"Key Released!"<<endl;
currentKey = '0';
}
//implement UMouseMove function
void UMouseMove(int x, int y)
{
if(mouseDetected)
{
lastMouseX = x;
lastMouseY = y;
mouseDetected = false;
}
//get the direction mouse was moved
mouseXOffset = x - lastMouseX;
mouseYOffset = lastMouseY - y;
//update new coordinates
lastMouseX = x;
lastMouseY = y;
//apply sensitivity
mouseXOffset *= sensitivity;
mouseYOffset *= sensitivity;
//accumulate yaw and pitch
yaw += mouseXOffset;
pitch += mouseYOffset;
//maintain 90 degree pitch
if (pitch > 89.0f)
pitch = 89.0f;
if (pitch > -89.0f)
pitch = -89.0f;
//convert mouse coordinates
front.x = cos(glm::radians(pitch)) * cos(glm::radians(yaw));
front.y = sin(glm::radians(pitch));
front.z = cos(glm::radians(pitch)) * sin(glm::radians(yaw));
}
Start at a camera position, which is translated along the positiv z axis (e.g. (0, 0, 10)). front has to be initialized:
glm::vec3 cameraPosition = glm::vec3(0.0f,0.0f,10.0f);
glm::vec3 CameraUpY = glm::vec3(0.0f,1.0f,0.0f);
glm::vec3 CameraForwardZ = glm::vec3(0.0f,0.0f,-1.0f);
glm::vec3 front = glm::vec3(0.0f,0.0f,-1.0f);
You have to initialize the model matrix variable glm::mat4 model.
The glm API documentation refers to The OpenGL Shading Language specification 4.20.
5.4.2 Vector and Matrix Constructors
If there is a single scalar parameter to a vector constructor, it is used to initialize all components of the constructed vector to that scalar’s value. If there is a single scalar parameter to a matrix constructor, it is used to initialize all the components on the matrix’s diagonal, with the remaining components initialized to 0.0.
This means, that an Identity matrix can be initialized by the single parameter 1.0:
glm::mat4 model(1.0f);
The unit of the angles in OpenGL Mathematics is radian rather than degree. (glm::perspective, glm::rotate):
// Transforms the object
glm::mat4 model(1.0f);
model = glm::translate(model, glm::vec3(0.0, 0.0f, 0.0f)); // Place the object at the center of the 7i,p9rA
model = glm::rotate(model, glm::radians(45.0f), glm::vec3(1.0, 1.0f, 1.0f)); // Rotate the object 45 degrees on the XYZ
model = glm::scale(model, glm::vec3(1.0f, 1.0f, -1.0f)); // Increase the object size by a scale of 2
// Transforms the camera
glm::mat4 view = glm::lookAt(cameraPosition, cameraPosition + CameraForwardZ, CameraUpY); //Moves the world 0.5 units on X and -5 units in Z
// Creates a perspective projection
glm::mat4 projection = glm::perspective(glm::radians(45.0f), (GLfloat)WindowWidth / (GLfloat)WindowHeight, 0.1f, 100.0f);
There are some mistakes when front is calculated. pitch < -89.0f rather than pitch > -89.0f. The x axis is sin(glm::radians(yaw)) and the z axis is -cos(glm::radians(yaw)):
//maintain 90 degree pitch
if (pitch > 89.0f)
pitch = 89.0f;
if (pitch < -89.0f)
pitch = -89.0f;
//convert mouse coordinates
front.x = cos(glm::radians(pitch)) * sin(glm::radians(yaw));
front.y = sin(glm::radians(pitch));
front.z = cos(glm::radians(pitch)) * -cos(glm::radians(yaw));
Furthermore, the sensitivity seams to be to strong, I recommend to reduce it (e.g. GLfloat sensitivity = 0.05f;).
Related
Recently, I have been trying to add lighting to a simple OpenGL scene using the Blinn-Phong shading model as described in this website.
I tried to follow the tutorial as closely as possible. However, the lighting seems off, especially on the side faces of the cube as the light source begins to move across the front.
I believe it would have something to do with the positions of the Normals not being in the right place due to rotation on the model matrix or having done something wrong in the lighting shader, however, I am not sure whether either of those is really the cause.
Here is the source code, by the way:
#include <glad/glad.h>
#include <SFML/Graphics.hpp>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <iostream>
#include <cstdlib>
#include <cmath>
// Vertex shader for the light source cube
const std::string source_vert_shader = R"(
#version 330 core
layout (location = 0) in vec3 vertPos;
uniform mat4 proj, view, model;
void main() {
gl_Position = proj * view * model * vec4(vertPos, 1);
}
)";
// Fragment shader for the light source cube
const std::string source_frag_shader = R"(
#version 330 core
out vec4 FragColor;
void main() {
FragColor = vec4(1);
}
)";
// Vertex shader for the cube
const std::string cube_vert_shader = R"(
#version 330 core
layout (location = 0) in vec3 vertPos;
layout (location = 1) in vec3 vertNorm;
uniform mat4 proj, view, model;
out vec3 fragPos;
out vec3 interNorm;
void main() {
fragPos = vec3(model * vec4(vertPos, 1));
gl_Position = proj * view * vec4(fragPos, 1);
interNorm = mat3(transpose(inverse(model))) * vertNorm;
}
)";
// Fragment shader for the cube
const std::string cube_frag_shader = R"(
#version 330 core
in vec3 fragPos;
in vec3 interNorm;
out vec4 FragColor;
uniform vec3 viewPos;
uniform vec3 lightPos;
uniform vec3 objectColor;
const float pi = 3.14159265;
const float shininess = 16;
void main() {
vec3 normal = normalize(interNorm);
vec3 lightDir = normalize(lightPos - fragPos);
float dist = length(lightPos - fragPos);
float attenuation = 1 / (dist * dist);
// Ambient light effect
const float ambientStrength = 0.05;
vec3 ambient = ambientStrength * objectColor;
// Diffuse light effect
float diff = max(dot(normal, lightDir), 0);
vec3 diffuse = attenuation * diff * objectColor;
// Specular light effect
vec3 specular = vec3(0);
if (diff != 0) {
const float energy_conservation = (8 + shininess) / (8 * pi);
vec3 viewDir = normalize(viewPos - fragPos);
vec3 halfwayDir = normalize(lightDir + viewDir);
float spec = energy_conservation * pow(max(dot(normal, halfwayDir), 0), shininess);
specular = attenuation * spec * vec3(0.3);
}
const float gamma = 2.2;
// Apply the different lighting techniques of the Phong shading model and finally apply gamma correction
FragColor = vec4(pow(ambient + diffuse + specular, vec3(1 / gamma)), 1);
}
)";
int main() {
// Initialize the window
sf::RenderWindow window(
sf::VideoMode(1365, 768), "Lighting", sf::Style::Default,
sf::ContextSettings(24, 8, 4, 3, 3, sf::ContextSettings::Core, true));
// Initialize OpenGL functions
gladLoadGLLoader(reinterpret_cast<GLADloadproc>(sf::Context::getFunction));
// Specify the viewport of the scene
glViewport(0, 0, window.getSize().x, window.getSize().y);
// Enable depth testing
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
// Enable blending
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// Load the shaders into the application
sf::Shader shader, source_shader;
(void)shader.loadFromMemory(cube_vert_shader, cube_frag_shader);
(void)source_shader.loadFromMemory(source_vert_shader, source_frag_shader);
// Define the vertices of the cube and the light source cube
float vertices[] = {
// Vertices Normals
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f,
-0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f
};
// Attach the vertices in the vertices array to the VAO and the VBO
GLuint vao, vbo;
glGenVertexArrays(1, &vao);
glGenBuffers(1, &vbo);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof vertices, vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), nullptr);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), reinterpret_cast<void*>(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
// The same VBO can be used to render the light source cube
GLuint source_vao;
glGenVertexArrays(1, &source_vao);
glBindVertexArray(source_vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), nullptr);
glEnableVertexAttribArray(0);
// Projection matrix
auto proj = glm::perspective(glm::radians(45.0f), static_cast<GLfloat>(window.getSize().x) / window.getSize().y, 0.1f, 100.0f);
glm::vec3 view_pos(0.0f, 0.0f, -5.0f);
// View/camera matrix
glm::mat4 view(1.0f);
view = glm::translate(view, view_pos);
view = glm::rotate(view, glm::radians(45.0f), glm::vec3(1.0f, 1.0f, 1.0f));
// Model matrix
glm::mat4 model(1.0f);
//model = glm::rotate(model, glm::radians(45.0f), glm::vec3(1.0f, 1.0f, 0.0f));
// For the cube in the center
shader.setUniform("proj", sf::Glsl::Mat4(glm::value_ptr(proj)));
shader.setUniform("view", sf::Glsl::Mat4(glm::value_ptr(view)));
shader.setUniform("model", sf::Glsl::Mat4(glm::value_ptr(model)));
shader.setUniform("viewPos", sf::Glsl::Vec3(view_pos.x, view_pos.y, view_pos.z));
shader.setUniform("objectColor", sf::Glsl::Vec3(1.0f, 0.3f, 1.0f));
// For the light source cube
source_shader.setUniform("proj", sf::Glsl::Mat4(glm::value_ptr(proj)));
source_shader.setUniform("view", sf::Glsl::Mat4(glm::value_ptr(view)));
sf::Clock clock;
sf::Event evt{};
while (window.isOpen()) {
while (window.pollEvent(evt)) {
if (evt.type == sf::Event::Closed) {
// When window is closed, destroy the VAO and the VBO
glDeleteBuffers(1, &vbo);
glDeleteVertexArrays(1, &vao);
window.close();
}
if (evt.type == sf::Event::Resized)
// Update the viewport as the window is resized
glViewport(0, 0, evt.size.width, evt.size.height);
}
// Clear the screen with a color
glClearColor(0.8f, 0.2f, 0.6f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Calculate an angular factor based on the elapsed time
auto const angular_factor = glm::radians(45.0f) * clock.getElapsedTime().asSeconds();
sf::Shader::bind(&shader);
// Makes the light source move in circles around the cube in the center
glm::vec3 light_pos(
6.0f * std::sin(angular_factor),
0.0f,
6.0f * std::cos(angular_factor)
);
shader.setUniform("lightPos", sf::Glsl::Vec3(light_pos.x, light_pos.y, light_pos.z));
// Draw the cube
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, 36);
sf::Shader::bind(&source_shader);
model = glm::identity<glm::mat4>();
model = glm::scale(model, glm::vec3(0.3f, 0.3f, 0.3f));
model = glm::translate(model, light_pos);
source_shader.setUniform("model", sf::Glsl::Mat4(glm::value_ptr(model)));
// Draw the light source cube
glBindVertexArray(source_vao);
glDrawArrays(GL_TRIANGLES, 0, 36);
sf::Shader::bind(nullptr);
// Swap the window's buffers
window.display();
}
}
I created a simple 3D cube with a camera. I am attempting to implement zooming, orbiting and panning of the cube object using a keyboard modifier and mouse input. The requirements for this functionality are as follows:
Holding ALT and the LEFT mouse button while moving the mouse left to pan left or right to pan right.
Holding ALT and LEFT mouse button while moving the mouse up or down will orbit the cube vertically.
Holding ALT and Right mouse button while moving the mouse up will zoom in and moving the mouse down will zoom out.
The functionality of these events does indeed work.
However, the following issues exist:
The cube only updates after I hold ALT, click and release the mouse button. I would like to be able to have the image rendered continuously. I think it would provide a smoother user experience.
When the program first starts up it appears that the cube is up close but this then resets to the location that I intended as soon as the ALT button is pressed.
The libraries required for this code are as follows:
glu32, glew32, freeglut, opengl32
The code is as follows:
// Header Inclusions
#include <iostream>
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <GL/glcorearb.h> // Used for glClear
// GLM Math Header inclusions
#include <glm/glm.hpp> // Located in TDM-GCC-64
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
using namespace std; // Standard namespace
#define WINDOW_TITLE "Modern OpenGL" // Window title macro
// Shader program macro
#ifndef GLSL
#define GLSL(Version, Source) "#version " #Version "\n" #Source
#endif
/* Variable declarations for shader, window size initialization,
* buffer and array objects */
GLint shaderProgram, WindowWidth = 800, WindowHeight = 600;
GLuint VBO, VAO;
GLfloat cameraSpeed = 0.5f; // Movement speed per frame
GLfloat lastMouseX = 400, lastMouseY = 300; // Locks mouse cursor to center of screen
GLfloat mouseXOffset, mouseYOffset, yaw = 0.0f, pitch = 0.0f; // mouse offset, yaw, and pitch variables
GLfloat sensitivity = 0.01f; // Used for mouse camera rotation sensitivity
GLfloat zoom = 10.0f; // Zoom multiple set to 10.
bool mouseDetected = true; // Initially true when mouse movement is detected
bool leftMouseClicked = false; // Set to false until button is clicked
bool rightMouseClicked = false; // Set to false until button is clicked
/* Will store key pressed: Used to determine if orthogonal view should be used instead of 3D
* when the letter z is pressed down */
GLchar currentKey;
// Global vector declarations
glm::vec3 cameraPosition = glm::vec3(0.0f, 0.0f, 1.0f); // Initial camera position. Placed 5 units in z
glm::vec3 CameraUpY = glm::vec3(0.0f, 1.0f, 0.0f); // Temporary y unit vector
glm::vec3 CameraForwardZ = glm::vec3(0.0f, 0.0f, -1.0f); // Temporary z unit vector
glm::vec3 front = glm::vec3(0.0f, 0.0f, 0.0f); // Temp z unit vector for mouse
// Function prototypes
void UResizeWindow(int, int);
void URenderGraphics(void);
void UCreateShader(void);
void UCreateBuffers(void);
void UMouseMove(int x, int y);
void OnMouseClick(int button, int state, int x, int y);
// Vertex Shader Source Code
const GLchar * vertexShaderSource = GLSL(330,
layout (location = 0) in vec3 position; // Vertex data from Vertex Attrib Pointer 0
layout (location = 1) in vec3 color; // Color data from Vertex Attrib Pointer 1
out vec3 mobileColor; // variable to transfer color data to the fragment shader
// Global variables for the transform matrices.
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main(){
gl_Position = projection * view * model * vec4(position, 1.0f); // transform vertices to clip coordinates
mobileColor = color; // references incoming color data
}
);
// Fragment Shader Source Code
const GLchar * fragmentShaderSource = GLSL(330,
in vec3 mobileColor; // Variable to hold incoming color data from vertex shader
out vec4 gpuColor; // Variable to pass color data to the GPU
void main(){
gpuColor = vec4(mobileColor, 1.0); // Sends color data to the GPU for rendering
}
);
/* MAIN PROGRAM */
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowSize(WindowWidth, WindowHeight);
glutCreateWindow(WINDOW_TITLE);
glutReshapeFunc(UResizeWindow);
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK){
std::cout << "Failed to initialize GLEW" << std::endl;
return -1;
}
UCreateShader();
UCreateBuffers();
// Use the Shader program
glUseProgram(shaderProgram);
glClearColor(0.0f,0.0f, 0.0f, 1.0f); // set background color
glutDisplayFunc(URenderGraphics); // Renders graphics
glutPassiveMotionFunc(UMouseMove); // Detects mouse movement
glutMouseFunc(OnMouseClick); // Detects mouse button clicked
glutMainLoop();
// Destroys Buffer objects once used
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
return 0;
}
// Resize the window
void UResizeWindow(int w, int h){
WindowWidth = w;
WindowHeight = h;
glViewport(0, 0, WindowWidth, WindowHeight);
}
// Renders graphics
void URenderGraphics(void){
glEnable(GL_DEPTH_TEST); //Enable z-depth
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clears the screen
glBindVertexArray(VAO); // Activate the Vertex Array Object before rendering and transforming them
CameraForwardZ = front; // Replaces camera forward vector with Radians normalized as a unit vector
// Transform the object
glm::mat4 model;
model = glm::translate(model, glm::vec3(0.0, 0.0f, 0.0f)); // Place the object at the center of the viewport
model = glm::rotate(model, 45.0f, glm::vec3(0.0, 1.0f, 0.0f)); // Rotate the object 45 degrees on the X axis
model = glm::scale(model, glm::vec3(2.0f, 2.0f, 2.0f)); // Increase the object size by a scale of 2
// Transform the camera
glm::mat4 view;
view = glm::lookAt(CameraForwardZ, cameraPosition, CameraUpY);
// Display perspective
glm::mat4 projection;
// Creates an perspective projection
projection = glm::perspective(45.0f, (GLfloat)WindowWidth / (GLfloat)WindowHeight, 0.1f, 100.0f);
// Retrieves and passes transform matrices to the shader program
GLint modelLoc = glGetUniformLocation(shaderProgram, "model");
GLint viewLoc = glGetUniformLocation(shaderProgram, "view");
GLint projLoc = glGetUniformLocation(shaderProgram, "projection");
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
glutPostRedisplay();
// Draws the triangles
glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(0); // Deactivate the Vertex Array Object
glutSwapBuffers(); // Flips the back buffer with the from buffer every frame. Similar to GL Flush.
}
// Creates the shader program
void UCreateShader(){
// vertex shader
GLint vertexShader = glCreateShader(GL_VERTEX_SHADER); // Create the vertex shader
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); // Attaches the Vertex shader to the source code
glCompileShader(vertexShader); // Compiles the Vertex shader
// Fragment shader
GLint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); // Create the fragment shader
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL); // Attaches fragment shader to source code
glCompileShader(fragmentShader); // Compiles the fragment shader
// Shader program
shaderProgram = glCreateProgram(); // Create the shader program and return an id
glAttachShader(shaderProgram, vertexShader); // Attach Vertex shader to the shader program
glAttachShader(shaderProgram, fragmentShader); // Attach fragment shader to the shader program
glLinkProgram(shaderProgram); // Link vertex and fragment shader to shader program
// Delete the vertex and fragment shader once linked
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
}
// Create the buffer and array objects
void UCreateBuffers(){
// Position and color data
GLfloat vertices[] = {
// Vertex positions // colors
-0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f,
0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.0f,
0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 1.0f
};
// Generate buffer Ids
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
// Activate the Vertex Array Object before binding and setting any VBO's and Vertex Attribute Pointers
glBindVertexArray(VAO);
// Activate the VBO
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); // Copy vertices to VBO
// Set attribute pointer 0 to hold Position data
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0); // Enables vertex attribute
// Set attribute pointer 1 to hold Position data
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1); // Enables vertex attribute
glBindVertexArray(0); // Deactivates the VAO which is good practice
}
// Implements the UMouseMove function
void UMouseMove(int x, int y) {
/* If mouse is clicked and left alt is held down then the cube
* will be rotated in the direction of the mouse.*/
if(glutGetModifiers() == GLUT_ACTIVE_ALT) {
mouseXOffset = x - lastMouseX;
mouseYOffset = lastMouseY - y;
lastMouseX = x;
lastMouseY = y;
mouseXOffset *= sensitivity;
mouseYOffset *= sensitivity;
// Rotate Object if left mouse clicked
while(leftMouseClicked) {
yaw += mouseXOffset;
pitch -= mouseYOffset;
pitch = max(-0.5f, pitch);
pitch = min(0.5f, pitch);
leftMouseClicked = false; // resets leftMouseClicked to default state
}
// Zoom object if right mouse clicked
while(rightMouseClicked) {
zoom += mouseYOffset * cameraSpeed; // Zoom into object
rightMouseClicked = false; // resets rightMouseClicked to default state
}
front.x = zoom * cos(yaw);
front.y = zoom * sin(pitch);
front.z = sin(yaw) * cos(pitch) * zoom;
}
lastMouseX = x;
lastMouseY = y;
}
// Check the mouse button click state to verify which button is pressed
void OnMouseClick(int button, int state, int x, int y){
// Set leftMouseClicked State to true
if(state == GLUT_DOWN && button == GLUT_LEFT_BUTTON){
leftMouseClicked = true;
}
// Set rightMouseClicked State to true
if(state == GLUT_DOWN && button == GLUT_RIGHT_BUTTON){
rightMouseClicked = true;
}
}
The problem here is the use of glutPassiveMotionFunc within the main program function. This function executes only when the mouse is moving with no buttons being clicked. glutMouseFunc generates a callback each time a mouse button is pressed and released. This triggers the function "OnMouseClick" that only sets the variable of leftMouseClicked or rightMouseClicked to true. Nothing is rendered until the mouse button is no longer being clicked (mouse up condition). At this point no buttons are being pressed which causes glutPassiveMotionFunc to send a call back triggering the "UMouseMove" function. The "UMouseMove" function then calculates the change in y or x and updates the front focus of the camera. This is why the object does not render while the mouse button is being pressed down. Only when the mouse button is released (the mouse is moving with no buttons being pressed) do the coordinates update for rendering.
The solution to this is to use glutMotionFunc instead of glutPassiveMotionFunc. glutMotionFunc executes the callback when the mouse moves while a mouse button is clicked (mouse down position). This executes the "UMouseMove" function while the mouse button is pressed down and concurrently updates the front focus of the camera.
Recommendations:
Change glutPassiveMotionFunc to glutMotionFunc in main as follows:
glutDisplayFunc(URenderGraphics); // Renders graphics
glutMotionFunc(UMouseMove); // <--- Change this line //Detects mouse movement
glutMouseFunc(OnMouseClick); // Detects mouse button clicked
glutMainLoop();
Edit the "UMouseMove" function to first check if the ALT key modifier is being pressed. Remove handling the leftMouseClicked and rightMouseClicked variables within this method. Move the last two lines of this function within the if statement as shown:
// Implements the UMouseMove function
void UMouseMove(int x, int y) {
/* If mouse is clicked and left alt is held down then the cube
* will be rotated in the direction of the mouse.*/
if(glutGetModifiers() == GLUT_ACTIVE_ALT) {
mouseXOffset = x - lastMouseX;
mouseYOffset = lastMouseY - y;
lastMouseX = x;
lastMouseY = y;
mouseXOffset *= sensitivity;
mouseYOffset *= sensitivity;
// Rotate Object if left mouse clicked
if(leftMouseClicked) {
yaw += mouseXOffset;
pitch -= mouseYOffset;
pitch = max(-0.5f, pitch);
pitch = min(0.5f, pitch);
}
// Zoom object if right mouse clicked
else if(rightMouseClicked) {
zoom += mouseYOffset * cameraSpeed; // Zoom into object
}
front.x = zoom * cos(yaw);
front.y = zoom * sin(pitch);
front.z = sin(yaw) * cos(pitch) * zoom;
lastMouseX = x;
lastMouseY = y;
}
}
The OnMouseClick function should handle all mouse button click events for good housekeeping practice. This can be something as simple as the following:
// Check the mouse button click state to verify which button is pressed
void OnMouseClick(int button, int state, int x, int y){
// Set leftMouseClicked State to true
if(state == GLUT_DOWN && button == GLUT_LEFT_BUTTON){
leftMouseClicked = true;
}
else{
leftMouseClicked = false;
}
// Set rightMouseClicked State to true
if(state == GLUT_DOWN && button == GLUT_RIGHT_BUTTON){
rightMouseClicked = true;
}
else{
rightMouseClicked = false;
}
}
I think am missing something when drawing the textured pyramid. I can't get it to work properly since I am not good with 3d modern OpenGL. Somehow, I managed to draw a cube but seems am going wrong with the pyramid. I want the four sides to have 0.5(top), 0.0(left), 1,0 (right). and the bottom to be 0,1 (top left), 1,1 (top right), 0,0 (bottom left) and 1,0 (bottom right). I need these coordinates since am only getting flunky images with my coordinate. Any help would be appreciated.
here is my code with the vertices of a cube that I had created earlier and was running well.
/*Header Inclusions*/
#include <iostream>
#include <GL/Glew.h>
#include <GL/freeglut.h>
// GLM Math inclusions
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include<glm/gtc/type_ptr.hpp>
//include soil
#include "SOIL2/SOIL2.h"
using namespace std; // Uses the standard namespace
#define WINDOW_TITLE "Modern OpenGL" // Macro for window title
//Vertex and fragment shader
#ifndef GLSL
#define GLSL(Version, source) "#version " #Version "\n" #source
#endif
// Variables for window width and height
GLint ShaderProgram, WindowWidth = 800, WindowHeight = 600;
GLuint VBO, VAO, texture;
GLfloat degrees = glm::radians(-45.0f);
/* User-defined Function prototypes to:*/
void UResizeWindow(int,int);
void URenderGraphics(void);
void UCreateShader(void);
void UCreateBuffers(void);
void UGenerateTexture(void);
/*Vertex shader source code*/
const GLchar * vertexShaderSource = GLSL(330,
layout(location = 0) in vec3 position;
layout(location = 2) in vec2 textureCoordinate;
out vec2 mobileTextureCoordinate; //declare a vec 4 variable
//Global variables for the transform matrices
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main(){
gl_Position = projection * view * model * vec4(position, 1.0f);//transform vertices
mobileTextureCoordinate = vec2(textureCoordinate.x, 1.0f - textureCoordinate.y);
}
);
/*Fragment shader program source code*/
const GLchar * fragmentShaderSource = GLSL(330,
in vec2 mobileTextureCoordinate;
out vec4 gpuTexture;//out vertex_Color;
uniform sampler2D uTexture;
void main(){
gpuTexture = texture(uTexture, mobileTextureCoordinate);
}
);
//main program
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowSize(WindowWidth, WindowHeight);
glutCreateWindow(WINDOW_TITLE);
glutReshapeFunc(UResizeWindow);
glewExperimental = GL_TRUE;
if (glewInit()!= GLEW_OK)
{
std::cout << "Failed to initialize GLEW" << std::endl;
return -1;
}
UCreateShader();
UCreateBuffers();
UGenerateTexture();
// Use the Shader program
glUseProgram(ShaderProgram);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set background color
glutDisplayFunc(URenderGraphics);
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION);
glutMainLoop();
// Destroys Buffer objects once used
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
return 0;
}
/* Resizes the window*/
void UResizeWindow(int w, int h)
{
WindowWidth = w;
WindowHeight = h;
glViewport(0, 0, WindowWidth, WindowHeight);
}
/* Renders graphics */
void URenderGraphics(void)
{
glEnable(GL_DEPTH_TEST); // Enable z-depth
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clears the screen
glBindVertexArray(VAO); // Activate the Vertex Array Object before rendering and transforming them
// Transforms the object
glm::mat4 model;
model = glm::translate(model, glm::vec3(0.0, 0.0f, 0.0f)); // Place the object at the center of the 7i,p9rA
model = glm::rotate(model, degrees, glm::vec3(0.0, 1.0f, 0.0f)); // Rotate the object 45 degrees on the XYZ
model = glm::scale(model, glm::vec3(2.0f, 2.0f, 2.0f)); // Increase the object size by a scale of 2
// Transforms the camera
glm::mat4 view;
view = glm::translate(view, glm::vec3(0.0f,0.0f,-5.0f)); //Moves the world 0.5 units on X and -5 units in Z
// Creates a perspective projection
glm::mat4 projection;
projection = glm::perspective(45.0f, (GLfloat)WindowWidth / (GLfloat)WindowHeight, 0.1f, 100.0f);
// Retrieves and passes transform matrices to the Shader program
GLint modelLoc = glGetUniformLocation(ShaderProgram, "model");
GLint viewLoc = glGetUniformLocation(ShaderProgram, "view");
GLint projLoc = glGetUniformLocation(ShaderProgram, "projection");
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
glutPostRedisplay();
glBindTexture(GL_TEXTURE_2D, texture);
// Draws the triangles
glDrawArrays(GL_TRIANGLES,0, 36);
glBindVertexArray(0); // Deactivate the Vertex Array Object
glutSwapBuffers(); // Flips the the back buffer with the front buffer every frame. Similar to GL FLush
}
/*Creates the Shader program*/
void UCreateShader()
{
// Vertex shader
GLint vertexShader = glCreateShader(GL_VERTEX_SHADER); // Creates the Vertex Shader
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); // Attaches the Vertex Shader to the source code
glCompileShader(vertexShader); // Compiles the Vertex Shader
// Fragment Shader
GLint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); // Creates the Fragment Shader
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);// Attaches the Fragment Shader to the source code
glCompileShader(fragmentShader); // Compiles the Fragment Shader
// Shader program
ShaderProgram = glCreateProgram(); // Creates the Shader program and returns an id
glAttachShader(ShaderProgram, vertexShader); // Attach Vertex Shader to the Shader program
glAttachShader(ShaderProgram, fragmentShader);; // Attach Fragment Shader to the Shader program
glLinkProgram(ShaderProgram); //Link Vertex and Fragment shader, to Shader program
// Delete the Vertex and Fragment shaders once linked
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
}
/*creates the buffer and array object*/
void UCreateBuffers()
{
//position and color data
GLfloat vertices[] = {
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f
};
//Generate buffer id,
glGenVertexArrays(1, &VAO);
glGenBuffers(1,&VBO);
// Activate the Vertex Array Object before binding and setting any VB0s and Vertex Attribute Pointers.
glBindVertexArray(VAO);
// Activate the VBO
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); //Copy vertices to VBO
// Set attribute pointer 0 to hold Position data
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0); // Enables vertex attribute
// Set attribute pointer 2 to hold Color data
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(2); // Enables vertex attribute
glBindVertexArray(0); // Deactivates the VAC, which is good practice
}
/*Generate and load the texture*/
void UGenerateTexture(){
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
int width,height;
unsigned char* image = SOIL_load_image("snhu.jpg", &width, &height, 0, SOIL_LOAD_RGB);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
glGenerateMipmap(GL_TEXTURE_2D);
SOIL_free_image_data(image);
glBindTexture(GL_TEXTURE_2D, 0);
}
I recommend to define a structure type for the attribute tuples:
struct TAttributeTuple
{
glm::vec3 v;
glm::vec2 uv;
};
Define the 5 corner points of the pyramid:
(Your explanation of the points is a bit unclear, so I am not sure if the points are according to your specification. Possibly you've modify them.)
glm::vec3 top( 0.5f, 0.5f, 0.5f );
glm::vec3 p01( -0.1f, 0.0f, 1.0f );
glm::vec3 p11( 1.1f, 0.0f, 1.0f );
glm::vec3 p00( 0.0f, 0.0f, 0.0f );
glm::vec3 p10( 1.0f, 0.0f, 0.0f );
Setup the array of vertex attributes:
TAttributeTuple vertices[]
{
{ p00, glm::vec2(0.0f, 0.0f) },
{ p10, glm::vec2(1.0f, 0.0f) },
{ p11, glm::vec2(1.0f, 1.0f) },
{ p00, glm::vec2(0.0f, 0.0f) },
{ p11, glm::vec2(1.0f, 1.0f) },
{ p01, glm::vec2(0.0f, 1.0f) },
{ p00, glm::vec2(0.0f, 0.0f) },
{ p10, glm::vec2(1.0f, 0.0f) },
{ top, glm::vec2(0.5f, 1.0f) },
{ p10, glm::vec2(0.0f, 0.0f) },
{ p11, glm::vec2(1.0f, 0.0f) },
{ top, glm::vec2(0.5f, 1.0f) },
{ p11, glm::vec2(0.0f, 0.0f) },
{ p01, glm::vec2(1.0f, 0.0f) },
{ top, glm::vec2(0.5f, 1.0f) },
{ p01, glm::vec2(0.0f, 0.0f) },
{ p00, glm::vec2(1.0f, 0.0f) },
{ top, glm::vec2(0.5f, 1.0f) }
};
For some reason the colors are not rendering when I run my program. With the addition of glm, I have been running into issues with some strange images rendering on run. It might be a library, but it is highly doubtful. I have checked and rechecked my includes and libraries. I am using Eclipse.
Here is my code
/*
* Module5.cpp
*
* Created on: Aug 21, 2017
* Author:
*/
#include <iostream>
#include <Gl/glew.h>
#include <GL/freeglut.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
using namespace std;
#define WINDOW_TITLE "Window"
#ifndef GLSL
#define GLSL(Version, Source) "#version " #Version "\n" #Source
#endif
GLint shaderProgram, WindowWidth = 800, WindowHeight = 600;
GLuint VBO, VAO; //Global variables for Buffer Object etc.
GLfloat cameraSpeed = 0.0005f;
GLchar currentKey; //will store key pressed
glm::vec3 cameraPosition = glm::vec3(0.0f, 0.0f, 5.0f);
glm::vec3 CameraUpY = glm::vec3(0.0f, 1.0f, 0.0f);
glm::vec3 CameraForwardZ = glm::vec3(0.0f, 0.0f, -1.0f);
void UResizeWindow(int, int);
void URenderGraphics(void);
void UCreateShader(void);
void UCreateBuffers(void);
void UKeyboard(unsigned char key, int x, int y);
void UKeyReleased(unsigned char key, int x, int y);
const GLchar * vertexShaderSource = GLSL(330,
layout(location=0) in vec3 position; //incoming data
layout(location=1) in vec3 color;
out vec4 mobileColor; //Attrib pointer 0
//out vec4 colorFromVShader;
//uniform mat4 primitiveTransform; //transform for shape
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
//gl_Position = primitiveTransform * vertex_Position; //move object on y-axis .5
gl_Position = projection * view * model * vec4(position, 1.0f); //move object on y-axis .5
//colorFromVShader = colorFromVBO;
mobileColor = color;
}
);
const GLchar * fragmentShaderSource = GLSL(440,
in vec3 mobileColor;
out vec4 gpuColor;
void main(){
// gl_FragColor= vec4(1.0, 0.5, 0.0, 1.0);
gpuColor= vec4(mobileColor, 1.0);
}
);
//Main
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowSize(WindowWidth, WindowHeight);
glutCreateWindow(WINDOW_TITLE);
glutReshapeFunc(UResizeWindow);
glewExperimental = GL_TRUE;
if(glewInit() != GLEW_OK)
{
cout << "Failed to initialize glew!" << endl;
return -1;
}
UCreateShader();
UCreateBuffers();
glUseProgram(shaderProgram);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glutDisplayFunc(URenderGraphics);
glutKeyboardFunc(UKeyboard);
glutKeyboardUpFunc(UKeyReleased);
glutMainLoop();
glDeleteVertexArrays(1, &VAO);//cleanup
glDeleteBuffers(1, &VBO);//cleanup
return 0;
}
void UResizeWindow(int w, int h)
{
WindowWidth = w;
WindowHeight = h;
glViewport(0, 0, WindowWidth, WindowHeight);
}
void URenderGraphics(void)
{
glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//clears screen
glBindVertexArray(VAO); //activate vertex array to render the vertices that render our shape
if(currentKey == 'w')
cameraPosition += cameraSpeed * CameraForwardZ;
if(currentKey == 's')
cameraPosition -= cameraSpeed * CameraForwardZ;
if(currentKey == 'a')
cameraPosition -= cameraSpeed * CameraForwardZ;
if(currentKey == 'd')
cameraPosition += cameraSpeed * CameraForwardZ;
glm::mat4 model;
model = glm::translate(model,glm::vec3(0.0f, 0.0f, 0.0));
model = glm::rotate(model, glm::radians(-45.0f), glm::vec3(0.0f, 1.0f, 0.0f)); //rotate shape x-axis by 1.0f
model = glm::scale(model, glm::vec3(2.0f, 2.0f, 2.0f)); //scale shape
glm::mat4 view; //camera
view = glm::lookAt(cameraPosition, cameraPosition + CameraForwardZ, CameraUpY); //move camera back by 5 (z)
glm::mat4 projection;
projection = glm::perspective(45.0f, (GLfloat)WindowWidth / (GLfloat)WindowHeight, 0.1f, 100.0f);
//projection = glm::ortho(-5.0f, 5.0f, -5.0f, 5.0f, 0.1f, 100.0f);
GLint modelLoc = glGetUniformLocation(shaderProgram, "model");
GLint viewLoc = glGetUniformLocation(shaderProgram, "view");
GLint projLoc = glGetUniformLocation(shaderProgram, "projection");
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
//apply projection matrix
/*
glm::mat4 newTransform; //references 4 x 4 matrix
newTransform = glm::translate(newTransform, glm::vec3(0.0f, 0.5f, 0.0)); //make square move up y-axis
newTransform = glm::rotate(newTransform, glm::radians(45.0f), glm::vec3(0.0f, 0.0f, 1.0f)); //rotate shape
//newTransform = glm::scale(newTransform, glm::vec3(0.5f, 0.5f, 0.5f)); //rotate shape
GLuint transformInfo = glGetUniformLocation(ProgramId, "primitiveTransform"); //id for shader, name of variable shader
glUniformMatrix4fv(transformInfo, 1, GL_FALSE, glm::value_ptr(newTransform));
*/
glutPostRedisplay();
glDrawArrays(GL_TRIANGLES, 0 , 36);
glBindVertexArray(0);
glutSwapBuffers();
}
void UCreateShader()
{
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
}
/*void applyDepthSettings() {
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set background color to black and opaque
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glShadeModel(GL_SMOOTH);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
}*/
void UCreateBuffers()
{
//specify coords for creating square
// Positon and Color data
GLfloat vertices[] = {
// Vertex Positions // Colors
-0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, // Top Right Vertex 0
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, // Bottom Right Vertex 1
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, // Bottom Left Vertex 2
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, // Top Left Vertex 3
-0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 0.0f, // Top Right Vertex 0
0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 0.0f, // Bottom Right Vertex 1
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, // Bottom Left Vertex 2
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, // Top Left Vertex 3
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, // Top Right Vertex 0
-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, // Bottom Right Vertex 1
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, // Bottom Left Vertex 2
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, // Top Left Vertex 3
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 0.0f, // Top Right Vertex 0
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f, // Bottom Right Vertex 1
0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.0f, // Bottom Left Vertex 2
0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.0f, // Top Left Vertex 3
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 1.0f, // Top Right Vertex 0
0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 1.0f, // Bottom Right Vertex 1
0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 1.0f, // Bottom Left Vertex 2
0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 1.0f, // Top Left Vertex 3
-0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 1.0f, // Top Right Vertex 0
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 1.0f, // Bottom Right Vertex 1
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f, // Bottom Left Vertex 2
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f, // Top Left Vertex 3
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 1.0f,
};
//generate id's for buffer object
glGenVertexArrays(1, &VAO); //generate for Vertex Array Object
glGenBuffers(1, &VBO); //generate for Vertex Buffer Object
glBindVertexArray(VAO); //activate text array object
glBindBuffer(GL_ARRAY_BUFFER, VBO); //activating VBO buffer
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); //pass in size of array from line 128
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);//send data to shader (accepts 6 arguments)GL_FALSE=not using normalization
glEnableVertexAttribArray(0);//enable vertex attribute pointer, starting position of x,y,z
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));//send data to shader (accepts 6 arguments)GL_FALSE=not using normalization
glEnableVertexAttribArray(1);//specify color starting point
glBindVertexArray(0); //deactivate vertex array object (VBO)
}
void UKeyboard(unsigned char key, GLint x, GLint y)
{
switch(key)
{
case'w':
cout<<"You pressed W!" <<endl;
break;
case 's':
cout<<"You pressed S!"<<endl;
break;
case'a':
cout<<"You pressed A!"<<endl;
break;
case 'd':
cout<<"You pressed D!"<<endl;
break;
default:
cout<<"Press a key!"<<endl;
}
}
/*Implements the UKeyReleased function*/
void UKeyReleased(unsigned char key, GLint x, GLint y)
{
cout<<"Key released"<<endl;
}
Your vertex shader does not compile, because mobileColor is of type vec4 and color is of type vec3.
Change:
mobileColor = color;
to:
mobileColor = vec4(color, 1.0);
Note, your shader program was not used, because it was not successfully built. Everything you have drawn was drawn by default OpenGL with the currently set glColor, which is by default white (1,1,1,1).
Whether the compilation of a shader succeeded can be checked by glGetShaderiv, and the error message can be retrieved with glGetShaderInfoLog:
GLint status = GL_TRUE;
glCompileShader( shaderStage );
glGetShaderiv( shaderStage, GL_COMPILE_STATUS, &status );
if ( status == GL_FALSE )
{
GLint logLen;
glGetShaderiv( shaderStage, GL_INFO_LOG_LENGTH, &logLen );
std::vector< char >log( logLen+1 );
GLsizei written;
glGetShaderInfoLog( shaderStage, logLen, &written, log.data() );
std::cout << "compile error:" << std::endl << log.data() << std::endl;
}
Whether a program was linked successfully can be checked by glGetProgramiv, and the error message can be retrieved with glGetProgramInfoLog:
GLint status = GL_TRUE;
glLinkProgram( shaderProgram );
glGetProgramiv( shaderProgram, GL_LINK_STATUS, &status );
if ( status == GL_FALSE )
{
GLint logLen;
glGetProgramiv( shaderProgram, GL_INFO_LOG_LENGTH, &logLen );
std::vector< char >log( logLen+1 );
GLsizei written;
glGetProgramInfoLog( shaderProgram, logLen, &written, log.data() );
std::cout << "link error:" << std::endl << log.data() << std::endl;
}
I have created a simple cube in OpenGL, and am still coming to grips with developing an FPS camera to move around it. For now, the code only allows for left, right, up and down movements via the W,A,S,D keys. The application code is as follows:
#include <iostream>
#include <cmath>
// GLEW
#define GLEW_STATIC
#include <GL/glew.h>
// GLFW
#include <GLFW/glfw3.h>
// GLM Mathematics
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
// Other includes
#include "Shader.h"
// Function prototypes
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
void do_movement();
// Window dimensions
const GLuint WIDTH = 800, HEIGHT = 600;
// Camera
glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 3.0f);
glm::vec3 cameraFront = glm::vec3(0.0f, 0.0f, -1.0f);
glm::vec3 cameraUp = glm::vec3(0.0f, 1.0f, 0.0f);
bool keys[1024];
// Deltatime
GLfloat deltaTime = 0.0f; // Time between current frame and last frame
GLfloat lastFrame = 0.0f; // Time of last frame
// The MAIN function, from here we start the application and run the game loop
int main()
{
// Init GLFW
glfwInit();
// Set all the required options for GLFW
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
// Create a GLFWwindow object that we can use for GLFW's functions
GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr);
glfwMakeContextCurrent(window);
// Set the required callback functions
glfwSetKeyCallback(window, key_callback);
// Set this to true so GLEW knows to use a modern approach to retrieving function pointers and extensions
glewExperimental = GL_TRUE;
// Initialize GLEW to setup the OpenGL Function pointers
glewInit();
// Define the viewport dimensions
glViewport(0, 0, WIDTH, HEIGHT);
//Enable depth test
glEnable(GL_DEPTH_TEST);
// Build and compile our shader program
Shader ourShader("C:/Users/Noel/Documents/Visual Studio 2013/Projects/RoomSim/Vertexshader.vs", "C:/Users/Noel/Documents/Visual Studio 2013/Projects/RoomSim/FragShader.frag");
// Set up vertex data (and buffer(s)) and attribute pointers
GLfloat vertices[] = {
-0.5f, -0.5f, -0.5f,
0.5f, -0.5f, -0.5f,
0.5f, 0.5f, -0.5f,
0.5f, 0.5f, -0.5f,
-0.5f, 0.5f, -0.5f,
-0.5f, -0.5f, -0.5f,
-0.5f, -0.5f, 0.5f,
0.5f, -0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
-0.5f, -0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, -0.5f,
-0.5f, -0.5f, -0.5f,
-0.5f, -0.5f, -0.5f,
-0.5f, -0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
0.5f, 0.5f, -0.5f,
0.5f, -0.5f, -0.5f,
0.5f, -0.5f, -0.5f,
0.5f, -0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
-0.5f, -0.5f, -0.5f,
0.5f, -0.5f, -0.5f,
0.5f, -0.5f, 0.5f,
0.5f, -0.5f, 0.5f,
-0.5f, -0.5f, 0.5f,
-0.5f, -0.5f, -0.5f,
-0.5f, 0.5f, -0.5f,
0.5f, 0.5f, -0.5f,
0.5f, 0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, -0.5f,
};
GLuint VBO, VAO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
// Bind the Vertex Array Object first, then bind and set vertex buffer(s) and attribute pointer(s).
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
//glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
// Position attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3* sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
// Color attribute
//glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
//glEnableVertexAttribArray(1);
glBindVertexArray(0); // Unbind VAO
// Game loop
while (!glfwWindowShouldClose(window))
{
// Calculate deltatime of current frame
GLfloat currentFrame = glfwGetTime();
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
// Check if any events have been activiated (key pressed, mouse moved etc.) and call corresponding response functions
glfwPollEvents();
do_movement();
// Render
// Clear the colorbuffer
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//Transformations
// Create transformations
//glm::mat4 transform;
//transform = glm::translate(transform, glm::vec3(0.5f, -0.5f, 0.0f));
//transform = glm::rotate(transform, (GLfloat)glfwGetTime() * 50.0f, glm::vec3(0.0f, 0.0f, 1.0f));
// Get matrix's uniform location and set matrix
//GLint transformLoc = glGetUniformLocation(ourShader.Program, "transform");
//glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(transform));
// Draw the triangle
ourShader.Use();
// Create transformations
glm::mat4 model;
glm::mat4 view;
glm::mat4 projection;
//Camera particulars for view
glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 3.0f);
glm::vec3 cameraFront = glm::vec3(0.0f, 0.0f, -1.0f);
glm::vec3 cameraUp = glm::vec3(0.0f, 1.0f, 0.0f);
model = glm::rotate(model, 50.0f, glm::vec3(1.0f, 0.0f, 0.0f));
view = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp);
projection = glm::perspective(45.0f, (GLfloat)WIDTH / (GLfloat)HEIGHT, 0.1f, 100.0f);
// Get their uniform location
GLint modelLoc = glGetUniformLocation(ourShader.Program, "model");
GLint viewLoc = glGetUniformLocation(ourShader.Program, "view");
GLint projLoc = glGetUniformLocation(ourShader.Program, "projection");
glBindVertexArray(VAO);
// Pass them to the shaders
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(0);
// Swap the screen buffers
glfwSwapBuffers(window);
}
// Properly de-allocate all resources once they've outlived their purpose
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
// Terminate GLFW, clearing any resources allocated by GLFW.
glfwTerminate();
return 0;
}
// Is called whenever a key is pressed/released via GLFW
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
if (key >= 0 && key < 1024)
{
if (action == GLFW_PRESS)
keys[key] = true;
else if (action == GLFW_RELEASE)
keys[key] = false;
}
}
void do_movement()
{
GLfloat cameraSpeed = 5.0f * deltaTime;
// Camera controls
if (keys[GLFW_KEY_W])
cameraPos += cameraSpeed * cameraFront;
if (keys[GLFW_KEY_S])
cameraPos -= cameraSpeed * cameraFront;
if (keys[GLFW_KEY_A])
cameraPos -= glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed;
if (keys[GLFW_KEY_D])
cameraPos += glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed;
}
The issue is that nothing happens on pressing the W,A,S,D keys whatsover. The Vertex shader implemented is as below:
#version 330 core
layout(location = 0) in vec3 position;
layout(location = 1) in vec3 color;
out vec3 ourColor;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(position, 1.0f);
ourColor = color;
}
What could be the cause for no movement?
You redefine cameraPos inside the while loop, this shadows the global cameraPos you update in the doMovement function.
Just remove the declarations from inside the while.
There are two variables called cameraPos:
One in global scope which is used in key_callback
and a local one in main (inside the while loop) which is set to a constant value and is used to create the view-matrix.
Solution: Remove the local variable in main and just use the global one.