LWJGL Forum

Programming => OpenGL => Topic started by: TheBoneJarmer on October 16, 2015, 18:20:34

Title: VBO - Strange black quad appears sometimes
Post by: TheBoneJarmer on October 16, 2015, 18:20:34
Hey guys

I got a very odd situation here. I have a set of primitive 3D models (cube, sphere and cylinder) which I made using AC3D. I export them as OBJ and load them in my game. The cube and sphere are displayed just fine, but when I try to load my cylinder, the effect you can see in the screenshot happens. I'll add my 3 models in case you'd like to study them. If you need any code just ask. I'm not certain what to add because I do not know what the problem's source is. Bytheway, it is black because I didn't add any lights or emission in case you'd wonder.

Thanks in advance!
TBJ
Title: Re: VBO - Strange black quad appears sometimes
Post by: Kai on October 16, 2015, 18:58:56
Looks fine in Blender and when loaded with LWJGL3's demo WavefrontMeshLoader (https://github.com/LWJGL/lwjgl3-demos/blob/master/src/org/lwjgl/demo/opengl/util/WavefrontMeshLoader.java). (see attached image).
Though the bottom side of the cylinder has flipped normals pointing into +Y and also inconsistent/clockwise winding order.
With backface culling enabled in OpenGL you will not see the bottom side of your cylinder.
Regarding the strange quad, I somehow suspect your VBO being bigger than the actual model data and containing garbage at the end and you issue more vertices to be rendered than you imported.
Title: Re: VBO - Strange black quad appears sometimes
Post by: TheBoneJarmer on October 16, 2015, 20:29:34
Quote from: Kai on October 16, 2015, 18:58:56
I somehow suspect your VBO being bigger than the actual model data and containing garbage at the end and you issue more vertices to be rendered than you imported.

I suspected the same thing so I've been searching all classes involved. But it makes no sense because it doesn't happen to the sphere or cube. Thanks for taking a look at it that way! Indeed, it does appear fine in Blender but perhaps it has something to do with a small bug inside the meshes itself? I know you tested it out but what you told me about the flipped normals and such may have something to do with it. Perhaps it is the data that somehow is different and because of a piece of code I wrote it may not display right.

That being said, I'm using shaders right now but I thinking about creating an example with the fixed function pipeline instead of shaders to see if it does make any differences or not. It could help me locating the source of the problem and making sure the shaders don't have anything to do with it.
Title: Re: VBO - Strange black quad appears sometimes
Post by: Kai on October 16, 2015, 20:40:19
I am very certain that the shaders are not the issue.
It's very unlikely that the uniform vertex transformation in your shader correctly transforms all vertices except that few.
After all a shader transforms what is given to it. Using the fixed-function pipeline will very likely not change anything.
What I would do is to suspect the problem in the wavefront obj loader.
Then to verify that assumption I would debug the positions that it imports/produces in the positions buffer by printing them out or by computing the bounding box or by asserting that they do not exceed a certain value.
If the loader is fine, then I would verify whether you issue the same number of vertices in the draw call that you imported from the obj file.
Title: Re: VBO - Strange black quad appears sometimes
Post by: TheBoneJarmer on October 16, 2015, 21:04:52
Quote from: Kai on October 16, 2015, 20:40:19
What I would do is to suspect the problem in the wavefront obj loader.
Then to verify that assumption I would debug the positions that it imports/produces in the positions buffer by printing them out or by computing the bounding box or by asserting that they do not exceed a certain value.
If the loader is fine, then I would verify whether you issue the same number of vertices in the draw call that you imported from the obj file.

Done all that, bounding box is correct, positions are correct. Nope, results are positive so it can't be the OBJ loader.

Quote from: Kai on October 16, 2015, 20:40:19
It's very unlikely that the uniform vertex transformation in your shader correctly transforms all vertices except that few.
After all a shader transforms what is given to it. Using the fixed-function pipeline will very likely not change anything.

It actually did. I copied my engine's source code to a temp folder, removed the entire shader thing and replaced it with FFP. The model is now rendered the way it should. That proves at least the VBO and the OBJ loader work so I can remove that from my list of possible sources. You are right about the shaders, they only render what they receive. So the shaders are not the source of the problem either. It seems something else is causing troubles.
Title: Re: VBO - Strange black quad appears sometimes
Post by: TheBoneJarmer on October 17, 2015, 09:55:34
Okay, I did some testing again and I finally found the source of the problem. It turns out it has to do with the fragment shader. And a really stupid thing too. Here is my shadercode:


#version 120

struct Light
{
vec3 position;
vec4 color;
float range;
int directional;
int enabled;
};

uniform mat4 MVP;
uniform mat4 ModelMatrix;
uniform mat4 ViewMatrix;
uniform mat4 ProjectionMatrix;
uniform mat4 NormalMatrix;

//Material
uniform vec4 MaterialDiffuse = vec4(1.0, 1.0, 1.0, 1.0);
uniform vec4 MaterialAmbient = vec4(0, 0, 0, 0);
uniform vec4 MaterialSpecular = vec4(1.0, 1.0, 1.0, 1.0);
uniform vec4 MaterialEmission = vec4(0.0, 0.0, 0.0, 1.0);
uniform float MaterialShininess = 0;
uniform sampler2D MaterialTexture0;
uniform sampler2D MaterialTexture1;
uniform sampler2D MaterialTexture2;
uniform sampler2D MaterialTexture3;
uniform sampler2D MaterialTexture4;
uniform sampler2D MaterialTexture5;
uniform sampler2D MaterialTexture6;
uniform sampler2D MaterialTexture7;
uniform int UseTexture0;
uniform int UseTexture1;
uniform int UseTexture2;
uniform int UseTexture3;
uniform int UseTexture4;
uniform int UseTexture5;
uniform int UseTexture6;
uniform int UseTexture7;

//Light
uniform Light lights[100];
uniform int LightCount;

varying vec3 VertexPosition;
varying vec3 VertexNormal;
varying vec3 EyeDirection;

void main()
{
//The final fragment color
vec4 finalColor = vec4(0.0, 0.0, 0.0, 0.0);

//Apply the material based on all the lights in the scene
vec4 finalTexture = vec4(1.0, 1.0, 1.0, 1.0);

if (UseTexture0 == 1) finalTexture = texture2D(MaterialTexture0, gl_TexCoord[0].st);
if (UseTexture1 == 1) finalTexture += texture2D(MaterialTexture1, gl_TexCoord[0].st);
if (UseTexture2 == 1) finalTexture += texture2D(MaterialTexture2, gl_TexCoord[0].st);
if (UseTexture3 == 1) finalTexture += texture2D(MaterialTexture3, gl_TexCoord[0].st);
if (UseTexture4 == 1) finalTexture += texture2D(MaterialTexture4, gl_TexCoord[0].st);
if (UseTexture5 == 1) finalTexture += texture2D(MaterialTexture5, gl_TexCoord[0].st);
if (UseTexture6 == 1) finalTexture += texture2D(MaterialTexture6, gl_TexCoord[0].st);
if (UseTexture7 == 1) finalTexture += texture2D(MaterialTexture7, gl_TexCoord[0].st);

for (int i=0; i<LightCount; i++) {
if (lights[i].enabled == 1) {

vec4 finalMaterial = vec4(0.0, 0.0, 0.0, 0.0);
vec3 lightDirection = (NormalMatrix * vec4(lights[i].position, 1)).xyz + EyeDirection;

if (lights[i].directional == 0) {
float lightDistance = length(lights[i].position - VertexPosition);
float lightAttenuation = 1 / (1.0 + (0 * lights[i].range) + ((1 / (lights[i].range * lights[i].range)) * (lightDistance * lightDistance)));

vec3 n = normalize(VertexNormal);
vec3 l = normalize(lightDirection);

float theta = clamp(dot(l, n), 0, 1);

finalMaterial += MaterialAmbient * finalTexture * lights[i].color;
finalMaterial += MaterialDiffuse * finalTexture * lights[i].color * theta;
finalMaterial += MaterialSpecular * finalTexture * pow(theta, 5);
finalMaterial *= lightAttenuation;

finalColor += finalMaterial / (lightDistance / lights[i].range);
} else {
vec3 n = normalize(VertexNormal);
vec3 l = normalize(lights[i].position);

float theta = clamp(dot(n, -l), 0, 1);

finalMaterial += MaterialAmbient * MaterialDiffuse * finalTexture;
finalMaterial += MaterialDiffuse * finalTexture * lights[i].color * theta;
finalMaterial += MaterialSpecular * finalTexture * pow(theta, 5);

finalColor += finalMaterial;
}
}
}

finalColor.w = MaterialDiffuse.w * finalTexture.w;
finalColor += vec4(MaterialEmission.xyz, 0.0);

//Set the result
gl_FragColor = finalColor;
}


The problem is rather odd and I have not been able to figure out how to fix it but at least I do know the source of the problem. It has to do with this line:


if (lights[i].enabled == 1) {


For some reason the condition is true, even when I set the uniform in my Java code to 0. So why is the condition still true? The reason I see that black quad is because none of the other lighting uniform variables have values, so it only would make sense strange results occur. Because if the condition is true, it would check if it is directional or not, since directional is 0, it assumes it is a point light and from that point on shit happens. When I put the entire code inside that if condition as a multiline comment that black quad won't render and things are the way I expected.

I'll search and try on, but also here any help would be appreciated! Kai, thanks for your help so far! Your advice helped me figuring this one out.

EDIT:

Is it just me or is the codeblock not appearing correct? I tried to edit and adjust it, but for some odd reason no scrollbars appear when they do in the previewmode when editing this message.
Title: Re: VBO - Strange black quad appears sometimes
Post by: TheBoneJarmer on October 17, 2015, 11:37:51
Sorry for the triple post but due to a bug in the codeblock my fragment shader is not entirely visible. I reported the bug to Spasi and since he asked me not to edit the post anymore, I'll make an exception for now and add a reply with the fragment shader as attachment. Sorry for the inconvience!
Title: Re: VBO - Strange black quad appears sometimes
Post by: Kai on October 17, 2015, 12:10:25
Did you ever think about throwing everything in your fragment shader over board and replace it with:


#version 110
void main() {
  gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}


What does that show?
Title: Re: VBO - Strange black quad appears sometimes
Post by: TheBoneJarmer on October 17, 2015, 12:23:23
It works like a charm that way. I started out doing that and slowely adding more and more of my original shader I added as attachment to see whether or not it would make a difference. And it turns out the problem I described above is what is causing that quad.
Title: Re: VBO - Strange black quad appears sometimes
Post by: Kai on October 17, 2015, 12:26:56
Huh... then it's definitely got to be a driver bug.
I cannot explain how a fragment shader could possibly produce fragments where there were no primitives.
Can you get hold of another computer to try your app on that, preferably with a different graphics card/driver?
Maybe you feed some shader API functions with wrong data and somehow (due to a driver bug) cause other memory to be overwritten?
Are you using a geometry shader or framebuffer objects?
Could you probably make a standalone single-file example that reproduces your issue?
Title: Re: VBO - Strange black quad appears sometimes
Post by: TheBoneJarmer on October 17, 2015, 13:09:51
Quote from: Kai on October 17, 2015, 12:26:56
Huh... then it's definitely got to be a driver bug.
I cannot explain how a fragment shader could possibly produce fragments where there were no primitives.
Can you get hold of another computer to try your app on that, preferably with a different graphics card/driver?
Maybe you feed some shader API functions with wrong data and somehow (due to a driver bug) cause other memory to be overwritten?
Are you using a geometry shader or framebuffer objects?
Could you probably make a standalone single-file example that reproduces your issue?

I'll give all of this a try!. I just tried something with the if condition I was talking about. It turns out the condition works correct after all. Because when I replaced the code inside the if block with a "finalColor = vec4(1.0, 1.0, 1.0, 1.0);". According to my previous theory it should turn white, but it didn't. Which means the code never ran in the first place and the if conditon returned false.
Title: Re: VBO - Strange black quad appears sometimes
Post by: TheBoneJarmer on October 19, 2015, 09:41:42
Okay, I finally managed to find the source of the problem. I don't think it has anything to do with my driver (luckily *pfew*) but with this line in the fragment shader:


vec3 lightDirection = (NormalMatrix * vec4(lights[i].position.x, -lights[i].position.y, lights[i].position.z, 1)).xyz + EyeDirection;


This is what is causing all the trouble. And in particular, the uniform NormalMatrix. When I replaced NormalMatrix with ModelMatrix * ViewMatrix everything works fine. So it turns out something is wrong with the normal matrix. In my java code, the normal matrix is being uploaded like this:


mNormal.identity();
shader.setUniform("NormalMatrix", Camera.main.getMatrixView().normal(mNormal));


As for the Camera's getMatrixView method, here is what it looks like.


public Matrix4f getMatrixView() {
mView.identity();
mView.rotateX(MathHelper.toRadians(rotation.x));
mView.rotateY(MathHelper.toRadians(rotation.y));
mView.rotateZ(MathHelper.toRadians(rotation.z));
mView.translate(position.x, position.y, position.z);

return mView;
}


As for my thoughts, I think something goes wrong when the matrix is being uploaded to the shader. The method I'm using to set uniforms is working like it should, otherwise I would not have been able to see my model in the first place because the ModelViewProjection matrix is being uploaded the same way. So what is left is the JOML's Matrix4f's normal() method. Is it possible I'm using it the wrong way or could this be a bug?

Anyway, thanks for your help so far!
TBJ

EDIT

It turns out the uniform ViewMatrix has problems too. Because when I replace ModelMatrix * ViewMatrix with ViewMatrix that quad appears again. Since the normal matrix is generated by the view matrix I guess the origin has something to do with it. Although I do wonder why it makes such a difference. The code is not being executed but yet when I turn it into a comment that quad doesn't appear.
Title: Re: VBO - Strange black quad appears sometimes
Post by: Kai on October 19, 2015, 10:21:59
There was indeed a bug in JOML's Matrix4f.normal().
See this commit (https://github.com/JOML-CI/JOML/commit/fa21cd91da3f2fd7bfe708dacf6414129167e03f). In some cases the normal matrix was created incorrectly.
If you use Maven, then please switch to 1.6.6-SNAPSHOT. If not, then clone/pull the repository (again).

But I repeat myself: This cannot possibly be the "source" of your problem.
It simply CANNOT be. A wrong normal matrix cannot possibly result in some fragments being shown where there was no rasterized geometry. It CANNOT!
A wrong normal matrix can however result in wrong lighting calculations where some fragments (that are being produced by visible geometry) are being lit incorrectly.

But the "source" of your problem this is surely not. You just tend to always find "manifestations" of the problem when changing something in your shader. But I still suspect a driver bug.
Title: Re: VBO - Strange black quad appears sometimes
Post by: TheBoneJarmer on October 19, 2015, 10:27:16
Oh god I almost forgot. I tried my game at another computer. Not just one but an entire forest of triangles appeared. The computer I used (still) runs Windows 7. What both computers have in common is that they both use Intel graphic cards. Are you absolutely certain it is a driver bug? Because it never happened before. I have Unity3D installed and a few other 3D editors and they work like a charm. At least, I never experienced this before. Darn this is mindbreaking haha

I do not have another laptop in range with another graphic card unfortunately. If this is a driver bug, a better question would be how to fix it. I got no clue where it starts and why, and why changing the fragment shader makes a difference. And also, is there a connection between those uniforms and the bug. A hell lot of questions. I do know a way to test it out at another computer, but that is only possible later this day. That one has a NVIDEA graphic card.
Title: Re: VBO - Strange black quad appears sometimes
Post by: Kai on October 19, 2015, 10:30:19
Can you run some of the examples in the lwjgl3-demos (https://github.com/LWJGL/lwjgl3-demos) repository?
Such as those in the fbo subpackage?
Do those work for you?
Title: Re: VBO - Strange black quad appears sometimes
Post by: TheBoneJarmer on October 19, 2015, 10:50:21
A few FBO examples work, but most examples exit on startup with this error:


java.lang.NullPointerException: in is null
at java.util.zip.ZipInputStream.<init>(ZipInputStream.java:101)
at java.util.zip.ZipInputStream.<init>(ZipInputStream.java:80)
at org.lwjgl.demo.opengl.util.WavefrontMeshLoader.readSingleFileZip(WavefrontMeshLoader.java:89)
at org.lwjgl.demo.opengl.util.WavefrontMeshLoader.loadMesh(WavefrontMeshLoader.java:103)
at org.lwjgl.demo.opengl.fbo.DepthEdgeShaderDemo20.createCube(DepthEdgeShaderDemo20.java:227)
at org.lwjgl.demo.opengl.fbo.DepthEdgeShaderDemo20.init(DepthEdgeShaderDemo20.java:165)
at org.lwjgl.demo.opengl.fbo.DepthEdgeShaderDemo20.run(DepthEdgeShaderDemo20.java:397)
at org.lwjgl.demo.opengl.fbo.DepthEdgeShaderDemo20.main(DepthEdgeShaderDemo20.java:416)


But different than that, I tried some random examples from different demos and they seem to work just fine.
Title: Re: VBO - Strange black quad appears sometimes
Post by: Cornix on October 19, 2015, 10:53:08
It might be that there is some error somewhere else in your code. Something you just overlooked. But if both computers show different behavior then it becomes likely that it is indeed some problem with the driver. It might be that you are doing something illegal (by opengl rules) but your driver does not produce an error and instead shows garbage data. This happened to me once. I was passing invalid arguments to an OpenGL function and weird things started to happen. There was no error and nothing, the driver just went with the garbage data.
Title: Re: VBO - Strange black quad appears sometimes
Post by: Kai on October 19, 2015, 10:54:51
Quote from: TheBoneJarmer on October 19, 2015, 10:50:21
A few FBO examples work, but most examples exit on startup with this error:
You need to have the /res folder in the source/classpath.
Title: Re: VBO - Strange black quad appears sometimes
Post by: TheBoneJarmer on October 19, 2015, 12:00:43
Quote from: Kai on October 19, 2015, 10:54:51
Quote from: TheBoneJarmer on October 19, 2015, 10:50:21
A few FBO examples work, but most examples exit on startup with this error:
You need to have the /res folder in the source/classpath.

Thanks, that fixed it!

Quote from: Cornix on October 19, 2015, 10:53:08
It might be that there is some error somewhere else in your code. Something you just overlooked. But if both computers show different behavior then it becomes likely that it is indeed some problem with the driver.

I do not know if I mentioned it earlier, but both graphic cards from the laptop I'm using right now and my previous one are from Intel. Different ones though but the same manufacturer. My current one shows less garbage data compared to my previous one. But they do show garbage data nonetheless.

Quote from: Cornix on October 19, 2015, 10:53:08
It might be that you are doing something illegal (by opengl rules) but your driver does not produce an error and instead shows garbage data. This happened to me once. I was passing invalid arguments to an OpenGL function and weird things started to happen. There was no error and nothing, the driver just went with the garbage data.

I just ran my game with a different computer which has a NVIDEA graphics card. The garbage data didn't occur there. Everything was working just the way it should. My mom has a laptop with a ATI Radeon graphics card which I, unfortunately, was unable to use but when I can I'll try my game there as well. But for now I got a result I can do something with. Good to know it was running fine at someone else's computer, a shame to realize it has to do with Intel (once again).

Quote from: Kai on October 19, 2015, 10:21:59
But I repeat myself: This cannot possibly be the "source" of your problem.
It simply CANNOT be. A wrong normal matrix cannot possibly result in some fragments being shown where there was no rasterized geometry. It CANNOT!
A wrong normal matrix can however result in wrong lighting calculations where some fragments (that are being produced by visible geometry) are being lit incorrectly.

But the "source" of your problem this is surely not. You just tend to always find "manifestations" of the problem when changing something in your shader. But I still suspect a driver bug.

I'm sorry but I think you misunderstood my intentions with changing the shader code. I saw a difference when I did that, so I thought that data could have been a result of a possible driver bug. But to find the bug, I have to know what part of it is going wrong. Still, I was almost certain that change would make a difference! My apologies for the inconvenience though.
Title: Re: VBO - Strange black quad appears sometimes
Post by: Kai on October 19, 2015, 12:10:43
If it's really a driver bug, which I am now also not quite certain, it would be nearly impossible to find it. After all, what do you want to find? It could be that you end up saying: Well, if I set the third-column-first-row matrix element of my MVP matrix to 0.0 instead of 1.0, everything works.
Or if you set the red component of your light color to 0.6 instead of 0.7 everything works.
The bug can manifest itself very wildly.
But those are all likely just manifestations of some other bug in your code due to you issuing wrong OpenGL commands/arguments like what Cornix said.
You just gonna have to plow through your own code once again and really make sure that you call each GL method with the correct (and by your driver supported!) arguments. Also, you should enable OpenGL debugging with a debug callback.
If that is unsupported by your card/driver you should insert GL11.glGetError() after each and every GL call.
Title: Re: VBO - Strange black quad appears sometimes
Post by: TheBoneJarmer on October 19, 2015, 18:52:00
I have been through my entire code with the glGetError() method, everything is working like a charm. But I've done more. I have made and downloaded different models. Ranging from a pack of cubes, spheres and other geometry to a dinosaur, sunglasses, fruitbasket and a porche. With those models, everything works like a charm. It only happened so far with a cylinder. And I am really starting to wonder why. Why is it that every other model I use works fine but that damned cylinder turns into crap. haha
Title: Re: VBO - Strange black quad appears sometimes
Post by: TheBoneJarmer on August 31, 2022, 07:45:35
It is has been 7 years since I used LWJGL and just learned I still have an account here. How times flies. Reading back my comments feels embarrassing. God I was a naive young idiot. Now I am just a naive idiot. lol In the meantime I have learned much, much more about OpenGL so I ought it was nice to share an update on the matter for those who like me back in the day experiences this issue. Kinda feels weird solving an issue for my past self but here goes! It was not the shader nor the driver and none of all the wild goose chasing ideas I threw up.

A couple of years ago I experienced the same issue with c++ and I learned it was actually my buffer data. My example worked with triangles and I was likely screwing up my buffers by not passing the right amount of vertices, texcoords and normals. Or with the wrong parameters for that matter. With what I know now, Kay was absolute correct to state it could not be the shaders. I know its a bit late but sorry for confusion the whack out of you! What I experienced back then was a case of what they call undefined behavior in c++. Same happens when you try to fetch an element from a const float* array that goes out of bounds. You won't get an error, just memory corruption. Which is why I saw those fragments. It was really that simple.