192 lines
8.4 KiB
Plaintext
Raw Normal View History

2026-05-01 13:07:13 +02:00
//////////////////////////////////////////
// Complementary Shaders by EminGT //
// With Euphoria Patches by SpacEagle17 //
//////////////////////////////////////////
//Common//
#include "/lib/common.glsl"
//////////Fragment Shader//////////Fragment Shader//////////Fragment Shader//////////
#ifdef FRAGMENT_SHADER
//Pipeline Constants//
//Common Variables//
//Common Functions//
//Includes//
//Program//
void main() {
discard;
}
#endif
//////////Vertex Shader//////////Vertex Shader//////////Vertex Shader//////////
#ifdef VERTEX_SHADER
//Pipeline Constants//
#if END_CRYSTAL_VORTEX_INTERNAL > 0 || DRAGON_DEATH_EFFECT_INTERNAL > 0 || defined END_PORTAL_BEAM_INTERNAL
#extension GL_ARB_shader_image_load_store : enable
#endif
//Uniforms//
#if END_CRYSTAL_VORTEX_INTERNAL > 0 || DRAGON_DEATH_EFFECT_INTERNAL > 0 || defined END_PORTAL_BEAM_INTERNAL
layout(r32i) uniform iimage2D endcrystal_img;
#endif
//Attributes//
//Common Variables//
//Common Functions//
//Includes//
//Program//
void main() {
#if END_CRYSTAL_VORTEX_INTERNAL > 0 || DRAGON_DEATH_EFFECT_INTERNAL > 0 || defined END_PORTAL_BEAM_INTERNAL
vec4 position0 = ftransform();
if (position0.x < 0.0 && position0.y > 0.0) {
#if END_CRYSTAL_VORTEX_INTERNAL % 2 == 1
// update temporally stable end crystal data
for (int index = 0; index < 20; index++) {
int state = imageLoad(endcrystal_img, ivec2(index, 8)).r;
state -= max(1, int(10000 * frameTime));
if (state < 0) {
for (int i = 0; i < 5; i++) {
imageStore(endcrystal_img, ivec2(index, i+5), ivec4(0));
}
} else {
ivec4 writeData = ivec4(
imageLoad(endcrystal_img, ivec2(index, 5)).r,
imageLoad(endcrystal_img, ivec2(index, 6)).r,
imageLoad(endcrystal_img, ivec2(index, 7)).r,
state
);
writeData.xyz += ivec3(10000 * (previousCameraPosition - cameraPosition));
for (int i = 0; i < 4; i++) {
imageStore(endcrystal_img, ivec2(index, i+5), ivec4(writeData[i]));
}
imageStore(endcrystal_img, ivec2(index, 9), ivec4(
imageLoad(endcrystal_img, ivec2(index, 9)).r + int(10000 * frameTime)
));
}
}
// crystals
for (int index = 0; index < 20; index++) {
ivec4 newData = ivec4(
imageLoad(endcrystal_img, ivec2(index, 1)).r,
imageLoad(endcrystal_img, ivec2(index, 2)).r,
imageLoad(endcrystal_img, ivec2(index, 3)).r,
imageLoad(endcrystal_img, ivec2(index, 4)).r
);
if (newData.w > 0) {
vec3 pos = vec3(newData.xyz) / newData.w;
int temporalIndex = -1;
for (int k = 0; k < 20; k++) {
ivec4 temporalData = ivec4(
imageLoad(endcrystal_img, ivec2(k, 5)).r,
imageLoad(endcrystal_img, ivec2(k, 6)).r,
imageLoad(endcrystal_img, ivec2(k, 7)).r,
imageLoad(endcrystal_img, ivec2(k, 8)).r
);
vec3 temporalPos = 0.0001 * temporalData.xyz;
if (temporalData.w > 0 && length((temporalPos - pos) * vec3(1.0, 0.3, 1.0)) < 1.0) {
temporalIndex = k;
break;
}
}
if (temporalIndex == -1) {
for (int k = 0; k < 20; k++) {
int previousWeight = imageAtomicCompSwap(endcrystal_img, ivec2(k, 8), 0, -1);
if (previousWeight == 0) {
temporalIndex = k;
break;
}
}
}
if (temporalIndex >= 0) {
ivec4 storeData = ivec4(10000 * pos, 16000);
for (int i = 0; i < 4; i++) {
imageStore(endcrystal_img, ivec2(temporalIndex, i+5), ivec4(storeData[i]));
}
}
}
}
#endif
#if END_CRYSTAL_VORTEX_INTERNAL / 2 == 1
// healing beams
for (int index = 20; index < 35; index++) {
ivec4 writeData = ivec4(
imageLoad(endcrystal_img, ivec2(index, 1)).r,
imageLoad(endcrystal_img, ivec2(index, 2)).r,
imageLoad(endcrystal_img, ivec2(index, 3)).r,
imageLoad(endcrystal_img, ivec2(index, 4)).r
);
for (int i = 0; i < 4; i++) {
imageStore(endcrystal_img, ivec2(index, i + 5), ivec4(writeData[i]));
}
}
#endif
#if END_CRYSTAL_VORTEX_INTERNAL / 2 == 1 || DRAGON_DEATH_EFFECT_INTERNAL > 0
// dragon position
{
const int index = 35;
int isDying = imageLoad(endcrystal_img, ivec2(index, 0)).r;
// if (isDying == 0) isDying = 10000; // Helpful for debugging
ivec4 readData = ivec4(
imageLoad(endcrystal_img, ivec2(index, 1)).r,
imageLoad(endcrystal_img, ivec2(index, 2)).r,
imageLoad(endcrystal_img, ivec2(index, 3)).r,
imageLoad(endcrystal_img, ivec2(index, 4)).r
);
ivec4 temporalData = ivec4(
imageLoad(endcrystal_img, ivec2(index, 5)).r,
imageLoad(endcrystal_img, ivec2(index, 6)).r,
imageLoad(endcrystal_img, ivec2(index, 7)).r,
imageLoad(endcrystal_img, ivec2(index, 8)).r
);
ivec4 writeData = ivec4( // is 0 if dragon is dead, otherwise contains dragon position
isDying <= 9000 && temporalData.w > 0 ? ivec3(0.0) :
readData.w > 0 ? 10000.0 * readData.xyz / readData.w :
abs(length(vec3(readData.xyz)) - length(vec3(temporalData.xyz))) <= 0.001 ? ivec3(0.0) :
temporalData.xyz + ivec3(10000 * (previousCameraPosition - cameraPosition)),
isDying > 0 ? temporalData.w + int(10000 * frameTime) : 0
);
imageStore(endcrystal_img, ivec2(index, 0), ivec4(max(0, isDying - int(1000 * frameTime))));
for (int i = 0; i < 4; i++) {
imageStore(endcrystal_img, ivec2(index, i + 1), ivec4(0));
imageStore(endcrystal_img, ivec2(index, i + 5), ivec4(writeData[i]));
}
}
#endif
#ifdef END_PORTAL_BEAM_INTERNAL
for (int k = 0; k < 4; k++) {
imageStore(
endcrystal_img,
ivec2(35, k+5),
imageLoad(endcrystal_img, ivec2(35, k))
);
}
#endif
// clear temporally unstable data
for (int index = 0; index < 36; index++) {
#if DRAGON_DEATH_EFFECT_INTERNAL > 0
if (index == 35) {
continue;
}
#endif
for (int i = 0; i < 5; i++) {
imageStore(endcrystal_img, ivec2(index, i), ivec4(0));
}
}
}
gl_Position = vec4(-1);
#endif
}
#endif