|
@@ -1,152 +0,0 @@
|
|
|
-/*
|
|
|
- * 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;
|
|
|
-}
|