1
0

shader.wgsl 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. // Copyright © SixtyFPS GmbH <info@slint.dev>
  2. // SPDX-License-Identifier: MIT
  3. struct VertexOutput {
  4. @builtin(position) position: vec4<f32>,
  5. @location(0) frag_position: vec2<f32>,
  6. };
  7. @vertex
  8. fn vs_main(
  9. @builtin(vertex_index) vertex_index: u32
  10. ) -> VertexOutput {
  11. var output: VertexOutput;
  12. var positions = array<vec2<f32>, 3>(
  13. vec2<f32>(-1.0, 3.0),
  14. vec2<f32>(-1.0, -1.0),
  15. vec2<f32>( 3.0, -1.0)
  16. );
  17. let pos = positions[vertex_index];
  18. output.position = vec4<f32>(pos.x, -pos.y, 0.0, 1.0);
  19. output.frag_position = pos;
  20. return output;
  21. }
  22. struct PushConstants {
  23. light_color_and_time: vec4<f32>,
  24. };
  25. var<push_constant> pc: PushConstants;
  26. fn sdRoundBox(p: vec3<f32>, b: vec3<f32>, r: f32) -> f32 {
  27. let q = abs(p) - b;
  28. return length(max(q, vec3<f32>(0.0))) + min(max(q.x, max(q.y, q.z)), 0.0) - r;
  29. }
  30. fn rotateY(r: vec3<f32>, angle: f32) -> vec3<f32> {
  31. let c = cos(angle);
  32. let s = sin(angle);
  33. let rotation_matrix = mat3x3<f32>(
  34. vec3<f32>( c, 0.0, s),
  35. vec3<f32>(0.0, 1.0, 0.0),
  36. vec3<f32>(-s, 0.0, c)
  37. );
  38. return rotation_matrix * r;
  39. }
  40. fn rotateZ(r: vec3<f32>, angle: f32) -> vec3<f32> {
  41. let c = cos(angle);
  42. let s = sin(angle);
  43. let rotation_matrix = mat3x3<f32>(
  44. vec3<f32>( c, -s, 0.0),
  45. vec3<f32>( s, c, 0.0),
  46. vec3<f32>(0.0, 0.0, 1.0)
  47. );
  48. return rotation_matrix * r;
  49. }
  50. // Distance from the scene
  51. fn scene(r: vec3<f32>) -> f32 {
  52. let iTime = pc.light_color_and_time.w;
  53. let pos = rotateZ(rotateY(r + vec3<f32>(-1.0, -1.0, 4.0), iTime), iTime);
  54. let cube = vec3<f32>(0.5, 0.5, 0.5);
  55. let edge = 0.1;
  56. return sdRoundBox(pos, cube, edge);
  57. }
  58. // https://iquilezles.org/articles/normalsSDF
  59. fn normal(pos: vec3<f32>) -> vec3<f32> {
  60. let e = vec2<f32>(1.0, -1.0) * 0.5773;
  61. let eps = 0.0005;
  62. return normalize(
  63. e.xyy * scene(pos + e.xyy * eps) +
  64. e.yyx * scene(pos + e.yyx * eps) +
  65. e.yxy * scene(pos + e.yxy * eps) +
  66. e.xxx * scene(pos + e.xxx * eps)
  67. );
  68. }
  69. fn render(fragCoord: vec2<f32>, light_color: vec3<f32>) -> vec4<f32> {
  70. var color = vec4<f32>(0.0, 0.0, 0.0, 1.0);
  71. var camera = vec3<f32>(1.0, 2.0, 1.0);
  72. var p = vec3<f32>(fragCoord.x, fragCoord.y + 1.0, -1.0);
  73. var dir = normalize(p - camera);
  74. var i = 0;
  75. loop {
  76. if (i >= 90) { break; }
  77. let dist = scene(p);
  78. if (dist < 0.0001) { break; }
  79. p = p + dir * dist;
  80. i = i + 1;
  81. }
  82. let surf_normal = normal(p);
  83. let light_position = vec3<f32>(2.0, 4.0, -0.5);
  84. var light = 7.0 + 2.0 * dot(surf_normal, light_position);
  85. light = light / (0.2 * pow(length(light_position - p), 3.5));
  86. let alpha = select(0.0, 1.0, i < 90);
  87. return vec4<f32>(light * light_color, alpha) * 2.0;
  88. }
  89. @fragment
  90. fn fs_main(@location(0) frag_position: vec2<f32>) -> @location(0) vec4<f32> {
  91. let selected_light_color = pc.light_color_and_time.xyz;
  92. let r = vec2<f32>(0.5 * frag_position.x + 1.0, 0.5 - 0.5 * frag_position.y);
  93. return render(r, selected_light_color);
  94. }