// Colored Particles System Module
// Developed by EminGT
// Modified by Haider

// Colored Particles Rendering Function
vec3 GetColoredParticles(vec3 nPlayerPos, vec3 translucentMult, float lViewPos, float lViewPos1, float dither) 
{
    // Initialize particle accumulator
    vec3 particleAccumulation = vec3(0.0);
    
    // Define sampling parameters for particle ray marching
    const float samplingStepSize = 8.0;
    
    // Calculate maximum sampling distance with performance limits
    float maxSamplingDistance = min(effectiveACLdistance * 0.5, far);
    int totalSamples = int(maxSamplingDistance / samplingStepSize + 0.001);
    
    // Setup ray marching vectors
    vec3 rayStepVector = nPlayerPos * samplingStepSize;
    vec3 currentRayPosition = rayStepVector * dither;
    
    // Main particle sampling loop
    for (int i = 0; i < totalSamples; i++) {
        float currentDistance = length(currentRayPosition);
        
        // Early exit conditions for performance optimization
        if (currentDistance > lViewPos1) break;
        if (any(greaterThan(abs(currentRayPosition * 2.0), vec3(voxelVolumeSize)))) break;
        
        // Transform world position to voxel coordinate space
        vec3 voxelCoordinates = SceneToVoxel(currentRayPosition);
        voxelCoordinates = clamp01(voxelCoordinates / vec3(voxelVolumeSize));
        
        // Sample volumetric light data at current position
        vec4 volumetricLightData = GetLightVolume(voxelCoordinates);
        vec3 lightContribution = volumetricLightData.rgb;
        
        // Calculate distance-based attenuation with quality scaling
        float attenuationDistance = length(
            vec3(
                currentRayPosition.x,
                #if COLORED_LIGHTING_INTERNAL <= 512
                    currentRayPosition.y * 2.0,    // Standard quality scaling
                #elif COLORED_LIGHTING_INTERNAL == 768
                    currentRayPosition.y * 3.0,    // Enhanced quality scaling
                #elif COLORED_LIGHTING_INTERNAL == 1024
                    currentRayPosition.y * 4.0,    // Maximum quality scaling
                #endif
                currentRayPosition.z
            )
        );
        
        // Apply distance-based light falloff
        lightContribution *= max0(1.0 - attenuationDistance / maxSamplingDistance);
        
        // Apply distance-based particle intensity scaling
        lightContribution *= pow2(min1(currentDistance * 0.03125));
        
        // Apply transparency effects for occluded particles
        if (currentDistance > lViewPos) {
            lightContribution *= translucentMult;
        }
        
        // Accumulate particle contribution
        particleAccumulation += lightContribution;
        
        // Advance ray position for next sample
        currentRayPosition += rayStepVector;
    }
    
    // Apply environment-specific particle modifications
    #ifdef NETHER
        particleAccumulation *= netherColor * 5.0;
    #endif
    
    // Apply global visibility modifiers
    particleAccumulation *= 1.0 - maxBlindnessDarkness;
    
    // Normalize and apply gamma correction for final output
    return pow(particleAccumulation / totalSamples, vec3(0.25));
}

// Legacy Compatibility
#define GetColoredLightFog GetColoredParticles
