Skip to content

Instantly share code, notes, and snippets.

@hahuang65
Last active March 15, 2016 16:14
Show Gist options
  • Save hahuang65/1ffd2752ea0f637550bd to your computer and use it in GitHub Desktop.
Save hahuang65/1ffd2752ea0f637550bd to your computer and use it in GitHub Desktop.
Beginning OpenGL Development: Abstracting Shaders Post 2 - 5/23/2014
#version 410 core
out vec4 color;
void main(void)
{
color = vec4(0.0, 0.8, 1.0, 1.0);
}
#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "shader.h"
// Define some of the global variables we're using for this sample
GLuint program;
GLuint vao;
// This is the callback we'll be registering with GLFW for errors.
// It'll just print out the error to the STDERR stream.
void error_callback(int error, const char* description) {
fputs(description, stderr);
}
// This is the callback we'll be registering with GLFW for keyboard handling.
// The only thing we're doing here is setting up the window to close when we press ESC
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() {
// Initialize GLFW, and if it fails to initialize for any reason, print it out to STDERR.
if (!glfwInit()) {
fprintf(stderr, "Failed initialize GLFW.");
exit(EXIT_FAILURE);
}
// Set the error callback, as mentioned above.
glfwSetErrorCallback(error_callback);
// Set up OpenGL options.
// Use OpenGL verion 4.1,
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
// GLFW_OPENGL_FORWARD_COMPAT specifies whether the OpenGL context should be forward-compatible, i.e. one where all functionality deprecated in the requested version of OpenGL is removed.
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
// Indicate we only want the newest core profile, rather than using backwards compatible and deprecated features.
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// Make the window resize-able.
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
// Create a window to put our stuff in.
GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL", NULL, NULL);
// If the window fails to be created, print out the error, clean up GLFW and exit the program.
if(!window) {
fprintf(stderr, "Failed to create GLFW window.");
glfwTerminate();
exit(EXIT_FAILURE);
}
// Use the window as the current context (everything that's drawn will be place in this window).
glfwMakeContextCurrent(window);
// Set the keyboard callback so that when we press ESC, it knows what to do.
glfwSetKeyCallback(window, key_callback);
printf("OpenGL version supported by this platform (%s): \n", glGetString(GL_VERSION));
// Makes sure all extensions will be exposed in GLEW and initialize GLEW.
glewExperimental = GL_TRUE;
glewInit();
// THIS IS THE SECTION THAT CHANGED:
GL::Shader vertex = GL::Shader(GL_VERTEX_SHADER, "vertex.shader");
GL::Shader fragment = GL::Shader(GL_FRAGMENT_SHADER, "fragment.shader");
// This next section we'll generate the OpenGL program and attach the shaders to it so that we can render our triangle.
program = glCreateProgram();
vertex.attachTo(program);
fragment.attachTo(program);
// END CHANGES IN FILE.
glLinkProgram(program);
// Generate vertex arrays for our program. More explanation on this will come in the future.
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// We'll specify that we want to use this program that we've attached the shaders to.
glUseProgram(program);
// This is our render loop. As long as our window remains open (ESC is not pressed), we'll continue to render things.
while(!glfwWindowShouldClose(window))
{
// Set up our green background color
static const GLfloat green[] = { 0.0f, 0.25f, 0.0f, 1.0f };
// Clear the entire buffer with our green color (sets the background to be green).
glClearBufferfv(GL_COLOR, 0, green);
// Draw our triangles
glDrawArrays(GL_TRIANGLES, 0, 3);
// Swap the buffers so that what we drew will appear on the screen.
glfwSwapBuffers(window);
glfwPollEvents();
}
// Program clean up when the window gets closed.
glDeleteVertexArrays(1, &vao);
glDeleteProgram(program);
}
# OBJS specifies which files to compile as part of the project
OBJS = main.cpp util.cpp shader.cpp
# CC specifies which compiler we're using
CC = g++
# INCLUDE_PATHS specifies the additional include paths we'll need
INCLUDE_PATHS = -I/usr/local/include -I/opt/X11/include
# LIBRARY_PATHS specifies the additional library paths we'll need
LIBRARY_PATHS = -L/usr/local/lib -I/opt/X11/lib
# COMPILER_FLAGS specifies the additional compilation options we're using
# -w suppresses all warnings
COMPILER_FLAGS = -w
# LINKER_FLAGS specifies the libraries we're linking against
# Cocoa, IOKit, and CoreVideo are needed for static GLFW3.
LINKER_FLAGS = -framework OpenGL -lglfw3 -lglew
# OBJ_NAME specifies the name of our exectuable
OBJ_NAME = main
#This is the target that compiles our executable
all : $(OBJS)
$(CC) $(OBJS) $(INCLUDE_PATHS) $(LIBRARY_PATHS) $(COMPILER_FLAGS) $(LINKER_FLAGS) -o $(OBJ_NAME)
#include "shader.h"
namespace GL {
// Public
Shader::Shader(GLenum type, char* location) {
_handle = glCreateShader(type);
GLchar* src = Util::fileToBuffer(location);
glShaderSource(_handle, 1, (const GLchar**)&src, NULL);
printf("Compiling Shader: %s ID: %i\n", location, _handle);
glCompileShader(_handle);
if (status() == GL_FALSE) {
logError(location);
}
}
GLuint Shader::getHandle() {
return _handle;
}
GLint Shader::status() {
GLint status;
glGetShaderiv(_handle, GL_COMPILE_STATUS, &status);
return status;
}
void Shader::attachTo(GLuint programId) {
printf("Attaching shader: %i to program: %i\n", _handle, programId);
glAttachShader(programId, _handle);
}
void Shader::detachFrom(GLuint programId) {
printf("Detaching shader: %i from program: %i\n", _handle, programId);
glDetachShader(programId, _handle);
printf("Deleting shader: %i\n", _handle);
glDeleteShader(_handle);
}
// END Public
// Private
void Shader::logError(char* location) {
GLint infoLogLength;
glGetShaderiv(_handle, GL_INFO_LOG_LENGTH, &infoLogLength);
GLchar *strInfoLog = new GLchar[infoLogLength + 1];
glGetShaderInfoLog(_handle, infoLogLength, NULL, strInfoLog);
fprintf(stderr, "Shader Compile failure in %s:\n%s\n", location, strInfoLog);
delete[] strInfoLog;
}
// END Private
}
#ifndef SHADER_H
#define SHADER_H
#include <GL/glew.h>
#include "Util.h"
namespace GL {
class Shader {
public:
Shader(GLenum shaderType, char* shaderLocation);
GLuint getHandle(); // Returns the ID referring to this shader in the GL.
GLint status(); // Returns the status of compiling the shader.
void attachTo(GLuint programId); // Attaches the shader to a GL program.
void detachFrom(GLuint programId); // Detaches the shader from a GL program.
private:
GLuint _handle;
void logError(char* location);
};
}
#endif
#include "util.h"
namespace Util {
char* fileToBuffer(char *file)
{
FILE *fptr;
long length;
char *buf;
fptr = fopen(file, "rb"); /* Open file for reading */
if (!fptr) /* Return NULL on failure */
return NULL;
fseek(fptr, 0, SEEK_END); /* Seek to the end of the file */
length = ftell(fptr); /* Find out how many bytes into the file we are */
buf = (char*)malloc(length+1); /* Allocate a buffer for the entire length of the file and a null terminator */
fseek(fptr, 0, SEEK_SET); /* Go back to the beginning of the file */
fread(buf, length, 1, fptr); /* Read the contents of the file in to the buffer */
fclose(fptr); /* Close the file */
buf[length] = 0; /* Null terminator */
return buf; /* Return the buffer */
}
}
#include <stdlib.h>
#include <stdio.h>
namespace Util {
char* fileToBuffer(char *file);
}
#version 410 core
void main(void)
{
const vec4 vertices[] = vec4[](vec4( 0.25, -0.25, 0.5, 1.0),
vec4(-0.25, -0.25, 0.5, 1.0),
vec4( 0.25, 0.25, 0.5, 1.0));
gl_Position = vertices[gl_VertexID];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment