From 12020be05acf34d5657797ac9bd40681dfa8b86a Mon Sep 17 00:00:00 2001 From: "C. J. Howard" Date: Wed, 2 Sep 2020 13:25:34 -0700 Subject: [PATCH] Depth-sort decals properly, add decal offset, and fix painting cursor position --- src/game/components/tool-component.hpp | 1 + src/game/events/tool-events.cpp | 2 ++ src/game/events/tool-events.hpp | 3 ++ src/game/systems/painting-system.cpp | 20 +++++++----- src/game/systems/painting-system.hpp | 1 + src/game/systems/tool-system.cpp | 5 +++ src/renderer/passes/material-pass.cpp | 42 ++++++++++++++++++++++++-- 7 files changed, 63 insertions(+), 11 deletions(-) diff --git a/src/game/components/tool-component.hpp b/src/game/components/tool-component.hpp index a2e1781..cc1654c 100644 --- a/src/game/components/tool-component.hpp +++ b/src/game/components/tool-component.hpp @@ -28,6 +28,7 @@ struct tool_component float idle_distance; float active_distance; bool heliotropic; + float3 cursor; //float activation_speed; }; diff --git a/src/game/events/tool-events.cpp b/src/game/events/tool-events.cpp index bcb51e2..4985f28 100644 --- a/src/game/events/tool-events.cpp +++ b/src/game/events/tool-events.cpp @@ -23,6 +23,7 @@ event_base* tool_pressed_event::clone() const { tool_pressed_event* event = new tool_pressed_event(); event->entity = entity; + event->position = position; return event; } @@ -30,5 +31,6 @@ event_base* tool_released_event::clone() const { tool_released_event* event = new tool_released_event(); event->entity = entity; + event->position = position; return event; } diff --git a/src/game/events/tool-events.hpp b/src/game/events/tool-events.hpp index 4b41581..556dca9 100644 --- a/src/game/events/tool-events.hpp +++ b/src/game/events/tool-events.hpp @@ -21,6 +21,7 @@ #define ANTKEEPER_TOOL_EVENTS_HPP #include "event/event.hpp" +#include "utility/fundamental-types.hpp" #include class tool_pressed_event: public event @@ -28,6 +29,7 @@ class tool_pressed_event: public event public: virtual event_base* clone() const; entt::entity entity; + float3 position; }; class tool_released_event: public event @@ -35,6 +37,7 @@ class tool_released_event: public event public: virtual event_base* clone() const; entt::entity entity; + float3 position; }; #endif // ANTKEEPER_TOOL_EVENTS_HPP diff --git a/src/game/systems/painting-system.cpp b/src/game/systems/painting-system.cpp index c57a8e2..ec951bd 100644 --- a/src/game/systems/painting-system.cpp +++ b/src/game/systems/painting-system.cpp @@ -20,6 +20,7 @@ #include "painting-system.hpp" #include "game/components/transform-component.hpp" #include "game/components/brush-component.hpp" +#include "game/components/tool-component.hpp" #include "event/event-dispatcher.hpp" #include "resources/resource-manager.hpp" #include "scene/scene.hpp" @@ -49,6 +50,7 @@ painting_system::painting_system(entt::registry& registry, ::event_dispatcher* e event_dispatcher->subscribe(this); max_miter_angle = math::radians(135.0f); + decal_offset = 0.01f; stroke_width = 1.0f; min_stroke_length = 1.0f; min_stroke_length_squared = min_stroke_length * min_stroke_length; @@ -93,7 +95,9 @@ void painting_system::update(double t, double dt) { if (painting) { - auto cast_result = cast_ray(ec::get_world_transform(registry, brush_entity).translation); + const tool_component& tool = registry.get(brush_entity); + + auto cast_result = cast_ray(tool.cursor); if (cast_result.has_value()) { float3 p2 = @@ -123,10 +127,10 @@ void painting_system::update(double t, double dt) float3 a = p0a; float3 b = p0b; - float3 c = p1 - segment_right * stroke_width * 0.5f; - float3 d = p1 + segment_right * stroke_width * 0.5f; - float3 e = p2 - segment_right * stroke_width * 0.5f; - float3 f = p2 + segment_right * stroke_width * 0.5f; + float3 c = p1 - segment_right * stroke_width * 0.5f + segment_up * decal_offset; + float3 d = p1 + segment_right * stroke_width * 0.5f + segment_up * decal_offset; + float3 e = p2 - segment_right * stroke_width * 0.5f + segment_up * decal_offset; + float3 f = p2 + segment_right * stroke_width * 0.5f + segment_up * decal_offset; // Adjust c and d bool mitered = false; @@ -136,8 +140,8 @@ void painting_system::update(double t, double dt) if (angle < max_miter_angle) { mitered = true; - c = p1 - float3{miter.x, 0.0f, miter.y} * miter_length * 0.5f; - d = p1 + float3{miter.x, 0.0f, miter.y} * miter_length * 0.5f; + c = p1 - float3{miter.x, 0.0f, miter.y} * miter_length * 0.5f + segment_up * decal_offset; + d = p1 + float3{miter.x, 0.0f, miter.y} * miter_length * 0.5f + segment_up * decal_offset; } } @@ -201,7 +205,7 @@ void painting_system::handle_event(const tool_pressed_event& event) { if (registry.has(event.entity)) { - auto cast_result = cast_ray(ec::get_world_transform(registry, event.entity).translation); + auto cast_result = cast_ray(event.position); if (cast_result.has_value()) { diff --git a/src/game/systems/painting-system.hpp b/src/game/systems/painting-system.hpp index 7544da6..a689bbe 100644 --- a/src/game/systems/painting-system.hpp +++ b/src/game/systems/painting-system.hpp @@ -67,6 +67,7 @@ private: int max_stroke_segments; int current_stroke_segment; float max_miter_angle; + float decal_offset; float3 stroke_bounds_min; float3 stroke_bounds_max; float3 p0; diff --git a/src/game/systems/tool-system.cpp b/src/game/systems/tool-system.cpp index 9167cee..24f0333 100644 --- a/src/game/systems/tool-system.cpp +++ b/src/game/systems/tool-system.cpp @@ -208,6 +208,9 @@ void tool_system::update(double t, double dt) ec::assign_render_layers(registry, active_tool, 1); warp = false; } + + // Update tool's cursor position + tool.cursor = pick_spring.x0; //math::quaternion rotation = math::angle_axis(orbit_cam->get_azimuth() + pick_angle, float3{0, 1, 0}); //transform.transform.rotation = rotation; @@ -296,6 +299,7 @@ void tool_system::set_tool_active(bool active) // Queue tool pressed event tool_pressed_event event; event.entity = active_tool; + event.position = pick_spring.x0; event_dispatcher->queue(event); } else @@ -306,6 +310,7 @@ void tool_system::set_tool_active(bool active) // Queue tool pressed event tool_released_event event; event.entity = active_tool; + event.position = pick_spring.x0; event_dispatcher->queue(event); } } diff --git a/src/renderer/passes/material-pass.cpp b/src/renderer/passes/material-pass.cpp index 7fb239c..123b8ec 100644 --- a/src/renderer/passes/material-pass.cpp +++ b/src/renderer/passes/material-pass.cpp @@ -347,14 +347,22 @@ void material_pass::render(render_context* context) const { if (material_flags & MATERIAL_FLAG_DECAL) { - glDisable(GL_DEPTH_TEST); + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LEQUAL); + glDepthMask(GL_FALSE); + glEnable(GL_STENCIL_TEST); glStencilFunc(GL_EQUAL, 1, ~0); + //glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO); + //glStencilMask(~0); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); glStencilMask(0); } else { glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + glDepthMask(GL_TRUE); glDisable(GL_STENCIL_TEST); glStencilMask(0); } @@ -582,8 +590,36 @@ bool operation_compare(const render_operation& a, const render_operation& b) { if (transparent_b) { - // A and B are both transparent, render back to front - return (a.depth >= b.depth); + // Determine decal status + bool decal_a = a.material->get_flags() & MATERIAL_FLAG_DECAL; + bool decal_b = b.material->get_flags() & MATERIAL_FLAG_DECAL; + + if (decal_a) + { + if (decal_b) + { + // A and B are both transparent decals, render back to front + return (a.depth >= b.depth); + } + else + { + // A is a transparent decal, B is transparent but not a decal, render A first + return true; + } + } + else + { + if (decal_b) + { + // A is transparent but not a decal, B is a transparent decal, render B first + return false; + } + else + { + // A and B are both transparent, but not decals, render back to front + return (a.depth >= b.depth); + } + } } else {