start adding GL shaders, program, texture loading

This commit is contained in:
Josh Holtrop 2014-06-10 14:27:21 -04:00
parent d4a4cfc9df
commit afd3cb56f1
6 changed files with 269 additions and 1 deletions

99
GLProgram.cc Normal file
View File

@ -0,0 +1,99 @@
#include "GLProgram.h"
#include <stdint.h>
#include <iostream>
using namespace std;
GLProgram::GLProgram()
{
m_id = 0;
}
GLProgram::~GLProgram()
{
if (m_id > 0)
{
glDeleteProgram(m_id);
}
}
bool GLProgram::create(const char *v_source, const char *f_source, ...)
{
va_list va;
va_start(va, f_source);
bool rv = createv(v_source, f_source, va);
va_end(va);
return rv;
}
bool GLProgram::create(const uint8_t *v_source, const uint8_t *f_source, ...)
{
va_list va;
va_start(va, f_source);
bool rv = createv((const char *) v_source, (const char *) f_source, va);
va_end(va);
return rv;
}
bool GLProgram::createv(const char *v_source, const char *f_source, va_list va)
{
if (v_source == NULL || f_source == NULL)
return false;
if (!m_v_shader.create(GL_VERTEX_SHADER, v_source))
{
cerr << "Failed vertex shader source:" << endl << v_source << endl;
return false;
}
if (!m_f_shader.create(GL_FRAGMENT_SHADER, f_source))
{
cerr << "Failed fragment shader source:" << endl << f_source << endl;
return false;
}
m_id = glCreateProgram();
if (m_id <= 0)
{
cerr << "Error allocating GL program object" << endl;
return false;
}
glAttachShader(m_id, m_v_shader.get_id());
glAttachShader(m_id, m_f_shader.get_id());
for (;;)
{
const char *attribute_name = va_arg(va, const char *);
if (attribute_name == NULL)
break;
GLuint attribute_index = va_arg(va, uint32_t);
glBindAttribLocation(m_id, attribute_index, attribute_name);
}
glLinkProgram(m_id);
GLint link_status;
glGetProgramiv(m_id, GL_LINK_STATUS, &link_status);
if (link_status != GL_TRUE)
{
GLint log_length;
glGetProgramiv(m_id, GL_INFO_LOG_LENGTH, &log_length);
if (log_length > 0)
{
char *log = new char[log_length];
glGetProgramInfoLog(m_id, log_length, &log_length, log);
cerr << "Program log:" << endl << log << endl;
delete[] log;
}
return false;
}
for (;;)
{
const char *uniform_name = va_arg(va, const char *);
if (uniform_name == NULL)
break;
GLint loc = glGetUniformLocation(m_id, uniform_name);
m_uniform_locations.push_back(loc);
m_uniform_location_names[uniform_name] = loc;
}
return true;
}

30
GLProgram.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef GLPROGRAM_H
#define GLPROGRAM_H
#include <stdarg.h>
#include "GLShader.h"
#include <map>
#include <string>
#include <vector>
class GLProgram
{
public:
GLProgram();
~GLProgram();
bool create(const char *v_source, const char *f_source, ...);
bool create(const uint8_t *v_source, const uint8_t *f_source, ...);
bool createv(const char *v_source, const char *f_source, va_list va);
GLuint get_id() { return m_id; }
void use() { glUseProgram(m_id); }
GLint uniform(int i) { return m_uniform_locations[i]; }
GLint uniform(const std::string & s) { return m_uniform_location_names[s]; }
protected:
GLuint m_id;
GLShader m_v_shader;
GLShader m_f_shader;
std::vector<GLint> m_uniform_locations;
std::map<std::string, GLint> m_uniform_location_names;
};
#endif

59
GLShader.cc Normal file
View File

@ -0,0 +1,59 @@
#include "GLShader.h"
#include <iostream>
using namespace std;
GLShader::GLShader()
{
m_id = 0;
}
GLShader::~GLShader()
{
if (m_id > 0)
{
glDeleteShader(m_id);
}
}
bool GLShader::create(GLenum shaderType, const char *source)
{
GLint status;
m_id = glCreateShader(shaderType);
if (m_id > 0)
{
glShaderSource(m_id, 1, &source, NULL);
glCompileShader(m_id);
glGetShaderiv(m_id, GL_COMPILE_STATUS, &status);
if (status == GL_TRUE)
{
return true;
}
GLint log_length;
cerr << "Error compiling ";
switch (shaderType)
{
case GL_VERTEX_SHADER:
cerr << "vertex";
break;
case GL_FRAGMENT_SHADER:
cerr << "fragment";
break;
}
cerr << " shader" << endl;
glGetShaderiv(m_id, GL_INFO_LOG_LENGTH, &log_length);
if (log_length > 0)
{
char * log = new char[log_length];
glGetShaderInfoLog(m_id, log_length, &log_length, log);
cerr << "Shader Log:" << endl << log << endl;
delete[] log;
}
glDeleteShader(m_id);
}
return false;
}

18
GLShader.h Normal file
View File

@ -0,0 +1,18 @@
#ifndef GLSHADER_H
#define GLSHADER_H
#include "gl3w.h"
class GLShader
{
public:
GLShader();
~GLShader();
bool create(GLenum shaderType, const char *source);
GLuint get_id() { return m_id; }
bool valid() { return m_id > 0; }
protected:
GLuint m_id;
};
#endif

View File

@ -7,7 +7,7 @@ CFLAGS := $(shell freetype-config --cflags) $(shell sdl2-config --cflags)
CXXFLAGS := $(CFLAGS)
LDFLAGS := -l$(GL_LIB) -ldl -lfreetype $(shell sdl2-config --libs) $(shell freetype-config --libs)
freetype2gl3: gl3w.o freetype2gl3.o
freetype2gl3: gl3w.o freetype2gl3.o GLShader.o GLProgram.o
$(CXX) -o $@ $^ $(LDFLAGS)
.PHONY: clean

View File

@ -3,6 +3,7 @@
#include <iostream>
#include <ft2build.h>
#include FT_FREETYPE_H
#include "GLProgram.h"
using namespace std;
@ -11,15 +12,76 @@ using namespace std;
static FT_Library ft;
static FT_Face face;
static GLProgram program;
static GLint uniform_tex;
const char vertex_shader[] =
"#version 120\n"
"\n"
"attribute vec4 coord;\n"
"\n"
"varying vec2 tex_coord_i;\n"
"\n"
"void main(void)\n"
"{\n"
" gl_Position = vec4(coord.xy, 0, 1);\n"
" tex_coord_i = coord.zw;\n"
"}\n";
const char fragment_shader[] =
"varying vec2 tex_coord_i;\n"
"\n"
"uniform sampler2D tex;\n"
"uniform vec4 color;\n"
"\n"
"void main(void)\n"
"{\n"
" gl_FragColor = vec4(1, 1, 1, texture2D(tex, tex_coord_i).a) * color;\n"
"}\n";
void init(void)
{
glClearColor (0.0, 0.0, 0.0, 0.0);
program.create(vertex_shader, fragment_shader,
"coord", 0, NULL,
"tex", NULL);
uniform_tex = program.uniform("tex");
program.use();
}
void display(SDL_Window * window)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if (FT_Load_Char(face, 'h', FT_LOAD_RENDER) != 0)
{
cerr << "Failed to load character" << endl;
}
#if 0
GLuint texture_id;
glActiveTexture(GL_TEXTURE0);
glGenTextures(1, &texture_id);
glBindTexture(GL_TEXTURE_2D, texture_id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_ALPHA,
face->glyph->bitmap.width,
face->glyph->bitmap.rows,
0,
GL_ALPHA,
GL_UNSIGNED_BYTE,
face->glyph->bitmap.buffer);
GLuint vbo;
glGenBuffers(1, &vbo);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
glUniform1i(uniform_tex, 0);
#endif
SDL_GL_SwapWindow(window);
}