Jump to content

  • Log In with Google      Sign In   
  • Create Account

Interested in a FREE copy of HTML5 game maker Construct 2?

We'll be giving away three Personal Edition licences in next Tuesday's GDNet Direct email newsletter!

Sign up from the right-hand sidebar on our homepage and read Tuesday's newsletter for details!


We're also offering banner ads on our site from just $5! 1. Details HERE. 2. GDNet+ Subscriptions HERE. 3. Ad upload HERE.


OIT with weighted average


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
2 replies to this topic

#1 EarthBanana   Members   -  Reputation: 958

Like
0Likes
Like

Posted 21 April 2013 - 12:56 AM

I have decided to switch my engine to OIT for a couple reasons - mainly because of my map styles. I just don't really like sorting geometry much - and the results are never pixel perfect.. anyways after looking at depth peeling, dual depth peeling, a-buffer, weighted average, and weighted sum techniques I decided on weighted average.

 

I'm a bit confused on the logistics of implementing it - in the white paper (Bavoil and Myers 2008) it states

 

"The average RGBA color for each pixel is generated by rendering the transparent geometry
into an accumulation buffer implemented as a 16-bit floating-point texture. The result is an

accumulated RGBA color and the number of fragments per pixel (depth complexity) "

 

So - I'm already using a deferred shading engine - generating another texture is not a big deal - what I don't quite understand is how to write the average RGBA color and number of fragments per pixel to a 16 bit floating point texture.

 

Here's where I'm a bit confused:

 

This may be silly - but from my understanding.. for each fragment I would add the current RGBA color to the 16 bit texture  -

 

My first question is how do I do this? Do I just set glBlendEquation to GL_FUNC_ADD and glBlendFunc(GL_ONE, GL_ONE)?

 

My second question is how do I save the depth complexity to the 16 bit texture also? The only way I can think to do it is making another texture and adding 1 to every texel that I pass over in the fragment shader (with the blend mode set as above)

 

Any insight to how to do this would be appreciated - thanks



Sponsor:

#2 Tsus   Members   -  Reputation: 1048

Like
1Likes
Like

Posted 21 April 2013 - 08:54 AM

Hi,

 

Your suggestion is already the solution. So, yeah, you got it right. I'll summarize the steps briefly for you:


Your transparent rendering would happen in the rendering loop after the deferred pass:

  1. Fill your deferred buffer (color, depth, …)
  2. Do the deferred lighting
  3. Render the transparent objects

For the last step, do the following:

  1. Disable depth writing (glDepthMask) -> we want no transparent object to be culled by other transparent objects
  2. Enable depth test (glDepthTest) -> compare with your deferred depth buffer (cull by opaque geometry)
  3. Use additive blending (source: GL_ONE, dest: GL_ONE)
  4. Bind two new render targets; let’s call them AccumColors (four (half) float components) and AccumCount (single float component)
  5. Render the transparent objects into those two targets (explained in a moment)
  6. Bind deferred color buffer as render target
  7. Disable depth test (glDepthTest)
  8. Use back-to-front blending (source: GL_ONE_MINUS_SRC_ALPHA, dest: GL_SRC_ALPHA)
  9. Bind AccumColor and AccumCount as textures
  10. Full screen pass: compute the average color/transparency (explained in a moment) and blend with the deferred color buffer

The idea is to compute the average of the colors, weighted by their transparencies. For blending with the background, we additionally need the average opacity. (FYI: I assume that alpha = 1 means opaque, and alpha = 0 means transparent)

 

Step 5 computes the sums. This is what the fragment shader does:

Input: vec3 color, float alpha
Output: 
  AccumColor = vec4(color*alpha, alpha);  // color multiplied (=weighted) with alpha!
  AccumCount = 1;

 

Step 10 compute the average color. Again, the fragment shader:

Input: vec4 AccumColor, float AccumCount

if (AccumCount < 0.00001 || AccumColor.w < 0.00001)
{
  discard;  // nothing here; discard the fragment.
}
else
{
  vec4 avgColor = vec4(
  AccumColor.xyz / AccumColor.w,    // weighted average color
  AccumColor.w / AccumCount);        // average alpha
  // the alpha, used to blend with the background is computed by assuming 
  // that all transparent layers have the average alpha:
  float dstAlpha = 1-pow(max(0,1-avgColor.w), AccumCount);
  // write out the average color and the alpha, used for compositing
  result = vec4 (avgColor.xyz, dstAlpha);
}

Hope that gives some insights. smile.png

Best regards!


 


Edited by Tsus, 29 April 2013 - 10:04 AM.


#3 EarthBanana   Members   -  Reputation: 958

Like
0Likes
Like

Posted 21 April 2013 - 11:11 AM

Wow - that is literally exactly what I was looking for. Thanks for taking the time to write that out - this should be fairly simple to implement. I will post a picture when I get it working.. should be tomorrow.

 

Thanks again! Great explanation






Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS