## 描边 - RenderToonOutlineToBaseColor - RenderToonOutlineToSceneColor 相关Shader: - ToonDataPassShader.usf - ToonOutline.usf - ToonShadingModel.ush 相关RT ``` //Begin YivanLee's Modify TRefCountPtr SceneColorCopy; TRefCountPtr BaseColorCopy; TRefCountPtr ToonBufferDepth; TRefCountPtr ToonOutlineTexture; TRefCountPtr ToonOutlineMaskBlurTexture; TRefCountPtr ToonIDOutlineTexture; //ToonDataTexture01 is ToonNormal TRefCountPtr ToonDataTexture01; //ToonDataTexture02 is R: ShadowController G: B: A: TRefCountPtr ToonDataTexture02; //ToonDataTexture03 is OutlineColorMask and OutlineMask TRefCountPtr ToonDataTexture03; //ToonDataTexture04 is IDTexture TRefCountPtr 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 ToonDataPassTextures; uint32 ToonDataTextureCount = SceneContext.GetToonDataGBufferRenderTargets(GraphBuilder, ToonDataPassTextures); TArrayView 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 ```c# 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 - ToonDataA:R ShadowOffset GBA 未使用 - ToonDataB:RGB OutlineColor A OutlineMask - ToonDataC:RGB IDMap A OutlineWidth - PreIntegratedToonBRDF: R 为NoL 预积分Ramp G 为GGX高光预积分值。 - PreIntegratedToonSkinBRDF:RGB为皮肤预积分颜色。 - 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); ```c++ 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的基础上做了以下修改: 固有色部分相同。 高光部分增加各向异性计算: ```c++ 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*/ ```