1 /*
2 This Source Code Form is subject to the terms of the Mozilla Public
3 License, v. 2.0. If a copy of the MPL was not distributed with this
4 file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 */
6
7 #include "shader.h"
8
9
10 namespace PatateCommon
11 {
12
13
14 static const char* pVSName = "VS";
15 static const char* pTessCSName = "TessCS";
16 static const char* pTessESName = "TessES";
17 static const char* pGSName = "GS";
18 static const char* pFSName = "FS";
19
ShaderType2ShaderName(GLuint _Type)20 inline const char* ShaderType2ShaderName(GLuint _Type)
21 {
22 switch (_Type)
23 {
24 case GL_VERTEX_SHADER:
25 return pVSName;
26 case GL_TESS_CONTROL_SHADER:
27 return pTessCSName;
28 case GL_TESS_EVALUATION_SHADER:
29 return pTessESName;
30 case GL_GEOMETRY_SHADER:
31 return pGSName;
32 case GL_FRAGMENT_SHADER:
33 return pFSName;
34 default:
35 assert(0);
36 }
37
38 return NULL;
39 }
40
Shader()41 Shader::Shader()
42 : m_shaderProg(0), m_status(UNINITIALIZED)
43 {
44 }
45
46
~Shader()47 Shader::~Shader()
48 {
49 if(getShaderId())
50 {
51 destroy();
52 }
53 }
54
55
create()56 bool Shader::create()
57 {
58 m_shaderProg = glCreateProgram();
59
60 if (m_shaderProg == 0)
61 {
62 fprintf(stderr, "Error creating shader program\n");
63 return false;
64 }
65
66 m_status = NOT_COMPILED;
67 return true;
68 }
69
70
destroy()71 void Shader::destroy()
72 {
73 PATATE_ASSERT_NO_GL_ERROR();
74
75 glDeleteProgram(m_shaderProg);
76
77 if(glGetError() == GL_NO_ERROR)
78 m_shaderProg = 0;
79 m_status = UNINITIALIZED;
80 }
81
82
use()83 void Shader::use()
84 {
85 glUseProgram(m_shaderProg);
86 }
87
88
setGLSLVersionHeader(const std::string & header)89 void Shader::setGLSLVersionHeader(const std::string& header)
90 {
91 m_versionHeader = header;
92 }
93
94
addShader(GLenum _ShaderType,const char * _pShaderText)95 bool Shader::addShader(GLenum _ShaderType, const char* _pShaderText)
96 {
97 PATATE_ASSERT_NO_GL_ERROR();
98
99 GLuint ShaderObj = glCreateShader(_ShaderType);
100
101 if (ShaderObj == 0)
102 {
103 fprintf(stderr, "Error creating shader type %d\n", _ShaderType);
104 return false;
105 }
106
107 m_shaderObjList.push_back(ShaderObj);
108
109 const GLchar* p[2];
110 p[0] = m_versionHeader.empty()? 0: &m_versionHeader[0];
111 p[1] = _pShaderText;
112 GLint Lengths[2];
113 Lengths[0] = m_versionHeader.size();
114 Lengths[1] = strlen(_pShaderText);
115 glShaderSource(ShaderObj, 2, p, Lengths);
116
117 glCompileShader(ShaderObj);
118
119 GLint success;
120 glGetShaderiv(ShaderObj, GL_COMPILE_STATUS, &success);
121
122 if (!success)
123 {
124 GLchar InfoLog[1024];
125 glGetShaderInfoLog(ShaderObj, 1024, NULL, InfoLog);
126 fprintf(stderr, "Error compiling %s: '%s'\n", ShaderType2ShaderName(_ShaderType), InfoLog);
127 return false;
128 }
129
130 glAttachShader(m_shaderProg, ShaderObj);
131
132 return glGetError() == GL_NO_ERROR;
133 }
134
135
addShaderFromFile(GLenum _ShaderType,const char * _pFilename)136 bool Shader::addShaderFromFile(GLenum _ShaderType, const char* _pFilename)
137 {
138 FILE* fp;
139 size_t filesize;
140 char* pShaderText;
141
142 fp = fopen(_pFilename, "rb");
143
144 if(!fp)
145 {
146 return 0;
147 }
148
149 fseek(fp, 0, SEEK_END);
150 filesize = ftell(fp);
151 fseek(fp, 0, SEEK_SET);
152
153 pShaderText = new char[filesize + 1];
154 if(!pShaderText)
155 {
156 return 0;
157 }
158
159 fread(pShaderText, 1, filesize, fp);
160 pShaderText[filesize] = 0;
161 fclose(fp);
162
163 bool res = addShader(_ShaderType, pShaderText);
164
165 delete [] pShaderText;
166
167 return res;
168 }
169
170
clearShaderList()171 void Shader::clearShaderList()
172 {
173 for (ShaderObjList::iterator it = m_shaderObjList.begin() ; it != m_shaderObjList.end() ; it++)
174 {
175 glDetachShader(m_shaderProg, *it);
176 glDeleteShader(*it);
177 }
178 m_shaderObjList.clear();
179 }
180
181
finalize()182 bool Shader::finalize()
183 {
184 PATATE_ASSERT_NO_GL_ERROR();
185
186 GLint Success = 0;
187 GLchar ErrorLog[1024] = { 0 };
188
189 m_status = COMPILATION_FAILED;
190
191 glLinkProgram(m_shaderProg);
192
193 glGetProgramiv(m_shaderProg, GL_LINK_STATUS, &Success);
194 if (Success == 0)
195 {
196 glGetProgramInfoLog(m_shaderProg, sizeof(ErrorLog), NULL, ErrorLog);
197 fprintf(stderr, "Error linking shader program: '%s'\n", ErrorLog);
198 return false;
199 }
200
201 glValidateProgram(m_shaderProg);
202 glGetProgramiv(m_shaderProg, GL_VALIDATE_STATUS, &Success);
203 if (!Success)
204 {
205 glGetProgramInfoLog(m_shaderProg, sizeof(ErrorLog), NULL, ErrorLog);
206 fprintf(stderr, "Invalid shader program: '%s'\n", ErrorLog);
207 return false;
208 }
209
210 if(glGetError() == GL_NO_ERROR)
211 {
212 clearShaderList();
213 m_status = COMPILATION_SUCCESSFULL;
214 }
215
216 return m_status == COMPILATION_SUCCESSFULL;
217 }
218
219
bindAttributeLocation(const char * name,unsigned location)220 void Shader::bindAttributeLocation(const char* name, unsigned location)
221 {
222 glBindAttribLocation(m_shaderProg, location, name);
223 }
224
225
getUniformLocation(const char * _pUniformName)226 GLint Shader::getUniformLocation(const char* _pUniformName)
227 {
228 GLint location = glGetUniformLocation(m_shaderProg, _pUniformName);
229
230 if (location < 0)
231 {
232 fprintf(stderr, "Warning! Unable to get the location of uniform '%s'\n", _pUniformName);
233 }
234
235 return location;
236 }
237
getProgramParam(GLint _param)238 GLint Shader::getProgramParam(GLint _param)
239 {
240 GLint ret;
241 glGetProgramiv(m_shaderProg, _param, &ret);
242 return ret;
243 }
244
245
246 }
247