Near plane clipping (was: techniques for displaying text)

Started by MichaelJPCT, January 03, 2016, 02:12:42 PM

Previous topic - Next topic

MichaelJPCT

i am trying to do multipass rendering of a single world, dividing a world into near/middle/far parts. render far parts before rendering near parts,  like this:

world.setClippingPlanes(250.0 , 20000.0); world.renderScene(framebuffer); world.draw(framebuffer); framebuffer.clearZBufferOnly(); world.setClippingPlanes(5.0 , 250.0); world.renderScene(framebuffer); world.draw(framebuffer); framebuffer.clearZBufferOnly();
world.setClippingPlanes(0.1 , 5.0); world.renderScene(framebuffer); world.draw(framebuffer)

but the end result is not what i expect. is my method wrong? how can i achieve the multipass effect i described?

EgonOlsen

You might have to set Config.glIgnoreNearPlane to false. But even then, I'm not sure if that does what you want. Why do you want to do that in the first place?

MichaelJPCT

i tried glIgnoreNearPlane to false, but still not right. all scene are messed up.
that multipass thing is to increase the accuracy of Z-buffer, 20000.0 to 0.1 is a very large ratio, the Z-buffer can't distinguish 2 polygons at 10000.0 and 10000.01 for example.
i thought JPCT renderer has a multi-thread nature so something is messed, but i don't know details about the renderer.

EgonOlsen


EgonOlsen

#4
Quote from: MichaelJPCT on January 03, 2016, 04:08:14 PM
that multipass thing is to increase the accuracy of Z-buffer, 20000.0 to 0.1 is a very large ratio, the Z-buffer can't distinguish 2 polygons at 10000.0 and 10000.01 for example.
Is that really an issue in your case? Usually, depth buffers are w-buffers anyway, i.e. they are more accurate near the camera than far away and that's for good reason. If your scene is setup in a way, that it's important to distinguish between 10000.0 and 10000.01, I would say that the scene setup should be improved instead.


EgonOlsen

In that case, it's not multi-threaded unless you set Config.useMultipleThreads to true.

MichaelJPCT

i have a doubt that in JPCT RenderScene method there is a glFrustum call.
the parameters for glFrustum are (left,right,bottom,top,zNear,zFar), where (left,right,bottom,top) should all be multiplied by zNear. but JPCT assumes zNear to be 1 and (left,right,bottom,top) are not multiplied. so the resulting projection matrix is wrong.

for me, using hardware processing power to increase accuracy is a much easier solution than optimizing the scene, so i chose multipass rendering.

EgonOlsen

No, there is no glFrustum call in renderScene. There's one in draw (at least if the frustum changes). And it doesn't assume that zNear is 1, if you set Config.glIgnoreNearPlane to false.
However, you are right about the multiplication with zNear. It doesn't do that (anymore) and looking at the source code, that's on purpose. The code that once did that has been commented out in 2012 and replaced by a method in Camera that adjusts the fov instead (Camera.adjustFovToNearPlane()). However, this method has an issue, if you are using setClippingPlanes() instead of the setters in Config ATM. I'll fix this and report back.
I really don't remember, why I did it in this crude way. I do remember that I wasn't really happy with this solution, but that I had to do it for some reason and that I assumed that it wouldn't be an issue for most people anyway. And that's actually true, because in 3 years, you are the first user who asked about it.

Anyway, I'll look into the issue mentioned above and report back.


EgonOlsen

OK, this should fix it: http://jpct.de/download/beta/jpct.jar

But as said, you have to adjust the Fov by calling the mentioned method instead of letting jPCT do the multiplication internally as it actually should. Anyway, there was a reason that I can't remember and I don't want to go through it all again. Here'a a modified HelloWorld example that shows how to use this:


import java.awt.Color;

import com.threed.jpct.Camera;
import com.threed.jpct.Config;
import com.threed.jpct.FrameBuffer;
import com.threed.jpct.IRenderer;
import com.threed.jpct.Object3D;
import com.threed.jpct.Primitives;
import com.threed.jpct.Texture;
import com.threed.jpct.TextureManager;
import com.threed.jpct.World;

public class HelloWorldMultipass {

private World world;

private FrameBuffer buffer;

private Object3D box;

public static void main(String[] args) throws Exception {
new HelloWorldMultipass().loop();
}

public HelloWorldMultipass() throws Exception {
Config.glIgnoreNearPlane = false;

world = new World();
world.setAmbientLight(100, 100, 100);

TextureManager.getInstance().addTexture("box", new Texture("box.jpg"));

box = Primitives.getBox(13f, 2f);
box.calcTextureWrapSpherical();
box.setTexture("box");
box.setEnvmapped(Object3D.ENVMAP_ENABLED);
box.build();
box.compile();
world.addObject(box);

world.getCamera().setPosition(0, 0, -100);
world.getCamera().lookAt(box.getTransformedCenter());
}

private void loop() throws Exception {

buffer = new FrameBuffer(800, 600, FrameBuffer.SAMPLINGMODE_GL_AA_2X);
buffer.disableRenderer(IRenderer.RENDERER_SOFTWARE);
buffer.enableRenderer(IRenderer.RENDERER_OPENGL);

Camera cam=world.getCamera();
cam.setFOV(1.5f);

while (!org.lwjgl.opengl.Display.isCloseRequested()) {

box.rotateY(0.01f);
buffer.clear(java.awt.Color.BLUE);

// First pass
box.setAdditionalColor(null);
world.setClippingPlanes(1, 90);
cam.adjustFovToNearPlane(world);
world.renderScene(buffer);
world.draw(buffer);

// Second pass
box.setAdditionalColor(Color.RED);
world.setClippingPlanes(90, 95);
cam.adjustFovToNearPlane(world);
world.renderScene(buffer);
world.draw(buffer);

// Third pass
box.setAdditionalColor(Color.GREEN);
world.setClippingPlanes(95, 1000);
cam.adjustFovToNearPlane(world);
world.renderScene(buffer);
world.draw(buffer);

buffer.update();
buffer.displayGLOnly();

Thread.sleep(10);
}
buffer.disableRenderer(IRenderer.RENDERER_OPENGL);
buffer.dispose();
System.exit(0);
}

}



Hope this helps.

MichaelJPCT

that works , thanks.
but beware, this also affects texture blitting. i added an empty world and set the nearclip to 1, in order to reset the matrix for 2D blitting.

EgonOlsen

Yes, it affects blitting and the blitting method itself should actual deal with it...and it does. But again, this doesn't work properly, if you set the planes via World and not directly in Config. I'll look into it, sorry for the inconvenience.

MichaelJPCT

no need for sorry. i found this to be useful - i can scale the whole 2D blitted image by setting the nearclip of the world before blitting. don't need to recalculate the size and position of every blit call.

EgonOlsen

#13
Interesting method... ;)...but I've actually fixed the behaviour now. But I guess that this will break your trick, or won't it? Anyway, fixed version is here: http://jpct.de/download/beta/jpct.jar

MichaelJPCT

it would be better if texture blitting as well as 3D objects has tree-like hierachy which pass translations including move, scale, rotation and show/hide states. so everything can be managed in groups.