Revision control
++ // Copyright (C) 2023 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
++
++
++ const uint particleSize = 4;
++
++ struct Particle
++ {
++ vec3 position;
++ float size;
++ vec3 rotation;
++ float age;
++ vec4 color;
++ vec3 center;
++ };
++
++ vec2 qt_indexToUV(in uint index)
++ {
++ uint v = index / qt_countPerSlice;
++ uint u = index - qt_countPerSlice * v;
++ return (vec2(u * particleSize, v) + vec2(0.5)) * qt_oneOverParticleImageSize;
++ }
++
++ Particle qt_loadParticle(in uint index)
++ {
++ Particle p;
++ vec2 offset = qt_indexToUV(index);
++ vec4 p0 = texture(qt_particleTexture, offset);
++ vec4 p1 = texture(qt_particleTexture, vec2(offset.x + qt_oneOverParticleImageSize.x, offset.y));
++ vec4 p2 = texture(qt_particleTexture, vec2(offset.x + 2.0 * qt_oneOverParticleImageSize.x, offset.y));
++ vec4 p3 = texture(qt_particleTexture, vec2(offset.x + 3.0 * qt_oneOverParticleImageSize.x, offset.y));
++ p.position = p0.xyz;
++ p.size = p0.w;
++ p.rotation = p1.xyz;
++ p.age = p1.w;
++ p.color = p2;
++ p.center = p3.xyz;
++ return p;
++ }
++
++ mat3 qt_fromEulerRotation(in vec3 rotation)
++ {
++ float a = cos(rotation.x);
++ float b = sin(rotation.x);
++ float c = cos(rotation.y);
++ float d = sin(rotation.y);
++ float e = cos(rotation.z);
++ float f = sin(rotation.z);
++ mat3 ret;
++ float bd = b * d;
++ float ad = a * d;
++ ret[0][0] = c * e;
++ ret[0][1] = -c * f;
++ ret[0][2] = d;
++ ret[1][0] = bd * e + a * f;
++ ret[1][1] = a * e - bd * f;
++ ret[1][2] = -b * c;
++ ret[2][0] = b * f - ad * e;
++ ret[2][1] = ad * f + b * e;
++ ret[2][2] = a * c;
++ return ret;
++ }
++
++ vec3 qt_applyParticle(in vec3 position, in vec3 normal, in vec4 color, out vec3 outNormal, out vec4 outColor, in mat4 particleMatrix)
++ {
++ uint index = (gl_VertexIndex + qt_particleIndexOffset) / 3;
++ Particle p = qt_loadParticle(index);
++ mat3 rotMat = qt_fromEulerRotation(p.rotation);
++ vec3 particlePos = p.size * rotMat * (position - p.center);
++ vec3 pos = particlePos + (particleMatrix * vec4(p.position, 1.0)).xyz;
++ outNormal = normalize(rotMat * normal);
++ outColor = color * p.color;
++ return pos;
++ }