Stacks.azsl 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <scenesrg.srgi>
  9. #include <viewsrg.srgi>
  10. #include <Atom/Features/PBR/DefaultObjectSrg.azsli>
  11. #include <Atom/RPI/ShaderResourceGroups/DefaultDrawSrg.azsli>
  12. // This shader draws a model with most of the surface clipped away, only drawing regularly spaced slices of it.
  13. // The idea is to run a model through several variants of this same shader, so the combined appearance is a shell
  14. // broken into multiple slices that are oscillating in different directions.
  15. // This demonstrates a material's ability to run multiple shader variants, over multiple passes.
  16. // Indicates which direction the stack of slices will animate/wobble.
  17. // This demonstrates the use of a ShaderOption that is an enum, and is controlled through a ShaderCollectionFunctor.
  18. option enum class Direction { None, Left, Right, Up, Down } o_wobbleDirection;
  19. // Indicates the number of independent slice stacks, which will animate together, and the index of the current slice stack.
  20. // Running the shader for each of the available stacks will render enough slices to cover the entire model.
  21. [range(2, 4)]
  22. option uint o_stackCount;
  23. [range(0, 3)]
  24. option int o_stackIndex;
  25. // Indicates whether the current stack's wobble animation should be enabled.
  26. option bool o_animated;
  27. // Indicates whether the current stack's color should be highlighted.
  28. option bool o_highlighted;
  29. // Indicates whether the current stack's color should be highlighted (using an alternate color).
  30. option bool o_highlighted2;
  31. ShaderResourceGroup MaterialSrg : SRG_PerMaterial
  32. {
  33. float3 m_color;
  34. float3 m_lightDir;
  35. float m_sliceThickness;
  36. };
  37. struct VertexInput
  38. {
  39. float3 m_position : POSITION;
  40. float3 m_normal : NORMAL;
  41. };
  42. struct VertexOutput
  43. {
  44. float4 m_position : SV_Position;
  45. float3 m_normal : NORMAL;
  46. float4 m_localPos : UV1;
  47. };
  48. // Oscillates a value between min and max.
  49. float CalcShift(float speed, float min, float max)
  50. {
  51. float t = sin(SceneSrg::m_time * speed) * 0.5 + 0.5;
  52. // Make it snap to min a bit
  53. t = saturate(t * 2 - 1);
  54. float shift = lerp(min, max, t);
  55. return shift;
  56. }
  57. VertexOutput MainVS(VertexInput input)
  58. {
  59. const float4x4 objectToWorldMatrix = ObjectSrg::GetWorldMatrix();
  60. const float wobbleSize = 0.05;
  61. const float wobbleSpeed = 5;
  62. float3 wobbleDir;
  63. switch(o_wobbleDirection)
  64. {
  65. case Direction::Left: wobbleDir = float3(-1, 0, 0); break;
  66. case Direction::Right: wobbleDir = float3( 1, 0, 0); break;
  67. case Direction::Up: wobbleDir = float3(0, 0, 1); break;
  68. case Direction::Down: wobbleDir = float3(0, 0, -1); break;
  69. default: wobbleDir = float3(0, 0, 0);
  70. }
  71. float3 shift;
  72. if (o_animated)
  73. {
  74. shift = wobbleDir * CalcShift(wobbleSpeed, 0, wobbleSize);
  75. }
  76. else
  77. {
  78. shift = wobbleDir * wobbleSize;
  79. }
  80. const float4 position = float4(input.m_position, 1);
  81. VertexOutput output;
  82. output.m_localPos = position;
  83. float3 worldPosition = mul(objectToWorldMatrix, position + float4(shift,0)).xyz;
  84. output.m_position = mul(ViewSrg::m_viewProjectionMatrix, float4(worldPosition, 1.0));
  85. output.m_normal = mul(ObjectSrg::GetWorldMatrixInverseTranspose(), input.m_normal);
  86. output.m_normal = normalize(output.m_normal);
  87. return output;
  88. }
  89. struct PixelOutput
  90. {
  91. float4 m_color : SV_Target0;
  92. };
  93. PixelOutput MainPS(VertexOutput input)
  94. {
  95. PixelOutput output;
  96. float sliceThickness = MaterialSrg::m_sliceThickness;
  97. float sliceStride = sliceThickness * o_stackCount;
  98. float arbitraryBigNumber = 1000; // Used to make the slices not weird around 0
  99. float stackOffset = abs(fmod(input.m_localPos.y + arbitraryBigNumber, sliceStride)) - sliceThickness * o_stackIndex;
  100. // Discard if stackOffset < 0
  101. clip(stackOffset);
  102. // Discard if stackOffset > sliceThickness
  103. clip(sliceThickness - stackOffset);
  104. // fakeLighting is peaks at 0.9, so we can leave room for the o_highlighted option
  105. float3 normal = normalize(input.m_normal);
  106. float fakeLighting = dot(normal, MaterialSrg::m_lightDir) * 0.6 + 0.3;
  107. output.m_color.rgb = fakeLighting * MaterialSrg::m_color;
  108. const float highlightAmount = 0.1;
  109. if (o_highlighted)
  110. {
  111. output.m_color.rgb += highlightAmount * float3(1.0, 0.5, 0.5);
  112. }
  113. if (o_highlighted2)
  114. {
  115. output.m_color.rgb += highlightAmount * float3(0.5, 0.5, 1.0);
  116. }
  117. output.m_color.a = 1;
  118. return output;
  119. }