From 30e7b60acbdaae60424877875bae8dd0becd4cb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tur=C3=A1nszki=20J=C3=A1nos?= Date: Mon, 11 Mar 2024 18:01:39 +0100 Subject: [PATCH] trail renderer (#811) --- .../ScriptingAPI-Documentation.md | 27 ++ Content/scripts/trail_renderer.lua | 58 +++ WickedEngine/CMakeLists.txt | 4 + WickedEngine/WickedEngine.h | 1 + WickedEngine/WickedEngine_SOURCE.vcxitems | 4 + .../WickedEngine_SOURCE.vcxitems.filters | 12 + WickedEngine/offlineshadercompiler.cpp | 2 + WickedEngine/shaders/ShaderInterop.h | 1 + WickedEngine/shaders/ShaderInterop_Renderer.h | 8 + WickedEngine/shaders/Shaders_SOURCE.vcxitems | 6 + .../shaders/Shaders_SOURCE.vcxitems.filters | 6 + WickedEngine/shaders/trailPS.hlsl | 11 + WickedEngine/shaders/trailVS.hlsl | 18 + WickedEngine/wiEmittedParticle.cpp | 12 + WickedEngine/wiInitializer.cpp | 1 + WickedEngine/wiInitializer.h | 1 + WickedEngine/wiLua.cpp | 2 + WickedEngine/wiRenderer.cpp | 14 + WickedEngine/wiRenderer.h | 5 + WickedEngine/wiRenderer_BindLua.cpp | 20 ++ WickedEngine/wiTrailRenderer.cpp | 336 ++++++++++++++++++ WickedEngine/wiTrailRenderer.h | 35 ++ WickedEngine/wiTrailRenderer_BindLua.cpp | 311 ++++++++++++++++ WickedEngine/wiTrailRenderer_BindLua.h | 48 +++ WickedEngine/wiVersion.cpp | 4 +- 25 files changed, 945 insertions(+), 2 deletions(-) create mode 100644 Content/scripts/trail_renderer.lua create mode 100644 WickedEngine/shaders/trailPS.hlsl create mode 100644 WickedEngine/shaders/trailVS.hlsl create mode 100644 WickedEngine/wiTrailRenderer.cpp create mode 100644 WickedEngine/wiTrailRenderer.h create mode 100644 WickedEngine/wiTrailRenderer_BindLua.cpp create mode 100644 WickedEngine/wiTrailRenderer_BindLua.h diff --git a/Content/Documentation/ScriptingAPI-Documentation.md b/Content/Documentation/ScriptingAPI-Documentation.md index 57163560f..403f28aad 100644 --- a/Content/Documentation/ScriptingAPI-Documentation.md +++ b/Content/Documentation/ScriptingAPI-Documentation.md @@ -63,6 +63,7 @@ This is a reference and explanation of Lua scripting features in Wicked Engine. 14. [Path finding](#path-finding) 1. [VoxelGrid](#voxelgrid) 2. [PathQuery](#pathquery) + 15. [TrailRenderer](#trailrenderer) ## Introduction and usage Scripting in Wicked Engine is powered by Lua, meaning that the user can make use of the @@ -158,6 +159,7 @@ You can use the Renderer with the following functions, all of which are in the g [outer]DEBUG_TEXT_CAMERA_SCALING -- text will be always the same size, independent of distance to camera - DrawVoxelGrid(VoxelGrid voxelgrid) -- draws the voxel grid in the debug rendering phase. VoxelGrid object must not be destroyed until then! - DrawPathQuery(PathQuery pathquery) -- draws the path query in the debug rendering phase. PathQuery object must not be destroyed until then! +- DrawTrail(TrailRenderer trail) -- draws the trail in the debug rendering phase. TrailRenderer object must not be destroyed until then! - PutWaterRipple(Vector position) -- put down a water ripple with default embedded asset - PutWaterRipple(string imagename, Vector position) -- put down water ripple texture from image asset file - ClearWorld(opt Scene scene) -- Clears the scene and the associated renderer resources. If parmaeter is not specified, it will clear the global scene @@ -1802,3 +1804,28 @@ Path finding operations can be made by using a voxel grid and path queries. The - GetAgentHeight(int value) : int - GetWaypointCount() : int -- returns the number of waypoints that were computed in Process() - GetWaypoint(int index) : Vector returns the waypoint at specified index (direction: start -> goal) + +### TrailRenderer +- [constructor] TrailRenderer() +- AddPoint(Vector pos, opt float width = 1, opt Vector color = Vector(1,1,1,1)) -- adds a new point to the trail +- Cut() -- cuts the trail at last point and starts a new trail +- Clear() -- removes all points and cuts from the trail +- GetPointCount() : int -- returns the number of points in the trail +- GetPoint() : Vector pos, float width -- returns the point of the trail on the specified index +- SetPoint(Vector pos, opt float width = 1, opt Vector color = Vector(1,1,1,1)) -- sets the point parameters on the specified index +- SetBlendMode(int blendmode) -- set blend mode of the whole trail +- GetBlendMode() : int +- SetSubdivision(int subdiv) -- set the subdivision amount of the whole trail +- GetSubdivision() : int +- SetWidth(float width) -- set the width of the whole trail +- GetWidth() : float +- SetColor(Vector color) -- set the color of the whole trail +- GetColor() : Vector +- SetTexture(Texture tex) -- set the texture of the whole trail +- GetTexture() : Texture +- SetTexture2(Texture tex) -- set the texture2 of the whole trail +- GetTexture2() : Texture +- SetTexMulAdd(Texture tex) -- set the texture UV tiling multiply-add value of the whole trail +- GetTexMulAdd() : Texture +- SetTexMulAdd2(Texture tex) -- set the texture2 UV tiling multiply-add value of the whole trail +- GetTexMulAdd2() : Texture diff --git a/Content/scripts/trail_renderer.lua b/Content/scripts/trail_renderer.lua new file mode 100644 index 000000000..6dd702082 --- /dev/null +++ b/Content/scripts/trail_renderer.lua @@ -0,0 +1,58 @@ +killProcesses() -- stops all running lua coroutine processes + +backlog_post("---> START SCRIPT: trail_renderer.lua") + +local trail = TrailRenderer() +trail.SetWidth(0.2) +trail.SetColor(Vector(10,0.1,0.1,1)) +trail.SetBlendMode(BLENDMODE_ADDITIVE) +trail.SetSubdivision(100) + +-- Trail begins as red: +trail.AddPoint(Vector(-5,2,-3), 4, Vector(10,0.1,0.1,1)) +trail.AddPoint(Vector(5,1,1), 0.5, Vector(10,0.1,0.1,1)) +trail.AddPoint(Vector(10,5,4), 1.2, Vector(10,0.1,0.1,1)) +trail.AddPoint(Vector(6,8,2), 1, Vector(10,0.1,0.1,1)) +trail.AddPoint(Vector(-6,5,0), 1, Vector(10,0.1,0.1,1)) +-- Trail turn into green: +trail.AddPoint(Vector(0,2,-5), 1, Vector(0.1,100,0.1,1)) +trail.AddPoint(Vector(1,3,5), 1, Vector(0.1,100,0.1,1)) +trail.AddPoint(Vector(-3,2,8), 1, Vector(0.1,100,0.1,1)) + +trail.Cut() -- start a new trail without connecting to previous points + +-- Last trail segment is blue: +trail.AddPoint(Vector(-5,0,-2), 1, Vector(0.1,0.1,100,1)) +trail.AddPoint(Vector(5,8,5), 1, Vector(0.1,0.1,100,1)) + +-- First texture is a circle gradient, this makes the overall trail smooth at the edges: +local texture = texturehelper.CreateGradientTexture( + GradientType.Circular, + 256, 256, + Vector(0.5, 0.5), Vector(0.5, 0), + GradientFlags.Inverse, + "rrrr" +) +trail.SetTexture(texture) + +-- Second texture is a linear gradient that will be tiled and animated to achieve stippled look: +local texture2 = texturehelper.CreateGradientTexture( + GradientType.Linear, + 256, 256, + Vector(0.5, 0), Vector(0, 0), + GradientFlags.Inverse | GradientFlags.Smoothstep, + "rrrr" +) +trail.SetTexture2(texture2) + +runProcess(function() + local scrolling = 0 + while true do + scrolling = scrolling - getDeltaTime() + trail.SetTexMulAdd2(Vector(10,1,scrolling,0)) + DrawTrail(trail) + render() -- this loop will be blocked until render tick + end +end) + +backlog_post("---> END SCRIPT: trail_renderer.lua") diff --git a/WickedEngine/CMakeLists.txt b/WickedEngine/CMakeLists.txt index 8d4b301e4..2970fd580 100644 --- a/WickedEngine/CMakeLists.txt +++ b/WickedEngine/CMakeLists.txt @@ -150,6 +150,8 @@ set(HEADER_FILES wiPathQuery.h wiVoxelGrid_BindLua.h wiPathQuery_BindLua.h + wiTrailRenderer.h + wiTrailRenderer_BindLua.h ) add_library(${TARGET_NAME} ${WICKED_LIBRARY_TYPE} @@ -228,6 +230,8 @@ add_library(${TARGET_NAME} ${WICKED_LIBRARY_TYPE} wiPathQuery.cpp wiVoxelGrid_BindLua.cpp wiPathQuery_BindLua.cpp + wiTrailRenderer.cpp + wiTrailRenderer_BindLua.cpp ${HEADER_FILES} ) add_library(WickedEngine ALIAS ${TARGET_NAME}) diff --git a/WickedEngine/WickedEngine.h b/WickedEngine/WickedEngine.h index d50010fd6..730893dc5 100644 --- a/WickedEngine/WickedEngine.h +++ b/WickedEngine/WickedEngine.h @@ -74,6 +74,7 @@ #include "wiVideo.h" #include "wiVoxelGrid.h" #include "wiPathQuery.h" +#include "wiTrailRenderer.h" #ifdef PLATFORM_WINDOWS_DESKTOP #pragma comment(lib,"WickedEngine_Windows.lib") diff --git a/WickedEngine/WickedEngine_SOURCE.vcxitems b/WickedEngine/WickedEngine_SOURCE.vcxitems index 7cba51473..05ddddd6f 100644 --- a/WickedEngine/WickedEngine_SOURCE.vcxitems +++ b/WickedEngine/WickedEngine_SOURCE.vcxitems @@ -278,6 +278,8 @@ + + @@ -713,6 +715,8 @@ + + diff --git a/WickedEngine/WickedEngine_SOURCE.vcxitems.filters b/WickedEngine/WickedEngine_SOURCE.vcxitems.filters index 20d75d4fc..af629b040 100644 --- a/WickedEngine/WickedEngine_SOURCE.vcxitems.filters +++ b/WickedEngine/WickedEngine_SOURCE.vcxitems.filters @@ -1137,6 +1137,12 @@ ENGINE\Scripting\LuaBindings + + ENGINE\Graphics + + + ENGINE\Scripting\LuaBindings + @@ -1904,6 +1910,12 @@ ENGINE\Scripting\LuaBindings + + ENGINE\Graphics + + + ENGINE\Scripting\LuaBindings + diff --git a/WickedEngine/offlineshadercompiler.cpp b/WickedEngine/offlineshadercompiler.cpp index 588ea3762..6499b380b 100644 --- a/WickedEngine/offlineshadercompiler.cpp +++ b/WickedEngine/offlineshadercompiler.cpp @@ -280,6 +280,7 @@ wi::vector shaders = { {"ddgi_debugPS", wi::graphics::ShaderStage::PS }, {"copyDepthPS", wi::graphics::ShaderStage::PS }, {"copyStencilBitPS", wi::graphics::ShaderStage::PS }, + {"trailPS", wi::graphics::ShaderStage::PS }, {"hairparticleVS", wi::graphics::ShaderStage::VS }, @@ -335,6 +336,7 @@ wi::vector shaders = { {"shadowVS_transparent", wi::graphics::ShaderStage::VS }, {"shadowVS_transparent_emulation", wi::graphics::ShaderStage::VS }, {"screenVS", wi::graphics::ShaderStage::VS }, + {"trailVS", wi::graphics::ShaderStage::VS }, diff --git a/WickedEngine/shaders/ShaderInterop.h b/WickedEngine/shaders/ShaderInterop.h index 726288f7b..77574b5cf 100644 --- a/WickedEngine/shaders/ShaderInterop.h +++ b/WickedEngine/shaders/ShaderInterop.h @@ -112,6 +112,7 @@ static const uint IndirectDispatchArgsAlignment = 4u; #define CBSLOT_OTHER_GPUSORTLIB 4 #define CBSLOT_MSAO 4 #define CBSLOT_FSR 4 +#define CBSLOT_TRAILRENDERER 3 #else // Don't use overlapping slots on PS5: diff --git a/WickedEngine/shaders/ShaderInterop_Renderer.h b/WickedEngine/shaders/ShaderInterop_Renderer.h index dbc7de137..d54849c5a 100644 --- a/WickedEngine/shaders/ShaderInterop_Renderer.h +++ b/WickedEngine/shaders/ShaderInterop_Renderer.h @@ -1396,5 +1396,13 @@ struct VirtualTextureTileRequestsPush int padding2; }; +CBUFFER(TrailRendererCB, CBSLOT_TRAILRENDERER) +{ + float4x4 g_xTrailTransform; + float4 g_xTrailColor; + float4 g_xTrailTexMulAdd; + float4 g_xTrailTexMulAdd2; +}; + #endif // WI_SHADERINTEROP_RENDERER_H diff --git a/WickedEngine/shaders/Shaders_SOURCE.vcxitems b/WickedEngine/shaders/Shaders_SOURCE.vcxitems index 0725a21dc..4a61c0512 100644 --- a/WickedEngine/shaders/Shaders_SOURCE.vcxitems +++ b/WickedEngine/shaders/Shaders_SOURCE.vcxitems @@ -1007,6 +1007,12 @@ Compute 4.0 + + Pixel + + + Vertex + Compute 4.0 diff --git a/WickedEngine/shaders/Shaders_SOURCE.vcxitems.filters b/WickedEngine/shaders/Shaders_SOURCE.vcxitems.filters index 1cd3aa802..16826db97 100644 --- a/WickedEngine/shaders/Shaders_SOURCE.vcxitems.filters +++ b/WickedEngine/shaders/Shaders_SOURCE.vcxitems.filters @@ -1139,6 +1139,12 @@ PS + + VS + + + PS + diff --git a/WickedEngine/shaders/trailPS.hlsl b/WickedEngine/shaders/trailPS.hlsl new file mode 100644 index 000000000..b0237f24d --- /dev/null +++ b/WickedEngine/shaders/trailPS.hlsl @@ -0,0 +1,11 @@ +#include "globals.hlsli" + +Texture2D tex : register(t0); +Texture2D tex2 : register(t1); + +float4 main(float4 pos : SV_Position, float4 uv : TEXCOORD, float4 color : COLOR) : SV_TARGET +{ + color *= tex.Sample(sampler_linear_mirror, uv.xy); + color *= tex2.Sample(sampler_linear_mirror, uv.zw); + return color; +} diff --git a/WickedEngine/shaders/trailVS.hlsl b/WickedEngine/shaders/trailVS.hlsl new file mode 100644 index 000000000..c29b1734d --- /dev/null +++ b/WickedEngine/shaders/trailVS.hlsl @@ -0,0 +1,18 @@ +#include "globals.hlsli" + +struct VertexOut +{ + float4 pos : SV_Position; + float4 uv : TEXCOORD; + float4 color : COLOR; +}; + +VertexOut main(float3 pos : POSITION, float2 uv : TEXCOORD, float4 color : COLOR) +{ + VertexOut Out; + Out.pos = mul(g_xTrailTransform, float4(pos, 1)); + Out.uv.xy = mad(uv, g_xTrailTexMulAdd.xy, g_xTrailTexMulAdd.zw); + Out.uv.zw = mad(uv, g_xTrailTexMulAdd2.xy, g_xTrailTexMulAdd2.zw); + Out.color = color * g_xTrailColor; + return Out; +} diff --git a/WickedEngine/wiEmittedParticle.cpp b/WickedEngine/wiEmittedParticle.cpp index 7dfd6b339..3d1e6d2f7 100644 --- a/WickedEngine/wiEmittedParticle.cpp +++ b/WickedEngine/wiEmittedParticle.cpp @@ -948,6 +948,18 @@ namespace wi bd.independent_blend_enable = false; blendStates[BLENDMODE_PREMULTIPLIED] = bd; + bd.render_target[0].src_blend = Blend::DEST_COLOR; + bd.render_target[0].dest_blend = Blend::ZERO; + bd.render_target[0].blend_op = BlendOp::ADD; + bd.render_target[0].src_blend_alpha = Blend::DEST_ALPHA; + bd.render_target[0].dest_blend_alpha = Blend::ZERO; + bd.render_target[0].blend_op_alpha = BlendOp::ADD; + bd.render_target[0].blend_enable = true; + bd.render_target[0].render_target_write_mask = ColorWrite::ENABLE_ALL; + bd.alpha_to_coverage_enable = false; + bd.independent_blend_enable = false; + blendStates[BLENDMODE_MULTIPLY] = bd; + bd.render_target[0].blend_enable = false; blendStates[BLENDMODE_OPAQUE] = bd; diff --git a/WickedEngine/wiInitializer.cpp b/WickedEngine/wiInitializer.cpp index cc4d3c5ab..aad7abbd7 100644 --- a/WickedEngine/wiInitializer.cpp +++ b/WickedEngine/wiInitializer.cpp @@ -55,6 +55,7 @@ namespace wi::initializer wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { wi::GPUBVH::Initialize(); systems[INITIALIZED_SYSTEM_GPUBVH].store(true); }); wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { wi::physics::Initialize(); systems[INITIALIZED_SYSTEM_PHYSICS].store(true); }); wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { wi::audio::Initialize(); systems[INITIALIZED_SYSTEM_AUDIO].store(true); }); + wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { wi::TrailRenderer::Initialize(); systems[INITIALIZED_SYSTEM_TRAILRENDERER].store(true); }); // Initialize this immediately: wi::lua::Initialize(); systems[INITIALIZED_SYSTEM_LUA].store(true); diff --git a/WickedEngine/wiInitializer.h b/WickedEngine/wiInitializer.h index b0cfef1c0..dadb42a92 100644 --- a/WickedEngine/wiInitializer.h +++ b/WickedEngine/wiInitializer.h @@ -17,6 +17,7 @@ namespace wi::initializer INITIALIZED_SYSTEM_PHYSICS, INITIALIZED_SYSTEM_LUA, INITIALIZED_SYSTEM_AUDIO, + INITIALIZED_SYSTEM_TRAILRENDERER, INITIALIZED_SYSTEM_COUNT }; diff --git a/WickedEngine/wiLua.cpp b/WickedEngine/wiLua.cpp index 202b087dd..be46f4690 100644 --- a/WickedEngine/wiLua.cpp +++ b/WickedEngine/wiLua.cpp @@ -23,6 +23,7 @@ #include "wiPhysics_BindLua.h" #include "wiVoxelGrid_BindLua.h" #include "wiPathQuery_BindLua.h" +#include "wiTrailRenderer_BindLua.h" #include "wiTimer.h" #include "wiVector.h" @@ -205,6 +206,7 @@ namespace wi::lua Physics_BindLua::Bind(); VoxelGrid_BindLua::Bind(); PathQuery_BindLua::Bind(); + TrailRenderer_BindLua::Bind(); wi::backlog::post("wi::lua Initialized (" + std::to_string((int)std::round(timer.elapsed())) + " ms)"); } diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index 4f9ed058a..45d6ae09d 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -20,6 +20,9 @@ #include "wiTimer.h" #include "wiUnorderedMap.h" // leave it here for shader dump! #include "wiFont.h" +#include "wiVoxelGrid.h" +#include "wiPathQuery.h" +#include "wiTrailRenderer.h" #include "shaders/ShaderInterop_Postprocess.h" #include "shaders/ShaderInterop_Raytracing.h" @@ -150,6 +153,7 @@ wi::vector debugTextStorage; // A stream of DebugText struct + text cha wi::vector paintrads; wi::vector renderableVoxelgrids; wi::vector renderablePathqueries; +wi::vector renderableTrails; wi::SpinLock deferredMIPGenLock; wi::vector> deferredMIPGens; @@ -6203,6 +6207,12 @@ void DrawDebugWorld( } renderablePathqueries.clear(); + for (auto& x : renderableTrails) + { + x->Draw(camera, cmd); + } + renderableTrails.clear(); + if (debugCameras) { device->EventBegin("DebugCameras", cmd); @@ -16543,6 +16553,10 @@ void DrawPathQuery(const wi::PathQuery* pathquery) { renderablePathqueries.push_back(pathquery); } +void DrawTrail(const wi::TrailRenderer* trail) +{ + renderableTrails.push_back(trail); +} void AddDeferredMIPGen(const Texture& texture, bool preserve_coverage) { diff --git a/WickedEngine/wiRenderer.h b/WickedEngine/wiRenderer.h index 704384ee9..1968d2c6f 100644 --- a/WickedEngine/wiRenderer.h +++ b/WickedEngine/wiRenderer.h @@ -19,6 +19,7 @@ namespace wi { struct VoxelGrid; struct PathQuery; + struct TrailRenderer; } namespace wi::renderer @@ -1151,6 +1152,10 @@ namespace wi::renderer // WARNING: This retains pointer until next call to DrawDebugScene(), so path query must not be destroyed until then! void DrawPathQuery(const wi::PathQuery* pathquery); + // Add trail to be drawn in debug rendering phase. + // WARNING: This retains pointer until next call to DrawDebugScene(), so trail must not be destroyed until then! + void DrawTrail(const wi::TrailRenderer* trail); + // Add a texture that should be mipmapped whenever it is feasible to do so void AddDeferredMIPGen(const wi::graphics::Texture& texture, bool preserve_coverage = false); void AddDeferredBlockCompression(const wi::graphics::Texture& texture_src, const wi::graphics::Texture& texture_bc); diff --git a/WickedEngine/wiRenderer_BindLua.cpp b/WickedEngine/wiRenderer_BindLua.cpp index de98ac4b6..df7f0393c 100644 --- a/WickedEngine/wiRenderer_BindLua.cpp +++ b/WickedEngine/wiRenderer_BindLua.cpp @@ -11,6 +11,7 @@ #include "wiEventHandler.h" #include "wiVoxelGrid_BindLua.h" #include "wiPathQuery_BindLua.h" +#include "wiTrailRenderer_BindLua.h" using namespace wi::ecs; using namespace wi::graphics; @@ -459,6 +460,24 @@ namespace wi::lua::renderer return 0; } + int DrawTrail(lua_State* L) + { + int argc = wi::lua::SGetArgCount(L); + if (argc > 0) + { + TrailRenderer_BindLua* a = Luna::lightcheck(L, 1); + if (a) + { + wi::renderer::DrawTrail(&a->trail); + } + else + wi::lua::SError(L, "DrawTrail(TrailRenderer trail) first argument must be a TrailRenderer type!"); + } + else + wi::lua::SError(L, "DrawTrail(TrailRenderer trail) not enough arguments!"); + + return 0; + } int PutWaterRipple(lua_State* L) { @@ -547,6 +566,7 @@ namespace wi::lua::renderer wi::lua::RegisterFunc("DrawDebugText", DrawDebugText); wi::lua::RegisterFunc("DrawVoxelGrid", DrawVoxelGrid); wi::lua::RegisterFunc("DrawPathQuery", DrawPathQuery); + wi::lua::RegisterFunc("DrawTrail", DrawTrail); wi::lua::RegisterFunc("PutWaterRipple", PutWaterRipple); diff --git a/WickedEngine/wiTrailRenderer.cpp b/WickedEngine/wiTrailRenderer.cpp new file mode 100644 index 000000000..fa57ae9f6 --- /dev/null +++ b/WickedEngine/wiTrailRenderer.cpp @@ -0,0 +1,336 @@ +#include "wiTrailRenderer.h" +#include "wiEventHandler.h" +#include "wiBacklog.h" +#include "wiTimer.h" +#include "wiRenderer.h" +#include "wiTextureHelper.h" +#include "wiScene.h" + +using namespace wi::graphics; +using namespace wi::enums; +using namespace wi::scene; + +namespace wi +{ + static Shader vertexShader; + static Shader pixelShader; + static InputLayout inputLayout; + static BlendState blendStates[BLENDMODE_COUNT]; + static RasterizerState rasterizerState; + static RasterizerState wireFrameRS; + static DepthStencilState depthStencilState; + static PipelineState PSO[BLENDMODE_COUNT]; + static PipelineState PSO_wire; + + void TrailRenderer::Cut() + { + if (points.empty()) + return; + if (cuts.empty() || cuts.back() != points.size()) + { + cuts.push_back((uint32_t)points.size()); + } + } + + void TrailRenderer::Draw(const CameraComponent& camera, CommandList cmd) const + { + if (points.size() < 2) + return; + + GraphicsDevice* device = GetDevice(); + + device->EventBegin("TrailRenderer", cmd); + + if (wi::renderer::IsWireRender()) + { + device->BindPipelineState(&PSO_wire, cmd); + } + else + { + device->BindPipelineState(&PSO[blendMode], cmd); + } + + TrailRendererCB sb; + sb.g_xTrailTransform = camera.VP; + sb.g_xTrailColor = color; + sb.g_xTrailTexMulAdd = texMulAdd; + sb.g_xTrailTexMulAdd2 = texMulAdd2; + device->BindDynamicConstantBuffer(sb, CBSLOT_TRAILRENDERER, cmd); + + struct Vertex + { + XMFLOAT3 position; + uint16_t uvx; + uint16_t uvy; + XMHALF4 color; + }; + + uint32_t num_cuts = uint32_t(cuts.size()); + if (num_cuts == 0) + { + num_cuts += 1; // there were no cuts + } + if (!cuts.empty() && cuts.back() != (uint32_t)points.size()) + { + num_cuts += 1; // when last segment was not indicated with cut + } + const uint32_t num_segments = uint32_t(points.size()) - num_cuts; + + const uint32_t subdivision = std::max(1u, this->subdivision); + const uint32_t vertexCountAlloc = (num_segments * subdivision + num_cuts) * 2; + + const uint32_t indexCountAlloc = num_segments * subdivision * 6; + + auto mem = device->AllocateGPU(sizeof(Vertex) * vertexCountAlloc + sizeof(uint32_t) * indexCountAlloc, cmd); + Vertex* vertices = (Vertex*)mem.data; + uint32_t* indices = (uint32_t*)(vertices + vertexCountAlloc); + + const float resolution_rcp = 1.0f / subdivision; + const XMVECTOR CAM = camera.GetEye(); + + uint32_t next_cut = 0; + + uint32_t vertexCount = 0; + uint32_t indexCount = 0; + + int i = 0; + while (next_cut <= cuts.size()) + { + int startcut = i; + int count = next_cut < cuts.size() ? cuts[next_cut] : (uint32_t)points.size(); + float subdiv_count_within_cut = float((count - 1 - startcut) * subdivision); + float subdiv_within_cut = 0; + + for (; i < count; ++i) + { + XMVECTOR P0 = XMLoadFloat3(&points[std::max(startcut, std::min(i - 1, count - 1))].position); + XMVECTOR P1 = XMLoadFloat3(&points[std::max(startcut, std::min(i, count - 1))].position); + XMVECTOR P2 = XMLoadFloat3(&points[std::max(startcut, std::min(i + 1, count - 1))].position); + XMVECTOR P3 = XMLoadFloat3(&points[std::max(startcut, std::min(i + 2, count - 1))].position); + + float width_current = points[i].width; + float width_next = points[std::min(i + 1, count - 1)].width; + + XMFLOAT4 color_current = points[i].color; + XMFLOAT4 color_next = points[std::min(i + 1, count - 1)].color; + + if (i == startcut) + { + // when P0 == P1, centripetal catmull doesn't work, so we have to do a dummy control point + P0 += P1 - P2; + } + if (i >= count - 2) + { + // when P2 == P3, centripetal catmull doesn't work, so we have to do a dummy control point + P3 += P2 - P1; + } + + bool cap = i == (count - 1); + uint32_t segment_resolution = cap ? 1 : subdivision; + + for (uint32_t j = 0; j < segment_resolution; ++j) + { + float t = float(j) / float(segment_resolution); + + XMVECTOR P = cap ? XMVectorLerp(P1, P2, t) : wi::math::CatmullRomCentripetal(P0, P1, P2, P3, t); + XMVECTOR P_prev = cap ? XMVectorLerp(P0, P1, t - resolution_rcp) : wi::math::CatmullRomCentripetal(P0, P1, P2, P3, t - resolution_rcp); + XMVECTOR P_next = cap ? XMVectorLerp(P1, P2, t + resolution_rcp) : wi::math::CatmullRomCentripetal(P0, P1, P2, P3, t + resolution_rcp); + float width_interpolated = wi::math::Lerp(width_current, width_next, t); + XMFLOAT4 color_interpolated = wi::math::Lerp(color_current, color_next, t); + + XMVECTOR T = XMVector3Normalize(P_next - P_prev); + XMVECTOR B = XMVector3Normalize(XMVector3Cross(T, P - CAM)); + B *= width_interpolated * width; + + if (!cap) + { + indices[indexCount++] = vertexCount; + indices[indexCount++] = vertexCount + 1; + indices[indexCount++] = vertexCount + 2; + indices[indexCount++] = vertexCount + 2; + indices[indexCount++] = vertexCount + 1; + indices[indexCount++] = vertexCount + 3; + } + + const float cut_percent = subdiv_within_cut / subdiv_count_within_cut; + subdiv_within_cut += 1; + + Vertex vert = {}; + vert.uvx = uint16_t(cut_percent * 65535); + vert.color.x = XMConvertFloatToHalf(color_interpolated.x); + vert.color.y = XMConvertFloatToHalf(color_interpolated.y); + vert.color.z = XMConvertFloatToHalf(color_interpolated.z); + vert.color.w = XMConvertFloatToHalf(color_interpolated.w); + + vert.uvy = 0; + XMStoreFloat3(&vert.position, XMVectorSetW(P - B, 1)); + std::memcpy(vertices + vertexCount, &vert, sizeof(vert)); + vertexCount++; + + vert.uvy = 65535; + XMStoreFloat3(&vert.position, XMVectorSetW(P + B, 1)); + std::memcpy(vertices + vertexCount, &vert, sizeof(vert)); + vertexCount++; + } + } + next_cut++; + } + assert(vertexCount == vertexCountAlloc); + assert(indexCount == indexCountAlloc); + + const GPUBuffer* vbs[] = { + &mem.buffer, + }; + const uint32_t strides[] = { + sizeof(Vertex), + }; + const uint64_t offsets[] = { + mem.offset, + }; + device->BindVertexBuffers(vbs, 0, arraysize(vbs), strides, offsets, cmd); + + device->BindIndexBuffer(&mem.buffer, IndexBufferFormat::UINT32, mem.offset + sizeof(Vertex) * vertexCountAlloc, cmd); + + device->BindResource(texture.IsValid() ? &texture : wi::texturehelper::getWhite(), 0, cmd); + device->BindResource(texture2.IsValid() ? &texture2 : wi::texturehelper::getWhite(), 1, cmd); + + device->DrawIndexed(indexCount, 0, 0, cmd); + + device->EventEnd(cmd); + } + + namespace TrailRenderer_Internal + { + void LoadShaders() + { + wi::renderer::LoadShader(ShaderStage::VS, vertexShader, "trailVS.cso"); + wi::renderer::LoadShader(ShaderStage::PS, pixelShader, "trailPS.cso"); + + inputLayout.elements = { + { "POSITION", 0, Format::R32G32B32_FLOAT, 0, InputLayout::APPEND_ALIGNED_ELEMENT, InputClassification::PER_VERTEX_DATA }, + { "TEXCOORD", 0, Format::R16G16_UNORM, 0, InputLayout::APPEND_ALIGNED_ELEMENT, InputClassification::PER_VERTEX_DATA }, + { "COLOR", 0, Format::R16G16B16A16_FLOAT, 0, InputLayout::APPEND_ALIGNED_ELEMENT, InputClassification::PER_VERTEX_DATA }, + }; + + GraphicsDevice* device = wi::graphics::GetDevice(); + + for (int i = 0; i < BLENDMODE_COUNT; ++i) + { + PipelineStateDesc desc; + desc.pt = PrimitiveTopology::TRIANGLELIST; + desc.vs = &vertexShader; + desc.ps = &pixelShader; + desc.il = &inputLayout; + desc.bs = &blendStates[i]; + desc.rs = &rasterizerState; + desc.dss = &depthStencilState; + device->CreatePipelineState(&desc, &PSO[i]); + } + + { + PipelineStateDesc desc; + desc.pt = PrimitiveTopology::TRIANGLELIST; + desc.vs = &vertexShader; + desc.ps = &pixelShader; + desc.il = &inputLayout; + desc.bs = &blendStates[BLENDMODE_ALPHA]; + desc.rs = &wireFrameRS; + desc.dss = &depthStencilState; + + device->CreatePipelineState(&desc, &PSO_wire); + } + } + } + void TrailRenderer::Initialize() + { + wi::Timer timer; + + RasterizerState rs; + rs.fill_mode = FillMode::SOLID; + rs.cull_mode = CullMode::NONE; + rs.front_counter_clockwise = true; + rs.depth_bias = 0; + rs.depth_bias_clamp = 0; + rs.slope_scaled_depth_bias = 0; + rs.depth_clip_enable = false; + rs.multisample_enable = false; + rs.antialiased_line_enable = false; + rasterizerState = rs; + + + rs.fill_mode = FillMode::WIREFRAME; + rs.cull_mode = CullMode::NONE; + rs.front_counter_clockwise = true; + rs.depth_bias = 0; + rs.depth_bias_clamp = 0; + rs.slope_scaled_depth_bias = 0; + rs.depth_clip_enable = false; + rs.multisample_enable = false; + rs.antialiased_line_enable = false; + wireFrameRS = rs; + + + DepthStencilState dsd; + dsd.depth_enable = true; + dsd.depth_write_mask = DepthWriteMask::ZERO; + dsd.depth_func = ComparisonFunc::GREATER_EQUAL; + dsd.stencil_enable = false; + depthStencilState = dsd; + + + BlendState bd; + bd.render_target[0].blend_enable = true; + bd.render_target[0].src_blend = Blend::SRC_ALPHA; + bd.render_target[0].dest_blend = Blend::INV_SRC_ALPHA; + bd.render_target[0].blend_op = BlendOp::ADD; + bd.render_target[0].src_blend_alpha = Blend::ONE; + bd.render_target[0].dest_blend_alpha = Blend::INV_SRC_ALPHA; + bd.render_target[0].blend_op_alpha = BlendOp::ADD; + bd.render_target[0].render_target_write_mask = ColorWrite::ENABLE_ALL; + bd.independent_blend_enable = false; + blendStates[BLENDMODE_ALPHA] = bd; + + bd.render_target[0].blend_enable = true; + bd.render_target[0].src_blend = Blend::SRC_ALPHA; + bd.render_target[0].dest_blend = Blend::ONE; + bd.render_target[0].blend_op = BlendOp::ADD; + bd.render_target[0].src_blend_alpha = Blend::ZERO; + bd.render_target[0].dest_blend_alpha = Blend::ONE; + bd.render_target[0].blend_op_alpha = BlendOp::ADD; + bd.render_target[0].render_target_write_mask = ColorWrite::ENABLE_ALL; + bd.independent_blend_enable = false; + blendStates[BLENDMODE_ADDITIVE] = bd; + + bd.render_target[0].blend_enable = true; + bd.render_target[0].src_blend = Blend::ONE; + bd.render_target[0].dest_blend = Blend::INV_SRC_ALPHA; + bd.render_target[0].blend_op = BlendOp::ADD; + bd.render_target[0].src_blend_alpha = Blend::ONE; + bd.render_target[0].dest_blend_alpha = Blend::ONE; + bd.render_target[0].blend_op_alpha = BlendOp::ADD; + bd.render_target[0].render_target_write_mask = ColorWrite::ENABLE_ALL; + bd.independent_blend_enable = false; + blendStates[BLENDMODE_PREMULTIPLIED] = bd; + + bd.render_target[0].src_blend = Blend::DEST_COLOR; + bd.render_target[0].dest_blend = Blend::ZERO; + bd.render_target[0].blend_op = BlendOp::ADD; + bd.render_target[0].src_blend_alpha = Blend::DEST_ALPHA; + bd.render_target[0].dest_blend_alpha = Blend::ZERO; + bd.render_target[0].blend_op_alpha = BlendOp::ADD; + bd.render_target[0].blend_enable = true; + bd.render_target[0].render_target_write_mask = ColorWrite::ENABLE_ALL; + bd.alpha_to_coverage_enable = false; + bd.independent_blend_enable = false; + blendStates[BLENDMODE_MULTIPLY] = bd; + + bd.render_target[0].blend_enable = false; + blendStates[BLENDMODE_OPAQUE] = bd; + + + static wi::eventhandler::Handle handle = wi::eventhandler::Subscribe(wi::eventhandler::EVENT_RELOAD_SHADERS, [](uint64_t userdata) { TrailRenderer_Internal::LoadShaders(); }); + TrailRenderer_Internal::LoadShaders(); + + wi::backlog::post("wi::TrailRenderer Initialized (" + std::to_string((int)std::round(timer.elapsed())) + " ms)"); + } +} diff --git a/WickedEngine/wiTrailRenderer.h b/WickedEngine/wiTrailRenderer.h new file mode 100644 index 000000000..00518c96a --- /dev/null +++ b/WickedEngine/wiTrailRenderer.h @@ -0,0 +1,35 @@ +#pragma once +#include "CommonInclude.h" +#include "wiVector.h" +#include "wiGraphicsDevice.h" +#include "wiEnums.h" +#include "wiScene_Decl.h" + +namespace wi +{ + struct TrailRenderer + { + struct TrailPoint + { + XMFLOAT3 position = XMFLOAT3(0, 0, 0); + float width = 1; + XMFLOAT4 color = XMFLOAT4(1, 1, 1, 1); + }; + wi::vector points; + wi::vector cuts; + XMFLOAT4 color = XMFLOAT4(1, 1, 1, 1); + wi::enums::BLENDMODE blendMode = wi::enums::BLENDMODE_ALPHA; + uint32_t subdivision = 100; + float width = 1; + wi::graphics::Texture texture; + wi::graphics::Texture texture2; + XMFLOAT4 texMulAdd = XMFLOAT4(1, 1, 0, 0); + XMFLOAT4 texMulAdd2 = XMFLOAT4(1, 1, 0, 0); + + void Cut(); + + void Draw(const wi::scene::CameraComponent& camera, wi::graphics::CommandList cmd) const; + + static void Initialize(); + }; +} diff --git a/WickedEngine/wiTrailRenderer_BindLua.cpp b/WickedEngine/wiTrailRenderer_BindLua.cpp new file mode 100644 index 000000000..cabbf144c --- /dev/null +++ b/WickedEngine/wiTrailRenderer_BindLua.cpp @@ -0,0 +1,311 @@ +#include "wiTrailRenderer_BindLua.h" +#include "wiMath_BindLua.h" +#include "wiTexture_BindLua.h" + +namespace wi::lua +{ + Luna::FunctionType TrailRenderer_BindLua::methods[] = { + lunamethod(TrailRenderer_BindLua, AddPoint), + lunamethod(TrailRenderer_BindLua, Cut), + lunamethod(TrailRenderer_BindLua, Clear), + lunamethod(TrailRenderer_BindLua, GetPointCount), + lunamethod(TrailRenderer_BindLua, GetPoint), + lunamethod(TrailRenderer_BindLua, SetPoint), + lunamethod(TrailRenderer_BindLua, SetBlendMode), + lunamethod(TrailRenderer_BindLua, GetBlendMode), + lunamethod(TrailRenderer_BindLua, SetSubdivision), + lunamethod(TrailRenderer_BindLua, GetSubdivision), + lunamethod(TrailRenderer_BindLua, SetWidth), + lunamethod(TrailRenderer_BindLua, GetWidth), + lunamethod(TrailRenderer_BindLua, SetColor), + lunamethod(TrailRenderer_BindLua, GetColor), + lunamethod(TrailRenderer_BindLua, SetTexture), + lunamethod(TrailRenderer_BindLua, GetTexture), + lunamethod(TrailRenderer_BindLua, SetTexture2), + lunamethod(TrailRenderer_BindLua, GetTexture2), + lunamethod(TrailRenderer_BindLua, SetTexMulAdd), + lunamethod(TrailRenderer_BindLua, GetTexMulAdd), + lunamethod(TrailRenderer_BindLua, SetTexMulAdd2), + lunamethod(TrailRenderer_BindLua, GetTexMulAdd2), + { NULL, NULL } + }; + Luna::PropertyType TrailRenderer_BindLua::properties[] = { + { NULL, NULL } + }; + + int TrailRenderer_BindLua::AddPoint(lua_State* L) + { + int argc = wi::lua::SGetArgCount(L); + if (argc < 1) + { + wi::lua::SError(L, "TrailRenderer::AddPoint(Vector pos, opt float width = 1, opt Vector color = Vector(1,1,1,1)) not enough arguments!"); + return 0; + } + Vector_BindLua* pos = Luna::lightcheck(L, 1); + if (pos == nullptr) + { + wi::lua::SError(L, "TrailRenderer::AddPoint(Vector pos, opt float width = 1, opt Vector color = Vector(1,1,1,1)) first argument is not a Vector!"); + return 0; + } + TrailRenderer::TrailPoint point; + point.position = pos->GetFloat3(); + + if (argc > 1) + { + point.width = wi::lua::SGetFloat(L, 2); + if (argc > 2) + { + Vector_BindLua* col = Luna::lightcheck(L, 3); + if (col == nullptr) + { + wi::lua::SError(L, "TrailRenderer::AddPoint(Vector pos, opt float width = 1, opt Vector color = Vector(1,1,1,1)) third argument is not a Vector!"); + } + else + { + point.color = col->data; + } + } + } + + trail.points.push_back(point); + return 0; + } + int TrailRenderer_BindLua::Cut(lua_State* L) + { + trail.Cut(); + return 0; + } + int TrailRenderer_BindLua::Clear(lua_State* L) + { + trail.points.clear(); + trail.cuts.clear(); + return 0; + } + int TrailRenderer_BindLua::GetPointCount(lua_State* L) + { + wi::lua::SSetInt(L, int(trail.points.size())); + return 1; + } + int TrailRenderer_BindLua::GetPoint(lua_State* L) + { + int argc = wi::lua::SGetArgCount(L); + int index = wi::lua::SGetInt(L, 1); + if (index >= trail.points.size()) + { + wi::lua::SError(L, "TrailRenderer::GetPoint(int index): index out of range!"); + return 0; + } + auto& point = trail.points[index]; + Luna::push(L, point.position); + wi::lua::SSetFloat(L, point.width); + Luna::push(L, point.color); + return 3; + } + int TrailRenderer_BindLua::SetPoint(lua_State* L) + { + int argc = wi::lua::SGetArgCount(L); + if (argc < 2) + { + wi::lua::SError(L, "TrailRenderer::SetPoint(int index, Vector pos, opt float width = 1, opt Vector color = Vector(1,1,1,1)): not enough arguments!"); + return 0; + } + Vector_BindLua* pos = Luna::lightcheck(L, 2); + if (pos == nullptr) + { + wi::lua::SError(L, "TrailRenderer::SetPoint(int index, Vector pos, opt float width = 1, opt Vector color = Vector(1,1,1,1)): second argument is not a Vector!"); + return 0; + } + int index = wi::lua::SGetInt(L, 1); + if (index >= trail.points.size()) + { + wi::lua::SError(L, "TrailRenderer::SetPoint(int index, Vector pos, opt float width = 1, opt Vector color = Vector(1,1,1,1)): index out of range!"); + return 0; + } + auto& point = trail.points[index]; + point.position = pos->GetFloat3(); + if (argc > 2) + { + point.width = wi::lua::SGetFloat(L, 3); + if (argc > 3) + { + Vector_BindLua* col = Luna::lightcheck(L, 4); + if (col == nullptr) + { + wi::lua::SError(L, "TrailRenderer::SetPoint(int index, Vector pos, opt float width = 1, opt Vector color = Vector(1,1,1,1)): fourth argument is not a Vector!"); + } + else + { + point.color = col->data; + } + } + } + return 0; + } + int TrailRenderer_BindLua::SetBlendMode(lua_State* L) + { + int argc = wi::lua::SGetArgCount(L); + if (argc < 1) + { + wi::lua::SError(L, "TrailRenderer::SetBlendMode(int blendmode): not enough arguments!"); + return 0; + } + trail.blendMode = (wi::enums::BLENDMODE)wi::lua::SGetInt(L, 1); + return 0; + } + int TrailRenderer_BindLua::GetBlendMode(lua_State* L) + { + wi::lua::SSetInt(L, (int)trail.blendMode); + return 1; + } + int TrailRenderer_BindLua::SetSubdivision(lua_State* L) + { + int argc = wi::lua::SGetArgCount(L); + if (argc < 1) + { + wi::lua::SError(L, "TrailRenderer::SetSubdivision(int subdiv): not enough arguments!"); + return 0; + } + trail.subdivision = (uint32_t)wi::lua::SGetInt(L, 1); + return 0; + } + int TrailRenderer_BindLua::GetSubdivision(lua_State* L) + { + wi::lua::SSetInt(L, (int)trail.subdivision); + return 1; + } + int TrailRenderer_BindLua::SetWidth(lua_State* L) + { + int argc = wi::lua::SGetArgCount(L); + if (argc < 1) + { + wi::lua::SError(L, "TrailRenderer::SetWidth(float width): not enough arguments!"); + return 0; + } + trail.width = wi::lua::SGetFloat(L, 1); + return 0; + } + int TrailRenderer_BindLua::GetWidth(lua_State* L) + { + wi::lua::SSetFloat(L, trail.width); + return 1; + } + int TrailRenderer_BindLua::SetColor(lua_State* L) + { + int argc = wi::lua::SGetArgCount(L); + if (argc < 1) + { + wi::lua::SError(L, "TrailRenderer::SetColor(Vector color): not enough arguments!"); + return 0; + } + Vector_BindLua* vec = Luna::lightcheck(L, 1); + if (vec == nullptr) + { + wi::lua::SError(L, "TrailRenderer::SetColor(Vector color): first argument is not a Vector!"); + return 0; + } + trail.color = vec->data; + return 0; + } + int TrailRenderer_BindLua::GetColor(lua_State* L) + { + Luna::push(L, trail.color); + return 1; + } + int TrailRenderer_BindLua::SetTexture(lua_State* L) + { + int argc = wi::lua::SGetArgCount(L); + if (argc < 1) + { + wi::lua::SError(L, "TrailRenderer::SetTexture(Texture tex): not enough arguments!"); + return 0; + } + Texture_BindLua* tex = Luna::lightcheck(L, 1); + if (tex == nullptr) + { + wi::lua::SError(L, "TrailRenderer::SetTexture(Texture tex): first argument is not a Texture!"); + return 0; + } + trail.texture = tex->resource.GetTexture(); + return 0; + } + int TrailRenderer_BindLua::GetTexture(lua_State* L) + { + wi::Resource res; + res.SetTexture(trail.texture); + Luna::push(L, res); + return 1; + } + int TrailRenderer_BindLua::SetTexture2(lua_State* L) + { + int argc = wi::lua::SGetArgCount(L); + if (argc < 1) + { + wi::lua::SError(L, "TrailRenderer::SetTexture2(Texture tex): not enough arguments!"); + return 0; + } + Texture_BindLua* tex = Luna::lightcheck(L, 1); + if (tex == nullptr) + { + wi::lua::SError(L, "TrailRenderer::SetTexture2(Texture tex): first argument is not a Texture!"); + return 0; + } + trail.texture2 = tex->resource.GetTexture(); + return 0; + } + int TrailRenderer_BindLua::GetTexture2(lua_State* L) + { + wi::Resource res; + res.SetTexture(trail.texture2); + Luna::push(L, res); + return 1; + } + int TrailRenderer_BindLua::SetTexMulAdd(lua_State* L) + { + int argc = wi::lua::SGetArgCount(L); + if (argc < 1) + { + wi::lua::SError(L, "TrailRenderer::SetTexMulAdd(Vector): not enough arguments!"); + return 0; + } + Vector_BindLua* vec = Luna::lightcheck(L, 1); + if (vec == nullptr) + { + wi::lua::SError(L, "TrailRenderer::SetTexMulAdd(Vector): first argument is not a Vector!"); + return 0; + } + trail.texMulAdd = vec->data; + return 0; + } + int TrailRenderer_BindLua::GetTexMulAdd(lua_State* L) + { + Luna::push(L, trail.texMulAdd); + return 1; + } + int TrailRenderer_BindLua::SetTexMulAdd2(lua_State* L) + { + int argc = wi::lua::SGetArgCount(L); + if (argc < 1) + { + wi::lua::SError(L, "TrailRenderer::SetTexMulAdd2(Vector): not enough arguments!"); + return 0; + } + Vector_BindLua* vec = Luna::lightcheck(L, 1); + if (vec == nullptr) + { + wi::lua::SError(L, "TrailRenderer::SetTexMulAdd2(Vector): first argument is not a Vector!"); + return 0; + } + trail.texMulAdd2 = vec->data; + return 0; + } + int TrailRenderer_BindLua::GetTexMulAdd2(lua_State* L) + { + Luna::push(L, trail.texMulAdd2); + return 1; + } + + void TrailRenderer_BindLua::Bind() + { + Luna::Register(wi::lua::GetLuaState()); + } +} diff --git a/WickedEngine/wiTrailRenderer_BindLua.h b/WickedEngine/wiTrailRenderer_BindLua.h new file mode 100644 index 000000000..fe20323b5 --- /dev/null +++ b/WickedEngine/wiTrailRenderer_BindLua.h @@ -0,0 +1,48 @@ +#pragma once +#include "CommonInclude.h" +#include "wiLua.h" +#include "wiLuna.h" +#include "wiTrailRenderer.h" + +namespace wi::lua +{ + class TrailRenderer_BindLua + { + public: + wi::TrailRenderer trail; + + inline static constexpr char className[] = "TrailRenderer"; + static Luna::FunctionType methods[]; + static Luna::PropertyType properties[]; + + TrailRenderer_BindLua() = default; + TrailRenderer_BindLua(lua_State* L) {} + TrailRenderer_BindLua(wi::TrailRenderer& ref) : trail(ref) {} + TrailRenderer_BindLua(wi::TrailRenderer* ref) : trail(*ref) {} + + int AddPoint(lua_State* L); + int Cut(lua_State* L); + int Clear(lua_State* L); + int GetPointCount(lua_State* L); + int GetPoint(lua_State* L); + int SetPoint(lua_State* L); + int SetBlendMode(lua_State* L); + int GetBlendMode(lua_State* L); + int SetSubdivision(lua_State* L); + int GetSubdivision(lua_State* L); + int SetWidth(lua_State* L); + int GetWidth(lua_State* L); + int SetColor(lua_State* L); + int GetColor(lua_State* L); + int SetTexture(lua_State* L); + int GetTexture(lua_State* L); + int SetTexture2(lua_State* L); + int GetTexture2(lua_State* L); + int SetTexMulAdd(lua_State* L); + int GetTexMulAdd(lua_State* L); + int SetTexMulAdd2(lua_State* L); + int GetTexMulAdd2(lua_State* L); + + static void Bind(); + }; +} diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 7cd281351..f23e7fbdc 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wi::version // minor features, major updates, breaking compatibility changes const int minor = 71; // minor bug fixes, alterations, refactors, updates - const int revision = 395; + const int revision = 396; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision); @@ -50,7 +50,7 @@ All contributors: https://github.com/turanszkij/WickedEngine/graphs/contributors Patreon supporters --------------------------- -Nemerle, James Webb, Quifeng Jin, TheGameCreators, Joseph Goldin, Yuri, Sergey K, Yukawa Kanta, Dragon Josh, John, LurkingNinja, Bernardo Del Castillo, Invictus, Scott Hunt, Yazan Altaki, Tuan NV, Robert MacGregor, cybernescence, Alexander Dahlin, blueapples, Delhills, NI NI, Sherief, ktopoet, Justin Macklin, Cédric Fabre, TogetherTeam, Bartosz Boczula, Arne Koenig, Ivan Trajchev, nathants, Fahd Ahmed, Gabriel Jadderson, SAS_Controller, Dominik Madarász, Segfault, Mike amanfo, Dennis Brakhane, rookie, Peter Moore, therealjtgill, Nicolas Embleton, Desuuc, radino1977, Anthony Curtis, manni heck, Matthias Hölzl, Phyffer, Lucas Pinheiro, Tapkaara, gpman, Anthony Python, Gnowos, Klaus, slaughternaut, Paul Brain, Connor Greaves, Alexandr, Lee Bamber, MCAlarm MC2, Titoutan, Willow, Aldo, lokimx, K. Osterman, Nomad, ykl, Alex Krokos, Timmy +Nemerle, James Webb, Quifeng Jin, TheGameCreators, Joseph Goldin, Yuri, Sergey K, Yukawa Kanta, Dragon Josh, John, LurkingNinja, Bernardo Del Castillo, Invictus, Scott Hunt, Yazan Altaki, Tuan NV, Robert MacGregor, cybernescence, Alexander Dahlin, blueapples, Delhills, NI NI, Sherief, ktopoet, Justin Macklin, Cédric Fabre, TogetherTeam, Bartosz Boczula, Arne Koenig, Ivan Trajchev, nathants, Fahd Ahmed, Gabriel Jadderson, SAS_Controller, Dominik Madarász, Segfault, Mike amanfo, Dennis Brakhane, rookie, Peter Moore, therealjtgill, Nicolas Embleton, Desuuc, radino1977, Anthony Curtis, manni heck, Matthias Hölzl, Phyffer, Lucas Pinheiro, Tapkaara, gpman, Anthony Python, Gnowos, Klaus, slaughternaut, Paul Brain, Connor Greaves, Alexandr, Lee Bamber, MCAlarm MC2, Titoutan, Willow, Aldo, lokimx, K. Osterman, Nomad, ykl, Alex Krokos, Timmy, Avaflow )"; return credits;