首先要说明的是不建议使用UE(❌️)
为什么?因为Godot才是最合适的,网上有很多实现3Dpixel的教程,最关键的是Godot是能所有像素对齐的,所以你可以通过默认功能规避很多麻烦:)
但我用UE:(
首先要说明的是如何使得画面像素化(✅️)
像素化的核心其实就是降低分辨率
目前的方式其实有很多
- 后处理
- 降低Scene Render Percentage
- sceneCapture捕捉画面到texture缩小后放大
那都可以用吗?
当然不可以,原因是降低分辨率后像素边缘在移动以及旋转时会闪烁,并且不断地抖动,能用的其实只有3
接下来就是如何保证像素稳定
如果你成功的实现了上述任意像素化方式,你肯定会看到物体边缘在不断地闪烁(如果你不清楚,可以试一下,你会知道我在说什么的)
《得益于》UE先进的3D渲染技术,有几个点需要注意
- 相机需要正交,实现像素画面
- 抗锯齿需要关闭,因为要实现像素风格,我们不能启用任何抗锯齿
- 阴影要使用ShadowMap,UE的虚拟阴影贴图会导致阴影边缘的闪烁,光追我没有尝试,但理论上讲pixel相机正交的情况下,RayTracing因为正交相机没有透视效果,所有的射线都会平行,效果肯定是不正确的
- cascadedShadowMap中的距离要与相机的springArm匹配,因为在shadowMap下,DirectionLight的cascadeShadowMap才是动态阴影,这个阴影质量我们必须要调
- AO效果只有SSAO能用,原因同3
- 等等基于正交相机下的影响
在上面这些配置好后,我们就可以开始了
1 | void ABSPlayerController::Tick(float DeltaSeconds) |
这是什么?
这个是在UE中如何正确的Snap到grid,这个其实就是原理,我们需要把相机的偏移换算成像素的偏移,而且偏移的大小是由本身的正交相机的size/RT的size(别忘了我们使用的方法3,SceneCapture场景到RT上),这个大小其实就是折算后的屏幕分辨率下的onePixelSize。
但这还没完,我们要实现的是相机平滑移动,单纯吸附到像素,你的画面移动会变成一卡一卡的
我们需要subpixelMove,但UE里面没有这个功能。
还记的我们使用方法3吗?这时候我们render到RT后,可以通过新建材质给到Widget,同时,我们把springArm的worldSpace转换成screenSpace,再去setLocattion,这就能得到一个smooth相机了。

BUT?
虽然但是,我也想没有这个BUT,但他确实发生了,如果这时候你查看你的像素边缘,依然有一些抖动,他可以通过降低RT分辨率极大的减缓。
为什么会发生这个?
我不知道Ciallo~(∠・ω< )
截止2025/12/15,我确实不太清楚产生这个的原因,可能是因为本身在移动时不断snap导致的,那么我们也许可以通过将角色移动与相机移动拆开来,让相机delay下他的跟随
会有很多小问题值得注意
比如RT的采样方式应该设置为2Dpixel之类的,这样可以让你的material采样的时候能够避免线性插值带来的模糊(其实就是nearest采样,我单独写了个自定义最邻近采样发现没有什么必要),或许这部分我应该总结下?但有点又臭又长还没必要:(
总而言之
如果你想做一个像素游戏,其实最好的选择是godot,其次是Unity(自定义管线方便),最后才是UE
have fun :)