OpengL数组纹理显示失真

时间:2014-12-02 02:17:24

标签: c++ macos opengl textures texture2d

这是我的纹理

enter image description here

这就是它出现的方式

enter image description here

使用数组纹理时,我只得到这个扭曲的结果。

我是否需要创建mipmap? 我使用的是错误的图像类型?

bmp可能是图像的一个想法,但我暂时使用它们的简单。

代码

#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, 255.0f, 0.0f);

    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LESS); 

    GLuint vai; // vertex array id
    glGenVertexArrays(1, &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("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);

  glPixelStorei(GL_UNPACK_ROW_LENGTH, 16);

  glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGB8, width, height, layerCount);
  glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, width, height, layerCount, GL_RGB, 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[] = {
     0, 1, 0,
     1, 1, 0,
     1, 0, 0,

     0, 1, 0,
     0, 0, 0,
     1, 0, 0,
  };
  GLfloat uv[] = {
     0.0f , 16.0f,
     16.0f, 16.0f,
     16.0f, 0.0f ,

     0.0f , 16.0f,
     0.0f , 0.0f ,
     16.0f, 0.0f ,
  };

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

片段着色器

#version 400 core
in vec2 uv;                      // Interpolated values from the vertex shaders
out vec3 color;                  // Ouput data
uniform sampler2DArray material; // Values that stay constant for the whole mesh.

void main(){
    color = texture(material,vec3(uv,0)).rgb;
}

vert shader

#version 400 core
layout(location = 0) in vec3 vertex_pos;
layout(location = 1) in vec2 vertex_uv;

out vec2 uv;
uniform mat4 MVP;

void main(){
    gl_Position =  MVP * vec4(vertex_pos,1);
  uv          = vertex_uv;
}

1 个答案:

答案 0 :(得分:0)

我最终付钱让别人为我解决这个问题。

我需要更新纹理顶点。我也不需要调用glPixelStorei所以我删除它。

GLfloat vertex[] = {
   0, 1, 0,
   1, 1, 0,
   1, 0, 0,

   0, 1, 0,
   0, 0, 0,
   1, 0, 0,
};

纹理文件边界(uv坐标)在x和y轴上从0.0到1.0。如果要将整个纹理映射到四边形,可以将四个角设置为四边形的四个角。以下图片是一个很好的例子: http://www.c-jump.com/bcc/common/Talk3/OpenGL/Wk07_texture/const_images/textureMap.png