Handmade Hero»Episode Guide
Fixing Depth Peel Artifacts
?
?

Keyboard Navigation

Global Keys

[, < / ], > Jump to previous / next episode
W, K, P / S, J, N Jump to previous / next marker
t / T Toggle theatre / SUPERtheatre mode
V Revert filter to original state Y Select link (requires manual Ctrl-c)

Menu toggling

q Quotes r References f Filter y Link c Credits

In-Menu Movement

a
w
s
d
h j k l


Quotes and References Menus

Enter Jump to timecode

Quotes, References and Credits Menus

o Open URL (in new tab)

Filter Menu

x, Space Toggle category and focus next
X, ShiftSpace Toggle category and focus previous
v Invert topics / media as per focus

Filter and Link Menus

z Toggle filter / linking mode

Credits Menu

Enter Open URL (in new tab)
0:22Recap and set the stage for the day, improving the depth peeling
0:22Recap and set the stage for the day, improving the depth peeling
0:22Recap and set the stage for the day, improving the depth peeling
2:14Run the game, note the rendering artifacts while depth peeling, and consider what may be causing them
2:14Run the game, note the rendering artifacts while depth peeling, and consider what may be causing them
2:14Run the game, note the rendering artifacts while depth peeling, and consider what may be causing them
7:23handmade_opengl.cpp: Consider how CompilePeelComposite() is computing the ResultColor
7:23handmade_opengl.cpp: Consider how CompilePeelComposite() is computing the ResultColor
7:23handmade_opengl.cpp: Consider how CompilePeelComposite() is computing the ResultColor
10:16handmade_opengl.cpp: Make CompilePeelComposite() clamp the ResultColor to 0 to 11
10:16handmade_opengl.cpp: Make CompilePeelComposite() clamp the ResultColor to 0 to 11
10:16handmade_opengl.cpp: Make CompilePeelComposite() clamp the ResultColor to 0 to 11
10:57Run the game to see that that did not improve our situation, but did change our background colour
10:57Run the game to see that that did not improve our situation, but did change our background colour
10:57Run the game to see that that did not improve our situation, but did change our background colour
11:43handmade_opengl.cpp: Investigate how CompilePeelComposite() is drawing the peels
11:43handmade_opengl.cpp: Investigate how CompilePeelComposite() is drawing the peels
11:43handmade_opengl.cpp: Investigate how CompilePeelComposite() is drawing the peels
15:58Run the game to determine that the alpha inverse computation is wrong
15:58Run the game to determine that the alpha inverse computation is wrong
15:58Run the game to determine that the alpha inverse computation is wrong
16:44handmade_opengl.cpp: Prevent CompilePeelComposite() from putting alpha in Peel3
16:44handmade_opengl.cpp: Prevent CompilePeelComposite() from putting alpha in Peel3
16:44handmade_opengl.cpp: Prevent CompilePeelComposite() from putting alpha in Peel3
17:48handmade_opengl.cpp: Make CompilePeelComposite() clamp the colours again, and run the game to determine that this part of the composite is not the problem
17:48handmade_opengl.cpp: Make CompilePeelComposite() clamp the colours again, and run the game to determine that this part of the composite is not the problem
17:48handmade_opengl.cpp: Make CompilePeelComposite() clamp the colours again, and run the game to determine that this part of the composite is not the problem
19:16handmade_opengl.cpp: Make CompilePeelComposite() colour the peels
19:16handmade_opengl.cpp: Make CompilePeelComposite() colour the peels
19:16handmade_opengl.cpp: Make CompilePeelComposite() colour the peels
21:10Run the game to see the coloured peels
21:10Run the game to see the coloured peels
21:10Run the game to see the coloured peels
22:43handmade_opengl.cpp: Make CompilePeelComposite() multiply the peel colour by its alpha, and run the game to see that the error occurs where many peels overlap
22:43handmade_opengl.cpp: Make CompilePeelComposite() multiply the peel colour by its alpha, and run the game to see that the error occurs where many peels overlap
22:43handmade_opengl.cpp: Make CompilePeelComposite() multiply the peel colour by its alpha, and run the game to see that the error occurs where many peels overlap
25:17handmade_opengl.cpp: Enable CompileZBiasProgram() to fog pixels out before their alpha is 0
25:17handmade_opengl.cpp: Enable CompileZBiasProgram() to fog pixels out before their alpha is 0
25:17handmade_opengl.cpp: Enable CompileZBiasProgram() to fog pixels out before their alpha is 0
26:19Run the game and erroneously see colour on pixels that should have been fogged completely out
26:19Run the game and erroneously see colour on pixels that should have been fogged completely out
26:19Run the game and erroneously see colour on pixels that should have been fogged completely out
28:07handmade_opengl.cpp: Make CompileZBiasProgram() correctly clip out transparent pixels from the depth peel
28:07handmade_opengl.cpp: Make CompileZBiasProgram() correctly clip out transparent pixels from the depth peel
28:07handmade_opengl.cpp: Make CompileZBiasProgram() correctly clip out transparent pixels from the depth peel
29:41Run the game to see that we're a lot better
29:41Run the game to see that we're a lot better
29:41Run the game to see that we're a lot better
31:47handmade_opengl.cpp: Try making CompileZBiasProgram() draw Peel3 as bright pink and run the game to see purple where the artifact occurs
31:47handmade_opengl.cpp: Try making CompileZBiasProgram() draw Peel3 as bright pink and run the game to see purple where the artifact occurs
31:47handmade_opengl.cpp: Try making CompileZBiasProgram() draw Peel3 as bright pink and run the game to see purple where the artifact occurs
33:50Consider how best to mix the peels together
33:50Consider how best to mix the peels together
33:50Consider how best to mix the peels together
36:26Blackboard: Depth Peel Sandwich
36:26Blackboard: Depth Peel Sandwich
36:26Blackboard: Depth Peel Sandwich
40:26Run the game and think about what's actually happening with the artifact
40:26Run the game and think about what's actually happening with the artifact
40:26Run the game and think about what's actually happening with the artifact
43:24handmade_opengl.cpp: Enable CompileZBiasProgram() to draw something in the last peel above a given alpha threshold
43:24handmade_opengl.cpp: Enable CompileZBiasProgram() to draw something in the last peel above a given alpha threshold
43:24handmade_opengl.cpp: Enable CompileZBiasProgram() to draw something in the last peel above a given alpha threshold
48:18Run the game to see that that did help
48:18Run the game to see that that did help
48:18Run the game to see that that did help
50:51handmade_opengl.cpp: Make OpenGLRenderCommands() clear the alpha to 1, and the shader to undo the premultiplied alpha
50:51handmade_opengl.cpp: Make OpenGLRenderCommands() clear the alpha to 1, and the shader to undo the premultiplied alpha
50:51handmade_opengl.cpp: Make OpenGLRenderCommands() clear the alpha to 1, and the shader to undo the premultiplied alpha
52:20Run the game to see that it looks worse
52:20Run the game to see that it looks worse
52:20Run the game to see that it looks worse
52:53handmade_opengl.cpp: Note that our art asset packer does not handle sRGB
52:53handmade_opengl.cpp: Note that our art asset packer does not handle sRGB
52:53handmade_opengl.cpp: Note that our art asset packer does not handle sRGB
55:54handmade_opengl.cpp: Consider that clamped values cannot be used at the vertex level
55:54handmade_opengl.cpp: Consider that clamped values cannot be used at the vertex level
55:54handmade_opengl.cpp: Consider that clamped values cannot be used at the vertex level
57:12Blackboard: Incorrect clamping
57:12Blackboard: Incorrect clamping
57:12Blackboard: Incorrect clamping
58:10handmade_opengl.cpp: Make the FragmentCode itself in CompileZBiasProgram() clamp and compute the fog
58:10handmade_opengl.cpp: Make the FragmentCode itself in CompileZBiasProgram() clamp and compute the fog
58:10handmade_opengl.cpp: Make the FragmentCode itself in CompileZBiasProgram() clamp and compute the fog
58:54Blackboard: Vertex and Fragment Shader Output
58:54Blackboard: Vertex and Fragment Shader Output
58:54Blackboard: Vertex and Fragment Shader Output
1:00:23Run the game, crash in shader compilation and reorganise the code
1:00:23Run the game, crash in shader compilation and reorganise the code
1:00:23Run the game, crash in shader compilation and reorganise the code
1:01:39Run the game to see that the effect is very different, and the artifact is gone
1:01:39Run the game to see that the effect is very different, and the artifact is gone
1:01:39Run the game to see that the effect is very different, and the artifact is gone
1:04:38Note that we probably would still want to use multisampling on fast GPUs
1:04:38Note that we probably would still want to use multisampling on fast GPUs
1:04:38Note that we probably would still want to use multisampling on fast GPUs
1:06:46handmade_opengl.cpp: Begin to enable OpenGLRenderCommands() to conditionally perform multisampling
1:06:46handmade_opengl.cpp: Begin to enable OpenGLRenderCommands() to conditionally perform multisampling
1:06:46handmade_opengl.cpp: Begin to enable OpenGLRenderCommands() to conditionally perform multisampling
1:13:08Consider changing the renderer to draw at the size at which the game is running
1:13:08Consider changing the renderer to draw at the size at which the game is running
1:13:08Consider changing the renderer to draw at the size at which the game is running
1:17:07handmade_opengl.cpp: Change OpenGLRenderCommands() to draw at the correct aspect ratio
1:17:07handmade_opengl.cpp: Change OpenGLRenderCommands() to draw at the correct aspect ratio
1:17:07handmade_opengl.cpp: Change OpenGLRenderCommands() to draw at the correct aspect ratio
1:21:06Run the game to see the correct letterboxing
1:21:06Run the game to see the correct letterboxing
1:21:06Run the game to see the correct letterboxing
1:21:41handmade_opengl.cpp: Enable OpenGLBindFramebuffer() to blit to the correct size
1:21:41handmade_opengl.cpp: Enable OpenGLBindFramebuffer() to blit to the correct size
1:21:41handmade_opengl.cpp: Enable OpenGLBindFramebuffer() to blit to the correct size
1:25:11Run the game to see that it's nice and clean
1:25:11Run the game to see that it's nice and clean
1:25:11Run the game to see that it's nice and clean
1:25:38win32_handmade.cpp: Draw to a lower resolution, stretched up
1:25:38win32_handmade.cpp: Draw to a lower resolution, stretched up
1:25:38win32_handmade.cpp: Draw to a lower resolution, stretched up
1:26:02Run the game and see some weird artifacts and investigate those artifacts
1:26:02Run the game and see some weird artifacts and investigate those artifacts
1:26:02Run the game and see some weird artifacts and investigate those artifacts
1:28:33handmade_opengl.cpp: Try to force real sRGB off
1:28:33handmade_opengl.cpp: Try to force real sRGB off
1:28:33handmade_opengl.cpp: Try to force real sRGB off
1:30:07Run the game and consider that, because the alpha is not computed with sRGB, it does not line up right when stretched
1:30:07Run the game and consider that, because the alpha is not computed with sRGB, it does not line up right when stretched
1:30:07Run the game and consider that, because the alpha is not computed with sRGB, it does not line up right when stretched
1:31:18handmade_opengl.cpp: Consider that the bilinear filter on the depth peel composite may not be correct
1:31:18handmade_opengl.cpp: Consider that the bilinear filter on the depth peel composite may not be correct
1:31:18handmade_opengl.cpp: Consider that the bilinear filter on the depth peel composite may not be correct
1:33:47handmade_opengl.cpp: Make OpenGLRenderCommands() use a raw texel sample in the depth peel
1:33:47handmade_opengl.cpp: Make OpenGLRenderCommands() use a raw texel sample in the depth peel
1:33:47handmade_opengl.cpp: Make OpenGLRenderCommands() use a raw texel sample in the depth peel
1:34:38Run the game to see that the fringing while stretching has gone
1:34:38Run the game to see that the fringing while stretching has gone
1:34:38Run the game to see that the fringing while stretching has gone
1:35:02Blackboard: Correctly sampling from texels for stretching
1:35:02Blackboard: Correctly sampling from texels for stretching
1:35:02Blackboard: Correctly sampling from texels for stretching
1:39:25handmade_opengl.cpp: Determine to composite to an intermediate framebuffer, and then stretch that to the final image
1:39:25handmade_opengl.cpp: Determine to composite to an intermediate framebuffer, and then stretch that to the final image
1:39:25handmade_opengl.cpp: Determine to composite to an intermediate framebuffer, and then stretch that to the final image
1:42:57handmade_opengl.cpp: Introduce CompileFinalStretch()
1:42:57handmade_opengl.cpp: Introduce CompileFinalStretch()
1:42:57handmade_opengl.cpp: Introduce CompileFinalStretch()
1:48:34handmade_opengl.cpp: Introduce CreateFramebuffer()
1:48:34handmade_opengl.cpp: Introduce CreateFramebuffer()
1:48:34handmade_opengl.cpp: Introduce CreateFramebuffer()
1:57:03handmade_opengl.cpp: Enable CreateFramebuffer() to conditionally apply filtering2
1:57:03handmade_opengl.cpp: Enable CreateFramebuffer() to conditionally apply filtering2
1:57:03handmade_opengl.cpp: Enable CreateFramebuffer() to conditionally apply filtering2
1:58:37handmade_opengl.cpp: Make OpenGLRenderCommands() create the final GlobalResolveFramebuffer
1:58:37handmade_opengl.cpp: Make OpenGLRenderCommands() create the final GlobalResolveFramebuffer
1:58:37handmade_opengl.cpp: Make OpenGLRenderCommands() create the final GlobalResolveFramebuffer
2:02:34Run the game to admire the correct composite and then stretching
2:02:34Run the game to admire the correct composite and then stretching
2:02:34Run the game to admire the correct composite and then stretching
2:03:35win32_handmade.cpp: Draw to decreasingly smaller resolutions
2:03:35win32_handmade.cpp: Draw to decreasingly smaller resolutions
2:03:35win32_handmade.cpp: Draw to decreasingly smaller resolutions
2:05:58Run the game in pixel art modeα
2:05:58Run the game in pixel art modeα
2:05:58Run the game in pixel art modeα
2:07:04Q&A
🗩
2:07:04Q&A
🗩
2:07:04Q&A
🗩
2:07:36naysayer88 OpenGL sucks
🗪
2:07:36naysayer88 OpenGL sucks
🗪
2:07:36naysayer88 OpenGL sucks
🗪
2:10:56naysayer88 The problem is there is no way for me to know what the "good API" is any more...
🗪
2:10:56naysayer88 The problem is there is no way for me to know what the "good API" is any more...
🗪
2:10:56naysayer88 The problem is there is no way for me to know what the "good API" is any more...
🗪
2:14:30jezzi23 In Win32InitOpenGL(), why do you use two different forms for assigning modern OpenGL function pointers, i.e. using Win32GetOpenGLFunction(Name) macro for some but assigning others directly?
🗪
2:14:30jezzi23 In Win32InitOpenGL(), why do you use two different forms for assigning modern OpenGL function pointers, i.e. using Win32GetOpenGLFunction(Name) macro for some but assigning others directly?
🗪
2:14:30jezzi23 In Win32InitOpenGL(), why do you use two different forms for assigning modern OpenGL function pointers, i.e. using Win32GetOpenGLFunction(Name) macro for some but assigning others directly?
🗪
2:15:01serialqwiller Just so you know, your stream no longer shows up in either the "Game Development" or "Programming" categories on twitch. It's almost a hidden stream now just for those who already followed
🗪
2:15:01serialqwiller Just so you know, your stream no longer shows up in either the "Game Development" or "Programming" categories on twitch. It's almost a hidden stream now just for those who already followed
🗪
2:15:01serialqwiller Just so you know, your stream no longer shows up in either the "Game Development" or "Programming" categories on twitch. It's almost a hidden stream now just for those who already followed
🗪
2:16:10nyeecola I tried your anonymous union and structs trick and the compiler (g++) screams at me saying I need some label in the struct name to conform to the standard. So I looked it up on google and it appears to be undefined behavior to use this trick. Should I be afraid of that?
🗪
2:16:10nyeecola I tried your anonymous union and structs trick and the compiler (g++) screams at me saying I need some label in the struct name to conform to the standard. So I looked it up on google and it appears to be undefined behavior to use this trick. Should I be afraid of that?
🗪
2:16:10nyeecola I tried your anonymous union and structs trick and the compiler (g++) screams at me saying I need some label in the struct name to conform to the standard. So I looked it up on google and it appears to be undefined behavior to use this trick. Should I be afraid of that?
🗪
2:19:56soysaucethekid The cursor always seems to be on the loading(?) icon. Is there a way to fix that? (I'm running into this issue and am not sure if there is some windows message I need to process)
🗪
2:19:56soysaucethekid The cursor always seems to be on the loading(?) icon. Is there a way to fix that? (I'm running into this issue and am not sure if there is some windows message I need to process)
🗪
2:19:56soysaucethekid The cursor always seems to be on the loading(?) icon. Is there a way to fix that? (I'm running into this issue and am not sure if there is some windows message I need to process)
🗪
2:20:18win32_handmade.cpp: Try to stop the wait cursor displaying once we have finished loading
2:20:18win32_handmade.cpp: Try to stop the wait cursor displaying once we have finished loading
2:20:18win32_handmade.cpp: Try to stop the wait cursor displaying once we have finished loading
2:28:38fr0styninja You can set the cursor on the WNDCLASS struct .hCursor = LoadCursor(0, IDC_ARROW);
🗪
2:28:38fr0styninja You can set the cursor on the WNDCLASS struct .hCursor = LoadCursor(0, IDC_ARROW);
🗪
2:28:38fr0styninja You can set the cursor on the WNDCLASS struct .hCursor = LoadCursor(0, IDC_ARROW);
🗪
2:30:06nyeecola You said on one stream that you don't need header guards because you have only one translation unit. I guess you meant that you're sure you only include each header once? Because even if you only have one translation unit you still can have problems if you include the same header twice
🗪
2:30:06nyeecola You said on one stream that you don't need header guards because you have only one translation unit. I guess you meant that you're sure you only include each header once? Because even if you only have one translation unit you still can have problems if you include the same header twice
🗪
2:30:06nyeecola You said on one stream that you don't need header guards because you have only one translation unit. I guess you meant that you're sure you only include each header once? Because even if you only have one translation unit you still can have problems if you include the same header twice
🗪
2:31:37nyeecola Multiple anonymous unions inside one struct, is that allowed?
🗪
2:31:37nyeecola Multiple anonymous unions inside one struct, is that allowed?
🗪
2:31:37nyeecola Multiple anonymous unions inside one struct, is that allowed?
🗪
2:32:37Wrap it up with a plug of Lysa3
📖
2:32:37Wrap it up with a plug of Lysa3
📖
2:32:37Wrap it up with a plug of Lysa3
📖
2:35:19Promote CaptainKraft's Patreon4
📖
2:35:19Promote CaptainKraft's Patreon4
📖
2:35:19Promote CaptainKraft's Patreon4
📖
2:37:01That's about it for today, with a glimpse into the future
🗩
2:37:01That's about it for today, with a glimpse into the future
🗩
2:37:01That's about it for today, with a glimpse into the future
🗩