ShaderProgram.cc 5.89 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>
8
#include <ACGL/OpenGL/Objects/FrameBufferObject.hh>
Robert Menzel's avatar
Robert Menzel committed
9
#include <ACGL/OpenGL/Tools.hh>
Robert Menzel's avatar
Robert Menzel committed
10

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

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

19
#ifdef ACGL_CHECK_CRITICAL_GL_ERRORS
Robert Menzel's avatar
Robert Menzel committed
20
21
    if ( openGLRareErrorOccured() )
    {
22
23
        // 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
24
25
26
        return false;
    }

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

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

    GLsizei length = 0;
38
    glGetProgramiv(mObjectName, GL_INFO_LOG_LENGTH, &length);
39
40
41
42
    if (length > 1)
    {
        // error log or warnings:
        GLchar* pInfo = new char[length + 1];
43
        glGetProgramInfoLog(mObjectName,  length, &length, pInfo);
44
45
46
47
        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
48
    }
49
#endif
Robert Menzel's avatar
Robert Menzel committed
50
51
    return true;
}
52

Robert Menzel's avatar
Robert Menzel committed
53
void ShaderProgram::setAttributeLocations(ConstSharedLocationMappings _locationMappings)
54
55
56
{
    bool needsRelink = false;

Robert Menzel's avatar
Robert Menzel committed
57
58
    // search through all attributes:
    LocationMappings::LocationMap locations = _locationMappings->getLocations();
59

Robert Menzel's avatar
Robert Menzel committed
60
61
62
63
64
65
    for(LocationMappings::LocationMap::iterator it = locations.begin();
        it != locations.end();
        ++it)
    {
        // find out whether a fragment data location with a matching name exists in this shader
        GLint attributeLocation = getAttributeLocation((*it).first);
66

Robert Menzel's avatar
Robert Menzel committed
67
68
        if (            attributeLocation  != -1            // attributeLocation with that name exists?
            && ((GLuint)attributeLocation) != (*it).second) // attributeLocation with that name not already bound correctly?
69
        {
Robert Menzel's avatar
Robert Menzel committed
70
            bindAttributeLocation((*it).first, (*it).second);
71
72
73
74
75
76
            needsRelink = true;
        }
    }

    // re-link the program only if necessary
    if(needsRelink)
77
78
79
80
81
82
    {
        link();
        openGLRareError();
    }
}

Robert Menzel's avatar
Robert Menzel committed
83
void ShaderProgram::setFragmentDataLocations(ConstSharedLocationMappings _locationMappings)
84
85
86
{
    bool needsRelink = false;

Robert Menzel's avatar
Robert Menzel committed
87
88
89
90
91
92
    // search through all color attachments:
    LocationMappings::LocationMap locations = _locationMappings->getLocations();

    for(LocationMappings::LocationMap::iterator it = locations.begin();
        it != locations.end();
        ++it)
93
94
    {
        // find out whether a fragment data location with a matching name exists in this shader
Robert Menzel's avatar
Robert Menzel committed
95
        GLint fragmentDataLocation = getFragmentDataLocation((*it).first);
96

Robert Menzel's avatar
Robert Menzel committed
97
98
99
100
        if (             fragmentDataLocation  != -1            // fragment data location with that name exists?
            && ((GLuint) fragmentDataLocation) != (*it).second) // fragment data location with that name not already bound correctly?
        {
            bindFragmentDataLocation((*it).first, (*it).second);
101
102
103
104
105
106
107
            needsRelink = true;
        }
    }

    // re-link the program only if necessary
    if(needsRelink)
    {
108
        link();
109
110
111
112
        openGLRareError();
    }
}

Robert Menzel's avatar
Robert Menzel committed
113
114
115
116


/*
void ShaderProgram::setAttributeLocationsByVAO(ConstSharedVertexArrayObject _vao)
117
{
Robert Menzel's avatar
Robert Menzel committed
118
    // TODO: deprecate
119

Robert Menzel's avatar
Robert Menzel committed
120
    bool needsRelink = false;
121

Robert Menzel's avatar
Robert Menzel committed
122
123
124
    // search through all attributes of _vao
    VertexArrayObject::AttributeVec vaoAttributes = _vao->getAttributes();
    for(VertexArrayObject::AttributeVec::size_type i = 0; i < vaoAttributes.size(); ++i)
125
    {
Robert Menzel's avatar
Robert Menzel committed
126
127
        if(vaoAttributes[i].location == -1)
            continue;
128

Robert Menzel's avatar
Robert Menzel committed
129
130
131
132
133
134
135
        // 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?
136
        {
Robert Menzel's avatar
Robert Menzel committed
137
            bindAttributeLocation(arrayBufferAttributeName, vaoAttributes[i].location);
138
139
140
141
142
143
144
145
146
147
148

            needsRelink = true;
        }
    }

    // re-link the program only if necessary
    if(needsRelink)
    {
        link();
        openGLRareError();
    }
Robert Menzel's avatar
Robert Menzel committed
149
150
151
}*/
/*
void ShaderProgram::setFragmentDataLocationsByFBO(ConstSharedFrameBufferObject _fbo)
152
{
Robert Menzel's avatar
Robert Menzel committed
153
154
    // TODO: deprecate

155
156
157
    bool needsRelink = false;

    // search through all color attachments of _fbo
Robert Menzel's avatar
Robert Menzel committed
158
159
    FrameBufferObject::AttachmentVec fboAttachments = _fbo->getColorAttachments();
    for(FrameBufferObject::AttachmentVec::size_type i = 0; i < fboAttachments.size(); ++i)
160
161
    {
        // find out whether a fragment data location with a matching name exists in this shader
Robert Menzel's avatar
Robert Menzel committed
162
163
164
        GLint fragmentDataLocation = getFragmentDataLocation(fboAttachments[i].name);
        if (   fragmentDataLocation != -1           // fragment data location with that name exists?
            && fragmentDataLocation !=  (GLint) i)  // fragment data location with that name not already bound correctly?
165
        {
Robert Menzel's avatar
Robert Menzel committed
166
            bindFragmentDataLocation(fboAttachments[i].name, i);
167
168
169
170
171
172
173
174
175
176
177

            needsRelink = true;
        }
    }

    // re-link the program only if necessary
    if(needsRelink)
    {
        link();
        openGLRareError();
    }
Robert Menzel's avatar
Robert Menzel committed
178
}*/