Unreal——Shader初探(一)

使用Shader文件

在项目根目录新建一个文件夹Shaders,新建shader文件,必须以.usf 或者.ush 结尾。

通过添加一个custom node,在code中添加代码,在Gaussian Blur中添加

1
2
#include "C:/UGit/Shader/CustomShaders/CustomShadersStarter/Shaders/Gaussian.usf"
return 1;

然后在Gaussian.usf中填充shader

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
static const int SceneTextureId = 14;
float2 TexelSize = View.ViewSizeAndInvSize.zw; //将偏移量转换到UV空间
float2 UV = GetDefaultSceneTextureUV(Parameters, SceneTextureId); //当前像素的UV
float3 PixelSum = float3(0, 0, 0); //将内核(kernel)中每一个像素的颜色累加(sum)起来。
float WeightSum = 0; //将内核中每一个像素的权重累加起来。

for (int x = -Radius; x <= Radius; x++) //水平方向
{
for (int y = -Radius; y <= Radius; y++) //垂直方向
{
float2 Offset = UV + float2(x, y) * TexelSize; //计算采样像素的相对偏移量并将其转换为UV空间
float3 PixelColor = SceneTextureLookup(Offset, SceneTextureId, 0).rgb; //经过偏移量对场景纹理进行采样
float Weight = Calculate1DGaussian(x / Radius) * Calculate1DGaussian(y / Radius); //计算采样像素的加权。为了计算二维的高斯模糊,你须要将两个一维的高斯模糊相乘(multiply),除以(divide)radius是由于简化的高斯模糊公式的值域是[-1,1],因此须要将它们的值归一化。
PixelSum += PixelColor * Weight; //将加权的颜色添加到PixelSum
WeightSum += Weight; //将权重添加给WeightSum

}
}

return PixelSum / WeightSum;

image-20210726150720610

高质量实时渲染(一)

Reflective Shadow Maps(RSM)

在shadowmap上的每一个像素都是场景中表面上的一小块

假设:反射物都是diffuse

回顾:

  • 单位面积单位立体角 radiance
  • 单位立体角Radiant Intensity
  • 单位面积irradiance

MC光线追踪

在球面坐标,一个方向向量可以采用$(\theta,\phi)$来表示,分别为天顶角和方位角,立体角定义为
$$
dw=\frac{dA}{r^2}
$$
在单位球体上,$dw=dA$,我们转换用$(\theta,\phi)$求微分面积,根据弧长公式

$$
\begin{align}
s_{\theta}&=\theta * r_{\theta} \\
s_{\phi}&=\phi * r_{\phi} \\
d_{s \theta}&=r_{\theta} d \theta \\
d_{s \phi}&=r_{\phi} d \phi
\end{align}
$$

微分面积$dA$可以看作为一个微矩形,宽高为$d_{r\phi}$和$d_{r\theta}$,对于单位球体,$r_\theta=1,r_{\phi}=r_{\theta}*sin$

$$
dw=dA=d_{s\theta}*{s\phi}=sin\theta d\theta d\phi
$$
可对材质表面进行brdf采样,也可对光源进行直接采样

直接光源采样

$\alpha$夹角是采样方向向量与光源矩形表面法线向量的夹角,$dAcos\alpha$就是将矩形微分表面$dA$投影到采样方向$pq$上。
$$
d \omega=\frac{d A * \cos \alpha}{|p q|^{2}}
$$
我们对$dA$的采样概率应该是$\frac{dA}{A}$,在球体方向对立体角$d\omega$的采样概率为$p(direction)d\omega$,$p(direction)$为假定对光源直接采样的概率密度函数
$$
p(direction)*\frac{d A * \cos \alpha}{|p q|^{2}}=\frac{dA}{A}\
\rightarrow p(direction)=\frac{|p q|^{2}}{Acos\alpha}
$$

Unreal学习开发(二)

动态多播代理

例子1

1
2
3
4
5
6
DECLARE_DYNAMIC_MULTICAST_DELEGATE_SixParams(FOnHealthChangedSignature, USHealthComponent*, OwningHealthComp,
float, Health, float, HealthDelta, const class UDamageType*, DamageType, class AController*, InstigatedBy, AActor*, DamageCauser);//1.宏声明一个自定义delegate类型
FOnHealthChangedSignature OnHealthChanged;//2.create a instance in class
HealthComp->OnHealthChanged.AddDynamic(this, &ASCharacter::OnHealthChanged);//3.增加动态代理,一旦broadcast,执行ASCharacter::OnHealthChanged中的函数。
OnHealthChanged.Broadcast(this, Health, Damage, DamageType, InstigatedBy, DamageCauser);//4.触发代理Broadcast
FOnHealthChangedSignature OnHealthChanged;

例子2

Actor自带的代理(OnTakeAnyDamage

Called when the actor is damaged in any way.

1
2
3
4
DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_NineParams( FTakePointDamageSignature, AActor, OnTakePointDamage, AActor*, DamagedActor, float, Damage, class AController*, InstigatedBy, FVector, HitLocation, class UPrimitiveComponent*, FHitComponent, FName, BoneName, FVector, ShotFromDirection, const class UDamageType*, DamageType, AActor*, DamageCauser );//1.
FTakeAnyDamageSignature OnTakeAnyDamage;//2.
MyOwner->OnTakeAnyDamage.AddDynamic(this, &USHealthComponent::HandleTakeAnyDamage);//3.
OnTakePointDamage.Broadcast(this, ActualDamage, EventInstigator, PointDamageEvent->HitInfo.ImpactPoint, PointDamageEvent->HitInfo.Component.Get(), PointDamageEvent->HitInfo.BoneName, PointDamageEvent->ShotDirection, DamageTypeCDO, DamageCauser);//4.Broadcast

Unreal学习开发(一)

Actor

An Actor is any object that can be placed into a level, such as a Camera, static mesh, or player start location. Actors support 3D transformations such as translation, rotation, and scaling. They can be created (spawned) and destroyed through gameplay code (C++ or Blueprints).

In C++, AActor is the base class of all Actors

Each actor has a instigator, in new version it is private so ues GetInstigator() to get it .

Delegates

Data types that reference and execute member functions on C++ Objects.

Pawn

Pawn是可作为世界场景中”代理”的Actor。Pawn可被控制器所有,

    • AAIController

Character

PlayerInputComponent

Character basic control animation

Controller

  • AController
    • PlayerController
    • AAIController

Weapon class

Add damage to a target dummy

  • TSubclassOf

    1
    2
    3
    /** type of damage */
    UPROPERTY(EditDefaultsOnly, Category=Damage)
    TSubclassOf<UDamageType> DamageType;

    Let designer choose demage type.

  • Spawn an actor in world.

1
GetWorld()->SpawnActor<AActor>(ProjectileClass);

Weapon to Character need to set owner.

TPSCamera

1
CameraComp->SetFieldOfView(FOV);

terminology

OKR: Objective and key results

Muzzle: 枪口

Replicated:同步给服务端

定义component 起始字母为U(Uobject),Actor 为A(Actor)

Black Magic

UE_4.26\Engine\Binaries\Win64 下UnrealHeaderTool.target

TypeName 行尾加一个空格。

可以加快编译速度。

UE4 定义属性修饰符总结

UE4C++定义属性修饰符总结 - 烤肉酱 - 博客园 (cnblogs.com)

Reference

虚幻引擎4文档 | 虚幻引擎文档 (unrealengine.com)

Unreal Engine 4 Mastery

C++ 重复引用符号 问题 Inline keyword

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// h.hpp
#ifndef _H_HPP
#define _H_HPP

void h()
{
...
}

#endif

-----------------------------------------------------

// a.cpp

#include "h.hpp"

int main()
{
h();
return 0;
}

-----------------------------------------------------

// b.cpp

#include "h.hpp"

void b()
{
h();
}

执行下面的编译语句:

1
g++ a.cpp b.cpp -o main

通过inline 或者 static 来解决在编译过程中产生相同符合的问题。

使用static,最终会产生两个不同的函数符号

使用inline 被 include 进多个编译单元的 h 函数,在多个编译单元中分别编译,得到了多个副本;在链接的时候,链接器随便选取其中的一个副本保留,其余的被丢弃。

从图片上重新采样曲线

最近一直有一个需求是从已知连续曲线上取点重新resample,这个虽然不难实现,但是标点转换点坐标很是麻烦,所以我找了下市面的软件,看有没有工具可以帮助实现这个。OriginPro是具有这个功能的,打开它的Digitizer 就可以进行操作。

界面如下

origindigitizer

OriginPro tools=> Digitizer

import image

manully pick points

Results => go to data && go to image

之后我觉得可以实现一个简单的网页版,可以用起来方便一些。

切连科夫辐射

切连科夫辐射

介质中运动的电荷速度超过该介质中光速时发出的一种以短波长为主的电磁辐射,其特征是蓝色辉光。

虽然根据狭义相对论,具有静质量的物体运动速度不可能超过真空中的光速c,但光在介质中的传播速度(相速度)是小于c的,例如在水中(折射率n≈1.33)光仅以0.75c的相速度在传播,故物体可以被加速到超过介电质中的光相速,加速的来源可以是核反应或者是粒子加速器。当带电粒子以超过介质中的光速穿过介质时,会发出切连科夫辐射。

cargo,rust基础笔记0

cargo

1
2
3
4
5
cargo new "project_name"
cargo build
cargo run
cargo test
cargo build --release
  • std::rc reference counted
  • std::cell::RefCell
1
2
3
4
5
6
7
use std::rc::Rc;
let my_rc = Rc::new(());
Rc::downgrade(&my_rc);

let foo = Rc::new(vec![1.0,2.0,3.0]);
let a = foo.clone();
let b = Rc::clone(&foo);

Borrowing

1
2
3
4
5
6
7
8
9
10
11
fn foo(v1: &Vec<i32>, v2: &Vec<i32>) -> i32 {
// do stuff with v1 and v2

// return the answer
42
}

let v1 = vec![1, 2, 3];
let v2 = vec![1, 2, 3];

let answer = foo(&v1, &v2);

Rules about borrowing in Rust

  1. any borrow must last for a scope no greater than that of the owner
  2. you may have one or the other of these two kinds of borrows, but not both at the same time
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
enum Coin {
Penny,
Nickel,
Dime,
Quarter,
}
fn value_in_cents(coin: Coin) -> u8 {
match coin {
Coin::Penny => {
println!("Lucky penny!");
1
},
Coin::Nickel => 5,
Coin::Dime => 10,
Coin::Quarter => 25,
}
}
1
2
3
4
5
6
7
8
9
10
fn plus_one(x: Option<i32>) -> Option<i32> {
match x {
None => None,
Some(i) => Some(i + 1),
}
}

let five = Some(5);
let six = plus_one(five);
let none = plus_one(None);
if let 简单控制流
1
2
3
4
5
6
7
8
9
10
11
12
13
14
let some_u8_value = Some(0u8);
match some_u8_value {
Some(3) => println!("three"),
_ => (),
}
if let Some(3) = some_u8_value {
println!("three");
}
let mut count = 0;
if let Coin::Quarter(state) = coin {
println!("State quarter from {:?}!", state);
} else {
count += 1;
}

使用pub来使得mod、结构体、函数共有。

使用super来调用父模块的东西

1
2
3
4
5
6
7
8
9
10
fn serve_order() {}

mod back_of_house {
fn fix_incorrect_order() {
cook_order();
super::serve_order();
}

fn cook_order() {}
}
使用struct 来定义结构体成员变量,使用impl来定义结构方法
使用trait关键字定义一个接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
trait Area{
fn area(&self) -> f64;
}

struct Circle{
r : f64;
}
impl Area for Circle{
fn area(&self) -> f64{
(3.14 * self.r)
}
}
fn main(){
let r = Circle{r :10.5};
println!("area={:?}",r.area());
}

std::include

1
2
3
4
let my_string = include!("monkeys.in");
mod math{
include!("math.rs");
}

mod math;

泛型数据类型

git设置socks5代理

1
2
git config --global https.proxy 'socks5://127.0.0.1:2080'
git config --global http.proxy 'socks5://127.0.0.1:2080'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
set http_proxy=http://127.0.0.1:2080

set https_proxy=http://127.0.0.1:2080

set http_proxy_user=user
set http_proxy_pass=pass

set https_proxy_user=user
set https_proxy_pass=pass

# 恢复
set http_proxy=

set https_proxy=

# Ubuntu 下命令为 export
# export http_proxy=http://127.0.0.1:1080

Linux解决multiple Definition的链接错误

当我们在跨平台开发的时候,windows上的版本通常使用visual studio 进行编译,但是到了linux环境下却发现会出现multiple-definition的问题。

先分析下从源码编译到可执行文件的过程:

  1. 预处理将伪指令(宏定义、条件编译、引用头文件)特殊符号进行处理
  2. 编译过程通过词法分析、语法分析生成汇编代码,此步还会进行优化
  3. 汇编过程将汇编代码翻译为目标机器指令的过程(.o 文件 包含代码段和数据段)
  4. 链接程序将所有需要用到的目标代码(变量函数、其他库文件)装配到一个整体(可分为静态链接和动态链接)

前三个步骤为编译过程,第四个为链接过程

我们这个链接失败的原因就是,C语言规定 一个变量可以多次声明但只能定义一次,所以每个头文件需要加宏定义的条件编译,但c++中链接错误同样会发生 原因为ifndef 作用域仅在单个文件,所以还是会出现重复定义的错误。
在Windows环境中,链接器-》命令行-》添加/force 即可。

在Linux环境中,最简单的解决方法就是编译命令加上以下

1
-Wl,--allow-multiple-definition

Example:

1
g++ -fopenmp -o Multiblock3d testSinglePhaseRender.o simpleBlock3d.o string_extra.o propagate.o Ocblock.o objLoader.o obj_parser.o mlStreamGpu.o mlCuRunTime.o mlCollideGpu.o mlCalMacroGpu.o mlBndConditionGpu.o list.o geometry3D.o colorramp.o -lcudart -L/usr/local/cuda/lib64 -Wl,--allow-multiple-definition

原文地址:https://www.cnblogs.com/edwardcmh/archive/2013/06/09/3129364.html