diff --git a/engine/assets/builtin/shaders/infinite-grid/infinite-grid.ps.hlsl b/engine/assets/builtin/shaders/infinite-grid/infinite-grid.ps.hlsl new file mode 100644 index 00000000..164da268 --- /dev/null +++ b/engine/assets/builtin/shaders/infinite-grid/infinite-grid.ps.hlsl @@ -0,0 +1,132 @@ +// XC_BUILTIN_INFINITE_GRID_D3D12_PS +cbuffer GridConstants : register(b0) { + float4x4 gViewProjectionMatrix; + float4 gCameraPositionAndScale; + float4 gCameraRightAndFade; + float4 gCameraUpAndTanHalfFov; + float4 gCameraForwardAndAspect; + float4 gViewportNearFar; + float4 gGridTransition; +}; + +struct VSOutput { + float4 position : SV_POSITION; +}; + +float PristineGridLine(float2 uv) { + float2 deriv = max(fwidth(uv), float2(1e-6, 1e-6)); + float2 uvMod = frac(uv); + float2 uvDist = min(uvMod, 1.0 - uvMod); + float2 distInPixels = uvDist / deriv; + float2 lineAlpha = 1.0 - smoothstep(0.0, 1.0, distInPixels); + float density = max(deriv.x, deriv.y); + float densityFade = 1.0 - smoothstep(0.5, 1.0, density); + return max(lineAlpha.x, lineAlpha.y) * densityFade; +} + +float AxisLineAA(float coord, float deriv) { + float distInPixels = abs(coord) / max(deriv, 1e-6); + return 1.0 - smoothstep(0.0, 1.5, distInPixels); +} + +struct GridLayer { + float minor; + float major; +}; + +GridLayer SampleGridLayer(float2 worldPos2D, float baseScale) { + GridLayer layer; + const float2 gridCoord1 = worldPos2D / baseScale; + const float2 gridCoord10 = worldPos2D / (baseScale * 10.0); + const float grid1 = PristineGridLine(gridCoord1); + const float grid10 = PristineGridLine(gridCoord10); + const float2 deriv1 = fwidth(gridCoord1); + const float lodFactor = smoothstep(0.3, 0.6, max(deriv1.x, deriv1.y)); + + layer.major = max(grid10, grid1 * 0.35); + layer.minor = grid1 * (1.0 - lodFactor); + return layer; +} + +struct PSOutput { + float4 color : SV_TARGET0; + float depth : SV_Depth; +}; + +PSOutput MainPS(VSOutput input) { + const float2 viewportSize = max(gViewportNearFar.xy, float2(1.0, 1.0)); + const float scale = max(gCameraPositionAndScale.w, 1e-4); + const float fadeDistance = max(gCameraRightAndFade.w, scale * 10.0); + const float tanHalfFov = max(gCameraUpAndTanHalfFov.w, 1e-4); + const float aspect = max(gCameraForwardAndAspect.w, 1e-4); + const float transitionBlend = saturate(gGridTransition.x); + const float nearClip = gViewportNearFar.z; + const float sceneFarClip = gViewportNearFar.w; + + const float2 ndc = float2( + (input.position.x / viewportSize.x) * 2.0 - 1.0, + 1.0 - (input.position.y / viewportSize.y) * 2.0); + + const float3 cameraPosition = gCameraPositionAndScale.xyz; + const float3 rayDirection = normalize( + gCameraForwardAndAspect.xyz + + ndc.x * aspect * tanHalfFov * gCameraRightAndFade.xyz + + ndc.y * tanHalfFov * gCameraUpAndTanHalfFov.xyz); + + if (abs(rayDirection.y) < 1e-5) { + discard; + } + + const float t = -cameraPosition.y / rayDirection.y; + if (t <= nearClip) { + discard; + } + + const float3 worldPosition = cameraPosition + rayDirection * t; + float depth = 0.999999; + if (t < sceneFarClip) { + const float4 clipPosition = mul(gViewProjectionMatrix, float4(worldPosition, 1.0)); + if (clipPosition.w <= 1e-6) { + discard; + } + + depth = clipPosition.z / clipPosition.w; + if (depth <= 0.0 || depth >= 1.0) { + discard; + } + } + + const float radialFade = + 1.0 - smoothstep(fadeDistance * 0.3, fadeDistance, length(worldPosition - cameraPosition)); + const float normalFade = smoothstep(0.0, 0.15, abs(rayDirection.y)); + const float fadeFactor = radialFade * normalFade; + if (fadeFactor < 1e-3) { + discard; + } + + const float2 worldPos2D = worldPosition.xz; + const GridLayer baseLayer = SampleGridLayer(worldPos2D, scale); + const GridLayer nextLayer = SampleGridLayer(worldPos2D, scale * 10.0); + const float minorGridIntensity = lerp(baseLayer.minor, nextLayer.minor, transitionBlend); + const float majorGridIntensity = lerp(baseLayer.major, nextLayer.major, transitionBlend); + float3 finalColor = float3(0.56, 0.56, 0.56); + float finalAlpha = max( + 0.13 * minorGridIntensity * fadeFactor, + 0.28 * majorGridIntensity * fadeFactor); + + const float2 worldDeriv = max(fwidth(worldPos2D), float2(1e-6, 1e-6)); + const float xAxisAlpha = AxisLineAA(worldPos2D.y, worldDeriv.y) * fadeFactor; + const float zAxisAlpha = AxisLineAA(worldPos2D.x, worldDeriv.x) * fadeFactor; + + const float axisAlpha = max(xAxisAlpha, zAxisAlpha); + finalAlpha = max(finalAlpha, 0.34 * saturate(axisAlpha)); + + if (finalAlpha < 1e-3) { + discard; + } + + PSOutput output; + output.color = float4(finalColor, finalAlpha); + output.depth = depth; + return output; +} diff --git a/engine/assets/builtin/shaders/infinite-grid/infinite-grid.shader b/engine/assets/builtin/shaders/infinite-grid/infinite-grid.shader new file mode 100644 index 00000000..0e530a08 --- /dev/null +++ b/engine/assets/builtin/shaders/infinite-grid/infinite-grid.shader @@ -0,0 +1,29 @@ +{ + "name": "Builtin Infinite Grid", + "passes": [ + { + "name": "InfiniteGrid", + "tags": { + "LightMode": "InfiniteGrid" + }, + "variants": [ + { + "stage": "Vertex", + "backend": "D3D12", + "language": "HLSL", + "source": "infinite-grid.vs.hlsl", + "entryPoint": "MainVS", + "profile": "vs_5_0" + }, + { + "stage": "Fragment", + "backend": "D3D12", + "language": "HLSL", + "source": "infinite-grid.ps.hlsl", + "entryPoint": "MainPS", + "profile": "ps_5_0" + } + ] + } + ] +} diff --git a/engine/assets/builtin/shaders/infinite-grid/infinite-grid.vs.hlsl b/engine/assets/builtin/shaders/infinite-grid/infinite-grid.vs.hlsl new file mode 100644 index 00000000..5b712fdc --- /dev/null +++ b/engine/assets/builtin/shaders/infinite-grid/infinite-grid.vs.hlsl @@ -0,0 +1,26 @@ +// XC_BUILTIN_INFINITE_GRID_D3D12_VS +cbuffer GridConstants : register(b0) { + float4x4 gViewProjectionMatrix; + float4 gCameraPositionAndScale; + float4 gCameraRightAndFade; + float4 gCameraUpAndTanHalfFov; + float4 gCameraForwardAndAspect; + float4 gViewportNearFar; + float4 gGridTransition; +}; + +struct VSOutput { + float4 position : SV_POSITION; +}; + +VSOutput MainVS(uint vertexId : SV_VertexID) { + static const float2 positions[3] = { + float2(-1.0, -1.0), + float2(-1.0, 3.0), + float2( 3.0, -1.0) + }; + + VSOutput output; + output.position = float4(positions[vertexId], 0.0, 1.0); + return output; +} diff --git a/engine/assets/builtin/shaders/object-id-outline/object-id-outline.ps.hlsl b/engine/assets/builtin/shaders/object-id-outline/object-id-outline.ps.hlsl new file mode 100644 index 00000000..3b4b2e7a --- /dev/null +++ b/engine/assets/builtin/shaders/object-id-outline/object-id-outline.ps.hlsl @@ -0,0 +1,89 @@ +// XC_BUILTIN_OBJECT_ID_OUTLINE_D3D12_PS +cbuffer OutlineConstants : register(b0) { + float4 gViewportSizeAndTexelSize; + float4 gOutlineColor; + float4 gSelectedInfo; + float4 gSelectedObjectColors[256]; +}; + +Texture2D gObjectIdTexture : register(t0); + +struct VSOutput { + float4 position : SV_POSITION; +}; + +int2 ClampPixelCoord(int2 pixelCoord) { + const int2 maxCoord = int2( + max((int)gViewportSizeAndTexelSize.x - 1, 0), + max((int)gViewportSizeAndTexelSize.y - 1, 0)); + return clamp(pixelCoord, int2(0, 0), maxCoord); +} + +float4 LoadObjectId(int2 pixelCoord) { + return gObjectIdTexture.Load(int3(ClampPixelCoord(pixelCoord), 0)); +} + +bool IsSelectedObject(float4 objectIdColor) { + if (objectIdColor.a <= 0.0) { + return false; + } + + const int selectedCount = min((int)gSelectedInfo.x, 256); + [loop] + for (int i = 0; i < selectedCount; ++i) { + const float4 selectedColor = gSelectedObjectColors[i]; + if (all(abs(objectIdColor - selectedColor) <= float4( + 0.0025, + 0.0025, + 0.0025, + 0.0025))) { + return true; + } + } + + return false; +} + +float4 MainPS(VSOutput input) : SV_TARGET { + const int2 pixelCoord = int2(input.position.xy); + const bool debugSelectionMask = gSelectedInfo.y > 0.5; + const bool centerSelected = IsSelectedObject(LoadObjectId(pixelCoord)); + + if (debugSelectionMask) { + return centerSelected ? float4(1.0, 1.0, 1.0, 1.0) : float4(0.0, 0.0, 0.0, 1.0); + } + + if (centerSelected) { + discard; + } + + const int outlineWidth = max((int)gSelectedInfo.z, 1); + float outline = 0.0; + [loop] + for (int y = -2; y <= 2; ++y) { + [loop] + for (int x = -2; x <= 2; ++x) { + if (x == 0 && y == 0) { + continue; + } + + const float distancePixels = length(float2((float)x, (float)y)); + if (distancePixels > outlineWidth) { + continue; + } + + if (!IsSelectedObject(LoadObjectId(pixelCoord + int2(x, y)))) { + continue; + } + + const float weight = saturate(1.0 - ((distancePixels - 1.0) / max((float)outlineWidth, 1.0))); + outline = max(outline, weight); + } + } + + if (outline <= 0.001) { + discard; + } + + return float4(gOutlineColor.rgb, gOutlineColor.a * outline); +} diff --git a/engine/assets/builtin/shaders/object-id-outline/object-id-outline.shader b/engine/assets/builtin/shaders/object-id-outline/object-id-outline.shader new file mode 100644 index 00000000..f9d75bc4 --- /dev/null +++ b/engine/assets/builtin/shaders/object-id-outline/object-id-outline.shader @@ -0,0 +1,29 @@ +{ + "name": "Builtin Object Id Outline", + "passes": [ + { + "name": "ObjectIdOutline", + "tags": { + "LightMode": "ObjectIdOutline" + }, + "variants": [ + { + "stage": "Vertex", + "backend": "D3D12", + "language": "HLSL", + "source": "object-id-outline.vs.hlsl", + "entryPoint": "MainVS", + "profile": "vs_5_0" + }, + { + "stage": "Fragment", + "backend": "D3D12", + "language": "HLSL", + "source": "object-id-outline.ps.hlsl", + "entryPoint": "MainPS", + "profile": "ps_5_0" + } + ] + } + ] +} diff --git a/engine/assets/builtin/shaders/object-id-outline/object-id-outline.vs.hlsl b/engine/assets/builtin/shaders/object-id-outline/object-id-outline.vs.hlsl new file mode 100644 index 00000000..a290e975 --- /dev/null +++ b/engine/assets/builtin/shaders/object-id-outline/object-id-outline.vs.hlsl @@ -0,0 +1,25 @@ +// XC_BUILTIN_OBJECT_ID_OUTLINE_D3D12_VS +cbuffer OutlineConstants : register(b0) { + float4 gViewportSizeAndTexelSize; + float4 gOutlineColor; + float4 gSelectedInfo; + float4 gSelectedObjectColors[256]; +}; + +Texture2D gObjectIdTexture : register(t0); + +struct VSOutput { + float4 position : SV_POSITION; +}; + +VSOutput MainVS(uint vertexId : SV_VertexID) { + static const float2 positions[3] = { + float2(-1.0, -1.0), + float2(-1.0, 3.0), + float2( 3.0, -1.0) + }; + + VSOutput output; + output.position = float4(positions[vertexId], 0.0, 1.0); + return output; +} diff --git a/engine/assets/builtin/shaders/object-id/object-id.frag.glsl b/engine/assets/builtin/shaders/object-id/object-id.frag.glsl new file mode 100644 index 00000000..efa34cbb --- /dev/null +++ b/engine/assets/builtin/shaders/object-id/object-id.frag.glsl @@ -0,0 +1,14 @@ +// XC_BUILTIN_OBJECT_ID_OPENGL_PS +#version 430 +layout(std140, binding = 0) uniform PerObjectConstants { + mat4 gProjectionMatrix; + mat4 gViewMatrix; + mat4 gModelMatrix; + vec4 gObjectIdColor; +}; + +layout(location = 0) out vec4 fragColor; + +void main() { + fragColor = gObjectIdColor; +} diff --git a/engine/assets/builtin/shaders/object-id/object-id.frag.vk.glsl b/engine/assets/builtin/shaders/object-id/object-id.frag.vk.glsl new file mode 100644 index 00000000..ed9e94d0 --- /dev/null +++ b/engine/assets/builtin/shaders/object-id/object-id.frag.vk.glsl @@ -0,0 +1,14 @@ +// XC_BUILTIN_OBJECT_ID_VULKAN_PS +#version 450 +layout(set = 0, binding = 0, std140) uniform PerObjectConstants { + mat4 gProjectionMatrix; + mat4 gViewMatrix; + mat4 gModelMatrix; + vec4 gObjectIdColor; +}; + +layout(location = 0) out vec4 fragColor; + +void main() { + fragColor = gObjectIdColor; +} diff --git a/engine/assets/builtin/shaders/object-id/object-id.ps.hlsl b/engine/assets/builtin/shaders/object-id/object-id.ps.hlsl new file mode 100644 index 00000000..0d77a87c --- /dev/null +++ b/engine/assets/builtin/shaders/object-id/object-id.ps.hlsl @@ -0,0 +1,15 @@ +// XC_BUILTIN_OBJECT_ID_D3D12_PS +cbuffer PerObjectConstants : register(b0) { + float4x4 gProjectionMatrix; + float4x4 gViewMatrix; + float4x4 gModelMatrix; + float4 gObjectIdColor; +}; + +struct PSInput { + float4 position : SV_POSITION; +}; + +float4 MainPS(PSInput input) : SV_TARGET { + return gObjectIdColor; +} diff --git a/engine/assets/builtin/shaders/object-id/object-id.shader b/engine/assets/builtin/shaders/object-id/object-id.shader new file mode 100644 index 00000000..713be6f8 --- /dev/null +++ b/engine/assets/builtin/shaders/object-id/object-id.shader @@ -0,0 +1,53 @@ +{ + "name": "Builtin Object Id", + "passes": [ + { + "name": "ObjectId", + "tags": { + "LightMode": "ObjectId" + }, + "variants": [ + { + "stage": "Vertex", + "backend": "D3D12", + "language": "HLSL", + "source": "object-id.vs.hlsl", + "entryPoint": "MainVS", + "profile": "vs_5_0" + }, + { + "stage": "Fragment", + "backend": "D3D12", + "language": "HLSL", + "source": "object-id.ps.hlsl", + "entryPoint": "MainPS", + "profile": "ps_5_0" + }, + { + "stage": "Vertex", + "backend": "OpenGL", + "language": "GLSL", + "source": "object-id.vert.glsl" + }, + { + "stage": "Fragment", + "backend": "OpenGL", + "language": "GLSL", + "source": "object-id.frag.glsl" + }, + { + "stage": "Vertex", + "backend": "Vulkan", + "language": "GLSL", + "source": "object-id.vert.vk.glsl" + }, + { + "stage": "Fragment", + "backend": "Vulkan", + "language": "GLSL", + "source": "object-id.frag.vk.glsl" + } + ] + } + ] +} diff --git a/engine/assets/builtin/shaders/object-id/object-id.vert.glsl b/engine/assets/builtin/shaders/object-id/object-id.vert.glsl new file mode 100644 index 00000000..a2c8085c --- /dev/null +++ b/engine/assets/builtin/shaders/object-id/object-id.vert.glsl @@ -0,0 +1,16 @@ +// XC_BUILTIN_OBJECT_ID_OPENGL_VS +#version 430 +layout(location = 0) in vec3 aPosition; + +layout(std140, binding = 0) uniform PerObjectConstants { + mat4 gProjectionMatrix; + mat4 gViewMatrix; + mat4 gModelMatrix; + vec4 gObjectIdColor; +}; + +void main() { + vec4 positionWS = gModelMatrix * vec4(aPosition, 1.0); + vec4 positionVS = gViewMatrix * positionWS; + gl_Position = gProjectionMatrix * positionVS; +} diff --git a/engine/assets/builtin/shaders/object-id/object-id.vert.vk.glsl b/engine/assets/builtin/shaders/object-id/object-id.vert.vk.glsl new file mode 100644 index 00000000..5e5ebec1 --- /dev/null +++ b/engine/assets/builtin/shaders/object-id/object-id.vert.vk.glsl @@ -0,0 +1,16 @@ +// XC_BUILTIN_OBJECT_ID_VULKAN_VS +#version 450 +layout(location = 0) in vec3 aPosition; + +layout(set = 0, binding = 0, std140) uniform PerObjectConstants { + mat4 gProjectionMatrix; + mat4 gViewMatrix; + mat4 gModelMatrix; + vec4 gObjectIdColor; +}; + +void main() { + vec4 positionWS = gModelMatrix * vec4(aPosition, 1.0); + vec4 positionVS = gViewMatrix * positionWS; + gl_Position = gProjectionMatrix * positionVS; +} diff --git a/engine/assets/builtin/shaders/object-id/object-id.vs.hlsl b/engine/assets/builtin/shaders/object-id/object-id.vs.hlsl new file mode 100644 index 00000000..fb71b6d9 --- /dev/null +++ b/engine/assets/builtin/shaders/object-id/object-id.vs.hlsl @@ -0,0 +1,23 @@ +// XC_BUILTIN_OBJECT_ID_D3D12_VS +cbuffer PerObjectConstants : register(b0) { + float4x4 gProjectionMatrix; + float4x4 gViewMatrix; + float4x4 gModelMatrix; + float4 gObjectIdColor; +}; + +struct VSInput { + float3 position : POSITION; +}; + +struct PSInput { + float4 position : SV_POSITION; +}; + +PSInput MainVS(VSInput input) { + PSInput output; + float4 positionWS = mul(gModelMatrix, float4(input.position, 1.0)); + float4 positionVS = mul(gViewMatrix, positionWS); + output.position = mul(gProjectionMatrix, positionVS); + return output; +} diff --git a/engine/src/Resources/BuiltinResources.cpp b/engine/src/Resources/BuiltinResources.cpp index 9ad2c6b6..023edc78 100644 --- a/engine/src/Resources/BuiltinResources.cpp +++ b/engine/src/Resources/BuiltinResources.cpp @@ -43,6 +43,12 @@ size_t CalculateBuiltinShaderMemorySize(const Shader& shader); constexpr const char* kBuiltinForwardLitShaderManifestRelativePath = "engine/assets/builtin/shaders/forward-lit/forward-lit.shader"; +constexpr const char* kBuiltinObjectIdShaderManifestRelativePath = + "engine/assets/builtin/shaders/object-id/object-id.shader"; +constexpr const char* kBuiltinObjectIdOutlineShaderManifestRelativePath = + "engine/assets/builtin/shaders/object-id-outline/object-id-outline.shader"; +constexpr const char* kBuiltinInfiniteGridShaderManifestRelativePath = + "engine/assets/builtin/shaders/infinite-grid/infinite-grid.shader"; Containers::String NormalizeBuiltinAssetPath(const std::filesystem::path& path) { return Containers::String(path.lexically_normal().generic_string().c_str()); @@ -79,8 +85,9 @@ bool TryResolveBuiltinAssetPathFromAnchor( return false; } -bool TryResolveBuiltinForwardLitShaderManifestPath(Containers::String& outPath) { - const std::filesystem::path relativePath(kBuiltinForwardLitShaderManifestRelativePath); +bool TryResolveBuiltinShaderManifestPath( + const std::filesystem::path& relativePath, + Containers::String& outPath) { std::filesystem::path resolvedPath; std::error_code ec; @@ -104,6 +111,34 @@ bool TryResolveBuiltinForwardLitShaderManifestPath(Containers::String& outPath) return false; } +const char* GetBuiltinShaderManifestRelativePath(const Containers::String& builtinShaderPath) { + if (builtinShaderPath == Containers::String(kBuiltinForwardLitShaderPath)) { + return kBuiltinForwardLitShaderManifestRelativePath; + } + if (builtinShaderPath == Containers::String(kBuiltinObjectIdShaderPath)) { + return kBuiltinObjectIdShaderManifestRelativePath; + } + if (builtinShaderPath == Containers::String(kBuiltinObjectIdOutlineShaderPath)) { + return kBuiltinObjectIdOutlineShaderManifestRelativePath; + } + if (builtinShaderPath == Containers::String(kBuiltinInfiniteGridShaderPath)) { + return kBuiltinInfiniteGridShaderManifestRelativePath; + } + + return nullptr; +} + +bool TryResolveBuiltinShaderManifestPath( + const Containers::String& builtinShaderPath, + Containers::String& outPath) { + const char* relativePath = GetBuiltinShaderManifestRelativePath(builtinShaderPath); + if (relativePath == nullptr) { + return false; + } + + return TryResolveBuiltinShaderManifestPath(std::filesystem::path(relativePath), outPath); +} + Shader* LoadBuiltinShaderFromManifest( const Containers::String& builtinPath, const Containers::String& manifestPath) { @@ -120,6 +155,15 @@ Shader* LoadBuiltinShaderFromManifest( return shader; } +Shader* TryLoadBuiltinShaderFromManifest(const Containers::String& builtinPath) { + Containers::String manifestPath; + if (!TryResolveBuiltinShaderManifestPath(builtinPath, manifestPath)) { + return nullptr; + } + + return LoadBuiltinShaderFromManifest(builtinPath, manifestPath); +} + const char kBuiltinForwardHlsl[] = R"( Texture2D gBaseColorTexture : register(t1); SamplerState gLinearSampler : register(s1); @@ -1133,11 +1177,8 @@ size_t CalculateBuiltinShaderMemorySize(const Shader& shader) { } Shader* BuildBuiltinForwardLitShader(const Containers::String& path) { - Containers::String manifestPath; - if (TryResolveBuiltinForwardLitShaderManifestPath(manifestPath)) { - if (Shader* shader = LoadBuiltinShaderFromManifest(path, manifestPath)) { - return shader; - } + if (Shader* shader = TryLoadBuiltinShaderFromManifest(path)) { + return shader; } auto* shader = new Shader(); @@ -1213,6 +1254,10 @@ Shader* BuildBuiltinForwardLitShader(const Containers::String& path) { } Shader* BuildBuiltinObjectIdShader(const Containers::String& path) { + if (Shader* shader = TryLoadBuiltinShaderFromManifest(path)) { + return shader; + } + auto* shader = new Shader(); IResource::ConstructParams params; params.name = Containers::String("Builtin Object Id"); @@ -1286,6 +1331,10 @@ Shader* BuildBuiltinObjectIdShader(const Containers::String& path) { } Shader* BuildBuiltinInfiniteGridShader(const Containers::String& path) { + if (Shader* shader = TryLoadBuiltinShaderFromManifest(path)) { + return shader; + } + auto* shader = new Shader(); IResource::ConstructParams params; params.name = Containers::String("Builtin Infinite Grid"); @@ -1321,6 +1370,10 @@ Shader* BuildBuiltinInfiniteGridShader(const Containers::String& path) { } Shader* BuildBuiltinObjectIdOutlineShader(const Containers::String& path) { + if (Shader* shader = TryLoadBuiltinShaderFromManifest(path)) { + return shader; + } + auto* shader = new Shader(); IResource::ConstructParams params; params.name = Containers::String("Builtin Object Id Outline"); diff --git a/tests/Resources/Shader/test_shader_loader.cpp b/tests/Resources/Shader/test_shader_loader.cpp index 4650f79f..a2c7d1c0 100644 --- a/tests/Resources/Shader/test_shader_loader.cpp +++ b/tests/Resources/Shader/test_shader_loader.cpp @@ -312,6 +312,27 @@ TEST(ShaderLoader, LoadBuiltinObjectIdShaderBuildsBackendVariants) { EXPECT_NE(shader->FindVariant("ObjectId", ShaderType::Vertex, ShaderBackend::Vulkan), nullptr); EXPECT_NE(shader->FindVariant("ObjectId", ShaderType::Fragment, ShaderBackend::Vulkan), nullptr); + const ShaderStageVariant* d3d12Vertex = shader->FindVariant( + "ObjectId", + ShaderType::Vertex, + ShaderBackend::D3D12); + ASSERT_NE(d3d12Vertex, nullptr); + EXPECT_NE(std::string(d3d12Vertex->sourceCode.CStr()).find("XC_BUILTIN_OBJECT_ID_D3D12_VS"), std::string::npos); + + const ShaderStageVariant* openglFragment = shader->FindVariant( + "ObjectId", + ShaderType::Fragment, + ShaderBackend::OpenGL); + ASSERT_NE(openglFragment, nullptr); + EXPECT_NE(std::string(openglFragment->sourceCode.CStr()).find("XC_BUILTIN_OBJECT_ID_OPENGL_PS"), std::string::npos); + + const ShaderStageVariant* vulkanFragment = shader->FindVariant( + "ObjectId", + ShaderType::Fragment, + ShaderBackend::Vulkan); + ASSERT_NE(vulkanFragment, nullptr); + EXPECT_NE(std::string(vulkanFragment->sourceCode.CStr()).find("XC_BUILTIN_OBJECT_ID_VULKAN_PS"), std::string::npos); + delete shader; } @@ -337,6 +358,13 @@ TEST(ShaderLoader, LoadBuiltinInfiniteGridShaderBuildsD3D12Variants) { EXPECT_EQ(shader->FindVariant("InfiniteGrid", ShaderType::Vertex, ShaderBackend::OpenGL), nullptr); EXPECT_EQ(shader->FindVariant("InfiniteGrid", ShaderType::Fragment, ShaderBackend::OpenGL), nullptr); + const ShaderStageVariant* d3d12Fragment = shader->FindVariant( + "InfiniteGrid", + ShaderType::Fragment, + ShaderBackend::D3D12); + ASSERT_NE(d3d12Fragment, nullptr); + EXPECT_NE(std::string(d3d12Fragment->sourceCode.CStr()).find("XC_BUILTIN_INFINITE_GRID_D3D12_PS"), std::string::npos); + delete shader; } @@ -362,6 +390,15 @@ TEST(ShaderLoader, LoadBuiltinObjectIdOutlineShaderBuildsD3D12Variants) { EXPECT_EQ(shader->FindVariant("ObjectIdOutline", ShaderType::Vertex, ShaderBackend::OpenGL), nullptr); EXPECT_EQ(shader->FindVariant("ObjectIdOutline", ShaderType::Fragment, ShaderBackend::OpenGL), nullptr); + const ShaderStageVariant* d3d12Fragment = shader->FindVariant( + "ObjectIdOutline", + ShaderType::Fragment, + ShaderBackend::D3D12); + ASSERT_NE(d3d12Fragment, nullptr); + EXPECT_NE( + std::string(d3d12Fragment->sourceCode.CStr()).find("XC_BUILTIN_OBJECT_ID_OUTLINE_D3D12_PS"), + std::string::npos); + delete shader; }