Revision control

Copy as Markdown

// Copyright (C) 2025 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifdef QQ3D_SHADER_META
/*{
"uniforms": [
{ "type": "uimage2D", "name": "qt_imgAbuffer" , "imgtype" : "rgba32ui" , "qualifiers": "restrict coherent writeonly" , "condition": "QSSG_OIT_METHOD == QSSG_OIT_LINKED_LIST" },
{ "type": "uimage2D", "name": "qt_imgAux" , "imgtype" : "r32ui" , "qualifiers": "restrict coherent" , "condition": "QSSG_OIT_METHOD == QSSG_OIT_LINKED_LIST" },
{ "type": "uimage2D", "name": "qt_imgCounter" , "imgtype" : "r32ui" , "qualifiers": "restrict" , "condition": "QSSG_OIT_METHOD == QSSG_OIT_LINKED_LIST" }
]
}*/
#endif // QQ3D_SHADER_META
#include "../effectlib/oitcommon.glsllib"
ivec2 qt_indexToImageCoord(in uint index, const uint width)
{
ivec2 uv;
uv.y = int(index / width);
uv.x = int(index - uv.y * width);
return uv;
}
#if QSSG_OIT_METHOD == QSSG_OIT_LINKED_LIST
vec4 qt_oitLinkedList(const vec4 color, const uint listNodeCount, const uint abufImageWidth, const ivec2 viewSize, const uint viewIndex)
{
// +1 as 0 is used as a list terminator. Adds 1 to imgCounter[0,0] and
// returns the original value.
if (color.a <= 0.000001)
return vec4(0);
const uint newOffset = imageAtomicAdd(qt_imgCounter, ivec2(0), 1) + 1;
vec4 ret = vec4(0.0);
if(newOffset < listNodeCount) {
#if QSHADER_VIEW_COUNT >= 2
ivec2 coord = ivec2(gl_FragCoord.x, gl_FragCoord.y + viewIndex * viewSize.y);
#else
ivec2 coord = ivec2(gl_FragCoord.x, gl_FragCoord.y);
#endif
#if QSSG_MULTISAMPLE == 1
coord.x += gl_SampleID * viewSize.x;
#endif
// Note that this is indeed thread-safe! The order in which threads
// reach this line determines the order of the fragments in the linked list.
const uint oldOffset = imageAtomicExchange(qt_imgAux, coord, newOffset);
const uvec4 storeValue = uvec4(packUnorm4x8(color),
floatBitsToUint(gl_FragCoord.z),
oldOffset,
0);
imageStore(qt_imgAbuffer, qt_indexToImageCoord(newOffset - 1, abufImageWidth), storeValue);
} else {
ret = color;
}
return ret;
}
#endif