refactor: externalize builtin forward-lit shader asset
This commit is contained in:
@@ -0,0 +1,36 @@
|
|||||||
|
// XC_BUILTIN_FORWARD_LIT_OPENGL_PS
|
||||||
|
#version 430
|
||||||
|
layout(binding = 1) uniform sampler2D uBaseColorTexture;
|
||||||
|
|
||||||
|
layout(std140, binding = 1) uniform PerObjectConstants {
|
||||||
|
mat4 gProjectionMatrix;
|
||||||
|
mat4 gViewMatrix;
|
||||||
|
mat4 gModelMatrix;
|
||||||
|
mat4 gNormalMatrix;
|
||||||
|
vec4 gMainLightDirectionAndIntensity;
|
||||||
|
vec4 gMainLightColorAndFlags;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(std140, binding = 2) uniform MaterialConstants {
|
||||||
|
vec4 gBaseColorFactor;
|
||||||
|
};
|
||||||
|
|
||||||
|
in vec3 vNormalWS;
|
||||||
|
in vec2 vTexCoord;
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 fragColor;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec4 baseColor = texture(uBaseColorTexture, vTexCoord) * gBaseColorFactor;
|
||||||
|
if (gMainLightColorAndFlags.w < 0.5) {
|
||||||
|
fragColor = baseColor;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 normalWS = normalize(vNormalWS);
|
||||||
|
vec3 directionToLightWS = normalize(gMainLightDirectionAndIntensity.xyz);
|
||||||
|
float diffuse = max(dot(normalWS, directionToLightWS), 0.0);
|
||||||
|
vec3 lighting = vec3(0.28) +
|
||||||
|
gMainLightColorAndFlags.rgb * (diffuse * gMainLightDirectionAndIntensity.w);
|
||||||
|
fragColor = vec4(baseColor.rgb * lighting, baseColor.a);
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
// XC_BUILTIN_FORWARD_LIT_VULKAN_PS
|
||||||
|
#version 450
|
||||||
|
layout(set = 3, binding = 0) uniform texture2D uBaseColorTexture;
|
||||||
|
layout(set = 4, binding = 0) uniform sampler uLinearSampler;
|
||||||
|
|
||||||
|
layout(set = 1, binding = 0, std140) uniform PerObjectConstants {
|
||||||
|
mat4 gProjectionMatrix;
|
||||||
|
mat4 gViewMatrix;
|
||||||
|
mat4 gModelMatrix;
|
||||||
|
mat4 gNormalMatrix;
|
||||||
|
vec4 gMainLightDirectionAndIntensity;
|
||||||
|
vec4 gMainLightColorAndFlags;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(set = 2, binding = 0, std140) uniform MaterialConstants {
|
||||||
|
vec4 gBaseColorFactor;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(location = 0) in vec3 vNormalWS;
|
||||||
|
layout(location = 1) in vec2 vTexCoord;
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 fragColor;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec4 baseColor = texture(sampler2D(uBaseColorTexture, uLinearSampler), vTexCoord) * gBaseColorFactor;
|
||||||
|
if (gMainLightColorAndFlags.w < 0.5) {
|
||||||
|
fragColor = baseColor;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 normalWS = normalize(vNormalWS);
|
||||||
|
vec3 directionToLightWS = normalize(gMainLightDirectionAndIntensity.xyz);
|
||||||
|
float diffuse = max(dot(normalWS, directionToLightWS), 0.0);
|
||||||
|
vec3 lighting = vec3(0.28) +
|
||||||
|
gMainLightColorAndFlags.rgb * (diffuse * gMainLightDirectionAndIntensity.w);
|
||||||
|
fragColor = vec4(baseColor.rgb * lighting, baseColor.a);
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
// XC_BUILTIN_FORWARD_LIT_D3D12_PS
|
||||||
|
Texture2D gBaseColorTexture : register(t1);
|
||||||
|
SamplerState gLinearSampler : register(s1);
|
||||||
|
|
||||||
|
cbuffer PerObjectConstants : register(b1) {
|
||||||
|
float4x4 gProjectionMatrix;
|
||||||
|
float4x4 gViewMatrix;
|
||||||
|
float4x4 gModelMatrix;
|
||||||
|
float4x4 gNormalMatrix;
|
||||||
|
float4 gMainLightDirectionAndIntensity;
|
||||||
|
float4 gMainLightColorAndFlags;
|
||||||
|
};
|
||||||
|
|
||||||
|
cbuffer MaterialConstants : register(b2) {
|
||||||
|
float4 gBaseColorFactor;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PSInput {
|
||||||
|
float4 position : SV_POSITION;
|
||||||
|
float3 normalWS : TEXCOORD0;
|
||||||
|
float2 texcoord : TEXCOORD1;
|
||||||
|
};
|
||||||
|
|
||||||
|
float4 MainPS(PSInput input) : SV_TARGET {
|
||||||
|
float4 baseColor = gBaseColorTexture.Sample(gLinearSampler, input.texcoord) * gBaseColorFactor;
|
||||||
|
if (gMainLightColorAndFlags.a < 0.5f) {
|
||||||
|
return baseColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
float3 normalWS = normalize(input.normalWS);
|
||||||
|
float3 directionToLightWS = normalize(gMainLightDirectionAndIntensity.xyz);
|
||||||
|
float diffuse = saturate(dot(normalWS, directionToLightWS));
|
||||||
|
float3 lighting = float3(0.28f, 0.28f, 0.28f) +
|
||||||
|
gMainLightColorAndFlags.rgb * (diffuse * gMainLightDirectionAndIntensity.w);
|
||||||
|
return float4(baseColor.rgb * lighting, baseColor.a);
|
||||||
|
}
|
||||||
53
engine/assets/builtin/shaders/forward-lit/forward-lit.shader
Normal file
53
engine/assets/builtin/shaders/forward-lit/forward-lit.shader
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
{
|
||||||
|
"name": "Builtin Forward Lit",
|
||||||
|
"passes": [
|
||||||
|
{
|
||||||
|
"name": "ForwardLit",
|
||||||
|
"tags": {
|
||||||
|
"LightMode": "ForwardBase"
|
||||||
|
},
|
||||||
|
"variants": [
|
||||||
|
{
|
||||||
|
"stage": "Vertex",
|
||||||
|
"backend": "D3D12",
|
||||||
|
"language": "HLSL",
|
||||||
|
"source": "forward-lit.vs.hlsl",
|
||||||
|
"entryPoint": "MainVS",
|
||||||
|
"profile": "vs_5_0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"stage": "Fragment",
|
||||||
|
"backend": "D3D12",
|
||||||
|
"language": "HLSL",
|
||||||
|
"source": "forward-lit.ps.hlsl",
|
||||||
|
"entryPoint": "MainPS",
|
||||||
|
"profile": "ps_5_0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"stage": "Vertex",
|
||||||
|
"backend": "OpenGL",
|
||||||
|
"language": "GLSL",
|
||||||
|
"source": "forward-lit.vert.glsl"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"stage": "Fragment",
|
||||||
|
"backend": "OpenGL",
|
||||||
|
"language": "GLSL",
|
||||||
|
"source": "forward-lit.frag.glsl"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"stage": "Vertex",
|
||||||
|
"backend": "Vulkan",
|
||||||
|
"language": "GLSL",
|
||||||
|
"source": "forward-lit.vert.vk.glsl"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"stage": "Fragment",
|
||||||
|
"backend": "Vulkan",
|
||||||
|
"language": "GLSL",
|
||||||
|
"source": "forward-lit.frag.vk.glsl"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
// XC_BUILTIN_FORWARD_LIT_OPENGL_VS
|
||||||
|
#version 430
|
||||||
|
layout(location = 0) in vec3 aPosition;
|
||||||
|
layout(location = 1) in vec3 aNormal;
|
||||||
|
layout(location = 2) in vec2 aTexCoord;
|
||||||
|
|
||||||
|
layout(std140, binding = 1) uniform PerObjectConstants {
|
||||||
|
mat4 gProjectionMatrix;
|
||||||
|
mat4 gViewMatrix;
|
||||||
|
mat4 gModelMatrix;
|
||||||
|
mat4 gNormalMatrix;
|
||||||
|
vec4 gMainLightDirectionAndIntensity;
|
||||||
|
vec4 gMainLightColorAndFlags;
|
||||||
|
};
|
||||||
|
|
||||||
|
out vec3 vNormalWS;
|
||||||
|
out vec2 vTexCoord;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec4 positionWS = gModelMatrix * vec4(aPosition, 1.0);
|
||||||
|
vec4 positionVS = gViewMatrix * positionWS;
|
||||||
|
gl_Position = gProjectionMatrix * positionVS;
|
||||||
|
vNormalWS = mat3(gNormalMatrix) * aNormal;
|
||||||
|
vTexCoord = aTexCoord;
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
// XC_BUILTIN_FORWARD_LIT_VULKAN_VS
|
||||||
|
#version 450
|
||||||
|
layout(location = 0) in vec3 aPosition;
|
||||||
|
layout(location = 1) in vec3 aNormal;
|
||||||
|
layout(location = 2) in vec2 aTexCoord;
|
||||||
|
|
||||||
|
layout(set = 1, binding = 0, std140) uniform PerObjectConstants {
|
||||||
|
mat4 gProjectionMatrix;
|
||||||
|
mat4 gViewMatrix;
|
||||||
|
mat4 gModelMatrix;
|
||||||
|
mat4 gNormalMatrix;
|
||||||
|
vec4 gMainLightDirectionAndIntensity;
|
||||||
|
vec4 gMainLightColorAndFlags;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(location = 0) out vec3 vNormalWS;
|
||||||
|
layout(location = 1) out vec2 vTexCoord;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec4 positionWS = gModelMatrix * vec4(aPosition, 1.0);
|
||||||
|
vec4 positionVS = gViewMatrix * positionWS;
|
||||||
|
gl_Position = gProjectionMatrix * positionVS;
|
||||||
|
vNormalWS = mat3(gNormalMatrix) * aNormal;
|
||||||
|
vTexCoord = aTexCoord;
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
// XC_BUILTIN_FORWARD_LIT_D3D12_VS
|
||||||
|
Texture2D gBaseColorTexture : register(t1);
|
||||||
|
SamplerState gLinearSampler : register(s1);
|
||||||
|
|
||||||
|
cbuffer PerObjectConstants : register(b1) {
|
||||||
|
float4x4 gProjectionMatrix;
|
||||||
|
float4x4 gViewMatrix;
|
||||||
|
float4x4 gModelMatrix;
|
||||||
|
float4x4 gNormalMatrix;
|
||||||
|
float4 gMainLightDirectionAndIntensity;
|
||||||
|
float4 gMainLightColorAndFlags;
|
||||||
|
};
|
||||||
|
|
||||||
|
cbuffer MaterialConstants : register(b2) {
|
||||||
|
float4 gBaseColorFactor;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VSInput {
|
||||||
|
float3 position : POSITION;
|
||||||
|
float3 normal : NORMAL;
|
||||||
|
float2 texcoord : TEXCOORD0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PSInput {
|
||||||
|
float4 position : SV_POSITION;
|
||||||
|
float3 normalWS : TEXCOORD0;
|
||||||
|
float2 texcoord : TEXCOORD1;
|
||||||
|
};
|
||||||
|
|
||||||
|
PSInput MainVS(VSInput input) {
|
||||||
|
PSInput output;
|
||||||
|
float4 positionWS = mul(gModelMatrix, float4(input.position, 1.0f));
|
||||||
|
float4 positionVS = mul(gViewMatrix, positionWS);
|
||||||
|
output.position = mul(gProjectionMatrix, positionVS);
|
||||||
|
output.normalWS = mul((float3x3)gNormalMatrix, input.normal);
|
||||||
|
output.texcoord = input.texcoord;
|
||||||
|
return output;
|
||||||
|
}
|
||||||
@@ -7,10 +7,13 @@
|
|||||||
#include <XCEngine/Resources/Material/Material.h>
|
#include <XCEngine/Resources/Material/Material.h>
|
||||||
#include <XCEngine/Resources/Mesh/Mesh.h>
|
#include <XCEngine/Resources/Mesh/Mesh.h>
|
||||||
#include <XCEngine/Resources/Shader/Shader.h>
|
#include <XCEngine/Resources/Shader/Shader.h>
|
||||||
|
#include <XCEngine/Resources/Shader/ShaderLoader.h>
|
||||||
#include <XCEngine/Resources/Texture/Texture.h>
|
#include <XCEngine/Resources/Texture/Texture.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <system_error>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace XCEngine {
|
namespace XCEngine {
|
||||||
@@ -36,6 +39,87 @@ struct MeshBuffers {
|
|||||||
std::vector<Core::uint32> indices;
|
std::vector<Core::uint32> indices;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
size_t CalculateBuiltinShaderMemorySize(const Shader& shader);
|
||||||
|
|
||||||
|
constexpr const char* kBuiltinForwardLitShaderManifestRelativePath =
|
||||||
|
"engine/assets/builtin/shaders/forward-lit/forward-lit.shader";
|
||||||
|
|
||||||
|
Containers::String NormalizeBuiltinAssetPath(const std::filesystem::path& path) {
|
||||||
|
return Containers::String(path.lexically_normal().generic_string().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TryResolveBuiltinAssetPathFromAnchor(
|
||||||
|
const std::filesystem::path& anchor,
|
||||||
|
const std::filesystem::path& relativePath,
|
||||||
|
std::filesystem::path& outPath) {
|
||||||
|
if (anchor.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::error_code ec;
|
||||||
|
std::filesystem::path current = anchor.lexically_normal();
|
||||||
|
if (std::filesystem::is_regular_file(current, ec)) {
|
||||||
|
current = current.parent_path();
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!current.empty()) {
|
||||||
|
const std::filesystem::path candidate = (current / relativePath).lexically_normal();
|
||||||
|
if (std::filesystem::exists(candidate, ec)) {
|
||||||
|
outPath = candidate;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::filesystem::path parent = current.parent_path();
|
||||||
|
if (parent == current) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
current = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TryResolveBuiltinForwardLitShaderManifestPath(Containers::String& outPath) {
|
||||||
|
const std::filesystem::path relativePath(kBuiltinForwardLitShaderManifestRelativePath);
|
||||||
|
std::filesystem::path resolvedPath;
|
||||||
|
std::error_code ec;
|
||||||
|
|
||||||
|
if (TryResolveBuiltinAssetPathFromAnchor(std::filesystem::current_path(ec), relativePath, resolvedPath)) {
|
||||||
|
outPath = NormalizeBuiltinAssetPath(resolvedPath);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Containers::String& resourceRoot = ResourceManager::Get().GetResourceRoot();
|
||||||
|
if (!resourceRoot.Empty() &&
|
||||||
|
TryResolveBuiltinAssetPathFromAnchor(std::filesystem::path(resourceRoot.CStr()), relativePath, resolvedPath)) {
|
||||||
|
outPath = NormalizeBuiltinAssetPath(resolvedPath);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TryResolveBuiltinAssetPathFromAnchor(std::filesystem::path(__FILE__), relativePath, resolvedPath)) {
|
||||||
|
outPath = NormalizeBuiltinAssetPath(resolvedPath);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Shader* LoadBuiltinShaderFromManifest(
|
||||||
|
const Containers::String& builtinPath,
|
||||||
|
const Containers::String& manifestPath) {
|
||||||
|
ShaderLoader shaderLoader;
|
||||||
|
LoadResult result = shaderLoader.Load(manifestPath);
|
||||||
|
if (!result || result.resource == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* shader = static_cast<Shader*>(result.resource);
|
||||||
|
shader->m_path = builtinPath;
|
||||||
|
shader->m_guid = ResourceGUID::Generate(builtinPath);
|
||||||
|
shader->m_memorySize = CalculateBuiltinShaderMemorySize(*shader);
|
||||||
|
return shader;
|
||||||
|
}
|
||||||
|
|
||||||
const char kBuiltinForwardHlsl[] = R"(
|
const char kBuiltinForwardHlsl[] = R"(
|
||||||
Texture2D gBaseColorTexture : register(t1);
|
Texture2D gBaseColorTexture : register(t1);
|
||||||
SamplerState gLinearSampler : register(s1);
|
SamplerState gLinearSampler : register(s1);
|
||||||
@@ -1049,6 +1133,13 @@ size_t CalculateBuiltinShaderMemorySize(const Shader& shader) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Shader* BuildBuiltinForwardLitShader(const Containers::String& path) {
|
Shader* BuildBuiltinForwardLitShader(const Containers::String& path) {
|
||||||
|
Containers::String manifestPath;
|
||||||
|
if (TryResolveBuiltinForwardLitShaderManifestPath(manifestPath)) {
|
||||||
|
if (Shader* shader = LoadBuiltinShaderFromManifest(path, manifestPath)) {
|
||||||
|
return shader;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto* shader = new Shader();
|
auto* shader = new Shader();
|
||||||
IResource::ConstructParams params;
|
IResource::ConstructParams params;
|
||||||
params.name = Containers::String("Builtin Forward Lit");
|
params.name = Containers::String("Builtin Forward Lit");
|
||||||
|
|||||||
@@ -264,6 +264,27 @@ TEST(ShaderLoader, LoadBuiltinForwardLitShaderBuildsBackendVariants) {
|
|||||||
EXPECT_NE(shader->FindVariant("ForwardLit", ShaderType::Vertex, ShaderBackend::Vulkan), nullptr);
|
EXPECT_NE(shader->FindVariant("ForwardLit", ShaderType::Vertex, ShaderBackend::Vulkan), nullptr);
|
||||||
EXPECT_NE(shader->FindVariant("ForwardLit", ShaderType::Fragment, ShaderBackend::Vulkan), nullptr);
|
EXPECT_NE(shader->FindVariant("ForwardLit", ShaderType::Fragment, ShaderBackend::Vulkan), nullptr);
|
||||||
|
|
||||||
|
const ShaderStageVariant* d3d12Vertex = shader->FindVariant(
|
||||||
|
"ForwardLit",
|
||||||
|
ShaderType::Vertex,
|
||||||
|
ShaderBackend::D3D12);
|
||||||
|
ASSERT_NE(d3d12Vertex, nullptr);
|
||||||
|
EXPECT_NE(std::string(d3d12Vertex->sourceCode.CStr()).find("XC_BUILTIN_FORWARD_LIT_D3D12_VS"), std::string::npos);
|
||||||
|
|
||||||
|
const ShaderStageVariant* openglFragment = shader->FindVariant(
|
||||||
|
"ForwardLit",
|
||||||
|
ShaderType::Fragment,
|
||||||
|
ShaderBackend::OpenGL);
|
||||||
|
ASSERT_NE(openglFragment, nullptr);
|
||||||
|
EXPECT_NE(std::string(openglFragment->sourceCode.CStr()).find("XC_BUILTIN_FORWARD_LIT_OPENGL_PS"), std::string::npos);
|
||||||
|
|
||||||
|
const ShaderStageVariant* vulkanFragment = shader->FindVariant(
|
||||||
|
"ForwardLit",
|
||||||
|
ShaderType::Fragment,
|
||||||
|
ShaderBackend::Vulkan);
|
||||||
|
ASSERT_NE(vulkanFragment, nullptr);
|
||||||
|
EXPECT_NE(std::string(vulkanFragment->sourceCode.CStr()).find("XC_BUILTIN_FORWARD_LIT_VULKAN_PS"), std::string::npos);
|
||||||
|
|
||||||
delete shader;
|
delete shader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user