Success!
And without needing to edit the processing source.
I realised that if I work out what world-coordinates turn into in z-buffer values, I could just scale the fog colouring as a ratio between the near and far z-buffer depths, and do a per-pixel fogging that way.
Unfortunately, this does require drawing to screen for a single frame when set-up. If anyone knows a way to convert world coordinate distance from camera into zbuffer values, this part could be skipped. I've looked through the source, and can't quite work out how it's calculated.
Anyway, without further ado, here's the code:
Code:class fog
{
float near, far;
PGraphics3 pg3;
fog(float worldnear, float worldfar,PGraphics pg)
{
pg3=(PGraphics3)pg;
pushMatrix();
camera(0,0,0,0,0,1,0,1,0);
beginShape(QUADS);
{
vertex(-100,-100,worldnear);
vertex(100,-100,worldnear);
vertex(100,100,worldnear);
vertex(-100,100,worldnear);
}
endShape();
updatePixels();
near=pg3.zbuffer[width/2+((height/2)*width)];
background(0);
beginShape(QUADS);
{
vertex(-100,-100,worldfar);
vertex(100,-100,worldfar);
vertex(100,100,worldfar);
vertex(-100,100,worldfar);
}
endShape();
updatePixels();
far=pg3.zbuffer[width/2+((height/2)*width)];
popMatrix();
camera();
background(0);
if(near == MAX_FLOAT || far == MAX_FLOAT)
{
throw new RuntimeException("Near and Far must be positive values, and not clipped");
}
println("Near:" +worldnear+"="+near);
println("Far:" +worldfar+"="+far);
}
float getDepth(float zval)
{
if(zval < near)
return 0;
else if(zval > far)
return 1;
else
{
return (zval-near)/(far-near);
}
}
void doFog(color mistColour)
{
loadPixels();
for(int i=0;i<pixels.length;i++)
{
float a=this.getDepth(pg3.zbuffer[i]);
pixels[i]=cblend(pixels[i],mistColour,a);
}
updatePixels();
}
}
color cblend(color a, color b, float ratio)
{
if(ratio<=0)
return a;
if(ratio>=1)
return b;
float r=red(a)*(1-ratio)+red(b)*ratio;
float g=green(a)*(1-ratio)+green(b)*ratio;
float bl=blue(a)*(1-ratio)+blue(b)*ratio;
return color(r,g,bl);
}
used like:
Code:color mist;
fog f;
void setup()
{
size(400,400,P3D);
f=new fog(400,500,g);
mist=color(128,128,255);
noStroke();
}
void draw()
{
background(0);
fill(255,255,255);
beginShape(TRIANGLES);
vertex(100,100,0);
vertex(300,100,-100);
vertex(300,300,-300);
endShape();
f.doFog(mist);
}
(note the discrpency between fog depth, and object z-coordinate, this is because the camera isn't at 0,0,0, but 0,0,-(something) to mean things at z=0 are on screen)