123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152 |
- /*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
- #include <scenesrg.srgi>
- #include <viewsrg.srgi>
- #include <Atom/Features/PBR/DefaultObjectSrg.azsli>
- #include <Atom/RPI/ShaderResourceGroups/DefaultDrawSrg.azsli>
- // This shader draws a model with most of the surface clipped away, only drawing regularly spaced slices of it.
- // The idea is to run a model through several variants of this same shader, so the combined appearance is a shell
- // broken into multiple slices that are oscillating in different directions.
- // This demonstrates a material's ability to run multiple shader variants, over multiple passes.
- // Indicates which direction the stack of slices will animate/wobble.
- // This demonstrates the use of a ShaderOption that is an enum, and is controlled through a ShaderCollectionFunctor.
- option enum class Direction { None, Left, Right, Up, Down } o_wobbleDirection;
- // Indicates the number of independent slice stacks, which will animate together, and the index of the current slice stack.
- // Running the shader for each of the available stacks will render enough slices to cover the entire model.
- [range(2, 4)]
- option uint o_stackCount;
- [range(0, 3)]
- option int o_stackIndex;
- // Indicates whether the current stack's wobble animation should be enabled.
- option bool o_animated;
- // Indicates whether the current stack's color should be highlighted.
- option bool o_highlighted;
- // Indicates whether the current stack's color should be highlighted (using an alternate color).
- option bool o_highlighted2;
- ShaderResourceGroup MaterialSrg : SRG_PerMaterial
- {
- float3 m_color;
- float3 m_lightDir;
- float m_sliceThickness;
- };
- struct VertexInput
- {
- float3 m_position : POSITION;
- float3 m_normal : NORMAL;
- };
- struct VertexOutput
- {
- float4 m_position : SV_Position;
- float3 m_normal : NORMAL;
- float4 m_localPos : UV1;
- };
- // Oscillates a value between min and max.
- float CalcShift(float speed, float min, float max)
- {
- float t = sin(SceneSrg::m_time * speed) * 0.5 + 0.5;
- // Make it snap to min a bit
- t = saturate(t * 2 - 1);
- float shift = lerp(min, max, t);
- return shift;
- }
- VertexOutput MainVS(VertexInput input)
- {
- const float4x4 objectToWorldMatrix = ObjectSrg::GetWorldMatrix();
- const float wobbleSize = 0.05;
- const float wobbleSpeed = 5;
- float3 wobbleDir;
- switch(o_wobbleDirection)
- {
- case Direction::Left: wobbleDir = float3(-1, 0, 0); break;
- case Direction::Right: wobbleDir = float3( 1, 0, 0); break;
- case Direction::Up: wobbleDir = float3(0, 0, 1); break;
- case Direction::Down: wobbleDir = float3(0, 0, -1); break;
- default: wobbleDir = float3(0, 0, 0);
- }
- float3 shift;
- if (o_animated)
- {
- shift = wobbleDir * CalcShift(wobbleSpeed, 0, wobbleSize);
- }
- else
- {
- shift = wobbleDir * wobbleSize;
- }
- const float4 position = float4(input.m_position, 1);
- VertexOutput output;
- output.m_localPos = position;
- float3 worldPosition = mul(objectToWorldMatrix, position + float4(shift,0)).xyz;
- output.m_position = mul(ViewSrg::m_viewProjectionMatrix, float4(worldPosition, 1.0));
- output.m_normal = mul(ObjectSrg::GetWorldMatrixInverseTranspose(), input.m_normal);
- output.m_normal = normalize(output.m_normal);
- return output;
- }
- struct PixelOutput
- {
- float4 m_color : SV_Target0;
- };
- PixelOutput MainPS(VertexOutput input)
- {
- PixelOutput output;
-
- float sliceThickness = MaterialSrg::m_sliceThickness;
- float sliceStride = sliceThickness * o_stackCount;
- float arbitraryBigNumber = 1000; // Used to make the slices not weird around 0
- float stackOffset = abs(fmod(input.m_localPos.y + arbitraryBigNumber, sliceStride)) - sliceThickness * o_stackIndex;
- // Discard if stackOffset < 0
- clip(stackOffset);
- // Discard if stackOffset > sliceThickness
- clip(sliceThickness - stackOffset);
- // fakeLighting is peaks at 0.9, so we can leave room for the o_highlighted option
- float3 normal = normalize(input.m_normal);
- float fakeLighting = dot(normal, MaterialSrg::m_lightDir) * 0.6 + 0.3;
- output.m_color.rgb = fakeLighting * MaterialSrg::m_color;
- const float highlightAmount = 0.1;
- if (o_highlighted)
- {
- output.m_color.rgb += highlightAmount * float3(1.0, 0.5, 0.5);
- }
- if (o_highlighted2)
- {
- output.m_color.rgb += highlightAmount * float3(0.5, 0.5, 1.0);
- }
- output.m_color.a = 1;
- return output;
- }
|