Skip to content

Instantly share code, notes, and snippets.

@kovrov
Created May 12, 2011 00:27
Show Gist options
  • Select an option

  • Save kovrov/967695 to your computer and use it in GitHub Desktop.

Select an option

Save kovrov/967695 to your computer and use it in GitHub Desktop.
glsl_test.d
import std.stdio;
import std.conv;
import std.string : toStringz;
import gl;
import glut;
class ShaderException : Exception
{
this(GLuint shader, string file = __FILE__, uint line = __LINE__)
{
GLint length;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
char[] buffer = new char[length];
glGetShaderInfoLog(shader, length, null, buffer.ptr);
super(to!string(buffer), file, line);
}
}
class Program
{
GLuint id;
this(const Shader[] shaders)
{
GLenum error = glGetError();
this.id = glCreateProgram();
foreach (shader; shaders) glAttachShader(this.id, shader.id);
glLinkProgram(this.id);
glUseProgram(this.id);
error = glGetError();
if (error != GL_NO_ERROR) // Could not create the shader program
throw new Exception(to!string(gluErrorString(error)));
}
~this()
{
GLenum error = glGetError();
glUseProgram(0);
glDeleteProgram(this.id);
error = glGetError();
if (error != GL_NO_ERROR) // Could not destroy the shader program
throw new Exception(to!string(gluErrorString(error)));
}
}
class Shader
{
GLuint id;
this(GLenum shader_type, string shader_code)
{
this.id = glCreateShader(shader_type);
assert (this.id);
auto shader_code_ptr = shader_code.ptr;
glShaderSource(this.id, 1, &shader_code_ptr, null);
glCompileShader(this.id);
GLint compile_success;
glGetShaderiv(this.id, GL_COMPILE_STATUS, &compile_success);
if (compile_success != GL_TRUE)
throw new ShaderException(this.id);
}
~this()
{
glDeleteShader(this.id);
}
}
// http://www.opengl.org/registry/specs/ARB/vertex_buffer_object.txt
class VertexBufferObject(T)
{
GLuint id;
GLuint vao_id;
GLsizei count;
this()
{
glGenBuffers(1, &this.id);
glGenVertexArrays(1, &this.vao_id);
}
~this()
{
GLenum error = glGetError();
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDeleteBuffers(1, &this.id);
error = glGetError();
if (error != GL_NO_ERROR) // Could not destroy the VBO
throw new Exception(to!string(gluErrorString(error)));
glBindVertexArray(0);
glDeleteVertexArrays(1, &this.vao_id);
error = glGetError();
if (error != GL_NO_ERROR) // Could not destroy the VAO
throw new Exception(to!string(gluErrorString(error)));
}
void draw()
{
glBindVertexArray(this.vao_id);
glDrawArrays(GL_POLYGON, 0, this.count);
glBindVertexArray(0);
}
@property
void bufferData(GLenum usage)(const T[] vertices)
{
GLenum error = glGetError();
glBindBuffer(GL_ARRAY_BUFFER, this.id);
glBufferData(GL_ARRAY_BUFFER, vertices.length * T.sizeof, vertices.ptr, usage);
glBindBuffer(GL_ARRAY_BUFFER, 0);
error = glGetError();
if (error != GL_NO_ERROR)
throw new Exception(to!string(gluErrorString(error)));
this.count = cast(GLsizei)vertices.length;
}
void vertexAttrib(GLint location, size_t offset)
{
glBindVertexArray(this.vao_id);
glBindBuffer(GL_ARRAY_BUFFER, this.id);
glVertexAttribPointer(location, 4, GL_FLOAT, GL_FALSE, T.sizeof, cast(GLvoid*)(offset));
glBindBuffer(GL_ARRAY_BUFFER, 0);
glEnableVertexAttribArray(location);
glBindVertexArray(0);
}
}
class Ctx
{
Shader fragmentShader;
Shader vertexShader;
Program program;
VertexBufferObject!Vertex vbo;
this()
{
writefln("INFO: OpenGL Version: %s", to!string(glGetString(GL_VERSION)));
// generic
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
// create shaders
this.vertexShader = new Shader(GL_VERTEX_SHADER,
`
#version 120
attribute vec4 in_Position;
attribute vec4 in_Color;
void main()
{
gl_Position = in_Position;
gl_FrontColor = in_Color;
}
`);
this.fragmentShader = new Shader(GL_FRAGMENT_SHADER,
`
#version 120
void main()
{
gl_FragColor = gl_Color;
}
`);
this.program = new Program([this.vertexShader, this.fragmentShader]);
// create buffers
this.vbo = new VertexBufferObject!Vertex;
this.vbo.vertexAttrib(glGetAttribLocation(this.program.id, "in_Position"), 0);
this.vbo.vertexAttrib(glGetAttribLocation(this.program.id, "in_Color"), float.sizeof*4); // Vertex.RGBA.offsetof
}
~this()
{
// destroy buffers
delete this.vbo;
// destroy shaders
delete this.fragmentShader;
delete this.vertexShader;
delete this.program;
}
}
struct Vertex
{
float XYZW[4];
float RGBA[4];
}
int CurrentWidth = 256,
CurrentHeight = 256,
WindowHandle;
Ctx g_ctx;
void main(string[] args)
{
InitWindow(args);
g_ctx = new Ctx();
scope (exit) delete g_ctx;
glutMainLoop();
}
void InitWindow(string[] args)
{
auto c_args = new immutable(char)*[args.length];
foreach (int i, string arg; args) c_args[i] = toStringz(arg);
auto argc = cast(int)c_args.length;
glutInit(&argc, c_args.ptr);
glutSetOption(GLUT.ACTION_ON_WINDOW_CLOSE, GLUT.ACTION_GLUTMAINLOOP_RETURNS);
glutInitWindowSize(CurrentWidth, CurrentHeight);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
WindowHandle = glutCreateWindow("glsl test");
if (WindowHandle < 1)
throw new Exception("Could not create a new rendering window.");
glutReshapeFunc(&ResizeFunction);
glutDisplayFunc(&RenderFunction);
}
void ResizeFunction(int Width, int Height)
{
CurrentWidth = Width;
CurrentHeight = Height;
glViewport(0, 0, CurrentWidth, CurrentHeight);
}
void RenderFunction()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
g_ctx.vbo.bufferData!GL_STREAM_DRAW = [
Vertex([-0.8f, -0.8f, 0.0f, 1.0f], [ 1.0f, 0.0f, 0.0f, 1.0f]),
Vertex([ 0.0f, 0.8f, 0.0f, 1.0f], [ 0.0f, 1.0f, 0.0f, 1.0f]),
Vertex([ 0.8f, -0.8f, 0.0f, 1.0f], [ 0.0f, 0.0f, 1.0f, 1.0f])];
g_ctx.vbo.draw();
glutSwapBuffers();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment