2012-01-07 90 views
0

我有一个纹理问题 - 它正确加载图像,但会将垃圾渲染到几何体上。几何图形本身绘制得很好(一个简单的三角形),但无论我加载哪种纹理,都会将随机图案吐出到三角形上。OpenGL纹理垃圾

我用G ++ 4.2.1 Mac OS X上使用Qt 4.7和OpenGL

首先,这里的控制台输出:

BallGLWidget::initializeGL called 
Image format is GL_RGB 
Checking textures... 
glGetError enum value: GL_NO_ERROR 

而且,我对着色器初始化日志代码不会注册任何错误。

OpenGL的初始化函数:

void BallGLWidget::initializeGL() 
{ 

    cout << "BallGLWidget::initializeGL called" << endl; 

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

    initializeShaders(); 



    checkOpenGLError(); 

    glEnableVertexAttribArray(VERTEX_POS_NUM); 
    glEnableVertexAttribArray(TEX_POS_NUM); 

    glBindAttribLocation(programHandle, VERTEX_POS_NUM, VERTEX_POS_ATTRIB_NAME); 
    glBindAttribLocation(programHandle, TEX_POS_NUM, TEX_COORD_ATTRIB_NAME); 

    //this MUST be called AFTER glBindAttribLocation 
    glLinkProgram(programHandle); 
//FIXME:-----------DEBUG----------- 
printProgramInfoLog(programHandle); 
//-----------END-DEBUG----------- 
glUseProgram(programHandle); 
//FIXME:-----------DEBUG----------- 
printProgramInfoLog(programHandle); 
//-----------END-DEBUG----------- 


    checkOpenGLError(); 

    samplerUniformLocation = 
       glGetUniformLocation(programHandle, BALL_SAMPLER_NAME); 

    glUniform1f(samplerUniformLocation, 0); 
    glActiveTexture(GL_TEXTURE0); 


    ball_texture_handle = loadTexture(BALL_IMAGE_PATH); 




    //bind it in initialization because we're only using 
    //1 texture in the program 
    glBindTexture(GL_TEXTURE_2D, ball_texture_handle); 
} 

这里的loadTexture功能:

GLuint BallGLWidget::loadTexture(const char* filenamePtr) 
{ 
    //create & prepare a temporary texture handle that will be copied to 
    //DesktopMain::ball_texture_handle after this function returns 
    GLuint texHandle; 
    glGenTextures(1, &texHandle); 
    glBindTexture(GL_TEXTURE_2D, texHandle); 

    QImage* img = new QImage(); 
    if(!img->load(filenamePtr)) 
    { 
     //error loading image, handle error 
     cerr << "ERROR LOADING TEXTURE" << endl; 
    } 


    //This is the Qt way- its commented out for conventional OpenGL code 
    //bind the texture to the current context 
    //GLuint texHandle = bindTexture(*img); 

    GLenum openglImageFormat; 
    QImage::Format imgFormat = img->format(); 
    switch(imgFormat) 
    { 
    case QImage::Format_RGB32: 
     openglImageFormat = GL_RGB; 

     cout << "Image format is GL_RGB" << endl; 
     break; 
    case QImage::Format_ARGB32: 
     openglImageFormat = GL_RGBA; 

     cout << "Image format is GL_RGBA" << endl; 
     break; 
    //handle this case the same as ARGB32 
    case QImage::Format_ARGB32_Premultiplied: 
     openglImageFormat = GL_RGBA; 

     cout << "Image format is GL_RGBA (premultiplied)" << endl; 
     break; 
    case QImage::Format_Invalid: 
     cerr << "ERROR: INVALID IMAGE FORMAT" << endl; 
     return -1; 
     break; 
    default: 
     cerr << "ERROR: UNRECOGNIZED IMAGE FORMT" << endl; 
     return -1; 
     break; 
    } 

    //use tightly packed pixel values 
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 

    //use linear filtering 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 
      img->width(), img->height(), 0, openglImageFormat, 
      GL_UNSIGNED_BYTE, img->bits()); 

    cerr << "Checking textures..." << endl; 
    checkOpenGLError(); 

    delete img; 

    return texHandle; 
} 

顶点着色器:

attribute vec2 a_v_position; 
attribute vec2 a_tex_position; 

varying vec2 tex_coord_output; 


void main() 
{ 
    //copy attributes to varyings for use in the frag shader 
    tex_coord_output = a_tex_position; 

    gl_Position = vec4(a_v_position, 0.0, 1.0); 
} 

片段着色器:

varying vec2 tex_coord_output; 

uniform sampler2D ballsampler; 

void main() 
{ 
    gl_FragColor = texture2D(ballsampler, tex_coord_output); 
} 

编辑:

该程序的屏幕截图,根据要求。

https://docs.google.com/open?id=0B8xCefwW3X4TY2Y3N2M0MGYtMDQ0NS00MDk4LWEzODgtNDc3OWFkODI3ZWE3

编辑:

属性的位置是了,因为显然glBindAttribLocation只有工作,如果调用之前的程序对象链接(http://www.opengl.org/sdk/docs/man/ XHTML/glBindAttribLocation.xml)。我改变了上面的代码据此,但该计划仍然看起来像下面(还有与纹理一个问题...):

我得到以下结果: https://docs.google.com/open?id=0B8xCefwW3X4TNWE0YTQ5MTktZTA2Yy00YmI4LWJmMjMtYTlhOTYxMGNkMTk0

+1

你调用glTexImage2D()指定为GL_RGB的内部格式,但后来上面的代码中说,它可能是格式的RGBA图像。这两个必须匹配。如果您的图像有4个通道,则内部格式需要为GL_RGBA(或其他4通道格式)。 – user1118321 2012-01-08 01:42:07

+0

谢谢 - 这可能是解决方案的一部分,但它没有解决它。我仍然遇到同样的问题 – Prime 2012-01-08 02:17:16

+0

顶点/片段着色器将有助于理解。他们编译的事实并没有多大帮助。另外,该问题的屏幕截图也有助于确定解决方案。 – 2012-01-08 08:45:40

回答

0

分解,试一下简单:

vert.glsl

#version 120 

uniform mat4 projection; 
uniform mat4 modelview; 

attribute vec2 position; 
attribute vec2 texcoord; 

varying vec2 fragTexCoord; 

void main(void) 
{ 
    fragTexCoord = texcoord; 
    gl_Position = projection * modelview * vec4(position, 0.0, 1.0); 
} 

frag.glsl

#version 120 

uniform sampler2D texture; 

varying vec2 fragTexCoord; 

void main(void) 
{  
    gl_FragColor = texture2D(texture, fragTexCoord);  
} 

的main.cpp

#include <GL/glew.h> 
#include <GL/glut.h> 

#include <cstdlib> 
#include <stdexcept> 
#include <iostream> 
#include <fstream> 
#include <sstream> 
#include <vector> 

using namespace std; 


GLuint CreateShader(const GLenum& aShaderType, const string& aShaderSource) 
{ 
    GLuint shader = glCreateShader(aShaderType); 

    const GLchar* shaderString = aShaderSource.c_str(); 
    GLint shaderLength = aShaderSource.size(); 
    glShaderSource(shader, 1, &shaderString, &shaderLength); 

    glCompileShader(shader); 

    GLint compiled; 
    glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);  
    if(GL_FALSE == compiled) 
    { 
     // compile failure, dump log 
     GLint loglen; 
     glGetShaderiv(shader, GL_INFO_LOG_LENGTH , &loglen); 

     vector<char> log(loglen); 
     glGetShaderInfoLog(shader, loglen, NULL, &log[0]); 

     string type; 
     switch(aShaderType) 
     { 
      case GL_VERTEX_SHADER:  type = "GL_VERTEX_SHADER";  break; 
      case GL_FRAGMENT_SHADER: type = "GL_FRAGMENT_SHADER"; break; 
      default:     type = "UNKNOWN SHADER";  break; 
     } 

     stringstream err; 
     err << "*** " << type << " ***" << endl; 
     err << aShaderSource; 
     err << "*** Compilation Log ***" << endl; 
     err << string(log.begin(), log.end()); 

     throw std::logic_error(err.str());   
    } 

    return shader; 
} 


GLuint CreateProgram(const string& aVertexShader, const string& aFragmentShader) 
{ 
    GLuint vert = CreateShader(GL_VERTEX_SHADER, aVertexShader); 
    GLuint frag = CreateShader(GL_FRAGMENT_SHADER, aFragmentShader); 

    GLuint program = glCreateProgram(); 
    glAttachShader(program, vert); 
    glAttachShader(program, frag); 
    glLinkProgram(program); 

    glDeleteShader(vert); 
    glDeleteShader(frag); 

    GLint linked; 
    glGetProgramiv(program, GL_LINK_STATUS, &linked);  
    if(GL_FALSE == linked) 
    { 
     // link failure, dump log 
     GLint loglen; 
     glGetProgramiv(program, GL_INFO_LOG_LENGTH , &loglen); 

     vector<char> log(loglen); 
     glGetProgramInfoLog(program, loglen, NULL, &log[0]); 

     stringstream err; 
     err << "*** Link log ***" << endl; 
     err << string(log.begin(), log.end()); 
     throw std::logic_error(err.str());   
    } 

    return program; 
} 


string LoadFile(const string& filename) 
{ 
    ifstream infile(filename.c_str(), ios::binary); 
    istreambuf_iterator<char> begin(infile), end; 
    return string(begin, end); 
} 


GLuint prog = 0; 
GLuint tex = 0; 
void init() 
{ 
    GLenum glewError = glewInit(); 
    if(GLEW_OK != glewError) 
    { 
     stringstream err; 
     err << "GLEW error: " << glewGetErrorString(glewError) << endl; 
     throw std::logic_error(err.str());  
    }  

    cout << "GLEW_VERSION : " << glewGetString(GLEW_VERSION) << endl; 
    cout << "GL_VERSION : " << glGetString(GL_VERSION) << endl; 
    cout << "GLSL VERSION : " << glGetString(GL_SHADING_LANGUAGE_VERSION) << endl; 
    cout << "GL_VENDOR : " << glGetString(GL_VENDOR) << endl; 
    cout << "GL_RENDERER : " << glGetString(GL_RENDERER) << endl;  

    if(!GLEW_VERSION_2_1) 
    { 
     stringstream err; 
     err << "OpenGL 2.1 or better required for GLSL support." << endl; 
     throw std::logic_error(err.str()); 
    } 

    // load shaders 
    string vert = LoadFile("vert.glsl"); 
    string frag = LoadFile("frag.glsl"); 
    prog = CreateProgram(vert, frag); 

    // create random texture 
    const unsigned int width = 32; 
    const unsigned int height = 32; 
    const unsigned int channels = 3; 
    unsigned char buffer[ width * height * channels ]; 
    for(unsigned int i = 0; i < width * height; ++i) 
    { 
     buffer[i*channels + 0] = rand()%255; 
     buffer[i*channels + 1] = rand()%255; 
     buffer[i*channels + 2] = rand()%255; 
    } 

    // upload texture data 
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 
    glGenTextures(1, &tex); 
    glBindTexture(GL_TEXTURE_2D, tex); 
    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_NEAREST); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
    glTexImage2D(GL_TEXTURE_2D, 0, channels, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer); 
} 


struct Vertex 
{ 
    Vertex() : x(0), y(0), s(0), t(0) {} 
    Vertex(float _x, float _y, float _s, float _t) : x(_x), y(_y), s(_s), t(_t) {} 
    float x, y; 
    float s, t; 
}; 

void display() 
{ 
    static float currentTime = glutGet(GLUT_ELAPSED_TIME)/1000.0f; 
    float newTime = glutGet(GLUT_ELAPSED_TIME)/1000.0f; 
    float frameTime = newTime - currentTime; 
    currentTime = newTime; 

    vector<Vertex> verts; 
    verts.push_back(Vertex(-1, -1, 0, 0)); 
    verts.push_back(Vertex( 1, -1, 1, 0)); 
    verts.push_back(Vertex( 1, 1, 1, 1)); 
    verts.push_back(Vertex(-1, 1, 0, 1)); 

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 

    static float angle = 0; 
    angle += 60 * frameTime; 
    glRotatef(angle, 0, 0, 1); 
    glScalef(5, 5, 5); 

    glUseProgram(prog); 

    // load uniforms 
    GLfloat projection[16]; 
    glGetFloatv(GL_PROJECTION_MATRIX, projection); 
    GLint projection_loc = glGetUniformLocation(prog, "projection"); 
    glUniformMatrix4fv(projection_loc, 1, GL_FALSE, projection); 

    GLfloat modelview[16]; 
    glGetFloatv(GL_MODELVIEW_MATRIX, modelview); 
    GLint modelview_loc = glGetUniformLocation(prog, "modelview"); 
    glUniformMatrix4fv(modelview_loc, 1, GL_FALSE, modelview); 

    GLint texture_loc = glGetUniformLocation(prog, "texture"); 
    glUniform1i(texture_loc, 0);  
    glActiveTexture(GL_TEXTURE0); 
    glBindTexture(GL_TEXTURE_2D, tex); 

    // load attributes 
    GLint position_loc = glGetAttribLocation(prog, "position"); 
    glVertexAttribPointer(position_loc, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), &verts[0].x); 
    glEnableVertexAttribArray(position_loc); 

    GLint texcoord_loc = glGetAttribLocation(prog, "texcoord"); 
    glVertexAttribPointer(texcoord_loc, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), &verts[0].s); 
    glEnableVertexAttribArray(texcoord_loc); 

    // render 
    glDrawArrays(GL_QUADS, 0, verts.size()); 

    glDisableVertexAttribArray(position_loc); 
    glDisableVertexAttribArray(texcoord_loc); 

    glutSwapBuffers(); 
} 


void reshape(int w, int h) 
{ 
    glViewport(0, 0, w, h); 

    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    double aspect = (double)w/(double)h; 
    glOrtho(-10*aspect, 10*aspect, -10, 10, -1, 1); 
} 


int main(int argc, char **argv) 
{ 
    glutInit(&argc, argv); 
    glutInitWindowSize(800,600); 
    glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE); 
    glutCreateWindow("GLSL"); 

    try 
    { 
     init(); 
    } 
    catch(std::exception& e) 
    { 
     cout << "Init failure: " << endl << e.what() << endl; 
     return EXIT_FAILURE; 
    } 

    glutDisplayFunc(display); 
    glutIdleFunc(display); 
    glutReshapeFunc(reshape); 
    glutMainLoop(); 
    return EXIT_SUCCESS; 
} 
+0

请问您能解释一下在我自己的代码中究竟是什么问题,或者究竟要改变什么? – Prime 2012-01-11 09:26:44

+2

@dragonwrenn:你能发布你的完整代码吗? – genpfault 2012-01-13 19:11:23