最近一直在用visual effect graph ,常常利用贴图来存储数据,再导入vfx采用SampleTexture结点采样使用,因此涉及到数据的保存等问题;此外这两天才真正算是尝试了computeShader的编写,同时用到了renderTexture存储数据;想来可以做个总结以及留几个还未明白的坑。
一、Texture2D
- Texture2D的创建赋值Setpixel即可,很简单(其他方法请查看官方文档):
Texture2D
- Texture2D保存为png图片:
string
二、Texture3D
- Texture3D创建其实和2d差不多,但是其中一个point是,当texture所存储的数据类型为“compressed or other non-color texture format ”时,例如本例子中使用的RFloat,就无法使用setPixel来赋值了,此时可用SetPixelData,方法如下:
Texture3D
- 分享一个Texture3D预览插件,可以方便查看三维点云数据,排查数据是否出了问题:

- Texure3D的保存:
//debug 将计算前的贴图保存为3DTEXTURE利用上面的插件便于观看
三、RenderTexture(2D)
renderTexture可以用Graphics.Blit(2dtextre,destination rendertexture)方法赋值
RenderTexture
- 将renderTexture2D保存为png:
public void saveRenderTexture (RenderTexture renderTexture, string file) {
RenderTexture.active = renderTexture;
Texture2D texture = new Texture2D (renderTexture.width, renderTexture.height, TextureFormat.ARGB32, false, false);
texture.ReadPixels (new Rect (0, 0, renderTexture.width, renderTexture.height), 0, 0);
texture.Apply ();
byte[] bytes = texture.EncodeToPNG ();
UnityEngine.Object.Destroy (texture);
System.IO.File.WriteAllBytes (file, bytes);
Debug.Log ("write to File over");
UnityEditor.AssetDatabase.Refresh (); //自动刷新资源
}
四、RenderTexture(3D volumetric )
- 三维RenderTexture 的创建比较特别;
- 新建时只需要Texture.dimension =UnityEngine.Rendering.TextureDimension.Tex3D;就可以变为3d的;
- 通常会以为construct的前三个为w,h,d(长、宽、高),但其实不是的,第三个depth指的是z buffer的bit数,一般在2drendertexture中,要将其与相机的rendertarget相关联时,才需要深度缓冲区,用深度来控制不需要render的像素,所以如果利用3d纹理进行数据运算时,depth设置为0即可(当然这也是我的一个猜想)。“高度”的设置用.volumeDepth,代表纹理的切片数。
RenderTexture
- 3D renderTexture的赋值:
【坑1】还记得 2drenderTexture 可以通过Texture2D 用bilt方法来赋值吗?于是我在3d时也使用bilt方法,结果发现只bilt了3d纹理的first layer 即第一个切片。后来查看了官方文档,发现了:

于是我以为下面这样就成功了,但是我的结果告诉我,bilt是bilt上了,bilt上去的值却和我原本的值不一样,but I don't know why? 在这里留一个坑。实际上无需在cpu为3d renderTexture赋值,在computeShader中写个函数就可以轻松初始化了。所以上面的坑估计这辈子我也不用踩了。
for
【坑2】注意cs中如果要引用其他索引的值要这么写my3DRenderTexture[id.xyz+int(0,-1,1)],而my3DRenderTexture[id.x,id.y-1,id.z+1)]是错的~
【坑3】本例中我使用了RenderTextureFormat.RFloat类型的数据,但我本来是想用Rint 或者R8类型(因为我的数据原本是整型的),但是不知为何cs会报错,我理解的是cs不支持这类数据或者在renderTexture 3d 中使用这类整型数据有特定表示或方式(大半是后者的原因),这个问题没搞明白,留着。不过我有个猜想是在unity shader中整型是32bit int ,而R8 是8bit整型所以不可以,但很遗憾的是RenderTextureFormat.RInt也是32bit int,而TextureFormat没有RInt类型,最大只有R16,这个猜想似乎也可以886了。
- 3D renderTexture的保存:
AssetDatabase.CreateAsset (stateTexture, "Assets/yourTex3d.asset");
五、一些参数的解释或资料
- 关于纹理的线性空间和伽马空间:

RenderTextureReadWrite

Debug
- 关于纹理的mipmap:
使用mipmap后,会生成不同大小的多张贴图,贴图会根据和摄像机距离的远近选择使用不同精度的贴图,下面文章解释了mipmap的作用。
优快云-专业IT技术社区-登录blog.youkuaiyun.com- 关于纹理的FiltetMode(平滑处理模式),即采样的方式,由1到3纹理效果越来越好,性能消耗越来越大,纹理变得越来越平滑
- point单像素采样,纹理块状化
- bilinear 双线性插值采样,纹理变模糊
- trilinear三线性插值采样,和2差不多,在不同的miplevel进行了模糊
- 关于纹理数据类型RenderTextureFormat与TextureFormat:
//Note that a particular render texture format might not be supported by the current platform or GPU.
- 关于cg数据类型:

六、【题外话】ComputeShader中如何传入四维数组进行计算(同理可得三维数组方法)
//Just use a linear buffer with dimX * dimY * dimZ number of elements. Then index into it using:
感想:因为一些小坑耽误了不少时间,这告诉我们什么道理呢?遇到问题直奔官方文档,官方文档就是圣经啊啊啊!