diff --git a/src/gltk/array.d b/src/gltk/array.d new file mode 100644 index 0000000..90291ce --- /dev/null +++ b/src/gltk/array.d @@ -0,0 +1,32 @@ +module gltk.array; +import derelict.opengl; + +class Array +{ + private GLuint m_id; + + this() + { + m_id = 0u; + glGenVertexArrays(1, &m_id); + if (m_id == 0u) + { + throw new Exception("Failed to allocate an OpenGL array"); + } + } + + ~this() + { + glDeleteVertexArrays(1, &m_id); + } + + void bind() + { + glBindVertexArray(m_id); + } + + @property GLuint id() + { + return m_id; + } +} diff --git a/src/gltk/buffer.d b/src/gltk/buffer.d new file mode 100644 index 0000000..a76d958 --- /dev/null +++ b/src/gltk/buffer.d @@ -0,0 +1,41 @@ +module gltk.buffer; +import derelict.opengl; + +class Buffer +{ + private GLuint m_id; + + private GLenum m_target; + + this() + { + m_id = 0u; + glGenBuffers(1, &m_id); + if (m_id == 0u) + { + throw new Exception("Failed to allocate an OpenGL buffer"); + } + } + + ~this() + { + glDeleteBuffers(1, &m_id); + } + + void bind() + { + glBindBuffer(m_target, m_id); + } + + @property GLuint id() + { + return m_id; + } + + void set_buffer_data(GLenum target, GLenum usage, const void * ptr, size_t size) + { + m_target = target; + bind(); + glBufferData(target, size, ptr, usage); + } +} diff --git a/src/gltk/package.d b/src/gltk/package.d new file mode 100644 index 0000000..656c281 --- /dev/null +++ b/src/gltk/package.d @@ -0,0 +1,3 @@ +module gltk; + +public import gltk.texture; diff --git a/src/gltk/program.d b/src/gltk/program.d new file mode 100644 index 0000000..211226d --- /dev/null +++ b/src/gltk/program.d @@ -0,0 +1,66 @@ +module gltk.program; +import gltk.shader; +import derelict.opengl; +import std.string; + +class Program +{ + private GLuint m_id; + + this() + { + m_id = glCreateProgram(); + if (m_id == 0u) + { + throw new Exception("Failed to allocate an OpenGL program"); + } + } + + ~this() + { + glDeleteProgram(m_id); + } + + void attach_shader(Shader shader) const + { + glAttachShader(m_id, shader.id); + } + + void link() const + { + glLinkProgram(m_id); + + GLint link_status; + glGetProgramiv(m_id, GL_LINK_STATUS, &link_status); + if (link_status != GL_TRUE) + { + string message = "Failed to link program"; + GLint log_length = 0; + 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.ptr); + message ~= "\n"; + message ~= log; + message ~= "\n"; + } + throw new Exception(message); + } + } + + GLint get_uniform_location(string uniform_name) + { + return glGetUniformLocation(m_id, uniform_name.toStringz()); + } + + @property GLuint id() + { + return m_id; + } + + void use() const + { + glUseProgram(m_id); + } +} diff --git a/src/gltk/shader.d b/src/gltk/shader.d new file mode 100644 index 0000000..4d7c259 --- /dev/null +++ b/src/gltk/shader.d @@ -0,0 +1,80 @@ +module gltk.shader; +import derelict.opengl; +static import std.file; + +class Shader +{ + private GLuint m_id; + + private GLenum m_shader_type; + + this(GLenum shader_type) + { + m_shader_type = shader_type; + m_id = glCreateShader(shader_type); + if (m_id == 0u) + { + throw new Exception("Failed to allocate an OpenGL shader"); + } + } + + ~this() + { + glDeleteShader(m_id); + } + + void set_source(const char * source, int length = -1) + { + GLint status; + + GLint gllength = length; + glShaderSource(m_id, 1, &source, &gllength); + + glCompileShader(m_id); + + glGetShaderiv(m_id, GL_COMPILE_STATUS, &status); + if (status == GL_TRUE) + { + return; + } + + string message = "Error compiling "; + switch (m_shader_type) + { + case GL_VERTEX_SHADER: + message ~= "vertex"; + break; + case GL_FRAGMENT_SHADER: + message ~= "fragment"; + break; + default: + message ~= "unknown"; + break; + } + message ~= " shader"; + + GLint log_length; + 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.ptr); + message ~= "\nShader Log:\n"; + message ~= log; + message ~= "\n"; + } + glDeleteShader(m_id); + throw new Exception(message); + } + + void set_source_from_file(string filename) + { + const(char)[] file_data = cast(const(char)[])std.file.read(filename); + set_source(file_data.ptr, cast(int)file_data.length); + } + + @property GLuint id() + { + return m_id; + } +} diff --git a/src/gltk/texture.d b/src/gltk/texture.d new file mode 100644 index 0000000..8ef6506 --- /dev/null +++ b/src/gltk/texture.d @@ -0,0 +1,44 @@ +module gltk.texture; +import derelict.opengl; + +class Texture +{ + private GLuint m_id; + + this() + { + m_id = 0u; + glGenTextures(1, &m_id); + if (m_id == 0u) + { + throw new Exception("Failed to allocate an OpenGL texture"); + } + } + + ~this() + { + glDeleteTextures(1, &m_id); + } + + void bind(GLenum target) const + { + glBindTexture(target, m_id); + } + + @property GLuint id() + { + return m_id; + } + + static uint next_power_of_2(uint n) + { + n--; + n |= n >> 1u; + n |= n >> 2u; + n |= n >> 4u; + n |= n >> 8u; + n |= n >> 16u; + n++; + return n; + } +};