Shader.cc 4.82 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
9
#include <ACGL/OpenGL/Objects/Shader.hh>
#include <ACGL/OpenGL/Tools.hh>
#include <ACGL/Base/StringOperations.hh>
Robert Menzel's avatar
Robert Menzel committed
10
11
12
13

#include <iostream>
#include <fstream>

Robert Menzel's avatar
Robert Menzel committed
14
using namespace ACGL::Base;
Robert Menzel's avatar
Robert Menzel committed
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
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

bool Shader::setFromFile(const std::string& _filename)
{
    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;
    }
    
40
41
42
43
44
45
46
47
48
49
50
51
52
    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
53
54
}

55
bool Shader::setSource(const std::string& _source, bool _checkForCompileErrors)
Robert Menzel's avatar
Robert Menzel committed
56
{
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
    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
76
77
}

78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
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
110
{
111
    glCompileShader(mObjectName);
Robert Menzel's avatar
Robert Menzel committed
112
    
113
114
115
116
117
#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
118
    {
119
        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
120
121
        return false;
    }
122
123
124
#endif
    return true;
}
Robert Menzel's avatar
Robert Menzel committed
125

126
127
void Shader::getCompileLog( std::string &_log, bool &_wasErrorLog ) const
{
Robert Menzel's avatar
Robert Menzel committed
128
129
    // check for shader compile errors:
    GLint shaderError;
130
    glGetShaderiv(mObjectName, GL_COMPILE_STATUS, &shaderError);
Robert Menzel's avatar
Robert Menzel committed
131
132
133
    if(shaderError != GL_TRUE)
    {
        // yes, errors
134
135
136
        _wasErrorLog = true;
    } else {
        _wasErrorLog = false;
Robert Menzel's avatar
Robert Menzel committed
137
138
    }

139
    // the log could be warnings:
Robert Menzel's avatar
Robert Menzel committed
140
    GLsizei length = 0;
141
    glGetShaderiv(mObjectName, GL_INFO_LOG_LENGTH, &length);
142
    if(length > 1) // null terminated, so 1 could also be empty
Robert Menzel's avatar
Robert Menzel committed
143
144
    {
        // a compile log can get produced even if there were no errors, but warnings!
145
        GLchar* pInfo = new char[length];
146
        glGetShaderInfoLog(mObjectName,  length, &length, pInfo);
147
148
        //error() << "Compile log: " << std::string(pInfo) << std::endl;
        _log = std::string( pInfo );
Robert Menzel's avatar
Robert Menzel committed
149
        delete[] pInfo;
150
151
    } else {
        _log = "";
Robert Menzel's avatar
Robert Menzel committed
152
153
    }
}