panel_fragment.glsl 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. //
  2. // Fragment Shader template
  3. //
  4. // Texture uniforms
  5. uniform sampler2D MatTexture;
  6. uniform vec2 MatTexinfo[3];
  7. // Macros to access elements inside the MatTexinfo array
  8. #define MatTexOffset MatTexinfo[0]
  9. #define MatTexRepeat MatTexinfo[1]
  10. #define MatTexFlipY bool(MatTexinfo[2].x) // not used
  11. #define MatTexVisible bool(MatTexinfo[2].y) // not used
  12. // Inputs from vertex shader
  13. in vec2 FragTexcoord;
  14. // Input uniform
  15. uniform vec4 Panel[8];
  16. #define Bounds Panel[0] // panel bounds in texture coordinates
  17. #define Border Panel[1] // panel border in texture coordinates
  18. #define Padding Panel[2] // panel padding in texture coordinates
  19. #define Content Panel[3] // panel content area in texture coordinates
  20. #define BorderColor Panel[4] // panel border color
  21. #define PaddingColor Panel[5] // panel padding color
  22. #define ContentColor Panel[6] // panel content color
  23. #define TextureValid bool(Panel[7].x) // texture valid flag
  24. // Output
  25. out vec4 FragColor;
  26. /***
  27. * Checks if current fragment texture coordinate is inside the
  28. * supplied rectangle in texture coordinates:
  29. * rect[0] - position x [0,1]
  30. * rect[1] - position y [0,1]
  31. * rect[2] - width [0,1]
  32. * rect[3] - height [0,1]
  33. */
  34. bool checkRect(vec4 rect) {
  35. if (FragTexcoord.x < rect[0]) {
  36. return false;
  37. }
  38. if (FragTexcoord.x > rect[0] + rect[2]) {
  39. return false;
  40. }
  41. if (FragTexcoord.y < rect[1]) {
  42. return false;
  43. }
  44. if (FragTexcoord.y > rect[1] + rect[3]) {
  45. return false;
  46. }
  47. return true;
  48. }
  49. void main() {
  50. // Discard fragment outside of received bounds
  51. // Bounds[0] - xmin
  52. // Bounds[1] - ymin
  53. // Bounds[2] - xmax
  54. // Bounds[3] - ymax
  55. if (FragTexcoord.x <= Bounds[0] || FragTexcoord.x >= Bounds[2]) {
  56. discard;
  57. }
  58. if (FragTexcoord.y <= Bounds[1] || FragTexcoord.y >= Bounds[3]) {
  59. discard;
  60. }
  61. // Check if fragment is inside content area
  62. if (checkRect(Content)) {
  63. // If no texture, the color will be the material color.
  64. vec4 color = ContentColor;
  65. if (TextureValid) {
  66. // Adjust texture coordinates to fit texture inside the content area
  67. vec2 offset = vec2(-Content[0], -Content[1]);
  68. vec2 factor = vec2(1/Content[2], 1/Content[3]);
  69. vec2 texcoord = (FragTexcoord + offset) * factor;
  70. vec4 texColor = texture(MatTexture, texcoord * MatTexRepeat + MatTexOffset);
  71. // Mix content color with texture color.
  72. // Note that doing a simple linear interpolation (e.g. using mix()) is not correct!
  73. // The right formula can be found here: https://en.wikipedia.org/wiki/Alpha_compositing#Alpha_blending
  74. // For a more in-depth discussion: http://apoorvaj.io/alpha-compositing-opengl-blending-and-premultiplied-alpha.html#toc4
  75. // Pre-multiply the content color
  76. vec4 contentPre = ContentColor;
  77. contentPre.rgb *= contentPre.a;
  78. // Pre-multiply the texture color
  79. vec4 texPre = texColor;
  80. texPre.rgb *= texPre.a;
  81. // Combine colors the premultiplied final color
  82. color = texPre + contentPre * (1 - texPre.a);
  83. // Un-pre-multiply (pre-divide? :P)
  84. color.rgb /= color.a;
  85. }
  86. FragColor = color;
  87. return;
  88. }
  89. // Checks if fragment is inside paddings area
  90. if (checkRect(Padding)) {
  91. FragColor = PaddingColor;
  92. return;
  93. }
  94. // Checks if fragment is inside borders area
  95. if (checkRect(Border)) {
  96. FragColor = BorderColor;
  97. return;
  98. }
  99. // Fragment is in margins area (always transparent)
  100. FragColor = vec4(1,1,1,0);
  101. }