1 /** 2 Copyright: Copyright (c) 2017-2018 Andrey Penechko. 3 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). 4 Authors: Andrey Penechko. 5 */ 6 7 module voxelman.world.mesh.vertex; 8 9 import voxelman.model.vertex; 10 import voxelman.graphics.gl; 11 import voxelman.graphics.irenderer; 12 import voxelman.graphics.shaderprogram; 13 import voxelman.graphics.shaders; 14 import voxelman.math; 15 import voxelman.graphics.color; 16 17 //alias MeshVertex = VertexPosUvColor!(float, 3, ubyte, 4); 18 //alias MeshVertex = VertexPosColor!(float, 3, ubyte, 4); 19 //alias MeshVertex = MeshVertex8; 20 alias MeshVertex = MeshVertex16; 21 22 //alias ChunkShader = ChunkShader8; 23 alias ChunkShader = ChunkShader16; 24 25 struct MeshVertex16 26 { 27 vec3 position; 28 ubyte[2] uv; 29 ubyte gray; 30 31 this(T)(Vector!(T, 3) pos, ubyte[2] uv, ubyte gray) { 32 set(pos.x, pos.y, pos.z, uv, gray); 33 } 34 this(float x, float y, float z, ubyte[2] uv, ubyte gray) { 35 set(x, y, z, uv, gray); 36 } 37 38 void set(float x, float y, float z, ubyte[2] uv, ubyte gray) { 39 position.x = x; 40 position.y = y; 41 position.z = z; 42 this.uv = uv; 43 this.gray = gray; 44 } 45 46 void addOffset(vec3 offset) 47 { 48 position += offset; 49 } 50 51 static void setAttributes() { 52 enum Size = typeof(this).sizeof; 53 // (int index, int numComponents, AttrT, bool normalize, int totalVertSize, int offset) 54 setupAttribute!(0, 3, float, false, true, Size, position.offsetof); 55 setupAttribute!(1, 3, ubyte, false, true, Size, uv.offsetof); 56 } 57 58 void toString()(scope void delegate(const(char)[]) sink) { 59 import std.format : formattedWrite; 60 sink.formattedWrite("v(%s, %s, %s)", position, uv, gray); 61 } 62 } 63 static assert(MeshVertex16.sizeof == 16); 64 65 struct MeshVertex8 66 { 67 uint packed_position; 68 ubyte[2] uv; 69 ubyte gray; 70 71 vec3 position() @property { 72 return vec3( 73 (packed_position >> 0) & 1023, 74 (packed_position >> 10) & 1023, 75 (packed_position >> 20) & 1023) / 31; 76 } 77 78 this(T)(Vector!(T, 3) pos, ubyte[2] uv, ubyte gray) { 79 set(cast(int)(pos.x * 31), cast(int)(pos.y * 31), cast(int)(pos.z * 31), uv, gray); 80 } 81 this(int x, int y, int z, ubyte[2] uv, ubyte gray) { 82 set(x * 31, y * 31, z * 31, uv, gray); 83 } 84 85 private void set(int x, int y, int z, ubyte[2] uv, ubyte gray) { 86 packed_position = ((x & 1023) << 0) | ((y & 1023) << 10) | ((z & 1023) << 20); 87 this.uv = uv; 88 this.gray = gray; 89 } 90 91 void addOffset(vec3 offset) 92 { 93 uint pos = ((cast(int)(offset.x * 31) & 1023) << 0) | ((cast(int)(offset.y * 31) & 1023) << 10) | ((cast(int)(offset.z * 31) & 1023) << 20); 94 packed_position += pos; 95 } 96 97 static void setAttributes() { 98 enum Size = typeof(this).sizeof; 99 // (int index, int numComponents, AttrT, bool normalize, int totalVertSize, int offset) 100 glEnableVertexAttribArray(0); 101 checkgl!glVertexAttribPointer(0, 4, GL_UNSIGNED_INT_2_10_10_10_REV, false, Size, cast(void*)packed_position.offsetof); 102 setupAttribute!(1, 3, ubyte, false, true, Size, uv.offsetof); 103 //setupAttribute!(2, 1, ubyte, true, true, Size, gray.offsetof); 104 } 105 106 void toString()(scope void delegate(const(char)[]) sink) { 107 import std.format : formattedWrite; 108 sink.formattedWrite("v(%s, %s, %s)", position, uv, gray); 109 } 110 111 /* 112 this(T)(Vector!(T, 3) pos, ubvec3 color) { set(cast(int)(pos.x * 31), cast(int)(pos.y * 31), cast(int)(pos.z * 31), color.arrayof); } 113 this(T)(Vector!(T, 3) pos, ubyte[3] color) {set(cast(int)(pos.x * 31), cast(int)(pos.y * 31), cast(int)(pos.z * 31), color); } 114 this(int x, int y, int z, ubyte[3] color) {set(x * 31, y * 31, z * 31, color); } 115 116 void set(int x, int y, int z, ubyte[3] color) { 117 packed_position = ((x & 1023) << 0) | ((y & 1023) << 10) | ((z & 1023) << 20) | 0b01_00000_00000_00000_00000_00000_00000; 118 this.color = color; 119 } 120 121 static void setAttributes() { 122 enum Size = typeof(this).sizeof; 123 // (int index, int numComponents, AttrT, bool normalize, int totalVertSize, int offset) 124 glEnableVertexAttribArray(0); 125 checkgl!glVertexAttribPointer(0, 4, GL_UNSIGNED_INT_2_10_10_10_REV, false, Size, cast(void*)packed_position.offsetof); 126 setupAttribute!(1, 3, ubyte, true, true, Size, color.offsetof); 127 } 128 */ 129 } 130 static assert(MeshVertex8.sizeof == 8); 131 132 string chunk_vert_shader8 = ` 133 #version 330 134 135 layout(location = 0) in vec3 packed_position; 136 layout(location = 1) in vec3 uv_shade; 137 138 uniform sampler2D atlas_uniform; 139 uniform mat4 mvp; 140 141 smooth out float frag_shade; 142 out vec2 frag_uv; 143 144 void main() { 145 gl_Position = mvp * vec4(packed_position/31, 1); 146 frag_uv = uv_shade.xy*32 / textureSize(atlas_uniform, 0); 147 frag_shade = uv_shade.z / 255; 148 } 149 `; 150 151 string chunk_frag_shader8 = ` 152 #version 330 153 154 smooth in float frag_shade; 155 in vec2 frag_uv; 156 157 uniform sampler2D atlas_uniform; 158 uniform float transparency; 159 160 out vec4 out_color; 161 162 void main() { 163 vec3 color = vec3(frag_shade * texture(atlas_uniform, frag_uv)); 164 out_color = vec4(color, transparency); 165 } 166 `; 167 168 struct ChunkShader8 169 { 170 ShaderProgram shader; 171 alias shader this; 172 173 GLint transparency_location = -1; 174 GLint mvp_location = -1; 175 176 void setMvp(Matrix4f mvp) { checkgl!glUniformMatrix4fv(mvp_location, 1, GL_FALSE, mvp.arrayof.ptr); } 177 void setTransparency(float transparency) { checkgl!glUniform1f(transparency_location, transparency); } 178 179 void compile(IRenderer renderer) { 180 shader = renderer.createShaderProgram(chunk_vert_shader8, chunk_frag_shader8); 181 182 transparency_location = checkgl!glGetUniformLocation(handle, "transparency"); 183 mvp_location = checkgl!glGetUniformLocation(handle, "mvp"); 184 } 185 } 186 187 string chunk_vert_shader16 = ` 188 #version 330 189 190 layout(location = 0) in vec3 packed_position; 191 layout(location = 1) in vec3 uv_shade; 192 193 uniform sampler2D atlas_uniform; 194 uniform mat4 mvp; 195 196 smooth out float frag_shade; 197 out vec2 frag_uv; 198 199 void main() { 200 gl_Position = mvp * vec4(packed_position, 1); 201 frag_uv = uv_shade.xy*32 / textureSize(atlas_uniform, 0); 202 frag_shade = uv_shade.z / 255; 203 } 204 `; 205 206 struct ChunkShader16 207 { 208 ShaderProgram shader; 209 alias shader this; 210 211 GLint transparency_location = -1; 212 GLint mvp_location = -1; 213 214 void setMvp(Matrix4f mvp) { checkgl!glUniformMatrix4fv(mvp_location, 1, GL_FALSE, mvp.arrayof.ptr); } 215 void setTransparency(float transparency) { checkgl!glUniform1f(transparency_location, transparency); } 216 217 void compile(IRenderer renderer) { 218 shader = renderer.createShaderProgram(chunk_vert_shader16, chunk_frag_shader8); 219 220 transparency_location = checkgl!glGetUniformLocation(handle, "transparency"); 221 mvp_location = checkgl!glGetUniformLocation(handle, "mvp"); 222 } 223 }