【目标】

UE4的Tonemapper

【思路】

1 UE3中关键字

  • USE_TONEMAPPERTYPE
  • \Shaders\UberPostProcessBlendPixelShader.usf
  • TonemapAndGammaCorrect

2 UE3的算法

half3 TonemapAndGammaCorrect(half3 LinearColor)
{
half A = (half)ImageAdjustments2.x;
half B = (half)ImageAdjustments2.y;

half3 GammaColor;

#if USE_TONEMAPPERTYPE == 0
// no tonemapper
{
GammaColor = pow(LinearColor, 1.0f / 2.2f);
}
#elif USE_TONEMAPPERTYPE == 1
// filmic approximation (s-curve, contrast enhances, small toe, changes saturation and hue)
// simple but effective tonemapper
// outputs in 0..1 range (saturate())
// clamps negative colors to 0 (abs())
{
GammaColor = LinearColor / abs(LinearColor + A) * B;
}

#elif USE_TONEMAPPERTYPE == 2
// neutral soft white clamp (experimental, not optimized yet)
// outputs in 0..1 range (saturate())
// clamps negataive colors to 0 (abs())
{
// ToeFactor 0 = non means linear .. 1 = full (filmic look)
half ToeFactor = (half)ImageAdjustments3.x;
half LinearSteepness = (half)ImageAdjustments2.w;
// value below we have linear adjustments to the sigmoid curve that we don't to above the value
half FunctionSplitPos = ImageAdjustments2.z;

half3 GammaColorOldTonemapperTonemapperStartingFromLinear = LinearColor / abs(LinearColor + A) * B;

// efficient 3 component implementation of: LinearColor >= FunctionSplitPos
half3 SplitMask = saturate((LinearColor - FunctionSplitPos) * 10000.0f);

const half3 GammaColorNotTonemapped = pow(LinearColor * LinearSteepness, 1.0f / 2.2f);

half3 FlatGammaColor = lerp(GammaColorNotTonemapped, GammaColorOldTonemapperTonemapperStartingFromLinear, SplitMask);

GammaColor = lerp(FlatGammaColor, GammaColorOldTonemapperTonemapperStartingFromLinear, ToeFactor);
}
#endif

// in all cases it's good to clamp into the 0..1 range (e.g for LUT color grading)
GammaColor = saturate(GammaColor);

return GammaColor;
}

变量定义

// xy=Grain Offset to have animated noise, z=unused, w=ImageGrainScale
// Note: ImageAdjustments1.xy is a random float2 in the range 0..1
float4 ImageAdjustments1;
// TonemapperFunction(x) = x / (x + A) * B
// x=A, y=B, z=split pos, w=LinearSteepness
float4 ImageAdjustments2;
// x=tonemapper toe factor (0=linear..1=full toe)
float4 ImageAdjustments3;

3 UE4相关

ACES Gets in the Games

Mon, 04/10/2017 - 12:01 -- Sarah Priestnall

The Motion Picture Academy’s Academy Color Encoding System is now widely used across the movie industry but perhaps surprisingly, it’s also gaining traction in the gaming world. To learn more, Digital Cinema Report recently spoke with Brian Karis at Cary, North Carolina-based Epic Games. The company is known for its industry-leading Unreal Engine, a ground breaking game engine that can be used by other game developers who do not want to develop their own engine.

Digital Cinema Report: Tell us what your role at Epic Games is?

Brian Karis: I'm a senior graphics programmer on the rendering team here at Epic. I work on many different aspects of the renderer.

DCR: What made you decide to incorporate ACES?

BK: A couple of years ago I tackled changing our tone mapper from a proprietary ad hoc curve with some artist parameters to a new curve that better simulated film response and could be configured to fit a number of different film responses. During that effort I learned a ton about color science and physical film. I also came upon ACES and decided it should be the foundation for our color handling. Right now, we do all rendering in Rec. 709 space but do the grading in ACEScg and then use an Output Transform. I ended up creating a parametric curve that combines the Reference Rendering Transform (RRT) and Output Device Transform (ODT) for 100 nit monitors that allows the artist to get different film stock looks than the ACES standard look but our defaults match ACES. So currently the default tone mapper and color grading in Unreal Engine 4 (UE4) is ACES.

DCR: What advantages do you see in using ACES within a gaming engine?

BK: What advantages there are is a large question but I'll touch on a few things. In my opinion the biggest impact is from doing tone mapping in ACEScg space. Regardless of the curve, that alone makes colors look so much better and more realistic. The specific curve of ACES matches film characteristics but honestly it is just a choice of look amongst many options. Having the RRT and ODT separated is a really good idea and one I wish I had embraced earlier. If I had, I could have had my parametric curve work for HDR displays as well. That now needs a bit of a rethink. Matching a standard that we can load up in Nuke or other packages has proven useful so far and I expect will be ever more useful in the future as UE4 becomes more used by film and VFX companies.

For HDR displays we use the ACES ODTs and disable those controls. I'd like to make that work in the future. We are also interested in adding support for rendering in ACEScg space. I recently engaged with the larger ACES community in helping write a retrospective and suggestions for improvements for future versions.

来源: http://www.digitalcinemareport.com/article/aces-gets-games#.WVnw8WONXFs

4 youtube介绍

https://www.youtube.com/watch?v=A-wectYNfRQ

Filmic Tonemapper | Feature Highlight | Unreal Engine


5 UE4 Shader流向

TonemapCommon.usf FilmSlope ->FLUTBlenderPS.FilmSlope

FilmToneMap函数

/*
============================================
// Uncharted settings
Slope = 0.63;
Toe = 0.55;
Shoulder = 0.47;
BlackClip= 0;
WhiteClip = 0.01;

// HP settings
Slope = 0.65;
Toe = 0.63;
Shoulder = 0.45;
BlackClip = 0;
WhiteClip = 0;

// Legacy settings
Slope = 0.98;
Toe = 0.3;
Shoulder = 0.22;
BlackClip = 0;
WhiteClip = 0.025;

// ACES settings
Slope = 0.88;
Toe = 0.55;
Shoulder = 0.26;
BlackClip = 0;
WhiteClip = 0.04;
===========================================
*/

float FilmSlope;
float FilmToe;
float FilmShoulder;
float FilmBlackClip;
float FilmWhiteClip;

half3 FilmToneMap( half3 LinearColor ) 
{
const float3x3 sRGB_2_AP0 = mul( XYZ_2_AP0_MAT, mul( D65_2_D60_CAT, sRGB_2_XYZ_MAT ) );
const float3x3 sRGB_2_AP1 = mul( XYZ_2_AP1_MAT, mul( D65_2_D60_CAT, sRGB_2_XYZ_MAT ) );
const float3x3 AP1_2_sRGB = mul( XYZ_2_sRGB_MAT, mul( D60_2_D65_CAT, AP1_2_XYZ_MAT ) );
#if !ES2_PROFILE //disabling this part for mobile, Adreno devices can't handle it (UE-40689)
float3 ACESColor = mul( sRGB_2_AP0, float3(LinearColor) );

// --- Red modifier --- //
const float RRT_RED_SCALE = 0.82;
const float RRT_RED_PIVOT = 0.03;
const float RRT_RED_HUE = 0;
const float RRT_RED_WIDTH = 135;

float saturation = rgb_2_saturation( ACESColor );
float hue = rgb_2_hue( ACESColor );
float centeredHue = center_hue( hue, RRT_RED_HUE );
float hueWeight = Square( smoothstep( 0, 1, 1 - abs( 2 * centeredHue / RRT_RED_WIDTH ) ) );
ACESColor.r += hueWeight * saturation * (RRT_RED_PIVOT - ACESColor.r) * (1. - RRT_RED_SCALE);

// Use ACEScg primaries as working space
float3 WorkingColor = mul( AP0_2_AP1_MAT, ACESColor );
#else
// Use ACEScg primaries as working space
float3 WorkingColor = mul( sRGB_2_AP1, float3(LinearColor) );
#endif

WorkingColor = max( 0, WorkingColor );

// Pre desaturate
WorkingColor = lerp( dot( WorkingColor, AP1_RGB2Y ), WorkingColor, 0.96 );
const half ToeScale = 1 + FilmBlackClip - FilmToe;
const half ShoulderScale = 1 + FilmWhiteClip - FilmShoulder;
const float InMatch = 0.18;
const float OutMatch = 0.18;

float ToeMatch;
if( FilmToe > 0.8 )
{
// 0.18 will be on straight segment
ToeMatch = ( 1 - FilmToe  - OutMatch ) / FilmSlope + log10( InMatch );
}
else
{
// 0.18 will be on toe segment

// Solve for ToeMatch such that input of InMatch gives output of OutMatch.
const float bt = ( OutMatch + FilmBlackClip ) / ToeScale - 1;
ToeMatch = log10( InMatch ) - 0.5 * log( (1+bt)/(1-bt) ) * (ToeScale / FilmSlope);
}

float StraightMatch = ( 1 - FilmToe ) / FilmSlope - ToeMatch;
float ShoulderMatch = FilmShoulder / FilmSlope - StraightMatch;
half3 LogColor = log10( WorkingColor );
half3 StraightColor = FilmSlope * ( LogColor + StraightMatch );
half3 ToeColor = (    -FilmBlackClip ) + (2 *      ToeScale) / ( 1 + exp( (-2 * FilmSlope /      ToeScale) * ( LogColor -      ToeMatch ) ) );
half3 ShoulderColor = ( 1 + FilmWhiteClip ) - (2 * ShoulderScale) / ( 1 + exp( ( 2 * FilmSlope / ShoulderScale) * ( LogColor - ShoulderMatch ) ) );

ToeColor = LogColor <      ToeMatch ?      ToeColor : StraightColor;
ShoulderColor = LogColor > ShoulderMatch ? ShoulderColor : StraightColor;

half3 t = saturate( ( LogColor - ToeMatch ) / ( ShoulderMatch - ToeMatch ) );
t = ShoulderMatch < ToeMatch ? 1 - t : t;
t = (3-2*t)*t*t;
half3 ToneColor = lerp( ToeColor, ShoulderColor, t );

// Post desaturate
ToneColor = lerp( dot( float3(ToneColor), AP1_RGB2Y ), ToneColor, 0.93 );

// Returning positive AP1 values
return max( 0, ToneColor );

//ToneColor = mul( AP1_2_sRGB, ToneColor );

//return saturate( ToneColor );
//return max( 0, ToneColor );
}

6  \UnrealEngine4\Engine\Shaders\ACES.usf 定义一些要用到的常量

https://github.com/ampas/aces-dev/tree/v1.0

\UnrealEngine4\Engine\Shaders\PostProcessTonemap.usf

\UnrealEngine4\Engine\Shaders\TonemapCommon.usf

7 计算流程

  • PostProcessCombineLUTs.usf MainPS

8 https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/

【步骤】

1 修改 \Engine\Shaders\UberPostProcessBlendPixelShader.usf


elif USE_TONEMAPPERTYPE == 3
{
//float a = 2.51f;
    //float b = 0.03f;
    //float c = 2.43f;
    //float d = 0.59f;
    //float e = 0.14f;
    //return saturate((x*(a*x+b))/(x*(c*x+d)+e));
    GammaColor = saturate((LinearColor*(2.51f*LinearColor+0.03f))/(LinearColor*(2.43f*LinearColor+0.59f)+0.14f));
}

2 修改\Development\Src\Engine\Classes\UberPostProcessEffect.uc 添加类型

/** Allows to specify the tone mapper function which maps HDR colors into the LDR color range. */
var(Tonemapper) enum ETonemapperType
{
    Tonemapper_Off<DisplayName=Off>, 
    Tonemapper_ACES<DisplayName=ACES>, 
    Tonemapper_Customizable<DisplayName=Customizable>, 
    Tonemapper_Filmic<DisplayName=Filmic>, 
} TonemapperType;

3 FUberPostProcessSceneProxy.Render 

#define VARIATION1(A)        VARIATION2(A,0)            VARIATION2(A,1)            VARIATION2(A,2)            VARIATION2(A,3)

4 UberPostProcessEffect.cpp 

#define VARIATION1(A)        VARIATION2(A,0)            VARIATION2(A,1)            VARIATION2(A,2)        VARIATION2(A,3)

运行 ACES效果

对比film效果
没有试过UE4的效果

5 UE4算法

6 拷贝ACES.usf
在\Engine\Shaders\UberPostProcessBlendPixelShader.usf
#include "ACES.usf"
...


\Engine\Shaders\UberPostProcessBlendPixelShader.usf

/*
============================================
// Uncharted settings
Slope = 0.63;
Toe = 0.55;
Shoulder = 0.47;
BlackClip= 0;
WhiteClip = 0.01;
// HP settings
Slope = 0.65;
Toe = 0.63;
Shoulder = 0.45;
BlackClip = 0;
WhiteClip = 0;
// Legacy settings
Slope = 0.98;
Toe = 0.3;
Shoulder = 0.22;
BlackClip = 0;
WhiteClip = 0.025;
// ACES settings
Slope = 0.88;
Toe = 0.55;
Shoulder = 0.26;
BlackClip = 0;
WhiteClip = 0.04;
===========================================
*/
const static float FilmSlope = 0.88;
const static float FilmToe = 0.55;
const static float FilmShoulder = 0.26;
const static float FilmBlackClip = 0;
const static float FilmWhiteClip = 0.04;
half3 FilmToneMap( half3 LinearColor ) 
{
const float3x3 sRGB_2_AP0 = mul( XYZ_2_AP0_MAT, mul( D65_2_D60_CAT, sRGB_2_XYZ_MAT ) );
const float3x3 sRGB_2_AP1 = mul( XYZ_2_AP1_MAT, mul( D65_2_D60_CAT, sRGB_2_XYZ_MAT ) );
const float3x3 AP1_2_sRGB = mul( XYZ_2_sRGB_MAT, mul( D60_2_D65_CAT, AP1_2_XYZ_MAT ) );
float3 ACESColor = mul( sRGB_2_AP0, float3(LinearColor) );
// --- Red modifier --- //
const float RRT_RED_SCALE = 0.82;
const float RRT_RED_PIVOT = 0.03;
const float RRT_RED_HUE = 0;
const float RRT_RED_WIDTH = 135;
float saturation = rgb_2_saturation( ACESColor );
float hue = rgb_2_hue( ACESColor );
float centeredHue = center_hue( hue, RRT_RED_HUE );
float hueWeight = Square( smoothstep( 0, 1, 1 - abs( 2 * centeredHue / RRT_RED_WIDTH ) ) );
ACESColor.r += hueWeight * saturation * (RRT_RED_PIVOT - ACESColor.r) * (1. - RRT_RED_SCALE);
// Use ACEScg primaries as working space
float3 WorkingColor = mul( AP0_2_AP1_MAT, ACESColor );
WorkingColor = max( 0, WorkingColor );
// Pre desaturate
WorkingColor = lerp( dot( WorkingColor, AP1_RGB2Y ), WorkingColor, 0.96 );
const half ToeScale = 1 + FilmBlackClip - FilmToe;
const half ShoulderScale = 1 + FilmWhiteClip - FilmShoulder;
const float InMatch = 0.18;
const float OutMatch = 0.18;
float ToeMatch;
if( FilmToe > 0.8 )
{
// 0.18 will be on straight segment
ToeMatch = ( 1 - FilmToe  - OutMatch ) / FilmSlope + log10( InMatch );
}
else
{
// 0.18 will be on toe segment
// Solve for ToeMatch such that input of InMatch gives output of OutMatch.
const float bt = ( OutMatch + FilmBlackClip ) / ToeScale - 1;
ToeMatch = log10( InMatch ) - 0.5 * log( (1+bt)/(1-bt) ) * (ToeScale / FilmSlope);
}
float StraightMatch = ( 1 - FilmToe ) / FilmSlope - ToeMatch;
float ShoulderMatch = FilmShoulder / FilmSlope - StraightMatch;
half3 LogColor = log10( WorkingColor );
half3 StraightColor = FilmSlope * ( LogColor + StraightMatch );
half3 ToeColor = (    -FilmBlackClip ) + (2 *      ToeScale) / ( 1 + exp( (-2 * FilmSlope /      ToeScale) * ( LogColor -      ToeMatch ) ) );
half3 ShoulderColor = ( 1 + FilmWhiteClip ) - (2 * ShoulderScale) / ( 1 + exp( ( 2 * FilmSlope / ShoulderScale) * ( LogColor - ShoulderMatch ) ) );
ToeColor = LogColor <      ToeMatch ?      ToeColor : StraightColor;
ShoulderColor = LogColor > ShoulderMatch ? ShoulderColor : StraightColor;
half3 t = saturate( ( LogColor - ToeMatch ) / ( ShoulderMatch - ToeMatch ) );
t = ShoulderMatch < ToeMatch ? 1 - t : t;
t = (3-2*t)*t*t;
half3 ToneColor = lerp( ToeColor, ShoulderColor, t );
// Post desaturate
ToneColor = lerp( dot( float3(ToneColor), AP1_RGB2Y ), ToneColor, 0.93 );
// Returning positive AP1 values
return max( 0, ToneColor );
//ToneColor = mul( AP1_2_sRGB, ToneColor );
//return saturate( ToneColor );
//return max( 0, ToneColor );
}

...
GammaColor = FilmToneMap(LinearColor);

【运行】

7 几个配置都加进去
#elif USE_TONEMAPPERTYPE == 3
{
// Simple ACES
//float a = 2.51f;
    //float b = 0.03f;
    //float c = 2.43f;
    //float d = 0.59f;
    //float e = 0.14f;
    //return saturate((x*(a*x+b))/(x*(c*x+d)+e));
    GammaColor = saturate(( LinearColor * (2.51f * LinearColor + 0.03f )) / ( LinearColor * ( 2.43f * LinearColor + 0.59f ) + 0.14f ));  
}
#elif USE_TONEMAPPERTYPE == 4
{
// Uncharted settings
  FilmSlope = 0.63;
FilmToe = 0.55;
FilmShoulder = 0.47;
FilmBlackClip= 0;
FilmWhiteClip = 0.01;
GammaColor = FilmToneMap(LinearColor);
}
#elif USE_TONEMAPPERTYPE == 5
{
// HP settings
FilmSlope = 0.65;
FilmToe = 0.63;
FilmShoulder = 0.45;
FilmBlackClip = 0;
FilmWhiteClip = 0;
GammaColor = FilmToneMap(LinearColor);
}
#elif USE_TONEMAPPERTYPE == 6
{
// Legacy settings
FilmSlope = 0.98;
FilmToe = 0.3;
FilmShoulder = 0.22;
FilmBlackClip = 0;
FilmWhiteClip = 0.025;
GammaColor = FilmToneMap(LinearColor);
}
#elif USE_TONEMAPPERTYPE == 7
{
// ACES settings
FilmSlope = 0.88;
FilmToe = 0.55;
FilmShoulder = 0.26;
FilmBlackClip = 0;
FilmWhiteClip = 0.04;
FilmGammaColor = FilmToneMap(LinearColor);
}
#endif

 

FUberPostProcessSceneProxy.Render 

#define VARIATION1(A)        VARIATION2(A,0)            VARIATION2(A,1)            VARIATION2(A,2)    VARIATION2(A,3) VARIATION2(A,4) VARIATION2(A,5) VARIATION2(A,6) VARIATION2(A,7)

UberPostProcessEffect.cpp 

#define VARIATION1(A)        VARIATION2(A,0)            VARIATION2(A,1)            VARIATION2(A,2)        VARIATION2(A,3) VARIATION2(A,4) VARIATION2(A,5) VARIATION2(A,6) VARIATION2(A,7)

语法报错嵌套太深 感觉超过48层就报错了

只能采用传另外一个参数

ImageAdjustments3只用的第一个Float

9 FUberPostProcessSceneProxy 中添加属性

    UINT TonemapperACESType;

FUberPostProcessSceneProxy.FUberPostProcessSceneProxy

    FUberPostProcessSceneProxy(const UUberPostProcessEffect* InEffect,const FPostProcessSettings* WorldSettings, UINT InColorGradingCVar, 
        UINT InTonemapperType,UINT InTonemapperACESType, UBOOL bInMotionBlur, UBOOL bInImageGrain,const FCameraInfo& CI)
        :    FDOFAndBloomPostProcessSceneProxy(InEffect, WorldSettings,CI)
        ,    MotionBlurSoftEdgeKernelSize(InEffect->MotionBlurSoftEdgeKernelSize)
        ,    TonemapperToeFactor(InEffect->TonemapperToeFactor)
        ,    TonemapperRange(InEffect->TonemapperRange)
        ,    ColorGradingCVar(InColorGradingCVar)
        ,    TonemapperType(InTonemapperType)
        ,    TonemapperACESType(InTonemapperACESType)

10 \ue3\Development\Src\Engine\Classes\UberPostProcessEffect.uc

var(Tonemapper) enum EACESType
{
    ACES_One<DisplayName=ACES>, 
    ACES_Simple<DisplayName=Simple>, 
    ACES_Uncharted<DisplayName=Uncharted>, 
    ACES_HP<DisplayName=HP>, 
    ACES_Legacy<DisplayName=Legacy>, 
} ACESType;

11 UUberPostProcessEffect.CreateSceneProxy

    return new FUberPostProcessSceneProxy(this, WorldSettings, GColorGrading, LocalTonemapperType,ACESType, bLocalMotionBlur, bEnableImageGrain,CI);

12 Shader赋值FUberPostProcessSceneProxy.RenderVariationFullRes.{.SetPixelShaderValue 

            SetPixelShaderValue(
                BlendPixelShader->GetPixelShader(), 
                BlendPixelShader->ImageAdjustments3Parameter,
                FVector4(Clamp(TonemapperToeFactor, 0.0f, 1.0f), TonemapperACESType, 0, 0));


13 \Engine\Shaders\UberPostProcessBlendPixelShader.usf

#elif USE_TONEMAPPERTYPE == 3
{

if (ACESType == 1)
{
// Simple ACES
//float a = 2.51f;
    //float b = 0.03f;
    //float c = 2.43f;
    //float d = 0.59f;
    //float e = 0.14f;
    //return saturate((x*(a*x+b))/(x*(c*x+d)+e));
    GammaColor = saturate(( LinearColor * (2.51f * LinearColor + 0.03f )) / ( LinearColor * ( 2.43f * LinearColor + 0.59f ) + 0.14f ));  
    }
    else
    {
    if (ACESType == 0)
    {
    // ACES settings
FilmSlope = 0.88;
FilmToe = 0.55;
FilmShoulder = 0.26;
FilmBlackClip = 0;
FilmWhiteClip = 0.04;
  }
  else if (ACESType == 2)
  {
  // Uncharted settings
FilmSlope = 0.63;
FilmToe = 0.55;
FilmShoulder = 0.47;
FilmBlackClip= 0;
FilmWhiteClip = 0.01;
  }
  else if (ACESType == 3)
  {
// HP settings
FilmSlope = 0.65;
FilmToe = 0.63;
FilmShoulder = 0.45;
FilmBlackClip = 0;
FilmWhiteClip = 0;
  }
  else if (ACESType == 4)
  {
  // Legacy settings
FilmSlope = 0.98;
FilmToe = 0.3;
FilmShoulder = 0.22;
FilmBlackClip = 0;
FilmWhiteClip = 0.025;
  }
  
  GammaColor = FilmToneMap(LinearColor);
    }
}
#endif

14 添加指令

UUberPostProcessEffect.CreateSceneProxy.

        CVar = GConsoleManager->FindConsoleVariable(TEXT("ACESType")); 
        Value = CVar->GetInt();
        if (Value >= ACES_One && Value < ACES_MAX)
        {
            LocalACESType = Value;
        }

CreateConsoleVariables

    GConsoleManager->RegisterConsoleVariable(TEXT("ACESType"),
        -1,
        TEXT("Allows to override which ACESType function (during the post processing stage to transform HDR to LDR colors) is used:\n")
        TEXT("-1: use what is specified elsewhere (default)\n")
        TEXT(" 0: ACES settings \n")
        TEXT(" 1: Simple ACES \n")
        TEXT(" 2: Uncharted settings\n")
        TEXT(" 3: HP settings"),
        TEXT(" 4: Legacy settings"),
        ECVF_Cheat);

指令

TonemapperType 3
ACESType 0-4

" 0: ACES settings"

" 1: Simple ACES"

" 2: Uncharted settings"

" 3: HP settings"

" 4: Legacy settings"

15 

16
来自为知笔记(Wiz)

转载于:https://www.cnblogs.com/username/p/8879963.html

17070302(UE4的Tonemapper)相关推荐

  1. UE4 性能优化方法(工具篇)

    http://www.cnblogs.com/ghl_carmack/p/5481763.html 本文依据UE4官方文档以及官方博客等总结而来,可能不全面,后面会陆续添加.内置工具的详细说明请参考官 ...

  2. UE4 调整引擎功能的级别

    Unreal Engine 4.9 性能及分析 SHARE: 控制台变量和命令 有些功能可以在运行时,由游戏的控制台或者编辑器的输出日志窗口/控制台进行开关切换. 已有很多控制台变量可以用来调整引擎的 ...

  3. 【UE4】UE4框选

    目录: 视窗操作篇 反转鼠标中键 自适应视窗缩放速度 解除对选中物体旋转 对屏幕外物体进行位移旋转缩放 物体吸附到模型顶点 屏幕编队(记录当前相机位置和旋转) 落到正下方物体 显示与隐藏 资源操作篇 ...

  4. UE4虚幻引擎开发手机游戏

    该文章来自用户转载 点击阅读原文 UE4虚幻引擎作为游戏开发引擎之一,在很多项目中都会使用到.下面就给大家分享下如何使用UE4开发高品质的手机游戏. 作者介绍 大纲 •介绍 •UE4 针对3A级手游的 ...

  5. 墨尘 - UE4 入门教程笔记 —— 二

    一.C4D - 入门篇 旋转视图:Alt + 鼠标左键 缩放视图:Alt + 鼠标右键 平移视图:Alt + 鼠标中间 移动:E.缩放:T.R:旋转 撤回:Ctrl + Z 复原视图:Ctrl + s ...

  6. [UE4]Stat命令

    说明 测试并优化你的游戏时,不可以避免用的要要那个到Stat命令.即专门针对显示游戏统计的控制台命令. stat命令参考文档 要分析 虚幻引擎(UE) 项目,开发人员可以在使用 编辑器中运行(PIE) ...

  7. ue4 改变枢轴位置_[UE4]偏门实用技巧合集

    前言: 不论是玩游戏,还是玩软件,我对操作和技巧都有着痴迷的追求.而且是个快捷键狂魔. 从这个工具就能看出来,我对快捷键的执着,对工作效率极致提升的吹毛求疵. 戴巍:[SD Plugin] 快捷键创建 ...

  8. ue4 改变枢轴位置_UE4虚幻引擎学习云笔记(五)-静态网格体编辑器

    [五.静态网格体编辑器(Static Mesh Editor)] 19-09-26 静态网格体编辑器一般用以分配材质至静态网格体,每个LOD可以有不同材质. 静态网格体编辑器(Static Mesh ...

  9. ue4手机ui_UE4虚幻引擎开发手机游戏

    特性集介绍 •ES2 •Mobile渲染器 •对应OpenGLES2.0-3.x(Android平台)       OpenGL ES2.0(iOS平台,支持ES3.0的IOS平台已经能够支持meta ...

最新文章

  1. Prometheus 序章/第一/二讲
  2. I Got a Matrix!
  3. GoogLenet网络解读及代码实现(Pytorch)
  4. java ee 值范围_javaEE四大作用域(共享域)
  5. fatal error LINK1123:failure during conversion to COFF:file invalid or corrupt
  6. nginx 作为Web缓存服务器
  7. UNIX环境高级编程之第6章:系统数据文件和信息-习题
  8. [Linux] - 网速测试命令
  9. 【设备管理】【OEE】30页精彩PPT:详解精益生产OEE
  10. 如何让计算机从固态硬盘启动不了,电脑设置固态硬盘启动的方法
  11. ie11浏览器For win7 x64 官方下载 V9600 官方版
  12. 微信小程序解析后台返回的html格式
  13. MacOS系统上有什么好用的思维导图软件?
  14. 零和博弈,囚徒困境,马斯洛需求层次理论
  15. 3分钟学会制作动态折线图!
  16. 各位端午节快乐 -- Happy the Dragon-Boat Festival
  17. spring-IOC-三更的扩展版
  18. pip全局设置镜像源
  19. android数据库的创建
  20. TT100K/BDD100K数据集格式转换

热门文章

  1. Web服务器,应用服务器,HTTP服务器,web软件数据流向
  2. 高级扫描技术及原理介绍(转)
  3. 基于模拟退火的交巡警平台调度问题
  4. JAVA 基础 12月06日 第一天
  5. dtd文件生成java类
  6. 不错的ERP社区: http://www.erppub.cn/?fromuid=10575
  7. 视频教程-Vue零基础到精通视频教程-Vue
  8. 浅谈CAD如何精准导入图新地球并应用在工程行业
  9. 微信小程序 Storage API
  10. mvn打包中使用-D替换pom中的值