/*============================================================================= AOITCommon.usf=============================================================================*/
// Copyright 2011 Intel Corporation// All Rights Reserved//// Permission is granted to use, copy, distribute and prepare derivative works of this// software for any purpose and without fee, provided, that the above copyright notice// and this statement appear in all copies. Intel makes no representations about the// suitability of this software for any purpose. THIS SOFTWARE IS PROVIDED "AS IS."// INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, AND ALL LIABILITY,// INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES, FOR THE USE OF THIS SOFTWARE,// INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY RIGHTS, AND INCLUDING THE// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Intel does not// assume any responsibility for any errors which may appear in this software nor any// responsibility to update it.#ifndef H_COMMON#define H_COMMON//// Defines//#define AVSM_FILTERING_ENABLED#define LT_BILINEAR_FILTERING#define EARLY_DEPTH_CULL_ALPHA (0x1UL)///// Resources///TextureCube gIBLTexture;SamplerState gIBLSampler;Texture2DMSgCompositingBuffer;//// Constants//struct UIConstants{ uint faceNormals; uint avsmSortingMethod; uint volumeShadowMethod; uint enableVolumeShadowLookup; uint pauseParticleAnimaton; float particleSize; uint particleOpacity; uint hairThickness; uint hairShadowThickness; uint hairOpacity; uint lightingOnly; uint stNumSamples;};cbuffer PerFrameConstants{ float4x4 mCameraWorldViewProj; float4x4 mCameraWorldView; float4x4 mCameraViewProj; float4x4 mCameraProj; float4 mCameraPos; float4x4 mLightWorldViewProj; float4x4 mAvsmLightWorldViewProj; float4x4 mCameraViewToWorld; float4x4 mCameraViewToLightProj; float4x4 mCameraViewToLightView; float4x4 mCameraViewToAvsmLightProj; float4x4 mCameraViewToAvsmLightView; float4 mLightDir; float4 mMSAACoverageNorm; float4 mGeometryAlpha; float4 mAlphaThreshold; UIConstants mUI;};// data that we can read or derived from the surface shader outputsstruct SurfaceData{ float3 positionView; // View space position float3 positionViewDX; // Screen space derivatives float3 positionViewDY; // of view space position float3 normal; // View space normal float4 albedo; float2 lightTexCoord; // Texture coordinates in light space, [0, 1] float2 lightTexCoordDX; // Screen space partial derivatives float2 lightTexCoordDY; // of light space texture coordinates. float lightSpaceZ; // Z coordinate (depth) of surface in light space};//// Full screen pass////struct FullScreenTriangleVSOut//{// float4 positionViewport : SV_Position;// float4 positionClip : positionClip;// float2 texCoord : texCoord;//};//// Helper Functions//float linstep(float min, float max, float v){ return saturate((v - min) / (max - min));}float2 ProjectIntoLightTexCoord(float3 positionView){ float4 positionLight = mul(float4(positionView, 1.0f), mCameraViewToLightProj); float2 texCoord = (positionLight.xy / positionLight.w) * float2(0.5f, -0.5f) + float2(0.5f, 0.5f); return texCoord;}float2 ProjectIntoAvsmLightTexCoord(float3 positionView){ float4 positionLight = mul(float4(positionView, 1.0f), mCameraViewToAvsmLightProj); float2 texCoord = (positionLight.xy / positionLight.w) * float2(0.5f, -0.5f) + float2(0.5f, 0.5f); return texCoord;}#endif // H_COMMON
/*============================================================================= AOITCaptureShader.usf: capture translucent pixels onto AOIT fragment list=============================================================================*/#include "Common.usf"#include "BasePassPixelCommon.usf"#include "FragmentList.usf"#if NEEDS_BASEPASS_FOGGING #include "HeightFogCommon.usf"#if BASEPASS_ATMOSPHERIC_FOG #include "AtmosphereCommon.usf"#endif#endif#define DEBUG_AOIT_CAPTURE 0struct FAOITCaptureVSToPS{ FVertexFactoryInterpolantsVSToPS FactoryInterpolants; FBasePassInterpolantsVSToPS BasePassInterpolants; float4 Position : SV_POSITION;};#if USING_TESSELLATION struct FAOITCaptureVSToDS { FVertexFactoryInterpolantsVSToDS FactoryInterpolants; FBasePassInterpolantsVSToDS BasePassInterpolants; float4 Position : VS_To_DS_Position; OPTIONAL_VertexID_VS_To_DS }; #define FAOITCaptureVSOutput FAOITCaptureVSToPS #define VertexFactoryGetInterpolants VertexFactoryGetInterpolantsVSToDS #define FPassSpecificVSToDS FAOITCaptureVSToPS #define FPassSpecificVSToPS FAOITCaptureVSToDS#else #define FAOITCaptureVSOutput FAOITCaptureVSToPS #define VertexFactoryGetInterpolants VertexFactoryGetInterpolantsVSToPS#endif#if USING_TESSELLATIONFAOITCaptureVSToDS PassInterpolate(FAOITCaptureVSToDS a, float aInterp, FAOITCaptureVSToDS b, float bInterp){ FAOITCaptureVSToDS O; O.FactoryInterpolants = VertexFactoryInterpolate(a.FactoryInterpolants, aInterp, b.FactoryInterpolants, bInterp); #if NEEDS_BASEPASS_FOGGING TESSELLATION_INTERPOLATE_MEMBER(BasePassInterpolants.VertexFog); #endif #if USE_WORLD_POSITION_EXCLUDING_SHADER_OFFSETS TESSELLATION_INTERPOLATE_MEMBER(BasePassInterpolants.WorldPositionExcludingWPO); #endif return O;}FAOITCaptureVSToPS PassFinalizeTessellationOutput(FAOITCaptureVSToDS Interpolants, float4 WorldPosition, FMaterialTessellationParameters MaterialParameters){ FAOITCaptureVSToPS O; O.FactoryInterpolants = VertexFactoryAssignInterpolants(Interpolants.FactoryInterpolants); // Copy everything in the shared base class over to the pixel shader input (FSharedBasePassInterpolants)O.BasePassInterpolants = (FSharedBasePassInterpolants)Interpolants.BasePassInterpolants; // Transform position to clip-space ISOLATE { O.Position = mul(WorldPosition, View.TranslatedWorldToClip); } // Calc position-dependent interps O.BasePassInterpolants.PixelPosition = WorldPosition; #if USE_WORLD_POSITION_EXCLUDING_SHADER_OFFSETS O.BasePassInterpolants.PixelPositionExcludingWPO = float4(Interpolants.BasePassInterpolants.WorldPositionExcludingWPO, 1); #endif return O;}// This gets us the MainHull and MainDomain shader definitions#include "Tessellation.usf"#endifvoid VSMain( FVertexFactoryInput Input, OPTIONAL_VertexID out FAOITCaptureVSOutput Output ){ FVertexFactoryIntermediates VFIntermediates = GetVertexFactoryIntermediates(Input); float4 WorldPositionExcludingWPO = VertexFactoryGetWorldPosition(Input, VFIntermediates); float4 WorldPosition = WorldPositionExcludingWPO; float3x3 TangentToLocal = VertexFactoryGetTangentToLocal(Input, VFIntermediates); FMaterialVertexParameters VertexParameters = GetMaterialVertexParameters(Input, VFIntermediates, WorldPosition.xyz, TangentToLocal); // Isolate instructions used for world position offset // As these cause the optimizer to generate different position calculating instructions in each pass, resulting in self-z-fighting. // This is only necessary for shaders used in passes that have depth testing enabled. ISOLATE { WorldPosition.xyz += GetMaterialWorldPositionOffset(VertexParameters); }#if USING_TESSELLATION // We let the Domain Shader convert to post projection when tessellating Output.Position = WorldPosition; #if USE_WORLD_POSITION_EXCLUDING_SHADER_OFFSETS Output.BasePassInterpolants.WorldPositionExcludingWPO = WorldPositionExcludingWPO; #endif#else ISOLATE { float4 RasterizedWorldPosition = VertexFactoryGetRasterizedWorldPosition(Input, VFIntermediates, WorldPosition); Output.Position = mul(RasterizedWorldPosition, View.TranslatedWorldToClip); } Output.BasePassInterpolants.PixelPosition = WorldPosition; #if USE_WORLD_POSITION_EXCLUDING_SHADER_OFFSETS Output.BasePassInterpolants.PixelPositionExcludingWPO = WorldPositionExcludingWPO; #endif#endif Output.FactoryInterpolants = VertexFactoryGetInterpolants(Input, VFIntermediates, VertexParameters);// Calculate the fog needed for translucency#if NEEDS_BASEPASS_FOGGING#if BASEPASS_ATMOSPHERIC_FOG Output.BasePassInterpolants.VertexFog = CalculateVertexAtmosphericFog(WorldPosition.xyz, View.TranslatedViewOrigin.xyz);#else Output.BasePassInterpolants.VertexFog = CalculateVertexHeightFog(WorldPosition.xyz, View.TranslatedViewOrigin);#endif#endif OutputVertexID( Output );}EARLYDEPTHSTENCILvoid PSMain( FVertexFactoryInterpolantsVSToPS Interpolants, FBasePassInterpolantsVSToPS BasePassInterpolants, float4 InSVPosition : SV_POSITION, OPTIONAL_IsFrontFace#if DEBUG_AOIT_CAPTURE ,out float4 OutColor : SV_Target0#endif ){ FMaterialPixelParameters MaterialParameters = GetMaterialPixelParameters(Interpolants, BasePassInterpolants.PixelPosition); CalcMaterialParameters(MaterialParameters,InSVPosition, bIsFrontFace,BasePassInterpolants.PixelPosition#if USE_WORLD_POSITION_EXCLUDING_SHADER_OFFSETS , BasePassInterpolants.PixelPositionExcludingWPO#endif );#if EDITOR_PRIMITIVE_MATERIAL && (FEATURE_LEVEL >= FEATURE_LEVEL_SM4 || ES2_EMULATION) const bool bEditorWeightedZBuffering = true;#else const bool bEditorWeightedZBuffering = false;#endif //Clip if the blend mode requires it. if(!bEditorWeightedZBuffering) { GetMaterialCoverageAndClipping(MaterialParameters); } // Store the results in local variables and reuse instead of calling the functions multiple times. half3 BaseColor = GetMaterialBaseColor( MaterialParameters ); half Metallic = GetMaterialMetallic( MaterialParameters ); half Specular = GetMaterialSpecular( MaterialParameters ); float MaterialAO = GetMaterialAmbientOcclusion(MaterialParameters); float Roughness = GetMaterialRoughness(MaterialParameters); // 0..1, SubsurfaceProfileId = int(x * 255) float SubsurfaceProfile = 0; // If we don't use this shading model the color should be black (don't generate shader code for unused data, don't do indirectlighting cache lighting with this color). float3 SubsurfaceColor = 0;#if MATERIAL_SHADINGMODEL_SUBSURFACE || MATERIAL_SHADINGMODEL_PREINTEGRATED_SKIN || MATERIAL_SHADINGMODEL_SUBSURFACE_PROFILE { float4 SubsurfaceData = GetMaterialSubsurfaceData(MaterialParameters);#if MATERIAL_SHADINGMODEL_SUBSURFACE || MATERIAL_SHADINGMODEL_PREINTEGRATED_SKIN SubsurfaceColor = SubsurfaceData.rgb;#endif SubsurfaceProfile = SubsurfaceData.a; }#endif#if MATERIAL_FULLY_ROUGH Roughness = 1;#endif // So that the following code can still use DiffuseColor and SpecularColor.#if MATERIAL_SHADINGMODEL_HAIR half3 DiffuseColor = BaseColor; half3 SpecularColor = lerp( 0.08 * Specular.xxx, BaseColor, Metallic.xxx );#else half3 DiffuseColor = BaseColor - BaseColor * Metallic; half3 SpecularColor = lerp( 0.08 * Specular.xxx, BaseColor, Metallic.xxx );#endif// todo: COMPILE_SHADERS_FOR_DEVELOPMENT is unfinished feature, using XBOXONE_PROFILE as workaround#if COMPILE_SHADERS_FOR_DEVELOPMENT == 1 && !XBOXONE_PROFILE && !ES31_AEP_PROFILE { // this feature is only needed for development/editor - we can compile it out for a shipping build (see r.CompileShadersForDevelopment cvar help) DiffuseColor = DiffuseColor * View.DiffuseOverrideParameter.w + View.DiffuseOverrideParameter.xyz; SpecularColor = SpecularColor * View.SpecularOverrideParameter.w + View.SpecularOverrideParameter.xyz; }#endif half3 Color = 0; float IndirectIrradiance = 0; #if !MATERIAL_SHADINGMODEL_UNLIT float3 DiffuseIndirectLighting; float3 SubsurfaceIndirectLighting; GetPrecomputedIndirectLightingAndSkyLight(MaterialParameters, Interpolants, BasePassInterpolants, DiffuseIndirectLighting, SubsurfaceIndirectLighting, IndirectIrradiance); #if MATERIAL_SHADINGMODEL_SUBSURFACE || MATERIAL_SHADINGMODEL_PREINTEGRATED_SKIN // Add subsurface energy to diffuse //@todo - better subsurface handling for these shading models with skylight and precomputed GI DiffuseColor += SubsurfaceColor; #endif Color += (DiffuseIndirectLighting * DiffuseColor + SubsurfaceIndirectLighting * SubsurfaceColor) * MaterialAO; #if SIMPLE_DYNAMIC_LIGHTING // always unshadowed so BiasedNDotL is not needed half Lambert = saturate(dot(MaterialParameters.WorldNormal, View.DirectionalLightDirection)); Color += DiffuseColor * Lambert * View.DirectionalLightColor.rgb; Color += GetMaterialHemisphereLightTransferFull( DiffuseColor, MaterialParameters, View.UpperSkyColor.rgb, View.LowerSkyColor.rgb ); #endif #endif half Opacity = GetMaterialOpacity(MaterialParameters); #if NEEDS_BASEPASS_FOGGING float4 VertexFog = BasePassInterpolants.VertexFog; #else float4 VertexFog = float4(0,0,0,1); #endif // Volume lighting for lit translucency #if (MATERIAL_SHADINGMODEL_DEFAULT_LIT || MATERIAL_SHADINGMODEL_SUBSURFACE) && ( MATERIALBLENDING_TRANSLUCENT || MATERIALBLENDING_ADDITIVE ) Color += GetTranslucencyLighting(MaterialParameters, DiffuseColor, Roughness, SpecularColor, IndirectIrradiance, MaterialAO); #endif #if MATERIAL_SHADINGMODEL_HAIR && MATERIALBLENDING_TRANSLUCENT Color += GetTranslucentHairLighting(MaterialParameters, DiffuseColor, Roughness, SpecularColor, IndirectIrradiance, MaterialAO); #endif #if !MATERIAL_SHADINGMODEL_UNLIT Color = lerp(Color, DiffuseColor + SpecularColor, View.UnlitViewmodeMask); #endif half3 Emissive = GetMaterialEmissive(MaterialParameters);// todo: COMPILE_SHADERS_FOR_DEVELOPMENT is unfinished feature, using XBOXONE_PROFILE as workaround#if COMPILE_SHADERS_FOR_DEVELOPMENT == 1 && !XBOXONE_PROFILE && !ES31_AEP_PROFILE // this feature is only needed for development/editor - we can compile it out for a shipping build (see r.CompileShadersForDevelopment cvar help) #if SM5_PROFILE || SM4_PROFILE BRANCH if (View.OutOfBoundsMask > 0) { if (any(abs(MaterialParameters.WorldPosition - Primitive.ObjectWorldPositionAndRadius.xyz) > Primitive.ObjectBounds + 1)) { float Gradient = frac(dot(MaterialParameters.WorldPosition, float3(.577f, .577f, .577f)) / 500.0f); Emissive = lerp(float3(1,1,0), float3(0,1,1), Gradient.xxx > .5f); Opacity = 1; } } #endif#endif Color += Emissive; #if MATERIALBLENDING_TRANSLUCENT Color = Color * VertexFog.a + VertexFog.rgb; Color *= Opacity; #elif MATERIALBLENDING_ADDITIVE Color = Color * VertexFog.aaa; Color *= Opacity; Opacity = 0.0; #elif MATERIALBLENDING_MODULATE Color = lerp(float3(1, 1, 1), Color, VertexFog.aaa * VertexFog.aaa); #endif float2 screenPositionF = MaterialParameters.ScreenPosition.xy / MaterialParameters.ScreenPosition.w * View.ScreenPositionScaleBias.xy + View.ScreenPositionScaleBias.wz; int2 screenPosition = int2( screenPositionF * View.RenderTargetSize ); uint newNodeAddress; uint mask; if (FL_AllocNode(newNodeAddress)) { // Fill node FragmentListNode node; node.color = FL_PackColor3(Color, mask); #if SUPPORT_ALL_TRANSLUCENCY #if MATERIALBLENDING_MODULATE mask |= 0x10UL; #endif node.depth = FL_PackDepthAndMask5(MaterialParameters.ScreenPosition.w - MaterialParameters.ScreenPosition.z, mask);#else node.depth = FL_PackDepthAndMask4(MaterialParameters.ScreenPosition.w - MaterialParameters.ScreenPosition.z, mask);#endif // Insert node! FL_InsertNode(screenPosition, newNodeAddress, node, 1.0 - Opacity); } #if DEBUG_AOIT_CAPTURE OutColor = half4(Color, 1); #endif}
/*============================================================================= AOITResolveShader.usf: resolve AOIT fragment list to final buffer=============================================================================*/#include "Common.usf"#include "AOIT.usf"#include "FragmentList.usf"void Main( FScreenVertexOutput Input, out float4 OutColor : SV_Target0 ){ uint i; uint nodeOffset; int2 screenAddress = int2(Input.Position.xy); // Get offset to the first node uint firstNodeOffset = FL_GetFirstNodeOffset(screenAddress); AOITData data; // Initialize AVSM data [unroll]for (i = 0; i < AOIT_RT_COUNT; ++i) { data.depth[i] = AIOT_EMPTY_NODE_DEPTH.xxxx;#if SUPPORT_ALL_TRANSLUCENCY data.trans[i][0] = AOIT_FIRT_NODE_TRANS.xxx; data.trans[i][1] = AOIT_FIRT_NODE_TRANS.xxx; data.trans[i][2] = AOIT_FIRT_NODE_TRANS.xxx; data.trans[i][3] = AOIT_FIRT_NODE_TRANS.xxx;#else data.trans[i] = AOIT_FIRT_NODE_TRANS.xxxx;#endif } // Fetch all nodes and add them to our visibiity function nodeOffset = firstNodeOffset; [loop] while (nodeOffset != FL_NODE_LIST_NULL) { // Get node.. FragmentListNode node = FL_GetNode(nodeOffset); float depth; uint mask;#if SUPPORT_ALL_TRANSLUCENCY FL_UnpackDepthAndMask5(node.depth, depth, mask);#else FL_UnpackDepthAndMask4(node.depth, depth, mask);#endif uint next; float transA; next = FL_UnpackIndexAndOpcity(node.next, transA); #if SUPPORT_ALL_TRANSLUCENCY float3 trans = transA.xxx; float3 nodeColor; nodeColor = FL_UnpackColor3(node.color, (uint)(mask & 0xFUL)); trans = lerp(trans, nodeColor, float(mask>>4));#else float trans = transA;#endif AOITInsertFragment(depth, trans, data); // Move to next node nodeOffset = next; } float3 color = float3(0, 0, 0); // Fetch all nodes again and composite them nodeOffset = firstNodeOffset; [loop] while (nodeOffset != FL_NODE_LIST_NULL) { // Get node.. FragmentListNode node = FL_GetNode(nodeOffset); float depth; uint mask;#if SUPPORT_ALL_TRANSLUCENCY FL_UnpackDepthAndMask5(node.depth, depth, mask);#else FL_UnpackDepthAndMask4(node.depth, depth, mask);#endif // Unpack color float3 nodeColor; nodeColor = FL_UnpackColor3(node.color, (uint)(mask & 0xFUL)); uint next; float transA; next = FL_UnpackIndexAndOpcity(node.next, transA); AOITFragment frag = AOITFindFragment(data, depth);#if SUPPORT_ALL_TRANSLUCENCY float3 vis = frag.index == 0 ? float3(1.0,1.0,1.0) : frag.transA; color += nodeColor * (1.0 - float(mask>>4)) * vis;#else float vis = frag.index == 0 ? 1.0f : frag.transA; color += nodeColor * vis.xxx;#endif // Move to next node nodeOffset = next; } #if SUPPORT_ALL_TRANSLUCENCY OutColor = float4(color, data.trans[AOIT_RT_COUNT - 1][3][0]);#else OutColor = float4(color, data.trans[AOIT_RT_COUNT - 1][3]);#endif OutColor = RETURN_COLOR(OutColor);}
/*============================================================================= AOIT.usf=============================================================================*/
// Copyright 2011 Intel Corporation
// All Rights Reserved//// Permission is granted to use, copy, distribute and prepare derivative works of this// software for any purpose and without fee, provided, that the above copyright notice// and this statement appear in all copies. Intel makes no representations about the// suitability of this software for any purpose. THIS SOFTWARE IS PROVIDED "AS IS."// INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, AND ALL LIABILITY,// INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES, FOR THE USE OF THIS SOFTWARE,// INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY RIGHTS, AND INCLUDING THE// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Intel does not// assume any responsibility for any errors which may appear in this software nor any// responsibility to update it.#ifndef H_AOIT#define H_AOIT#include "AOITCommon.usf"//// Defines//#ifndef AOIT_NODE_COUNT #define AOIT_NODE_COUNT (16)#endif#define AOIT_FIRT_NODE_TRANS (1)#define AOIT_RT_COUNT (AOIT_NODE_COUNT / 4)#define AIOT_EMPTY_NODE_DEPTH (1E30)// Forces compression to only work on the second half of the nodes (cheaper and better IQ in most cases)#define AOIT_DONT_COMPRESS_FIRST_HALF //// Structs//struct AOITData { float4 depth[AOIT_RT_COUNT];#if SUPPORT_ALL_TRANSLUCENCY float3 trans[AOIT_RT_COUNT][4];#else float4 trans[AOIT_RT_COUNT];#endif};struct AOITFragment{ int index; float depthA;#if SUPPORT_ALL_TRANSLUCENCY float3 transA;#else float transA;#endif};//// Two-level search for AT visibility functions// AOITFragment AOITFindFragment(in AOITData data, in float fragmentDepth){ int index;#if SUPPORT_ALL_TRANSLUCENCY float4 depth; float3 trans[4];#else float4 depth, trans;#endif float leftDepth;#if SUPPORT_ALL_TRANSLUCENCY float3 leftTrans;#else float leftTrans;#endif AOITFragment Output; #if AOIT_RT_COUNT > 7 [flatten]if (fragmentDepth > data.depth[6][3]) { depth = data.depth[7]; trans = data.trans[7]; leftDepth = data.depth[6][3]; leftTrans = data.trans[6][3]; Output.index = 28; } else#endif #if AOIT_RT_COUNT > 6 [flatten]if (fragmentDepth > data.depth[5][3]) { depth = data.depth[6]; trans = data.trans[6]; leftDepth = data.depth[5][3]; leftTrans = data.trans[5][3]; Output.index = 24; } else#endif #if AOIT_RT_COUNT > 5 [flatten]if (fragmentDepth > data.depth[4][3]) { depth = data.depth[5]; trans = data.trans[5]; leftDepth = data.depth[4][3]; leftTrans = data.trans[4][3]; Output.index = 20; } else#endif #if AOIT_RT_COUNT > 4 [flatten]if (fragmentDepth > data.depth[3][3]) { depth = data.depth[4]; trans = data.trans[4]; leftDepth = data.depth[3][3]; leftTrans = data.trans[3][3]; Output.index = 16; } else#endif #if AOIT_RT_COUNT > 3 [flatten]if (fragmentDepth > data.depth[2][3]) { depth = data.depth[3]; trans = data.trans[3]; leftDepth = data.depth[2][3]; leftTrans = data.trans[2][3]; Output.index = 12; } else#endif #if AOIT_RT_COUNT > 2 [flatten]if (fragmentDepth > data.depth[1][3]) { depth = data.depth[2]; trans = data.trans[2]; leftDepth = data.depth[1][3]; leftTrans = data.trans[1][3]; Output.index = 8; } else#endif #if AOIT_RT_COUNT > 1 [flatten]if (fragmentDepth > data.depth[0][3]) { depth = data.depth[1]; trans = data.trans[1]; leftDepth = data.depth[0][3]; leftTrans = data.trans[0][3]; Output.index = 4; } else#endif { depth = data.depth[0]; trans = data.trans[0]; leftDepth = data.depth[0][0]; leftTrans = data.trans[0][0]; Output.index = 0; } [flatten]if (fragmentDepth <= depth[0]) { Output.depthA = leftDepth; Output.transA = leftTrans; } else if (fragmentDepth <= depth[1]) { Output.index += 1; Output.depthA = depth[0]; Output.transA = trans[0]; } else if (fragmentDepth <= depth[2]) { Output.index += 2; Output.depthA = depth[1]; Output.transA = trans[1]; } else if (fragmentDepth <= depth[3]) { Output.index += 3; Output.depthA = depth[2]; Output.transA = trans[2]; } else { Output.index += 4; Output.depthA = depth[3]; Output.transA = trans[3]; } return Output;} ////// Insert a new fragment in the visibility function////void AOITInsertFragment(in float fragmentDepth,#if SUPPORT_ALL_TRANSLUCENCY in float3 fragmentTrans,#else in float fragmentTrans,#endif inout AOITData aoitData){ int i, j; // Unpack AOIT data float depth[AOIT_NODE_COUNT + 1]; #if SUPPORT_ALL_TRANSLUCENCY float3 trans[AOIT_NODE_COUNT + 1];#else float trans[AOIT_NODE_COUNT + 1];#endif [unroll] for (i = 0; i < AOIT_RT_COUNT; ++i) { [unroll] for (j = 0; j < 4; ++j) { depth[4 * i + j] = aoitData.depth[i][j]; trans[4 * i + j] = aoitData.trans[i][j]; } } // Find insertion index AOITFragment tempFragment = AOITFindFragment(aoitData, fragmentDepth); const int index = tempFragment.index; // If we are inserting in the first node then use 1.0 as previous transmittance value // (we don't store it, but it's implicitly set to 1. This allows us to store one more node)#if SUPPORT_ALL_TRANSLUCENCY const float3 prevTrans = index != 0 ? tempFragment.transA : float3(1.0,1.0,1.0);#else const float prevTrans = index != 0 ? tempFragment.transA : 1.0f;#endif // Make space for the new fragment. Also composite new fragment with the current curve // (except for the node that represents the new fragment) [unroll]for (i = AOIT_NODE_COUNT - 1; i >= 0; --i) { [flatten]if (index <= i) { depth[i + 1] = depth[i]; trans[i + 1] = trans[i] * fragmentTrans; } } // Insert new fragment [unroll]for (i = 0; i <= AOIT_NODE_COUNT; ++i) { [flatten]if (index == i) { depth[i] = fragmentDepth; trans[i] = fragmentTrans * prevTrans; } } // pack representation if we have too many nodes [flatten]if (depth[AOIT_NODE_COUNT] != AIOT_EMPTY_NODE_DEPTH) { // That's total number of nodes that can be possibly removed const int removalCandidateCount = (AOIT_NODE_COUNT + 1) - 1;#ifdef AOIT_DONT_COMPRESS_FIRST_HALF // Although to bias our compression scheme in order to favor.. // .. the closest nodes to the eye we skip the first 50% const int startRemovalIdx = removalCandidateCount / 2;#else const int startRemovalIdx = 1;#endif#if AOIT_NODE_COUNT == 8 float nodeUnderError[removalCandidateCount] = { 0,0,0,0 ,0,0,0,0};#elif AOIT_NODE_COUNT == 16 float nodeUnderError[removalCandidateCount] = { 0,0,0,0 ,0,0,0,0 ,0,0,0,0 ,0,0,0,0};#elif AOIT_NODE_COUNT == 24 float nodeUnderError[removalCandidateCount] = { 0,0,0,0 ,0,0,0,0 ,0,0,0,0 ,0,0,0,0 ,0,0,0,0 ,0,0,0,0};#elif AOIT_NODE_COUNT == 32 float nodeUnderError[removalCandidateCount] = { 0,0,0,0 ,0,0,0,0 ,0,0,0,0 ,0,0,0,0 ,0,0,0,0 ,0,0,0,0 ,0,0,0,0 ,0,0,0,0};#else float nodeUnderError[removalCandidateCount];#endif [unroll]for (i = startRemovalIdx; i < removalCandidateCount; ++i) { nodeUnderError[i] = (depth[i] - depth[i - 1]) * dot((trans[i - 1] - trans[i]), (trans[i - 1] - trans[i])); } // Find the node the generates the smallest removal error int smallestErrorIdx; float smallestError; smallestErrorIdx = startRemovalIdx; smallestError = nodeUnderError[smallestErrorIdx]; i = startRemovalIdx + 1; [unroll]for ( ; i < removalCandidateCount; ++i) { [flatten]if (nodeUnderError[i] < smallestError) { smallestError = nodeUnderError[i]; smallestErrorIdx = i; } } // Remove that node.. [unroll]for (i = startRemovalIdx; i < AOIT_NODE_COUNT; ++i) { [flatten]if (smallestErrorIdx <= i) { depth[i] = depth[i + 1]; } } [unroll]for (i = startRemovalIdx - 1; i < AOIT_NODE_COUNT; ++i) { [flatten]if (smallestErrorIdx - 1 <= i) { trans[i] = trans[i + 1]; } } } // Pack AOIT data [unroll] for (i = 0; i < AOIT_RT_COUNT; ++i) { [unroll] for (j = 0; j < 4; ++j) { aoitData.depth[i][j] = depth[4 * i + j]; aoitData.trans[i][j] = trans[4 * i + j]; } } }#endif // H_AOIT
posted on 2017-06-23 15:29 阅读( ...) 评论( ...) 收藏