1 /* 2 * Copyright (c) 2007-2013 Scott Lembcke and Howling Moon Software 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a copy 5 * of this software and associated documentation files (the "Software"), to deal 6 * in the Software without restriction, including without limitation the rights 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 * copies of the Software, and to permit persons to whom the Software is 9 * furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 * SOFTWARE. 21 */ 22 module demo.ChipmunkDemoShaderSupport; 23 24 import core.stdc.stdlib; 25 26 import std.conv; 27 import std.stdio; 28 import std..string; 29 30 import demo.dchip; 31 32 import glad.gl.all; 33 import glad.gl.loader; 34 35 string SET_ATTRIBUTE(string program, string type, string name, string gltype) 36 { 37 return q{ 38 SetAttribute(program, "%1$s", %2$s.%1$s.sizeof / GLfloat.sizeof, %3$s, %2$s.sizeof, cast(GLvoid *)%2$s.%1$s.offsetof); 39 }.format(name, type, gltype); 40 } 41 42 /// Converts an OpenGL errorenum to a string 43 string toString(GLenum error) 44 { 45 switch (error) 46 { 47 case GL_INVALID_ENUM: 48 return "An unacceptable value is specified for an enumerated argument."; 49 50 case GL_INVALID_VALUE: 51 return "A numeric argument is out of range."; 52 53 case GL_INVALID_OPERATION: 54 return "The specified operation is not allowed in the current state."; 55 56 case GL_INVALID_FRAMEBUFFER_OPERATION: 57 return "The framebuffer object is not complete."; 58 59 case GL_OUT_OF_MEMORY: 60 return "There is not enough memory left to execute the command. WARNING: GL operation is undefined."; 61 62 case GL_STACK_UNDERFLOW: 63 return "An attempt has been made to perform an operation that would cause an internal stack to underflow."; 64 65 case GL_STACK_OVERFLOW: 66 return "An attempt has been made to perform an operation that would cause an internal stack to overflow."; 67 68 default: 69 assert(0, format("Unhandled GLenum error state: '%s'", error)); 70 } 71 } 72 73 void CheckGLErrors() 74 { 75 for (GLenum err = glGetError(); err; err = glGetError()) 76 { 77 if (err) 78 { 79 stderr.writefln("Error: - %s", err.toString()); 80 stderr.writefln("GLError(%s:%d) 0x%04X\n", __FILE__, __LINE__, err); 81 assert(0); 82 } 83 } 84 } 85 86 alias PFNGLGETSHADERIVPROC = fp_glGetShaderiv; 87 alias PFNGLGETSHADERINFOLOGPROC = fp_glGetProgramInfoLog; 88 89 //typedef GLAPIENTRY void (*GETIV)(GLuint shader, GLenum pname, GLint *params); 90 //typedef GLAPIENTRY void (*GETINFOLOG)(GLuint shader, GLsizei maxLength, GLsizei *length, GLchar *infoLog); 91 92 static cpBool CheckError(GLint obj, GLenum status, PFNGLGETSHADERIVPROC getiv, PFNGLGETSHADERINFOLOGPROC getInfoLog) 93 { 94 GLint success; 95 getiv(obj, status, &success); 96 97 if (!success) 98 { 99 GLint length; 100 getiv(obj, GL_INFO_LOG_LENGTH, &length); 101 102 char* log = cast(char*)alloca(length); 103 getInfoLog(obj, length, null, log); 104 105 stderr.writefln("Shader compile error for 0x%04X: %s\n", status, log.to!string); 106 return cpFalse; 107 } 108 else 109 { 110 return cpTrue; 111 } 112 } 113 114 GLint CompileShader(GLenum type, string source) 115 { 116 GLint shader = glCreateShader(type); 117 118 auto ssp = source.ptr; 119 int ssl = cast(int)(source.length); 120 glShaderSource(shader, 1, &ssp, &ssl); 121 glCompileShader(shader); 122 123 // TODO return placeholder shader instead? 124 cpAssertHard(CheckError(shader, GL_COMPILE_STATUS, glGetShaderiv, glGetShaderInfoLog), "Error compiling shader"); 125 126 return shader; 127 } 128 129 GLint LinkProgram(GLint vshader, GLint fshader) 130 { 131 GLint program = glCreateProgram(); 132 133 glAttachShader(program, vshader); 134 glAttachShader(program, fshader); 135 glLinkProgram(program); 136 137 // todo return placeholder program instead? 138 cpAssertHard(CheckError(program, GL_LINK_STATUS, glGetProgramiv, glGetProgramInfoLog), "Error linking shader program"); 139 140 return program; 141 } 142 143 cpBool ValidateProgram(GLint program) 144 { 145 // TODO 146 return cpTrue; 147 } 148 149 void SetAttribute(GLuint program, string name, GLint size, GLenum gltype, GLsizei stride, GLvoid* offset) 150 { 151 GLint index = glGetAttribLocation(program, name.toStringz); 152 glEnableVertexAttribArray(index); 153 glVertexAttribPointer(index, size, gltype, GL_FALSE, stride, offset); 154 }