Shader.cc 5.51 KB
Newer Older
1
2
3
4
5
/***********************************************************************
 * Copyright 2011-2012 Computer Graphics Group RWTH Aachen University. *
 * All rights reserved.                                                *
 * Distributed under the terms of the MIT License (see LICENSE.TXT).   *
 **********************************************************************/
Robert Menzel's avatar
Robert Menzel committed
6

Robert Menzel's avatar
Robert Menzel committed
7
8
#include <ACGL/OpenGL/Objects/Shader.hh>
#include <ACGL/OpenGL/Tools.hh>
9
#include <ACGL/Utils/StringHelpers.hh>
Robert Menzel's avatar
Robert Menzel committed
10
11
12

#include <iostream>
#include <fstream>
13
#include <algorithm>
Robert Menzel's avatar
Robert Menzel committed
14
15

using namespace ACGL::Utils;
Robert Menzel's avatar
Robert Menzel committed
16
using namespace ACGL::OpenGL;
Robert Menzel's avatar
Robert Menzel committed
17

18
19

bool Shader::setFromFileNoImportParsing(const std::string& _filename)
Robert Menzel's avatar
Robert Menzel committed
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
{
    std::string line = "";
    std::string fileContent = "";
    
    std::ifstream fileStream(_filename.c_str(), std::ifstream::in);
    
    if(fileStream.is_open())
    {
        while (fileStream.good())
        {
            std::getline(fileStream,line);
            fileContent += line + "\n";
        }
        fileStream.close();
    }
    else
    {
        error() << "Failed to open file: " << _filename << std::endl;
        return false;
    }
    
41
42
43
44
45
46
47
48
49
50
51
52
53
    bool compileErrors = true;
    if ( setSource(fileContent, false) ) { // don't check for errors, we will do that on our own:
        std::string compileLog;
        getCompileLog( compileLog, compileErrors );
        if (compileLog.size() > 0) {
            if (compileErrors) {
                error() << "\nIn file: " << _filename << ": \n" << compileLog << "\n" << std::endl;
            } else {
                warning() << "\nIn file: " << _filename << ": \n" << compileLog << "\n" << std::endl;
            }
        }
    }
    return !compileErrors; // return true iff there were no errors
Robert Menzel's avatar
Robert Menzel committed
54
55
}

56
bool Shader::setFromFile(SharedShaderParser const& _sp)
57
58
{
    bool compileErrors = true;
59
    if ( setSources( _sp->getSources(), false) ) { // don't check for errors, we will do that on our own:
60
61
62
63
        std::string compileLog;
        getCompileLog( compileLog, compileErrors );
        if (compileLog.size() > 0) {
            if (compileErrors) {
64
                error() << "\nIn files: \n" << _sp->getFileNamesPrintable() << compileLog << "\n" << std::endl;
65
            } else {
66
                warning() << "\nIn files: \n" << _sp->getFileNamesPrintable() << compileLog << "\n" << std::endl;
67
68
69
70
71
72
            }
        }
    }
    return !compileErrors; // return true iff there were no errors
}

73
bool Shader::setSource(const std::string& _source, bool _checkForCompileErrors)
Robert Menzel's avatar
Robert Menzel committed
74
{
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
    const char *pProgramString = _source.c_str();
    glShaderSource(mObjectName, 1, &pProgramString, NULL); // can't create OpenGL errors
    if (!compile()) {
        return false;
    }
    // the compile call should work even if there are compile errors itself:
    bool compileErrors = false;
    if (_checkForCompileErrors) {
        std::string compileLog;
        getCompileLog( compileLog, compileErrors );
        if (compileLog.size() > 0) {
            if (compileErrors) {
                error() << compileLog << std::endl;
            } else {
                warning() << compileLog << std::endl;
            }
        }
    }
    return !compileErrors; // return true iff there were NO errors
Robert Menzel's avatar
Robert Menzel committed
94
95
}

96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
bool Shader::setSources(const std::vector<std::string> &_sources, bool _checkForCompileErrors )
{
    unsigned int numberOfStrings = _sources.size();
    const char **pProgramStrings = new const char*[ numberOfStrings ];

    for (unsigned int i = 0; i < numberOfStrings; ++i) {
        pProgramStrings[i] = _sources[i].c_str();
    }

    glShaderSource(mObjectName, numberOfStrings, pProgramStrings, NULL); // can't create OpenGL errors
    delete[] pProgramStrings;

    if (!compile()) {
        return false;
    }
    // the compile call should work even if there are compile errors itself:
    bool compileErrors = false;
    if (_checkForCompileErrors) {
        std::string compileLog;
        getCompileLog( compileLog, compileErrors );
        if (compileLog.size() > 0) {
            if (compileErrors) {
                error() << compileLog << std::endl;
            } else {
                warning() << compileLog << std::endl;
            }
        }
    }
    return !compileErrors; // return true iff there were NO errors
}

bool Shader::compile() const
Robert Menzel's avatar
Robert Menzel committed
128
{
129
    glCompileShader(mObjectName);
Robert Menzel's avatar
Robert Menzel committed
130
    
131
132
133
134
135
#ifdef ACGL_CHECK_CRITICAL_GL_ERRORS
    // problems with the shader creation are always a bad thing...
    // from here on only error checks are performed:
    //
    if ( openGLRareErrorOccured() )
Robert Menzel's avatar
Robert Menzel committed
136
    {
137
        error() << "glCompileShader failed, that can only mean, that the object name used is not a valid shader object!" << std::endl;
Robert Menzel's avatar
Robert Menzel committed
138
139
        return false;
    }
140
141
142
#endif
    return true;
}
Robert Menzel's avatar
Robert Menzel committed
143

144
145
void Shader::getCompileLog( std::string &_log, bool &_wasErrorLog ) const
{
Robert Menzel's avatar
Robert Menzel committed
146
147
    // check for shader compile errors:
    GLint shaderError;
148
    glGetShaderiv(mObjectName, GL_COMPILE_STATUS, &shaderError);
Robert Menzel's avatar
Robert Menzel committed
149
150
151
    if(shaderError != GL_TRUE)
    {
        // yes, errors
152
153
154
        _wasErrorLog = true;
    } else {
        _wasErrorLog = false;
Robert Menzel's avatar
Robert Menzel committed
155
156
    }

157
    // the log could be warnings:
Robert Menzel's avatar
Robert Menzel committed
158
    GLsizei length = 0;
159
    glGetShaderiv(mObjectName, GL_INFO_LOG_LENGTH, &length);
160
    if(length > 1) // null terminated, so 1 could also be empty
Robert Menzel's avatar
Robert Menzel committed
161
162
    {
        // a compile log can get produced even if there were no errors, but warnings!
163
        GLchar* pInfo = new char[length];
164
        glGetShaderInfoLog(mObjectName,  length, &length, pInfo);
165
166
        //error() << "Compile log: " << std::string(pInfo) << std::endl;
        _log = std::string( pInfo );
Robert Menzel's avatar
Robert Menzel committed
167
        delete[] pInfo;
168
169
    } else {
        _log = "";
Robert Menzel's avatar
Robert Menzel committed
170
171
    }
}