Implemented scanline and silhouette effect #363
|
@ -0,0 +1,8 @@
|
|||
- VertexShader: 38847805
|
||||
FragmentShader: 42962441
|
||||
SubPass: Object VFX Subpass No Depth
|
||||
Properties:
|
||||
data.color: {x: 1, y: 1, z: 1, w: 1}
|
||||
data.textureIndex: 0
|
||||
data.alpha: 0
|
||||
data.beta: {x: 1, y: 1, z: 1}
|
|
@ -0,0 +1,3 @@
|
|||
Name: Silhouette
|
||||
ID: 126391182
|
||||
Type: 7
|
|
@ -0,0 +1,67 @@
|
|||
#version 450
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
#extension GL_ARB_shading_language_420pack : enable
|
||||
#extension GL_EXT_nonuniform_qualifier : require
|
||||
|
||||
struct MatPropData
|
||||
{
|
||||
vec4 color;
|
||||
};
|
||||
|
||||
struct GenericData
|
||||
{
|
||||
//! Delta time
|
||||
float dt;
|
||||
|
||||
//! Elapsed time of the application
|
||||
float elapsedTime;
|
||||
|
||||
//! Viewport width of the scene (excluding imgui, that means smaller than window)
|
||||
uint viewportWidth;
|
||||
|
||||
//! Ditto but for height
|
||||
uint viewportHeight;
|
||||
};
|
||||
|
||||
layout(location = 0) in struct
|
||||
{
|
||||
vec4 vertPos; // location 0
|
||||
vec2 uv; // location = 1
|
||||
vec4 normal; // location = 2
|
||||
vec4 worldPos; // location = 3
|
||||
} In;
|
||||
|
||||
// material stuff
|
||||
layout(location = 4) flat in struct
|
||||
{
|
||||
int materialIndex;
|
||||
uint eid;
|
||||
uint lightLayerIndex;
|
||||
} In2;
|
||||
|
||||
layout (set = 0, binding = 1) uniform sampler2D textures[]; // for textures (global)
|
||||
layout (std430, set = 2, binding = 0) buffer MaterialProperties // For materials
|
||||
{
|
||||
MatPropData data[];
|
||||
} MatProp;
|
||||
|
||||
layout (set = 0, binding = 0) uniform GenericDataBuffer
|
||||
{
|
||||
GenericData data;
|
||||
} genericDataBuffer;
|
||||
|
||||
layout(location = 0) out vec4 objectVFX;
|
||||
layout(input_attachment_index = 0, set = 3, binding = 0) uniform subpassInput depthBuffer;
|
||||
|
||||
void main()
|
||||
{
|
||||
// Sample depth buffer using UV and save it
|
||||
float currentDepth = subpassLoad (depthBuffer).r;
|
||||
|
||||
// Use depth buffer to check against current fragment's depth. If fragment is behind depth buffer, render fragment.
|
||||
if (currentDepth > gl_FragCoord.z)
|
||||
discard;
|
||||
|
||||
objectVFX = MatProp.data[In2.materialIndex].color;
|
||||
|
||||
}
|
Binary file not shown.
|
@ -0,0 +1,3 @@
|
|||
Name: Silhouette_FS
|
||||
ID: 42962441
|
||||
Type: 2
|
|
@ -0,0 +1,68 @@
|
|||
#version 450
|
||||
#extension GL_KHR_vulkan_glsl : enable
|
||||
|
||||
//#include "ShaderDescriptorDefinitions.glsl"
|
||||
|
||||
|
||||
layout(location = 0) in vec3 aVertexPos;
|
||||
layout(location = 1) in vec2 aUV;
|
||||
layout(location = 2) in vec3 aNormal;
|
||||
layout(location = 3) in vec3 aTangent;
|
||||
layout(location = 4) in mat4 worldTransform;
|
||||
layout(location = 8) in uvec2 integerData;
|
||||
layout(location = 9) in uvec4 aBoneIndices;
|
||||
layout(location = 10) in vec4 aBoneWeights;
|
||||
layout(location = 11) in uint firstBoneIndex;
|
||||
|
||||
layout(location = 0) out struct
|
||||
{
|
||||
vec4 vertPos; // location 0
|
||||
vec2 uv; // location = 1
|
||||
vec4 normal; // location = 2
|
||||
vec4 worldPos; // location = 3
|
||||
|
||||
} Out;
|
||||
|
||||
// material stuff
|
||||
layout(location = 4) out struct
|
||||
{
|
||||
int materialIndex;
|
||||
uint eid;
|
||||
uint lightLayerIndex;
|
||||
|
||||
} Out2;
|
||||
|
||||
layout(set = 1, binding = 0) uniform CameraData
|
||||
{
|
||||
vec4 position;
|
||||
mat4 vpMat;
|
||||
mat4 viewMat;
|
||||
mat4 projMat;
|
||||
} cameraData;
|
||||
|
||||
void main()
|
||||
{
|
||||
Out2.materialIndex = gl_InstanceIndex;
|
||||
Out2.eid = integerData[0];
|
||||
Out2.lightLayerIndex = integerData[1];
|
||||
|
||||
// for transforming gBuffer position and normal data
|
||||
mat4 modelViewMat = cameraData.viewMat * worldTransform;
|
||||
|
||||
// gBuffer position will be in view space
|
||||
Out.vertPos = modelViewMat * vec4(aVertexPos, 1.0f);
|
||||
|
||||
Out.worldPos = worldTransform * vec4 (aVertexPos, 1.0f);
|
||||
|
||||
// uvs for texturing in fragment shader
|
||||
Out.uv = aUV;
|
||||
|
||||
mat3 transposeInv = mat3 (transpose(inverse(modelViewMat)));
|
||||
|
||||
// normals are also in view space
|
||||
Out.normal.rgb = transposeInv * aNormal.rgb;
|
||||
Out.normal.rgb = normalize (Out.normal.rgb);
|
||||
|
||||
// clip space for rendering
|
||||
gl_Position = cameraData.vpMat * worldTransform * vec4 (aVertexPos, 1.0f);
|
||||
}
|
Binary file not shown.
|
@ -0,0 +1,3 @@
|
|||
Name: Silhouette_VS
|
||||
ID: 38847805
|
||||
Type: 2
|
|
@ -3,7 +3,7 @@
|
|||
#extension GL_ARB_shading_language_420pack : enable
|
||||
#extension GL_EXT_nonuniform_qualifier : require
|
||||
|
||||
layout (input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput sceneTexture;
|
||||
layout (input_attachment_index = 0, set = 3, binding = 0) uniform subpassInput sceneTexture;
|
||||
|
||||
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
|
|
Binary file not shown.
|
@ -28,6 +28,7 @@ namespace SHADE
|
|||
{SHPredefinedDescriptorTypes::STATIC_DATA, 0},
|
||||
{SHPredefinedDescriptorTypes::CAMERA, 1},
|
||||
{SHPredefinedDescriptorTypes::PER_INSTANCE_BATCH, 2},
|
||||
{SHPredefinedDescriptorTypes::RENDER_GRAPH_RESOURCE, 3},
|
||||
});
|
||||
|
||||
perSystemData[SHUtilities::ConvertEnum(SystemType::BATCHING_ANIM)].descMappings.AddMappings
|
||||
|
|
|
@ -129,11 +129,13 @@ namespace SHADE
|
|||
static constexpr std::string_view GBUFFER_WRITE_SUBPASS = "G-Buffer Write";
|
||||
static constexpr std::string_view UI_SUBPASS = "UI";
|
||||
static constexpr std::string_view VFX_SUBPASS = "VFX";
|
||||
static constexpr std::string_view OBJ_VFX_SUBPASS = "Object VFX Subpass No Depth";
|
||||
|
||||
static constexpr std::array USABLE_SUBPASSES =
|
||||
{
|
||||
GBUFFER_WRITE_SUBPASS,
|
||||
UI_SUBPASS
|
||||
UI_SUBPASS,
|
||||
OBJ_VFX_SUBPASS
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -215,7 +215,7 @@ namespace SHADE
|
|||
renderGraph->AddResource("Normals", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, true, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat);
|
||||
//worldRenderGraph->AddResource("Tangents", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat);
|
||||
renderGraph->AddResource("Albedo", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, true, windowDims.first, windowDims.second);
|
||||
renderGraph->AddResource("Depth Buffer", { SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH_STENCIL }, true, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint);
|
||||
renderGraph->AddResource("Depth Buffer", { SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT }, true, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint);
|
||||
renderGraph->AddResource("Entity ID", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::SHARED }, true, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
|
||||
renderGraph->AddResource("Light Layer Indices", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, true, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
|
||||
renderGraph->AddResource("Scene", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE, SH_RENDER_GRAPH_RESOURCE_FLAGS::SHARED }, true, windowDims.first, windowDims.second);
|
||||
|
@ -255,7 +255,13 @@ namespace SHADE
|
|||
gBufferSubpass->AddColorOutput("Object VFX");
|
||||
gBufferSubpass->AddDepthOutput("Depth Buffer", SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH_STENCIL);
|
||||
|
||||
usableSubpassesMapping.emplace (std::string (SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_WRITE_SUBPASS.data()), gBufferSubpass);
|
||||
// We add the object VFX render target and depth buffer as input just in case we want to make comparisons
|
||||
auto objectVfxSubpassNoDepth = gBufferNode->AddSubpass(SHGraphicsConstants::RenderGraphEntityNames::OBJ_VFX_SUBPASS.data(), worldViewport, worldRenderer);
|
||||
objectVfxSubpassNoDepth->AddColorOutput("Object VFX");
|
||||
objectVfxSubpassNoDepth->AddInput ("Depth Buffer");
|
||||
|
||||
usableSubpassesMapping.emplace(std::string(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_WRITE_SUBPASS.data()), gBufferSubpass);
|
||||
usableSubpassesMapping.emplace(std::string(SHGraphicsConstants::RenderGraphEntityNames::OBJ_VFX_SUBPASS.data()), objectVfxSubpassNoDepth);
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* SSAO PASS AND DATA INIT */
|
||||
|
|
|
@ -512,8 +512,9 @@ namespace SHADE
|
|||
uint32_t h = static_cast<uint32_t>(resource->GetHeight());
|
||||
cmdBuffer->SetViewportScissor(static_cast<float>(w), static_cast<float>(h), w, h);
|
||||
|
||||
static constexpr uint32_t INPUT_IMAGE_SET_INDEX = 0;
|
||||
newSubpass->BindInputDescriptorSets (cmdBuffer, INPUT_IMAGE_SET_INDEX, frameIndex);
|
||||
//static constexpr uint32_t INPUT_IMAGE_SET_INDEX = 0;
|
||||
auto const& mappings = SHGraphicsPredefinedData::GetMappings(SHGraphicsPredefinedData::SystemType::BATCHING);
|
||||
newSubpass->BindInputDescriptorSets (cmdBuffer, mappings.at(SHPredefinedDescriptorTypes::RENDER_GRAPH_RESOURCE), frameIndex);
|
||||
|
||||
// draw a quad.
|
||||
cmdBuffer->DrawArrays(4, 1, 0, 0);
|
||||
|
@ -570,7 +571,8 @@ namespace SHADE
|
|||
auto cmdBuffer = commandBuffers[frameIndex];
|
||||
cmdBuffer->BeginLabeledSegment(name);
|
||||
|
||||
auto batchingSystemData = SHGraphicsPredefinedData::GetSystemData(SHGraphicsPredefinedData::SystemType::BATCHING);
|
||||
auto const& batchingSystemData = SHGraphicsPredefinedData::GetSystemData(SHGraphicsPredefinedData::SystemType::BATCHING);
|
||||
|
||||
|
||||
// Force bind pipeline layout
|
||||
cmdBuffer->ForceSetPipelineLayout(batchingSystemData.dummyPipelineLayout, SH_PIPELINE_TYPE::GRAPHICS);
|
||||
|
|
|
@ -184,12 +184,13 @@ namespace SHADE
|
|||
for (auto& inputAtt : subpass->inputReferences)
|
||||
{
|
||||
auto resource = attResources[inputAtt.attachment];
|
||||
if (resource->resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT))
|
||||
auto typeFlags = resource->resourceTypeFlags;
|
||||
if (typeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT))
|
||||
{
|
||||
if (resource->resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR) ||
|
||||
resource->resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT))
|
||||
if (typeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR) ||
|
||||
typeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT))
|
||||
colorRead |= (1 << i);
|
||||
else if (resource->resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH_STENCIL))
|
||||
else if (typeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH_STENCIL) || typeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH))
|
||||
depthRead |= (1 << i);
|
||||
}
|
||||
else
|
||||
|
@ -265,6 +266,7 @@ namespace SHADE
|
|||
|
||||
// initialize input descriptors
|
||||
subpasses[i]->CreateInputDescriptors();
|
||||
subpasses[i]->GenerateDummyPipielineLayout();
|
||||
|
||||
++i;
|
||||
}
|
||||
|
|
|
@ -226,11 +226,15 @@ namespace SHADE
|
|||
commandBuffer->SetViewportScissor(static_cast<float>(w), static_cast<float>(h), w, h);
|
||||
}
|
||||
|
||||
commandBuffer->ForceSetPipelineLayout(dummyPipelineLayout, SH_PIPELINE_TYPE::GRAPHICS);
|
||||
|
||||
auto const& descMappings = SHGraphicsPredefinedData::GetMappings(SHGraphicsPredefinedData::SystemType::BATCHING);
|
||||
|
||||
if (renderer)
|
||||
renderer->BindDescriptorSet(commandBuffer, SH_PIPELINE_TYPE::GRAPHICS, descMappings.at(SHPredefinedDescriptorTypes::CAMERA), frameIndex);
|
||||
|
||||
BindInputDescriptorSets (commandBuffer, descMappings.at(SHPredefinedDescriptorTypes::RENDER_GRAPH_RESOURCE), frameIndex);
|
||||
|
||||
// If companion subpass is not a valid handle, render super batch normally
|
||||
if (!companionSubpass.companion)
|
||||
{
|
||||
|
@ -439,6 +443,33 @@ namespace SHADE
|
|||
}
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Generates the dummy pipeline layout for subpass; specifically add the
|
||||
input descriptor set layout if it exists.
|
||||
|
||||
|
||||
\return
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
void SHSubpass::GenerateDummyPipielineLayout(void) noexcept
|
||||
{
|
||||
auto const& batchingSystemData = SHGraphicsPredefinedData::GetSystemData(SHGraphicsPredefinedData::SystemType::BATCHING);
|
||||
std::vector newLayouts = batchingSystemData.descSetLayouts;
|
||||
if (inputDescriptorLayout)
|
||||
{
|
||||
newLayouts.push_back(inputDescriptorLayout);
|
||||
}
|
||||
|
||||
dummyPipelineLayout = graphStorage->logicalDevice->CreatePipelineLayoutDummy
|
||||
(
|
||||
SHPipelineLayoutParamsDummy{ newLayouts }
|
||||
);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ namespace SHADE
|
|||
class SHRenderer;
|
||||
class SHViewport;
|
||||
class SHVkPipeline;
|
||||
class SHVkPipelineLayout;
|
||||
|
||||
class SH_API SHSubpass : public ISelfHandle<SHSubpass>
|
||||
{
|
||||
|
@ -87,6 +88,12 @@ namespace SHADE
|
|||
|
||||
std::vector<Handle<SHVkSampler>> inputSamplers;
|
||||
|
||||
//! Dummy pipeline layout for subpass to bind before draw.
|
||||
//! // IMPORTANT NOTE: After implementing input descriptors, every subpass differs in number input descriptors.
|
||||
//! Before binding the input descriptors, a pipeline layout containing the desc set layouts
|
||||
//! for the input descriptors is required, making this umbrella initial dummy bind invalid.
|
||||
Handle<SHVkPipelineLayout> dummyPipelineLayout;
|
||||
|
||||
|
||||
////! subpass compute image barriers. We do this because every frame has a different
|
||||
////! swapchain image. If the resource we want to transition is not a swapchain image,
|
||||
|
@ -146,6 +153,7 @@ namespace SHADE
|
|||
//void InitComputeBarriers (void) noexcept;
|
||||
void CreateInputDescriptors (void) noexcept;
|
||||
void UpdateWriteDescriptors (void) noexcept;
|
||||
void GenerateDummyPipielineLayout (void) noexcept;
|
||||
|
||||
private:
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
|
Loading…
Reference in New Issue