A game about forced loneliness, made by TACStudios
1#ifndef GRA_HLSL_3
2#define GRA_HLSL_3 0
3#endif
4
5#ifndef GRA_HLSL_4
6#define GRA_HLSL_4 0
7#endif
8
9#ifndef GRA_HLSL_5
10#define GRA_HLSL_5 0
11#endif
12
13#ifndef GRA_GLSL_120
14#define GRA_GLSL_120 0
15#endif
16
17#ifndef GRA_GLSL_130
18#define GRA_GLSL_130 0
19#endif
20
21#ifndef GRA_GLSL_330
22#define GRA_GLSL_330 0
23#endif
24
25#ifndef GRA_VERTEX_SHADER
26#define GRA_VERTEX_SHADER 0
27#endif
28
29#ifndef GRA_PIXEL_SHADER
30#define GRA_PIXEL_SHADER 0
31#endif
32
33#ifndef GRA_HQ_CUBEMAPPING
34#define GRA_HQ_CUBEMAPPING 0
35#endif
36
37#ifndef GRA_DEBUG_TILES
38#define GRA_DEBUG_TILES 0
39#endif
40
41#ifndef GRA_BGRA
42#define GRA_BGRA 0
43#endif
44
45#ifndef GRA_ROW_MAJOR
46#define GRA_ROW_MAJOR 1
47#endif
48
49#ifndef GRA_DEBUG
50#define GRA_DEBUG 1
51#endif
52
53#ifndef GRA_64BIT_RESOLVER
54#define GRA_64BIT_RESOLVER 0
55#endif
56
57#ifndef GRA_RWTEXTURE2D_SCALE
58#define GRA_RWTEXTURE2D_SCALE 16
59#endif
60
61#ifndef GRA_DISABLE_TEX_LOAD
62#define GRA_DISABLE_TEX_LOAD 0
63#endif
64
65#ifndef GRA_PACK_RESOLVE_OUTPUT
66#define GRA_PACK_RESOLVE_OUTPUT 1
67#endif
68
69// Temp workaround for some platforms's lack of unorm.
70#ifdef GRA_NO_UNORM
71 #define GRA_UNORM
72#else
73 #define GRA_UNORM unorm
74#endif
75
76#ifndef GRA_TEXTURE_ARRAY_SUPPORT
77 #if (GRA_HLSL_5 == 1) || (GRA_HLSL_4 == 1) || (GRA_GLSL_330 == 1)
78 #define GRA_TEXTURE_ARRAY_SUPPORT 1
79 #else
80 #define GRA_TEXTURE_ARRAY_SUPPORT 0
81 #endif
82#endif
83
84#define GRA_HLSL_FAMILY ((GRA_HLSL_3 == 1) || (GRA_HLSL_5 == 1) || (GRA_HLSL_4 == 1))
85#define GRA_GLSL_FAMILY ((GRA_GLSL_120 == 1) || (GRA_GLSL_130 == 1) || (GRA_GLSL_330 == 1))
86
87#if GRA_HLSL_FAMILY
88 #define gra_Float2 float2
89 #define gra_Float3 float3
90 #define gra_Float4 float4
91 #define gra_Int3 int3
92 #define gra_Float4x4 float4x4
93 #define gra_Unroll [unroll]
94 #define gra_Branch [branch]
95#elif GRA_GLSL_FAMILY
96 #if (GRA_VERTEX_SHADER == 0) && (GRA_PIXEL_SHADER ==0)
97 #error GLSL requires knowledge of the shader stage! Neither GRA_VERTEX_SHADER or GRA_PIXEL_SHADER are defined!
98 #else
99 #define gra_Float2 vec2
100 #define gra_Float3 vec3
101 #define gra_Float4 vec4
102 #define gra_Int3 ivec3
103 #define gra_Float4x4 mat4
104 #define gra_Unroll
105 #define gra_Branch
106 #if (GRA_VERTEX_SHADER == 1)
107 #define ddx
108 #define ddy
109 #elif (GRA_PIXEL_SHADER == 1)
110 #define ddx dFdx
111 #define ddy dFdy
112 #endif
113 #define frac fract
114 #define lerp mix
115 /** This is not correct (http://stackoverflow.com/questions/7610631/glsl-mod-vs-hlsl-fmod) but it is for our case */
116 #define fmod mod
117 #endif
118#else
119 #error unknown shader architecture
120#endif
121
122#if (GRA_DISABLE_TEX_LOAD!=1)
123 #if (GRA_HLSL_5 == 1) || (GRA_HLSL_4 == 1) || (GRA_GLSL_130 == 1) || (GRA_GLSL_330 == 1)
124 #define GRA_LOAD_INSTR 1
125 #else
126 #define GRA_LOAD_INSTR 0
127 #endif
128#else
129 #define GRA_LOAD_INSTR 0
130#endif
131
132/**
133 a cross API texture handle
134*/
135#if (GRA_HLSL_5 == 1) || (GRA_HLSL_4 == 1)
136 struct GraniteTranslationTexture
137 {
138 SamplerState Sampler;
139 Texture2D Texture;
140 };
141 struct GraniteCacheTexture
142 {
143 SamplerState Sampler;
144
145 #if GRA_TEXTURE_ARRAY_SUPPORT
146 Texture2DArray TextureArray;
147 #else
148 Texture2D Texture;
149 #endif
150 };
151#elif (GRA_HLSL_3 == 1) || (GRA_GLSL_120 == 1) || (GRA_GLSL_130 == 1) || (GRA_GLSL_330 == 1)
152 #define GraniteTranslationTexture sampler2D
153
154 #if GRA_TEXTURE_ARRAY_SUPPORT
155 #define GraniteCacheTexture sampler2DArray
156 #else
157 #define GraniteCacheTexture sampler2D
158 #endif
159
160#else
161 #error unknow shader archtecture
162#endif
163
164/**
165 Struct defining the constant buffer for each streaming texture.
166 Use IStreamingTexture::GetConstantBuffer to fill this struct.
167*/
168struct GraniteStreamingTextureConstantBuffer
169{
170 #define _grStreamingTextureCBSize 2
171 gra_Float4 data[_grStreamingTextureCBSize];
172};
173
174/**
175 Struct defining the constant buffer for each cube streaming texture.
176 Use multiple calls to IStreamingTexture::GetConstantBuffer this struct (one call for each face).
177 */
178struct GraniteStreamingTextureCubeConstantBuffer
179{
180 #define _grStreamingTextureCubeCBSize 6
181 GraniteStreamingTextureConstantBuffer data[_grStreamingTextureCubeCBSize];
182};
183
184/**
185 Struct defining the constant buffer for each tileset.
186 Use ITileSet::GetConstantBuffer to fill this struct.
187*/
188struct GraniteTilesetConstantBuffer
189{
190 #define _grTilesetCBSize 2
191 gra_Float4x4 data[_grTilesetCBSize];
192};
193
194/**
195 Utility struct used by the shaderlib to wrap up all required constant buffers needed to perform a VT lookup/sample.
196 */
197struct GraniteConstantBuffers
198{
199 GraniteTilesetConstantBuffer tilesetBuffer;
200 GraniteStreamingTextureConstantBuffer streamingTextureBuffer;
201};
202
203/**
204 Utility struct used by the shaderlib to wrap up all required constant buffers needed to perform a Cube VT lookup/sample.
205 */
206struct GraniteCubeConstantBuffers
207{
208 GraniteTilesetConstantBuffer tilesetBuffer;
209 GraniteStreamingTextureCubeConstantBuffer streamingTextureCubeBuffer;
210};
211
212/**
213 The Granite lookup data for the different sampling functions.
214*/
215
216// Granite lookup data for automatic mip level selecting sampling
217struct GraniteLookupData
218{
219 gra_Float4 translationTableData;
220 gra_Float2 textureCoordinates;
221 gra_Float2 dX;
222 gra_Float2 dY;
223};
224
225// Granite lookup data for explicit level-of-detail sampling
226struct GraniteLODLookupData
227{
228 gra_Float4 translationTableData;
229 gra_Float2 textureCoordinates;
230 float cacheLevel;
231};
232//@IGNORE_END
233
234// public interface
235
236/*
237 END OF PUBLIC INTERFACE
238 Everything below this point should be treated as private to GraniteShaderLib.h
239*/
240
241//@INSERT_DEFINES
242#define gra_TilesetBuffer grCB.tilesetBuffer
243#define gra_TilesetBufferInternal tsCB.data[0]
244#define gra_TilesetCacheBuffer tsCB.data[1]
245
246#define gra_StreamingTextureCB grCB.streamingTextureBuffer
247#define gra_StreamingTextureCubeCB grCB.streamingTextureCubeBuffer
248
249#define gra_Transform grCB.streamingTextureBuffer.data[0]
250#define gra_CubeTransform grCB.streamingTextureCubeBuffer.data
251
252#define gra_StreamingTextureTransform grSTCB.data[0]
253#define gra_StreamingTextureInfo grSTCB.data[1]
254
255#define gra_NumLevels gra_StreamingTextureInfo.x
256#define gra_AssetWidthRcp gra_StreamingTextureInfo.y
257#define gra_AssetHeightRcp gra_StreamingTextureInfo.z
258
259#if GRA_ROW_MAJOR == 1
260
261 #define gra_TranslationTableBias gra_TilesetBufferInternal[0][0]
262 #define gra_MaxAnisotropyLog2 gra_TilesetBufferInternal[1][0]
263 #define gra_CalcMiplevelDeltaScale gra_Float2(gra_TilesetBufferInternal[2][0], gra_TilesetBufferInternal[3][0])
264 #define gra_CalcMiplevelDeltaScaleX gra_TilesetBufferInternal[2][0]
265 #define gra_CalcMiplevelDeltaScaleY gra_TilesetBufferInternal[3][0]
266 #define gra_LodBiasPow2 gra_TilesetBufferInternal[0][1]
267 #define gra_TrilinearOffset gra_TilesetBufferInternal[0][2]
268 #define gra_TileContentInTiles gra_Float2(gra_TilesetBufferInternal[0][2], gra_TilesetBufferInternal[1][2])
269 #define gra_Level0NumTilesX gra_TilesetBufferInternal[0][3]
270 #define gra_NumTilesYScale gra_TilesetBufferInternal[1][3]
271 #define gra_TextureMagic gra_TilesetBufferInternal[2][3]
272 #define gra_TextureId gra_TilesetBufferInternal[3][3]
273
274 #define gra_RcpCacheInTiles(l) gra_Float2(gra_TilesetCacheBuffer[0][l], gra_TilesetCacheBuffer[1][l])
275 #define gra_BorderPixelsRcpCache(l) gra_Float2(gra_TilesetCacheBuffer[2][l], gra_TilesetCacheBuffer[3][l])
276
277#else
278
279 #define gra_TranslationTableBias gra_TilesetBufferInternal[0][0]
280 #define gra_MaxAnisotropyLog2 gra_TilesetBufferInternal[0][1]
281 #define gra_CalcMiplevelDeltaScale gra_Float2(gra_TilesetBufferInternal[0][2], gra_TilesetBufferInternal[0][3])
282 #define gra_CalcMiplevelDeltaScaleX gra_TilesetBufferInternal[0][2]
283 #define gra_CalcMiplevelDeltaScaleY gra_TilesetBufferInternal[0][3]
284 #define gra_LodBiasPow2 gra_TilesetBufferInternal[1][0]
285 #define gra_TrilinearOffset gra_TilesetBufferInternal[2][0]
286 #define gra_TileContentInTiles gra_Float2(gra_TilesetBufferInternal[2][0], gra_TilesetBufferInternal[2][1])
287 #define gra_Level0NumTilesX gra_TilesetBufferInternal[3][0]
288 #define gra_NumTilesYScale gra_TilesetBufferInternal[3][1]
289 #define gra_TextureMagic gra_TilesetBufferInternal[3][2]
290 #define gra_TextureId gra_TilesetBufferInternal[3][3]
291
292 #define gra_RcpCacheInTiles(l) gra_Float2(gra_TilesetCacheBuffer[l][0], gra_TilesetCacheBuffer[l][1])
293 #define gra_BorderPixelsRcpCache(l) gra_Float2(gra_TilesetCacheBuffer[l][2], gra_TilesetCacheBuffer[l][3])
294
295#endif
296
297#if (GRA_GLSL_120==1)
298 // Extension needed for texture2DLod
299 //extension GL_ARB_shader_texture_lod : enable
300 // Extensions needed fot texture2DGrad
301 //extension GL_EXT_gpu_shader4 : enable
302 // Extensions needed for bit manipulation
303 //extension GL_ARB_shader_bit_encoding : enable
304#endif
305
306
307#if (GRA_TEXTURE_ARRAY_SUPPORT==1)
308 gra_Float4 GranitePrivate_SampleArray(in GraniteCacheTexture tex, in gra_Float3 texCoord)
309 {
310 #if (GRA_HLSL_5 == 1) || (GRA_HLSL_4 == 1)
311 return tex.TextureArray.Sample(tex.Sampler, texCoord);
312 #elif (GRA_GLSL_330 == 1)
313 return texture(tex, texCoord);
314 #else
315 #error using unsupported function
316 #endif
317 }
318
319 gra_Float4 GranitePrivate_SampleGradArray(in GraniteCacheTexture tex, in gra_Float3 texCoord, in gra_Float2 dX, in gra_Float2 dY)
320 {
321 #if (GRA_HLSL_5 == 1) || (GRA_HLSL_4 == 1)
322 return tex.TextureArray.SampleGrad(tex.Sampler,texCoord,dX,dY);
323 #elif (GRA_GLSL_330 == 1)
324 return textureGrad(tex, texCoord, dX, dY);
325 #else
326 #error using unsupported function
327 #endif
328 }
329
330 gra_Float4 GranitePrivate_SampleLevelArray(in GraniteCacheTexture tex, in gra_Float3 texCoord, in float level)
331 {
332 #if (GRA_HLSL_5 == 1) || (GRA_HLSL_4 == 1)
333 return tex.TextureArray.SampleLevel(tex.Sampler, texCoord, level);
334 #elif (GRA_GLSL_330 == 1)
335 return textureLod(tex, texCoord, level);
336 #else
337 #error using unsupported function
338 #endif
339 }
340#else
341 gra_Float4 GranitePrivate_Sample(in GraniteCacheTexture tex, in gra_Float2 texCoord)
342 {
343 #if (GRA_HLSL_5 == 1) || (GRA_HLSL_4 == 1)
344 return tex.Texture.Sample(tex.Sampler,texCoord);
345 #elif (GRA_HLSL_3 == 1)
346 return tex2D(tex,texCoord);
347 #elif (GRA_GLSL_120 == 1) || (GRA_GLSL_130 == 1)
348 return texture2D(tex, texCoord);
349 #elif (GRA_GLSL_330 == 1)
350 return texture(tex, texCoord);
351 #endif
352 }
353
354 gra_Float4 GranitePrivate_SampleLevel(in GraniteCacheTexture tex, in gra_Float2 texCoord, in float level)
355 {
356 #if (GRA_HLSL_5 == 1) || (GRA_HLSL_4 == 1)
357 return tex.Texture.SampleLevel(tex.Sampler, texCoord, level);
358 #elif (GRA_HLSL_3 == 1)
359 return tex2Dlod(tex,gra_Float4(texCoord,0.0,level));
360 #elif (GRA_GLSL_120 == 1)
361 return texture2DLod(tex, texCoord, level);
362 #elif (GRA_GLSL_130 == 1) || (GRA_GLSL_330 == 1)
363 return textureLod(tex, texCoord, level);
364 #endif
365 }
366
367 gra_Float4 GranitePrivate_SampleGrad(in GraniteCacheTexture tex, in gra_Float2 texCoord, in gra_Float2 dX, in gra_Float2 dY)
368 {
369 #if (GRA_HLSL_5 == 1) || (GRA_HLSL_4 == 1)
370 return tex.Texture.SampleGrad(tex.Sampler,texCoord,dX,dY);
371 #elif (GRA_HLSL_3 == 1)
372 return tex2D(tex,texCoord,dX,dY);
373 #elif (GRA_GLSL_120 == 1)
374 return texture2DGrad(tex, texCoord, dX, dY);
375 #elif (GRA_GLSL_130 == 1) || (GRA_GLSL_330 == 1)
376 return textureGrad(tex, texCoord, dX, dY);
377 #endif
378 }
379#endif //#if (GRA_TEXTURE_ARRAY_SUPPORT==1)
380
381#if (GRA_LOAD_INSTR==1)
382gra_Float4 GranitePrivate_Load(in GraniteTranslationTexture tex, in gra_Int3 location)
383{
384#if (GRA_HLSL_5 == 1) || (GRA_HLSL_4 == 1)
385 return tex.Texture.Load(location);
386#elif (GRA_GLSL_130 == 1) || (GRA_GLSL_330 == 1)
387 return texelFetch(tex, location.xy, location.z);
388#elif (GRA_HLSL_3 == 1) || (GRA_GLSL_120 == 1)
389 #error using unsupported function
390#endif
391}
392#endif
393
394//work-around shader compiler bug
395//compiler gets confused with GranitePrivate_SampleLevel taking a GraniteCacheTexture as argument when array support is disabled
396//Without array support, GraniteCacheTexture and GraniteTranslationTexture are the same (but still different types!)
397//compiler is confused (ERR_AMBIGUOUS_FUNCTION_CALL). Looks like somebody is over enthusiastic optimizing...
398gra_Float4 GranitePrivate_SampleLevel_Translation(in GraniteTranslationTexture tex, in gra_Float2 texCoord, in float level)
399{
400#if (GRA_HLSL_5 == 1) || (GRA_HLSL_4 == 1)
401 return tex.Texture.SampleLevel(tex.Sampler, texCoord, level);
402#elif (GRA_HLSL_3 == 1)
403 return tex2Dlod(tex,gra_Float4(texCoord,0.0,level));
404#elif (GRA_GLSL_120 == 1)
405 return texture2DLod(tex, texCoord, level);
406#elif (GRA_GLSL_130 == 1) || (GRA_GLSL_330 == 1)
407 return textureLod(tex, texCoord, level);
408#endif
409}
410
411float GranitePrivate_Saturate(in float value)
412{
413#if GRA_HLSL_FAMILY
414 return saturate(value);
415#elif GRA_GLSL_FAMILY
416 return clamp(value, 0.0f, 1.0f);
417#endif
418}
419
420#if (GRA_HLSL_5 == 1) || (GRA_HLSL_4 == 1) || (GRA_GLSL_330 == 1)
421uint GranitePrivate_FloatAsUint(float value)
422{
423#if (GRA_HLSL_5 == 1) || (GRA_HLSL_4 == 1)
424 return asuint(value);
425#elif (GRA_GLSL_330 == 1)
426 return floatBitsToUint(value);
427#endif
428}
429#endif
430
431float GranitePrivate_Pow2(uint exponent)
432{
433#if GRA_HLSL_FAMILY
434 return pow(2.0, exponent);
435#else
436 return pow(2.0, float(exponent));
437#endif
438}
439
440gra_Float2 GranitePrivate_RepeatUV(in gra_Float2 uv, in GraniteStreamingTextureConstantBuffer grSTCB)
441{
442 return frac(uv);
443}
444
445gra_Float2 GranitePrivate_UdimUV(in gra_Float2 uv, in GraniteStreamingTextureConstantBuffer grSTCB)
446{
447 return uv;
448}
449
450gra_Float2 GranitePrivate_ClampUV(in gra_Float2 uv, in GraniteStreamingTextureConstantBuffer grSTCB)
451{
452 gra_Float2 epsilon2 = gra_Float2(gra_AssetWidthRcp, gra_AssetHeightRcp);
453 return clamp(uv, epsilon2, gra_Float2(1,1) - epsilon2);
454}
455
456gra_Float2 GranitePrivate_MirrorUV(in gra_Float2 uv, in GraniteStreamingTextureConstantBuffer grSTCB)
457{
458 gra_Float2 t = frac(uv*0.5)*2.0;
459 gra_Float2 l = gra_Float2(1.0,1.0);
460 return l-abs(t-l);
461}
462
463// function definitons for private functions
464gra_Float4 GranitePrivate_PackTileId(in gra_Float2 tileXY, in float level, in float textureID);
465
466gra_Float4 Granite_DebugPackedTileId64(in gra_Float4 PackedTile)
467{
468#if GRA_64BIT_RESOLVER
469 gra_Float4 output;
470
471 const float scale = 1.0f / 65535.0f;
472 gra_Float4 temp = PackedTile / scale;
473
474 output.x = fmod(temp.x, 256.0f);
475 output.y = floor(temp.x / 256.0f) + fmod(temp.y, 16.0f) * 16.0f;
476 output.z = floor(temp.y / 16.0f);
477 output.w = temp.z + temp.a * 16.0f;
478
479 return gra_Float4
480 (
481 (float)output.x / 255.0f,
482 (float)output.y / 255.0f,
483 (float)output.z / 255.0f,
484 (float)output.w / 255.0f
485 );
486#else
487 return PackedTile;
488#endif
489}
490
491gra_Float3 Granite_UnpackNormal(in gra_Float4 PackedNormal, float scale)
492{
493 gra_Float2 reconstructed = gra_Float2(PackedNormal.x * PackedNormal.a, PackedNormal.y) * 2.0f - 1.0f;
494 reconstructed *= scale;
495 float z = sqrt(1.0f - GranitePrivate_Saturate(dot(reconstructed, reconstructed)));
496 return gra_Float3(reconstructed, z);
497}
498
499gra_Float3 Granite_UnpackNormal(in gra_Float4 PackedNormal)
500{
501 return Granite_UnpackNormal(PackedNormal, 1.0);
502}
503
504#if GRA_HLSL_FAMILY
505GraniteTilesetConstantBuffer Granite_ApplyResolutionOffset(in GraniteTilesetConstantBuffer INtsCB, in float resolutionOffsetPow2)
506{
507 GraniteTilesetConstantBuffer tsCB = INtsCB;
508 gra_LodBiasPow2 *= resolutionOffsetPow2;
509 //resolutionOffsetPow2 *= resolutionOffsetPow2; //Square it before multiplying it in below
510 gra_CalcMiplevelDeltaScaleX *= resolutionOffsetPow2;
511 gra_CalcMiplevelDeltaScaleY *= resolutionOffsetPow2;
512 return tsCB;
513}
514
515GraniteTilesetConstantBuffer Granite_SetMaxAnisotropy(in GraniteTilesetConstantBuffer INtsCB, in float maxAnisotropyLog2)
516{
517 GraniteTilesetConstantBuffer tsCB = INtsCB;
518 gra_MaxAnisotropyLog2 = min(gra_MaxAnisotropyLog2, maxAnisotropyLog2);
519 return tsCB;
520}
521#else
522void Granite_ApplyResolutionOffset(inout GraniteTilesetConstantBuffer tsCB, in float resolutionOffsetPow2)
523{
524 gra_LodBiasPow2 *= resolutionOffsetPow2;
525 //resolutionOffsetPow2 *= resolutionOffsetPow2; //Square it before multiplying it in below
526 gra_CalcMiplevelDeltaScaleX *= resolutionOffsetPow2;
527 gra_CalcMiplevelDeltaScaleY *= resolutionOffsetPow2;
528}
529
530void Granite_SetMaxAnisotropy(inout GraniteTilesetConstantBuffer tsCB, in float maxAnisotropyLog2)
531{
532 gra_MaxAnisotropyLog2 = min(gra_MaxAnisotropyLog2, maxAnisotropyLog2);
533}
534#endif
535
536gra_Float2 Granite_Transform(in GraniteStreamingTextureConstantBuffer grSTCB, in gra_Float2 textureCoord)
537{
538 return textureCoord * gra_StreamingTextureTransform.zw + gra_StreamingTextureTransform.xy;
539}
540
541gra_Float4 Granite_MergeResolveOutputs(in gra_Float4 resolve0, in gra_Float4 resolve1, in gra_Float2 pixelLocation)
542{
543 gra_Float2 screenPos = frac(pixelLocation * 0.5f);
544 bool dither = (screenPos.x != screenPos.y);
545 return (dither) ? resolve0 : resolve1;
546}
547
548gra_Float4 Granite_PackTileId(in gra_Float4 unpackedTileID)
549{
550 return GranitePrivate_PackTileId(unpackedTileID.xy, unpackedTileID.z, unpackedTileID.w);
551}
552
553#if (GRA_HLSL_5 == 1)
554void Granite_DitherResolveOutput(in gra_Float4 resolve, in RWTexture2D<GRA_UNORM gra_Float4> resolveTexture, in gra_Float2 screenPos, in float alpha)
555{
556 const uint2 pixelPos = int2(screenPos);
557 const uint2 pixelLocation = pixelPos % GRA_RWTEXTURE2D_SCALE;
558 bool dither = (pixelLocation.x == 0) && (pixelLocation.y == 0);
559 uint2 writePos = pixelPos / GRA_RWTEXTURE2D_SCALE;
560
561 if ( alpha == 0 )
562 {
563 dither = false;
564 }
565 else if (alpha != 1.0)
566 {
567 // Do a 4x4 dither patern so alternating pixels resolve to the first or the second texture
568 gra_Float2 pixelLocationAlpha = frac(screenPos * 0.25f); // We don't scale after the frac so this will give coords 0, 0.25, 0.5, 0.75
569 int pixelId = (int)(pixelLocationAlpha.y * 16 + pixelLocationAlpha.x * 4); //faster as a dot2 ?
570
571 // Clamp
572 // This ensures that for example alpha=0.95 still resolves some tiles of the surfaces behind it
573 // and alpha=0.05 still resolves some tiles of this surface
574 alpha = min(max(alpha, 0.0625), 0.9375);
575
576 // Modern hardware supports array indexing with per pixel varying indexes
577 // on old hardware this will be expanded to a conditional tree by the compiler
578 const float thresholdMaxtrix[16] = { 1.0f / 17.0f, 9.0f / 17.0f, 3.0f / 17.0f, 11.0f / 17.0f,
579 13.0f / 17.0f, 5.0f / 17.0f, 15.0f / 17.0f, 7.0f / 17.0f,
580 4.0f / 17.0f, 12.0f / 17.0f, 2.0f / 17.0f, 10.0f / 17.0f,
581 16.0f / 17.0f, 8.0f / 17.0f, 14.0f / 17.0f, 6.0f / 17.0f};
582 float threshold = thresholdMaxtrix[pixelId];
583
584 if (alpha < threshold)
585 {
586 dither = false;
587 }
588 }
589
590 gra_Branch if (dither)
591 {
592#if (GRA_PACK_RESOLVE_OUTPUT==0)
593 resolveTexture[writePos] = Granite_PackTileId(resolve);
594#else
595 resolveTexture[writePos] = resolve;
596#endif
597 }
598}
599#endif
600
601float GranitePrivate_CalcMiplevelAnisotropic(in GraniteTilesetConstantBuffer tsCB, in GraniteStreamingTextureConstantBuffer grSTCB, in gra_Float2 ddxTc, in gra_Float2 ddyTc)
602{
603 // Calculate the required mipmap level, this uses a similar
604 // formula as the GL spec.
605 // To reduce sqrt's and log2's we do some stuff in squared space here and further below in log space
606 // i.e. we wait with the sqrt untill we can do it for 'free' later during the log2
607
608 ddxTc *= gra_CalcMiplevelDeltaScale;
609 ddyTc *= gra_CalcMiplevelDeltaScale;
610
611 float lenDxSqr = dot(ddxTc, ddxTc);
612 float lenDySqr = dot(ddyTc, ddyTc);
613 float dMaxSqr = max(lenDxSqr, lenDySqr);
614 float dMinSqr = min(lenDxSqr, lenDySqr);
615
616 // Calculate mipmap levels directly from sqared distances. This uses log2(sqrt(x)) = 0.5 * log2(x) to save some sqrt's
617 float maxLevel = 0.5 * log2( dMaxSqr );
618 float minLevel = 0.5 * log2( dMinSqr );
619
620 // Calculate the log2 of the anisotropy and clamp it by the max supported. This uses log2(a/b) = log2(a)-log2(b) and min(log(a),log(b)) = log(min(a,b))
621 float anisoLog2 = maxLevel - minLevel;
622 anisoLog2 = min( anisoLog2, gra_MaxAnisotropyLog2 );
623
624 // Adjust for anisotropy & clamp to level 0
625 float result = max(maxLevel - anisoLog2 - 0.5f, 0.0f); //Subtract 0.5 to compensate for trilinear mipmapping
626
627 // Added clamping to avoid "hot pink" on small tilesets that try to sample past the 1x1 tile miplevel
628 // This happens if you for example import a relatively small texture and zoom out
629 return min(result, gra_NumLevels);
630}
631
632float GranitePrivate_CalcMiplevelLinear(in GraniteTilesetConstantBuffer tsCB, in GraniteStreamingTextureConstantBuffer grSTCB, in gra_Float2 ddxTc, in gra_Float2 ddyTc)
633{
634 // Calculate the required mipmap level, this uses a similar
635 // formula as the GL spec.
636 // To reduce sqrt's and log2's we do some stuff in squared space here and further below in log space
637 // i.e. we wait with the sqrt untill we can do it for 'free' later during the log2
638
639 ddxTc *= gra_CalcMiplevelDeltaScale;
640 ddyTc *= gra_CalcMiplevelDeltaScale;
641
642 float lenDxSqr = dot(ddxTc, ddxTc);
643 float lenDySqr = dot(ddyTc, ddyTc);
644 float dMaxSqr = max(lenDxSqr, lenDySqr);
645
646 // Calculate mipmap levels directly from squared distances. This uses log2(sqrt(x)) = 0.5 * log2(x) to save some sqrt's
647 float maxLevel = 0.5 * log2(dMaxSqr) - 0.5f; //Subtract 0.5 to compensate for trilinear mipmapping
648
649 return clamp(maxLevel, 0.0f, gra_NumLevels);
650}
651
652gra_Float4 GranitePrivate_PackTileId(in gra_Float2 tileXY, in float level, in float textureID)
653{
654#if GRA_64BIT_RESOLVER == 0
655 gra_Float4 resultBits;
656
657 resultBits.x = fmod(tileXY.x, 256.0f);
658 resultBits.y = floor(tileXY.x / 256.0f) + fmod(tileXY.y, 32.0f) * 8.0f;
659 resultBits.z = floor(tileXY.y / 32.0f) + fmod(level, 4.0f) * 64.0f;
660 resultBits.w = floor(level / 4.0f) + textureID * 4.0f;
661
662 const float scale = 1.0f / 255.0f;
663
664#if GRA_BGRA == 0
665 return scale * gra_Float4
666 (
667 float(resultBits.x),
668 float(resultBits.y),
669 float(resultBits.z),
670 float(resultBits.w)
671 );
672#else
673 return scale * gra_Float4
674 (
675 float(resultBits.z),
676 float(resultBits.y),
677 float(resultBits.x),
678 float(resultBits.w)
679 );
680#endif
681#else
682 const float scale = 1.0f / 65535.0f;
683 return gra_Float4(tileXY.x, tileXY.y, level, textureID) * scale;
684#endif
685
686}
687
688gra_Float4 GranitePrivate_UnpackTileId(in gra_Float4 packedTile)
689{
690 gra_Float4 swiz;
691#if GRA_BGRA == 0
692 swiz = packedTile;
693#else
694 swiz = packedTile.zyxw;
695#endif
696 swiz *= 255.0f;
697
698 float tileX = swiz.x + fmod(swiz.y, 16.0f) * 256.0f;
699 float tileY = floor(swiz.y / 16.0f) + swiz.z * 16.0f;
700 float level = fmod(swiz.w, 16.0f);
701 float tex = floor(swiz.w / 16.0f);
702
703 return gra_Float4(tileX, tileY, level, tex);
704}
705
706gra_Float3 GranitePrivate_TranslateCoord(in GraniteTilesetConstantBuffer tsCB, in gra_Float2 inputTexCoord, in gra_Float4 translationData, in int layer, out gra_Float2 numPagesOnLevel)
707{
708 // The translation table contains uint32_t values so we have to get to the individual bits of the float data
709 uint data = GranitePrivate_FloatAsUint(translationData[layer]);
710
711 // Slice Index: 7 bits, Cache X: 10 bits, Cache Y: 10 bits, Tile Level: 4 bits
712 uint slice = (data >> 24u) & 0x7Fu;
713 uint cacheX = (data >> 14u) & 0x3FFu;
714 uint cacheY = (data >> 4u) & 0x3FFu;
715 uint revLevel = data & 0xFu;
716
717 gra_Float2 numTilesOnLevel;
718 numTilesOnLevel.x = GranitePrivate_Pow2(revLevel);
719 numTilesOnLevel.y = numTilesOnLevel.x * gra_NumTilesYScale;
720
721 gra_Float2 tileTexCoord = frac(inputTexCoord * numTilesOnLevel);
722
723 gra_Float2 tileTexCoordCache = tileTexCoord * gra_TileContentInTiles + gra_Float2(cacheX, cacheY);
724 gra_Float3 final = gra_Float3(tileTexCoordCache * gra_RcpCacheInTiles(layer) + gra_BorderPixelsRcpCache(layer), slice);
725
726 numPagesOnLevel = numTilesOnLevel * gra_TileContentInTiles * gra_RcpCacheInTiles(layer);
727
728 return final;
729}
730
731gra_Float4 GranitePrivate_DrawDebugTiles(in gra_Float4 sourceColor, in gra_Float2 textureCoord, in gra_Float2 numPagesOnLevel)
732{
733 // Calculate the border values
734 gra_Float2 cacheOffs = frac(textureCoord * numPagesOnLevel);
735 float borderTemp = max(cacheOffs.x, 1.0-cacheOffs.x);
736 borderTemp = max(max(cacheOffs.y, 1.0-cacheOffs.y), borderTemp);
737 float border = smoothstep(0.98, 0.99, borderTemp);
738
739 // White
740 gra_Float4 borderColor = gra_Float4(1,1,1,1);
741
742 //Lerp it over the source color
743 return lerp(sourceColor, borderColor, border);
744}
745
746gra_Float4 GranitePrivate_MakeResolveOutput(in GraniteTilesetConstantBuffer tsCB, in gra_Float2 tileXY, in float level)
747{
748#if GRA_PACK_RESOLVE_OUTPUT
749 return GranitePrivate_PackTileId(tileXY, level, gra_TextureId);
750#else
751 return gra_Float4(tileXY, level, gra_TextureId);
752#endif
753}
754
755gra_Float4 GranitePrivate_ResolverPixel(in GraniteTilesetConstantBuffer tsCB, in gra_Float2 inputTexCoord, in float LOD)
756{
757 float level = floor(LOD + 0.5f);
758
759 // Number of tiles on level zero
760 gra_Float2 level0NumTiles;
761 level0NumTiles.x = gra_Level0NumTilesX;
762 level0NumTiles.y = gra_Level0NumTilesX * gra_NumTilesYScale;
763
764 // Calculate xy of the tiles to load
765 gra_Float2 virtualTilesUv = floor(inputTexCoord * level0NumTiles * pow(0.5, level));
766
767 return GranitePrivate_MakeResolveOutput(tsCB, virtualTilesUv, level);
768}
769
770void GranitePrivate_CalculateCubemapCoordinates(in gra_Float3 inputTexCoord, in gra_Float3 dVx, in gra_Float3 dVy, in GraniteStreamingTextureCubeConstantBuffer transforms, out int faceIdx, out gra_Float2 texCoord, out gra_Float2 dX, out gra_Float2 dY)
771{
772 gra_Float2 contTexCoord;
773 gra_Float3 derivX;
774 gra_Float3 derivY;
775
776 float majorAxis;
777 if (abs(inputTexCoord.z) >= abs(inputTexCoord.x) && abs(inputTexCoord.z) >= abs(inputTexCoord.y))
778 {
779 // Z major axis
780 if(inputTexCoord.z < 0.0)
781 {
782 faceIdx = 5;
783 texCoord.x = -inputTexCoord.x;
784 }
785 else
786 {
787 faceIdx = 4;
788 texCoord.x = inputTexCoord.x;
789 }
790 texCoord.y = -inputTexCoord.y;
791 majorAxis = inputTexCoord.z;
792
793 contTexCoord = gra_Float2(inputTexCoord.x, inputTexCoord.y);
794 derivX = gra_Float3(dVx.x, dVx.y, dVx.z);
795 derivY = gra_Float3(dVy.x, dVy.y, dVy.z);
796 }
797 else if (abs(inputTexCoord.y) >= abs(inputTexCoord.x))
798 {
799 // Y major axis
800 if(inputTexCoord.y < 0.0)
801 {
802 faceIdx = 3;
803 texCoord.y = -inputTexCoord.z;
804 }
805 else
806 {
807 faceIdx = 2;
808 texCoord.y = inputTexCoord.z;
809 }
810 texCoord.x = inputTexCoord.x;
811 majorAxis = inputTexCoord.y;
812
813 contTexCoord = gra_Float2(inputTexCoord.x, inputTexCoord.z);
814 derivX = gra_Float3(dVx.x, dVx.z, dVx.y);
815 derivY = gra_Float3(dVy.x, dVy.z, dVy.y);
816 }
817 else
818 {
819 // X major axis
820 if(inputTexCoord.x < 0.0)
821 {
822 faceIdx = 1;
823 texCoord.x = inputTexCoord.z;
824 }
825 else
826 {
827 faceIdx = 0;
828 texCoord.x = -inputTexCoord.z;
829 }
830 texCoord.y = -inputTexCoord.y;
831 majorAxis = inputTexCoord.x;
832
833 contTexCoord = gra_Float2(inputTexCoord.z, inputTexCoord.y);
834 derivX = gra_Float3(dVx.z, dVx.y, dVx.x);
835 derivY = gra_Float3(dVy.z, dVy.y, dVy.x);
836 }
837 texCoord = (texCoord + majorAxis) / (2.0 * abs(majorAxis));
838
839#if GRA_HQ_CUBEMAPPING
840 dX = /*contTexCoord **/ ((contTexCoord + derivX.xy) / ( 2.0 * (majorAxis + derivX.z)) - (contTexCoord / (2.0 * majorAxis)));
841 dY = /*contTexCoord **/ ((contTexCoord + derivY.xy) / ( 2.0 * (majorAxis + derivY.z)) - (contTexCoord / (2.0 * majorAxis)));
842#else
843 dX = ((/*contTexCoord **/ derivX.xy) / (2.0 * abs(majorAxis)));
844 dY = ((/*contTexCoord **/ derivY.xy) / (2.0 * abs(majorAxis)));
845#endif
846
847 // Now scale the derivatives with the texture transform scale
848 dX *= transforms.data[faceIdx].data[0].zw;
849 dY *= transforms.data[faceIdx].data[0].zw;
850}
851
852// Auto-level
853void GranitePrivate_CalculateCubemapCoordinates(in gra_Float3 inputTexCoord, in GraniteStreamingTextureCubeConstantBuffer transforms, out int faceIdx, out gra_Float2 texCoord, out gra_Float2 dX, out gra_Float2 dY)
854{
855 gra_Float3 dVx = ddx(inputTexCoord);
856 gra_Float3 dVy = ddy(inputTexCoord);
857
858 GranitePrivate_CalculateCubemapCoordinates(inputTexCoord, dVx, dVy, transforms, faceIdx, texCoord, dX, dY);
859}
860
861gra_Float2 Granite_GetTextureDimensions(in GraniteStreamingTextureConstantBuffer grSTCB)
862{
863 return gra_Float2(1.0 / gra_AssetWidthRcp, 1.0 / gra_AssetHeightRcp); //TODO(ddebaets) use HLSL rcp here
864}