I'm using a cube map in GLSL, and all of the cube map faces are rotated by 90 degrees. Is this a common problem? I couldn't find anything through the search feature.
OpenGL cube map faces are rotated
Assuming that the textures are in order and come in the correct pattern for a GL_TEXTURE_CUBE_MAP, it can only be the texture coordinates or the order of the vertices, imo.
Spoiler: vertices in order for gldrawarrays ?
std::vector<omath::vec3> skyboxVertices{
// positions
omath::vec3{ -1.0f, 1.0f, -1.0f },
omath::vec3{ -1.0f, -1.0f, -1.0f },
omath::vec3{ 1.0f, -1.0f, -1.0f },
omath::vec3{ 1.0f, -1.0f, -1.0f },
omath::vec3{ 1.0f, 1.0f, -1.0f },
omath::vec3{ -1.0f, 1.0f, -1.0f },
omath::vec3{ -1.0f, -1.0f, 1.0f },
omath::vec3{ -1.0f, -1.0f, -1.0f },
omath::vec3{ -1.0f, 1.0f, -1.0f },
omath::vec3{ -1.0f, 1.0f, -1.0f },
omath::vec3{ -1.0f, 1.0f, 1.0f },
omath::vec3{ -1.0f, -1.0f, 1.0f },
omath::vec3{ 1.0f, -1.0f, -1.0f },
omath::vec3{ 1.0f, -1.0f, 1.0f },
omath::vec3{ 1.0f, 1.0f, 1.0f },
omath::vec3{ 1.0f, 1.0f, 1.0f },
omath::vec3{ 1.0f, 1.0f, -1.0f },
omath::vec3{ 1.0f, -1.0f, -1.0f },
omath::vec3{ -1.0f, -1.0f, 1.0f },
omath::vec3{ -1.0f, 1.0f, 1.0f },
omath::vec3{ 1.0f, 1.0f, 1.0f },
omath::vec3{ 1.0f, 1.0f, 1.0f },
omath::vec3{ 1.0f, -1.0f, 1.0f },
omath::vec3{ -1.0f, -1.0f, 1.0f },
omath::vec3{ -1.0f, 1.0f, -1.0f },
omath::vec3{ 1.0f, 1.0f, -1.0f },
omath::vec3{ 1.0f, 1.0f, 1.0f },
omath::vec3{ 1.0f, 1.0f, 1.0f },
omath::vec3{ -1.0f, 1.0f, 1.0f },
omath::vec3{ -1.0f, 1.0f, -1.0f },
omath::vec3{ -1.0f, -1.0f, -1.0f },
omath::vec3{ -1.0f, -1.0f, 1.0f },
omath::vec3{ 1.0f, -1.0f, -1.0f },
omath::vec3{ 1.0f, -1.0f, -1.0f },
omath::vec3{ -1.0f, -1.0f, 1.0f },
omath::vec3{ 1.0f, -1.0f, 1.0f }
};
... so you can simply pass the texture coordinates through the vertex shader, use a samplerCube and a simple texture lookup.
Thanks for the reply. There aren't vertices and texture coordinates, just 6 glTexImage2D() calls like GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_X, etc.
That doesn't sound right, but i am unsure as you're probably much more experienced than i am. I only know the way of drawing the 6 textures of the cube map onto 6 quads. This works at least for a skybox.
Load the cube's faces (i use stbi as loader). And i use a 3D texture as a cube map is nothing but a 3D texture with 6 layers.
glCreateTextures( GL_TEXTURE_CUBE_MAP, 1, &m_textureName );
// with known image dimensions do:
glTextureStorage2D( m_textureName, 1, internalFormat, width, height );
// One mip level only because the skybox is fix.
for( unsigned int face{ 0 }; face < 6; ++face ) {
data = stbi_load( files[face].c_str(), &width, &height, &numChannels, 0 );
if( NULL != data ) {
glTextureSubImage3D( m_textureName, 0, 0, 0,// target, level , xOffset, yOffset
face, width, height, 1, format, // cube map face, width, height, 1 face a time, format
GL_UNSIGNED_BYTE, data ); // datatype, data pointer
stbi_image_free( data );
data = NULL;
} else {
std::string s{ "Cubemap texture '" + files[face] + "' failed to load." };
Logbook::getInstance().logMsg( Logbook::RENDERER, Logbook::WARNING, s );
}
}
// Sampler
glTextureParameteri( m_textureName, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTextureParameteri( m_textureName, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
glTextureParameteri( m_textureName, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE );
The vertex buffer to bind is the above. Then drawing goes this way:
// Example for a skybox, draw last
glEnable( GL_DEPTH_TEST );
glDepthFunc( GL_LEQUAL );
glEnable( GL_TEXTURE_CUBE_MAP_SEAMLESS );
// Trivial vertex- and fragment shader
m_program->use();
// The vertex array as above
m_skyboxArray->bind();
// The cube map texture
m_texture->bind();
// Skybox follows camera
setUniform( m_program->getProgram(), "projectionView",
m_scene->getCamera()->getUntranslatedViewProjMatrix() );
glDrawArrays( GL_TRIANGLES, 0, 36 );
glDepthFunc( GL_LESS );
Plus a pair of trivial shaders.
Question: how do you draw the textures without mapping them to vertices ? Probably something i haven't explored yet ?
Edit: should you wonder, the order of the faces is in the arrays of the filenames ...
Or are you rendering to the cube map and i completely misunderstood ?
Well I do have one quad that I draw, which is eventually fed to the vertex and fragment shader program. I don't use any textures other than the cube map, and so I don't need to provide texture coordinates. And to be fair, I should mention that this is OpenGL 2.x. Everything works, except that the cube map faces are rotated. Not sure why. Thanks for your input.
31 minutes ago, taby said:I don't use any textures other than the cube map, and so I don't need to provide texture coordinates.
Weird. Can you let people know a bit of your code in order to have a better understanding of what you are doing ? Give detail also. You don't need to provide texture coordinates, because ? From your quote, this doesn't sound like a cause-effect statement. So how do you texture your model ? Also, is your cube-mapped model a 2D quad ?
Yes, I suppose that it's weird that I don't have to supply texture coordinates for the quad.
Unfortunately, I can't provide the code, because I'm not the code owner, just a guy trying to add functionality to the code.
The fragment shader is a ray tracer, and the normals of the intersected object are used to get a pixel from the cube map, to make an environment map.
In any case, the use of the cube map does not require uv coordinates -- it takes a 3-vector.
Yep, either draw arrays with vertices, or elements with vertices + indices.
Wildly guessing: Is there a view matrix passed in somewhere, with x or z up instead of y ?
Stupid question, i know ? but without code ...
18 minutes ago, taby said:In any case, the use of the cube map does not require uv coordinates -- it takes a 3-vector.
These are called uvw (or stu). But they are texture coordinates. Cube-mapping just requires 3D texture coordinates whereas "normal" image texture mapping only needs 2D texture coordinates. But this is logical.
20 minutes ago, taby said:the normals of the intersected object are used to get a pixel from the cube map, to make an environment map.
OK. Sounds good. Should work.
22 minutes ago, taby said:Unfortunately, I can't provide the code
So how do you expect reasonable help on this one ?
I was hoping that it would be something common. In any case, I did get permission to post the code, so it's listed below.
Instead of uvw, or stu, or rgb, it is xyz when using a cube map.
Here is the initialization code:
int[] cube_map_tex = new int[1];
gr.glActiveTexture(GR.GL_TEXTURE0);
gr.glGenTextures(1, cube_map_tex);
gr.glBindTexture(GR.GL_TEXTURE_2D, cube_map_tex[0]);
int width, height;
byte [] px_data = read_data_from_file("px.png", out width, out height);
gr.glTexImage2D(
GR.GL_TEXTURE_CUBE_MAP_POSITIVE_X,
0, GR.GL_RGBA, width, height, 0, GR.GL_RGBA, GR.GL_UNSIGNED_BYTE, px_data);
byte [] nx_data = read_data_from_file("nx.png", out width, out height);
gr.glTexImage2D(
GR.GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
0, GR.GL_RGBA, width, height, 0, GR.GL_RGBA, GR.GL_UNSIGNED_BYTE, nx_data);
byte[] py_data = read_data_from_file("py.png", out width, out height);
gr.glTexImage2D(
GR.GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
0, GR.GL_RGBA, width, height, 0, GR.GL_RGBA, GR.GL_UNSIGNED_BYTE, py_data);
byte[] ny_data = read_data_from_file("ny.png", out width, out height);
gr.glTexImage2D(
GR.GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
0, GR.GL_RGBA, width, height, 0, GR.GL_RGBA, GR.GL_UNSIGNED_BYTE, ny_data);
byte[] pz_data = read_data_from_file("pz.png", out width, out height);
gr.glTexImage2D(
GR.GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
0, GR.GL_RGBA, width, height, 0, GR.GL_RGBA, GR.GL_UNSIGNED_BYTE, pz_data);
byte[] nz_data = read_data_from_file("nz.png", out width, out height);
gr.glTexImage2D(
GR.GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
0, GR.GL_RGBA, width, height, 0, GR.GL_RGBA, GR.GL_UNSIGNED_BYTE, nz_data);
gr.glTexParameteri(GR.GL_TEXTURE_CUBE_MAP, GR.GL_TEXTURE_MAG_FILTER, GR.GL_LINEAR);
gr.glTexParameteri(GR.GL_TEXTURE_CUBE_MAP, GR.GL_TEXTURE_MIN_FILTER, GR.GL_LINEAR);
gr.glTexParameteri(GR.GL_TEXTURE_CUBE_MAP, GR.GL_TEXTURE_WRAP_S, GR.GL_CLAMP_TO_EDGE);
gr.glTexParameteri(GR.GL_TEXTURE_CUBE_MAP, GR.GL_TEXTURE_WRAP_T, GR.GL_CLAMP_TO_EDGE);
gr.glTexParameteri(GR.GL_TEXTURE_CUBE_MAP, GR.GL_TEXTURE_WRAP_R, GR.GL_CLAMP_TO_EDGE);
gr.glUniform1i(gr.glGetUniformLocation(mShaderProgramHandle, "cube_map"), 0); // use GL_TEXTURE0
Here is the draw code:
gr.glBegin(GR.GL_QUADS);
// v2
gr.glColor3f(-1.0f, -1.0f, 0.0f);
gr.glVertex2f(-1.0f, -1.0f);
// v3
gr.glColor3f(1.0f, -1.0f, 0.0f);
gr.glVertex2f(1.0f, -1.0f);
// v0
gr.glColor3f(1.0f, 1.0f, 0.0f);
gr.glVertex2f(1.0f, 1.0f);
// v1
gr.glColor3f(-1.0f, 1.0f, 0.0f);
gr.glVertex2f(-1.0f, 1.0f);
gr.glEnd();