shader optimizations with hdr float packing

This commit is contained in:
Turánszki János
2021-10-02 13:15:04 +02:00
parent 93fba8e122
commit ffcb5c9a39
20 changed files with 412 additions and 101 deletions
@@ -0,0 +1,164 @@
//
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
// Developed by Minigraph
//
// Author: James Stanard
//
#pragma warning( disable : 3571 )
#ifndef __COLOR_SPACE_UTILITY_HLSLI__
#define __COLOR_SPACE_UTILITY_HLSLI__
//
// Gamma ramps and encoding transfer functions
//
// Orthogonal to color space though usually tightly coupled. For instance, sRGB is both a
// color space (defined by three basis vectors and a white point) and a gamma ramp. Gamma
// ramps are designed to reduce perceptual error when quantizing floats to integers with a
// limited number of bits. More variation is needed in darker colors because our eyes are
// more sensitive in the dark. The way the curve helps is that it spreads out dark values
// across more code words allowing for more variation. Likewise, bright values are merged
// together into fewer code words allowing for less variation.
//
// The sRGB curve is not a true gamma ramp but rather a piecewise function comprising a linear
// section and a power function. When sRGB-encoded colors are passed to an LCD monitor, they
// look correct on screen because the monitor expects the colors to be encoded with sRGB, and it
// removes the sRGB curve to linearize the values. When textures are encoded with sRGB--as many
// are--the sRGB curve needs to be removed before involving the colors in linear mathematics such
// as physically based lighting.
float3 ApplySRGBCurve( float3 x )
{
// Approximately pow(x, 1.0 / 2.2)
return x < 0.0031308 ? 12.92 * x : 1.055 * pow(x, 1.0 / 2.4) - 0.055;
}
float3 RemoveSRGBCurve( float3 x )
{
// Approximately pow(x, 2.2)
return x < 0.04045 ? x / 12.92 : pow( (x + 0.055) / 1.055, 2.4 );
}
// These functions avoid pow() to efficiently approximate sRGB with an error < 0.4%.
float3 ApplySRGBCurve_Fast( float3 x )
{
return x < 0.0031308 ? 12.92 * x : 1.13005 * sqrt(x - 0.00228) - 0.13448 * x + 0.005719;
}
float3 RemoveSRGBCurve_Fast( float3 x )
{
return x < 0.04045 ? x / 12.92 : -7.43605 * x - 31.24297 * sqrt(-0.53792 * x + 1.279924) + 35.34864;
}
// The OETF recommended for content shown on HDTVs. This "gamma ramp" may increase contrast as
// appropriate for viewing in a dark environment. Always use this curve with Limited RGB as it is
// used in conjunction with HDTVs.
float3 ApplyREC709Curve( float3 x )
{
return x < 0.0181 ? 4.5 * x : 1.0993 * pow(x, 0.45) - 0.0993;
}
float3 RemoveREC709Curve( float3 x )
{
return x < 0.08145 ? x / 4.5 : pow((x + 0.0993) / 1.0993, 1.0 / 0.45);
}
// This is the new HDR transfer function, also called "PQ" for perceptual quantizer. Note that REC2084
// does not also refer to a color space. REC2084 is typically used with the REC2020 color space.
float3 ApplyREC2084Curve(float3 L)
{
float m1 = 2610.0 / 4096.0 / 4;
float m2 = 2523.0 / 4096.0 * 128;
float c1 = 3424.0 / 4096.0;
float c2 = 2413.0 / 4096.0 * 32;
float c3 = 2392.0 / 4096.0 * 32;
float3 Lp = pow(L, m1);
return pow((c1 + c2 * Lp) / (1 + c3 * Lp), m2);
}
float3 RemoveREC2084Curve(float3 N)
{
float m1 = 2610.0 / 4096.0 / 4;
float m2 = 2523.0 / 4096.0 * 128;
float c1 = 3424.0 / 4096.0;
float c2 = 2413.0 / 4096.0 * 32;
float c3 = 2392.0 / 4096.0 * 32;
float3 Np = pow(N, 1 / m2);
return pow(max(Np - c1, 0) / (c2 - c3 * Np), 1 / m1);
}
//
// Color space conversions
//
// These assume linear (not gamma-encoded) values. A color space conversion is a change
// of basis (like in Linear Algebra). Since a color space is defined by three vectors--
// the basis vectors--changing space involves a matrix-vector multiplication. Note that
// changing the color space may result in colors that are "out of bounds" because some
// color spaces have larger gamuts than others. When converting some colors from a wide
// gamut to small gamut, negative values may result, which are inexpressible in that new
// color space.
//
// It would be ideal to build a color pipeline which never throws away inexpressible (but
// perceivable) colors. This means using a color space that is as wide as possible. The
// XYZ color space is the neutral, all-encompassing color space, but it has the unfortunate
// property of having negative values (specifically in X and Z). To correct this, a further
// transformation can be made to X and Z to make them always positive. They can have their
// precision needs reduced by dividing by Y, allowing X and Z to be packed into two UNORM8s.
// This color space is called YUV for lack of a better name.
//
// Note: Rec.709 and sRGB share the same color primaries and white point. Their only difference
// is the transfer curve used.
float3 REC709toREC2020( float3 RGB709 )
{
static const float3x3 ConvMat =
{
0.627402, 0.329292, 0.043306,
0.069095, 0.919544, 0.011360,
0.016394, 0.088028, 0.895578
};
return mul(ConvMat, RGB709);
}
float3 REC2020toREC709(float3 RGB2020)
{
static const float3x3 ConvMat =
{
1.660496, -0.587656, -0.072840,
-0.124547, 1.132895, -0.008348,
-0.018154, -0.100597, 1.118751
};
return mul(ConvMat, RGB2020);
}
float3 REC709toDCIP3( float3 RGB709 )
{
static const float3x3 ConvMat =
{
0.822458, 0.177542, 0.000000,
0.033193, 0.966807, 0.000000,
0.017085, 0.072410, 0.910505
};
return mul(ConvMat, RGB709);
}
float3 DCIP3toREC709( float3 RGBP3 )
{
static const float3x3 ConvMat =
{
1.224947, -0.224947, 0.000000,
-0.042056, 1.042056, 0.000000,
-0.019641, -0.078651, 1.098291
};
return mul(ConvMat, RGBP3);
}
#endif // __COLOR_SPACE_UTILITY_HLSLI__
@@ -0,0 +1,127 @@
//
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
// Developed by Minigraph
//
// Author: James Stanard
//
#ifndef __PIXEL_PACKING_R11G11B10_HLSLI__
#define __PIXEL_PACKING_R11G11B10_HLSLI__
#include "ColorSpaceUtility.hlsli"
// The standard 32-bit HDR color format. Each float has a 5-bit exponent and no sign bit.
uint Pack_R11G11B10_FLOAT( float3 rgb )
{
// Clamp upper bound so that it doesn't accidentally round up to INF
// Exponent=15, Mantissa=1.11111
rgb = min(rgb, asfloat(0x477C0000));
uint r = ((f32tof16(rgb.x) + 8) >> 4) & 0x000007FF;
uint g = ((f32tof16(rgb.y) + 8) << 7) & 0x003FF800;
uint b = ((f32tof16(rgb.z) + 16) << 17) & 0xFFC00000;
return r | g | b;
}
float3 Unpack_R11G11B10_FLOAT( uint rgb )
{
float r = f16tof32((rgb << 4 ) & 0x7FF0);
float g = f16tof32((rgb >> 7 ) & 0x7FF0);
float b = f16tof32((rgb >> 17) & 0x7FE0);
return float3(r, g, b);
}
// An improvement to float is to store the mantissa in logarithmic form. This causes a
// smooth and continuous change in precision rather than having jumps in precision every
// time the exponent increases by whole amounts.
uint Pack_R11G11B10_FLOAT_LOG( float3 rgb )
{
float3 flat_mantissa = asfloat((asuint(rgb) & 0x7FFFFF) | 0x3F800000);
float3 curved_mantissa = min(log2(flat_mantissa) + 1.0, asfloat(0x3FFFFFFF));
rgb = asfloat((asuint(rgb) & 0xFF800000) | (asuint(curved_mantissa) & 0x7FFFFF));
uint r = ((f32tof16(rgb.x) + 8) >> 4) & 0x000007FF;
uint g = ((f32tof16(rgb.y) + 8) << 7) & 0x003FF800;
uint b = ((f32tof16(rgb.z) + 16) << 17) & 0xFFC00000;
return r | g | b;
}
float3 Unpack_R11G11B10_FLOAT_LOG( uint p )
{
float3 rgb = f16tof32(uint3(p << 4, p >> 7, p >> 17) & uint3(0x7FF0, 0x7FF0, 0x7FE0));
float3 curved_mantissa = asfloat((asuint(rgb) & 0x7FFFFF) | 0x3F800000);
float3 flat_mantissa = exp2(curved_mantissa - 1.0);
return asfloat((asuint(rgb) & 0xFF800000) | (asuint(flat_mantissa) & 0x7FFFFF));
}
// As an alternative to floating point, we can store the log2 of a value in fixed point notation.
// The 11-bit fields store 5.6 fixed point notation for log2(x) with an exponent bias of 15. The
// 10-bit field uses 5.5 fixed point. The disadvantage here is we don't handle underflow. Instead
// we use the extra two exponent values to extend the range down through two more exponents.
// Range = [2^-16, 2^16)
uint Pack_R11G11B10_FIXED_LOG(float3 rgb)
{
uint3 p = clamp((log2(rgb) + 16.0) * float3(64, 64, 32) + 0.5, 0.0, float3(2047, 2047, 1023));
return p.b << 22 | p.g << 11 | p.r;
}
float3 Unpack_R11G11B10_FIXED_LOG(uint p)
{
return exp2((uint3(p, p >> 11, p >> 21) & uint3(2047, 2047, 2046)) / 64.0 - 16.0);
}
// These next two encodings are great for LDR data. By knowing that our values are [0.0, 1.0]
// (or [0.0, 2.0), incidentally), we can reduce how many bits we need in the exponent. We can
// immediately eliminate all postive exponents. By giving more bits to the mantissa, we can
// improve precision at the expense of range. The 8E3 format goes one bit further, quadrupling
// mantissa precision but increasing smallest exponent from -14 to -6. The smallest value of 8E3
// is 2^-14, while the smallest value of 7E4 is 2^-21. Both are smaller than the smallest 8-bit
// sRGB value, which is close to 2^-12.
// This is like R11G11B10_FLOAT except that it moves one bit from each exponent to each mantissa.
uint Pack_R11G11B10_E4_FLOAT( float3 rgb )
{
// Clamp to [0.0, 2.0). The magic number is 1.FFFFF x 2^0. (We can't represent hex floats in HLSL.)
// This trick works because clamping your exponent to 0 reduces the number of bits needed by 1.
rgb = clamp( rgb, 0.0, asfloat(0x3FFFFFFF) );
uint r = ((f32tof16(rgb.r) + 4) >> 3 ) & 0x000007FF;
uint g = ((f32tof16(rgb.g) + 4) << 8 ) & 0x003FF800;
uint b = ((f32tof16(rgb.b) + 8) << 18) & 0xFFC00000;
return r | g | b;
}
float3 Unpack_R11G11B10_E4_FLOAT( uint rgb )
{
float r = f16tof32((rgb << 3 ) & 0x3FF8);
float g = f16tof32((rgb >> 8 ) & 0x3FF8);
float b = f16tof32((rgb >> 18) & 0x3FF0);
return float3(r, g, b);
}
// This is like R11G11B10_FLOAT except that it moves two bits from each exponent to each mantissa.
uint Pack_R11G11B10_E3_FLOAT( float3 rgb )
{
// Clamp to [0.0, 2.0). Divide by 256 to bias the exponent by -8. This shifts it down to use one
// fewer bit while still taking advantage of the denormalization hardware. In half precision,
// the exponent of 0 is 0xF. Dividing by 256 makes the max exponent 0x7--one fewer bit.
rgb = clamp( rgb, 0.0, asfloat(0x3FFFFFFF) ) / 256.0;
uint r = ((f32tof16(rgb.r) + 2) >> 2 ) & 0x000007FF;
uint g = ((f32tof16(rgb.g) + 2) << 9 ) & 0x003FF800;
uint b = ((f32tof16(rgb.b) + 4) << 19) & 0xFFC00000;
return r | g | b;
}
float3 Unpack_R11G11B10_E3_FLOAT( uint rgb )
{
float r = f16tof32((rgb << 2 ) & 0x1FFC);
float g = f16tof32((rgb >> 9 ) & 0x1FFC);
float b = f16tof32((rgb >> 19) & 0x1FF8);
return float3(r, g, b) * 256.0;
}
#endif // __PIXEL_PACKING_R11G11B10_HLSLI__
+2 -1
View File
@@ -5,7 +5,6 @@
#include "SamplerMapping.h"
#include "ResourceMapping.h"
#ifdef __cplusplus // not invoking shader compiler, but included in engine source
// Application-side types:
@@ -34,6 +33,8 @@ typedef XMINT4 int4;
#else
#include "PixelPacking_R11G11B10.hlsli"
// Shader - side types:
#define CBUFFER(name, slot) cbuffer name : register(b ## slot)
@@ -28,8 +28,6 @@ static const uint SHADERMATERIAL_OPTION_BIT_TRANSPARENT = 1 << 8;
struct ShaderMaterial
{
float4 baseColor;
float4 specularColor;
float4 emissiveColor;
float4 subsurfaceScattering;
float4 subsurfaceScattering_inv;
float4 texMulAdd;
@@ -46,8 +44,8 @@ struct ShaderMaterial
float transmission;
uint options;
int padding0;
int padding1;
uint emissive_r11g11b10;
uint specular_r11g11b10;
uint layerMask;
int uvset_baseColorMap;
@@ -69,12 +67,10 @@ struct ShaderMaterial
int padding2;
int padding3;
uint sheenColor_r11g11b10;
float sheenRoughness;
float clearcoat;
float clearcoatRoughness;
float padding4;
float4 sheenColor;
float4 baseColorAtlasMulAdd;
float4 surfaceMapAtlasMulAdd;
@@ -101,6 +97,12 @@ struct ShaderMaterial
int padding6;
int padding7;
#ifndef __cplusplus
float3 GetEmissive() { return Unpack_R11G11B10_FLOAT(emissive_r11g11b10); }
float3 GetSpecular() { return Unpack_R11G11B10_FLOAT(specular_r11g11b10); }
float3 GetSheenColor() { return Unpack_R11G11B10_FLOAT(sheenColor_r11g11b10); }
#endif // __cplusplus
inline bool IsUsingVertexColors() { return options & SHADERMATERIAL_OPTION_BIT_USE_VERTEXCOLORS; }
inline bool IsUsingSpecularGlossinessWorkflow() { return options & SHADERMATERIAL_OPTION_BIT_SPECULARGLOSSINESS_WORKFLOW; }
inline bool IsOcclusionEnabled_Primary() { return options & SHADERMATERIAL_OPTION_BIT_OCCLUSION_PRIMARY; }
@@ -17,6 +17,7 @@
<None Include="$(MSBuildThisFileDirectory)bitonicSortHF.hlsli" />
<None Include="$(MSBuildThisFileDirectory)brdf.hlsli" />
<None Include="$(MSBuildThisFileDirectory)circle.hlsli" />
<None Include="$(MSBuildThisFileDirectory)ColorSpaceUtility.hlsli" />
<None Include="$(MSBuildThisFileDirectory)cone.hlsli" />
<None Include="$(MSBuildThisFileDirectory)cube.hlsli" />
<None Include="$(MSBuildThisFileDirectory)cullingShaderHF.hlsli" />
@@ -33,6 +34,7 @@
<None Include="$(MSBuildThisFileDirectory)objectHF.hlsli" />
<None Include="$(MSBuildThisFileDirectory)objectHF_tessellation.hlsli" />
<None Include="$(MSBuildThisFileDirectory)oceanSurfaceHF.hlsli" />
<None Include="$(MSBuildThisFileDirectory)PixelPacking_R11G11B10.hlsli" />
<None Include="$(MSBuildThisFileDirectory)quad.hlsli" />
<None Include="$(MSBuildThisFileDirectory)raytracingHF.hlsli" />
<None Include="$(MSBuildThisFileDirectory)skyAtmosphere.hlsli" />
@@ -129,6 +129,12 @@
<None Include="$(MSBuildThisFileDirectory)objectHF_tessellation.hlsli">
<Filter>HF</Filter>
</None>
<None Include="$(MSBuildThisFileDirectory)ColorSpaceUtility.hlsli">
<Filter>HF</Filter>
</None>
<None Include="$(MSBuildThisFileDirectory)PixelPacking_R11G11B10.hlsli">
<Filter>HF</Filter>
</None>
</ItemGroup>
<ItemGroup>
<FxCompile Include="$(MSBuildThisFileDirectory)hairparticle_simulateCS.hlsl">
+4 -4
View File
@@ -136,7 +136,7 @@ struct Surface
float roughness; // roughness: [0:smooth -> 1:rough] (perceptual)
float occlusion; // occlusion [0 -> 1]
float opacity; // opacity for blending operation [0 -> 1]
float4 emissiveColor; // light emission [0 -> 1]
float3 emissiveColor; // light emission [0 -> 1]
float4 refraction; // refraction color (rgb), refraction amount (a)
float transmission; // transmission factor
float2 pixel; // pixel coordinate (used for randomization effects)
@@ -211,7 +211,7 @@ struct Surface
opacity = 1;
}
roughness = material.roughness;
f0 = material.specularColor.rgb * specularMap.rgb * specularMap.a * material.specularColor.a;
f0 = material.GetSpecular() * specularMap.rgb * specularMap.a;
if (g_xFrame.Options & OPTION_BIT_FORCE_DIFFUSE_LIGHTING)
{
@@ -391,14 +391,14 @@ struct Surface
create(material, baseColor, surfaceMap, specularMap);
emissiveColor = material.emissiveColor;
emissiveColor = material.GetEmissive();
[branch]
if (material.texture_emissivemap_index >= 0)
{
const float2 UV_emissiveMap = material.uvset_emissiveMap == 0 ? uvsets.xy : uvsets.zw;
float4 emissiveMap = bindless_textures[NonUniformResourceIndex(material.texture_emissivemap_index)].SampleLevel(sampler_linear_wrap, UV_emissiveMap, 0);
emissiveMap.rgb = DEGAMMA(emissiveMap.rgb);
emissiveColor *= emissiveMap;
emissiveColor *= emissiveMap.rgb * emissiveMap.a;
}
transmission = material.transmission;
@@ -37,7 +37,7 @@ float4 main(VertextoPixel input) : SV_TARGET
float opacity = saturate(color.a * inputColor.a * fade);
color.rgb *= inputColor.rgb * (1 + material.emissiveColor.rgb * material.emissiveColor.a);
color.rgb *= inputColor.rgb * (1 + material.GetEmissive());
color.a = opacity;
#ifdef EMITTEDPARTICLE_DISTORTION
+18 -18
View File
@@ -351,7 +351,7 @@ struct PixelInput
inline void ApplyEmissive(in Surface surface, inout Lighting lighting)
{
lighting.direct.specular += surface.emissiveColor.rgb * surface.emissiveColor.a;
lighting.direct.specular += surface.emissiveColor;
}
inline void LightMapping(in int lightmap, in float2 ATLAS, inout Lighting lighting)
@@ -1166,16 +1166,16 @@ float4 main(PixelInput input, in bool is_frontface : SV_IsFrontFace) : SV_TARGET
// Emissive map:
surface.emissiveColor = GetMaterial().emissiveColor;
surface.emissiveColor = GetMaterial().GetEmissive();
#ifdef OBJECTSHADER_USE_UVSETS
[branch]
if (surface.emissiveColor.a > 0 && GetMaterial().uvset_emissiveMap >= 0)
if (any(surface.emissiveColor) && GetMaterial().uvset_emissiveMap >= 0)
{
const float2 UV_emissiveMap = GetMaterial().uvset_emissiveMap == 0 ? input.uvsets.xy : input.uvsets.zw;
float4 emissiveMap = texture_emissivemap.Sample(sampler_objectshader, UV_emissiveMap);
emissiveMap.rgb = DEGAMMA(emissiveMap.rgb);
surface.emissiveColor *= emissiveMap;
surface.emissiveColor *= emissiveMap.rgb * emissiveMap.a;
}
#endif // OBJECTSHADER_USE_UVSETS
@@ -1235,16 +1235,16 @@ float4 main(PixelInput input, in bool is_frontface : SV_IsFrontFace) : SV_TARGET
}
#endif // OBJECTSHADER_USE_UVSETS
surface2.emissiveColor = GetMaterial().emissiveColor;
surface2.emissiveColor = GetMaterial().GetEmissive();
#ifdef OBJECTSHADER_USE_UVSETS
[branch]
if (GetMaterial().uvset_emissiveMap >= 0 && any(GetMaterial().emissiveColor))
if (GetMaterial().uvset_emissiveMap >= 0 && any(surface2.emissiveColor))
{
float2 uv = GetMaterial().uvset_emissiveMap == 0 ? input.uvsets.xy : input.uvsets.zw;
sam = texture_emissivemap.Sample(sampler_objectshader, uv);
sam.rgb = DEGAMMA(sam.rgb);
surface2.emissiveColor *= sam;
surface2.emissiveColor *= sam.rgb * sam.a;
}
#endif // OBJECTSHADER_USE_UVSETS
@@ -1297,16 +1297,16 @@ float4 main(PixelInput input, in bool is_frontface : SV_IsFrontFace) : SV_TARGET
}
#endif // OBJECTSHADER_USE_UVSETS
surface2.emissiveColor = GetMaterial1().emissiveColor;
surface2.emissiveColor = GetMaterial1().GetEmissive();
#ifdef OBJECTSHADER_USE_UVSETS
[branch]
if (GetMaterial1().uvset_emissiveMap >= 0 && any(GetMaterial().emissiveColor))
if (GetMaterial1().uvset_emissiveMap >= 0 && any(surface2.emissiveColor))
{
float2 uv = GetMaterial1().uvset_emissiveMap == 0 ? input.uvsets.xy : input.uvsets.zw;
sam = texture_blend1_emissivemap.Sample(sampler_objectshader, uv);
sam.rgb = DEGAMMA(sam.rgb);
surface2.emissiveColor *= sam;
surface2.emissiveColor *= sam.rgb * sam.a;
}
#endif // OBJECTSHADER_USE_UVSETS
@@ -1359,16 +1359,16 @@ float4 main(PixelInput input, in bool is_frontface : SV_IsFrontFace) : SV_TARGET
}
#endif // OBJECTSHADER_USE_UVSETS
surface2.emissiveColor = GetMaterial2().emissiveColor;
surface2.emissiveColor = GetMaterial2().GetEmissive();
#ifdef OBJECTSHADER_USE_UVSETS
[branch]
if (GetMaterial2().uvset_emissiveMap >= 0 && any(GetMaterial2().emissiveColor))
if (GetMaterial2().uvset_emissiveMap >= 0 && any(surface2.emissiveColor))
{
float2 uv = GetMaterial2().uvset_emissiveMap == 0 ? input.uvsets.xy : input.uvsets.zw;
sam = texture_blend2_emissivemap.Sample(sampler_objectshader, uv);
sam.rgb = DEGAMMA(sam.rgb);
surface2.emissiveColor *= sam;
surface2.emissiveColor *= sam.rgb * sam.a;
}
#endif // OBJECTSHADER_USE_UVSETS
@@ -1421,16 +1421,16 @@ float4 main(PixelInput input, in bool is_frontface : SV_IsFrontFace) : SV_TARGET
}
#endif // OBJECTSHADER_USE_UVSETS
surface2.emissiveColor = GetMaterial3().emissiveColor;
surface2.emissiveColor = GetMaterial3().GetEmissive();
#ifdef OBJECTSHADER_USE_UVSETS
[branch]
if (GetMaterial3().uvset_emissiveMap >= 0 && any(GetMaterial3().emissiveColor))
if (GetMaterial3().uvset_emissiveMap >= 0 && any(surface2.emissiveColor))
{
float2 uv = GetMaterial3().uvset_emissiveMap == 0 ? input.uvsets.xy : input.uvsets.zw;
sam = texture_blend3_emissivemap.Sample(sampler_objectshader, uv);
sam.rgb = DEGAMMA(sam.rgb);
surface2.emissiveColor *= sam;
surface2.emissiveColor *= sam.rgb * sam.a;
}
#endif // OBJECTSHADER_USE_UVSETS
@@ -1449,7 +1449,7 @@ float4 main(PixelInput input, in bool is_frontface : SV_IsFrontFace) : SV_TARGET
#ifdef OBJECTSHADER_USE_EMISSIVE
surface.emissiveColor *= unpack_rgba(input.emissiveColor);
surface.emissiveColor *= Unpack_R11G11B10_FLOAT(input.emissiveColor);
#endif // OBJECTSHADER_USE_EMISSIVE
@@ -1481,7 +1481,7 @@ float4 main(PixelInput input, in bool is_frontface : SV_IsFrontFace) : SV_TARGET
#ifdef BRDF_SHEEN
surface.sheen.color = GetMaterial().sheenColor.rgb;
surface.sheen.color = GetMaterial().GetSheenColor();
surface.sheen.roughness = GetMaterial().sheenRoughness;
#ifdef OBJECTSHADER_USE_UVSETS
+4 -4
View File
@@ -19,16 +19,16 @@ float4 main(PixelInput input) : SV_TARGET
}
color *= input.color;
float4 emissiveColor = GetMaterial().emissiveColor;
float3 emissiveColor = GetMaterial().GetEmissive();
[branch]
if (emissiveColor.a > 0 && GetMaterial().uvset_emissiveMap >= 0)
if (any(emissiveColor) && GetMaterial().uvset_emissiveMap >= 0)
{
const float2 UV_emissiveMap = GetMaterial().uvset_emissiveMap == 0 ? input.uvsets.xy : input.uvsets.zw;
float4 emissiveMap = texture_emissivemap.Sample(sampler_objectshader, UV_emissiveMap);
emissiveMap.rgb = DEGAMMA(emissiveMap.rgb);
emissiveColor *= emissiveMap;
emissiveColor *= emissiveMap.rgb * emissiveMap.a;
}
color.rgb += emissiveColor.rgb * emissiveColor.a;
color.rgb += emissiveColor;
float time = g_xFrame.Time;
float2 uv = input.pos.xy * g_xFrame.InternalResolution_rcp;
+12 -12
View File
@@ -41,14 +41,14 @@ void main(PSInput input)
}
baseColor *= input.color;
float4 color = baseColor;
float4 emissiveColor = GetMaterial().emissiveColor;
float3 emissiveColor = GetMaterial().GetEmissive();
[branch]
if (GetMaterial().emissiveColor.a > 0 && GetMaterial().uvset_emissiveMap >= 0)
if (any(emissiveColor) && GetMaterial().uvset_emissiveMap >= 0)
{
const float2 UV_emissiveMap = GetMaterial().uvset_emissiveMap == 0 ? input.uvsets.xy : input.uvsets.zw;
float4 emissiveMap = texture_emissivemap.Sample(sampler_linear_wrap, UV_emissiveMap);
emissiveMap.rgb = DEGAMMA(emissiveMap.rgb);
emissiveColor *= emissiveMap;
emissiveColor *= emissiveMap.rgb * emissiveMap.a;
}
@@ -76,12 +76,12 @@ void main(PSInput input)
color += sam * GetMaterial().baseColor * blend_weights.x;
[branch]
if (GetMaterial().uvset_emissiveMap >= 0 && any(GetMaterial().emissiveColor))
if (GetMaterial().uvset_emissiveMap >= 0 && any(GetMaterial().GetEmissive()))
{
float2 uv = GetMaterial().uvset_emissiveMap == 0 ? input.uvsets.xy : input.uvsets.zw;
sam = texture_emissivemap.Sample(sampler_objectshader, uv);
sam.rgb = DEGAMMA(sam.rgb);
emissiveColor += sam * GetMaterial().emissiveColor * blend_weights.x;
emissiveColor += sam.rgb * sam.a * GetMaterial().GetEmissive() * blend_weights.x;
}
}
@@ -102,12 +102,12 @@ void main(PSInput input)
color += sam * GetMaterial1().baseColor * blend_weights.y;
[branch]
if (GetMaterial1().uvset_emissiveMap >= 0 && any(GetMaterial1().emissiveColor))
if (GetMaterial1().uvset_emissiveMap >= 0 && any(GetMaterial1().GetEmissive()))
{
float2 uv = GetMaterial1().uvset_emissiveMap == 0 ? input.uvsets.xy : input.uvsets.zw;
sam = texture_blend1_emissivemap.Sample(sampler_objectshader, uv);
sam.rgb = DEGAMMA(sam.rgb);
emissiveColor += sam * GetMaterial1().emissiveColor * blend_weights.y;
emissiveColor += sam.rgb * sam.a * GetMaterial1().GetEmissive() * blend_weights.y;
}
}
@@ -128,12 +128,12 @@ void main(PSInput input)
color += sam * GetMaterial2().baseColor * blend_weights.z;
[branch]
if (GetMaterial2().uvset_emissiveMap >= 0 && any(GetMaterial2().emissiveColor))
if (GetMaterial2().uvset_emissiveMap >= 0 && any(GetMaterial2().GetEmissive()))
{
float2 uv = GetMaterial2().uvset_emissiveMap == 0 ? input.uvsets.xy : input.uvsets.zw;
sam = texture_blend2_emissivemap.Sample(sampler_objectshader, uv);
sam.rgb = DEGAMMA(sam.rgb);
emissiveColor += sam * GetMaterial2().emissiveColor * blend_weights.z;
emissiveColor += sam.rgb * sam.a * GetMaterial2().GetEmissive() * blend_weights.z;
}
}
@@ -154,12 +154,12 @@ void main(PSInput input)
color += sam * GetMaterial3().baseColor * blend_weights.w;
[branch]
if (GetMaterial3().uvset_emissiveMap >= 0 && any(GetMaterial3().emissiveColor))
if (GetMaterial3().uvset_emissiveMap >= 0 && any(GetMaterial3().GetEmissive()))
{
float2 uv = GetMaterial3().uvset_emissiveMap == 0 ? input.uvsets.xy : input.uvsets.zw;
sam = texture_blend3_emissivemap.Sample(sampler_objectshader, uv);
sam.rgb = DEGAMMA(sam.rgb);
emissiveColor += sam * GetMaterial3().emissiveColor * blend_weights.w;
emissiveColor += sam.rgb * sam.a * GetMaterial3().GetEmissive() * blend_weights.w;
}
}
@@ -314,7 +314,7 @@ void main(PSInput input)
color.rgb *= lighting.direct.diffuse;
color.rgb += emissiveColor.rgb * emissiveColor.a;
color.rgb += emissiveColor;
uint color_encoded = PackVoxelColor(color);
uint normal_encoded = pack_unitvector(N);
+1 -1
View File
@@ -114,7 +114,7 @@ void main(uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex)
surface.update();
result += max(0, energy * surface.emissiveColor.rgb * surface.emissiveColor.a);
result += max(0, energy * surface.emissiveColor);
+1 -1
View File
@@ -255,7 +255,7 @@ float4 main(Input input) : SV_TARGET
surface.update();
result += max(0, energy * surface.emissiveColor.rgb * surface.emissiveColor.a);
result += max(0, energy * surface.emissiveColor);
// Calculate chances of reflection types:
const float refractChance = surface.transmission;
+1 -1
View File
@@ -170,7 +170,7 @@ void RTReflection_ClosestHit(inout RayPayload payload, in BuiltInTriangleInterse
lighting.indirect.specular += max(0, EnvironmentReflection_Global(surface));
LightingPart combined_lighting = CombineLighting(surface, lighting);
payload.data.xyz = surface.albedo * combined_lighting.diffuse + combined_lighting.specular + surface.emissiveColor.rgb * surface.emissiveColor.a;
payload.data.xyz = surface.albedo * combined_lighting.diffuse + combined_lighting.specular + surface.emissiveColor;
payload.data.w = RayTCurrent();
}
+1 -1
View File
@@ -315,7 +315,7 @@ void main(uint3 DTid : SV_DispatchThreadID)
#endif // SURFEL_ENABLE_INFINITE_BOUNCES
hit_result *= surface.albedo;
hit_result += max(0, surface.emissiveColor.rgb * surface.emissiveColor.a);
hit_result += max(0, surface.emissiveColor);
result += float4(hit_result, 1);
}
+6 -8
View File
@@ -17,8 +17,8 @@ RWTEXTURE2D(output, float3, 0);
static const uint TILE_BORDER = 1;
static const uint TILE_SIZE = POSTPROCESS_BLOCKSIZE + TILE_BORDER * 2;
groupshared uint tile_RG[TILE_SIZE*TILE_SIZE];
groupshared uint tile_B_depth[TILE_SIZE*TILE_SIZE];
groupshared uint tile_color[TILE_SIZE*TILE_SIZE];
groupshared float tile_depth[TILE_SIZE*TILE_SIZE];
[numthreads(POSTPROCESS_BLOCKSIZE, POSTPROCESS_BLOCKSIZE, 1)]
void main(uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint3 Gid : SV_GroupID, uint groupIndex : SV_GroupIndex)
@@ -36,8 +36,8 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint3
const uint2 pixel = tile_upperleft + unflatten2D(t, TILE_SIZE);
const float depth = texture_lineardepth[pixel];
const float3 color = input_current[pixel].rgb;
tile_RG[t] = f32tof16(color.r) | (f32tof16(color.g) << 16);
tile_B_depth[t] = f32tof16(color.b) | (f32tof16(depth) << 16);
tile_color[t] = Pack_R11G11B10_FLOAT(color);
tile_depth[t] = depth;
}
GroupMemoryBarrierWithGroupSync();
@@ -49,10 +49,8 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint3
{
const int2 offset = int2(x, y);
const uint idx = flatten2D(GTid.xy + TILE_BORDER + offset, TILE_SIZE);
const uint RG = tile_RG[idx];
const uint B_depth = tile_B_depth[idx];
const float3 neighbor = float3(f16tof32(RG), f16tof32(RG >> 16), f16tof32(B_depth));
const float3 neighbor = Unpack_R11G11B10_FLOAT(tile_color[idx]);
neighborhoodMin = min(neighborhoodMin, neighbor);
neighborhoodMax = max(neighborhoodMax, neighbor);
if (x == 0 && y == 0)
@@ -60,7 +58,7 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint3
current = neighbor;
}
const float depth = f16tof32(B_depth >> 16);
const float depth = tile_depth[idx];
if (depth < bestDepth)
{
bestDepth = depth;
-34
View File
@@ -2,9 +2,6 @@
namespace wiMath
{
#define saturate(x) std::min(std::max(x,0.0f),1.0f)
float TriangleArea(const XMVECTOR& A, const XMVECTOR& B, const XMVECTOR& C)
{
// Heron's formula:
@@ -419,35 +416,4 @@ namespace wiMath
return HALTON[idx % arraysize(HALTON)];
}
uint32_t CompressNormal(const XMFLOAT3& normal)
{
uint32_t retval = 0;
retval |= (uint32_t)((uint8_t)(normal.x * 127.5f + 127.5f) << 0);
retval |= (uint32_t)((uint8_t)(normal.y * 127.5f + 127.5f) << 8);
retval |= (uint32_t)((uint8_t)(normal.z * 127.5f + 127.5f) << 16);
return retval;
}
uint32_t CompressColor(const XMFLOAT3& color)
{
uint32_t retval = 0;
retval |= (uint32_t)((uint8_t)(saturate(color.x) * 255.0f) << 0);
retval |= (uint32_t)((uint8_t)(saturate(color.y) * 255.0f) << 8);
retval |= (uint32_t)((uint8_t)(saturate(color.z) * 255.0f) << 16);
return retval;
}
uint32_t CompressColor(const XMFLOAT4& color)
{
uint32_t retval = 0;
retval |= (uint32_t)((uint8_t)(saturate(color.x) * 255.0f) << 0);
retval |= (uint32_t)((uint8_t)(saturate(color.y) * 255.0f) << 8);
retval |= (uint32_t)((uint8_t)(saturate(color.z) * 255.0f) << 16);
retval |= (uint32_t)((uint8_t)(saturate(color.w) * 255.0f) << 24);
return retval;
}
}
+48 -3
View File
@@ -5,6 +5,8 @@
namespace wiMath
{
inline float saturate(float x) { return std::min(std::max(x, 0.0f), 1.0f); }
inline float Length(const XMFLOAT2& v)
{
return sqrtf(v.x*v.x + v.y*v.y);
@@ -173,9 +175,52 @@ namespace wiMath
// Returns an element of a precomputed halton sequence. Specify which iteration to get with idx >= 0
const XMFLOAT4& GetHaltonSequence(int idx);
uint32_t CompressNormal(const XMFLOAT3& normal);
uint32_t CompressColor(const XMFLOAT3& color);
uint32_t CompressColor(const XMFLOAT4& color);
inline uint32_t CompressNormal(const XMFLOAT3& normal)
{
uint32_t retval = 0;
retval |= (uint32_t)((uint8_t)(normal.x * 127.5f + 127.5f) << 0);
retval |= (uint32_t)((uint8_t)(normal.y * 127.5f + 127.5f) << 8);
retval |= (uint32_t)((uint8_t)(normal.z * 127.5f + 127.5f) << 16);
return retval;
}
inline uint32_t CompressColor(const XMFLOAT3& color)
{
uint32_t retval = 0;
retval |= (uint32_t)((uint8_t)(saturate(color.x) * 255.0f) << 0);
retval |= (uint32_t)((uint8_t)(saturate(color.y) * 255.0f) << 8);
retval |= (uint32_t)((uint8_t)(saturate(color.z) * 255.0f) << 16);
return retval;
}
inline uint32_t CompressColor(const XMFLOAT4& color)
{
uint32_t retval = 0;
retval |= (uint32_t)((uint8_t)(saturate(color.x) * 255.0f) << 0);
retval |= (uint32_t)((uint8_t)(saturate(color.y) * 255.0f) << 8);
retval |= (uint32_t)((uint8_t)(saturate(color.z) * 255.0f) << 16);
retval |= (uint32_t)((uint8_t)(saturate(color.w) * 255.0f) << 24);
return retval;
}
inline XMFLOAT3 Unpack_R11G11B10_FLOAT(uint32_t value)
{
XMFLOAT3PK pk;
pk.v = value;
XMVECTOR V = XMLoadFloat3PK(&pk);
XMFLOAT3 result;
XMStoreFloat3(&result, V);
return result;
}
inline uint32_t Pack_R11G11B10_FLOAT(const XMFLOAT3& color)
{
XMFLOAT3PK pk;
XMStoreFloat3PK(&pk, XMLoadFloat3(&color));
return pk.v;
}
+4 -4
View File
@@ -231,8 +231,8 @@ namespace wiScene
void MaterialComponent::WriteShaderMaterial(ShaderMaterial* dest) const
{
dest->baseColor = baseColor;
dest->specularColor = specularColor;
dest->emissiveColor = emissiveColor;
dest->emissive_r11g11b10 = wiMath::Pack_R11G11B10_FLOAT(XMFLOAT3(emissiveColor.x * emissiveColor.w, emissiveColor.y * emissiveColor.w, emissiveColor.z * emissiveColor.w));
dest->specular_r11g11b10 = wiMath::Pack_R11G11B10_FLOAT(XMFLOAT3(specularColor.x * specularColor.w, specularColor.y * specularColor.w, specularColor.z * specularColor.w));
dest->texMulAdd = texMulAdd;
dest->roughness = roughness;
dest->reflectance = reflectance;
@@ -262,7 +262,7 @@ namespace wiScene
dest->uvset_clearcoatRoughnessMap = textures[CLEARCOATROUGHNESSMAP].GetUVSet();
dest->uvset_clearcoatNormalMap = textures[CLEARCOATNORMALMAP].GetUVSet();
dest->uvset_specularMap = textures[SPECULARMAP].GetUVSet();
dest->sheenColor = sheenColor;
dest->sheenColor_r11g11b10 = wiMath::Pack_R11G11B10_FLOAT(XMFLOAT3(sheenColor.x, sheenColor.y, sheenColor.z));
dest->sheenRoughness = sheenRoughness;
dest->clearcoat = clearcoat;
dest->clearcoatRoughness = clearcoatRoughness;
@@ -3185,7 +3185,7 @@ namespace wiScene
}
inst.uid = entity;
inst.color = wiMath::CompressColor(object.color);
inst.emissive = wiMath::CompressColor(object.emissiveColor);
inst.emissive = wiMath::Pack_R11G11B10_FLOAT(XMFLOAT3(object.emissiveColor.x * object.emissiveColor.w, object.emissiveColor.y * object.emissiveColor.w, object.emissiveColor.z * object.emissiveColor.w));
inst.meshIndex = (uint)meshes.GetIndex(object.meshID);
if (TLAS_instancesMapped != nullptr)
+1 -1
View File
@@ -9,7 +9,7 @@ namespace wiVersion
// minor features, major updates, breaking compatibility changes
const int minor = 57;
// minor bug fixes, alterations, refactors, updates
const int revision = 39;
const int revision = 40;
const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);