game-boy-advance.fs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. #version 150
  2. #in coloremulation
  3. #in red
  4. #in green
  5. #in blue
  6. #in gain
  7. #in gamma
  8. #in blacklevel
  9. #in ambient
  10. #in BGR
  11. #in persistence
  12. #define outgamma 2.2
  13. #ifdef coloremulation
  14. const uint curve[32] = {
  15. 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0e, 0x10, 0x12,
  16. 0x14, 0x16, 0x18, 0x1c, 0x20, 0x28, 0x38, 0x38,
  17. 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x80,
  18. 0x88, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0
  19. };
  20. #endif
  21. #define fetch_offset(coord,offset) (pow(vec3(gain) * texelFetchOffset(source[0], (coord), 0, (offset)).rgb + vec3(blacklevel), vec3(gamma)) + vec3(ambient))
  22. // integral of (1 - x^2 - x^4 + x^6)^2
  23. const float coeffs_x[] = float[](1.0, -2.0/3.0, -1.0/5.0, 4.0/7.0, -1.0/9.0, -2.0/11.0, 1.0/13.0);
  24. // integral of (1 - 2x^4 + x^6)^2
  25. const float coeffs_y[] = float[](1.0, 0.0, -4.0/5.0, 2.0/7.0, 4.0/9.0, -4.0/11.0, 1.0/13.0);
  26. float intsmear_func(float z, float coeffs[7])
  27. {
  28. float z2 = z*z;
  29. float zn = z;
  30. float ret = 0.0;
  31. for (int i = 0; i < 7; i++) {
  32. ret += zn*coeffs[i];
  33. zn *= z2;
  34. }
  35. return ret;
  36. }
  37. float intsmear(float x, float dx, float d, float coeffs[7])
  38. {
  39. float zl = clamp((x-dx*0.5)/d,-1.0,1.0);
  40. float zh = clamp((x+dx*0.5)/d,-1.0,1.0);
  41. return d * ( intsmear_func(zh,coeffs) - intsmear_func(zl,coeffs) )/dx;
  42. }
  43. #define round(x) floor( (x) + 0.5 )
  44. #define gamma 2.2
  45. uniform sampler2D source[];
  46. uniform vec4 sourceSize[];
  47. uniform vec4 targetSize;
  48. uniform sampler2D history[];
  49. in Vertex {
  50. vec2 texCoord;
  51. };
  52. out vec4 fragColor;
  53. void main() {
  54. //motion blur
  55. vec3 color = texture(history[7], texCoord).rgb;
  56. color = mix(texture(history[6], texCoord).rgb, color, persistence);
  57. color = mix(texture(history[5], texCoord).rgb, color, persistence);
  58. color = mix(texture(history[4], texCoord).rgb, color, persistence);
  59. color = mix(texture(history[3], texCoord).rgb, color, persistence);
  60. color = mix(texture(history[2], texCoord).rgb, color, persistence);
  61. color = mix(texture(history[1], texCoord).rgb, color, persistence);
  62. color = mix(texture(history[0], texCoord).rgb, color, persistence);
  63. color = mix(texture(source[0], texCoord).rgb, color, persistence);
  64. vec4 rgba = vec4(pow(color, vec3(gamma)), 1.0);
  65. //palette shift
  66. vec4 gbacolor;
  67. #ifndef coloremulation
  68. gbacolor = rgba;
  69. #else
  70. uint R = curve[uint(rgba[0] * 31)];
  71. uint G = curve[uint(rgba[1] * 31)];
  72. uint B = curve[uint(rgba[2] * 31)];
  73. uint Rr = R * 16;
  74. uint Gr = R * 4;
  75. uint Br = R * 4;
  76. uint Rg = G * 8;
  77. uint Gg = G * 16;
  78. uint Bg = G * 8;
  79. uint Rb = B * 0; //intentionally always zero
  80. uint Gb = B * 8;
  81. uint Bb = B * 16;
  82. // With no pointers, the shader language has no swap method.
  83. #define swap(a, b) {a ^= b; b ^= a; a ^= b;}
  84. if(Rr < Rg) swap(Rr, Rg);
  85. if(Rr < Rb) swap(Rr, Rb);
  86. if(Rg < Rb) swap(Rg, Rb);
  87. if(Gr < Gg) swap(Gr, Gg);
  88. if(Gr < Gb) swap(Gr, Gb);
  89. if(Gg < Gb) swap(Gg, Gb);
  90. if(Br < Bg) swap(Br, Bg);
  91. if(Br < Bb) swap(Br, Bb);
  92. if(Bg < Bb) swap(Bg, Bb);
  93. R = (((4 * Rr + 2 * Rg + Rb) * 160) >> 14) + 32;
  94. G = (((4 * Gr + 2 * Gg + Gb) * 160) >> 14) + 32;
  95. B = (((4 * Br + 2 * Bg + Bb) * 160) >> 14) + 32;
  96. gbacolor = vec4(
  97. R / 255.0,
  98. G / 255.0,
  99. B / 255.0,
  100. 0.0
  101. );
  102. #endif
  103. //pixel grid
  104. vec2 texelSize = 1.0 / sourceSize[0].xy;
  105. vec2 range = sourceSize[0].xy / (targetSize.xy * sourceSize[0].xy);
  106. vec3 cred = pow(red, vec3(outgamma));
  107. vec3 cgreen = pow(green, vec3(outgamma));
  108. vec3 cblue = pow(blue, vec3(outgamma));
  109. ivec2 tli = ivec2(floor(texCoord/texelSize-vec2(0.4999)));
  110. vec3 lcol, rcol;
  111. float subpix = (texCoord.x/texelSize.x - 0.4999 - float(tli.x))*3.0;
  112. float rsubpix = range.x/texelSize.x * 3.0;
  113. lcol = vec3(intsmear(subpix+1.0,rsubpix, 1.5, coeffs_x),
  114. intsmear(subpix ,rsubpix, 1.5, coeffs_x),
  115. intsmear(subpix-1.0,rsubpix, 1.5, coeffs_x));
  116. rcol = vec3(intsmear(subpix-2.0,rsubpix, 1.5, coeffs_x),
  117. intsmear(subpix-3.0,rsubpix, 1.5, coeffs_x),
  118. intsmear(subpix-4.0,rsubpix, 1.5, coeffs_x));
  119. #ifdef BGR
  120. lcol.rgb = lcol.bgr;
  121. rcol.rgb = rcol.bgr;
  122. #endif
  123. float tcol, bcol;
  124. subpix = texCoord.y/texelSize.y - 0.4999 - float(tli.y);
  125. rsubpix = range.y/texelSize.y;
  126. tcol = intsmear(subpix ,rsubpix, 0.63, coeffs_y);
  127. bcol = intsmear(subpix-1.0,rsubpix, 0.63, coeffs_y);
  128. vec3 topLeftColor = fetch_offset(tli, ivec2(0,0)) * lcol * vec3(tcol);
  129. vec3 bottomRightColor = fetch_offset(tli, ivec2(1,1)) * rcol * vec3(bcol);
  130. vec3 bottomLeftColor = fetch_offset(tli, ivec2(0,1)) * lcol * vec3(bcol);
  131. vec3 topRightColor = fetch_offset(tli, ivec2(1,0)) * rcol * vec3(tcol);
  132. vec3 averageColor = topLeftColor + bottomRightColor + bottomLeftColor + topRightColor;
  133. averageColor = mat3x3(cred, cgreen, cblue) * averageColor;
  134. vec4 intermed = vec4(averageColor, 1.0);
  135. fragColor = (gbacolor + pow(intermed,vec4(1.0/gamma))) / 2.0;
  136. }