浏览代码

HDRenderPipeline: Draft about surface gradient code

/Branch_Batching2
Sebastien Lagarde 7 年前
当前提交
4d17bef2
共有 8 个文件被更改,包括 144 次插入22 次删除
  1. 44
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitData.hlsl
  2. 44
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitDataInternal.hlsl
  3. 1
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/ShaderPass/LitDepthPass.hlsl
  4. 1
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/ShaderPass/LitDistortionPass.hlsl
  5. 1
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/ShaderPass/LitVelocityPass.hlsl
  6. 4
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/MaterialUtilities.hlsl
  7. 16
      Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/FragInputs.hlsl
  8. 55
      Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/VaryingMesh.hlsl

44
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitData.hlsl


float3 triplanarWeights;
};
// To flip in case of double sided, we must flip the vertex normal and this will apply to the whole process either in surface gradient or not.
// As here we are in the function call GetSurfaceAndBuiltinData(), the tangent space is already built, so we need to flip both normal and bitangent.
// This function will modify FragInputs and this is not propagate outside of GetSurfaceAndBuiltinData(). This is ok as tangent space is not use outside of GetSurfaceAndBuiltinData().
void ApplyDoubleSidedFlip(inout FragInputs input)
{
#ifdef _DOUBLESIDED_ON
// _DoubleSidedMode is float3(-1, -1, -1) in flip mode and float3(1, 1, -1) in mirror mode
float flipSign = input.isFrontFace ? 1.0 : _DoubleSidedMode.x; // TOCHECK : GetOddNegativeScale() is not necessary here as it is apply for tangent space creation.
#ifdef SURFACE_GRADIENT
input.vtxNormalWS = flipSign * input.vtxNormalWS;
input.mikktsBino = flipSign * input.mikktsBino;
// TOCHECK: seems that we don't need to invert any genBasisTB(), sign cancel. Which is expected as we deal with surface gradient.
#else
input.tangentToWorld[0] = flipSign * input.tangentToWorld[0];
input.tangentToWorld[1] = flipSign * input.tangentToWorld[1];
#endif
#endif
}
// To mirror a normal: in ws reflect around the vertex normal / in tangent space apply minus on the z component.
// For surface gradient it is sufficient to take the opposite of the surface gradient.
void ApplyDoubleSidedMirror(inout float3 normalTS)
{
#ifdef _DOUBLESIDED_ON
// _DoubleSidedMode is float3(-1, -1, -1) in flip mode and float3(1, 1, -1) in mirror mode
float flipSign = input.isFrontFace ? 1.0 : -_DoubleSidedMode.x; // TOCHECK : GetOddNegativeScale() is not necessary here as it is apply for tangent space creation.
#ifdef SURFACE_GRADIENT
normalTS = flipSign * normalTS;
#else
normalTS.z *= flipSign;
#endif
#endif
}
#ifndef LAYERED_LIT_SHADER
#define SAMPLER_NORMALMAP_IDX sampler_NormalMap

void GetSurfaceAndBuiltinData(FragInputs input, float3 V, inout PositionInputs posInput, out SurfaceData surfaceData, out BuiltinData builtinData)
{
ApplyDoubleSidedFlip(input); // Apply double sided flip on the vertex normal
LayerTexCoord layerTexCoord;
GetLayerTexCoord(input.texCoord0, input.texCoord1, input.texCoord2, input.texCoord3,
input.positionWS, input.tangentToWorld[2].xyz, layerTexCoord);

// so it allow us to correctly deal with detail normal map and optimize the code for the layered shaders
float3 normalTS;
float alpha = GetSurfaceData(input, layerTexCoord, surfaceData, normalTS);
ApplyDoubleSidedMirror(normalTS); // Apply double sided mirror on the final normalTS
GetNormalAndTangentWS(input, V, normalTS, surfaceData.normalWS, surfaceData.tangentWS);
// Done one time for all layered - cumulate with spec occ alpha for now
surfaceData.specularOcclusion *= GetHorizonOcclusion(V, surfaceData.normalWS, input.tangentToWorld[2].xyz, _HorizonFade);

float3 mainNormalTS = GetNormalTS0(input, layerTexCoord, float3(0.0, 0.0, 1.0), 0.0, true, maxMipBias * (1.0 - influenceFactor));
// Add on our regular normal a bit of Main Layer normal base on influence factor. Note that this affect only the "visible" normal.
#ifdef SURFACE_GRADIENT
return normalTS + influenceFactor * mainNormalTS;
#else
#endif
}
float3 ComputeMainBaseColorInfluence(float3 baseColor0, float3 baseColor1, float3 baseColor2, float3 baseColor3, float compoMask, LayerTexCoord layerTexCoord, float weights[_MAX_LAYER])

void GetSurfaceAndBuiltinData(FragInputs input, float3 V, inout PositionInputs posInput, out SurfaceData surfaceData, out BuiltinData builtinData)
{
ApplyDoubleSidedFlip(input); // Apply double sided flip on the vertex normal
LayerTexCoord layerTexCoord;
GetLayerTexCoord(input.texCoord0, input.texCoord1, input.texCoord2, input.texCoord3,
input.positionWS, input.tangentToWorld[2].xyz, layerTexCoord);

surfaceData.coatPerceptualSmoothness = 1.0;
surfaceData.specularColor = float3(0.0, 0.0, 0.0);
ApplyDoubleSidedMirror(normalTS); // Apply double sided mirror on the final normalTS
GetNormalAndTangentWS(input, V, normalTS, surfaceData.normalWS, surfaceData.tangentWS);
// Done one time for all layered - cumulate with spec occ alpha for now
surfaceData.specularOcclusion = SURFACEDATA_BLEND_SCALAR(surfaceData, specularOcclusion, weights);

44
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitDataInternal.hlsl


normalTS = SAMPLE_LAYER_NORMALMAP(ADD_IDX(_NormalMap), SAMPLER_NORMALMAP_IDX, ADD_IDX(layerTexCoord.base), ADD_IDX(_NormalScale));
}
#else // Object space
// to be able to combine object space normal with detail map we transform it to tangent space (object space normal composition is complex operation).
// to be able to combine object space normal with detail map or to apply a "scale" we transform it to tangent space (object space normal composition is complex operation).
// Note: There is no such a thing like triplanar with object space normal, so we call directly 2D function
float3 normalOS = SAMPLE_LAYER_NORMALMAP_RGB_BIAS(ADD_IDX(_NormalMap), SAMPLER_NORMALMAP_IDX, ADD_IDX(layerTexCoord.base), ADD_IDX(_NormalScale), bias).rgb;
#ifdef SURFACE_GRADIENT
// /We need to decompress the normal ourselve here as UnpackNormalRGB will return a surface gradient
float3 normalOS = SAMPLE_TEXTURE2D_BIAS(layerTex, SAMPLER_NORMALMAP_IDX, ADD_IDX(layerTexCoord.base).uv, bias).xyz * 2.0 - 1.0;
// normalize(normalOS) // TO CHECK: surfgradFromPerturbedNormal doesn't require normalOS to be normalize, to check
normalTS = surfgradFromPerturbedNormal(input.vtxNormalWS, normalOS);
normalTS *= ADD_IDX(_NormalScale);
#else
float3 normalOS = UnpackNormalRGB(SAMPLE_TEXTURE2D_BIAS(layerTex, SAMPLER_NORMALMAP_IDX, ADD_IDX(layerTexCoord.base).uv, bias), 1.0);
normalTS.xy *= ADD_IDX(_NormalScale); // Scale in tangent space
normalTS = (normalTS);
#endif
float3 normalOS = SAMPLE_LAYER_NORMALMAP_RGB(ADD_IDX(_NormalMap), SAMPLER_NORMALMAP_IDX, ADD_IDX(layerTexCoord.base), ADD_IDX(_NormalScale)).rgb;
#ifdef SURFACE_GRADIENT
// /We need to decompress the normal ourselve here as UnpackNormalRGB will return a surface gradient
float3 normalOS = SAMPLE_TEXTURE2D(layerTex, SAMPLER_NORMALMAP_IDX, ADD_IDX(layerTexCoord.base).uv).xyz * 2.0 - 1.0;
// normalize(normalOS) // TO CHECK: surfgradFromPerturbedNormal doesn't require normalOS to be normalize, to check
normalTS = surfgradFromPerturbedNormal(input.vtxNormalWS, normalOS);
normalTS *= ADD_IDX(_NormalScale);
#else
float3 normalOS = UnpackNormalRGB(SAMPLE_TEXTURE2D(layerTex, SAMPLER_NORMALMAP_IDX, ADD_IDX(layerTexCoord.base).uv), 1.0);
normalTS.xy *= ADD_IDX(_NormalScale); // Scale in tangent space
normalTS = (normalTS);
#endif
normalTS = lerp(normalTS, BlendNormalRNM(normalTS, detailNormalTS), detailMask);
#ifdef SURFACE_GRADIENT
normalTS += detailNormalTS;
#else
normalTS = lerp(normalTS, BlendNormalRNM(normalTS, detailNormalTS), detailMask);
#endif
#ifdef SURFACE_GRADIENT
normalTS = float3(0.0, 0.0, 0.0); // No gradient
#else
#endif
#ifdef _DOUBLESIDED_ON
// _DoubleSidedMode is float3(-1, -1, -1) in flip mode and float3(1, 1, -1) in mirror mode (Mirror the normal with the plane define by vertex normal)
float3 oppositeNormalTS = normalTS * _DoubleSidedConstants.xyz;
// TODO : Test if GetOddNegativeScale() is necessary here in case of normal map, as GetOddNegativeScale is take into account in CreateTangentToWorld();
normalTS = input.isFrontFace ? (GetOddNegativeScale() >= 0.0 ? normalTS : oppositeNormalTS) : (-GetOddNegativeScale() >= 0.0 ? normalTS : oppositeNormalTS);
#endif
#endif
return normalTS;

1
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/ShaderPass/LitDepthPass.hlsl


// Varying - Use for pixel shader
// This second set of define allow to say which varyings will be output in the vertex (no more tesselation)
#if REQUIRE_TANGENT_TO_WORLD
#define VARYINGS_NEED_POSITION_WS // Required to get view vector
#define VARYINGS_NEED_TANGENT_TO_WORLD
#endif

1
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/ShaderPass/LitDistortionPass.hlsl


// Varying - Use for pixel shader
// This second set of define allow to say which varyings will be output in the vertex (no more tesselation)
#if REQUIRE_TANGENT_TO_WORLD
#define VARYINGS_NEED_POSITION_WS // Required to get view vector
#define VARYINGS_NEED_TANGENT_TO_WORLD
#endif

1
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/ShaderPass/LitVelocityPass.hlsl


#define VARYINGS_NEED_POSITION_WS
#if REQUIRE_TANGENT_TO_WORLD
#define VARYINGS_NEED_POSITION_WS // Required to get view vector
#define VARYINGS_NEED_TANGENT_TO_WORLD
#endif

4
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/MaterialUtilities.hlsl


// This function convert the tangent space normal/tangent to world space and orthonormalize it + apply a correction of the normal if it is not pointing towards the near plane
void GetNormalAndTangentWS(FragInputs input, float3 V, float3 normalTS, inout float3 normalWS, inout float3 tangentWS, bool twoSided = false)
{
#ifdef SURFACE_GRADIENT
normalWS = resolveNormalFromSurfaceGradient(input.vtxNormalWS, normalTS);
#else
#endif
// NdotV should not be negative for visible pixels, but it can happen due to the
// perspective projection and the normal mapping + decals. In that case, the normal

16
Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/FragInputs.hlsl


float2 texCoord1;
float2 texCoord2;
float2 texCoord3;
float3 tangentToWorld[3]; // These 3 vectors are normalized (no need for the material to normalize) and these are only for UVSet 0
#ifdef SURFACE_GRADIENT
// Various tangent space for all UVSet
// used for vertex level tangent space only (support on UV set 0 only)
float3 vtxNormalWS;
float3 mikktsTang;
float3 mikktsBino;
// Use for the 3 other UVSet;
float3 vT1, vB1;
float3 vT2, vB2;
float3 vT3, vB3;
#else
float3 tangentToWorld[3]; // These 3 vectors are normalized (no need for the material to normalize) and these are only for UVSet 0
#endif
// For two sided lighting
bool isFrontFace;

55
Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/VaryingMesh.hlsl


output.positionWS.xyz = input.interpolators0.xyz;
#endif
#ifdef VARYINGS_NEED_TANGENT_TO_WORLD
// Normalize the normal/tangent after interpolation
float3 normalWS = normalize(input.interpolators1);
float4 tangentWS = float4(normalize(input.interpolators2.xyz), input.interpolators2.w);
float3x3 tangentToWorld = CreateTangentToWorld(normalWS, tangentWS.xyz, tangentWS.w);
output.tangentToWorld[0] = tangentToWorld[0];
output.tangentToWorld[1] = tangentToWorld[1];
output.tangentToWorld[2] = tangentToWorld[2];
#endif
#ifdef VARYINGS_NEED_TEXCOORD0
output.texCoord0 = input.interpolators3.xy;
#endif

#if defined(VARYINGS_NEED_CULLFACE) && SHADER_STAGE_FRAGMENT
output.isFrontFace = IS_FRONT_VFACE(input.cullFace, true, false);
#endif
#ifdef VARYINGS_NEED_TANGENT_TO_WORLD
#ifdef SURFACE_GRADIENT
// Caution: We assume that tangent space are always use in a context where positionWS is availble.
// Which is true in our framework. When positionWS is 0 it mean we are in a deffered or compute pass which don't use our tangent space (so code will be remove by the compiler)
// TODO: We should use relative camera position here - This will be automatic when we will move to camera relative space.
float3 dPdx = ddx_fine(output.positionWS.xyz);
float3 dPdy = ddy_fine(output.positionWS.xyz);
float renormFactor = 1.0 / length(input.interpolators1);
float3 nrmVertexNormal = renormFactor * input.interpolators1;
float3 sigmaX = dPdx - dot(dPdx, nrmVertexNormal) * nrmVertexNormal;
float3 sigmaY = dPdy - dot(dPdy, nrmVertexNormal) * nrmVertexNormal;
//float flip_sign = dot(sigmaY, cross(nrmVertexNormal, sigmaX) ) ? -1 : 1;
float flipSign = dot(dPdy, cross(nrmVertexNormal, dPdx)) < 0 ? -1 : 1; // gives same as the commented out line above
output.vtxNormalWS = nrmVertexNormal;
// mikkts for conventional vertex level tspace (no normalizes is mandatory)
output.mikktsTang = input.interpolators2.xyz;
// bitangent on the fly option in xnormal to reduce vertex shader outputs. Also described in https://wiki.blender.org/index.php/Dev:Shading/Tangent_Space_Normal_Maps
output.mikktsBino = (input.interpolators2.w > 0.0 ? 1.0 : -1.0) * GetOddNegativeScale() * cross(input.interpolators1, input.interpolators2.xyz); // TODO: use CreateTangentToWorld instead once we clean code
// prepare for surfgrad formulation without breaking compliance (use exact same scale as applied to interpolated vertex normal to avoid breaking compliance).
output.mikktsTang *= renormFactor;
output.mikktsBino *= renormFactor;
#ifdef VARYINGS_NEED_TEXCOORD1
genBasisTB(nrmVertexNormal, sigmaX, sigmaY, flipSign, output.vT1, output.vB1, output.texCoord1);
#endif
#ifdef VARYINGS_NEED_TEXCOORD2
genBasisTB(nrmVertexNormal, sigmaX, sigmaY, flipSign, output.vT2, output.vB2, output.texCoord2);
#endif
#ifdef VARYINGS_NEED_TEXCOORD3
genBasisTB(nrmVertexNormal, sigmaX, sigmaY, flipSign, output.vT3, output.vB3, output.texCoord3);
#endif
#else
// Normalize the normal/tangent after interpolation
float3 normalWS = normalize(input.interpolators1);
float4 tangentWS = float4(normalize(input.interpolators2.xyz), input.interpolators2.w > 0.0 ? 1.0 : -1.0);
float3x3 tangentToWorld = CreateTangentToWorld(normalWS, tangentWS.xyz, tangentWS.w);
output.tangentToWorld[0] = tangentToWorld[0];
output.tangentToWorld[1] = tangentToWorld[1];
output.tangentToWorld[2] = tangentToWorld[2];
#endif // SURFACE_GRADIENT
#endif
return output;

正在加载...
取消
保存