2014-06-10 3 views
0

텍스처를 삼각형 스트립에로드하는 데 문제가 있습니다. 나는 Anton Gerdelan's tutorial을 따르고 있으며, 내 메인 프로그램에서 실패한 후에 나는 기본으로 돌아가서 그냥 평평한 사각형을 만들고 그 위에 텍스처 (두개골과 이미지)를 넣으려고했다.OpenGL C++ 버텍스 버퍼 및 텍스쳐 버퍼 사용 순서

효과가있는 그의 "Hello Triangle" 페이지에서 코드를 완전히 복사하고 붙여 넣었지만 위의 텍스처 튜토리얼의 코드에 맞게 (그리고 삼각형을 사각형으로 변경) 한 번 시도해 보니 커다란 흰색 사각형이되었습니다. 아무 텍스처없이.

glGetShaderiv()로 쉐이더의 상태를 확인한 결과 양수로 반환되었습니다.로드 한 이미지를 확인하여 픽셀 데이터가 합리적인 지 확인 했으므로 VBO를 선언 할 때 오류가 발생했습니다. 주문/매개 변수를 사용하고 있습니다.

다음은 Visual Studio 2013에서 정상적으로 컴파일 된 전체 코드입니다. 출력이 예상 한 것과 다릅니다.

나는 당신이 texcoords와 버퍼 있어야하는데 두 번째 버퍼를 오용하고있는 STBI 이미지 헤더

#include <GL/glew.h> // include GLEW and new version of GL on Windows 
#include <GL/glfw3.h> // GLFW helper library 
#include <stdio.h> 
#define STB_IMAGE_IMPLEMENTATION 
#include <stb/stb_image.h> 

const char* vertex_shader = 
"#version 400\n" 
"in vec3 vp;" 
"layout (location=1) in vec2 vt; // per-vertex texture co-ords" 
"out vec2 texture_coordinates; " 
"void main() {" 
" gl_Position = vec4 (vp, 1.0);" 
" texture_coordinates = vt; " 
"}"; 

const char* fragment_shader = 
"#version 400\n" 
"in vec2 texture_coordinates;" 
"uniform sampler2D basic_texture;" 
"out vec4 frag_colour;" 
"void main() {" 
"vec4 texel = texture(basic_texture, texture_coordinates);" 
"frag_colour = texel; " 
"}"; 

float points[] = { 
    -0.5f, -0.5f, 0.0f, 
    -0.5f, 0.5f, 0.0f, 
    0.5f, -0.5f, 0.0f, 
    0.5f, 0.5f, 0.0f 

}; 

float texcoords[] = { 
    0.0f, 1.0f, 
    0.0f, 0.0f, 
    1.0, 0.0, 
    1.0, 0.0, 
    1.0, 1.0, 
    0.0, 1.0 
}; 

GLFWwindow* window; 
unsigned int vt_vbo; 
unsigned int tex = 0; 
GLuint vao = 0; 
GLuint vbo = 0; 
GLuint shader_programme; 

void initializeGL(){ 
    // start GL context and O/S window using the GLFW helper library 
    if (!glfwInit()) { 
     printf("ERROR: could not start GLFW3\n"); 
     return; 
    } 

    window = glfwCreateWindow(640, 480, "Texture Test", NULL, NULL); 
    if (!window) { 
     printf("ERROR: could not open window with GLFW3\n"); 
     glfwTerminate(); 
     return; 
    } 
    glfwMakeContextCurrent(window); 

    // start GLEW extension handler 
    glewExperimental = GL_TRUE; 
    glewInit(); 

    // get version info 
    const GLubyte* renderer = glGetString(GL_RENDERER); // get renderer string 
    const GLubyte* version = glGetString(GL_VERSION); // version as a string 
    printf("Renderer: %s\n", renderer); 
    printf("OpenGL version supported %s\n", version); 

    // tell GL to only draw onto a pixel if the shape is closer to the viewer 
    glEnable(GL_DEPTH_TEST); // enable depth-testing 
    glDepthFunc(GL_LESS); // depth-testing interprets a smaller value as "closer" 
} 

void startShaders(){ 

    GLuint vs = glCreateShader(GL_VERTEX_SHADER); 
    glShaderSource(vs, 1, &vertex_shader, NULL); 
    glCompileShader(vs); 
    GLuint fs = glCreateShader(GL_FRAGMENT_SHADER); 
    glShaderSource(fs, 1, &fragment_shader, NULL); 
    glCompileShader(fs); 

    shader_programme = glCreateProgram(); 
    glAttachShader(shader_programme, fs); 
    glAttachShader(shader_programme, vs); 
    glLinkProgram(shader_programme); 
    GLint vsstat; 
    glGetShaderiv(vs, GL_COMPILE_STATUS, &vsstat); 
    GLint fsstat; 
    glGetShaderiv(fs, GL_COMPILE_STATUS, &fsstat); 
    printf("%i\n%i\n", vsstat, fsstat); 
} 

void loadImage(){ 
    int x, y, n; 
    int force_channels = 4; 
    unsigned char* image_data = stbi_load("skulluvmap.png", &x, &y, &n, force_channels); 
    if (!image_data) { 
     printf("ERROR: could not load %s\n", "skulluvmap.png"); 
    } 

    int width_in_bytes = x * 4; 
    unsigned char *top = NULL; 
    unsigned char *bottom = NULL; 
    unsigned char temp = 0; 
    int half_height = y/2; 


    for (int row = 0; row < half_height; row++) { 
     top = image_data + row * width_in_bytes; 
     bottom = image_data + (y - row - 1) * width_in_bytes; 
     for (int col = 0; col < width_in_bytes; col++) { 
      temp = *top; 
      *top = *bottom; 
      *bottom = temp; 
      top++; 
      bottom++; 
     } 
    } 
    printf("first 4 bytes are: %i %i %i %i\n", 
     image_data[0], image_data[1], image_data[2], image_data[3] 
     ); 
    glGenTextures(1, &tex); 
    glActiveTexture(GL_TEXTURE0); 
    glBindTexture(GL_TEXTURE_2D, tex); 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
} 

void generateBuffers(){ 
    glGenVertexArrays(1, &vao); 
    glBindVertexArray(vao); 

    glGenBuffers(1, &vbo); 
    glBindBuffer(GL_ARRAY_BUFFER, vbo); 
    glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(float), points, GL_STATIC_DRAW); 

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL); 
    glEnableVertexAttribArray(0); // don't forget this! 

    glGenBuffers(1, &vt_vbo); 
    glBindBuffer(GL_ARRAY_BUFFER, vt_vbo); 
    glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(float), texcoords, GL_STATIC_DRAW); 

    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, NULL); 
    glEnableVertexAttribArray(1); // don't forget this! 
} 

void mainLoop(){ 
    while (!glfwWindowShouldClose(window)) { 
     // wipe the drawing surface clear 
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
     int tex_loc = glGetUniformLocation(shader_programme, "basic_texture"); 
     glUseProgram(shader_programme); 
     glUniform1i(tex_loc, 0); // use active texture 0 
     // draw points 0-4 from the currently bound VAO with current in-use shader 
     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 
     // update other events like input handling 
     glfwPollEvents(); 
     // put the stuff we've been drawing onto the display 
     glfwSwapBuffers(window); 
    } 
} 

int main() { 

    initializeGL(); 
    startShaders(); 
    loadImage(); 
    generateBuffers(); 
    mainLoop(); 

    // close GL context and any other GLFW resources 
    glfwTerminate(); 
    return 0; 
} 
+0

버텍스 쉐이더에서'in vec3 vp; '앞에'layout (location = 0)'을 추가 할 수 있습니까? 그렇지 않으면 위치 속성이 위치 0에 있어야합니다. –

답변

1

와 함께, GLEW와 GLFW의 정적 라이브러리를 사용하고 있습니다. 따라서 실제로 달성하고자하는 것은 모든 정점에 대해 한 쌍의 텍스처 좌표를 갖는 것입니다. 즉, 포인트 배열에 4 개의 트리플이 있기 때문에 실제로 배열을 배열해야합니다. 이것이 바로 첫 번째 문제입니다. 당신의 vt_vbo 잘못의 generateBuffers에서 다음

float texcoords[] = { 
0.0f, 1.0f, 
0.0f, 0.0f, 
1.0, 0.0, 
1.0, 1.0, 
}; 

: 당신은 아마 같이하고 싶다. 데이터는 다음과 같이 전달해야합니다.

glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(float), texcoords, GL_STATIC_DRAW); 

여기에 8 개의 값만 전달해야하기 때문에 데이터를 전달해야합니다. 각 꼭지점마다 2 개의 텍스쳐.

편집 : 당신의 질감이 전혀 나타나지 않는 이유

이 있지만, 완전히 설명하지 않습니다. 나는 주로 귀하의 texcoords 포인터에 문제가있을 것이라고 생각했지만 그럴 것 같지 않습니다.

+0

이 코드는 일반적인 정점 속성을 사용합니다. 'glVertexAttribPointer (1, ..)'은 텍스처 좌표를 설정합니다. 'glTexCoordPointer()'는 고정 함수 정점 속성을위한 것으로 여기에서 사용하는 것은 잘못 될 것입니다. –

+0

@ 레토 코라 디 : 좋은 지적, 나쁘다. 하지만 어쨌든, 텍스처 위치가 1이라고 가정하는 것이 안전할까요? "glGetAttribLocation (MyShader,"InTexCoord0 ");"과 같이하지 말아야합니다. 해당 위치를 검색하는 데 사용됩니까? – Elvithari

+0

위치는 버텍스 쉐이더의 '레이아웃'에 지정됩니다. 응용 프로그램이 수동으로 다시 정의하지 않는 한 1입니다. – keltar

관련 문제