Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
291 views
in Technique[技术] by (71.8m points)

textures - Texturing a cube with different images using OpenGL

I have a project from school I'm currently working on and I need to texture a non-rotating cube showing just 3 faces. I've tried doing it on my own but I only get one image on all the 3 faces. I don't know if it's my method that's wrong or the way I'm loading the remaining two images. I would really appreciate help from anyone.

This is how I load my textures

GLuint VAO, VBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);

glBindVertexArray(VAO);

glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

// position attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// texture coord attribute
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);

// this is for texture coords

//Load Image
//int width, height; // width1, height1;
//unsigned char* image = SOIL_load_image("res/images/image1.jpg", &width, &height, 0, SOIL_LOAD_RGBA);

GLuint texture1, texture2, texture3;
// texture 1
// ---------
glGenTextures(1, &texture1);
glBindTexture(GL_TEXTURE_2D, texture1);
// set the texture wrapping parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// set texture filtering parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// load image, create texture and generate mipmaps
int width, height;
stbi_set_flip_vertically_on_load(true); // tell stb_image.h to flip loaded texture's on the y-axis.
unsigned char* image = SOIL_load_image("res/images/image1.jpg", &width, &height, 0, SOIL_LOAD_RGBA);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
glGenerateMipmap(GL_TEXTURE_2D);

SOIL_free_image_data(image);
glBindTexture(GL_TEXTURE_2D, 0);
// texture 2
// ---------
glGenTextures(1, &texture2);
glBindTexture(GL_TEXTURE_2D, texture2);
// set the texture wrapping parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// set texture filtering parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// load image, create texture and generate mipmaps
int width1, height1;
unsigned char* image1 = SOIL_load_image("res/images/image2.jpg", &width1, &height1, 0, SOIL_LOAD_RGBA);

// note that the awesomeface.png has transparency and thus an alpha channel, so make sure to tell OpenGL the data type is of GL_RGBA
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width1, height1, 0, GL_RGBA, GL_UNSIGNED_BYTE, image1);
glGenerateMipmap(GL_TEXTURE_2D);

SOIL_free_image_data(image1);
glBindTexture(GL_TEXTURE_2D, 1);

// texture 3
// ---------
glGenTextures(1, &texture3);
glBindTexture(GL_TEXTURE_2D, texture3);
// set the texture wrapping parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// set texture filtering parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// load image, create texture and generate mipmaps
int width2, height2;
unsigned char* image2 = SOIL_load_image("res/images/image3.jpg", &width2, &height2, 0, SOIL_LOAD_RGBA);

// note that the awesomeface.png has transparency and thus an alpha channel, so make sure to tell OpenGL the data type is of GL_RGBA
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width2, height2, 0, GL_RGBA, GL_UNSIGNED_BYTE, image2);
glGenerateMipmap(GL_TEXTURE_2D);

SOIL_free_image_data(image2);
glBindTexture(GL_TEXTURE_2D, 2);

// tell opengl for each sampler to which texture unit it belongs to (only has to be done once)
// -------------------------------------------------------------------------------------------
shader.Use();
shader.setInt("texture0", 0); // Function to get UniformLocation
shader.setInt("texture1", 0);
shader.setInt("texture2", 2);

And this is the code for when I activate and bind the texture in the rendering Loop

shader.Use();
glActiveTexture(GL_TEXTURE0);
glBindVertexArray(VAO);

glBindTexture(GL_TEXTURE_2D, texture1);

glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(0);

glActiveTexture(GL_TEXTURE1);
glBindVertexArray(VAO);
glBindTexture(GL_TEXTURE_2D, texture2);

glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(0);

glActiveTexture(GL_TEXTURE2);
glBindVertexArray(VAO);
glBindTexture(GL_TEXTURE_2D, texture2);

glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(0);

This is my fragment shader for the program. I really don't know how to use the 3 sampler2D variables I also created here

#version 330 core
in vec2 textCoords;
//in vec2 textCoords2;
//in vec3 ourColor;

out vec4 color1;
out vec4 color2;

uniform sampler2D texture0;
uniform sampler2D texture1;
uniform sampler2D texture2;

void main()
{
   // color = vec4(ourColor, 1.0f);
    color1 = texture(texture0,textCoords) ;   
    //color2 = texture(texture1,textCoords2);

}

This is the result I get for now with this code, but I want different images on the three faces:

img

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You are not binding textures correctly...

  1. you bind txr1 and render whole cube
  2. then you bind txr2 and render whole cube
  3. then you bind txr3 and render whole cube

so depending on the depth test you see either only txr1 or txr3 or some z fighting mess ...

You need either separate faces with the same texture into separate VAO/VBOs (instead of having whole cube in single one)

Or use texture "atlas" (put all textures into single image) and correct texture coordinates... For example something like this:

cubemap

In the new versions there is also possibility of using bindless teturing (never used that however it should be just a matter of passing texture id to the shaders)

[Edit1] texture atlas

Ok lets have some texture atlas for example this one (I just compiled):

texture atlas

As you can see its 7x7 square textures so each texture i = 0,1,2,...,7*7-1 starts at texture coordinate:

x = (i%7)/7.0;
y = (i/7)/7.0;

so you simply add the x,y to your texture coordinate for each vertex of each face where i is the selected texture and normalize the coordinates to size of individual texture so:

x = ((i%7)+x0)/7.0;
y = ((i/7)+y0)/7.0;

where x0,y0 are texture coordinates for normal texture (like you got now) and i is selected texture. If you have different layout of the atlas then just change the 7 for the xcount of texture in each axis in your atlas.

I modified my complete GL+GLSL+VAO/VBO C++ example and added textures for the cube:

//---------------------------------------------------------------------------
//--- GL simple ver: 1.002 --------------------------------------------------
//---------------------------------------------------------------------------
// [complete GL+GLSL+VAO/VBO C++ example](https://stackoverflow.com/a/31913542/2521214)
//---------------------------------------------------------------------------
#define GLEW_STATIC
#include "glew.c"
#include <glgl.h>
#include <glglu.h>
//---------------------------------------------------------------------------
//--- OpenGL GL example -----------------------------------------------------
//---------------------------------------------------------------------------
int     xs,ys;      // screen size
HDC     hdc=NULL;   // device context
HGLRC   hrc=NULL;   // rendering context
int  gl_inicialized=0;
int  gl_init(HWND Handle);
void gl_exit();
void gl_draw();
void gl_resize(int _xs,int _ys);
//---------------------------------------------------------------------------
//--- OpenGL GLSL example ---------------------------------------------------
//---------------------------------------------------------------------------
GLint prog_id=0,    // whole program
      vert_id=0,    // vertex shader
      geom_id=0,    // geometry shader
      frag_id=0;    // fragment shader
char  glsl_log[4096];// compile/link GLSL log
int   glsl_logs=0;
void  glsl_init(char *vert,char *frag);     // create/compile/link GLSL program
void  glsl_exit();
//---------------------------------------------------------------------------
//--- OpenGL VAO example ----------------------------------------------------
//---------------------------------------------------------------------------
#pragma pack(1)
// #define vao_indices
GLuint vbo[5]={-1,-1,-1,-1,-1};
GLuint vao[5]={-1,-1,-1,-1,-1};
const GLfloat vao_pos[]=
    {
//  x    y    z     //ix
    -1.0,+1.0,-1.0, //0
    +1.0,+1.0,-1.0, //1
    +1.0,-1.0,-1.0, //2
    -1.0,-1.0,-1.0, //3

    -1.0,-1.0,+1.0, //4
    +1.0,-1.0,+1.0, //5
    +1.0,+1.0,+1.0, //6
    -1.0,+1.0,+1.0, //7

    #ifndef vao_indices
    -1.0,-1.0,-1.0, //3
    +1.0,-1.0,-1.0, //2
    +1.0,-1.0,+1.0, //5
    -1.0,-1.0,+1.0, //4

    +1.0,-1.0,-1.0, //2
    +1.0,+1.0,-1.0, //1
    +1.0,+1.0,+1.0, //6
    +1.0,-1.0,+1.0, //5

    +1.0,+1.0,-1.0, //1
    -1.0,+1.0,-1.0, //0
    -1.0,+1.0,+1.0, //7
    +1.0,+1.0,+1.0, //6

    -1.0,+1.0,-1.0, //0
    -1.0,-1.0,-1.0, //3
    -1.0,-1.0,+1.0, //4
    -1.0,+1.0,+1.0, //7
    #endif
    };

const GLfloat vao_txr[]=
    {
//  x    y      //ix
    (0.0+0.0)/7.0,(5.0+1.0)/7.0, //0
    (0.0+1.0)/7.0,(5.0+1.0)/7.0, //1
    (0.0+1.0)/7.0,(5.0+0.0)/7.0, //2
    (0.0+0.0)/7.0,(5.0+0.0)/7.0, //3

    (5.0+0.0)/7.0,(5.0+0.0)/7.0, //4
    (5.0+1.0)/7.0,(5.0+0.0)/7.0, //5
    (5.0+1.0)/7.0,(5.0+1.0)/7.0, //6
    (5.0+0.0)/7.0,(5.0+1.0)/7.0, //7

    #ifndef vaices
    (5.0+0.0)/7.0,(4.0+0.0)/7.0, //3
    (5.0+1.0)/7.0,(4.0+0.0)/7.0, //2
    (5.0+1.0)/7.0,(4.0+1.0)/7.0, //5
    (5.0+0.0)/7.0,(4.0+1.0)/7.0, //4

    (3.0+1.0)/7.0,(2.0+0.0)/7.0, //2
    (3.0+1.0)/7.0,(2.0+1.0)/7.0, //1
    (3.0+0.0)/7.0,(2.0+1.0)/7.0, //6
    (3.0+0.0)/7.0,(2.0+0.0)/7.0, //5

    (0.0+1.0)/7.0,(6.0+1.0)/7.0, //1
    (0.0+0.0)/7.0,(6.0+1.0)/7.0, //0
    (0.0+0.0)/7.0,(6.0+0.0)/7.0, //7
    (0.0+1.0)/7.0,(6.0+0.0)/7.0, //6

    (2.0+1.0)/7.0,(6.0+1.0)/7.0, //0
    (2.0+1.0)/7.0,(6.0+0.0)/7.0, //3
    (2.0+0.0)/7.0,(6.0+0.0)/7.0, //4
    (2.0+0.0)/7.0,(6.0+1.0)/7.0, //7
    #endif
    };

const GLfloat vao_col[]=
    {
//  r   g   b    //ix
    0.0,0.0,0.0, //0
    1.0,0.0,0.0, //1
    1.0,1.0,0.0, //2
    0.0,1.0,0.0, //3
    0.0,0.0,1.0, //4
    1.0,0.0,1.0, //5
    1.0,1.0,1.0, //6
    0.0,1.0,1.0, //7

    #ifndef vao_indices
    0.0,0.0,0.0, //0
    1.0,0.0,0.0, //1
    1.0,0.0,1.0, //5
    0.0,0.0,1.0, //4

    1.0,0.0,0.0, //1
    1.0,1.0,0.0, //2
    1.0,1.0,1.0, //6
    1.0,0.0,1.0, //5

    1.0,1.0,0.0, //2
    0.0,1.0,0.0, //3
    0.0,1.0,1.0, //7
    1.0,1.0,1.0, //6

    0.0,1.0,0.0, //3
    0.0,0.0,0.0, //0
    0.0,0.0,1.0, //4
    0.0,1.0,1.0, //7
    #endif
    };

#ifndef vao_indices
const GLfloat vao_nor[]=
    {
//   nx   ny   nz   //ix
     0.0, 0.0,-1.0, //0
     0.0, 0.0,-1.0, //1
     0.0, 0.0,-1.0, //2
     0.0, 0.0,-1.0, //3

     0.0, 0.0,+1.0, //4
     0.0, 0.0,+1.0, //5
     0.0, 0.0,+1.0, //6
     0.0, 0.0,+1.0, //7

     0.0,-1.0, 0.0, //0
     0.0,-1.0, 0.0, //1
     0.0,-1.0, 0.0, //5
     0.0,-1.0, 0.0, //4

    +1.0, 0.0, 0.0, //1
    +1.0, 0.0, 0.0, //2
    +1.0, 0.0, 0.0, //6
    +1.0, 0.0, 0.0, //5

     0.0,+1.0, 0.0, //2
     0.0,+1.0, 0.0, //3
     0.0,+1.0, 0.0, //7
     0.0,+1.0, 0.0, //6

    -1.0, 0.0, 0.0, //3
    -1.0, 0.0, 0.0, //0
    -1.0, 0.0, 0.0, //4
    -1.0, 0.0, 0.0, //7
    };
#endif

#ifdef vao_indices
const GLuint vao_ix[]=
    {
    0,1,2,3,
    4,5,6,7,
    3,2,5,4,
    2,1,6,5,
    1,0,7,6,
    0,3,4,7,
    };
#endif

#pragma pack()
void vao_init();
void vao_exit();
void vao_draw();
//---------------------------------------------------------------------------
//--- bodies: ---------------------------------------------------------------
//---------------------------------------------------------------------------
int gl_init(HWND Handle)
    {
    if (gl_inicialized) return 1;
    hdc = GetDC(Handle);            // get device context
    PIXELFORMATDESCRIPTOR pfd;
    ZeroMemory( &pfd, sizeof( pfd ) );      // set the pixel format for the DC
    pfd.nSize = sizeof( pfd );
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = 24;
    pfd.cDepthBits = 24;
    pfd.iLayerType = PFD_MAIN_PLANE;
    SetPixelFormat(hdc,ChoosePixelFormat(hdc, &pfd),&pfd);
    hrc = wglCreateContext(hdc);            // create current rendering context
    if(hrc == NULL)
            {
            ShowMessage("Could not initialize OpenGL Rendering context !!!");
            gl_inicialized=0;
            return 0;
            }
    if(wglMakeCurrent(hdc, hrc) == false)
            {
            ShowMessage("Could not make current OpenGL Rendering context !!!");
            wglDeleteContext(hrc);          // destroy rendering context
            gl_inicialized=0;
            return 0;
            }
    gl_resize(1,1);
    glEnable(GL_DEPTH_TEST);                // Zbuf
    glDisable(GL_CULL_FACE);                // vynechavaj odvratene steny
    glDisable(GL_TEXTURE_2D);               // pouzivaj textury, farbu pouzivaj z textury
    glDisable(GL_BLEND);                    // priehladnost
    glShadeModel(GL_SMOOTH);                // gourard shading
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);   // background color
    gl_inicialized=1;
    glewInit();
    return 1;
    }
//---------------------------------------------------------------------------
void gl_exit()
    {
    if (!gl_inicialized) return;
    wglMakeCurrent(NULL, NULL);     // release current rendering context
    wglDeleteContext(hrc);          // destroy rendering context
    gl_inicialized=0;
    }
//---------------------------------------------------------------------------
void gl_resize(int _xs,int _ys)
    {
    xs=_xs;
    ys=_ys;
    if (xs<=0) xs = 1;                  // Prevent a divide by zero
    if (ys<=0) ys = 1;
    if (!gl_inicialized) return;
    glViewport(0,0,xs,ys);              // Set Viewport to window dimensions
    glMatrixMode(GL_PROJECTION);        // operacie s projekcnou maticou
    glLoadIdentity();                   // jednotkova matica projekcie
    gluPerspective(30,float(xs)/float(ys),0.1,100.0); // matica=perspektiva,120 stupnov premieta z viewsize do 0.1
    glMatrixMode(GL_TEXTURE);           // operacie s texturovou maticou
    glLoadIdentity();                   // jednotkova matica textury
    glMatrixMode(GL_MODELVIEW);         // operacie s modelovou maticou
    glLoadIdentity();                   // jednotkova matica modelu (objektu)
    }
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
void glsl_init(char *vert,char *geom,char *frag)
    {
    const int _size=1024;
    GLint status,siz=0,i;
    const char * VS = vert;
    const char * GS = geom;
    const char * FS = frag;
    glsl_logs=0;
    if (prog_id<=0) prog_id=glCreateProgram();

    if (vert_id<=0) vert_id=glCreateShader(GL_VERTEX_SHADER); else glDetachShader(prog_id,vert_id);
    if (vert)
        {
        glShaderSource(vert_id, 1, &VS,NULL);
        glCompileShader(vert_id);
        glAttachShader(prog_id,vert_id);
        glGetShaderiv(vert_id,GL_COMPILE_STATUS,&status);
        const char t[]="[Vertex]
"; for (i=0;t[i];i++) { glsl_log[glsl_logs]=t[i]; glsl_logs++; }
        glGetShaderInfoLog(vert_id,_size,&siz,glsl_log+glsl_logs);
        glsl_logs+=siz;
        }
    if (geom_id<=0) geom_id=glCreateShader(GL_GEOMETRY_SHADER); else glDetachShader(prog_id,geom_id);
    if (geom)
        {
        glShaderSource(geom_id, 1, &GS,NULL);
        glCompileShader(geom_id);
        glAttachShader(prog_id,geom_id);
        glGetShaderiv(geom_id,GL_COMPILE_STATUS,&status);
        const char t[]="[Geometry]
"; for (i=0;t[i];i++) { glsl_log[glsl_logs]=t[i]; glsl_logs++; }
        glGetShaderInfoLog(geom_id,_size,&siz,glsl_log+glsl_logs);
        glsl_logs+=siz;
        }
    if (frag_id<=0) frag_id=glCreateShader(GL_FRAGMENT_SHADER); else glDetachShader(prog_id,frag_id);
    if

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...