Graphics: Add DepthMaterial
This commit is contained in:
@@ -94,107 +94,115 @@ namespace Nz
|
||||
colorPtr[3] = diffuse.a / 255.f;
|
||||
}
|
||||
|
||||
bool BasicMaterial::Initialize()
|
||||
MaterialSettings::Builder BasicMaterial::Build(const UniformOffsets& offsets, std::vector<UInt8> defaultValues, std::vector<std::shared_ptr<UberShader>> uberShaders, std::size_t* uniformBlockIndex, OptionIndexes* optionIndexes, TextureIndexes* textureIndexes)
|
||||
{
|
||||
FieldOffsets fieldOffsets(StructLayout::Std140);
|
||||
|
||||
s_uniformOffsets.alphaThreshold = fieldOffsets.AddField(StructFieldType::Float1);
|
||||
s_uniformOffsets.diffuseColor = fieldOffsets.AddField(StructFieldType::Float4);
|
||||
s_uniformOffsets.totalSize = fieldOffsets.GetSize();
|
||||
|
||||
MaterialSettings::Builder settings;
|
||||
|
||||
std::vector<MaterialSettings::UniformVariable> variables;
|
||||
variables.assign({
|
||||
{
|
||||
if (offsets.alphaThreshold != std::numeric_limits<std::size_t>::max())
|
||||
{
|
||||
variables.push_back({
|
||||
"AlphaThreshold",
|
||||
s_uniformOffsets.alphaThreshold
|
||||
},
|
||||
{
|
||||
offsets.alphaThreshold
|
||||
});
|
||||
}
|
||||
|
||||
if (offsets.diffuseColor != std::numeric_limits<std::size_t>::max())
|
||||
{
|
||||
variables.push_back({
|
||||
"DiffuseColor",
|
||||
s_uniformOffsets.diffuseColor
|
||||
}
|
||||
});
|
||||
offsets.diffuseColor
|
||||
});
|
||||
}
|
||||
|
||||
if (offsets.alphaThreshold != std::numeric_limits<std::size_t>::max())
|
||||
AccessByOffset<float&>(defaultValues.data(), offsets.alphaThreshold) = 0.2f;
|
||||
|
||||
static_assert(sizeof(Vector4f) == 4 * sizeof(float), "Vector4f is expected to be exactly 4 floats wide");
|
||||
if (offsets.diffuseColor != std::numeric_limits<std::size_t>::max())
|
||||
AccessByOffset<Vector4f&>(defaultValues.data(), offsets.diffuseColor) = Vector4f(1.f, 1.f, 1.f, 1.f);
|
||||
|
||||
// Textures
|
||||
if (textureIndexes)
|
||||
textureIndexes->alpha = settings.textures.size();
|
||||
|
||||
std::vector<UInt8> defaultValues(fieldOffsets.GetSize());
|
||||
AccessByOffset<Vector4f&>(defaultValues.data(), s_uniformOffsets.diffuseColor) = Vector4f(1.f, 1.f, 1.f, 1.f);
|
||||
AccessByOffset<float&>(defaultValues.data(), s_uniformOffsets.alphaThreshold) = 0.2f;
|
||||
|
||||
s_textureIndexes.alpha = settings.textures.size();
|
||||
settings.textures.push_back({
|
||||
2,
|
||||
"Alpha",
|
||||
ImageType::E2D
|
||||
});
|
||||
|
||||
s_textureIndexes.diffuse = settings.textures.size();
|
||||
if (textureIndexes)
|
||||
textureIndexes->diffuse = settings.textures.size();
|
||||
|
||||
settings.textures.push_back({
|
||||
1,
|
||||
"Diffuse",
|
||||
ImageType::E2D
|
||||
});
|
||||
|
||||
s_uniformBlockIndex = settings.uniformBlocks.size();
|
||||
if (uniformBlockIndex)
|
||||
*uniformBlockIndex = settings.uniformBlocks.size();
|
||||
|
||||
settings.uniformBlocks.push_back({
|
||||
0,
|
||||
"BasicSettings",
|
||||
fieldOffsets.GetSize(),
|
||||
offsets.totalSize,
|
||||
std::move(variables),
|
||||
std::move(defaultValues)
|
||||
});
|
||||
|
||||
// Shaders
|
||||
ShaderAst::StatementPtr shaderAst = ShaderLang::Parse(std::string_view(reinterpret_cast<const char*>(r_shader), sizeof(r_shader)));
|
||||
auto uberShader = std::make_shared<UberShader>(ShaderStageType::Fragment | ShaderStageType::Vertex, shaderAst);
|
||||
|
||||
settings.shaders.emplace_back(uberShader);
|
||||
settings.shaders = std::move(uberShaders);
|
||||
|
||||
// Options
|
||||
|
||||
// HasDiffuseMap
|
||||
{
|
||||
std::array<UInt64, ShaderStageTypeCount> shaderOptions;
|
||||
shaderOptions.fill(0);
|
||||
shaderOptions[UnderlyingCast(ShaderStageType::Fragment)] = uberShader->GetOptionFlagByName("HAS_DIFFUSE_TEXTURE");
|
||||
shaderOptions[UnderlyingCast(ShaderStageType::Vertex)] = uberShader->GetOptionFlagByName("HAS_DIFFUSE_TEXTURE");
|
||||
if (optionIndexes)
|
||||
optionIndexes->hasDiffuseMap = settings.options.size();
|
||||
|
||||
s_optionIndexes.hasDiffuseMap = settings.options.size();
|
||||
settings.options.push_back({
|
||||
"HasDiffuseMap",
|
||||
shaderOptions
|
||||
});
|
||||
}
|
||||
MaterialSettings::BuildOption(settings.options, settings.shaders, "HasDiffuseMap", "HAS_DIFFUSE_TEXTURE");
|
||||
|
||||
// HasAlphaMap
|
||||
{
|
||||
std::array<UInt64, ShaderStageTypeCount> shaderOptions;
|
||||
shaderOptions.fill(0);
|
||||
shaderOptions[UnderlyingCast(ShaderStageType::Fragment)] = uberShader->GetOptionFlagByName("HAS_ALPHA_TEXTURE");
|
||||
shaderOptions[UnderlyingCast(ShaderStageType::Vertex)] = uberShader->GetOptionFlagByName("HAS_ALPHA_TEXTURE");
|
||||
if (optionIndexes)
|
||||
optionIndexes->hasAlphaMap = settings.options.size();
|
||||
|
||||
s_optionIndexes.hasAlphaMap = settings.options.size();
|
||||
settings.options.push_back({
|
||||
"HasAlphaMap",
|
||||
shaderOptions
|
||||
});
|
||||
}
|
||||
MaterialSettings::BuildOption(settings.options, settings.shaders, "HasAlphaMap", "HAS_ALPHA_TEXTURE");
|
||||
|
||||
// AlphaTest
|
||||
{
|
||||
std::array<UInt64, ShaderStageTypeCount> shaderOptions;
|
||||
shaderOptions.fill(0);
|
||||
shaderOptions[UnderlyingCast(ShaderStageType::Fragment)] = uberShader->GetOptionFlagByName("ALPHA_TEST");
|
||||
if (optionIndexes)
|
||||
optionIndexes->alphaTest = settings.options.size();
|
||||
|
||||
s_optionIndexes.alphaTest = settings.options.size();
|
||||
settings.options.push_back({
|
||||
"AlphaTest",
|
||||
shaderOptions
|
||||
});
|
||||
}
|
||||
MaterialSettings::BuildOption(settings.options, settings.shaders, "AlphaTest", "ALPHA_TEST");
|
||||
|
||||
s_materialSettings = std::make_shared<MaterialSettings>(std::move(settings));
|
||||
return settings;
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<UberShader>> BasicMaterial::BuildShaders()
|
||||
{
|
||||
ShaderAst::StatementPtr shaderAst = ShaderLang::Parse(std::string_view(reinterpret_cast<const char*>(r_shader), sizeof(r_shader)));
|
||||
auto shader = std::make_shared<UberShader>(ShaderStageType::Fragment | ShaderStageType::Vertex, shaderAst);
|
||||
|
||||
return { std::move(shader) };
|
||||
}
|
||||
|
||||
auto BasicMaterial::BuildUniformOffsets() -> std::pair<UniformOffsets, FieldOffsets>
|
||||
{
|
||||
FieldOffsets fieldOffsets(StructLayout::Std140);
|
||||
|
||||
UniformOffsets uniformOffsets;
|
||||
uniformOffsets.alphaThreshold = fieldOffsets.AddField(StructFieldType::Float1);
|
||||
uniformOffsets.diffuseColor = fieldOffsets.AddField(StructFieldType::Float4);
|
||||
uniformOffsets.totalSize = fieldOffsets.GetSize();
|
||||
|
||||
return std::make_pair(std::move(uniformOffsets), std::move(fieldOffsets));
|
||||
}
|
||||
|
||||
bool BasicMaterial::Initialize()
|
||||
{
|
||||
std::tie(s_uniformOffsets, std::ignore) = BuildUniformOffsets();
|
||||
|
||||
std::vector<UInt8> defaultValues(s_uniformOffsets.totalSize);
|
||||
s_materialSettings = std::make_shared<MaterialSettings>(Build(s_uniformOffsets, std::move(defaultValues), BuildShaders(), &s_uniformBlockIndex, &s_optionIndexes, &s_textureIndexes));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
44
src/Nazara/Graphics/DepthMaterial.cpp
Normal file
44
src/Nazara/Graphics/DepthMaterial.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Graphics module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Graphics/DepthMaterial.hpp>
|
||||
#include <Nazara/Shader/ShaderLangParser.hpp>
|
||||
#include <Nazara/Utility/FieldOffsets.hpp>
|
||||
#include <Nazara/Graphics/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
namespace
|
||||
{
|
||||
const UInt8 r_shader[] = {
|
||||
#include <Nazara/Graphics/Resources/Shaders/depth_material.nzsl.h>
|
||||
};
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<UberShader>> DepthMaterial::BuildShaders()
|
||||
{
|
||||
ShaderAst::StatementPtr shaderAst = ShaderLang::Parse(std::string_view(reinterpret_cast<const char*>(r_shader), sizeof(r_shader)));
|
||||
auto shader = std::make_shared<UberShader>(ShaderStageType::Fragment | ShaderStageType::Vertex, shaderAst);
|
||||
|
||||
return { std::move(shader) };
|
||||
}
|
||||
|
||||
bool DepthMaterial::Initialize()
|
||||
{
|
||||
UniformOffsets offsets;
|
||||
std::tie(offsets, std::ignore) = BuildUniformOffsets();
|
||||
|
||||
std::vector<UInt8> defaultValues(offsets.totalSize);
|
||||
s_materialSettings = std::make_shared<MaterialSettings>(Build(offsets, std::move(defaultValues), BuildShaders()));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DepthMaterial::Uninitialize()
|
||||
{
|
||||
s_materialSettings.reset();
|
||||
}
|
||||
|
||||
std::shared_ptr<MaterialSettings> DepthMaterial::s_materialSettings;
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <Nazara/Core/File.hpp>
|
||||
#include <Nazara/Core/Log.hpp>
|
||||
#include <Nazara/Graphics/BasicMaterial.hpp>
|
||||
#include <Nazara/Graphics/DepthMaterial.hpp>
|
||||
#include <Nazara/Graphics/MaterialPass.hpp>
|
||||
#include <Nazara/Graphics/MaterialSettings.hpp>
|
||||
#include <Nazara/Graphics/PhongLightingMaterial.hpp>
|
||||
@@ -78,6 +79,7 @@ namespace Nz
|
||||
bool MaterialPipeline::Initialize()
|
||||
{
|
||||
BasicMaterial::Initialize();
|
||||
DepthMaterial::Initialize();
|
||||
PhongLightingMaterial::Initialize();
|
||||
|
||||
return true;
|
||||
@@ -87,6 +89,7 @@ namespace Nz
|
||||
{
|
||||
s_pipelineCache.clear();
|
||||
PhongLightingMaterial::Uninitialize();
|
||||
DepthMaterial::Uninitialize();
|
||||
BasicMaterial::Uninitialize();
|
||||
}
|
||||
|
||||
|
||||
93
src/Nazara/Graphics/Resources/Shaders/depth_material.nzsl
Normal file
93
src/Nazara/Graphics/Resources/Shaders/depth_material.nzsl
Normal file
@@ -0,0 +1,93 @@
|
||||
option HAS_DIFFUSE_TEXTURE: bool;
|
||||
option HAS_ALPHA_TEXTURE: bool;
|
||||
option ALPHA_TEST: bool;
|
||||
|
||||
const HasUV = ALPHA_TEST && (HAS_DIFFUSE_TEXTURE || HAS_ALPHA_TEXTURE);
|
||||
|
||||
[layout(std140)]
|
||||
struct BasicSettings
|
||||
{
|
||||
AlphaThreshold: f32,
|
||||
DiffuseColor: vec4<f32>
|
||||
}
|
||||
|
||||
[layout(std140)]
|
||||
struct InstanceData
|
||||
{
|
||||
worldMatrix: mat4<f32>,
|
||||
invWorldMatrix: mat4<f32>
|
||||
}
|
||||
|
||||
[layout(std140)]
|
||||
struct ViewerData
|
||||
{
|
||||
projectionMatrix: mat4<f32>,
|
||||
invProjectionMatrix: mat4<f32>,
|
||||
viewMatrix: mat4<f32>,
|
||||
invViewMatrix: mat4<f32>,
|
||||
viewProjMatrix: mat4<f32>,
|
||||
invViewProjMatrix: mat4<f32>,
|
||||
renderTargetSize: vec2<f32>,
|
||||
invRenderTargetSize: vec2<f32>,
|
||||
eyePosition: vec3<f32>
|
||||
}
|
||||
|
||||
external
|
||||
{
|
||||
[set(0), binding(0)] viewerData: uniform<ViewerData>,
|
||||
[set(1), binding(0)] instanceData: uniform<InstanceData>,
|
||||
[set(2), binding(0)] settings: uniform<BasicSettings>,
|
||||
[set(2), binding(2)] MaterialAlphaMap: sampler2D<f32>,
|
||||
[set(2), binding(1)] MaterialDiffuseMap: sampler2D<f32>
|
||||
}
|
||||
|
||||
// Fragment stage
|
||||
struct FragIn
|
||||
{
|
||||
[location(0), cond(HasUV)] uv: vec2<f32>
|
||||
}
|
||||
|
||||
[entry(frag), cond(ALPHA_TEST)]
|
||||
fn main(input: FragIn)
|
||||
{
|
||||
let alpha = settings.DiffuseColor.a;
|
||||
const if (HAS_DIFFUSE_TEXTURE)
|
||||
// TODO: alpha *= MaterialDiffuseMap.Sample(input.uv).a;
|
||||
alpha = alpha * MaterialDiffuseMap.Sample(input.uv).a;
|
||||
|
||||
const if (HAS_ALPHA_TEXTURE)
|
||||
// TODO: alpha *= MaterialAlphaMap.Sample(input.uv).x
|
||||
alpha = alpha * MaterialAlphaMap.Sample(input.uv).x;
|
||||
|
||||
if (alpha < settings.AlphaThreshold)
|
||||
discard;
|
||||
}
|
||||
|
||||
// Dummy fragment shader (TODO: Add a way to delete stage?)
|
||||
[entry(frag), cond(!ALPHA_TEST)]
|
||||
fn main() {}
|
||||
|
||||
// Vertex stage
|
||||
struct VertIn
|
||||
{
|
||||
[location(0)] pos: vec3<f32>,
|
||||
[location(1), cond(HasUV)] uv: vec2<f32>
|
||||
}
|
||||
|
||||
struct VertOut
|
||||
{
|
||||
[location(0), cond(HasUV)] uv: vec2<f32>,
|
||||
[builtin(position)] position: vec4<f32>
|
||||
}
|
||||
|
||||
[entry(vert)]
|
||||
fn main(input: VertIn) -> VertOut
|
||||
{
|
||||
let output: VertOut;
|
||||
output.position = viewerData.viewProjMatrix * instanceData.worldMatrix * vec4<f32>(input.pos, 1.0);
|
||||
|
||||
const if (HasUV)
|
||||
output.uv = input.uv;
|
||||
|
||||
return output;
|
||||
}
|
||||
Reference in New Issue
Block a user