/
Shader.cpp
119 lines (96 loc) · 3.02 KB
/
Shader.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
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
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
110
111
112
113
114
115
116
117
118
/*
tdogl::Shader
Copyright 2012 Thomas Dalling - http://tomdalling.com/
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "Shader.h"
#include <stdexcept>
#include <fstream>
#include <string>
#include <cassert>
#include <sstream>
using namespace tdogl;
Shader::Shader(const std::string& shaderCode, GLenum shaderType) :
_object(0),
_refCount(NULL)
{
//create the shader object
_object = glCreateShader(shaderType);
if(_object == 0)
throw std::runtime_error("glCreateShader failed");
//set the source code
const char* code = shaderCode.c_str();
glShaderSource(_object, 1, (const GLchar**)&code, NULL);
//compile
glCompileShader(_object);
//throw exception if compile error occurred
GLint status;
glGetShaderiv(_object, GL_COMPILE_STATUS, &status);
if (status == GL_FALSE) {
std::string msg("Compile failure in shader:\n");
GLint infoLogLength;
glGetShaderiv(_object, GL_INFO_LOG_LENGTH, &infoLogLength);
char* strInfoLog = new char[infoLogLength + 1];
glGetShaderInfoLog(_object, infoLogLength, NULL, strInfoLog);
msg += strInfoLog;
delete[] strInfoLog;
glDeleteShader(_object); _object = 0;
throw std::runtime_error(msg);
}
_refCount = new unsigned;
*_refCount = 1;
}
Shader::Shader(const Shader& other) :
_object(other._object),
_refCount(other._refCount)
{
_retain();
}
Shader::~Shader() {
//_refCount will be NULL if constructor failed and threw an exception
if(_refCount) _release();
}
GLuint Shader::object() const {
return _object;
}
Shader& Shader::operator = (const Shader& other) {
_release();
_object = other._object;
_refCount = other._refCount;
_retain();
return *this;
}
Shader Shader::shaderFromFile(const std::string& filePath, GLenum shaderType) {
//open file
std::ifstream f;
f.open(filePath.c_str(), std::ios::in | std::ios::binary);
if(!f.is_open()){
throw std::runtime_error(std::string("Failed to open file: ") + filePath);
}
//read whole file into stringstream buffer
std::stringstream buffer;
buffer << f.rdbuf();
//return new shader
Shader shader(buffer.str(), shaderType);
return shader;
}
void Shader::_retain() {
assert(_refCount);
*_refCount += 1;
}
void Shader::_release() {
assert(_refCount && *_refCount > 0);
*_refCount -= 1;
if(*_refCount == 0){
glDeleteShader(_object); _object = 0;
delete _refCount; _refCount = NULL;
}
}