Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cube mapping in OpenGL

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):

enter image description here

I've noticed that duplicated texture is fifth loaded texture (GL_TEXTURE_CUBE_MAP_POSITIVE_Z).

enter image description here

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

like image 731
CppMonster Avatar asked Jul 27 '13 07:07

CppMonster


People also ask

How does cube mapping work?

In computer graphics, cube mapping is a method of environment mapping that uses the six faces of a cube as the map shape. The environment is projected onto the sides of a cube and stored as six square textures, or unfolded into six regions of a single texture.

How do you make a cube map?

Select Assets > Create > Legacy > Cubemap from the menu, and drag six textures into empty slots in the inspector. Textures for the corresponding cubemap face. Width and Height of each Cubemap face in pixels. The textures will be scaled automatically to fit this size.

How many coordinates are needed when getting a sample from a cube texture?

When specifying your texture coordinates, you will then use sets of 3 coordinates instead of sets of 2. In a simple cube, you point to the 8 corners using normalized vectors.


1 Answers

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);
like image 99
Luca Avatar answered Sep 28 '22 08:09

Luca