OpenGL 3D Game Tutorial 27: Skybox

preview_player
Показать описание
LWJGL tutorial series on how to create a 3D Java game with OpenGL!

Programming a skybox this week using cube map textures!

Common Problems:

-Due to hardware limitations on some computers you may see some visible seams at the edges of the skybox. If this is the case then add these two lines to the end of the loadCubeMap() method, just before returning the texID:

End of video music- Kai Engel, "Waking Stars":
Рекомендации по теме
Комментарии
Автор

Best tutorials on tube. Simple, clear, short and with a pinch of humor.
I wish you all the best.
You make the world a better place.

zamesprobes
Автор

One quick tip I have for skyboxes: this skybox will clip through the terrain and reduce the draw distance, wasting render time on objects/terrain which is beyond the bounds of the skybox. You can fix this by adding this code to the start of the skybox render method:


glDepthMask(GL_FALSE);
glDepthRange(1f, 1f);


And adding this code to the end of the method:


glDepthRange(0f, 1f);
glDepthMask(GL_TRUE);


This for one stops the skybox from being drawn onto the depth buffer, and two makes the skybox draw behind everything else, which keeps everything in view and puts the skybox at the back of the scene, so it doesn't cut any objects off.

jackdavenport
Автор

YES FINALLY! I have waited for a skybox tutorial for so long! Thank you, and keep up the good work ^^

ImSoNotSleepy
Автор

Great tutorial TM! Thanks for doing these tutorials for us they really help a lot!!

Joern
Автор

Man you're incredible keep going . I'm going to watch every single tutorial !!

droneview
Автор

A simple optimisation would be to render a sky quad, rather than the full sky box.

Because why draw all 6 faces of a cube, when the player - sitting inside it - will never see more than 5 faces and, looking up towards a corner, only 3 faces?

The idea of the sky quad is to only render a single full screen quad and then calculate the correct sampling coordinates by "unprojecting" its corners into world space.

Ordinarily, we have objects in world space that we transform into screen space for rendering. But the full screen sky quad actually lives in screen space and we unproject it - by doing the inverse transform of screen-to-world space - to work out where those quad corners would be in world space to sample the cube map in the right places.

So, render a full screen quad and the vertex shader code for that quad would be:

mat4 inverseProjection = inverse(ProjectionMatrix);
mat3 inverseModelview =
vec3 unprojected = (inverseProjection * Vertex).xyz;
eyeDirection = inverseModelview * unprojected;
gl_Position = Vertex;

Passing it your projection and camera matrices - "ProjectionMatrix" and "CameraMatrix" - in uniform variables and this can pass on "eyeDirection" to the fragment shader, which only has to simply sample the cube map at the "eyeDirection" coordinates.

(A further optimisation would be to calculate the inverse of these matrices outside of the shaders and pass them as a uniform matrix - as they are the same for all the vertices of the sky quad, so you only need calculate that once - and combine the projection and camera matrices into a single matrix.

As the only reason for passing them separately in the above is just to remove the translation on the camera matrix - by truncating it to a 3 x 3 matrix with "mat3" - so that we're always in the centre of the cube map and the sky doesn't get any closer. The equivalent of moving a sky box around so it's always centred on the camera.

The above code is just to make it nice and clear how the calculations work for people to understand what's happening. You can precalculate the matrix once and just pass that to the vertex shader, reducing the shader code to nothing more than "eyeDirection = InverseProjectCameraMatrix * Vertex.xyz" and the pixel shader to nothing more than "gl_FragColor = texture(cubemap, eyeDirection)" for two single line shaders.)

The cool thing about a sky quad is that, as it's not real geometry, the camera can never get behind it - never get on the "outside" of this imaginary sky box.

A further optimisation is to set the vertex Z coordinate to the vertex's W coordinate in the vertex shader, because then, in the perspective divide, Z / W always equals 1.0 and this means that the sky quad always lives on the far plane, behind everything, and can be rendered last, after all your scene geometry, so only the bits of it that are visible past everything ever get rendered. To make sure it then passes the depth test, change the depth testing function to "LEQUAL", so that the sky quad's 1.0 depth always passes.

The results will look indistinguishable to a traditional sky box, but the GPU has to do a lot less work to achieve it.

I thought I'd share this little trick here, as there aren't really any tutorials out there that take the "sky quad" approach instead and some folks, once they've mastered what's in this video, might want to play around with this simple optimisation to further improve things.

klaxoncow
Автор

If you're getting seams at the edge of your skybox the add these two lines to the end of the loadCubeMap() method, just before returning the texID:
GL11.glTexParameteri(GL13.GL_TEXTURE_CUBE_MAP, GL11.GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE);
GL11.glTexParameteri(GL13.GL_TEXTURE_CUBE_MAP, GL11.GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE);

ThinMatrix
Автор

Reading some comments of people being annoyed that you're sticking to basics, thought I'd give my 2 cents as a completely biased supporter of you.
I've built entire 2d games using opengl and lwgjl and your tutorials are my first step into 3d. These basics are incredibly helpful, I've tried to dick around with sky boxes but i couldn't get it.
Would I like collision detection and normal maps? Hell yeah. But I was still super excited to finally have the skybox tutorial, and I sincerely hope you put your game first. This series should always be behind in priority.

I guess what I'm saying is I found this tutorial useful, and someone always will, so please don't skip steps.

Looking forward to your kick starter!

AdelaarGD
Автор

TM thank you for another informative tutorial. I do hope you continue as per your schedule, as I am trying to work ahead to get an understanding of these concepts.

gilleyman
Автор

First of all, thank you too much for this amazing tutorial series. I'm looking forward for the multiplayer part. It will be lovely! THANK YOU!

AlissonEgea
Автор

Just wanna say keep making new tutorials pls. You're the apple of my eye!!

Leonustice
Автор

I don't know if someone else has mentioned this already, but in the vertex shader it's also possible to multiply the view matrix with vec4(position, 0.0f) instead of vec4(position, 1.0f). Because of the 0.0f the view matrix' translation won't affect the vector at all, but the rotation (and scale) will. That way you don't have to create a modified view matrix just for this shader.
After that multiplication the vector's w coordinate does need to be manually set back to 1.0f though, otherwise the projection matrix won't apply correctly anymore:

vec4 untranslated_view = viewMatrix * vec4(position, 0.0f);
untranslated_view.w = 1.0f;
gl_Position = projectionMatrix * untranslated_view;

It probably doesn't make any difference for the performance, but it's still nice, I suppose. ^w^

Kumodatsu
Автор

Au top ! I'm waiting for thoses four next episodes !!

tks_
Автор

Great tutorial as always ! Can't wait for the next one ! :)

JesseScene
Автор

I love how you give us the viewmatrix to start with, tell us to delete, then add it again. :P

beethovenbay-toe-venn
Автор

In the 17:30 I get black world background and no skybox:/

AdriansNetlis
Автор

im getting holes in the corners of the skybox, any ideas?

EDIT: found that the corners are too far away to render, changed some stuff around and it works fine 

WolfAntian
Автор

My skybox was black, I accidentally forgot to multiple width by 4 at pngdecoder..now its working...good tutorial Tnx Matrix.

alexanderlastname
Автор

Amazing just finished the tutorial and everything works great and im happy its ever 2 weeks because than i can focus of my work and than once in a while do my game

MohammedPlaysMC
Автор

I spent a good couple of hours tracking down my issue of the Skybox not being drawn. Eventually I figured out that the first thing I needed to do in the SkyboxRenderer class's Render method was disable backface culling. Then the last thing before leaving the method was re-enable backface culling.

mpgef