浏览代码

First draft of POM with layering - work on simple case - no influence mode

/stochastic_alpha_test
Sebastien Lagarde 7 年前
当前提交
02cabcb8
共有 2 个文件被更改,包括 202 次插入28 次删除
  1. 62
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitData.hlsl
  2. 168
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitDataInternal.hlsl

62
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitData.hlsl


#ifdef _BENTNORMALMAP
#define _BENTNORMALMAP_IDX
#endif
#ifdef _HEIGHTMAP
#define _HEIGHTMAP_IDX
#endif
#include "LitDataInternal.hlsl"
// This maybe call directly by tessellation (domain) shader, thus all part regarding surface gradient must be done

return maxDisplacement;
}
/*
// Return the minimun uv size for all layers including triplanar
float2 GetMinUvSize(LayerTexCoord layerTexCoord)
{

}
#include "../../../Core/ShaderLibrary/PerPixelDisplacement.hlsl"
*/
void ApplyDisplacementTileScale(inout float height)
{

#endif
}
/*
float ApplyPerPixelDisplacement(FragInputs input, float3 V, inout LayerTexCoord layerTexCoord)
{
#if defined(_PIXEL_DISPLACEMENT) && defined(_HEIGHTMAP)

#else
return 0.0;
#endif
*/
// Calculate displacement for per vertex displacement mapping
float3 ComputePerVertexDisplacement(LayerTexCoord layerTexCoord, float4 vertexColor, float lod)

// Define a helper macro
#define ADD_ZERO_IDX(Name) Name##0
// include LitDataInternal multiple time to define the variation of GetSurfaceData for each layer

#endif
#ifdef _BENTNORMALMAP0
#define _BENTNORMALMAP_IDX
#endif
#ifdef _HEIGHTMAP0
#define _HEIGHTMAP_IDX
#endif
#include "LitDataInternal.hlsl"
#undef LAYER_INDEX

#undef _DETAIL_MAP_IDX
#undef _MASKMAP_IDX
#undef _BENTNORMALMAP_IDX
#undef _HEIGHTMAP_IDX
#define LAYER_INDEX 1
#define ADD_IDX(Name) Name##1

#endif
#ifdef _BENTNORMALMAP1
#define _BENTNORMALMAP_IDX
#endif
#ifdef _HEIGHTMAP1
#define _HEIGHTMAP_IDX
#endif
#include "LitDataInternal.hlsl"
#undef LAYER_INDEX

#undef _DETAIL_MAP_IDX
#undef _MASKMAP_IDX
#undef _BENTNORMALMAP_IDX
#undef _HEIGHTMAP_IDX
#define LAYER_INDEX 2
#define ADD_IDX(Name) Name##2

#ifdef _BENTNORMALMAP2
#define _BENTNORMALMAP_IDX
#endif
#if defined(_HEIGHTMAP2) && (_LAYER_COUNT > 2)
#define _HEIGHTMAP_IDX
#endif
#include "LitDataInternal.hlsl"
#undef LAYER_INDEX
#undef ADD_IDX

#undef _MASKMAP_IDX
#undef _BENTNORMALMAP_IDX
#undef _HEIGHTMAP_IDX
#define LAYER_INDEX 3
#define ADD_IDX(Name) Name##3

#ifdef _BENTNORMALMAP3
#define _BENTNORMALMAP_IDX
#endif
#if defined(_HEIGHTMAP3) && (_LAYER_COUNT > 3)
#define _HEIGHTMAP_IDX
#endif
#include "LitDataInternal.hlsl"
#undef LAYER_INDEX
#undef ADD_IDX

#undef _MASKMAP_IDX
#undef _BENTNORMALMAP_IDX
#undef _HEIGHTMAP_IDX
float3 BlendLayeredVector3(float3 x0, float3 x1, float3 x2, float3 x3, float weight[4])
{

return maxDisplacement;
}
/*
// Return the minimun uv size for all layers including triplanar
float2 GetMinUvSize(LayerTexCoord layerTexCoord)
{

// We need to calculate the texture space direction. It depends on the mapping.
if (isTriplanar)
{
// TODO: implement. Require 3 call to POM + dedicated viewDirTS based on triplanar convention
// apply the 3 offset on all layers
/*
ppdParam.uv[0] = layerTexCoord.base0.uvZY;
ppdParam.uv[1] = layerTexCoord.base1.uvYZ;
ppdParam.uv[2] = layerTexCoord.base2.uvYZ;
ppdParam.uv[3] = layerTexCoord.base3.uvYZ;
float3 viewDirTS = ;
int numSteps = (int)lerp(_PPDMaxSamples, _PPDMinSamples, abs(viewDirTS.z));
ParallaxOcclusionMapping(lod, _PPDLodThreshold, numSteps, viewDirTS, maxHeight, ppdParam);
// Apply to all uvZY
// Repeat for uvXZ
// Repeat for uvXY
// Apply to all layer that used triplanar
*/
height = 1;
NdotV = 1;
}

return 0.0;
#endif
}
*/
float GetMaxHeight(float4 heights)
{

influenceMask = GetInfluenceMask(layerTexCoord);
#endif
float depthOffset = ApplyPerPixelDisplacement(input, V, layerTexCoord, influenceMask);
#ifdef _DEPTHOFFSET_ON
ApplyDepthOffsetPositionInput(V, depthOffset, GetWorldToHClipMatrix(), posInput);
#endif
float depthOffset0 = ApplyPerPixelDisplacement0(input, V, layerTexCoord);
float depthOffset1 = ApplyPerPixelDisplacement1(input, V, layerTexCoord);
float depthOffset2 = ApplyPerPixelDisplacement2(input, V, layerTexCoord);
float depthOffset3 = ApplyPerPixelDisplacement3(input, V, layerTexCoord);
SurfaceData surfaceData0, surfaceData1, surfaceData2, surfaceData3;
float3 normalTS0, normalTS1, normalTS2, normalTS3;

float4 blendMasks = GetBlendMask(layerTexCoord, input.color);
float weights[_MAX_LAYER];
ComputeLayerWeights(input, layerTexCoord, float4(alpha0, alpha1, alpha2, alpha3), blendMasks, weights);
float depthOffset = PROP_BLEND_SCALAR(depthOffset, weights);
#ifdef _DEPTHOFFSET_ON
ApplyDepthOffsetPositionInput(V, depthOffset, GetWorldToHClipMatrix(), posInput);
#endif
// For layered shader, alpha of base color is used as either an opacity mask, a composition mask for inheritance parameters or a density mask.
float alpha = PROP_BLEND_SCALAR(alpha, weights);

168
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitDataInternal.hlsl


#endif
}
// Return the minimun uv size for all layers including triplanar
float2 ADD_IDX(GetMinUvSize)(LayerTexCoord layerTexCoord)
{
float2 minUvSize = float2(FLT_MAX, FLT_MAX);
if (ADD_IDX(layerTexCoord.base).mappingType == UV_MAPPING_TRIPLANAR)
{
minUvSize = min(ADD_IDX(layerTexCoord.base).uvZY * MERGE_NAME(ADD_IDX(_HeightMap), _TexelSize.zw), minUvSize);
minUvSize = min(ADD_IDX(layerTexCoord.base).uvXZ * MERGE_NAME(ADD_IDX(_HeightMap), _TexelSize.zw), minUvSize);
minUvSize = min(ADD_IDX(layerTexCoord.base).uvXY * MERGE_NAME(ADD_IDX(_HeightMap), _TexelSize.zw), minUvSize);
}
else
{
minUvSize = min(ADD_IDX(layerTexCoord.base).uv * MERGE_NAME(ADD_IDX(_HeightMap), _TexelSize.zw), minUvSize);
}
return minUvSize;
}
//TODO: #define USE_HEIGHTMAP_INFLUENCE ((LAYER_INDEX != 0) && defined(_MAIN_LAYER_INFLUENCE_MODE) && defined(_HEIGHTMAP0))
// define only once
#if (LAYER_INDEX == 0) && defined(_PIXEL_DISPLACEMENT)
struct PerPixelHeightDisplacementParam
{
float2 uv;
TEXTURE2D(heightmap);
SAMPLER2D(heightmapSampler);
};
// Calculate displacement for per vertex displacement mapping
float ComputePerPixelHeightDisplacement(float2 texOffsetCurrent, float lod, PerPixelHeightDisplacementParam param)
{
// Note: No multiply by amplitude here. This is include in the maxHeight provide to POM
// Tiling is automatically handled correctly here.
float height = SAMPLE_TEXTURE2D_LOD(param.heightmap, param.heightmapSampler, param.uv + texOffsetCurrent, lod).r;
#if USE_HEIGHTMAP_INFLUENCE
// TODO: We are suppose to get blendmask and influence mask and apply height inheritance... Crazy in term of performance.... + need to deal with macro stuff
#endif
return height;
}
#include "../../../Core/ShaderLibrary/PerPixelDisplacement.hlsl"
#endif
float ADD_IDX(ApplyPerPixelDisplacement)(FragInputs input, float3 V, inout LayerTexCoord layerTexCoord)
{
#if defined(_PIXEL_DISPLACEMENT) && defined(_HEIGHTMAP_IDX)
// These variables are known at the compile time.
bool isPlanar = ADD_IDX(layerTexCoord.base).mappingType == UV_MAPPING_PLANAR;
bool isTriplanar = ADD_IDX(layerTexCoord.base).mappingType == UV_MAPPING_TRIPLANAR;
// _HeightAmplitude can be negative if min and max are inverted, but the max displacement must be positive
float maxHeight = abs(ADD_IDX(_HeightAmplitude));
#if USE_HEIGHTMAP_INFLUENCE
// TODO: maxHeight is supposed to be affect, but how ?
#endif
// Inverse tiling scale = 2 / (abs(_BaseColorMap_ST.x) + abs(_BaseColorMap_ST.y)
// Inverse tiling scale *= (1 / _TexWorldScale) if planar or triplanar
#ifdef _DISPLACEMENT_LOCK_TILING_SCALE
maxHeight *= ADD_IDX(_InvTilingScale);
// TODO: handle _LAYER_TILING_COUPLED_WITH_UNIFORM_OBJECT_SCALE
#endif
float2 minUvSize = ADD_IDX(GetMinUvSize)(layerTexCoord);
float lod = ComputeTextureLOD(minUvSize);
float2 invPrimScale = (isPlanar || isTriplanar) ? float2(1.0, 1.0) : _InvPrimScale.xy;
float worldScale = (isPlanar || isTriplanar) ? ADD_IDX(_TexWorldScale) : 1.0;
float2 uvSpaceScale = invPrimScale * MERGE_NAME(ADD_IDX(_BaseColorMap), _ST.xy) * (worldScale * maxHeight);
PerPixelHeightDisplacementParam ppdParam;
ppdParam.heightmap = ADD_IDX(_HeightMap);
ppdParam.heightmapSampler = SAMPLER_HEIGHTMAP_IDX;
float height = 0; // final height processed
float NdotV = 0;
// planar/triplanar
float2 uvXZ;
float2 uvXY;
float2 uvZY;
GetTriplanarCoordinate(V, uvXZ, uvXY, uvZY);
// TODO: support object space planar/triplanar ?
// We need to calculate the texture space direction. It depends on the mapping.
if (isTriplanar)
{
float planeHeight;
// Perform a POM in each direction and modify appropriate texture coordinate
[branch] if (layerTexCoord.triplanarWeights.x >= 0.001)
{
ppdParam.uv = ADD_IDX(layerTexCoord.base).uvZY;
float3 viewDirTS = float3(uvZY, abs(V.x));
float3 viewDirUV = normalize(float3(viewDirTS.xy * uvSpaceScale, viewDirTS.z)); // TODO: skip normalize
float unitAngle = saturate(FastACosPos(viewDirUV.z) * INV_HALF_PI); // TODO: optimize
int numSteps = (int)lerp(_PPDMinSamples, _PPDMaxSamples, unitAngle);
float2 offset = ParallaxOcclusionMapping(lod, _PPDLodThreshold, numSteps, viewDirUV, 1, ppdParam, planeHeight);
// Apply offset to all triplanar UVSet
ADD_IDX(layerTexCoord.base).uvZY += offset;
ADD_IDX(layerTexCoord.details).uvZY += offset;
height += layerTexCoord.triplanarWeights.x * planeHeight;
NdotV += layerTexCoord.triplanarWeights.x * viewDirTS.z;
}
[branch] if (layerTexCoord.triplanarWeights.y >= 0.001)
{
ppdParam.uv = ADD_IDX(layerTexCoord.base).uvXZ;
float3 viewDirTS = float3(uvXZ, abs(V.y));
float3 viewDirUV = normalize(float3(viewDirTS.xy * uvSpaceScale, viewDirTS.z)); // TODO: skip normalize
float unitAngle = saturate(FastACosPos(viewDirUV.z) * INV_HALF_PI); // TODO: optimize
int numSteps = (int)lerp(_PPDMinSamples, _PPDMaxSamples, unitAngle);
float2 offset = ParallaxOcclusionMapping(lod, _PPDLodThreshold, numSteps, viewDirUV, 1, ppdParam, planeHeight);
ADD_IDX(layerTexCoord.base).uvXZ += offset;
ADD_IDX(layerTexCoord.details).uvXZ += offset;
height += layerTexCoord.triplanarWeights.y * planeHeight;
NdotV += layerTexCoord.triplanarWeights.y * viewDirTS.z;
}
[branch] if (layerTexCoord.triplanarWeights.z >= 0.001)
{
ppdParam.uv = ADD_IDX(layerTexCoord.base).uvXY;
float3 viewDirTS = float3(uvXY, abs(V.z));
float3 viewDirUV = normalize(float3(viewDirTS.xy * uvSpaceScale, viewDirTS.z)); // TODO: skip normalize
float unitAngle = saturate(FastACosPos(viewDirUV.z) * INV_HALF_PI); // TODO: optimize
int numSteps = (int)lerp(_PPDMinSamples, _PPDMaxSamples, unitAngle);
float2 offset = ParallaxOcclusionMapping(lod, _PPDLodThreshold, numSteps, viewDirUV, 1, ppdParam, planeHeight);
ADD_IDX(layerTexCoord.base).uvXY += offset;
ADD_IDX(layerTexCoord.details).uvXY += offset;
height += layerTexCoord.triplanarWeights.z * planeHeight;
NdotV += layerTexCoord.triplanarWeights.z * viewDirTS.z;
}
}
else
{
ppdParam.uv = ADD_IDX(layerTexCoord.base).uv; // For planar it is uv too, not uvXZ
// Note: The TBN is not normalize as it is based on mikkt. We should normalize it, but POM is always use on simple enough surface that mean it is not required (save 2 normalize). Tag: SURFACE_GRADIENT
// Note: worldToTangent is only define for UVSet0, so we expect that layer that use POM have UVSet0
float3 viewDirTS = isPlanar ? float3(uvXZ, V.y) : TransformWorldToTangent(V, input.worldToTangent) * GetDisplacementObjectScale(false).xzy; // Switch from Y-up to Z-up (as we move to tangent space)
NdotV = viewDirTS.z;
// Transform the view vector into the UV space.
float3 viewDirUV = normalize(float3(viewDirTS.xy * uvSpaceScale, viewDirTS.z)); // TODO: skip normalize
float unitAngle = saturate(FastACosPos(viewDirUV.z) * INV_HALF_PI); // TODO: optimize
int numSteps = (int)lerp(_PPDMinSamples, _PPDMaxSamples, unitAngle);
float2 offset = ParallaxOcclusionMapping(lod, _PPDLodThreshold, numSteps, viewDirUV, 1, ppdParam, height);
// Apply offset to all UVSet0 / planar
ADD_IDX(layerTexCoord.base).uv += offset;
ADD_IDX(layerTexCoord.details).uv += isPlanar ? offset : ADD_IDX(_UVDetailsMappingMask).x * offset; // Only apply offset if details map use UVSet0 _UVDetailsMappingMask.x will be 1 in this case, else 0
}
// Since POM "pushes" geometry inwards (rather than extrude it), { height = height - 1 }.
// Since the result is used as a 'depthOffsetVS', it needs to be positive, so we flip the sign.
float verticalDisplacement = maxHeight - height * maxHeight;
return verticalDisplacement / NdotV;
#else
return 0.0;
#endif
}
// Caution: Duplicate from GetBentNormalTS - keep in sync!
float3 ADD_IDX(GetNormalTS)(FragInputs input, LayerTexCoord layerTexCoord, float3 detailNormalTS, float detailMask)
{

正在加载...
取消
保存