# OpenGL texture2d/image sampling issue. Strange artifacts in texture

I have an issue when using textures in OpenGL, strange artifacts occur where geometry overlaps, but not always. Video Reference. I am using a GL_TEXTURE_2D with GL_ARB_image_load_store to make a custom depth test shader that stores material data for opaque and transparent geometry. The video given shows the artifacts occur where the support structure for a table is occluded behind the top of the table, but strangely, not occurring where the base of the table is occluded by the support.

#version 450 core

in VS_OUT {
vec3 Position;
vec3 Normal;
vec2 TexCoords;

mat3 TanBitanNorm;
} fs_in;

// Material data
uniform sampler2D uAlbedoMap;
uniform sampler2D uNormalMap;
uniform sampler2D uMetallicMap;

// Material info out
layout(rgba16f) coherent uniform image2D uAlbedoDepthOpaque;
layout(rgba16f) coherent uniform image2D uNormalMetallicOpaque;
layout(rgba16f) coherent uniform image2D uAlbedoDepthTransparent;
layout(rgba16f) coherent uniform image2D uNormalAlphaTransparent;

// Depth info in/out
layout(r8) uniform image2D uDepthBufferOpaque;
layout(r8) uniform image2D uDepthBufferTransparent;

void main() {
vec3 n_tex = texture(uNormalMap, fs_in.TexCoords).xyz;
n_tex = n_tex * 2.0f - 1.0f;

ivec2 tx_loc = ivec2(gl_FragCoord.xy);
const float opaque_depth = imageLoad(uDepthBufferOpaque, tx_loc).r; // Stored depth of opaque
const float trans_depth = imageLoad(uDepthBufferTransparent, tx_loc).r; // Stored depth of transparent

// Depth processing
if (gl_FragCoord.z > opaque_depth) {
bool tran = false;
if (trans_depth > opaque_depth)
tran = trans_depth > gl_FragCoord.z;
else
tran = true;

// Transparent
if (texture(uAlbedoMap, fs_in.TexCoords).a < 1.0f && tran) {
imageStore(uDepthBufferTransparent, tx_loc,
vec4(gl_FragCoord.z));

imageStore(uAlbedoDepthTransparent, tx_loc,
vec4(texture(uAlbedoMap, fs_in.TexCoords).rgb, gl_FragCoord.z));
imageStore(uNormalAlphaTransparent, tx_loc,
vec4(abs(length(n_tex) - 1.0f) > 0.1f ? fs_in.Normal : normalize(fs_in.TanBitanNorm * n_tex), texture(uAlbedoMap, fs_in.TexCoords).a));
}

// Opaque
else {
imageStore(uDepthBufferOpaque, tx_loc,
vec4(gl_FragCoord.z));

imageStore(uAlbedoDepthOpaque, tx_loc,
vec4(texture(uAlbedoMap, fs_in.TexCoords).rgb, gl_FragCoord.z));
imageStore(uNormalMetallicOpaque, tx_loc,
vec4(abs(length(n_tex) - 1.0f) > 0.1f ? fs_in.Normal : normalize(fs_in.TanBitanNorm * n_tex), texture(uMetallicMap, fs_in.TexCoords).r));
}
}

if (opaque_depth == 0.0f) {
imageStore(uDepthBufferOpaque, tx_loc,
vec4(0.125f));
}

else {
imageStore(uDepthBufferOpaque, tx_loc,
vec4(0.125f + opaque_depth));
}
}


Render with overlapping geometry shows that artifacts still occur outside of reading from the texture. Also in the video, I move the camera back and forth (with orthographic projection) and the artifacts become brighter and darker. Render with overlapping geometry w/out depth processing shows that the brighter/darker values were from the depth test.

Any ideas on why this occurs, and how can I fix it?

• This looks like Z-fighting from the legs of the table occasionally mapping to the same depth range as the table top. This can happen if your near and far planes are very far apart. Have you tried clamping them in to hug the scene more tightly? – DMGregory Jul 13 '20 at 2:15
• I have the near and far planes really close currently. -10 units and 10 units, whereas the scene is around 3x3x3 units. – William Jul 13 '20 at 2:18
• Both links appear dead. Can you put the pics into the question itself please? – Kromster Jul 13 '20 at 5:15
• All three links work for me (Even cleared cookies), and I would put them into the question, but they are videos. I figured streamable would work fine. – William Jul 13 '20 at 5:24
• I've been thinking over what may be happening, and I think multiple fragments are being processed at the same time. If fragments can be processed simultaneously, is there a way to disable it? – William Jul 16 '20 at 22:08

The issue is Z-fighting.

The gpu, when choosing which pixels to write to the back buffer, write using a sort of painter's algorithm, farthest away, to closest, for each pixel. This is called depth testing.

Normally, this would be caused by two objects occupying the same depth in the depth buffer, but you are bypassing that, in an attempt to achieve transparency.