diff options
author | Jacek Antonelli | 2008-09-06 18:24:57 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-09-06 18:25:07 -0500 |
commit | 798d367d54a6c6379ad355bd8345fa40e31e7fe9 (patch) | |
tree | 1921f1708cd0240648c97bc02df2c2ab5f2fc41e /linden/indra/llrender/llglslshader.cpp | |
parent | Second Life viewer sources 1.20.15 (diff) | |
download | meta-impy-798d367d54a6c6379ad355bd8345fa40e31e7fe9.zip meta-impy-798d367d54a6c6379ad355bd8345fa40e31e7fe9.tar.gz meta-impy-798d367d54a6c6379ad355bd8345fa40e31e7fe9.tar.bz2 meta-impy-798d367d54a6c6379ad355bd8345fa40e31e7fe9.tar.xz |
Second Life viewer sources 1.21.0-RC
Diffstat (limited to '')
-rw-r--r-- | linden/indra/llrender/llglslshader.cpp | 823 |
1 files changed, 823 insertions, 0 deletions
diff --git a/linden/indra/llrender/llglslshader.cpp b/linden/indra/llrender/llglslshader.cpp new file mode 100644 index 0000000..26984e1 --- /dev/null +++ b/linden/indra/llrender/llglslshader.cpp | |||
@@ -0,0 +1,823 @@ | |||
1 | /** | ||
2 | * @file llglslshader.cpp | ||
3 | * @brief GLSL helper functions and state. | ||
4 | * | ||
5 | * $LicenseInfo:firstyear=2005&license=viewergpl$ | ||
6 | * | ||
7 | * Copyright (c) 2005-2008, Linden Research, Inc. | ||
8 | * | ||
9 | * Second Life Viewer Source Code | ||
10 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
11 | * to you under the terms of the GNU General Public License, version 2.0 | ||
12 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
13 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
14 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
15 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
16 | * | ||
17 | * There are special exceptions to the terms and conditions of the GPL as | ||
18 | * it is applied to this Source Code. View the full text of the exception | ||
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
20 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | ||
22 | * By copying, modifying or distributing this software, you acknowledge | ||
23 | * that you have read and understood your obligations described above, | ||
24 | * and agree to abide by those obligations. | ||
25 | * | ||
26 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
27 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
28 | * COMPLETENESS OR PERFORMANCE. | ||
29 | * $/LicenseInfo$ | ||
30 | */ | ||
31 | |||
32 | #include "linden_common.h" | ||
33 | |||
34 | #include "llglslshader.h" | ||
35 | |||
36 | #include "llshadermgr.h" | ||
37 | #include "llfile.h" | ||
38 | #include "llrender.h" | ||
39 | |||
40 | #if LL_DARWIN | ||
41 | #include "OpenGL/OpenGL.h" | ||
42 | #endif | ||
43 | |||
44 | #ifdef LL_RELEASE_FOR_DOWNLOAD | ||
45 | #define UNIFORM_ERRS LL_WARNS_ONCE("Shader") | ||
46 | #else | ||
47 | #define UNIFORM_ERRS LL_ERRS("Shader") | ||
48 | #endif | ||
49 | |||
50 | // Lots of STL stuff in here, using namespace std to keep things more readable | ||
51 | using std::vector; | ||
52 | using std::pair; | ||
53 | using std::make_pair; | ||
54 | using std::string; | ||
55 | |||
56 | BOOL shouldChange(const LLVector4& v1, const LLVector4& v2) | ||
57 | { | ||
58 | return v1 != v2; | ||
59 | } | ||
60 | |||
61 | LLShaderFeatures::LLShaderFeatures() | ||
62 | : calculatesLighting(false), isShiny(false), isFullbright(false), hasWaterFog(false), | ||
63 | hasTransport(false), hasSkinning(false), hasAtmospherics(false), isSpecular(false), | ||
64 | hasGamma(false), hasLighting(false), calculatesAtmospherics(false) | ||
65 | { | ||
66 | } | ||
67 | |||
68 | //=============================== | ||
69 | // LLGLSL Shader implementation | ||
70 | //=============================== | ||
71 | LLGLSLShader::LLGLSLShader() | ||
72 | : mProgramObject(0), mShaderLevel(0), mShaderGroup(SG_DEFAULT) | ||
73 | { | ||
74 | } | ||
75 | |||
76 | void LLGLSLShader::unload() | ||
77 | { | ||
78 | stop_glerror(); | ||
79 | mAttribute.clear(); | ||
80 | mTexture.clear(); | ||
81 | mUniform.clear(); | ||
82 | mShaderFiles.clear(); | ||
83 | |||
84 | if (mProgramObject) | ||
85 | { | ||
86 | GLhandleARB obj[1024]; | ||
87 | GLsizei count; | ||
88 | |||
89 | glGetAttachedObjectsARB(mProgramObject, 1024, &count, obj); | ||
90 | for (GLsizei i = 0; i < count; i++) | ||
91 | { | ||
92 | glDeleteObjectARB(obj[i]); | ||
93 | } | ||
94 | |||
95 | glDeleteObjectARB(mProgramObject); | ||
96 | |||
97 | mProgramObject = 0; | ||
98 | } | ||
99 | |||
100 | //hack to make apple not complain | ||
101 | glGetError(); | ||
102 | |||
103 | stop_glerror(); | ||
104 | } | ||
105 | |||
106 | BOOL LLGLSLShader::createShader(vector<string> * attributes, | ||
107 | vector<string> * uniforms) | ||
108 | { | ||
109 | llassert_always(!mShaderFiles.empty()); | ||
110 | BOOL success = TRUE; | ||
111 | |||
112 | // Create program | ||
113 | mProgramObject = glCreateProgramObjectARB(); | ||
114 | |||
115 | // Attach existing objects | ||
116 | if (!LLShaderMgr::instance()->attachShaderFeatures(this)) | ||
117 | { | ||
118 | return FALSE; | ||
119 | } | ||
120 | |||
121 | vector< pair<string,GLenum> >::iterator fileIter = mShaderFiles.begin(); | ||
122 | for ( ; fileIter != mShaderFiles.end(); fileIter++ ) | ||
123 | { | ||
124 | GLhandleARB shaderhandle = LLShaderMgr::instance()->loadShaderFile((*fileIter).first, mShaderLevel, (*fileIter).second); | ||
125 | LL_DEBUGS("ShaderLoading") << "SHADER FILE: " << (*fileIter).first << " mShaderLevel=" << mShaderLevel << LL_ENDL; | ||
126 | if (mShaderLevel > 0) | ||
127 | { | ||
128 | attachObject(shaderhandle); | ||
129 | } | ||
130 | else | ||
131 | { | ||
132 | success = FALSE; | ||
133 | } | ||
134 | } | ||
135 | |||
136 | // Map attributes and uniforms | ||
137 | if (success) | ||
138 | { | ||
139 | success = mapAttributes(attributes); | ||
140 | } | ||
141 | if (success) | ||
142 | { | ||
143 | success = mapUniforms(uniforms); | ||
144 | } | ||
145 | if( !success ) | ||
146 | { | ||
147 | LL_WARNS("ShaderLoading") << "Failed to link shader: " << mName << LL_ENDL; | ||
148 | |||
149 | // Try again using a lower shader level; | ||
150 | if (mShaderLevel > 0) | ||
151 | { | ||
152 | LL_WARNS("ShaderLoading") << "Failed to link using shader level " << mShaderLevel << " trying again using shader level " << (mShaderLevel - 1) << LL_ENDL; | ||
153 | mShaderLevel--; | ||
154 | return createShader(attributes,uniforms); | ||
155 | } | ||
156 | } | ||
157 | return success; | ||
158 | } | ||
159 | |||
160 | BOOL LLGLSLShader::attachObject(std::string object) | ||
161 | { | ||
162 | if (LLShaderMgr::instance()->mShaderObjects.count(object) > 0) | ||
163 | { | ||
164 | stop_glerror(); | ||
165 | glAttachObjectARB(mProgramObject, LLShaderMgr::instance()->mShaderObjects[object]); | ||
166 | stop_glerror(); | ||
167 | return TRUE; | ||
168 | } | ||
169 | else | ||
170 | { | ||
171 | LL_WARNS("ShaderLoading") << "Attempting to attach shader object that hasn't been compiled: " << object << LL_ENDL; | ||
172 | return FALSE; | ||
173 | } | ||
174 | } | ||
175 | |||
176 | void LLGLSLShader::attachObject(GLhandleARB object) | ||
177 | { | ||
178 | if (object != 0) | ||
179 | { | ||
180 | stop_glerror(); | ||
181 | glAttachObjectARB(mProgramObject, object); | ||
182 | stop_glerror(); | ||
183 | } | ||
184 | else | ||
185 | { | ||
186 | LL_WARNS("ShaderLoading") << "Attempting to attach non existing shader object. " << LL_ENDL; | ||
187 | } | ||
188 | } | ||
189 | |||
190 | void LLGLSLShader::attachObjects(GLhandleARB* objects, S32 count) | ||
191 | { | ||
192 | for (S32 i = 0; i < count; i++) | ||
193 | { | ||
194 | attachObject(objects[i]); | ||
195 | } | ||
196 | } | ||
197 | |||
198 | BOOL LLGLSLShader::mapAttributes(const vector<string> * attributes) | ||
199 | { | ||
200 | //link the program | ||
201 | BOOL res = link(); | ||
202 | |||
203 | mAttribute.clear(); | ||
204 | U32 numAttributes = (attributes == NULL) ? 0 : attributes->size(); | ||
205 | mAttribute.resize(LLShaderMgr::instance()->mReservedAttribs.size() + numAttributes, -1); | ||
206 | |||
207 | if (res) | ||
208 | { //read back channel locations | ||
209 | |||
210 | //read back reserved channels first | ||
211 | for (U32 i = 0; i < (S32) LLShaderMgr::instance()->mReservedAttribs.size(); i++) | ||
212 | { | ||
213 | const char* name = LLShaderMgr::instance()->mReservedAttribs[i].c_str(); | ||
214 | S32 index = glGetAttribLocationARB(mProgramObject, (const GLcharARB *)name); | ||
215 | if (index != -1) | ||
216 | { | ||
217 | mAttribute[i] = index; | ||
218 | LL_DEBUGS("ShaderLoading") << "Attribute " << name << " assigned to channel " << index << LL_ENDL; | ||
219 | } | ||
220 | } | ||
221 | if (attributes != NULL) | ||
222 | { | ||
223 | for (U32 i = 0; i < numAttributes; i++) | ||
224 | { | ||
225 | const char* name = (*attributes)[i].c_str(); | ||
226 | S32 index = glGetAttribLocationARB(mProgramObject, name); | ||
227 | if (index != -1) | ||
228 | { | ||
229 | mAttribute[LLShaderMgr::instance()->mReservedAttribs.size() + i] = index; | ||
230 | LL_DEBUGS("ShaderLoading") << "Attribute " << name << " assigned to channel " << index << LL_ENDL; | ||
231 | } | ||
232 | } | ||
233 | } | ||
234 | |||
235 | return TRUE; | ||
236 | } | ||
237 | |||
238 | return FALSE; | ||
239 | } | ||
240 | |||
241 | void LLGLSLShader::mapUniform(GLint index, const vector<string> * uniforms) | ||
242 | { | ||
243 | if (index == -1) | ||
244 | { | ||
245 | return; | ||
246 | } | ||
247 | |||
248 | GLenum type; | ||
249 | GLsizei length; | ||
250 | GLint size; | ||
251 | char name[1024]; /* Flawfinder: ignore */ | ||
252 | name[0] = 0; | ||
253 | |||
254 | glGetActiveUniformARB(mProgramObject, index, 1024, &length, &size, &type, (GLcharARB *)name); | ||
255 | S32 location = glGetUniformLocationARB(mProgramObject, name); | ||
256 | if (location != -1) | ||
257 | { | ||
258 | mUniformMap[name] = location; | ||
259 | LL_DEBUGS("ShaderLoading") << "Uniform " << name << " is at location " << location << LL_ENDL; | ||
260 | |||
261 | //find the index of this uniform | ||
262 | for (S32 i = 0; i < (S32) LLShaderMgr::instance()->mReservedUniforms.size(); i++) | ||
263 | { | ||
264 | if ( (mUniform[i] == -1) | ||
265 | && (LLShaderMgr::instance()->mReservedUniforms[i].compare(0, length, name, LLShaderMgr::instance()->mReservedUniforms[i].length()) == 0)) | ||
266 | { | ||
267 | //found it | ||
268 | mUniform[i] = location; | ||
269 | mTexture[i] = mapUniformTextureChannel(location, type); | ||
270 | return; | ||
271 | } | ||
272 | } | ||
273 | |||
274 | if (uniforms != NULL) | ||
275 | { | ||
276 | for (U32 i = 0; i < uniforms->size(); i++) | ||
277 | { | ||
278 | if ( (mUniform[i+LLShaderMgr::instance()->mReservedUniforms.size()] == -1) | ||
279 | && ((*uniforms)[i].compare(0, length, name, (*uniforms)[i].length()) == 0)) | ||
280 | { | ||
281 | //found it | ||
282 | mUniform[i+LLShaderMgr::instance()->mReservedUniforms.size()] = location; | ||
283 | mTexture[i+LLShaderMgr::instance()->mReservedUniforms.size()] = mapUniformTextureChannel(location, type); | ||
284 | return; | ||
285 | } | ||
286 | } | ||
287 | } | ||
288 | } | ||
289 | } | ||
290 | |||
291 | GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type) | ||
292 | { | ||
293 | if (type >= GL_SAMPLER_1D_ARB && type <= GL_SAMPLER_2D_RECT_SHADOW_ARB) | ||
294 | { //this here is a texture | ||
295 | glUniform1iARB(location, mActiveTextureChannels); | ||
296 | LL_DEBUGS("ShaderLoading") << "Assigned to texture channel " << mActiveTextureChannels << LL_ENDL; | ||
297 | return mActiveTextureChannels++; | ||
298 | } | ||
299 | return -1; | ||
300 | } | ||
301 | |||
302 | BOOL LLGLSLShader::mapUniforms(const vector<string> * uniforms) | ||
303 | { | ||
304 | BOOL res = TRUE; | ||
305 | |||
306 | mActiveTextureChannels = 0; | ||
307 | mUniform.clear(); | ||
308 | mUniformMap.clear(); | ||
309 | mTexture.clear(); | ||
310 | mValue.clear(); | ||
311 | //initialize arrays | ||
312 | U32 numUniforms = (uniforms == NULL) ? 0 : uniforms->size(); | ||
313 | mUniform.resize(numUniforms + LLShaderMgr::instance()->mReservedUniforms.size(), -1); | ||
314 | mTexture.resize(numUniforms + LLShaderMgr::instance()->mReservedUniforms.size(), -1); | ||
315 | |||
316 | bind(); | ||
317 | |||
318 | //get the number of active uniforms | ||
319 | GLint activeCount; | ||
320 | glGetObjectParameterivARB(mProgramObject, GL_OBJECT_ACTIVE_UNIFORMS_ARB, &activeCount); | ||
321 | |||
322 | for (S32 i = 0; i < activeCount; i++) | ||
323 | { | ||
324 | mapUniform(i, uniforms); | ||
325 | } | ||
326 | |||
327 | unbind(); | ||
328 | |||
329 | return res; | ||
330 | } | ||
331 | |||
332 | BOOL LLGLSLShader::link(BOOL suppress_errors) | ||
333 | { | ||
334 | return LLShaderMgr::instance()->linkProgramObject(mProgramObject, suppress_errors); | ||
335 | } | ||
336 | |||
337 | void LLGLSLShader::bind() | ||
338 | { | ||
339 | if (gGLManager.mHasShaderObjects) | ||
340 | { | ||
341 | glUseProgramObjectARB(mProgramObject); | ||
342 | |||
343 | if (mUniformsDirty) | ||
344 | { | ||
345 | LLShaderMgr::instance()->updateShaderUniforms(this); | ||
346 | mUniformsDirty = FALSE; | ||
347 | } | ||
348 | } | ||
349 | } | ||
350 | |||
351 | void LLGLSLShader::unbind() | ||
352 | { | ||
353 | if (gGLManager.mHasShaderObjects) | ||
354 | { | ||
355 | for (U32 i = 0; i < mAttribute.size(); ++i) | ||
356 | { | ||
357 | vertexAttrib4f(i, 0,0,0,1); | ||
358 | } | ||
359 | glUseProgramObjectARB(0); | ||
360 | } | ||
361 | } | ||
362 | |||
363 | void LLGLSLShader::bindNoShader(void) | ||
364 | { | ||
365 | glUseProgramObjectARB(0); | ||
366 | } | ||
367 | |||
368 | S32 LLGLSLShader::enableTexture(S32 uniform, S32 mode) | ||
369 | { | ||
370 | if (uniform < 0 || uniform >= (S32)mTexture.size()) | ||
371 | { | ||
372 | UNIFORM_ERRS << "Uniform out of range: " << uniform << LL_ENDL; | ||
373 | return -1; | ||
374 | } | ||
375 | S32 index = mTexture[uniform]; | ||
376 | if (index != -1) | ||
377 | { | ||
378 | gGL.getTexUnit(index)->activate(); | ||
379 | glEnable(mode); | ||
380 | } | ||
381 | return index; | ||
382 | } | ||
383 | |||
384 | S32 LLGLSLShader::disableTexture(S32 uniform, S32 mode) | ||
385 | { | ||
386 | if (uniform < 0 || uniform >= (S32)mTexture.size()) | ||
387 | { | ||
388 | UNIFORM_ERRS << "Uniform out of range: " << uniform << LL_ENDL; | ||
389 | return -1; | ||
390 | } | ||
391 | S32 index = mTexture[uniform]; | ||
392 | if (index != -1) | ||
393 | { | ||
394 | gGL.getTexUnit(index)->activate(); | ||
395 | glDisable(mode); | ||
396 | } | ||
397 | return index; | ||
398 | } | ||
399 | |||
400 | void LLGLSLShader::uniform1f(U32 index, GLfloat x) | ||
401 | { | ||
402 | if (mProgramObject > 0) | ||
403 | { | ||
404 | if (mUniform.size() <= index) | ||
405 | { | ||
406 | UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; | ||
407 | return; | ||
408 | } | ||
409 | |||
410 | if (mUniform[index] >= 0) | ||
411 | { | ||
412 | std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); | ||
413 | if (iter == mValue.end() || iter->second.mV[0] != x) | ||
414 | { | ||
415 | glUniform1fARB(mUniform[index], x); | ||
416 | mValue[mUniform[index]] = LLVector4(x,0.f,0.f,0.f); | ||
417 | } | ||
418 | } | ||
419 | } | ||
420 | } | ||
421 | |||
422 | void LLGLSLShader::uniform2f(U32 index, GLfloat x, GLfloat y) | ||
423 | { | ||
424 | if (mProgramObject > 0) | ||
425 | { | ||
426 | if (mUniform.size() <= index) | ||
427 | { | ||
428 | UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; | ||
429 | return; | ||
430 | } | ||
431 | |||
432 | if (mUniform[index] >= 0) | ||
433 | { | ||
434 | std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); | ||
435 | LLVector4 vec(x,y,0.f,0.f); | ||
436 | if (iter == mValue.end() || shouldChange(iter->second,vec)) | ||
437 | { | ||
438 | glUniform2fARB(mUniform[index], x, y); | ||
439 | mValue[mUniform[index]] = vec; | ||
440 | } | ||
441 | } | ||
442 | } | ||
443 | } | ||
444 | |||
445 | void LLGLSLShader::uniform3f(U32 index, GLfloat x, GLfloat y, GLfloat z) | ||
446 | { | ||
447 | if (mProgramObject > 0) | ||
448 | { | ||
449 | if (mUniform.size() <= index) | ||
450 | { | ||
451 | UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; | ||
452 | return; | ||
453 | } | ||
454 | |||
455 | if (mUniform[index] >= 0) | ||
456 | { | ||
457 | std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); | ||
458 | LLVector4 vec(x,y,z,0.f); | ||
459 | if (iter == mValue.end() || shouldChange(iter->second,vec)) | ||
460 | { | ||
461 | glUniform3fARB(mUniform[index], x, y, z); | ||
462 | mValue[mUniform[index]] = vec; | ||
463 | } | ||
464 | } | ||
465 | } | ||
466 | } | ||
467 | |||
468 | void LLGLSLShader::uniform4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) | ||
469 | { | ||
470 | if (mProgramObject > 0) | ||
471 | { | ||
472 | if (mUniform.size() <= index) | ||
473 | { | ||
474 | UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; | ||
475 | return; | ||
476 | } | ||
477 | |||
478 | if (mUniform[index] >= 0) | ||
479 | { | ||
480 | std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); | ||
481 | LLVector4 vec(x,y,z,w); | ||
482 | if (iter == mValue.end() || shouldChange(iter->second,vec)) | ||
483 | { | ||
484 | glUniform4fARB(mUniform[index], x, y, z, w); | ||
485 | mValue[mUniform[index]] = vec; | ||
486 | } | ||
487 | } | ||
488 | } | ||
489 | } | ||
490 | |||
491 | void LLGLSLShader::uniform1fv(U32 index, U32 count, const GLfloat* v) | ||
492 | { | ||
493 | if (mProgramObject > 0) | ||
494 | { | ||
495 | if (mUniform.size() <= index) | ||
496 | { | ||
497 | UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; | ||
498 | return; | ||
499 | } | ||
500 | |||
501 | if (mUniform[index] >= 0) | ||
502 | { | ||
503 | std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); | ||
504 | LLVector4 vec(v[0],0.f,0.f,0.f); | ||
505 | if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) | ||
506 | { | ||
507 | glUniform1fvARB(mUniform[index], count, v); | ||
508 | mValue[mUniform[index]] = vec; | ||
509 | } | ||
510 | } | ||
511 | } | ||
512 | } | ||
513 | |||
514 | void LLGLSLShader::uniform2fv(U32 index, U32 count, const GLfloat* v) | ||
515 | { | ||
516 | if (mProgramObject > 0) | ||
517 | { | ||
518 | if (mUniform.size() <= index) | ||
519 | { | ||
520 | UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; | ||
521 | return; | ||
522 | } | ||
523 | |||
524 | if (mUniform[index] >= 0) | ||
525 | { | ||
526 | std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); | ||
527 | LLVector4 vec(v[0],v[1],0.f,0.f); | ||
528 | if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) | ||
529 | { | ||
530 | glUniform2fvARB(mUniform[index], count, v); | ||
531 | mValue[mUniform[index]] = vec; | ||
532 | } | ||
533 | } | ||
534 | } | ||
535 | } | ||
536 | |||
537 | void LLGLSLShader::uniform3fv(U32 index, U32 count, const GLfloat* v) | ||
538 | { | ||
539 | if (mProgramObject > 0) | ||
540 | { | ||
541 | if (mUniform.size() <= index) | ||
542 | { | ||
543 | UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; | ||
544 | return; | ||
545 | } | ||
546 | |||
547 | if (mUniform[index] >= 0) | ||
548 | { | ||
549 | std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); | ||
550 | LLVector4 vec(v[0],v[1],v[2],0.f); | ||
551 | if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) | ||
552 | { | ||
553 | glUniform3fvARB(mUniform[index], count, v); | ||
554 | mValue[mUniform[index]] = vec; | ||
555 | } | ||
556 | } | ||
557 | } | ||
558 | } | ||
559 | |||
560 | void LLGLSLShader::uniform4fv(U32 index, U32 count, const GLfloat* v) | ||
561 | { | ||
562 | if (mProgramObject > 0) | ||
563 | { | ||
564 | if (mUniform.size() <= index) | ||
565 | { | ||
566 | UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; | ||
567 | return; | ||
568 | } | ||
569 | |||
570 | if (mUniform[index] >= 0) | ||
571 | { | ||
572 | std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); | ||
573 | LLVector4 vec(v[0],v[1],v[2],v[3]); | ||
574 | if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) | ||
575 | { | ||
576 | glUniform4fvARB(mUniform[index], count, v); | ||
577 | mValue[mUniform[index]] = vec; | ||
578 | } | ||
579 | } | ||
580 | } | ||
581 | } | ||
582 | |||
583 | void LLGLSLShader::uniformMatrix2fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v) | ||
584 | { | ||
585 | if (mProgramObject > 0) | ||
586 | { | ||
587 | if (mUniform.size() <= index) | ||
588 | { | ||
589 | UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; | ||
590 | return; | ||
591 | } | ||
592 | |||
593 | if (mUniform[index] >= 0) | ||
594 | { | ||
595 | glUniformMatrix2fvARB(mUniform[index], count, transpose, v); | ||
596 | } | ||
597 | } | ||
598 | } | ||
599 | |||
600 | void LLGLSLShader::uniformMatrix3fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v) | ||
601 | { | ||
602 | if (mProgramObject > 0) | ||
603 | { | ||
604 | if (mUniform.size() <= index) | ||
605 | { | ||
606 | UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; | ||
607 | return; | ||
608 | } | ||
609 | |||
610 | if (mUniform[index] >= 0) | ||
611 | { | ||
612 | glUniformMatrix3fvARB(mUniform[index], count, transpose, v); | ||
613 | } | ||
614 | } | ||
615 | } | ||
616 | |||
617 | void LLGLSLShader::uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v) | ||
618 | { | ||
619 | if (mProgramObject > 0) | ||
620 | { | ||
621 | if (mUniform.size() <= index) | ||
622 | { | ||
623 | UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; | ||
624 | return; | ||
625 | } | ||
626 | |||
627 | if (mUniform[index] >= 0) | ||
628 | { | ||
629 | glUniformMatrix4fvARB(mUniform[index], count, transpose, v); | ||
630 | } | ||
631 | } | ||
632 | } | ||
633 | |||
634 | GLint LLGLSLShader::getUniformLocation(const string& uniform) | ||
635 | { | ||
636 | if (mProgramObject > 0) | ||
637 | { | ||
638 | std::map<string, GLint>::iterator iter = mUniformMap.find(uniform); | ||
639 | if (iter != mUniformMap.end()) | ||
640 | { | ||
641 | llassert(iter->second == glGetUniformLocationARB(mProgramObject, uniform.c_str())); | ||
642 | return iter->second; | ||
643 | } | ||
644 | } | ||
645 | |||
646 | return -1; | ||
647 | } | ||
648 | |||
649 | void LLGLSLShader::uniform1f(const string& uniform, GLfloat v) | ||
650 | { | ||
651 | GLint location = getUniformLocation(uniform); | ||
652 | |||
653 | if (location >= 0) | ||
654 | { | ||
655 | std::map<GLint, LLVector4>::iterator iter = mValue.find(location); | ||
656 | LLVector4 vec(v,0.f,0.f,0.f); | ||
657 | if (iter == mValue.end() || shouldChange(iter->second,vec)) | ||
658 | { | ||
659 | glUniform1fARB(location, v); | ||
660 | mValue[location] = vec; | ||
661 | } | ||
662 | } | ||
663 | } | ||
664 | |||
665 | void LLGLSLShader::uniform2f(const string& uniform, GLfloat x, GLfloat y) | ||
666 | { | ||
667 | GLint location = getUniformLocation(uniform); | ||
668 | |||
669 | if (location >= 0) | ||
670 | { | ||
671 | std::map<GLint, LLVector4>::iterator iter = mValue.find(location); | ||
672 | LLVector4 vec(x,y,0.f,0.f); | ||
673 | if (iter == mValue.end() || shouldChange(iter->second,vec)) | ||
674 | { | ||
675 | glUniform2fARB(location, x,y); | ||
676 | mValue[location] = vec; | ||
677 | } | ||
678 | } | ||
679 | |||
680 | } | ||
681 | |||
682 | void LLGLSLShader::uniform3f(const string& uniform, GLfloat x, GLfloat y, GLfloat z) | ||
683 | { | ||
684 | GLint location = getUniformLocation(uniform); | ||
685 | |||
686 | if (location >= 0) | ||
687 | { | ||
688 | std::map<GLint, LLVector4>::iterator iter = mValue.find(location); | ||
689 | LLVector4 vec(x,y,z,0.f); | ||
690 | if (iter == mValue.end() || shouldChange(iter->second,vec)) | ||
691 | { | ||
692 | glUniform3fARB(location, x,y,z); | ||
693 | mValue[location] = vec; | ||
694 | } | ||
695 | } | ||
696 | } | ||
697 | |||
698 | void LLGLSLShader::uniform4f(const string& uniform, GLfloat x, GLfloat y, GLfloat z, GLfloat w) | ||
699 | { | ||
700 | GLint location = getUniformLocation(uniform); | ||
701 | |||
702 | if (location >= 0) | ||
703 | { | ||
704 | std::map<GLint, LLVector4>::iterator iter = mValue.find(location); | ||
705 | LLVector4 vec(x,y,z,w); | ||
706 | if (iter == mValue.end() || shouldChange(iter->second,vec)) | ||
707 | { | ||
708 | glUniform4fARB(location, x,y,z,w); | ||
709 | mValue[location] = vec; | ||
710 | } | ||
711 | } | ||
712 | } | ||
713 | |||
714 | void LLGLSLShader::uniform1fv(const string& uniform, U32 count, const GLfloat* v) | ||
715 | { | ||
716 | GLint location = getUniformLocation(uniform); | ||
717 | |||
718 | if (location >= 0) | ||
719 | { | ||
720 | std::map<GLint, LLVector4>::iterator iter = mValue.find(location); | ||
721 | LLVector4 vec(v[0],0.f,0.f,0.f); | ||
722 | if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) | ||
723 | { | ||
724 | glUniform1fvARB(location, count, v); | ||
725 | mValue[location] = vec; | ||
726 | } | ||
727 | } | ||
728 | } | ||
729 | |||
730 | void LLGLSLShader::uniform2fv(const string& uniform, U32 count, const GLfloat* v) | ||
731 | { | ||
732 | GLint location = getUniformLocation(uniform); | ||
733 | |||
734 | if (location >= 0) | ||
735 | { | ||
736 | std::map<GLint, LLVector4>::iterator iter = mValue.find(location); | ||
737 | LLVector4 vec(v[0],v[1],0.f,0.f); | ||
738 | if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) | ||
739 | { | ||
740 | glUniform2fvARB(location, count, v); | ||
741 | mValue[location] = vec; | ||
742 | } | ||
743 | } | ||
744 | } | ||
745 | |||
746 | void LLGLSLShader::uniform3fv(const string& uniform, U32 count, const GLfloat* v) | ||
747 | { | ||
748 | GLint location = getUniformLocation(uniform); | ||
749 | |||
750 | if (location >= 0) | ||
751 | { | ||
752 | std::map<GLint, LLVector4>::iterator iter = mValue.find(location); | ||
753 | LLVector4 vec(v[0],v[1],v[2],0.f); | ||
754 | if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) | ||
755 | { | ||
756 | glUniform3fvARB(location, count, v); | ||
757 | mValue[location] = vec; | ||
758 | } | ||
759 | } | ||
760 | } | ||
761 | |||
762 | void LLGLSLShader::uniform4fv(const string& uniform, U32 count, const GLfloat* v) | ||
763 | { | ||
764 | GLint location = getUniformLocation(uniform); | ||
765 | |||
766 | if (location >= 0) | ||
767 | { | ||
768 | LLVector4 vec(v); | ||
769 | std::map<GLint, LLVector4>::iterator iter = mValue.find(location); | ||
770 | if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) | ||
771 | { | ||
772 | glUniform4fvARB(location, count, v); | ||
773 | mValue[location] = vec; | ||
774 | } | ||
775 | } | ||
776 | } | ||
777 | |||
778 | void LLGLSLShader::uniformMatrix2fv(const string& uniform, U32 count, GLboolean transpose, const GLfloat* v) | ||
779 | { | ||
780 | GLint location = getUniformLocation(uniform); | ||
781 | |||
782 | if (location >= 0) | ||
783 | { | ||
784 | glUniformMatrix2fvARB(location, count, transpose, v); | ||
785 | } | ||
786 | } | ||
787 | |||
788 | void LLGLSLShader::uniformMatrix3fv(const string& uniform, U32 count, GLboolean transpose, const GLfloat* v) | ||
789 | { | ||
790 | GLint location = getUniformLocation(uniform); | ||
791 | |||
792 | if (location >= 0) | ||
793 | { | ||
794 | glUniformMatrix3fvARB(location, count, transpose, v); | ||
795 | } | ||
796 | } | ||
797 | |||
798 | void LLGLSLShader::uniformMatrix4fv(const string& uniform, U32 count, GLboolean transpose, const GLfloat* v) | ||
799 | { | ||
800 | GLint location = getUniformLocation(uniform); | ||
801 | |||
802 | if (location >= 0) | ||
803 | { | ||
804 | glUniformMatrix4fvARB(location, count, transpose, v); | ||
805 | } | ||
806 | } | ||
807 | |||
808 | |||
809 | void LLGLSLShader::vertexAttrib4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) | ||
810 | { | ||
811 | if (mAttribute[index] > 0) | ||
812 | { | ||
813 | glVertexAttrib4fARB(mAttribute[index], x, y, z, w); | ||
814 | } | ||
815 | } | ||
816 | |||
817 | void LLGLSLShader::vertexAttrib4fv(U32 index, GLfloat* v) | ||
818 | { | ||
819 | if (mAttribute[index] > 0) | ||
820 | { | ||
821 | glVertexAttrib4fvARB(mAttribute[index], v); | ||
822 | } | ||
823 | } | ||