You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Those were my findings over the months and years of exposing myself to OpenGL. I hope it helps anyone.
15
+
These are my findings over the months and years of exposing myself to OpenGL. I hope it helps someone.
16
16
17
-
### First Things To Do
17
+
The OpenGL specification is mentioned several times throughout the article, it can be found [here](https://registry.khronos.org/OpenGL/specs/gl/glspec46.core.pdf).
18
18
19
-
Hook up [RenderDoc](https://renderdoc.org). If you have not read its getting-started, read it before anything else.
20
-
There is also a plugin available "Where is my drawcall" hook it up by following the instructions on RenderDoc's site.
19
+
### First things to do
21
20
22
-
Setup `glDebugMessageCallback` see [here](https://deccer.github.io/OpenGL-Getting-Started/02-debugging/02-debug-callback/) for example code.
21
+
Install [RenderDoc](https://renderdoc.org). If you have not read its getting-started, read it before anything else.
22
+
There is also a plugin called [Where is my Draw?](https://github.com/baldurk/renderdoc-contrib/blob/main/baldurk/whereismydraw/README.md) — install it by following the instructions [on the official repo](https://github.com/baldurk/renderdoc-contrib/tree/main).
23
23
24
-
If you use `glGetError` with or without macros like `GLCALL` or `GLCHECK` or rolled your own, get rid of it. `glDebugMessageCallback` will replace those. There is a high chance that you used it incorrectly anyway because you copy pasted it from some questionable source.
24
+
Set up `glDebugMessageCallback`. See [here](https://deccer.github.io/OpenGL-Getting-Started/02-debugging/02-debug-callback/) for example code.
25
25
26
-
Make sure you check that shader compilation *and* linking was successful. See `glGetShaderiv` & `glGetProgramiv` on compile and link status.
26
+
If you use `glGetError` with or without macros like `GLCALL` or `GLCHECK`, or you rolled your own error checking functions, get rid of them. `glDebugMessageCallback` will replace them, while avoiding any subtle bugs that may have been caused by error checking copy-paste.
27
27
28
-
### You are on a Mac
28
+
Always check that both shader compilation *and* linking were successful. Search for `glGetShaderiv` and `glGetProgramiv` for more on compile and link status.
29
29
30
-
Please port your engine to `metal` or `webgpu` at least, seriously. There is no support for `KHR_debug` and you cannot use anything > gl 4.1. That is enough reason
30
+
### If you are on a Mac
31
31
32
-
You are getting `UNSUPPORTED (log once): POSSIBLE ISSUE: unit 0 GLD_TEXTURE_INDEX_2D is unloadable and bound to sampler type (Float) - using zero texture because texture unloadable`. You need to call glGenerateMipmap(GL_TEXTURE_2D) after glTexImage2D() or set max level to 0 if you dont need/want mips.
32
+
Please port your application to Metal or WebGPU at least, seriously. There is no support for `KHR_debug`and you cannot use anything newer than OpenGL 4.1. That is enough reason to not want to use OpenGL on a Mac. If you insist on using a Mac, stay with OpenGL 3.3.
33
33
34
-
If you insist on using Mac, stay with OpenGL 3.3.
34
+
You are getting `UNSUPPORTED (log once): POSSIBLE ISSUE: unit 0 GLD_TEXTURE_INDEX_2D is unloadable and bound to sampler type (Float) - using zero texture because texture unloadable`. You need to call `glGenerateMipmap(GL_TEXTURE_2D)` after `glTexImage2D()` or set max level to 0 if you don't need or want mips.
35
35
36
36
### RenderDoc is crashing when trying to run your application
37
37
38
-
This is most likely **not** RenderDoc's fault, but yours. Something in your code is fishy and RenderDoc doesnt like it. Use a debugger/code-sanitizer to figure out
39
-
what is going on in your application. Most likely some problem around memory allocation/freeing/UB related thing.
38
+
There is a high chance something in the application's code is fishy. Use a debugger or code-sanitizer to figure out what is going on in your application. Most likely some problem with memory allocation, freeing or some kind of UB.
40
39
41
-
Another reason why RenderDoc is crashing is that it doesnt like certain extensions you might be using in your code. RenderDoc used to tell you usually and not just
42
-
crash, but that behaviour has changed since 1.36 or so. I don't know why. I have not bothered asking baldur yet. But what you can do is check your code for
43
-
things involving bindless textures, and bindless buffers. Stuff like `glMakeTextureResidentARB`, `glProgramUniform...64NV`, `glGetTextureHandleARB`. RenderDoc also does
44
-
not support legacy OpenGL. Make sure you arent using those either `glVertexXy`, `glNormalXy` etc. To debug old school stuff, use `apitrace` or nVidia's NSight Graphics.
45
-
Older versions of `gEDebugger` or `CodeXL` might work too.
40
+
Another reason why RenderDoc is crashing is that it doesn't like certain extensions you might be using in your code. RenderDoc used to tell you and not just
41
+
crash, but that behaviour has changed since 1.36 or so. But what you can do is check your code for things involving bindless textures, and bindless buffers. Stuff like `glMakeTextureResidentARB`, `glProgramUniform...64NV`, `glGetTextureHandleARB`.
46
42
47
-
### You use GLAD but it is giving you a hard time about symbols not found and multiple definitions or the likes
43
+
RenderDoc also does not support legacy OpenGL. Make sure you aren't using `glVertexXy`, `glNormalXy` etc. To debug old school stuff, use apitrace or nVidia's NSight Graphics.
44
+
Older versions of gEDebugger or CodeXL might work too.
48
45
49
-
It is most likely that the headers you are using are just outdated. Regenerate the header on dav1d's site. Or check your build system that it is
50
-
pulling a recent version of glad.
46
+
### You use GLAD but it is giving you a hard time about symbols not being found, about multiple definitions, or other similar errors
51
47
52
-
### Debug Callback Says
48
+
It is most likely that the headers you are using are just outdated. Regenerate the header on [dav1d's site](https://glad.dav1d.de/), or check that your build system is pulling a recent version of glad.
53
49
54
-
-`GL_INVALID_OPERATION error generated. Array object is not active.`:
55
-
You didn't bind a VAO. Core Context OpenGL requires a VAO bound at all times. Bind one.
50
+
### Debug callback says
56
51
57
-
### Shader Compiler Log Says
52
+
-`GL_INVALID_OPERATION error generated. Array object is not active.`
53
+
54
+
You didn't bind a VAO. Core Context OpenGL requires a VAO bound at all times.
55
+
56
+
### Shader compiler log says
58
57
59
58
-`function "main" is already defined`
60
-
You probably compile your fragment shader as vertex shader or other way around
59
+
60
+
You probably compile your fragment shader as vertex shader or the other way around.
61
61
62
62
### You are unable to figure out if an extension is supported
63
63
64
-
`GL_NV_conservative_raster` for example despite calling `glGetString(GL_EXTENSIONS)` and all that.
65
-
You either need to query extensions with a forward compatible context or you switch to query `GL_NUM_EXTENSIONS` first and
66
-
then iterate over all of them with `glGetStringi` and then check if the extension is part of that list. The latter requires a core OpenGL context.
64
+
-`GL_NV_conservative_raster` for example, despite calling `glGetString(GL_EXTENSIONS)`
65
+
66
+
You either need to query extensions with a forward compatible context or switch to query `GL_NUM_EXTENSIONS` first and then iterate over all of them with `glGetStringi` and then check if the extension is part of that list. The latter requires a core OpenGL context.
67
67
68
-
### Exception when calling glDrawElements - aka "0xC0000005"
68
+
### Exception when calling glDrawElements a.k.a. "0xC0000005"
69
69
70
-
You most likely have no indexbuffer is bound. Or it is not associated to/with the current VAO.
70
+
You most likely have no index buffer bound, or it is not associated with the current VAO.
71
71
72
-
### Exception when calling glDrawArrays / or worse the driver is crashing
72
+
### Exception when calling glDrawArrays or worse, the driver is crashing
73
73
74
-
You probably want to draw more primitives than you have in your vertexbuffer, check arguments of your `glDrawArrays` call.
75
-
Potentially you might not have set the vertex count variable and that contains an ununitialized value because you used c/c++ and are a doofus.
74
+
-You're probably drawing more primitives than you have in your vertex buffer, check the arguments of your `glDrawArrays` call.
75
+
- You might have not set the vertex count variable and as a result it contains an uninitialized value, assuming you used a language like C or C++.
76
76
77
77
### Textures/Triangles are black
78
78
79
79
Did you forget to bind the texture in question?
80
80
81
-
When you are not using `glXXXTextureStorage` but not good and old `glTexImageXX` make sure the texture is complete.
82
-
**Check** with **OpenGL Specification** what completeness entails.
81
+
If you are using `glTexImageXX`, make sure the texture is complete. Check with the OpenGL Specification what completeness entails.
83
82
84
-
If it was not complete it should have told you about it in the debug callback. **Shame on you** if you still have not set it up.
83
+
If it was not complete it should have told you about it in the debug callback. **Shame on you** if you still have not set it up :)
85
84
86
85
You might be using sampler objects. Make sure you bind one.
87
86
88
-
You might be sampling from a corner of your texture where its actually black, Check your UVs.
87
+
You might be sampling from a corner of your texture where it's actually black, check your UVs.
89
88
90
-
Another very likely reason is you didn't understand VAOs and copy pastaed it from learnopengl and added your own twist to it.
91
-
Check that your VAO setup is correct. Make sure stride, offset is set correctly. And if you are using multiple vertexbuffers for all your attributes, make sure
89
+
Check that your VAO setup is correct. Make sure stride, offset are set correctly. And if you are using multiple vertex buffers for all your attributes, make sure
92
90
they are bound properly.
93
91
94
92
You tried to use vertex colors, but you didn't setup the VAO properly.
93
+
95
94
Vertex colors might just be black. If it wasn't intentional, check the contents of your VBO.
96
95
97
96
### Screen is Black
98
97
99
98
- Check if your screen is on/connected properly
100
-
- Camera (projection/view matrices are fucked) is not looking at the scene in question
101
-
- No texture is sampled due to missing or wrong uvs => default value is 0 aka black (depends on the driver)
99
+
- Make sure your clear color is not pure black
100
+
- Camera is not looking at the scene in question (projection and/or view matrices are wrong)
101
+
- No texture is sampled due to missing or wrong uvs => default value is most likely 0, meaning black (the value depends on the driver)
102
102
- No shader bound (especially fragment shader)
103
-
- Fragment shader doesnt write anything to its output
104
-
- No viewport is set/is too small
105
-
- you might be rendering to a framebuffer, but not blitting that framebuffer to the default one or using it in a way to see its contents.
106
-
- Let clearcolor be something else than pure black
107
-
- are you rendering to multiple render targets?
108
-
- if yes, check that you called the right `gl(Named)DrawBuffers`. Check that you didnt call `gl(Named)DrawBuffer` once per render target.
109
-
- are you playing with depth-pre-pass-isms?
110
-
- make sure the gl state between passes is the same, face winding, cullmode, etc. See Appending A.3 in the gl spec for more clues about invariance.
111
-
- check winding order and cullmode, you might be looking at the wrong side of your faces
112
-
- you check renderdoc and wonder why the vertex list contains the same (perhaps even first element) only, for all vertices. Make sure your `glDrawElements(..., ..., GL_UNSIGNED_INT, ...)` or whatever datatype your indexbuffer consists of matches that parameter
113
-
- Perhaps you are trying to read an int/uint or long/ulong value from your vertex attribute. Get some glasses and double check that you called the right `glVertexAttrib`**`X`**`Pointer` when setting up your VAO.
103
+
- Fragment shader doesn't write anything to its output
104
+
- No viewport is set, or it is too small
105
+
- You might be rendering to a framebuffer, but not using it in a way that lets you see its contents like blitting it to the default framebuffer.
106
+
- Are you rendering to multiple render targets?
107
+
108
+
If you are, check that you called the right `gl(Named)DrawBuffers`. Check that you didn't call `gl(Named)DrawBuffer`, once per render target.
109
+
- Are you playing with depth-pre-pass-isms?
110
+
111
+
Make sure the gl state between passes is the same, face winding, cull mode, etc. See Appendix A.3 in the gl spec for more clues about invariance.
112
+
- Check winding order and cull mode, you might be looking at the wrong side of your faces
113
+
- You checked RenderDoc and wonder why the vertex list contains the same (perhaps even first element) only, for all vertices. Make sure your `glDrawElements(..., ..., GL_UNSIGNED_INT, ...)` or whatever datatype your indexbuffer consists of matches that parameter.
114
+
- Perhaps you are trying to read an int/uint or long/ulong value from your vertex attribute. Double check that you called the right `glVertexAttrib`**`X`**`Pointer` when setting up your VAO.
114
115
115
116
All these things can be checked with a graphics debugger of your choice.
116
117
117
118
### Textures look funny, like a garbled version of the actual image
118
119
119
-
Make sure your internalformat and actual pixel format match.
120
-
You probably used stb_image to load, but used 0 as the last parameter, and pixel data has 3 components, instead of the 4 (GL_RGBA) you told OpenGL about.
121
-
Request 4 channels from stb_image. There is almost never a reason to request 3 or less channels for color bearing pixelmaps.
120
+
Make sure your internal format and actual pixel format match.
121
+
You probably used stb_image to load, but used 0 as the last parameter, and pixel data has 3 components, instead of the 4 (`GL_RGBA`) you told OpenGL about.
122
+
Request 4 channels from stb_image. There is almost never a reason to request 3 or fewer channels for textures with color data.
122
123
123
124
### Textures look like one color component is more prominent than others
124
125
125
-
Happens when you are used to DirectXisms
126
-
127
126
- Colors are more shifted towards blue
128
127
129
-
-You probably messed up the format and asked for GL_BRG.. of sorts => make sure they match
128
+
-Original pixel data was probably in `RGB` but you asked for `GL_BRG` or some other non-matching format => make sure they match
130
129
131
130
- Colors are more shifted towards red
132
131
133
-
- Original pixeldata was probably in BGR... but you asked for GL_RGB... of sorts => make sure they match
132
+
- Original pixel data was probably in `BGR` but you asked for `GL_RGB` or some other non-matching format => make sure they match
134
133
135
134
### Textures seem to work, but the mesh also appears to be shaded weirdly as if its in some black fog
136
135
137
136
Did you generate mipmaps?
138
137
139
138
### Render artifacts like small missing tiles on a floor
140
139
141
-
VERY likely an alignment issue. **Check** the alignment rules in the **GLSL Specification**.
140
+
Very likely an alignment issue. Check the alignment rules in the GLSL Specification.
142
141
143
-
Other reasons could be that you are binding multiple textures to the same slot/unit. Check your `glBindTextureUnit` calls and if you are stuck in nonDSA land,
142
+
Other reasons could be that you are binding multiple textures to the same slot/unit. Check your `glBindTextureUnit` calls and if you are stuck in non-DSA land,
144
143
check your `glBindTexture/glActiveTexture/glUniform1f` combinations.
145
144
146
-
Another classic is not using a flat index when indexing into material buffers or texture arrays.
145
+
Another classic reason is not using a flat index when indexing into material buffers or texture arrays.
147
146
148
147
```glsl
149
148
layout(location = n) flat int in v_material_index;
150
149
```
151
150
152
151
Synchronization issues could be yet another reason. Perhaps a missing `glMemoryBarrier` at the right spot.
153
152
154
-
### Depth buffer not cleared
153
+
### Depth buffer not cleared despite calling `glClear(GL_DEPTH_BUFFER_BIT)`
155
154
156
-
- Despite calling `glClear(GL_DEPTH_BUFFER_BIT)` => check if `glDepthMask` was set to `GL_FALSE`. When you use FBOs migrate to glClearNamedFramebuffer() if you havent already (still requires glDepthMask set properly)
155
+
Check if `glDepthMask` was set to `GL_FALSE`. When using FBOs, use `glClearNamedFramebuffer()` (it still requires `glDepthMask` to be set properly)
157
156
158
157
### Weird "Z-Fighting"
159
158
160
-
-check your depth buffer, near and far planes... try near 0.1f and 512/1024 as farplane
161
-
-your depth buffer might be too small and is set to D16 only, set it to something D24 or D32
162
-
-you use SDL2 and on your platform the default might be set to D16, find the SDL2_GL_Set_Attribute which sets the depth bits for the default fbo
159
+
-Check your depth buffer, near, and far planes. Try near `0.1f` and `512/1024` as far plane.
160
+
-Your depth buffer might be too small and is set to `D16` only, set it to something `D24` or `D32`.
161
+
-You use SDL2 and on your platform the default might be set to `D16`, find the `SDL2_GL_Set_Attribute` which sets the depth bits for the default FBO.
163
162
164
-
### PS
163
+
### P.S.
165
164
166
-
`RenderDoc` is not a profiler, the frametimes you see reported there are not really usable. Use an actual gpu profiler like `NSight Graphics`. I hear you complain already
167
-
that Version YYYY.XX doesnt support your potato GPU. NVidia provides downloads for older versions as well, you just dont get the latest bling features with it.
165
+
`RenderDoc` is not a profiler, the frametimes you see reported there are not really usable. Use an actual GPU profiler like NSight Graphics. NVidia provides downloads for older versions as well, in case you have an older GPU. You just dont get the latest bling features with them.
0 commit comments