Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Transparency #589

Open
wants to merge 40 commits into
base: master
Choose a base branch
from
Open

Transparency #589

wants to merge 40 commits into from

Conversation

psieg
Copy link
Contributor

@psieg psieg commented Apr 21, 2014

We should have done this earlier....
Here comes Order Independent Transparency using Weighted Average
Because we use instancing etc it was not possible to directly use the glow implementation, but most is stolen from there.
With two render passes and one additional render target, you get transparency for any Voxel in a VoxelCluster and any Particle
Please try this ASAP and be blown by the awesomeness 😄

@xchrdw
Copy link
Member

xchrdw commented Apr 21, 2014

looks good. I tried to make these yellow things in the gamescenario transparent but it didn't work. What did I do wrong?

@psieg
Copy link
Contributor Author

psieg commented Apr 21, 2014

nothing, seems to work for me. note you edited the gamescenario (the big battle) and not the frozen one.

@mrzzzrm
Copy link

mrzzzrm commented Apr 21, 2014

Is that a freaking transparent cockpit on the mox? wooooha!

void main() {
vec4 opaque = texture(color, v_uv) + texture(bloom, v_uv);
vec4 accumulated = texture(transparencyAcc, v_uv);
accumulated.a = texture(transparencyCnt, v_uv).z; // Why is Acc.a always 1?!
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could use some input with this:
Even though I switched the textures to RGBA the alpha value always returns 1. It's no problem because I have space in the count buffer, but why?

@mrzzzrm
Copy link

mrzzzrm commented Apr 21, 2014

I don't know the limitations of weighted average, but would it be possible to make a whole planet or maybe at least the yellow enemies (-> frozengamescenario) appear transparent? Currently the planet turns almost white and the enemies appear transparent only from some angles.

@psieg
Copy link
Contributor Author

psieg commented Apr 21, 2014

you should be able to...
tmp
can you be more specific about the enemies?

@psieg
Copy link
Contributor Author

psieg commented Apr 21, 2014

because all voxels are rendred those on the outer edge appear more transparent from some angles, because there are only 2 transparent layers rather than the >4 everywhere else, is that what you mean?

@mrzzzrm
Copy link

mrzzzrm commented Apr 21, 2014

That's probably it. We should use multiple layers of transparent voxels then, I guess.
Also performance drops extremly here when flying throught the transparent planet. Is that inevitable?

@psieg
Copy link
Contributor Author

psieg commented Apr 21, 2014

The performance impact from the trancparency is constant (well, the number of transparent pixels might have some impact), the perfomance drop must result from splitdetection.
Also, please explain what you mean by multiple layers or transparent voxels

@mrzzzrm
Copy link

mrzzzrm commented Apr 21, 2014

I flew through the planet via freecam, so no splitdetection. Are there ifs only triggered on transparency in the shaders? Sometimes they are evil. :D
I mean, I don't think the transparent Wall (when viewed from the front, just turns white), or let alone the planet, look good anymore. So we should be carefull not to overdo it when using transparency.

}
if (transparentPass == 0 && f_color.a < 0.9999) {
discard;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there are ifs, I don't see how we can get around these though...
And indeed the game spends 90% in nvogl.dll when in the planet
Weighted average is one of the faster algorithms, so yes, it's not perfect, especially with many layers of transparent pixels. But if you don't start making whole ships or objects transparent, I think it does the job quite well

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see why there is a performance difference with transparent voxels though. The scene is rendered twice, any fragment passes either trough the first if in the first run or the second if in the second run. This means any fragment passes the part below the ifs once per frame.
I can't explain it via Z-Buffer either because the z test is applied after the fragment shader has run. Can blending be the problem? With many transparent fragments on one pixel, the GPU has to blend a lot

@psieg
Copy link
Contributor Author

psieg commented Apr 21, 2014

GTX460 video load in the transparency2_perf branch (without moving the camera, shader doesn't discard anything):
single rendering: 54%
render, clear, render: 84% 81%
render, clear, render without writing z-buffer: 84% 88%
render, clear, render without backface culling: 84% 87%
render, clear, render without both: 99% 98%
single render without z-buffer: 80%
single render without backface culling: 56%
single render without both: 99%
=> the if in the shader isn't the problem
=> transparency (a) renders twice and (b) renders the second run without writing to z and backface -> way more fragments
=> don't make too many layers transparent....
The weird thing is the z buffer test should happen after the fragment shader, what is it that produces the load then? the fact that the already-shaded fragment is not written/blended to the buffer?

@mrzzzrm
Copy link

mrzzzrm commented Apr 22, 2014

Need some less euphoria? Crashes on my bp-pc

#0  0x0000000000000000 in ?? ()
#1  0x00007ffff67ca999 in glow::Buffer::clearData (this=0x160de40, internalformat=33334, format=6403, type=5125, 
    data=0x7ffff665f388 <glowutils::WeightedAverageAlgorithm::draw(std::function<void (glow::Program*)> const&, glowutils::Camera*, int, int)::initialDepthComplexity>)
    at /home/moritz/workspace/voxellancer/lib/glow/source/glow/source/Buffer.cpp:292
#2  0x00007ffff63e7c55 in glowutils::WeightedAverageAlgorithm::draw(std::function<void (glow::Program*)> const&, glowutils::Camera*, int, int) (this=0x16082a0, 
    drawFunction=..., camera=0x1607e30, width=1280, height=800) at /home/moritz/workspace/voxellancer/lib/glow/source/glowutils/source/WeightedAverageAlgorithm.cpp:57
#3  0x0000000000777037 in GamePlayScene::drawGame (this=0x1214590, camera=..., destinationViewport=...)
    at /home/moritz/workspace/voxellancer/src/gamestate/gameplay/gameplayscene.cpp:122
#4  0x0000000000776907 in GamePlayScene::draw (this=0x1214590, camera=..., target=0x7ffff6b408c0 <glow::FrameBufferObject::s_defaultFBO>, destinationViewport=..., side=None)
    at /home/moritz/workspace/voxellancer/src/gamestate/gameplay/gameplayscene.cpp:62
#5  0x0000000000762af8 in MonoView::draw (this=0x1217d80, scene=..., cameraHead=...) at /home/moritz/workspace/voxellancer/src/display/monoview.cpp:58
#6  0x0000000000762fcd in Viewer::draw (this=0x1219110, scene=..., cameraHead=...) at /home/moritz/workspace/voxellancer/src/display/viewer.cpp:48
#7  0x000000000076a98f in Game::draw (this=0x11b0b40) at /home/moritz/workspace/voxellancer/src/gamestate/game.cpp:56
#8  0x00000000007ad4f5 in mainloop () at /home/moritz/workspace/voxellancer/src/main.cpp:155
#9  0x00000000007adefa in main (argc=1, argv=0x7fffffffdf48) at /home/moritz/workspace/voxellancer/src/main.cpp:251

@mrzzzrm
Copy link

mrzzzrm commented Apr 22, 2014

    at /home/moritz/workspace/voxellancer/lib/glow/source/glow/source/Buffer.cpp:292
292         glClearNamedBufferDataEXT(m_id, internalformat, format, type, data);

Probably because glClearNamedBufferDataEXT isnt set by glewInit....

glBlendFunc(GL_ONE, GL_ONE);
CheckGLError();
drawGame(camera, true);
//drawGameAlpha(camera);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove may 🐝 ?

@mrzzzrm
Copy link

mrzzzrm commented May 8, 2014

Not quite done yet, I need to think about splitting the particleengine a bit, but so far it looks pretty good.
Could you place some explaining words into the combine shader how the weighted-average-algorithm works?

vec4 accumulated = texture(transparencyAcc, v_uv);
// HACK: actually accumulated.a should be the accumulation of the a values
// It seems to always be 1, while using the count-buffer's z for the same purpose works
accumulated.a = texture(transparencyCnt, v_uv).z;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

open to ideas... I didn't try cnt.a, don't the textures have alpha? The framebuffer creates them with
texture->image2D(0, GL_RGBA, m_resolution.x, m_resolution.y, 0, GL_RGBA, GL_FLOAT, nullptr);

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't look but you have enabled GL_BLEND? Otherwise I wouldn't be surprised if OpenGL optimizes values out that aren't explicitely set (as is the case for the alpha value of the color)

vec3 rgbColor = voxelFragmentColor(f_color.rgb, f_emissiveness, f_normal, f_modelposition);
fragColor = vec4(rgbColor * f_color.a, f_color.a);
emissiveness = voxelFragmentEmissiveness(f_color.xyz, f_emissiveness);
if(transparentPass) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about
normalz = (1-transparentPass) * voxelFragmenNormalZ(f_normal);?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ifs are evil, I have been told, as we need voxelFragmenNormalZ() in most cases (=most of the pixels won't be transparent), this should be better

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so long as this operation is properly defined with bool, I'm on. Will try

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you will probably need to cast to float explicitely

@@ -23,6 +24,7 @@ namespace {
"NormalZ",
"Emissisiveness",
"BlurTmp",
"Bloom",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be considered premature optimization... and its a bit confusing as well. And what is the pupose to name a buffer "Emissiveness" if it is used for something else as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, the use still is only Emissiveness == Bloom. Since they are the same buffer now it could be named bloom. Otherwise it's not an optimization but was needed to get two more buffers (limit is 8 on most GPUs)

@mrzzzrm
Copy link

mrzzzrm commented May 18, 2014

When I run the PirateScenario and fly through the enginetrail of the normandy, I suffer slowdowns. Can you reproduce this?

@psieg
Copy link
Contributor Author

psieg commented May 18, 2014

my load goes from 33% without significant transparent voxels up to 80% when the entire screen is filled with transparent voxels.
The reason is the same as with the planet, many non-culling non-z-testing fragment shader passes I think. Maybe we can ask daniel about it but I wouldn't know how to avoid this

@mrzzzrm
Copy link

mrzzzrm commented May 18, 2014

Well, it's definitely to much of a drop for that few particles there, that definitely needs to be fixed somehow. Or we have to forbid transparent particles

@psieg
Copy link
Contributor Author

psieg commented May 18, 2014

note the performance critical part is screen coverage (pixels), not particle count. with a bad perspective, you probably can mess up any scenario by overlapping n transparent surfaces and filling the entire screen with it. I agree though, we'll have to find some solution. Maybe a performance setting (so HD4000's don't have it but GTX780 players may enjoy it)

@mrzzzrm
Copy link

mrzzzrm commented May 18, 2014

I have problems to believe this. Even my HD5830 has a pixelfillrate of 200Mio/Frame. That's each pixel 100 times in HD. And I am not even running the game in HD! http://techreport.com/review/18521/amd-radeon-hd-5830-graphics-card/5

@psieg
Copy link
Contributor Author

psieg commented May 18, 2014

I know too few about GPUs to argue.
Try disabling z testing in the current master and looking at the planet:
glDepthMask(false); in gameplayscene:56
with depth mask I'm at 49%, without >90%, so the issue isn't directly linked to the transparency (as in blending, ifs, etc)

@mrzzzrm mrzzzrm mentioned this pull request May 22, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants