1//-----------------------------------------------------------------------------
2// Program Name: SGXLib_IntegratedPSSM
3// Program Desc: Texture Atlas functions.
4// Program Type: Vertex/Pixel shader
5// Language: GLSL
6//-----------------------------------------------------------------------------
7#extension GL_ARB_shader_texture_lod : require
8
9float mipmapLevel(vec2 coords, vec2 texSize)
10{
11	coords = coords.xy * texSize;
12	vec2 dx = dFdx(coords.xy);
13	vec2 dy = dFdy(coords.xy);
14	float Px = length(dx);
15	float Py = length(dy);
16	float Pmax = max(Px, Py);
17	return log2(max(Pmax,1));
18}
19
20
21//-----------------------------------------------------------------------------
22void SGX_Atlas_Sample_Auto_Adjust(in sampler2D sample,
23		in vec2 origTexcoord,
24		in vec2 atlasTexcoord,
25		in vec4 textureData,
26		in vec2 imageSize,
27		out vec4 texel)
28{
29	//
30	// Most of the idea for this function has been taken from the code under the webpage:
31	// http://www.gamedev.net/topic/534149-solved-texture-seams-using-atlas-with-screenshots/
32
33
34	// origTexcoord - original texture coordintates as received from the vertex buffer.
35	// atlasTexcoord - texture coordinates that have gone through on which different mathematical
36	//			functions to simulate different texture addressing modes (wrap, mirror, clamp)
37	// textureData.xy - top left corner (in 0-1 units) where the needed texture in the texture atlas begins
38	// textureData.zw - width and height in power of 2 for the needed texture in the texture atlas
39	// imageSize - size of the image in pixels
40	// texel - [Output] The color of the pixel at the requested position
41
42	vec2 startPos = textureData.xy;
43
44
45	// calculate the tileSize by using the power of 2 value
46	vec2 pwrs = textureData.zw;
47
48	//Calculate the power of 2 size of the maximum avialable Mipmap
49	//Note: We limit the amount of available LODs to [actual number] - 2
50	//as some atlas packaging tools do not include the last 2 LODs
51	//when packeging DXT format atlas textures.
52	float availableLODCount = min(pwrs.x,pwrs.y) - 2;
53	vec2 tileSize = pow(vec2(2.0,2.0),pwrs);
54
55	// retrieve the mipmap level for this pixel clamped by the power of 2 value
56	float lod = clamp(mipmapLevel(origTexcoord, tileSize), 0, availableLODCount);
57
58	vec2 relativeTileSize = tileSize / imageSize;
59	// get the width/height of the mip surface we've decided on
60	vec2 mipSize = pow(vec2(2.0,2.0), pwrs.xy - ceil(lod));
61
62	// compute the inverse fraction size for the tile
63	//vec2 lodSize = mipSize * imageSize / tileSize;
64	vec2 lodSizeInv = (relativeTileSize / mipSize);
65	//compute the new coordinates
66	//atlasTexcoord = atlasTexcoord * ((lodSize * (tileSize / imageSize) - 1.0) / lodSize) + (0.5 / lodSize) + startPos;
67	atlasTexcoord = atlasTexcoord * (relativeTileSize - lodSizeInv) + (0.5 * lodSizeInv) + startPos;
68
69	//return the pixel from the correct mip surface of the atlas
70	texel = texture2DLod(sample, atlasTexcoord, lod);
71}
72//-----------------------------------------------------------------------------
73void SGX_Atlas_Sample_Normal(in sampler2D sample,
74		in vec2 origTexcoord,
75		in vec2 atlasTexcoord,
76		in vec4 textureData,
77		in vec2 imageSize,
78		out vec4 texel)
79{
80	//texcoord contain:
81	// x = texture atlas u
82	// y = texture atlas v
83	// z = derivative of original u
84	// w = derivative of original v
85	atlasTexcoord = textureData.xy + (atlasTexcoord * pow(vec2(2.0,2.0),textureData.zw) / imageSize);
86	//texel = texture2DLod(sample, vec4(atlasTexcoord, 0,0));
87	texel = texture2D(sample, atlasTexcoord);
88}
89
90//-----------------------------------------------------------------------------
91void SGX_Atlas_Wrap(in float inpCoord, out float outCoord)
92{
93	outCoord = fract(inpCoord);
94}
95
96//-----------------------------------------------------------------------------
97void SGX_Atlas_Clamp(in float inpCoord, out float outCoord)
98{
99	outCoord = clamp(inpCoord, 0.0, 1.0);
100}
101//-----------------------------------------------------------------------------
102void SGX_Atlas_Mirror(in float inpCoord, out float outCoord)
103{
104	outCoord = (inpCoord + 1) * 0.5;
105	outCoord = abs(fract(outCoord) * 2 - 1);
106}
107
108//-----------------------------------------------------------------------------
109void SGX_Atlas_Border(in float inpCoord, out float outCoord)
110{
111	//
112	//The shader needs to check whether the original texcoord are beyond the 0,1 range.
113	//The shader attempts to do so without using if statments which are complicated for shaders
114	//
115
116	//if texcoord is in the 0,1 range then check will equal 0,
117	//Otherwise it will equal the number 1 or greater
118	float check = step(inpCoord, 0) + step(1, inpCoord);
119
120	//using the check value transport the value of the texcoord beyond the 0,1 range so it will
121	//recive the border color
122	outCoord = abs(inpCoord) + check * 2;
123}
124