WIP
This commit is contained in:
committed by
Jérôme Leclercq
parent
4a10c1f8fe
commit
e990a320cc
@@ -8,7 +8,6 @@
|
||||
#include <Nazara/Graphics/ElementRendererRegistry.hpp>
|
||||
#include <Nazara/Graphics/FrameGraph.hpp>
|
||||
#include <Nazara/Graphics/FramePipeline.hpp>
|
||||
#include <Nazara/Graphics/Graphics.hpp>
|
||||
#include <Nazara/Graphics/InstancedRenderable.hpp>
|
||||
#include <Nazara/Graphics/Material.hpp>
|
||||
#include <Nazara/Renderer/RenderFrame.hpp>
|
||||
@@ -16,15 +15,16 @@
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
DepthPipelinePass::DepthPipelinePass(FramePipeline& owner, ElementRendererRegistry& elementRegistry, AbstractViewer* viewer) :
|
||||
DepthPipelinePass::DepthPipelinePass(FramePipeline& owner, ElementRendererRegistry& elementRegistry, AbstractViewer* viewer, std::size_t passIndex, std::string passName) :
|
||||
m_passIndex(passIndex),
|
||||
m_lastVisibilityHash(0),
|
||||
m_passName(std::move(passName)),
|
||||
m_viewer(viewer),
|
||||
m_elementRegistry(elementRegistry),
|
||||
m_pipeline(owner),
|
||||
m_rebuildCommandBuffer(false),
|
||||
m_rebuildElements(false)
|
||||
{
|
||||
m_depthPassIndex = Graphics::Instance()->GetMaterialPassRegistry().GetPassIndex("DepthPass");
|
||||
}
|
||||
|
||||
void DepthPipelinePass::Prepare(RenderFrame& renderFrame, const Frustumf& frustum, const std::vector<FramePipelinePass::VisibleRenderable>& visibleRenderables, std::size_t visibilityHash)
|
||||
@@ -42,7 +42,7 @@ namespace Nz
|
||||
renderableData.worldInstance
|
||||
};
|
||||
|
||||
renderableData.instancedRenderable->BuildElement(m_elementRegistry, elementData, m_depthPassIndex, m_renderElements);
|
||||
renderableData.instancedRenderable->BuildElement(m_elementRegistry, elementData, m_passIndex, m_renderElements);
|
||||
}
|
||||
|
||||
m_renderQueueRegistry.Clear();
|
||||
@@ -105,7 +105,7 @@ namespace Nz
|
||||
|
||||
void DepthPipelinePass::RegisterMaterialInstance(const MaterialInstance& materialInstance)
|
||||
{
|
||||
if (!materialInstance.HasPass(m_depthPassIndex))
|
||||
if (!materialInstance.HasPass(m_passIndex))
|
||||
return;
|
||||
|
||||
auto it = m_materialInstances.find(&materialInstance);
|
||||
@@ -114,7 +114,7 @@ namespace Nz
|
||||
auto& matPassEntry = m_materialInstances[&materialInstance];
|
||||
matPassEntry.onMaterialInstancePipelineInvalidated.Connect(materialInstance.OnMaterialInstancePipelineInvalidated, [=](const MaterialInstance*, std::size_t passIndex)
|
||||
{
|
||||
if (passIndex != m_depthPassIndex)
|
||||
if (passIndex != m_passIndex)
|
||||
return;
|
||||
|
||||
m_rebuildElements = true;
|
||||
@@ -131,7 +131,7 @@ namespace Nz
|
||||
|
||||
FramePass& DepthPipelinePass::RegisterToFrameGraph(FrameGraph& frameGraph, std::size_t depthBufferIndex)
|
||||
{
|
||||
FramePass& depthPrepass = frameGraph.AddPass("Depth pre-pass");
|
||||
FramePass& depthPrepass = frameGraph.AddPass(m_passName);
|
||||
depthPrepass.SetDepthStencilOutput(depthBufferIndex);
|
||||
depthPrepass.SetDepthStencilClear(1.f, 0);
|
||||
|
||||
|
||||
@@ -177,11 +177,13 @@ namespace Nz
|
||||
|
||||
std::size_t ForwardFramePipeline::RegisterViewer(AbstractViewer* viewerInstance, Int32 renderOrder)
|
||||
{
|
||||
std::size_t depthPassIndex = Graphics::Instance()->GetMaterialPassRegistry().GetPassIndex("DepthPass");
|
||||
|
||||
std::size_t viewerIndex;
|
||||
auto& viewerData = *m_viewerPool.Allocate(viewerIndex);
|
||||
viewerData.renderOrder = renderOrder;
|
||||
viewerData.debugDrawPass = std::make_unique<DebugDrawPipelinePass>(*this, viewerInstance);
|
||||
viewerData.depthPrepass = std::make_unique<DepthPipelinePass>(*this, m_elementRegistry, viewerInstance);
|
||||
viewerData.depthPrepass = std::make_unique<DepthPipelinePass>(*this, m_elementRegistry, viewerInstance, depthPassIndex, "Depth pre-pass");
|
||||
viewerData.forwardPass = std::make_unique<ForwardPipelinePass>(*this, m_elementRegistry, viewerInstance);
|
||||
viewerData.viewer = viewerInstance;
|
||||
viewerData.onTransferRequired.Connect(viewerInstance->GetViewerInstance().OnTransferRequired, [this](TransferInterface* transferInterface)
|
||||
@@ -211,6 +213,20 @@ namespace Nz
|
||||
return worldInstanceIndex;
|
||||
}
|
||||
|
||||
const Light* ForwardFramePipeline::RetrieveLight(std::size_t lightIndex) const
|
||||
{
|
||||
return m_lightPool.RetrieveFromIndex(lightIndex)->light.get();
|
||||
}
|
||||
|
||||
const Texture* ForwardFramePipeline::RetrieveLightShadowmap(std::size_t lightIndex) const
|
||||
{
|
||||
if (!m_shadowCastingLights.UnboundedTest(lightIndex))
|
||||
return nullptr;
|
||||
|
||||
std::size_t shadowmapIndex = m_lightPool.RetrieveFromIndex(lightIndex)->shadowMapAttachmentIndex;
|
||||
return m_bakedFrameGraph.GetAttachmentTexture(shadowmapIndex).get();
|
||||
}
|
||||
|
||||
void ForwardFramePipeline::Render(RenderFrame& renderFrame)
|
||||
{
|
||||
m_currentRenderFrame = &renderFrame;
|
||||
@@ -355,13 +371,17 @@ namespace Nz
|
||||
|
||||
m_visibleLights.clear();
|
||||
for (const LightData& lightData : m_lightPool)
|
||||
for (auto it = m_lightPool.begin(); it != m_lightPool.end(); ++it)
|
||||
{
|
||||
const LightData& lightData = *it;
|
||||
std::size_t lightIndex = it.GetIndex();
|
||||
|
||||
const BoundingVolumef& boundingVolume = lightData.light->GetBoundingVolume();
|
||||
|
||||
// TODO: Use more precise tests for point lights (frustum/sphere is cheap)
|
||||
if (renderMask & lightData.renderMask && frustum.Contains(boundingVolume))
|
||||
{
|
||||
m_visibleLights.push_back(lightData.light.get());
|
||||
m_visibleLights.push_back(lightIndex);
|
||||
visibilityHash = CombineHash(visibilityHash, std::hash<const void*>()(lightData.light.get()));
|
||||
}
|
||||
}
|
||||
@@ -575,7 +595,7 @@ namespace Nz
|
||||
m_transferSet.insert(transferInterface);
|
||||
});
|
||||
|
||||
lightData->camera->UpdateFOV(spotLight.GetOuterAngle());
|
||||
lightData->camera->UpdateFOV(spotLight.GetOuterAngle() * 2.f);
|
||||
lightData->camera->UpdateZFar(spotLight.GetRadius());
|
||||
lightData->camera->UpdateViewport(Recti(0, 0, SafeCast<int>(shadowMapSize), SafeCast<int>(shadowMapSize)));
|
||||
|
||||
@@ -584,13 +604,15 @@ namespace Nz
|
||||
|
||||
if (!lightData->pass)
|
||||
{
|
||||
lightData->pass = std::make_unique<DepthPipelinePass>(*this, m_elementRegistry, lightData->camera.get());
|
||||
std::size_t shadowPassIndex = Graphics::Instance()->GetMaterialPassRegistry().GetPassIndex("ShadowPass");
|
||||
|
||||
lightData->pass = std::make_unique<DepthPipelinePass>(*this, m_elementRegistry, lightData->camera.get(), shadowPassIndex, "Spot shadowmap");
|
||||
for (RenderableData& renderable : m_renderablePool)
|
||||
{
|
||||
std::size_t matCount = renderable.renderable->GetMaterialCount();
|
||||
for (std::size_t i = 0; i < matCount; ++i)
|
||||
for (std::size_t j = 0; j < matCount; ++j)
|
||||
{
|
||||
if (MaterialInstance* mat = renderable.renderable->GetMaterial(i).get())
|
||||
if (MaterialInstance* mat = renderable.renderable->GetMaterial(j).get())
|
||||
lightData->pass->RegisterMaterialInstance(*mat);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace Nz
|
||||
m_lightUboPool = std::make_shared<LightUboPool>();
|
||||
}
|
||||
|
||||
void ForwardPipelinePass::Prepare(RenderFrame& renderFrame, const Frustumf& frustum, const std::vector<FramePipelinePass::VisibleRenderable>& visibleRenderables, const std::vector<const Light*>& visibleLights, std::size_t visibilityHash)
|
||||
void ForwardPipelinePass::Prepare(RenderFrame& renderFrame, const Frustumf& frustum, const std::vector<FramePipelinePass::VisibleRenderable>& visibleRenderables, const std::vector<std::size_t>& visibleLights, std::size_t visibilityHash)
|
||||
{
|
||||
if (m_lastVisibilityHash != visibilityHash || m_rebuildElements) //< FIXME
|
||||
{
|
||||
@@ -65,17 +65,22 @@ namespace Nz
|
||||
|
||||
// Select lights
|
||||
m_renderableLights.clear();
|
||||
for (const Light* light : visibleLights)
|
||||
for (std::size_t lightIndex : visibleLights)
|
||||
{
|
||||
const Light* light = m_pipeline.RetrieveLight(lightIndex);
|
||||
|
||||
const BoundingVolumef& boundingVolume = light->GetBoundingVolume();
|
||||
if (boundingVolume.Intersect(renderableBoundingVolume.aabb))
|
||||
m_renderableLights.push_back(light);
|
||||
{
|
||||
float contributionScore = light->ComputeContributionScore(renderableBoundingVolume);
|
||||
m_renderableLights.push_back({ light, lightIndex, contributionScore });
|
||||
}
|
||||
}
|
||||
|
||||
// Sort lights
|
||||
std::sort(m_renderableLights.begin(), m_renderableLights.end(), [&](const Light* lhs, const Light* rhs)
|
||||
std::sort(m_renderableLights.begin(), m_renderableLights.end(), [&](const RenderableLight& lhs, const RenderableLight& rhs)
|
||||
{
|
||||
return lhs->ComputeContributionScore(renderableBoundingVolume) < rhs->ComputeContributionScore(renderableBoundingVolume);
|
||||
return lhs.contributionScore < rhs.contributionScore;
|
||||
});
|
||||
|
||||
std::size_t lightCount = std::min(m_renderableLights.size(), MaxLightCountPerDraw);
|
||||
@@ -83,7 +88,7 @@ namespace Nz
|
||||
LightKey lightKey;
|
||||
lightKey.fill(nullptr);
|
||||
for (std::size_t i = 0; i < lightCount; ++i)
|
||||
lightKey[i] = m_renderableLights[i];
|
||||
lightKey[i] = m_renderableLights[i].light;
|
||||
|
||||
RenderBufferView lightUboView;
|
||||
|
||||
@@ -130,7 +135,7 @@ namespace Nz
|
||||
UInt8* lightPtr = static_cast<UInt8*>(lightDataPtr) + lightOffsets.lightsOffset;
|
||||
for (std::size_t i = 0; i < lightCount; ++i)
|
||||
{
|
||||
m_renderableLights[i]->FillLightData(lightPtr);
|
||||
m_renderableLights[i].light->FillLightData(lightPtr);
|
||||
lightPtr += lightOffsets.lightSize;
|
||||
}
|
||||
|
||||
@@ -155,7 +160,15 @@ namespace Nz
|
||||
for (std::size_t i = previousCount; i < m_renderElements.size(); ++i)
|
||||
{
|
||||
const RenderElement* element = m_renderElements[i].GetElement();
|
||||
m_lightPerRenderElement.emplace(element, lightUboView);
|
||||
|
||||
LightPerElementData perElementData;
|
||||
perElementData.lightCount = lightCount;
|
||||
perElementData.lightUniformBuffer = lightUboView;
|
||||
|
||||
for (std::size_t i = 0; i < lightCount; ++i)
|
||||
perElementData.shadowMaps[i] = m_pipeline.RetrieveLightShadowmap(m_renderableLights[i].lightIndex);
|
||||
|
||||
m_lightPerRenderElement.emplace(element, perElementData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,8 +235,25 @@ namespace Nz
|
||||
auto it = lightPerRenderElement.find(elements[i]);
|
||||
assert(it != lightPerRenderElement.end());
|
||||
|
||||
const LightPerElementData& lightData = it->second;
|
||||
|
||||
auto& renderStates = m_renderStates.emplace_back();
|
||||
renderStates.lightData = it->second;
|
||||
renderStates.lightData = lightData.lightUniformBuffer;
|
||||
|
||||
for (std::size_t i = 0; i < lightData.lightCount; ++i)
|
||||
{
|
||||
const Texture* texture = lightData.shadowMaps[i];
|
||||
if (!texture)
|
||||
continue;
|
||||
|
||||
if (texture->GetType() == ImageType::E2D)
|
||||
renderStates.shadowMaps2D[i] = texture;
|
||||
else
|
||||
{
|
||||
assert(texture->GetType() == ImageType::Cubemap);
|
||||
renderStates.shadowMapsCube[i] = texture;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
elementRenderer.Prepare(viewerInstance, *m_elementRendererData[elementType], renderFrame, elementCount, elements, m_renderStates.data());
|
||||
|
||||
@@ -218,7 +218,7 @@ namespace Nz
|
||||
{
|
||||
if (auto it = m_pending.attachmentToTextures.find(depthStencilOutput); it == m_pending.attachmentToTextures.end())
|
||||
{
|
||||
// Special case where multiples attachements point simultaneously to the same texture
|
||||
// Special case where multiples attachments point simultaneously to the same texture
|
||||
m_pending.attachmentToTextures.emplace(depthStencilOutput, textureId);
|
||||
|
||||
auto inputIt = m_pending.attachmentLastUse.find(depthStencilInput);
|
||||
|
||||
@@ -173,7 +173,7 @@ namespace Nz
|
||||
RenderPipelineLayoutInfo layoutInfo;
|
||||
layoutInfo.bindings.assign({
|
||||
{
|
||||
0, 0,
|
||||
1, 0, 0,
|
||||
ShaderBindingType::Texture,
|
||||
nzsl::ShaderStageType::Fragment
|
||||
}
|
||||
@@ -230,7 +230,10 @@ namespace Nz
|
||||
MaterialPass depthPass = forwardPass;
|
||||
depthPass.options[CRC32("DepthPass")] = true;
|
||||
settings.AddPass(depthPassIndex, depthPass);
|
||||
settings.AddPass(shadowPassIndex, depthPass);
|
||||
|
||||
MaterialPass shadowPass = depthPass;
|
||||
shadowPass.states.faceCulling = FaceCulling::Front;
|
||||
settings.AddPass(shadowPassIndex, shadowPass);
|
||||
|
||||
m_defaultMaterials.basicMaterial = std::make_shared<Material>(std::move(settings), "BasicMaterial");
|
||||
}
|
||||
@@ -249,7 +252,10 @@ namespace Nz
|
||||
MaterialPass depthPass = forwardPass;
|
||||
depthPass.options[CRC32("DepthPass")] = true;
|
||||
settings.AddPass(depthPassIndex, depthPass);
|
||||
settings.AddPass(shadowPassIndex, depthPass);
|
||||
|
||||
MaterialPass shadowPass = depthPass;
|
||||
shadowPass.states.faceCulling = FaceCulling::Front;
|
||||
settings.AddPass(shadowPassIndex, shadowPass);
|
||||
|
||||
m_defaultMaterials.pbrMaterial = std::make_shared<Material>(std::move(settings), "PhysicallyBasedMaterial");
|
||||
}
|
||||
@@ -268,7 +274,13 @@ namespace Nz
|
||||
MaterialPass depthPass = forwardPass;
|
||||
depthPass.options[CRC32("DepthPass")] = true;
|
||||
settings.AddPass(depthPassIndex, depthPass);
|
||||
settings.AddPass(shadowPassIndex, depthPass);
|
||||
|
||||
MaterialPass shadowPass = depthPass;
|
||||
shadowPass.states.faceCulling = FaceCulling::Front;
|
||||
shadowPass.states.depthBias = true;
|
||||
shadowPass.states.depthBiasConstantFactor = 0.005f;
|
||||
shadowPass.states.depthBiasSlopeFactor = 0.05f;
|
||||
settings.AddPass(shadowPassIndex, shadowPass);
|
||||
|
||||
m_defaultMaterials.phongMaterial = std::make_shared<Material>(std::move(settings), "PhongMaterial");
|
||||
}
|
||||
@@ -301,6 +313,38 @@ namespace Nz
|
||||
|
||||
void Graphics::BuildDefaultTextures()
|
||||
{
|
||||
// Depth textures (white but with a depth format)
|
||||
{
|
||||
PixelFormat depthFormat = PixelFormat::Undefined;
|
||||
for (PixelFormat depthStencilCandidate : { PixelFormat::Depth16, PixelFormat::Depth24, PixelFormat::Depth32F })
|
||||
{
|
||||
if (m_renderDevice->IsTextureFormatSupported(depthStencilCandidate, TextureUsage::ShaderSampling))
|
||||
{
|
||||
depthFormat = depthStencilCandidate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (depthFormat == PixelFormat::Undefined)
|
||||
throw std::runtime_error("couldn't find a sampling-compatible depth pixel format");
|
||||
|
||||
TextureInfo texInfo;
|
||||
texInfo.width = texInfo.height = texInfo.depth = texInfo.mipmapLevel = 1;
|
||||
texInfo.pixelFormat = depthFormat;
|
||||
|
||||
std::array<UInt8, 6> whitePixels = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
|
||||
for (std::size_t i = 0; i < ImageTypeCount; ++i)
|
||||
{
|
||||
texInfo.type = static_cast<ImageType>(i);
|
||||
if (texInfo.type == ImageType::E3D)
|
||||
continue;
|
||||
|
||||
m_defaultTextures.depthTextures[i] = m_renderDevice->InstantiateTexture(texInfo);
|
||||
m_defaultTextures.depthTextures[i]->Update(whitePixels.data());
|
||||
}
|
||||
}
|
||||
|
||||
// White texture 2D
|
||||
{
|
||||
TextureInfo texInfo;
|
||||
|
||||
@@ -94,6 +94,12 @@ namespace Nz
|
||||
if (auto it = block->uniformBlocks.find("ViewerData"); it != block->uniformBlocks.end())
|
||||
m_engineShaderBindings[UnderlyingCast(EngineShaderBinding::ViewerDataUbo)] = it->second.bindingIndex;
|
||||
|
||||
if (auto it = block->samplers.find("ShadowMaps2D"); it != block->samplers.end())
|
||||
m_engineShaderBindings[UnderlyingCast(EngineShaderBinding::Shadowmap2D)] = it->second.bindingIndex;
|
||||
|
||||
if (auto it = block->samplers.find("ShadowMapsCube"); it != block->samplers.end())
|
||||
m_engineShaderBindings[UnderlyingCast(EngineShaderBinding::ShadowmapCube)] = it->second.bindingIndex;
|
||||
|
||||
if (auto it = block->uniformBlocks.find("SkeletalData"); it != block->uniformBlocks.end())
|
||||
m_engineShaderBindings[UnderlyingCast(EngineShaderBinding::SkeletalDataUbo)] = it->second.bindingIndex;
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ namespace Nz
|
||||
lightData.lightMemberOffsets.parameter2 = lightStruct.AddField(nzsl::StructFieldType::Float4);
|
||||
lightData.lightMemberOffsets.parameter3 = lightStruct.AddField(nzsl::StructFieldType::Float4);
|
||||
lightData.lightMemberOffsets.shadowMappingFlag = lightStruct.AddField(nzsl::StructFieldType::Bool1);
|
||||
lightData.lightMemberOffsets.viewProjMatrix = lightStruct.AddMatrix(nzsl::StructFieldType::Float1, 4, 4, true);
|
||||
|
||||
lightData.lightSize = lightStruct.GetAlignedSize();
|
||||
|
||||
|
||||
@@ -15,8 +15,8 @@ struct VertOut
|
||||
}
|
||||
|
||||
const vertPos = array[vec2[f32]](
|
||||
vec2[f32](-1.0, 1.0),
|
||||
vec2[f32](-1.0, -3.0),
|
||||
vec2[f32](-1.0, 1.0),
|
||||
vec2[f32]( 3.0, 1.0)
|
||||
);
|
||||
|
||||
|
||||
@@ -13,7 +13,8 @@ struct Light
|
||||
parameter1: vec4[f32],
|
||||
parameter2: vec4[f32],
|
||||
parameter3: vec4[f32],
|
||||
hasShadowMapping: u32
|
||||
hasShadowMapping: u32,
|
||||
viewProjMatrix: mat4[f32]
|
||||
}
|
||||
|
||||
[export]
|
||||
|
||||
@@ -47,6 +47,7 @@ const HasTangent = (VertexTangentLoc >= 0);
|
||||
const HasUV = (VertexUvLoc >= 0);
|
||||
const HasNormalMapping = HasNormalTexture && HasNormal && HasTangent && !DepthPass;
|
||||
const HasSkinning = (VertexJointIndicesLoc >= 0 && VertexJointWeightsLoc >= 0);
|
||||
const HasLighting = HasNormal && !DepthPass;
|
||||
|
||||
[layout(std140)]
|
||||
struct MaterialSettings
|
||||
@@ -96,8 +97,8 @@ external
|
||||
[tag("ViewerData")] viewerData: uniform[ViewerData],
|
||||
[tag("SkeletalData")] skeletalData: uniform[SkeletalData],
|
||||
[tag("LightData")] lightData: uniform[LightData],
|
||||
[tag("ShadowMaps2D")] shadowMaps2D: array[sampler2D[f32], MaxLightCount],
|
||||
[tag("ShadowMapsCube")] shadowMapsCube: array[samplerCube[f32], MaxLightCount]
|
||||
[tag("ShadowMaps2D")] shadowMaps2D: array[depth_sampler2D[f32], MaxLightCount],
|
||||
[tag("ShadowMapsCube")] shadowMapsCube: array[depth_sampler_cube[f32], MaxLightCount]
|
||||
}
|
||||
|
||||
struct VertToFrag
|
||||
@@ -107,6 +108,7 @@ struct VertToFrag
|
||||
[location(2), cond(HasColor)] color: vec4[f32],
|
||||
[location(3), cond(HasNormal)] normal: vec3[f32],
|
||||
[location(4), cond(HasNormalMapping)] tangent: vec3[f32],
|
||||
[location(5), cond(HasLighting)] lightProjPos: array[vec4[f32], MaxLightCount],
|
||||
[builtin(position)] position: vec4[f32],
|
||||
}
|
||||
|
||||
@@ -139,7 +141,7 @@ fn main(input: VertToFrag) -> FragOut
|
||||
discard;
|
||||
}
|
||||
|
||||
const if (HasNormal && !DepthPass)
|
||||
const if (HasLighting)
|
||||
{
|
||||
let lightAmbient = vec3[f32](0.0, 0.0, 0.0);
|
||||
let lightDiffuse = vec3[f32](0.0, 0.0, 0.0);
|
||||
@@ -225,17 +227,41 @@ fn main(input: VertToFrag) -> FragOut
|
||||
let attenuationFactor = max(1.0 - dist * lightInvRadius, 0.0);
|
||||
attenuationFactor *= max((curAngle - lightOuterAngle) / innerMinusOuterAngle, 0.0);
|
||||
|
||||
lightAmbient += attenuationFactor * light.color.rgb * lightAmbientFactor * settings.AmbientColor.rgb;
|
||||
|
||||
let lambert = max(dot(normal, -lightToPosNorm), 0.0);
|
||||
|
||||
lightDiffuse += attenuationFactor * lambert * light.color.rgb * lightDiffuseFactor;
|
||||
|
||||
let reflection = reflect(lightToPosNorm, normal);
|
||||
let specFactor = max(dot(reflection, eyeVec), 0.0);
|
||||
specFactor = pow(specFactor, settings.Shininess);
|
||||
|
||||
lightSpecular += attenuationFactor * specFactor * light.color.rgb;
|
||||
let shadowFactor = 0.0;
|
||||
if (true) //< TODO: HasShadowMapping
|
||||
{
|
||||
let shadowTexSize = 1.0 / 512.0; //< FIXME
|
||||
|
||||
let offsetArray = array[vec2[f32], 9](
|
||||
vec2[f32](-1.0, -1.0),
|
||||
vec2[f32](-1.0, 0.0),
|
||||
vec2[f32](-1.0, 1.0),
|
||||
vec2[f32](0.0, -1.0),
|
||||
vec2[f32](0.0, 0.0),
|
||||
vec2[f32](0.0, 1.0),
|
||||
vec2[f32](1.0, -1.0),
|
||||
vec2[f32](1.0, 0.0),
|
||||
vec2[f32](1.0, 1.0)
|
||||
);
|
||||
|
||||
for offset in offsetArray
|
||||
{
|
||||
let shadowCoords = input.lightProjPos[i].xyz / input.lightProjPos[i].w;
|
||||
shadowCoords.xy += offset * shadowTexSize;
|
||||
shadowFactor += shadowMaps2D[i].SampleDepthComp(shadowCoords.xy, shadowCoords.z).r;
|
||||
}
|
||||
shadowFactor /= 9.0;
|
||||
}
|
||||
|
||||
lightAmbient += attenuationFactor * light.color.rgb * lightAmbientFactor * settings.AmbientColor.rgb;
|
||||
lightDiffuse += shadowFactor * attenuationFactor * lambert * light.color.rgb * lightDiffuseFactor;
|
||||
lightSpecular += shadowFactor * attenuationFactor * specFactor * light.color.rgb;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -382,5 +408,11 @@ fn main(input: VertIn) -> VertToFrag
|
||||
const if (HasNormalMapping)
|
||||
output.tangent = rotationMatrix * input.tangent;
|
||||
|
||||
const if (HasLighting)
|
||||
{
|
||||
for i in u32(0) -> lightData.lightCount
|
||||
output.lightProjPos[i] = lightData.lights[i].viewProjMatrix * worldPosition;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
@@ -73,16 +73,14 @@ namespace Nz
|
||||
else
|
||||
throw std::runtime_error("unexpected type " + ToString(varType));
|
||||
|
||||
for (UInt32 i = 0; i < arraySize; ++i)
|
||||
{
|
||||
// TODO: Get more precise shader stage type
|
||||
m_pipelineLayoutInfo.bindings.push_back({
|
||||
bindingSet, // setIndex
|
||||
bindingIndex + i, // bindingIndex
|
||||
bindingType, // type
|
||||
nzsl::ShaderStageType_All // shaderStageFlags
|
||||
});
|
||||
}
|
||||
// TODO: Get more precise shader stage type
|
||||
m_pipelineLayoutInfo.bindings.push_back({
|
||||
arraySize, // arraySize
|
||||
bindingIndex, // bindingIndex
|
||||
bindingSet, // setIndex
|
||||
bindingType, // type
|
||||
nzsl::ShaderStageType_All // shaderStageFlags
|
||||
});
|
||||
|
||||
if (!externalVar.tag.empty() && externalBlock)
|
||||
{
|
||||
|
||||
@@ -30,6 +30,7 @@ namespace Nz
|
||||
AccessByOffset<Vector4f&>(data, lightOffset.lightMemberOffsets.parameter2) = Vector4f(m_direction.x, m_direction.y, m_direction.z, 0.f);
|
||||
AccessByOffset<Vector4f&>(data, lightOffset.lightMemberOffsets.parameter3) = Vector4f(m_innerAngleCos, m_outerAngleCos, 0.f, 0.f);
|
||||
AccessByOffset<UInt8&>(data, lightOffset.lightMemberOffsets.shadowMappingFlag) = 0;
|
||||
AccessByOffset<Matrix4f&>(data, lightOffset.lightMemberOffsets.viewProjMatrix) = m_viewProjMatrix;
|
||||
}
|
||||
|
||||
void SpotLight::UpdateTransform(const Vector3f& position, const Quaternionf& rotation, const Vector3f& /*scale*/)
|
||||
|
||||
@@ -54,9 +54,16 @@ namespace Nz
|
||||
currentShaderBinding = nullptr;
|
||||
};
|
||||
|
||||
const auto& whiteTexture = Graphics::Instance()->GetDefaultTextures().whiteTextures[UnderlyingCast(ImageType::E2D)];
|
||||
const auto& depthTexture2D = Graphics::Instance()->GetDefaultTextures().depthTextures[UnderlyingCast(ImageType::E2D)];
|
||||
const auto& depthTextureCube = Graphics::Instance()->GetDefaultTextures().depthTextures[UnderlyingCast(ImageType::Cubemap)];
|
||||
const auto& whiteTexture2D = Graphics::Instance()->GetDefaultTextures().whiteTextures[UnderlyingCast(ImageType::E2D)];
|
||||
const auto& whiteTextureCube = Graphics::Instance()->GetDefaultTextures().whiteTextures[UnderlyingCast(ImageType::Cubemap)];
|
||||
const auto& defaultSampler = graphics->GetSamplerCache().Get({});
|
||||
|
||||
TextureSamplerInfo samplerInfo;
|
||||
samplerInfo.depthCompare = true;
|
||||
const auto& shadowSampler = graphics->GetSamplerCache().Get(samplerInfo);
|
||||
|
||||
std::size_t oldDrawCallCount = data.drawCalls.size();
|
||||
|
||||
for (std::size_t i = 0; i < elementCount; ++i)
|
||||
@@ -122,6 +129,8 @@ namespace Nz
|
||||
assert(currentMaterialInstance);
|
||||
|
||||
m_bindingCache.clear();
|
||||
m_textureBindingCache.clear();
|
||||
m_textureBindingCache.reserve(renderState.shadowMaps2D.size() + renderState.shadowMapsCube.size());
|
||||
currentMaterialInstance->FillShaderBinding(m_bindingCache);
|
||||
|
||||
const Material& material = *currentMaterialInstance->GetParentMaterial();
|
||||
@@ -150,6 +159,50 @@ namespace Nz
|
||||
};
|
||||
}
|
||||
|
||||
if (UInt32 bindingIndex = material.GetEngineBindingIndex(EngineShaderBinding::Shadowmap2D); bindingIndex != Material::InvalidBindingIndex)
|
||||
{
|
||||
std::size_t textureBindingBaseIndex = m_textureBindingCache.size();
|
||||
|
||||
for (std::size_t j = 0; j < renderState.shadowMaps2D.size(); ++j)
|
||||
{
|
||||
const Texture* texture = renderState.shadowMaps2D[j];
|
||||
if (!texture)
|
||||
texture = depthTexture2D.get();
|
||||
|
||||
auto& textureEntry = m_textureBindingCache.emplace_back();
|
||||
textureEntry.texture = texture;
|
||||
textureEntry.sampler = shadowSampler.get();
|
||||
}
|
||||
|
||||
auto& bindingEntry = m_bindingCache.emplace_back();
|
||||
bindingEntry.bindingIndex = bindingIndex;
|
||||
bindingEntry.content = ShaderBinding::TextureBindings {
|
||||
SafeCast<UInt32>(renderState.shadowMaps2D.size()), &m_textureBindingCache[textureBindingBaseIndex]
|
||||
};
|
||||
}
|
||||
|
||||
if (UInt32 bindingIndex = material.GetEngineBindingIndex(EngineShaderBinding::ShadowmapCube); bindingIndex != Material::InvalidBindingIndex)
|
||||
{
|
||||
std::size_t textureBindingBaseIndex = m_textureBindingCache.size();
|
||||
|
||||
for (std::size_t j = 0; j < renderState.shadowMapsCube.size(); ++j)
|
||||
{
|
||||
const Texture* texture = renderState.shadowMapsCube[j];
|
||||
if (!texture)
|
||||
texture = depthTextureCube.get();
|
||||
|
||||
auto& textureEntry = m_textureBindingCache.emplace_back();
|
||||
textureEntry.texture = texture;
|
||||
textureEntry.sampler = shadowSampler.get();
|
||||
}
|
||||
|
||||
auto& bindingEntry = m_bindingCache.emplace_back();
|
||||
bindingEntry.bindingIndex = bindingIndex;
|
||||
bindingEntry.content = ShaderBinding::TextureBindings {
|
||||
SafeCast<UInt32>(renderState.shadowMaps2D.size()), &m_textureBindingCache[textureBindingBaseIndex]
|
||||
};
|
||||
}
|
||||
|
||||
if (UInt32 bindingIndex = material.GetEngineBindingIndex(EngineShaderBinding::SkeletalDataUbo); bindingIndex != Material::InvalidBindingIndex && currentSkeletonInstance)
|
||||
{
|
||||
const auto& skeletalBuffer = currentSkeletonInstance->GetSkeletalBuffer();
|
||||
@@ -179,7 +232,7 @@ namespace Nz
|
||||
auto& bindingEntry = m_bindingCache.emplace_back();
|
||||
bindingEntry.bindingIndex = bindingIndex;
|
||||
bindingEntry.content = ShaderBinding::TextureBinding{
|
||||
whiteTexture.get(), defaultSampler.get()
|
||||
whiteTexture2D.get(), defaultSampler.get()
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -21,10 +21,14 @@ namespace Nz
|
||||
unsigned int bindingIndex = 0;
|
||||
for (const auto& binding : m_layoutInfo.bindings)
|
||||
{
|
||||
UInt64 bindingKey = UInt64(binding.setIndex) << 32 | UInt64(binding.bindingIndex);
|
||||
for (UInt32 i = 0; i < binding.arraySize; ++i)
|
||||
{
|
||||
UInt64 bindingKey = UInt64(binding.setIndex) << 32 | UInt64(binding.bindingIndex + i);
|
||||
|
||||
m_bindingMapping[bindingKey] = bindingIndex++;
|
||||
m_maxDescriptorCount = std::max<std::size_t>(m_maxDescriptorCount, binding.bindingIndex + 1);
|
||||
m_bindingMapping[bindingKey] = bindingIndex++;
|
||||
}
|
||||
|
||||
m_maxDescriptorCount = std::max<std::size_t>(m_maxDescriptorCount, binding.bindingIndex + binding.arraySize);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,18 @@ namespace Nz
|
||||
{
|
||||
using DescriptorType = std::decay_t<decltype(descriptor)>;
|
||||
|
||||
auto bindingIt = std::find_if(layoutInfo.bindings.begin(), layoutInfo.bindings.end(), [&](const auto& binding) { return binding.setIndex == setIndex && binding.bindingIndex == bindingIndex; });
|
||||
auto bindingIt = std::find_if(layoutInfo.bindings.begin(), layoutInfo.bindings.end(), [&](const auto& binding)
|
||||
{
|
||||
if (binding.setIndex != setIndex)
|
||||
return false;
|
||||
|
||||
assert(binding.arraySize > 0);
|
||||
if (bindingIndex < binding.bindingIndex || bindingIndex >= binding.bindingIndex + binding.arraySize)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
if (bindingIt == layoutInfo.bindings.end())
|
||||
throw std::runtime_error("invalid binding index");
|
||||
|
||||
@@ -88,26 +99,11 @@ namespace Nz
|
||||
storageDescriptor.buffer = 0;
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, TextureBinding>)
|
||||
HandleTextureBinding(binding.bindingIndex, arg);
|
||||
else if constexpr (std::is_same_v<T, TextureBindings>)
|
||||
{
|
||||
auto& textureDescriptor = m_owner.GetTextureDescriptor(m_poolIndex, m_bindingIndex, binding.bindingIndex);
|
||||
|
||||
if (const OpenGLTexture* glTexture = static_cast<const OpenGLTexture*>(arg.texture))
|
||||
{
|
||||
textureDescriptor.texture = glTexture->GetTexture().GetObjectId();
|
||||
|
||||
if (const OpenGLTextureSampler* glSampler = static_cast<const OpenGLTextureSampler*>(arg.sampler))
|
||||
textureDescriptor.sampler = glSampler->GetSampler(glTexture->GetLevelCount() > 1).GetObjectId();
|
||||
else
|
||||
textureDescriptor.sampler = 0;
|
||||
|
||||
textureDescriptor.textureTarget = OpenGLTexture::ToTextureTarget(glTexture->GetType());
|
||||
}
|
||||
else
|
||||
{
|
||||
textureDescriptor.sampler = 0;
|
||||
textureDescriptor.texture = 0;
|
||||
textureDescriptor.textureTarget = GL::TextureTarget::Target2D;
|
||||
}
|
||||
for (UInt32 i = 0; i < arg.arraySize; ++i)
|
||||
HandleTextureBinding(binding.bindingIndex + i, arg.textureBindings[i]);
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, UniformBufferBinding>)
|
||||
{
|
||||
@@ -137,6 +133,29 @@ namespace Nz
|
||||
// No OpenGL object to name
|
||||
}
|
||||
|
||||
void OpenGLShaderBinding::HandleTextureBinding(UInt32 bindingIndex, const TextureBinding& textureBinding)
|
||||
{
|
||||
auto& textureDescriptor = m_owner.GetTextureDescriptor(m_poolIndex, m_bindingIndex, bindingIndex);
|
||||
|
||||
if (const OpenGLTexture* glTexture = static_cast<const OpenGLTexture*>(textureBinding.texture))
|
||||
{
|
||||
textureDescriptor.texture = glTexture->GetTexture().GetObjectId();
|
||||
|
||||
if (const OpenGLTextureSampler* glSampler = static_cast<const OpenGLTextureSampler*>(textureBinding.sampler))
|
||||
textureDescriptor.sampler = glSampler->GetSampler(glTexture->GetLevelCount() > 1).GetObjectId();
|
||||
else
|
||||
textureDescriptor.sampler = 0;
|
||||
|
||||
textureDescriptor.textureTarget = OpenGLTexture::ToTextureTarget(glTexture->GetType());
|
||||
}
|
||||
else
|
||||
{
|
||||
textureDescriptor.sampler = 0;
|
||||
textureDescriptor.texture = 0;
|
||||
textureDescriptor.textureTarget = GL::TextureTarget::Target2D;
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLShaderBinding::Release()
|
||||
{
|
||||
m_owner.Release(*this);
|
||||
|
||||
@@ -36,6 +36,12 @@ namespace Nz
|
||||
|
||||
if (samplerInfo.anisotropyLevel > 1.f)
|
||||
sampler.SetParameterf(GL_TEXTURE_MAX_ANISOTROPY_EXT, samplerInfo.anisotropyLevel);
|
||||
|
||||
if (samplerInfo.depthCompare)
|
||||
{
|
||||
sampler.SetParameteri(GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
|
||||
sampler.SetParameteri(GL_TEXTURE_COMPARE_FUNC, ToOpenGL(samplerInfo.depthComparison));
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLTextureSampler::UpdateDebugName(std::string_view name)
|
||||
|
||||
@@ -565,8 +565,13 @@ namespace Nz::GL
|
||||
glGetIntegerv(GL_VIEWPORT, res.data());
|
||||
m_state.viewport = { res[0], res[1], res[2], res[3] };
|
||||
|
||||
m_state.renderStates.depthCompare = RendererComparison::Less; //< OpenGL default depth mode is GL_LESS
|
||||
m_state.renderStates.frontFace = FrontFace::CounterClockwise; //< OpenGL default front face is GL_CCW
|
||||
// Set default OpenGL states
|
||||
m_state.renderStates.depthBuffer = false;
|
||||
m_state.renderStates.depthCompare = RendererComparison::Less;
|
||||
m_state.renderStates.faceCulling = FaceCulling::None;
|
||||
m_state.renderStates.frontFace = FrontFace::CounterClockwise;
|
||||
m_state.renderStates.scissorTest = false;
|
||||
m_state.renderStates.stencilTest = false;
|
||||
|
||||
EnableVerticalSync(false);
|
||||
|
||||
@@ -671,6 +676,18 @@ namespace Nz::GL
|
||||
if (!SetCurrentContext(this))
|
||||
throw std::runtime_error("failed to activate context");
|
||||
|
||||
// Depth bias
|
||||
if (renderStates.depthBias)
|
||||
{
|
||||
if (!NumberEquals(m_state.renderStates.depthBiasConstantFactor, renderStates.depthBiasConstantFactor) ||
|
||||
!NumberEquals(m_state.renderStates.depthBiasSlopeFactor, renderStates.depthBiasSlopeFactor))
|
||||
{
|
||||
glPolygonOffset(renderStates.depthBiasConstantFactor, renderStates.depthBiasSlopeFactor);
|
||||
m_state.renderStates.depthBiasConstantFactor = renderStates.depthBiasConstantFactor;
|
||||
m_state.renderStates.depthBiasSlopeFactor = renderStates.depthBiasSlopeFactor;
|
||||
}
|
||||
}
|
||||
|
||||
// Depth compare and depth write
|
||||
if (renderStates.depthBuffer)
|
||||
{
|
||||
@@ -687,14 +704,23 @@ namespace Nz::GL
|
||||
}
|
||||
}
|
||||
|
||||
// Face culling side
|
||||
if (renderStates.faceCulling)
|
||||
// Face culling
|
||||
if (m_state.renderStates.faceCulling != renderStates.faceCulling)
|
||||
{
|
||||
if (m_state.renderStates.cullingSide != renderStates.cullingSide)
|
||||
bool wasEnabled = (m_state.renderStates.faceCulling != FaceCulling::None);
|
||||
bool isEnabled = (renderStates.faceCulling != FaceCulling::None);
|
||||
|
||||
if (isEnabled)
|
||||
{
|
||||
glCullFace(ToOpenGL(renderStates.cullingSide));
|
||||
m_state.renderStates.cullingSide = renderStates.cullingSide;
|
||||
if (!wasEnabled)
|
||||
glEnable(GL_CULL_FACE);
|
||||
|
||||
glCullFace(ToOpenGL(renderStates.faceCulling));
|
||||
}
|
||||
else if (wasEnabled)
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
m_state.renderStates.faceCulling = renderStates.faceCulling;
|
||||
}
|
||||
|
||||
// Front face
|
||||
@@ -811,6 +837,18 @@ namespace Nz::GL
|
||||
m_state.renderStates.colorWriteMask = renderStates.colorWriteMask;
|
||||
}
|
||||
|
||||
// Depth bias
|
||||
if (m_state.renderStates.depthBias != renderStates.depthBias)
|
||||
{
|
||||
// TODO: Handle line and points
|
||||
if (renderStates.depthBias)
|
||||
glEnable(GL_POLYGON_OFFSET_FILL);
|
||||
else
|
||||
glDisable(GL_POLYGON_OFFSET_FILL);
|
||||
|
||||
m_state.renderStates.depthBias = renderStates.depthBias;
|
||||
}
|
||||
|
||||
// Depth buffer
|
||||
if (m_state.renderStates.depthBuffer != renderStates.depthBuffer)
|
||||
{
|
||||
@@ -835,17 +873,6 @@ namespace Nz::GL
|
||||
m_state.renderStates.depthClamp = renderStates.depthClamp;
|
||||
}
|
||||
|
||||
// Face culling
|
||||
if (m_state.renderStates.faceCulling != renderStates.faceCulling)
|
||||
{
|
||||
if (renderStates.faceCulling)
|
||||
glEnable(GL_CULL_FACE);
|
||||
else
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
m_state.renderStates.faceCulling = renderStates.faceCulling;
|
||||
}
|
||||
|
||||
// Scissor test
|
||||
if (m_state.renderStates.scissorTest != renderStates.scissorTest)
|
||||
{
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace Nz
|
||||
RenderPipelineLayoutInfo layoutInfo;
|
||||
layoutInfo.bindings.assign({
|
||||
{
|
||||
0, 0,
|
||||
1, 0, 0,
|
||||
ShaderBindingType::UniformBuffer,
|
||||
nzsl::ShaderStageType::Vertex
|
||||
}
|
||||
|
||||
@@ -133,8 +133,8 @@ namespace Nz
|
||||
std::string appName = parameters.GetStringParameter("VkAppInfo_OverrideApplicationName").GetValueOr("Another application made with Nazara Engine");
|
||||
std::string engineName = parameters.GetStringParameter("VkAppInfo_OverrideEngineName").GetValueOr("Nazara Engine - Vulkan Renderer");
|
||||
|
||||
UInt32 appVersion = parameters.GetIntegerParameter("VkAppInfo_OverrideApplicationVersion").GetValueOr(VK_MAKE_API_VERSION(0, 1, 0, 0));
|
||||
UInt32 engineVersion = parameters.GetIntegerParameter("VkAppInfo_OverrideEngineVersion").GetValueOr(VK_MAKE_API_VERSION(0, 1, 0, 0));
|
||||
UInt32 appVersion = SafeCast<UInt32>(parameters.GetIntegerParameter("VkAppInfo_OverrideApplicationVersion").GetValueOr(VK_MAKE_API_VERSION(0, 1, 0, 0)));
|
||||
UInt32 engineVersion = SafeCast<UInt32>(parameters.GetIntegerParameter("VkAppInfo_OverrideEngineVersion").GetValueOr(VK_MAKE_API_VERSION(0, 1, 0, 0)));
|
||||
|
||||
if (auto result = parameters.GetIntegerParameter("VkAppInfo_OverrideAPIVersion"))
|
||||
targetApiVersion = SafeCast<UInt32>(result.GetValue());
|
||||
@@ -160,7 +160,7 @@ namespace Nz
|
||||
targetApiVersion
|
||||
};
|
||||
|
||||
VkInstanceCreateFlags createFlags = parameters.GetIntegerParameter("VkInstanceInfo_OverrideCreateFlags").GetValueOr(0);
|
||||
VkInstanceCreateFlags createFlags = SafeCast<VkInstanceCreateFlags>(parameters.GetIntegerParameter("VkInstanceInfo_OverrideCreateFlags").GetValueOr(0));
|
||||
|
||||
std::vector<const char*> enabledLayers;
|
||||
|
||||
|
||||
@@ -159,7 +159,10 @@ namespace Nz
|
||||
{
|
||||
VkPipelineRasterizationStateCreateInfo createInfo = {};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
|
||||
createInfo.cullMode = (pipelineInfo.faceCulling) ? ToVulkan(pipelineInfo.cullingSide) : VK_CULL_MODE_NONE;
|
||||
createInfo.cullMode = ToVulkan(pipelineInfo.faceCulling);
|
||||
createInfo.depthBiasEnable = pipelineInfo.depthBias;
|
||||
createInfo.depthBiasConstantFactor = pipelineInfo.depthBiasConstantFactor;
|
||||
createInfo.depthBiasSlopeFactor = pipelineInfo.depthBiasSlopeFactor;
|
||||
createInfo.depthClampEnable = pipelineInfo.depthClamp;
|
||||
createInfo.frontFace = ToVulkan(pipelineInfo.frontFace);
|
||||
createInfo.lineWidth = pipelineInfo.lineWidth;
|
||||
|
||||
@@ -69,7 +69,7 @@ namespace Nz
|
||||
|
||||
VkDescriptorSetLayoutBinding& layoutBinding = descriptorSetLayoutInfo.bindings.emplace_back();
|
||||
layoutBinding.binding = bindingInfo.bindingIndex;
|
||||
layoutBinding.descriptorCount = 1U;
|
||||
layoutBinding.descriptorCount = bindingInfo.arraySize;
|
||||
layoutBinding.descriptorType = ToVulkan(bindingInfo.type);
|
||||
layoutBinding.pImmutableSamplers = nullptr;
|
||||
layoutBinding.stageFlags = ToVulkan(bindingInfo.shaderStageFlags);
|
||||
|
||||
@@ -15,8 +15,34 @@ namespace Nz
|
||||
{
|
||||
void VulkanShaderBinding::Update(const Binding* bindings, std::size_t bindingCount)
|
||||
{
|
||||
StackVector<VkDescriptorBufferInfo> bufferBinding = NazaraStackVector(VkDescriptorBufferInfo, bindingCount);
|
||||
StackVector<VkDescriptorImageInfo> imageBinding = NazaraStackVector(VkDescriptorImageInfo, bindingCount);
|
||||
std::size_t bufferBindingCount = 0;
|
||||
std::size_t imageBindingCount = 0;
|
||||
for (std::size_t i = 0; i < bindingCount; ++i)
|
||||
{
|
||||
const Binding& binding = bindings[i];
|
||||
|
||||
std::visit([&](auto&& arg)
|
||||
{
|
||||
using T = std::decay_t<decltype(arg)>;
|
||||
|
||||
if constexpr (std::is_same_v<T, StorageBufferBinding> || std::is_same_v<T, UniformBufferBinding>)
|
||||
bufferBindingCount++;
|
||||
else if constexpr (std::is_same_v<T, TextureBinding>)
|
||||
imageBindingCount++;
|
||||
else if constexpr (std::is_same_v<T, TextureBindings>)
|
||||
imageBindingCount += arg.arraySize;
|
||||
else
|
||||
static_assert(AlwaysFalse<T>(), "non-exhaustive visitor");
|
||||
|
||||
}, binding.content);
|
||||
}
|
||||
|
||||
NazaraAssert(bufferBindingCount < 128, "too many concurrent buffer update");
|
||||
NazaraAssert(imageBindingCount < 128, "too many concurrent image binding update");
|
||||
NazaraAssert(bindingCount < 128, "too many binding update");
|
||||
|
||||
StackVector<VkDescriptorBufferInfo> bufferBinding = NazaraStackVector(VkDescriptorBufferInfo, bufferBindingCount);
|
||||
StackVector<VkDescriptorImageInfo> imageBinding = NazaraStackVector(VkDescriptorImageInfo, imageBindingCount);
|
||||
StackVector<VkWriteDescriptorSet> writeOps = NazaraStackVector(VkWriteDescriptorSet, bindingCount);
|
||||
|
||||
for (std::size_t i = 0; i < bindingCount; ++i)
|
||||
@@ -34,7 +60,7 @@ namespace Nz
|
||||
|
||||
if constexpr (std::is_same_v<T, StorageBufferBinding>)
|
||||
{
|
||||
VulkanBuffer* vkBuffer = static_cast<VulkanBuffer*>(arg.buffer);
|
||||
VulkanBuffer* vkBuffer = SafeCast<VulkanBuffer*>(arg.buffer);
|
||||
|
||||
VkDescriptorBufferInfo& bufferInfo = bufferBinding.emplace_back();
|
||||
bufferInfo.buffer = (vkBuffer) ? vkBuffer->GetBuffer() : VK_NULL_HANDLE;
|
||||
@@ -47,8 +73,8 @@ namespace Nz
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, TextureBinding>)
|
||||
{
|
||||
const VulkanTexture* vkTexture = static_cast<const VulkanTexture*>(arg.texture);
|
||||
const VulkanTextureSampler* vkSampler = static_cast<const VulkanTextureSampler*>(arg.sampler);
|
||||
const VulkanTexture* vkTexture = SafeCast<const VulkanTexture*>(arg.texture);
|
||||
const VulkanTextureSampler* vkSampler = SafeCast<const VulkanTextureSampler*>(arg.sampler);
|
||||
|
||||
VkDescriptorImageInfo& imageInfo = imageBinding.emplace_back();
|
||||
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
@@ -59,6 +85,23 @@ namespace Nz
|
||||
writeOp.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
writeOp.pImageInfo = &imageInfo;
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, TextureBindings>)
|
||||
{
|
||||
for (UInt32 i = 0; i < arg.arraySize; ++i)
|
||||
{
|
||||
const VulkanTexture* vkTexture = SafeCast<const VulkanTexture*>(arg.textureBindings[i].texture);
|
||||
const VulkanTextureSampler* vkSampler = SafeCast<const VulkanTextureSampler*>(arg.textureBindings[i].sampler);
|
||||
|
||||
VkDescriptorImageInfo& imageInfo = imageBinding.emplace_back();
|
||||
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
imageInfo.imageView = (vkTexture) ? vkTexture->GetImageView() : VK_NULL_HANDLE;
|
||||
imageInfo.sampler = (vkSampler) ? vkSampler->GetSampler() : VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
writeOp.descriptorCount = arg.arraySize;
|
||||
writeOp.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
writeOp.pImageInfo = &imageBinding[imageBinding.size() - arg.arraySize];
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, UniformBufferBinding>)
|
||||
{
|
||||
VulkanBuffer* vkBuffer = static_cast<VulkanBuffer*>(arg.buffer);
|
||||
|
||||
@@ -293,15 +293,19 @@ namespace Nz
|
||||
if (!copyCommandBuffer->Begin(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT))
|
||||
return false;
|
||||
|
||||
VkImageAspectFlagBits aspect = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
if (PixelFormatInfo::GetContent(m_params.pixelFormat) == PixelFormatContent::Depth)
|
||||
aspect = VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
|
||||
VkImageSubresourceLayers subresourceLayers = { //< FIXME
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
aspect,
|
||||
level, //< mipLevel
|
||||
0, //< baseArrayLayer
|
||||
UInt32((m_params.type == ImageType::Cubemap) ? 6 : 1) //< layerCount
|
||||
};
|
||||
|
||||
VkImageSubresourceRange subresourceRange = { //< FIXME
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
aspect,
|
||||
0, //< baseMipLevel
|
||||
1, //< levelCount
|
||||
subresourceLayers.baseArrayLayer, //< baseArrayLayer
|
||||
|
||||
@@ -22,6 +22,8 @@ namespace Nz
|
||||
createInfo.addressModeW = ToVulkan(samplerInfo.wrapModeW);
|
||||
createInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
|
||||
createInfo.mipmapMode = ToVulkan(samplerInfo.mipmapMode);
|
||||
createInfo.compareEnable = samplerInfo.depthCompare;
|
||||
createInfo.compareOp = ToVulkan(samplerInfo.depthComparison);
|
||||
|
||||
if (samplerInfo.anisotropyLevel > 1.f)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user