Cube mapping in OpenGL
opengl, texture-mapping
Solution
Texture cube maps are mapped using a 3D texture coordinate: it is used to determine which face cube is actually selected, and then derive the actual 2D texture coordinate used for accessing to the cube map face textel.
Your texture coordinates are 2D (wrongly), and indeed you texture coordinate `vertexUV` (and consequently `vCoords`) Z coordinate is always 0, mapping non-definitively the texture (missing components are copied by the default attribute value, that is vec4(0,0,0,1)).
To get the wanted result, modify the vertex shader in order to use a meaninful coordinate:
vCoords = normalize(vVertexPos);
Problem
I try to map cube with 6 bitmaps to achieve skybox effect. My problem is fact that one texture is mapping to every face of cube. I've checked in gDEBugger, in cube texture memory I have only one image (as I try to load six images). Code preparing texture: ``` bool Texture::LoadCubicTexture(vector<string> filenameTable) { glGenTextures(1,&texID); glBindTexture(GL_TEXTURE_CUBE_MAP,texID); glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_MIN_FILTER,GL_LINEAR); 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); int i = 0; vector<string>::iterator vsit; // There is always six filenames for(vsit=filenameTable.begin();vsit!=filenameTable.end();++vsit) { string filename = *vsit; BMPData* bmpData = LoadTextureBMPData_custom(filename); glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+i,0,GL_RGB,bmpData->width,bmpData->height,0,GL_BGR,GL_UNSIGNED_BYTE,&(bmpData->data[0])); i++; delete daneObrazu; } glGenerateMipmap(GL_TEXTURE_CUBE_MAP); return true; } ``` VS: ``` #version 330 core in vec3 vVertexPos; in vec3 vertexUV; out vec3 vCoords; uniform mat4 MVP; void main() { vCoords = normalize(vertexUV); gl_Position = MVP * vec4(vVertexPos,1.0); } ``` FS: ``` #version 330 core in vec3 vCoords; uniform samplerCube cube; out vec4 vFragColor; void main() { vFragColor = texture(cube, vCoords); } ``` OBJ File: ``` # Blender v2.62 (sub 0) OBJ File: 'skybox.blend' # www.blender.org mtllib skybox.mtl o Cube v 10.487665 -10.487666 -10.487665 v 10.487665 -10.487666 10.487665 v -10.487667 -10.487666 10.487664 v -10.487662 -10.487666 -10.487670 v 10.487671 10.487666 -10.487660 v 10.487659 10.487666 10.487673 v -10.487670 10.487666 10.487662 v -10.487665 10.487666 -10.487666 vt 0.990480 0.014286 vt 0.993478 0.991259 vt 0.016505 0.994256 vt 0.013507 0.017283 vt 0.988479 0.008111 vt 0.985457 0.993412 vt 0.000157 0.990390 vt 0.003179 0.005089 vt 0.002693 1.001082 vt -0.000347 0.009939 vt 0.990796 0.006898 vt 0.993837 0.998041 vt 0.004581 0.999210 vt 0.001535 0.006444 vt 0.994302 0.003398 vt 0.997347 0.996165 vt 0.004172 -0.000587 vt 0.996320 -0.003630 vt 0.999364 0.988517 vt 0.007216 0.991561 vt 0.000632 0.000140 vt 0.983846 -0.002921 vt 0.986862 0.995017 vt 0.003648 0.998078 vn 0.000000 -1.000000 0.000000 vn 0.000000 1.000000 0.000000 vn 1.000000 0.000000 0.000000 vn -0.000000 -0.000000 1.000000 vn -1.000000 -0.000000 -0.000000 vn 0.000000 0.000000 -1.000000 usemtl Skybox s off f 1/1/1 2/2/1 3/3/1 f 1/1/1 3/3/1 4/4/1 f 5/5/2 8/6/2 7/7/2 f 5/5/2 7/7/2 6/8/2 f 1/9/3 5/10/3 6/11/3 f 1/9/3 6/11/3 2/12/3 f 2/13/4 6/14/4 7/15/4 f 2/13/4 7/15/4 3/16/4 f 3/17/5 7/18/5 8/19/5 f 3/17/5 8/19/5 4/20/5 f 5/21/6 1/22/6 4/23/6 f 5/21/6 4/23/6 8/24/6 ``` My questions: - Are techniques I use in this code looks ok? - How textures are mapping for cube (in GL_TEXTURE_CUBE_MAP texture), when there is only 2 UV? (I mean in general.) - Can I use automatic generation of UV's in this situation (do I have to do many changes to shader)? - Can anybody suggest me where can I search for a problem? (with some probability; buffers, shaders, meshes;only suggestion)? [Edit]: I tried to hardcode vertices and uvs in separate source file and I have the same problem- one texture for all faces of cube. Hardcoded data seems to be correct: ``` #include "TestCube.h" vector<vec3> GetTestCubeVertices() { vector<vec3> vrtx; const float xd = 1.0f; const float yd = 1.0f; const float zd = 1.0f; const float testCubeVertices[] = { -xd, -yd, zd, xd, -yd, zd, -xd, yd, zd, // ABE xd, -yd, zd, -xd, yd, zd, xd, yd, zd, // BEF xd, -yd, zd, xd, -yd, -zd, xd, yd, zd, // BCF xd, -yd, -zd, xd, yd, zd, xd, yd, -zd, // CFG xd, -yd, -zd, -xd, -yd, -zd, xd, yd, -zd, // CDG -xd, -yd, -zd, xd, yd, -zd, -xd, yd, -zd, // DGH -xd, -yd, -zd, -xd, -yd, zd, -xd, yd, -zd, // DAH -xd, -yd, zd, -xd, yd, -zd, -xd, yd, zd, // AHE -xd, yd, zd, xd, yd, zd, -xd, yd, -zd, // EFH xd, yd, zd, -xd, yd, -zd, xd, yd, -zd, // FHG xd, -yd, zd, -xd, -yd, zd, xd, -yd, -zd, // BAC -xd, -yd, zd, xd, -yd, -zd, -xd, -yd, -zd, // ACD }; for(int i=0;i<108;i=i+3) vrtx.push_back(vec3(testCubeVertices[i],testCubeVertices[i+1],testCubeVertices[i+2])); return vrtx; } vector<vec2> GetTestCubeUVs() { vector<vec2> uv; const float testCubeUV[] = { 0,0, 1,0, 0,1, // ABE 1,0, 0,1, 1,1, // BEF 0,0, 1,0, 0,1, // BCF 1,0, 0,1, 1,1, // CFG 0,0, 1,0, 0,1, // CDG 1,0, 0,1, 1,1, // DGH 0,0, 1,0, 0,1, // DAH 1,0, 0,1, 1,1, // AHE 0,0, 1,0, 0,1, // EFH 1,0, 0,1, 1,1, // FHG 0,0, 1,0, 0,1, // BAC 1,0, 0,1, 1,1, // ACD }; for(int i=0;i<72;i=i+2) uv.push_back(vec2(testCubeUV[i],testCubeUV[i+1])); return uv; } ``` Still two suplementary questions, I have OpenGL call: ``` glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_WRAP_R,GL_CLAMP_TO_EDGE); ``` - I understand that OpenGL handles r coordinate automatically, because have the information in constant GL_TEXTURE_CUBE_MAP_POSITIVE_X for glTexImage2D()? - Is there necessary any modification of r coordinate in Vertex Shader? There's result screen below (disabled writing to depth buffer and didn't set scalling, but it's not my problem now): I've noticed that duplicated texture is fifth loaded texture (GL_TEXTURE_CUBE_MAP_POSITIVE_Z). [LAST EDIT]: There was problem with UV coordinates in Skybox VS (r coordinate has one value), Skybox VS should be, as below: ``` void main() { vCoords = normalize(vVertexPos); gl_Position = MVP * vec4(vVertexPos,1.0); } ``` There's a few issues with Skybox technique, but they wasn't topic of this thread. Solved.