首页 > 代码库 > 材质 “Glow 效果” 的实现【UE4】
材质 “Glow 效果” 的实现【UE4】
效果如下:(由于对上传图片大小有限制,所以GIF截图质量下降严重)
算法较简单,首先来看 Base color 部分:
就是将对实现准备好的三张纹理进行线性插值,其中 Mask 为遮罩纹理
接着再来看 Emissive Color 部分:
算法也很简单,即随着时间的变化,经过变化的常量颜色和遮罩纹理进行线性插值,然后结果传入 Emissive Color
总览图
最后,附上 UE4 自动生成 HLSL 代码,有兴趣的朋友可以研究一下:
// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved. /** * MaterialTemplate.usf: Filled in by FHLSLMaterialTranslator::GetMaterialShaderCode for each material being compiled. */ #include "Random.usf" #include "UniformBuffers/Material.usf" // for MaterialExpressionDepthOfFieldFunction #include "DepthOfFieldCommon.usf" #include "CircleDOFCommon.usf" #include "GlobalDistanceFieldShared.usf" #if USES_SPEEDTREE #include "SpeedTreeCommon.usf" #endif #define NUM_MATERIAL_TEXCOORDS_VERTEX 1 #define NUM_MATERIAL_TEXCOORDS 1 #ifdef MIN_MATERIAL_TEXCOORDS #include "MinMaterialTexCoords.usf" #endif #if MATERIAL_ATMOSPHERIC_FOG #include "AtmosphereCommon.usf" #endif #include "PaniniProjection.usf" #ifndef USE_DITHERED_LOD_TRANSITION #if USE_INSTANCING #ifndef USE_DITHERED_LOD_TRANSITION_FOR_INSTANCED #error "USE_DITHERED_LOD_TRANSITION_FOR_INSTANCED should have been defined" #endif #define USE_DITHERED_LOD_TRANSITION USE_DITHERED_LOD_TRANSITION_FOR_INSTANCED #else #ifndef USE_DITHERED_LOD_TRANSITION_FROM_MATERIAL #error "USE_DITHERED_LOD_TRANSITION_FROM_MATERIAL should have been defined" #endif #define USE_DITHERED_LOD_TRANSITION USE_DITHERED_LOD_TRANSITION_FROM_MATERIAL #endif #endif #ifndef USE_STENCIL_LOD_DITHER #define USE_STENCIL_LOD_DITHER USE_STENCIL_LOD_DITHER_DEFAULT #endif //Platforms that don‘t run the editor shouldn‘t need editor features in the shaders. #define PLATFORM_SUPPORTS_EDITOR_SHADERS (!PS4_PROFILE && !XBOXONE_PROFILE && !ESDEFERRED_PROFILE && !WOLF_PROFILE) //Tie Editor features to platform support and the COMPILE_SHADERS_FOR_DEVELOPMENT which is set via CVAR. #define USE_EDITOR_SHADERS (PLATFORM_SUPPORTS_EDITOR_SHADERS && USE_DEVELOPMENT_SHADERS) //Materials also have to opt in to these features. #define USE_EDITOR_COMPOSITING (USE_EDITOR_SHADERS && EDITOR_PRIMITIVE_MATERIAL) #define MATERIALBLENDING_ANY_TRANSLUCENT (MATERIALBLENDING_TRANSLUCENT || MATERIALBLENDING_ADDITIVE || MATERIALBLENDING_MODULATE) /** * Parameters used by vertex and pixel shaders to access particle properties. */ struct FMaterialParticleParameters { /** Relative time [0-1]. */ half RelativeTime; /** Fade amount due to motion blur. */ half MotionBlurFade; /** Random value per particle [0-1]. */ half Random; /** XYZ: Direction, W: Speed. */ half4 Velocity; /** Per-particle color. */ half4 Color; /** Particle translated world space position and size(radius). */ float4 TranslatedWorldPositionAndSize; /** Macro UV scale and bias. */ half4 MacroUV; /** Dynamic parameter used by particle systems. */ half4 DynamicParameter; /** mesh particle orientation */ float4x4 LocalToWorld; #if USE_PARTICLE_SUBUVS /** SubUV texture coordinates*/ MaterialFloat2 SubUVCoords[2]; /** SubUV interpolation value*/ MaterialFloat SubUVLerp; #endif /** The size of the particle. */ float2 Size; }; float4 GetDynamicParameter(FMaterialParticleParameters Parameters, float4 Default) { #if PARTICLE_FACTORY return Parameters.DynamicParameter; #else return Default; #endif } /** * Parameters calculated from the pixel material inputs. */ struct FPixelMaterialInputs { MaterialFloat3 EmissiveColor; MaterialFloat Opacity; MaterialFloat OpacityMask; MaterialFloat3 BaseColor; MaterialFloat Metallic; MaterialFloat Specular; MaterialFloat Roughness; MaterialFloat3 Normal; MaterialFloat AmbientOcclusion; MaterialFloat2 Refraction; MaterialFloat PixelDepthOffset; }; /** * Parameters needed by pixel shader material inputs, related to Geometry. * These are independent of vertex factory. */ struct FMaterialPixelParameters { #if NUM_MATERIAL_TEXCOORDS float2 TexCoords[NUM_MATERIAL_TEXCOORDS]; #endif /** Interpolated vertex color, in linear color space. */ half4 VertexColor; /** Normalized tangent space normal. */ half3 TangentNormal; /** Normalized world space normal. */ half3 WorldNormal; /** Normalized world space reflected camera vector. */ half3 ReflectionVector; /** Normalized world space camera vector, which is the vector from the point being shaded to the camera position. */ half3 CameraVector; /** World space light vector, only valid when rendering a light function. */ half3 LightVector; /** * Like SV_Position (.xy is pixel position at pixel center, z:DeviceZ, .w:SceneDepth) * using shader generated value SV_POSITION * Warning: unlike SV_Position, this is not relative to the current viewport. SV_Position = MaterialParameters.SvPosition.xy - View.ViewRectMin.xy; */ float4 SvPosition; /** Post projection position reconstructed from SvPosition, before the divide by W. left..top -1..1, bottom..top -1..1 within the viewport, W is the SceneDepth */ float4 ScreenPosition; half UnMirrored; half TwoSidedSign; /** * Orthonormal rotation-only transform from tangent space to world space * The transpose(TangentToWorld) is WorldToTangent, and TangentToWorld[2] is WorldVertexNormal */ half3x3 TangentToWorld; /** * Interpolated worldspace position of this pixel * todo: Make this TranslatedWorldPosition and also rename the VS/DS/HS WorldPosition to be TranslatedWorldPosition */ float3 AbsoluteWorldPosition; /** * Interpolated worldspace position of this pixel, centered around the camera */ float3 WorldPosition_CamRelative; /** * Interpolated worldspace position of this pixel, not including any world position offset or displacement. * Only valid if shader is compiled with NEEDS_WORLD_POSITION_EXCLUDING_SHADER_OFFSETS, otherwise just contains 0 */ float3 WorldPosition_NoOffsets; /** * Interpolated worldspace position of this pixel, not including any world position offset or displacement. * Only valid if shader is compiled with NEEDS_WORLD_POSITION_EXCLUDING_SHADER_OFFSETS, otherwise just contains 0 */ float3 WorldPosition_NoOffsets_CamRelative; /** Offset applied to the lighting position for translucency, used to break up aliasing artifacts. */ half3 LightingPositionOffset; float AOMaterialMask; #if LIGHTMAP_UV_ACCESS float2 LightmapUVs; #endif #if USE_INSTANCING half4 PerInstanceParams; #endif /** Per-particle properties. Only valid for particle vertex factories. */ FMaterialParticleParameters Particle; #if (ES2_PROFILE || ES3_1_PROFILE) float4 LayerWeights; #endif #if TEX_COORD_SCALE_ANALYSIS /** Parameters used by the MaterialTexCoordScales shader. */ FTexCoordScalesParams TexCoordScalesParams; #endif #if POST_PROCESS_MATERIAL && (FEATURE_LEVEL <= FEATURE_LEVEL_ES3_1) /** Used in mobile custom pp material to preserve original SceneColor Alpha */ half BackupSceneColorAlpha; #endif }; // @todo compat hack FMaterialPixelParameters MakeInitializedMaterialPixelParameters() { FMaterialPixelParameters MPP; MPP = (FMaterialPixelParameters)0; MPP.TangentToWorld = float3x3(1,0,0,0,1,0,0,0,1); return MPP; } /** * Parameters needed by domain shader material inputs. * These are independent of vertex factory. */ struct FMaterialTessellationParameters { // Note: Customized UVs are only evaluated in the vertex shader, which is not really what you want with tessellation, but keeps the code simpler // (tessellation texcoords are the same as pixels shader texcoords) #if NUM_MATERIAL_TEXCOORDS float2 TexCoords[NUM_MATERIAL_TEXCOORDS]; #endif float4 VertexColor; // TODO: Non translated world position float3 WorldPosition; float3 TangentToWorldPreScale; // TangentToWorld[2] is WorldVertexNormal, [0] and [1] are binormal and tangent float3x3 TangentToWorld; }; /** * Parameters needed by vertex shader material inputs. * These are independent of vertex factory. */ struct FMaterialVertexParameters { // Position in the translated world (VertexFactoryGetWorldPosition). // Previous position in the translated world (VertexFactoryGetPreviousWorldPosition) if // computing material‘s output for previous frame (See {BasePassVertex,Velocity}Shader.usf). float3 WorldPosition; // TangentToWorld[2] is WorldVertexNormal half3x3 TangentToWorld; #if USE_INSTANCING /** Per-instance properties. */ float4x4 InstanceLocalToWorld; float3 InstanceLocalPosition; float4 PerInstanceParams; #elif PARTICLE_MESH_FACTORY /** Per-particle properties. */ float4x4 InstanceLocalToWorld; #endif float3 PreSkinnedPosition; half4 VertexColor; #if NUM_MATERIAL_TEXCOORDS_VERTEX float2 TexCoords[NUM_MATERIAL_TEXCOORDS_VERTEX]; #if (ES2_PROFILE || ES3_1_PROFILE) float2 TexCoordOffset; // Offset for UV localization for large UV values #endif #endif /** Per-particle properties. Only valid for particle vertex factories. */ FMaterialParticleParameters Particle; }; float3 GetTranslatedWorldPosition(FMaterialVertexParameters Parameters) { return Parameters.WorldPosition; } float3 GetPrevTranslatedWorldPosition(FMaterialVertexParameters Parameters) { // Previous world position and current world position are sharing the // same attribute in Parameters, because in BasePassVertexShader.usf // and in VelocityShader.usf, we are regenerating a Parameters from // VertexFactoryGetPreviousWorldPosition() instead of // VertexFactoryGetWorldPosition(). return GetTranslatedWorldPosition(Parameters); } float3 GetWorldPosition(FMaterialVertexParameters Parameters) { return GetTranslatedWorldPosition(Parameters) - ResolvedView.PreViewTranslation; } float3 GetPrevWorldPosition(FMaterialVertexParameters Parameters) { return GetPrevTranslatedWorldPosition(Parameters) - ResolvedView.PrevPreViewTranslation; } //TODO(bug UE-17131): We should compute world displacement for the previous frame float3 GetWorldPosition(FMaterialTessellationParameters Parameters) { return Parameters.WorldPosition; } float3 GetTranslatedWorldPosition(FMaterialTessellationParameters Parameters) { return Parameters.WorldPosition + ResolvedView.PreViewTranslation; } float3 GetWorldPosition(FMaterialPixelParameters Parameters) { return Parameters.AbsoluteWorldPosition; } float3 GetWorldPosition_NoMaterialOffsets(FMaterialPixelParameters Parameters) { return Parameters.WorldPosition_NoOffsets; } float3 GetTranslatedWorldPosition(FMaterialPixelParameters Parameters) { return Parameters.WorldPosition_CamRelative; } float3 GetTranslatedWorldPosition_NoMaterialOffsets(FMaterialPixelParameters Parameters) { return Parameters.WorldPosition_NoOffsets_CamRelative; } // using this function allows to write the same code for VS and PS float4 GetScreenPosition(FMaterialVertexParameters Parameters) { return mul(float4(Parameters.WorldPosition, 1.0f), ResolvedView.TranslatedWorldToClip); } // using this function allows to write the same code for VS and PS float4 GetScreenPosition(FMaterialPixelParameters Parameters) { return Parameters.ScreenPosition; } #if DEFERRED_DECAL && NUM_MATERIAL_TEXCOORDS /* * Material node DecalMipmapLevel‘s code designed to avoid the 2x2 pixels artefacts on the edges around where the decal * is projected to. The technique is fetched from (http://www.humus.name/index.php?page=3D&ID=84). * * The problem around edges of the meshes, is that the hardware computes the mipmap level according to ddx(uv) and ddy(uv), * but since the pixel shader are invocated by group of 2x2 pixels, then on edges some pixel might be getting the * current depth of an differet mesh that the other pixel of the same groups. If this mesh is very far from the other * mesh of the same group of pixel, then one of the delta might be very big, leading to choosing a low mipmap level for this * group of 4 pixels, causing the artefacts. */ float2 ComputeDecalUVFromSvPosition(float4 SvPosition) { half DeviceZ = LookupDeviceZ(SvPositionToBufferUV(SvPosition)); SvPosition.z = DeviceZ; float4 DecalVector = mul(float4(SvPosition.xyz,1), SvPositionToDecal); DecalVector.xyz /= DecalVector.w; DecalVector = DecalVector * 0.5f + 0.5f; DecalVector.xyz = DecalVector.zyx; return DecalVector.xy; } float2 ComputeDecalDDX(FMaterialPixelParameters Parameters) { /* * Assuming where in a pixel shader invocation, then we compute manualy compute two d(uv)/d(x) * with the pixels‘s left and right neighbours. */ float4 ScreenDeltaX = float4(1, 0, 0, 0); float2 UvDiffX0 = Parameters.TexCoords[0] - ComputeDecalUVFromSvPosition(Parameters.SvPosition - ScreenDeltaX); float2 UvDiffX1 = ComputeDecalUVFromSvPosition(Parameters.SvPosition + ScreenDeltaX) - Parameters.TexCoords[0]; /* * So we have two diff on the X axis, we want the one that has the smallest length * to avoid the 2x2 pixels mipmap artefacts on the edges. */ return dot(UvDiffX0, UvDiffX0) < dot(UvDiffX1, UvDiffX1) ? UvDiffX0 : UvDiffX1; } float2 ComputeDecalDDY(FMaterialPixelParameters Parameters) { // do same for the Y axis float4 ScreenDeltaY = float4(0, 1, 0, 0); float2 UvDiffY0 = Parameters.TexCoords[0] - ComputeDecalUVFromSvPosition(Parameters.SvPosition - ScreenDeltaY); float2 UvDiffY1 = ComputeDecalUVFromSvPosition(Parameters.SvPosition + ScreenDeltaY) - Parameters.TexCoords[0]; return dot(UvDiffY0, UvDiffY0) < dot(UvDiffY1, UvDiffY1) ? UvDiffY0 : UvDiffY1; } float ComputeDecalMipmapLevel(FMaterialPixelParameters Parameters, float2 TextureSize) { float2 UvPixelDiffX = ComputeDecalDDX(Parameters) * TextureSize; float2 UvPixelDiffY = ComputeDecalDDY(Parameters) * TextureSize; // Computes the mipmap level float MaxDiff = max(dot(UvPixelDiffX, UvPixelDiffX), dot(UvPixelDiffY, UvPixelDiffY)); return 0.5 * log2(MaxDiff); } #else // DEFERRED_DECAL && NUM_MATERIAL_TEXCOORDS float2 ComputeDecalDDX(FMaterialPixelParameters Parameters) { return 0.0f; } float2 ComputeDecalDDY(FMaterialPixelParameters Parameters) { return 0.0f; } float ComputeDecalMipmapLevel(FMaterialPixelParameters Parameters, float2 TextureSize) { return 0.0f; } #endif // DEFERRED_DECAL && NUM_MATERIAL_TEXCOORDS #if DEFERRED_DECAL /* * Deferred decal don‘t have a Primitive uniform buffer, because we don‘t know on which primitive the decal * is being projected to. But the user may still need to get the decal‘s actor world position. * So instead of setting up a primitive buffer that may cost to much CPU effort to be almost never used, * we directly fetch this value from the DeferredDecal.usf specific uniform variable DecalToWorld. */ float3 GetActorWorldPosition() { return DecalToWorld[3].xyz; } #else float3 GetActorWorldPosition() { return Primitive.ActorWorldPosition; } #endif // DEFERRED_DECAL #if DECAL_PRIMITIVE float DecalLifetimeOpacity() { return DecalParams.y; } #else float DecalLifetimeOpacity() { return 0.0f; } #endif // DECAL_PRIMITIVE /** Transforms a vector from tangent space to world space, prescaling by an amount calculated previously */ MaterialFloat3 TransformTangentVectorToWorld_PreScaled(FMaterialTessellationParameters Parameters, MaterialFloat3 InTangentVector) { #if FEATURE_LEVEL >= FEATURE_LEVEL_SM5 // used optionally to scale up the vector prior to conversion InTangentVector *= abs( Parameters.TangentToWorldPreScale ); // Transform directly to world space // The vector transform is optimized for this case, only one vector-matrix multiply is needed return mul(InTangentVector, Parameters.TangentToWorld); #else return TransformTangentVectorToWorld(Parameters.TangentToWorld, InTangentVector); #endif // #if FEATURE_LEVEL_SM5 } /** Transforms a vector from tangent space to view space */ MaterialFloat3 TransformTangentVectorToView(FMaterialPixelParameters Parameters, MaterialFloat3 InTangentVector) { // Transform from tangent to world, and then to view space return mul(mul(InTangentVector, Parameters.TangentToWorld), (MaterialFloat3x3)ResolvedView.TranslatedWorldToView); } /** Transforms a vector from local space to world space (VS version) */ MaterialFloat3 TransformLocalVectorToWorld(FMaterialVertexParameters Parameters,MaterialFloat3 InLocalVector) { #if USE_INSTANCING || PARTICLE_MESH_FACTORY return mul(InLocalVector, (MaterialFloat3x3)Parameters.InstanceLocalToWorld); #else return mul(InLocalVector, GetLocalToWorld3x3()); #endif } /** Transforms a vector from local space to world space (PS version) */ MaterialFloat3 TransformLocalVectorToWorld(FMaterialPixelParameters Parameters,MaterialFloat3 InLocalVector) { return mul(InLocalVector, GetLocalToWorld3x3()); } #if HAS_PRIMITIVE_UNIFORM_BUFFER /** Transforms a vector from world space to local space */ MaterialFloat3 TransformWorldVectorToLocal(MaterialFloat3 InWorldVector) { return mul(InWorldVector, (MaterialFloat3x3)Primitive.WorldToLocal); } /** Transforms a position from local space to absolute world space */ float3 TransformLocalPositionToWorld(FMaterialPixelParameters Parameters,float3 InLocalPosition) { return mul(float4(InLocalPosition, 1), Primitive.LocalToWorld).xyz; } /** Transforms a position from local space to absolute world space */ float3 TransformLocalPositionToWorld(FMaterialVertexParameters Parameters,float3 InLocalPosition) { #if USE_INSTANCING || PARTICLE_MESH_FACTORY return mul(float4(InLocalPosition, 1), Parameters.InstanceLocalToWorld).xyz; #else return mul(float4(InLocalPosition, 1), Primitive.LocalToWorld).xyz; #endif } #endif #if HAS_PRIMITIVE_UNIFORM_BUFFER /** Return the object‘s position in world space */ float3 GetObjectWorldPosition(FMaterialPixelParameters Parameters) { return Primitive.ObjectWorldPositionAndRadius.xyz; } float3 GetObjectWorldPosition(FMaterialTessellationParameters Parameters) { return Primitive.ObjectWorldPositionAndRadius.xyz; } /** Return the object‘s position in world space. For instanced meshes, this returns the instance position. */ float3 GetObjectWorldPosition(FMaterialVertexParameters Parameters) { #if USE_INSTANCING || PARTICLE_MESH_FACTORY return Parameters.InstanceLocalToWorld[3].xyz; #else return Primitive.ObjectWorldPositionAndRadius.xyz; #endif } #endif /** Get the per-instance random value when instancing */ float GetPerInstanceRandom(FMaterialVertexParameters Parameters) { #if USE_INSTANCING return Parameters.PerInstanceParams.x; #else return 0.0; #endif } /** Get the per-instance random value when instancing */ float GetPerInstanceRandom(FMaterialPixelParameters Parameters) { #if USE_INSTANCING return Parameters.PerInstanceParams.x; #else return 0.0; #endif } /** Get the per-instance fade-out amount when instancing */ float GetPerInstanceFadeAmount(FMaterialPixelParameters Parameters) { #if USE_INSTANCING return float(Parameters.PerInstanceParams.y); #else return float(1.0); #endif } /** Get the per-instance fade-out amount when instancing */ float GetPerInstanceFadeAmount(FMaterialVertexParameters Parameters) { #if USE_INSTANCING return float(Parameters.PerInstanceParams.y); #else return float(1.0); #endif } MaterialFloat GetDistanceCullFade() { return saturate( View.RealTime * PrimitiveFade.FadeTimeScaleBias.x + PrimitiveFade.FadeTimeScaleBias.y ); } /** Rotates Position about the given axis by the given angle, in radians, and returns the offset to Position. */ float3 RotateAboutAxis(float4 NormalizedRotationAxisAndAngle, float3 PositionOnAxis, float3 Position) { // Project Position onto the rotation axis and find the closest point on the axis to Position float3 ClosestPointOnAxis = PositionOnAxis + NormalizedRotationAxisAndAngle.xyz * dot(NormalizedRotationAxisAndAngle.xyz, Position - PositionOnAxis); // Construct orthogonal axes in the plane of the rotation float3 UAxis = Position - ClosestPointOnAxis; float3 VAxis = cross(NormalizedRotationAxisAndAngle.xyz, UAxis); float CosAngle; float SinAngle; sincos(NormalizedRotationAxisAndAngle.w, SinAngle, CosAngle); // Rotate using the orthogonal axes float3 R = UAxis * CosAngle + VAxis * SinAngle; // Reconstruct the rotated world space position float3 RotatedPosition = ClosestPointOnAxis + R; // Convert from position to a position offset return RotatedPosition - Position; } // Material Expression function float MaterialExpressionDepthOfFieldFunction(float SceneDepth, int FunctionValueIndex) { // tryed switch() but seems that doesn‘t work if(FunctionValueIndex == 0) // TDOF_NearAndFarMask { return CalcUnfocusedPercentCustomBound(SceneDepth, 1, 1); } else if(FunctionValueIndex == 1) // TDOF_Near { return CalcUnfocusedPercentCustomBound(SceneDepth, 1, 0); } else if(FunctionValueIndex == 2) // TDOF_Far { return CalcUnfocusedPercentCustomBound(SceneDepth, 0, 1); } else if(FunctionValueIndex == 3) // TDOF_CircleOfConfusionRadius { // * 2 to compensate for half res return DepthToCoc(SceneDepth) * 2.0f; } return 0; } // TODO convert to LUT float3 MaterialExpressionBlackBody( float Temp ) { float u = ( 0.860117757f + 1.54118254e-4f * Temp + 1.28641212e-7f * Temp*Temp ) / ( 1.0f + 8.42420235e-4f * Temp + 7.08145163e-7f * Temp*Temp ); float v = ( 0.317398726f + 4.22806245e-5f * Temp + 4.20481691e-8f * Temp*Temp ) / ( 1.0f - 2.89741816e-5f * Temp + 1.61456053e-7f * Temp*Temp ); float x = 3*u / ( 2*u - 8*v + 4 ); float y = 2*v / ( 2*u - 8*v + 4 ); float z = 1 - x - y; float Y = 1; float X = Y/y * x; float Z = Y/y * z; float3x3 XYZtoRGB = { 3.2404542, -1.5371385, -0.4985314, -0.9692660, 1.8760108, 0.0415560, 0.0556434, -0.2040259, 1.0572252, }; return mul( XYZtoRGB, float3( X, Y, Z ) ) * pow( 0.0004 * Temp, 4 ); } float4 MaterialExpressionAtmosphericFog(FMaterialPixelParameters Parameters, float3 AbsoluteWorldPosition) { #if MATERIAL_ATMOSPHERIC_FOG // WorldPosition default value is Parameters.AbsoluteWorldPosition if not overridden by the user float3 ViewVector = AbsoluteWorldPosition - ResolvedView.WorldCameraOrigin; float SceneDepth = length(ViewVector); return GetAtmosphericFog(ResolvedView.WorldCameraOrigin, ViewVector, SceneDepth, float3(0.f, 0.f, 0.f)); #else return float4(0.f, 0.f, 0.f, 0.f); #endif } float3 MaterialExpressionAtmosphericLightVector(FMaterialPixelParameters Parameters) { #if MATERIAL_ATMOSPHERIC_FOG return View.AtmosphericFogSunDirection; #else return float3(0.f, 0.f, 0.f); #endif } float3 MaterialExpressionAtmosphericLightColor(FMaterialPixelParameters Parameters) { #if MATERIAL_ATMOSPHERIC_FOG return View.AtmosphericFogSunColor; #else return float3(0.f, 0.f, 0.f); #endif } /** * Utility function to unmirror one coordinate value to the other side * UnMirrored == 1 if normal * UnMirrored == -1 if mirrored * * Used by most of parameter functions generated via code in this file */ MaterialFloat UnMirror( MaterialFloat Coordinate, FMaterialPixelParameters Parameters ) { return ((Coordinate)*(Parameters.UnMirrored)*0.5+0.5); } /** * UnMirror only U */ MaterialFloat2 UnMirrorU( MaterialFloat2 UV, FMaterialPixelParameters Parameters ) { return MaterialFloat2(UnMirror(UV.x, Parameters), UV.y); } /** * UnMirror only V */ MaterialFloat2 UnMirrorV( MaterialFloat2 UV, FMaterialPixelParameters Parameters ) { return MaterialFloat2(UV.x, UnMirror(UV.y, Parameters)); } /** * UnMirror only UV */ MaterialFloat2 UnMirrorUV( MaterialFloat2 UV, FMaterialPixelParameters Parameters ) { return MaterialFloat2(UnMirror(UV.x, Parameters), UnMirror(UV.y, Parameters)); } /** * Transforms screen space positions into UVs with [.5, .5] centered on ObjectPostProjectionPosition, * And [1, 1] at ObjectPostProjectionPosition + (ObjectRadius, ObjectRadius). */ MaterialFloat2 GetParticleMacroUV(FMaterialPixelParameters Parameters) { return (Parameters.ScreenPosition.xy / Parameters.ScreenPosition.w - Parameters.Particle.MacroUV.xy) * Parameters.Particle.MacroUV.zw + MaterialFloat2(.5, .5); } #ifndef MOBILE_EMULATION #define MOBILE_EMULATION ((FEATURE_LEVEL == FEATURE_LEVEL_ES2 || FEATURE_LEVEL == FEATURE_LEVEL_ES3_1) && (!(COMPILER_GLSL_ES2||COMPILER_GLSL_ES3_1) && USE_DEVELOPMENT_SHADERS && (COMPILER_METAL && MAC))) #endif MaterialFloat4 ProcessMaterialColorTextureLookup(MaterialFloat4 TextureValue) { #if (ES2_PROFILE || ES3_1_PROFILE) #if MOBILE_EMULATION if( View.MobilePreviewMode > 0.5f) { // undo HW srgb->lin TextureValue.rgb = pow(TextureValue.rgb, 1.0f / 2.2f); // TODO: replace with a more accurate lin -> sRGB conversion. } #endif // sRGB read approximation TextureValue.rgb *= TextureValue.rgb; #endif return TextureValue; } MaterialFloat4 ProcessMaterialLinearColorTextureLookup(MaterialFloat4 TextureValue) { return TextureValue; } MaterialFloat ProcessMaterialGreyscaleTextureLookup(MaterialFloat TextureValue) { #if (ES2_PROFILE || ES3_1_PROFILE) #if MOBILE_EMULATION if( View.MobilePreviewMode > 0.5f ) { // undo HW srgb->lin TextureValue = http://www.mamicode.com/pow(TextureValue, 1.0f/2.2f); // TODO: replace with a more accurate lin -> sRGB conversion.>
(完)
材质 “Glow 效果” 的实现【UE4】
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。