1.初始化
-
创建2D image
用一个2D image来储存各个像素链表的头指针 -
创建Pixel Unpack Buffer
用一个PBO来刷新2D image -
创建原子计数器
用一个原子计数器来记录pixel个数 -
创建一维缓存
用一个一维缓存来存储片元数据
2.渲染
- 刷新Image中的head指针
- 刷新原子计数器
- Pass 1 PShader
#version 420 core
layout (early_fragment_tests) in;
//原子计数器
layout (binding = 0, offset = 0) uniform atomic_uint index_counter;
//1D image 缓存
layout (binding = 0, rgba32ui) uniform imageBuffer list_buffer;
//2D image
layout (binding = 1, r32ui) uniform image2D head_pointer_image;
void main (void)
{
vec4 frag_color = shaderFragment();
//获取当前pixel的序号
uint index = atomicCounterIncrement( index_counter );
//替换该位置原来的序号
uint old_header = imageAtomicExchange( head_pointer_image, ivec2(gl_FragCoord.xy), index );
//记录该pixel的信息,包括
uvec4 item;
item.x = old_head; //上一个pixel的序号
item.y = packUnorm4x8(frag_color); //当前pixel的颜色//压缩
item.z = floatBistToUint(gl_FragCoord.z); //当前pixel的深度
item.w = 0;
//把该pixel的信息存入imagebuffer
imageStore(list_buffer, index, item);
}
- Pass 2 PShader
#version 420 core
uniform sampler2D head_pointer_image;
uniform samplerBuffer list_buffer;
#define MAX_FRAGMENTS 15
uvec4 fragments[MAX_FRAGMENTS];
layout (location = 0) out vec4 output_color;
void main(void)
{
//取值
int frag_count=0;//该点上叠加的pixel个数
//根据序号在imageBuffer中寻找该点所有的pixel,存入数组fragments[MAX_FRAGMENTS]
uint current = texelFetch(head_pointer_image, ivec2(gl_FragCoord.xy), 0);
while(current != 0xFFFFFFFF && frag_count < MAX_FRAGMENTS)
{
item = texelFetch(list_buffer, current);
current = item.x;
fragment[frag_count] = item;
frag_count++
}
//排序
uint i, j;
if (fragment_count > 1)
{
for (i = 0; i < fragment_count - 1; i++)
{
for (j = i + 1; j < fragment_count; j++)
{
uvec4 fragment1 = fragment_list[i];
uvec4 fragment2 = fragment_list[j];
float depth1 = uintBitsToFloat(fragment1.z);
float depth2 = uintBitsToFloat(fragment2.z);
if (depth1 < depth2)
{
fragment_list[i] = fragment2;
fragment_list[j] = fragment1;
}
}
}
}
//融混
vec4 final_color = vec4(0.0);
for (i = 0; i < fragment_count; i++)
{
vec4 modulator = unpackUnorm4x8(fragment_list[i].y);
vec4 additive_component = unpackUnorm4x8(fragment_list[i].w);
final_color = mix(final_color, modulator, modulator.a) + additive_component;
}
color = final_color;
}