Skip to content

Instantly share code, notes, and snippets.

@ugovaretto
Last active Aug 29, 2015
Embed
What would you like to do?
OpenGL 3.3 core profile - minimal example
//OpenGL scratch - reference implementation of OpenGL >= 3.3 rendering code
//Author: Ugo Varetto
//Requires GLFW and GLM, to deal with the missing support for matrix stack
//in OpenGL >= 3.3
//g++ ../src/12_scratch.cpp \
// -I/usr/local/glfw/include \
// -DGLM_FORCE_RADIANS
// -DGL_GLEXT_PROTOTYPES -L/usr/local/glfw/lib -lglfw \
// -I/usr/local/glm/include \
// -lGL
//clang++ -DGL_GLEXT_PROTOTYPES \
//-L /opt/local/lib -lglfw \
//-I /opt/local/include \
//-framework OpenGL
//-DGLM_FORCE_RADIANS 12_scratch.cpp
#ifdef __APPLE__
#include <OpenGL/gl3.h>
#endif
#include <GLFW/glfw3.h>
// Include GLM
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <cstdlib>
#include <iostream>
#include <vector>
#ifdef USE_DOUBLE
typedef double real_t;
const GLenum GL_REAL_T = GL_DOUBLE;
#else
typedef float real_t;
const GLenum GL_REAL_T = GL_FLOAT;
#endif
#ifdef LOG_
#define gle std::cout << "[GL] - " \
<< __LINE__ << ' ' << glGetError() << std::endl;
#else
#define gle
#endif
//------------------------------------------------------------------------------
GLuint create_program(const char* vertexSrc,
const char* fragmentSrc) {
// Create the shaders
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
GLint res = GL_FALSE;
int logsize = 0;
// Compile Vertex Shader
glShaderSource(vs, 1, &vertexSrc, 0);
glCompileShader(vs);
// Check Vertex Shader
glGetShaderiv(vs, GL_COMPILE_STATUS, &res);
glGetShaderiv(vs, GL_INFO_LOG_LENGTH, &logsize);
if(logsize > 1){
std::vector<char> errmsg(logsize + 1, 0);
glGetShaderInfoLog(vs, logsize, 0, &errmsg[0]);
std::cout << &errmsg[0] << std::endl;
}
// Compile Fragment Shader
glShaderSource(fs, 1, &fragmentSrc, 0);
glCompileShader(fs);
// Check Fragment Shader
glGetShaderiv(fs, GL_COMPILE_STATUS, &res);
glGetShaderiv(fs, GL_INFO_LOG_LENGTH, &logsize);
if(logsize > 1){
std::vector<char> errmsg(logsize + 1, 0);
glGetShaderInfoLog(fs, logsize, 0, &errmsg[0]);
std::cout << &errmsg[0] << std::endl;
}
// Link the program
GLuint program = glCreateProgram();
glAttachShader(program, vs);
glAttachShader(program, fs);
glLinkProgram(program);
// Check the program
glGetProgramiv(program, GL_LINK_STATUS, &res);
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logsize);
if(logsize > 1) {
std::vector<char> errmsg(logsize + 1, 0);
glGetShaderInfoLog(program, logsize, 0, &errmsg[0]);
std::cout << &errmsg[0] << std::endl;
}
glDeleteShader(vs);
glDeleteShader(fs);
return program;
}
//------------------------------------------------------------------------------
void error_callback(int error, const char* description) {
std::cerr << description << std::endl;
}
//------------------------------------------------------------------------------
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);
}
//------------------------------------------------------------------------------
const char fragmentShaderSrc[] =
"#version 330 core\n"
"smooth in vec2 UV;\n"
"out vec3 outColor;\n"
"uniform sampler2D cltexture;\n"
"void main() {\n"
" outColor = texture(cltexture, UV).rrr;\n"
"}";
const char vertexShaderSrc[] =
"#version 330 core\n"
"layout(location = 0) in vec4 pos;\n"
"layout(location = 1) in vec2 tex;\n"
"smooth out vec2 UV;\n"
"uniform mat4 MVP;\n"
"void main() {\n"
" gl_Position = MVP * pos;\n"
" UV = tex;\n"
"}";
//------------------------------------------------------------------------------
int main(int argc, char** argv) {
//USER INPUT
if(argc < 2) {
std::cout << "usage: " << argv[0]
<< " <size>"
<< std::endl;
exit(EXIT_FAILURE);
}
const int SIZE = atoi(argv[1]);
//GRAPHICS SETUP
glfwSetErrorCallback(error_callback);
if(!glfwInit()) {
std::cerr << "ERROR - glfwInit" << std::endl;
exit(EXIT_FAILURE);
}
//WARNING: THIS DOESN'T WORK
// glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
// glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
// glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
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);
#endif
GLFWwindow* window = glfwCreateWindow(640, 480,
"GL 3.3 core", NULL, NULL);
if (!window) {
std::cerr << "ERROR - glfwCreateWindow" << std::endl;
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwSetKeyCallback(window, key_callback);
glfwMakeContextCurrent(window);
std::cout << "OpenGL version: " << glGetString(GL_VERSION) << std::endl;
std::cout << "GLSL version: "
<< glGetString(GL_SHADING_LANGUAGE_VERSION) << std::endl;
std::cout << "Vendor: " << glGetString(GL_VENDOR) << std::endl;
std::cout << "Renderer: " << glGetString(GL_RENDERER) << std::endl;
//GEOMETRY
//geometry: textured quad
float quad[] = {-1.0f, 1.0f, 0.0f, 1.0f,
-1.0f, -1.0f, 0.0f, 1.0f,
1.0f, -1.0f, 0.0f, 1.0f,
1.0f, -1.0f, 0.0f, 1.0f,
1.0f, 1.0f, 0.0f, 1.0f,
-1.0f, 1.0f, 0.0f, 1.0f};
float texcoord[] = {0.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f};
//OpenGL >= 3.3 core requires a vertex array object containing multiple attribute
//buffers
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
//geometry buffer
GLuint quadvbo;
glGenBuffers(1, &quadvbo);
glBindBuffer(GL_ARRAY_BUFFER, quadvbo);
glBufferData(GL_ARRAY_BUFFER, 6 * 4 * sizeof(float),
&quad[0], GL_STATIC_DRAW);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
//texture coordinate buffer
GLuint texbo;
glGenBuffers(1, &texbo);
glBindBuffer(GL_ARRAY_BUFFER, texbo);
glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(real_t),
&texcoord[0], GL_STATIC_DRAW);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
// create texture
std::vector< float > tc(SIZE * SIZE, 0.5f);
GLuint tex;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RED,
SIZE,
SIZE,
0,
GL_RED,
GL_FLOAT,
&tc[0]);
//optional
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
//required
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
//OPENGL RENDERING SHADERS
GLuint glprogram = create_program(vertexShaderSrc, fragmentShaderSrc);
//enable gl program
glUseProgram(glprogram);
//extract ids of shader variables
GLint mvpID = glGetUniformLocation(glprogram, "MVP");
assert(mvpID>=0);
GLint textureID = glGetUniformLocation(glprogram, "cltexture");
assert(textureID>=0);
//only need texture unit 0
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex);
glUniform1i(textureID, 0);
//beckground color
glClearColor(0.0f, 0.0f, 0.4f, 1.0f);
//RENDER LOOP
//rendering & simulation loop
while (true) {//!glfwWindowShouldClose(window)) {
glClear(GL_COLOR_BUFFER_BIT);
//setup OpenGL matrices: no more matrix stack in OpenGL >= 3 core
//profile, need to co// Clear the screen
int width, height;
glfwGetFramebufferSize(window, &width, &height);
assert(width > 0 && height > 0);
const float ratio = width / float(height);
const glm::mat4 orthoProj = glm::ortho(-ratio, ratio,
-1.0f, 1.0f,
1.0f, -1.0f);
const glm::mat4 modelView = glm::mat4(1.0f);
const glm::mat4 MVP = orthoProj * modelView;
glViewport(0, 0, width, height);
glUniformMatrix4fv(mvpID, 1, GL_FALSE, glm::value_ptr(MVP));
//select geometry to render
glBindVertexArray(vao);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
//draw
glDrawArrays(GL_TRIANGLES, 0, 6);
//unbind
glBindVertexArray(0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
//put pixels on screen
glfwSwapBuffers(window);
//query events
glfwPollEvents();
}
//CLEANUP
glDeleteBuffers(1, &quadvbo);
glDeleteBuffers(1, &texbo);
glDeleteVertexArrays(1, &vao);
glDeleteTextures(1, &tex);
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment