Java-Gaming.org Hi !
Featured games (91)
games approved by the League of Dukes
Games in Showcase (803)
Games in Android Showcase (237)
games submitted by our members
Games in WIP (867)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Cube outline is see-through  (Read 4779 times)
0 Members and 1 Guest are viewing this topic.
Offline ShadedVertex
« Posted 2015-12-13 08:15:38 »

I was working on outlining 3D cubes in OpenGL and I wanted depth testing to be enabled when drawing the outlines, so that other cubes wouldn't render on top of the outline. When I look to the right using the virtual camera, the stencils are drawn perfectly with the depth testing enabled.

However, when I look to the left, the depth testing for the outlines doesn't really work and you can kind of see through the outlines. I'm using stencil testing for the outlines. The outlines are black.

This is how it looks when I look to the right:

http://i.imgur.com/YA0GDPR.png

And this is how it looks when I look to the left:

http://i.imgur.com/FPQzoIG.png

EDIT: The depth testing for the outlines doesn't work if I look down (X:0, Y:-1, Z:0) or backwards (X:0, Y:0, Z:1).
Offline orange451

JGO Kernel


Medals: 564
Projects: 8
Exp: 8 years


Your face? Your ass? What's the difference?


« Reply #1 - Posted 2015-12-13 08:19:23 »

Do you need to sort the drawing of the cubes based on distance to the camera?

First Recon. A java made online first person shooter!
Offline ShadedVertex
« Reply #2 - Posted 2015-12-13 08:22:42 »

orange451 I draw all the cubes, I don't sort them based on the distance to the camera.

The depth testing for the cubes themselves works. But the outlines are see-through.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline theagentd
« Reply #3 - Posted 2015-12-13 14:22:31 »

How are you trying to draw outlines? From the looks of it you're drawing first a cube and then a slightly scaled up black cube for the outlines, correct? I have an idea what the problem could be, but I'll need to see your code to be sure.

Myomyomyo.
Offline ShadedVertex
« Reply #4 - Posted 2015-12-13 14:23:47 »

You're right! That's exactly what I'm doing, theagentd.
Offline theagentd
« Reply #5 - Posted 2015-12-13 14:24:33 »

Still need to see code to see what stencil function and draw order you're using.

Myomyomyo.
Offline ShadedVertex
« Reply #6 - Posted 2015-12-13 14:26:41 »

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
GL11.glEnable(GL11.GL_CULL_FACE);
GL11.glCullFace(GL11.GL_BACK);
GL11.glEnable(GL11.GL_DEPTH_TEST);
GL11.glEnable(GL11.GL_STENCIL_TEST);
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT|GL11.GL_DEPTH_BUFFER_BIT|GL11.GL_STENCIL_BUFFER_BIT);
GL11.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_REPLACE);
GL11.glClearColor(backgroundColour.getRed(), backgroundColour.getGreen(), backgroundColour.getBlue(), 1);

for(Block b : world.getBlockList()){
            if(b != null){
               GL11.glStencilFunc(GL11.GL_ALWAYS, 1, GL11.GL_TRUE);
               GL11.glStencilMask(0xFF);
               renderer.render(b, blockProgram, cam);
               if(!b.getColour().equals(goalColour)){
                  b.scale(b.getScale().getX() + 0.00002f, b.getScale().getY() + 0.00002f, b.getScale().getZ() + 0.00002f); //this is intentional
                  GL11.glStencilFunc(GL11.GL_NOTEQUAL, 1, GL11.GL_TRUE);
                  GL11.glStencilMask(0x00);
                  b.scale(b.getScale().getX() + 0.002f, b.getScale().getY() + 0.002f, b.getScale().getZ() + 0.002f);
                  Colour colour = b.getColour();
                  b.setColour(Colour.BLACK);
                  renderer.render(b, blockProgram, cam);
                  b.setColour(colour);
                  b.scale(b.getScale().getX() - 0.002f, b.getScale().getY() - 0.002f, b.getScale().getZ() - 0.002f);
               }
            }
         }


I'm looping through the blocks in the world, as you can see. And also, the blocks are supposed to increase in size every frame, so the outlines are adjusted as well. I really need a solution  Cry

EDIT: I am actually clearing the colour, depth and stencil buffer bits, I just forgot to include that. I'm enabling the depth and stencil test too.
Offline theagentd
« Reply #7 - Posted 2015-12-13 14:58:57 »

GL_TRUE is not a "valid" input to glStencilFunc(), but in this case it works since GL_TRUE=1. I'm gonna assume you're setting glStencilOp() to something sane before that loop. My guess at what's happening is that you mark pixels belonging to a cube with the value 1 in the stencil buffer and then try to draw the outline on pixels that are not equal to 1. This means that every time you draw a cube, the pixels it's covering will be marked to 1 for all following cubes too, so even if the outline of a later cube is closer to the camera it will still be removed since the pixel is marked with a 1. What you need to do is to reset the stencil buffer between each cube so that it is all 0s again.

You can do this by adding a glClear(GL_STENCIL_BUFFER_BIT) after you've drawn each box, but this will get slow. Still, try this to confirm that you're on the right track. It'd be faster to use the entire 8-bit precision of the stencil buffer and first mask with 1, then 2 for the second box, 3 for the third, etc until you reach to 256, when you clear the stencil buffer to 0 again. That way you could draw 255 boxes between every clear, but you'd still have a rather big number of clears if you draw lots of boxes.

A faster but less precise way of doing this would be to reset the stencil buffer to 0 when drawing the outline. In the marking pass you mark the pixels with a 1, and in the outline drawing pass you reset them back to 0 again. Since the outline is bigger than the original model, all pixels will get changed back to 0. This could be done like this:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
//glStencilMask() is always set to 0xFF here.

//Render cube
glStencilFunc(GL_ALWAYS, 1, 0xFF);
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); //Mark all pixels that the original box touches the box regardless of depth testing.
renderCube();

//Render outline
glStencilFunc(GL_NOTEQUAL, 0, 0xFF);
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); //Reset all pixels to 0
renderCube();


This has some major drawbacks. It will have artifacts if the box and/or its outline intersects the near plane (pixels won't be reset back to 0), and it also won't work with complex (concave) models that overlap themselves in any way as the first overdraw will reset it to 0 and the second overdraw will be allowed to place the outline over the model itself. For cubes however this is the fastest way.


The best solution by far would be to just use a depth-detecting shader to compute an outline per pixel. This is what most games nowadays (like Borderlands) do.

Myomyomyo.
Offline ShadedVertex
« Reply #8 - Posted 2015-12-13 15:14:21 »

You are awesome. I have nothing else to say. Thanks for taking the time to type all that out Cheesy I really appreciate it...geddit?

Anyway, I tried your different methods but none of them really seemed to work. I played around with the stuff, tried your different solutions, but they either gave the same results, or the entire thing just started bugging out and lagging until it became really slow.

I'm going to keep trying to solve it from different angles. I figure it's something got to do with either the projection matrix or the depth buffer. Thanks, anyway. I really, really appreciate it, because most people don't take as much time as you do to help people out.
Offline theagentd
« Reply #9 - Posted 2015-12-13 16:54:18 »

Adding a stencil clear between every cube+outline draw should solve the problem. Hmm. What do you get if you add that?

Myomyomyo.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline ShadedVertex
« Reply #10 - Posted 2015-12-14 11:05:33 »

It works now. Thanks, man!
Pages: [1]
  ignore  |  Print  
 
 

 
Riven (397 views)
2019-09-04 15:33:17

hadezbladez (5280 views)
2018-11-16 13:46:03

hadezbladez (2204 views)
2018-11-16 13:41:33

hadezbladez (5544 views)
2018-11-16 13:35:35

hadezbladez (1150 views)
2018-11-16 13:32:03

EgonOlsen (4584 views)
2018-06-10 19:43:48

EgonOlsen (5462 views)
2018-06-10 19:43:44

EgonOlsen (3119 views)
2018-06-10 19:43:20

DesertCoockie (4015 views)
2018-05-13 18:23:11

nelsongames (4708 views)
2018-04-24 18:15:36
A NON-ideal modular configuration for Eclipse with JavaFX
by philfrei
2019-12-19 19:35:12

Java Gaming Resources
by philfrei
2019-05-14 16:15:13

Deployment and Packaging
by philfrei
2019-05-08 15:15:36

Deployment and Packaging
by philfrei
2019-05-08 15:13:34

Deployment and Packaging
by philfrei
2019-02-17 20:25:53

Deployment and Packaging
by mudlee
2018-08-22 18:09:50

Java Gaming Resources
by gouessej
2018-08-22 08:19:41

Deployment and Packaging
by gouessej
2018-08-22 08:04:08
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!