1 /* 2 * BSD 3-Clause License 3 * 4 * Copyright (c) 2016, Mango-Engine Team 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions are met: 9 * 10 * * Redistributions of source code must retain the above copyright notice, this 11 * list of conditions and the following disclaimer. 12 * 13 * * Redistributions in binary form must reproduce the above copyright notice, 14 * this list of conditions and the following disclaimer in the documentation 15 * and/or other materials provided with the distribution. 16 * 17 * * Neither the name of the copyright holder nor the names of its 18 * contributors may be used to endorse or promote products derived from 19 * this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 module mango_engine.graphics.opengl.gl_texture; 33 34 version(mango_GLBackend) { 35 import mango_engine.game; 36 import mango_engine.graphics.texture; 37 38 import blocksound.util : toCString; 39 40 import derelict.opengl3.gl3; 41 import derelict.freeimage.freeimage; 42 43 /// Uses FreeImage to load a BitMap. 44 FIBITMAP* loadImageBitMap(in string file) @system { 45 FIBITMAP* map; 46 FREE_IMAGE_FORMAT format; 47 48 format = FreeImage_GetFileType(toCString(file), 0); 49 50 if(format == FIF_UNKNOWN) { 51 throw new ImageLoadException(file ~ " has an unknown format!"); 52 } 53 if(!FreeImage_FIFSupportsReading(format)) { 54 throw new ImageLoadException(file ~ " is not supported for reading!"); 55 } 56 57 map = FreeImage_Load(format, toCString(file)); 58 return map; 59 } 60 61 class GLTexture : Texture { 62 package shared GLuint textureId; 63 64 this(GameManager game, in string name, in string filename, in bool useAlpha = true) @safe { 65 super(game, name, filename, useAlpha); 66 67 this.game.renderer.submitOperation(&this.doLoad); 68 } 69 70 void use() @system nothrow { 71 glBindTexture(GL_TEXTURE_2D, this.textureId); 72 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 73 } 74 75 private void doLoad() @trusted { 76 FIBITMAP* map = loadImageBitMap(this.filename); 77 if(!map) { 78 throw new ImageLoadException("Failed to load Texture: " ~ filename); 79 } 80 81 _width = FreeImage_GetWidth(map); 82 _height = FreeImage_GetHeight(map); 83 84 GLuint id; 85 86 glGenTextures(1, &id); 87 this.textureId = id; 88 use(); 89 90 setOptions(); 91 92 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, useAlpha ? GL_BGRA : GL_BGR, GL_UNSIGNED_BYTE, FreeImage_GetBits(map)); 93 glGenerateMipmap(GL_TEXTURE_2D); 94 95 FreeImage_Unload(map); 96 } 97 98 protected void setOptions() @system nothrow { 99 // TODO: adjustable 100 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 101 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 102 103 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 104 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 105 } 106 107 override void cleanup() @system { 108 this.game.renderer.submitOperation(() { 109 GLuint id = this.textureId; 110 111 glDeleteTextures(1, &id); 112 }); 113 } 114 } 115 } 116 117 /// Exception related to loading images. 118 class ImageLoadException : Exception { 119 /// Default constructor. 120 this(in string message) @safe nothrow { 121 super(message); 122 } 123 }