add GL module; move OpenGL loading from Window to GL
This commit is contained in:
parent
f620f2b335
commit
e2608b1d29
34
runtime/lib/gl.rb
Normal file
34
runtime/lib/gl.rb
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
module GL
|
||||||
|
@programs = {}
|
||||||
|
|
||||||
|
class << self
|
||||||
|
|
||||||
|
def load_shaders
|
||||||
|
program_sources = {
|
||||||
|
text: ["text.v.glsl", "text.f.glsl"],
|
||||||
|
basic: ["basic.v.glsl", "basic.f.glsl"],
|
||||||
|
rect: ["rect.v.glsl", "basic.f.glsl"],
|
||||||
|
}
|
||||||
|
|
||||||
|
program_sources.each do |program, (v_src_fname, f_src_fname)|
|
||||||
|
v_src = Runtime.read(:shader, v_src_fname)
|
||||||
|
v_shader = GLShader.new(:vertex, v_src)
|
||||||
|
v_shader or raise "Could not find shader #{v_src_fname}"
|
||||||
|
|
||||||
|
f_src = Runtime.read(:shader, f_src_fname)
|
||||||
|
f_shader = GLShader.new(:fragment, f_src)
|
||||||
|
f_shader or raise "Could not find shader #{f_src_fname}"
|
||||||
|
|
||||||
|
uniforms = (v_src + f_src).lines.map do |line|
|
||||||
|
if line =~ /\buniform\s.*\s(\S+);/
|
||||||
|
$1
|
||||||
|
end
|
||||||
|
end.compact
|
||||||
|
|
||||||
|
@programs[program] = GLProgram.new(v_shader, f_shader,
|
||||||
|
uniforms: uniforms)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
@ -1,6 +1,7 @@
|
|||||||
require "set"
|
require "set"
|
||||||
|
|
||||||
class Window
|
class Window
|
||||||
|
|
||||||
include Widget
|
include Widget
|
||||||
|
|
||||||
@windows = Set.new
|
@windows = Set.new
|
||||||
@ -16,42 +17,12 @@ class Window
|
|||||||
end
|
end
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
super
|
|
||||||
@programs = {}
|
|
||||||
load_shaders
|
|
||||||
Window.register(self)
|
Window.register(self)
|
||||||
|
super
|
||||||
end
|
end
|
||||||
|
|
||||||
def close
|
def close
|
||||||
Window.remove(self)
|
Window.remove(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def load_shaders
|
|
||||||
program_sources = {
|
|
||||||
text: ["text.v.glsl", "text.f.glsl"],
|
|
||||||
basic: ["basic.v.glsl", "basic.f.glsl"],
|
|
||||||
rect: ["rect.v.glsl", "basic.f.glsl"],
|
|
||||||
}
|
|
||||||
|
|
||||||
program_sources.each do |program, (v_src_fname, f_src_fname)|
|
|
||||||
v_src = Runtime.read(:shader, v_src_fname)
|
|
||||||
v_shader = GLShader.new(:vertex, v_src)
|
|
||||||
v_shader or raise "Could not find shader #{v_src_fname}"
|
|
||||||
|
|
||||||
f_src = Runtime.read(:shader, f_src_fname)
|
|
||||||
f_shader = GLShader.new(:fragment, f_src)
|
|
||||||
f_shader or raise "Could not find shader #{f_src_fname}"
|
|
||||||
|
|
||||||
uniforms = (v_src + f_src).lines.map do |line|
|
|
||||||
if line =~ /\buniform\s.*\s(\S+);/
|
|
||||||
$1
|
|
||||||
end
|
|
||||||
end.compact
|
|
||||||
|
|
||||||
@programs[program] = GLProgram.new(v_shader, f_shader,
|
|
||||||
uniforms: uniforms)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
@ -3,6 +3,7 @@ def init_loadpath
|
|||||||
end
|
end
|
||||||
|
|
||||||
def load_lib_files
|
def load_lib_files
|
||||||
|
require "gl"
|
||||||
require "gl_program"
|
require "gl_program"
|
||||||
require "runtime"
|
require "runtime"
|
||||||
require "widget"
|
require "widget"
|
||||||
|
101
src/GL.cc
Normal file
101
src/GL.cc
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
#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];
|
||||||
|
|
||||||
|
void GL_Init()
|
||||||
|
{
|
||||||
|
ruby_module = rb_define_module("GL");
|
||||||
|
}
|
||||||
|
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
}
|
8
src/GL.h
Normal file
8
src/GL.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#ifndef GL_H
|
||||||
|
#define GL_H
|
||||||
|
|
||||||
|
void GL_Init();
|
||||||
|
void GL_Load();
|
||||||
|
void GL_Resize(int width, int height);
|
||||||
|
|
||||||
|
#endif
|
@ -1,4 +1,5 @@
|
|||||||
#include "gl3w.h"
|
#include "gl3w.h"
|
||||||
|
#include "GL.h"
|
||||||
#include "GLBuffer.h"
|
#include "GLBuffer.h"
|
||||||
#include "GLProgram.h"
|
#include "GLProgram.h"
|
||||||
#include "ruby.h"
|
#include "ruby.h"
|
||||||
@ -8,25 +9,9 @@
|
|||||||
#define WIDTH 500
|
#define WIDTH 500
|
||||||
#define HEIGHT 500
|
#define HEIGHT 500
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
PROGRAM_TEXT,
|
|
||||||
PROGRAM_BASIC,
|
|
||||||
PROGRAM_RECT,
|
|
||||||
PROGRAM_COUNT
|
|
||||||
};
|
|
||||||
|
|
||||||
const char * program_names[PROGRAM_COUNT] = {
|
|
||||||
"text",
|
|
||||||
"basic",
|
|
||||||
"rect",
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
SDL_Window * sdl_window;
|
SDL_Window * sdl_window;
|
||||||
GLBufferRef rect_buffer;
|
|
||||||
GLProgram * programs[PROGRAM_COUNT];
|
|
||||||
} Window;
|
} Window;
|
||||||
|
|
||||||
static VALUE ruby_class;
|
static VALUE ruby_class;
|
||||||
@ -49,47 +34,6 @@ static void Init_SDL()
|
|||||||
initialized = true;
|
initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void load_gl_buffers(Window * window)
|
|
||||||
{
|
|
||||||
static const GLint rect_coords[4][2] = {
|
|
||||||
{0, 0},
|
|
||||||
{1, 0},
|
|
||||||
{0, 1},
|
|
||||||
{1, 1},
|
|
||||||
};
|
|
||||||
|
|
||||||
window->rect_buffer = new GLBuffer();
|
|
||||||
if (!window->rect_buffer->create(GL_ARRAY_BUFFER, GL_STATIC_DRAW,
|
|
||||||
&rect_coords, sizeof(rect_coords)))
|
|
||||||
{
|
|
||||||
rb_raise(rb_eRuntimeError, "Failed to create rectangle VBO");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Init_OpenGL()
|
|
||||||
{
|
|
||||||
static bool initialized = false;
|
|
||||||
|
|
||||||
if (initialized)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (gl3wInit() != 0)
|
|
||||||
{
|
|
||||||
SDL_Quit();
|
|
||||||
rb_raise(rb_eRuntimeError, "Failed to gl3wInit()");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!gl3wIsSupported(3, 0))
|
|
||||||
{
|
|
||||||
SDL_Quit();
|
|
||||||
rb_raise(rb_eRuntimeError, "OpenGL 3.0 is not supported");
|
|
||||||
}
|
|
||||||
|
|
||||||
glEnable(GL_SCISSOR_TEST);
|
|
||||||
|
|
||||||
initialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Window_free(void * ptr)
|
static void Window_free(void * ptr)
|
||||||
{
|
{
|
||||||
Window * window = (Window *)ptr;
|
Window * window = (Window *)ptr;
|
||||||
@ -102,23 +46,19 @@ static void Window_free(void * ptr)
|
|||||||
|
|
||||||
static void resize()
|
static void resize()
|
||||||
{
|
{
|
||||||
GLint viewport_size[2];
|
int width;
|
||||||
|
int height;
|
||||||
Window * window;
|
Window * window;
|
||||||
Data_Get_Struct(window_instance, Window, window);
|
Data_Get_Struct(window_instance, Window, window);
|
||||||
SDL_GetWindowSize(window->sdl_window, &viewport_size[0], &viewport_size[1]);
|
SDL_GetWindowSize(window->sdl_window, &width, &height);
|
||||||
glViewport(0, 0, viewport_size[0], viewport_size[1]);
|
GL_Resize(width, height);
|
||||||
for (int i = 0; i < PROGRAM_COUNT; i++)
|
|
||||||
{
|
|
||||||
glUseProgram(window->programs[i]->id);
|
|
||||||
glUniform2iv(window->programs[i]->uniforms[UNIFORM_VIEWPORT_SIZE], 1, &viewport_size[0]);
|
|
||||||
}
|
|
||||||
rb_funcall(window_instance,
|
rb_funcall(window_instance,
|
||||||
rb_intern("resize"),
|
rb_intern("resize"),
|
||||||
4,
|
4,
|
||||||
INT2FIX(0),
|
INT2FIX(0),
|
||||||
INT2FIX(0),
|
INT2FIX(0),
|
||||||
INT2FIX(viewport_size[0]),
|
INT2FIX(width),
|
||||||
INT2FIX(viewport_size[1]));
|
INT2FIX(height));
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE Window_new(VALUE klass)
|
static VALUE Window_new(VALUE klass)
|
||||||
@ -149,33 +89,12 @@ static VALUE Window_new(VALUE klass)
|
|||||||
|
|
||||||
(void)SDL_GL_CreateContext(window->sdl_window);
|
(void)SDL_GL_CreateContext(window->sdl_window);
|
||||||
|
|
||||||
Init_OpenGL();
|
GL_Load();
|
||||||
|
|
||||||
load_gl_buffers(window);
|
|
||||||
|
|
||||||
one_created = true;
|
one_created = true;
|
||||||
|
|
||||||
VALUE rv = Data_Wrap_Struct(ruby_class, NULL, Window_free, window);
|
VALUE rv = Data_Wrap_Struct(ruby_class, NULL, Window_free, window);
|
||||||
rb_obj_call_init(rv, 0, NULL);
|
rb_obj_call_init(rv, 0, NULL);
|
||||||
VALUE programs = rb_iv_get(rv, "@programs");
|
|
||||||
for (int i = 0; i < PROGRAM_COUNT; i++)
|
|
||||||
{
|
|
||||||
VALUE program = rb_funcall(programs,
|
|
||||||
rb_intern("[]"),
|
|
||||||
1,
|
|
||||||
ID2SYM(rb_intern(program_names[i])));
|
|
||||||
if (RTEST(program))
|
|
||||||
{
|
|
||||||
window->programs[i] = GLProgram_FromRuby(program);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
delete window;
|
|
||||||
rb_raise(rb_eLoadError,
|
|
||||||
"Error resolving %s program",
|
|
||||||
program_names[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO: remove window_instance and map SDL_Window * to Window Ruby object
|
/* TODO: remove window_instance and map SDL_Window * to Window Ruby object
|
||||||
* to support multiple windows. */
|
* to support multiple windows. */
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include "ruby.h"
|
#include "ruby.h"
|
||||||
|
|
||||||
#include "Font.h"
|
#include "Font.h"
|
||||||
|
#include "GL.h"
|
||||||
#include "GLProgram.h"
|
#include "GLProgram.h"
|
||||||
#include "GLShader.h"
|
#include "GLShader.h"
|
||||||
#include "Widget.h"
|
#include "Widget.h"
|
||||||
@ -54,6 +55,7 @@ static int bootstrap()
|
|||||||
int err_state = 0;
|
int err_state = 0;
|
||||||
|
|
||||||
Font_Init();
|
Font_Init();
|
||||||
|
GL_Init();
|
||||||
GLProgram_Init();
|
GLProgram_Init();
|
||||||
GLShader_Init();
|
GLShader_Init();
|
||||||
Widget_Init();
|
Widget_Init();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user