2023-06-29 11:55:02 +08:00

7.1 KiB
Raw Blame History

描边

  • RenderToonOutlineToBaseColor
  • RenderToonOutlineToSceneColor

相关Shader

  • ToonDataPassShader.usf
  • ToonOutline.usf
  • ToonShadingModel.ush

相关RT

//Begin YivanLee's Modify
TRefCountPtr<IPooledRenderTarget> SceneColorCopy;
TRefCountPtr<IPooledRenderTarget> BaseColorCopy;
TRefCountPtr<IPooledRenderTarget> ToonBufferDepth;
TRefCountPtr<IPooledRenderTarget> ToonOutlineTexture;
TRefCountPtr<IPooledRenderTarget> ToonOutlineMaskBlurTexture;
TRefCountPtr<IPooledRenderTarget> ToonIDOutlineTexture;

//ToonDataTexture01 is ToonNormal
TRefCountPtr<IPooledRenderTarget> ToonDataTexture01;
//ToonDataTexture02 is R: ShadowController G: B: A:
TRefCountPtr<IPooledRenderTarget> ToonDataTexture02;
//ToonDataTexture03 is OutlineColorMask and OutlineMask
TRefCountPtr<IPooledRenderTarget> ToonDataTexture03;
//ToonDataTexture04 is IDTexture
TRefCountPtr<IPooledRenderTarget> ToonDataTexture04;
//End YivanLee's Modify

GBuffer

ToonData0 = float4(N * 0.5 + 0.5, 1.0f);//WorldNormal ToonData1 = GetMaterialToonDataA(MaterialParameters);//Shadow controller ToonData2 = GetMaterialToonDataB(MaterialParameters);//OutlinleColor,OutlineMask ToonData3 = GetMaterialToonDataC(MaterialParameters);//IDTexture,OutlineWidth

BasePass部分

位于FDeferredShadingSceneRenderer::RenderBasePass()最后,

if (ShouldRenderToonDataPass())
{
	//Begin Recreate ToonData Render targets
	SceneContext.ReleaseToonDataTarget();
	SceneContext.AllocateToonDataTarget(GraphBuilder.RHICmdList);
	SceneContext.ReleaseToonDataGBuffer();
	SceneContext.AllocateToonDataGBuffer(GraphBuilder.RHICmdList);
	//End Recreate ToonData Render targets

	TStaticArray<FRDGTextureRef, MaxSimultaneousRenderTargets> ToonDataPassTextures;
	uint32 ToonDataTextureCount = SceneContext.GetToonDataGBufferRenderTargets(GraphBuilder, ToonDataPassTextures);
	TArrayView<FRDGTextureRef> ToonDataPassTexturesView = MakeArrayView(ToonDataPassTextures.GetData(), ToonDataTextureCount);
	
	ERenderTargetLoadAction ToonTargetsAction;
	if (bEnableParallelBasePasses)//Windows DirectX12
	{
		ToonTargetsAction = ERenderTargetLoadAction::ELoad;
	}
	else//Windows DirectX11
	{
		ToonTargetsAction = ERenderTargetLoadAction::EClear;
	}
	FRenderTargetBindingSlots ToonDataPassRenderTargets = GetRenderTargetBindings(ToonTargetsAction, ToonDataPassTexturesView);
	ToonDataPassRenderTargets.DepthStencil = FDepthStencilBinding(SceneDepthTexture, ERenderTargetLoadAction::ELoad, ERenderTargetLoadAction::ELoad, ExclusiveDepthStencil);
	ToonDataPassRenderTargets.ShadingRateTexture = GVRSImageManager.GetVariableRateShadingImage(GraphBuilder, ViewFamily, nullptr, EVRSType::None);

	AddSetCurrentStatPass(GraphBuilder, GET_STATID(STAT_CLM_ToonDataPass));
	RenderToonDataPass(GraphBuilder, ToonDataPassTextures, ToonDataTextureCount, ToonDataPassRenderTargets, bEnableParallelBasePasses);
	AddSetCurrentStatPass(GraphBuilder, GET_STATID(STAT_CLM_AfterToonDataPass));

	RenderToonOutlineToBaseColor(GraphBuilder, SceneDepthTexture, bEnableParallelBasePasses);
}

RenderNormalDepthOutline

  • ToonOutlineMain:使用拉普拉斯算子与Sobel算子计算并混合结果。计算Depth与Normal最后Length(float4(Normal,Depth));
  • ToonIDOutlinePSMain:使用Sobel计算描边。

RenderToonIDOutline

CombineOutlineToBaseColor

渲染管线Render()

RenderToonOutlineToSceneColor()位于RenderLights()之后与RenderDeferredReflectionsAndSkyLighting()之前的位置。

ShaderModel

DefaultLitBxDF

Lighting.Diffuse  = AreaLight.FalloffColor * (Falloff * NoL) * Diffuse_Lambert( GBuffer.DiffuseColor );
Lighting.Specular = AreaLight.FalloffColor * (Falloff * NoL) * SpecularGGX(GBuffer.Roughness, GBuffer.SpecularColor, Context, NoL, AreaLight);

Toon

  • ToonDataAR ShadowOffset GBA 未使用
  • ToonDataBRGB OutlineColor A OutlineMask
  • ToonDataCRGB IDMap A OutlineWidth
  • PreIntegratedToonBRDF: R 为NoL 预积分Ramp G 为GGX高光预积分值。
  • PreIntegratedToonSkinBRDFRGB为皮肤预积分颜色。
  • SubsurfaceColor该数据存放在CustomData.rgb位置,在天光计算中其作用

PS.ToonShadingStandard没有使用SubsurfaceColor。

ToonShadingStandard

在原始的PBR公式做了以下修改 固有色部分

  1. 使用ShadowOffset(ToonDataA.r)来控制阴影区域的偏移也就是类似UTS的Step。但使用lerp(Context.NoL, 1.0, ShadowOffset),这导致偏移并不易于控制。
  2. 计算FallOffMask预积分衰减调整系数。使用ShadowOffset过的NoL与Metalic作为UV对PreIntegratedToonBRDF图进行查表返回r值。
  3. Lighting.Diffuse = AreaLight.FalloffColor * FallOffMask * GBuffer.BaseColor / 3.1415927f;

高光部分

  1. D预积分GGX使用NoH与Roughness作为UV对PreIntegratedToonBRDF进行查表返回g值。
  2. F边缘光效果系数return smoothstep(0.67, 1.0, 1 - NoV);
  3. Lighting.Specular = (F + D) * (AreaLight.FalloffColor * GBuffer.SpecularColor * FallOffMask * 8);
float ShadowOffset = GBuffer.ToonDataA.r;
float FallOffMask = Falloff * GetPreintegratedToonBRDF(lerp(Context.NoL, 1.0, ShadowOffset), GBuffer.Metallic);
Lighting.Diffuse = AreaLight.FalloffColor * FallOffMask * GBuffer.BaseColor / 3.1415927f;

float R2 = GBuffer.Roughness * GBuffer.Roughness;
float ToonGGX = GetPreintegratedToonSpecBRDF(Context.NoH, GBuffer.Roughness);
float D = lerp(ToonGGX, 0.0, R2);
float3 F = GetToonF(Context.NoV);
Lighting.Specular = (F + D) * (AreaLight.FalloffColor * GBuffer.SpecularColor * FallOffMask * 8);

ToonShadingSkin

在ToonShadingStandard的基础上做了以下修改 固有色部分:

  1. 使用ShadowOffset来偏移Context.NoL * Shadow.SurfaceShadow来获得ShadowMask。
  2. 使用ShadowMask与Opacity作为UV来查询PreIntegratedToonSkinBRDF返回rgb值。
  3. Lighting.Diffuse = AreaLight.FalloffColor * FallOffMask * GBuffer.BaseColor / 3.1415927f * PreintegratedBRDF;

高光部分相同。

ToonShadingHair

在ToonShadingStandard的基础上做了以下修改 固有色部分相同。

高光部分增加各向异性计算:

float3 H = normalize(L + V);
float HoL = dot(H, geotangent);
float sinTH = saturate(sqrt(1 - HoL * HoL));
float spec = pow(sinTH, lerp(256, 4, GBuffer.Roughness));
float R2 = GBuffer.Roughness * GBuffer.Roughness;
float3 F = GetToonF(Context.NoV);
spec += F;

Lighting.Specular = AreaLight.FalloffColor * FallOffMask * spec * GBuffer.BaseColor;

天光(环境光)

阴影部分的光照主要为环境光逻辑为于ReflectionEnvironmentSkyLighting()

/*BeginYivanLee's Modify*/
float3 SkyLighting = float3(0.0, 0.0, 0.0);
BRANCH
if(ShadingModelID == SHADINGMODELID_TOONSTANDARD || ShadingModelID == SHADINGMODELID_TOONHAIR || ShadingModelID == SHADINGMODELID_TOONSKIN)
{
	float3 SubsurfaceColor = ExtractSubsurfaceColor(GBuffer);
	float3 SkyToonLighting = GBuffer.BaseColor * SubsurfaceColor.rgb;
	float3 SkyDiffuseLighting = SkyLightDiffuse(GBuffer, AmbientOcclusion, BufferUV, ScreenPosition, BentNormal, DiffuseColor) * CloudAmbientOcclusion;
	SkyLighting = lerp(SkyDiffuseLighting, SkyToonLighting, 0.8f);
}
else
{
	SkyLighting = SkyLightDiffuse(GBuffer, AmbientOcclusion, BufferUV, ScreenPosition, BentNormal, DiffuseColor) * CloudAmbientOcclusion;
}
/*EndYivanLee's Modify*/