Author Topic: Post-processing on a single world  (Read 1582 times)

Offline atreyu64

  • byte
  • *
  • Posts: 44
    • View Profile
Post-processing on a single world
« on: February 27, 2014, 12:57:35 am »
Hi,

I'm trying to make a neon light like effect on some polylines ONLY, using the mighty BloomGLProcessor class.
For this I've created a special world for polylines, which I draw first, then launch post-process, and finally draw my main world.

So basically this is how I'm rendering things :

Code: [Select]
// polylines first :
linesWorld.renderScene(fb);
linesWorld.draw(fb);
bloomProcessor.process();

// main scene :
world.renderScene(fb);
world.draw(fb);

The problem is that I don't get what I expected, the blur effect is not visible after drawing the main world.
Is there a solution ? Thanks in advance !  ;D


Here is my normal scene before trying anything stupid :

Without bloom par atreyu64, sur Flickr

Trying to make the bloom on polyline as explained above :


Polylines and World par atreyu64, sur Flickr

Displaying only the polyline world (with post-processing) :


Polylines only par atreyu64, sur Flickr

What I would like to get (made with Photoshop) :

What I Want par atreyu64, sur Flickr
« Last Edit: February 27, 2014, 01:10:19 am by atreyu64 »

Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 11746
    • View Profile
    • http://www.jpct.net
Re: Post-processing on a single world
« Reply #1 on: February 27, 2014, 07:47:00 am »
That's because the blur is a post process. It writes into the color buffer but not into the depth buffer (it can't...). So when rendering another world on top of the result, it will still consider the depth buffer from the actual rendering, but the blurred parts will be overdrawn. I think it should be pretty easy to modify the bloom processor in a way that you can delay the actual combination of the bloomed buffer with the final image. That should do the trick...i'll look into it later.

Offline AGP

  • quad
  • ******
  • Posts: 1516
    • View Profile
Re: Post-processing on a single world
« Reply #2 on: February 27, 2014, 08:26:20 am »
I have a glsl 4 shader for a sort of bloom effect, but it hasn't been working, I think, because the grammar is of too new a version. If it worked it would solve his problem. Here it goes.

Code: [Select]
#version 400

in vec3 TexCoord;
layout (location = 0) out vec4 FragColor;

uniform BlobSettings {
     vec4 innerColor;
     vec4 outerColor;
     float radiusInner;
     float radiusOuter;
};
void main() {
     float deltaX = TexCoord.x -.5;
     float deltaY = TexCoord.y -.5;
     float distance = sqrt(deltaX*deltaX +deltaY*deltaY);


     FragColor = mix (innerColor, outerColor, smoothstep(radiusInner, radiusOuter, distance));
}

#version 400

layout (location = 0) in vec3 VertexPosition;
layout (location = 1) in vec3 VertexTexCoord;

out vec3 TexCoord;

void main() {
     TexCoord = VextexTexCoord;
     gl_Position = vec4(VertexPosition, 1.0);
}

Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 11746
    • View Profile
    • http://www.jpct.net
Re: Post-processing on a single world
« Reply #3 on: February 27, 2014, 08:46:57 am »
If it doesn't work, it's a problem with your hardware or driver. The engine doesn't care about the glsl version as long as the driver can compile it. Aynway, i think that adding this would be too much of a hassle. Tweaking the bloom processor should be much simpler.

Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 11746
    • View Profile
    • http://www.jpct.net
Re: Post-processing on a single world
« Reply #4 on: February 27, 2014, 08:52:23 am »
...and apart from that, it won't solve the actual problem. A bloom shader is also just a post processing step on some image rendered into a texture. It has the same issues as the bloom processor has with the fixed function pipeline.

Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 11746
    • View Profile
    • http://www.jpct.net
Re: Post-processing on a single world
« Reply #5 on: February 27, 2014, 09:20:18 pm »
It wasn't as easy as i thought, because you have to take the depth buffer into account. The result seems to work:



...but isn't really intuitive to use. Here's the jar: http://jpct.de/download/beta/jpct.jar

and here's a simple example of how to use it:

Code: [Select]
import java.awt.Color;

import org.lwjgl.opengl.Display;

import com.threed.jpct.Camera;
import com.threed.jpct.FrameBuffer;
import com.threed.jpct.IRenderer;
import com.threed.jpct.Object3D;
import com.threed.jpct.Polyline;
import com.threed.jpct.SimpleVector;
import com.threed.jpct.World;
import com.threed.jpct.procs.BloomGLProcessor;
import com.threed.jpct.util.ExtendedPrimitives;
import com.threed.jpct.util.Light;

public class PolylineTest {

/**
* @param args
*/
public static void main(String[] args) throws Exception {
FrameBuffer buffer = new FrameBuffer(1024, 768, FrameBuffer.SAMPLINGMODE_GL_AA_4X);
buffer.disableRenderer(IRenderer.RENDERER_SOFTWARE);
buffer.enableRenderer(IRenderer.RENDERER_OPENGL);

World world = new World();
Object3D obj = ExtendedPrimitives.createCube(10);
world.addObject(obj);

World linesWorld = new World();

Light light = new Light(world);
light.setAttenuation(-1);
light.setPosition(new SimpleVector(100, 100, 0));
light.setIntensity(255, 0, 0);
obj.build();
obj.compile();

float d = 7f;

SimpleVector[] sv = new SimpleVector[5];
sv[0] = new SimpleVector(-d, -d, d);
sv[1] = new SimpleVector(d, -d, d);
sv[2] = new SimpleVector(d, d, d);
sv[3] = new SimpleVector(-d, d, d);
sv[4] = new SimpleVector(-d, -d, d);

Polyline lines = new Polyline(sv, Color.WHITE);
lines.setParent(obj);
lines.setWidth(10);
linesWorld.addPolyline(lines);

sv = new SimpleVector[5];
sv[0] = new SimpleVector(-d, -d, -d);
sv[1] = new SimpleVector(d, -d, -d);
sv[2] = new SimpleVector(d, d, -d);
sv[3] = new SimpleVector(-d, d, -d);
sv[4] = new SimpleVector(-d, -d, -d);

lines = new Polyline(sv, Color.WHITE);
lines.setParent(obj);
lines.setWidth(10);
linesWorld.addPolyline(lines);

sv = new SimpleVector[5];
sv[0] = new SimpleVector(-d, -d, d);
sv[1] = new SimpleVector(-d, -d, -d);
sv[2] = new SimpleVector(-d, d, -d);
sv[3] = new SimpleVector(-d, d, d);
sv[4] = new SimpleVector(-d, -d, d);

lines = new Polyline(sv, Color.WHITE);
lines.setParent(obj);
lines.setWidth(10);
linesWorld.addPolyline(lines);

sv = new SimpleVector[5];
sv[0] = new SimpleVector(d, -d, d);
sv[1] = new SimpleVector(d, -d, -d);
sv[2] = new SimpleVector(d, d, -d);
sv[3] = new SimpleVector(d, d, d);
sv[4] = new SimpleVector(d, -d, d);

lines = new Polyline(sv, Color.WHITE);
lines.setParent(obj);
lines.setWidth(10);
linesWorld.addPolyline(lines);

linesWorld.setCameraTo(world.getCamera());
world.getCamera().moveCamera(Camera.CAMERA_MOVEOUT, 50);

while (!buffer.isInitialized()) {
Thread.sleep(100);
}

BloomGLProcessor bloom = new BloomGLProcessor(1, 4, 5, 2);
buffer.addPostProcessor(bloom);
bloom.setDelayed(true);

while (!Display.isCloseRequested()) {
// First render the actual world to fill the zbuffer and let the
// processor take a snapshot of the result
buffer.clear(Color.BLACK);
world.renderScene(buffer);
world.draw(buffer);
bloom.snapshot();

// Then render the line world and apply the blur...but only to the
// back buffer of the processor because it's delayed.
// Make sure to clear the color but not the depth buffer.
buffer.clearColorBufferOnly(Color.BLACK);
linesWorld.renderScene(buffer);
linesWorld.draw(buffer);
buffer.runPostProcessors();

// Now combine the snapshot with the blurred image.
bloom.render();

buffer.update();
buffer.displayGLOnly();
obj.rotateX(0.01f);
obj.rotateY(0.01f);
}
}

}

Normal usage of the BloomGLProcessor shouldn't be affected. The new methods are setDelayed(<boolean>), snapshot(), and render().
« Last Edit: February 27, 2014, 11:24:45 pm by EgonOlsen »

Offline atreyu64

  • byte
  • *
  • Posts: 44
    • View Profile
Re: Post-processing on a single world
« Reply #6 on: February 27, 2014, 10:39:36 pm »
That is perfect, works like a charm, thank you so much !
Is (or will) it be also available on JPCT AE ?

By the way, what is the Polyline.setParent(Object3D) method for ? Just to make the polyline follow the parent object when moving ?

Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 11746
    • View Profile
    • http://www.jpct.net
Re: Post-processing on a single world
« Reply #7 on: February 27, 2014, 11:08:24 pm »
Is (or will) it be also available on JPCT AE ?

By the way, what is the Polyline.setParent(Object3D) method for ? Just to make the polyline follow the parent object when moving ?
ATM, there's no BloomGLProcessor for the Android version. I didn't port it because it would eat up a lot of fill rate and would be too slow in it's current form. One would have to implement the same thing via shaders, but i haven't done that yet.

The setParent() method has been added on demand yesterday. Yes, it makes the polyline inherit the parent object's transformations.

Offline AGP

  • quad
  • ******
  • Posts: 1516
    • View Profile
Re: Post-processing on a single world
« Reply #8 on: February 28, 2014, 04:51:20 am »
Again, try my shader. If it works, use it for AE. I got the shader off a book.

Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 11746
    • View Profile
    • http://www.jpct.net
Re: Post-processing on a single world
« Reply #9 on: February 28, 2014, 07:32:45 am »
Again, try my shader. If it works, use it for AE. I got the shader off a book.
The shader is only one part...and that one in particular does...something...but most likely not what you would need for this. There's no actual texture sampler being used. All it seems to do is to blend two fixed colors together based on the distance between some texture coordinates. Do you have a screen shot of the result? There's no way that this thing alone takes the actual scene into account...