diff --git a/Source/Game-Lib/Game-Lib/Rendering/GameRenderer.cpp b/Source/Game-Lib/Game-Lib/Rendering/GameRenderer.cpp index bd342fb..b9f7719 100644 --- a/Source/Game-Lib/Game-Lib/Rendering/GameRenderer.cpp +++ b/Source/Game-Lib/Game-Lib/Rendering/GameRenderer.cpp @@ -498,7 +498,7 @@ void GameRenderer::CreatePermanentResources() visibilityBufferDesc.debugName = "VisibilityBuffer"; visibilityBufferDesc.dimensions = vec2(1.0f, 1.0f); visibilityBufferDesc.dimensionType = Renderer::ImageDimensionType::DIMENSION_SCALE_RENDERSIZE; - visibilityBufferDesc.format = Renderer::ImageFormat::R32G32B32A32_UINT; + visibilityBufferDesc.format = Renderer::ImageFormat::R32G32_UINT; visibilityBufferDesc.sampleCount = Renderer::SampleCount::SAMPLE_COUNT_1; visibilityBufferDesc.clearUInts = uvec4(0, 0, 0, 0); diff --git a/Source/Game-Lib/Game-Lib/Rendering/Material/MaterialRenderer.cpp b/Source/Game-Lib/Game-Lib/Rendering/Material/MaterialRenderer.cpp index 6996488..490a7f4 100644 --- a/Source/Game-Lib/Game-Lib/Rendering/Material/MaterialRenderer.cpp +++ b/Source/Game-Lib/Game-Lib/Rendering/Material/MaterialRenderer.cpp @@ -101,7 +101,15 @@ void MaterialRenderer::AddPreEffectsPass(Renderer::RenderGraph* renderGraph, Ren commandList.BindDescriptorSet(Renderer::DescriptorSetSlot::MODEL, data.modelSet, frameIndex); commandList.BindDescriptorSet(Renderer::DescriptorSetSlot::PER_PASS, data.preEffectsSet, frameIndex); - uvec2 outputSize = _renderer->GetImageDimensions(resources.packedNormals, 0); + vec2 outputSize = static_cast(_renderer->GetImageDimensions(resources.packedNormals, 0)); + + struct Constants + { + vec4 renderInfo; // x = Render Width, y = Render Height, z = 1/Width, w = 1/Height + }; + + Constants* constants = graphResources.FrameNew(); + constants->renderInfo = vec4(outputSize, 1.0f / outputSize); uvec2 dispatchSize = uvec2((outputSize.x + 7) / 8, (outputSize.y + 7) / 8); commandList.Dispatch(dispatchSize.x, dispatchSize.y, 1); @@ -207,6 +215,7 @@ void MaterialRenderer::AddMaterialPass(Renderer::RenderGraph* renderGraph, Rende struct Constants { + vec4 renderInfo; // x = Render Width, y = Render Height, z = 1/Width, w = 1/Height uvec4 lightInfo; // x = Directional Light Count, Y = Point Light Count, Z = Cascade Count, W = Shadows Enabled vec4 fogColor; vec4 fogSettings; // x = Enabled, y = Begin Fog Blend Dist, z = End Fog Blend Dist, w = UNUSED @@ -221,6 +230,9 @@ void MaterialRenderer::AddMaterialPass(Renderer::RenderGraph* renderGraph, Rende Constants* constants = graphResources.FrameNew(); + vec2 outputSize = static_cast(_renderer->GetImageDimensions(resources.sceneColor, 0)); + constants->renderInfo = vec4(outputSize, 1.0f / outputSize); + CVarSystem* cvarSystem = CVarSystem::Get(); const u32 numCascades = static_cast(*cvarSystem->GetIntCVar(CVarCategory::Client | CVarCategory::Rendering, "shadowCascadeNum")); const u32 shadowEnabled = static_cast(*cvarSystem->GetIntCVar(CVarCategory::Client | CVarCategory::Rendering, "shadowEnabled")); diff --git a/Source/Shaders/Shaders/Include/VisibilityBuffers.inc.hlsl b/Source/Shaders/Shaders/Include/VisibilityBuffers.inc.hlsl index 4a8a974..63f87ef 100644 --- a/Source/Shaders/Shaders/Include/VisibilityBuffers.inc.hlsl +++ b/Source/Shaders/Shaders/Include/VisibilityBuffers.inc.hlsl @@ -5,8 +5,141 @@ #include "Model/ModelShared.inc.hlsl" #include "globalData.inc.hlsl" +// Choose barycentric reconstruction method method (default = plane). For ray, define RECONSTRUCT_BARY_RAY. +//#define RECONSTRUCT_BARY_RAY + +// Calculates the local (barycentric coordinates) position of a ray hitting a triangle (Muller-Trumbore algorithm) +// Parameters: p0,p1,p2 -> World space coordinates of triangle +// o -> Origin of ray in world space (Mainly view camera here) +// d-> Unit vector direction of ray from origin +float3 RayTriangleIntersection(float3 p0, float3 p1, float3 p2, float3 o, float3 d) +{ + float3 v0v1 = p1 - p0; + float3 v0v2 = p2 - p0; + float3 pvec = cross(d, v0v2); + float det = dot(v0v1, pvec); + float invDet = 1 / det; + float3 tvec = o - p0; + float u = dot(tvec, pvec) * invDet; + float3 qvec = cross(tvec, v0v1); + float v = dot(d, qvec) * invDet; + float w = 1.0f - v - u; + return float3(w, u, v); +} + +struct BarycentricDeriv +{ + float3 m_lambda; + float3 m_ddx; + float3 m_ddy; +}; + +// Calculate ray differentials for a point in world-space +// Parameters +// - pt0,pt1,pt2 -> world space coordinates of the triangle currently visible on the pixel +// - screenPos -> 2D NDC position of current pixel, range [-1, 1] +// - rayOrigin -> camera position +// +// This approach produces the same quality as CalcFullBary, but a bit slower +// with more register allocation and generates more MUL/FMA instructions for matrix multiplication +BarycentricDeriv CalcRayBary(float3 pt0, float3 pt1, float3 pt2, float2 pixelNdc, float3 rayOrigin, float4x4 viewInv, float4x4 projInv, float2 twoOverScreenSize) +{ + BarycentricDeriv ret; + + // 1px offsets in NDC (Y-down screen to NDC Y-up already handled by caller) + float3 ndcPos = float3(pixelNdc, 1.0); + float3 ndcDx = float3(pixelNdc + float2(twoOverScreenSize.x, 0), 1.0); + float3 ndcDy = float3(pixelNdc - float2(0, twoOverScreenSize.y), 1.0); + + // Clip to View and divide by w + float4 vp = mul(float4(ndcPos, 1.0), projInv); + float4 vpx = mul(float4(ndcDx, 1.0), projInv); + float4 vpy = mul(float4(ndcDy, 1.0), projInv); + vp.xyz /= vp.w; vpx.xyz /= vpx.w; vpy.xyz /= vpy.w; + + // Build directions in VIEW (from camera origin), transform to WORLD, normalize once + float3 rayDir = mul(float4(vp.xyz, 0.0), viewInv).xyz; + float3 rayDirDx = mul(float4(vpx.xyz, 0.0), viewInv).xyz; + float3 rayDirDy = mul(float4(vpy.xyz, 0.0), viewInv).xyz; + rayDir = normalize(rayDir); + rayDirDx = normalize(rayDirDx); + rayDirDy = normalize(rayDirDy); + + // Intersection returns (w,u,v); our pipeline stores (b0,b1) = (w,u) + float3 l = RayTriangleIntersection(pt0, pt1, pt2, rayOrigin, rayDir); + float3 ldx = RayTriangleIntersection(pt0, pt1, pt2, rayOrigin, rayDirDx); + float3 ldy = RayTriangleIntersection(pt0, pt1, pt2, rayOrigin, rayDirDy); + + ret.m_lambda = l; // (b0,b1,b2) = (w,u,v) + ret.m_ddx = ldx - l; // (db0,db1,db2) + ret.m_ddy = ldy - l; + return ret; +} + +// Computes the partial derivatives of a triangle from the homogeneous clip space vertices +BarycentricDeriv CalcFullBary(float4 pt0, float4 pt1, float4 pt2, float2 pixelNdc, float2 two_over_windowsize) +{ + BarycentricDeriv ret; + float3 invW = rcp(float3(pt0.w, pt1.w, pt2.w)); + //Project points on screen to calculate post projection positions in 2D + float2 ndc0 = pt0.xy * invW.x; + float2 ndc1 = pt1.xy * invW.y; + float2 ndc2 = pt2.xy * invW.z; + + // Computing partial derivatives and prospective correct attribute interpolation with barycentric coordinates + // Equation for calculation taken from Appendix A of DAIS paper: + // https://cg.ivd.kit.edu/publications/2015/dais/DAIS.pdf + + // Calculating inverse of determinant(rcp of area of triangle). + float invDet = rcp(determinant(float2x2(ndc2 - ndc1, ndc0 - ndc1))); + + //determining the partial derivatives + // ddx[i] = (y[i+1] - y[i-1])/Determinant + ret.m_ddx = float3(ndc1.y - ndc2.y, ndc2.y - ndc0.y, ndc0.y - ndc1.y) * invDet * invW; + ret.m_ddy = float3(ndc2.x - ndc1.x, ndc0.x - ndc2.x, ndc1.x - ndc0.x) * invDet * invW; + // sum of partial derivatives. + float ddxSum = dot(ret.m_ddx, float3(1, 1, 1)); + float ddySum = dot(ret.m_ddy, float3(1, 1, 1)); + + // Delta vector from pixel's screen position to vertex 0 of the triangle. + float2 deltaVec = pixelNdc - ndc0; + + // Calculating interpolated W at point. + float interpInvW = invW.x + deltaVec.x * ddxSum + deltaVec.y * ddySum; + float interpW = rcp(interpInvW); + // The barycentric co-ordinate (m_lambda) is determined by perspective-correct interpolation. + // Equation taken from DAIS paper. + ret.m_lambda.x = interpW * (invW[0] + deltaVec.x * ret.m_ddx.x + deltaVec.y * ret.m_ddy.x); + ret.m_lambda.y = interpW * (0.0f + deltaVec.x * ret.m_ddx.y + deltaVec.y * ret.m_ddy.y); + ret.m_lambda.z = interpW * (0.0f + deltaVec.x * ret.m_ddx.z + deltaVec.y * ret.m_ddy.z); + + //Scaling from NDC to pixel units + ret.m_ddx *= two_over_windowsize.x; + ret.m_ddy *= two_over_windowsize.y; + ddxSum *= two_over_windowsize.x; + ddySum *= two_over_windowsize.y; + + ret.m_ddy *= -1.0f; + ddySum *= -1.0f; + + // This part fixes the derivatives error happening for the projected triangles. + // Instead of calculating the derivatives constantly across the 2D triangle we use a projected version + // of the gradients, this is more accurate and closely matches GPU raster behavior. + // Final gradient equation: ddx = (((lambda/w) + ddx) / (w+|ddx|)) - lambda + + // Calculating interpW at partial derivatives position sum. + float interpW_ddx = 1.0f / (interpInvW + ddxSum); + float interpW_ddy = 1.0f / (interpInvW + ddySum); + + // Calculating perspective projected derivatives. + ret.m_ddx = interpW_ddx * (ret.m_lambda * interpInvW + ret.m_ddx) - ret.m_lambda; + ret.m_ddy = interpW_ddy * (ret.m_lambda * interpInvW + ret.m_ddy) - ret.m_lambda; + + return ret; +} + #if GEOMETRY_PASS -uint4 PackVisibilityBuffer(uint typeID, uint instanceID, uint triangleID, float2 barycentrics, float2 ddxBarycentrics, float2 ddyBarycentrics) +uint2 PackVisibilityBuffer(uint typeID, uint instanceID, uint triangleID) { // VisibilityBuffer is 4 uints packed like this: // X @@ -15,32 +148,15 @@ uint4 PackVisibilityBuffer(uint typeID, uint instanceID, uint triangleID, float2 // TypeID 4 bits // Y // TriangleID 8 bits (out of 16), the remainder - // Barycentrics.x 12 bits - // Barycentrics.y 12 bits - // Z - // ddx(bary).x 16 bits - // ddx(bary).y 16 bits - // W - // ddy(bary).x 16 bits - // ddy(bary).y 16 bits - - uint2 twelveBitUnormBarycentrics = barycentrics * 4096; - - uint4 packedVisBuffer; + // UNUSED 24 bits + + uint2 packedVisBuffer; // X packedVisBuffer.x = (triangleID & 0xFF); packedVisBuffer.x |= instanceID << 8; packedVisBuffer.x |= typeID << 28; // Y packedVisBuffer.y = (triangleID >> 8); - packedVisBuffer.y |= twelveBitUnormBarycentrics.x << 8; - packedVisBuffer.y |= twelveBitUnormBarycentrics.y << 20; - // Z - packedVisBuffer.z = f32tof16(ddxBarycentrics.x); - packedVisBuffer.z |= f32tof16(ddxBarycentrics.y) << 16; - // W - packedVisBuffer.w = f32tof16(ddyBarycentrics.x); - packedVisBuffer.w |= f32tof16(ddyBarycentrics.y) << 16; return packedVisBuffer; } @@ -66,7 +182,7 @@ float2 NBLCalculateBarycentrics(in float3 pointPosition, in float3x3 vertexPosit #else // GEOMETRY_PASS -[[vk::binding(2, PER_PASS)]] Texture2D _visibilityBuffer; +[[vk::binding(2, PER_PASS)]] Texture2D _visibilityBuffer; struct Barycentrics { @@ -81,31 +197,23 @@ struct VisibilityBuffer uint instanceID; uint padding; uint triangleID; - Barycentrics barycentrics; }; -uint4 LoadVisibilityBuffer(uint2 pixelPos) +uint2 LoadVisibilityBuffer(uint2 pixelPos) { return _visibilityBuffer[pixelPos]; } -const VisibilityBuffer UnpackVisibilityBuffer(uint4 data) +const VisibilityBuffer UnpackVisibilityBuffer(uint2 data) { - // VisibilityBuffer is 4 uints packed like this: + // VisibilityBuffer is 2 uints packed like this: // X // TriangleID 8 bits (out of 16), we had to split this to fit // InstanceID 20 bits, different types can have the same InstanceID // TypeID 4 bits // Y // TriangleID 8 bits (out of 16), the remainder - // Barycentrics.x 12 bits - // Barycentrics.y 12 bits - // Z - // ddx(bary).x 16 bits - // ddx(bary).y 16 bits - // W - // ddy(bary).x 16 bits - // ddy(bary).y 16 bits + // UNUSED 24 bits VisibilityBuffer vBuffer; vBuffer.typeID = data.x >> 28; @@ -113,16 +221,6 @@ const VisibilityBuffer UnpackVisibilityBuffer(uint4 data) vBuffer.triangleID = (data.x & 0xFF) | ((data.y & 0xFF) << 8); - uint barycentrics = (data.y >> 8); - vBuffer.barycentrics.bary.x = float(barycentrics & 0xFFF) / 4095.0f; - vBuffer.barycentrics.bary.y = float(barycentrics >> 12) / 4095.0f; - - vBuffer.barycentrics.ddxBary.x = f16tof32(data.z); - vBuffer.barycentrics.ddxBary.y = f16tof32(data.z >> 16); - - vBuffer.barycentrics.ddyBary.x = f16tof32(data.w); - vBuffer.barycentrics.ddyBary.y = f16tof32(data.w >> 16); - return vBuffer; } @@ -230,6 +328,40 @@ FullBary3 CalcFullBary3(Barycentrics barycentrics, float3 v0, float3 v1, float3 return result; } +// Shared helper for reconstructing barycentrics (plane vs ray path). +Barycentrics ReconstructBarycentrics(float2 pixelPos, float2 renderSize, float3 wP0, float3 wP1, float3 wP2, uint cameraIndex) +{ + float2 pixelCenter = pixelPos + 0.5f; + float2 pixelNdc = pixelCenter / renderSize * 2.0f - 1.0f; + pixelNdc.y *= -1.0f; // flip once if screen Y-down + float2 twoOverScreenSize = 2.0f / renderSize; + + Camera cam = _cameras[cameraIndex]; + BarycentricDeriv bd; + +#if defined(RECONSTRUCT_BARY_RAY) + // Ray method expects inverse-projection to view space and inverse-view to world. + float4x4 projInv = cam.clipToView; + float4x4 viewInv = cam.viewToWorld; + float3 camWS = cam.eyePosition.xyz; + + bd = CalcRayBary(wP0, wP1, wP2, pixelNdc, camWS, viewInv, projInv, twoOverScreenSize); +#else + // Plane/projection path + float4x4 worldToClip = cam.worldToClip; + float4 c0 = mul(float4(wP0, 1.0f), worldToClip); + float4 c1 = mul(float4(wP1, 1.0f), worldToClip); + float4 c2 = mul(float4(wP2, 1.0f), worldToClip); + bd = CalcFullBary(c0, c1, c2, pixelNdc, twoOverScreenSize); +#endif + + Barycentrics useBary; + useBary.bary = bd.m_lambda.xy; + useBary.ddxBary = bd.m_ddx.xy; + useBary.ddyBary = bd.m_ddy.xy; + return useBary; +} + struct PixelVertexData { uint typeID; @@ -244,119 +376,104 @@ struct PixelVertexData float2 pixelPos; }; -PixelVertexData GetPixelVertexDataTerrain(const uint2 pixelPos, const VisibilityBuffer vBuffer, const uint cameraIndex) +PixelVertexData GetPixelVertexDataTerrain(const uint2 pixelPos, const VisibilityBuffer vBuffer, const uint cameraIndex, float2 renderSize) { InstanceData cellInstance = _instanceDatas[vBuffer.instanceID]; uint globalCellID = cellInstance.globalCellID; - - // Find the cell and chunk - uint globalVertexOffset = globalCellID * NUM_VERTICES_PER_CELL; uint3 localVertexIDs = GetLocalTerrainVertexIDs(vBuffer.triangleID); const uint cellID = cellInstance.packedChunkCellID & 0xFFFF; const uint chunkID = cellInstance.packedChunkCellID >> 16; - // Get vertices - TerrainVertex vertices[3]; + uint globalVertexOffset = globalCellID * NUM_VERTICES_PER_CELL; + TerrainVertex vertices[3]; [unroll] - for (uint i = 0; i < 3; i++) + for (uint i = 0; i < 3; i++) { vertices[i] = LoadTerrainVertex(chunkID, cellID, globalVertexOffset, localVertexIDs[i]); } - // Interpolate the pixels vertex attributes + float3 wP0 = vertices[0].position; + float3 wP1 = vertices[1].position; + float3 wP2 = vertices[2].position; + + Barycentrics bary = ReconstructBarycentrics(pixelPos, renderSize, wP0, wP1, wP2, cameraIndex); + PixelVertexData result; result.typeID = vBuffer.typeID; result.drawCallID = vBuffer.instanceID; result.extraID = 0; - // UV - result.uv0 = CalcFullBary2(vBuffer.barycentrics, vertices[0].uv, vertices[1].uv, vertices[2].uv); // [0..8] This is correct for terrain color textures + result.uv0 = CalcFullBary2(bary, vertices[0].uv, vertices[1].uv, vertices[2].uv); result.uv1 = result.uv0; + result.color = InterpolateVertexAttribute(bary, vertices[0].color, vertices[1].color, vertices[2].color); - // Color - result.color = InterpolateVertexAttribute(vBuffer.barycentrics, vertices[0].color, vertices[1].color, vertices[2].color); - - // Normal - result.worldNormal = normalize(InterpolateVertexAttribute(vBuffer.barycentrics, vertices[0].normal, vertices[1].normal, vertices[2].normal)); - - // Position - result.worldPos = InterpolateVertexAttribute(vBuffer.barycentrics, vertices[0].position, vertices[1].position, vertices[2].position); + result.worldNormal = normalize(InterpolateVertexAttribute(bary, vertices[0].normal, vertices[1].normal, vertices[2].normal)); + result.worldPos = InterpolateVertexAttribute(bary, vertices[0].position, vertices[1].position, vertices[2].position); result.viewPos = mul(float4(result.worldPos, 1.0f), _cameras[cameraIndex].worldToView); result.pixelPos = pixelPos; - return result; } -PixelVertexData GetPixelVertexDataModel(const uint2 pixelPos, const VisibilityBuffer vBuffer, const uint cameraIndex) +PixelVertexData GetPixelVertexDataModel(const uint2 pixelPos, const VisibilityBuffer vBuffer, const uint cameraIndex, float2 renderSize) { InstanceRef instanceRef = GetModelInstanceID(vBuffer.instanceID); uint instanceID = instanceRef.instanceID; uint drawID = instanceRef.drawID; ModelInstanceData instanceData = _modelInstanceDatas[instanceID]; - - // Get the VertexIDs of the triangle we're in IndexedDraw draw = _modelDraws[drawID]; uint3 vertexIDs = GetVertexIDs(vBuffer.triangleID, draw, _modelIndices); - // Get Vertices ModelVertex vertices[3]; - [unroll] - for (uint i = 0; i < 3; i++) + for (uint i = 0; i < 3; i++) { vertices[i] = LoadModelVertex(vertexIDs[i]); - - // Animate the vertex normal if we need to - if (instanceData.boneMatrixOffset != 4294967295) + if (instanceData.boneMatrixOffset != 4294967295) { - // Calculate bone transform matrix float4x4 boneTransformMatrix = CalcBoneTransformMatrix(instanceData, vertices[i]); - - vertices[i].position = mul(vertices[i].position, (float3x3)boneTransformMatrix); + vertices[i].position = mul(float4(vertices[i].position, 1.0f), boneTransformMatrix).xyz; vertices[i].normal = mul(vertices[i].normal, (float3x3)boneTransformMatrix); } } - // Interpolate the pixels vertex attributes + float4x4 instanceMatrix = _modelInstanceMatrices[instanceID]; + float3 wP0 = mul(float4(vertices[0].position, 1.0f), instanceMatrix).xyz; + float3 wP1 = mul(float4(vertices[1].position, 1.0f), instanceMatrix).xyz; + float3 wP2 = mul(float4(vertices[2].position, 1.0f), instanceMatrix).xyz; + + Barycentrics bary = ReconstructBarycentrics(pixelPos, renderSize, wP0, wP1, wP2, cameraIndex); + PixelVertexData result; result.typeID = vBuffer.typeID; result.drawCallID = instanceRef.drawID; result.extraID = instanceRef.extraID; - // UV - result.uv0 = CalcFullBary2(vBuffer.barycentrics, vertices[0].uv01.xy, vertices[1].uv01.xy, vertices[2].uv01.xy); - result.uv1 = CalcFullBary2(vBuffer.barycentrics, vertices[0].uv01.zw, vertices[1].uv01.zw, vertices[2].uv01.zw); - - // Models don't have vertex colors + result.uv0 = CalcFullBary2(bary, vertices[0].uv01.xy, vertices[1].uv01.xy, vertices[2].uv01.xy); + result.uv1 = CalcFullBary2(bary, vertices[0].uv01.zw, vertices[1].uv01.zw, vertices[2].uv01.zw); result.color = float3(1, 1, 1); - float4x4 instanceMatrix = _modelInstanceMatrices[instanceID]; - - // Normal - float3 vertexNormal = normalize(InterpolateVertexAttribute(vBuffer.barycentrics, vertices[0].normal, vertices[1].normal, vertices[2].normal)); - result.worldNormal = normalize(mul(vertexNormal, (float3x3)instanceMatrix)); // Convert to world space + float3 vertexNormal = normalize(InterpolateVertexAttribute(bary, vertices[0].normal, vertices[1].normal, vertices[2].normal)); + result.worldNormal = normalize(mul(vertexNormal, (float3x3)instanceMatrix)); - // World Position - float3 pixelVertexPosition = InterpolateVertexAttribute(vBuffer.barycentrics, vertices[0].position, vertices[1].position, vertices[2].position); - result.worldPos = mul(float4(pixelVertexPosition, 1.0f), instanceMatrix).xyz; // Convert to world space + float3 pixelVertexPos = InterpolateVertexAttribute(bary, vertices[0].position, vertices[1].position, vertices[2].position); + result.worldPos = mul(float4(pixelVertexPos, 1.0f), instanceMatrix).xyz; result.viewPos = mul(float4(result.worldPos, 1.0f), _cameras[cameraIndex].worldToView); result.pixelPos = pixelPos; - return result; } -PixelVertexData GetPixelVertexData(const uint2 pixelPos, const VisibilityBuffer vBuffer, uint cameraIndex) +PixelVertexData GetPixelVertexData(const uint2 pixelPos, const VisibilityBuffer vBuffer, uint cameraIndex, float2 renderSize) { if (vBuffer.typeID == ObjectType::Terrain) { - return GetPixelVertexDataTerrain(pixelPos, vBuffer, cameraIndex); + return GetPixelVertexDataTerrain(pixelPos, vBuffer, cameraIndex, renderSize); } else if (vBuffer.typeID == ObjectType::ModelOpaque) { - return GetPixelVertexDataModel(pixelPos, vBuffer, cameraIndex); + return GetPixelVertexDataModel(pixelPos, vBuffer, cameraIndex, renderSize); } PixelVertexData result; @@ -431,5 +548,4 @@ float3 CascadeIDToColor(uint cascadeID) return cascadeColors[cascadeID % cascadeCount]; } - #endif // VISIBILITYBUFFERS_INCLUDED \ No newline at end of file diff --git a/Source/Shaders/Shaders/MaterialPass.cs.hlsl b/Source/Shaders/Shaders/MaterialPass.cs.hlsl index 059071a..bf0acbc 100644 --- a/Source/Shaders/Shaders/MaterialPass.cs.hlsl +++ b/Source/Shaders/Shaders/MaterialPass.cs.hlsl @@ -11,9 +11,9 @@ permutation EDITOR_MODE = [0, 1]; // Off, Terrain #include "Terrain/TerrainShared.inc.hlsl" #include "Model/ModelShared.inc.hlsl" -// Reenable this in C++ as well struct Constants { + float4 renderInfo; // x = Render Width, y = Render Height, z = 1/Width, w = 1/Height uint4 lightInfo; // x = Num Directional Lights, y = Num Point Lights, z = Num Cascades, w = Shadows Enabled float4 fogColor; float4 fogSettings; // x = Enabled, y = Begin Fog Blend Dist, z = End Fog Blend Dist, w = UNUSED @@ -37,7 +37,7 @@ struct Constants float4 ShadeTerrain(const uint2 pixelPos, const float2 screenUV, const VisibilityBuffer vBuffer, out float3 outPixelWorldPos) { // Get the interpolated vertex data from the visibility buffer - PixelVertexData pixelVertexData = GetPixelVertexDataTerrain(pixelPos, vBuffer, 0); + PixelVertexData pixelVertexData = GetPixelVertexDataTerrain(pixelPos, vBuffer, 0, _constants.renderInfo.xy); InstanceData cellInstance = _instanceDatas[vBuffer.instanceID]; uint globalCellID = cellInstance.globalCellID; @@ -188,7 +188,7 @@ float4 ShadeTerrain(const uint2 pixelPos, const float2 screenUV, const Visibilit float4 ShadeModel(const uint2 pixelPos, const float2 screenUV, const VisibilityBuffer vBuffer, out float3 outPixelWorldPos) { // Get the interpolated vertex data from the visibility buffer - PixelVertexData pixelVertexData = GetPixelVertexDataModel(pixelPos, vBuffer, 0); + PixelVertexData pixelVertexData = GetPixelVertexDataModel(pixelPos, vBuffer, 0, _constants.renderInfo.xy); TextureData textureData = LoadModelTextureData(pixelVertexData.extraID); @@ -253,15 +253,12 @@ void main(uint3 dispatchThreadId : SV_DispatchThreadID) { uint2 pixelPos = dispatchThreadId.xy; - float2 dimensions; - _resolvedColor.GetDimensions(dimensions.x, dimensions.y); - - if (any(pixelPos > dimensions)) + if (any(pixelPos > _constants.renderInfo.xy)) { return; } - uint4 vBufferData = LoadVisibilityBuffer(pixelPos); + uint2 vBufferData = LoadVisibilityBuffer(pixelPos); const VisibilityBuffer vBuffer = UnpackVisibilityBuffer(vBufferData); #if DEBUG_ID != 0 @@ -286,13 +283,13 @@ void main(uint3 dispatchThreadId : SV_DispatchThreadID) return; #elif DEBUG_ID == 4 // CascadeID uint numCascades = _constants.lightInfo.z; - PixelVertexData pixelVertexData = GetPixelVertexData(pixelPos, vBuffer, 0); + PixelVertexData pixelVertexData = GetPixelVertexData(pixelPos, vBuffer, 0, _constants.renderInfo.xy); uint cascadeIndex = GetShadowCascadeIndexFromDepth(pixelVertexData.viewPos.z, numCascades); _resolvedColor[pixelPos] = float4(CascadeIDToColor(cascadeIndex), 1); return; #endif - float2 pixelUV = pixelPos / dimensions; + float2 pixelUV = pixelPos / _constants.renderInfo.xy; float4 color = float4(0, 0, 0, 1); @@ -316,7 +313,7 @@ void main(uint3 dispatchThreadId : SV_DispatchThreadID) } else { - color.rg = vBuffer.barycentrics.bary; + color.rg = float2(1, 1); } // Composite Transparency diff --git a/Source/Shaders/Shaders/Model/Draw.ps.hlsl b/Source/Shaders/Shaders/Model/Draw.ps.hlsl index 8f49bd5..b04a07f 100644 --- a/Source/Shaders/Shaders/Model/Draw.ps.hlsl +++ b/Source/Shaders/Shaders/Model/Draw.ps.hlsl @@ -13,7 +13,6 @@ struct PSInput float4 uv01 : TEXCOORD1; #if !SHADOW_PASS - float3 modelPosition : TEXCOORD2; uint triangleID : SV_PrimitiveID; #endif }; @@ -21,7 +20,7 @@ struct PSInput #if !SHADOW_PASS struct PSOutput { - uint4 visibilityBuffer : SV_Target0; + uint2 visibilityBuffer : SV_Target0; }; #else #define PSOutput void @@ -75,39 +74,8 @@ PSOutput main(PSInput input) } #if !SHADOW_PASS - ModelInstanceData instanceData = _modelInstanceDatas[instanceID]; - float4x4 instanceMatrix = _modelInstanceMatrices[instanceID]; - - // Get the VertexIDs of the triangle we're in - IndexedDraw draw = _modelDraws[drawCallID]; - uint3 vertexIDs = GetVertexIDs(input.triangleID, draw, _modelIndices); - - // Load the vertices - ModelVertex vertices[3]; - - [unroll] - for (uint i = 0; i < 3; i++) - { - vertices[i] = LoadModelVertex(vertexIDs[i]); - - // Load the skinned vertex position (in model-space) if this vertex was animated - if (instanceData.boneMatrixOffset != 4294967295) - { - uint localVertexID = vertexIDs[i] - instanceData.modelVertexOffset; // This gets the local vertex ID relative to the model - uint animatedVertexID = localVertexID + instanceData.animatedVertexOffset; // This makes it relative to the animated instance - - vertices[i].position = LoadAnimatedVertexPosition(animatedVertexID); - } - } - - // Calculate Barycentrics - float2 barycentrics = NBLCalculateBarycentrics(input.modelPosition, float3x3(vertices[0].position.xyz, vertices[1].position.xyz, vertices[2].position.xyz)); - - float2 ddxBarycentrics = ddx(barycentrics); - float2 ddyBarycentrics = ddy(barycentrics); - PSOutput output; - output.visibilityBuffer = PackVisibilityBuffer(ObjectType::ModelOpaque, instanceRefID, input.triangleID, barycentrics, ddxBarycentrics, ddyBarycentrics); + output.visibilityBuffer = PackVisibilityBuffer(ObjectType::ModelOpaque, instanceRefID, input.triangleID); return output; #endif diff --git a/Source/Shaders/Shaders/Model/Draw.vs.hlsl b/Source/Shaders/Shaders/Model/Draw.vs.hlsl index 431215a..0836ebc 100644 --- a/Source/Shaders/Shaders/Model/Draw.vs.hlsl +++ b/Source/Shaders/Shaders/Model/Draw.vs.hlsl @@ -27,9 +27,6 @@ struct VSOutput nointerpolation uint4 drawIDInstanceIDTextureDataIDInstanceRefID : TEXCOORD0; float4 uv01 : TEXCOORD1; #endif -#if (!EDITOR_PASS) && (!SHADOW_PASS) - float3 modelPosition : TEXCOORD2; -#endif }; VSOutput main(VSInput input) @@ -54,7 +51,6 @@ VSOutput main(VSInput input) StoreAnimatedVertexPosition(animatedVertexID, position.xyz); } - float3 modelPosition = position.xyz; float4x4 instanceMatrix = _modelInstanceMatrices[instanceID]; position = mul(position, instanceMatrix); @@ -96,9 +92,6 @@ VSOutput main(VSInput input) output.uv01 = UVs; #endif -#if (!EDITOR_PASS) && (!SHADOW_PASS) - output.modelPosition = modelPosition.xyz; -#endif return output; } \ No newline at end of file diff --git a/Source/Shaders/Shaders/PreEffectsPass.cs.hlsl b/Source/Shaders/Shaders/PreEffectsPass.cs.hlsl index 87edf55..a94a57b 100644 --- a/Source/Shaders/Shaders/PreEffectsPass.cs.hlsl +++ b/Source/Shaders/Shaders/PreEffectsPass.cs.hlsl @@ -3,6 +3,13 @@ #include "globalData.inc.hlsl" #include "Include/VisibilityBuffers.inc.hlsl" +struct Constants +{ + float4 renderInfo; // x = Render Width, y = Render Height, z = 1/Width, w = 1/Height +}; + +[[vk::push_constant]] Constants _constants; + [[vk::binding(0, PER_PASS)]] SamplerState _sampler; [[vk::binding(3, PER_PASS)]] RWTexture2D _packedNormals; @@ -11,18 +18,15 @@ void main(uint3 dispatchThreadId : SV_DispatchThreadID) { uint2 pixelPos = dispatchThreadId.xy; - float2 dimensions; - _packedNormals.GetDimensions(dimensions.x, dimensions.y); - - if (any(pixelPos > dimensions)) + if (any(pixelPos > _constants.renderInfo.xy)) { return; } - uint4 vBufferData = LoadVisibilityBuffer(pixelPos); + uint2 vBufferData = LoadVisibilityBuffer(pixelPos); const VisibilityBuffer vBuffer = UnpackVisibilityBuffer(vBufferData); - PixelVertexData pixelVertexData = GetPixelVertexData(pixelPos, vBuffer, 0); + PixelVertexData pixelVertexData = GetPixelVertexData(pixelPos, vBuffer, 0, _constants.renderInfo.xy); float3 normal = pixelVertexData.worldNormal; diff --git a/Source/Shaders/Shaders/Terrain/Draw.ps.hlsl b/Source/Shaders/Shaders/Terrain/Draw.ps.hlsl index feaf9e6..5e69557 100644 --- a/Source/Shaders/Shaders/Terrain/Draw.ps.hlsl +++ b/Source/Shaders/Shaders/Terrain/Draw.ps.hlsl @@ -10,51 +10,17 @@ struct PSInput { uint triangleID : SV_PrimitiveID; uint instanceID : TEXCOORD0; - uint culledInstanceID : TEXCOORD1; - float3 worldPosition : TEXCOORD2; }; struct PSOutput { - uint4 visibilityBuffer : SV_Target0; + uint2 visibilityBuffer : SV_Target0; }; PSOutput main(PSInput input) { PSOutput output; - const uint padding = 0; - - // Get the vertexIDs of the triangle we're in - InstanceData instanceData = _instanceDatas[input.culledInstanceID]; - - // Get the cellID and chunkID - const uint cellID = instanceData.packedChunkCellID & 0xFFFF; - const uint chunkID = instanceData.packedChunkCellID >> 16; - - uint3 localVertexIDs = GetLocalTerrainVertexIDs(input.triangleID); - - uint globalVertexOffset = instanceData.globalCellID * NUM_VERTICES_PER_CELL; - - // Load the vertices - TerrainVertex vertices[3]; - - [unroll] - for (uint i = 0; i < 3; i++) - { - vertices[i] = LoadTerrainVertex(chunkID, cellID, globalVertexOffset, localVertexIDs[i]); - - vertices[i].position = mul(float4(vertices[i].position.xyz, 1.0f), _cameras[0].worldToView).xyz; - } - - // Calculate Barycentrics - float3 viewPosition = mul(float4(input.worldPosition, 1.0f), _cameras[0].worldToView).xyz; - - float2 barycentrics = NBLCalculateBarycentrics(viewPosition, float3x3(vertices[0].position.xyz, vertices[1].position.xyz, vertices[2].position.xyz)); - - float2 ddxBarycentrics = ddx(barycentrics); - float2 ddyBarycentrics = ddy(barycentrics); - - output.visibilityBuffer = PackVisibilityBuffer(ObjectType::Terrain, input.instanceID, input.triangleID, barycentrics, ddxBarycentrics, ddyBarycentrics); + output.visibilityBuffer = PackVisibilityBuffer(ObjectType::Terrain, input.instanceID, input.triangleID); return output; } \ No newline at end of file diff --git a/Source/Shaders/Shaders/Terrain/Draw.vs.hlsl b/Source/Shaders/Shaders/Terrain/Draw.vs.hlsl index 1963a40..d95c8e1 100644 --- a/Source/Shaders/Shaders/Terrain/Draw.vs.hlsl +++ b/Source/Shaders/Shaders/Terrain/Draw.vs.hlsl @@ -24,8 +24,6 @@ struct VSOutput float4 position : SV_Position; #if !EDITOR_PASS && !SHADOW_PASS uint instanceID : TEXCOORD0; - uint culledInstanceID : TEXCOORD1; - float3 worldPosition : TEXCOORD2; #endif }; @@ -53,8 +51,6 @@ VSOutput main(VSInput input) #if !EDITOR_PASS && !SHADOW_PASS output.instanceID = instanceData.globalCellID; - output.culledInstanceID = input.culledInstanceID; - output.worldPosition = vertex.position; #endif return output; diff --git a/Source/Shaders/Shaders/Utils/ObjectQuery.cs.hlsl b/Source/Shaders/Shaders/Utils/ObjectQuery.cs.hlsl index 4ea7db9..dee3837 100644 --- a/Source/Shaders/Shaders/Utils/ObjectQuery.cs.hlsl +++ b/Source/Shaders/Shaders/Utils/ObjectQuery.cs.hlsl @@ -27,7 +27,7 @@ void main(uint3 dispatchThreadId : SV_DispatchThreadID) { uint2 pixelPos = _constants.requests[i]; - uint4 vBufferData = LoadVisibilityBuffer(pixelPos); + uint2 vBufferData = LoadVisibilityBuffer(pixelPos); VisibilityBuffer vBuffer = UnpackVisibilityBuffer(vBufferData); _result[i].type = vBuffer.typeID;