OpenGL纹理垃圾



我在纹理处理方面遇到了问题——它正确地加载了图像,但在几何体上渲染了垃圾。几何体本身绘制得很好(一个简单的三角形),但无论我加载哪种纹理,它都只是在三角形上吐出随机图案。

我在Mac OS X上使用g++4.2.1,带有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

分解它,尝试一些简单的东西:

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

相关内容

  • 没有找到相关文章

最新更新