I'm trying to create a toggle to change between ortho and perspective views. I have successfully coded buttons to initiate camera movement but can't figure out how to code a button to perform this change.
How I would toggle the projection modes here?
My code so far:
#include <iostream> // cout, cerr
#include <cstdlib> // EXIT_FAILURE
#include <GL/glew.h> // GLEW library
#include <GLFW/glfw3.h> // GLFW library
// GLM Math Header inclusions
#include <glm/glm.hpp>
#include <glm/gtx/transform.hpp>
#include <glm/gtc/type_ptr.hpp>
//Camera class
#include <learnOpengl/camera.h>
using namespace std; // Standard namespace
/*Shader program Macro*/
#ifndef GLSL
#define GLSL(Version, Source) "#version " #Version " core \n" #Source
#endif
// Unnamed namespace
namespace
{
const char* const WINDOW_TITLE = "Milestone 4-5"; // Macro for window title
// Variables for window width and height
const int WINDOW_WIDTH = 800;
const int WINDOW_HEIGHT = 600;
// Stores the GL data relative to a given mesh
struct GLMesh
{
GLuint vao; // Handle for the vertex array object
GLuint vbo; // Handles for the vertex buffer objects
GLuint nVertices; // Number of indices of the mesh
};
// Main GLFW window
GLFWwindow* gWindow = nullptr;
// Triangle mesh data
GLMesh gMesh;
// Shader program
GLuint gProgramId;
// camera
Camera gCamera(glm::vec3(0.0f, 0.0f, 3.0f));
float gLastX = WINDOW_WIDTH / 2.0f;
float gLastY = WINDOW_HEIGHT / 2.0f;
bool gFirstMouse = true;
glm::vec3 gCameraPos = glm::vec3(0.0f, 0.0f, 3.0f);
glm::vec3 gCameraFront = glm::vec3(0.0f, 0.0f, -1.0f);
glm::vec3 gCameraUp = glm::vec3(0.0f, 1.0f, 0.0f);
// timing
float gDeltaTime = 0.0f; // time between current frame and last frame
float gLastFrame = 0.0f;
}
/* User-defined Function prototypes to:
* initialize the program, set the window size,
* redraw graphics on the window when resized,
* and render graphics on the screen
*/
bool UInitialize(int, char* [], GLFWwindow** window);
void UResizeWindow(GLFWwindow* window, int width, int height);
void UProcessInput(GLFWwindow* window);
void UMousePositionCallback(GLFWwindow* window, double xpos, double ypos);
void UMouseScrollCallback(GLFWwindow* window, double xoffset, double yoffset);
void UMouseButtonCallback(GLFWwindow* window, int button, int action, int mods);
void UCreateMesh(GLMesh& mesh);
void UDestroyMesh(GLMesh& mesh);
void URender();
bool UCreateShaderProgram(const char* vtxShaderSource, const char* fragShaderSource, GLuint& programId);
void UDestroyShaderProgram(GLuint programId);
/* Vertex Shader Source Code*/
const GLchar* vertexShaderSource = GLSL(440,
layout(location = 0) in vec3 position; // Vertex data from Vertex Attrib Pointer 0
layout(location = 1) in vec4 color; // Color data from Vertex Attrib Pointer 1
out vec4 vertexColor; // 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); // transforms vertices to clip coordinates
vertexColor = color; // references incoming color data
}
);
/* Fragment Shader Source Code*/
const GLchar* fragmentShaderSource = GLSL(440,
in vec4 vertexColor; // Variable to hold incoming color data from vertex shader
out vec4 fragmentColor;
void main()
{
fragmentColor = vec4(vertexColor);
}
);
int main(int argc, char* argv[])
{
if (!UInitialize(argc, argv, &gWindow))
return EXIT_FAILURE;
// Create the mesh
UCreateMesh(gMesh); // Calls the function to create the Vertex Buffer Object
// Create the shader program
if (!UCreateShaderProgram(vertexShaderSource, fragmentShaderSource, gProgramId))
return EXIT_FAILURE;
// Sets the background color of the window to black (it will be implicitly used by glClear)
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
// render loop
// -----------
while (!glfwWindowShouldClose(gWindow))
{
// per-frame timing
// --------------------
float currentFrame = glfwGetTime();
gDeltaTime = currentFrame - gLastFrame;
gLastFrame = currentFrame;
// input
// -----
UProcessInput(gWindow);
// Render this frame
URender();
glfwPollEvents();
}
// Release mesh data
UDestroyMesh(gMesh);
// Release shader program
UDestroyShaderProgram(gProgramId);
exit(EXIT_SUCCESS); // Terminates the program successfully
}
// Initialize GLFW, GLEW, and create a window
bool UInitialize(int argc, char* argv[], GLFWwindow** window)
{
// GLFW: initialize and configure
// ------------------------------
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 4);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
// GLFW: window creation
// ---------------------
* window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_TITLE, NULL, NULL);
if (*window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return false;
}
glfwMakeContextCurrent(*window);
glfwSetFramebufferSizeCallback(*window, UResizeWindow);
glfwSetCursorPosCallback(*window, UMousePositionCallback);
glfwSetScrollCallback(*window, UMouseScrollCallback);
glfwSetMouseButtonCallback(*window, UMouseButtonCallback);
// tell GLFW to capture our mouse
glfwSetInputMode(*window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
// GLEW: initialize
// ----------------
// Note: if using GLEW version 1.13 or earlier
glewExperimental = GL_TRUE;
GLenum GlewInitResult = glewInit();
if (GLEW_OK != GlewInitResult)
{
std::cerr << glewGetErrorString(GlewInitResult) << std::endl;
return false;
}
// Displays GPU OpenGL version
cout << "INFO: OpenGL Version: " << glGetString(GL_VERSION) << endl;
return true;
}
// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
void UProcessInput(GLFWwindow* window)
{
static const float cameraSpeed = 2.5f;
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
gCamera.ProcessKeyboard(FORWARD, gDeltaTime);
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
gCamera.ProcessKeyboard(BACKWARD, gDeltaTime);
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
gCamera.ProcessKeyboard(LEFT, gDeltaTime);
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
gCamera.ProcessKeyboard(RIGHT, gDeltaTime);
if (glfwGetKey(window, GLFW_KEY_Q) == GLFW_PRESS)
gCamera.ProcessKeyboard(UP, gDeltaTime);
if (glfwGetKey(window, GLFW_KEY_E) == GLFW_PRESS)
gCamera.ProcessKeyboard(DOWN, gDeltaTime);
}
// glfw: whenever the window size changed (by OS or user resize) this callback function executes
void UResizeWindow(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
// glfw: whenever the mouse moves, this callback is called
// -------------------------------------------------------
void UMousePositionCallback(GLFWwindow* window, double xpos, double ypos)
{
if (gFirstMouse)
{
gLastX = xpos;
gLastY = ypos;
gFirstMouse = false;
}
float xoffset = xpos - gLastX;
float yoffset = gLastY - ypos; // reversed since y-coordinates go from bottom to top
gLastX = xpos;
gLastY = ypos;
gCamera.ProcessMouseMovement(xoffset, yoffset);
}
// glfw: whenever the mouse scroll wheel scrolls, this callback is called
// ----------------------------------------------------------------------
void UMouseScrollCallback(GLFWwindow* window, double xoffset, double yoffset)
{
gCamera.ProcessMouseScroll(yoffset);
}
// glfw: handle mouse button events
// --------------------------------
void UMouseButtonCallback(GLFWwindow* window, int button, int action, int mods)
{
switch (button)
{
case GLFW_MOUSE_BUTTON_LEFT:
{
if (action == GLFW_PRESS)
cout << "Left mouse button pressed" << endl;
else
cout << "Left mouse button released" << endl;
}
break;
case GLFW_MOUSE_BUTTON_MIDDLE:
{
if (action == GLFW_PRESS)
cout << "Middle mouse button pressed" << endl;
else
cout << "Middle mouse button released" << endl;
}
break;
case GLFW_MOUSE_BUTTON_RIGHT:
{
if (action == GLFW_PRESS)
cout << "Right mouse button pressed" << endl;
else
cout << "Right mouse button released" << endl;
}
break;
default:
cout << "Unhandled mouse button event" << endl;
break;
}
}
// Functioned called to render a frame
void URender()
{
// Enable z-depth
glEnable(GL_DEPTH_TEST);
// Clear the frame and z buffers
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 1. Scales the object by 0.5
glm::mat4 scale = glm::scale(glm::vec3(0.5f, 0.5f, 0.5f));
// 2. Rotates shape by 37 degrees
glm::mat4 rotation = glm::rotate(37.0f, glm::vec3(1.0, 0.4f, 1.0f));
// 3. Place object at the origin
glm::mat4 translation = glm::translate(glm::vec3(0.0f, 0.0f, 0.0f));
// Model matrix: transformations are applied right-to-left order
glm::mat4 model = translation * rotation * scale;
// camera/view transformation
glm::mat4 view = gCamera.GetViewMatrix();
// Creates a perspective projection
glm::mat4 projection = glm::perspective(glm::radians(gCamera.Zoom), (GLfloat)WINDOW_WIDTH / (GLfloat)WINDOW_HEIGHT, 0.1f, 100.0f);
// Set the shader to be used
glUseProgram(gProgramId);
// Retrieves and passes transform matrices to the Shader program
GLint modelLoc = glGetUniformLocation(gProgramId, "model");
GLint viewLoc = glGetUniformLocation(gProgramId, "view");
GLint projLoc = glGetUniformLocation(gProgramId, "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));
// Activate the VBOs contained within the mesh's VAO
glBindVertexArray(gMesh.vao);
// Draws the triangles
glDrawArrays(GL_TRIANGLES, 0, gMesh.nVertices);
// Deactivate the Vertex Array Object
glBindVertexArray(0);
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
glfwSwapBuffers(gWindow); // Flips the the back buffer with the front buffer every frame.
}
// Implements the UCreateMesh function
void UCreateMesh(GLMesh& mesh)
{
// Position and Color data
GLfloat verts[] = {
// Vertex Positions // Colors (r,g,b,a)
2.8f, 2.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // top right 0
2.8f, 0.2f, 0.0f, 0.5f, 1.0f, 1.0f, 1.0f, // bottom right 1
-0.8f, 2.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, // top left 3
2.8f, 0.2f, 0.0f, 0.5f, 1.0f, 1.0f, 1.0f, // bottom right 1
-0.8f, 0.2f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, // bottom left 2
-0.8f, 2.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, // top left 3
2.8f, 2.0f, -1.0f, 0.5f, 0.5f, 1.0f, 1.0f, // 4 back top right
2.8f, 0.2f, -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, // 5 back bot right
-0.8f, 2.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // 7 back top left
2.8f, 0.2f, -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, // 5 back bot right
-0.8f, 0.2f, -1.0f, 0.2f, 0.2f, 0.5f, 1.0f, // 6 back bot left
-0.8f, 2.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // 7 back top left
2.8f, 2.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // top right 0
2.8f, 2.0f, -1.0f, 0.5f, 0.5f, 1.0f, 1.0f, // 4 back top right
-0.8f, 2.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // 7 back top left
2.8f, 2.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // top right 0
-0.8f, 2.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, // top left 3
-0.8f, 2.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // 7 back top left
2.8f, 0.2f, 0.0f, 0.5f, 1.0f, 1.0f, 1.0f, // bottom right 1
2.8f, 0.2f, -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, // 5 back bot right
-0.8f, 0.2f, -1.0f, 0.2f, 0.2f, 0.5f, 1.0f, // 6 back bot left
2.8f, 0.2f, 0.0f, 0.5f, 1.0f, 1.0f, 1.0f, // bottom right 1
-0.8f, 0.2f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, // bottom left 2
-0.8f, 0.2f, -1.0f, 0.2f, 0.2f, 0.5f, 1.0f, // 6 back bot left
-0.8f, 0.2f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, // bottom left 2
-0.8f, 2.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, // top left 3
-0.8f, 2.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // 7 back top left
-0.8f, 0.2f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, // bottom left 2
-0.8f, 0.2f, -1.0, 0.2f, 0.2f, 0.5f, 1.0f, // 6 back bot left
-0.8f, 2.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // 7 back top left
2.8f, 2.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // top right 0
2.8f, 0.2f, 0.0f, 0.5f, 1.0f, 1.0f, 1.0f, // bottom right 1
2.8f, 2.0f, -1.0f, 0.5f, 0.5f, 1.0f, 1.0f, // 4 back top right
2.8f, 0.2f, 0.0f, 0.5f, 1.0f, 1.0f, 1.0f, // bottom right 1
2.8f, 2.0f, -1.0f, 0.5f, 0.5f, 1.0f, 1.0f, // 4 back top right
2.8f, 0.2f, -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, // 5 back bot right
1.6f, 1.8f, 0.1f, 0.0f, 1.0f, 1.0f, 1.0f, // 8 top of vent pyramid
2.2f, 1.0f, 0.1f, 1.0f, 0.0f, 1.0f, 1.0f, // 9 right side of vent pyramid
1.5f, 1.2f, 0.1f, 0.0f, 0.0f, 0.0f, 0.0f, // 11 center apex
1.6f, 0.2f, 0.1f, 1.0f, 1.0f, 0.0f, 1.0f, // 10 bottom of vent pyramid
2.2f, 1.0f, 0.1f, 1.0f, 0.0f, 1.0f, 1.0f, // 9 right side of vent pyramid
1.5f, 1.2f, 0.1f, 0.0f, 0.0f, 0.0f, 0.0f, // 11 center apex
1.6f, 0.2f, 0.1f, 1.0f, 1.0f, 0.0f, 1.0f, // 10 bottom of vent pyramid
1.1f, 1.0f, 0.1f, 0.0f, 1.0f, 0.0f, 1.0f, // 12 left side of vent pyramid
1.5f, 1.2f, 0.1f, 0.0f, 0.0f, 0.0f, 0.0f, // 11 center apex
1.1f, 1.0f, 0.1f, 0.0f, 1.0f, 0.0f, 1.0f, // 12 left side of vent pyramid
1.5f, 1.2f, 0.1f, 0.0f, 0.0f, 0.0f, 0.0f, // 11 center apex
1.6f, 1.8f, 0.1f, 0.0f, 1.0f, 1.0f, 1.0f, // 8 top of vent pyramid
-4.0f, 4.0f, -1.0f, 0.0f, 0.25f, 0.25f, 1.0f,
4.0f, 4.0f, -1.0f, 0.0f, 0.25f, 0.25f, 1.0f,
-4.0f, -4.0f, -1.0f, 0.0f, 0.25f, 0.25f, 1.0f,
4.0f, 4.0f, -1.0f, 0.0f, 0.25f, 0.25f, 1.0f,
4.0f, -4.0f, -1.0f, 0.0f, 0.25f, 0.25f, 1.0f,
-4.0f, -4.0f, -1.0f, 0.0f, 0.25f, 0.25f, 1.0f,
};
const GLuint floatsPerVertex = 3;
const GLuint floatsPerColor = 4;
mesh.nVertices = sizeof(verts) / (sizeof(verts[0]) * (floatsPerVertex + floatsPerColor));
glGenVertexArrays(1, &mesh.vao); // we can also generate multiple VAOs or buffers at the same time
glBindVertexArray(mesh.vao);
// Create VBO
glGenBuffers(1, &mesh.vbo);
glBindBuffer(GL_ARRAY_BUFFER, mesh.vbo); // Activates the buffer
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW); // Sends vertex or coordinate data to the GPU
// Strides between vertex coordinates
GLint stride = sizeof(float) * (floatsPerVertex + floatsPerColor);
// Create Vertex Attribute Pointers
glVertexAttribPointer(0, floatsPerVertex, GL_FLOAT, GL_FALSE, stride, 0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, floatsPerColor, GL_FLOAT, GL_FALSE, stride, (char*)(sizeof(float) * floatsPerVertex));
glEnableVertexAttribArray(1);
}
void UDestroyMesh(GLMesh& mesh)
{
glDeleteVertexArrays(1, &mesh.vao);
glDeleteBuffers(1, &mesh.vbo);
}
// Implements the UCreateShaders function
bool UCreateShaderProgram(const char* vtxShaderSource, const char* fragShaderSource, GLuint& programId)
{
// Compilation and linkage error reporting
int success = 0;
char infoLog[512];
// Create a Shader program object.
programId = glCreateProgram();
// Create the vertex and fragment shader objects
GLuint vertexShaderId = glCreateShader(GL_VERTEX_SHADER);
GLuint fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER);
// Retrive the shader source
glShaderSource(vertexShaderId, 1, &vtxShaderSource, NULL);
glShaderSource(fragmentShaderId, 1, &fragShaderSource, NULL);
// Compile the vertex shader, and print compilation errors (if any)
glCompileShader(vertexShaderId); // compile the vertex shader
// check for shader compile errors
glGetShaderiv(vertexShaderId, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShaderId, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
return false;
}
// compile the fragment shader
glCompileShader(fragmentShaderId);
// check for shader compile errors
glGetShaderiv(fragmentShaderId, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragmentShaderId, sizeof(infoLog), NULL, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
return false;
}
// Attached compiled shaders to the shader program
glAttachShader(programId, vertexShaderId);
glAttachShader(programId, fragmentShaderId);
glLinkProgram(programId); // links the shader program
// check for linking errors
glGetProgramiv(programId, GL_LINK_STATUS, &success);
if (!success)
{
glGetProgramInfoLog(programId, sizeof(infoLog), NULL, infoLog);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
return false;
}
glUseProgram(programId); // Uses the shader program
return true;
}
void UDestroyShaderProgram(GLuint programId)
{
glDeleteProgram(programId);
}
Simply change your
glm::mat4 projection = glm::perspective(glm::radians(gCamera.Zoom), (GLfloat)WINDOW_WIDTH / (GLfloat)WINDOW_HEIGHT, 0.1f, 100.0f);
to use glm::ortho depending on your game state.
You'll likely have to tinker a bit with the view projection as well.
Related
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;
}
}
So Im working on opengl project from learnopengl and I am a beginner in C++ so I have little problem with it. It is a VS2017 project.
I have problem with main.cpp, when I compile it it shows this error:
name followed by '::' must be a class or namespace
it is in (FileSystem::getPath) so when i include filesystem.h in main.cpp it shows another error but in filesystem.h : cannot open
source file "root_directory.h"
so I downloaded root_directory.h from https://github.com/alifradityar/LastOrder same for entry.h. Now I have 10 warnings and 3 errors :-) just this is what happens when one wants to repair one error.
logl_root undeclared identifier from filesystem.h 23 next 'getenv': This function or variable may be unsafe. Consider using _dupenv_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. Every help is welcome.
I know I am only beginner but how am I supposed to learn it without trying to deal with problems ? And I know how stupid this question is :D...
Here if full project in 7z.:
https://drive.google.com/open?id=1vNTkh9HEcMKvM8Yzm0iCTJtx1d2xqvlR
filesystem.h, root_directory.h and entry.h are in /includes/learnopengl
lib-s and includes are linked in VS.
line: 24 - logl_root undefined 23 - 'getenv': This function or
variable may be unsafe. Consider using _dupenv_s instead. To disable
deprecation, use _CRT_SECURE_NO_WARNINGS. Every help is welcome.
**filesystem.h**
#ifndef FILESYSTEM_H
#define FILESYSTEM_H
#include <string>
#include <cstdlib>
#include "root_directory.h" // This is a configuration file generated by CMake.
class FileSystem
{
private:
typedef std::string (*Builder) (const std::string& path);
public:
static std::string getPath(const std::string& path)
{
static std::string(*pathBuilder)(std::string const &) = getPathBuilder();
return (*pathBuilder)(path);
}
private:
static std::string const & getRoot()
{
static char const * envRoot = getenv("LOGL_ROOT_PATH");
static char const * givenRoot = (envRoot != nullptr ? envRoot : logl_root);
static std::string root = (givenRoot != nullptr ? givenRoot : "");
return root;
}
//static std::string(*foo (std::string const &)) getPathBuilder()
static Builder getPathBuilder()
{
if (getRoot() != "")
return &FileSystem::getPathRelativeRoot;
else
return &FileSystem::getPathRelativeBinary;
}
static std::string getPathRelativeRoot(const std::string& path)
{
return getRoot() + std::string("/") + path;
}
static std::string getPathRelativeBinary(const std::string& path)
{
return "../../../" + path;
}
};
// FILESYSTEM_H
#endif
**root_directory.h**
#ifndef __ROOT
#define __ROOT
#include "entry.h"
#include <iostream>
#include <vector>
#include <string>
#include <ctime>
using namespace std;
class RootDirectory {
public:
vector <Entry> data;
RootDirectory();
string toString();
void load(string);
};
#endif#ifndef __ROOT
#define __ROOT
#include "entry.h"
#include <iostream>
#include <vector>
#include <string>
#include <ctime>
using namespace std;
class RootDirectory {
public:
vector <Entry> data;
RootDirectory();
string toString();
void load(string);
};
#endif
**main.cpp**
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <stb_image.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <learnopengl/shader_m.h>
#include <learnopengl/camera.h>
#include <learnopengl/filesystem.h>
#include <iostream>
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
void processInput(GLFWwindow *window);
unsigned int loadTexture(const char *path);
// settings
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;
// camera
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
float lastX = SCR_WIDTH / 2.0f;
float lastY = SCR_HEIGHT / 2.0f;
bool firstMouse = true;
// timing
float deltaTime = 0.0f;
float lastFrame = 0.0f;
int main()
{
// glfw: initialize and configure
// ------------------------------
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
// glfw window creation
// --------------------
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
glfwSetCursorPosCallback(window, mouse_callback);
glfwSetScrollCallback(window, scroll_callback);
// tell GLFW to capture our mouse
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
// glad: load all OpenGL function pointers
// ---------------------------------------
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
// configure global opengl state
// -----------------------------
glEnable(GL_DEPTH_TEST);
// build and compile our shader zprogram
// ------------------------------------
Shader lightingShader("5.4.light_casters.vs", "5.4.light_casters.fs");
Shader lampShader("5.4.lamp.vs", "5.4.lamp.fs");
// set up vertex data (and buffer(s)) and configure vertex attributes
// ------------------------------------------------------------------
float vertices[] = {
// positions // normals // texture coords
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f
};
// positions all containers
glm::vec3 cubePositions[] = {
glm::vec3(0.0f, 0.0f, 0.0f),
glm::vec3(2.0f, 5.0f, -15.0f),
glm::vec3(-1.5f, -2.2f, -2.5f),
glm::vec3(-3.8f, -2.0f, -12.3f),
glm::vec3(2.4f, -0.4f, -3.5f),
glm::vec3(-1.7f, 3.0f, -7.5f),
glm::vec3(1.3f, -2.0f, -2.5f),
glm::vec3(1.5f, 2.0f, -2.5f),
glm::vec3(1.5f, 0.2f, -1.5f),
glm::vec3(-1.3f, 1.0f, -1.5f)
};
// first, configure the cube's VAO (and VBO)
unsigned int VBO, cubeVAO;
glGenVertexArrays(1, &cubeVAO);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindVertexArray(cubeVAO);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(2);
// second, configure the light's VAO (VBO stays the same; the vertices are the same for the light object which is also a 3D cube)
unsigned int lightVAO;
glGenVertexArrays(1, &lightVAO);
glBindVertexArray(lightVAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
// note that we update the lamp's position attribute's stride to reflect the updated buffer data
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// load textures (we now use a utility function to keep the code more organized)
// -----------------------------------------------------------------------------
unsigned int diffuseMap = loadTexture(FileSystem::getPath("resources/textures/container2.png").c_str());
unsigned int specularMap = loadTexture(FileSystem::getPath("resources/textures/container2_specular.png").c_str());
// shader configuration
// --------------------
lightingShader.use();
lightingShader.setInt("material.diffuse", 0);
lightingShader.setInt("material.specular", 1);
// render loop
// -----------
while (!glfwWindowShouldClose(window))
{
// per-frame time logic
// --------------------
float currentFrame = glfwGetTime();
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
// input
// -----
processInput(window);
// render
// ------
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// be sure to activate shader when setting uniforms/drawing objects
lightingShader.use();
lightingShader.setVec3("light.position", camera.Position);
lightingShader.setVec3("light.direction", camera.Front);
lightingShader.setFloat("light.cutOff", glm::cos(glm::radians(12.5f)));
lightingShader.setFloat("light.outerCutOff", glm::cos(glm::radians(17.5f)));
lightingShader.setVec3("viewPos", camera.Position);
// light properties
lightingShader.setVec3("light.ambient", 0.1f, 0.1f, 0.1f);
// we configure the diffuse intensity slightly higher; the right lighting conditions differ with each lighting method and environment.
// each environment and lighting type requires some tweaking to get the best out of your environment.
lightingShader.setVec3("light.diffuse", 0.8f, 0.8f, 0.8f);
lightingShader.setVec3("light.specular", 1.0f, 1.0f, 1.0f);
lightingShader.setFloat("light.constant", 1.0f);
lightingShader.setFloat("light.linear", 0.09f);
lightingShader.setFloat("light.quadratic", 0.032f);
// material properties
lightingShader.setFloat("material.shininess", 32.0f);
// view/projection transformations
glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
glm::mat4 view = camera.GetViewMatrix();
lightingShader.setMat4("projection", projection);
lightingShader.setMat4("view", view);
// world transformation
glm::mat4 model;
lightingShader.setMat4("model", model);
// bind diffuse map
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, diffuseMap);
// bind specular map
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, specularMap);
// render containers
glBindVertexArray(cubeVAO);
for (unsigned int i = 0; i < 10; i++)
{
// calculate the model matrix for each object and pass it to shader before drawing
glm::mat4 model;
model = glm::translate(model, cubePositions[i]);
float angle = 20.0f * i;
model = glm::rotate(model, glm::radians(angle), glm::vec3(1.0f, 0.3f, 0.5f));
lightingShader.setMat4("model", model);
glDrawArrays(GL_TRIANGLES, 0, 36);
}
// again, a lamp object is weird when we only have a spot light, don't render the light object
// lampShader.use();
// lampShader.setMat4("projection", projection);
// lampShader.setMat4("view", view);
// model = glm::mat4();
// model = glm::translate(model, lightPos);
// model = glm::scale(model, glm::vec3(0.2f)); // a smaller cube
// lampShader.setMat4("model", model);
// glBindVertexArray(lightVAO);
// glDrawArrays(GL_TRIANGLES, 0, 36);
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
// -------------------------------------------------------------------------------
glfwSwapBuffers(window);
glfwPollEvents();
}
// optional: de-allocate all resources once they've outlived their purpose:
// ------------------------------------------------------------------------
glDeleteVertexArrays(1, &cubeVAO);
glDeleteVertexArrays(1, &lightVAO);
glDeleteBuffers(1, &VBO);
// glfw: terminate, clearing all previously allocated GLFW resources.
// ------------------------------------------------------------------
glfwTerminate();
return 0;
}
// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
// ---------------------------------------------------------------------------------------------------------
void processInput(GLFWwindow *window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
camera.ProcessKeyboard(FORWARD, deltaTime);
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
camera.ProcessKeyboard(BACKWARD, deltaTime);
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
camera.ProcessKeyboard(LEFT, deltaTime);
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
camera.ProcessKeyboard(RIGHT, deltaTime);
}
// glfw: whenever the window size changed (by OS or user resize) this callback function executes
// ---------------------------------------------------------------------------------------------
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
// make sure the viewport matches the new window dimensions; note that width and
// height will be significantly larger than specified on retina displays.
glViewport(0, 0, width, height);
}
// glfw: whenever the mouse moves, this callback is called
// -------------------------------------------------------
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
{
if (firstMouse)
{
lastX = xpos;
lastY = ypos;
firstMouse = false;
}
float xoffset = xpos - lastX;
float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top
lastX = xpos;
lastY = ypos;
camera.ProcessMouseMovement(xoffset, yoffset);
}
// glfw: whenever the mouse scroll wheel scrolls, this callback is called
// ----------------------------------------------------------------------
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{
camera.ProcessMouseScroll(yoffset);
}
// utility function for loading a 2D texture from file
// ---------------------------------------------------
unsigned int loadTexture(char const * path)
{
unsigned int textureID;
glGenTextures(1, &textureID);
int width, height, nrComponents;
unsigned char *data = stbi_load(path, &width, &height, &nrComponents, 0);
if (data)
{
GLenum format;
if (nrComponents == 1)
format = GL_RED;
else if (nrComponents == 3)
format = GL_RGB;
else if (nrComponents == 4)
format = GL_RGBA;
glBindTexture(GL_TEXTURE_2D, textureID);
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
stbi_image_free(data);
}
else
{
std::cout << "Texture failed to load at path: " << path << std::endl;
stbi_image_free(data);
}
return textureID;
}
If anyone is still searching for an answer...
// The FileSystem::getPath(...) is part of the GitHub repository so we can find files on any IDE/platform; replace it with your own image path.
I make this an answer instead of a comment (although I probably should be a comment). As you told yourself you want to learn. So instead of telling you a "solution", I'll try to show you the ropes how to properly deal with this kind of problems.
First and foremost, the most important part when dealing with compilation errors is to actually read the error message and then to understand it! Don't jump to conclusions, download arbitrary files from unrelated sources and mash things together! This approach won't work!
Let's break this down. You have a compiler error. It reads like the following:
(…) name followed by '::' must be a class or namespace (…)
Your quote, unfortunately is missing some information, namely in what file at which line the problem occoured. There's a certain logic behind how compilers report errors; older versions of GCC spat out rather arcane error logs, often several pages long; the culprit usually hides somewhere in the very first 5 lines or so of the whole error log. Usually you can safely ignore all the rest.
Anyway, it tells you what is wrong. Namely, that in C++ if you write something like a::b then a must be the name of a class or a namespace (which is exactly what the error tells you). However usually classes and namespaces are pulled in by a header include. If a include directive fails the preprocessor does bail out though, so it's unlikely that this has anything to do with a missing include at all.
But what can happen as well is, that before an include something is not how it should be. Usually a missing semicolon (;). which might cause a class declaration to be mangled up with something else.
So here's what you should do: Carefully reread the compiler log from the beginning. Look at all the warnings and errors on top, then work your way down.
If you get stuck again, edit your question, and if I can help you, I'll append to this answer.
I am writing a mini OpenGL program with instancing in it. But when I ran the code, only one instance was shown. I thought that it should be easy, but I failed. Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <GL/glut.h>
#include <vector>
#include <fstream>
#include <string>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <vector>
#define WIDTH 1280
#define HEIGHT 720
static const std::string vertexShader =
"#version 330 core\n"
"in vec3 position;\n"
"in vec3 color;\n"
"in ivec3 Glob_pos;\n"
"uniform mat4 MVP;\n"
"out vec3 ToFragColor;\n"
"void main(){\n"
" gl_Position = MVP * vec4(vec3(Glob_pos) + position,1.0);\n"
" ToFragColor = color;\n"
"}\n";
static const std::string fragmentShader =
"#version 330 core\n"
"in vec3 ToFragColor;\n"
"uniform vec3 Cam;\n"
"out vec3 out_color;\n"
"void main(){\n"
" out_color = ToFragColor;\n"
"}\n";
static const GLfloat CUBE_VERT[12*3*2*3] = {
-1.0f,-1.0f,-1.0f, 1.0f, 0.0f, 1.0f,
-1.0f,-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
-1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 1.0f,-1.0f, 1.0f, 1.0f, 1.0f,
-1.0f,-1.0f,-1.0f, 0.0f, 0.0f, 1.0f,
-1.0f, 1.0f,-1.0f, 0.0f, 1.0f, 1.0f,
1.0f,-1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
-1.0f,-1.0f,-1.0f, 0.0f, 0.0f, 0.0f,
1.0f,-1.0f,-1.0f, 1.0f, 0.0f, 0.0f,
1.0f, 1.0f,-1.0f, 1.0f, 1.0f, 1.0f,
1.0f,-1.0f,-1.0f, 1.0f, 0.0f, 1.0f,
-1.0f,-1.0f,-1.0f, 0.0f, 0.0f, 1.0f,
-1.0f,-1.0f,-1.0f, 1.0f, 0.0f, 1.0f,
-1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
-1.0f, 1.0f,-1.0f, 1.0f, 1.0f, 1.0f,
1.0f,-1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
-1.0f,-1.0f, 1.0f, 0.0f, 1.0f, 0.0f,
-1.0f,-1.0f,-1.0f, 0.0f, 0.0f, 0.0f,
-1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
-1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
1.0f,-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
1.0f,-1.0f,-1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 1.0f,-1.0f, 0.0f, 1.0f, 1.0f,
1.0f,-1.0f,-1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
1.0f,-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
//TOP
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f,
1.0f, 1.0f,-1.0f, 1.0f, 0.0f, -1.0f,
-1.0f, 1.0f,-1.0f, 0.0f, 0.0f, -1.0f,
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f,
-1.0f, 1.0f,-1.0f, 0.0f, 0.0f, -1.0f,
-1.0f, 1.0f, 1.0f, 0.0f, 1.0f, -1.0f
};
GLuint LoadShaders();
void setup(GLuint programID);
void render(GLuint programID);
void computeMatricesFromInputs(GLFWwindow* window);
GLuint vao, vbo, ib;
GLuint MatrixID;
GLuint CamID;
//For model view matrix calculation
glm::vec3 CamLoc = glm::vec3(0,0,-5);
glm::mat4 Projection = glm::perspective(glm::radians(45.0f), (float) WIDTH / (float)HEIGHT, 1.0f, 1000.0f);
glm::mat4 View = glm::lookAt(
CamLoc,
glm::vec3(0,0,0),
glm::vec3(0,1,0)
);
glm::mat4 Model = glm::mat4(1.0f);
glm::mat4 mvp = Projection * View * Model;
glm::vec3 direction;
float horizontalAngle = 3.14f;
float verticalAngle = 0.0f;
float initialFoV = 45.0f;
float speed = 3.0f;
float mouseSpeed = 0.005f;
float mtimeScale = 0.1f;
float ktimeScale = 1.0f;
float FoV = initialFoV; //- 5 * glfwGetMouseWheel();
double lastPos[] = { 0,0 };
const glm::vec3 null = glm::vec3(0,0,0);
//For model view matrix calculation -- end
std::vector<int> instanceObj;
int main(int argc, char **argv){
glutInit(&argc, argv);
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window;
window = glfwCreateWindow(WIDTH, HEIGHT, "DearDaniel's OpenGL", NULL, NULL);
glfwMakeContextCurrent(window);
glewExperimental = true;
glewInit();
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
GLuint programID = LoadShaders();
MatrixID = glGetUniformLocation(programID, "MVP");
CamID = glGetUniformLocation(programID, "Cam");
glEnable (GL_DEPTH_TEST); glDepthFunc (GL_LESS);
glEnable(GL_CULL_FACE); glCullFace(GL_BACK);
glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
setup(programID);
do{
glUseProgram(programID);
computeMatricesFromInputs(window);
render(programID);
glfwSwapBuffers(window);
glfwPollEvents();
} while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS && glfwWindowShouldClose(window) == 0 );
glDeleteProgram(programID);
return 0;
}
GLuint LoadShaders(){
GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
char const * VertexSourcePointer = vertexShader.c_str();
glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL);
glCompileShader(VertexShaderID);
char const * FragmentSourcePointer = fragmentShader.c_str();
glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL);
glCompileShader(FragmentShaderID);
GLuint ProgramID = glCreateProgram();
glAttachShader(ProgramID, VertexShaderID);
glAttachShader(ProgramID, FragmentShaderID);
glLinkProgram(ProgramID);
glDetachShader(ProgramID, VertexShaderID);
glDetachShader(ProgramID, FragmentShaderID);
glDeleteShader(VertexShaderID);
glDeleteShader(FragmentShaderID);
return ProgramID;
}
void setup(GLuint programID) {
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, 12*3*2*3*sizeof(int), CUBE_VERT, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*) 0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
glGenBuffers(1, &ib);
glBindBuffer(GL_ARRAY_BUFFER, ib);
glVertexAttribPointer(2, 3, GL_INT, GL_FALSE, 3 * sizeof( int), (void*) 0);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glVertexAttribDivisor(2, 1);
glBindVertexArray(0);
}
void render(GLuint programID) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, ib);
instanceObj.clear();
for (int i = 0; i < 32; i+=2)
for (int j = 0; j < 32; j +=2)
for (int k = 0; k < 32; k +=2) {
instanceObj.push_back(i);
instanceObj.push_back(j);
instanceObj.push_back(k);
}
glBufferData(GL_ARRAY_BUFFER, sizeof(int)*instanceObj.size(), &instanceObj[0], GL_STATIC_DRAW);
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &mvp[0][0]);
glUniform3f(CamID, CamLoc.x, CamLoc.y, CamLoc.z);
glDrawArraysInstanced(GL_TRIANGLES, 0, 36, 16*16*16);
glBindVertexArray(0);
}
void computeMatricesFromInputs(GLFWwindow* window){
static double lastTime = glfwGetTime();
double currentTime = glfwGetTime();
float deltaTime = float(currentTime - lastTime);
double xpos, ypos;
glfwGetCursorPos(window, &xpos, &ypos);
float hori = horizontalAngle + mouseSpeed * float( xpos - lastPos[0] ) * mtimeScale;
float vert = verticalAngle + mouseSpeed * float( ypos - lastPos[1] ) * mtimeScale;
horizontalAngle = hori;
if (vert > -3.14f/2.0f && vert < 3.14f/2.0f) verticalAngle = vert;
lastPos[0] = xpos;
lastPos[1] = ypos;
direction = glm::vec3 (
cos(verticalAngle) * sin(horizontalAngle),
sin(verticalAngle),
cos(verticalAngle) * cos(horizontalAngle)
);
glm::vec3 right = glm::vec3(
sin(horizontalAngle - 3.14f/2.0f),
0,
cos(horizontalAngle - 3.14f/2.0f)
);
glm::vec3 up = glm::cross( right, direction );
if (glfwGetKey( window, GLFW_KEY_UP ) == GLFW_PRESS) CamLoc += direction * deltaTime * speed * ktimeScale;
if (glfwGetKey( window, GLFW_KEY_DOWN ) == GLFW_PRESS) CamLoc -= direction * deltaTime * speed * ktimeScale;
if (glfwGetKey( window, GLFW_KEY_RIGHT ) == GLFW_PRESS) CamLoc += right * deltaTime * speed * ktimeScale;
if (glfwGetKey( window, GLFW_KEY_LEFT ) == GLFW_PRESS) CamLoc -= right * deltaTime * speed * ktimeScale;
Projection = glm::perspective(glm::radians(FoV), 4.0f / 3.0f, 0.1f, 100.0f);
View = glm::lookAt(
CamLoc, // Camera is here
CamLoc+direction, // and looks here : at the same position, plus "direction"
up // Head is up (set to 0,-1,0 to look upside-down)
);
lastTime = currentTime;
mvp = Projection * View;
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
printf("%f ", mvp[i][j]);
}
printf("\n");
}
}
I used the following command to compile my code:
g++ miniGL.cpp -Wall -std=c++11 -L/usr/local/lib -pthread -lGLEW -lGLU -lGL -lglut -lglfw3 -ldl -lrt -lXrandr -lXxf86vm -lXi -lXinerama -lX11 -lXcursor -lglfw -o ogl
I was meant to render 16*16*16 cubes onto the screen, but only one has shown. I spent more than ten hours for debugging. Now I gave up and shamelessly seeking for help.
You have to use glVertexAttribIPointer, when defining the array of generic vertex attribute data, for the vertex attrbute in ivec3 Glob_pos;.
glVertexAttribPointer is for floating point attributes only (integral data will be converted to floating point).
See the Khronos group reference page for glVertexAttribPointer:
For glVertexAttribPointer, if normalized is set to GL_TRUE, it indicates that values stored in an integer format are to be mapped to the range [-1,1] (for signed values) or [0,1] (for unsigned values) when they are accessed and converted to floating point. Otherwise, values will be converted to floats directly without normalization.
For glVertexAttribIPointer, only the integer types GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_INT, GL_UNSIGNED_INT are accepted. Values are always left as integer values.
Note, probably Glob_pos is never set and has always the same, but undefined value.
Since you don't use glGetAttribLocation to get the attribute indices for the vertex attributes (position, color, Glob_pos), you should use Layout Qualifiers:
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 color;
layout (location = 2) in ivec3 Glob_pos;
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'm trying to draw a cube on OpenGL.
When I compile and run this code, all I see is a black window. Which part of my
code causes this problem? Any help would be appreciated as I am very new to opengl
Here is my source file:
#include <GL/glew.h>
#include <GL/glfw.h>
#include <iostream>
#include <cmath>
void drawCube() {
//vertices of the triangle
GLfloat vertices[] = {
-1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f,
1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f,
-1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f
};
//colors of the triangle
GLfloat colors[] = {
0.410f, 0.481f, 0.675f,
0.177f, 0.823f, 0.970f,
0.604f, 0.516f, 0.611f,
0.676f, 0.779f, 0.331f,
0.179f, 0.275f, 0.338f,
0.041f, 0.616f, 0.984f,
0.799f, 0.315f, 0.460f,
0.945f, 0.719f, 0.295f
};
static float alpha = 0;
//attempt to rotate cube
glRotatef(alpha, 0, 1, 0);
/* We have a color array and a vertex array */
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertices);
glColorPointer(3, GL_FLOAT, 0, colors);
/* Send data : 24 vertices */
glDrawArrays(GL_TRIANGLES, 0, 24);
/* Cleanup states */
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
alpha += 1;
};
int main() {
if (!glfwInit()) {
std::cerr << "Unable to initialize OpenGL!\n";
return -1;
}
if (!glfwOpenWindow(1024, 768, //width and height of the screen
8, 8, 8, 0, //Red, Green, Blue and Alpha bits
0, 0, //Depth and Stencil bits
GLFW_WINDOW)) {
std::cerr << "Unable to create OpenGL window.\n";
glfwTerminate();
return -1;
}
glfwSetWindowTitle("GLFW Simple Example");
// Ensure we can capture the escape key being pressed below
glfwEnable(GLFW_STICKY_KEYS);
do {
GLint width, height;
// Get window size (may be different than the requested size)
//we do this every frame to accommodate window resizing.
glfwGetWindowSize(&width, &height);
glViewport(0, 0, width, height);
glEnable(GL_DEPTH_TEST); // Depth Testing
glDepthFunc(GL_LEQUAL);
glDisable(GL_CULL_FACE);
glCullFace(GL_BACK);
glfwSwapInterval(1);
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION_MATRIX);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW_MATRIX);
glTranslatef(0, 0, -5);
gluPerspective(60, (double)width / (double)height, 0.1, 100);
drawCube();
//VERY IMPORTANT: displays the buffer to the screen
glfwSwapBuffers();
} while (glfwGetKey(GLFW_KEY_ESC) != GLFW_PRESS &&
glfwGetWindowParam(GLFW_OPENED));
glfwTerminate();
return 0;
}
The problem is that you don't use a perspective projection, so you are basically seeing one face of the cube in an orthogonal view.
To use perspective, you can use gluPerspective:
glMatrixMode(GL_PROJECTION_MATRIX);
glLoadIdentity();
gluPerspective(60, (double)width / (double)height, 0.1, 100); // Set up perspective matrix.