Jump to content
  • Advertisement
Sign in to follow this  
taby

OpenGL cube map faces are rotated

Recommended Posts

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.

Share this post


Link to post
Share on other sites
Advertisement
Posted (edited)

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.

 

Edited by Green_Baron

Share this post


Link to post
Share on other sites
Posted (edited)

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.

Edited by taby

Share this post


Link to post
Share on other sites
Posted (edited)

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 ?

 

Edited by Green_Baron
code formatting ...

Share this post


Link to post
Share on other sites
Posted (edited)

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.

Edited by taby

Share this post


Link to post
Share on other sites
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 ?

Share this post


Link to post
Share on other sites
Posted (edited)

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.

Edited by taby

Share this post


Link to post
Share on other sites
Posted (edited)

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

Edited by Green_Baron

Share this post


Link to post
Share on other sites
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 ?

Share this post


Link to post
Share on other sites
Posted (edited)

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

 

Edited by taby

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!