BicubicUpsample.bsl 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. shader BicubicUpsample
  2. {
  3. depth
  4. {
  5. read = false;
  6. write = false;
  7. };
  8. blend
  9. {
  10. target
  11. {
  12. enabled = true;
  13. color = { one, one, add };
  14. };
  15. };
  16. variations
  17. {
  18. HERMITE = { true, false };
  19. };
  20. code
  21. {
  22. #if HERMITE
  23. #define CUBIC_FUNC cubicHermite
  24. #else
  25. #define CUBIC_FUNC cubicLagrange
  26. #endif
  27. [internal]
  28. cbuffer Input
  29. {
  30. [color]
  31. float4 gTint;
  32. uint2 gTextureSize;
  33. float2 gInvPixel;
  34. float2 gInvTwoPixels;
  35. }
  36. struct VStoFS
  37. {
  38. noperspective float4 position : SV_POSITION;
  39. noperspective float2 uv0 : TEXCOORD0;
  40. };
  41. struct VertexInput
  42. {
  43. float2 screenPos : POSITION;
  44. float2 uv0 : TEXCOORD0;
  45. };
  46. VStoFS vsmain(VertexInput input)
  47. {
  48. VStoFS output;
  49. output.position = float4(input.screenPos, 0, 1);
  50. output.uv0 = input.uv0;
  51. return output;
  52. }
  53. Texture2D<float4> gSource;
  54. [alias(gSource)]
  55. SamplerState gSampler
  56. {
  57. Filter = MIN_MAG_MIP_POINT;
  58. };
  59. static float4 OFFSET = float4(-1.0f, 0.0f, 1.0f, 2.0f);
  60. float3 cubicLagrange(float3 A, float3 B, float3 C, float3 D, float t)
  61. {
  62. return
  63. A *
  64. (
  65. (t - OFFSET.y) / (OFFSET.x - OFFSET.y) *
  66. (t - OFFSET.z) / (OFFSET.x - OFFSET.z) *
  67. (t - OFFSET.w) / (OFFSET.x - OFFSET.w)
  68. ) +
  69. B *
  70. (
  71. (t - OFFSET.x) / (OFFSET.y - OFFSET.x) *
  72. (t - OFFSET.z) / (OFFSET.y - OFFSET.z) *
  73. (t - OFFSET.w) / (OFFSET.y - OFFSET.w)
  74. ) +
  75. C *
  76. (
  77. (t - OFFSET.x) / (OFFSET.z - OFFSET.x) *
  78. (t - OFFSET.y) / (OFFSET.z - OFFSET.y) *
  79. (t - OFFSET.w) / (OFFSET.z - OFFSET.w)
  80. ) +
  81. D *
  82. (
  83. (t - OFFSET.x) / (OFFSET.w - OFFSET.x) *
  84. (t - OFFSET.y) / (OFFSET.w - OFFSET.y) *
  85. (t - OFFSET.z) / (OFFSET.w - OFFSET.z)
  86. );
  87. }
  88. float3 cubicHermite(float3 A, float3 B, float3 C, float3 D, float t)
  89. {
  90. float t2 = t*t;
  91. float t3 = t*t*t;
  92. float3 a = -A/2.0f + (3.0f*B)/2.0f - (3.0f*C)/2.0f + D/2.0f;
  93. float3 b = A - (5.0f*B)/2.0f + 2.0f*C - D / 2.0f;
  94. float3 c = -A/2.0f + C/2.0f;
  95. float3 d = B;
  96. return a*t3 + b*t2 + c*t + d;
  97. }
  98. float4 fsmain(VStoFS input) : SV_Target0
  99. {
  100. float2 pixel = input.uv0 * gTextureSize + 0.5f;
  101. float2 fractional = frac(pixel);
  102. pixel = floor(pixel) / gTextureSize - gInvPixel/2.0f;
  103. // Note: Investigate a version requiring less taps: http://vec3.ca/bicubic-filtering-in-fewer-taps/
  104. float3 C00 = gSource.Sample(gSampler, pixel + float2(-gInvPixel.x , -gInvPixel.y)).rgb;
  105. float3 C10 = gSource.Sample(gSampler, pixel + float2( 0.0f , -gInvPixel.y)).rgb;
  106. float3 C20 = gSource.Sample(gSampler, pixel + float2( gInvPixel.x , -gInvPixel.y)).rgb;
  107. float3 C30 = gSource.Sample(gSampler, pixel + float2( gInvTwoPixels.x , -gInvPixel.y)).rgb;
  108. float3 C01 = gSource.Sample(gSampler, pixel + float2(-gInvPixel.x , 0.0f)).rgb;
  109. float3 C11 = gSource.Sample(gSampler, pixel + float2( 0.0f , 0.0f)).rgb;
  110. float3 C21 = gSource.Sample(gSampler, pixel + float2( gInvPixel.x , 0.0f)).rgb;
  111. float3 C31 = gSource.Sample(gSampler, pixel + float2( gInvTwoPixels.x , 0.0f)).rgb;
  112. float3 C02 = gSource.Sample(gSampler, pixel + float2(-gInvPixel.x , gInvPixel.y)).rgb;
  113. float3 C12 = gSource.Sample(gSampler, pixel + float2( 0.0f , gInvPixel.y)).rgb;
  114. float3 C22 = gSource.Sample(gSampler, pixel + float2( gInvPixel.x , gInvPixel.y)).rgb;
  115. float3 C32 = gSource.Sample(gSampler, pixel + float2( gInvTwoPixels.x , gInvPixel.y)).rgb;
  116. float3 C03 = gSource.Sample(gSampler, pixel + float2(-gInvPixel.x , gInvTwoPixels.y)).rgb;
  117. float3 C13 = gSource.Sample(gSampler, pixel + float2( 0.0f , gInvTwoPixels.y)).rgb;
  118. float3 C23 = gSource.Sample(gSampler, pixel + float2( gInvPixel.x , gInvTwoPixels.y)).rgb;
  119. float3 C33 = gSource.Sample(gSampler, pixel + float2( gInvTwoPixels.x , gInvTwoPixels.y)).rgb;
  120. float3 CP0X = CUBIC_FUNC(C00, C10, C20, C30, fractional.x);
  121. float3 CP1X = CUBIC_FUNC(C01, C11, C21, C31, fractional.x);
  122. float3 CP2X = CUBIC_FUNC(C02, C12, C22, C32, fractional.x);
  123. float3 CP3X = CUBIC_FUNC(C03, C13, C23, C33, fractional.x);
  124. return float4(CUBIC_FUNC(CP0X, CP1X, CP2X, CP3X, fractional.y), 1.0f) * gTint;
  125. }
  126. };
  127. };