Formalize builtin fullscreen shaders
This commit is contained in:
@@ -1,16 +0,0 @@
|
|||||||
// XC_BUILTIN_COLOR_SCALE_POST_PROCESS_OPENGL_PS
|
|
||||||
#version 430
|
|
||||||
|
|
||||||
layout(binding = 0) uniform sampler2D uSourceColorTexture;
|
|
||||||
|
|
||||||
layout(std140, binding = 0) uniform PostProcessConstants {
|
|
||||||
vec4 gColorScale;
|
|
||||||
};
|
|
||||||
|
|
||||||
in vec2 vTexCoord;
|
|
||||||
|
|
||||||
layout(location = 0) out vec4 fragColor;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
fragColor = texture(uSourceColorTexture, vTexCoord) * gColorScale;
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
// XC_BUILTIN_COLOR_SCALE_POST_PROCESS_VULKAN_PS
|
|
||||||
#version 450
|
|
||||||
|
|
||||||
layout(set = 0, binding = 0, std140) uniform PostProcessConstants {
|
|
||||||
vec4 gColorScale;
|
|
||||||
};
|
|
||||||
|
|
||||||
layout(set = 1, binding = 0) uniform texture2D uSourceColorTexture;
|
|
||||||
layout(set = 2, binding = 0) uniform sampler uLinearClampSampler;
|
|
||||||
|
|
||||||
layout(location = 0) in vec2 vTexCoord;
|
|
||||||
|
|
||||||
layout(location = 0) out vec4 fragColor;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
fragColor = texture(sampler2D(uSourceColorTexture, uLinearClampSampler), vTexCoord) * gColorScale;
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
// XC_BUILTIN_COLOR_SCALE_POST_PROCESS_D3D12_PS
|
|
||||||
Texture2D gSourceColorTexture : register(t0);
|
|
||||||
SamplerState gLinearClampSampler : register(s0);
|
|
||||||
|
|
||||||
cbuffer PostProcessConstants : register(b0) {
|
|
||||||
float4 gColorScale;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PSInput {
|
|
||||||
float4 position : SV_POSITION;
|
|
||||||
float2 texcoord : TEXCOORD0;
|
|
||||||
};
|
|
||||||
|
|
||||||
float4 MainPS(PSInput input) : SV_TARGET {
|
|
||||||
return gSourceColorTexture.Sample(gLinearClampSampler, input.texcoord) * gColorScale;
|
|
||||||
}
|
|
||||||
@@ -4,24 +4,63 @@ Shader "Builtin Color Scale Post Process"
|
|||||||
{
|
{
|
||||||
_ColorScale ("Color Scale", Color) = (0.65,0.80,1.00,1.0)
|
_ColorScale ("Color Scale", Color) = (0.65,0.80,1.00,1.0)
|
||||||
}
|
}
|
||||||
|
HLSLINCLUDE
|
||||||
|
cbuffer PostProcessConstants : register(b0)
|
||||||
|
{
|
||||||
|
float4 gColorScale;
|
||||||
|
};
|
||||||
|
|
||||||
|
Texture2D gSourceColorTexture : register(t0);
|
||||||
|
SamplerState gLinearClampSampler : register(s0);
|
||||||
|
|
||||||
|
struct VSOutput
|
||||||
|
{
|
||||||
|
float4 position : SV_POSITION;
|
||||||
|
float2 texcoord : TEXCOORD0;
|
||||||
|
};
|
||||||
|
|
||||||
|
VSOutput MainVS(uint vertexId : SV_VertexID)
|
||||||
|
{
|
||||||
|
const float2 positions[3] = {
|
||||||
|
float2(-1.0f, -1.0f),
|
||||||
|
float2(-1.0f, 3.0f),
|
||||||
|
float2( 3.0f, -1.0f)
|
||||||
|
};
|
||||||
|
|
||||||
|
const float2 position = positions[vertexId];
|
||||||
|
|
||||||
|
VSOutput output;
|
||||||
|
output.position = float4(position, 1.0f, 1.0f);
|
||||||
|
|
||||||
|
float2 uv = float2(
|
||||||
|
position.x * 0.5f + 0.5f,
|
||||||
|
position.y * 0.5f + 0.5f);
|
||||||
|
#if UNITY_UV_STARTS_AT_TOP
|
||||||
|
uv.y = 1.0f - uv.y;
|
||||||
|
#endif
|
||||||
|
output.texcoord = uv;
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 MainPS(VSOutput input) : SV_TARGET
|
||||||
|
{
|
||||||
|
return gSourceColorTexture.Sample(gLinearClampSampler, input.texcoord) * gColorScale;
|
||||||
|
}
|
||||||
|
ENDHLSL
|
||||||
SubShader
|
SubShader
|
||||||
{
|
{
|
||||||
Pass
|
Pass
|
||||||
{
|
{
|
||||||
Name "ColorScale"
|
Name "ColorScale"
|
||||||
Tags { "LightMode" = "PostProcess" }
|
Tags { "LightMode" = "PostProcess" }
|
||||||
Resources
|
Cull Off
|
||||||
{
|
ZWrite Off
|
||||||
PostProcessConstants (ConstantBuffer, 0, 0)
|
ZTest Always
|
||||||
SourceColorTexture (Texture2D, 1, 0)
|
Blend Off
|
||||||
LinearClampSampler (Sampler, 2, 0)
|
|
||||||
}
|
|
||||||
HLSLPROGRAM
|
HLSLPROGRAM
|
||||||
|
#pragma target 4.5
|
||||||
#pragma vertex MainVS
|
#pragma vertex MainVS
|
||||||
#pragma fragment MainPS
|
#pragma fragment MainPS
|
||||||
#pragma backend D3D12 HLSL "color-scale-post-process.vs.hlsl" "color-scale-post-process.ps.hlsl" vs_5_0 ps_5_0
|
|
||||||
#pragma backend OpenGL GLSL "color-scale-post-process.vert.glsl" "color-scale-post-process.frag.glsl"
|
|
||||||
#pragma backend Vulkan GLSL "color-scale-post-process.vert.vk.glsl" "color-scale-post-process.frag.vk.glsl"
|
|
||||||
ENDHLSL
|
ENDHLSL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
// XC_BUILTIN_COLOR_SCALE_POST_PROCESS_OPENGL_VS
|
|
||||||
#version 430
|
|
||||||
|
|
||||||
out vec2 vTexCoord;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
const vec2 positions[3] = vec2[3](
|
|
||||||
vec2(-1.0, -1.0),
|
|
||||||
vec2(-1.0, 3.0),
|
|
||||||
vec2( 3.0, -1.0)
|
|
||||||
);
|
|
||||||
|
|
||||||
vec2 position = positions[gl_VertexID];
|
|
||||||
gl_Position = vec4(position, 1.0, 1.0);
|
|
||||||
vTexCoord = position * 0.5 + 0.5;
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
// XC_BUILTIN_COLOR_SCALE_POST_PROCESS_VULKAN_VS
|
|
||||||
#version 450
|
|
||||||
|
|
||||||
layout(location = 0) out vec2 vTexCoord;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
const vec2 positions[3] = vec2[3](
|
|
||||||
vec2(-1.0, -1.0),
|
|
||||||
vec2(-1.0, 3.0),
|
|
||||||
vec2( 3.0, -1.0)
|
|
||||||
);
|
|
||||||
|
|
||||||
vec2 position = positions[gl_VertexIndex];
|
|
||||||
gl_Position = vec4(position, 1.0, 1.0);
|
|
||||||
vTexCoord = vec2(
|
|
||||||
position.x * 0.5 + 0.5,
|
|
||||||
1.0 - (position.y * 0.5 + 0.5));
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
// XC_BUILTIN_COLOR_SCALE_POST_PROCESS_D3D12_VS
|
|
||||||
struct VSOutput {
|
|
||||||
float4 position : SV_POSITION;
|
|
||||||
float2 texcoord : TEXCOORD0;
|
|
||||||
};
|
|
||||||
|
|
||||||
VSOutput MainVS(uint vertexId : SV_VertexID) {
|
|
||||||
const float2 positions[3] = {
|
|
||||||
float2(-1.0f, -1.0f),
|
|
||||||
float2(-1.0f, 3.0f),
|
|
||||||
float2( 3.0f, -1.0f)
|
|
||||||
};
|
|
||||||
|
|
||||||
const float2 position = positions[vertexId];
|
|
||||||
|
|
||||||
VSOutput output;
|
|
||||||
output.position = float4(position, 1.0f, 1.0f);
|
|
||||||
output.texcoord = float2(
|
|
||||||
position.x * 0.5f + 0.5f,
|
|
||||||
1.0f - (position.y * 0.5f + 0.5f));
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
// XC_BUILTIN_FINAL_COLOR_OPENGL_PS
|
|
||||||
#version 430
|
|
||||||
|
|
||||||
layout(binding = 0) uniform sampler2D uSourceColorTexture;
|
|
||||||
|
|
||||||
layout(std140, binding = 0) uniform FinalColorConstants {
|
|
||||||
vec4 gColorScale;
|
|
||||||
vec4 gFinalColorParams;
|
|
||||||
};
|
|
||||||
|
|
||||||
in vec2 vTexCoord;
|
|
||||||
|
|
||||||
layout(location = 0) out vec4 fragColor;
|
|
||||||
|
|
||||||
float SRGBEncodeChannel(float value) {
|
|
||||||
float linear = max(value, 0.0);
|
|
||||||
return linear <= 0.0031308
|
|
||||||
? linear * 12.92
|
|
||||||
: 1.055 * pow(linear, 1.0 / 2.4) - 0.055;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 ApplyLinearToSRGB(vec3 color) {
|
|
||||||
return vec3(
|
|
||||||
SRGBEncodeChannel(color.r),
|
|
||||||
SRGBEncodeChannel(color.g),
|
|
||||||
SRGBEncodeChannel(color.b));
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 ApplyNeutralToneMapping(vec3 color) {
|
|
||||||
return color / (color + vec3(1.0));
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 ApplyAcesToneMapping(vec3 color) {
|
|
||||||
const float a = 2.51;
|
|
||||||
const float b = 0.03;
|
|
||||||
const float c = 2.43;
|
|
||||||
const float d = 0.59;
|
|
||||||
const float e = 0.14;
|
|
||||||
return clamp((color * (a * color + b)) / (color * (c * color + d) + e), 0.0, 1.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 ApplyToneMapping(vec3 color, float toneMappingMode) {
|
|
||||||
if (toneMappingMode > 1.5) {
|
|
||||||
return ApplyAcesToneMapping(color);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (toneMappingMode > 0.5) {
|
|
||||||
return ApplyNeutralToneMapping(color);
|
|
||||||
}
|
|
||||||
|
|
||||||
return color;
|
|
||||||
}
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
vec4 color = texture(uSourceColorTexture, vTexCoord);
|
|
||||||
color.rgb *= max(gFinalColorParams.x, 0.0);
|
|
||||||
color *= gColorScale;
|
|
||||||
color.rgb = ApplyToneMapping(color.rgb, gFinalColorParams.z);
|
|
||||||
|
|
||||||
if (gFinalColorParams.y > 0.5) {
|
|
||||||
color.rgb = ApplyLinearToSRGB(color.rgb);
|
|
||||||
}
|
|
||||||
|
|
||||||
fragColor = color;
|
|
||||||
}
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
// XC_BUILTIN_FINAL_COLOR_VULKAN_PS
|
|
||||||
#version 450
|
|
||||||
|
|
||||||
layout(set = 0, binding = 0, std140) uniform FinalColorConstants {
|
|
||||||
vec4 gColorScale;
|
|
||||||
vec4 gFinalColorParams;
|
|
||||||
};
|
|
||||||
|
|
||||||
layout(set = 1, binding = 0) uniform texture2D uSourceColorTexture;
|
|
||||||
layout(set = 2, binding = 0) uniform sampler uLinearClampSampler;
|
|
||||||
|
|
||||||
layout(location = 0) in vec2 vTexCoord;
|
|
||||||
|
|
||||||
layout(location = 0) out vec4 fragColor;
|
|
||||||
|
|
||||||
float SRGBEncodeChannel(float value) {
|
|
||||||
float linear = max(value, 0.0);
|
|
||||||
return linear <= 0.0031308
|
|
||||||
? linear * 12.92
|
|
||||||
: 1.055 * pow(linear, 1.0 / 2.4) - 0.055;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 ApplyLinearToSRGB(vec3 color) {
|
|
||||||
return vec3(
|
|
||||||
SRGBEncodeChannel(color.r),
|
|
||||||
SRGBEncodeChannel(color.g),
|
|
||||||
SRGBEncodeChannel(color.b));
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 ApplyNeutralToneMapping(vec3 color) {
|
|
||||||
return color / (color + vec3(1.0));
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 ApplyAcesToneMapping(vec3 color) {
|
|
||||||
const float a = 2.51;
|
|
||||||
const float b = 0.03;
|
|
||||||
const float c = 2.43;
|
|
||||||
const float d = 0.59;
|
|
||||||
const float e = 0.14;
|
|
||||||
return clamp((color * (a * color + b)) / (color * (c * color + d) + e), 0.0, 1.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 ApplyToneMapping(vec3 color, float toneMappingMode) {
|
|
||||||
if (toneMappingMode > 1.5) {
|
|
||||||
return ApplyAcesToneMapping(color);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (toneMappingMode > 0.5) {
|
|
||||||
return ApplyNeutralToneMapping(color);
|
|
||||||
}
|
|
||||||
|
|
||||||
return color;
|
|
||||||
}
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
vec4 color = texture(sampler2D(uSourceColorTexture, uLinearClampSampler), vTexCoord);
|
|
||||||
color.rgb *= max(gFinalColorParams.x, 0.0);
|
|
||||||
color *= gColorScale;
|
|
||||||
color.rgb = ApplyToneMapping(color.rgb, gFinalColorParams.z);
|
|
||||||
|
|
||||||
if (gFinalColorParams.y > 0.5) {
|
|
||||||
color.rgb = ApplyLinearToSRGB(color.rgb);
|
|
||||||
}
|
|
||||||
|
|
||||||
fragColor = color;
|
|
||||||
}
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
// XC_BUILTIN_FINAL_COLOR_D3D12_PS
|
|
||||||
Texture2D gSourceColorTexture : register(t0);
|
|
||||||
SamplerState gLinearClampSampler : register(s0);
|
|
||||||
|
|
||||||
cbuffer FinalColorConstants : register(b0) {
|
|
||||||
float4 gColorScale;
|
|
||||||
float4 gFinalColorParams;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PSInput {
|
|
||||||
float4 position : SV_POSITION;
|
|
||||||
float2 texcoord : TEXCOORD0;
|
|
||||||
};
|
|
||||||
|
|
||||||
float SRGBEncodeChannel(float value) {
|
|
||||||
const float linearValue = max(value, 0.0f);
|
|
||||||
return linearValue <= 0.0031308f
|
|
||||||
? linearValue * 12.92f
|
|
||||||
: 1.055f * pow(linearValue, 1.0f / 2.4f) - 0.055f;
|
|
||||||
}
|
|
||||||
|
|
||||||
float3 ApplyLinearToSRGB(float3 color) {
|
|
||||||
return float3(
|
|
||||||
SRGBEncodeChannel(color.r),
|
|
||||||
SRGBEncodeChannel(color.g),
|
|
||||||
SRGBEncodeChannel(color.b));
|
|
||||||
}
|
|
||||||
|
|
||||||
float3 ApplyNeutralToneMapping(float3 color) {
|
|
||||||
return color / (color + 1.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
float3 ApplyAcesToneMapping(float3 color) {
|
|
||||||
const float a = 2.51f;
|
|
||||||
const float b = 0.03f;
|
|
||||||
const float c = 2.43f;
|
|
||||||
const float d = 0.59f;
|
|
||||||
const float e = 0.14f;
|
|
||||||
return saturate((color * (a * color + b)) / (color * (c * color + d) + e));
|
|
||||||
}
|
|
||||||
|
|
||||||
float3 ApplyToneMapping(float3 color, float toneMappingMode) {
|
|
||||||
if (toneMappingMode > 1.5f) {
|
|
||||||
return ApplyAcesToneMapping(color);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (toneMappingMode > 0.5f) {
|
|
||||||
return ApplyNeutralToneMapping(color);
|
|
||||||
}
|
|
||||||
|
|
||||||
return color;
|
|
||||||
}
|
|
||||||
|
|
||||||
float4 MainPS(PSInput input) : SV_TARGET {
|
|
||||||
float4 color = gSourceColorTexture.Sample(gLinearClampSampler, input.texcoord);
|
|
||||||
color.rgb *= max(gFinalColorParams.x, 0.0f);
|
|
||||||
color *= gColorScale;
|
|
||||||
color.rgb = ApplyToneMapping(color.rgb, gFinalColorParams.z);
|
|
||||||
|
|
||||||
if (gFinalColorParams.y > 0.5f) {
|
|
||||||
color.rgb = ApplyLinearToSRGB(color.rgb);
|
|
||||||
}
|
|
||||||
|
|
||||||
return color;
|
|
||||||
}
|
|
||||||
@@ -7,24 +7,117 @@ Shader "Builtin Final Color"
|
|||||||
_OutputTransferMode ("Output Transfer Mode", Float) = 0.0
|
_OutputTransferMode ("Output Transfer Mode", Float) = 0.0
|
||||||
_ToneMappingMode ("Tone Mapping Mode", Float) = 0.0
|
_ToneMappingMode ("Tone Mapping Mode", Float) = 0.0
|
||||||
}
|
}
|
||||||
|
HLSLINCLUDE
|
||||||
|
cbuffer FinalColorConstants : register(b0)
|
||||||
|
{
|
||||||
|
float4 gColorScale;
|
||||||
|
float4 gFinalColorParams;
|
||||||
|
};
|
||||||
|
|
||||||
|
Texture2D gSourceColorTexture : register(t0);
|
||||||
|
SamplerState gLinearClampSampler : register(s0);
|
||||||
|
|
||||||
|
struct VSOutput
|
||||||
|
{
|
||||||
|
float4 position : SV_POSITION;
|
||||||
|
float2 texcoord : TEXCOORD0;
|
||||||
|
};
|
||||||
|
|
||||||
|
VSOutput MainVS(uint vertexId : SV_VertexID)
|
||||||
|
{
|
||||||
|
const float2 positions[3] = {
|
||||||
|
float2(-1.0f, -1.0f),
|
||||||
|
float2(-1.0f, 3.0f),
|
||||||
|
float2( 3.0f, -1.0f)
|
||||||
|
};
|
||||||
|
|
||||||
|
const float2 position = positions[vertexId];
|
||||||
|
|
||||||
|
VSOutput output;
|
||||||
|
output.position = float4(position, 1.0f, 1.0f);
|
||||||
|
|
||||||
|
float2 uv = float2(
|
||||||
|
position.x * 0.5f + 0.5f,
|
||||||
|
position.y * 0.5f + 0.5f);
|
||||||
|
#if UNITY_UV_STARTS_AT_TOP
|
||||||
|
uv.y = 1.0f - uv.y;
|
||||||
|
#endif
|
||||||
|
output.texcoord = uv;
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
float SRGBEncodeChannel(float value)
|
||||||
|
{
|
||||||
|
const float linearValue = max(value, 0.0f);
|
||||||
|
return linearValue <= 0.0031308f
|
||||||
|
? linearValue * 12.92f
|
||||||
|
: 1.055f * pow(linearValue, 1.0f / 2.4f) - 0.055f;
|
||||||
|
}
|
||||||
|
|
||||||
|
float3 ApplyLinearToSRGB(float3 color)
|
||||||
|
{
|
||||||
|
return float3(
|
||||||
|
SRGBEncodeChannel(color.r),
|
||||||
|
SRGBEncodeChannel(color.g),
|
||||||
|
SRGBEncodeChannel(color.b));
|
||||||
|
}
|
||||||
|
|
||||||
|
float3 ApplyNeutralToneMapping(float3 color)
|
||||||
|
{
|
||||||
|
return color / (color + 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
float3 ApplyAcesToneMapping(float3 color)
|
||||||
|
{
|
||||||
|
const float a = 2.51f;
|
||||||
|
const float b = 0.03f;
|
||||||
|
const float c = 2.43f;
|
||||||
|
const float d = 0.59f;
|
||||||
|
const float e = 0.14f;
|
||||||
|
return saturate((color * (a * color + b)) / (color * (c * color + d) + e));
|
||||||
|
}
|
||||||
|
|
||||||
|
float3 ApplyToneMapping(float3 color, float toneMappingMode)
|
||||||
|
{
|
||||||
|
if (toneMappingMode > 1.5f) {
|
||||||
|
return ApplyAcesToneMapping(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toneMappingMode > 0.5f) {
|
||||||
|
return ApplyNeutralToneMapping(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 MainPS(VSOutput input) : SV_TARGET
|
||||||
|
{
|
||||||
|
float4 color = gSourceColorTexture.Sample(gLinearClampSampler, input.texcoord);
|
||||||
|
color.rgb *= max(gFinalColorParams.x, 0.0f);
|
||||||
|
color *= gColorScale;
|
||||||
|
color.rgb = ApplyToneMapping(color.rgb, gFinalColorParams.z);
|
||||||
|
|
||||||
|
if (gFinalColorParams.y > 0.5f) {
|
||||||
|
color.rgb = ApplyLinearToSRGB(color.rgb);
|
||||||
|
}
|
||||||
|
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
ENDHLSL
|
||||||
SubShader
|
SubShader
|
||||||
{
|
{
|
||||||
Pass
|
Pass
|
||||||
{
|
{
|
||||||
Name "FinalColor"
|
Name "FinalColor"
|
||||||
Tags { "LightMode" = "FinalOutput" }
|
Tags { "LightMode" = "FinalOutput" }
|
||||||
Resources
|
Cull Off
|
||||||
{
|
ZWrite Off
|
||||||
FinalColorConstants (ConstantBuffer, 0, 0)
|
ZTest Always
|
||||||
SourceColorTexture (Texture2D, 1, 0)
|
Blend Off
|
||||||
LinearClampSampler (Sampler, 2, 0)
|
|
||||||
}
|
|
||||||
HLSLPROGRAM
|
HLSLPROGRAM
|
||||||
|
#pragma target 4.5
|
||||||
#pragma vertex MainVS
|
#pragma vertex MainVS
|
||||||
#pragma fragment MainPS
|
#pragma fragment MainPS
|
||||||
#pragma backend D3D12 HLSL "final-color.vs.hlsl" "final-color.ps.hlsl" vs_5_0 ps_5_0
|
|
||||||
#pragma backend OpenGL GLSL "final-color.vert.glsl" "final-color.frag.glsl"
|
|
||||||
#pragma backend Vulkan GLSL "final-color.vert.vk.glsl" "final-color.frag.vk.glsl"
|
|
||||||
ENDHLSL
|
ENDHLSL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
// XC_BUILTIN_FINAL_COLOR_OPENGL_VS
|
|
||||||
#version 430
|
|
||||||
|
|
||||||
out vec2 vTexCoord;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
const vec2 positions[3] = vec2[3](
|
|
||||||
vec2(-1.0, -1.0),
|
|
||||||
vec2(-1.0, 3.0),
|
|
||||||
vec2( 3.0, -1.0)
|
|
||||||
);
|
|
||||||
|
|
||||||
vec2 position = positions[gl_VertexID];
|
|
||||||
gl_Position = vec4(position, 1.0, 1.0);
|
|
||||||
vTexCoord = position * 0.5 + 0.5;
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
// XC_BUILTIN_FINAL_COLOR_VULKAN_VS
|
|
||||||
#version 450
|
|
||||||
|
|
||||||
layout(location = 0) out vec2 vTexCoord;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
const vec2 positions[3] = vec2[3](
|
|
||||||
vec2(-1.0, -1.0),
|
|
||||||
vec2(-1.0, 3.0),
|
|
||||||
vec2( 3.0, -1.0)
|
|
||||||
);
|
|
||||||
|
|
||||||
vec2 position = positions[gl_VertexIndex];
|
|
||||||
gl_Position = vec4(position, 1.0, 1.0);
|
|
||||||
vTexCoord = vec2(
|
|
||||||
position.x * 0.5 + 0.5,
|
|
||||||
1.0 - (position.y * 0.5 + 0.5));
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
// XC_BUILTIN_FINAL_COLOR_D3D12_VS
|
|
||||||
struct VSOutput {
|
|
||||||
float4 position : SV_POSITION;
|
|
||||||
float2 texcoord : TEXCOORD0;
|
|
||||||
};
|
|
||||||
|
|
||||||
VSOutput MainVS(uint vertexId : SV_VertexID) {
|
|
||||||
const float2 positions[3] = {
|
|
||||||
float2(-1.0f, -1.0f),
|
|
||||||
float2(-1.0f, 3.0f),
|
|
||||||
float2( 3.0f, -1.0f)
|
|
||||||
};
|
|
||||||
|
|
||||||
const float2 position = positions[vertexId];
|
|
||||||
|
|
||||||
VSOutput output;
|
|
||||||
output.position = float4(position, 1.0f, 1.0f);
|
|
||||||
output.texcoord = float2(
|
|
||||||
position.x * 0.5f + 0.5f,
|
|
||||||
1.0f - (position.y * 0.5f + 0.5f));
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
// XC_BUILTIN_SKYBOX_OPENGL_PS
|
|
||||||
#version 430
|
|
||||||
|
|
||||||
layout(binding = 0) uniform sampler2D uSkyboxPanoramicTexture;
|
|
||||||
layout(binding = 1) uniform samplerCube uSkyboxTexture;
|
|
||||||
|
|
||||||
layout(std140, binding = 0) uniform EnvironmentConstants {
|
|
||||||
vec4 gSkyboxTopColor;
|
|
||||||
vec4 gSkyboxHorizonColor;
|
|
||||||
vec4 gSkyboxBottomColor;
|
|
||||||
vec4 gCameraRightAndTanHalfFov;
|
|
||||||
vec4 gCameraUpAndAspect;
|
|
||||||
vec4 gCameraForwardAndUnused;
|
|
||||||
};
|
|
||||||
|
|
||||||
layout(std140, binding = 1) uniform MaterialConstants {
|
|
||||||
vec4 gSkyboxTintAndExposure;
|
|
||||||
vec4 gSkyboxRotationAndMode;
|
|
||||||
};
|
|
||||||
|
|
||||||
in vec2 vNdc;
|
|
||||||
|
|
||||||
layout(location = 0) out vec4 fragColor;
|
|
||||||
|
|
||||||
const float XC_PI = 3.14159265358979323846;
|
|
||||||
const float XC_INV_PI = 0.31830988618379067154;
|
|
||||||
const float XC_INV_TWO_PI = 0.15915494309189533577;
|
|
||||||
|
|
||||||
vec3 EvaluateProceduralSkybox(vec3 viewRay) {
|
|
||||||
float vertical = clamp(viewRay.y, -1.0, 1.0);
|
|
||||||
vec3 color = gSkyboxHorizonColor.rgb;
|
|
||||||
if (vertical >= 0.0) {
|
|
||||||
color = mix(gSkyboxHorizonColor.rgb, gSkyboxTopColor.rgb, pow(clamp(vertical, 0.0, 1.0), 0.65));
|
|
||||||
} else {
|
|
||||||
color = mix(gSkyboxHorizonColor.rgb, gSkyboxBottomColor.rgb, pow(clamp(-vertical, 0.0, 1.0), 0.55));
|
|
||||||
}
|
|
||||||
|
|
||||||
return color;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 RotateAroundY(vec3 viewRay) {
|
|
||||||
float rotation = gSkyboxRotationAndMode.x;
|
|
||||||
float sinTheta = sin(rotation);
|
|
||||||
float cosTheta = cos(rotation);
|
|
||||||
return normalize(vec3(
|
|
||||||
viewRay.x * cosTheta - viewRay.z * sinTheta,
|
|
||||||
viewRay.y,
|
|
||||||
viewRay.x * sinTheta + viewRay.z * cosTheta));
|
|
||||||
}
|
|
||||||
|
|
||||||
vec2 ComputePanoramicUv(vec3 viewRay) {
|
|
||||||
vec3 rotatedRay = RotateAroundY(viewRay);
|
|
||||||
float u = fract(atan(rotatedRay.z, rotatedRay.x) * XC_INV_TWO_PI + 0.5);
|
|
||||||
float v = acos(clamp(rotatedRay.y, -1.0, 1.0)) * XC_INV_PI;
|
|
||||||
return vec2(u, clamp(v, 0.0, 1.0));
|
|
||||||
}
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
float tanHalfFov = gCameraRightAndTanHalfFov.w;
|
|
||||||
float aspect = gCameraUpAndAspect.w;
|
|
||||||
|
|
||||||
vec3 viewRay = normalize(
|
|
||||||
gCameraForwardAndUnused.xyz +
|
|
||||||
vNdc.x * aspect * tanHalfFov * gCameraRightAndTanHalfFov.xyz +
|
|
||||||
vNdc.y * tanHalfFov * gCameraUpAndAspect.xyz);
|
|
||||||
|
|
||||||
vec3 color = EvaluateProceduralSkybox(viewRay);
|
|
||||||
if (gSkyboxRotationAndMode.y > 1.5) {
|
|
||||||
color = texture(uSkyboxTexture, RotateAroundY(viewRay)).rgb *
|
|
||||||
gSkyboxTintAndExposure.rgb *
|
|
||||||
gSkyboxTintAndExposure.w;
|
|
||||||
} else if (gSkyboxRotationAndMode.y > 0.5) {
|
|
||||||
color = texture(uSkyboxPanoramicTexture, ComputePanoramicUv(viewRay)).rgb *
|
|
||||||
gSkyboxTintAndExposure.rgb *
|
|
||||||
gSkyboxTintAndExposure.w;
|
|
||||||
}
|
|
||||||
|
|
||||||
fragColor = vec4(color, 1.0);
|
|
||||||
}
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
// XC_BUILTIN_SKYBOX_VULKAN_PS
|
|
||||||
#version 450
|
|
||||||
|
|
||||||
layout(set = 0, binding = 0, std140) uniform EnvironmentConstants {
|
|
||||||
vec4 gSkyboxTopColor;
|
|
||||||
vec4 gSkyboxHorizonColor;
|
|
||||||
vec4 gSkyboxBottomColor;
|
|
||||||
vec4 gCameraRightAndTanHalfFov;
|
|
||||||
vec4 gCameraUpAndAspect;
|
|
||||||
vec4 gCameraForwardAndUnused;
|
|
||||||
};
|
|
||||||
|
|
||||||
layout(set = 1, binding = 0, std140) uniform MaterialConstants {
|
|
||||||
vec4 gSkyboxTintAndExposure;
|
|
||||||
vec4 gSkyboxRotationAndMode;
|
|
||||||
};
|
|
||||||
|
|
||||||
layout(set = 2, binding = 0) uniform texture2D uSkyboxPanoramicTexture;
|
|
||||||
layout(set = 3, binding = 0) uniform textureCube uSkyboxTexture;
|
|
||||||
layout(set = 4, binding = 0) uniform sampler uLinearSampler;
|
|
||||||
|
|
||||||
layout(location = 0) in vec2 vNdc;
|
|
||||||
|
|
||||||
layout(location = 0) out vec4 fragColor;
|
|
||||||
|
|
||||||
const float XC_PI = 3.14159265358979323846;
|
|
||||||
const float XC_INV_PI = 0.31830988618379067154;
|
|
||||||
const float XC_INV_TWO_PI = 0.15915494309189533577;
|
|
||||||
|
|
||||||
vec3 EvaluateProceduralSkybox(vec3 viewRay) {
|
|
||||||
float vertical = clamp(viewRay.y, -1.0, 1.0);
|
|
||||||
vec3 color = gSkyboxHorizonColor.rgb;
|
|
||||||
if (vertical >= 0.0) {
|
|
||||||
color = mix(gSkyboxHorizonColor.rgb, gSkyboxTopColor.rgb, pow(clamp(vertical, 0.0, 1.0), 0.65));
|
|
||||||
} else {
|
|
||||||
color = mix(gSkyboxHorizonColor.rgb, gSkyboxBottomColor.rgb, pow(clamp(-vertical, 0.0, 1.0), 0.55));
|
|
||||||
}
|
|
||||||
|
|
||||||
return color;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 RotateAroundY(vec3 viewRay) {
|
|
||||||
float rotation = gSkyboxRotationAndMode.x;
|
|
||||||
float sinTheta = sin(rotation);
|
|
||||||
float cosTheta = cos(rotation);
|
|
||||||
return normalize(vec3(
|
|
||||||
viewRay.x * cosTheta - viewRay.z * sinTheta,
|
|
||||||
viewRay.y,
|
|
||||||
viewRay.x * sinTheta + viewRay.z * cosTheta));
|
|
||||||
}
|
|
||||||
|
|
||||||
vec2 ComputePanoramicUv(vec3 viewRay) {
|
|
||||||
vec3 rotatedRay = RotateAroundY(viewRay);
|
|
||||||
float u = fract(atan(rotatedRay.z, rotatedRay.x) * XC_INV_TWO_PI + 0.5);
|
|
||||||
float v = acos(clamp(rotatedRay.y, -1.0, 1.0)) * XC_INV_PI;
|
|
||||||
return vec2(u, clamp(v, 0.0, 1.0));
|
|
||||||
}
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
float tanHalfFov = gCameraRightAndTanHalfFov.w;
|
|
||||||
float aspect = gCameraUpAndAspect.w;
|
|
||||||
|
|
||||||
vec3 viewRay = normalize(
|
|
||||||
gCameraForwardAndUnused.xyz +
|
|
||||||
vNdc.x * aspect * tanHalfFov * gCameraRightAndTanHalfFov.xyz +
|
|
||||||
vNdc.y * tanHalfFov * gCameraUpAndAspect.xyz);
|
|
||||||
|
|
||||||
vec3 color = EvaluateProceduralSkybox(viewRay);
|
|
||||||
if (gSkyboxRotationAndMode.y > 1.5) {
|
|
||||||
color = texture(samplerCube(uSkyboxTexture, uLinearSampler), RotateAroundY(viewRay)).rgb *
|
|
||||||
gSkyboxTintAndExposure.rgb *
|
|
||||||
gSkyboxTintAndExposure.w;
|
|
||||||
} else if (gSkyboxRotationAndMode.y > 0.5) {
|
|
||||||
color = texture(sampler2D(uSkyboxPanoramicTexture, uLinearSampler), ComputePanoramicUv(viewRay)).rgb *
|
|
||||||
gSkyboxTintAndExposure.rgb *
|
|
||||||
gSkyboxTintAndExposure.w;
|
|
||||||
}
|
|
||||||
|
|
||||||
fragColor = vec4(color, 1.0);
|
|
||||||
}
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
// XC_BUILTIN_SKYBOX_D3D12_PS
|
|
||||||
Texture2D gSkyboxPanoramicTexture : register(t0);
|
|
||||||
TextureCube gSkyboxTexture : register(t1);
|
|
||||||
SamplerState gLinearSampler : register(s0);
|
|
||||||
|
|
||||||
cbuffer EnvironmentConstants : register(b0) {
|
|
||||||
float4 gSkyboxTopColor;
|
|
||||||
float4 gSkyboxHorizonColor;
|
|
||||||
float4 gSkyboxBottomColor;
|
|
||||||
float4 gCameraRightAndTanHalfFov;
|
|
||||||
float4 gCameraUpAndAspect;
|
|
||||||
float4 gCameraForwardAndUnused;
|
|
||||||
}
|
|
||||||
|
|
||||||
cbuffer MaterialConstants : register(b1) {
|
|
||||||
float4 gSkyboxTintAndExposure;
|
|
||||||
float4 gSkyboxRotationAndMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct PSInput {
|
|
||||||
float4 position : SV_POSITION;
|
|
||||||
float2 ndc : TEXCOORD0;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const float XC_PI = 3.14159265358979323846f;
|
|
||||||
static const float XC_INV_PI = 0.31830988618379067154f;
|
|
||||||
static const float XC_INV_TWO_PI = 0.15915494309189533577f;
|
|
||||||
|
|
||||||
float3 EvaluateProceduralSkybox(float3 viewRay) {
|
|
||||||
const float vertical = clamp(viewRay.y, -1.0f, 1.0f);
|
|
||||||
float3 color = gSkyboxHorizonColor.rgb;
|
|
||||||
if (vertical >= 0.0f) {
|
|
||||||
color = lerp(gSkyboxHorizonColor.rgb, gSkyboxTopColor.rgb, pow(saturate(vertical), 0.65f));
|
|
||||||
} else {
|
|
||||||
color = lerp(gSkyboxHorizonColor.rgb, gSkyboxBottomColor.rgb, pow(saturate(-vertical), 0.55f));
|
|
||||||
}
|
|
||||||
|
|
||||||
return color;
|
|
||||||
}
|
|
||||||
|
|
||||||
float3 RotateAroundY(float3 viewRay) {
|
|
||||||
const float rotation = gSkyboxRotationAndMode.x;
|
|
||||||
const float sinTheta = sin(rotation);
|
|
||||||
const float cosTheta = cos(rotation);
|
|
||||||
return normalize(float3(
|
|
||||||
viewRay.x * cosTheta - viewRay.z * sinTheta,
|
|
||||||
viewRay.y,
|
|
||||||
viewRay.x * sinTheta + viewRay.z * cosTheta));
|
|
||||||
}
|
|
||||||
|
|
||||||
float2 ComputePanoramicUv(float3 viewRay) {
|
|
||||||
const float3 rotatedRay = RotateAroundY(viewRay);
|
|
||||||
const float u = frac(atan2(rotatedRay.z, rotatedRay.x) * XC_INV_TWO_PI + 0.5f);
|
|
||||||
const float v = acos(clamp(rotatedRay.y, -1.0f, 1.0f)) * XC_INV_PI;
|
|
||||||
return float2(u, saturate(v));
|
|
||||||
}
|
|
||||||
|
|
||||||
float4 MainPS(PSInput input) : SV_Target {
|
|
||||||
const float tanHalfFov = gCameraRightAndTanHalfFov.w;
|
|
||||||
const float aspect = gCameraUpAndAspect.w;
|
|
||||||
|
|
||||||
float3 viewRay = normalize(
|
|
||||||
gCameraForwardAndUnused.xyz +
|
|
||||||
input.ndc.x * aspect * tanHalfFov * gCameraRightAndTanHalfFov.xyz +
|
|
||||||
input.ndc.y * tanHalfFov * gCameraUpAndAspect.xyz);
|
|
||||||
|
|
||||||
float3 color = EvaluateProceduralSkybox(viewRay);
|
|
||||||
if (gSkyboxRotationAndMode.y > 1.5f) {
|
|
||||||
color = gSkyboxTexture.Sample(gLinearSampler, RotateAroundY(viewRay)).rgb *
|
|
||||||
gSkyboxTintAndExposure.rgb *
|
|
||||||
gSkyboxTintAndExposure.w;
|
|
||||||
} else if (gSkyboxRotationAndMode.y > 0.5f) {
|
|
||||||
color = gSkyboxPanoramicTexture.Sample(gLinearSampler, ComputePanoramicUv(viewRay)).rgb *
|
|
||||||
gSkyboxTintAndExposure.rgb *
|
|
||||||
gSkyboxTintAndExposure.w;
|
|
||||||
}
|
|
||||||
|
|
||||||
return float4(color, 1.0f);
|
|
||||||
}
|
|
||||||
@@ -8,26 +8,121 @@ Shader "Builtin Skybox"
|
|||||||
_MainTex ("Panoramic", 2D) = "white" [Semantic(SkyboxPanoramicTexture)]
|
_MainTex ("Panoramic", 2D) = "white" [Semantic(SkyboxPanoramicTexture)]
|
||||||
_Tex ("Cubemap (HDR)", Cube) = "white" [Semantic(SkyboxTexture)]
|
_Tex ("Cubemap (HDR)", Cube) = "white" [Semantic(SkyboxTexture)]
|
||||||
}
|
}
|
||||||
|
HLSLINCLUDE
|
||||||
|
cbuffer EnvironmentConstants : register(b0)
|
||||||
|
{
|
||||||
|
float4 gSkyboxTopColor;
|
||||||
|
float4 gSkyboxHorizonColor;
|
||||||
|
float4 gSkyboxBottomColor;
|
||||||
|
float4 gCameraRightAndTanHalfFov;
|
||||||
|
float4 gCameraUpAndAspect;
|
||||||
|
float4 gCameraForwardAndUnused;
|
||||||
|
};
|
||||||
|
|
||||||
|
cbuffer MaterialConstants : register(b1)
|
||||||
|
{
|
||||||
|
float4 gSkyboxTintAndExposure;
|
||||||
|
float4 gSkyboxRotationAndMode;
|
||||||
|
};
|
||||||
|
|
||||||
|
Texture2D SkyboxPanoramicTexture : register(t0);
|
||||||
|
TextureCube SkyboxTexture : register(t1);
|
||||||
|
SamplerState LinearClampSampler : register(s0);
|
||||||
|
|
||||||
|
struct VSOutput
|
||||||
|
{
|
||||||
|
float4 position : SV_POSITION;
|
||||||
|
float2 ndc : TEXCOORD0;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const float XC_PI = 3.14159265358979323846f;
|
||||||
|
static const float XC_INV_PI = 0.31830988618379067154f;
|
||||||
|
static const float XC_INV_TWO_PI = 0.15915494309189533577f;
|
||||||
|
|
||||||
|
VSOutput MainVS(uint vertexId : SV_VertexID)
|
||||||
|
{
|
||||||
|
const float2 positions[3] = {
|
||||||
|
float2(-1.0f, -1.0f),
|
||||||
|
float2(-1.0f, 3.0f),
|
||||||
|
float2( 3.0f, -1.0f)
|
||||||
|
};
|
||||||
|
|
||||||
|
VSOutput output;
|
||||||
|
output.position = float4(positions[vertexId], 1.0f, 1.0f);
|
||||||
|
output.ndc = positions[vertexId];
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
float3 EvaluateProceduralSkybox(float3 viewRay)
|
||||||
|
{
|
||||||
|
const float vertical = clamp(viewRay.y, -1.0f, 1.0f);
|
||||||
|
float3 color = gSkyboxHorizonColor.rgb;
|
||||||
|
if (vertical >= 0.0f) {
|
||||||
|
color = lerp(gSkyboxHorizonColor.rgb, gSkyboxTopColor.rgb, pow(saturate(vertical), 0.65f));
|
||||||
|
} else {
|
||||||
|
color = lerp(gSkyboxHorizonColor.rgb, gSkyboxBottomColor.rgb, pow(saturate(-vertical), 0.55f));
|
||||||
|
}
|
||||||
|
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
float3 RotateAroundY(float3 viewRay)
|
||||||
|
{
|
||||||
|
const float rotation = gSkyboxRotationAndMode.x;
|
||||||
|
const float sinTheta = sin(rotation);
|
||||||
|
const float cosTheta = cos(rotation);
|
||||||
|
return normalize(float3(
|
||||||
|
viewRay.x * cosTheta - viewRay.z * sinTheta,
|
||||||
|
viewRay.y,
|
||||||
|
viewRay.x * sinTheta + viewRay.z * cosTheta));
|
||||||
|
}
|
||||||
|
|
||||||
|
float2 ComputePanoramicUv(float3 viewRay)
|
||||||
|
{
|
||||||
|
const float3 rotatedRay = RotateAroundY(viewRay);
|
||||||
|
const float u = frac(atan2(rotatedRay.z, rotatedRay.x) * XC_INV_TWO_PI + 0.5f);
|
||||||
|
const float v = acos(clamp(rotatedRay.y, -1.0f, 1.0f)) * XC_INV_PI;
|
||||||
|
return float2(u, saturate(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 MainPS(VSOutput input) : SV_TARGET
|
||||||
|
{
|
||||||
|
const float tanHalfFov = gCameraRightAndTanHalfFov.w;
|
||||||
|
const float aspect = gCameraUpAndAspect.w;
|
||||||
|
|
||||||
|
const float3 viewRay = normalize(
|
||||||
|
gCameraForwardAndUnused.xyz +
|
||||||
|
input.ndc.x * aspect * tanHalfFov * gCameraRightAndTanHalfFov.xyz +
|
||||||
|
input.ndc.y * tanHalfFov * gCameraUpAndAspect.xyz);
|
||||||
|
|
||||||
|
float3 color = EvaluateProceduralSkybox(viewRay);
|
||||||
|
if (gSkyboxRotationAndMode.y > 1.5f) {
|
||||||
|
color = SkyboxTexture.Sample(LinearClampSampler, RotateAroundY(viewRay)).rgb *
|
||||||
|
gSkyboxTintAndExposure.rgb *
|
||||||
|
gSkyboxTintAndExposure.w;
|
||||||
|
} else if (gSkyboxRotationAndMode.y > 0.5f) {
|
||||||
|
color = SkyboxPanoramicTexture.Sample(LinearClampSampler, ComputePanoramicUv(viewRay)).rgb *
|
||||||
|
gSkyboxTintAndExposure.rgb *
|
||||||
|
gSkyboxTintAndExposure.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
return float4(color, 1.0f);
|
||||||
|
}
|
||||||
|
ENDHLSL
|
||||||
SubShader
|
SubShader
|
||||||
{
|
{
|
||||||
Pass
|
Pass
|
||||||
{
|
{
|
||||||
Name "Skybox"
|
Name "Skybox"
|
||||||
Tags { "LightMode" = "Skybox" }
|
Tags { "LightMode" = "Skybox" }
|
||||||
Resources
|
Cull Off
|
||||||
{
|
ZWrite Off
|
||||||
EnvironmentConstants (ConstantBuffer, 0, 0) [Semantic(Environment)]
|
ZTest LEqual
|
||||||
MaterialConstants (ConstantBuffer, 1, 0) [Semantic(Material)]
|
Blend Off
|
||||||
SkyboxPanoramicTexture (Texture2D, 2, 0) [Semantic(SkyboxPanoramicTexture)]
|
|
||||||
SkyboxTexture (TextureCube, 3, 0) [Semantic(SkyboxTexture)]
|
|
||||||
LinearClampSampler (Sampler, 4, 0) [Semantic(LinearClampSampler)]
|
|
||||||
}
|
|
||||||
HLSLPROGRAM
|
HLSLPROGRAM
|
||||||
|
#pragma target 4.5
|
||||||
#pragma vertex MainVS
|
#pragma vertex MainVS
|
||||||
#pragma fragment MainPS
|
#pragma fragment MainPS
|
||||||
#pragma backend D3D12 HLSL "skybox.vs.hlsl" "skybox.ps.hlsl" vs_5_0 ps_5_0
|
|
||||||
#pragma backend OpenGL GLSL "skybox.vert.glsl" "skybox.frag.glsl"
|
|
||||||
#pragma backend Vulkan GLSL "skybox.vert.vk.glsl" "skybox.frag.vk.glsl"
|
|
||||||
ENDHLSL
|
ENDHLSL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
// XC_BUILTIN_SKYBOX_OPENGL_VS
|
|
||||||
#version 430
|
|
||||||
|
|
||||||
out vec2 vNdc;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
const vec2 positions[3] = vec2[3](
|
|
||||||
vec2(-1.0, -1.0),
|
|
||||||
vec2(-1.0, 3.0),
|
|
||||||
vec2( 3.0, -1.0)
|
|
||||||
);
|
|
||||||
|
|
||||||
vec2 position = positions[gl_VertexID];
|
|
||||||
gl_Position = vec4(position, 1.0, 1.0);
|
|
||||||
vNdc = position;
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
// XC_BUILTIN_SKYBOX_VULKAN_VS
|
|
||||||
#version 450
|
|
||||||
|
|
||||||
layout(location = 0) out vec2 vNdc;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
const vec2 positions[3] = vec2[3](
|
|
||||||
vec2(-1.0, -1.0),
|
|
||||||
vec2(-1.0, 3.0),
|
|
||||||
vec2( 3.0, -1.0)
|
|
||||||
);
|
|
||||||
|
|
||||||
vec2 position = positions[gl_VertexIndex];
|
|
||||||
gl_Position = vec4(position, 1.0, 1.0);
|
|
||||||
vNdc = position;
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
// XC_BUILTIN_SKYBOX_D3D12_VS
|
|
||||||
struct VSOutput {
|
|
||||||
float4 position : SV_POSITION;
|
|
||||||
float2 ndc : TEXCOORD0;
|
|
||||||
};
|
|
||||||
|
|
||||||
VSOutput MainVS(uint vertexId : SV_VertexID) {
|
|
||||||
const float2 positions[3] = {
|
|
||||||
float2(-1.0f, -1.0f),
|
|
||||||
float2(-1.0f, 3.0f),
|
|
||||||
float2( 3.0f, -1.0f)
|
|
||||||
};
|
|
||||||
|
|
||||||
VSOutput output;
|
|
||||||
output.position = float4(positions[vertexId], 1.0f, 1.0f);
|
|
||||||
output.ndc = positions[vertexId];
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
@@ -59,7 +59,7 @@ Mesh* CreateQuadMesh() {
|
|||||||
vertices[3].position = Vector3(1.0f, 1.0f, 0.0f);
|
vertices[3].position = Vector3(1.0f, 1.0f, 0.0f);
|
||||||
vertices[3].uv0 = Vector2(1.0f, 0.0f);
|
vertices[3].uv0 = Vector2(1.0f, 0.0f);
|
||||||
|
|
||||||
const uint32_t indices[6] = { 0, 1, 2, 2, 1, 3 };
|
const uint32_t indices[6] = { 0, 2, 1, 2, 3, 1 };
|
||||||
mesh->SetVertexData(
|
mesh->SetVertexData(
|
||||||
vertices,
|
vertices,
|
||||||
sizeof(vertices),
|
sizeof(vertices),
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ Mesh* CreateQuadMesh() {
|
|||||||
vertices[3].position = Vector3(1.0f, 1.0f, 0.0f);
|
vertices[3].position = Vector3(1.0f, 1.0f, 0.0f);
|
||||||
vertices[3].uv0 = Vector2(1.0f, 0.0f);
|
vertices[3].uv0 = Vector2(1.0f, 0.0f);
|
||||||
|
|
||||||
const uint32_t indices[6] = { 0, 1, 2, 2, 1, 3 };
|
const uint32_t indices[6] = { 0, 2, 1, 2, 3, 1 };
|
||||||
mesh->SetVertexData(
|
mesh->SetVertexData(
|
||||||
vertices,
|
vertices,
|
||||||
sizeof(vertices),
|
sizeof(vertices),
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ Mesh* CreateQuadMesh() {
|
|||||||
vertices[3].position = Vector3(1.0f, 1.0f, 0.0f);
|
vertices[3].position = Vector3(1.0f, 1.0f, 0.0f);
|
||||||
vertices[3].uv0 = Vector2(1.0f, 0.0f);
|
vertices[3].uv0 = Vector2(1.0f, 0.0f);
|
||||||
|
|
||||||
const uint32_t indices[6] = { 0, 1, 2, 2, 1, 3 };
|
const uint32_t indices[6] = { 0, 2, 1, 2, 3, 1 };
|
||||||
mesh->SetVertexData(
|
mesh->SetVertexData(
|
||||||
vertices,
|
vertices,
|
||||||
sizeof(vertices),
|
sizeof(vertices),
|
||||||
|
|||||||
@@ -455,7 +455,7 @@ TEST(BuiltinDepthStylePass_Test, OpenGLRuntimeTranspilesShadowCasterAlphaVariant
|
|||||||
delete shader;
|
delete shader;
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(BuiltinForwardPipeline_Test, BuiltinSkyboxShaderDeclaresExplicitEnvironmentResourceContract) {
|
TEST(BuiltinForwardPipeline_Test, BuiltinSkyboxShaderUsesUnityStyleSingleSourceContract) {
|
||||||
ShaderLoader loader;
|
ShaderLoader loader;
|
||||||
LoadResult result = loader.Load(GetBuiltinSkyboxShaderPath());
|
LoadResult result = loader.Load(GetBuiltinSkyboxShaderPath());
|
||||||
ASSERT_TRUE(result);
|
ASSERT_TRUE(result);
|
||||||
@@ -466,7 +466,11 @@ TEST(BuiltinForwardPipeline_Test, BuiltinSkyboxShaderDeclaresExplicitEnvironment
|
|||||||
|
|
||||||
const ShaderPass* pass = shader->FindPass("Skybox");
|
const ShaderPass* pass = shader->FindPass("Skybox");
|
||||||
ASSERT_NE(pass, nullptr);
|
ASSERT_NE(pass, nullptr);
|
||||||
ASSERT_EQ(pass->resources.Size(), 5u);
|
EXPECT_TRUE(pass->resources.Empty());
|
||||||
|
EXPECT_TRUE(pass->hasFixedFunctionState);
|
||||||
|
EXPECT_EQ(pass->fixedFunctionState.cullMode, MaterialCullMode::None);
|
||||||
|
EXPECT_FALSE(pass->fixedFunctionState.depthWriteEnable);
|
||||||
|
EXPECT_EQ(pass->fixedFunctionState.depthFunc, MaterialComparisonFunc::LessEqual);
|
||||||
|
|
||||||
const ShaderPropertyDesc* tint = shader->FindProperty("_Tint");
|
const ShaderPropertyDesc* tint = shader->FindProperty("_Tint");
|
||||||
ASSERT_NE(tint, nullptr);
|
ASSERT_NE(tint, nullptr);
|
||||||
@@ -493,35 +497,37 @@ TEST(BuiltinForwardPipeline_Test, BuiltinSkyboxShaderDeclaresExplicitEnvironment
|
|||||||
EXPECT_EQ(cubemap->type, ShaderPropertyType::TextureCube);
|
EXPECT_EQ(cubemap->type, ShaderPropertyType::TextureCube);
|
||||||
EXPECT_EQ(cubemap->semantic, "SkyboxTexture");
|
EXPECT_EQ(cubemap->semantic, "SkyboxTexture");
|
||||||
|
|
||||||
EXPECT_EQ(pass->resources[0].semantic, "Environment");
|
delete shader;
|
||||||
EXPECT_EQ(pass->resources[0].type, ShaderResourceType::ConstantBuffer);
|
}
|
||||||
EXPECT_EQ(pass->resources[0].set, 0u);
|
|
||||||
EXPECT_EQ(pass->resources[0].binding, 0u);
|
|
||||||
|
|
||||||
EXPECT_EQ(pass->resources[1].semantic, "Material");
|
TEST(BuiltinForwardPipeline_Test, BuildsBuiltinPassResourceBindingPlanFromImplicitSkyboxShaderContract) {
|
||||||
EXPECT_EQ(pass->resources[1].type, ShaderResourceType::ConstantBuffer);
|
ShaderLoader loader;
|
||||||
EXPECT_EQ(pass->resources[1].set, 1u);
|
LoadResult result = loader.Load(GetBuiltinSkyboxShaderPath());
|
||||||
EXPECT_EQ(pass->resources[1].binding, 0u);
|
ASSERT_TRUE(result);
|
||||||
|
ASSERT_NE(result.resource, nullptr);
|
||||||
|
|
||||||
EXPECT_EQ(pass->resources[2].semantic, "SkyboxPanoramicTexture");
|
Shader* shader = static_cast<Shader*>(result.resource);
|
||||||
EXPECT_EQ(pass->resources[2].type, ShaderResourceType::Texture2D);
|
ASSERT_NE(shader, nullptr);
|
||||||
EXPECT_EQ(pass->resources[2].set, 2u);
|
|
||||||
EXPECT_EQ(pass->resources[2].binding, 0u);
|
|
||||||
|
|
||||||
EXPECT_EQ(pass->resources[3].semantic, "SkyboxTexture");
|
const ShaderPass* pass = shader->FindPass("Skybox");
|
||||||
EXPECT_EQ(pass->resources[3].type, ShaderResourceType::TextureCube);
|
ASSERT_NE(pass, nullptr);
|
||||||
EXPECT_EQ(pass->resources[3].set, 3u);
|
|
||||||
EXPECT_EQ(pass->resources[3].binding, 0u);
|
|
||||||
|
|
||||||
EXPECT_EQ(pass->resources[4].semantic, "LinearClampSampler");
|
BuiltinPassResourceBindingPlan plan = {};
|
||||||
EXPECT_EQ(pass->resources[4].type, ShaderResourceType::Sampler);
|
String error;
|
||||||
EXPECT_EQ(pass->resources[4].set, 4u);
|
EXPECT_TRUE(TryBuildBuiltinPassResourceBindingPlan(*pass, plan, &error)) << error.CStr();
|
||||||
EXPECT_EQ(pass->resources[4].binding, 0u);
|
ASSERT_EQ(plan.bindings.Size(), 5u);
|
||||||
|
EXPECT_TRUE(plan.environment.IsValid());
|
||||||
|
EXPECT_TRUE(plan.material.IsValid());
|
||||||
|
EXPECT_TRUE(plan.skyboxPanoramicTexture.IsValid());
|
||||||
|
EXPECT_TRUE(plan.skyboxTexture.IsValid());
|
||||||
|
EXPECT_TRUE(plan.linearClampSampler.IsValid());
|
||||||
|
EXPECT_EQ(plan.firstDescriptorSet, 0u);
|
||||||
|
EXPECT_EQ(plan.descriptorSetCount, 5u);
|
||||||
|
|
||||||
delete shader;
|
delete shader;
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(BuiltinForwardPipeline_Test, BuiltinFinalColorShaderDeclaresExplicitFullscreenResourceContract) {
|
TEST(BuiltinForwardPipeline_Test, BuiltinFinalColorShaderUsesUnityStyleSingleSourceContract) {
|
||||||
ShaderLoader loader;
|
ShaderLoader loader;
|
||||||
LoadResult result = loader.Load(GetBuiltinFinalColorShaderPath());
|
LoadResult result = loader.Load(GetBuiltinFinalColorShaderPath());
|
||||||
ASSERT_TRUE(result);
|
ASSERT_TRUE(result);
|
||||||
@@ -532,7 +538,11 @@ TEST(BuiltinForwardPipeline_Test, BuiltinFinalColorShaderDeclaresExplicitFullscr
|
|||||||
|
|
||||||
const ShaderPass* pass = shader->FindPass("FinalColor");
|
const ShaderPass* pass = shader->FindPass("FinalColor");
|
||||||
ASSERT_NE(pass, nullptr);
|
ASSERT_NE(pass, nullptr);
|
||||||
ASSERT_EQ(pass->resources.Size(), 3u);
|
EXPECT_TRUE(pass->resources.Empty());
|
||||||
|
EXPECT_TRUE(pass->hasFixedFunctionState);
|
||||||
|
EXPECT_EQ(pass->fixedFunctionState.cullMode, MaterialCullMode::None);
|
||||||
|
EXPECT_FALSE(pass->fixedFunctionState.depthWriteEnable);
|
||||||
|
EXPECT_EQ(pass->fixedFunctionState.depthFunc, MaterialComparisonFunc::Always);
|
||||||
|
|
||||||
const ShaderPropertyDesc* colorScale = shader->FindProperty("_ColorScale");
|
const ShaderPropertyDesc* colorScale = shader->FindProperty("_ColorScale");
|
||||||
ASSERT_NE(colorScale, nullptr);
|
ASSERT_NE(colorScale, nullptr);
|
||||||
@@ -550,20 +560,307 @@ TEST(BuiltinForwardPipeline_Test, BuiltinFinalColorShaderDeclaresExplicitFullscr
|
|||||||
ASSERT_NE(toneMappingMode, nullptr);
|
ASSERT_NE(toneMappingMode, nullptr);
|
||||||
EXPECT_EQ(toneMappingMode->type, ShaderPropertyType::Float);
|
EXPECT_EQ(toneMappingMode->type, ShaderPropertyType::Float);
|
||||||
|
|
||||||
EXPECT_STREQ(pass->resources[0].name.CStr(), "FinalColorConstants");
|
delete shader;
|
||||||
EXPECT_EQ(pass->resources[0].type, ShaderResourceType::ConstantBuffer);
|
}
|
||||||
EXPECT_EQ(pass->resources[0].set, 0u);
|
|
||||||
EXPECT_EQ(pass->resources[0].binding, 0u);
|
|
||||||
|
|
||||||
EXPECT_STREQ(pass->resources[1].name.CStr(), "SourceColorTexture");
|
TEST(BuiltinForwardPipeline_Test, BuildsBuiltinPassResourceBindingPlanFromImplicitFinalColorShaderContract) {
|
||||||
EXPECT_EQ(pass->resources[1].type, ShaderResourceType::Texture2D);
|
ShaderLoader loader;
|
||||||
EXPECT_EQ(pass->resources[1].set, 1u);
|
LoadResult result = loader.Load(GetBuiltinFinalColorShaderPath());
|
||||||
EXPECT_EQ(pass->resources[1].binding, 0u);
|
ASSERT_TRUE(result);
|
||||||
|
ASSERT_NE(result.resource, nullptr);
|
||||||
|
|
||||||
EXPECT_STREQ(pass->resources[2].name.CStr(), "LinearClampSampler");
|
Shader* shader = static_cast<Shader*>(result.resource);
|
||||||
EXPECT_EQ(pass->resources[2].type, ShaderResourceType::Sampler);
|
ASSERT_NE(shader, nullptr);
|
||||||
EXPECT_EQ(pass->resources[2].set, 2u);
|
|
||||||
EXPECT_EQ(pass->resources[2].binding, 0u);
|
const ShaderPass* pass = shader->FindPass("FinalColor");
|
||||||
|
ASSERT_NE(pass, nullptr);
|
||||||
|
|
||||||
|
BuiltinPassResourceBindingPlan plan = {};
|
||||||
|
String error;
|
||||||
|
EXPECT_TRUE(TryBuildBuiltinPassResourceBindingPlan(*pass, plan, &error)) << error.CStr();
|
||||||
|
ASSERT_EQ(plan.bindings.Size(), 3u);
|
||||||
|
EXPECT_TRUE(plan.passConstants.IsValid());
|
||||||
|
EXPECT_TRUE(plan.sourceColorTexture.IsValid());
|
||||||
|
EXPECT_TRUE(plan.linearClampSampler.IsValid());
|
||||||
|
EXPECT_EQ(plan.firstDescriptorSet, 0u);
|
||||||
|
EXPECT_EQ(plan.descriptorSetCount, 3u);
|
||||||
|
|
||||||
|
delete shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(BuiltinForwardPipeline_Test, BuiltinColorScalePostProcessShaderUsesUnityStyleSingleSourceContract) {
|
||||||
|
ShaderLoader loader;
|
||||||
|
LoadResult result = loader.Load(GetBuiltinColorScalePostProcessShaderPath());
|
||||||
|
ASSERT_TRUE(result);
|
||||||
|
ASSERT_NE(result.resource, nullptr);
|
||||||
|
|
||||||
|
Shader* shader = static_cast<Shader*>(result.resource);
|
||||||
|
ASSERT_NE(shader, nullptr);
|
||||||
|
|
||||||
|
const ShaderPass* pass = shader->FindPass("ColorScale");
|
||||||
|
ASSERT_NE(pass, nullptr);
|
||||||
|
EXPECT_TRUE(pass->resources.Empty());
|
||||||
|
EXPECT_TRUE(pass->hasFixedFunctionState);
|
||||||
|
EXPECT_EQ(pass->fixedFunctionState.cullMode, MaterialCullMode::None);
|
||||||
|
EXPECT_FALSE(pass->fixedFunctionState.depthWriteEnable);
|
||||||
|
EXPECT_EQ(pass->fixedFunctionState.depthFunc, MaterialComparisonFunc::Always);
|
||||||
|
|
||||||
|
const ShaderPropertyDesc* colorScale = shader->FindProperty("_ColorScale");
|
||||||
|
ASSERT_NE(colorScale, nullptr);
|
||||||
|
EXPECT_EQ(colorScale->type, ShaderPropertyType::Color);
|
||||||
|
|
||||||
|
delete shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(BuiltinForwardPipeline_Test, BuildsBuiltinPassResourceBindingPlanFromImplicitColorScalePostProcessShaderContract) {
|
||||||
|
ShaderLoader loader;
|
||||||
|
LoadResult result = loader.Load(GetBuiltinColorScalePostProcessShaderPath());
|
||||||
|
ASSERT_TRUE(result);
|
||||||
|
ASSERT_NE(result.resource, nullptr);
|
||||||
|
|
||||||
|
Shader* shader = static_cast<Shader*>(result.resource);
|
||||||
|
ASSERT_NE(shader, nullptr);
|
||||||
|
|
||||||
|
const ShaderPass* pass = shader->FindPass("ColorScale");
|
||||||
|
ASSERT_NE(pass, nullptr);
|
||||||
|
|
||||||
|
BuiltinPassResourceBindingPlan plan = {};
|
||||||
|
String error;
|
||||||
|
EXPECT_TRUE(TryBuildBuiltinPassResourceBindingPlan(*pass, plan, &error)) << error.CStr();
|
||||||
|
ASSERT_EQ(plan.bindings.Size(), 3u);
|
||||||
|
EXPECT_TRUE(plan.passConstants.IsValid());
|
||||||
|
EXPECT_TRUE(plan.sourceColorTexture.IsValid());
|
||||||
|
EXPECT_TRUE(plan.linearClampSampler.IsValid());
|
||||||
|
EXPECT_EQ(plan.firstDescriptorSet, 0u);
|
||||||
|
EXPECT_EQ(plan.descriptorSetCount, 3u);
|
||||||
|
|
||||||
|
delete shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(BuiltinForwardPipeline_Test, VulkanRuntimeCompileDescRewritesUnityStyleFinalColorBindingsToDescriptorSpaces) {
|
||||||
|
ShaderLoader loader;
|
||||||
|
LoadResult result = loader.Load(GetBuiltinFinalColorShaderPath());
|
||||||
|
ASSERT_TRUE(result);
|
||||||
|
ASSERT_NE(result.resource, nullptr);
|
||||||
|
|
||||||
|
Shader* shader = static_cast<Shader*>(result.resource);
|
||||||
|
ASSERT_NE(shader, nullptr);
|
||||||
|
|
||||||
|
const ShaderPass* pass = shader->FindPass("FinalColor");
|
||||||
|
ASSERT_NE(pass, nullptr);
|
||||||
|
|
||||||
|
const ShaderStageVariant* d3d12Fragment = shader->FindVariant(
|
||||||
|
"FinalColor",
|
||||||
|
XCEngine::Resources::ShaderType::Fragment,
|
||||||
|
XCEngine::Resources::ShaderBackend::D3D12);
|
||||||
|
ASSERT_NE(d3d12Fragment, nullptr);
|
||||||
|
|
||||||
|
ShaderCompileDesc d3d12CompileDesc = {};
|
||||||
|
::XCEngine::Rendering::Detail::ApplyShaderStageVariant(
|
||||||
|
*pass,
|
||||||
|
XCEngine::Resources::ShaderBackend::D3D12,
|
||||||
|
*d3d12Fragment,
|
||||||
|
d3d12CompileDesc);
|
||||||
|
const std::string d3d12Source(
|
||||||
|
reinterpret_cast<const char*>(d3d12CompileDesc.source.data()),
|
||||||
|
d3d12CompileDesc.source.size());
|
||||||
|
EXPECT_NE(d3d12Source.find("cbuffer FinalColorConstants : register(b0)"), std::string::npos);
|
||||||
|
EXPECT_NE(d3d12Source.find("Texture2D gSourceColorTexture : register(t0)"), std::string::npos);
|
||||||
|
EXPECT_NE(d3d12Source.find("SamplerState gLinearClampSampler : register(s0)"), std::string::npos);
|
||||||
|
EXPECT_EQ(d3d12Source.find("space1"), std::string::npos);
|
||||||
|
EXPECT_EQ(d3d12Source.find("space2"), std::string::npos);
|
||||||
|
|
||||||
|
const ShaderStageVariant* vulkanFragment = shader->FindVariant(
|
||||||
|
"FinalColor",
|
||||||
|
XCEngine::Resources::ShaderType::Fragment,
|
||||||
|
XCEngine::Resources::ShaderBackend::Vulkan);
|
||||||
|
ASSERT_NE(vulkanFragment, nullptr);
|
||||||
|
|
||||||
|
const std::string runtimeSource =
|
||||||
|
::XCEngine::Rendering::Detail::BuildRuntimeShaderSource(
|
||||||
|
*pass,
|
||||||
|
XCEngine::Resources::ShaderBackend::Vulkan,
|
||||||
|
*vulkanFragment);
|
||||||
|
EXPECT_NE(
|
||||||
|
runtimeSource.find("cbuffer FinalColorConstants : register(b0, space0)"),
|
||||||
|
std::string::npos);
|
||||||
|
EXPECT_NE(
|
||||||
|
runtimeSource.find("Texture2D gSourceColorTexture : register(t0, space1)"),
|
||||||
|
std::string::npos);
|
||||||
|
EXPECT_NE(
|
||||||
|
runtimeSource.find("SamplerState gLinearClampSampler : register(s0, space2)"),
|
||||||
|
std::string::npos);
|
||||||
|
|
||||||
|
ShaderCompileDesc vulkanCompileDesc = {};
|
||||||
|
::XCEngine::Rendering::Detail::ApplyShaderStageVariant(
|
||||||
|
*pass,
|
||||||
|
XCEngine::Resources::ShaderBackend::Vulkan,
|
||||||
|
*vulkanFragment,
|
||||||
|
vulkanCompileDesc);
|
||||||
|
const std::string vulkanSource(
|
||||||
|
reinterpret_cast<const char*>(vulkanCompileDesc.source.data()),
|
||||||
|
vulkanCompileDesc.source.size());
|
||||||
|
EXPECT_NE(vulkanSource.find("ApplyLinearToSRGB"), std::string::npos);
|
||||||
|
EXPECT_NE(vulkanSource.find("ApplyToneMapping"), std::string::npos);
|
||||||
|
|
||||||
|
delete shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(BuiltinForwardPipeline_Test, OpenGLRuntimeTranspilesFinalColorVariantToCombinedSourceSampler) {
|
||||||
|
ShaderLoader loader;
|
||||||
|
LoadResult result = loader.Load(GetBuiltinFinalColorShaderPath());
|
||||||
|
ASSERT_TRUE(result);
|
||||||
|
ASSERT_NE(result.resource, nullptr);
|
||||||
|
|
||||||
|
Shader* shader = static_cast<Shader*>(result.resource);
|
||||||
|
ASSERT_NE(shader, nullptr);
|
||||||
|
|
||||||
|
const ShaderPass* pass = shader->FindPass("FinalColor");
|
||||||
|
ASSERT_NE(pass, nullptr);
|
||||||
|
|
||||||
|
const ShaderStageVariant* openGLFragment = shader->FindVariant(
|
||||||
|
"FinalColor",
|
||||||
|
XCEngine::Resources::ShaderType::Fragment,
|
||||||
|
XCEngine::Resources::ShaderBackend::OpenGL);
|
||||||
|
ASSERT_NE(openGLFragment, nullptr);
|
||||||
|
|
||||||
|
ShaderCompileDesc compileDesc = {};
|
||||||
|
::XCEngine::Rendering::Detail::ApplyShaderStageVariant(
|
||||||
|
*pass,
|
||||||
|
XCEngine::Resources::ShaderBackend::OpenGL,
|
||||||
|
*openGLFragment,
|
||||||
|
compileDesc);
|
||||||
|
|
||||||
|
XCEngine::RHI::CompiledSpirvShader spirvShader = {};
|
||||||
|
std::string errorMessage;
|
||||||
|
ASSERT_TRUE(
|
||||||
|
XCEngine::RHI::CompileSpirvShader(
|
||||||
|
compileDesc,
|
||||||
|
XCEngine::RHI::SpirvTargetEnvironment::Vulkan,
|
||||||
|
spirvShader,
|
||||||
|
&errorMessage))
|
||||||
|
<< errorMessage;
|
||||||
|
|
||||||
|
std::string glslSource;
|
||||||
|
ASSERT_TRUE(XCEngine::RHI::TranspileSpirvToOpenGLGLSL(spirvShader, glslSource, &errorMessage))
|
||||||
|
<< errorMessage;
|
||||||
|
EXPECT_NE(glslSource.find("uniform sampler2D SPIRV_Cross_Combined"), std::string::npos);
|
||||||
|
EXPECT_NE(glslSource.find("texture(SPIRV_Cross_Combined"), std::string::npos);
|
||||||
|
EXPECT_NE(glslSource.find("FinalColorConstants"), std::string::npos);
|
||||||
|
|
||||||
|
delete shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(BuiltinForwardPipeline_Test, VulkanRuntimeCompileDescRewritesUnityStyleColorScaleBindingsToDescriptorSpaces) {
|
||||||
|
ShaderLoader loader;
|
||||||
|
LoadResult result = loader.Load(GetBuiltinColorScalePostProcessShaderPath());
|
||||||
|
ASSERT_TRUE(result);
|
||||||
|
ASSERT_NE(result.resource, nullptr);
|
||||||
|
|
||||||
|
Shader* shader = static_cast<Shader*>(result.resource);
|
||||||
|
ASSERT_NE(shader, nullptr);
|
||||||
|
|
||||||
|
const ShaderPass* pass = shader->FindPass("ColorScale");
|
||||||
|
ASSERT_NE(pass, nullptr);
|
||||||
|
|
||||||
|
const ShaderStageVariant* d3d12Fragment = shader->FindVariant(
|
||||||
|
"ColorScale",
|
||||||
|
XCEngine::Resources::ShaderType::Fragment,
|
||||||
|
XCEngine::Resources::ShaderBackend::D3D12);
|
||||||
|
ASSERT_NE(d3d12Fragment, nullptr);
|
||||||
|
|
||||||
|
ShaderCompileDesc d3d12CompileDesc = {};
|
||||||
|
::XCEngine::Rendering::Detail::ApplyShaderStageVariant(
|
||||||
|
*pass,
|
||||||
|
XCEngine::Resources::ShaderBackend::D3D12,
|
||||||
|
*d3d12Fragment,
|
||||||
|
d3d12CompileDesc);
|
||||||
|
const std::string d3d12Source(
|
||||||
|
reinterpret_cast<const char*>(d3d12CompileDesc.source.data()),
|
||||||
|
d3d12CompileDesc.source.size());
|
||||||
|
EXPECT_NE(d3d12Source.find("cbuffer PostProcessConstants : register(b0)"), std::string::npos);
|
||||||
|
EXPECT_NE(d3d12Source.find("Texture2D gSourceColorTexture : register(t0)"), std::string::npos);
|
||||||
|
EXPECT_NE(d3d12Source.find("SamplerState gLinearClampSampler : register(s0)"), std::string::npos);
|
||||||
|
EXPECT_EQ(d3d12Source.find("space1"), std::string::npos);
|
||||||
|
EXPECT_EQ(d3d12Source.find("space2"), std::string::npos);
|
||||||
|
|
||||||
|
const ShaderStageVariant* vulkanFragment = shader->FindVariant(
|
||||||
|
"ColorScale",
|
||||||
|
XCEngine::Resources::ShaderType::Fragment,
|
||||||
|
XCEngine::Resources::ShaderBackend::Vulkan);
|
||||||
|
ASSERT_NE(vulkanFragment, nullptr);
|
||||||
|
|
||||||
|
const std::string runtimeSource =
|
||||||
|
::XCEngine::Rendering::Detail::BuildRuntimeShaderSource(
|
||||||
|
*pass,
|
||||||
|
XCEngine::Resources::ShaderBackend::Vulkan,
|
||||||
|
*vulkanFragment);
|
||||||
|
EXPECT_NE(
|
||||||
|
runtimeSource.find("cbuffer PostProcessConstants : register(b0, space0)"),
|
||||||
|
std::string::npos);
|
||||||
|
EXPECT_NE(
|
||||||
|
runtimeSource.find("Texture2D gSourceColorTexture : register(t0, space1)"),
|
||||||
|
std::string::npos);
|
||||||
|
EXPECT_NE(
|
||||||
|
runtimeSource.find("SamplerState gLinearClampSampler : register(s0, space2)"),
|
||||||
|
std::string::npos);
|
||||||
|
|
||||||
|
ShaderCompileDesc vulkanCompileDesc = {};
|
||||||
|
::XCEngine::Rendering::Detail::ApplyShaderStageVariant(
|
||||||
|
*pass,
|
||||||
|
XCEngine::Resources::ShaderBackend::Vulkan,
|
||||||
|
*vulkanFragment,
|
||||||
|
vulkanCompileDesc);
|
||||||
|
const std::string vulkanSource(
|
||||||
|
reinterpret_cast<const char*>(vulkanCompileDesc.source.data()),
|
||||||
|
vulkanCompileDesc.source.size());
|
||||||
|
EXPECT_NE(vulkanSource.find("gSourceColorTexture.Sample"), std::string::npos);
|
||||||
|
EXPECT_NE(vulkanSource.find("gColorScale"), std::string::npos);
|
||||||
|
|
||||||
|
delete shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(BuiltinForwardPipeline_Test, OpenGLRuntimeTranspilesColorScaleVariantToCombinedSourceSampler) {
|
||||||
|
ShaderLoader loader;
|
||||||
|
LoadResult result = loader.Load(GetBuiltinColorScalePostProcessShaderPath());
|
||||||
|
ASSERT_TRUE(result);
|
||||||
|
ASSERT_NE(result.resource, nullptr);
|
||||||
|
|
||||||
|
Shader* shader = static_cast<Shader*>(result.resource);
|
||||||
|
ASSERT_NE(shader, nullptr);
|
||||||
|
|
||||||
|
const ShaderPass* pass = shader->FindPass("ColorScale");
|
||||||
|
ASSERT_NE(pass, nullptr);
|
||||||
|
|
||||||
|
const ShaderStageVariant* openGLFragment = shader->FindVariant(
|
||||||
|
"ColorScale",
|
||||||
|
XCEngine::Resources::ShaderType::Fragment,
|
||||||
|
XCEngine::Resources::ShaderBackend::OpenGL);
|
||||||
|
ASSERT_NE(openGLFragment, nullptr);
|
||||||
|
|
||||||
|
ShaderCompileDesc compileDesc = {};
|
||||||
|
::XCEngine::Rendering::Detail::ApplyShaderStageVariant(
|
||||||
|
*pass,
|
||||||
|
XCEngine::Resources::ShaderBackend::OpenGL,
|
||||||
|
*openGLFragment,
|
||||||
|
compileDesc);
|
||||||
|
|
||||||
|
XCEngine::RHI::CompiledSpirvShader spirvShader = {};
|
||||||
|
std::string errorMessage;
|
||||||
|
ASSERT_TRUE(
|
||||||
|
XCEngine::RHI::CompileSpirvShader(
|
||||||
|
compileDesc,
|
||||||
|
XCEngine::RHI::SpirvTargetEnvironment::Vulkan,
|
||||||
|
spirvShader,
|
||||||
|
&errorMessage))
|
||||||
|
<< errorMessage;
|
||||||
|
|
||||||
|
std::string glslSource;
|
||||||
|
ASSERT_TRUE(XCEngine::RHI::TranspileSpirvToOpenGLGLSL(spirvShader, glslSource, &errorMessage))
|
||||||
|
<< errorMessage;
|
||||||
|
EXPECT_NE(glslSource.find("uniform sampler2D SPIRV_Cross_Combined"), std::string::npos);
|
||||||
|
EXPECT_NE(glslSource.find("texture(SPIRV_Cross_Combined"), std::string::npos);
|
||||||
|
EXPECT_NE(glslSource.find("PostProcessConstants"), std::string::npos);
|
||||||
|
|
||||||
delete shader;
|
delete shader;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2117,6 +2117,160 @@ TEST(ShaderLoader, LoadBuiltinShadowCasterShaderBuildsUnityStyleSingleSourceVari
|
|||||||
delete shader;
|
delete shader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(ShaderLoader, LoadBuiltinFinalColorShaderBuildsUnityStyleSingleSourceVariants) {
|
||||||
|
ShaderLoader loader;
|
||||||
|
LoadResult result = loader.Load(GetBuiltinFinalColorShaderPath());
|
||||||
|
ASSERT_TRUE(result);
|
||||||
|
ASSERT_NE(result.resource, nullptr);
|
||||||
|
|
||||||
|
Shader* shader = static_cast<Shader*>(result.resource);
|
||||||
|
ASSERT_NE(shader, nullptr);
|
||||||
|
ASSERT_TRUE(shader->IsValid());
|
||||||
|
|
||||||
|
const ShaderPass* pass = shader->FindPass("FinalColor");
|
||||||
|
ASSERT_NE(pass, nullptr);
|
||||||
|
ASSERT_EQ(shader->GetProperties().Size(), 4u);
|
||||||
|
ASSERT_EQ(pass->variants.Size(), 2u);
|
||||||
|
ASSERT_EQ(pass->tags.Size(), 1u);
|
||||||
|
EXPECT_TRUE(pass->resources.Empty());
|
||||||
|
EXPECT_TRUE(pass->hasFixedFunctionState);
|
||||||
|
EXPECT_EQ(pass->fixedFunctionState.cullMode, MaterialCullMode::None);
|
||||||
|
EXPECT_FALSE(pass->fixedFunctionState.depthWriteEnable);
|
||||||
|
EXPECT_EQ(pass->fixedFunctionState.depthFunc, MaterialComparisonFunc::Always);
|
||||||
|
EXPECT_EQ(pass->tags[0].name, "LightMode");
|
||||||
|
EXPECT_EQ(pass->tags[0].value, "FinalOutput");
|
||||||
|
|
||||||
|
const ShaderPropertyDesc* colorScaleProperty = shader->FindProperty("_ColorScale");
|
||||||
|
ASSERT_NE(colorScaleProperty, nullptr);
|
||||||
|
EXPECT_EQ(colorScaleProperty->type, ShaderPropertyType::Color);
|
||||||
|
|
||||||
|
const ShaderPropertyDesc* exposureProperty = shader->FindProperty("_Exposure");
|
||||||
|
ASSERT_NE(exposureProperty, nullptr);
|
||||||
|
EXPECT_EQ(exposureProperty->type, ShaderPropertyType::Float);
|
||||||
|
|
||||||
|
const ShaderPropertyDesc* outputTransferProperty = shader->FindProperty("_OutputTransferMode");
|
||||||
|
ASSERT_NE(outputTransferProperty, nullptr);
|
||||||
|
EXPECT_EQ(outputTransferProperty->type, ShaderPropertyType::Float);
|
||||||
|
|
||||||
|
const ShaderPropertyDesc* toneMappingProperty = shader->FindProperty("_ToneMappingMode");
|
||||||
|
ASSERT_NE(toneMappingProperty, nullptr);
|
||||||
|
EXPECT_EQ(toneMappingProperty->type, ShaderPropertyType::Float);
|
||||||
|
|
||||||
|
EXPECT_NE(shader->FindVariant("FinalColor", ShaderType::Vertex, ShaderBackend::D3D12), nullptr);
|
||||||
|
EXPECT_NE(shader->FindVariant("FinalColor", ShaderType::Fragment, ShaderBackend::D3D12), nullptr);
|
||||||
|
EXPECT_NE(shader->FindVariant("FinalColor", ShaderType::Vertex, ShaderBackend::OpenGL), nullptr);
|
||||||
|
EXPECT_NE(shader->FindVariant("FinalColor", ShaderType::Fragment, ShaderBackend::OpenGL), nullptr);
|
||||||
|
EXPECT_NE(shader->FindVariant("FinalColor", ShaderType::Vertex, ShaderBackend::Vulkan), nullptr);
|
||||||
|
EXPECT_NE(shader->FindVariant("FinalColor", ShaderType::Fragment, ShaderBackend::Vulkan), nullptr);
|
||||||
|
|
||||||
|
const ShaderStageVariant* d3d12Vertex = shader->FindVariant(
|
||||||
|
"FinalColor",
|
||||||
|
ShaderType::Vertex,
|
||||||
|
ShaderBackend::D3D12);
|
||||||
|
ASSERT_NE(d3d12Vertex, nullptr);
|
||||||
|
EXPECT_EQ(d3d12Vertex->backend, ShaderBackend::Generic);
|
||||||
|
EXPECT_EQ(d3d12Vertex->language, ShaderLanguage::HLSL);
|
||||||
|
EXPECT_EQ(d3d12Vertex->entryPoint, "MainVS");
|
||||||
|
EXPECT_EQ(d3d12Vertex->profile, "vs_5_0");
|
||||||
|
EXPECT_NE(std::string(d3d12Vertex->sourceCode.CStr()).find("UNITY_UV_STARTS_AT_TOP"), std::string::npos);
|
||||||
|
|
||||||
|
const ShaderStageVariant* openglFragment = shader->FindVariant(
|
||||||
|
"FinalColor",
|
||||||
|
ShaderType::Fragment,
|
||||||
|
ShaderBackend::OpenGL);
|
||||||
|
ASSERT_NE(openglFragment, nullptr);
|
||||||
|
EXPECT_EQ(openglFragment->backend, ShaderBackend::Generic);
|
||||||
|
EXPECT_EQ(openglFragment->language, ShaderLanguage::HLSL);
|
||||||
|
EXPECT_EQ(openglFragment->entryPoint, "MainPS");
|
||||||
|
EXPECT_EQ(openglFragment->profile, "ps_5_0");
|
||||||
|
EXPECT_NE(std::string(openglFragment->sourceCode.CStr()).find("gSourceColorTexture.Sample"), std::string::npos);
|
||||||
|
|
||||||
|
const ShaderStageVariant* vulkanFragment = shader->FindVariant(
|
||||||
|
"FinalColor",
|
||||||
|
ShaderType::Fragment,
|
||||||
|
ShaderBackend::Vulkan);
|
||||||
|
ASSERT_NE(vulkanFragment, nullptr);
|
||||||
|
EXPECT_EQ(vulkanFragment->backend, ShaderBackend::Generic);
|
||||||
|
EXPECT_EQ(vulkanFragment->language, ShaderLanguage::HLSL);
|
||||||
|
EXPECT_EQ(vulkanFragment->entryPoint, "MainPS");
|
||||||
|
EXPECT_EQ(vulkanFragment->profile, "ps_5_0");
|
||||||
|
EXPECT_NE(std::string(vulkanFragment->sourceCode.CStr()).find("ApplyToneMapping"), std::string::npos);
|
||||||
|
EXPECT_NE(std::string(vulkanFragment->sourceCode.CStr()).find("gFinalColorParams"), std::string::npos);
|
||||||
|
|
||||||
|
delete shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ShaderLoader, LoadBuiltinColorScalePostProcessShaderBuildsUnityStyleSingleSourceVariants) {
|
||||||
|
ShaderLoader loader;
|
||||||
|
LoadResult result = loader.Load(GetBuiltinColorScalePostProcessShaderPath());
|
||||||
|
ASSERT_TRUE(result);
|
||||||
|
ASSERT_NE(result.resource, nullptr);
|
||||||
|
|
||||||
|
Shader* shader = static_cast<Shader*>(result.resource);
|
||||||
|
ASSERT_NE(shader, nullptr);
|
||||||
|
ASSERT_TRUE(shader->IsValid());
|
||||||
|
|
||||||
|
const ShaderPass* pass = shader->FindPass("ColorScale");
|
||||||
|
ASSERT_NE(pass, nullptr);
|
||||||
|
ASSERT_EQ(shader->GetProperties().Size(), 1u);
|
||||||
|
ASSERT_EQ(pass->variants.Size(), 2u);
|
||||||
|
ASSERT_EQ(pass->tags.Size(), 1u);
|
||||||
|
EXPECT_TRUE(pass->resources.Empty());
|
||||||
|
EXPECT_TRUE(pass->hasFixedFunctionState);
|
||||||
|
EXPECT_EQ(pass->fixedFunctionState.cullMode, MaterialCullMode::None);
|
||||||
|
EXPECT_FALSE(pass->fixedFunctionState.depthWriteEnable);
|
||||||
|
EXPECT_EQ(pass->fixedFunctionState.depthFunc, MaterialComparisonFunc::Always);
|
||||||
|
EXPECT_EQ(pass->tags[0].name, "LightMode");
|
||||||
|
EXPECT_EQ(pass->tags[0].value, "PostProcess");
|
||||||
|
|
||||||
|
const ShaderPropertyDesc* colorScaleProperty = shader->FindProperty("_ColorScale");
|
||||||
|
ASSERT_NE(colorScaleProperty, nullptr);
|
||||||
|
EXPECT_EQ(colorScaleProperty->type, ShaderPropertyType::Color);
|
||||||
|
|
||||||
|
EXPECT_NE(shader->FindVariant("ColorScale", ShaderType::Vertex, ShaderBackend::D3D12), nullptr);
|
||||||
|
EXPECT_NE(shader->FindVariant("ColorScale", ShaderType::Fragment, ShaderBackend::D3D12), nullptr);
|
||||||
|
EXPECT_NE(shader->FindVariant("ColorScale", ShaderType::Vertex, ShaderBackend::OpenGL), nullptr);
|
||||||
|
EXPECT_NE(shader->FindVariant("ColorScale", ShaderType::Fragment, ShaderBackend::OpenGL), nullptr);
|
||||||
|
EXPECT_NE(shader->FindVariant("ColorScale", ShaderType::Vertex, ShaderBackend::Vulkan), nullptr);
|
||||||
|
EXPECT_NE(shader->FindVariant("ColorScale", ShaderType::Fragment, ShaderBackend::Vulkan), nullptr);
|
||||||
|
|
||||||
|
const ShaderStageVariant* d3d12Vertex = shader->FindVariant(
|
||||||
|
"ColorScale",
|
||||||
|
ShaderType::Vertex,
|
||||||
|
ShaderBackend::D3D12);
|
||||||
|
ASSERT_NE(d3d12Vertex, nullptr);
|
||||||
|
EXPECT_EQ(d3d12Vertex->backend, ShaderBackend::Generic);
|
||||||
|
EXPECT_EQ(d3d12Vertex->language, ShaderLanguage::HLSL);
|
||||||
|
EXPECT_EQ(d3d12Vertex->entryPoint, "MainVS");
|
||||||
|
EXPECT_EQ(d3d12Vertex->profile, "vs_5_0");
|
||||||
|
EXPECT_NE(std::string(d3d12Vertex->sourceCode.CStr()).find("UNITY_UV_STARTS_AT_TOP"), std::string::npos);
|
||||||
|
|
||||||
|
const ShaderStageVariant* openglFragment = shader->FindVariant(
|
||||||
|
"ColorScale",
|
||||||
|
ShaderType::Fragment,
|
||||||
|
ShaderBackend::OpenGL);
|
||||||
|
ASSERT_NE(openglFragment, nullptr);
|
||||||
|
EXPECT_EQ(openglFragment->backend, ShaderBackend::Generic);
|
||||||
|
EXPECT_EQ(openglFragment->language, ShaderLanguage::HLSL);
|
||||||
|
EXPECT_EQ(openglFragment->entryPoint, "MainPS");
|
||||||
|
EXPECT_EQ(openglFragment->profile, "ps_5_0");
|
||||||
|
EXPECT_NE(std::string(openglFragment->sourceCode.CStr()).find("gSourceColorTexture.Sample"), std::string::npos);
|
||||||
|
|
||||||
|
const ShaderStageVariant* vulkanFragment = shader->FindVariant(
|
||||||
|
"ColorScale",
|
||||||
|
ShaderType::Fragment,
|
||||||
|
ShaderBackend::Vulkan);
|
||||||
|
ASSERT_NE(vulkanFragment, nullptr);
|
||||||
|
EXPECT_EQ(vulkanFragment->backend, ShaderBackend::Generic);
|
||||||
|
EXPECT_EQ(vulkanFragment->language, ShaderLanguage::HLSL);
|
||||||
|
EXPECT_EQ(vulkanFragment->entryPoint, "MainPS");
|
||||||
|
EXPECT_EQ(vulkanFragment->profile, "ps_5_0");
|
||||||
|
EXPECT_NE(std::string(vulkanFragment->sourceCode.CStr()).find("gColorScale"), std::string::npos);
|
||||||
|
EXPECT_NE(std::string(vulkanFragment->sourceCode.CStr()).find("gSourceColorTexture.Sample"), std::string::npos);
|
||||||
|
|
||||||
|
delete shader;
|
||||||
|
}
|
||||||
|
|
||||||
TEST(ShaderLoader, ResourceManagerLazilyLoadsBuiltinForwardLitShader) {
|
TEST(ShaderLoader, ResourceManagerLazilyLoadsBuiltinForwardLitShader) {
|
||||||
ResourceManager& manager = ResourceManager::Get();
|
ResourceManager& manager = ResourceManager::Get();
|
||||||
manager.Shutdown();
|
manager.Shutdown();
|
||||||
|
|||||||
Reference in New Issue
Block a user