I've been using glDisable(GL_DEPTH_TEST) to disable depth testing, thinking that it only disables depth "testing". The reason I've been confused I guess is because I've created two functions, one to disable the depth "test", and another to disable depth "writes" with glDepthMask(GL_FALSE);
If disabling GL_DEPTH_TEST disables both "testing" and "writing" then would it be the equivalent of doing:
glDepthFunc(GL_ALWAYS); // DISABLE TESTS (OR ACTUALLY ALWAYS LET THE TEST SUCCEED)
glDepthMask(GL_FALSE); // DISABLE WRITES
I'm thinking that there's little use for disabling GL_DEPTH_TEST unless I want to disable both tests and writes, and I'm wondering which one is better. The wording seems confusing, but maybe it's just me. I suppose doing disabling depth tests with glDepthFun(GL_ALWAYS) will still do a comparison, I suppose there's no way to disable the depth test entirely while still allowing writes?
glDisable(GL_DEPTH_TEST)
turns off the Depth Test from pipeline. If you use:
glDepthFunc(GL_ALWAYS);
glDepthMask(GL_FALSE);
instead it just hide it after condition (but still present in the pipeline) which could mean performance difference on some platforms ...
Also using your equivalent would need you to set/remember original DepthFunc in case you want to turn it on again (as there are many rendering techniques that need to switch the DeptTest on/off several times.
And lastly two GL function calls are bigger overhead than just one. So from performance point of view using glDisable(GL_DEPTH_TEST) is better for this. The glDepthFunc,glDepthMask are intended for different purpose like multi pass rendering, order independent transparency,holes, etc ...
Related
I was reading about the side effects of using "discard" in OpenGL's fragment shader, such as early testing being disabled. But I could not find any alternative for alpha-testing until I stumbled upon glAlphaFunc, which seems to be deprecated since OpenGL 3.0. However I could not find any documentation on why it has been removed, and there seems to be no alternative to "discard".
Alpha testing has (on all implementations I know of) never been done in the early testing stage. I don't think it is even possible there because before the fragment shader has been executed there is no concept of a color or a alpha channel.
In addition, enabling alpha testing usually disables early depth testing (see here), which means that it behaves the same as when discard is used in the shader.
I cannot directly answer why glAlphaFunc has been removed, but since there is no real difference between discard and alpha testing, it's not really a problem.
I'm in the processing of learning Vulkan, and I have just integrated ImGui into my code using the Vulkan-GLFW example in the original ImGui repo, and it works fine.
Now I want to render both the GUI and my 3D model on the screen at the same time, and since the GUI and the model definitely needs different shaders, I need to use multiple pipelines and submit multiples commands. The GUI is partly transparent, so I would like it to be rendered after the model. The Vulkan specs states that the execution order of commands are not likely to be the order that I record the commands, thus I need synchronization of some kind. In this Reddit post several methods of exactly achieving my goals was proposed, and I once believed that I must use multiple subpasses (together with subpass dependency) or barriers or other synchronization methods like that to solve this problem.
Then I had a look at SaschaWillems' Vulkan examples, in the ImGui example though, I see no synchronization between the two draw calls, it just record the command to draw the model first, and then the command to draw the GUI.
I am confused. Is synchronization really needed in this case, or did I misunderstand something about command re-ordering or blending? Thanks.
Think about what you're doing for a second. Why do you think there needs to be synchronization between the two sets of commands? Because the second set of commands needs to blend with the data in the first set, right? And therefore, it needs to do a read/modify/write (RMW), which must be able to read data written by the previous set of commands. The data being read has to have been written, and that typically requires synchronization.
But think a bit more about what that means. Blending has to read from the framebuffer to do its job. But... so does the depth test, right? It has to read the existing sample's depth value, compare it with the incoming fragment, and then discard the fragment or not based on the depth test. So basically every draw call that uses a depth test contains a framebuffer read/modify/wright.
And yet... your depth tests work. Not only do they work between draw calls without explicit synchronization, they also work within a draw call. If two triangles in a draw call overlap, you don't have any problem with seeing the bottom one through the top one, right? You don't have to do inter-triangle synchronization to make sure that the previous triangles' writes are finished before the reads.
So somehow, the depth test's RMW works without any explicit synchronization. So... why do you think that this is untrue of the blend stage's RMW?
The Vulkan specification states that commands, and stages within commands, will execute in a largely unordered way, with several exceptions. The most obvious being the presence of explicit execution barriers/dependencies. But it also says that the fixed-function per-sample testing and blending stages will always execute (as if) in submission order (within a subpass). Not only that, it requires that the triangles generated within a command also execute these stages (as if) in a specific, well-defined order.
That's why your depth test doesn't need synchronization; Vulkan requires that this is handled. This is also why your blending will not need synchronization (within a subpass).
So you have plenty of options (in order from fastest to slowest):
Render your UI in the same subpass as the non-UI. Just change pipelines as appropriate.
Render your UI in a subpass with an explicit dependency on the framebuffer images of the non-UI subpass. While this is technically slower, it probably won't be slower by much if at all. Also, this is useful for deferred rendering, since your UI needs to happen after your lighting pass, which will undoubtedly be its own subpass.
Render your UI in a different render pass. This would only really be needed for cases where you need to do some full-screen work (SSAO) that would force your non-UI render pass to terminate anyway.
I made an interesting, if confusing discovery today.
Thus far I've gotten by fine using glDraw*(GL_LINE_STRIP...) (or related GL_LINE* draw modes). Of course, this always requires some re-ordering of vertices in order to make the same vertex data work seamlessly between GL_TRIANGLES and GL_LINE_STRIP, but okay, all good there.
Then today I reintroduced some older code I had and found glPolygonMode(GL_FRONT_AND_BACK, GL_LINE) among it. I looked it up and people were saying that while GL_BACK and GL_FRONT are deprecated in 3.3 core context, glPolygonMode is undeprecated, though supported only by GL_FRONT_AND_BACK as the first argument. So I tried it with GL_LINE as the second argument, along with glDraw*(GL_TRIANGLES...) and not only did it work perfectly, it also required none of the explicit re-ordering of vertices required to suit GL_LINE_STRIP. (I went back to an earlier configuration to test this).
Questions:
What am I supposed to be using, in 3.3 core context? Is either method OK? The reason I ask is that I am wondering whether the line glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); is really even giving me a core profile, since it is after all only a hint to GLFW.
Which approach is recommended? Are there performance impacts to the latter? It certainly seems a lot more convenient.
Why even have glDraw*(GL_LINE*...) if this can be done via glPolygonMode?
Ad 1: Both methods are perfectly fine in OpenGL Core profile.
Ad 2: I'm not sure about this, but I guess that there will not be a huge performance difference.
Ad 3: This methods exist because one might also want to draw line objects that are not composed from triangles. Examples for this are circles or even straight lines.
Our deferred renderer reached to a point where we need to apply environment maps & IBL to push the quality to a higher level ( As you can see the cubemaps are clearly missing ):
After a couple of hours of research on this topic i still found no solution which makes me really happy.
This is what i found so far
Additional forward pass whichs result is added to the LA-Buffer. This looks like a bad idea somehow, we use deferred shading to avoid multiple passes and then render everything again for cubemapping & IBL. But at least we could use the existing GBuffer-Data ( inc. depth ) to render the objects and the selection of the used cubemap can be easily done on the CPU.
Render a fullscreen plane and perform some crazy selection of the right cubemap in the shader ( what is done on the CPU in the shader ). This seems even more bad than rendering everything again, the glsl shader is going to be huge. Even if i implement tiled-deferred-rendering ( not done yet ), it still seems to be a bad idea.
Also storing the cubemap information directly into the GBuffer of the first pass is not applicable in my renderer. I've used all components of my 3 buffers ( 3 to stay compatible with ES 3.0 ), and already used compression on the color values ( YCoCg ) and the normals ( Spheremap Transform ).
Last but not least the very simple and not really a good solution: Use a single cubemap and apply it on the hole scene. This is not really a option, because this is going to have a huge impact on the quality.
I want to know if another approach exists for environment cubemapping. If not what is the best approach of them. My personal favorite is the second one so far even if this requires rendering the whole scene again ( At least on devices which only support 4 rendertargets ).
After testing different stuff i found out that the best idea is to use the second solution, however the implementation is tough. The best approach is to use compute shaders, however these are not supported on the most mobile devices these days.
So you need to use a single cubemap on mobile devices or get the data into the buffer in the first render pass. If this is not possible you need to render it tiled with some frustum culling for each tile ( to reduce number of operations on each pixel ).
I'm having a rough time trying to set up this behavior in my program.
Basically, I want it that when a the user presses the "a" key a new sphere is displayed on the screen.
How can you do that?
I would probably do it by simply having some kind of data structure (array, linked list, whatever) holding the current "scene". Initially this is empty. Then when the event occurs, you create some kind of representation of the new desired geometry, and add that to the list.
On each frame, you clear the screen, and go through the data structure, mapping each representation into a suitble set of OpenGL commands. This is really standard.
The data structure is often referred to as a scene graph, it is often in the form of a tree or graph, where geometry can have child-geometries and so on.
If you're using the GLuT library (which is pretty standard), you can take advantage of its automatic primitive generation functions, like glutSolidSphere. You can find the API docs here. Take a look at section 11, 'Geometric Object Rendering'.
As unwind suggested, your program could keep some sort of list, but of the parameters for each primitive, rather than the actual geometry. In the case of the sphere, this would be position/radius/slices. You can then use the GLuT functions to easily draw the objects. Obviously this limits you to what GLuT can draw, but that's usually fine for simple cases.
Without some more details of what environment you are using it's difficult to be specific, but a few of pointers to things that can easily go wrong when setting up OpenGL
Make sure you have the camera set up to look at point you are drawing the sphere. This can be surprisingly hard, and the simplest approach is to implement glutLookAt from the OpenGL Utility Toolkit. Make sure you front and back planes are set to sensible values.
Turn off backface culling, at least to start with. Sure with production code backface culling gives you a quick performance gain, but it's remarkably easy to set up normals incorrectly on an object and not see it because you're looking at the invisible face
Remember to call glFlush to make sure that all commands are executed. Drawing to the back buffer then failing to call glSwapBuffers is also a common mistake.
Occasionally you can run into issues with buffer formats - although if you copy from sample code that works on your system this is less likely to be a problem.
Graphics coding tends to be quite straightforward to debug once you have the basic environment correct because the output is visual, but setting up the rendering environment on a new system can always be a bit tricky until you have that first cube or sphere rendered. I would recommend obtaining a sample or template and modifying that to start with rather than trying to set up the rendering window from scratch. Using GLUT to check out first drafts of OpenGL calls is good technique too.