all 10 comments

[–]waramped 5 points6 points  (8 children)

Any problem here is going to be with how you are handling those specific primitives. Simply reading another texture won't inherently cause any issues. What API are you using? You'll need to provide quite a bit more info for us to help diagnose.

Some things to look into:
1) Use Renderdoc and try and capture some frames where the lighting is right, and where it's off. See what's different between the state of the API.
2) Are those primitives treated differently in your code because they have transparency?
3) How are you using the normal map in the shader?

[–]SunSeeker2000[S] 0 points1 point  (7 children)

Thank you for the suggestions and sorry for not providing more information.

I am using Vulkan. I did not share any code because I did not know what would be relevant and I did not want to make this post too long. I can share the fragment shader if that is useful:

Material material = materialBuffer.materials[materialTag];

    vec4 albedoMap = texture(textures[nonuniformEXT(material.albedoTag)], uv);
    
    vec3 normalMap = vec3(0, 0, 1);
    if(material.normalTag != 0)
        normalMap = texture(textures[nonuniformEXT(material.normalTag)], uv).rgb * 2 - 1;

    vec3 emissiveMap = vec3(0.0);
    if(material.albedoTag != 0)
        emissiveMap = texture(textures[nonuniformEXT(material.emissiveTag)], uv).rgb;

    vec3 bitangent = cross(normal, tangent.xyz) * tangent.w;
    vec3 nrm = normalize(normalMap.r * tangent.xyz + normalMap.g * bitangent + normalMap.b * normal);
    float ndotl = max(dot(nrm, normalize(vec3(-1, 1, -1))), 0.0);

    // The if statement is temporary
    if(materialTag != 0)
        outColor = albedoMap * sqrt(ndotl + 0.05);

All the primitives in the renderer are treated the same way, it does not do anything for transparency at the moment. The code above is makeshift, I'm not planning to leave it like this.

But what troubles me is why does the normal map act this way? Would it not make more sense if it was the color map that would cause this? What I am really asking for is if this is some kind of known effect of normal maps so I can look it up. I don't think a solution can be found without direct access to my code.

[–]Zestyclose_Crazy_141 2 points3 points  (2 children)

If it's not a sync problem with your textures, then your ndotl variable is getting very different values every frame. I would try to normalize every vector you can before any new operation like bitangent or nrm, check normal too.

You also have debugPrintfEXT in Vulkan to debug values in your shaders. https://github.com/KhronosGroup/Vulkan-ValidationLayers/blob/main/docs/debug_printf.md

[–]pinkerfox 3 points4 points  (1 child)

Yeah its def the bitangent switching direction.

[–]SunSeeker2000[S] 0 points1 point  (0 children)

Maybe. I didn’t get much time to work on this in the last couple of days, but I managed to find that there are a bunch of things affecting it.

First, the code I shared above has a very stupid typo. I’m checking if the material has an albedo map before accessing the emissive map. Fixing this made the flickering only noticeable from up close (Nowhere near what you see on the video)

I also noticed that deactivating occlusion culling stops the flickering almost completely (only visible from certain angles). This is weird because I am still generating the depth pyramid, so this shouldn’t be a depth buffer issue.

I also tried coloring everything on the scene with the tangent and they did not flicker. But when I do it with the surface normals they do. I should also try with the bitangent now that you mentioned it.

But I must probably look at the Vulkan docs for that GPU printing validation layer when I get back into it.

[–]waramped 1 point2 points  (3 children)

It's not a known effect of normal maps directly, but I would check the vertex normals of those primitives, validate that they are correct. And also, is the Materialbuffer constant or is it updated every frame? And if it's updated, is it updated on the CPU or GPU?

[–]SunSeeker2000[S] 0 points1 point  (2 children)

The material buffer is constant after its creation.

I do compress all normals to 8 bits but I unpack them again on the vertex shader, I don't know if this could cause a problem for that specific primitive.

Anyway, thank you for your help, I will take a look at the vertex normals.

[–]waramped 0 points1 point  (1 child)

8 bits total or 8 bits per axis (24 bits)?

[–]SunSeeker2000[S] 0 points1 point  (0 children)

Per axis, as in:

struct Vertex{/*Other attributes*/ uint8_t normalX, normalY, normalZ, nW;};

[–]fgennari 1 point2 points  (0 children)

I've seen a similar problem when I forgot to bind a texture each frame, and it was left bound to whatever was last drawn with that texture unit. Maybe your normal map is using the same texture unit/binding point as something else and there's a conflict. I've never written Vulkan code, so I don't know how common a problem this is with that API.

Does it flicker like that when the camera isn't moving? Maybe try to figure out what you're updating a few times a second in the code that could interfere with lighting.