-
-
Save roxlu/82273f36a0f4de6c1954 to your computer and use it in GitHub Desktop.
Easy embeddable OpenGL Grid drawer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <Grid.h> | |
/* ------------------------------------------------------------------------*/ | |
/* Embeddable OpenGL wrappers. */ | |
/* ------------------------------------------------------------------------*/ | |
static int create_shader(GLuint* out, GLenum type, const char* src); /* create a shader, returns 0 on success, < 0 on error. e.g. create_shader(&vert, GL_VERTEX_SHADER, DRAWER_VS); */ | |
static int create_program(GLuint* out, GLuint vert, GLuint frag, int link); /* create a program from the given vertex and fragment shader. returns 0 on success, < 0 on error. e.g. create_program(&prog, vert, frag, 1); */ | |
static int print_shader_compile_info(GLuint shader); /* prints the compile info of a shader. returns 0 when shader compiled, < 0 on error. */ | |
static int print_program_link_info(GLuint prog); /* prints the program link info. returns 0 on success, < 0 on error. */ | |
/* ------------------------------------------------------------------------*/ | |
static const char* GRID_VS = "" | |
"#version 330\n" | |
"" | |
"uniform mat4 u_pm;" | |
"uniform mat4 u_vm;" | |
"" | |
"layout (location = 0) in vec4 a_pos;" | |
"layout (location = 1) in vec4 a_col;" | |
"" | |
"out vec4 v_col;" | |
"" | |
"void main() {" | |
" gl_Position = u_pm * u_vm * a_pos;" | |
" v_col = a_col;" | |
"}" | |
""; | |
static const char* GRID_FS = "" | |
"#version 330\n" | |
"" | |
"layout (location = 0) out vec4 fragcolor;" | |
"" | |
"in vec4 v_col;" | |
"" | |
"void main() {" | |
" fragcolor = v_col;" | |
"}" | |
""; | |
/* ------------------------------------------------------------------------*/ | |
GLuint Grid::vert = 0; | |
GLuint Grid::frag = 0; | |
GLuint Grid::prog = 0; | |
GLint Grid::u_vm = -1; | |
GLint Grid::u_pm = -1; | |
/* ------------------------------------------------------------------------*/ | |
Grid::Grid() | |
:vao(0) | |
,vbo(0) | |
{ | |
} | |
Grid::~Grid() { | |
if (0 != vao) { | |
glDeleteVertexArrays(1, &vao); | |
vao = 0; | |
} | |
if (0 != vbo) { | |
glDeleteBuffers(1, &vbo); | |
vbo = 0; | |
} | |
} | |
int Grid::init(int hcols, int hrows, float step) { | |
/* (Cached) variables that we use when creating the vertices for the grid. */ | |
int half_rows = hrows; | |
int half_cols = hcols; | |
int cols = half_cols * 2; | |
int rows = half_rows * 2; | |
float size_w = step * cols; | |
float size_h = step * rows; | |
float half_size_w = size_w * 0.5; | |
float half_size_h = size_h * 0.5; | |
float z = 0.0f; | |
float x = 0.0f; | |
/* Colors. */ | |
float white[4] = { 1.0f, 1.0f, 1.0f, 1.0f}; | |
float red[4] = { 1.0f, 0.0f, 0.0f, 1.0f }; | |
float green[4] = { 0.0f, 1.0f, 0.0f, 1.0f }; | |
float blue[4] = { 0.0f, 0.0f, 1.0f, 1.0f }; | |
float gray[4] = { 0.3f, 0.3f, 0.3f, 0.6f }; | |
/* Create shader */ | |
if (0 == vert) { | |
if (0 != create_shader(&vert, GL_VERTEX_SHADER, GRID_VS)) { | |
printf("Error: cannot create the grid vertex shader.\n"); | |
return -1; | |
} | |
if (0 != create_shader(&frag, GL_FRAGMENT_SHADER, GRID_FS)) { | |
printf("Error: cannot create the grid fragment shader.\n"); | |
/* @todo delete vert shader. */ | |
return -2; | |
} | |
if (0 != create_program(&prog, vert, frag, 1)) { | |
printf("Error: cannot create program.\n"); | |
/* @todo delete vert, frag, prog shader. */ | |
return -3; | |
} | |
glUseProgram(prog); | |
u_pm = glGetUniformLocation(prog, "u_pm"); | |
u_vm = glGetUniformLocation(prog, "u_vm"); | |
if (-1 == u_pm) { | |
printf("Error: failed to get the u_pm uniform.\n"); | |
/* @todo delete vert, frag, prog shader. */ | |
return -4; | |
} | |
if (-1 == u_vm) { | |
printf("Error: failed to get the u_vm uniform.\n"); | |
/* @todo delete vert, frag, prog shader. */ | |
return -5; | |
} | |
} | |
vertices.clear(); | |
/* Recreate? */ | |
if (0 != vao) { | |
glDeleteVertexArrays(1, &vao); | |
vao = 0; | |
} | |
if (0 != vbo) { | |
glDeleteBuffers(1, &vbo); | |
vbo = 0; | |
} | |
/* Column lines and axis. */ | |
for (int i = 1; i < cols; ++i) { | |
x = -half_size_w + i * step; | |
if (i != half_cols) { | |
addVertex(x, 0.0f, -half_size_h, gray); | |
addVertex(x, 0.0f, half_size_h, gray); | |
} | |
else { | |
/* Z-axis. */ | |
addVertex(x, 0.0f, 0.0f, blue); | |
addVertex(x, 0.0f, -half_size_h, blue); | |
addVertex(x, 0.0f, half_size_h, gray); | |
addVertex(x, 0.0f, 0.0f, gray); | |
} | |
} | |
/* Row lines and axis */ | |
for (int j = 1; j < rows; ++j) { | |
z = -half_size_h + j * step; | |
if (j != half_rows) { | |
addVertex(-half_size_w, 0.0f, z, gray); | |
addVertex(half_size_w, 0.0f, z, gray); | |
} | |
else { | |
/* X-axis. */ | |
addVertex(0.0f, 0.0f, z, red); | |
addVertex(half_size_w, 0.0f, z, red); | |
addVertex(-half_size_w, 0.0f, z, gray); | |
addVertex(0.0f, 0.0f, z, gray); | |
} | |
} | |
/* Y-axis */ | |
addVertex(0.0f, 0.0f, 0.0f, green); | |
addVertex(0.0f, half_size_w, 0.0f, green); | |
/* Lines around grid. */ | |
addVertex(-half_size_w, 0.0f, half_size_h, white); | |
addVertex(half_size_w, 0.0f, half_size_h, white); | |
addVertex(-half_size_w, 0.0f, -half_size_h, white); | |
addVertex(half_size_w, 0.0f, -half_size_h, white); | |
addVertex(-half_size_w, 0.0f, half_size_h, white); | |
addVertex(-half_size_w, 0.0f, -half_size_h, white); | |
addVertex(half_size_w, 0.0f, half_size_h, white); | |
addVertex(half_size_w, 0.0f, -half_size_h, white); | |
/* VBO + VAO */ | |
glGenVertexArrays(1, &vao); | |
glBindVertexArray(vao); | |
glGenBuffers(1, &vbo); | |
glBindBuffer(GL_ARRAY_BUFFER, vbo); | |
glBufferData(GL_ARRAY_BUFFER, sizeof(GridVertex) * vertices.size(), &vertices[0].pos[0], GL_STATIC_DRAW); | |
glEnableVertexAttribArray(0); | |
glEnableVertexAttribArray(1); | |
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(GridVertex), (GLvoid*)0); | |
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(GridVertex), (GLvoid*)12); | |
return 0; | |
} | |
void Grid::draw(float* pm, float* vm) { | |
if (0 == vertices.size()) { | |
return; | |
} | |
glBindVertexArray(vao); | |
glUseProgram(prog); | |
glUniformMatrix4fv(u_vm, 1, GL_FALSE, vm); | |
glUniformMatrix4fv(u_pm, 1, GL_FALSE, pm); | |
glDrawArrays(GL_LINES, 0, vertices.size()); | |
} | |
/* ------------------------------------------------------------------------*/ | |
/* Embeddable OpenGL wrappers. */ | |
/* ------------------------------------------------------------------------*/ | |
static int create_shader(GLuint* out, GLenum type, const char* src) { | |
*out = glCreateShader(type); | |
glShaderSource(*out, 1, &src, NULL); | |
glCompileShader(*out); | |
if (0 != print_shader_compile_info(*out)) { | |
*out = 0; | |
return -1; | |
} | |
return 0; | |
} | |
/* create a program, store the result in *out. when link == 1 we link too. returns -1 on error, otherwise 0 */ | |
static int create_program(GLuint* out, GLuint vert, GLuint frag, int link) { | |
*out = glCreateProgram(); | |
glAttachShader(*out, vert); | |
glAttachShader(*out, frag); | |
if(1 == link) { | |
glLinkProgram(*out); | |
if (0 != print_program_link_info(*out)) { | |
*out = 0; | |
return -1; | |
} | |
} | |
return 0; | |
} | |
/* checks + prints program link info. returns 0 when linking didn't result in an error, on link erorr < 0 */ | |
static int print_program_link_info(GLuint prog) { | |
GLint status = 0; | |
GLint count = 0; | |
GLchar* error = NULL; | |
GLsizei nchars = 0; | |
glGetProgramiv(prog, GL_LINK_STATUS, &status); | |
if(status) { | |
return 0; | |
} | |
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &count); | |
if(count <= 0) { | |
return 0; | |
} | |
error = (GLchar*)malloc(count); | |
glGetProgramInfoLog(prog, count, &nchars, error); | |
if (nchars <= 0) { | |
free(error); | |
error = NULL; | |
return -1; | |
} | |
printf("\nPROGRAM LINK ERROR"); | |
printf("\n--------------------------------------------------------\n"); | |
printf("%s", error); | |
printf("--------------------------------------------------------\n\n"); | |
free(error); | |
error = NULL; | |
return -1; | |
} | |
/* checks the compile info, if it didn't compile we return < 0, otherwise 0 */ | |
static int print_shader_compile_info(GLuint shader) { | |
GLint status = 0; | |
GLint count = 0; | |
GLchar* error = NULL; | |
glGetShaderiv(shader, GL_COMPILE_STATUS, &status); | |
if(status) { | |
return 0; | |
} | |
error = (GLchar*) malloc(count); | |
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &count); | |
if(count <= 0) { | |
free(error); | |
error = NULL; | |
return 0; | |
} | |
glGetShaderInfoLog(shader, count, NULL, error); | |
printf("\nSHADER COMPILE ERROR"); | |
printf("\n--------------------------------------------------------\n"); | |
printf("%s", error); | |
printf("--------------------------------------------------------\n\n"); | |
free(error); | |
error = NULL; | |
return -1; | |
} | |
/* ------------------------------------------------------------------------*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* -*-c++-*- */ | |
/* | |
Grid | |
==== | |
This class generated the vertices for a 3D grid, using the XZ-Plane to draw a | |
Grid. This class uses OpenGL to drow the grid; doesn't do any fancy stuff. | |
The lines that are drawn use the alpha channel; so make sure you enable | |
blending and set a appropriate blend func. | |
````c++ | |
glEnable(GL_BLEND); | |
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | |
```` | |
Example render: | |
--------------- | |
https://www.flickr.com/photos/diederick/18570328802/in/dateposted-public/ | |
*/ | |
#ifndef GRID_H | |
#define GRID_H | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <glad/glad.h> | |
#include <vector> | |
/* ------------------------------------------------------------------------*/ | |
struct GridVertex { | |
float pos[3]; | |
float col[4]; | |
}; | |
/* ------------------------------------------------------------------------*/ | |
class Grid { | |
public: | |
Grid(); | |
~Grid(); | |
int init(int hrows, int hcols, float step); /* Initialize with the half number of rows (e.g. 5 to create 10 rows, 5 in positive and 5 along negative axis. */ | |
void draw(float* pm, float* vm); /* Draw the grid using the given, column major projection and view matrices. */ | |
private: | |
void addVertex(float x, float y, float z, float* col); /* Internally used to add a vertex for the VBO. */ | |
void addVertex(float x, float y, float z, float r, float g, float b, float a); /* "" "" "" */ | |
public: | |
static GLuint vert; /* The GL_VERTEX_SHADER */ | |
static GLuint frag; /* The GL_FRAGMENT_SHADER */ | |
static GLuint prog; /* The shader program we use to draw. */ | |
static GLint u_pm; /* The location of the projection matrix. */ | |
static GLint u_vm; /* The location of the view matrix. */ | |
GLuint vao; /* The Vertex Array Object. */ | |
GLuint vbo; /* The Vertex Buffer Object. */ | |
std::vector<GridVertex> vertices; /* The vertices that are used to draw the grid. */ | |
}; | |
/* ------------------------------------------------------------------------*/ | |
inline void Grid::addVertex(float x, float y, float z, float* col) { | |
addVertex(x, y, z, col[0], col[1], col[2], col[3]); | |
} | |
inline void Grid::addVertex(float x, float y, float z, float r, float g, float b, float a) { | |
GridVertex v; | |
v.pos[0] = x; | |
v.pos[1] = y; | |
v.pos[2] = z; | |
v.col[0] = r; | |
v.col[1] = g; | |
v.col[2] = b; | |
v.col[3] = a; | |
vertices.push_back(v); | |
} | |
#endif |
Author
roxlu
commented
Jun 7, 2015
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment