This is to build the skybox texture.
What happens is that the skybox textures are upside down and switched. I'm using code from tutorials and searched everywhere what might cause this and maybe it is a silly thing. Ok I can just flip the actual textures and pass them in a different order, but that shouldn't be happening.
I load with stb header img loader. Here's all the pertinent code:
LOADER
GLuint load_texture_cube( const std::string& front, const std::string& back, const std::string& up, const std::string& down, const std::string& left, const std::string& right) { GLuint tex_cube; glGenTextures( 1, &tex_cube ); glActiveTexture( GL_TEXTURE0 ); auto load_cube_side = [=]( GLuint texture, GLenum side_target, const std::string& file_name ) { int x, y, n; /// RGBA channels int force_channels = 4; unsigned char* image_data = stbi_load( file_name.c_str(), &x, &y, &n, force_channels ); if ( !image_data ) { fprintf( stderr, "ERROR: could not load %s\n", file_name.c_str() ); } /// no need to power of 2 check https://www.khronos.org/opengl/wiki/Cubemap_Texture#Creation glBindTexture( GL_TEXTURE_CUBE_MAP, texture ); glTexImage2D( side_target, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data ); free( image_data ); }; load_cube_side( tex_cube, GL_TEXTURE_CUBE_MAP_POSITIVE_X, right ); load_cube_side( tex_cube, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, left ); load_cube_side( tex_cube, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, up ); load_cube_side( tex_cube, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, down ); load_cube_side( tex_cube, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, back ); load_cube_side( tex_cube, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, front ); glTexParameteri( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); glTexParameteri( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); glTexParameteri( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE ); glTexParameteri( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); return tex_cube; }
Loading
auto tex_skybox = load_texture_cube("textures/skybox/midday/front.png","textures/skybox/midday/back.png", "textures/skybox/midday/up.png","textures/skybox/midday/down.png", "textures/skybox/midday/left.png","textures/skybox/midday/right.png" );
SHADER
#version 410 layout (location = 0) in vec3 vPoints; uniform mat4 proj_mat, view_mat; out vec3 texcoords; void main () { texcoords = vPoints; // transforming view matrix into mat3 removes the translation part (last row), then putting it back // zeroes it // this is to make the skybox update with camera rotation but not with camera translation, because that's // unecessary #if 1 vec4 pos = proj_mat * mat4(mat3(view_mat)) * vec4 (vPoints, 1.0); #else vec4 pos = proj_mat * view_mat * vec4 (vPoints, 1.0); #endif gl_Position = pos.xyww; } ///////////////////////////// #version 410 in vec3 texcoords; uniform samplerCube cube_texture; out vec4 frag_color; void main () { frag_color = texture(cube_texture, texcoords); }
VERTICES
shapes::Skybox::Skybox() { points = { -1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, ////////// -1, -1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, ////////// 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, ////////// -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, ////////// -1, 1, -1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, ////////// -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1 }; }
VAO Generating
void Model_lean::generate(const V_Float& points) { glGenVertexArrays(1, &m_VAO); glBindVertexArray(m_VAO); glGenBuffers(1, &m_VBO); glBindBuffer(GL_ARRAY_BUFFER, m_VBO); glBufferData( GL_ARRAY_BUFFER, points.size() * sizeof( points[0] ), points.data(), GL_STATIC_DRAW ); glEnableVertexAttribArray( 0 ); glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 0, 0 ); }
REndering
Call in main loop, where proj_mat is the regular perspective matrix, and vmat is the camera view matrix that will be stripped out of translation in the shader (it doesn't matter if i try to do different things here, like regenerating only the rotation matrices, skybox sides still upside down and some switched)
Use_programme(skybox_prog); Load_matrix4(skybox_prog, "proj_mat", proj_mat.m); Load_matrix4(skybox_prog, "view_mat", vmat.m); draw_skybox(&skybox_model,tex_skybox);
void draw_skybox(Model_lean* model, GLuint texture) { glDepthFunc(GL_LEQUAL); glActiveTexture( GL_TEXTURE0 ); glBindTexture(GL_TEXTURE_CUBE_MAP, texture); model->bind_VAO(); glDrawArrays( GL_TRIANGLES, 0, 36 ); glDepthFunc(GL_LESS); }