#include <GL\glew.h>
#include <GLFW\glfw3.h>
#include <iostream>
// GLM library
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
using namespace std;
int width, height;
// Draw Primitive(s)
void draw() {
GLenum mode = GL_TRIANGLES;
GLsizei indices = 6;
glDrawElements(mode, indices, GL_UNSIGNED_BYTE, nullptr);
}
// Create and Compile Shaders
static GLuint CompileShader(const string& source, GLuint shaderType) {
// Create Shader Object
GLuint shaderID = glCreateShader(shaderType);
const char* src = source.c_str();
// Attach source code to Shader object
glShaderSource(shaderID, 1, &src, nullptr);
// Compile Shader
glCompileShader(shaderID);
// Return ID of Compiled shader
return shaderID;
}
// Create Program Object
static GLuint CreateShaderProgram(const string& vertexShader, const string& fragmentShader) {
// Compile vertex shader
GLuint vertexShaderComp = CompileShader(vertexShader, GL_VERTEX_SHADER);
// Compile fragment shader
GLuint fragmentShaderComp = CompileShader(fragmentShader, GL_FRAGMENT_SHADER);
// Create program object
GLuint shaderProgram = glCreateProgram();
// Attch vertex and fragment shaders to program object
glAttachShader(shaderProgram, vertexShaderComp);
glAttachShader(shaderProgram, fragmentShaderComp);
// Link shaders to create executable
glLinkProgram(shaderProgram);
// Delete compiled vertex and fragment shaders
glDeleteShader(vertexShaderComp);
glDeleteShader(fragmentShaderComp);
// Return Shader Program
return shaderProgram;
}
int main(void) {
width = 640; height = 480;
GLFWwindow* window;
// Initialize the library
if (!glfwInit())
return -1;
// Create a windowed mode window and its OpenGL context
window = glfwCreateWindow(width, height, "Main Window", NULL, NULL);
if (!window) {
glfwTerminate();
return -1;
}
// Make the window's context current
glfwMakeContextCurrent(window);
// Initialize GLEW
if (glewInit() != GLEW_OK)
cout << "Error!" << endl;
GLfloat vertices[] = {
// Triangle 1
-0.5, -0.5, 0.0, // vert 0
1.0, 0.0, 0.0, // red
-0.5, 0.5, 0.0, // vert 1
0.0, 1.0, 0.0, // green
0.5, -0.5, 0.0, // vert 2
0.0, 0.0, 1.0, // blue
// Part of Triangle 2
0.5, 0.5, 0.0, // vert 3
1.0, 0.0, 1.0 // purple
};
// Define element indices
GLubyte indices[] = {
0,1,2,
1,2,3
};
GLuint VBO, EBO, VAO;
glGenBuffers(1, &VBO); // Create VBO and returns ID
glGenBuffers(1, &EBO); // Create EBO
glGenVertexArrays(1, &VAO); // Create VAO
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO); // Select VBO and activate buffer
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); // Select EBO
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); // Load vertex attributes
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); // Load indices attributes
// Specify attributes location and layout to GPU
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
// Color attribute location and layout
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
glBindVertexArray(0);
// Vertex shader source code
string vertexShaderSource =
"#version 330 core\n"
"layout(location = 0) in vec4 vPosition;"
"layout(location = 1) in vec4 aColor;"
"out vec4 oColor;"
"uniform mat4 model;"
"void main()\n"
"{\n"
"gl_Position = model * vPosition;"
"oColor = aColor;"
"}\n";
// Fragment shader source code
string fragmentShaderSource =
"#version 330 core\n"
"in vec4 oColor;"
"out vec4 fragColor;"
"void main()\n"
"{\n"
"fragColor = oColor;"
"}\n";
// Creating Shader Program
GLuint shaderProgram = CreateShaderProgram(vertexShaderSource, fragmentShaderSource);
while (!glfwWindowShouldClose(window)) {
// Resize window and graphics simultaneously
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
// Render here
glClear(GL_COLOR_BUFFER_BIT);
// Use Shader Program exe and select VAO before drawing
glUseProgram(shaderProgram); // Call Shader per-frame when updating attributes
// Declare identity matrix
glm::mat4 modelMatrix;
// Initialize transforms
modelMatrix = glm::translate(modelMatrix, glm::vec3(0.0f, 0.0f, 0.0f));
modelMatrix = glm::rotate(modelMatrix, 45.0f, glm::vec3(0.0f, 0.0f, 1.0f));
modelMatrix = glm::scale(modelMatrix, glm::vec3(0.5f, 0.5f, 0.5f));
// Select transform and sent to shader
GLuint modelLoc = glGetUniformLocation(shaderProgram, "model");
glBindVertexArray(VAO); // User-defined VAO must be called before draw
// Draw primitive(s)
draw();
// Unbind Shader exe and VOA after drawing per frame
glBindVertexArray(0); // In case different VAO will be used after
glUseProgram(0); // In case different shader will be used after
// Pass transform to Shader
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(modelMatrix));
glBindVertexArray(VAO);
// Swap front and back buffers
glfwSwapBuffers(window);
// Poll for and process events
glfwPollEvents();
}
glfwTerminate();
return 0;
}
I am trying to develop OpenGL code that uses shaders to render shapes. Within my Vertex Shader, whenever I add "uniform mat4 model;" and "gl_Position = model * vPosition;" my code stops rendering a shape. But when I remove "uniform mat4 model;" and take away "model from "gl_Position = model * vPosition;" it doesn't render anything. Why is this?
The modelMatrix
is not initialized. This uninitialized matrix is used in the subsequent transformation functions. You have to initialize the matrix with the Identity matrix. This can be done with a single argument 1.0:
glm::mat4 modelMatrix;
glm::mat4 modelMatrix(1.0f);
glUniform*
sets a value of a uniform in the default uniform block of the currently installed program. Therefore the program has to be installed with glUseProgram
when glUniformMatrix4fv
is called. Actually there is no need to uninstall the program with glUseProgram(0);
and you have to set the uniform before drawing the object:
glm::mat4 modelMatrix(1.0f);
modelMatrix = glm::translate(modelMatrix, glm::vec3(0.0f, 0.0f, 0.0f));
modelMatrix = glm::rotate(modelMatrix, 45.0f, glm::vec3(0.0f, 0.0f, 1.0f));
modelMatrix = glm::scale(modelMatrix, glm::vec3(0.5f, 0.5f, 0.5f));
GLuint modelLoc = glGetUniformLocation(shaderProgram, "model");
glUseProgram(shaderProgram);
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(modelMatrix));
glBindVertexArray(VAO);
draw();