Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (517)
Games in Android Showcase (123)
games submitted by our members
Games in WIP (578)
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  
  Drawing a transparent Image over another while using the depth buffer  (Read 2459 times)
0 Members and 1 Guest are viewing this topic.
Offline R.D.

Senior Duke


Medals: 2
Projects: 1


"For the last time, Hats ARE Awesome"


« Posted 2011-11-18 19:47:43 »

This started in the Slick2D forum but turned out to be an OpenGl problem so I guess making a topic here will help get an answer fast since I have to ship the game in 9 weeks Cheesy

So, I draw my map using the depth buffer and it works just fine, so I can draw my player in between after drawing each layer of the gray scale map. This too works fine but now i have a problem.
I want to blend in a color version of the map to achieve the effect of a world which gets grey and stuff. The problem is, if I turn on DEPHT_TEST, the Blending -of course- does not work probatly anymore Sad
There is there a way to make this work or do I need to think of some fancy other stuff for it? (For sprites I used sorting but I also found the way to slow and the depth buffer is using this whole stuff fro free!)
Offline Orangy Tang

JGO Kernel


Medals: 56
Projects: 11


Monkey for a head


« Reply #1 - Posted 2011-11-18 20:03:57 »

The problem is, if I turn on DEPHT_TEST, the Blending -of course- does not work probatly anymore Sad

I think you're going to have to explain what 'not work properly' actually means, otherwise we're grasping at straws a little.

Wild guess: you want to leave DEPTH_TEST enabled, but disable actually updating the depth buffer when drawing transparent pixels, so do that with glDepthMask(false). Remember to put it back to glDepthMask(true) once you've finished with your transparent stuff.

[ TriangularPixels.com - Play Growth Spurt, Rescue Squad and Snowman Village ] [ Rebirth - game resource library ]
Offline R.D.

Senior Duke


Medals: 2
Projects: 1


"For the last time, Hats ARE Awesome"


« Reply #2 - Posted 2011-11-18 23:10:05 »

Argh sorry, was too upset :p

Okay, so what's not working is that the transparent image that should be drawn over the normal want just does not appear until the scale value (which alters the alpha) reaches 1.0f. Until then the texture simply will stay invisible Sad

I will try your idea when I'm working at it tomorrow but I won't have internet until sunday so it might take a bit before I answer Smiley Thanks for the help!
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline R.D.

Senior Duke


Medals: 2
Projects: 1


"For the last time, Hats ARE Awesome"


« Reply #3 - Posted 2011-11-19 12:41:47 »

Okay, tested it with glDepthMask(); but that did not do the trick Sad

Maybe I schould explain with code what I'm doing.
So I have an image which will be drawn by Slick2D the code their does this:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
   texture.bind();
   glTranslatef(x, y, 0);
     
   glBegin(SGL.GL_QUADS);
      glTexCoord2f(textureOffsetX, textureOffsetY);
      glVertex3f(x, y, 0);
      glTexCoord2f(textureOffsetX, textureOffsetY + textureHeight);
      glVertex3f(x, y + height, 0);
      glTexCoord2f(textureOffsetX + textureWidth, textureOffsetY + textureHeight);
      glVertex3f(x + width, y + height, 0);
      glTexCoord2f(textureOffsetX + textureWidth, textureOffsetY);
      glVertex3f(x + width, y, 0);
   glEnd();
   glTranslatef(-x, -y, 0);


So I can't see any problems here. It's does draw the image at a position. Now I'm using this code to enter the depth buffer:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
   public static void enterDepthTest() {
      if(!inDepth) {
         lastDepth = 0;
         GL11.glDisable(GL11.GL_BLEND);
         GL11.glEnable(GL11.GL_DEPTH_TEST);
         GL11.glEnable(GL11.GL_ALPHA_TEST);
         GL11.glAlphaFunc(GL11.GL_GEQUAL, 1f);
         GL11.glDepthFunc(GL11.GL_LEQUAL);
         inDepth = true;
      }
   }


then I use this to set the depth:
1  
2  
3  
4  
5  
   public static void setDepth(float depth) {
      GL11.glTranslatef(0, 0, -lastDepth);
      lastDepth = depth;
      GL11.glTranslatef(0, 0, lastDepth);
   }


I draw the first image at setDepth(-0.1f);and the second at the same postion and the same depth, so the last one will be drawn over the first one. For the second one I also included this line:
1  
glColor4f(1, 1, 1, scale);


Where scale tells me how much of the second image should be seen (Or am I wrong here?).

And finally I leave the depth buffer with this code:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
   public static void leaveDepthTest() {
      if(inDepth) {
         lastDepth = 0;
         GL11.glDisable(GL11.GL_ALPHA_TEST);
         GL11.glDisable(GL11.GL_DEPTH_TEST);
         GL11.glEnable(SGL.GL_BLEND);
         GL11.glColorMask(true, true, true, true);
         GL11.glBlendFunc(SGL.GL_SRC_ALPHA, SGL.GL_ONE_MINUS_SRC_ALPHA);
         inDepth = false;
      }
   }


If and I don't use the enter- and leaveDeothTest code then everything works as plant, but as said I can't draw stuff between layer then Sad
Offline theagentd
« Reply #4 - Posted 2011-11-19 13:19:56 »

You won't ever be able to achieve blending "between layers" like you're asking for with a normal z-buffer. That's because the z-buffer only stores the closest z-value, not the z-value of individual "layers". When you draw with blending, it just blends it with whatever color is already there if it passes the depth test.

Do you even know what the alpha testing does? It removes pixels which do not pass the alpha test, similar to how the depth test removes pixels that do not pass the depth test. You've enabled alpha testing with the GL_GEQUAL func with the value 1f. That means that only fragments that have an alpha of 1 or greater will pass. If you pass 0.9999f to alpha in glColor4f, all fragments will fail the alpha test and you won't get anything on your screen.

The idea of the z-buffer is that you shouldn't have to sort things from back to front. This works perfectly for opaque (alpha = 1) geometry, but it does NOT work with transparency.

To get what you want.
1. Enable depth testing and depth writing
2. Draw everything that is opaque (alpha = 1)
3. Sort your transparent surfaces based on their depth, with the ones the furthest away first.
4. Keep depth testing enabled but disable depth WRITING, and draw your transparent surfaces.

Myomyomyo.
Offline loom_weaver

JGO Coder


Medals: 17



« Reply #5 - Posted 2011-11-19 16:53:06 »

Hey OP, I feel your pain.

I wanted both depth-testing and alpha-blending but for technical reasons described by theagentd it just isn't possible to do both at once.

In my game I ended up sorting all objects manually and basically used a painters algorithm.
Offline theagentd
« Reply #6 - Posted 2011-11-19 19:21:22 »

There are several features of OpenGL that you can use besides the one I listed before that doesn't require sorting of the things you draw, but they are either dead slow or low quality compared to simply sorting them.

There's deep rendering / depth peeling, which is more what OP was assuming the z-buffer was doing. You basically route the drawing to different depth buffers and color buffers, and then sort them when everything is rendered. This obviously requires insane amounts of memory, and the number of overdraws is limited to the number of layers you use. The only really viable method of doing this is to use a multisampled buffer and route the drawn pixels to different samples by disabling multisampling and using the stencil test. The stencil test is still executed for each sample, as we have still have a multisampled buffer. We can then read all the samples in a shader at the end, and sort and blend them correctly. This is obviously limited to the number of samples the system supports, which is 8 at best. That means you can have 8 overlapping primitives, and if you have more than that they are simply discarded. This is obviously incompatible with multisampling antialiasing as it uses the same buffers. This has pretty good performance, at least with 4 samples.

There's also a new feature specifically designed for this problem where each pixel is basically a linked list of samples. The actual samples are stored in a huge data buffer unordered, and each pixels holds pointers to these samples. That means that the number of samples you have is limited by the data buffer size, and not for each pixel. For example you can have all 100 samples in one pixel, or 5 samples on every pixel. However, this method is so slow that if you have 2 full screen primitives, you'll get under 60 FPS on mainstream hardware, so it's basically unusable.

In the end, good old sorting is the way to go. Considering OP is doing a 2.5D game it makes no sense to use more advanced techniques, especially when sorting is this easy.

Myomyomyo.
Offline R.D.

Senior Duke


Medals: 2
Projects: 1


"For the last time, Hats ARE Awesome"


« Reply #7 - Posted 2011-11-20 17:02:36 »

Thanks theagentd! I actually hoped that you would say something to my problem and I was right Cool I used the alpha test for transparencies in the image itself because it kinda did not work without it but your right, it's dull in this szenario Sad My Super Bible told me already that blending and depth test is not working very well but I hoped that maybe there is way Cheesy Thanks for explaining it anyway I really like to read your explanations to be honest xD
 
I already changed it to a listener based system, where I call the listener when one layer has been drawn on the screen and the sort my sprites which are on that layer. I did that first i have to say but I just thought maybe there is a chance to make it work xD

So problem kinda solved, I'm not sure if I should mark this Thread solved so I leave like it is now Cool
Offline theagentd
« Reply #8 - Posted 2011-11-20 18:23:04 »

GLaD to help!  Grin

Myomyomyo.
Online ra4king

JGO Kernel


Medals: 353
Projects: 3
Exp: 5 years


I'm the King!


« Reply #9 - Posted 2011-11-20 19:40:15 »

I see what you did there Wink

Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

DarkCart (6 views)
2014-10-31 21:44:48

DarkCart (7 views)
2014-10-31 21:43:57

TehJavaDev (38 views)
2014-10-27 03:28:38

TehJavaDev (29 views)
2014-10-27 03:27:51

DarkCart (43 views)
2014-10-26 19:37:11

Luminem (24 views)
2014-10-26 10:17:50

Luminem (29 views)
2014-10-26 10:14:04

theagentd (35 views)
2014-10-25 15:46:29

Longarmx (63 views)
2014-10-17 03:59:02

Norakomi (61 views)
2014-10-16 15:22:06
Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06
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!