Shader.cc 5.24 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
{
Philip Trettner's avatar
Philip Trettner committed
58
59
    assert(_sp->getSources().size() > 0); // did you forget to call _sp->parse(...)?

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

75
bool Shader::setSource(const std::string& _source, bool _checkForCompileErrors)
Robert Menzel's avatar
Robert Menzel committed
76
{
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
    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
96
97
}

98
99
bool Shader::setSources(const std::vector<std::string> &_sources, bool _checkForCompileErrors )
{
100
    unsigned int numberOfStrings = (unsigned int) _sources.size();
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
128
129
    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
130
{
131
    glCompileShader(mObjectName);
132
133
    return true;
}
Robert Menzel's avatar
Robert Menzel committed
134

135
136
void Shader::getCompileLog( std::string &_log, bool &_wasErrorLog ) const
{
Robert Menzel's avatar
Robert Menzel committed
137
138
    // check for shader compile errors:
    GLint shaderError;
139
    glGetShaderiv(mObjectName, GL_COMPILE_STATUS, &shaderError);
Robert Menzel's avatar
Robert Menzel committed
140
141
142
    if(shaderError != GL_TRUE)
    {
        // yes, errors
143
144
145
        _wasErrorLog = true;
    } else {
        _wasErrorLog = false;
Robert Menzel's avatar
Robert Menzel committed
146
147
    }

148
    // the log could be warnings:
Robert Menzel's avatar
Robert Menzel committed
149
    GLsizei length = 0;
150
    glGetShaderiv(mObjectName, GL_INFO_LOG_LENGTH, &length);
151
    if(length > 1) // null terminated, so 1 could also be empty
Robert Menzel's avatar
Robert Menzel committed
152
153
    {
        // a compile log can get produced even if there were no errors, but warnings!
154
        GLchar* pInfo = new char[length];
155
        glGetShaderInfoLog(mObjectName,  length, &length, pInfo);
156
157
        //error() << "Compile log: " << std::string(pInfo) << std::endl;
        _log = std::string( pInfo );
Robert Menzel's avatar
Robert Menzel committed
158
        delete[] pInfo;
159
160
    } else {
        _log = "";
Robert Menzel's avatar
Robert Menzel committed
161
162
    }
}