3d gpu particle system renders darkened colors exclusively on ATI cards

Hi everyone, I’m currently working on a project that involves running a 3d particle system on an iMac equipped with an ATI discrete graphic chip. So far, it was tested on several macbooks with intel chipsets as well as an hackintosh with a last generation Nvidia geforce card, and it worked like a charm on every one of these setups. I’m using Neil Mendoza’s ofxGpuParticles extension (https://github.com/neilmendoza/ofxGpuParticles) with custom shaders.

Today, I ran it for the first time on the target iMac and to my surprise, I discovered that everything worked fine except for the fact that the colors of the particles (these are just gl_points) are really darkened, almost black. I also noticed that if I zoom in with the camera, they start to appear and become a bit brighter (at first everything was black), so this “darkening” seems proportional with the depth of the scene. This makes me think that it must be a feature and not a bug, and that for some reason it’s activated by default on ATI drivers and not others. I’ve tried searching for gl extensions that could be responsible, but so far I found nothing.

Also, I tried running it on another macbook with a discrete ATI chip and it behaves exactly the same, so I’m starting to be pretty sure this has something to do with the drivers or the card itself.

Here’s the draw fragment shader :

 #version 120

#extension GL_ARB_texture_rectangle : enable

uniform vec4 color;

varying float col;
varying float depth;
varying float meduz;

void main()
{
if (meduz < 0.5) {
gl_FragColor = vec4(col, color.g,1 - col, color.a);
}
else {
gl_FragColor = color;
}
}

Here is my setup function :

void ofApp::setup()
{
    settings.loadFile("settings.xml");
    numParticles = settings.getValue("numParticles", 1500);
    width = settings.getValue("width", 1920);
    height = settings.getValue("height", 1080);
    distance = settings.getValue("distance", 400);

    ofBackground(0);
    ofSetFrameRate(30);
    ofSetWindowShape(width, height);
    cam.setAutoDistance(false);
    cam.setDistance(distance);
    ofEnableAntiAliasing();
    glEnable(GL_PROGRAM_POINT_SIZE);
    
    particles.init(numParticles, numParticles);
    
    particles.loadShaders("shaders120/update", "shaders120/draw");
    mainOutputSyphonServer.setName("Screen Output");
    
    bounds = ofVec3f(1.,1.,1.);
    steps = 8;
    color = ofVec4f(settings.getValue("red", 0.3),settings.getValue("green", 0.2), settings.getValue("blue", 0.6),settings.getValue("alpha", 0.1));
    
    initPosVel();
    
    // listen for update event to set additonal update uniforms
    ofAddListener(particles.updateEvent, this, &ofApp::onParticlesUpdate);
    ofAddListener(particles.drawEvent, this, &ofApp::onParticlesDraw);
    
    receiver.setup(7171);
}

I tried deactivating gl_point_size, setting the particles colors directly in the shader’s output and many other small tweaks without success. Has anybody ever encountered something like that ? Any idea on how I could get rid of it ?

Thanks :slight_smile:

Update : On a closer look, it looks like part of the problem comes from the fact that blending is not working. When I zoom in and see the points becoming circles, they mask everything behind. The alpha channel only defines brightness, but not transparency. I tried adding the following lines to my setup() function :

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable( GL_BLEND );

But it doesn’t seem to change anything. Ideas anyone ?

Update 2 : After some tinkering, I realized that blending is working, but not the way I was used to so the results are still disappointing (better though). The default behavior I was used to was “fully additive blending”, meaning that the values of each point present in a pixel would be added until it reached pure white. Now what happens is that when the value of the base particle color is reached (let’s say .3 .4 .5 for example) it stops, meaning that I’m not able to reach interesting contrasts because if I keep adding particles it ends up looking like a flat area with the original color. I’ve tried many blending functions, either found on the net or anything I could think of, but the problem remains the same. Maybe that’s a better behaviour in some cases, but not in mine sadly. Any ideas of a workaround ?