#include "GLShader.h" typedef struct { GLuint id; } GLShader; static VALUE ruby_class; static const char * get_shader_type_name(GLenum shader_type) { switch (shader_type) { case GL_VERTEX_SHADER: return "vertex"; case GL_FRAGMENT_SHADER: return "fragment"; default: return "unknown"; } } static GLuint create_shader(GLenum shader_type, const char *source, size_t size) { GLuint id = glCreateShader(shader_type); if (id > 0) { GLint status; GLint length = size; glShaderSource(id, 1, &source, &length); glCompileShader(id); glGetShaderiv(id, GL_COMPILE_STATUS, &status); if (status != GL_TRUE) { GLint log_length; glGetShaderiv(id, GL_INFO_LOG_LENGTH, &log_length); if (log_length > 0) { char log[log_length + 1]; glGetShaderInfoLog(id, log_length, &log_length, log); log[log_length] = '\0'; glDeleteShader(id); rb_raise(rb_eRuntimeError, "Error compiling %s shader:\n%s\n%s\n%s\n", get_shader_type_name(shader_type), "--------------------", log, "--------------------"); } else { glDeleteShader(id); rb_raise(rb_eRuntimeError, "Error compiling %s shader", get_shader_type_name(shader_type)); } } } return id; } static void GLShader_free(void * ptr) { GLShader * glshader = (GLShader *)ptr; if (glshader->id > 0) { glDeleteShader(glshader->id); } delete glshader; } static VALUE GLShader_new(VALUE klass, VALUE type, VALUE source) { GLenum shader_type; if (type == ID2SYM(rb_intern("vertex"))) { shader_type = GL_VERTEX_SHADER; } else if (type == ID2SYM(rb_intern("fragment"))) { shader_type = GL_FRAGMENT_SHADER; } else { type = rb_funcall(type, rb_intern("inspect"), 0); const char * type_cstr = StringValueCStr(type); rb_raise(rb_eRuntimeError, "Unknown shader type: %s", type_cstr); } GLuint id = create_shader(shader_type, RSTRING_PTR(source), RSTRING_LEN(source)); GLShader * glshader = new GLShader(); glshader->id = id; return Data_Wrap_Struct(klass, NULL, GLShader_free, glshader); } void GLShader_Init() { ruby_class = rb_define_class("GLShader", rb_cObject); rb_define_singleton_method(ruby_class, "new", (VALUE(*)(...))GLShader_new, 2); } GLuint GLShader_id(VALUE shader) { GLShader * glshader; Data_Get_Struct(shader, GLShader, glshader); return glshader->id; }