【问题标题】:Texturing a cube with different images using OpenGL使用 OpenGL 对具有不同图像的立方体进行纹理处理
【发布时间】:2021-03-24 08:12:38
【问题描述】:

我目前正在从事一个学校项目,我需要对一个仅显示 3 个面的非旋转立方体进行纹理处理。我试过自己做,但我只能在所有 3 张脸上得到一张图像。我不知道是我的方法错误还是我加载剩余两张图像的方式。我非常感谢任何人的帮助。

这就是我加载纹理的方式

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

这是我在渲染循环中激活和绑定纹理时的代码

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

这是我的程序片段着色器。我真的不知道如何使用我在这里创建的 3 个 sampler2D 变量

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

}

这是我现在使用这段代码得到的结果,但我想要三个面上的不同图像:

【问题讨论】:

    标签: opengl textures visual-studio-2019 glfw glew


    【解决方案1】:

    您没有正确绑定纹理...

    1. 您绑定 txr1 并渲染整个立方体
    2. 然后绑定 txr2 并渲染整个立方体
    3. 然后绑定 txr3 并渲染整个立方体

    所以根据深度测试,您看到的只有 txr1 或 txr3 或一些 z 战斗混乱......

    您需要将具有相同纹理的单独面分成单独的 VAO/VBO(而不是将整个立方体放在一个中)

    或使用 texture "atlas"(将所有纹理放入单个图像中)并校正纹理坐标...例如这样的:

    在新版本中也有可能使用无绑定 teturing(从未使用过,但它应该只是将纹理 id 传递给着色器的问题)

    [Edit1] 纹理图集

    好的,让我们有一些纹理图集,例如这个(我刚刚编译):

    您可以看到它的 7x7 方形纹理,因此每个纹理 i = 0,1,2,...,7*7-1 都从纹理坐标开始:

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

    所以您只需将x,y 添加到每个面的每个顶点的纹理坐标中,其中i 是所选纹理,并将坐标标准化为单个纹理的大小,因此:

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

    x0,y0 是普通纹理的纹理坐标(就像你现在得到的那样),i 是选定的纹理。如果您有不同的图集布局,则只需更改 7 以获取图集中每个轴的纹理 xcount。

    我修改了我的complete GL+GLSL+VAO/VBO C++ example 并为立方体添加了纹理:

    //---------------------------------------------------------------------------
    //--- 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 <gl\gl.h>
    #include <gl\glu.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]\r\n"; 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]\r\n"; 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 (frag)
            {
            glShaderSource(frag_id, 1, &FS,NULL);
            glCompileShader(frag_id);
            glAttachShader(prog_id,frag_id);
            glGetShaderiv(frag_id,GL_COMPILE_STATUS,&status);
            const char t[]="[Fragment]\r\n"; for (i=0;t[i];i++) { glsl_log[glsl_logs]=t[i]; glsl_logs++; }
            glGetShaderInfoLog(frag_id,_size,&siz,glsl_log+glsl_logs);
            glsl_logs+=siz;
            }
        glLinkProgram(prog_id);
        glGetProgramiv(prog_id,GL_LINK_STATUS,&status);
        const char t[]="[Program]\r\n"; for (i=0;t[i];i++) { glsl_log[glsl_logs]=t[i]; glsl_logs++; }
        glGetProgramInfoLog(prog_id,_size,&siz,glsl_log+glsl_logs);
        glsl_logs+=siz;
    
        glReleaseShaderCompiler();
        glsl_log[glsl_logs]=0;
        }
    //------------------------------------------------------------------------------
    void glsl_exit()
        {
        glUseProgram(0);
        if (vert_id>0) { glDetachShader(prog_id,vert_id); glDeleteShader(vert_id); }
        if (geom_id>0) { glDetachShader(prog_id,geom_id); glDeleteShader(geom_id); }
        if (frag_id>0) { glDetachShader(prog_id,frag_id); glDeleteShader(frag_id); }
        if (prog_id>0) {                                  glDeleteShader(prog_id); }
        glsl_log[0]=0;
        }
    //---------------------------------------------------------------------------
    //------------------------------------------------------------------------------
    void vao_init()
        {
        GLuint i;
        glGenVertexArrays(4,vao);
        glGenBuffers(4,vbo);
        glBindVertexArray(vao[0]);
        i=0; // vertex
        glBindBuffer(GL_ARRAY_BUFFER,vbo[i]);
        glBufferData(GL_ARRAY_BUFFER,sizeof(vao_pos),vao_pos,GL_STATIC_DRAW);
        glEnableVertexAttribArray(i);
        glVertexAttribPointer(i,3,GL_FLOAT,GL_FALSE,0,0);
        i=1; // indices
        #ifdef vao_indices
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,vbo[i]);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(vao_ix),vao_ix,GL_STATIC_DRAW);
        glEnableVertexAttribArray(i);
        glVertexAttribIPointer(i,4,GL_UNSIGNED_INT,0,0);
        #endif
        i=2; // normal
        #ifndef vao_indices
        glBindBuffer(GL_ARRAY_BUFFER,vbo[i]);
        glBufferData(GL_ARRAY_BUFFER,sizeof(vao_nor),vao_nor,GL_STATIC_DRAW);
        glEnableVertexAttribArray(i);
        glVertexAttribPointer(i,3,GL_FLOAT,GL_FALSE,0,0);
        #endif
        i=3; // color
        glBindBuffer(GL_ARRAY_BUFFER,vbo[i]);
        glBufferData(GL_ARRAY_BUFFER,sizeof(vao_col),vao_col,GL_STATIC_DRAW);
        glEnableVertexAttribArray(i);
        glVertexAttribPointer(i,3,GL_FLOAT,GL_FALSE,0,0);
        i=4; // textures
        glBindBuffer(GL_ARRAY_BUFFER,vbo[i]);
        glBufferData(GL_ARRAY_BUFFER,sizeof(vao_txr),vao_txr,GL_STATIC_DRAW);
        glEnableVertexAttribArray(i);
        glVertexAttribPointer(i,2,GL_FLOAT,GL_FALSE,0,0);
    
        glBindVertexArray(0);
        glBindBuffer(GL_ARRAY_BUFFER,0);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
        glDisableVertexAttribArray(0);
        glDisableVertexAttribArray(1);
        glDisableVertexAttribArray(2);
        glDisableVertexAttribArray(3);
        glDisableVertexAttribArray(4);
        }
    //---------------------------------------------------------------------------
    void vao_exit()
        {
        glDeleteVertexArrays(5,vao);
        glDeleteBuffers(5,vbo);
        }
    //---------------------------------------------------------------------------
    void vao_draw()
        {
        glBindVertexArray(vao[0]);
        #ifndef vao_indices
        glDrawArrays(GL_QUADS,0,sizeof(vao_pos)/sizeof(vao_pos[0]));                    // QUADS ... no indices
        #endif
        #ifdef vao_indices
        glDrawElements(GL_QUADS,sizeof(vao_ix)/sizeof(vao_ix[0]),GL_UNSIGNED_INT,0);    // indices (choose just one line not both !!!)
        #endif
        glBindVertexArray(0);
        }
    //------------------------------------------------------------------------------
    //------------------------------------------------------------------------------
    

    您需要将纹理添加到着色器并将采样器单元与纹理坐标一起传递。这也不适用于启用索引,因为该示例不是为此而构建的,我懒得重新编码它。这里重要的是:

    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
        };
    

    如您所见,坐标的形式为start_of_texture+texture_coordinate,我从图集中为每张脸选择了 6 种不同的纹理...

    这里预览(禁用颜色以便纹理颜色更明显):

    为了完整起见,着色器(但是您的纹理可以正常工作,因此无需更改您的):

    // Fragment
    #version 400 core
    #extension GL_ARB_explicit_uniform_location : enable
    layout(location =64) uniform vec3 lt_pnt_pos;// point light source position [GCS]
    layout(location =67) uniform vec3 lt_pnt_col;// point light source color&strength
    layout(location =70) uniform vec3 lt_amb_col;// ambient light source color&strength
    layout(location =73) uniform sampler2D txr;
    in vec3 pixel_pos;      // fragment position [GCS]
    in vec3 pixel_col;      // fragment surface color
    in vec3 pixel_nor;      // fragment surface normal [GCS]
    in vec2 pixel_txr;      // fragment texture coord
    out vec4 col;
    void main()
        {
        float li;
        vec3 c,lt_dir;
        lt_dir=normalize(lt_pnt_pos-pixel_pos); // vector from fragment to point light source in [GCS]
        li=dot(pixel_nor,lt_dir);
        if (li<0.0) li=0.0;
        c =texture(txr,pixel_txr).rgb;
    //  c*=pixel_col;
        c*=(lt_amb_col+(lt_pnt_col*li));
        col=vec4(c,1.0);
        }
    
    // Vertex
    #version 400 core
    #extension GL_ARB_explicit_uniform_location : enable
    layout(location = 0) in vec3 pos;
    layout(location = 2) in vec3 nor;
    layout(location = 3) in vec3 col;
    layout(location = 4) in vec2 txr;
    layout(location = 0) uniform mat4 m_model;  // model matrix
    layout(location =16) uniform mat4 m_normal; // model matrix with origin=(0,0,0)
    layout(location =32) uniform mat4 m_view;   // inverse of camera matrix
    layout(location =48) uniform mat4 m_proj;   // projection matrix
    out vec3 pixel_pos;     // fragment position [GCS]
    out vec3 pixel_col;     // fragment surface color
    out vec3 pixel_nor;     // fragment surface normal [GCS]
    out vec2 pixel_txr;     // fragment texture coord
    void main()
        {
        pixel_col=col;
        pixel_pos=(m_model*vec4(pos,1)).xyz;
        pixel_nor=(m_normal*vec4(nor,1)).xyz;
        pixel_txr=txr;
        gl_Position=m_proj*m_view*m_model*vec4(pos,1);
        }
    

    这里是我的窗口的 C++/VCL 代码:

    //---------------------------------------------------------------------------
    #include <vcl.h>
    #include <jpeg.hpp>
    #pragma hdrstop
    #include "Unit1.h"
    #include "gl_simple.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TForm1 *Form1;
    //---------------------------------------------------------------------------
    GLfloat lt_pnt_pos[3]={+2.5,+2.5,+2.5};
    GLfloat lt_pnt_col[3]={0.8,0.8,0.8};
    GLfloat lt_amb_col[3]={0.2,0.2,0.2};
    GLuint  txrid=0;
    //---------------------------------------------------------------------------
    void gl_draw()
        {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glEnable(GL_CULL_FACE);
    
        // load values into shader
        GLint i,id;
        GLfloat m[16];
        glUseProgram(prog_id);
    /*
        id=glGetUniformLocation(prog_id,"lt_pnt_pos"); glUniform3fv(id,1,lt_pnt_pos);
        id=glGetUniformLocation(prog_id,"lt_pnt_col"); glUniform3fv(id,1,lt_pnt_col);
        id=glGetUniformLocation(prog_id,"lt_amb_col"); glUniform3fv(id,1,lt_amb_col);
        glGetFloatv(GL_MODELVIEW_MATRIX,m);
        id=glGetUniformLocation(prog_id,"m_model"   ); glUniformMatrix4fv(id,1,GL_FALSE,m);
        m[12]=0.0; m[13]=0.0; m[14]=0.0;
        id=glGetUniformLocation(prog_id,"m_normal"  ); glUniformMatrix4fv(id,1,GL_FALSE,m);
        for (i=0;i<16;i++) m[i]=0.0; m[0]=1.0; m[5]=1.0; m[10]=1.0; m[15]=1.0;
        id=glGetUniformLocation(prog_id,"m_view"    ); glUniformMatrix4fv(id,1,GL_FALSE,m);
        glGetFloatv(GL_PROJECTION_MATRIX,m);
        id=glGetUniformLocation(prog_id,"m_proj"    ); glUniformMatrix4fv(id,1,GL_FALSE,m);
    */
        id=64; glUniform3fv(id,1,lt_pnt_pos);
        id=67; glUniform3fv(id,1,lt_pnt_col);
        id=70; glUniform3fv(id,1,lt_amb_col);
        id=73; glUniform1i(id,0);   // texture unit
        glGetFloatv(GL_MODELVIEW_MATRIX,m);
        id=0; glUniformMatrix4fv(id,1,GL_FALSE,m);
        m[12]=0.0; m[13]=0.0; m[14]=0.0;
        id=16; glUniformMatrix4fv(id,1,GL_FALSE,m);
        for (i=0;i<16;i++) m[i]=0.0; m[0]=1.0; m[5]=1.0; m[10]=1.0; m[15]=1.0;
        id=32; glUniformMatrix4fv(id,1,GL_FALSE,m);
        glGetFloatv(GL_PROJECTION_MATRIX,m);
        id=48; glUniformMatrix4fv(id,1,GL_FALSE,m);
    
    
        // draw VAO cube
        glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D,txrid);
        vao_draw();
        glBindTexture(GL_TEXTURE_2D,0);
        glDisable(GL_TEXTURE_2D);
        // turn of shader
        glUseProgram(0);
    
        // render the cube in old style GL
        if (0)
            {
            glEnable(GL_LIGHTING);
            glEnable(GL_LIGHT0);
            glEnable(GL_COLOR_MATERIAL);
            #ifndef vao_indices
            glBegin(GL_QUADS);
            for (int i=0;i<6*4*3;i+=3)
                {
                glNormal3fv(vao_nor+i);
                glColor3fv (vao_col+i);
                glVertex3fv(vao_pos+i);
                }
            glEnd();
            #else
            int i,j,k;
            const GLfloat vao_nor[]=
                {
            //   nx   ny   nz
                 0.0, 0.0,-1.0,
                 0.0, 0.0,+1.0,
                 0.0,-1.0, 0.0,
                +1.0, 0.0, 0.0,
                 0.0,+1.0, 0.0,
                -1.0, 0.0, 0.0,
                };
            glBegin(GL_QUADS);
            for (j=0;j<6*4;j++)
                {
                i=vao_ix[j]; i+=i+i;
                k=j>>2; k+=k+k;
                glNormal3fv(vao_nor+k);
                glColor3fv (vao_col+i);
                glVertex3fv(vao_pos+i);
                }
            glEnd();
            #endif
            glDisable(GL_COLOR_MATERIAL);
            glDisable(GL_LIGHTING);
            glDisable(GL_LIGHT0);
            }
    
    
        // rotate the cube to see animation
        glMatrixMode(GL_MODELVIEW);
        glRotatef(1.0,0.0,1.0,0.0);
        glRotatef(1.0,1.0,0.0,0.0);
    
        // render point light source in [GCS]
        glMatrixMode(GL_MODELVIEW);
        glPushMatrix();
        glLoadIdentity();
        GLfloat x,y,z,d=0.25;
        x=lt_pnt_pos[0];
        y=lt_pnt_pos[1];
        z=lt_pnt_pos[2];
        glBegin(GL_LINES);
        glColor3fv(lt_pnt_col);
        glVertex3f(x-d,y,z);
        glVertex3f(x+d,y,z);
        glVertex3f(x,y-d,z);
        glVertex3f(x,y+d,z);
        glVertex3f(x,y,z-d);
        glVertex3f(x,y,z+d);
        glEnd();
        glMatrixMode(GL_MODELVIEW);
        glPopMatrix();
    
        glFlush();
        SwapBuffers(hdc);
        }
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner):TForm(Owner)
        {
        gl_init(Handle);
    
        // load shaders
        int hnd,siz; char vertex[4096],fragment[4096];
        hnd=FileOpen("normal_shading.glsl_vert",fmOpenRead); siz=FileSeek(hnd,0,2); FileSeek(hnd,0,0); FileRead(hnd,vertex  ,siz); vertex  [siz]=0; FileClose(hnd);
        hnd=FileOpen("normal_shading.glsl_frag",fmOpenRead); siz=FileSeek(hnd,0,2); FileSeek(hnd,0,0); FileRead(hnd,fragment,siz); fragment[siz]=0; FileClose(hnd);
        glsl_init(vertex,NULL,fragment);
        hnd=FileCreate("GLSL.txt"); FileWrite(hnd,glsl_log,glsl_logs); FileClose(hnd);
    
        // load texture atlas
        Byte q;
        unsigned int *pp;
        int xs,ys,x,y,adr,*txr;
        union { unsigned int c32; Byte db[4]; } c;
        TJPEGImage *jpg=new TJPEGImage;
        Graphics::TBitmap *bmp=new Graphics::TBitmap;
        if (bmp)
            {
            if (jpg)
                {
                jpg->LoadFromFile("textures128x128.jpg");
                bmp->Assign(jpg);
                delete jpg;
                }
            glGenTextures(1,&txrid);
            bmp->HandleType=bmDIB;      // allow direct access to pixels
            bmp->PixelFormat=pf32bit;   // set pixel to 32bit so int is the same size as pixel
            xs=bmp->Width;              // resolution should be power of 2
            ys=bmp->Height;
            txr=new int[xs*ys];         // create linear framebuffer
            for(adr=0,y=0;y<ys;y++)
                {
                pp=(unsigned int*)bmp->ScanLine[y];
                for(x=0;x<xs;x++,adr++)
                    {
                    // rgb2bgr and copy bmp -> txr[]
                        c.c32=pp[x];
                    q      =c.db[2];
                    c.db[2]=c.db[0];
                    c.db[0]=q;
                    txr[adr]=c.c32;
                    }
                }
            glEnable(GL_TEXTURE_2D);    // copy it to gfx card
            glBindTexture(GL_TEXTURE_2D,txrid);
            glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,GL_CLAMP);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,GL_CLAMP);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR);
            glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,GL_MODULATE);
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, xs, ys, 0, GL_RGBA, GL_UNSIGNED_BYTE, txr);
            glDisable(GL_TEXTURE_2D);
            delete[] txr;
            delete bmp;
            }
        vao_init();
        }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::FormDestroy(TObject *Sender)
        {
        glDeleteTextures(1,&txrid);
        gl_exit();
        glsl_exit();
        vao_exit();
        }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::FormResize(TObject *Sender)
        {
        gl_resize(ClientWidth,ClientHeight);
        glMatrixMode(GL_PROJECTION);
        glTranslatef(0,0,-15.0);
        }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::FormPaint(TObject *Sender)
        {
        gl_draw();
        }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Timer1Timer(TObject *Sender)
        {
        gl_draw();
        }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::FormMouseWheel(TObject *Sender, TShiftState Shift, int WheelDelta, TPoint &MousePos, bool &Handled)
        {
        GLfloat dz=2.0;
        if (WheelDelta<0) dz=-dz;
        glMatrixMode(GL_PROJECTION);
        glTranslatef(0,0,dz);
        gl_draw();
        }
    //---------------------------------------------------------------------------
    

    同样,大部分代码并不重要,您只需查找与 vao_ 相关的代码即可。

    【讨论】:

    • 你能解释一下我将如何使用纹理图集来解决这个问题吗?我真的很感激!
    • 如果不是太麻烦,如果您也用示例解释此方法,我也将不胜感激,“您需要将具有相同纹理的单独面放入单独的 VAO/VBO(而不是将整个立方体放入单一个)”
    • @joeOla 你不明白什么?这将与您现在得到的相同,但您需要 6 个 VAO(每个仅包含一个面)而不是 1 个(包含所有 6 个面),然后 1. 绑定纹理 0,渲染 VAO0 2. 绑定纹理 1,渲染 VAO1 。 .. 6. 绑定texture5,渲染VAO5 ...所以每个表都会被分成6个...
    • @joeOla 还有另一种选择,如果您使用相同的纹理对所有顶点进行分组,那么您不需要剖析您只需调用 glDrawArrays 不同的 first 和 @987654344 的 VAO/VBO @ ... 所以绑定texture0 调用glDrawArrays(?,0*n,n) 然后绑定texture1 调用glDrawArrays(?,1*n,n) 等等...其中n 是每个面的顶点数,所以如果使用三角形则为6,如果使用四边形则为4 ...
    • 所以我需要使用 glDrawArrays() 六次?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-12
    • 2017-10-29
    • 2014-12-15
    • 2020-08-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多