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