vault backup: 2023-12-08 12:34:00

This commit is contained in:
2023-12-08 12:34:00 +08:00
parent 957bf258b1
commit a5d1766f77
23 changed files with 59 additions and 0 deletions

View File

@@ -0,0 +1,408 @@
# VRM4U角色
https://hub.vroid.com/en/users/36144806
B站整理 https://www.bilibili.com/video/BV1gR4y1j7sK/?spm_id_from=333.788.recommend_more_video.2&vd_source=d47c0bb42f9c72fd7d74562185cee290
- Alicia Solidhttps://hub.vroid.com/en/characters/515144657245174640/models/6438391937465666012
- AvatarSample_Fhttps://hub.vroid.com/en/characters/6193066630030526355/models/537531113514541613
# VRM4U学习笔记
VRM4U是一个不错的插件在此记录一下功能与大致实现方式。
快速入门文档https://ruyo.github.io/VRM4U/01_quick-start/
功能介绍视频https://youtu.be/epcQ-uU6tfU
视频中的右上角的自定义编辑器可以通过搜索"WBP_"来找到对应的EditorUtilityWidget之后在Asset上有右键——点击运行EditorUtilityWidget。
- VRm4U定义了主要的VrmAssetListObject、VrmMetaObject、VrmLicenseObject、VrmRuntimeSettings以及若干组件与动画节点。
- VRM4UImporter主要的导入相关逻辑实现导入流程、导入设定窗口、若干动画节点。
- VRM4ULoader导入数据转换以及生成逻辑数据转换与生成Asset相关的类、UVrmLoaderComponent与若干组件实现。
- VRM4UEditorSequence编辑器函数EvaluateCurvesFromSequence()实现。
- VRM4UMiscLog日志类型定义。
PS.
- FVRM4UModule模块启动与结束时会分别注册/卸载
- FVRM4UImporterModule模块启动与结束时会分别注册/卸载 UVrmAssetListObject、UVrmLicenseObject、UVrmMetaObject自定义Asset类型与FVRMRetargetSrcAnimSequenceCustomization自定义属性编辑器。
- FVRM4ULoaderModule模块启动与结束时加载/卸载assimp的动态链接库如果勾选**Drop VRMFile Enable**,则会
## VRM4U的格式导入功能
值得学习:
- Runtime Import功能在游戏打包后依然可以通过拖拽文件到游戏窗口的方式来导入VRM文件。
- 导入窗口实现实现一个导入窗口SVrmOptionWindow这样Runtime与Editor导入都可以输入自定义的参数。
待改进:
- 没有实现VMD的导入逻辑虽然实现了BVH格式的导入逻辑
### 导入功能
VRM4U使用Assimp库来进行格式解析并且通过修改GLTF来实现VRM格式导入VRM是基于GLTF开发的。插件作者也公开了魔改的Assimp代码当然最好的方式就是下载编译好的库文件与h文件直接引用了。
得益于Assimp所以也可以导入PMX格式但需要勾选 Project Setting>Plugin>VRM4U>Allow All AassImp Format的选项之后就可以导入PMX格式的模型。开放格式pmx、obj、fbx、dae、gltf
![](https://ruyo.github.io/VRM4U/assets/images/small/04i_option.png)
同时可以通过下面的Ext List来添加其他格式的后缀名来使用VRM4U导入。
主要逻辑位于VRM4UImporter模块的UVRM4UImporterFactory中。
#### FactoryCreateBinary
UVrmImportUI用于存储用户设置的导入选项数据。ULoaderBPFunctionLibrary::GetVRMMeta()用来导入VRM的Meta数据。ULoaderBPFunctionLibrary::LoadVRMFileFromMemory()为核心导入逻辑。
导入流程为:
1. 在初始化UVrmImportUI导入选项对象会调用ULoaderBPFunctionLibrary::GetVRMMeta(),通过Assimp读取VRM文件的Meta数据缩略图与版权信息来填充UVrmImportUI。对于PMX格式会有额外的设置。模型缩放1=>0.1、不合并材质、不合并图元、强制材质双面显示)
2. 取得父窗口之后创建并添加自定义的SWindow2包裹SVrmOptionWindow来进行导入参数显示会在用户选择好数据后进行之后的步骤。
3. 创建`TAssetPtr<UVrmAssetListObject>``TArray< TAssetPtr<UObject> >``TAssetPtr<UClass>`对象。
4. 取得默认加载设置对象UVrmRuntimeSettings之后会依次尝试载入VrmObjectListBP、VrmAssetListObjectBP、UVrmAssetListObject来初始化上一步说的`TAssetPtr<UVrmAssetListObject>`
5. 创建static VRMConverter::Options并使用之前的用户修改过的设置选项进行初始化。
6. 使用上一步取得选项对象并调用ULoaderBPFunctionLibrary::LoadVRMFileLocal()来导入文件。导入的存放在UVrmAssetListObject mret中。
7. 返回mret->GetOuter();
#### LoadVRMFileFromMemory
1. 根据后缀名设置对应参数
2. 调用Assimp::Importer的ReadFileFromMemory()或者ReadFile()读取文件来获取场景节点aiScene。
3. 创建UVrmAssetListObject* OutVrmAsset复制InVrmAsset或NewObject
4. 使用VRMConverter对象取出VRM的Json与aiScene数据来以此初始化。之后更新OutVrmAsset里的数据调整材质的AlphaCutoff选项、替换骨骼名称、转换并且生成贴图与材质、转换VRM的Meta数据、转换并且生成模型数据、重命名Meta数据、设置骨骼模型的Rig Pose MorphTarget、转换重定向用的Humanoid、将之前所有数据保存成Asset
#### 运行时导入
主要的逻辑为调用LoadVRMFileAsync()加载文件并且初始化UVRMAssetList之后再设置SkeletalMesh或者SpawnActor等一系列设置。
使用这个功能前首先得确定 Project Settings->Plugin->VRM4U->Drop VRMFile Enable处于勾选状态才能使用这个功能。
功能演示可以查看参考插件Content的Maps/VRM4U_runtimeload其功能位于DropActor。其挂载了UVrmDropFilesComponent组件并在Beginplay绑定UVrmDropFilesComponent组件的OnDrogFile委托。其绑定的LoadVrmFronFilePath事件主要逻辑为创建VRMAssetList对象之后调用LoadVRMFileAsync()加载文件。之后给SpawnMToonActor并给骨骼物体设置动画。还有一些逻辑在关卡蓝图中
UVrmDropFilesComponent的主要功能
它定义了2个委托并会在组件注册/卸载时让StaticOnDropFilesDelegate绑定/解绑OnDropFilesDelegate_Handler()。OnDropFilesDelegate_Handler()会调用OnDropFiles.Broadcast(FileName);
```c++
DECLARE_MULTICAST_DELEGATE_OneParam(FStaticOnDropFiles, FString);
static FStaticOnDropFiles StaticOnDropFilesDelegate;
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnDropFiles, FString, FileName);
UPROPERTY(BlueprintAssignable)
FOnDropFiles OnDropFiles;
```
UVrmDropFilesComponent::VRMGetOpenFileName()会在关卡蓝图中被调用用于调用Winapi的GetOpenFileName()来显示一个打开文件用的窗口在选取了文件之后会调用DropActor的LoadVrmFronFilePath()。
##### 运行时拖拽导入
FDropMessageHandler的父类为IWindowsMessageHandler是一种用与处理Windows消息的一种接口类。FDropMessageHandler的主要逻辑为
1. 取得UVrmDropFilesComponent组件与World指针。
2. 如果世界类型为Game与PIE则调用Winapi的DragAcceptFiles()
3. 调用Winapi的DragQueryFile()查询拖拽入的文件,并将文件地址传**UVrmDropFilesComponent::StaticOnDropFilesDelegate.Broadcast(Filepath);**
在FVRM4ULoaderModule::StartupModule()中执行增加MessageHandler。
```c++
if (FSlateApplication::IsInitialized()) {
static FDropMessageHandler DropMessageHandler;// = FDropMessageHandler();
//FWindowsApplication* WindowsApplication = (FWindowsApplication*)GenericApplication.Get();
TSharedPtr<GenericApplication> App = FSlateApplication::Get().GetPlatformApplication();
if (App.IsValid()) {
auto WindowsApplication = (FWindowsApplication*)(App.Get());
//WindowsApplication->SetMessageHandler(DropMessageHandler);
WindowsApplication->AddMessageHandler(DropMessageHandler);
}
}
```
## 渲染与材质
值得学习:
- 卡通渲染材质里面有一些faker技巧
- 拍摄模式
- Over Parse模型压平的二次元模式视角矫正效果
VRM4U的MToon Lit、MToon Unlit、Subsurface、Subsurface Profile材质类型都是基于MaterialUtil\MToonUtil\M_VrmMToonBaseOpaque它是作者实现的一个接近UniVRM Shader效果的材质。里面有一些Hack技巧值得学习。上述这几材质类型的区别在于材质实例的属性不同以MToon Lit与MToon Unlit的区别为例
1. bUseLight是否勾选
2. ShaderModel不同Default Lit与Unlit
Unlit、PBR基于一个简单材质MaterialUtil\MToonUtil\M_VrmSimple。
### 轮廓线与投射阴影
使用MToonAttachActor来应用轮廓线和自身阴影Unlit ShaderModel不会接收其他物体的投影。自己制作的VRM模型可能会有问题导致Outline与阴影不能出现建议使用Vroid官方模型进行测试。
![](https://cdn.jsdelivr.net/gh/blueroseslol/ImageBag@latest/ImageBag/Images/VRM4U_MToonAttachActor.png)
- SceneCaptureComponent2D组件用于渲染Depth到RT上以此来制作Shadow。勾选WBP_VRMMaterial->Model->MToonAttachActor->Advanced->Debug Shadow Cube后会在角色正上方显示深度贴图Cube。
![](https://cdn.jsdelivr.net/gh/blueroseslol/ImageBag@latest/ImageBag/Images/VRM4U_ShowDebugShadowCube.png)
在MF_VrmMToonBase中搜索bUseShadowMap就可以找到所引用的计算函数
![](https://cdn.jsdelivr.net/gh/blueroseslol/ImageBag@latest/ImageBag/Images/VRM4U_bUseShadowMap.png)
里面逻辑就是通过Depth贴图计算ShadowMask
![](https://cdn.jsdelivr.net/gh/blueroseslol/ImageBag@latest/ImageBag/Images/VRM4U_ShadowMask.png)
- UVrmPoseableMeshComponent用于实现OutlineAOShadow目前没有作用。主要使用M_VrmNone一个Masked Unlit材质通过模型外扩实现Outline效果。
### 后处理效果
MToonMaterialSystem
![](https://cdn.jsdelivr.net/gh/blueroseslol/ImageBag@latest/ImageBag/Images/VRM4U_PostProcessSystem.png)
这些蓝图BP的大致逻辑为挂载带有PostProcess空间组件的BP之后往里面添加PostProcess材质。
Content\Util\Actor\Post\sub目录中有
- M_PostBloom
- M_ColorGradation
- MI_ColorGradation
- M_CenterBlur
### 光照工具与PostToon
- VRM4U_CameraLight有演示CharacterLightRigActor方便用户快速摆出主光、轮廓光其中轮廓光会一直对着摄像机旋转。
VRM4U有关的曝光的参数调节技巧https://ruyo.github.io/VRM4U/02_envlight/
- PostToonSystem文档https://ruyo.github.io/VRM4U/02_toon/
具体可以参考VRM4U_PostToon.umap设置步骤如下
1. 在场景中放置一个SkeletalMeshActor。
2. 在场景中放置一个BP_PoseCopyToon并且设置Target Actor为上一步放置的SkeletalMeshActor并调整参数。
#### PostToon原理
首先BP_PoseCopyToon挂载了5个组件隐藏了2个非重要组件SkeletalMesh为主要渲染VrmPoseableMesh用于接受光照。
- SkeletalMesh
- VrmPoseableMesh
- VrmPoseableMesh_translucent
1. 设置TargetMeshForLightSkeletalMesh或者VrmPoseableMesh
2. BP_PoseCopyToon会在一开始遍历TargetMeshForLight的Materials之后根据材质数目给VrmPoseableMesh添加对应数目的MI_BaseLight材质。M_BaseLight与MToon材质大致一样都使用MF_VrmMToonBase
3. 给VrmPoseableMesh_translucent执行上一步类似操作但添加的材质为MI_PostToon。
4. 如果SkeletalMesh中有使用M_VrmNone材质那VrmPoseableMesh与VrmPoseableMesh_translucent的对应部分也会被设置成M_VrmNone。
5. 隐藏Debug用的VrmPoseableMesh_translucent。
6. 调用VrmPoseableMesh的VRMSetLightingChannelPrim()。设置了图元的LightingChannel。
7. 调用VrmPoseableMesh_translucent的VRMSetPerBoneMotionBlur()。设置SkinnedMesh->bPerBoneMotionBlur默认是true。
![](https://cdn.jsdelivr.net/gh/blueroseslol/ImageBag@latest/ImageBag/Images/VRM4U_ToonPost.gif)
##### M_VrmMToonBaseOpaque、M_BaseLight、M_PostToon比较
- M_BaseLight有基础灯光计算NoL。**实际使用的是MI_BaseLight**所以会有一些参数改变比如他是一个PBR材质有调整过BaseColor、Metalic、Roughness。
- M_ToonPost
- M_VrmMToonBaseOpaque实现了TAA透明效果
M_VrmMToonBaseOpaque
![](https://cdn.jsdelivr.net/gh/blueroseslol/ImageBag@latest/ImageBag/Images/VRM4U_M_VrmMToonBaseOpaque.png)
M_BaseLight用于渲染光照效果
![](https://cdn.jsdelivr.net/gh/blueroseslol/ImageBag@latest/ImageBag/Images/VRM4U_M_BaseLight.png)
M_ToonPost用于取得光照效果并且合成在一起。使用SceneColor节点取得上一个Material渲染的结果作为灯光结果因为是透明材质所以是在后面渲染的
![](https://cdn.jsdelivr.net/gh/blueroseslol/ImageBag@latest/ImageBag/Images/VRM4U_M_ToonPost.png)
#### 使用Custom Material
VRM4U可以使用自定义的材质系统代替MToon材质。
1. 根据M_VrmSimple的格式创建自己的CustomMaterial。
2. 创建DS_VRMCustom DataAsset并且填入对应的Custom Material Instance改变Shader Model与Blend Mode
3. 在操作面板WBP_VRMMaterial的MaterialSettings上将材质模型设置成Custom并且填入上面创建的DS_VRMCustom DataAsset。
![](https://ruyo.github.io/VRM4U/assets/images/02d_custom1.png)
![](https://ruyo.github.io/VRM4U/assets/images/02d_custom2.png)
### 其他Hack技巧
- Anti-ToneMapping使用UE自带的函数抵消ToneMapping效果。
- Exposure使用EyeAdaptation节点控制亮度。
![image](D:/youdaonote-pull-master/youdaonote/youdaonote-images/8B1F13475DF3420E9F90FD29A1A0D7B4.octet-stream)
### 拍摄模式
1. 使用BP_VrmModelActor。
2. 视线跟踪 /VRM4U/Util/Actor/Misc/LookAtPoint放置TargetActor并设置目标模型。
3. VRM4U的角色相机使用Pawn类实现提供若干快捷操作方便用户得到最佳的镜头。https://ruyo.github.io/VRM4U/02_shortcut2/
4. 使用MToonMaterialSystem调整阴影效果。
5. 使用MorphControl控制角色表情目标设置为BP_VrmModelActor
### Over Parse
文档https://ruyo.github.io/VRM4U/02_pers/
![](https://ruyo.github.io/VRM4U/assets/images/small/02p_fix1.png)
![](https://ruyo.github.io/VRM4U/assets/images/small/02p_fix2.png)
![](https://ruyo.github.io/VRM4U/assets/images/small/02p_n2.png)
![](https://ruyo.github.io/VRM4U/assets/images/small/02p_n1.png)
![](https://ruyo.github.io/VRM4U/assets/images/small/02p_n3.png)
Actor位于Util\Actor\:
- FOVCharacter
- FOVCustom
FOVCustom使用了VrmCameraCheck组件并且会在蓝图的Construction Script中绑定SetFovDistance()至CameraMove委托。主要的逻辑位于SetFovDistance()中主要逻辑Tick()也会使用。
1. 将FOVCustom Attach 到 TargetActor上。
2. 寻找场景中所有MToonMaterialSystem并设置FovScaleBias、Fov_distance、Fov_scale参数并应用。
FOVCharacter逻辑相似核心逻辑在CustomEvent_1中他会绑定给VrmCameraCheck组件的CameraMove委托。主要设置了**材质集**的FOV2Begin、FOV2Pow、FOV2Scale、FOV2ScaleLimit、FOV2FarCenter、FOV2FarPoint、MainCameraPosition、MainCameraDirection。相关逻辑位于材质中。
![](https://cdn.jsdelivr.net/gh/blueroseslol/ImageBag@latest/ImageBag/Images/VRM4U_FovFix.png)
## 动画
值得学习:
- Runtime Retarget功能
- Limited Animation抽帧动画
- Control Rig与Morph Target控制器
实现动画节点:
- VRM4U
- AnimNode_VrmCopyHandBone
- AnimNode_VrmModifyBoneDynamic
- AnimNode_VrmModifyBoneList
- AnimNode_VrmModifyHumanoidBone
- AnimNode_VrmQuestHandBone
- AnimNode_VrmRetargetFromMannequin
- AnimNode_VrmSpringBone
- AnimNode_VrmVMC
- VRM4UImporter
- AnimGraphNode_VrmCopyHandBone
- AnimGraphNode_VrmModifyBoneDynamic
- AnimGraphNode_VrmModifyBoneList
- AnimGraphNode_VrmModifyHumanoidBone
- AnimGraphNode_VrmQuestHandBone
- AnimGraphNode_VrmRetargetFromMannequin
- AnimGraphNode_VrmSpringBone
- AnimGraphNode_VrmVMC
### BP_VrmPoseCopy
挂载了以下5个组件有一个子类BP_VrmPoseCopy_PostShadow。
- VrmPoseableMesh
- BP_VrmAnimControlComponent
- BP_VrmUtilComponent
- SkeletalMesh
有关抽帧效果其关键函数在于BP_VrmAnimControlComponent或者BP_VrmPoseCopy的SetFrameLimite(),函数是一个无线循环函数。
1. 判断是否开启EnableFrameLimit不开启就结束了
2. SetFrameLimite()中判断当前播放帧数是否达到nextToPlay变量的值如果没有则等待有则执行VrmPoseableMesh的VRMCopyPoseAndMorphFromSkeletalComponent()
3. 更新nextToPlay变量并触发OnFrameLimitUpdate委托。
4. 在更新完模型的Transform后跳回第2步。
**改进思路**在蓝图中这样实现会有很大的性能问题使用c++会更好。而且这个逻辑完全可以使用动画蓝图实现使用PoseCache之后根据条件输出更新Pose或是PoseCache。
UVrmPoseableMeshComponent继承自UPoseableMeshComponent。
```c++
void UVrmPoseableMeshComponent::VRMCopyPoseAndMorphFromSkeletalComponent(USkeletalMeshComponent* InComponentToCopy) {
if (InComponentToCopy) {
Super::CopyPoseFromSkeletalComponent(InComponentToCopy);
MorphTargetWeights = InComponentToCopy->MorphTargetWeights;
ActiveMorphTargets = InComponentToCopy->ActiveMorphTargets;
}
}
```
CopyPoseFromSkeletalComponent()的主要逻辑就是判断骨骼是否一一对应如果对应则使用移动构造函数对Target与Source骨骼数据进行交换不对应就遍历复制骨骼数据。
#### Limited Animation 抽帧效果
文档地址https://ruyo.github.io/VRM4U/05_limitedanim/
使用步骤
1. 在关卡上放置一个执行通常动画的骨架模型Actor。设置为“始终勾选姿势并刷新骨骼”以将动画移动到屏幕之外。
2. 在关卡中放置一个BP_VrmPoseCopy Actor并TargetActor设置为上一步中的骨骼模型。打开LimitedAnim输入你要播放的帧率12、24等每秒的帧数
#### 运行时重定向
文档https://ruyo.github.io/VRM4U/03_gray/
视频UE5的实时重定向方案https://www.bilibili.com/video/BV1HZ4y117Yk?spm_id_from=333.999.0.0
视频中的步骤:
1. 给新导入的VRM4U模型添加重定向骨骼链数据。
2. 新建IK Rig Asset并选择IK_Mannequin。假设使用UE5小蓝人来重定向
3. 新建IK Retarget Asset设置Source为IK_Mannequin的RigTarget为上一步新建的Rig。
4. 修改TPose=>APose。
5. 在角色类中的Mesh下面新建一个SkeletalMesh组件并且选择新导入的VRM4U模型。创建一个动画蓝图Asset并指定我感觉并不需要挂载新创建的SkeletalMesh
6. 动画蓝图中使用RetargetPoseFromMesh节点。
7. 将角色类中Mesh的VisibilityBasedAnimTickOption属性改为AlwaysTickPose=>AlwaysTickPoseAndRefreshBones。
8. 隐藏新建的SkeletalMesh组件。
VRM4U的实时重定向步骤
1. 将BP_VrmMannequinRetarget放入场景中之后设置Targetmannequin。
2. 设置VRM Asset List Override。
3. 最后点击GenerateRegargetPoseCopy即可。
![](https://ruyo.github.io/VRM4U/assets/images/small/03r_setM1.png)
BP_VrmMannequinRetarget使用了动画蓝图ABP_VRoidSimpleMannequinRetarget里面使用了VrmRetargetFromMannequin节点。大致逻辑就是遍历所有的骨骼humanoid_bone之后进行重定向。本质上与UE5的方法一样但UE5使用最新的骨骼链算法无论是便捷与效果都更胜一筹。
## 其他工具与实现
- 面部捕捉
- VirtualMotionCapture(VMC) 身体捕捉 https://ruyo.github.io/VRM4U/08_vmc/
VMC入门资料
1. UE VR Track介绍视频中使用了SteamVR控制器手柄https://www.bilibili.com/video/BV1kS4y167SK?spm_id_from=333.337.search-card.all.click
2. UE VRN4U VMC功能讲解https://www.bilibili.com/video/BV1ub4y1Y74K?spm_id_from=333.337.search-card.all.click
3. 捕捉数据软件介绍Up推荐VseeFace免费、效果好https://www.bilibili.com/video/BV1DK411u75k?spm_id_from=333.999.0.0
4. Vseeface和OBS的设置https://www.bilibili.com/video/BV16K4y1H7Cb?spm_id_from=333.999.0.0
5. VSeeFace配合LeapMotionhttps://www.bilibili.com/video/BV1KA41137os?spm_id_from=333.337.search-card.all.click
6. 全身动作捕捉软件ThreeDPoseTrackerhttps://www.bilibili.com/video/BV1vy4y157An?spm_id_from=333.999.0.0
## 其他模块文件
- VRM4U
- VrmUtil导入选项、GetXXX工具函数、骨骼转换映射表
- VrmUtilImage图片处理函数
- VRM4UImporter
- VRM4UDetailCustomize针对FVRMRetargetSrcAnimSequence的自定义编辑器
- VrmAssetListThumbnailRendererAsset缩略图渲染控制
Util中的工具
Actor
- latest作者研发用的文件夹里面的东西会引起打包出问题建议在打包的时候删掉。
# VRM4U 功能列表翻译
- Asset输出支持日语名称
- 显示许可证与文件的Meta信息
- bvh 支持
## 骨骼动画
- MorphControlActor。支持VRoid模型的Morph Target并且名称与原始数据相同
- 视线跟随Actor
- 增加动画节点VRMSpringBone
- 默认重定向是 A-pose。启用以更改为常规 T 姿势作为选项
- 增加套用ALS功能添加IKBone复制VirtualBone创建骨骼名称为UE4 Mannequin
- 可以从其他骨骼Asset上复制Socket
- 实现了 WindActor
- LiveLink 面部捕捉支持
- 角色相机添加了呼吸选项、更改角色相机的焦点位置功能。
- 对应ControlRig不能很好应用的模型PMX中骨骼层次不同的模型使用半标准骨骼的模型
- 添加了一个工具来控制Sequence中的面部动画
## MToon材质
默认材质设置为 Unlit除此之外还是先PBR与SSS模式。
- 实现 MPC 材质集来调整材质参数
- 自己实现ShaderMap以实现Unlit材质模型的投射阴影;可以设置第二个阴影颜色;修复可能无法绘制阴影的问题没有MaterialSystem可以正常绘制阴影
- EyeAdaptation (对轮廓线部分使用了特殊的眼部自适应调整)
- 实现 MatCap 上反射阴影
- RimLight
- UV Scroll
- 启用生成 AO 阴影模型
- MToonMaterialSystem 添加了 SSGI 切换选项
- 启用以引用 LightRig 中的 DirectionalLightComponent支持 SunSkyActor。通过定向光到 Light Rig 的俯仰角添加了亮度校正选项。
- 添加了一个参数来更改 FilmicTonemapper 逆变换的强度。从 MToonMaterialSystem 更改。
- PostShadow 新增卡通功能
-M MoonLit 会根据场景稍微变暗。我决定不参考 SkyLight 来减少负载。要回到过去,请从材质中打开 bUseSkyLightDirect。
- Rim light 和 matcap 不再受正常校正的影响
## VR相关
- 在AnimBP中增加MotionController 和 Leap Motion 跟踪
## 官方上的支持功能
您可以导入 VRM 文件
- 动画片
- 您可以轻松地重新定位。生成 A-pose / T-pose 和 BoneMap。
- 面部动画Morphtarget / BlendShapeGroup可用。
- 您可以为摆动骨骼选择 VRMSpringBone 或 PhysicsAsset。
- 有一个通用的控制装置和一个用于操作的 UMG。
- 您可以从外部应用程序接收动作捕捉数据。它支持 VMC 协议。
- 您可以在运行时从 UEMannequin 重定向到 VRM 模型。
- UE5可以自动生成 IKRetargeter 资产。您可以从 Epic Skeleton 简化重定向过程。
- 材料
- 再现 M Moon 的素材。阴影颜色规格、轮廓颜色/粗细调整、MatCap 等都适用。
- 您可以根据 PBR 背景切换和调整绘图模式。
- 现有的后置滤镜和光线追踪可以同时使用。
- 移动的
- 配合BoneMap缩减功能不用担心骨骼数量即可显示。
- 您可以切换绘图质量。它支持低规格。
- 虚拟现实/增强现实
- 绘图同时支持 Forward / Deferred。
- 由于它是由简单的函数组成的,所以它不会崩溃。
- 运行时负载
- 任何用户的 VRM 文件都可以从打包的 EXE 文件中读取。
- 动画可以在运行时重新定位。
- UE兼容性好
- 导入后,它将是一个标准的骨架网格体资源。
- 对应的UE版本是4.20~4.275.0截至2022/04很容易支持最新版本。
- 依次支持VRM1.0β
- VRM1.0数据在一定程度上可以导入。
- 您可以保留本地轴或在导入时选择它。
- 对应M Moon的新功能。
- 实验实现

View File

@@ -0,0 +1,235 @@
# Assimp入门
https://assimp-docs.readthedocs.io/en/latest/about/introduction.html
# 其他卡通渲染推主
https://twitter.com/rukikuri
# VRoid商城地址
https://booth.pm/zh-cn
# VRM格式地址
https://vrm.dev/
## Unity3d导入插件
导入https://github.com/vrm-c/UniVRM/releases
导出Fbx插件https://github.com/KellanHiggins/UnityFBXExporter
# VRM4U
https://github.com/ruyo/UnrealEngine_VRM4UPlugin
https://github.com/ruyo/VRM4U
## 渲染参考
原文(上/下):
https://qiita.com/ruyo/items/ec082d81dea3033e1500
https://qiita.com/ruyo/items/71a3f2f694d2853b3f1e
光照:
https://qiita.com/ruyo/items/28255f26725a6b6bd475
### 其他参考
MToonhttps://dwango.github.io/vrm/univrm/shaders/mtoon/
Ue4中的卡通渲染https://qiita.com/com04/items/a7895160df8d854fe924
## 曝光与ToneMapper问题解决
ToneMapper与曝光会影响贴图的亮度所以需要尝试干掉或者抵消掉他们的影响。
![image](D:/youdaonote-pull-master/youdaonote/youdaonote-images/1DC2666D4C03467FA93C5A3B160DF5B8.octet-stream)
![image](D:/youdaonote-pull-master/youdaonote/youdaonote-images/8B1F13475DF3420E9F90FD29A1A0D7B4.octet-stream)
手动去除了Gammer矫正以及ToneMapper取消并且使用 人眼适应节点抵消曝光效果。
除此之外还使用RayTracingQualitySwitchReplace节点与人眼适应节点做了Raytracing质量调整。手机端为1
## 阴影
![image](D:/youdaonote-pull-master/youdaonote/youdaonote-images/093F34C991EB4A9E8F024D6D5E156BEB.octet-stream)
使用了SceneCaptureComponent2D。
在Orthographic平行投影*将CaptureSource设置为 "SceneDepth in R"TexrureTarget格式设置为 "RTF R32f"。
这将导致深度在UnrealUnit中线性地写入缓冲区默认为1=1cm。 别紧张。
![image](D:/youdaonote-pull-master/youdaonote/youdaonote-images/9A6D0FAA881148ABBDB8CF64E5C9CB1D.octet-stream)
要用Shadowmap投出一个阴影你只需要知道从光线中看到的深度以及投影矩阵的矩阵。
我们会把这些东西找回来,传给材料。
https://www.shibuya24.info/entry/shadowmap
官方的SceneCaptureComponent2D会做很多无用的渲染工作推荐自己重新写一个以减少不必要的消耗。
### 蓝图传递逆矩阵
在蓝图中国计算出SceneCaptureComponent2D的逆矩阵后将其传入材质中。
![image](D:/youdaonote-pull-master/youdaonote/youdaonote-images/9DB8EE6F87D44F5BA8D4E2A68842A79F.octet-stream)
### 材质内
在一个自定义节点中将参数打包成float4x4并进行计算。
现在你可以从世界坐标中参考相应的影子图。
在材料函数中结果返回0-1。
![image](D:/youdaonote-pull-master/youdaonote/youdaonote-images/537BB41619BF456399438FE6D0974CE1.octet-stream)
## 描边
在具体节点方面,
投影结果 → TransformPosition节点转换为ViewSpace的转换结果
Pixel Thickness → VectorLength的值。
乘以倒数→部分除以VectorLength的值再乘以反数→部分除以VectorLength的值。
使用ScreenResolusion的原因是为了确保不影响窗口大小和宽高比。
我不确定我是否准备好了......
在MToon再现方面我们需要能够选择 "恒定厚度模式 "和 "世界坐标参考模式"。
![image](D:/youdaonote-pull-master/youdaonote/youdaonote-images/545E0EC3BB5C47C089BC47504FA4B742.octet-stream)
http://historia.co.jp/archives/5587/
使用PoseableMeshComponent与CopyPoseFromSkeletalComponent函数实现外描边。到时候比对一下这个方法与我的重定义图元方法的效率。
## 轮廓光
使用MaterialCapture材质制作轮廓光。
## 光照模式
默认的MToon为无光照模式自定义光照效果
其余的工作将通过增加材料参数来体现数值。 我就不说了,因为这样做是多余的。 (我没有评论了...)
也可以应用ShadingShadingShift。
主源和GI可以通过在自定义节点中写出以下内容来获得。
如果你用GetSkySHDiffuseSimple或GetSkySHDiffuse搜索usf文件会有帮助。
不要忘了在最终输出的SkyLight(ResolvedView.SkyLightColor.rgb)中乘以颜色。
```
//主光源.usf
return ResolvedView.DirectionalLightColor;
```
```
//GIの影響.usf,然而这个是天光
#if SIMPLE_FORWARD_SHADING
float4 NormalVector = float4(Normal, 1);
float3 Intermediate0;
Intermediate0.x = dot(View.SkyIrradianceEnvironmentMap[0], NormalVector);
Intermediate0.y = dot(View.SkyIrradianceEnvironmentMap[1], NormalVector);
Intermediate0.z = dot(View.SkyIrradianceEnvironmentMap[2], NormalVector);
// max to not get negative colors
return max(0, Intermediate0) * ResolvedView.SkyLightColor.rgb;
#else
float4 NormalVector = float4(Normal, 1);
float3 Intermediate0, Intermediate1, Intermediate2;
Intermediate0.x = dot(View.SkyIrradianceEnvironmentMap[0], NormalVector);
Intermediate0.y = dot(View.SkyIrradianceEnvironmentMap[1], NormalVector);
Intermediate0.z = dot(View.SkyIrradianceEnvironmentMap[2], NormalVector);
float4 vB = NormalVector.xyzz * NormalVector.yzzx;
Intermediate1.x = dot(View.SkyIrradianceEnvironmentMap[3], vB);
Intermediate1.y = dot(View.SkyIrradianceEnvironmentMap[4], vB);
Intermediate1.z = dot(View.SkyIrradianceEnvironmentMap[5], vB);
float vC = NormalVector.x * NormalVector.x - NormalVector.y * NormalVector.y;
Intermediate2 = View.SkyIrradianceEnvironmentMap[6].xyz * vC;
// max to not get negative colors
return max(0, Intermediate0 + Intermediate1 + Intermediate2) * ResolvedView.SkyLightColor.rgb;
#endif
```
## 其他光照模型
## Runtime载入思路
```
NewObject<USkeletalMesh>()
SkeletalMesh->GetResourceForRendering()
->LODRenderData[0]
• StaticVertexBuffers
顶点信息。 最起码,这将填补。
• MultiSizeIndexContainer
- 绘图时的顶点信息。 如果你要运行时加载的话,也要埋下这一点。
- 从GameThread停止重写的成员从RenderThread重写。
• SkeletalMesh->GetImportedModel()->LODModels[0].Sections;
- 网格和材料信息。 我也要把这个埋了。
• SkeletalMesh->RegisterMorphTarget()
- 混合形状信息。 我也要把这个埋了。
- UE4的顶点权重为uint8所以有一个分数。 最后,正常化。
```
### VRMglTF转换时需要注意
改变坐标系。
- 转换为Z-up
- 转换比例尺为虚幻单位(x100)
- 支持多种根骨。
- 去除不必要的骨头
- 如果你不想移除的话可以添加一个假根骨root
字符与编码转换
### 物理资源导入
```
• bs = NewObject<USkeletalBodySetup>();
• ct = NewObject<UPhysicsConstraintTemplate>();
• physicsAsset->SkeletalBodySetups.Add(bs);
• physicsAsset->ConstraintSetup.Add(ct);
```
我想让我的骨头不至于发狂。
- 物理学变得很粗糙。 当碰撞被猛烈地掩埋时,就会引起注意。
- 增加计算次数,会在一定程度上改善它。
- 我想保持我想要的形状。
- 我的头发因为地心引力而垂下来。
- 可移动的范围可以指定,但移动不规范。 杂项:
VRMSpringBone是Unity的一个实现目前已经发布了VRMSpringBone。
- 理论上可以移植到UE4上。
- 源码VRMSpringBone.cs只有329行。
- 我不知道这样可以吗?
于是作者移植了VRMSpringBone。
我现在可以看VRM了。
- 你现在可以导入/运行时加载
- 我现在也能读出混合形状和碰撞了!
- 现在你可以重新创建VRMSpringBone
- 你现在可以干扰UE4的碰撞了。
StaticMesh的运行时加载也是可能的。
- 我可以创建一个自定义的摇摆骨质节点。
- 对于那些对PhysicalAsset和AnimDynamics节点的行为不满意的人。
- 你为什么不尝试着去做一个呢?
## 动画部分
要想导入动画,可以使用
- (一) 骨架通用化
- (二) 重新定位动画资产。
但两者都是编辑器功能无法在runtime中使用。
### 使用AnimBP实现运行时重定向
![image](D:/youdaonote-pull-master/youdaonote/youdaonote-images/E65AE6C12BF84F12B26B2D0E80FC1AF8.octet-stream)
将复制资产设置为AnimInstance你就可以走了。
复制源头网状物。
设置在编辑器中创建的AnimBP
要复制的网状物。
设置VrmAnimInstanceCopy
# IM4U
https://github.com/bm9/IM4U
https://github.com/bm9/UnrealEngine_IM4UPlugin
# Blender和pmx2fbx
# Muro_CG
使用Unity卡通着色的3D动画表达
https://qiita.com/MuRo_CG/items/c417ef6d6cbeed3dd42b
Unity トゥーンシェーディングを使ったDアニメ表現
https://qiita.com/MuRo_CG/items/c417ef6d6cbeed3dd42b
https://github.com/unity3d-jp/unitychan-crs
https://ja.whotwi.com/MuRo_CG/tweets/popular
https://togetter.com/li/1438719
# Unity_Japan
【Unite 2017 Tokyo】VR MAGIC キャラクターに命を吹き込んだこの4年間の記録
https://www.slideshare.net/Unite2017Tokyo/unite-2017-tokyovr-magic4
https://www.youtube.com/watch?v=N4_x9w7wNNY&feature=youtu.be
# 米哈游
http://www.uniteseoul.com/2018/download_files/T1_0503_2.pdf

View File

@@ -0,0 +1,83 @@
## 自定义Asset
https://zhuanlan.zhihu.com/p/77812246
- FAssetTypeActions_Base是对已经创建好的资源操作函数的封装。这个资源在内容浏览器中的颜色类型名字显示的缩略图。
- UFactory这个是创建自定义类型文件的入口。以及创建资源的二级菜单。
- UBlueprint: 创建继承类,来实现一个新的视图编辑窗口
- UXXXX : Public Object 这里面存储我们要编辑的数据
VRM中对应类为
- FAssetTypeActions_VrmAssetList、UVrmAssetListThumbnailRenderer
- UVRM4UImporterFactory
- UVrmAssetListObject
## Assimp
资源工厂类中UVRM4UImporterFactory::FactoryCreateBinary
```
{
const UVrmRuntimeSettings* Settings = GetDefault<UVrmRuntimeSettings>();
{
FSoftObjectPath r = Settings->AssetListObject; //(TEXT("/VRM4U/VrmObjectListBP.VrmObjectListBP"));
UObject *u = r.TryLoad();
if (u) {
if (Cast<UBlueprint>(u)) {
c = (UClass*)(Cast<UBlueprint>(u)->GeneratedClass);
}
}
}
if (c == nullptr) {
FSoftObjectPath r(TEXT("/VRM4U/VrmAssetListObjectBP.VrmAssetListObjectBP"));
UObject *u = r.TryLoad();
if (u) {
c = (UClass*)(Cast<UBlueprint>(u)->GeneratedClass);
}
}
if (c == nullptr) {
c = UVrmAssetListObject::StaticClass();
}
m = NewObject<UVrmAssetListObject>((UObject*)GetTransientPackage(), c.Get());
}
UVrmAssetListObject* mret = nullptr;
if (m) {
//auto a = NewObject<UVrmAssetListObject>(MatClass.Object, NAME_None, RF_Transactional);
//MatClass.Object;
//ULoaderBPFunctionLibrary::LoadVRMFile(nullptr, fullFileName);
GWarn->BeginSlowTask( NSLOCTEXT("UnrealEd", "ImportVRM", "Importing VRM"), true );
int ret = true;
auto &g = VRMConverter::Options::Get();
g.SetVrmOption(ImportUI->GenerateOptionData());
ULoaderBPFunctionLibrary::SetImportMode(true, Cast<UPackage>(InParent));
{
ret = ULoaderBPFunctionLibrary::LoadVRMFileLocal(m.Get(), mret, fullFileName);
}
}
```
蓝图函数库中bool ULoaderBPFunctionLibrary::LoadVRMFileFromMemory()。
```
Assimp::Importer mImporter;
const aiScene* mScenePtr = nullptr; // delete by Assimp::Importer::~Importer
mScenePtr = mImporter.ReadFileFromMemory(pFileDataData, dataSize,
aiProcess_Triangulate | aiProcess_MakeLeftHanded | aiProcess_CalcTangentSpace | aiProcess_GenSmoothNormals | aiProcess_OptimizeMeshes,
e.c_str());
if (mScenePtr == nullptr) {
std::string file;
file = utf_16_to_shift_jis(*filepath);
mScenePtr = mImporter.ReadFile(file, aiProcess_Triangulate | aiProcess_MakeLeftHanded | aiProcess_CalcTangentSpace | aiProcess_GenSmoothNormals | aiProcess_OptimizeMeshes);
}
```

View File

@@ -0,0 +1,271 @@
# Assimp入门
https://assimp-docs.readthedocs.io/en/latest/about/introduction.html
# 其他卡通渲染推主
https://twitter.com/rukikuri
# VRM格式地址
https://vrm.dev/
## Unity3d导入插件
导入https://github.com/vrm-c/UniVRM/releases
导出Fbx插件https://github.com/KellanHiggins/UnityFBXExporter
# VRM4U
https://github.com/ruyo/UnrealEngine_VRM4UPlugin
https://github.com/ruyo/VRM4U
## 渲染原理介绍
原文(上/下):
https://qiita.com/ruyo/items/ec082d81dea3033e1500
https://qiita.com/ruyo/items/71a3f2f694d2853b3f1e
MToonhttps://dwango.github.io/vrm/univrm/shaders/mtoon/
Ue4中的卡通渲染https://qiita.com/com04/items/a7895160df8d854fe924
材质:
https://qiita.com/ruyo/items/ddf727e9fa81a24070fb (细节都在这里)
https://qiita.com/ruyo/items/28255f26725a6b6bd475
Unlit
![](D:/youdaonote-pull-master/youdaonote/youdaonote-images/1E4FA28EC67B429A9AA80930E9EAF9F3.octet-stream)
![](D:/youdaonote-pull-master/youdaonote/youdaonote-images/57CA6879C4F1427FA26539F0741C08EE.octet-stream)
PBR
![](D:/youdaonote-pull-master/youdaonote/youdaonote-images/35016887610E4A888B2347F20B6172B3.octet-stream)
![](D:/youdaonote-pull-master/youdaonote/youdaonote-images/C793A5679CA94AFC84610F1E47C6407B.octet-stream)
SSS
![](D:/youdaonote-pull-master/youdaonote/youdaonote-images/4A8C1C4C6D34423B9DABFE8131C6EF64.octet-stream)
![](D:/youdaonote-pull-master/youdaonote/youdaonote-images/DEDE97C7294E4D17844D75DAF46FE040.octet-stream)
## 灯光调整
![](D:/youdaonote-pull-master/youdaonote/youdaonote-images/0C39B9753A3A49A8BEF2B020BF88D4D4.octet-stream)
2种方法
- 开启天光的LowerHemisphereIsSolidColor但这样会场景效果变得有些奇怪
- 添加一个从下往上的方向光
使用这个方法 以及 PBR材质中的BaseColor与Emissive进行插值来接近HalfLambda的效果。
## 调整面部法线来柔化面部阴影
![](D:/youdaonote-pull-master/youdaonote/youdaonote-images/84D880E4938943ECB433A5B8E5379B0F.octet-stream)
![](D:/youdaonote-pull-master/youdaonote/youdaonote-images/993BEE4A49794E348A78ACA8CCB4D7E9.octet-stream)
## 曝光与ToneMapper问题解决
ToneMapper与曝光会影响贴图的亮度所以需要尝试干掉或者抵消掉他们的影响。
![image](D:/youdaonote-pull-master/youdaonote/youdaonote-images/1DC2666D4C03467FA93C5A3B160DF5B8.octet-stream)
![image](D:/youdaonote-pull-master/youdaonote/youdaonote-images/8B1F13475DF3420E9F90FD29A1A0D7B4.octet-stream)
手动去除了Gammer矫正以及ToneMapper取消并且使用 人眼适应节点抵消曝光效果。
除此之外还使用RayTracingQualitySwitchReplace节点与人眼适应节点做了Raytracing质量调整。手机端为1
## 阴影
![image](D:/youdaonote-pull-master/youdaonote/youdaonote-images/093F34C991EB4A9E8F024D6D5E156BEB.octet-stream)
使用了SceneCaptureComponent2D。
在Orthographic平行投影*将CaptureSource设置为 "SceneDepth in R"TexrureTarget格式设置为 "RTF R32f"。
这将导致深度在UnrealUnit中线性地写入缓冲区默认为1=1cm。 别紧张。
![image](D:/youdaonote-pull-master/youdaonote/youdaonote-images/9A6D0FAA881148ABBDB8CF64E5C9CB1D.octet-stream)
要用Shadowmap投出一个阴影你只需要知道从光线中看到的深度以及投影矩阵的矩阵。
我们会把这些东西找回来,传给材料。
https://www.shibuya24.info/entry/shadowmap
官方的SceneCaptureComponent2D会做很多无用的渲染工作推荐自己重新写一个以减少不必要的消耗。
### 蓝图传递逆矩阵
在蓝图中国计算出SceneCaptureComponent2D的逆矩阵后将其传入材质中。
![image](D:/youdaonote-pull-master/youdaonote/youdaonote-images/9DB8EE6F87D44F5BA8D4E2A68842A79F.octet-stream)
### 材质内
在一个自定义节点中将参数打包成float4x4并进行计算。
现在你可以从世界坐标中参考相应的影子图。
在材料函数中结果返回0-1。
![image](D:/youdaonote-pull-master/youdaonote/youdaonote-images/537BB41619BF456399438FE6D0974CE1.octet-stream)
## 描边
在具体节点方面,
投影结果 → TransformPosition节点转换为ViewSpace的转换结果
Pixel Thickness → VectorLength的值。
乘以倒数→部分除以VectorLength的值再乘以反数→部分除以VectorLength的值。
使用ScreenResolusion的原因是为了确保不影响窗口大小和宽高比。
我不确定我是否准备好了......
在MToon再现方面我们需要能够选择 "恒定厚度模式 "和 "世界坐标参考模式"。
![image](D:/youdaonote-pull-master/youdaonote/youdaonote-images/545E0EC3BB5C47C089BC47504FA4B742.octet-stream)
http://historia.co.jp/archives/5587/
使用PoseableMeshComponent与CopyPoseFromSkeletalComponent函数实现外描边。到时候比对一下这个方法与我的重定义图元方法的效率。
## 轮廓光
使用MaterialCapture材质制作轮廓光。
## 光照模式
默认的MToon为无光照模式自定义光照效果
其余的工作将通过增加材料参数来体现数值。 我就不说了,因为这样做是多余的。 (我没有评论了...)
也可以应用ShadingShadingShift。
主源和GI可以通过在自定义节点中写出以下内容来获得。
如果你用GetSkySHDiffuseSimple或GetSkySHDiffuse搜索usf文件会有帮助。
不要忘了在最终输出的SkyLight(ResolvedView.SkyLightColor.rgb)中乘以颜色。
```
//主光源.usf
return ResolvedView.DirectionalLightColor;
```
```
//GIの影響.usf,然而这个是天光
#if SIMPLE_FORWARD_SHADING
float4 NormalVector = float4(Normal, 1);
float3 Intermediate0;
Intermediate0.x = dot(View.SkyIrradianceEnvironmentMap[0], NormalVector);
Intermediate0.y = dot(View.SkyIrradianceEnvironmentMap[1], NormalVector);
Intermediate0.z = dot(View.SkyIrradianceEnvironmentMap[2], NormalVector);
// max to not get negative colors
return max(0, Intermediate0) * ResolvedView.SkyLightColor.rgb;
#else
float4 NormalVector = float4(Normal, 1);
float3 Intermediate0, Intermediate1, Intermediate2;
Intermediate0.x = dot(View.SkyIrradianceEnvironmentMap[0], NormalVector);
Intermediate0.y = dot(View.SkyIrradianceEnvironmentMap[1], NormalVector);
Intermediate0.z = dot(View.SkyIrradianceEnvironmentMap[2], NormalVector);
float4 vB = NormalVector.xyzz * NormalVector.yzzx;
Intermediate1.x = dot(View.SkyIrradianceEnvironmentMap[3], vB);
Intermediate1.y = dot(View.SkyIrradianceEnvironmentMap[4], vB);
Intermediate1.z = dot(View.SkyIrradianceEnvironmentMap[5], vB);
float vC = NormalVector.x * NormalVector.x - NormalVector.y * NormalVector.y;
Intermediate2 = View.SkyIrradianceEnvironmentMap[6].xyz * vC;
// max to not get negative colors
return max(0, Intermediate0 + Intermediate1 + Intermediate2) * ResolvedView.SkyLightColor.rgb;
#endif
```
## 其他光照模型
## Runtime载入思路
```
NewObject<USkeletalMesh>()
SkeletalMesh->GetResourceForRendering()
->LODRenderData[0]
• StaticVertexBuffers
顶点信息。 最起码,这将填补。
• MultiSizeIndexContainer
- 绘图时的顶点信息。 如果你要运行时加载的话,也要埋下这一点。
- 从GameThread停止重写的成员从RenderThread重写。
• SkeletalMesh->GetImportedModel()->LODModels[0].Sections;
- 网格和材料信息。 我也要把这个埋了。
• SkeletalMesh->RegisterMorphTarget()
- 混合形状信息。 我也要把这个埋了。
- UE4的顶点权重为uint8所以有一个分数。 最后,正常化。
```
### VRMglTF转换时需要注意
改变坐标系。
- 转换为Z-up
- 转换比例尺为虚幻单位(x100)
- 支持多种根骨。
- 去除不必要的骨头
- 如果你不想移除的话可以添加一个假根骨root
字符与编码转换
### 物理资源导入
```
• bs = NewObject<USkeletalBodySetup>();
• ct = NewObject<UPhysicsConstraintTemplate>();
• physicsAsset->SkeletalBodySetups.Add(bs);
• physicsAsset->ConstraintSetup.Add(ct);
```
我想让我的骨头不至于发狂。
- 物理学变得很粗糙。 当碰撞被猛烈地掩埋时,就会引起注意。
- 增加计算次数,会在一定程度上改善它。
- 我想保持我想要的形状。
- 我的头发因为地心引力而垂下来。
- 可移动的范围可以指定,但移动不规范。 杂项:
VRMSpringBone是Unity的一个实现目前已经发布了VRMSpringBone。
- 理论上可以移植到UE4上。
- 源码VRMSpringBone.cs只有329行。
- 我不知道这样可以吗?
于是作者移植了VRMSpringBone。
我现在可以看VRM了。
- 你现在可以导入/运行时加载
- 我现在也能读出混合形状和碰撞了!
- 现在你可以重新创建VRMSpringBone
- 你现在可以干扰UE4的碰撞了。
StaticMesh的运行时加载也是可能的。
- 我可以创建一个自定义的摇摆骨质节点。
- 对于那些对PhysicalAsset和AnimDynamics节点的行为不满意的人。
- 你为什么不尝试着去做一个呢?
## 动画部分
要想导入动画,可以使用
- (一) 骨架通用化
- (二) 重新定位动画资产。
但两者都是编辑器功能无法在runtime中使用。
### 使用AnimBP实现运行时重定向
![image](D:/youdaonote-pull-master/youdaonote/youdaonote-images/E65AE6C12BF84F12B26B2D0E80FC1AF8.octet-stream)
将复制资产设置为AnimInstance你就可以走了。
复制源头网状物。
设置在编辑器中创建的AnimBP
要复制的网状物。
设置VrmAnimInstanceCopy
# IM4U
https://github.com/bm9/IM4U
https://github.com/bm9/UnrealEngine_IM4UPlugin
# Blender和pmx2fbx
## U3d日本分部分项
『崩壊3rd』開発者が語るアニメ風レンダリングの極意
ユニティちゃんトゥーンシェーダー2.0使いこなしスペシャル ~こだわりの活用法を紹介します!~
〈七つの大罪〉をゲームで! 高品質グラフィックを具現化するための技法と開発最適化のご紹介 by Jaeseong Ryu 他
# Muro_CG
使用Unity卡通着色的3D动画表达
https://qiita.com/MuRo_CG/items/c417ef6d6cbeed3dd42b
Unity トゥーンシェーディングを使ったDアニメ表現
https://qiita.com/MuRo_CG/items/c417ef6d6cbeed3dd42b
https://github.com/unity3d-jp/unitychan-crs
https://ja.whotwi.com/MuRo_CG/tweets/popular
https://togetter.com/li/1438719
# Unity_Japan
【Unite 2017 Tokyo】VR MAGIC キャラクターに命を吹き込んだこの4年間の記録
https://www.slideshare.net/Unite2017Tokyo/unite-2017-tokyovr-magic4
https://www.youtube.com/watch?v=N4_x9w7wNNY&feature=youtu.be
# 米哈游
http://www.uniteseoul.com/2018/download_files/T1_0503_2.pdf
米哈游面部阴影实现:
Improved Alpha-Tested Magnification for Vector Textures and Special Effects
https://steamcdn-a.akamaihd.net/apps/valve/2007/SIGGRAPH2007_AlphaTestedMagnification.pdf