Add gltk
This commit is contained in:
parent
8d44370067
commit
f6cfbcc406
@ -8,6 +8,7 @@ env "app" do |env|
|
||||
"libs/bindbc-common/source",
|
||||
"libs/bindbc-sdl/source",
|
||||
"libs/glad",
|
||||
"libs/gltk",
|
||||
]
|
||||
sources = dirs.reduce([]) do |result, dir|
|
||||
result + glob("#{dir}/**/*.{d,c}")
|
||||
|
33
libs/gltk/gltk/array.d
Normal file
33
libs/gltk/gltk/array.d
Normal file
@ -0,0 +1,33 @@
|
||||
module gltk.array;
|
||||
|
||||
import gl;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
48
libs/gltk/gltk/buffer.d
Normal file
48
libs/gltk/gltk/buffer.d
Normal file
@ -0,0 +1,48 @@
|
||||
module gltk.buffer;
|
||||
|
||||
import gl;
|
||||
|
||||
class Buffer
|
||||
{
|
||||
private GLuint m_id;
|
||||
|
||||
private GLenum m_target;
|
||||
|
||||
this(GLenum target)
|
||||
{
|
||||
m_id = 0u;
|
||||
glGenBuffers(1, &m_id);
|
||||
if (m_id == 0u)
|
||||
{
|
||||
throw new Exception("Failed to allocate an OpenGL buffer");
|
||||
}
|
||||
m_target = target;
|
||||
}
|
||||
|
||||
~this()
|
||||
{
|
||||
glDeleteBuffers(1, &m_id);
|
||||
}
|
||||
|
||||
void bind()
|
||||
{
|
||||
glBindBuffer(m_target, m_id);
|
||||
}
|
||||
|
||||
@property GLuint id()
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
void set_buffer_data(GLenum usage, const void * ptr, size_t size)
|
||||
{
|
||||
bind();
|
||||
glBufferData(m_target, size, ptr, usage);
|
||||
}
|
||||
|
||||
void set_buffer_data(T)(GLenum usage, T[] arr)
|
||||
{
|
||||
bind();
|
||||
glBufferData(m_target, arr.length * arr[0].sizeof, arr.ptr, usage);
|
||||
}
|
||||
}
|
7
libs/gltk/gltk/package.d
Normal file
7
libs/gltk/gltk/package.d
Normal file
@ -0,0 +1,7 @@
|
||||
module gltk;
|
||||
|
||||
public import gltk.array;
|
||||
public import gltk.buffer;
|
||||
public import gltk.program;
|
||||
public import gltk.shader;
|
||||
public import gltk.texture;
|
182
libs/gltk/gltk/program.d
Normal file
182
libs/gltk/gltk/program.d
Normal file
@ -0,0 +1,182 @@
|
||||
module gltk.program;
|
||||
|
||||
import gltk.shader;
|
||||
import std.string;
|
||||
import gl;
|
||||
|
||||
class Program(uniforms...)
|
||||
{
|
||||
/* The number of template parameters must be a multiple of 2. */
|
||||
static assert((uniforms.length % 2) == 0);
|
||||
|
||||
private GLuint m_id;
|
||||
|
||||
static foreach (i, v; uniforms)
|
||||
{
|
||||
static if ((i % 2) == 0)
|
||||
{
|
||||
mixin("private GLint m_uniform_" ~ v ~ ";");
|
||||
}
|
||||
}
|
||||
|
||||
this(Args...)(Args args)
|
||||
{
|
||||
m_id = glCreateProgram();
|
||||
if (m_id == 0u)
|
||||
{
|
||||
throw new Exception("Failed to allocate an OpenGL program");
|
||||
}
|
||||
static if (args.length > 0u)
|
||||
{
|
||||
build(args);
|
||||
}
|
||||
}
|
||||
|
||||
~this()
|
||||
{
|
||||
glDeleteProgram(m_id);
|
||||
}
|
||||
|
||||
void attach_shader(Shader shader) const
|
||||
{
|
||||
glAttachShader(m_id, shader.id);
|
||||
}
|
||||
|
||||
void bind_attrib_location(string name, uint index) const
|
||||
{
|
||||
glBindAttribLocation(m_id, index, name.toStringz());
|
||||
}
|
||||
|
||||
void link()
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
static foreach(i, v; uniforms)
|
||||
{
|
||||
static if ((i % 2) == 0)
|
||||
{
|
||||
mixin("m_uniform_" ~ v ~ " = glGetUniformLocation(m_id, \"" ~ v ~ "\");");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GLint get_uniform_location(string uniform_name) const
|
||||
{
|
||||
return glGetUniformLocation(m_id, uniform_name.toStringz());
|
||||
}
|
||||
|
||||
void get_uniform_locations(Args...)(string uniform_name, GLint * uniform_location, Args args) const
|
||||
{
|
||||
*uniform_location = get_uniform_location(uniform_name);
|
||||
static if (args.length > 0u)
|
||||
{
|
||||
get_uniform_locations(args);
|
||||
}
|
||||
}
|
||||
|
||||
@property GLuint id() const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
void use() const
|
||||
{
|
||||
glUseProgram(m_id);
|
||||
}
|
||||
|
||||
private static string uniform_param_decl_list(string spec)
|
||||
{
|
||||
int count = spec[0] - '0';
|
||||
string type;
|
||||
if (spec[1] == 'i')
|
||||
{
|
||||
type = "GLint";
|
||||
}
|
||||
else if (spec[1..2] == "ui")
|
||||
{
|
||||
type = "GLuint";
|
||||
}
|
||||
else if (spec[1] == 'f')
|
||||
{
|
||||
type = "GLfloat";
|
||||
}
|
||||
assert(type != "");
|
||||
if (spec[$ - 1] == 'v')
|
||||
{
|
||||
return "uint count, const " ~ type ~ " * v";
|
||||
}
|
||||
else
|
||||
{
|
||||
string[] decls;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
decls ~= type ~ " v" ~ cast(char)('0' + i);
|
||||
}
|
||||
return decls.join(", ");
|
||||
}
|
||||
}
|
||||
|
||||
private static string uniform_param_list(string spec)
|
||||
{
|
||||
int count = spec[0] - '0';
|
||||
if (spec[$ - 1] == 'v')
|
||||
{
|
||||
return "count, v";
|
||||
}
|
||||
else
|
||||
{
|
||||
string[] vees;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
vees ~= "v" ~ cast(char)('0' + i);
|
||||
}
|
||||
return vees.join(", ");
|
||||
}
|
||||
}
|
||||
|
||||
static foreach (i, v; uniforms)
|
||||
{
|
||||
static if ((i % 2) == 0)
|
||||
{
|
||||
mixin("void set_" ~ v ~ "(" ~ uniform_param_decl_list(uniforms[i + 1]) ~ ")" ~
|
||||
"{" ~
|
||||
" glUniform" ~ uniforms[i + 1] ~ "(m_uniform_" ~ v ~ ", " ~ uniform_param_list(uniforms[i + 1]) ~ ");" ~
|
||||
"}");
|
||||
}
|
||||
}
|
||||
|
||||
private void build(Args...)(Shader s, Args args)
|
||||
{
|
||||
attach_shader(s);
|
||||
build(args);
|
||||
}
|
||||
|
||||
private void build(Args...)(string attrib_name, uint index, Args args)
|
||||
{
|
||||
bind_attrib_location(attrib_name, index);
|
||||
build(args);
|
||||
}
|
||||
|
||||
private void build()
|
||||
{
|
||||
link();
|
||||
}
|
||||
}
|
81
libs/gltk/gltk/shader.d
Normal file
81
libs/gltk/gltk/shader.d
Normal file
@ -0,0 +1,81 @@
|
||||
module gltk.shader;
|
||||
|
||||
import gl;
|
||||
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;
|
||||
}
|
||||
}
|
45
libs/gltk/gltk/texture.d
Normal file
45
libs/gltk/gltk/texture.d
Normal file
@ -0,0 +1,45 @@
|
||||
module gltk.texture;
|
||||
|
||||
import gl;
|
||||
|
||||
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;
|
||||
}
|
||||
};
|
@ -1,7 +1,8 @@
|
||||
import std.stdio;
|
||||
import sdl;
|
||||
import glad.gl.all;
|
||||
import gl;
|
||||
import glad.gl.loader;
|
||||
import gltk;
|
||||
|
||||
enum int WIDTH = 800;
|
||||
enum int HEIGHT = 600;
|
||||
|
Loading…
x
Reference in New Issue
Block a user