|
From: James W. <ja...@fr...> - 2009-08-22 00:52:00
|
I thought I was correctly handling transparency with multiple lighting passes in QORenderer::Renderer::RenderTransparent, but it turns out that in some cases it can be visibly incorrect. I'll try to explain a simplified scenario. Suppose we have an nearly-opaque object with color A, and in front of that there is a transparent object with color B. There are 2 lighting passes, contributing brightnesses L and M respectively. Then the resulting color value ought to be B*(L+M) + (1-alpha)*A*(L+M). But if we have to handle the lights in different passes, the first pass produces B*L + (1-alpha)*A*L. If we use glBlendFunc( GL_ONE, GL_ONE ) in the second pass, as RenderTransparent currently does, then we just add B*M + A*M, resulting in a total of B*(L+M) + (1-alpha)*A*L + A*M, which has too much contribution from A. I don't see that any choice of blend function will produce the right result in all cases. In many cases where I use a texture with an alpha channel, the alpha channel is pretty much either 1 or 0. In such a case, I think there would be pretty good results if we turned on the alpha test, and let opaque pixels write to the depth buffer, and didn't use blending. Thoughts? -- James W. Walker, Innoventive Software LLC <http://www.frameforge3d.com/> |
|
From: James W. <ja...@fr...> - 2009-08-22 01:05:39
|
James Walker wrote: > > In many cases where I use a texture with an alpha channel, the alpha > channel is pretty much either 1 or 0. In such a case, I think there > would be pretty good results if we turned on the alpha test, and let > opaque pixels write to the depth buffer, and didn't use blending. Oops, I shouldn't have said "didn't use blending" there. Blending, with glBlendFunc( GL_ONE, GL_ONE ), would still need to be used to add up the contributions of the lighting passes. -- James W. Walker, Innoventive Software LLC <http://www.frameforge3d.com/> |
|
From: Roger H. <rog...@mi...> - 2009-08-22 09:22:05
|
On 22 Aug 2009, at 01:25, James Walker wrote: > I thought I was correctly handling transparency with multiple lighting > passes in QORenderer::Renderer::RenderTransparent, but it turns out > that > in some cases it can be visibly incorrect. I'll try to explain a > simplified scenario. > > Suppose we have an nearly-opaque object with color A, and in front of > that there is a transparent object with color B. There are 2 lighting > passes, contributing brightnesses L and M respectively. Then the > resulting color value ought to be B*(L+M) + (1-alpha)*A*(L+M). For the diffuse component of the lighting, shouldn't that be alpha*B*(L +M) + (1-alpha)*A*(L+M) ? As my renderers are pure software ones, I'm not familiar with glBlendFunc so cannot comment on that but maybe it supports my version of the formula. The specular component is just added on, not being affected by the alpha. Roger |
|
From: James W. W. <os...@jw...> - 2009-08-22 16:52:04
|
On Aug 22, 2009, at 1:48 AM, Roger Holmes wrote: > > On 22 Aug 2009, at 01:25, James Walker wrote: > >> I thought I was correctly handling transparency with multiple >> lighting >> passes in QORenderer::Renderer::RenderTransparent, but it turns out >> that >> in some cases it can be visibly incorrect. I'll try to explain a >> simplified scenario. >> >> Suppose we have an nearly-opaque object with color A, and in front of >> that there is a transparent object with color B. There are 2 >> lighting >> passes, contributing brightnesses L and M respectively. Then the >> resulting color value ought to be B*(L+M) + (1-alpha)*A*(L+M). > > For the diffuse component of the lighting, shouldn't that be > alpha*B*(L > +M) + (1-alpha)*A*(L+M) ? I was assuming premultiplied alpha. > As my renderers are pure software ones, I'm not familiar with > glBlendFunc so cannot comment on that but maybe it supports my version > of the formula. Maybe your renderer doesn't have a limit of 8 lights, so you don't need multiple passes. > The specular component is just added on, not being affected by the > alpha. I was omitting specular for simplicity. |
|
From: Roger H. <rog...@mi...> - 2009-08-24 12:35:04
|
On 22 Aug 2009, at 17:25, James W. Walker wrote: > > On Aug 22, 2009, at 1:48 AM, Roger Holmes wrote: > >> >> On 22 Aug 2009, at 01:25, James Walker wrote: >> >>> I thought I was correctly handling transparency with multiple >>> lighting >>> passes in QORenderer::Renderer::RenderTransparent, but it turns out >>> that >>> in some cases it can be visibly incorrect. I'll try to explain a >>> simplified scenario. >>> >>> Suppose we have an nearly-opaque object with color A, and in front >>> of >>> that there is a transparent object with color B. There are 2 >>> lighting >>> passes, contributing brightnesses L and M respectively. Then the >>> resulting color value ought to be B*(L+M) + (1-alpha)*A*(L+M). >> >> For the diffuse component of the lighting, shouldn't that be >> alpha*B*(L >> +M) + (1-alpha)*A*(L+M) ? > > > I was assuming premultiplied alpha. I see. I always try to keep the alpha channel separate. The saving in time is rather small in 3D. > > >> As my renderers are pure software ones, I'm not familiar with >> glBlendFunc so cannot comment on that but maybe it supports my >> version >> of the formula. > > > Maybe your renderer doesn't have a limit of 8 lights, so you don't > need multiple passes. No limit, but to store all the shadow depth buffers I do have to use multiple passes when there is insufficient memory to store them. I also sometimes have to band the image when high resolution/large image/ anti-aliasing. Separate scan lines can be done in separate processors if available. Must do a 64 bit version sometime. > > >> The specular component is just added on, not being affected by the >> alpha. > > > > I was omitting specular for simplicity. OK. > > ------------------------------------------------------------------------------ > Let Crystal Reports handle the reporting - Free Crystal Reports 2008 > 30-Day > trial. Simplify your report design, integration and deployment - and > focus on > what you do best, core application coding. Discover what's new with > Crystal Reports now. http://p.sf.net/sfu/bobj-july > _______________________________________________ > Quesa-develop mailing list > Que...@li... > https://lists.sourceforge.net/lists/listinfo/quesa-develop |
|
From: James W. W. <os...@jw...> - 2009-08-23 16:49:09
|
It occurs to me that a possible solution is to use the accumulation buffer, rather than blending, to add the contributions of multiple lighting passes. |
|
From: Roger H. <rog...@mi...> - 2009-08-24 12:39:31
|
On 23 Aug 2009, at 17:48, James W. Walker wrote: > It occurs to me that a possible solution is to use the accumulation > buffer, rather than blending, to add the contributions of multiple > lighting passes. As long as your accumulation buffer has enough precision. Gut feeling is for each component, floats or maybe 16 bit fixed would be OK but 8 bits might show artefacts which should not be there. Roger. |
|
From: James W. <ja...@fr...> - 2009-08-24 18:19:05
|
Roger Holmes wrote: > On 23 Aug 2009, at 17:48, James W. Walker wrote: > >> It occurs to me that a possible solution is to use the accumulation >> buffer, rather than blending, to add the contributions of multiple >> lighting passes. > > As long as your accumulation buffer has enough precision. Gut feeling > is for each component, floats or maybe 16 bit fixed would be OK but 8 > bits might show artefacts which should not be there. Good point. I'm also a little concerned about how using the accumulation buffer might affect speed. I've committed a hack to mostly solve my immediate problem. This change only changes the behavior of the OpenGL renderer if you have set kQ3RendererPropertyDepthAlphaThreshold. I may still experiment with the accumulation buffer scheme. -- James W. Walker, Innoventive Software LLC <http://www.frameforge3d.com/> |