Renderer: Add proper support for blending

This commit is contained in:
Jérôme Leclercq 2021-05-14 01:50:46 +02:00
parent 61dbd91346
commit adbf1e1da0
13 changed files with 207 additions and 99 deletions

View File

@ -58,7 +58,12 @@ namespace Nz
inline void EnsurePipelineUpdate() const;
inline RendererComparison GetDepthCompareFunc() const;
inline BlendFunc GetDstBlend() const;
inline BlendEquation GetBlendAlphaModeEquation() const;
inline BlendEquation GetBlendColorModeEquation() const;
inline BlendFunc GetBlendDstAlphaFunc() const;
inline BlendFunc GetBlendDstColorFunc() const;
inline BlendFunc GetBlendSrcAlphaFunc() const;
inline BlendFunc GetBlendSrcColorFunc() const;
inline FaceSide GetFaceCulling() const;
inline FaceFilling GetFaceFilling() const;
inline float GetLineWidth() const;
@ -67,7 +72,6 @@ namespace Nz
inline float GetPointSize() const;
inline const std::shared_ptr<const MaterialSettings>& GetSettings() const;
inline const std::shared_ptr<UberShader>& GetShader(ShaderStageType shaderStage) const;
inline BlendFunc GetSrcBlend() const;
inline const std::shared_ptr<Texture>& GetTexture(std::size_t textureIndex) const;
inline const TextureSamplerInfo& GetTextureSampler(std::size_t textureIndex) const;
inline const std::shared_ptr<AbstractBuffer>& GetUniformBuffer(std::size_t bufferIndex) const;
@ -91,12 +95,12 @@ namespace Nz
inline bool IsShadowReceiveEnabled() const;
inline void SetDepthCompareFunc(RendererComparison depthFunc);
inline void SetDstBlend(BlendFunc func);
inline void SetBlendEquation(BlendEquation colorMode, BlendEquation alphaMode);
inline void SetBlendFunc(BlendFunc srcColor, BlendFunc dstColor, BlendFunc srcAlpha, BlendFunc dstAlpha);
inline void SetFaceCulling(FaceSide faceSide);
inline void SetFaceFilling(FaceFilling filling);
inline void SetLineWidth(float lineWidth);
inline void SetPointSize(float pointSize);
inline void SetSrcBlend(BlendFunc func);
inline void SetTexture(std::size_t textureIndex, std::shared_ptr<Texture> texture);
inline void SetTextureSampler(std::size_t textureIndex, TextureSamplerInfo samplerInfo);
inline void SetUniformBuffer(std::size_t bufferIndex, std::shared_ptr<AbstractBuffer> uniformBuffer);

View File

@ -336,16 +336,34 @@ namespace Nz
return m_pipelineInfo.depthCompare;
}
/*!
* \brief Gets the dst in blend
*
* \return Function for dst blending
*
* \see SetDstBlend
*/
inline BlendFunc Material::GetDstBlend() const
inline BlendEquation Material::GetBlendAlphaModeEquation() const
{
return m_pipelineInfo.dstBlend;
return m_pipelineInfo.blend.modeAlpha;
}
inline BlendEquation Material::GetBlendColorModeEquation() const
{
return m_pipelineInfo.blend.modeColor;
}
inline BlendFunc Material::GetBlendDstAlphaFunc() const
{
return m_pipelineInfo.blend.dstAlpha;
}
inline BlendFunc Material::GetBlendDstColorFunc() const
{
return m_pipelineInfo.blend.dstColor;
}
inline BlendFunc Material::GetBlendSrcAlphaFunc() const
{
return m_pipelineInfo.blend.srcAlpha;
}
inline BlendFunc Material::GetBlendSrcColorFunc() const
{
return m_pipelineInfo.blend.srcColor;
}
/*!
@ -421,15 +439,6 @@ namespace Nz
return m_pipelineInfo.shaders[UnderlyingCast(shaderStage)].uberShader;
}
/*!
* \brief Gets the src in blend
* \return Function for src blending
*/
inline BlendFunc Material::GetSrcBlend() const
{
return m_pipelineInfo.srcBlend;
}
inline const std::shared_ptr<Texture>& Material::GetTexture(std::size_t textureIndex) const
{
NazaraAssert(textureIndex < m_textures.size(), "Invalid texture index");
@ -596,16 +605,20 @@ namespace Nz
InvalidatePipeline();
}
/*!
* \brief Sets the dst in blend
*
* \param func Function for dst blending
*
* \remark Invalidates the pipeline
*/
inline void Material::SetDstBlend(BlendFunc func)
inline void Material::SetBlendEquation(BlendEquation colorMode, BlendEquation alphaMode)
{
m_pipelineInfo.dstBlend = func;
m_pipelineInfo.blend.modeAlpha = alphaMode;
m_pipelineInfo.blend.modeColor = colorMode;
InvalidatePipeline();
}
inline void Material::SetBlendFunc(BlendFunc srcColor, BlendFunc dstColor, BlendFunc srcAlpha, BlendFunc dstAlpha)
{
m_pipelineInfo.blend.dstAlpha = dstAlpha;
m_pipelineInfo.blend.dstColor = dstColor;
m_pipelineInfo.blend.srcAlpha = srcAlpha;
m_pipelineInfo.blend.srcColor = srcColor;
InvalidatePipeline();
}
@ -674,22 +687,6 @@ namespace Nz
InvalidatePipeline();
}
/*!
* \brief Sets the src in blend
*
* \param func Function for src blending
*
* \remark Invalidates the pipeline
*
* \see GetSrcBlend
*/
inline void Material::SetSrcBlend(BlendFunc func)
{
m_pipelineInfo.srcBlend = func;
InvalidatePipeline();
}
inline void Material::SetTexture(std::size_t textureIndex, std::shared_ptr<Texture> texture)
{
NazaraAssert(textureIndex < m_textures.size(), "Invalid texture index");

View File

@ -29,6 +29,7 @@ namespace Nz
inline std::optional<GLTextureFormat> DescribeTextureFormat(PixelFormat pixelFormat);
inline GLenum ToOpenGL(BlendEquation blendEquation);
inline GLenum ToOpenGL(BlendFunc blendFunc);
inline GLenum ToOpenGL(FaceSide filter);
inline GLenum ToOpenGL(PrimitiveMode primitiveMode);

View File

@ -32,20 +32,39 @@ namespace Nz
return {};
}
inline GLenum ToOpenGL(BlendEquation blendEquation)
{
switch (blendEquation)
{
case BlendEquation::Add: return GL_FUNC_ADD;
case BlendEquation::Max: return GL_MAX;
case BlendEquation::Min: return GL_MIN;
case BlendEquation::ReverseSubtract: return GL_FUNC_REVERSE_SUBTRACT;
case BlendEquation::Subtract: return GL_FUNC_SUBTRACT;
}
NazaraError("Unhandled BlendEquation 0x" + NumberToString(UnderlyingCast(blendEquation), 16));
return {};
}
inline GLenum ToOpenGL(BlendFunc blendFunc)
{
switch (blendFunc)
{
case BlendFunc_DestAlpha: return GL_DST_ALPHA;
case BlendFunc_DestColor: return GL_DST_COLOR;
case BlendFunc_SrcAlpha: return GL_SRC_ALPHA;
case BlendFunc_SrcColor: return GL_SRC_COLOR;
case BlendFunc_InvDestAlpha: return GL_ONE_MINUS_DST_ALPHA;
case BlendFunc_InvDestColor: return GL_ONE_MINUS_DST_COLOR;
case BlendFunc_InvSrcAlpha: return GL_ONE_MINUS_SRC_ALPHA;
case BlendFunc_InvSrcColor: return GL_ONE_MINUS_SRC_COLOR;
case BlendFunc_One: return GL_ONE;
case BlendFunc_Zero: return GL_ZERO;
case BlendFunc::ConstantAlpha: return GL_CONSTANT_ALPHA;
case BlendFunc::ConstantColor: return GL_CONSTANT_COLOR;
case BlendFunc::DstAlpha: return GL_DST_ALPHA;
case BlendFunc::DstColor: return GL_DST_COLOR;
case BlendFunc::InvConstantAlpha: return GL_ONE_MINUS_CONSTANT_ALPHA;
case BlendFunc::InvConstantColor: return GL_ONE_MINUS_CONSTANT_COLOR;
case BlendFunc::InvDstAlpha: return GL_ONE_MINUS_DST_ALPHA;
case BlendFunc::InvDstColor: return GL_ONE_MINUS_DST_COLOR;
case BlendFunc::InvSrcAlpha: return GL_ONE_MINUS_SRC_ALPHA;
case BlendFunc::InvSrcColor: return GL_ONE_MINUS_SRC_COLOR;
case BlendFunc::SrcAlpha: return GL_SRC_ALPHA;
case BlendFunc::SrcColor: return GL_SRC_COLOR;
case BlendFunc::One: return GL_ONE;
case BlendFunc::Zero: return GL_ZERO;
}
NazaraError("Unhandled BlendFunc 0x" + NumberToString(UnderlyingCast(blendFunc), 16));

View File

@ -29,7 +29,7 @@ typedef void (GL_APIENTRYP PFNGLSPECIALIZESHADERARBPROC) (GLuint shader, const G
cb(glBindSampler, PFNGLBINDSAMPLERPROC) \
cb(glBindTexture, PFNGLBINDTEXTUREPROC) \
cb(glBindVertexArray, PFNGLBINDVERTEXARRAYPROC) \
cb(glBlendFunc, PFNGLBLENDFUNCPROC) \
cb(glBlendEquationSeparate, PFNGLBLENDEQUATIONSEPARATEPROC) \
cb(glBlendFuncSeparate, PFNGLBLENDFUNCSEPARATEPROC) \
cb(glBlitFramebuffer, PFNGLBLITFRAMEBUFFERPROC) \
cb(glBufferData, PFNGLBUFFERDATAPROC) \

View File

@ -19,13 +19,21 @@ namespace Nz
struct RenderStates
{
BlendFunc dstBlend = BlendFunc_Zero;
BlendFunc srcBlend = BlendFunc_One;
FaceFilling faceFilling = FaceFilling_Fill;
FaceSide cullingSide = FaceSide_Back;
RendererComparison depthCompare = RendererComparison_Less;
PrimitiveMode primitiveMode = PrimitiveMode_TriangleList;
struct
{
BlendEquation modeAlpha = BlendEquation::Add;
BlendEquation modeColor = BlendEquation::Add;
BlendFunc dstAlpha = BlendFunc::Zero;
BlendFunc dstColor = BlendFunc::Zero;
BlendFunc srcAlpha = BlendFunc::One;
BlendFunc srcColor = BlendFunc::One;
} blend;
struct
{
RendererComparison compare = RendererComparison_Always;

View File

@ -30,8 +30,12 @@ namespace Nz
if (lhs.blending) //< Remember, at this time we know lhs.blending == rhs.blending
{
NazaraRenderStateMember(dstBlend);
NazaraRenderStateMember(srcBlend);
NazaraRenderStateMember(blend.dstAlpha);
NazaraRenderStateMember(blend.dstColor);
NazaraRenderStateMember(blend.modeAlpha);
NazaraRenderStateMember(blend.modeColor);
NazaraRenderStateMember(blend.srcAlpha);
NazaraRenderStateMember(blend.srcColor);
}
if (lhs.depthBuffer)
@ -101,8 +105,12 @@ namespace std
if (pipelineInfo.blending) //< Remember, at this time we know lhs.blending == rhs.blending
{
NazaraRenderStateEnum(dstBlend);
NazaraRenderStateEnum(srcBlend);
NazaraRenderStateEnum(blend.dstAlpha);
NazaraRenderStateEnum(blend.dstColor);
NazaraRenderStateEnum(blend.modeAlpha);
NazaraRenderStateEnum(blend.modeColor);
NazaraRenderStateEnum(blend.srcAlpha);
NazaraRenderStateEnum(blend.srcColor);
}
if (pipelineInfo.depthBuffer)

View File

@ -19,20 +19,31 @@ namespace Nz
AnimationType_Max = AnimationType_Static
};
enum BlendFunc
enum class BlendEquation
{
BlendFunc_DestAlpha,
BlendFunc_DestColor,
BlendFunc_SrcAlpha,
BlendFunc_SrcColor,
BlendFunc_InvDestAlpha,
BlendFunc_InvDestColor,
BlendFunc_InvSrcAlpha,
BlendFunc_InvSrcColor,
BlendFunc_One,
BlendFunc_Zero,
Add,
Max,
Min,
ReverseSubtract,
Subtract,
};
BlendFunc_Max = BlendFunc_Zero
enum class BlendFunc
{
ConstantColor,
ConstantAlpha,
DstAlpha,
DstColor,
SrcAlpha,
SrcColor,
InvConstantColor,
InvConstantAlpha,
InvDstAlpha,
InvDstColor,
InvSrcAlpha,
InvSrcColor,
One,
Zero
};
enum BufferAccess

View File

@ -22,6 +22,12 @@ namespace Nz
static constexpr const char* BackFaceStencilReference = "MatBackFaceStencilReference";
static constexpr const char* BackFaceStencilZFail = "MatBackFaceStencilZFail";
static constexpr const char* Blending = "MatBlending";
static constexpr const char* BlendModeAlpha = "MatBlendModeAlpha";
static constexpr const char* BlendModeColor = "MatBlendModeColor";
static constexpr const char* BlendDstAlpha = "MatBlendDstAlpha";
static constexpr const char* BlendDstColor = "MatBlendDstColor";
static constexpr const char* BlendSrcAlpha = "MatBlendSrcAlpha";
static constexpr const char* BlendSrcColor = "MatBlendSrcColor";
static constexpr const char* CullingSide = "MatCullingSide";
static constexpr const char* ColorWrite = "MatColorWrite";
static constexpr const char* DepthBuffer = "MatDepthBuffer";
@ -33,7 +39,6 @@ namespace Nz
static constexpr const char* DiffuseFilter = "MatDiffuseFilter";
static constexpr const char* DiffuseTexturePath = "MatDiffuseTexturePath";
static constexpr const char* DiffuseWrap = "MatDiffuseWrap";
static constexpr const char* DstBlend = "MatDstBlend";
static constexpr const char* EmissiveTexturePath = "MatEmissiveTexturePath";
static constexpr const char* FaceCulling = "MatFaceCulling";
static constexpr const char* FaceFilling = "MatFaceFilling";
@ -51,7 +56,6 @@ namespace Nz
static constexpr const char* SpecularFilter = "MatSpecularFilter";
static constexpr const char* SpecularTexturePath = "MatSpecularTexturePath";
static constexpr const char* SpecularWrap = "MatSpecularWrap";
static constexpr const char* SrcBlend = "MatSrcBlend";
static constexpr const char* StencilCompare = "MatStencilCompare";
static constexpr const char* StencilFail = "MatStencilFail";
static constexpr const char* StencilMask = "MatStencilMask";

View File

@ -10,7 +10,7 @@
namespace Nz
{
std::optional<PixelFormat> FromVulkan(VkFormat format)
inline std::optional<PixelFormat> FromVulkan(VkFormat format)
{
switch (format)
{
@ -26,7 +26,7 @@ namespace Nz
return std::nullopt;
}
VkAttachmentLoadOp ToVulkan(AttachmentLoadOp loadOp)
inline VkAttachmentLoadOp ToVulkan(AttachmentLoadOp loadOp)
{
switch (loadOp)
{
@ -39,7 +39,7 @@ namespace Nz
return {};
}
VkAttachmentStoreOp ToVulkan(AttachmentStoreOp storeOp)
inline VkAttachmentStoreOp ToVulkan(AttachmentStoreOp storeOp)
{
switch (storeOp)
{
@ -51,6 +51,45 @@ namespace Nz
return {};
}
inline VkBlendOp ToVulkan(BlendEquation blendEquation)
{
switch (blendEquation)
{
case BlendEquation::Add: return VK_BLEND_OP_ADD;
case BlendEquation::Max: return VK_BLEND_OP_MAX;
case BlendEquation::Min: return VK_BLEND_OP_MIN;
case BlendEquation::ReverseSubtract: return VK_BLEND_OP_REVERSE_SUBTRACT;
case BlendEquation::Subtract: return VK_BLEND_OP_SUBTRACT;
}
NazaraError("Unhandled BlendEquation 0x" + NumberToString(UnderlyingCast(blendEquation), 16));
return {};
}
inline VkBlendFactor ToVulkan(BlendFunc blendFunc)
{
switch (blendFunc)
{
case BlendFunc::ConstantAlpha: return VK_BLEND_FACTOR_CONSTANT_ALPHA;
case BlendFunc::ConstantColor: return VK_BLEND_FACTOR_CONSTANT_COLOR;
case BlendFunc::DstAlpha: return VK_BLEND_FACTOR_DST_ALPHA;
case BlendFunc::DstColor: return VK_BLEND_FACTOR_DST_COLOR;
case BlendFunc::InvConstantAlpha: return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA;
case BlendFunc::InvConstantColor: return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR;
case BlendFunc::InvDstAlpha: return VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA;
case BlendFunc::InvDstColor: return VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR;
case BlendFunc::InvSrcAlpha: return VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
case BlendFunc::InvSrcColor: return VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
case BlendFunc::SrcAlpha: return VK_BLEND_FACTOR_SRC_ALPHA;
case BlendFunc::SrcColor: return VK_BLEND_FACTOR_SRC_COLOR;
case BlendFunc::One: return VK_BLEND_FACTOR_ONE;
case BlendFunc::Zero: return VK_BLEND_FACTOR_ZERO;
}
NazaraError("Unhandled BlendFunc 0x" + NumberToString(UnderlyingCast(blendFunc), 16));
return {};
}
inline VkBufferUsageFlags ToVulkan(BufferType bufferType)
{
switch (bufferType)
@ -154,7 +193,7 @@ namespace Nz
return accessBits;
}
VkPipelineStageFlagBits ToVulkan(PipelineStage pipelineStage)
inline VkPipelineStageFlagBits ToVulkan(PipelineStage pipelineStage)
{
switch (pipelineStage)
{
@ -178,7 +217,7 @@ namespace Nz
return {};
}
VkPipelineStageFlags ToVulkan(PipelineStageFlags pipelineStages)
inline VkPipelineStageFlags ToVulkan(PipelineStageFlags pipelineStages)
{
VkShaderStageFlags pipelineStageBits = 0;
for (int i = 0; i <= UnderlyingCast(PipelineStage::Max); ++i)
@ -191,7 +230,7 @@ namespace Nz
return pipelineStageBits;
}
VkFormat ToVulkan(PixelFormat pixelFormat)
inline VkFormat ToVulkan(PixelFormat pixelFormat)
{
switch (pixelFormat)
{
@ -334,7 +373,7 @@ namespace Nz
return {};
}
VkImageLayout ToVulkan(TextureLayout textureLayout)
inline VkImageLayout ToVulkan(TextureLayout textureLayout)
{
switch (textureLayout)
{
@ -352,7 +391,7 @@ namespace Nz
return {};
}
VkImageUsageFlagBits ToVulkan(TextureUsage textureLayout)
inline VkImageUsageFlagBits ToVulkan(TextureUsage textureLayout)
{
switch (textureLayout)
{
@ -368,7 +407,7 @@ namespace Nz
return {};
}
VkImageUsageFlags ToVulkan(TextureUsageFlags textureLayout)
inline VkImageUsageFlags ToVulkan(TextureUsageFlags textureLayout)
{
VkImageUsageFlags imageUsageBits = 0;
for (int i = 0; i <= UnderlyingCast(TextureUsage::Max); ++i)

View File

@ -439,12 +439,24 @@ namespace Nz::GL
if (renderStates.blending)
{
if (m_state.renderStates.dstBlend != renderStates.dstBlend ||
m_state.renderStates.srcBlend != renderStates.srcBlend)
auto& currentBlend = m_state.renderStates.blend;
const auto& targetBlend = renderStates.blend;
if (currentBlend.modeColor != targetBlend.modeColor || currentBlend.modeAlpha != targetBlend.modeAlpha)
{
glBlendFunc(ToOpenGL(renderStates.srcBlend), ToOpenGL(renderStates.dstBlend));
m_state.renderStates.dstBlend = renderStates.dstBlend;
m_state.renderStates.srcBlend = renderStates.srcBlend;
glBlendEquationSeparate(ToOpenGL(targetBlend.modeColor), ToOpenGL(targetBlend.modeAlpha));
currentBlend.modeAlpha = targetBlend.modeAlpha;
currentBlend.modeColor = targetBlend.modeColor;
}
if (currentBlend.dstAlpha != targetBlend.dstAlpha || currentBlend.dstColor != targetBlend.dstColor ||
currentBlend.srcAlpha != targetBlend.srcAlpha || currentBlend.srcColor != targetBlend.srcColor)
{
glBlendFuncSeparate(ToOpenGL(targetBlend.srcColor), ToOpenGL(targetBlend.dstColor), ToOpenGL(targetBlend.srcAlpha), ToOpenGL(targetBlend.dstAlpha));
currentBlend.dstAlpha = targetBlend.dstAlpha;
currentBlend.dstColor = targetBlend.dstColor;
currentBlend.srcAlpha = targetBlend.srcAlpha;
currentBlend.srcColor = targetBlend.srcColor;
}
}

View File

@ -140,8 +140,12 @@ namespace Nz
// Some default settings
data.SetParameter(MaterialData::Blending, true);
data.SetParameter(MaterialData::DepthWrite, true);
data.SetParameter(MaterialData::DstBlend, static_cast<long long>(BlendFunc_InvSrcAlpha));
data.SetParameter(MaterialData::SrcBlend, static_cast<long long>(BlendFunc_SrcAlpha));
data.SetParameter(MaterialData::BlendDstAlpha, static_cast<long long>(BlendFunc::Zero));
data.SetParameter(MaterialData::BlendDstColor, static_cast<long long>(BlendFunc::InvSrcAlpha));
data.SetParameter(MaterialData::BlendModeAlpha, static_cast<long long>(BlendEquation::Add));
data.SetParameter(MaterialData::BlendModeColor, static_cast<long long>(BlendEquation::Add));
data.SetParameter(MaterialData::BlendSrcAlpha, static_cast<long long>(BlendFunc::One));
data.SetParameter(MaterialData::BlendSrcColor, static_cast<long long>(BlendFunc::SrcAlpha));
}
it = materialCache.emplace(matName, std::move(data)).first;

View File

@ -57,11 +57,12 @@ namespace Nz
if (pipelineInfo.blending)
{
//TODO
/*switch (pipelineInfo.dstBlend)
{
blendState.dstAlphaBlendFactor
}*/
colorBlendState.srcColorBlendFactor = ToVulkan(pipelineInfo.blend.srcColor);
colorBlendState.dstColorBlendFactor = ToVulkan(pipelineInfo.blend.dstColor);
colorBlendState.colorBlendOp = ToVulkan(pipelineInfo.blend.modeColor);
colorBlendState.srcAlphaBlendFactor = ToVulkan(pipelineInfo.blend.srcAlpha);
colorBlendState.dstAlphaBlendFactor = ToVulkan(pipelineInfo.blend.dstAlpha);
colorBlendState.alphaBlendOp = ToVulkan(pipelineInfo.blend.modeAlpha);
}
else
{