1
$\begingroup$

I'm trying to implement voxel world using OpenGL (Core 3.3). I've come across a problem with transparency. It looks like sometimes GPU decides to not render stuff that would be important. Can you help me diagnose the problem, please? (I thought this problem can be related to sorting (I don't perform any extra sorting at the moment), but I've changed "clear color" to glClearColor(1.0f, 1.0f, 1.0f, 0.01f); and the "gaps" are still noticeable)

EDIT: I've found a resource that claims that it is indeed sorting problem and drawing background triangles at first should solve this issue. However every 'chunk' (16x16 blocks' column) is rendered as a separate batch with single draw call. Is there a way to preserve this batch rendering?

Here are some pictures:

enter image description here enter image description here

enter image description here enter image description here

The Ftagment Shader is very simple:

#version 330 core
out vec4 FragColor;
in vec2 v_TexCoord;

uniform sampler2D u_Texture;

void main()
{
    vec4 texColor = texture(u_Texture, v_TexCoord);
    if(texColor.a < 0.2)
        discard;
    FragColor = texColor;
}

Depth test and blending:

void Renderer::clear() const {
    glClearColor(0.53f, 0.8f, 0.92f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}

//Before render loop

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_DEPTH_TEST);

Do you have any idea how can I fix this problem?

$\endgroup$
0
$\begingroup$

It depends on the order of rendering. When first rendering the object which is far away and then rendering the closer object, the transparency will work. Otherwise when first rendering the close object, you depthbuffer will block the object which is behind. There are different ways to manage this issue:

1:First render all opaque geometries. and then render the transparent.

This gives you NOT the correct output, because other transparent objects which are behind transparent objects will cause the same problem you described. But opaque objects will always be visible.

2:Use other rendertechniques like Order independent transparencies (OIT)

Here you create a list of fragments (pixels) for each pixel on your screen. The list of fragments must hold the depth and color value. when all geometry is rendered, you can iterate through each list and sort the fragments by the depth value and render them again from back to front. This will give you a very good final image.

This technique can be improved when first enable depth writing, depth testing and rendering the opaque objects. Disable depth writing, enable depth testing. And then render the transparent ones. This will shrink your list size.

$\endgroup$
4
  • $\begingroup$ In case using OIT: you can store the list in a Shader Storage Buffer Object (SSBO) and use atomicAdd(), atomicCompSwap() and other atomic functions within GLSL (shader) to avoid writing to the same memory location from different GPU "Threads" . $\endgroup$
    – Thomas
    Sep 23 at 6:32
  • 1
    $\begingroup$ I'll implement this and hopefully it'll solve the problem. (Unfortunately I do not have enough reputation to cast a vote for you). Thank you for your answers. $\endgroup$ Sep 23 at 10:06
  • $\begingroup$ @PawełPomierski you are welcome =) $\endgroup$
    – Thomas
    Sep 24 at 11:39
  • $\begingroup$ @PawełPomierski have in mind, that you can also render your blocks from back to front... if your datastructure (chunks) allow this $\endgroup$
    – Thomas
    Sep 24 at 11:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.