OpenGL 3D Game Tutorial 27: Skybox

LWJGL tutorial series on how to create a 3D Java game with OpenGL!

Programming a skybox this week using cube map textures!

Download PNGDecoder: or

Downloadable Source Code:

Skybox Textures:

OpenGL Textures Info:

Loads of skyboxes:

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:

Support the series on Patreon:

Facebook Page:
Check out my game on IndieDB:

End of video music- Kai Engel, “Waking Stars”:


Xem thêm bài viết khác:

Article Categories:

All Comments

  • 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.

    zames probes July 21, 2020 2:27 pm Reply
  • instead of changing the view matrix in the renderer you can treat the position of the vertex as a vector by replacing vec4(position, 1.0) with vec4(position, 0.0) when you calculate gl_Position

    MrTarnegol July 21, 2020 2:27 pm Reply
  • Couldn't I just go into blender and make my skybox there? :/

    Alan Burns July 21, 2020 2:27 pm Reply
  • i love your videos, but i have a problem and is that when rendering the sky box, this does not look right when being reflected by water

    Da_ K8Gamer July 21, 2020 2:27 pm Reply
  • Hi. I know this is a 4-year-old tutorial. Nevertheless, could you please help me out with this issue?

    Whenever I enter my game, only one side of the skybox renders, and the images render in a very distorted way. When I move back, away from it, one of the edges follows me. Whenever I implement the thing to make it follow the camera, it disappears.

    Some images here:

    Do you have any insights as to what could cause this problem?


    Lonsdaleite Politics July 21, 2020 2:27 pm Reply
  • For people who experience serious problems like flickering in the edges (seams) of the skybox just add this line somewhere in your project (it need to be called just one): glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS)

    Colorful Darkness July 21, 2020 2:27 pm Reply
  • For some reasons, up and down textures for cubemap are not seamless transitioning with other textures.
    I found solution for my case if you download skyboxes from such website as suggested in the video, you need to do the following

    – rotate up texture 90 degrees counter-clockwise
    – rotate bottom texture 90 degrees clockwise

    That's all! Thanks for video!

    haxpor July 21, 2020 2:27 pm Reply
  • Hi! It all looks wonderful, but I would like to see the sky (the top of the cube) without the ferns, player and other stuff… How can I do that?
    P.S.: I hope I'm not too buggy with my questions! 😀

    Silviu Alexandru July 21, 2020 2:27 pm Reply
  • Isn't it better to just render a huge textured cube with backface culling turned off?

    Bruce Walker July 21, 2020 2:27 pm Reply
  • 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:

    glDepthRange(1f, 1f);

    And adding this code to the end of the method:

    glDepthRange(0f, 1f);

    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.

    Jack Davenport July 21, 2020 2:27 pm Reply
  • An important note if you wish to create your own set of skybox images from scratch if that each of the images needs to be a 90 degree field of view. The total view around the entire skybox is 360 degrees. Seeing as how we have four sides, each side needs to cover a 90 degree field of view (90 * 4 = 360). The top and bottom also need to be 90 degree field of view. I used terragen to create some nice skyboxes, I rendered the sky etc… and set the view to 90 degrees, then turned the camera 90 degrees to get each direction perfectly, keeping the output square. I then faced what would be the front direction and then looked straight up and straight down to render top and bottom. For one skybox I left out the landscape entirely and then edited the sides and the bottom view so they had a fog colour and solid half at the bottom which was the same colour as the in game fog so it blends in perfectly. On my channel I have a video called "City3D" I made years ago which use this and you can see how well it works.

    With my own skybox, I took an idea from the older Battlefield 1942 game, which done it's skyboxes so that the bottom half of them, which you seen on the horizon had a more foggy, solid colour which matched whatever the fog colour was so they both blended together nicely.

    Neil Roy July 21, 2020 2:27 pm Reply
  • I didn't notice it before but when I looked at the corners of the skybox I saw that the corners were a little bit glitchy. How can this be fixed?

    KeN Ny July 21, 2020 2:27 pm Reply
  • Thank you for your Awesome tutorials! I have developed an APP with some OpenGL aspects:

    neo expert July 21, 2020 2:27 pm Reply
  • 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 July 21, 2020 2:27 pm Reply
  • Just wanna say keep making new tutorials pls. You're the apple of my eye!!

    Leon Lyu July 21, 2020 2:27 pm Reply
  • All the textures load fine, but the "top.png" is all multi colored lines, like an old TV(the static looking stuff). why is this? why just top.png and no others ? I would appreciate help from anyone

    Kyle Pearce July 21, 2020 2:27 pm Reply
  • I'm having a problem with the lwjgl library that seemed to start after I added the PNGDecoder jar. This is the console output: Exception in thread "main" java.lang.ExceptionInInitializerError
    Caused by:
    java.lang.RuntimeException: No OpenGL context found in the current thread.
    at org.lwjgl.opengl.GLContext.getCapabilities(
    at org.lwjgl.opengl.GL30.glBindVertexArray(
    at renderEngine.Loader.createVAO(
    at renderEngine.Loader.loadToVAO(
    at weapons.RenderWeapon.<init>(
    at entities.Camera.<init>(
    at gameObjects.GameObjects.<init>(
    at engineTester.MainGameLoop.<clinit>(
    I have no idea how to fix this.

    Tyler Marchildon July 21, 2020 2:27 pm Reply
  • If you render the skybox first with depth testing disabled, the skybox wont collide with the terrain like at 18:50.

    Aidan Haddon-Wright July 21, 2020 2:27 pm Reply
  • For me, the sides of the skybox is rendering upside down.

    coden4 July 21, 2020 2:27 pm Reply
  • Is it just my terrain that won't render at coordinates like 1, 1 and -2, -2?

    Bob Bobety July 21, 2020 2:27 pm Reply
  • my skybox is just a 2d wall?!?!

    thatmadhacker July 21, 2020 2:27 pm Reply
  • If anybody is getting this error: Exception in thread "main" java.lang.IllegalArgumentException: ByteBuffer is not direct
    In the loader class, in the decodeTextureFile method, look for where you allocate the bytebuffer and change that line to: buffer = ByteBuffer.allocateDirect(4 * width * height);

    Ojas Landge July 21, 2020 2:27 pm Reply
  • I'm starting to have PTSD from these Fragment and Vertex Shader files… Oh well I can't let it stop me from creating this, after spending so much time on it.

    Jordan Mancini July 21, 2020 2:27 pm Reply
  • My skybox was black,I accidentally forgot to multiple width by 4 at its working…good tutorial Tnx Matrix.

    Alexander LastName July 21, 2020 2:27 pm Reply
  • How would you do a procedural skybox I tried to set one up but it just ended up rendering the default blue color and nothing else

    Null void July 21, 2020 2:27 pm Reply
  • I am having trouble with the downloaded code in the loader class.
    none of the imports I can use appear to work for that.

    LegoGenius 1st July 21, 2020 2:27 pm Reply
  • er, what about the PNGDecoder class from slick util?

    Fireboyev July 21, 2020 2:27 pm Reply
  • why dont u just call import static org.lwjgl.opengl.GL13.*;
    or does it effect on memory?

    The Flair July 21, 2020 2:27 pm Reply
  • I tried to make the skybox size to 1000 and what happens is when i try to look above the sides of the skybox seems to have triangular wholes?

    lorenzo garcia July 21, 2020 2:27 pm Reply
  • why not skydome?

    lorenzo garcia July 21, 2020 2:27 pm Reply
  • I'm just wondering that the fog distance should be calculate from the player instead of the camera. Therefore, zoom in and out won't change visible area.

    Donkas July 21, 2020 2:27 pm Reply
  • Hey, I just wanted to say thanks with this for teaching me so much:
    i.imgur dot com/tInCooh.png

    LapisSea July 21, 2020 2:27 pm Reply
  • My skybox will only render as a 2d plane

    Singular Healer July 21, 2020 2:27 pm Reply
  • In the Loader method I keep getting a problem with the Format.RGBA constant. >.< it can find one but it expects another.

    Rui Lourenço July 21, 2020 2:27 pm Reply
  • my skybox is upside down, and all the vertex positions are not correct!

    CookingAndJava July 21, 2020 2:27 pm Reply
  • Sorry to bother you with this 2 years after upload but i cant get that Skybox working … it's just not rendering to the screen :/ And I can't find the error I made even after looking your vid about 5 times D: Do you coincidentally have the code for this episode so I can copy it ? ^^'

    Thomas Köhler July 21, 2020 2:27 pm Reply
  • your skybox is 500 in size, but in your shader you assign vertices to texcoords, isn't that a bit dangerous? because as I know texcoords goes from 0 to 1 (in this particular case from -1 to 1). Wouldn't be correct to have texcoords buffer attribute separately (exclusively in the range of -1…1) ?

    iani_3d July 21, 2020 2:27 pm Reply
  • Thanks for these tutorials. I'd rather build my own engine than use someone else's. I just want to understand all the details, and i feel that using some other already complete engine won't get me there.

    StormWolf01 July 21, 2020 2:27 pm Reply
  • Exception in thread "main" java.lang.IllegalArgumentException: Number of remaining buffer elements is 1051648, must be at least 4194304. Because at most 4194304 elements can be returned, a buffer with at least 4194304 elements is required, regardless of actual returned element count
    at org.lwjgl.BufferChecks.throwBufferSizeException(
    at org.lwjgl.BufferChecks.checkBufferSize(
    at org.lwjgl.BufferChecks.checkBuffer(
    at org.lwjgl.opengl.GL11.glTexImage2D(
    at renderEngine.Loader.loadCubeMap(
    at skybox.SkyboxRenderer.<init>(
    at renderEngine.MasterRenderer.<init>(
    at engineTester.MainGameLoop.main(

    Sergey Klassen July 21, 2020 2:27 pm Reply
  • 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.

    Matthew Gefaller July 21, 2020 2:27 pm Reply
  • why do you set a skybox size when you can just disable the GL_DEPTH_TEST

    Ross B July 21, 2020 2:27 pm Reply
  • There is a problem with the skybox code in dropbox. When I them it says "We can't find the page your looking for". Could someone please put the code in the comments?

    Technosis July 21, 2020 2:27 pm Reply
  • In Loader class the mothod i've copied from your link

    decoder.decode(buffer, width * 4, Format.RGBA);

    This Format.RGBA is not working. showing red.
    saying Wrond 3d argument type

    Stany Miles July 21, 2020 2:27 pm Reply
  • Sky skybox isnt a box and is textures completly wrong:

    Here my code:
    public int loadCubeMap(String[] textureFiles) {
    int texID = GL11.glGenTextures();
    GL11.glBindTexture(GL13.GL_TEXTURE_CUBE_MAP, texID);

    for(int i = 0; i < textureFiles.length; i++) {
    TextureData data = decodeTextureFile("res/skybox/cloud/" + textureFiles[i] + ".png");
    GL11.glTexImage2D(GL13.GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL11.GL_RGBA, data.getWidth(), data.getHeight(), 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, data.getBuffer());
    return texID;

    private static String[] TEXTURE_FILES = { "right", "left", "top", "bottom", "back", "front" };
    private RawModel cube;
    private int texture;
    private SkyboxShader shader;

    public SkyboxRenderer(Loader loader, Matrix4f projectionMatrix) {
    cube = loader.loadToVAO(VERTICES, 3);
    texture = loader.loadCubeMap(TEXTURE_FILES);
    shader = new SkyboxShader();

    public void render(Camera camera) {
    GL11.glBindTexture(GL13.GL_TEXTURE_CUBE_MAP, texture);
    GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, cube.getVertexCount());

    IceRise July 21, 2020 2:27 pm Reply
  • It seems as if only the front half of my skybox is rendering. The other half is just the regular sky color. Any ideas why?

    EDIT: I found the problem. In the render method of my SkyboxRenderer, in the 7th line, I had cube.getVaoID() instead of cube.getVertexCount(). I am such a dummy

    Some Random Fellow July 21, 2020 2:27 pm Reply
  • I find it mildly amusing that the skybox coordinates take up a kilobyte

    Some Random Fellow July 21, 2020 2:27 pm Reply

Leave a Reply

Your email address will not be published. Required fields are marked *