UE4 随笔记录1

1、蓝图材质转换HLSL代码

  • 在蓝图中创建Post Process Material,然后创建SceneTexture,ID选择CustomStencil,如下图:
    • UE4 随笔记录1_第1张图片
  • 在材质编辑器下,点击Window->Shader Code->HLSL Code,copy对应代码,保存生成custom.hsls文件(名称随便命名,目的方便描述该文件)。
    • HLSL code 是基于MaterialTemplate.ush(Engine/Shader/Private)进行生成。
    • 如何生成?目前没有深入研究,待后续更新(如果用到)。
  • 对比MaterialTemplate.ush和custom.hsls文件。在VSCode中,左侧目录同时选中两个文件,右键,有compare功能,进行对比哪些是custom.hsls新增的。
    • 实际对比,发现有大量的不同出现,然而我们在材质蓝图中,仅仅增加了一个SceneTexture函数,不应该有很多变化。没有深入分析原因,后面用到再研究。
    • 本次研究的重点是如何获得SceneTexture,测试的ID是CustomStencil。而不是Post Process Material如何被使用,因此下面内容会围绕本次重点展开。
    • 在custom.hsls中找出Emissive Color赋值出现的位置:
      • void CalcPixelMaterialInputs(in out FMaterialPixelParameters Parameters, in out FPixelMaterialInputs PixelMaterialInputs)
        • 不研究CalcPixelMaterialInputs如何被使用,只研究里面的内容。
      • EmissiveColor是有两个数值差值的出来。
        • Local0是和SceneTexture相关,深入研究
        • Material.VectorExpression[1].rgb,不是重点,没有深入研究。
      • 关键部分代码
      • MaterialFloat4 Local0 = SceneTextureLookup(GetDefaultSceneTextureUV(Parameters, 25), 25, false);
        MaterialFloat3 Local1 = erp(Local0.rgba.rgb,Material.VectorExpressions[1].rgb,MaterialFloat(Material.ScalarExpressions[0].x));
        PixelMaterialInputs.EmissiveColor = Local1;

         

  • SceneTextureLookup函数介绍
  • /** Applies an offset to the scene texture lookup and decodes the HDR linear space color. */
    float4 SceneTextureLookup(float2 UV, int SceneTextureIndex, bool bFiltered)
    {
    #if SCENE_TEXTURES_DISABLED
        return float4(0.0f, 0.0f, 0.0f, 0.0f);
    #endif
    
        FScreenSpaceData ScreenSpaceData = GetScreenSpaceData(UV, false);
        switch(SceneTextureIndex)
        {
            // order needs to match to ESceneTextureId
    
            case PPI_SceneColor:
                return float4(CalcSceneColor(UV), 0);
            case PPI_SceneDepth:
                return ScreenSpaceData.GBuffer.Depth;
            case PPI_DiffuseColor:
                return float4(ScreenSpaceData.GBuffer.DiffuseColor, 0);
            case PPI_SpecularColor:
                return float4(ScreenSpaceData.GBuffer.SpecularColor, 0);
            case PPI_SubsurfaceColor:
                return IsSubsurfaceModel(ScreenSpaceData.GBuffer.ShadingModelID) ? float4( ExtractSubsurfaceColor(ScreenSpaceData.GBuffer), ScreenSpaceData.GBuffer.CustomData.a ) : ScreenSpaceData.GBuffer.CustomData;
            case PPI_BaseColor:
                return float4(ScreenSpaceData.GBuffer.BaseColor, 0);
            case PPI_Specular:
                return ScreenSpaceData.GBuffer.Specular;
            case PPI_Metallic:
                return ScreenSpaceData.GBuffer.Metallic;
            case PPI_WorldNormal:
                return float4(ScreenSpaceData.GBuffer.WorldNormal, 0);
            case PPI_SeparateTranslucency:
                return float4(1, 1, 1, 1);    // todo
            case PPI_Opacity:
                return ScreenSpaceData.GBuffer.CustomData.a;
            case PPI_Roughness:
                return ScreenSpaceData.GBuffer.Roughness;
            case PPI_MaterialAO:
                return ScreenSpaceData.GBuffer.GBufferAO;
            case PPI_CustomDepth:
                return ScreenSpaceData.GBuffer.CustomDepth;
    #if POST_PROCESS_MATERIAL
            case PPI_PostProcessInput0:
                return Texture2DSample(PostProcessInput_0_Texture, bFiltered ? PostProcessInput_BilinearSampler : PostProcessInput_0_SharedSampler, UV);
            case PPI_PostProcessInput1:
                return Texture2DSample(PostProcessInput_1_Texture, bFiltered ? PostProcessInput_BilinearSampler : PostProcessInput_1_SharedSampler, UV);
            case PPI_PostProcessInput2:
                return Texture2DSample(PostProcessInput_2_Texture, bFiltered ? PostProcessInput_BilinearSampler : PostProcessInput_2_SharedSampler, UV);
            case PPI_PostProcessInput3:
                return Texture2DSample(PostProcessInput_3_Texture, bFiltered ? PostProcessInput_BilinearSampler : PostProcessInput_3_SharedSampler, UV);
            case PPI_PostProcessInput4:
                return Texture2DSample(PostProcessInput_4_Texture, bFiltered ? PostProcessInput_BilinearSampler : PostProcessInput_4_SharedSampler, UV);
    #endif // __POST_PROCESS_COMMON__
            case PPI_DecalMask:
                return 0;  // material compiler will return an error
            case PPI_ShadingModelColor:
                return float4(GetShadingModelColor(ScreenSpaceData.GBuffer.ShadingModelID), 1);
            case PPI_ShadingModelID:
                return float4(ScreenSpaceData.GBuffer.ShadingModelID, 0, 0, 0);
            case PPI_AmbientOcclusion:
                return ScreenSpaceData.AmbientOcclusion;
            case PPI_CustomStencil:
                return ScreenSpaceData.GBuffer.CustomStencil;
            case PPI_StoredBaseColor:
                return float4(ScreenSpaceData.GBuffer.StoredBaseColor, 0);
            case PPI_StoredSpecular:
                return float4(ScreenSpaceData.GBuffer.StoredSpecular.rrr, 0);
    #if POST_PROCESS_MATERIAL
            case PPI_Velocity:
                return float4(PostProcessVelocityLookup(ConvertToDeviceZ(ScreenSpaceData.GBuffer.Depth), UV), 0, 0);
    #endif
            case PPI_WorldTangent:
                return float4(ScreenSpaceData.GBuffer.WorldTangent, 0);
            case PPI_Anisotropy:
                return ScreenSpaceData.GBuffer.Anisotropy;
            default:
                return float4(0, 0, 0, 0);
        }
    }

    GetScreenSpaceData 在DeferredShadingCommon.ush文件中。

// @param UV - UV space in the GBuffer textures (BufferSize resolution)
FScreenSpaceData GetScreenSpaceData(float2 UV, bool bGetNormalizedNormal = true)
{
	FScreenSpaceData Out;

	Out.GBuffer = GetGBufferData(UV, bGetNormalizedNormal);
	float4 ScreenSpaceAO = Texture2DSampleLevel(SceneTexturesStruct.ScreenSpaceAOTexture, SceneTexturesStruct.ScreenSpaceAOTextureSampler, UV, 0);

	Out.AmbientOcclusion = ScreenSpaceAO.r;

	return Out;
}

在相同文件内:

// @param UV - UV space in the GBuffer textures (BufferSize resolution)
FGBufferData GetGBufferData(float2 UV, bool bGetNormalizedNormal = true)
{
#if 0 //METAL_MRT_PROFILE
	// @todo metal mrt: The deferred renderer isn't keeping these in tiled memory all the time - we don't know when this makes sense
	// versus just sampling a bound resolved texture
	float4 GBufferA = FramebufferFetchMRT(1);
	float4 GBufferB = FramebufferFetchMRT(2);
	float4 GBufferC = FramebufferFetchMRT(3);
	float4 GBufferD = FramebufferFetchMRT(4);
	// @todo metal mrt: We can't framebuffer fetch the depth, can we jam it in somewhere?
	float CustomNativeDepth = 0.5;
	#if ALLOW_STATIC_LIGHTING
		float4 GBufferE = FramebufferFetchMRT(5);
	#else
		float4 GBufferE = 1;
	#endif
#else	
	float4 GBufferA = Texture2DSampleLevel(SceneTexturesStruct.GBufferATexture, SceneTexturesStruct.GBufferATextureSampler, UV, 0);
	float4 GBufferB = Texture2DSampleLevel(SceneTexturesStruct.GBufferBTexture, SceneTexturesStruct.GBufferBTextureSampler, UV, 0);
	float4 GBufferC = Texture2DSampleLevel(SceneTexturesStruct.GBufferCTexture, SceneTexturesStruct.GBufferCTextureSampler, UV, 0);
	float4 GBufferD = Texture2DSampleLevel(SceneTexturesStruct.GBufferDTexture, SceneTexturesStruct.GBufferDTextureSampler, UV, 0);
	float CustomNativeDepth = Texture2DSampleLevel(SceneTexturesStruct.CustomDepthTexture, SceneTexturesStruct.CustomDepthTextureSampler, UV, 0).r;

#if FEATURE_LEVEL >= FEATURE_LEVEL_SM4
	int2 IntUV = (int2)trunc(UV * View.BufferSizeAndInvSize.xy);
	uint CustomStencil = SceneTexturesStruct.CustomStencilTexture.Load(int3(IntUV, 0)) STENCIL_COMPONENT_SWIZZLE;
#else
	uint CustomStencil = 0;
#endif

	#if ALLOW_STATIC_LIGHTING
		float4 GBufferE = Texture2DSampleLevel(SceneTexturesStruct.GBufferETexture, SceneTexturesStruct.GBufferETextureSampler, UV, 0);
	#else
		float4 GBufferE = 1;
	#endif

	#if WRITES_VELOCITY_TO_GBUFFER
		float4 GBufferVelocity = Texture2DSampleLevel(SceneTexturesStruct.GBufferVelocityTexture, SceneTexturesStruct.GBufferVelocityTextureSampler, UV, 0);
	#else
		float4 GBufferVelocity = 0;
	#endif
#endif

	float SceneDepth = CalcSceneDepth(UV);
	
	return DecodeGBufferData(GBufferA, GBufferB, GBufferC, GBufferD, GBufferE, GBufferVelocity, CustomNativeDepth, CustomStencil, SceneDepth, bGetNormalizedNormal, CheckerFromSceneColorUV(UV));
}

在相同文件里:

/** Populates FGBufferData */
// @param bChecker High frequency Checkerboard pattern computed with one of the CheckerFrom.. functions, todo: profile if float 0/1 would be better (need to make sure it's 100% the same)
FGBufferData DecodeGBufferData(
	float4 InGBufferA,
	float4 InGBufferB,
	float4 InGBufferC,
	float4 InGBufferD,
	float4 InGBufferE,
	float4 InGBufferVelocity,
	float CustomNativeDepth,
	uint CustomStencil,
	float SceneDepth,
	bool bGetNormalizedNormal,
	bool bChecker)
{
	FGBufferData GBuffer;

	GBuffer.WorldNormal = DecodeNormal( InGBufferA.xyz );
	if(bGetNormalizedNormal)
	{
		GBuffer.WorldNormal = normalize(GBuffer.WorldNormal);
	}

	GBuffer.PerObjectGBufferData = InGBufferA.a;  
	GBuffer.Metallic	= InGBufferB.r;
	GBuffer.Specular	= InGBufferB.g;
	GBuffer.Roughness	= InGBufferB.b;
	// Note: must match GetShadingModelId standalone function logic
	// Also Note: SimpleElementPixelShader directly sets SV_Target2 ( GBufferB ) to indicate unlit.
	// An update there will be required if this layout changes.
	GBuffer.ShadingModelID = DecodeShadingModelId(InGBufferB.a);
	GBuffer.SelectiveOutputMask = DecodeSelectiveOutputMask(InGBufferB.a);

	GBuffer.BaseColor = DecodeBaseColor(InGBufferC.rgb);

#if ALLOW_STATIC_LIGHTING
	GBuffer.GBufferAO = 1;
	GBuffer.IndirectIrradiance = DecodeIndirectIrradiance(InGBufferC.a);
#else
	GBuffer.GBufferAO = InGBufferC.a;
	GBuffer.IndirectIrradiance = 1;
#endif

	GBuffer.CustomData = !(GBuffer.SelectiveOutputMask & SKIP_CUSTOMDATA_MASK) ? InGBufferD : 0;

	GBuffer.PrecomputedShadowFactors = !(GBuffer.SelectiveOutputMask & SKIP_PRECSHADOW_MASK) ? InGBufferE :  ((GBuffer.SelectiveOutputMask & ZERO_PRECSHADOW_MASK) ? 0 :  1);
	GBuffer.CustomDepth = ConvertFromDeviceZ(CustomNativeDepth);
	GBuffer.CustomStencil = CustomStencil;
	GBuffer.Depth = SceneDepth;

	GBuffer.StoredBaseColor = GBuffer.BaseColor;
	GBuffer.StoredMetallic = GBuffer.Metallic;
	GBuffer.StoredSpecular = GBuffer.Specular;

	FLATTEN
	if( GBuffer.ShadingModelID == SHADINGMODELID_EYE )
	{
		GBuffer.Metallic = 0.0;
#if IRIS_NORMAL
		GBuffer.Specular = 0.25;
#endif
	}

	// derived from BaseColor, Metalness, Specular
	{
		GBuffer.SpecularColor = ComputeF0(GBuffer.Specular, GBuffer.BaseColor, GBuffer.Metallic);

		if (UseSubsurfaceProfile(GBuffer.ShadingModelID))
		{
			AdjustBaseColorAndSpecularColorForSubsurfaceProfileLighting(GBuffer.BaseColor, GBuffer.SpecularColor, GBuffer.Specular, bChecker);
		}

		GBuffer.DiffuseColor = GBuffer.BaseColor - GBuffer.BaseColor * GBuffer.Metallic;

		#if USE_DEVELOPMENT_SHADERS
		{
			// this feature is only needed for development/editor - we can compile it out for a shipping build (see r.CompileShadersForDevelopment cvar help)
			GBuffer.DiffuseColor = GBuffer.DiffuseColor * View.DiffuseOverrideParameter.www + View.DiffuseOverrideParameter.xyz;
			GBuffer.SpecularColor = GBuffer.SpecularColor * View.SpecularOverrideParameter.w + View.SpecularOverrideParameter.xyz;
		}
		#endif //USE_DEVELOPMENT_SHADERS
	}

	GBuffer.Velocity = !(GBuffer.SelectiveOutputMask & SKIP_VELOCITY_MASK) ? InGBufferVelocity : 0;

	return GBuffer;
}

回归到CustomStencil:

#if FEATURE_LEVEL >= FEATURE_LEVEL_SM4
	int2 IntUV = (int2)trunc(UV * View.BufferSizeAndInvSize.xy);
	uint CustomStencil = SceneTexturesStruct.CustomStencilTexture.Load(int3(IntUV, 0)) STENCIL_COMPONENT_SWIZZLE;
#else
	uint CustomStencil = 0;
#endif

 

你可能感兴趣的:(#,UE4之Shader研究)