OpenGL Текстурирующая Мусор - PullRequest
0 голосов
/ 08 января 2012

У меня проблема с текстурированием - он корректно загружает изображение, но выводит мусор на геометрию. Сама геометрия хорошо рисует (простой треугольник), но независимо от того, какую текстуру я загружаю, она просто плюет случайные узоры на треугольник.

Я использую 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);
}

EDIT:

Скриншот программы по запросу.

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

EDIT:

Расположение атрибутов было отключено, потому что, очевидно, glBindAttribLocation работает только в том случае, если вызывается ДО связывания программного объекта (http://www.opengl.org/sdk/docs/man/xhtml/glBindAttribLocation.xml). Я соответственно изменил код выше, но программа все равно выглядит ниже (проблема с текстурированием по-прежнему есть). .):

Я получаю следующий результат: https://docs.google.com/open?id=0B8xCefwW3X4TNWE0YTQ5MTktZTA2Yy00YmI4LWJmMjMtYTlhOTYxMGNkMTk0

1 Ответ

0 голосов
/ 10 января 2012

Разбейте его, попробуйте что-нибудь простое:

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