2017-06-13 40 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);