ShaderProgram.cc 2.78 KB
Newer Older
Robert Menzel's avatar
Robert Menzel committed
1
2
3
4
5
////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2011, Computer Graphics Group RWTH Aachen University         //
// All rights reserved.                                                       //
////////////////////////////////////////////////////////////////////////////////

Robert Menzel's avatar
Robert Menzel committed
6
#include <ACGL/OpenGL/Objects/ShaderProgram.hh>
7
#include <ACGL/OpenGL/Objects/VertexArrayObject.hh>
Robert Menzel's avatar
Robert Menzel committed
8
#include <ACGL/OpenGL/Tools.hh>
Robert Menzel's avatar
Robert Menzel committed
9

Robert Menzel's avatar
Robert Menzel committed
10
11
using namespace ACGL::OpenGL;
using namespace ACGL::Base;
Robert Menzel's avatar
Robert Menzel committed
12
13
14
15
using namespace ACGL::Utils;

bool ShaderProgram::link(void) const
{
16
    glLinkProgram(mObjectName);
Robert Menzel's avatar
Robert Menzel committed
17

18
#ifdef ACGL_CHECK_CRITICAL_GL_ERRORS
Robert Menzel's avatar
Robert Menzel committed
19
20
    if ( openGLRareErrorOccured() )
    {
21
22
        // it's uncommon that glLinkProgram creates errors,
        // linking errors create no gl errors but a GL_LINK_STATUS of GL_FALSE
Robert Menzel's avatar
Robert Menzel committed
23
24
25
        return false;
    }

26
27
    // check for program link errors:
    GLint programError;
28
    glGetProgramiv(mObjectName, GL_LINK_STATUS, &programError);
Robert Menzel's avatar
Robert Menzel committed
29

30
    if (programError != GL_TRUE)
Robert Menzel's avatar
Robert Menzel committed
31
32
    {
        // yes, errors :-(
33
34
35
36
        error() << "Program could not get linked:" << std::endl;
    }

    GLsizei length = 0;
37
    glGetProgramiv(mObjectName, GL_INFO_LOG_LENGTH, &length);
38
39
40
41
    if (length > 1)
    {
        // error log or warnings:
        GLchar* pInfo = new char[length + 1];
42
        glGetProgramInfoLog(mObjectName,  length, &length, pInfo);
43
44
45
46
        openGLRareError();
        warning() << "Linker log: " << std::string(pInfo) << std::endl;
        delete[] pInfo;
        return (programError == GL_TRUE); // if the log contains only warnings we return true
Robert Menzel's avatar
Robert Menzel committed
47
    }
48
#endif
Robert Menzel's avatar
Robert Menzel committed
49
50
    return true;
}
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80

void ShaderProgram::setAttributeLocationsByVAO( const SharedVertexArrayObject& _vao )
{
    bool needsRelink = false;

    // search through all attributes of _vao
    VertexArrayObject::AttributeVec vaoAttributes = _vao->getAttributes();
    for(VertexArrayObject::AttributeVec::size_type i = 0; i < vaoAttributes.size(); ++i)
    {
        if(vaoAttributes[i].location == -1)
            continue;

        // find the name of the current attribute in its ArrayBuffer
        std::string arrayBufferAttributeName = vaoAttributes[i].arrayBuffer->getAttributes()[vaoAttributes[i].attributeID].name;

        // find out whether an attribute with a matching name exists in this ShaderProgram
        GLint attribLocation = getAttributeLocation(arrayBufferAttributeName);
        if(attribLocation != -1                         // attribute with that name exists?
        && attribLocation != vaoAttributes[i].location) // attribute with that name not already bound correctly?
        {
            bindAttributeLocation(arrayBufferAttributeName, vaoAttributes[i].location);

            needsRelink = true;
        }
    }

    // re-link the program only if necessary
    if(needsRelink)
        link();
}