OpenGL顺序无关的透明(OIT)大型链表法

1.初始化

  1. 创建2D image
    用一个2D image来储存各个像素链表的头指针

  2. 创建Pixel Unpack Buffer
    用一个PBO来刷新2D image

  3. 创建原子计数器
    用一个原子计数器来记录pixel个数

  4. 创建一维缓存
    用一个一维缓存来存储片元数据

2.渲染

  1. 刷新Image中的head指针
  2. 刷新原子计数器
  3. 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);
 }
  1. 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;
}
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值