diff --git a/data/shaders/common_buffers.hlsl b/data/shaders/common_buffers.hlsl index 4d979d841..4c6a8f77d 100644 --- a/data/shaders/common_buffers.hlsl +++ b/data/shaders/common_buffers.hlsl @@ -35,9 +35,9 @@ struct FrameBufferData float2 taa_jitter_current; float2 taa_jitter_previous; + float time; float delta_time; uint frame; - float gamma; uint options; float3 camera_position; @@ -45,6 +45,9 @@ struct FrameBufferData float3 camera_direction; float camera_far; + + float gamma; + float3 padding; }; struct LightBufferData @@ -65,7 +68,7 @@ struct LightBufferData uint options; float3 cascade_ends; - float padding; + float padding2; }; struct MaterialBufferData @@ -88,7 +91,7 @@ struct MaterialBufferData float anisotropic_rotation; float sheen; float sheen_tint; - float padding2; + float padding3; }; cbuffer BufferFrame : register(b0) { FrameBufferData buffer_frame; }; // low frequency - updates once per frame diff --git a/data/shaders/common_vertex_operations.hlsl b/data/shaders/common_vertex_operations.hlsl index f860932cc..1a6ef8d9b 100644 --- a/data/shaders/common_vertex_operations.hlsl +++ b/data/shaders/common_vertex_operations.hlsl @@ -19,8 +19,25 @@ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -// this is shared between depth_prepass.hlsl and g_buffer.hlsl, this is because the calculations have to be exactly the same -float4 compute_screen_space_position(Vertex_PosUvNorTan input, matrix transform, matrix view_projection) +// thse functions are shared between depth_prepass.hlsl and g_buffer.hlsl, this is because the calculations have to be exactly the same + +float4 apply_wind_to_vertex(uint instance_id, float4 world_position, float time) +{ + const float3 wind_direction = float3(1, 0, 0); + const float sway_extent = 0.0001f; // oscillation amplitude + const float sway_speed = 2.0f; // oscillation frequency + const float sway_more_on_top = 2.0f; // sway at the top more + + float wave_factor = sin((time * sway_speed) + world_position.x + float(instance_id) * 0.1f); // offset by instance_id + float height_factor = pow(world_position.y, sway_more_on_top); + + float3 offset = wind_direction * wave_factor * height_factor * sway_extent; + world_position.xyz += offset; + + return world_position; +} + +float4 compute_screen_space_position(Vertex_PosUvNorTan input, uint instance_id, matrix transform, matrix view_projection) { float4 position = input.position; position.w = 1.0f; @@ -29,6 +46,7 @@ float4 compute_screen_space_position(Vertex_PosUvNorTan input, matrix transform, #if INSTANCED world_position = mul(world_position, input.instance_transform); + world_position = apply_wind_to_vertex(instance_id, world_position, buffer_frame.time); #endif return mul(world_position, view_projection); diff --git a/data/shaders/depth_prepass.hlsl b/data/shaders/depth_prepass.hlsl index 514cbd55a..9bd6f83a3 100644 --- a/data/shaders/depth_prepass.hlsl +++ b/data/shaders/depth_prepass.hlsl @@ -24,11 +24,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "common_vertex_operations.hlsl" //====================================== -Pixel_PosUv mainVS(Vertex_PosUvNorTan input) +Pixel_PosUv mainVS(Vertex_PosUvNorTan input, uint instance_id : SV_InstanceID) { Pixel_PosUv output; - output.position = compute_screen_space_position(input, buffer_pass.transform, buffer_frame.view_projection); + output.position = compute_screen_space_position(input, instance_id, buffer_pass.transform, buffer_frame.view_projection); output.uv = input.uv; return output; diff --git a/data/shaders/g_buffer.hlsl b/data/shaders/g_buffer.hlsl index eac00aea3..6d197c0b7 100644 --- a/data/shaders/g_buffer.hlsl +++ b/data/shaders/g_buffer.hlsl @@ -42,23 +42,26 @@ struct PixelOutputType float fsr2_transparency_mask : SV_Target5; }; -PixelInputType mainVS(Vertex_PosUvNorTan input) +PixelInputType mainVS(Vertex_PosUvNorTan input, uint instance_id : SV_InstanceID) { PixelInputType output; - output.position = compute_screen_space_position(input, buffer_pass.transform, buffer_frame.view_projection); - output.position_ss_current = output.position; - - // update this part to use the adjusted position_world for the previous frame as well + // position current + output.position = compute_screen_space_position(input, instance_id, buffer_pass.transform, buffer_frame.view_projection); + output.position_ss_current = output.position; + + // position previous float4 position_world_previous = mul(input.position, pass_get_transform_previous()); #if INSTANCED position_world_previous = mul(position_world_previous, input.instance_transform); + position_world_previous = apply_wind_to_vertex(instance_id, position_world_previous, buffer_frame.time - buffer_frame.delta_time); #endif output.position_ss_previous = mul(position_world_previous, buffer_frame.view_projection_previous); - - output.normal_world = normalize(mul(input.normal, (float3x3)buffer_pass.transform)).xyz; - output.tangent_world = normalize(mul(input.tangent, (float3x3)buffer_pass.transform)).xyz; - output.uv = input.uv; + + // misc + output.normal_world = normalize(mul(input.normal, (float3x3)buffer_pass.transform)).xyz; + output.tangent_world = normalize(mul(input.tangent, (float3x3)buffer_pass.transform)).xyz; + output.uv = input.uv; return output; } diff --git a/data/shaders/light_composition.hlsl b/data/shaders/light_composition.hlsl index 30bbcd97e..980c77f8b 100644 --- a/data/shaders/light_composition.hlsl +++ b/data/shaders/light_composition.hlsl @@ -88,7 +88,7 @@ void mainCS(uint3 thread_id : SV_DispatchThreadID) surface.Build(thread_id.xy, true, true, false); bool early_exit_1 = pass_is_opaque() && surface.is_transparent(); // if this is an opaque pass, ignore all transparent pixels. - bool early_exit_2 = pass_is_transparent() && surface.is_opaque(); // if this is an transparent pass, ignore all opaque pixels. + bool early_exit_2 = pass_is_transparent() && surface.is_opaque(); // if this is a transparent pass, ignore all opaque pixels. bool early_exit_3 = pass_is_transparent() && surface.is_sky(); // if this is a transparent pass, ignore sky pixels (they only render in the opaque) if (early_exit_1 || early_exit_2 || early_exit_3) return; @@ -101,7 +101,7 @@ void mainCS(uint3 thread_id : SV_DispatchThreadID) color.rgb += tex_environment.SampleLevel(samplers[sampler_bilinear_clamp], direction_sphere_uv(surface.camera_to_pixel), 0).rgb; color.rgb *= saturate(buffer_light.intensity); // modulate it's intensity in order to fake day/night. } - else // everything else + else // anything else { // diffuse and specular float3 light_diffuse = tex_light_diffuse[thread_id.xy].rgb; @@ -118,7 +118,7 @@ void mainCS(uint3 thread_id : SV_DispatchThreadID) // compose float3 light_ds = (light_diffuse + surface.gi) * surface.albedo + light_specular; - color.rgb += lerp(light_ds, light_refraction, 1.0f - surface.alpha); + color.rgb = lerp(light_ds, light_refraction, 1.0f - surface.alpha); } // volumetric fog diff --git a/editor/Widgets/Properties.cpp b/editor/Widgets/Properties.cpp index e254874d3..7a09ecf06 100644 --- a/editor/Widgets/Properties.cpp +++ b/editor/Widgets/Properties.cpp @@ -376,6 +376,7 @@ void Properties::ShowRenderable(shared_ptr renderable) const string name_mesh = mesh ? mesh->GetObjectName() : "N/A"; string name_material = material ? material->GetObjectName() : "N/A"; bool cast_shadows = renderable->GetCastShadows(); + bool affected_by_wind = renderable->GetAffectedByWind(); //===================================================================== // mesh @@ -400,13 +401,16 @@ void Properties::ShowRenderable(shared_ptr renderable) const renderable->SetMaterial(std::get(payload->data)); } - // cast shadows - ImGui::Text("Cast Shadows"); - ImGui::SameLine(column_pos_x); ImGui::Checkbox("##RenderableCastShadows", &cast_shadows); + ImGui::Text("Cast shadows"); + ImGui::SameLine(column_pos_x); ImGui::Checkbox("##renderable_cast_shadows", &cast_shadows); - //= MAP =================================================================================== + ImGui::Text("Affected by wind"); + ImGui::SameLine(column_pos_x); ImGui::Checkbox("##renderable_affected_by_wind", &affected_by_wind); + + //= MAP ========================================================================================== if (cast_shadows != renderable->GetCastShadows()) renderable->SetCastShadows(cast_shadows); - //========================================================================================= + if (cast_shadows != renderable->GetCastShadows()) renderable->SetAffectedByWind(affected_by_wind); + //================================================================================================ } component_end(); } diff --git a/runtime/Rendering/Renderer.cpp b/runtime/Rendering/Renderer.cpp index 96ee343db..741697715 100644 --- a/runtime/Rendering/Renderer.cpp +++ b/runtime/Rendering/Renderer.cpp @@ -353,9 +353,11 @@ namespace Spartan m_cb_frame_cpu.resolution_render = m_resolution_render; m_cb_frame_cpu.taa_jitter_previous = m_cb_frame_cpu.taa_jitter_current; m_cb_frame_cpu.taa_jitter_current = jitter_offset; - m_cb_frame_cpu.delta_time = static_cast(Timer::GetDeltaTimeSmoothedSec()); - m_cb_frame_cpu.gamma = GetOption(Renderer_Option::Gamma); + m_cb_frame_cpu.time = static_cast(Timer::GetTimeSec()); + m_cb_frame_cpu.delta_time = static_cast(Timer::GetDeltaTimeSec()); m_cb_frame_cpu.frame = static_cast(frame_num); + m_cb_frame_cpu.gamma = GetOption(Renderer_Option::Gamma); + // these must match what common_buffer.hlsl is reading m_cb_frame_cpu.set_bit(GetOption(Renderer_Option::ScreenSpaceReflections), 1 << 0); diff --git a/runtime/Rendering/Renderer_ConstantBuffers.h b/runtime/Rendering/Renderer_ConstantBuffers.h index 1ae146ba3..60f4e5a2f 100644 --- a/runtime/Rendering/Renderer_ConstantBuffers.h +++ b/runtime/Rendering/Renderer_ConstantBuffers.h @@ -47,9 +47,9 @@ namespace Spartan Math::Vector2 taa_jitter_current; Math::Vector2 taa_jitter_previous; + float time; float delta_time; uint32_t frame; - float gamma; uint32_t options; Math::Vector3 camera_position; @@ -58,6 +58,9 @@ namespace Spartan Math::Vector3 camera_direction; float camera_far; + float gamma; + Math::Vector3 padding; + void set_bit(const bool set, const uint32_t bit) { options = set ? (options |= bit) : (options & ~bit); @@ -73,6 +76,7 @@ namespace Spartan view_projection_ortho == rhs.view_projection_ortho && view_projection_unjittered == rhs.view_projection_unjittered && view_projection_previous == rhs.view_projection_previous && + time == rhs.time && delta_time == rhs.delta_time && frame == rhs.frame && camera_near == rhs.camera_near && diff --git a/runtime/Rendering/Renderer_Passes.cpp b/runtime/Rendering/Renderer_Passes.cpp index 26d68595f..cc61a8808 100644 --- a/runtime/Rendering/Renderer_Passes.cpp +++ b/runtime/Rendering/Renderer_Passes.cpp @@ -525,13 +525,16 @@ namespace Spartan } // set pass constants - m_cb_pass_cpu.transform = entity->GetTransform()->GetMatrix(); - m_cb_pass_cpu.set_f3_value( - material->HasTexture(MaterialTexture::AlphaMask) ? 1.0f : 0.0f, - material->HasTexture(MaterialTexture::Color) ? 1.0f : 0.0f, - material->GetProperty(MaterialProperty::ColorA) - ); - PushPassConstants(cmd_list); + { + m_cb_pass_cpu.transform = entity->GetTransform()->GetMatrix(); + m_cb_pass_cpu.set_f3_value( + material->HasTexture(MaterialTexture::AlphaMask) ? 1.0f : 0.0f, + material->HasTexture(MaterialTexture::Color) ? 1.0f : 0.0f, + material->GetProperty(MaterialProperty::ColorA) + ); + + PushPassConstants(cmd_list); + } // draw cmd_list->DrawIndexed( diff --git a/runtime/World/Components/Renderable.cpp b/runtime/World/Components/Renderable.cpp index 356a2f0dc..bd69d693a 100644 --- a/runtime/World/Components/Renderable.cpp +++ b/runtime/World/Components/Renderable.cpp @@ -41,6 +41,7 @@ namespace Spartan SP_REGISTER_ATTRIBUTE_VALUE_VALUE(m_material_default, bool); SP_REGISTER_ATTRIBUTE_VALUE_VALUE(m_material, Material*); SP_REGISTER_ATTRIBUTE_VALUE_VALUE(m_cast_shadows, bool); + SP_REGISTER_ATTRIBUTE_VALUE_VALUE(m_affected_by_wind, bool); SP_REGISTER_ATTRIBUTE_VALUE_VALUE(m_geometry_index_offset, uint32_t); SP_REGISTER_ATTRIBUTE_VALUE_VALUE(m_geometry_index_count, uint32_t); SP_REGISTER_ATTRIBUTE_VALUE_VALUE(m_geometry_vertex_offset, uint32_t); diff --git a/runtime/World/Components/Renderable.h b/runtime/World/Components/Renderable.h index 36dd6821d..f12c982fd 100644 --- a/runtime/World/Components/Renderable.h +++ b/runtime/World/Components/Renderable.h @@ -41,7 +41,7 @@ namespace Spartan Renderable(std::weak_ptr entity); ~Renderable(); - // IComponent + // icomponent void Serialize(FileStream* stream) override; void Deserialize(FileStream* stream) override; @@ -79,7 +79,11 @@ namespace Spartan // shadows void SetCastShadows(const bool cast_shadows) { m_cast_shadows = cast_shadows; } - auto GetCastShadows() const { return m_cast_shadows; } + bool GetCastShadows() const { return m_cast_shadows; } + + // affected by wind + void SetAffectedByWind(const bool affected_by_wind) { m_affected_by_wind = affected_by_wind; } + bool GetAffectedByWind() const { return m_affected_by_wind; } // instancing bool HasInstancing() const { return !m_instances.empty(); } @@ -109,5 +113,6 @@ namespace Spartan // misc Math::Matrix m_last_transform = Math::Matrix::Identity; bool m_cast_shadows = true; + bool m_affected_by_wind = false; }; }