Opengl Array Texture,适用于原始数据,但不适用于图像数据

Posted

技术标签:

【中文标题】Opengl Array Texture,适用于原始数据,但不适用于图像数据【英文标题】:Opengl Array Texture, works with raw data but not with image data 【发布时间】:2014-12-01 05:03:57 【问题描述】:

我可以加载单个纹理 我可以创建一个纹理数组传递纹素数据(如这里的示例) https://www.opengl.org/wiki/Array_Texture

但是当我将图像数据传递给 glTexSubImage3D 时,我什么都看不到。

源代码: https://github.com/omenking/17array_texture

#include <iostream>
using namespace std;
#include <cstdlib>
#include <stdio.h>

#include <GL/glew.h>
#include <GLFW/glfw3.h>

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
using namespace glm;

GLFWwindow* window;

#define WINDOW_HEIGHT 768
#define WINDOW_WIDTH 1024

#include "common/shaders.h"
#include "common/texture.h"
#include "common/controls.h"

#define BUFFER_OFFSET(i) ((char *)NULL + (i))


static void error_callback(int error, const char* description);
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods);

int main(void)


  if (!glfwInit()) 
        fprintf( stderr, "Failed to initialize GLFW\n" );
    exit(EXIT_FAILURE);
  

    glfwWindowHint(GLFW_SAMPLES, 4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
  glfwWindowHint(GLFW_OPENGL_PROFILE       , GLFW_OPENGL_CORE_PROFILE);
  glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);

  window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "Ortho", NULL, NULL);
  if (!window) 
        fprintf(stderr, "Failed to create window\n");
    glfwTerminate();
    exit(EXIT_FAILURE);
  
  glfwMakeContextCurrent(window);
  glfwSetKeyCallback(window, key_callback);
  glfwSetErrorCallback(error_callback);
    glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
  glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
    glfwSetCursorPos(window, WINDOW_WIDTH/2, WINDOW_HEIGHT/2);

  glewExperimental = GL_TRUE;
    if (glewInit() != GLEW_OK) 
        fprintf(stderr, "Failed to initialize GLEW\n");
    glfwTerminate();
    exit(EXIT_FAILURE);
    
  if (GL_EXT_texture_array)
        fprintf(stderr, "GL_EXT_texture_array\n");
  

    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LESS); 

    GLuint vai; // vertex array id
    glGenVertexArrays(2, &vai);
    glBindVertexArray(vai);

  char vert[] = "shaders/triangles.vert";
  char frag[] = "shaders/triangles.frag";

  GLuint program    = load_shaders(vert,frag);

    GLuint matrix_id  = glGetUniformLocation(program, "MVP");
    GLuint texture_id = glGetUniformLocation(program, "material");

  GLsizei width         = 16;
  GLsizei height        = 16;
  GLsizei layerCount    = 2;
  GLsizei mipLevelCount = 1;

  unsigned char* data = bmp_data("uvtemplate.bmp");
  //unsigned char* data = bmp_data("tiles.bmp");

  glGenTextures(1, &texture_id);
  glBindTexture(GL_TEXTURE_2D_ARRAY, texture_id);

  //GLubyte texels[32] = 
  //
       ////Texels for first image.
       //0,   0,   0,   255,
       //255, 0,   0,   255,
       //0,   255, 0,   255,
       //0,   0,   255, 255,
       ////Texels for second image.
       //255, 255, 255, 255,
       //255, 255,   0, 255,
       //0,   255, 255, 255,
       //255, 0,   255, 255,
  //;
  //glTexStorage3D(GL_TEXTURE_2D_ARRAY, mipLevelCount, GL_RGBA8, width, height, layerCount);
  //glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, width, height, layerCount, GL_RGBA, GL_UNSIGNED_BYTE, texels);

  glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_BGR, width, height, layerCount);
  glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, width, height, layerCount, GL_BGR, GL_UNSIGNED_BYTE, data);

  //glTexParameteri(GL_TEXTURE_2D_ARRAY,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
  //glTexParameteri(GL_TEXTURE_2D_ARRAY,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D_ARRAY,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
  glTexParameteri(GL_TEXTURE_2D_ARRAY,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
    delete [] data;

    GLuint vbo;
    GLuint uvbo;
  glGenBuffers(1, &vbo);
  glGenBuffers(1, &uvbo);
  // prep tile
  GLfloat vertex[] = 
    -1, 1,0,
     1, 1,0,
     1,-1,0,

     -1, 1,0,
     -1,-1,0,
      1,-1,0,
  ;
  GLfloat uv[] = 
    //-1, 1,0,
     //1, 1,0,
     //1,-1,0,

     //-1, 1,0,
     //-1,-1,0,
      //1,-1,0,

    0.000059f, 1.0f-0.000004f,
    0.000103f, 1.0f-0.336048f,
    0.335973f, 1.0f-0.335903f,

    0.000059f, 1.0f-0.000004f,
    0.000103f, 1.0f-0.336048f,
    0.335973f, 1.0f-0.335903f,
  ;

  glBindBuffer(GL_ARRAY_BUFFER, vbo);
  glBufferData(GL_ARRAY_BUFFER, sizeof(vertex), vertex, GL_STATIC_DRAW);

  glBindBuffer(GL_ARRAY_BUFFER, uvbo);
  glBufferData(GL_ARRAY_BUFFER, sizeof(uv), uv, GL_STATIC_DRAW);

  glUseProgram(program);
  while (!glfwWindowShouldClose(window)) 
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        computeMatricesFromInputs();
        glm::mat4 ProjectionMatrix = getProjectionMatrix();
        glm::mat4 ViewMatrix       = getViewMatrix();
        glm::mat4 ModelMatrix      = glm::mat4(1.0);
        glm::mat4 MVP              = ProjectionMatrix * ViewMatrix * ModelMatrix;

    glUniformMatrix4fv(matrix_id, 1, GL_FALSE, &MVP[0][0]);
    glUniform1i(texture_id, 0);

    // render tile
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);

    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,0,(void*)0);

    glBindBuffer(GL_ARRAY_BUFFER, uvbo);
    glVertexAttribPointer(1,2,GL_FLOAT,GL_FALSE,0,(void*)0);

    glDrawArrays(GL_TRIANGLES, 0, 2*3);

    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);



    glfwSwapBuffers(window);
    glfwPollEvents();
  
  glfwDestroyWindow(window);

    glDeleteProgram(program);
    glDeleteVertexArrays(2, &vai);

  glfwTerminate();
  exit(EXIT_SUCCESS);


static void error_callback(int error, const char* description)
  fputs(description, stderr);


static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
  if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
      glfwSetWindowShouldClose(window, 1);

【问题讨论】:

【参考方案1】:

你传递给glTexStorage3D()的格式有问题:

glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_BGR, width, height, layerCount);

GL_BGR 不是glTexStorage3D() 的有效格式。仅支持大小格式。有关有效格式的列表,请参阅man page。在您的情况下,GL_RGB8 可能是您想要的格式:

glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGB8, width, height, layerCount);

如果这是输入数据的字节顺序,您仍然可以在 glTexSubImage3D() 调用中使用 GL_BGR 作为格式参数。

一些可能会或可能不会导致您当前代码出现问题的小注释:

这会导致写入超出数组的边界,因为数组的大小为 1,但您请求两个顶点数组名称:

GLuint vai; // vertex array id
glGenVertexArrays(2, &vai);

您需要创建一个包含两个 id 的数组,或者将第一个参数更改为 1。

您可能需要当前已注释掉的glTexParameteri() 调用,至少是GL_TEXTURE_MIN_FILTER 的调用。

【讨论】:

通过将格式更改为 GL_RGB8,我能够看到渲染的纹理。 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGB8, width, height, layerCount); glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 宽度, 高度, layerCount, GL_BGR, GL_UNSIGNED_BYTE, 数据);

以上是关于Opengl Array Texture,适用于原始数据,但不适用于图像数据的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL渲染白色纹理错误

使用 GL_TEXTURE_2D_ARRAY 作为绘制目标

OpenGL学习——纹理

openGL之API学习(二零零)GL_TEXTURE_GEN_S GL_TEXTURE_GEN_T GL_TEXTURE_GEN_R GL_TEXTURE_GEN_Q

<OpenGL> Texture Mapping

是否可以将 SDL_Texture 绘制到 OpenGL?