1 /** 2 * Defines the Material and Texture classes. 3 */ 4 module dash.components.material; 5 import dash.core, dash.components, dash.graphics, dash.utility; 6 7 import yaml; 8 import derelict.opengl3.gl3, derelict.freeimage.freeimage; 9 import std.variant, std.conv, std..string; 10 11 mixin( registerComponents!() ); 12 13 /** 14 * A collection of textures that serve different purposes in the rendering pipeline. 15 */ 16 final class MaterialAsset : Asset 17 { 18 public: 19 /// The name of the material. 20 @rename( "Name" ) 21 string name; 22 /// The diffuse (or color) map. 23 @rename( "Diffuse" ) @asArray @optional 24 Texture diffuse; 25 /// The normal map, which specifies which way a face is pointing at a given pixel. 26 @rename( "Normal" ) @asArray @optional 27 Texture normal; 28 /// The specular map, which specifies how shiny a given point is. 29 @rename( "Specular" ) @asArray @optional 30 Texture specular; 31 32 /** 33 * Default constructor, makes sure everything is initialized to default. 34 */ 35 this( string name = "" ) 36 { 37 super( internalResource ); 38 diffuse = specular = defaultTex; 39 normal = defaultNormal; 40 this.name = name; 41 } 42 43 /** 44 * Duplicate the material. 45 */ 46 MaterialAsset clone() 47 { 48 auto mat = new MaterialAsset; 49 mat.diffuse = diffuse; 50 mat.normal = normal; 51 mat.specular = specular; 52 mat.name = name; 53 return mat; 54 } 55 56 /** 57 * Shuts down the material, making sure all references are released. 58 */ 59 override void shutdown() 60 { 61 diffuse = specular = normal = null; 62 } 63 } 64 65 /** 66 * A reference to a material. 67 */ 68 final class Material : AssetRef!MaterialAsset 69 { 70 alias asset this; 71 72 this() { } 73 this( MaterialAsset ass ) 74 { 75 super( ass ); 76 } 77 78 override void initialize() 79 { 80 super.initialize(); 81 82 // All materials should be unique. 83 if( asset ) 84 asset = asset.clone(); 85 86 asset.diffuse.initialize(); 87 asset.normal.initialize(); 88 asset.specular.initialize(); 89 } 90 } 91 92 /** 93 * TODO 94 */ 95 class TextureAsset : Asset 96 { 97 protected: 98 uint _width = 1; 99 uint _height = 1; 100 uint _glID; 101 102 /** 103 * TODO 104 * 105 * Params: 106 */ 107 this( ubyte* buffer, Resource filePath ) 108 { 109 super( filePath ); 110 glGenTextures( 1, &_glID ); 111 glBindTexture( GL_TEXTURE_2D, glID ); 112 updateBuffer( buffer ); 113 } 114 115 /** 116 * TODO 117 * 118 * Params: 119 */ 120 void updateBuffer( const ubyte* buffer ) 121 { 122 // Set texture to update 123 glBindTexture( GL_TEXTURE_2D, glID ); 124 125 // Update texture 126 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 127 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 128 glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, _width, _height, 0, GL_BGRA, GL_UNSIGNED_BYTE, buffer ); 129 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); 130 } 131 132 public: 133 /// TODO 134 mixin( Property!_width ); 135 /// TODO 136 mixin( Property!_height ); 137 /// TODO 138 mixin( Property!_glID ); 139 140 /** 141 * TODO 142 * 143 * Params: 144 */ 145 this( Resource filePath ) 146 { 147 auto imageData = loadFreeImage( filePath.fullPath ); 148 149 this( cast(ubyte*)FreeImage_GetBits( imageData ), filePath ); 150 151 FreeImage_Unload( imageData ); 152 } 153 154 /** 155 * Refresh the asset. 156 */ 157 override void refresh() 158 { 159 auto imageData = loadFreeImage( resource.fullPath ); 160 161 updateBuffer( cast(ubyte*)FreeImage_GetBits( imageData ) ); 162 163 FreeImage_Unload( imageData ); 164 } 165 166 /** 167 * TODO 168 */ 169 override void shutdown() 170 { 171 glBindTexture( GL_TEXTURE_2D, 0 ); 172 glDeleteBuffers( 1, &_glID ); 173 } 174 175 private: 176 auto loadFreeImage( string filePath ) 177 { 178 filePath ~= '\0'; 179 auto imageData = FreeImage_ConvertTo32Bits( FreeImage_Load( FreeImage_GetFileType( filePath.ptr, 0 ), filePath.ptr, 0 ) ); 180 181 width = FreeImage_GetWidth( imageData ); 182 height = FreeImage_GetHeight( imageData ); 183 184 return imageData; 185 } 186 } 187 188 /** 189 * A reference to a texture. 190 */ 191 class Texture : AssetRef!TextureAsset 192 { 193 alias asset this; 194 195 this() { } 196 this( TextureAsset ass ) 197 { 198 super( ass ); 199 } 200 } 201 202 /** 203 * A default black texture. 204 */ 205 @property Texture defaultTex() 206 { 207 static Texture def; 208 209 if( !def ) 210 def = new Texture( new TextureAsset( [cast(ubyte)0, cast(ubyte)0, cast(ubyte)0, cast(ubyte)255].ptr, internalResource ) ); 211 212 return def; 213 } 214 215 /** 216 * A default gray texture 217 */ 218 @property Texture defaultNormal() 219 { 220 static Texture def; 221 222 if( !def ) 223 def = new Texture( new TextureAsset( [cast(ubyte)255, cast(ubyte)127, cast(ubyte)127, cast(ubyte)255].ptr, internalResource ) ); 224 225 return def; 226 }