实验:为主相机添加一个事件:CameraEvent.AfterForwardOpaque
用于画一个立方体在rt中。
实验代码:
using UnityEngine;
using UnityEngine.Rendering;
public class TestCommandBuffer : MonoBehaviour
{
public RenderTexture rt;
public Camera m_camera;
public GameObject cube;
public Shader cubeShader;
private CommandBuffer cb;
void Start()
{
cb = new CommandBuffer();
cb.name = "testCb";
rt = new RenderTexture(m_camera.pixelWidth, m_camera.pixelHeight, 24);
cb.SetRenderTarget(rt);
cb.ClearRenderTarget(true, true, Color.black);
MeshFilter mf = cube.GetComponent<MeshFilter>();
Material mat = new Material(cubeShader);
Matrix4x4 m = Matrix4x4.identity;
m.SetTRS(new Vector3(0, 0, 10), Quaternion.identity, Vector3.one);
cb.DrawMesh(mf.mesh, Matrix4x4.identity, mat);
m_camera.AddCommandBuffer(CameraEvent.AfterForwardOpaque, cb);
}
}
实验小节:
这里要注意的是基本的步骤,when,what,where,how
什么时候画,画什么,在哪里画,怎么画。
什么时候画:在相机的某个时间点,如上面的:CameraEvent.AfterForwardOpaque
画什么:我们想画一个立方体,这里立方体可以事先在unity的层级视图中创建,并且隐藏,我们只想用其mesh即可。
在哪里画:这里有两个问题,在相机的什么位置画,才能保证物体被看到,就上面代码的m.SetTRS这个函数的调用。此时要注意到相机和物体的位置,保证物体能被摄像机看到即可。第二个,画在哪里,我们是想将画的结果存储在一个rt上,所以要开辟一个rt才行。
怎么画:这个是调用函数commandbuffer的DrawMesh的方法,传入要画的mesh,位置,材质球即可。
上面的问题搞清楚之后,我们还要注意到,在一开始画的时候,将rt清空,可以用一个颜色进行清空,比如上面的用的是黑色。下面我们看到帧调试器中的结果:
这样就得到了一个rt喽。
下面我们想将,这个rt画到屏幕上去,怎么做呢?
这里我有两个方法:
- 使用最简单的OnRenderImage方法:
public void OnRenderImage(RenderTexture source, RenderTexture destination)
{
Graphics.Blit(rt, destination);
}
这样就将rt绘制到了屏幕上。
2. 第二个方法是,手动绘制一个四边形的方法
using UnityEngine;
using UnityEngine.Rendering;
public class TestCommandBuffer : MonoBehaviour
{
public RenderTexture rt;
public Camera m_camera;
public GameObject cube;
public Shader cubeShader;
public Shader sampleShader;
private CommandBuffer cb;
private Mesh quad;
void Start()
{
cb = new CommandBuffer();
cb.name = "testCb";
rt = new RenderTexture(m_camera.pixelWidth, m_camera.pixelHeight, 24);
cb.SetRenderTarget(rt);
cb.ClearRenderTarget(true, true, Color.black);
MeshFilter mf = cube.GetComponent<MeshFilter>();
Material mat = new Material(cubeShader);
Matrix4x4 m = Matrix4x4.identity;
m.SetTRS(new Vector3(0, 0, 10), Quaternion.identity, Vector3.one);
cb.DrawMesh(mf.mesh, Matrix4x4.identity, mat);
m_camera.AddCommandBuffer(CameraEvent.AfterForwardOpaque, cb);
quad = new Mesh();
Vector3[] vertices = new Vector3[4];
vertices[0] = m_camera.ScreenToWorldPoint(new Vector3(0, 0, 10));
vertices[1] = m_camera.ScreenToWorldPoint(new Vector3(0, m_camera.pixelHeight, 10));
vertices[2] = m_camera.ScreenToWorldPoint(new Vector3(m_camera.pixelWidth, m_camera.pixelHeight, 10));
vertices[3] = m_camera.ScreenToWorldPoint(new Vector3(m_camera.pixelWidth, 0, 10));
Vector2[] uvs = new Vector2[4];
uvs[0] = new Vector2(0, 0);
uvs[1] = new Vector2(0, 1);
uvs[2] = new Vector2(1, 1);
uvs[3] = new Vector2(1, 0);
quad.vertices = vertices;
quad.uv = uvs;
int[] ids = new int[6];
ids[0] = 0;
ids[1] = 1;
ids[2] = 2;
ids[3] = 2;
ids[4] = 3;
ids[5] = 0;
quad.triangles = ids;
CommandBuffer cb2 = new CommandBuffer();
cb2.name = "drawScreen";
Material material = new Material(sampleShader);
material.SetTexture("_MainTex", rt);
cb2.DrawMesh(quad, Matrix4x4.identity, material);
m_camera.AddCommandBuffer(CameraEvent.AfterImageEffects, cb2);
}
}
这里同样要注意到这个四边形的位置,我们的相机是在(0,0,0)位置,quad的z坐标为10,所以能看到。
谈到这里我们就基本完成了对commandbuffer的认识了。后面会在进行详细的扩展。
问题1:我们如何将深度图绘制到屏幕上呢?