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}