举个例子,假如我在一个帧缓存中专门绘制了Phong光照模型的物体,在另一个帧缓存中专门绘制了Pbr光照模型的物体,在第三个帧缓存中只绘制了只有单一颜色的物体,等于现在我有三个离屏渲染的帧缓存,我需要把他们都绘制到铺满整个屏幕的同一个四边形中,同时保证深度测试,即在同一场景中绘制不同光照模型的物体,同时,保证在物体绘制重叠区域,深度测试正确!
How to do ?
这个方法属于比较笨比的方法,这个过程等于需要手动执行深度测试来决定当前像素点的颜色。
参考链接:https://stackoverflow.com/questions/47541674/merging-two-separate-framebuffers-onto-default-framebuffer-after-depth-testing
shader参考:
顶点着色器:
#version 330 core
layout (location = 0) in vec3 vPosition;
layout (location = 1) in vec3 vNormal;
layout (location = 2) in vec2 vTexureCoords;
out vec2 TextureCoords;
void main()
{
TextureCoords = vTexureCoords;
gl_Position = vec4(vPosition,1.0);
}
片段着色器:
#version 330 core
in vec2 TextureCoords;
// 使用帧缓存数组相关全局参数
#define FRAMEBUFFER_MAX_SIZE 5
struct FramebufferTexture
{
sampler2D ColorTexture;
sampler2D DepthTexture;
};
uniform FramebufferTexture framebufferTexture[FRAMEBUFFER_MAX_SIZE];
uniform int FRAMEBUFFER_NUM;
// 相机透视投影远近平面
uniform float NearPlane;
uniform float FarPlane;
// Tip: 深度0距离眼睛最近,深度1距离眼睛最远
// (0.0,0.0,0.0)表示黑色,(1.0,1.0,1.0)表示白色
// 越黑代表离眼睛更近,越白代表离眼睛更远
// 透视投影下将片段深度值转换为线性深度值,而正视投影本身深度值就是线性的,不需要转换
// depth : 当前片段的深度值
// nearPlane : 近平面
// farPlane : 远平面
// 参考网址 :
// (1) https://learnopengl.com/Advanced-Lighting/Shadows/Shadow-Mapping
// (2) https://learnopengl-cn.github.io/05%20Advanced%20Lighting/03%20Shadows/01%20Shadow%20Mapping/
float PerspectiveProjectionLinearizeDepth(float depth,float nearPlane,float farPlane)
{
float z = depth * 2.0 - 1.0; // Back to NDC
float linearDepth = (2.0 * nearPlane * farPlane) / (farPlane + nearPlane - z * (farPlane - nearPlane));
linearDepth /= farPlane;
return linearDepth;
}
// 得到所有深度图中深度值最小的元素索引
int GetMinDepthTextureIndex()
{
float minDepth = texture(framebufferTexture[0].DepthTexture,TextureCoords).r;
minDepth = PerspectiveProjectionLinearizeDepth(minDepth,NearPlane,FarPlane);
int minIndex = 0;
for(int i = 0; i < FRAMEBUFFER_NUM; ++i)
{
float tempDepth = texture(framebufferTexture[i].DepthTexture,TextureCoords).r;
tempDepth = PerspectiveProjectionLinearizeDepth(tempDepth,NearPlane,FarPlane);
if(tempDepth <= minDepth)
{
minIndex = i;
minDepth = tempDepth;
}
}
return minIndex;
}
out vec4 FragColor;
void main()
{
int index = GetMinDepthTextureIndex();
FragColor = texture(framebufferTexture[index].ColorTexture,TextureCoords);
}
我们看上述的方法,有一个非常明显的缺点就是在计算每一个像素点的颜色时都需要对每一个像素点的深度值进行最小值求解,这是个效率很低的方法,但是它给我们提供了一个思路,就是我们需要将每一个帧缓存的深度值引入到深度测试中,那我们该怎么做呢?
参考shader
顶点着色器:
#version 330 core
layout (location = 0) in vec3 vPosition;
layout (location = 1) in vec3 vNormal;
layout (location = 2) in vec2 vTexureCoords;
out vec2 TextureCoords;
void main()
{
TextureCoords = vTexureCoords;
gl_Position = vec4(vPosition,1.0);
}
片段着色器:
#version 330 core
in vec2 TextureCoords;
uniform sampler2D ScreenTexture;
uniform sampler2D DepthTexture;
uniform bool IsDepth;
uniform bool IsUseSingleColor;
uniform bool IsTransferDepth;
out vec4 FragColor;
void main()
{
vec3 color = vec3(0.0,0.0,0.0);
color = texture(ScreenTexture,TextureCoords).rgb;
float depth = texture(DepthTexture,TextureCoords).r;
gl_FragDepth = depth;
FragColor = vec4(color,1.0);
}
大家如果有兴趣可以访问我的个人站:http://www.stubbornhuang.com