2017-06-13 77 views
0

我擁有紋理,可以在OpenGL中通過常規方式渲染任何問題。但是現在我想在GLSL中渲染紋理,這是我目前遇到的問題。我沒有問題呈現一個常量矢量顏色,但它不檢測我發送給GLSL的紋理。無法通過GLSL呈現SDL紋理

下面是代碼:

GLunit wipeoutTexID; 

int main(int argc, char* args[]) { 

    // Start up SDL and create window 
    if (!init()) 
    { 
     printf("Failed to initialize!\n"); 
    } 
    else 
    { 
     // Main loop flag 
     bool quit = false; 

     // Event handler 
     SDL_Event e; 

     // Enable text input 
     SDL_StartTextInput(); 

     // While application is running 
     while (!quit) { 

      // Handle events on queue 
      while (SDL_PollEvent(&e) != 0) 
      { 
       // User requests quit 
       if (e.type == SDL_QUIT) { 
        quit = true; 
       } 
       // Handle keypress with current mouse position 
       else if (e.type == SDL_TEXTINPUT) 
       { 
        int x = 0, y = 0; 
        SDL_GetMouseState(&x, &y); 
        handleKeys(e.text.text[0], x, y); 
       } 
      } 

      // Update objects 
      update(); 

      // Render quad 
      render(); 

      // Update screen 
      SDL_GL_SwapWindow(gWindow); 

     } 

     // Disable text input 
     SDL_StopTextInput(); 

    } 

    // Free resources and close SDL 
    close(); 

    return 0; 

} 

bool init() { 

    .... 

    // Initialization flag 
    bool success = true; 

    .... 

    if(!initGL()) { 
     success = false; 
    } else 
    { 
     .... 

     wipeoutTexID = glLoadTexture(resPath + "wipeout.bmp"); 
     if(wipeoutTexID == NULL) 
     { 
      success = false; 
     } 

     .... 
    } 

    .... 

    return success; 

} 

bool initGL() 
{ 
// Success flag 
bool success = true; 

// Generate program 
gProgramID = glCreateProgram(); 

// Create vertex shader 
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); 

// Get vertex source 
const GLchar* vertexShaderSource[] = 
{ 
    "#version 140\nin vec3 aPos; void main() { vec4(aPos.x, aPos.y, aPos.z, 1.0); gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; gl_TexCoord[0] = gl_MultiTexCoord0; }" 
}; 

// Set vertex source 
glShaderSource(vertexShader, 1, vertexShaderSource, NULL); 

// Compile vertex source 
glCompileShader(vertexShader); 

// Check vertex shader for errors 
GLint vShaderCompiled = GL_FALSE; 
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &vShaderCompiled); 
if (vShaderCompiled != GL_TRUE) 
{ 
    printf("Unable to compile vertex shader %d!\n", vertexShader); 
    printShaderLog(vertexShader); 
    success = false; 
} 
else 
{ 
    // Attach vertex shader to program 
    glAttachShader(gProgramID, vertexShader); 

    // Create fragment shader 
    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); 

    // Get fragment source 
    const GLchar* fragmentShaderSource[] = 
    { 
     "#version 140\nuniform sampler2D tex; uniform vec4 ourColor; void main() { vec4 color = texture2D(tex, gl_TexCoord[0].xy); gl_FragColor = mix(ourColor, color, 0.5); }" 
    }; 

    // Set fragment source 
    glShaderSource(fragmentShader, 1, fragmentShaderSource, NULL); 

    // Compile fragment source 
    glCompileShader(fragmentShader); 

    // Check fragment shader for errors 
    GLint fShaderCompiled = GL_FALSE; 
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &fShaderCompiled); 
    if (fShaderCompiled != GL_TRUE) 
    { 
     printf("Unable to compile fragment shader %d!\n", fragmentShader); 
     printShaderLog(fragmentShader); 
     success = false; 
    } 
    else 
    { 
     // Attach fragment shader to program 
     glAttachShader(gProgramID, fragmentShader); 

     // Link program 
     glLinkProgram(gProgramID); 

     // Check for errors 
     GLint programSuccess = GL_TRUE; 
     glGetProgramiv(gProgramID, GL_LINK_STATUS, &programSuccess); 
     if (programSuccess != GL_TRUE) 
     { 
      printf("Error linking program %d!\n", gProgramID); 
      printProgramLog(gProgramID); 
      success = false; 
     } 
     else 
     { 
      // Get vertex attribute location 
      gVertexPos2DLocation = glGetAttribLocation(gProgramID, "aPos"); 
      if (gVertexPos2DLocation == -1) 
      { 
       printf("LVertexPos2D is not a valid glsl program variable!\n"); 
       success = false; 
      } 
      else 
      { 
       // Initialize clear color 
       glClearColor(0.f, 0.f, 0.f, 1.f); 

       // VBO data 
       GLfloat vertexData[] = 
       { 
        0.0f, 0.0f, 
        0.0f, 1.0f, 
        1.0f, 1.0f, 
        0.0f, 1.0f 

       }; 

       // IBO data 
       GLuint indexData[] = { 0, 1, 2, 3 }; 

       // Create VBO 
       glGenBuffers(1, &gVBO); 
       glBindBuffer(GL_ARRAY_BUFFER, gVBO); 
       glBufferData(GL_ARRAY_BUFFER, /*2 * 4 * sizeof(GLfloat)*/ sizeof(vertexData), vertexData, GL_STATIC_DRAW); 

       // Create IBO 
       glGenBuffers(1, &gIBO); 
       glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gIBO); 
       glBufferData(GL_ELEMENT_ARRAY_BUFFER, /*4 * sizeof(GLuint)*/ sizeof(indexData), indexData, GL_STATIC_DRAW); 
      } 
     } 
    } 
} 

return success; 
} 


GLuint glLoadTexture(const std::string &file) { 

GLuint tex; 
glGenTextures(1, &tex); 

glBindTexture(GL_TEXTURE_2D, tex); 

float color[] = {1.0f, 0.0f, 0.0f, 1.0f}; 
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color); 

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 

glGenerateMipmap(GL_TEXTURE_2D); 

gSurface = NULL; 
gSurface = SDL_LoadBMP(file.c_str()); 

if (gSurface == NULL) 
{ 
    return NULL; 
} 
else 
{ 
    std::cout << "Image height: " << gSurface->h << std::endl; 
    std::cout << "Image width: " << gSurface->w << std::endl; 
    std::cout << "Images Pixels: " << gSurface->pixels << std::endl; 
    std::cout << "Images BitsPerPixel: " << gSurface->format->BitsPerPixel << std::endl; 
    std::cout << "Images Rmask: " << gSurface->format->Rmask << std::endl; 
    std::cout << "Images Surface: " << gSurface << std::endl; 

    int mode = GL_RGB; 

    if (gSurface->format->BitsPerPixel == 4) 
    { 
     mode = GL_RGBA; 
    } 

    GLenum data_fmt = mode; 
    Uint8 test = SDL_MapRGB(gSurface->format, 0xAA, 0xBB, 0xCC) & 0xFF; 
    if (test == 0xAA) data_fmt = GL_RGB; 
    else if (test == 0xCC) data_fmt = 0x80E0;//GL_BGR; 
    else { 
     printf("Error: \"Loaded surface was neither RGB or BGR!\""); 
     return NULL; 
    } 

    glTexImage2D(GL_TEXTURE_2D, 0, mode, gSurface->w, gSurface->h, 0, data_fmt, GL_UNSIGNED_BYTE, gSurface->pixels); 
    SDL_FreeSurface(gSurface); 

    return tex; 
} 

} 

void render() { 

    // Clear color buffer 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 

    glActiveTexture(GL_TEXTURE0 + 0); 
    glBindTexture(GL_TEXTURE_2D, wipeoutTexID); 
    glUniform1i(glGetUniformLocation(gProgramID, "tex"), 0); 

    // Bind program 
    glUseProgram(gProgramID); 

    // Enable vertex position 
    glEnableVertexAttribArray(gVertexPos2DLocation); 

    // Set vertex data 
    glBindBuffer(GL_ARRAY_BUFFER, gVBO); 
    glVertexAttribPointer(gVertexPos2DLocation, 2, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), BUFFER_OFFSET(6 * sizeof(float))); 

    float timeValue = SDL_GetTicks(); 
    float greenValue = 0.8f - 0.2f * abs(sin(0.001f*timeValue)); 
    int vertexColorLocation = glGetUniformLocation(gProgramID, "ourColor"); 
    glUniform4f(vertexColorLocation, 0.0f, greenValue, 0.0f, 1.0f); 

    // Set index data and render 
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gIBO); 
    glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_INT, NULL); 

    // Disable vertex position 
    glDisableVertexAttribArray(gVertexPos2DLocation); 

    // Unbind program 
    glUseProgram(NULL); 

    glColor4f(1.f, 1.f, 1.f, 0.f); 
} 

你能看到我做錯了嗎?

頂點着色器:

#version 140 
in vec3 aPos; 

void main() 
{ 
    vec4(aPos.x, aPos.y, aPos.z, 1.0); 
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; 
    gl_TexCoord[0] = gl_MultiTexCoord0; 
} 

片段着色器:

#version 140 
uniform sampler2D tex; 
uniform vec4 ourColor; 

void main() { 
    vec4 color = texture2D(tex, gl_TexCoord[0].xy); 
    gl_FragColor = mix(ourColor, color, 0.5); 
} 
+1

請張貼shader代碼更易讀的方式 – Jeka

+0

嘗試做顯示紋理座標顏色,以檢查它是否正確。通常在片段着色器中使用每個頂點紋理座標的頂點着色器輸出。我看到你使用內置變量,但我不知道它們是如何工作的 – Jeka

+0

好吧我已經使用這些着色器的結構化和可讀代碼更新了帖子。 – john13th

回答

0

最快,最簡單的解決方案是添加紋理座標作爲輸出在頂點着色器:

頂點着色器:

#version 140 
in vec3 aPos; 
out vec2 uv; 

void main() 
{ 
    uv = gl_Vertex.xy; 
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; 
    gl_TexCoord[0] = gl_MultiTexCoord0; 
} 

片段着色器:

#version 140 
in vec2 uv; 
uniform sampler2D tex; 
uniform vec4 ourColor; 

void main() { 
    vec4 color = texture2D(tex, uv); 
    gl_FragColor = mix(ourColor, color, 0.5); 
} 

爲了更好地理解看看一些教程,專注於現代的OpenGL,您使用的是一些舊的過時的方法。

0

由於glUniform指定當前程序對象的統一變量的值,所以在函數render中存在指令順序問題。

均勻位置可以在任何時間通過glGetUniformLocation被檢索,並存儲以備後用,該程序被成功鏈接後(glLinkProgram):

int texLocation = glGetUniformLocation(gProgramID, "tex"); 

但是設置一個均勻的變量的值,所述程序必須是活動程序(glUseProgram)。請注意,在glUniform的sinity中沒有選擇程序的參數。
你必須使用程序,

// Bind program 
glUseProgram(gProgramID); 

之前設置的制服的值,因爲該組操作適用於當前使用的程序:

glUniform1i(texLocation, 0 /*texture unit 0*/); 

在功能render你做它以相反的順序。

此外,您正在使用vor紋理屬性的技術已被棄用,請參閱GLSL : common mistakes。 看看你對頂點in vec3 aPos;做了什麼,併爲紋理座標這麼做。

頂點着色器:

#version 140 

in vec3 aPos; 
in vec2 aTexCoord; 

out vec3 texCoord; 

void main() 
{ 
    texCoord = aTexCoord; 
    gl_Position = gl_ModelViewProjectionMatrix * vec3(aPos, 1.0); 
} 

片段着色器:

#version 140 

in texCoord; 

uniform sampler2D tex; 
uniform vec4 ourColor; 

void main() 
{ 
    vec4 color = texture2D(tex, texCoord.st); 
    gl_FragColor = mix(ourColor, color, 0.5); 
} 

創建陣列緩衝器:

GLfloat vertexData[] = { 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f }; 
GLfloat texCoordData[] = { 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f }; 
GLuint indexData[] = { 0, 1, 2, 3 }; 

GLuint gVBO[2] 
glGenBuffers(2, &(gVBO[0])); 
glBindBuffer(GL_ARRAY_BUFFER, gVBO[0]); 
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW); 
glBindBuffer(GL_ARRAY_BUFFER, gVBO[1]); 
glBufferData(GL_ARRAY_BUFFER, sizeof(texCoordData), texCoordData, GL_STATIC_DRAW); 
GLuint gIBO; 
glGenBuffers(1, &gIBO); 
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gIBO); 
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_STATIC_DRAW); 

獲得從所述着色器程序中的屬性指數:

gVertexPos2DLocation = glGetAttribLocation(gProgramID, "aPos"); 
gTexCoordLocation = glGetAttribLocation(gProgramID, "aTexCoord"); 

指定頂點屬性,使頂點屬性和並繪製網格:

glBindBuffer(GL_ARRAY_BUFFER, gVBO[0]); 
glVertexAttribPointer(gVertexPos2DLocation, 2, GL_FLOAT, GL_FALSE, 0, NULL); 
glBindBuffer(GL_ARRAY_BUFFER, gVBO[1]); 
glVertexAttribPointer(gTexCoordLocation, 2, GL_FLOAT, GL_FALSE, 0, NULL); 
glEnableVertexAttribArray(gVertexPos2DLocation); 
glEnableVertexAttribArray(gTexCoordLocation); 

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gIBO); 
glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_INT, NULL);