原理
通过创建渲染纹理,将相机的渲染目标设置成该纹理,即可将相机捕获到的内容作为一张纹理渲染到你想要的地方。
实践准备
- 创建一个空的场景,和几个需要拍摄的对象,这里用几个染色的方块表示。
- 创建一个新相机,这个相机用来渲染目标纹理。修改CullingMask对应的层,主要是根据需要,我这边相机渲染的内容只关心拍摄的物体,并且我修改了方块的Layer。其他内容不变。
- 讲相机对准需要拍摄的物体,保证物体能正确的渲染到相机的视野内。
- 创建材质,并选用Unlit/Texture的shader。因为这里只需要有个纹理作为背景板就行了。并在材质中放入一张纹理。这个创建好的材质将作为背景放入场景中。
- 使用UGUI创建几个按钮,最为代码方法的触发。
- 创建一个Plane的预制体,将之前做好的材质赋予它,使其成为背景板
代码部分
- 创建一个脚本名为Photograph作为主要逻辑脚本,并挂载在场景中。
- 创建方法CreatePhoto,用于按钮外部触发。内部逻辑如下
public void CreatePhoto()
{
if (renderCamera != null)
{
//renderCamera是我们的拍摄照片用的相机,一般情况下给它关闭,防止它对我们主要的渲染结果造成影响。
renderCamera.gameObject.SetActive(true);
//创建一个Texture2D 的纹理output ,作为一个临时纹理用于接收相机拍摄到的纹理
//这里使用大小是512x385和TextureFormat.RGB24类型的纹理格式,并关闭minmap,这里并不需要开启多级渐远纹理。(关于纹理格式和多级渐远纹理会在以后的文章补充)
Texture2D output = new Texture2D(512, 358, TextureFormat.RGB24, false);
//同样创建一个渲染纹理
RenderTexture renderTexture = new RenderTexture(512, 358, 32, RenderTextureFormat.ARGB32);
//这行代码将相机的渲染目标设置为上面创建的 renderTexture。这意味着,当相机进行渲染时,它的渲染结果将被保存到 renderTexture 中,而不是直接显示在屏幕上。
renderCamera.targetTexture = renderTexture;
//强制执行一次渲染,将渲染结果更新
renderCamera.Render();
//这行代码设置当前活动的渲染纹理为 renderTexture。这是为了确保接下来的 ReadPixels 操作读取的是 renderTexture 中的像素数据。
RenderTexture.active = renderTexture;
//rect_renderTexture 是一个矩形区域参数,用于定义要读取的区域。
Rect picture_renderTexture = new Rect(0, 0, 512, 512);
//这行代码从当前活动的渲染纹理(即renderTexture)中读取像素数据,并将其存储到 output 纹理对象中
output.ReadPixels(picture_renderTexture, 0, 0);
//这行代码应用了纹理的修改。在Unity中,ReadPixels 操作会修改纹理数据,但是这些修改不会立即生效,需要调用 Apply 方法来应用这些修改,使其生效。
output.Apply();
//将生成的纹理覆盖到背景板上
material.mainTexture = output;
//操作完毕后关闭渲染相机
renderCamera.gameObject.SetActive(false);
}
}
3.将对应的方法绑定按钮响应事件
最终效果
小结
基于渲染纹理的技术除了可以实现一些拍照的功能以外,还能进行扩展,比如生成一些动态头像,或者镜子效果等。