I'm working on rendering a scene that potentially has multiple intersecting transparent objects. This makes the standard method of sorting and drawing back to front problematic (even sorting triangles wouldn't work if the triangles intersect). So I've implemented depth peeling using a GLSL fragment shader to do the second depth test. It's works great.
Now I want to be able to apply certain effects using shaders. One of the objects in the scene is a syringe, and I would like to apply a glass effect. If I was drawing back to front, this would be easy - just start the shader when I draw the syringe, since everything behind it is already in the frame buffer. However, when using depth peeling this approach won't work.
So my questions are:
How to I apply shader effects to a single object in a scene when using depth peeling?
How do I combine effect shaders with my depth peeling shader (assuming they need to run at the same time)?
I should note that I'm pretty new at using shaders, so code examples are appreciated!
I'd be surprised if that's possible without ray tracing. As far as I know, the way to use refraction shaders is to do texture lookups in an environment map. This map can be either precomputed, or it's computed on the fly in a separate rendering pass. For the latter option you would need one separate environment map and one extra pass for each object that uses the shader. I kinda doubt that that's possible if the objects intersect each other. Even if it was, for each of these passes you would also need another couple passes for the depth peeling. Now if you also wanted the depth peeling shader passes to factor in refractions for the surrounding objects, this would quickly get out of hand.
Related
I'm rendering multiple layers of flat triangles with a raytracer in the fragment shader. The upper layers have holes, and I'm looking for a way how I can avoid running the shader for pixels that are filled already by one of the upper layers, i.e. I want only the parts of the lower layers rendered that lie in the holes in the upper layers. Of course, if there's a hole or not is not known unless the fragment shader did his thing for a layer.
As far as I understand, I cannot use early depth testing because there, the depth values are interpolated between the vertices and do not come from the fragment shader. Is there a way to "emulate" that behavior?
The best way to solve this issue is to not use layers. You are only using layers because of the limitations of using a 3D texture to store your scene data. So... don't do that.
SSBOs and buffer textures (if your hardware is too old for SSBOs) can access more memory than a 3D texture. And you could even employ manual swizzling of the data to improve cache locality if that is viable.
As far as I understand, I cannot use early depth testing because there, the depth values are interpolated between the vertices and do not come from the fragment shader.
This is correct insofar as you cannot use early depth tests, but it is incorrect as to why.
The "depth" provided by the VS doesn't need to be the depth of the actual fragment. You are rendering your scene in layers, presumably with each layer being a full-screen quad. By definition, everything in one layer of rendering is beneath everything in a lower layer. So the absolute depth value doesn't matter; what matters is whether there is something from a higher layer over this fragment.
So each layer could get its own depth value, with lower layers getting a lower depth value. The exact value is arbitrary and irrelevant; what matters is that higher layers have higher values.
The reason this doesn't work is this: if your raytracing algorithm detects a miss within a layer (a "hole"), you must discard that fragment. And the use of discard at all turns off early depth testing in most hardware, since the depth testing logic is usually tied to the depth writing logic (it is an atomic read/conditional-modify/conditional-write).
The core of my problem is that I have troubles with depth-fighting in pure OpenGL.
I have two identical geometries, but one is simpler than the other.
That forms a set of perfectly coplanar polygons, and I want to display the complex geometry on top of the simpler geometry.
Unsurprisingly, it leads me to depth-fighting when I draw sequentially the two sets of triangles using the OpenGL depth buffer. At the moment, I've patched it using glPolygonOffset but this solution is not suitable for me (I want the polygons the be exactly coplanar).
My idea is to temporary use a custom depth test when drawing the second set of triangles. I would like to save the depth of the fragments during the rendering of the first set. Next, I would use glDepthFunc(GL_ALWAYS) to disable the depth buffer (but still writing in it). When rendering the second set, I would discard fragments that have a greater z than the memory I just created, but with a certain allowance (at least one time the precision of the Z-buffer at the specific z, I guess). Then I would reset depth function to GL_LEQUAL.
Actually, I just want to force a certain allowance for the depth test.
Is it a possible approach ?
The problem is that I have no idea how to pass information (custom depth buffer) from one program to another.
Thanks
PS : I also looked into Frame Buffer Objects and Deferred Rendering because apparently it allows passing information via a 'G-buffer', but once I write:
unsigned int gBuffer;
glGenFramebuffers(1, &gBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, gBuffer);
My window goes black... Sorry if things are obvious I'm not familiar yet with OpenGL
As Rabbid76 said, I can simply disable depth writing using glDepthMask(GL_FALSE).
Now, I can draw several layers of coplanar polygons using the same offset.
Solved.
I'm trying to perform the depth peeling algorithm, to draw in correct order transparent objects in a scene already full of opaque objects (A terrain that almost occludes the transparent objects most of the time).
I have already separated the draw calls for opaque/transparent objects, drawing the opaque ones first. The problem lies in that each one of the "transparent objects drawing passes" the algorithm needs will actually use it's own (empty) z-buffer, but I need to check if a opaque object is occluding the view before drawing, and hence I need to reuse the z-buffer obtained after drawing the opaque objects multiple times, and not a empty one each.
Im aware i could dump the z-buffer state after drawing the opaque objects to a texture, and performing the depth comparisons from it in the fragment shader, but im afraid that performing the depth comparisons in the fragment shader would be extremelly slow. There is another faster way to solve that problem?
Edit: My target is a 3.X OpenGL version, so using the A-buffer is not an option in this particular case.
I am working on a painting app using the LibGDX framework, though this should be primarily OpenGL related.
Basically, I am looking for a way to prevent the sprites I use to draw from overlapping each other when they aren't fully opaque, as this creates a lot of unpleasant effects. Drawing the sprites at 1.0 alpha onto a texture and then drawing that texture back at the desired alpha gives the effect I want, but that method would involve constantly recreating the texture as the user is drawing, which is far too intensive to be viable.
From what I can see, the best option for me, in basic terms, is to sort of subtract one of these sprites from the other in the fragment shader. I am quite certain this route would work, but I cannot figure out how to get to the point where I can actually compare them in the fragment shader. Both will always use the same single texture, but they will be positioned in different spots. Is it at all possible to actually compare them like that, or is there a suitable alternative?
It's not actually possible to compare 2 textures that are applied to different geometry (sprites) in the fragment or vertex shader that way, because they will be rendered on different iterations of the shaders, at different points in time.
You could have two or more texture units to sample and subtract multiple textures, but they would have to be applied to the same vertices (sprites), which I think is not what you want.
A better approach would be to compute the proximity of the sprites before they are rendered. You could then either change their positions, or pass the proxmity as a uniform value into the shaders, which could then be used to change the alpha of the fragment pixels for the sprites.
Criteria: I’m using OpenGL with shaders (GLSL) and trying to stay with modern techniques (e.g., trying to stay away from deprecated concepts).
My questions, in a very general sense--see below for more detail—are as follows:
Do shaders allow you to do custom blending that help eliminate z-order transparency issues found when using GL_BLEND?
Is there a way for a shader to know what type of primitive is being drawn without “manually” passing it some sort of flag?
Is there a way for a shader to “ignore” or “discard” a vertex (especially when drawing points)?
Background: My application draws points connected with lines in an ortho projection (vertices have varying depth in the projection). I’ve only recently started using shaders in the project (trying to get away from deprecated concepts). I understand that standard blending has ordering issues with alpha testing and depth testing: basically, if a “translucent” pixel at a higher z level is drawn first (thus blending with whatever colors were already drawn to that pixel at a lower z level), and an opaque object is then drawn at that pixel but at a lower z level, depth testing prevents changing the pixel that was already drawn for the “higher” z level, thus causing blending issues. To overcome this, you need to draw opaque items first, then translucent items in ascending z order. My gut feeling is that shaders wouldn’t provide an (efficient) way to change this behavior—am I wrong?
Further, for speed and convenience, I pass information for each vertex (along with a couple of uniform variables) to the shaders and they use the information to find a subset of the vertices that need special attention. Without doing a similar set of logic in the app itself (and slowing things down) I can’t know a priori what subset of vericies that is. Thus I send all vertices to the shader. However, when I draw “points” I’d like the shader to ignore all the vertices that aren’t in the subset it determines. I think I can get the effect by setting alpha to zero and using an alpha function in the GL context that will prevent drawing anything with alpha less than, say, 0.01. However, is there a better or more “correct” glsl way for a shader to say “just ignore this vertex”?
Do shaders allow you to do custom blending that help eliminate z-order transparency issues found when using GL_BLEND?
Sort of. If you have access to GL 4.x-class hardware (Radeon HD 5xxx or better, or GeForce 4xx or better), then you can perform order-independent transparency. Earlier versions have techniques like depth peeling, but they're quite expensive.
The GL 4.x-class version uses essentially a series of "linked lists" of transparent samples, which you do a full-screen pass to resolve into the final sample color. It's not free of course, but it isn't as expensive as other OIT methods. How expensive it would be for your case is uncertain; it is proportional to how many overlapping pixels you have.
You still have to draw opaque stuff first, and you have to draw transparent stuff using special shader code.
Is there a way for a shader to know what type of primitive is being drawn without “manually” passing it some sort of flag?
No.
Is there a way for a shader to “ignore” or “discard” a vertex (especially when drawing points)?
No in general, but yes for points. A Geometry shader can conditionally emit vertices, thus allowing you to discard any vertex for arbitrary reasons.
Discarding a vertex in non-point primitives is possible, but it will also affect the interpretation of that primitive. The reason it's simple for points is because a vertex is a primitive, while a vertex in a triangle isn't a whole primitive. You can discard lines, but discarding a vertex within a line is... of dubious value.
That being said, your explanation for why you want to do this is of dubious merit. You want to update vertex data with essentially a boolean value that says "do stuff with me" or not to. That means that, every frame, you have to modify your data to say which points should be rendered and which shouldn't.
The simplest and most efficient way to do this is to simply not render with them. That is, arrange your data so that the only thing on the GPU are the points you want to render. Thus, there's no need to do anything special at all. If you're going to be constantly updating your vertex data, then you're already condemned to dealing with streaming vertex data. So you may as well stream it in a way that makes rendering efficient.