jes-ruby/src/GL.cc
2014-08-04 22:07:45 -04:00

124 lines
3.0 KiB
C++

#include "GL.h"
#include "gl3w.h"
#include "ruby.h"
#include "GLBuffer.h"
#include "GLProgram.h"
enum
{
PROGRAM_TEXT,
PROGRAM_BASIC,
PROGRAM_RECT,
PROGRAM_COUNT
};
static const char * program_names[PROGRAM_COUNT] = {
"text",
"basic",
"rect",
};
static VALUE ruby_module;
static GLBufferRef rect_buffer;
static GLProgram * programs[PROGRAM_COUNT];
static VALUE GL_draw_rect(VALUE klass,
VALUE x, VALUE y, VALUE width, VALUE height,
VALUE r, VALUE g, VALUE b, VALUE a)
{
glUseProgram(programs[PROGRAM_RECT]->id);
glUniform2i(programs[PROGRAM_RECT]->uniforms[UNIFORM_POSITION], FIX2INT(x), FIX2INT(y));
glUniform2i(programs[PROGRAM_RECT]->uniforms[UNIFORM_SIZE], FIX2INT(width), FIX2INT(height));
glUniform4f(programs[PROGRAM_RECT]->uniforms[UNIFORM_COLOR],
RFLOAT_VALUE(r),
RFLOAT_VALUE(g),
RFLOAT_VALUE(b),
RFLOAT_VALUE(a));
rect_buffer->bind();
glEnableVertexAttribArray(0);
glVertexAttribIPointer(0, 2, GL_INT, 0, 0);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
return Qnil;
}
void GL_Init()
{
ruby_module = rb_define_module("GL");
rb_define_singleton_method(ruby_module, "draw_rect",
(VALUE(*)(...))GL_draw_rect, 4);
}
static void load_gl_buffers()
{
static const GLint rect_coords[4][2] = {
{0, 0},
{1, 0},
{0, 1},
{1, 1},
};
rect_buffer = new GLBuffer();
if (!rect_buffer->create(GL_ARRAY_BUFFER, GL_STATIC_DRAW,
&rect_coords, sizeof(rect_coords)))
{
rb_raise(rb_eRuntimeError, "Failed to create rectangle VBO");
}
}
void GL_Load()
{
static bool loaded = false;
if (loaded)
return;
if (gl3wInit() != 0)
{
rb_raise(rb_eRuntimeError, "Failed to gl3wInit()");
}
if (!gl3wIsSupported(3, 0))
{
rb_raise(rb_eRuntimeError, "OpenGL 3.0 is not supported");
}
load_gl_buffers();
rb_funcall(ruby_module, rb_intern("load_shaders"), 0);
VALUE programs_hash = rb_iv_get(ruby_module, "@programs");
for (int i = 0; i < PROGRAM_COUNT; i++)
{
VALUE program = rb_funcall(programs_hash,
rb_intern("[]"),
1,
ID2SYM(rb_intern(program_names[i])));
if (RTEST(program))
{
programs[i] = GLProgram_FromRuby(program);
}
else
{
rb_raise(rb_eLoadError,
"Error resolving %s program",
program_names[i]);
}
}
glEnable(GL_SCISSOR_TEST);
loaded = true;
}
void GL_Resize(int width, int height)
{
GLint viewport_size[] = {width, height};
glViewport(0, 0, width, height);
for (int i = 0; i < PROGRAM_COUNT; i++)
{
glUseProgram(programs[i]->id);
glUniform2iv(programs[i]->uniforms[UNIFORM_VIEWPORT_SIZE], 1, &viewport_size[0]);
}
}