2016-10-11 3 views
0

Я пытаюсь использовать единую текстуру куба для skybox и отражений, но в итоге я получаю черную текстуру для обоих. Я использую временный массив пикселей для cubemap, чтобы убедиться, что изображение не является проблемой. Поэтому просто игнорируйте материал SDL в этой функции; Я прокомментировал некоторые из них. Кроме того, текстурные функции и шейдеры используются как для текстур 2d, так и для кубате, поэтому я также прокомментировал это.Opengl black/blank cubemap texture

текстуры загрузки: zTexture* вары относятся к классу вары

bool loadCubeMap(std::vector<const char*> path) 
{ 
    //Texture loading success 
    bool textureLoaded = false; 

    glEnable(GL_TEXTURE_CUBE_MAP); //probably not needed 

    for(int j=0; j<path.size(); j++) 
    { 
     //SDL_Surface* cubFacSurf = IMG_Load(path[j]); 
     if(cubFacSurf != NULL) 
     { 
      //SDL_LockSurface(cubFacSurf);    
      zTextureW = cubFacSurf->w; 
      zTextureH = cubFacSurf->h; 
      textureLoaded = loadFromPixels((GLuint*)cubFacSurf->pixels, zTextureW, zTextureH, GL_TEXTURE_CUBE_MAP, GL_RGB, GL_TEXTURE_CUBE_MAP_POSITIVE_X+j); 
      //SDL_UnlockSurface(cubFacSurf); 
      //SDL_FreeSurface(cubFacSurf); 
     } 
     if(textureLoaded == false) 
     { 
      SDL_Log("Unable to load %s\n", path[j]); 
     } 
    } 
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 

    glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
    glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 

    return textureLoaded; 
} 

Основной пиксель погрузчик

bool loadFromPixels(void* pixels, GLuint width, GLuint height, const GLenum tType = GL_TEXTURE_2D, const GLenum glPix = GL_RGB, const GLenum tFace = GL_TEXTURE_2D) 
{ 
    glGenTextures(1, &zTextureID); 
    glBindTexture(tType, zTextureID); 

    GLfloat checkerboard[] = {1.f,1.f,1.f, 0.f,0.f,0.f, 0.f,0.f,0.f, 1.f,0.f,1.f}; 
    if(tType == GL_TEXTURE_CUBE_MAP) 
     glTexImage2D(tFace, 0, glPix, 2, 2, 0, glPix, GL_FLOAT, &checkerboard); 
    //else 
    //glTexImage2D(tFace, 0, glPix, width, height, 0, glPix, GL_UNSIGNED_BYTE, pixels); 

    //Check for error 
    GLenum error = glGetError(); 
    if(error != GL_NO_ERROR) 
    { 
     SDL_Log("Error loading texture from %p pixels! %d\n", pixels, error); 
     return false; 
    } 
    return true; 
} 

Texture Binding:

void apply(const GLenum typ = GL_TEXTURE_2D) 
{ 
    glEnable(typ); //Probably not necessary doesnt change anything if left out 
    if(typ == GL_TEXTURE_2D) 
    { 
     glDisable(GL_TEXTURE_CUBE_MAP); //same here 
     glUniform1i(mainTxtrID, 0); //mainTxtrID = Textr in frag 
     glActiveTexture(GL_TEXTURE0); 
    } 
    else 
    { 
     glDisable(GL_TEXTURE_2D); //and here 
     glUniform1i(cubeID, 1); //cubeID = TextCub in frag 
     glActiveTexture(GL_TEXTURE1); 
    } 
    glBindTexture(typ, zTextureID); 
} 

"Uber" Shaders:
вершинных:

#version 100 
precision mediump float; 

uniform mat4 ModelMat; 
uniform mat4 ViewMat; 
uniform mat4 ProjMat; 
uniform mat4 OrthMat; 

uniform bool world; 
attribute vec4 vPosition; 
attribute vec2 UVCoordAt; 
attribute vec3 nPosition; 
varying vec2 UVCoord; 
varying vec3 vPos; 
varying vec3 vNor; 
varying vec3 vRefl; 

void main() 
{ 
    UVCoord = UVCoordAt; 
    vPos = vec3(vPosition); //skybox coords 
    vNor = normalize(vec3(ModelMat * vec4(nPosition,0.0))); 
    vRefl = reflect(normalize(vPos - vec3(ViewMat[3][0], ViewMat[3][1], ViewMat[3][2])), vNor); //reflection direction vector 
    if(world) 
      gl_Position = ProjMat * ViewMat * ModelMat * vPosition; 
    else gl_Position = OrthMat * ModelMat * vPosition; 
} 

фрагмент:

#version 100 
precision mediump float; 

uniform samplerCube TextCub; 
uniform sampler2D Textr; 
uniform vec3 LiPos; 
uniform vec4 fragCol; 

uniform bool lighting; 
uniform bool dimen; 
uniform bool isRefl; 
varying vec2 UVCoord; 
varying vec3 vPos; 
varying vec3 vNor; 
varying vec3 vRefl; 

void main() 
{ 
    vec4 textVect = texture2D(Textr, UVCoord); //default texturing 
    if(dimen){ textVect = textureCube(TextCub, vPos); } //skybox 
    else if(isRefl){ textVect = mix(textVect, textureCube(TextCub, vRefl), 0.7); } //reflections mixed with default textr 
    if(lighting){ 
     float diffuse = clamp(dot(vNor, LiPos), 0.0, 1.0); 
     gl_FragColor = clamp(diffuse*2.0, 0.6, 1.1) * fragCol * textVect; 
    } 
    else{ gl_FragColor = fragCol * textVect; } 
} 

Я использую GL_DEPTH_TEST, я сомневаюсь, что это влияет на что-нибудь. Я предполагаю, что проблема заключается в функции apply() или что-то еще, что я забыл. Есть расширения для cubemaps, но я предполагаю, что по умолчанию opengles работают с двумя кубами.

ответ

1

Вы создаете новую текстуру для каждой поверхности куба. В функции loadFromPixels(), которую вы называете для каждого лица:

glGenTextures(1, &zTextureID); 
glBindTexture(tType, zTextureID); 
... 
glTexImage2D(...); 

Это означает, что вы будете в конечном итоге с 6 текстур, каждая из которых только данные для одного лица, указанного, что делает их неполными.

Вам необходимо создать один текстуру куба, а затем указать данные для всех 6 сторон этой кубической карты.