Add demo shader and spinning colored cube

This commit is contained in:
Josh Holtrop 2024-01-25 20:57:33 -05:00
parent 8e6ec5f820
commit 8dc6e97585
8 changed files with 149 additions and 38 deletions

3
.gitmodules vendored
View File

@ -4,3 +4,6 @@
[submodule "libs/bindbc-common"] [submodule "libs/bindbc-common"]
path = libs/bindbc-common path = libs/bindbc-common
url = https://github.com/BindBC/bindbc-common url = https://github.com/BindBC/bindbc-common
[submodule "libs/gl3n"]
path = libs/gl3n
url = https://github.com/holtrop/gl3n

View File

@ -13,8 +13,10 @@ env "app" do |env|
sources = dirs.reduce([]) do |result, dir| sources = dirs.reduce([]) do |result, dir|
result + glob("#{dir}/**/*.{d,c}") result + glob("#{dir}/**/*.{d,c}")
end end
sources += glob("libs/gl3n/gl3n/**/*.{d,c}")
env["D_IMPORT_PATH"] += dirs env["D_IMPORT_PATH"] += dirs
env["DFLAGS"] += %w[--d-version=BindBC_Static --d-version=SDL_208] env["D_IMPORT_PATH"] += ["libs/gl3n"]
env["DFLAGS"] += %w[--d-version=BindBC_Static --d-version=SDL_208 -g]
env["LDFLAGS"] += %w[-L-lfreetype -L-lSDL2] env["LDFLAGS"] += %w[-L-lfreetype -L-lSDL2]
env.Program("^/app", sources) env.Program("^/app", sources)
end end

1
libs/gl3n Submodule

@ -0,0 +1 @@
Subproject commit cb233335f50d9cc12f055715b9b42955bf3d379e

View File

@ -34,7 +34,7 @@ class Array
/** /**
* Bind array. * Bind array.
*/ */
void bind() const public void bind() const
{ {
glBindVertexArray(m_id); glBindVertexArray(m_id);
} }
@ -42,7 +42,7 @@ class Array
/** /**
* Get array ID. * Get array ID.
*/ */
@property GLuint id() const public @property GLuint id() const
{ {
return m_id; return m_id;
} }

View File

@ -5,21 +5,22 @@ import gl;
/** /**
* OpenGL buffer object. * OpenGL buffer object.
*/ */
class Buffer class BufferBase(GLenum target = GL_ARRAY_BUFFER)
{ {
/** Buffer ID. */ /** Buffer ID. */
private GLuint m_id; private GLuint m_id;
/** Buffer target. */
private GLenum m_target;
/** /**
* Construct buffer. * Construct buffer.
* *
* @param target * @param data
* OpenGL buffer target (e.g. GL_ARRAY_BUFFER, GL_ELEMENT_BUFFER) * Buffer data.
* @param size
* Buffer data size.
* @param usage
* OpenGL buffer usage (default is GL_STATIC_DRAW)
*/ */
this(GLenum target) this(const(void) * data = null, size_t size, GLenum usage = GL_STATIC_DRAW)
{ {
m_id = 0u; m_id = 0u;
glGenBuffers(1, &m_id); glGenBuffers(1, &m_id);
@ -27,7 +28,31 @@ class Buffer
{ {
throw new Exception("Failed to allocate an OpenGL buffer"); throw new Exception("Failed to allocate an OpenGL buffer");
} }
m_target = target; bind();
if (data != null)
{
set_buffer_data(data, size, usage);
}
}
/**
* Construct buffer.
*
* @param data
* Buffer data.
* @param usage
* OpenGL buffer usage (default is GL_STATIC_DRAW)
*/
this(T)(const(T)[] data = null, GLenum usage = GL_STATIC_DRAW)
{
if (data is null)
{
this(null, 0u, usage);
}
else
{
this(data.ptr, data.length * data[0].sizeof, usage);
}
} }
/** /**
@ -41,15 +66,15 @@ class Buffer
/** /**
* Bind buffer. * Bind buffer.
*/ */
void bind() const public void bind() const
{ {
glBindBuffer(m_target, m_id); glBindBuffer(target, m_id);
} }
/** /**
* Get buffer ID. * Get buffer ID.
*/ */
@property GLuint id() const public @property GLuint id() const
{ {
return m_id; return m_id;
} }
@ -57,28 +82,43 @@ class Buffer
/** /**
* Set buffer data. * Set buffer data.
* *
* @param usage * @param data
* OpenGL buffer usage (e.g. GL_STATIC_DRAW, ...)
* @param ptr
* Pointer to buffer data. * Pointer to buffer data.
* @param size * @param size
* Buffer data size. * Buffer data size.
* @param usage
* OpenGL buffer usage (default is GL_STATIC_DRAW)
*/ */
void set_buffer_data(GLenum usage, const void * ptr, size_t size) public void set_buffer_data(const(void) * data, size_t size, GLenum usage = GL_STATIC_DRAW) const
{ {
glNamedBufferData(m_id, size, ptr, usage); glBufferData(target, size, data, usage);
} }
/** /**
* Set buffer data. * Set buffer data.
* *
* @param data
* Buffer data.
* @param usage * @param usage
* OpenGL buffer usage (e.g. GL_STATIC_DRAW, ...) * OpenGL buffer usage (e.g. GL_STATIC_DRAW, ...)
* @param array
* Buffer data.
*/ */
void set_buffer_data(T)(GLenum usage, T[] arr) public void set_buffer_data(T)(const(T)[] data, GLenum usage = GL_STATIC_DRAW) const
{ {
glNamedBufferData(m_id, arr.length * arr[0].sizeof, arr.ptr, usage); glBufferData(target, data.length * data[0].sizeof, data.ptr, usage);
} }
} }
/**
* Convenience class alias for a Buffer with a GL_ARRAY_BUFFER target.
*/
alias Buffer = BufferBase!(GL_ARRAY_BUFFER);
/**
* Convenience class alias for a Buffer with a GL_ELEMENT_ARRAY_BUFFER target.
*/
alias ElementBuffer = BufferBase!(GL_ELEMENT_ARRAY_BUFFER);
/**
* Convenience class alias for a Buffer with a GL_UNIFORM_BUFFER target.
*/
alias UniformBuffer = BufferBase!(GL_UNIFORM_BUFFER);

View File

@ -20,7 +20,7 @@ import gl;
* Attributes are specified as an associative array with attribute names as * Attributes are specified as an associative array with attribute names as
* keys and attribute locations as values. * keys and attribute locations as values.
*/ */
class Program(string[string] uniforms = [], int[string] attributes = []) class Program(alias uniforms = [], alias attributes = [])
{ {
/** Program ID. */ /** Program ID. */
private GLuint m_id; private GLuint m_id;
@ -151,13 +151,13 @@ class Program(string[string] uniforms = [], int[string] attributes = [])
mixin("private GLint m_uniform_" ~ uniform_name ~ ";"); mixin("private GLint m_uniform_" ~ uniform_name ~ ";");
mixin("public void set_" ~ uniform_name ~ "(" ~ uniform_param_decl_list(uniform_type) ~ ") const" ~ mixin("public void set_" ~ uniform_name ~ "(" ~ uniform_param_decl_list(uniform_type) ~ ") const" ~
"{" ~ "{" ~
" glProgramUniform" ~ uniform_type ~ "(m_id, m_uniform_" ~ uniform_name ~ ", " ~ (uniform_type_info(uniform_type).v ? "1, " : "") ~ (uniform_type_info(uniform_type).matrix ? "false, " : "") ~ uniform_param_list(uniform_type) ~ ");" ~ " glProgramUniform" ~ uniform_type ~ "(m_id, m_uniform_" ~ uniform_name ~ ", " ~ (uniform_type_info(uniform_type).v ? "1, " : "") ~ (uniform_type_info(uniform_type).matrix ? "GL_FALSE, " : "") ~ uniform_param_list(uniform_type) ~ ");" ~
"}"); "}");
static if (uniform_type_info(uniform_type).v) static if (uniform_type_info(uniform_type).v)
{ {
mixin("public void set_" ~ uniform_name ~ "(GLsizei count, " ~ uniform_param_decl_list(uniform_type) ~ ") const" ~ mixin("public void set_" ~ uniform_name ~ "(GLsizei count, " ~ uniform_param_decl_list(uniform_type) ~ ") const" ~
"{" ~ "{" ~
" glProgramUniform" ~ uniform_type ~ "(m_id, m_uniform_" ~ uniform_name ~ ", count, " ~ (uniform_type_info(uniform_type).matrix ? "false, " : "") ~ uniform_param_list(uniform_type) ~ ");" ~ " glProgramUniform" ~ uniform_type ~ "(m_id, m_uniform_" ~ uniform_name ~ ", count, " ~ (uniform_type_info(uniform_type).matrix ? "GL_FALSE, " : "") ~ uniform_param_list(uniform_type) ~ ");" ~
"}"); "}");
} }
} }
@ -346,10 +346,12 @@ class Program(string[string] uniforms = [], int[string] attributes = [])
else if (shader_type != 0) else if (shader_type != 0)
{ {
shader_source ~= line; shader_source ~= line;
shader_source ~= "\n";
} }
else else
{ {
common_source ~= line; common_source ~= line;
common_source ~= "\n";
} }
} }

View File

@ -43,17 +43,20 @@ class Shader
string message = "Error compiling "; string message = "Error compiling ";
switch (shader_type) switch (shader_type)
{ {
case GL_VERTEX_SHADER: case GL_VERTEX_SHADER:
message ~= "vertex"; message ~= "vertex";
break; break;
case GL_FRAGMENT_SHADER: case GL_FRAGMENT_SHADER:
message ~= "fragment"; message ~= "fragment";
break; break;
default: default:
message ~= "unknown"; message ~= "unknown";
break; break;
} }
message ~= " shader"; message ~= " shader:\n";
message ~= "---\n";
message ~= source;
message ~= "---\n";
GLint log_length; GLint log_length;
glGetShaderiv(m_id, GL_INFO_LOG_LENGTH, &log_length); glGetShaderiv(m_id, GL_INFO_LOG_LENGTH, &log_length);
@ -61,7 +64,7 @@ class Shader
{ {
char[] log = new char[log_length]; char[] log = new char[log_length];
glGetShaderInfoLog(m_id, log_length, &log_length, log.ptr); glGetShaderInfoLog(m_id, log_length, &log_length, log.ptr);
message ~= "\nShader Log:\n"; message ~= "Shader Log:\n";
message ~= log; message ~= log;
message ~= "\n"; message ~= "\n";
} }
@ -80,7 +83,7 @@ class Shader
/** /**
* Get shader ID. * Get shader ID.
*/ */
@property GLuint id() const public @property GLuint id() const
{ {
return m_id; return m_id;
} }

View File

@ -3,10 +3,17 @@ import sdl;
import gl; import gl;
import glad.gl.loader; import glad.gl.loader;
import gltk; import gltk;
import gl3n.linalg;
enum int WIDTH = 800; enum int WIDTH = 800;
enum int HEIGHT = 600; enum int HEIGHT = 600;
alias ColorShader = Program!(["view": "Matrix4fv"], ["position": 0, "color": 1]);
ColorShader color_shader;
Array spinny_vao;
GLuint program_id;
mat4 view_matrix;
void init() void init()
{ {
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
@ -15,12 +22,65 @@ void init()
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glClearColor (1.0, 0.6, 0.0, 0.0); glClearColor (1.0, 0.6, 0.0, 0.0);
glViewport(0, 0, WIDTH, HEIGHT); glViewport(0, 0, WIDTH, HEIGHT);
spinny_vao = new Array();
spinny_vao.bind();
string color_program_src = `
#version 450
uniform mat4 view;
vertex:
in vec2 position;
in vec4 color;
out vec4 color_i;
void main(void)
{
gl_Position = view * vec4(position, 0.0, 1.0);
color_i = color;
}
fragment:
in vec4 color_i;
out vec4 frag_color;
void main(void)
{
frag_color = color_i;
}`;
color_shader = new ColorShader(color_program_src);
color_shader.use();
float[] vertices = [0.4, 0.4, -0.4, 0.4, -0.4, -0.4, 0.4, -0.4];
float[] colors = [
1.0, 0.0, 0.0, 1.0,
0.0, 1.0, 0.0, 1.0,
0.0, 0.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0];
ushort[] indices = [0, 1, 2, 3];
Buffer vbo = new Buffer(vertices);
vbo.bind();
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, null);
Buffer cbo = new Buffer(colors);
cbo.bind();
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, null);
ElementBuffer ibo = new ElementBuffer(indices);
ibo.bind();
} }
void display(SDL_Window * window) void display(SDL_Window * window)
{ {
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
color_shader.use();
spinny_vao.bind();
view_matrix.make_identity();
view_matrix.scale(HEIGHT / cast(float)WIDTH, 1.0, 1.0);
view_matrix.rotatez(SDL_GetTicks() / 500.0);
color_shader.set_view(view_matrix.value_ptr);
glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_SHORT, null);
SDL_GL_SwapWindow(window); SDL_GL_SwapWindow(window);
} }