what you need to draw the skybox:
– ability to load textures (i use SOIL, it actually has a function to create a cubemap)
– a shader, a vertexarray and a buffer (filled with cube vertices)
here is how i setup my skybox:
float vertices[] = {
// vertex1 vertex2 vertex3 vertex4
/* xpos */ +1, -1, +1, +1, +1, +1, +1, +1, -1, +1, -1, -1,
/* xneg */ -1, -1, -1, -1, +1, -1, -1, +1, +1, -1, -1, +1,
/* ypos */ -1, +1, -1, +1, +1, -1, +1, +1, +1, -1, +1, +1,
/* yneg */ -1, -1, +1, +1, -1, +1, +1, -1, -1, -1, -1, -1,
/* zpos */ +1, -1, +1, -1, -1, +1, -1, +1, +1, +1, +1, +1,
/* zneg */ -1, -1, -1, +1, -1, -1, +1, +1, -1, -1, +1, -1,
};
// vertexarray
glGenVertexArrays(1, &m_vao);
glBindVertexArray(m_vao);
glGenBuffers(1, &m_vbo);
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, (void*)(sizeof(float) * 0));
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
// cubemap
m_texture = SOIL_load_OGL_cubemap
(
"xpos.jpg",
"xneg.jpg",
"ypos.jpg",
"yneg.jpg",
"zpos.jpg",
"zneg.jpg",
SOIL_LOAD_RGB,
SOIL_CREATE_NEW_ID,
SOIL_FLAG_MIPMAPS
);
m_shader = LoadShader("skybox.vs", "skybox.fs");
here is how i render it:
// seamless cubemap
glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
// skybox will be drawn first, so disallow writing into depth buffer
glDepthMask(GL_FALSE);
glUseProgram(m_shader);
glUniformMatrix4fv(glGetUniformLocation(m_shader, "Model"), 1, false, &glm::translate(camera.Position())[0][0]); // render cube around the view position
glUniformMatrix4fv(glGetUniformLocation(m_shader, "View"), 1, false, &camera.View()[0][0]); // use instead glm::lookAt(...)
glUniformMatrix4fv(glGetUniformLocation(m_shader, "Projection"), 1, false, &projection[0][0]);
glUniform1i(glGetUniformLocation(m_shader, "skybox"), 0);
glActiveTexture(GL_TEXTURE0 + 0);
glBindTexture(GL_TEXTURE_CUBE_MAP, m_texture);
glBindVertexArray(m_vao);
glDrawArrays(GL_QUADS, 0, 24);
glBindVertexArray(0);
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
glUseProgram(0);
glDepthMask(GL_TRUE);
i render the cube (of length 1) around the viewers current position (with no rotation)
because i render the skybox first, i have to disable writing into the depth buffer
(it isnt the best solution, but it works for me ^^ it would be better to draw it after you’ve rendered the scene …)
vertexshader
#version 450
layout (location = 0) in vec3 VertexPosition;
uniform mat4 Model;
uniform mat4 View;
uniform mat4 Projection;
out vec3 TexCoords;
void main()
{
mat4 MVP = Projection * View * Model;
gl_Position = MVP * vec4(VertexPosition, 1.0);
TexCoords = VertexPosition;
}
fragmentshader
#version 450
in vec3 TexCoords;
uniform samplerCube skybox;
layout (location = 0) out vec4 FragmentColor0;
void main()
{
FragmentColor0 = texture(skybox, TexCoords);
}