virtualtexture.sh 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. /*
  2. * Copyright 2011-2020 Branimir Karadzic. All rights reserved.
  3. * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
  4. */
  5. /*
  6. * Reference(s):
  7. * - Based on Virtual Texture Demo by Brad Blanchard
  8. * http://web.archive.org/web/20190103162638/http://linedef.com/virtual-texture-demo.html
  9. */
  10. uniform vec4 u_vt_settings_1;
  11. uniform vec4 u_vt_settings_2;
  12. #define VirtualTextureSize u_vt_settings_1.x
  13. #define AtlasScale u_vt_settings_1.y
  14. #define BorderScale u_vt_settings_1.z
  15. #define BorderOffset u_vt_settings_1.w
  16. #define MipBias u_vt_settings_2.x
  17. #define PageTableSize u_vt_settings_2.y
  18. SAMPLER2D(s_vt_page_table, 0);
  19. SAMPLER2D(s_vt_texture_atlas, 1);
  20. // This function estimates mipmap levels
  21. float MipLevel( vec2 uv, float size )
  22. {
  23. vec2 dx = dFdx( uv * size );
  24. vec2 dy = dFdy( uv * size );
  25. float d = max( dot( dx, dx ), dot( dy, dy ) );
  26. return max( 0.5 * log2( d ), 0 );
  27. }
  28. // This function samples the page table and returns the page's
  29. // position and mip level.
  30. vec3 SampleTable( vec2 uv, float mip )
  31. {
  32. vec2 offset = fract( uv * PageTableSize ) / PageTableSize;
  33. return texture2DLod( s_vt_page_table, uv - offset, mip ).xyz;
  34. }
  35. // This functions samples from the texture atlas and returns the final color
  36. vec4 SampleAtlas( vec3 page, vec2 uv )
  37. {
  38. float mipsize = exp2( floor( page.z * 255.0 + 0.5 ) );
  39. uv = fract( uv * PageTableSize / mipsize );
  40. uv *= BorderScale;
  41. uv += BorderOffset;
  42. vec2 offset = floor( page.xy * 255.0 + 0.5 );
  43. return texture2D( s_vt_texture_atlas, ( offset + uv ) * AtlasScale );
  44. }
  45. // Ugly brute force trilinear, look up twice and mix
  46. vec4 VirtualTextureTrilinear( vec2 uv )
  47. {
  48. float miplevel = MipLevel( uv, VirtualTextureSize );
  49. miplevel = clamp( miplevel, 0.0, log2( PageTableSize )-1.0 );
  50. float mip1 = floor( miplevel );
  51. float mip2 = mip1 + 1.0;
  52. float mipfrac = miplevel - mip1;
  53. vec3 page1 = SampleTable( uv, mip1 );
  54. vec3 page2 = SampleTable( uv, mip2 );
  55. vec4 sample1 = SampleAtlas( page1, uv );
  56. vec4 sample2 = SampleAtlas( page2, uv );
  57. return mix( sample1, sample2, mipfrac );
  58. }
  59. // Simple bilinear
  60. vec4 VirtualTexture( vec2 uv )
  61. {
  62. float mip = floor( MipLevel( uv, VirtualTextureSize ) );
  63. mip = clamp( mip, 0, log2( PageTableSize ) );
  64. vec3 page = SampleTable( uv, mip );
  65. return SampleAtlas( page, uv );
  66. }