1 module evael.graphics.TextureArray;
2 
3 import std.typecons : Flag, Yes, No;
4 
5 import evael.graphics.GL;
6 
7 import evael.system.Asset;
8 
9 import evael.graphics.GraphicsDevice;
10 import evael.graphics.Texture;
11 
12 /**
13  * TextureArray.
14  */
15 class TextureArray
16 {
17 	/// Texture array ID
18 	private uint m_id;
19 
20 	/** 
21 	 * TextureArray constructor.
22 	 */
23 	@nogc @safe
24 	public this(in uint id) pure nothrow
25 	{
26         this.m_id = id;
27 	}
28 
29 	/** 
30 	 * TextureArray destructor.
31 	 */
32 	@nogc
33 	public void dispose() const nothrow
34 	{
35 		gl.DeleteBuffers(1, &this.m_id);
36 	}
37 
38 	/**
39 	 * Builds a texture array from multiple textures.
40 	 * Params:
41 	 *		textures : textures to load
42 	 *		size : textures width and height
43      *      flipTexture : flip each texture ?
44 	 */
45 	public static TextureArray build(in string[] textures, in int size = 512, in Flag!"flipTextures" flipTextures = Yes.flipTextures)
46 	{
47         uint id;
48 		gl.GenTextures(1, &id);
49 
50         gl.ActiveTexture(GL_TEXTURE2);
51         gl.BindTexture(GL_TEXTURE_2D_ARRAY, id);
52 
53 		gl.TexImage3D(GL_TEXTURE_2D_ARRAY,
54 			0,                 // mipmap level
55 			GL_RGBA8,          // gpu texel format
56 			size,              // width
57 			size,              // height
58 			textures.length,   // depth
59 			0,                 // border
60 			GL_BGRA,      	   // cpu pixel format
61 			GL_UNSIGNED_BYTE,  // cpu pixel coord type
62 			null);             // pixel data
63 		
64         foreach (i, texture; textures)
65         {
66             auto bytes = Texture.loadBytes(texture);
67             gl.TexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, i, size, size, 1, GL_BGRA, GL_UNSIGNED_BYTE, bytes.ptr);
68         }
69 
70 		auto minificationFilter = GL_LINEAR;
71 		auto magnificationFilter = GL_LINEAR;
72 
73 		// Anisotropic filter
74 		float fLargest;
75 		gl.GetFloatv(0x84FF, &fLargest);
76 		gl.TexParameterf(GL_TEXTURE_2D_ARRAY, 0x84FE, fLargest);
77 
78 		// Specify our minification and magnification filters
79 		gl.TexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, minificationFilter);
80 		gl.TexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, magnificationFilter);
81 
82 		// If we're using MipMaps, then we'll generate them here.
83 		// Note: The glGenerateMipmap call requires OpenGL 3.0 as a minimum.
84 		if (minificationFilter == GL_LINEAR_MIPMAP_LINEAR   ||
85 			minificationFilter == GL_LINEAR_MIPMAP_NEAREST  ||
86 			minificationFilter == GL_NEAREST_MIPMAP_LINEAR  ||
87 			minificationFilter == GL_NEAREST_MIPMAP_NEAREST)
88 		{
89 			gl.GenerateMipmap(GL_TEXTURE_2D_ARRAY);
90 		}
91 
92         gl.BindTexture(GL_TEXTURE_2D_ARRAY, 0);
93         gl.ActiveTexture(GL_TEXTURE20);
94 
95         return new TextureArray(id);
96     }
97 
98 	/**
99 	 * Properties
100 	 */
101 	@nogc @safe
102 	@property pure nothrow
103 	{
104 		public uint id() const
105 		{
106 			return this.m_id;	
107 		}
108     }
109 }
110