unity text不能刷新_Unity使用ComputerShader实时压缩RT!
背景
computer shader最近突然變得異?;馃?#xff0c;原神和UE開發(fā)者大會多次被人提到通過computershader對手機平臺的優(yōu)化。一方面得益于最近手機硬件的提升,對computer shader的支持和性能提升。另一方面,新出的游戲?qū)τ诋嬅尜|(zhì)量的要求越來越高,一些新特性,諸如:SSAO,屏幕空間反射,RVT,甚至GPU pipeline,對于computer shader的需求提高。
前不久,在unity實現(xiàn)了RVT,里邊提到需要申請使用兩種4k的RT,在手機上測試,法線性能還是有一定的損失。雖然,非RVT在使用四層紋理,總共需要9張地形相關(guān)的貼圖(4*2 + 1,mask壓縮到diffuse和normal),但是貼圖的尺寸最多開到1024,一般就512就夠了。而RVT需要兩張4k的RT,并且RenderTexture是不能壓縮的,也就是全展開的4k*2,在原本手機帶寬就不夠的情況下,這個算得上非常奢侈,非常影響效率。UE開發(fā)者大會,正好提到在4.26版本加入VT的壓縮,正好可以拔過來,在Unity里實現(xiàn)了一下,用來支持RVT系統(tǒng)。
Computer Shader
UE4.26提供兩種VT的壓縮格式,BC3(PC)和ETC2(Android),并且ETC2的壓縮算法看了一下,為了提升性能,做了很多精簡。
我這里貼一下壓縮的主體部分代碼,具體壓縮算法部分,可以在UE4.26preview的ETCCompressionCommon.ush和BCCompressionCommon.ush中,也可以在我后面提供的壓縮文件里尋找(我做了一定的修改),或者拔GitHub上的代碼darksylinc/betsy
#include "ETCCompress.hlsl"#include "BCCompress.hlsl"
#pragma multi_compile _COMPRESS_BC3 _COMPRESS_ETC2
#pragma kernel CSMain
RWTexture2D<uint4> Result;
Texture2D<float4> RenderTexture0;
SamplerState samplerRenderTexture0;
uint4 DestRect;
[numthreads(8, 8, 1)]
void CSMain(uint3 ThreadId : SV_DispatchThreadID)
{
uint2 SamplePos = ThreadId.xy * 4;
if (any(SamplePos >= DestRect.zw))
return;
float2 TexelUVSize = 1.f / float2(DestRect.zw);
float2 SampleUV = (float2(SamplePos) + 0.5f) * TexelUVSize;
float3 BlockBaseColor[16];
ReadBlockRGB(RenderTexture0, samplerRenderTexture0, SampleUV, TexelUVSize, BlockBaseColor);
float BlockA[16];
for (int i = 0; i < 16; i++)
{
BlockA[i] = 1;
}
#ifdef _COMPRESS_ETC2
Result[ThreadId.xy] = CompressBlock_ETC2_RGBA(BlockBaseColor, BlockA);
#else
Result[ThreadId.xy] = CompressBC3Block_SRGB(BlockBaseColor, BlockA);
#endif
}
他這里的ETC2直接寫死的4x4block,然后分RGB和RGBA兩種。
C#調(diào)用
實例代碼中,比如我們想要壓縮一張256x256的圖片,我們需要申請一張64x64的R32G32B32A32_Uint的RT,在computer shader里填入數(shù)據(jù)。這個RT肯定不能直接當貼圖使用,我們需要把數(shù)據(jù)拷貝到Texture2D中,Texture2D是可以設(shè)置壓縮格式的。直接使用Graphics.CopyTexture整體拷貝數(shù)據(jù),這里比較坑的地方是
這兩句話居然不是同一個意思,一定要使用上面那樣,下面這種會報錯。
using UnityEngine;using UnityEngine.Experimental.Rendering;
using UnityEngine.UI;
public class ComputeShaderTest : MonoBehaviour
{
public ComputeShader shader;
Material _mat;
public Texture _mask;
int kernelHandle;
int[] DestRect;
public RenderTexture tex;
public Texture2D copyTex;
public Text tt;
GraphicsFormat format;
void Awake()
{
DestRect = new int[4] { 0, 0, 256, 256 };
}
void Start()
{
#if UNITY_ANDROID && !UNITY_EDITOR format = GraphicsFormat.RGBA_ETC2_UNorm;
shader.DisableKeyword("_COMPRESS_BC3");
shader.EnableKeyword("_COMPRESS_ETC2");
#else format = GraphicsFormat.RGBA_DXT5_UNorm;
shader.DisableKeyword("_COMPRESS_ETC2");
shader.EnableKeyword("_COMPRESS_BC3");
#endif kernelHandle = shader.FindKernel("CSMain");
tex = new RenderTexture(64, 64, 24)
{
graphicsFormat = GraphicsFormat.R32G32B32A32_UInt,
enableRandomWrite = true,
};
tex.Create();
//tt.text = format.ToString() + SystemInfo.IsFormatSupported(format, FormatUsage.Linear).ToString() + SystemInfo.supportsComputeShaders + SystemInfo.copyTextureSupport;
shader.SetTexture(kernelHandle, "Result", tex);
shader.SetTexture(kernelHandle, "RenderTexture0", _mask);
shader.SetInts("DestRect", DestRect);
shader.Dispatch(kernelHandle, (256 / 4 + 7) / 8, (256 / 4 + 7) / 8, 1);
copyTex = new Texture2D(256, 256, format, TextureCreationFlags.None);
Graphics.CopyTexture(tex, 0,0,0,0,64,64,copyTex,0,0,0,0);
_mat = GetComponent().sharedMaterial;
_mat.mainTexture = copyTex;
}
}
效果展示
在移動和PC都可以,vulkan在某些機型有bug,切換到GLES3就可以了。
最后貼一下主要代碼
鏈接:pan.baidu.com/15Ny0khWHg_MUKfzXkwopjg
提取碼:onbr
來源知乎專欄:Unity引擎應(yīng)用
總結(jié)
以上是生活随笔為你收集整理的unity text不能刷新_Unity使用ComputerShader实时压缩RT!的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 计算机系统基础:文件的存取和存储空间管理
- 下一篇: 论文阅读(4)--Part-Stacke