OpenGL cube map faces are rotated

Started by
16 comments, last by _Silence_ 4 years, 8 months ago

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.

Advertisement

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 ?

Spoiler

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();
	

 

This topic is closed to new replies.

Advertisement