# 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 MToon:https://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() SkeletalMesh->GetResourceForRendering() ->LODRenderData[0] • StaticVertexBuffers 顶点信息。 最起码,这将填补。 • MultiSizeIndexContainer - 绘图时的顶点信息。 如果你要运行时加载的话,也要埋下这一点。 - 从GameThread停止重写的成员从RenderThread重写。 • SkeletalMesh->GetImportedModel()->LODModels[0].Sections; - 网格和材料信息。 我也要把这个埋了。 • SkeletalMesh->RegisterMorphTarget() - 混合形状信息。 我也要把这个埋了。 - UE4的顶点权重为uint8,所以有一个分数。 最后,正常化。 ``` ### VRM(glTF)转换时需要注意 改变坐标系。 - 转换为Z-up - 转换比例尺为虚幻单位(x100) - 支持多种根骨。 - 去除不必要的骨头 - 如果你不想移除的话,可以添加一个假根骨(root)。 字符与编码转换 ### 物理资源导入 ``` • bs = NewObject(); • ct = NewObject(); • 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 トゥーンシェーディングを使った3Dアニメ表現 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