1 #include "Shader.h"
2 #include <fstream>
3 #include <string>
4 #include <iostream>
5
6
7
8
Allocate()9 bool GPU::Shader::PgObject::Allocate()
10 {
11 m_Id = glCreateShaderObjectARB( m_PgType );
12 return m_Id != 0;
13 }
14
15
Unallocate()16 bool GPU::Shader::PgObject::Unallocate()
17 {
18 glDeleteObjectARB( m_Id );
19 m_Id = 0;
20 return true;
21 }
22
23
CompileSrcFile(const std::string & filename,const GLenum pgType,std::string * logs)24 bool GPU::Shader::PgObject::CompileSrcFile( const std::string &filename,
25 const GLenum pgType,
26 std::string *logs )
27 {
28 // Open the source files.
29 std::ifstream file( filename.c_str(), std::ios::binary );
30 if( file.fail() )
31 return false;
32
33 // Map the content of the shader source file into a memory buffer.
34 file.seekg( 0, std::ios::end );
35 int fileSize = (int) file.tellg();
36 file.seekg( 0, std::ios::beg );
37
38 char *sourceString = new char [ fileSize+1 ];
39 file.read( sourceString, fileSize );
40 sourceString[ fileSize ] = '\0';
41
42 file.close();
43
44 // Create the shader object.
45 bool ok = CompileSrcString( sourceString, pgType, logs );
46
47 // Termination.
48 delete [] sourceString;
49 return ok;
50 }
51
52
CompileSrcString(const char * sourceString,const GLenum pgType,std::string * logs)53 bool GPU::Shader::PgObject::CompileSrcString( const char *sourceString,
54 const GLenum pgType,
55 std::string *logs )
56 {
57 // Ask for a free shader object name to OpenGL.
58 m_PgType = pgType;
59 if( Instantiate() )
60 {
61 // Create the shader object.
62 glShaderSourceARB ( m_Id, 1, (const GLcharARB**) &sourceString, NULL );
63 glCompileShaderARB( m_Id );
64
65 // Check the compilation status.
66 GLint status;
67 glGetObjectParameterivARB( m_Id, GL_OBJECT_COMPILE_STATUS_ARB, &status );
68
69 if( status )
70 return true;
71 else if( logs )
72 *logs = GPU::Shader::GetLogs( m_Id );
73
74 Release();
75 }
76
77 return false;
78 }
79
80
81
82
GetLogs(GLuint pgId)83 std::string GPU::Shader::GetLogs( GLuint pgId )
84 {
85 GLint logLength;
86 glGetObjectParameterivARB( pgId, GL_OBJECT_INFO_LOG_LENGTH_ARB, &logLength );
87
88 std::string infoLog;
89 infoLog.resize( logLength );
90 glGetInfoLogARB( pgId, logLength, &logLength, &infoLog[0] );
91
92 return infoLog;
93 }
94
95
RecoverActiveUniforms()96 void GPU::Shader::RecoverActiveUniforms()
97 {
98 m_Uniforms.clear();
99 m_Samplers.clear();
100
101 GLint count;
102 GLcharARB nameBuffer[512];
103
104 glGetObjectParameterivARB( m_Id, GL_OBJECT_ACTIVE_UNIFORMS_ARB, &count );
105
106 for( GLint i=0; i<count; ++i )
107 {
108 GLsizei length;
109 GLint size;
110 GLenum type;
111
112 glGetActiveUniformARB(
113 m_Id,
114 i,
115 sizeof(nameBuffer),
116 &length,
117 &size,
118 &type,
119 nameBuffer
120 );
121
122 std::string name( nameBuffer );
123
124 if( type<GL_SAMPLER_1D_ARB || type>GL_SAMPLER_2D_RECT_SHADOW_ARB )
125 {
126 m_Uniforms[name].location = glGetUniformLocationARB( m_Id, nameBuffer );
127 m_Uniforms[name].size = size;
128 m_Uniforms[name].type = type;
129 }
130 else
131 m_Samplers[name] = glGetUniformLocationARB( m_Id, nameBuffer );
132 }
133 }
134
135
RecoverActiveAttributes()136 void GPU::Shader::RecoverActiveAttributes()
137 {
138 m_Attributes.clear();
139
140 GLint count;
141 GLcharARB nameBuffer[512];
142
143 glGetObjectParameterivARB( m_Id, GL_OBJECT_ACTIVE_ATTRIBUTES_ARB, &count );
144
145 for( GLint i=0; i<count; ++i )
146 {
147 GLsizei length;
148 GLint size;
149 GLenum type;
150
151 glGetActiveAttribARB(
152 m_Id,
153 i,
154 sizeof(nameBuffer),
155 &length,
156 &size,
157 &type,
158 nameBuffer
159 );
160
161 GLint attribId = glGetAttribLocationARB( m_Id, nameBuffer );
162 if( attribId != -1 )
163 m_Attributes[ std::string(nameBuffer) ] = attribId;
164 }
165 }
166
167
Link(std::string * logs)168 bool GPU::Shader::Link( std::string *logs )
169 {
170 if( !m_Id && !(m_Id = glCreateProgramObjectARB()) )
171 return false;
172
173
174 if( m_VertPg.IsInstantiated() )
175 glAttachObjectARB( m_Id, m_VertPg.Id() );
176
177 if( m_FragPg.IsInstantiated() )
178 glAttachObjectARB( m_Id, m_FragPg.Id() );
179
180 if( m_GeomPg.IsInstantiated() )
181 glAttachObjectARB( m_Id, m_GeomPg.Id() );
182
183 glLinkProgramARB( m_Id );
184
185 GLint status;
186 glGetObjectParameterivARB( m_Id, GL_OBJECT_LINK_STATUS_ARB, &status );
187 if( !status )
188 {
189 if( logs )
190 *logs = GetLogs( m_Id );
191
192 glDeleteObjectARB( m_Id );
193 m_Id = 0;
194
195 return false;
196 }
197
198
199 RecoverActiveUniforms();
200 RecoverActiveAttributes();
201
202 return true;
203 }
204
205
206
Attach(const PgObject & pg)207 GPU::Shader& GPU::Shader::Attach( const PgObject &pg )
208 {
209 PgObject *dst = NULL;
210
211 switch( pg.Type() )
212 {
213 case GL_VERTEX_SHADER_ARB: dst = &m_VertPg; break;
214 case GL_FRAGMENT_SHADER_ARB: dst = &m_FragPg; break;
215 case GL_GEOMETRY_SHADER_EXT: dst = &m_GeomPg; break;
216 }
217
218 if( dst )
219 {
220 if( m_Id && dst->IsInstantiated() )
221 glDetachObjectARB( m_Id, dst->Id() );
222 *dst = pg;
223 }
224
225 return *this;
226 }
227
228
DetachVertPg()229 GPU::Shader& GPU::Shader::DetachVertPg()
230 {
231 if( m_Id && m_VertPg.IsInstantiated() )
232 glDetachObjectARB( m_Id, m_VertPg.Id() );
233 m_VertPg.Release();
234 return *this;
235 }
236
237
DetachFragPg()238 GPU::Shader& GPU::Shader::DetachFragPg()
239 {
240 if( m_Id && m_FragPg.IsInstantiated() )
241 glDetachObjectARB( m_Id, m_FragPg.Id() );
242 m_FragPg.Release();
243 return *this;
244 }
245
246
DetachGeomPg()247 GPU::Shader& GPU::Shader::DetachGeomPg()
248 {
249 if( m_Id && m_GeomPg.IsInstantiated() )
250 glDetachObjectARB( m_Id, m_GeomPg.Id() );
251 m_GeomPg.Release();
252 return *this;
253 }
254
255
256 /*
257 bool GPU::Shader::CreateFromFiles( const std::string &vshFilename,
258 const std::string &fshFilename )
259 {
260 VertPg vsh;
261 FragPg fsh;
262
263 return vsh.LoadFile( vshFilename ) &&
264 fsh.LoadFile( fshFilename ) &&
265 Create( vsh, fsh );
266 }
267
268
269 bool GPU::Shader::CreateFromSources( const char *vshSourceStr,
270 const char *fshSourceStr )
271 {
272 VertPg vsh;
273 FragPg fsh;
274
275 return vsh.LoadSource( vshSourceStr ) &&
276 fsh.LoadSource( fshSourceStr ) &&
277 Create( vsh, fsh );
278 }
279 */
280
281
Release()282 void GPU::Shader::Release()
283 {
284 if( m_Id )
285 {
286 if( m_VertPg.Id() )
287 {
288 glDetachObjectARB( m_Id, m_VertPg.Id() );
289 m_VertPg.Release();
290 }
291 if( m_FragPg.Id() )
292 {
293 glDetachObjectARB( m_Id, m_FragPg.Id() );
294 m_FragPg.Release();
295 }
296 if( m_GeomPg.Id() )
297 {
298 glDetachObjectARB( m_Id, m_GeomPg.Id() );
299 m_GeomPg.Release();
300 }
301
302 glDeleteObjectARB( m_Id );
303 m_Id = 0;
304
305 m_Uniforms.clear();
306 m_Attributes.clear();
307 }
308 }
309
310
SetUniform(const std::string & name,const void * value)311 void GPU::Shader::SetUniform( const std::string& name,
312 const void *value )
313 {
314 UniformMap::iterator uu = m_Uniforms.find( name );
315 if( uu != m_Uniforms.end() )
316 {
317 GLuint activeProgBackup = glGetHandleARB( GL_PROGRAM_OBJECT_ARB );
318 glUseProgramObjectARB( m_Id );
319
320 Uniform &u = uu->second;
321 switch( u.type )
322 {
323 case GL_FLOAT: glUniform1fvARB( u.location, u.size, (GLfloat*) value ); break;
324 case GL_FLOAT_VEC2_ARB: glUniform2fvARB( u.location, u.size, (GLfloat*) value ); break;
325 case GL_FLOAT_VEC3_ARB: glUniform3fvARB( u.location, u.size, (GLfloat*) value ); break;
326 case GL_FLOAT_VEC4_ARB: glUniform4fvARB( u.location, u.size, (GLfloat*) value ); break;
327 case GL_INT: glUniform1ivARB( u.location, u.size, (GLint*) value ); break;
328 case GL_INT_VEC2_ARB: glUniform2ivARB( u.location, u.size, (GLint*) value ); break;
329 case GL_INT_VEC3_ARB: glUniform3ivARB( u.location, u.size, (GLint*) value ); break;
330 case GL_INT_VEC4_ARB: glUniform4ivARB( u.location, u.size, (GLint*) value ); break;
331 case GL_BOOL_ARB: glUniform1ivARB( u.location, u.size, (GLint*) value ); break;
332 case GL_BOOL_VEC2_ARB: glUniform2ivARB( u.location, u.size, (GLint*) value ); break;
333 case GL_BOOL_VEC3_ARB: glUniform3ivARB( u.location, u.size, (GLint*) value ); break;
334 case GL_BOOL_VEC4_ARB: glUniform4ivARB( u.location, u.size, (GLint*) value ); break;
335 case GL_FLOAT_MAT2_ARB: glUniformMatrix2fvARB( u.location, u.size, GL_FALSE, (GLfloat*) value ); break;
336 case GL_FLOAT_MAT3_ARB: glUniformMatrix3fvARB( u.location, u.size, GL_FALSE, (GLfloat*) value ); break;
337 case GL_FLOAT_MAT4_ARB: glUniformMatrix4fvARB( u.location, u.size, GL_FALSE, (GLfloat*) value ); break;
338 }
339
340 glUseProgramObjectARB( activeProgBackup );
341 }
342 }
343
344
SetSampler(const std::string & name,const GLint texUnit)345 void GPU::Shader::SetSampler( const std::string& name,
346 const GLint texUnit )
347 {
348 SamplerMap::iterator s = m_Samplers.find( name );
349 if( s != m_Samplers.end() )
350 {
351 GLuint activeProgBackup = glGetHandleARB( GL_PROGRAM_OBJECT_ARB );
352 glUseProgramObjectARB( m_Id );
353
354 glUniform1iARB( s->second, texUnit );
355
356 glUseProgramObjectARB( activeProgBackup );
357 }
358 }
359