Created
May 12, 2011 00:27
-
-
Save kovrov/967695 to your computer and use it in GitHub Desktop.
glsl_test.d
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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