1 /* 2 ******************************************************************************************* 3 * Dgame (a D game framework) - Copyright (c) Randy Schütt 4 * 5 * This software is provided 'as-is', without any express or implied warranty. 6 * In no event will the authors be held liable for any damages arising from 7 * the use of this software. 8 * 9 * Permission is granted to anyone to use this software for any purpose, 10 * including commercial applications, and to alter it and redistribute it 11 * freely, subject to the following restrictions: 12 * 13 * 1. The origin of this software must not be misrepresented; you must not claim 14 * that you wrote the original software. If you use this software in a product, 15 * an acknowledgment in the product documentation would be appreciated but is 16 * not required. 17 * 18 * 2. Altered source versions must be plainly marked as such, and must not be 19 * misrepresented as being the original software. 20 * 21 * 3. This notice may not be removed or altered from any source distribution. 22 ******************************************************************************************* 23 */ 24 module Dgame.System.VertexRenderer; 25 26 private { 27 import derelict.opengl3.gl; 28 29 import Dgame.Internal.Log; 30 import Dgame.Graphics.Shape; 31 } 32 33 /** 34 * Declare which data is stored. Possible are Vertices, Colors or Texture coordinates. 35 */ 36 enum Target { 37 None = 0, /** Declare that the data consist of nothing relevant. */ 38 Vertex = 1, /** Declare that the data consist of vertices. */ 39 Color = 2, /** Declare that the data consist of colors. */ 40 TexCoords = 4 /** Declare that the data consist of texture coordinates. */ 41 } 42 43 /** 44 * Buffer is a wrapper for a static Vertex Array. 45 * <b>It has nothing to do with the class VertexArray</b> 46 * 47 * Author: rschuett 48 */ 49 final abstract class VertexRenderer { 50 /** 51 * Points to a specific Target. 52 * 53 * See: glVertexPointer 54 * See: glColorPointer 55 * See: glTexCoordPointer 56 * See: Target enum. 57 * 58 * Note: This method expects a <b>single</b> Target. 59 */ 60 static void pointTo(Target trg, void* ptr = null, ubyte stride = 0, ubyte offset = 0) { 61 VertexRenderer.enableState(trg); 62 63 if (ptr !is null) 64 ptr += offset; 65 else if (offset != 0) 66 ptr = cast(void*)(offset); 67 68 final switch (trg) { 69 case Target.None: 70 Log.error("Invalid Target"); 71 break; 72 case Target.Vertex: 73 glVertexPointer(3, GL_FLOAT, stride, ptr); 74 break; 75 case Target.Color: 76 glColorPointer(4, GL_FLOAT, stride, ptr); 77 break; 78 case Target.TexCoords: 79 glTexCoordPointer(2, GL_FLOAT, stride, ptr); 80 break; 81 } 82 } 83 84 /** 85 * Points to a specific Target. 86 * 87 * See: glVertexPointer 88 * See: glColorPointer 89 * See: glTexCoordPointer 90 * See: Target enum. 91 */ 92 static void pointTo(Target trg, const ubyte[Target] stride, const ubyte[Target] offset, void* ptr) { 93 if (trg & Target.None) 94 Log.error("Invalid Target"); 95 96 @safe 97 ubyte deref(const ubyte* ptr) pure nothrow { 98 return ptr !is null ? *ptr : 0; 99 } 100 101 if (trg & Target.Vertex) 102 VertexRenderer.pointTo(Target.Vertex, ptr, 103 deref(Target.Vertex in stride), 104 deref(Target.Vertex in offset)); 105 if (trg & Target.Color) 106 VertexRenderer.pointTo(Target.Color, ptr, 107 deref(Target.Color in stride), 108 deref(Target.Color in offset)); 109 if (trg & Target.TexCoords) 110 VertexRenderer.pointTo(Target.TexCoords, ptr, 111 deref(Target.TexCoords in stride), 112 deref(Target.TexCoords in offset)); 113 } 114 115 /** 116 * Enable a specific client state (with glEnableClientState) 117 * like GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY 118 * with the corresponding Target. 119 */ 120 static void enableState(Target trg) { 121 if (trg & Target.None) 122 Log.error("Invalid Target"); 123 124 if (trg & Target.Vertex) 125 glEnableClientState(GL_VERTEX_ARRAY); 126 if (trg & Target.Color) 127 glEnableClientState(GL_COLOR_ARRAY); 128 if (trg & Target.TexCoords) 129 glEnableClientState(GL_TEXTURE_COORD_ARRAY); 130 } 131 132 /** 133 * Enable all client states 134 */ 135 static void enableAllStates() { 136 VertexRenderer.enableState(Target.Vertex | Target.Color | Target.TexCoords); 137 } 138 139 /** 140 * Disable all client states 141 */ 142 static void disableAllStates() { 143 VertexRenderer.disableState(Target.Vertex | Target.Color | Target.TexCoords); 144 } 145 146 /** 147 * Disable a specific client state (with glDisableClientState) 148 */ 149 static void disableState(Target trg) { 150 if (trg & Target.None) 151 Log.error("Invalid Target"); 152 153 if (trg & Target.Vertex) 154 glDisableClientState(GL_VERTEX_ARRAY); 155 if (trg & Target.Color) 156 glDisableClientState(GL_COLOR_ARRAY); 157 if (trg & Target.TexCoords) 158 glDisableClientState(GL_TEXTURE_COORD_ARRAY); 159 } 160 161 /** 162 * Draw Shapes of a specific type from the data which is addressed through 'pointTo'. 163 * It will use count vertices. 164 * 165 * See: pointTo 166 */ 167 static void drawArrays(Shape.Type ptype, size_t count, size_t start = 0) { 168 glDrawArrays(ptype, cast(uint) start, cast(uint) count); 169 } 170 171 /** 172 * Draw Shapes of a specific type from the data which is addressed through 'pointTo'. 173 * It will use count vertices and indices for the correct index per vertex. 174 * 175 * See: pointTo 176 */ 177 static void drawElements(Shape.Type ptype, size_t count, uint[] indices) { 178 if (indices.length == 0) 179 return; 180 181 glDrawElements(ptype, cast(uint) count, GL_UNSIGNED_INT, &indices[0]); 182 } 183 184 /** 185 * Draw Shapes of a specific type from the data which is addressed through 'pointTo'. 186 * It will use count vertices and indices for the correct index per vertex. 187 * 188 * Note: If start or end are -1 or below, 0 and indices.length are used. 189 * 190 * See: pointTo 191 */ 192 static void drawRangeElements(Shape.Type ptype, size_t count, uint[] indices, uint start = 0, uint end = 0) { 193 if (indices.length == 0) 194 return; 195 196 glDrawRangeElements(ptype, start, end != 0 ? end : cast(uint) indices.length, cast(uint) count, GL_UNSIGNED_INT, &indices[0]); 197 } 198 }