两种好用的全屏Quad绘制方法
后期处理时经常要用到全屏Quad渲染,最简单的方法是绘制两个三角形拼成一个全屏的quad,这个不用思考太多。
另外一种则是绘制一个足够覆盖整个屏幕的三角形,这种做法在unity和ue4中都被采用了。
具体做法如下:
//cpu input
pos0 = float2(-1, -1);
pos1 = float2(3, -1);
pos2 = float2(-1, 3);
uv0 = float2(0, 0);
uv1 = float2(2, 0);
uv2 = float2(0, 2);
////////// 光栅插值模拟 /////////////
// 屏幕左下角
pos_bl = pos0 = float2(-1,-1);
uv_bl = uv0 = float2(0,0);
// 屏幕右下角
pos_br = (pos0 + pos1)*0.5 = float2(1,-1);
uv_br = (uv0 + uv1)*0.5 = float2(1,0);
// 屏幕左上角
pos_tl = (pos0 + pos2)*0.5 = float2(-1,1);
uv_tl = (uv0 + uv2)*0.5 = float2(0,1);
// 屏幕右上角
pos_tr = (pos1 + pos2)*0.5 = float2(1,1);
uv_tr = (uv1 + uv2)*0.5 = float2(1,1);
另外一种做法是在顶点着色器直接利用gl_VertexIndex算出一个全屏三角形,这连vao和vbo绑定都省了:
/////////////// cpu ////////////////
vkCmdDraw(cmd_buf, 3, 1, 0, 0);
////////////// vertex shader ////////////
#version 450
layout (location = 0) out vec2 outUV;
void main()
{
outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
gl_Position = vec4(outUV * 2.0f - 1.0f, 0.0f, 1.0f);
}
这里要注意绘制方向为顺时针方向,因此要设置管线状态如下:
rasterizationState.cullMode = VK_CULL_MODE_FRONT_BIT;
rasterizationState.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;