I can't seem to figure out how to add camera movement with WASD and mouse movement. Any directions or help?
I've attached my code below:
#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>
#define STB_IMAGE_IMPLEMENTATION
#include <stb-master/stb_image.h> // Image loading Utility functions
#include "meshes.h"
// Uses the standard namespace for debug output
using namespace std;
// Unnamed namespace for C++ defines //
namespace
{
// Macro for OpenGL window title
const char* const WINDOW_TITLE = "CS330 - Ice Cream";
// Variables for window width and height
const int WINDOW_WIDTH = 800;
const int WINDOW_HEIGHT = 800;
// Main GLFW window
GLFWwindow* gWindow = nullptr;
// Shader program
GLuint gProgramId1;
GLuint gProgramId2;
// Texture Ids
GLuint gTextureId;
Meshes meshes;
// Front Camera
glm::vec3 cameraPos;
glm::vec3 cameraFront;
glm::vec3 cameraUp;
GLuint gCurrentCameraIndex = 1;
GLfloat gCameraZoom = 45.0f;
GLuint gCameraOrtho = 0;
// timing
float deltaTime = 0.0f; // time between current frame and last frame
float lastFrame = 0.0f;
}
// User-defined Function prototypes //
bool Initialize(int, char* [], GLFWwindow** window);
void ProcessInput(GLFWwindow* window);
void Render();
bool CreateShaderProgram(const char* vtxShaderSource, const char* fragShaderSource, GLuint& programId);
void DestroyShaderProgram(GLuint programId);
bool CreateTexture(const char* filename, GLuint& textureId);
void DestroyTexture(GLuint textureId);
// Shader program Macro //
#ifndef GLSL
#define GLSL(Version, Source) "#version " #Version " core \n" #Source
#endif
// Vertex Shader Source Code //
const GLchar* vertexShaderSource1 = GLSL(440,
// Load vertex data from VBO location 0
layout(location = 0) in vec3 vertex;
// Load vertex normal data from VBO location 1
layout(location = 1) in vec3 vertexNormal;
// Load texture coordinate data from VBO location 2
layout(location = 2) in vec2 textureCoordinate;
// Output vertex normal values to fragment shader
out vec3 vs_vertexNormal;
// Output texture coordinates to fragment shader
out vec2 vs_textureCoordinate;
//Global variables for the model-view-projection
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
// Transforms vertices to clip coordinates
gl_Position = projection * view * model * vec4(vertex, 1.0f);
vs_textureCoordinate = textureCoordinate;
vs_vertexNormal = vertexNormal;
}
);
// Fragment Shader Source Code //
const GLchar* fragmentShaderSource1 = GLSL(440,
// Vertex normal from vertex shader
in vec3 vs_vertexNormal;
// Texture coordinates from vertex shader
in vec2 vs_textureCoordinate;
// Fragment output color
out vec4 fragmentColor;
// Texture image data passed in from outside shader
uniform sampler2D uTextureBase;
uniform vec2 uvScale;
uniform bool ubHasTexture;
uniform vec4 uCustomColor;
void main()
{
// if a texture is passed in, go ahead and use it
if (ubHasTexture)
fragmentColor = texture(uTextureBase, vs_textureCoordinate);// *uvScale);
else // otherwise just use preset color
fragmentColor = uCustomColor;
}
);
// main function. Entry point to the OpenGL program //
int main(int argc, char* argv[])
{
if (!Initialize(argc, argv, &gWindow))
return EXIT_FAILURE;
// Create the mesh, send data to VBO
meshes.CreateMeshes();
// Create the shader program
if (!CreateShaderProgram(vertexShaderSource1, fragmentShaderSource1, gProgramId1))
return EXIT_FAILURE;
// Load texture data from file
//const char * texFilename1 = "../../resources/textures/blue_granite.jpg";
//if (!CreateTexture(texFilename1, gTextureIdBlue))
//{
// cout << "Failed to load texture " << texFilename1 << endl;
// return EXIT_FAILURE;
//}
// Activate the program that will reference the texture
glUseProgram(gProgramId1);
// We set the texture as texture unit 0
glUniform1i(glGetUniformLocation(gProgramId1, "uTextureBase"), 0);
// Sets the background color of the window to black (it will be implicitely used by glClear)
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
// Set the camera parameters
cameraPos = glm::vec3(0.0f, .75f, 4.0f);
cameraFront = glm::vec3(0.0f, 0.0f, -2.0f);
cameraUp = glm::vec3(0.0f, 1.0f, 0.0f);
// Render loop
while (!glfwWindowShouldClose(gWindow))
{
// Process keyboard input before rendering
ProcessInput(gWindow);
// Render this frame
Render();
glfwPollEvents();
}
// Release mesh data
meshes.DestroyMeshes();
// Release shader program
DestroyShaderProgram(gProgramId1);
// Release the textures
//DestroyTexture(gTextureId);
exit(EXIT_SUCCESS); // Terminates the program successfully
}
// Initialize GLFW, GLEW, and create a window //
bool Initialize(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);
// GLFW: create OpenGL output window, return error if fails
*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;
}
// Set the context for the current window
glfwMakeContextCurrent(*window);
// GLEW: initialize
// ----------------
// Note: if using GLEW version 1.13 or earlier
glewExperimental = GL_TRUE;
GLenum GlewInitResult = glewInit();
// If init fails, output error string, return error
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 keyboard input
void ProcessInput(GLFWwindow* window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
float cameraSpeed = static_cast<float>(2.5 * deltaTime);
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
cameraPos += cameraSpeed * cameraFront;
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
cameraPos -= cameraSpeed * cameraFront;
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
cameraPos -= glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed;
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
cameraPos += glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed;
}
// Render the next frame to the OpenGL viewport //
void Render()
{
GLuint uHasTextureLoc;
bool ubHasTextureVal;
GLuint uCustomColorLoc;
glm::mat4 scale;
glm::mat4 rotation;
glm::mat4 translation;
glm::mat4 view;
glm::mat4 projection;
glm::mat4 model;
GLint modelLoc;
GLint viewLoc;
GLint projLoc;
// Enable z-depth
glEnable(GL_DEPTH_TEST);
// Clear the background
glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Set the current view and projection values
view = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp);
projection = glm::perspective(glm::radians(gCameraZoom), (GLfloat)WINDOW_WIDTH / (GLfloat)WINDOW_HEIGHT, 0.1f, 1000.0f);
//projection = glm::ortho(-2.0f, 2.0f, -2.0f, 2.0f, 0.1f, 1000.0f);
// Set the program to be used
glUseProgram(gProgramId1);
// Get the has texture location
uHasTextureLoc = glGetUniformLocation(gProgramId1, "ubHasTexture");
// Get the custom color location
uCustomColorLoc = glGetUniformLocation(gProgramId1, "uCustomColor");
ubHasTextureVal = false;
glUniform1i(uHasTextureLoc, ubHasTextureVal);
// Retrieves and passes transform matrices to the Shader program
modelLoc = glGetUniformLocation(gProgramId1, "model");
viewLoc = glGetUniformLocation(gProgramId1, "view");
projLoc = glGetUniformLocation(gProgramId1, "projection");
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
// Bottom of bowl
glBindVertexArray(meshes.gCylinderMesh.vao);
// Set the mesh transfomation values
scale = glm::scale(glm::vec3(0.3f, 0.08f, 0.3f));
rotation = glm::rotate(0.0f, glm::vec3(1.0f, 1.0f, 1.0f));
translation = glm::translate(glm::vec3(0.0f, 0.0f, 0.0f));
model = translation * rotation * scale;
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
// Set the custom color before drawing
glUniform4fv(uCustomColorLoc, 1, glm::value_ptr(glm::vec4(0.87f, 0.87f, 0.69f, 1.0f)));
// glDrawArrays(GL_TRIANGLE_FAN, 0, 36); //bottom
// glDrawArrays(GL_TRIANGLE_FAN, 36, 72); //top
glDrawArrays(GL_TRIANGLE_STRIP, 72, 146); //sides
// Deactivate the Vertex Array Object
glBindVertexArray(0);
// Bowl
glBindVertexArray(meshes.gSphereMesh.vao);
// Set the mesh transfomation values
scale = glm::scale(glm::vec3(1.0f, 0.4f, 1.0f));
rotation = glm::rotate(3.142f, glm::vec3(1.0f, 0.0f, 0.0f));
translation = glm::translate(glm::vec3(0.0f, 0.42f, 0.0f));
model = translation * rotation * scale;
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
// Set the custom color before drawing
glUniform4fv(uCustomColorLoc, 1, glm::value_ptr(glm::vec4(0.87f, 0.87f, 0.69f, 1.0f)));
glDrawElements(GL_TRIANGLES, 720, GL_UNSIGNED_INT, (void*)0);
// Deactivate the Vertex Array Object
glBindVertexArray(0);
// Table
glBindVertexArray(meshes.gPlaneMesh.vao);
// Set the mesh transfomation values
scale = glm::scale(glm::vec3(2.0f, 2.0f, 2.0f));
rotation = glm::rotate(0.0f, glm::vec3(1.0f, 1.0f, 1.0f));
translation = glm::translate(glm::vec3(0.0f, -0.02f, 0.0f));
model = translation * rotation * scale;
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
// Set the custom color before drawing
glUniform4fv(uCustomColorLoc, 1, glm::value_ptr(glm::vec4(0.43f, 0.17f, 0.01f, 1.0f)));
glDrawElements(GL_TRIANGLES, meshes.gPlaneMesh.nIndices, GL_UNSIGNED_INT, (void*)0);
// Deactivate the Vertex Array Object
glBindVertexArray(0);
// Ice Cream scoop#1
glBindVertexArray(meshes.gSphereMesh.vao);
// Set the mesh transfomation values
scale = glm::scale(glm::vec3(-0.5f, -0.25f, -0.5f));
rotation = glm::rotate(0.0f, glm::vec3(1.0f, 1.0f, 1.0f));
translation = glm::translate(glm::vec3(-0.25f, 0.5f, 0.0f));
model = translation * rotation * scale;
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
// Set the custom color before drawing
glUniform4fv(uCustomColorLoc, 1, glm::value_ptr(glm::vec4(0.96f, 0.95f, 0.92f, 1.0f)));
glDrawElements(GL_TRIANGLES, meshes.gSphereMesh.nIndices, GL_UNSIGNED_INT, (void*)0);
// Deactivate the Vertex Array Object
glBindVertexArray(0);
// Ice Cream scoop#2
glBindVertexArray(meshes.gSphereMesh.vao);
// Set the mesh transfomation values
scale = glm::scale(glm::vec3(-0.5f, -0.25f, -0.5f));
rotation = glm::rotate(0.0f, glm::vec3(1.0f, 1.0f, 1.0f));
translation = glm::translate(glm::vec3(0.25f, 0.5f, 0.0f));
model = translation * rotation * scale;
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
// Set the custom color before drawing
glUniform4fv(uCustomColorLoc, 1, glm::value_ptr(glm::vec4(0.92f, 0.91f, 0.86f, 1.0f)));
glDrawElements(GL_TRIANGLES, meshes.gSphereMesh.nIndices, GL_UNSIGNED_INT, (void*)0);
// Deactivate the Vertex Array Object
glBindVertexArray(0);
// Flips the the back buffer with the front buffer every frame (refresh)
glfwSwapBuffers(gWindow);
}
//****************************************************
// const char* vtxShaderSource: vertex shader source code
// const char* fragShaderSource: fragment shader source code
// GLuint &programId: unique ID of program associated with shaders
//****************************************************
bool CreateShaderProgram(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);
// Retrieve 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);
// Check for vertex 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, and print compilation errors (if any)
glCompileShader(fragmentShaderId);
// Check for fragment 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);
// Links the shader program
glLinkProgram(programId);
// 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;
}
// Uses the shader program
glUseProgram(programId);
return true;
}
// Destroy the linked shader program //
void DestroyShaderProgram(GLuint programId)
{
glDeleteProgram(programId);
}
// Images are loaded with Y axis going down, but OpenGL's Y axis goes up, so let's flip it //
void flipImageVertically(unsigned char* image, int width, int height, int channels)
{
for (int j = 0; j < height / 2; ++j)
{
int index1 = j * width * channels;
int index2 = (height - 1 - j) * width * channels;
for (int i = width * channels; i > 0; --i)
{
unsigned char tmp = image[index1];
image[index1] = image[index2];
image[index2] = tmp;
++index1;
++index2;
}
}
}
// Generate and load the texture //
bool CreateTexture(const char* filename, GLuint& textureId)
{
/*int width, height, channels;
unsigned char *image = stbi_load(filename, &width, &height, &channels, 0);
if (image)
{
flipImageVertically(image, width, height, channels);
glGenTextures(1, &textureId);
glBindTexture(GL_TEXTURE_2D, textureId);
// set the texture wrapping parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// set texture filtering parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
if (channels == 3)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
else if (channels == 4)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
else
{
cout << "Not implemented to handle image with " << channels << " channels" << endl;
return false;
}
glGenerateMipmap(GL_TEXTURE_2D);
stbi_image_free(image);
glBindTexture(GL_TEXTURE_2D, 0); // Unbind the texture
return true;
}
// Error loading the image*/
return false;
}
// Release the texture attached to textureId //
void DestroyTexture(GLuint textureId)
{
glGenTextures(1, &textureId);
}
This is what I have so far, I just need to be able to rotate around.
Ice Cream
Related
I have been able to create a 3D cube in OpenGL but need assistance with positioning it in the upper left-hand corner of the window. No matter what I try I cannot seem to get the cube in the upper left-hand corner of the window. Currently, the 3D Cube is position close to the center of the window. I have provided the C++ OpenGL code below for reference. Can someone please let me know where I am going wrong?
#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>
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 = "3D Cube"; // 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 vbos[2]; // Handles for the vertex buffer objects
GLuint nIndices; // Number of indices of the mesh
};
// Main GLFW window
GLFWwindow* gWindow = nullptr;
// Triangle mesh data
GLMesh gMesh;
// Shader program
GLuint gProgramId;
}
/* 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 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 implicitely used by glClear)
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
// render loop
// -----------
while (!glfwWindowShouldClose(gWindow))
{
// 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);
// 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)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}
// 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);
}
// 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 2
glm::mat4 scale = glm::scale(glm::vec3(2.0f, 2.0f, 2.0f));
// 2. Rotates shape by 15 degrees in the x axis
glm::mat4 rotation = glm::rotate(45.0f, glm::vec3(2.0f, 2.0f, 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;
// Transforms the camera: move the camera back (z axis)
glm::mat4 view = glm::translate(glm::vec3(0.0f, 0.0f, -5.0f));
// Creates a orthographic projection
glm::mat4 projection = glm::ortho(-5.0f, 5.0f, -5.0f, 5.0f, 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
glDrawElements(GL_TRIANGLES, gMesh.nIndices, GL_UNSIGNED_SHORT, NULL); // Draws the triangle
// 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)
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // Top Right Vertex 0
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, // Bottom Right Vertex 1
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, // Bottom Left Vertex 2
-0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, // Top Left Vertex 3
0.5f, -0.5f, -1.0f, 0.5f, 0.5f, 1.0f, 1.0f, // 4 br right
0.5f, 0.5f, -1.0f, 1.0f, 1.0f, 0.5f, 1.0f, // 5 tl right
-0.5f, 0.5f, -1.0f, 0.2f, 0.2f, 0.5f, 1.0f, // 6 tl top
-0.5f, -0.5f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f // 7 bl back
};
// Index data to share position data
GLushort indices[] = {
0, 1, 3, // Triangle 1
1, 2, 3, // Triangle 2
0, 1, 4, // Triangle 3
0, 4, 5, // Triangle 4
0, 5, 6, // Triangle 5
0, 3, 6, // Triangle 6
4, 5, 6, // Triangle 7
4, 6, 7, // Triangle 8
2, 3, 6, // Triangle 9
2, 6, 7, // Triangle 10
1, 4, 7, // Triangle 11
1, 2, 7 // Triangle 12
};
const GLuint floatsPerVertex = 3;
const GLuint floatsPerColor = 4;
glGenVertexArrays(1, &mesh.vao); // we can also generate multiple VAOs or buffers at the same time
glBindVertexArray(mesh.vao);
// Create 2 buffers: first one for the vertex data; second one for the indices
glGenBuffers(2, mesh.vbos);
glBindBuffer(GL_ARRAY_BUFFER, mesh.vbos[0]); // Activates the buffer
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW); // Sends vertex or coordinate data to the GPU
mesh.nIndices = sizeof(indices) / sizeof(indices[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.vbos[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
// Strides between vertex coordinates is 6 (x, y, z, r, g, b, a). A tightly packed stride is 0.
GLint stride = sizeof(float) * (floatsPerVertex + floatsPerColor);// The number of floats before each
// 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(2, mesh.vbos);
}
// 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;
}
glCompileShader(fragmentShaderId); // compile the fragment shader
// 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);
}
The unit of the angle of glm::rotate is radians, not degrees:
glm::mat4 rotation = glm::rotate(45.0f, glm::vec3(2.0f, 2.0f, 1.0f));
glm::mat4 rotation = glm::rotate(glm::radians(45.0f), glm::vec3(2.0f, 2.0f, 1.0f));
The size of the size of the cube is 1x1x1. The cube is scaled by 2. Because of the orthographic projection
(glm::mat4 projection = glm::ortho(-5.0f, 5.0f, -5.0f, 5.0f, 0.1f, 100.0f);)
the bottom left of the view port is (-5, -5) and the top right is (5, 5).
Because of the orthographic projection and scale, the bottom left corner of the cube is (-1, -1) and the top right corner is (1, 1). If you want to move the cube to the top left, don't rotate the cube, but move it 4 units to the left and 4 units up:
glm::mat4 scale = glm::scale(glm::vec3(2.0f, 2.0f, 2.0f));
glm::mat4 rotation = glm::mat4(1.0f);
glm::mat4 translation = glm::translate(glm::vec3(-4.0f, 4.0f, 0.0f));
glm::mat4 model = translation * rotation * scale;
I am a beginner with OpenGL and C++ and need assistance with implementing a camera into my code, which is below, to move around a 3D cube orbitally. I am unsure as to what else to insert into the code to get the camera to work. The code works but there is no camera movement at this time. I specifically need WASD keys to control the left, right, forward, and backward motions, the QE keys to control the upward and downward movement, and the cursor to control the orientation of the camera. Can someone assist me with what I need to insert into the code to make the camera work?
#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>
#include <learnOpengl/camera.h> // Camera class
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 = "3D Cube w/ Camera Movement"; // 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 vbos[2]; // Handles for the vertex buffer objects
GLuint nIndices; // Number of indices of the mesh
};
// Main GLFW window
GLFWwindow* gWindow = nullptr;
// Triangle mesh data
GLMesh gMesh;
// Shader program
GLuint gProgramId;
}
/* 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 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 implicitely used by glClear)
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
// render loop
// -----------
while (!glfwWindowShouldClose(gWindow))
{
// 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);
// 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)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}
// 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);
}
// 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 2
glm::mat4 scale = glm::scale(glm::vec3(2.0f, 2.0f, 2.0f));
// 2. Rotates shape by 15 degrees in the x axis
glm::mat4 rotation = glm::rotate(45.0f, glm::vec3(2.0f, 2.0f, 1.0f));
// 3. Place object at the origin
glm::mat4 translation = glm::translate(glm::vec3(-1.0f, 1.0f, 0.0f));
// Model matrix: transformations are applied right-to-left order
glm::mat4 model = translation * rotation * scale;
// Transforms the camera: move the camera back (z axis)
glm::mat4 view = glm::translate(glm::vec3(0.0f, 0.0f, -5.0f));
// Creates a orthographic projection
glm::mat4 projection = glm::ortho(-5.0f, 5.0f, -5.0f, 5.0f, 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
glDrawElements(GL_TRIANGLES, gMesh.nIndices, GL_UNSIGNED_SHORT, NULL); // Draws the triangle
// 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)
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // Top Right Vertex 0
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, // Bottom Right Vertex 1
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, // Bottom Left Vertex 2
-0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, // Top Left Vertex 3
0.5f, -0.5f, -1.0f, 0.5f, 0.5f, 1.0f, 1.0f, // 4 br right
0.5f, 0.5f, -1.0f, 1.0f, 1.0f, 0.5f, 1.0f, // 5 tl right
-0.5f, 0.5f, -1.0f, 0.2f, 0.2f, 0.5f, 1.0f, // 6 tl top
-0.5f, -0.5f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f // 7 bl back
};
// Index data to share position data
GLushort indices[] = {
0, 1, 3, // Triangle 1
1, 2, 3, // Triangle 2
0, 1, 4, // Triangle 3
0, 4, 5, // Triangle 4
0, 5, 6, // Triangle 5
0, 3, 6, // Triangle 6
4, 5, 6, // Triangle 7
4, 6, 7, // Triangle 8
2, 3, 6, // Triangle 9
2, 6, 7, // Triangle 10
1, 4, 7, // Triangle 11
1, 2, 7 // Triangle 12
};
const GLuint floatsPerVertex = 3;
const GLuint floatsPerColor = 4;
glGenVertexArrays(1, &mesh.vao); // we can also generate multiple VAOs or buffers at the same time
glBindVertexArray(mesh.vao);
// Create 2 buffers: first one for the vertex data; second one for the indices
glGenBuffers(2, mesh.vbos);
glBindBuffer(GL_ARRAY_BUFFER, mesh.vbos[0]); // Activates the buffer
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW); // Sends vertex or coordinate data to the GPU
mesh.nIndices = sizeof(indices) / sizeof(indices[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.vbos[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
// Strides between vertex coordinates is 6 (x, y, z, r, g, b, a). A tightly packed stride is 0.
GLint stride = sizeof(float) * (floatsPerVertex + floatsPerColor);// The number of floats before each
// 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(2, mesh.vbos);
}
// 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;
}
glCompileShader(fragmentShaderId); // compile the fragment shader
// 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);
}
The following code draws a white square to the screen. If I uncomment the line that uses the program, the square disappears.
When I debug the program with GLIntercept, the texture appears in a folder called Images, and the log says that the shaders compiled. However, it also says that the program links, but doesn't validate.
I've been poring over this for hours and I have no idea where to go from here.
// Vertex.vert
#version 150 core
in vec3 in_position;
in vec2 in_texture;
out vec2 Texture;
uniform mat4 in_model;
uniform mat4 in_view;
uniform mat4 in_projection;
void main()
{
gl_Position = in_projection * in_view * in_model * vec4(in_position, 1.0);
Texture = in_texture;
}
// Fragment.frag
#version 150 core
in vec2 Texture;
out vec4 Colour;
uniform sampler2D Sampler2D;
void main()
{
Colour = texture(Sampler2D, Texture);
}
// Source.cpp
#include <cfloat>
#include <iostream>
#include <string>
#include <vector>
#include <GL/glew.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtx/transform.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include "Archive.h"
using namespace glm;
using namespace sf;
using namespace std;
struct Camera
{
vec3 Position = { 0.0f, 0.0f, 1.0f };
vec3 Target = { 0.0f, 0.0f, 0.0f };
vec3 Up = { 0.0f, 1.0f, 0.0f };
float Fovy = 74.0f;
float Aspect = 16.0f / 9.0f;
float ZNear = FLT_MIN;
float ZFar = FLT_MAX;
mat4 View;
mat4 Projection;
};
struct Actor
{
vec3 Scale = { 1.0f, 1.0f, 1.0f };
vec3 Rotation = { 0.0f, 0.0f, 0.0f };
vec3 Position = { 0.0f, 0.0f, 0.0f };
vector<GLfloat> Vertices;
vector<GLuint> Elements;
GLuint Texture;
Actor(string fileName)
{
Image image;
if (!image.loadFromFile(fileName + ".png"))
{
cerr << "ERROR: Unable to load texture" << endl;
}
glGenTextures(1, &Texture);
glBindTexture(GL_TEXTURE_2D, Texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.getSize().x, image.getSize().y, 0, GL_RGBA, GL_UNSIGNED_BYTE, image.getPixelsPtr());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glGenerateMipmap(GL_TEXTURE_2D);
// Draw a square instead of the actual model
Vertices.push_back(-1.0f); Vertices.push_back(-1.0f); Vertices.push_back(0.0f); Vertices.push_back(0.0f); Vertices.push_back(0.0f);
Vertices.push_back(1.0f); Vertices.push_back(-1.0f); Vertices.push_back(0.0f); Vertices.push_back(1.0f); Vertices.push_back(0.0f);
Vertices.push_back(1.0f); Vertices.push_back(1.0f); Vertices.push_back(0.0f); Vertices.push_back(1.0f); Vertices.push_back(1.0f);
Vertices.push_back(-1.0f); Vertices.push_back(1.0f); Vertices.push_back(0.0f); Vertices.push_back(0.0f); Vertices.push_back(1.0f);
Elements.push_back(0); Elements.push_back(1); Elements.push_back(2);
Elements.push_back(2); Elements.push_back(3); Elements.push_back(0);
}
};
GLuint CreateShader(GLenum shaderType, string fileName, Archive& archive)
{
string source;
archive.open(fileName);
source.resize(archive.getSize());
archive.read(&source[0], archive.getSize());
GLuint shader = glCreateShader(shaderType);
const char* pointer = source.c_str();
glShaderSource(shader, 1, &pointer, nullptr);
glCompileShader(shader);
GLsizei length;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
if (length > 1)
{
GLchar* infoLog = new GLchar[length];
glGetShaderInfoLog(shader, length, &length, infoLog);
cerr << infoLog << endl;
delete[] infoLog;
}
return shader;
}
GLuint CreateProgram(GLuint vertex, GLuint fragment)
{
GLuint program = glCreateProgram();
glAttachShader(program, vertex);
glAttachShader(program, fragment);
glLinkProgram(program);
GLsizei length;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
if (length > 1)
{
GLchar* infoLog = new GLchar[length];
glGetProgramInfoLog(program, length, &length, infoLog);
cerr << infoLog << endl;
delete[] infoLog;
}
return program;
}
int main(int argc, char* argv[])
{
Window window(VideoMode(1920, 1080), "");
window.setVerticalSyncEnabled(true);
if (!window.setActive(true))
{
cerr << "ERROR: Unable to set the window as the current target for OpenGL rendering" << endl;
return 1;
}
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK)
{
cerr << "ERROR: Unable to initialise GLEW" << endl;
return 1;
}
Archive shaders("Shaders.lea");
Archive models("Models.lea");
Actor actor("tree01");
GLuint vertex = CreateShader(GL_VERTEX_SHADER, "Vertex.vert", shaders);
GLuint fragment = CreateShader(GL_FRAGMENT_SHADER, "Fragment.frag", shaders);
GLuint program = CreateProgram(vertex, fragment);
GLuint vertexArray;
GLuint vertexBuffer;
GLuint elementBuffer;
glGenVertexArrays(1, &vertexArray);
glBindVertexArray(vertexArray);
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glGenBuffers(1, &elementBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer);
// glUseProgram(program);
GLint position = glGetAttribLocation(program, "in_position");
glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, 0);
glEnableVertexAttribArray(position);
GLint texture = glGetAttribLocation(program, "in_texture");
glVertexAttribPointer(texture, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, (void*)(sizeof(GLfloat) * 3));
glEnableVertexAttribArray(texture);
GLint projection = glGetUniformLocation(program, "in_projection");
GLint view = glGetUniformLocation(program, "in_view");
GLint model = glGetUniformLocation(program, "in_model");
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
Camera camera;
while (window.isOpen())
{
// Input handling code omitted
camera.View = lookAt(camera.Position, camera.Target, camera.Up);
camera.Projection = perspective(radians(camera.Fovy), camera.Aspect, camera.ZNear, camera.ZFar);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUniformMatrix4fv(projection, 1, GL_FALSE, value_ptr(camera.Projection));
glUniformMatrix4fv(view, 1, GL_FALSE, value_ptr(camera.View));
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * actor.Vertices.size(), &actor.Vertices[0], GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * actor.Elements.size(), &actor.Elements[0], GL_STATIC_DRAW);
mat4 transform = translate(mat4(), actor.Position);
transform *= rotate(transform, actor.Rotation.z, vec3(0.0f, 0.0f, 1.0f));
transform *= rotate(transform, actor.Rotation.y, vec3(0.0f, 1.0f, 0.0f));
transform *= rotate(transform, actor.Rotation.x, vec3(1.0f, 0.0f, 0.0f));
transform *= scale(transform, actor.Scale);
glUniformMatrix4fv(model, 1, GL_FALSE, value_ptr(transform));
glBindTexture(GL_TEXTURE_2D, actor.Texture);
glDrawElements(GL_TRIANGLES, actor.Elements.size(), GL_UNSIGNED_INT, 0);
window.display();
}
glUseProgram(0);
glDisableVertexAttribArray(texture);
glDisableVertexAttribArray(position);
glDeleteBuffers(1, &elementBuffer);
glDeleteBuffers(1, &vertexBuffer);
glDeleteVertexArrays(1, &vertexArray);
glDetachShader(program, fragment);
glDetachShader(program, vertex);
glDeleteShader(fragment);
glDeleteShader(vertex);
glDeleteProgram(program);
return 0;
}
It was a combination of two things.
When I last used this code, it was with GLM 0.9.7.6, and mat4() generated an identity matrix. However, at some point between that version of GLM and the one I'm currently using (0.9.9.5), mat4() started generating an empty matrix. Instead, you need mat4(1.0f).
Also, I used bad values for the near and far planes. I did think that the values I had would work, but clearly I don't quite understand what's going on behind the scenes.
I've looked for an answer to my problem for two days. Maybe I'm just terrible at searching but there doesn't seem to be an answer already out there.
I am trying to draw lines on the screen using OpenGL's glDrawArrays(GL_LINES, ..., ...). This is the current code for my fragment shader:
#version 330 core
in vec4 vertexColor;
out vec4 color;
void main( )
{
//color = vec3(0.5f, 1.0f, 1.0f);
color = vec4(0.5f, 1.0f, 1.0f, 0.5f);
//color = vertexColor;
}
Originally the color=vertexColor line was supposed to work, but nothing appeared on the screen. I thought maybe something was wrong with the data being sent from the vertex shader so I tried setting the output manually in the fragment shader. I accidentally made it a vec3 instead of a vec4 and I got an error in my console window telling me compilation of the shader had failed. But the lines appeared! They showed up in the right spot as white/gray lines of static. When I corrected the mistake and set the output to a vec4, like shown, the lines were invisible again and I had no compilation error.
What am I doing wrong that makes my lines invisible?
Edit:
Here is my first go at a "minimal, complete, and verifiable example". If you link a project with these files to GLEW, GLFW and GLM, this should run on your system. If I'm not supposed to upload a whole program, I apologize. This seems a bit big, but I don't know how else it could be "complete".
Instead of making two white static lines, this one is making only one solid black line when the fragment shader fails to compile. It still renders nothing when compilation is successful.
Main.cpp
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "ShaderMaker.h"
#include "TargetBox.h"
const GLint WIDTH = 800, HEIGHT = 600;
//Camera
glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 0.0f);
glm::vec3 cameraFront = glm::vec3(0.0f, 0.0f, -1.0f);
glm::vec3 cameraUp = glm::vec3(0.0f, 1.0f, 0.0f);
GLfloat yaw = -90.0f;
GLfloat pitch = 0.0f;
// Delta time
GLfloat deltaTime = 0.0f;
GLfloat lastFrame = 0.0f;
int main() {
cameraFront.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch));
cameraFront.y = sin(glm::radians(pitch));
cameraFront.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch));
cameraFront = glm::normalize(cameraFront);
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);
GLFWwindow *window = glfwCreateWindow(WIDTH, HEIGHT, "Debugger", nullptr, nullptr);
int screenWidth, screenHeight;
glfwGetFramebufferSize(window, &screenWidth, &screenHeight);
if (window == nullptr) {
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return EXIT_FAILURE;
}
glfwMakeContextCurrent(window);
glewExperimental = GL_TRUE;
if (GLEW_OK != glewInit()) {
std::cout << "Failed to initialize GLEW" << std::endl;
return EXIT_FAILURE;
}
glViewport(0, 0, screenWidth, screenHeight);
glEnable(GL_DEPTH_TEST);
TargetBox tb;
GLuint modelLoc = tb.getUniform("model");
GLuint viewLoc = tb.getUniform("view");
GLuint projectionLoc = tb.getUniform("projection");
glm::mat4 projection;
projection = glm::perspective(glm::radians(45.0f), (float)screenWidth / screenHeight, 0.1f, 100.0f);
while (!glfwWindowShouldClose(window)) {
GLfloat currentFrame = glfwGetTime();
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
glfwPollEvents();
glClearColor(0.5f, 0.7f, 0.9f, 1.0f); // Unnecessary, but adds some color to an otherwise blank window
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glm::mat4 view;
view = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp);
tb.useShader();
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));
glBindVertexArray(tb.getVAO());
glm::vec3 posMod = tb.getPos();
glm::mat4 model;
model = glm::translate(model, glm::vec3(posMod.x, posMod.y, posMod.z));
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glDrawArrays(GL_LINES, 0, 4);
glBindVertexArray(0);
glfwSwapBuffers(window);
}
glfwTerminate();
return EXIT_SUCCESS;
}
ShaderMaker.h
#pragma once
#ifndef SHADERMAKER_H
#define SHADERMAKER_H
#include<string>
#include<fstream>
#include<sstream>
#include<iostream>
#include<GL/glew.h>
class ShaderMaker {
public:
// The program ID
GLuint Program;
// Constructor reads and builds the shader
ShaderMaker(const GLchar* vertexPath, const GLchar* fragmentPath) {
// 1. Retrieve the vertex/fragment source code from filePath
std::string vertexCode;
std::string fragmentCode;
std::ifstream vShaderFile;
std::ifstream fShaderFile;
// ensures ifstream objects can throw exceptions:
vShaderFile.exceptions(std::ifstream::badbit);
fShaderFile.exceptions(std::ifstream::badbit);
try {
// Open files
vShaderFile.open(vertexPath);
fShaderFile.open(fragmentPath);
std::stringstream vShaderStream, fShaderStream;
// Read file's buffer contents into streams
vShaderStream << vShaderFile.rdbuf();
fShaderStream << fShaderFile.rdbuf();
// close file handlers
vShaderFile.close();
fShaderFile.close();
// Convert stream into GLchar array
vertexCode = vShaderStream.str();
fragmentCode = fShaderStream.str();
}
catch (std::ifstream::failure e) {
std::cout << "ERROR::SHADER::FILE_NOT_SUCCESSFULLY_READ" << std::endl;
}
const GLchar* vShaderCode = vertexCode.c_str();
const GLchar* fShaderCode = fragmentCode.c_str();
// 2. Compile shaders
GLuint fragment;
GLint success;
GLchar infoLog[512];
// Vertex shader
GLuint vertex = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex, 1, &vShaderCode, NULL);
glCompileShader(vertex);
// Print compile errors if any
glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(vertex, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// Similar for fragment shader
fragment = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment, 1, &fShaderCode, NULL);
glCompileShader(fragment);
// Print compile errors if any
glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(fragment, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// Shader program
this->Program = glCreateProgram();
glAttachShader(this->Program, vertex);
glAttachShader(this->Program, fragment);
glLinkProgram(this->Program);
// Print linking errors if any
glGetShaderiv(this->Program, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(this->Program, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
}
// Delete the shaders as they're linked into our program now and no longer necessary
glDeleteShader(vertex);
glDeleteShader(fragment);
}
// Use the program
void Use() { glUseProgram(this->Program); }
// Get a uniform
GLint getUniform(const GLchar * name) {
return glGetUniformLocation(this->Program, name);
}
};
#endif
TargetBox.h
#pragma once
#ifndef TARGETBOX_H
#define TARGETBOX_H
#define GLEW_STATIC
#include <GL/glew.h>
#include<glm/glm.hpp>
#include <GLFW/glfw3.h>
#include "ShaderMaker.h"
class TargetBox
{
public:
TargetBox();
~TargetBox();
void useShader();
GLuint getVAO();
glm::vec3 getPos();
void setPos(glm::vec3 p);
GLuint getUniform(GLchar * u);
private:
glm::vec3 pos;
GLuint VAO, VBO;
const GLchar *vertexShaderPath = ".\\VShaderLine.txt";
const GLchar *fragmentShaderPath = ".\\FShaderLine.txt";
ShaderMaker shader = ShaderMaker(vertexShaderPath, fragmentShaderPath);
};
#endif
TargetBox.cpp
#include "TargetBox.h"
TargetBox::TargetBox()
{
glGenBuffers(1, &VBO);
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
GLfloat vertices[] = {
-2, 0, -5, 1.0f, 1.0f, 1.0f,
2, 0, 5, 1.0f, 1.0f, 1.0f,
2, 0, 5, 1.0f, 0.0f, 0.0f,
2, 10, 5, 0.0f, 1.0f, 0.0f
};
size_t data_len = sizeof(vertices);
glBufferData(GL_ARRAY_BUFFER, data_len, vertices, GL_STATIC_DRAW);
// Position attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid *)0);
glEnableVertexAttribArray(0);
//Color attribute
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
TargetBox::~TargetBox()
{
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
}
void TargetBox::useShader() { shader.Use(); }
GLuint TargetBox::getVAO() { return VAO; }
glm::vec3 TargetBox::getPos() { return pos; }
void TargetBox::setPos(glm::vec3 p) { pos = p; }
GLuint TargetBox::getUniform(GLchar * u) { return shader.getUniform(u); }
VShaderLine.txt
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 color;
out vec4 vertexColor;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main( )
{
// The order of multiplication is important?
gl_Position = projection * view * model * vec4( position, 1.0 );
vertexColor = vec4(color.xyz, 1.0f);
}
FShaderLine.txt
#version 330 core
in vec4 vertexColor;
out vec4 color;
void main( )
{
color = vec3(0.5f, 1.0f, 1.0f);
//color = vec4(0.5f, 1.0f, 1.0f, 0.5f);
//color = vertexColor;
}
I'm taking a Computer Graphics course at my university. I need to implement basic line drawing algorithms in modern OpenGL(3.3+) to draw primitives on the screen. Here's the function for Bresenham's Line Drawing Algorithm that I want to implement -
void bresenham(GLint xStart, GLint yStart, GLint xEnd, GLint yEnd) {
if (!(xStart < xEnd)) {
swap(xStart, xEnd);
swap(yStart, yEnd);
}
GLint dx = xEnd - xStart;
GLint dy = yEnd - yStart;
GLint p = 2 * dy - dx;
GLint x = xStart;
GLint y = yStart;
setPixel(x,y);
while (x < xEnd) {
x += 1;
if (p < 0)
p += (2 * dy);
else {
p += (2 * (dy - dx));
y += 1;
setPixel(x,y);
}
}
}
I'm clueless on how to realise the setPixel() function. Most answers I found here and elsewhere use older OpenGL functions -
void setPixel(int x, int y)
{
glColor3f(0.0, 0.0, 0.0); //Set pixel to black
glBegin(GL_POINTS);
glVertex2i(x, y); //Set pixel coordinates
glEnd();
glFlush(); //Render pixel
}
What is the equivalent way to do this in OpenGl 3.3+?
Assuming I can add the "pixels" to an std::vector array, how do I initialise the vertex buffer array to store this data?
Another problem I ran into while trying to plot a point using GL_POINTS is that due to clipping during conversion to normalised device coordinates, points beyond the range [-1,1] in either direction do not show on the window.
For example, only the first three points show up on the window screen. See the initialize() function -
#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <cstdlib>
#include <vector>
#include <iostream>
#include <fstream>
// Read a shader source from a file
// store the shader source in a std::vector<char>
void read_shader_src(const char* fname, std::vector<char> &buffer);
// Compile a shader
GLuint load_and_compile_shader(const char *fname, GLenum shaderType);
// Create a program from two shaders
GLuint create_program(const char *path_vert_shader, const char *path_frag_shader);
// Render scene
void display(GLuint &vao, GLFWwindow* window);
// Initialize the data to be rendered
void initialize(GLuint &vao);
//GLFW Callbacks
static void error_callback(int error, const char* description) {
fprintf(stderr, "Error: %s\n", description);
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
glfwSetWindowShouldClose(window, GL_TRUE);
}
}
int main() {
glfwSetErrorCallback(error_callback);
//Initialize GLFW
if (!glfwInit()) {
fprintf(stderr, "Failed to initialize GLFW.\n");
return -1;
}
//Set GLFW window settings and create window
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
GLFWwindow* window = glfwCreateWindow(500, 500, "My window", NULL, NULL);
if(!window) {
fprintf(stderr, "Window or context creation failed.\n");
return -1;
}
glfwSetKeyCallback(window, key_callback);
glfwMakeContextCurrent(window);
//Initialize GLEW
glewExperimental = GL_TRUE;
if(glewInit() != GLEW_OK) {
fprintf(stderr, "Failed to initialize glew");
glfwTerminate();
return -1;
}
//Create a vertex array object
GLuint vao;
//Initialize the data to be rendered
initialize(vao);
while (!glfwWindowShouldClose(window)) {
display(vao, window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
//Render scene
void display(GLuint &vao, GLFWwindow* window) {
//Red background
glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(vao);
glDrawArrays(GL_POINTS, 0, 12);
// Swap front and back buffers
glfwSwapBuffers(window);
}
void initialize(GLuint &vao) {
glEnable(GL_PROGRAM_POINT_SIZE);
// Use a Vertex Array Object
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
//Store verex positions in an array
GLfloat vertices[24] = {
0.0, 0.0, // Only these
0.5, 0.5, //three points show up
1.0, 1.0, //on the window screen
4.0, 4.0,
5.0, 5.0,
6.0, 6.0,
7.0, 7.0,
8.0, 8.0,
9.0, 9.0,
10.0, 10.0,
11.0, 11.0,
12.0, 12.0,
};
//Create a vertex buffer object to store the vertex data
GLuint vbo;
//Generates 1 buffer object name and stores it in vbo
glGenBuffers(1, &vbo);
//Bind the buffer object to the buffer binding target
glBindBuffer(GL_ARRAY_BUFFER, vbo);
//Creates and initializes the buffer object's data store(with data from vertices)
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
GLuint shaderProgram = create_program("/Users/.../vert.shader", "/Users/.../frag.shader"); //path to shader files
// Get the location of the attributes that enters in the vertex shader
GLint posAttrib = glGetAttribLocation(shaderProgram, "position");
// Specify how the data for position can be accessed
glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0);
//Enable the attribute
glEnableVertexAttribArray(posAttrib);
}
// Read a shader source from a file
// store the shader source in a std::vector<char>
void read_shader_src(const char *fname, std::vector<char> &buffer) {
std::ifstream in;
in.open(fname, std::ios::binary);
if(in.is_open()) {
// Get the number of bytes stored in this file
in.seekg(0, std::ios::end);
size_t length = (size_t)in.tellg();
// Go to start of the file
in.seekg(0, std::ios::beg);
// Read the content of the file in a buffer
buffer.resize(length + 1);
in.read(&buffer[0], length);
in.close();
// Add a valid C - string end
buffer[length] = '\0';
}
else {
std::cerr << "Unable to open " << fname << " I'm out!" << std::endl;
exit(-1);
}
}
//Compile a shader
GLuint load_and_compile_shader(const char* fname, GLenum shaderType) {
//Load a shader from an external file
std::vector<char> buffer;
read_shader_src(fname, buffer);
const char *src = &buffer[0];
//Create and compile the shader
GLuint shader = glCreateShader(shaderType);
glShaderSource(shader, 1, &src, NULL);
glCompileShader(shader);
GLint shader_compiled;
glGetShaderiv(shader, GL_COMPILE_STATUS, &shader_compiled);
if(!shader_compiled) {
GLchar message[1024];
glGetShaderInfoLog(shader, 1024, NULL, message);
std::cerr << "Shader compilation failed.";
std::cerr << "Log: " << &message << std::endl;
glfwTerminate();
exit(-1);
}
return shader;
}
// Create a program from two shaders
GLuint create_program(const char *path_vert_shader, const char *path_frag_shader) {
// Load and compile the vertex and fragment shaders
GLuint vertexShader = load_and_compile_shader(path_vert_shader, GL_VERTEX_SHADER);
GLuint fragmentShader = load_and_compile_shader(path_frag_shader, GL_FRAGMENT_SHADER);
// Attach the above shader to a program
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
// Flag the shaders for deletion
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
// Link and use the program
glLinkProgram(shaderProgram);
glUseProgram(shaderProgram);
return shaderProgram;
}
What modifications do I make so I can plot the rest of the points?
Vertex Shader -
#version 150 core
in vec4 position;
void main() {
gl_Position = position;
gl_PointSize = 10.0;
}
Fragment Shader -
#version 150 core
out vec4 out_color;
void main() {
out_color = vec4(1.0, 1.0, 1.0, 1.0);
}
From the comments, it sounds like you're trying to use OpenGL in place of a really old graphics library that is required for a class. Since computer graphics have changed so much that what you're trying to do in modern OpenGL is unreasonable, you should try doing this for the current assignment and your later ones:
Disclaimer: This is not a reasonable way to draw a line in modern OpenGL
Create a 2d array of some arbitrary size, large enough that the entire line can be drawn on it.
Draw the line using the original function, create some setPixel function that changes elements in that array
Once you're done drawing the line (or doing whatever else future assignments will have you do), create an OpenGL texture from that array. An excellent guide is available here: https://open.gl/textures
Some rough psuedocode:
GLuint tex;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_FLOAT, pixels);
glBindTexture(GL_TEXTURE_2D, 0);
Then you would create a quad (really just two triangles) that draw this texture to screen. Following the open.gl guide should work well since they already do this for their textures. Pulling from their provided code (which does a bit extra, all correct and following the spec though):
GLfloat vertices[] = {
// Position Color Texcoords
-0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // Top-left
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // Top-right
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // Bottom-right
-0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f // Bottom-left
};
GLuint elements[] = {
0, 1, 2,
2, 3, 0
};
// Set up buffer objects, create shaders, initialize GL, etc.
//drawing
//bind buffers, enable attrib arrays, etc
glBindTexture(GL_TEXTURE_2D, tex);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);