124 lines
3.0 KiB
C++
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]);
|
|
}
|
|
}
|