diff --git a/Documentation/ScriptingAPI-Documentation.md b/Documentation/ScriptingAPI-Documentation.md index 48ee6aa69..4748c97ad 100644 --- a/Documentation/ScriptingAPI-Documentation.md +++ b/Documentation/ScriptingAPI-Documentation.md @@ -640,6 +640,7 @@ It inherits functions from RenderPath2D, so it can render a 2D overlay. - AO_MSAO : int -- enable multi scale screen space ambient occlusion (use in SetAO() function) - SetHBAOEnabled(bool value) - SetSSREnabled(bool value) +- SetRaytracedReflectionsEnabled(bool value) - SetShadowsEnabled(bool value) - SetReflectionsEnabled(bool value) - SetFXAAEnabled(bool value) diff --git a/Editor/PostprocessWindow.cpp b/Editor/PostprocessWindow.cpp index 4fca3292b..3986bb4cc 100644 --- a/Editor/PostprocessWindow.cpp +++ b/Editor/PostprocessWindow.cpp @@ -141,6 +141,17 @@ PostprocessWindow::PostprocessWindow(EditorComponent* editor) : GUI(&editor->Get }); ppWindow->AddWidget(ssrCheckBox); + ssrCheckBox = new wiCheckBox("Ray Traced Reflections: "); + ssrCheckBox->SetTooltip("Enable Ray Traced Reflections. Only if GPU supports raytracing."); + ssrCheckBox->SetScriptTip("RenderPath3D::SetRaytracedReflectionsEnabled(bool value)"); + ssrCheckBox->SetPos(XMFLOAT2(x + 200, y)); + ssrCheckBox->SetCheck(editor->renderPath->getRaytracedReflectionEnabled()); + ssrCheckBox->OnClick([=](wiEventArgs args) { + editor->renderPath->setRaytracedReflectionsEnabled(args.bValue); + }); + ppWindow->AddWidget(ssrCheckBox); + ssrCheckBox->SetEnabled(wiRenderer::GetDevice()->CheckCapability(GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_RAYTRACING)); + sssCheckBox = new wiCheckBox("SSS: "); sssCheckBox->SetTooltip("Enable Subsurface Scattering. (Deferred only for now)"); sssCheckBox->SetScriptTip("RenderPath3D::SetSSSEnabled(bool value)"); diff --git a/Editor/PostprocessWindow.h b/Editor/PostprocessWindow.h index 6f5683777..df5260f60 100644 --- a/Editor/PostprocessWindow.h +++ b/Editor/PostprocessWindow.h @@ -28,6 +28,7 @@ public: wiSlider* aoRangeSlider; wiSlider* aoSampleCountSlider; wiCheckBox* ssrCheckBox; + wiCheckBox* raytracedReflectionsCheckBox; wiCheckBox* sssCheckBox; wiCheckBox* eyeAdaptionCheckBox; wiCheckBox* motionBlurCheckBox; diff --git a/WickedEngine/RenderPath3D.cpp b/WickedEngine/RenderPath3D.cpp index 10e5d33c2..30019cfdd 100644 --- a/WickedEngine/RenderPath3D.cpp +++ b/WickedEngine/RenderPath3D.cpp @@ -436,7 +436,7 @@ void RenderPath3D::RenderFrameSetUp(CommandList cmd) const device->BindResource(CS, &depthBuffer_Copy, TEXSLOT_DEPTH, cmd); wiRenderer::UpdateRenderData(cmd); - if (getAO() == AO_RTAO || wiRenderer::GetRaytracedShadowsEnabled()) + if (getAO() == AO_RTAO || wiRenderer::GetRaytracedShadowsEnabled() || getRaytracedReflectionEnabled()) { wiRenderer::UpdateRaytracingAccelerationStructures(cmd); } @@ -556,7 +556,11 @@ void RenderPath3D::RenderAO(CommandList cmd) const } void RenderPath3D::RenderSSR(const Texture& gbuffer1, const Texture& gbuffer2, CommandList cmd) const { - if (getSSREnabled()) + if (getRaytracedReflectionEnabled()) + { + wiRenderer::Postprocess_RTReflection(depthBuffer_Copy, gbuffer1, gbuffer2, rtSSR, cmd); + } + else if (getSSREnabled()) { wiRenderer::Postprocess_SSR(rtSceneCopy, depthBuffer_Copy, rtLinearDepth, gbuffer1, gbuffer2, rtSSR, cmd); } diff --git a/WickedEngine/RenderPath3D.h b/WickedEngine/RenderPath3D.h index 1060b2f99..2b4df16da 100644 --- a/WickedEngine/RenderPath3D.h +++ b/WickedEngine/RenderPath3D.h @@ -38,6 +38,7 @@ private: AO ao = AO_DISABLED; bool fxaaEnabled = false; bool ssrEnabled = false; + bool raytracedReflectionsEnabled = false; bool reflectionsEnabled = true; bool shadowsEnabled = true; bool bloomEnabled = true; @@ -145,6 +146,7 @@ public: constexpr bool getAOEnabled() const { return ao != AO_DISABLED; } constexpr AO getAO() const { return ao; } constexpr bool getSSREnabled() const { return ssrEnabled; } + constexpr bool getRaytracedReflectionEnabled() const { return raytracedReflectionsEnabled; } constexpr bool getShadowsEnabled() const { return shadowsEnabled; } constexpr bool getReflectionsEnabled() const { return reflectionsEnabled; } constexpr bool getFXAAEnabled() const { return fxaaEnabled; } @@ -184,6 +186,7 @@ public: constexpr void setAO(AO value) { ao = value; } constexpr void setSSREnabled(bool value){ ssrEnabled = value; } + constexpr void setRaytracedReflectionsEnabled(bool value){ raytracedReflectionsEnabled = value; } constexpr void setShadowsEnabled(bool value){ shadowsEnabled = value; } constexpr void setReflectionsEnabled(bool value){ reflectionsEnabled = value; } constexpr void setFXAAEnabled(bool value){ fxaaEnabled = value; } diff --git a/WickedEngine/RenderPath3D_BindLua.cpp b/WickedEngine/RenderPath3D_BindLua.cpp index d9aa3c1b7..8fb476819 100644 --- a/WickedEngine/RenderPath3D_BindLua.cpp +++ b/WickedEngine/RenderPath3D_BindLua.cpp @@ -24,6 +24,7 @@ Luna::FunctionType RenderPath3D_BindLua::methods[] = { lunamethod(RenderPath3D_BindLua, SetAO), lunamethod(RenderPath3D_BindLua, SetSSREnabled), + lunamethod(RenderPath3D_BindLua, SetRaytracedReflectionsEnabled), lunamethod(RenderPath3D_BindLua, SetShadowsEnabled), lunamethod(RenderPath3D_BindLua, SetReflectionsEnabled), lunamethod(RenderPath3D_BindLua, SetFXAAEnabled), @@ -83,6 +84,19 @@ int RenderPath3D_BindLua::SetSSREnabled(lua_State* L) wiLua::SError(L, "SetSSREnabled(bool value) not enough arguments!"); return 0; } +int RenderPath3D_BindLua::SetRaytracedReflectionsEnabled(lua_State* L) +{ + if (component == nullptr) + { + wiLua::SError(L, "SetRaytracedReflectionsEnabled(bool value) component is null!"); + return 0; + } + if (wiLua::SGetArgCount(L) > 0) + ((RenderPath3D*)component)->setRaytracedReflectionsEnabled(wiLua::SGetBool(L, 1)); + else + wiLua::SError(L, "SetRaytracedReflectionsEnabled(bool value) not enough arguments!"); + return 0; +} int RenderPath3D_BindLua::SetShadowsEnabled(lua_State* L) { if (component == nullptr) diff --git a/WickedEngine/RenderPath3D_BindLua.h b/WickedEngine/RenderPath3D_BindLua.h index 4eb69050c..6a654889b 100644 --- a/WickedEngine/RenderPath3D_BindLua.h +++ b/WickedEngine/RenderPath3D_BindLua.h @@ -20,6 +20,7 @@ public: int SetAO(lua_State* L); int SetSSREnabled(lua_State* L); + int SetRaytracedReflectionsEnabled(lua_State* L); int SetShadowsEnabled(lua_State* L); int SetReflectionsEnabled(lua_State* L); int SetFXAAEnabled(lua_State* L); diff --git a/WickedEngine/RenderPath3D_Deferred_BindLua.cpp b/WickedEngine/RenderPath3D_Deferred_BindLua.cpp index 678fc0695..954ed0ecc 100644 --- a/WickedEngine/RenderPath3D_Deferred_BindLua.cpp +++ b/WickedEngine/RenderPath3D_Deferred_BindLua.cpp @@ -23,6 +23,7 @@ Luna::FunctionType RenderPath3D_Deferred_BindLua: lunamethod(RenderPath3D_BindLua, SetAO), lunamethod(RenderPath3D_BindLua, SetSSREnabled), + lunamethod(RenderPath3D_BindLua, SetRaytracedReflectionsEnabled), lunamethod(RenderPath3D_BindLua, SetShadowsEnabled), lunamethod(RenderPath3D_BindLua, SetReflectionsEnabled), lunamethod(RenderPath3D_BindLua, SetFXAAEnabled), diff --git a/WickedEngine/RenderPath3D_Forward_BindLua.cpp b/WickedEngine/RenderPath3D_Forward_BindLua.cpp index f9369362a..b7cf7621a 100644 --- a/WickedEngine/RenderPath3D_Forward_BindLua.cpp +++ b/WickedEngine/RenderPath3D_Forward_BindLua.cpp @@ -23,6 +23,7 @@ Luna::FunctionType RenderPath3D_Forward_BindLua::m lunamethod(RenderPath3D_BindLua, SetAO), lunamethod(RenderPath3D_BindLua, SetSSREnabled), + lunamethod(RenderPath3D_BindLua, SetRaytracedReflectionsEnabled), lunamethod(RenderPath3D_BindLua, SetShadowsEnabled), lunamethod(RenderPath3D_BindLua, SetReflectionsEnabled), lunamethod(RenderPath3D_BindLua, SetFXAAEnabled), diff --git a/WickedEngine/RenderPath3D_TiledDeferred_BindLua.cpp b/WickedEngine/RenderPath3D_TiledDeferred_BindLua.cpp index d99f3776a..791572c75 100644 --- a/WickedEngine/RenderPath3D_TiledDeferred_BindLua.cpp +++ b/WickedEngine/RenderPath3D_TiledDeferred_BindLua.cpp @@ -23,6 +23,7 @@ Luna::FunctionType RenderPath3D_TiledDeferre lunamethod(RenderPath3D_BindLua, SetAO), lunamethod(RenderPath3D_BindLua, SetSSREnabled), + lunamethod(RenderPath3D_BindLua, SetRaytracedReflectionsEnabled), lunamethod(RenderPath3D_BindLua, SetShadowsEnabled), lunamethod(RenderPath3D_BindLua, SetReflectionsEnabled), lunamethod(RenderPath3D_BindLua, SetFXAAEnabled), diff --git a/WickedEngine/RenderPath3D_TiledForward_BindLua.cpp b/WickedEngine/RenderPath3D_TiledForward_BindLua.cpp index 0e134f596..9e2d48f43 100644 --- a/WickedEngine/RenderPath3D_TiledForward_BindLua.cpp +++ b/WickedEngine/RenderPath3D_TiledForward_BindLua.cpp @@ -23,6 +23,7 @@ Luna::FunctionType RenderPath3D_TiledForward_ lunamethod(RenderPath3D_BindLua, SetAO), lunamethod(RenderPath3D_BindLua, SetSSREnabled), + lunamethod(RenderPath3D_BindLua, SetRaytracedReflectionsEnabled), lunamethod(RenderPath3D_BindLua, SetShadowsEnabled), lunamethod(RenderPath3D_BindLua, SetReflectionsEnabled), lunamethod(RenderPath3D_BindLua, SetFXAAEnabled), diff --git a/WickedEngine/ShaderInterop_Postprocess.h b/WickedEngine/ShaderInterop_Postprocess.h index e8c927d6c..41c2c26e3 100644 --- a/WickedEngine/ShaderInterop_Postprocess.h +++ b/WickedEngine/ShaderInterop_Postprocess.h @@ -29,6 +29,9 @@ CBUFFER(PostProcessCB, CBSLOT_RENDERER_POSTPROCESS) #define rtao_power ssao_power #define rtao_seed xPPParams0.w +#define rtreflection_range ssao_range +#define rtreflection_seed xPPParams0.w + static const uint POSTPROCESS_HBAO_THREADCOUNT = 320; #define hbao_direction xPPParams0.xy #define hbao_power xPPParams0.z diff --git a/WickedEngine/Shaders_SOURCE.vcxitems b/WickedEngine/Shaders_SOURCE.vcxitems index d2d02f768..fc5bb6154 100644 --- a/WickedEngine/Shaders_SOURCE.vcxitems +++ b/WickedEngine/Shaders_SOURCE.vcxitems @@ -627,6 +627,11 @@ Compute Compute + + Compute + 4.0 + Document + Compute 4.0 diff --git a/WickedEngine/Shaders_SOURCE.vcxitems.filters b/WickedEngine/Shaders_SOURCE.vcxitems.filters index e9e221faf..bdde5d889 100644 --- a/WickedEngine/Shaders_SOURCE.vcxitems.filters +++ b/WickedEngine/Shaders_SOURCE.vcxitems.filters @@ -126,6 +126,9 @@ MS + + LIB + diff --git a/WickedEngine/lightingHF.hlsli b/WickedEngine/lightingHF.hlsli index 8dc123596..5bf0b16a6 100644 --- a/WickedEngine/lightingHF.hlsli +++ b/WickedEngine/lightingHF.hlsli @@ -93,7 +93,7 @@ inline float shadowTrace(float3 P, float3 N, float3 L, float dist) { #ifdef RAYTRACING_INLINE RayQuery< - RAY_FLAG_CULL_NON_OPAQUE | + RAY_FLAG_FORCE_OPAQUE | RAY_FLAG_SKIP_PROCEDURAL_PRIMITIVES | RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH > q; diff --git a/WickedEngine/rtaoLIB.hlsl b/WickedEngine/rtaoLIB.hlsl index e89a4988c..c31f17478 100644 --- a/WickedEngine/rtaoLIB.hlsl +++ b/WickedEngine/rtaoLIB.hlsl @@ -4,13 +4,11 @@ RWTEXTURE2D(output, unorm float, 0); -#ifdef RAYTRACING_GEOMETRYINDEX ConstantBuffer subsets_material[MAX_DESCRIPTOR_INDEXING] : register(b0, space1); Texture2D subsets_texture_baseColor[MAX_DESCRIPTOR_INDEXING] : register(t0, space1); Buffer subsets_indexBuffer[MAX_DESCRIPTOR_INDEXING] : register(t100000, space1); Buffer subsets_vertexBuffer_UV0[MAX_DESCRIPTOR_INDEXING] : register(t300000, space1); Buffer subsets_vertexBuffer_UV1[MAX_DESCRIPTOR_INDEXING] : register(t400000, space1); -#endif // RAYTRACING_GEOMETRYINDEX typedef BuiltInTriangleIntersectionAttributes MyAttributes; struct RayPayload @@ -49,18 +47,23 @@ void RTAO_Raygen() ray.TMax = rtao_range; ray.Origin = P + N * 0.1; - RayPayload payload = { 0 }; + RayPayload payload; + payload.color = 0; for (uint i = 0; i < (uint)rtao_samplecount; ++i) { ray.Direction = SampleHemisphere_cos(N, seed, uv); - TraceRay(scene_acceleration_structure, -#ifndef RAYTRACING_GEOMETRYINDEX // tier 1_0 method of alpha test without GeometryIndex() is not implemented yet - RAY_FLAG_FORCE_OPAQUE | - RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH | -#endif // RAYTRACING_GEOMETRYINDEX - RAY_FLAG_SKIP_CLOSEST_HIT_SHADER - , ~0, 0, 1, 0, ray, payload); + + TraceRay( + scene_acceleration_structure, // AccelerationStructure + RAY_FLAG_SKIP_CLOSEST_HIT_SHADER, // RayFlags + ~0, // InstanceInclusionMask + 0, // RayContributionToHitGroupIndex + 0, // MultiplierForGeomtryContributionToShaderIndex + 0, // MissShaderIndex + ray, // Ray + payload // Payload + ); } payload.color /= rtao_samplecount; @@ -76,15 +79,23 @@ void RTAO_ClosestHit(inout RayPayload payload, in MyAttributes attr) [shader("anyhit")] void RTAO_AnyHit(inout RayPayload payload, in MyAttributes attr) { -#ifdef RAYTRACING_GEOMETRYINDEX +#ifndef SPIRV float u = attr.barycentrics.x; float v = attr.barycentrics.y; float w = 1 - u - v; uint primitiveIndex = PrimitiveIndex(); uint geometryOffset = InstanceID(); +#ifdef RAYTRACING_GEOMETRYINDEX uint geometryIndex = GeometryIndex(); // requires tier_1_1 GeometryIndex feature!! +#else + uint geometryIndex = 0; +#endif // RAYTRACING_GEOMETRYINDEX uint descriptorIndex = geometryOffset + geometryIndex; ShaderMaterial material = subsets_material[descriptorIndex]; + if (material.uvset_baseColorMap < 0) + { + AcceptHitAndEndSearch(); + } uint i0 = subsets_indexBuffer[descriptorIndex][primitiveIndex * 3 + 0]; uint i1 = subsets_indexBuffer[descriptorIndex][primitiveIndex * 3 + 1]; uint i2 = subsets_indexBuffer[descriptorIndex][primitiveIndex * 3 + 2]; @@ -103,10 +114,9 @@ void RTAO_AnyHit(inout RayPayload payload, in MyAttributes attr) } float2 uv = uv0 * w + uv1 * u + uv2 * v; - float4 baseColor = material.baseColor; - baseColor *= subsets_texture_baseColor[descriptorIndex].SampleLevel(sampler_point_clamp, uv, 0); + float alpha = subsets_texture_baseColor[descriptorIndex].SampleLevel(sampler_point_wrap, uv, 2).a; - if (baseColor.a > 0.9) + if (alpha > 0.9) { AcceptHitAndEndSearch(); } @@ -114,7 +124,7 @@ void RTAO_AnyHit(inout RayPayload payload, in MyAttributes attr) { IgnoreHit(); } -#endif // RAYTRACING_GEOMETRYINDEX +#endif // SPIRV } [shader("miss")] diff --git a/WickedEngine/rtreflectionLIB.hlsl b/WickedEngine/rtreflectionLIB.hlsl new file mode 100644 index 000000000..179d1e1ec --- /dev/null +++ b/WickedEngine/rtreflectionLIB.hlsl @@ -0,0 +1,269 @@ +#define DISABLE_SOFT_SHADOWMAP +#define DISABLE_TRANSPARENT_SHADOWMAP +#include "globals.hlsli" +#include "ShaderInterop_Postprocess.h" +#include "raytracingHF.hlsli" +#include "stochasticSSRHF.hlsli" +#include "lightingHF.hlsli" + +RWTEXTURE2D(output, float4, 0); + +ConstantBuffer subsets_material[MAX_DESCRIPTOR_INDEXING] : register(b0, space1); +Texture2D subsets_texture_baseColor[MAX_DESCRIPTOR_INDEXING] : register(t0, space1); +Buffer subsets_indexBuffer[MAX_DESCRIPTOR_INDEXING] : register(t100000, space1); +ByteAddressBuffer subsets_vertexBuffer_POS[MAX_DESCRIPTOR_INDEXING] : register(t200000, space1); +Buffer subsets_vertexBuffer_UV0[MAX_DESCRIPTOR_INDEXING] : register(t300000, space1); +Buffer subsets_vertexBuffer_UV1[MAX_DESCRIPTOR_INDEXING] : register(t400000, space1); + +typedef BuiltInTriangleIntersectionAttributes MyAttributes; +struct RayPayload +{ + float3 color; + float roughness; +}; + +[shader("raygeneration")] +void RTReflection_Raygen() +{ + const float2 uv = ((float2)DispatchRaysIndex() + 0.5f) / (float2)DispatchRaysDimensions(); + const float depth = texture_depth.SampleLevel(sampler_point_clamp, uv, 0); + if (depth == 0.0f) + return; + + const float roughness = texture_gbuffer2.SampleLevel(sampler_linear_clamp, uv, 0).r; + + const float3 P = reconstructPosition(uv, depth); + const float3 N = decodeNormal(texture_gbuffer1.SampleLevel(sampler_point_clamp, uv, 0).xy); + const float3 V = normalize(g_xCamera_CamPos - P); + + + float4 H; + if (roughness > 0.1f) + { + const float surfaceMargin = 0.0f; + const float maxRegenCount = 15.0f; + + uint2 Random = Rand_PCG16(int3((DispatchRaysIndex().xy + 0.5f), g_xFrame_FrameCount)).xy; + + // Pick the best rays + + float RdotN = 0.0f; + float regenCount = 0; + [loop] + for (; RdotN <= surfaceMargin && regenCount < maxRegenCount; regenCount++) + { + // Low-discrepancy sequence + //float2 Xi = float2(Random) * rcp(65536.0); // equivalent to HammersleyRandom(0, 1, Random). + float2 Xi = HammersleyRandom16(regenCount, Random); // SingleSPP + + Xi.y = lerp(Xi.y, 0.0f, BRDFBias); + + // I should probably use importance sampling of visible normals http://jcgt.org/published/0007/04/01/paper.pdf + H = ImportanceSampleGGX(Xi, roughness); + H = TangentToWorld(H, N); + + RdotN = dot(N, reflect(-V, H.xyz)); + } + } + else + { + H = float4(N.xyz, 1.0f); + } + + const float3 R = -reflect(V, H.xyz); + + float seed = rtreflection_seed; + + RayDesc ray; + ray.TMin = 0.001; + ray.TMax = rtreflection_range; + ray.Origin = P + N * 0.1; + ray.Direction = normalize(R); + + RayPayload payload; + payload.color = 0; + payload.roughness = roughness; + + TraceRay( + scene_acceleration_structure, // AccelerationStructure + 0, // RayFlags + ~0, // InstanceInclusionMask + 0, // RayContributionToHitGroupIndex + 0, // MultiplierForGeomtryContributionToShaderIndex + 0, // MissShaderIndex + ray, // Ray + payload // Payload + ); + + output[DispatchRaysIndex().xy] = float4(payload.color, 1); +} + +[shader("closesthit")] +void RTReflection_ClosestHit(inout RayPayload payload, in MyAttributes attr) +{ +#ifndef SPIRV + float u = attr.barycentrics.x; + float v = attr.barycentrics.y; + float w = 1 - u - v; + uint primitiveIndex = PrimitiveIndex(); + uint geometryOffset = InstanceID(); +#ifdef RAYTRACING_GEOMETRYINDEX + uint geometryIndex = GeometryIndex(); // requires tier_1_1 GeometryIndex feature!! +#else + uint geometryIndex = 0; +#endif // RAYTRACING_GEOMETRYINDEX + uint descriptorIndex = geometryOffset + geometryIndex; + ShaderMaterial material = subsets_material[descriptorIndex]; + uint i0 = subsets_indexBuffer[descriptorIndex][primitiveIndex * 3 + 0]; + uint i1 = subsets_indexBuffer[descriptorIndex][primitiveIndex * 3 + 1]; + uint i2 = subsets_indexBuffer[descriptorIndex][primitiveIndex * 3 + 2]; + float4 uv0, uv1, uv2; + uv0.xy = subsets_vertexBuffer_UV0[descriptorIndex][i0]; + uv1.xy = subsets_vertexBuffer_UV0[descriptorIndex][i1]; + uv2.xy = subsets_vertexBuffer_UV0[descriptorIndex][i2]; + uv0.zw = subsets_vertexBuffer_UV1[descriptorIndex][i0]; + uv1.zw = subsets_vertexBuffer_UV1[descriptorIndex][i1]; + uv2.zw = subsets_vertexBuffer_UV1[descriptorIndex][i2]; + float3 n0, n1, n2; + n0 = unpack_unitvector(subsets_vertexBuffer_POS[descriptorIndex].Load4(i0 * 16).w); + n1 = unpack_unitvector(subsets_vertexBuffer_POS[descriptorIndex].Load4(i1 * 16).w); + n2 = unpack_unitvector(subsets_vertexBuffer_POS[descriptorIndex].Load4(i2 * 16).w); + + float4 uvsets = uv0 * w + uv1 * u + uv2 * v; + float3 N = normalize(n0 * w + n1 * u + n2 * v); + + float4 baseColor; + [branch] + if (material.uvset_baseColorMap >= 0) + { + const float2 UV_baseColorMap = material.uvset_baseColorMap == 0 ? uvsets.xy : uvsets.zw; + baseColor = subsets_texture_baseColor[descriptorIndex].SampleLevel(sampler_linear_wrap, UV_baseColorMap, 2); + baseColor.rgb = DEGAMMA(baseColor.rgb); + } + else + { + baseColor = 1; + } + baseColor *= material.baseColor; + float4 color = baseColor; + float4 emissiveColor = material.emissiveColor; + + + // Light sampling: + float3 P = WorldRayOrigin() + WorldRayDirection() * RayTCurrent(); + float3 V = normalize(g_xCamera_CamPos - P); + Surface surface = CreateSurface(P, N, V, baseColor, 0.5f, 1, 0, 0); + Lighting lighting = CreateLighting(0, 0, 0, 0); + + [loop] + for (uint iterator = 0; iterator < g_xFrame_LightArrayCount; iterator++) + { + ShaderEntity light = EntityArray[g_xFrame_LightArrayOffset + iterator]; + + if (light.GetFlags() & ENTITY_FLAG_LIGHT_STATIC) + { + continue; // static lights will be skipped (they are used in lightmap baking) + } + + switch (light.GetType()) + { + case ENTITY_TYPE_DIRECTIONALLIGHT: + { + DirectionalLight(light, surface, lighting); + } + break; + case ENTITY_TYPE_POINTLIGHT: + { + PointLight(light, surface, lighting); + } + break; + case ENTITY_TYPE_SPOTLIGHT: + { + SpotLight(light, surface, lighting); + } + break; + case ENTITY_TYPE_SPHERELIGHT: + { + SphereLight(light, surface, lighting); + } + break; + case ENTITY_TYPE_DISCLIGHT: + { + DiscLight(light, surface, lighting); + } + break; + case ENTITY_TYPE_RECTANGLELIGHT: + { + RectangleLight(light, surface, lighting); + } + break; + case ENTITY_TYPE_TUBELIGHT: + { + TubeLight(light, surface, lighting); + } + break; + } + } + + payload.color = baseColor.rgb * (lighting.direct.diffuse + GetAmbient(surface.N)) + emissiveColor.rgb * emissiveColor.a; + +#else + payload.color = float3(1, 0, 0); +#endif // SPIRV +} + +[shader("anyhit")] +void RTReflection_AnyHit(inout RayPayload payload, in MyAttributes attr) +{ +#ifndef SPIRV + float u = attr.barycentrics.x; + float v = attr.barycentrics.y; + float w = 1 - u - v; + uint primitiveIndex = PrimitiveIndex(); + uint geometryOffset = InstanceID(); +#ifdef RAYTRACING_GEOMETRYINDEX + uint geometryIndex = GeometryIndex(); // requires tier_1_1 GeometryIndex feature!! +#else + uint geometryIndex = 0; +#endif // RAYTRACING_GEOMETRYINDEX + uint descriptorIndex = geometryOffset + geometryIndex; + ShaderMaterial material = subsets_material[descriptorIndex]; + if (material.uvset_baseColorMap < 0) + { + return; + } + uint i0 = subsets_indexBuffer[descriptorIndex][primitiveIndex * 3 + 0]; + uint i1 = subsets_indexBuffer[descriptorIndex][primitiveIndex * 3 + 1]; + uint i2 = subsets_indexBuffer[descriptorIndex][primitiveIndex * 3 + 2]; + float2 uv0, uv1, uv2; + if (material.uvset_baseColorMap == 0) + { + uv0 = subsets_vertexBuffer_UV0[descriptorIndex][i0]; + uv1 = subsets_vertexBuffer_UV0[descriptorIndex][i1]; + uv2 = subsets_vertexBuffer_UV0[descriptorIndex][i2]; + } + else + { + uv0 = subsets_vertexBuffer_UV1[descriptorIndex][i0]; + uv1 = subsets_vertexBuffer_UV1[descriptorIndex][i1]; + uv2 = subsets_vertexBuffer_UV1[descriptorIndex][i2]; + } + + float2 uv = uv0 * w + uv1 * u + uv2 * v; + float alpha = subsets_texture_baseColor[descriptorIndex].SampleLevel(sampler_point_wrap, uv, 2).a; + + if (alpha < 0.9) + { + IgnoreHit(); + } +#endif // SPIRV +} + +[shader("miss")] +void RTReflection_Miss(inout RayPayload payload) +{ + Surface surface; + surface.roughness = payload.roughness; + surface.R = WorldRayDirection(); + payload.color = EnvironmentReflection_Global(surface, surface.roughness * g_xFrame_EnvProbeMipCount); +} diff --git a/WickedEngine/wiEnums.h b/WickedEngine/wiEnums.h index 4db46e00a..4308b3eb9 100644 --- a/WickedEngine/wiEnums.h +++ b/WickedEngine/wiEnums.h @@ -379,6 +379,7 @@ enum CSTYPES enum RTTYPES { RTTYPE_RTAO, + RTTYPE_RTREFLECTION, RTTYPE_COUNT }; diff --git a/WickedEngine/wiGraphicsDevice_DX12.cpp b/WickedEngine/wiGraphicsDevice_DX12.cpp index c4d39b9b5..67839f9e4 100644 --- a/WickedEngine/wiGraphicsDevice_DX12.cpp +++ b/WickedEngine/wiGraphicsDevice_DX12.cpp @@ -2206,7 +2206,6 @@ using namespace DX12_Internal; hr = device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS5, &features_5, sizeof(features_5)); RAYTRACING = features_5.RaytracingTier >= D3D12_RAYTRACING_TIER_1_0; - // needs Windows SDK 10.19041 or greater, this can be commented out safely: RAYTRACING_INLINE = features_5.RaytracingTier >= D3D12_RAYTRACING_TIER_1_1; hr = device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS6, &features_6, sizeof(features_6)); diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index 81fc59f40..0d4529da6 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -10409,9 +10409,13 @@ void Postprocess_RTAO( descriptorTable.resources.push_back({ TEXTURE2D, TEXSLOT_DEPTH }); descriptorTable.resources.push_back({ ACCELERATIONSTRUCTURE, TEXSLOT_ACCELERATION_STRUCTURE }); descriptorTable.resources.push_back({ RWTEXTURE2D, 0 }); + descriptorTable.resources.push_back({ ROOT_CONSTANTBUFFER, CB_GETBINDSLOT(FrameCB) }); descriptorTable.resources.push_back({ ROOT_CONSTANTBUFFER, CB_GETBINDSLOT(CameraCB) }); descriptorTable.resources.push_back({ ROOT_CONSTANTBUFFER, CB_GETBINDSLOT(PostProcessCB) }); descriptorTable.staticsamplers.push_back({ samplers[SSLOT_POINT_CLAMP], SSLOT_POINT_CLAMP }); + descriptorTable.staticsamplers.push_back({ samplers[SSLOT_LINEAR_CLAMP], SSLOT_LINEAR_CLAMP }); + descriptorTable.staticsamplers.push_back({ samplers[SSLOT_POINT_WRAP], SSLOT_POINT_WRAP }); + descriptorTable.staticsamplers.push_back({ samplers[SSLOT_LINEAR_WRAP], SSLOT_LINEAR_WRAP }); device->CreateDescriptorTable(&descriptorTable); rootSignature = RootSignature(); @@ -10521,8 +10525,9 @@ void Postprocess_RTAO( device->WriteDescriptor(&descriptorTable, 2, 0, &temp); device->BindDescriptorTable(RAYTRACING, 0, &descriptorTable, cmd); device->BindDescriptorTable(RAYTRACING, 1, &scene.descriptorTable, cmd); - device->BindRootDescriptor(RAYTRACING, 0, &constantBuffers[CBTYPE_CAMERA], 0, cmd); - device->BindRootDescriptor(RAYTRACING, 1, cb_alloc.buffer, cb_alloc.offset, cmd); + device->BindRootDescriptor(RAYTRACING, 0, &constantBuffers[CBTYPE_FRAME], 0, cmd); + device->BindRootDescriptor(RAYTRACING, 1, &constantBuffers[CBTYPE_CAMERA], 0, cmd); + device->BindRootDescriptor(RAYTRACING, 2, cb_alloc.buffer, cb_alloc.offset, cmd); size_t shaderIdentifierSize = device->GetShaderIdentifierSize(); GraphicsDevice::GPUAllocation shadertable_raygen = device->AllocateGPU(shaderIdentifierSize, cmd); @@ -10597,6 +10602,278 @@ void Postprocess_RTAO( wiProfiler::EndRange(prof_range); device->EventEnd(cmd); } +void Postprocess_RTReflection( + const Texture& depthbuffer, + const Texture& gbuffer1, + const Texture& gbuffer2, + const Texture& output, + CommandList cmd, + float range +) +{ + if (!wiRenderer::GetDevice()->CheckCapability(GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_RAYTRACING)) + return; + if (!wiRenderer::GetDevice()->CheckCapability(GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_DESCRIPTOR_MANAGEMENT)) + return; + + const Scene& scene = wiScene::GetScene(); + if (scene.objects.GetCount() <= 0) + { + return; + } + + GraphicsDevice* device = GetDevice(); + + device->EventBegin("Postprocess_RTReflection", cmd); + auto prof_range = wiProfiler::BeginRangeGPU("RTReflection", cmd); + + static Texture temp; + static Texture texture_temporal[2]; + + if (temp.desc.Width != output.desc.Width / 2 || temp.desc.Height != output.desc.Height / 2) + { + TextureDesc desc = output.desc; + desc.BindFlags |= BIND_UNORDERED_ACCESS; + desc.Width /= 2; + desc.Height /= 2; + + device->CreateTexture(&desc, nullptr, &temp); + device->SetName(&temp, "rtreflection_temp"); + + device->CreateTexture(&desc, nullptr, &texture_temporal[0]); + device->CreateTexture(&desc, nullptr, &texture_temporal[1]); + + } + + static RaytracingPipelineState RTPSO; + static DescriptorTable descriptorTable; + static RootSignature rootSignature; + + auto load_shaders = [&scene](uint64_t userdata) { + + GraphicsDevice* device = GetDevice(); + + descriptorTable = DescriptorTable(); + descriptorTable.resources.push_back({ RWTEXTURE2D, 0 }); + descriptorTable.resources.push_back({ ACCELERATIONSTRUCTURE, TEXSLOT_ACCELERATION_STRUCTURE }); + descriptorTable.resources.push_back({ TEXTURE2D, TEXSLOT_DEPTH }); + descriptorTable.resources.push_back({ TEXTURE2D, TEXSLOT_GBUFFER1 }); + descriptorTable.resources.push_back({ TEXTURE2D, TEXSLOT_GBUFFER2 }); + descriptorTable.resources.push_back({ TEXTURECUBEARRAY, TEXSLOT_ENVMAPARRAY }); + descriptorTable.resources.push_back({ TEXTURE2DARRAY, TEXSLOT_SHADOWARRAY_2D }); + descriptorTable.resources.push_back({ TEXTURECUBEARRAY, TEXSLOT_SHADOWARRAY_CUBE }); + descriptorTable.resources.push_back({ TEXTURECUBEARRAY, TEXSLOT_SHADOWARRAY_TRANSPARENT }); + descriptorTable.resources.push_back({ STRUCTUREDBUFFER, SBSLOT_ENTITYARRAY }); + descriptorTable.resources.push_back({ STRUCTUREDBUFFER, SBSLOT_MATRIXARRAY }); + descriptorTable.resources.push_back({ ROOT_CONSTANTBUFFER, CB_GETBINDSLOT(FrameCB) }); + descriptorTable.resources.push_back({ ROOT_CONSTANTBUFFER, CB_GETBINDSLOT(CameraCB) }); + descriptorTable.resources.push_back({ ROOT_CONSTANTBUFFER, CB_GETBINDSLOT(PostProcessCB) }); + descriptorTable.staticsamplers.push_back({ samplers[SSLOT_POINT_CLAMP], SSLOT_POINT_CLAMP }); + descriptorTable.staticsamplers.push_back({ samplers[SSLOT_LINEAR_CLAMP], SSLOT_LINEAR_CLAMP }); + descriptorTable.staticsamplers.push_back({ samplers[SSLOT_POINT_WRAP], SSLOT_POINT_WRAP }); + descriptorTable.staticsamplers.push_back({ samplers[SSLOT_LINEAR_WRAP], SSLOT_LINEAR_WRAP }); + descriptorTable.staticsamplers.push_back({ samplers[SSLOT_CMP_DEPTH], SSLOT_CMP_DEPTH }); + device->CreateDescriptorTable(&descriptorTable); + + rootSignature = RootSignature(); + rootSignature.tables.push_back(descriptorTable); + rootSignature.tables.push_back(scene.descriptorTable); + device->CreateRootSignature(&rootSignature); + + raytracingShaders[RTTYPE_RTREFLECTION].rootSignature = &rootSignature; + bool success = LoadShader(SHADERSTAGE_COUNT, raytracingShaders[RTTYPE_RTREFLECTION], "rtreflectionLIB.cso"); + assert(success); + + RaytracingPipelineStateDesc rtdesc; + rtdesc.rootSignature = &rootSignature; + + rtdesc.shaderlibraries.emplace_back(); + rtdesc.shaderlibraries.back().shader = &raytracingShaders[RTTYPE_RTREFLECTION]; + rtdesc.shaderlibraries.back().function_name = "RTReflection_Raygen"; + rtdesc.shaderlibraries.back().type = ShaderLibrary::RAYGENERATION; + + rtdesc.shaderlibraries.emplace_back(); + rtdesc.shaderlibraries.back().shader = &raytracingShaders[RTTYPE_RTREFLECTION]; + rtdesc.shaderlibraries.back().function_name = "RTReflection_ClosestHit"; + rtdesc.shaderlibraries.back().type = ShaderLibrary::CLOSESTHIT; + + rtdesc.shaderlibraries.emplace_back(); + rtdesc.shaderlibraries.back().shader = &raytracingShaders[RTTYPE_RTREFLECTION]; + rtdesc.shaderlibraries.back().function_name = "RTReflection_AnyHit"; + rtdesc.shaderlibraries.back().type = ShaderLibrary::ANYHIT; + + rtdesc.shaderlibraries.emplace_back(); + rtdesc.shaderlibraries.back().shader = &raytracingShaders[RTTYPE_RTREFLECTION]; + rtdesc.shaderlibraries.back().function_name = "RTReflection_Miss"; + rtdesc.shaderlibraries.back().type = ShaderLibrary::MISS; + + rtdesc.hitgroups.emplace_back(); + rtdesc.hitgroups.back().type = ShaderHitGroup::GENERAL; + rtdesc.hitgroups.back().name = "RTReflection_Raygen"; + rtdesc.hitgroups.back().general_shader = 0; + + rtdesc.hitgroups.emplace_back(); + rtdesc.hitgroups.back().type = ShaderHitGroup::GENERAL; + rtdesc.hitgroups.back().name = "RTReflection_Miss"; + rtdesc.hitgroups.back().general_shader = 3; + + rtdesc.hitgroups.emplace_back(); + rtdesc.hitgroups.back().type = ShaderHitGroup::TRIANGLES; + rtdesc.hitgroups.back().name = "RTReflection_Hitgroup"; + rtdesc.hitgroups.back().closesthit_shader = 1; + rtdesc.hitgroups.back().anyhit_shader = 2; + + rtdesc.max_trace_recursion_depth = 1; + rtdesc.max_payload_size_in_bytes = sizeof(float4); + rtdesc.max_attribute_size_in_bytes = sizeof(float2); // bary + success = device->CreateRaytracingPipelineState(&rtdesc, &RTPSO); + assert(success); + }; + + static wiEvent::Handle handle = wiEvent::Subscribe(SYSTEM_EVENT_RELOAD_SHADERS, load_shaders); + if (!RTPSO.IsValid()) + { + load_shaders(0); + } + + PostProcessCB cb; + cb.xPPResolution.x = temp.desc.Width; + cb.xPPResolution.y = temp.desc.Height; + cb.xPPResolution_rcp.x = 1.0f / cb.xPPResolution.x; + cb.xPPResolution_rcp.y = 1.0f / cb.xPPResolution.y; + cb.rtreflection_range = range; + cb.rtreflection_seed = renderTime; + GraphicsDevice::GPUAllocation cb_alloc = device->AllocateGPU(sizeof(cb), cmd); + memcpy(cb_alloc.data, &cb, sizeof(cb)); + + device->BindRaytracingPipelineState(&RTPSO, cmd); + device->WriteDescriptor(&descriptorTable, 0, 0, &temp); + device->WriteDescriptor(&descriptorTable, 1, 0, &scene.TLAS); + device->WriteDescriptor(&descriptorTable, 2, 0, &depthbuffer); + device->WriteDescriptor(&descriptorTable, 3, 0, &gbuffer1); + device->WriteDescriptor(&descriptorTable, 4, 0, &gbuffer2); + device->WriteDescriptor(&descriptorTable, 5, 0, &textures[TEXTYPE_CUBEARRAY_ENVMAPARRAY]); + device->WriteDescriptor(&descriptorTable, 6, 0, &shadowMapArray_2D); + device->WriteDescriptor(&descriptorTable, 7, 0, &shadowMapArray_Cube); + device->WriteDescriptor(&descriptorTable, 8, 0, &shadowMapArray_Transparent); + device->WriteDescriptor(&descriptorTable, 9, 0, &resourceBuffers[RBTYPE_ENTITYARRAY]); + device->WriteDescriptor(&descriptorTable, 10, 0, &resourceBuffers[RBTYPE_MATRIXARRAY]); + device->BindDescriptorTable(RAYTRACING, 0, &descriptorTable, cmd); + device->BindDescriptorTable(RAYTRACING, 1, &scene.descriptorTable, cmd); + device->BindRootDescriptor(RAYTRACING, 0, &constantBuffers[CBTYPE_FRAME], 0, cmd); + device->BindRootDescriptor(RAYTRACING, 1, &constantBuffers[CBTYPE_CAMERA], 0, cmd); + device->BindRootDescriptor(RAYTRACING, 2, cb_alloc.buffer, cb_alloc.offset, cmd); + + size_t shaderIdentifierSize = device->GetShaderIdentifierSize(); + GraphicsDevice::GPUAllocation shadertable_raygen = device->AllocateGPU(shaderIdentifierSize, cmd); + GraphicsDevice::GPUAllocation shadertable_miss = device->AllocateGPU(shaderIdentifierSize, cmd); + GraphicsDevice::GPUAllocation shadertable_hitgroup = device->AllocateGPU(shaderIdentifierSize, cmd); + + device->WriteShaderIdentifier(&RTPSO, 0, shadertable_raygen.data); + device->WriteShaderIdentifier(&RTPSO, 1, shadertable_miss.data); + device->WriteShaderIdentifier(&RTPSO, 2, shadertable_hitgroup.data); + + DispatchRaysDesc dispatchraysdesc; + dispatchraysdesc.raygeneration.buffer = shadertable_raygen.buffer; + dispatchraysdesc.raygeneration.offset = shadertable_raygen.offset; + dispatchraysdesc.raygeneration.size = shaderIdentifierSize; + + dispatchraysdesc.miss.buffer = shadertable_miss.buffer; + dispatchraysdesc.miss.offset = shadertable_miss.offset; + dispatchraysdesc.miss.size = shaderIdentifierSize; + dispatchraysdesc.miss.stride = shaderIdentifierSize; + + dispatchraysdesc.hitgroup.buffer = shadertable_hitgroup.buffer; + dispatchraysdesc.hitgroup.offset = shadertable_hitgroup.offset; + dispatchraysdesc.hitgroup.size = shaderIdentifierSize; + dispatchraysdesc.hitgroup.stride = shaderIdentifierSize; + + dispatchraysdesc.Width = temp.desc.Width; + dispatchraysdesc.Height = temp.desc.Height; + + device->DispatchRays(&dispatchraysdesc, cmd); + + GPUBarrier barriers[] = { + GPUBarrier::Memory(), + }; + device->Barrier(barriers, arraysize(barriers), cmd); + + device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); + device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); + + int temporal_output = device->GetFrameCount() % 2; + int temporal_history = 1 - temporal_output; + + // Temporal pass: + { + device->EventBegin("Temporal pass", cmd); + device->BindComputeShader(&computeShaders[CSTYPE_POSTPROCESS_SSR_TEMPORAL], cmd); + + device->BindResource(CS, &depthbuffer, TEXSLOT_DEPTH, cmd); + device->BindResource(CS, &temp, TEXSLOT_ONDEMAND0, cmd); + device->BindResource(CS, &texture_temporal[temporal_history], TEXSLOT_ONDEMAND1, cmd); + + const GPUResource* uavs[] = { + &texture_temporal[temporal_output], + }; + device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + + device->Dispatch( + (texture_temporal[temporal_output].GetDesc().Width + POSTPROCESS_BLOCKSIZE - 1) / POSTPROCESS_BLOCKSIZE, + (texture_temporal[temporal_output].GetDesc().Height + POSTPROCESS_BLOCKSIZE - 1) / POSTPROCESS_BLOCKSIZE, + 1, + cmd + ); + + GPUBarrier barriers[] = { + GPUBarrier::Memory(), + }; + device->Barrier(barriers, arraysize(barriers), cmd); + + device->UnbindUAVs(0, arraysize(uavs), cmd); + device->EventEnd(cmd); + } + + // Switch to full res + cb.xPPResolution.x = output.desc.Width; + cb.xPPResolution.y = output.desc.Height; + cb.xPPResolution_rcp.x = 1.0f / cb.xPPResolution.x; + cb.xPPResolution_rcp.y = 1.0f / cb.xPPResolution.y; + device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); + device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); + + // Median blur pass: + { + device->EventBegin("Median blur pass", cmd); + device->BindComputeShader(&computeShaders[CSTYPE_POSTPROCESS_SSR_MEDIAN], cmd); + + device->BindResource(CS, &depthbuffer, TEXSLOT_DEPTH, cmd); + device->BindResource(CS, &texture_temporal[temporal_output], TEXSLOT_ONDEMAND0, cmd); + + const GPUResource* uavs[] = { + &output, + }; + device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + + device->Dispatch( + (output.desc.Width + POSTPROCESS_BLOCKSIZE - 1) / POSTPROCESS_BLOCKSIZE, + (output.desc.Height + POSTPROCESS_BLOCKSIZE - 1) / POSTPROCESS_BLOCKSIZE, + 1, + cmd + ); + + GPUBarrier barriers[] = { + GPUBarrier::Memory(), + }; + device->Barrier(barriers, arraysize(barriers), cmd); + + device->UnbindUAVs(0, arraysize(uavs), cmd); + device->EventEnd(cmd); + } + + wiProfiler::EndRange(prof_range); + device->EventEnd(cmd); +} void Postprocess_SSR( const Texture& input, const Texture& depthbuffer, diff --git a/WickedEngine/wiRenderer.h b/WickedEngine/wiRenderer.h index 2736256ea..86b06a928 100644 --- a/WickedEngine/wiRenderer.h +++ b/WickedEngine/wiRenderer.h @@ -243,6 +243,14 @@ namespace wiRenderer uint32_t samplecount = 16, float power = 2.0f ); + void Postprocess_RTReflection( + const wiGraphics::Texture& depthbuffer, + const wiGraphics::Texture& gbuffer1, + const wiGraphics::Texture& gbuffer2, + const wiGraphics::Texture& output, + wiGraphics::CommandList cmd, + float range = 1000.0f + ); void Postprocess_SSR( const wiGraphics::Texture& input, const wiGraphics::Texture& depthbuffer, diff --git a/WickedEngine/wiScene.cpp b/WickedEngine/wiScene.cpp index 154f77644..d7cb35765 100644 --- a/WickedEngine/wiScene.cpp +++ b/WickedEngine/wiScene.cpp @@ -1158,6 +1158,7 @@ namespace wiScene descriptorTable.resources[DESCRIPTORTABLE_ENTRY_SUBSETS_MATERIAL] = { CONSTANTBUFFER, 0, MAX_DESCRIPTOR_INDEXING }; descriptorTable.resources[DESCRIPTORTABLE_ENTRY_SUBSETS_TEXTURE_BASECOLOR] = { TEXTURE2D, 0, MAX_DESCRIPTOR_INDEXING }; descriptorTable.resources[DESCRIPTORTABLE_ENTRY_SUBSETS_INDEXBUFFER] = { TYPEDBUFFER, MAX_DESCRIPTOR_INDEXING, MAX_DESCRIPTOR_INDEXING }; + descriptorTable.resources[DESCRIPTORTABLE_ENTRY_SUBSETS_VERTEXBUFFER_POSITION_NORMAL_WIND] = { RAWBUFFER, MAX_DESCRIPTOR_INDEXING * 2, MAX_DESCRIPTOR_INDEXING }; descriptorTable.resources[DESCRIPTORTABLE_ENTRY_SUBSETS_VERTEXBUFFER_UV0] = { TYPEDBUFFER, MAX_DESCRIPTOR_INDEXING * 3, MAX_DESCRIPTOR_INDEXING }; descriptorTable.resources[DESCRIPTORTABLE_ENTRY_SUBSETS_VERTEXBUFFER_UV1] = { TYPEDBUFFER, MAX_DESCRIPTOR_INDEXING * 4, MAX_DESCRIPTOR_INDEXING }; @@ -2174,6 +2175,12 @@ namespace wiScene &mesh.indexBuffer, -1, subset.indexOffset * mesh.GetIndexStride() ); + device->WriteDescriptor( + &descriptorTable, + DESCRIPTORTABLE_ENTRY_SUBSETS_VERTEXBUFFER_POSITION_NORMAL_WIND, + global_geometryIndex, + &mesh.vertexBuffer_POS + ); device->WriteDescriptor( &descriptorTable, DESCRIPTORTABLE_ENTRY_SUBSETS_VERTEXBUFFER_UV0, diff --git a/WickedEngine/wiScene.h b/WickedEngine/wiScene.h index 3ec1a988e..314940a5c 100644 --- a/WickedEngine/wiScene.h +++ b/WickedEngine/wiScene.h @@ -1146,6 +1146,7 @@ namespace wiScene DESCRIPTORTABLE_ENTRY_SUBSETS_MATERIAL, DESCRIPTORTABLE_ENTRY_SUBSETS_TEXTURE_BASECOLOR, DESCRIPTORTABLE_ENTRY_SUBSETS_INDEXBUFFER, + DESCRIPTORTABLE_ENTRY_SUBSETS_VERTEXBUFFER_POSITION_NORMAL_WIND, DESCRIPTORTABLE_ENTRY_SUBSETS_VERTEXBUFFER_UV0, DESCRIPTORTABLE_ENTRY_SUBSETS_VERTEXBUFFER_UV1, diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 51bf54c14..65764997d 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wiVersion // minor features, major updates, breaking API changes const int minor = 47; // minor bug fixes, alterations, refactors, updates - const int revision = 37; + const int revision = 38; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);