Line data Source code
1 : /* Copyright (C) 2021 Wildfire Games.
2 : * This file is part of 0 A.D.
3 : *
4 : * 0 A.D. is free software: you can redistribute it and/or modify
5 : * it under the terms of the GNU General Public License as published by
6 : * the Free Software Foundation, either version 2 of the License, or
7 : * (at your option) any later version.
8 : *
9 : * 0 A.D. is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : * GNU General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU General Public License
15 : * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16 : */
17 :
18 : #include "precompiled.h"
19 :
20 : #include "ShaderProgram.h"
21 :
22 : #include "graphics/ShaderDefines.h"
23 : #include "graphics/TextureManager.h"
24 : #include "lib/res/graphics/ogl_tex.h"
25 : #include "maths/Matrix3D.h"
26 : #include "maths/Vector3D.h"
27 : #include "ps/CLogger.h"
28 : #include "renderer/Renderer.h"
29 :
30 : #if !CONFIG2_GLES
31 :
32 : /**
33 : * CShaderProgramFFP allows rendering code to use the shader-based API
34 : * even if the 'shader' is actually implemented with the fixed-function
35 : * pipeline instead of anything programmable.
36 : *
37 : * Currently we just hard-code a number of FFP programs as subclasses of this.
38 : * If we have lots, it might be nicer to abstract out the common functionality
39 : * and load these from text files or something.
40 : */
41 : class CShaderProgramFFP : public CShaderProgram
42 : {
43 : public:
44 0 : CShaderProgramFFP(int streamflags) :
45 0 : CShaderProgram(streamflags)
46 : {
47 : }
48 :
49 0 : ~CShaderProgramFFP()
50 0 : {
51 0 : }
52 0 :
53 0 : virtual void Reload()
54 0 : {
55 0 : m_IsValid = true;
56 0 : }
57 0 :
58 : int GetUniformIndex(CStrIntern id)
59 0 : {
60 : std::map<CStrIntern, int>::iterator it = m_UniformIndexes.find(id);
61 0 : if (it == m_UniformIndexes.end())
62 0 : return -1;
63 : return it->second;
64 : }
65 :
66 0 : virtual Binding GetTextureBinding(uniform_id_t id)
67 0 : {
68 : int index = GetUniformIndex(CStrIntern(id));
69 0 : if (index == -1)
70 : return Binding();
71 : else
72 0 : return Binding((int)GL_TEXTURE_2D, index);
73 : }
74 0 :
75 0 : virtual void BindTexture(texture_id_t id, Handle tex)
76 0 : {
77 : int index = GetUniformIndex(CStrIntern(id));
78 0 : if (index != -1)
79 : ogl_tex_bind(tex, index);
80 : }
81 0 :
82 : virtual void BindTexture(texture_id_t id, GLuint tex)
83 0 : {
84 0 : int index = GetUniformIndex(CStrIntern(id));
85 0 : if (index != -1)
86 0 : {
87 : pglActiveTextureARB((int)(GL_TEXTURE0+index));
88 0 : glBindTexture(GL_TEXTURE_2D, tex);
89 : }
90 0 : }
91 0 :
92 : virtual void BindTexture(Binding id, Handle tex)
93 0 : {
94 0 : int index = id.second;
95 : if (index != -1)
96 0 : ogl_tex_bind(tex, index);
97 : }
98 0 :
99 : virtual Binding GetUniformBinding(uniform_id_t id)
100 0 : {
101 0 : return Binding(-1, GetUniformIndex(id));
102 0 : }
103 0 :
104 : virtual void Uniform(Binding UNUSED(id), float UNUSED(v0), float UNUSED(v1), float UNUSED(v2), float UNUSED(v3))
105 0 : {
106 : }
107 0 :
108 : virtual void Uniform(Binding UNUSED(id), const CMatrix3D& UNUSED(v))
109 : {
110 0 : }
111 :
112 0 : virtual void Uniform(Binding UNUSED(id), size_t UNUSED(count), const CMatrix3D* UNUSED(v))
113 : {
114 0 : }
115 :
116 0 : virtual void Uniform(Binding UNUSED(id), size_t UNUSED(count), const float* UNUSED(v))
117 : {
118 0 : }
119 :
120 0 : virtual std::vector<VfsPath> GetFileDependencies() const
121 : {
122 0 : return {};
123 : }
124 0 :
125 : protected:
126 0 : std::map<CStrIntern, int> m_UniformIndexes;
127 :
128 0 : void SetUniformIndex(const char* id, int value)
129 : {
130 : m_UniformIndexes[CStrIntern(id)] = value;
131 : }
132 : };
133 :
134 : //////////////////////////////////////////////////////////////////////////
135 :
136 0 : /**
137 : * A shader that does nothing but provide a shader-compatible interface to
138 : * fixed-function features, for compatibility with existing fixed-function
139 : * code that isn't fully ported to the shader API.
140 : */
141 : class CShaderProgramFFP_Dummy : public CShaderProgramFFP
142 : {
143 : public:
144 : CShaderProgramFFP_Dummy() :
145 : CShaderProgramFFP(0)
146 : {
147 : // Texture units, for when this shader is used with terrain:
148 : SetUniformIndex("baseTex", 0);
149 : }
150 0 :
151 0 : virtual void Bind()
152 : {
153 : BindClientStates();
154 0 : }
155 0 :
156 : virtual void Unbind()
157 0 : {
158 : UnbindClientStates();
159 0 : }
160 0 : };
161 :
162 0 : //////////////////////////////////////////////////////////////////////////
163 :
164 0 : class CShaderProgramFFP_OverlayLine : public CShaderProgramFFP
165 0 : {
166 : // Uniforms
167 : enum
168 : {
169 : ID_losTransform,
170 : ID_objectColor
171 : };
172 :
173 : bool m_IgnoreLos;
174 : bool m_UseObjectColor;
175 :
176 : public:
177 : CShaderProgramFFP_OverlayLine(const CShaderDefines& defines) :
178 : CShaderProgramFFP(0) // will be set manually in initializer below
179 : {
180 : SetUniformIndex("losTransform", ID_losTransform);
181 : SetUniformIndex("objectColor", ID_objectColor);
182 :
183 0 : // Texture units:
184 0 : SetUniformIndex("baseTex", 0);
185 : SetUniformIndex("maskTex", 1);
186 0 : SetUniformIndex("losTex", 2);
187 0 :
188 : m_IgnoreLos = (defines.GetInt("IGNORE_LOS") != 0);
189 : m_UseObjectColor = (defines.GetInt("USE_OBJECTCOLOR") != 0);
190 0 :
191 0 : m_StreamFlags = STREAM_POS | STREAM_UV0 | STREAM_UV1;
192 0 : if (!m_UseObjectColor)
193 : m_StreamFlags |= STREAM_COLOR;
194 0 : }
195 0 :
196 : bool IsIgnoreLos()
197 0 : {
198 0 : return m_IgnoreLos;
199 0 : }
200 0 :
201 : virtual void Uniform(Binding id, float v0, float v1, float v2, float v3)
202 0 : {
203 : if (id.second == ID_losTransform)
204 0 : {
205 : pglActiveTextureARB(GL_TEXTURE2);
206 : GLfloat texgenS1[4] = { v0, 0, 0, v1 };
207 0 : GLfloat texgenT1[4] = { 0, 0, v0, v1 };
208 : glTexGenfv(GL_S, GL_OBJECT_PLANE, texgenS1);
209 0 : glTexGenfv(GL_T, GL_OBJECT_PLANE, texgenT1);
210 : }
211 0 : else if (id.second == ID_objectColor)
212 0 : {
213 0 : float c[] = { v0, v1, v2, v3 };
214 0 : pglActiveTextureARB(GL_TEXTURE1);
215 0 : glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, c);
216 : }
217 0 : else
218 : {
219 0 : debug_warn(L"Invalid id");
220 0 : }
221 0 : }
222 :
223 : virtual void Uniform(Binding UNUSED(id), const CMatrix3D& UNUSED(v))
224 : {
225 0 : debug_warn(L"Not implemented");
226 : }
227 0 :
228 : virtual void Bind()
229 0 : {
230 : // RGB channels:
231 0 : // Unit 0: Sample base texture
232 0 : // Unit 1: Sample mask texture; interpolate with [objectColor or vertexColor] and base, depending on USE_OBJECTCOLOR
233 : // Unit 2: (Load LOS texture; multiply) if not #IGNORE_LOS, pass through otherwise
234 0 : // Alpha channel:
235 : // Unit 0: Sample base texture
236 : // Unit 1: Multiply by objectColor
237 : // Unit 2: Pass through
238 :
239 : pglActiveTextureARB(GL_TEXTURE0);
240 : glEnable(GL_TEXTURE_2D);
241 : glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
242 :
243 : // Sample base texture RGB
244 : glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
245 0 : glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
246 0 : glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
247 0 :
248 : // Sample base texture Alpha
249 : glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
250 0 : glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
251 0 : glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
252 0 :
253 : // -----------------------------------------------------------------------------
254 :
255 0 : pglActiveTextureARB(GL_TEXTURE1);
256 0 : glEnable(GL_TEXTURE_2D);
257 0 : glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
258 :
259 : // RGB: interpolate component-wise between [objectColor or vertexColor] and base using mask:
260 : // a0 * a2 + a1 * (1 - a2)
261 0 : // Overridden implementation of Uniform() sets GL_TEXTURE_ENV_COLOR to objectColor, which
262 0 : // is referenced as GL_CONSTANT (see spec)
263 0 : glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE);
264 : glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, m_UseObjectColor ? GL_CONSTANT : GL_PRIMARY_COLOR);
265 : glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
266 : glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS);
267 : glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
268 : glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);
269 0 : glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_COLOR);
270 0 :
271 0 : // ALPHA: Multiply base alpha with [objectColor or vertexColor] alpha
272 0 : glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);
273 0 : glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, m_UseObjectColor ? GL_CONSTANT : GL_PRIMARY_COLOR);
274 0 : glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
275 0 : glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS);
276 : glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA);
277 :
278 0 : // -----------------------------------------------------------------------------
279 0 :
280 0 : pglActiveTextureARB(GL_TEXTURE2);
281 0 : glEnable(GL_TEXTURE_2D);
282 0 : glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
283 :
284 : bool ignoreLos = IsIgnoreLos();
285 : if (ignoreLos)
286 0 : {
287 0 : // RGB pass through
288 0 : glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
289 : glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
290 0 : glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
291 0 : }
292 : else
293 : {
294 0 : // Multiply RGB result up till now with LoS texture alpha channel
295 0 : glEnable(GL_TEXTURE_GEN_S);
296 0 : glEnable(GL_TEXTURE_GEN_T);
297 : glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
298 : glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
299 : // Overridden implementation of Uniform() sets GL_OBJECT_PLANE values
300 :
301 0 : glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
302 0 : glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
303 0 : glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
304 0 : glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
305 : glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_ALPHA);
306 : }
307 0 :
308 0 : // alpha pass through
309 0 : glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
310 0 : glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS);
311 0 : glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
312 :
313 : BindClientStates();
314 : }
315 0 :
316 0 : virtual void Unbind()
317 0 : {
318 : UnbindClientStates();
319 0 :
320 0 : pglActiveTextureARB(GL_TEXTURE2);
321 : glDisable(GL_TEXTURE_2D);
322 0 :
323 : glDisable(GL_TEXTURE_GEN_S);
324 0 : glDisable(GL_TEXTURE_GEN_T);
325 :
326 0 : pglActiveTextureARB(GL_TEXTURE1);
327 0 : glDisable(GL_TEXTURE_2D);
328 :
329 0 : pglActiveTextureARB(GL_TEXTURE0);
330 0 : glDisable(GL_TEXTURE_2D);
331 : }
332 0 : };
333 0 :
334 : //////////////////////////////////////////////////////////////////////////
335 0 :
336 0 : class CShaderProgramFFP_GuiText : public CShaderProgramFFP
337 0 : {
338 : // Uniforms
339 : enum
340 : {
341 : ID_transform,
342 : ID_colorMul
343 : };
344 :
345 : public:
346 : CShaderProgramFFP_GuiText() :
347 : CShaderProgramFFP(STREAM_POS | STREAM_UV0)
348 : {
349 : SetUniformIndex("transform", ID_transform);
350 : SetUniformIndex("colorMul", ID_colorMul);
351 :
352 0 : // Texture units:
353 0 : SetUniformIndex("tex", 0);
354 : }
355 0 :
356 0 : virtual void Uniform(Binding id, float v0, float v1, float v2, float v3)
357 : {
358 : if (id.second == ID_colorMul)
359 0 : glColor4f(v0, v1, v2, v3);
360 0 : }
361 :
362 0 : virtual void Uniform(Binding id, const CMatrix3D& v)
363 : {
364 0 : if (id.second == ID_transform)
365 0 : glLoadMatrixf(&v._11);
366 0 : }
367 :
368 0 : virtual void Bind()
369 : {
370 0 : glMatrixMode(GL_PROJECTION);
371 0 : glPushMatrix();
372 0 : glLoadIdentity();
373 : glMatrixMode(GL_MODELVIEW);
374 0 : glPushMatrix();
375 :
376 0 : pglActiveTextureARB(GL_TEXTURE0);
377 0 : glEnable(GL_TEXTURE_2D);
378 0 : glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
379 0 :
380 0 : BindClientStates();
381 : }
382 0 :
383 0 : virtual void Unbind()
384 0 : {
385 : UnbindClientStates();
386 0 :
387 0 : pglActiveTextureARB(GL_TEXTURE0);
388 : glDisable(GL_TEXTURE_2D);
389 0 :
390 : glMatrixMode(GL_PROJECTION);
391 0 : glPopMatrix();
392 : glMatrixMode(GL_MODELVIEW);
393 0 : glPopMatrix();
394 0 : }
395 : };
396 0 :
397 0 : //////////////////////////////////////////////////////////////////////////
398 0 :
399 0 : class CShaderProgramFFP_Gui_Base : public CShaderProgramFFP
400 0 : {
401 : protected:
402 : // Uniforms
403 : enum
404 : {
405 : ID_transform,
406 : ID_color
407 : };
408 :
409 : public:
410 : CShaderProgramFFP_Gui_Base(int streamflags) :
411 : CShaderProgramFFP(streamflags)
412 : {
413 : SetUniformIndex("transform", ID_transform);
414 : SetUniformIndex("color", ID_color);
415 :
416 0 : // Texture units:
417 0 : SetUniformIndex("tex", 0);
418 : }
419 0 :
420 0 : virtual void Uniform(Binding id, const CMatrix3D& v)
421 : {
422 : if (id.second == ID_transform)
423 0 : glLoadMatrixf(&v._11);
424 0 : }
425 :
426 0 : virtual void Bind()
427 : {
428 0 : glMatrixMode(GL_PROJECTION);
429 0 : glPushMatrix();
430 0 : glLoadIdentity();
431 : glMatrixMode(GL_MODELVIEW);
432 0 : glPushMatrix();
433 :
434 0 : BindClientStates();
435 0 : }
436 0 :
437 0 : virtual void Unbind()
438 0 : {
439 : UnbindClientStates();
440 0 :
441 0 : glMatrixMode(GL_PROJECTION);
442 : glPopMatrix();
443 0 : glMatrixMode(GL_MODELVIEW);
444 : glPopMatrix();
445 0 : }
446 : };
447 0 :
448 0 : class CShaderProgramFFP_GuiMinimap : public CShaderProgramFFP
449 0 : {
450 0 : protected:
451 0 : CShaderDefines m_Defines;
452 : // Uniforms
453 : enum
454 : {
455 : ID_transform,
456 : ID_textureTransform,
457 : ID_color,
458 : ID_pointSize,
459 : };
460 : public:
461 : CShaderProgramFFP_GuiMinimap(const CShaderDefines& defines) :
462 : CShaderProgramFFP(0) // We set the streamflags later, during initialization.
463 : {
464 : m_Defines = defines;
465 : SetUniformIndex("transform", ID_transform);
466 : SetUniformIndex("textureTransform", ID_textureTransform);
467 0 : SetUniformIndex("color", ID_color);
468 0 : SetUniformIndex("pointSize", ID_pointSize);
469 :
470 0 : if (m_Defines.GetInt("MINIMAP_BASE") || m_Defines.GetInt("MINIMAP_LOS"))
471 0 : {
472 0 : SetUniformIndex("baseTex", 0);
473 0 : m_StreamFlags = STREAM_POS | STREAM_UV0;
474 0 : }
475 : else if (m_Defines.GetInt("MINIMAP_POINT"))
476 0 : m_StreamFlags = STREAM_POS | STREAM_COLOR;
477 : else
478 0 : m_StreamFlags = STREAM_POS;
479 0 : }
480 :
481 0 : virtual void Uniform(Binding id, const CMatrix3D& v)
482 0 : {
483 : if (id.second == ID_textureTransform)
484 0 : {
485 0 : glMatrixMode(GL_TEXTURE);
486 : glLoadMatrixf(&v._11);
487 0 : }
488 : else if (id.second == ID_transform)
489 0 : {
490 : glMatrixMode(GL_MODELVIEW);
491 0 : glLoadMatrixf(&v._11);
492 0 : }
493 : }
494 0 :
495 : virtual void Uniform(Binding id, float v0, float v1, float v2, float v3)
496 0 : {
497 0 : if (id.second == ID_color)
498 : glColor4f(v0, v1, v2, v3);
499 0 : else if (id.second == ID_pointSize)
500 : glPointSize(v0);
501 0 : }
502 :
503 0 : virtual void Bind()
504 0 : {
505 0 : // Setup matrix environment
506 0 : glMatrixMode(GL_PROJECTION);
507 0 : glPushMatrix();
508 : glLoadIdentity();
509 0 : glMatrixMode(GL_MODELVIEW);
510 : glPushMatrix();
511 : glLoadIdentity();
512 0 : glMatrixMode(GL_TEXTURE);
513 0 : glPushMatrix();
514 0 : glLoadIdentity();
515 0 :
516 0 : BindClientStates();
517 0 :
518 0 : // Setup texture environment
519 0 : if (m_Defines.GetInt("MINIMAP_BASE"))
520 0 : {
521 : pglActiveTextureARB(GL_TEXTURE0);
522 0 : glEnable(GL_TEXTURE_2D);
523 : glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
524 : glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
525 0 : glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
526 : }
527 0 : else if (m_Defines.GetInt("MINIMAP_LOS"))
528 0 : {
529 0 : pglActiveTextureARB(GL_TEXTURE0);
530 0 : glEnable(GL_TEXTURE_2D);
531 0 : glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
532 : glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
533 0 : glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PRIMARY_COLOR_ARB);
534 : glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
535 0 : glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
536 0 : glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
537 0 : glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_ONE_MINUS_SRC_ALPHA);
538 0 : glColor3f(0.0f, 0.0f, 0.0f);
539 0 : }
540 0 : else if (m_Defines.GetInt("MINIMAP_POINT"))
541 0 : {
542 0 : pglActiveTextureARB(GL_TEXTURE0);
543 0 : glDisable(GL_TEXTURE_2D);
544 0 : glEnableClientState(GL_VERTEX_ARRAY);
545 : glEnableClientState(GL_COLOR_ARRAY);
546 0 : }
547 : else if (m_Defines.GetInt("MINIMAP_LINE"))
548 0 : {
549 0 : // JoshuaJB 13.7.2014: This doesn't seem to do anything on my drivers.
550 0 : glEnable(GL_LINE_SMOOTH);
551 0 : }
552 : }
553 0 :
554 : virtual void Unbind()
555 : {
556 0 : // Reset texture environment
557 : if (m_Defines.GetInt("MINIMAP_POINT"))
558 0 : {
559 : pglActiveTextureARB(GL_TEXTURE0);
560 0 : glEnable(GL_TEXTURE_2D);
561 : glDisableClientState(GL_VERTEX_ARRAY);
562 : glDisableClientState(GL_COLOR_ARRAY);
563 0 : }
564 : else if (m_Defines.GetInt("MINIMAP_LINE"))
565 0 : {
566 0 : glDisable(GL_LINE_SMOOTH);
567 0 : }
568 0 :
569 : UnbindClientStates();
570 0 :
571 : // Clear matrix stack
572 0 : glMatrixMode(GL_TEXTURE);
573 : glPopMatrix();
574 : glMatrixMode(GL_PROJECTION);
575 0 : glPopMatrix();
576 : glMatrixMode(GL_MODELVIEW);
577 : glPopMatrix();
578 0 : }
579 0 : };
580 0 :
581 0 : class CShaderProgramFFP_GuiBasic : public CShaderProgramFFP_Gui_Base
582 0 : {
583 0 : public:
584 0 : CShaderProgramFFP_GuiBasic() :
585 : CShaderProgramFFP_Gui_Base(STREAM_POS | STREAM_UV0)
586 : {
587 : }
588 :
589 : virtual void Bind()
590 0 : {
591 0 : CShaderProgramFFP_Gui_Base::Bind();
592 :
593 : pglActiveTextureARB(GL_TEXTURE0);
594 : glEnable(GL_TEXTURE_2D);
595 0 : glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
596 : }
597 0 :
598 : virtual void Unbind()
599 0 : {
600 0 : pglActiveTextureARB(GL_TEXTURE0);
601 0 : glDisable(GL_TEXTURE_2D);
602 0 :
603 : CShaderProgramFFP_Gui_Base::Unbind();
604 0 : }
605 : };
606 0 :
607 0 : class CShaderProgramFFP_GuiAdd : public CShaderProgramFFP_Gui_Base
608 : {
609 0 : public:
610 0 : using CShaderProgramFFP_Gui_Base::Uniform;
611 :
612 : CShaderProgramFFP_GuiAdd() :
613 : CShaderProgramFFP_Gui_Base(STREAM_POS | STREAM_UV0)
614 : {
615 : }
616 :
617 : virtual void Uniform(Binding id, float v0, float v1, float v2, float v3)
618 0 : {
619 0 : if (id.second == ID_color)
620 : glColor4f(v0, v1, v2, v3);
621 : }
622 :
623 0 : virtual void Bind()
624 : {
625 0 : CShaderProgramFFP_Gui_Base::Bind();
626 0 :
627 0 : pglActiveTextureARB(GL_TEXTURE0);
628 : glEnable(GL_TEXTURE_2D);
629 0 :
630 : glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
631 0 :
632 : glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD);
633 0 : glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_ADD);
634 0 :
635 : glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
636 0 : glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
637 : glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
638 0 : glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
639 0 :
640 : glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PREVIOUS);
641 0 : glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
642 0 : glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_PREVIOUS);
643 0 : glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
644 0 : }
645 :
646 0 : virtual void Unbind()
647 0 : {
648 0 : glColor4f(1.f, 1.f, 1.f, 1.f);
649 0 :
650 0 : pglActiveTextureARB(GL_TEXTURE0);
651 : glDisable(GL_TEXTURE_2D);
652 0 :
653 : CShaderProgramFFP_Gui_Base::Unbind();
654 0 : }
655 : };
656 0 :
657 0 : class CShaderProgramFFP_GuiGrayscale : public CShaderProgramFFP_Gui_Base
658 : {
659 0 : public:
660 0 : CShaderProgramFFP_GuiGrayscale() :
661 : CShaderProgramFFP_Gui_Base(STREAM_POS | STREAM_UV0)
662 : {
663 : }
664 :
665 : virtual void Bind()
666 0 : {
667 0 : CShaderProgramFFP_Gui_Base::Bind();
668 :
669 : /*
670 :
671 0 : For the main conversion, use GL_DOT3_RGB, which is defined as
672 : L = 4 * ((Arg0r - 0.5) * (Arg1r - 0.5)+
673 0 : (Arg0g - 0.5) * (Arg1g - 0.5)+
674 : (Arg0b - 0.5) * (Arg1b - 0.5))
675 : where each of the RGB components is given the value 'L'.
676 :
677 : Use the magical luminance formula
678 : L = 0.3R + 0.59G + 0.11B
679 : to calculate the greyscale value.
680 :
681 : But to work around the annoying "Arg0-0.5", we need to calculate
682 : Arg0+0.5. But we also need to scale it into the range 0.5-1.0, else
683 : Arg0>0.5 will be clamped to 1.0. So use GL_INTERPOLATE, which outputs:
684 : A0 * A2 + A1 * (1 - A2)
685 : and set A2 = 0.5, A1 = 1.0, and A0 = texture (i.e. interpolating halfway
686 : between the texture and {1,1,1}) giving
687 : A0/2 + 0.5
688 : and use that as Arg0.
689 :
690 : So L = 4*(A0/2 * (Arg1-.5))
691 : = 2 (Rx+Gy+Bz) (where Arg1 = {x+0.5, y+0.5, z+0.5})
692 : = 2x R + 2y G + 2z B
693 : = 0.3R + 0.59G + 0.11B
694 : so e.g. 2y = 0.59 = 2(Arg1g-0.5) => Arg1g = 0.59/2+0.5
695 : which fortunately doesn't get clamped.
696 :
697 : So, just implement that:
698 :
699 : */
700 :
701 : static const float GreyscaleDotColor[4] = {
702 : 0.3f / 2.f + 0.5f,
703 : 0.59f / 2.f + 0.5f,
704 : 0.11f / 2.f + 0.5f,
705 : 1.0f
706 : };
707 0 : static const float GreyscaleInterpColor0[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
708 : static const float GreyscaleInterpColor1[4] = { 0.5f, 0.5f, 0.5f, 1.0f };
709 :
710 : pglActiveTextureARB(GL_TEXTURE0);
711 : glEnable(GL_TEXTURE_2D);
712 :
713 0 : glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
714 0 :
715 : glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
716 0 : glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
717 0 :
718 : glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
719 0 :
720 : glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_CONSTANT);
721 0 : glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
722 0 : glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, GreyscaleInterpColor0);
723 :
724 0 : glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_PREVIOUS);
725 : glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR);
726 0 :
727 0 : glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
728 0 : glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
729 : glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
730 0 :
731 0 : glColor4fv(GreyscaleInterpColor1);
732 :
733 0 : pglActiveTextureARB(GL_TEXTURE1);
734 0 : glEnable(GL_TEXTURE_2D);
735 0 :
736 : glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
737 0 :
738 : glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
739 0 : glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
740 0 : glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
741 : glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
742 0 :
743 : glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_DOT3_RGB);
744 0 :
745 0 : // GL_DOT3_RGB requires GL_(EXT|ARB)_texture_env_dot3.
746 0 : // We currently don't bother implementing a fallback because it's
747 0 : // only lacking on Riva-class HW, but at least want the rest of the
748 : // game to run there without errors. Therefore, squelch the
749 0 : // OpenGL error that's raised if they aren't actually present.
750 : // Note: higher-level code checks for this extension, but
751 : // allows users the choice of continuing even if not present.
752 : ogl_SquelchError(GL_INVALID_ENUM);
753 :
754 : glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
755 :
756 : glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_CONSTANT);
757 : glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
758 0 : glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, GreyscaleDotColor);
759 :
760 0 : // To activate the second texture unit, we have to have some kind
761 : // of texture bound into it, but we don't actually use the texture data,
762 0 : // so bind a dummy texture
763 0 : g_Renderer.GetTextureManager().GetErrorTexture()->Bind(1);
764 0 : }
765 :
766 : virtual void Unbind()
767 : {
768 : glColor4f(1.f, 1.f, 1.f, 1.f);
769 0 :
770 0 : pglActiveTextureARB(GL_TEXTURE1);
771 : glDisable(GL_TEXTURE_2D);
772 0 :
773 : pglActiveTextureARB(GL_TEXTURE0);
774 0 : glDisable(GL_TEXTURE_2D);
775 :
776 0 : CShaderProgramFFP_Gui_Base::Unbind();
777 0 : }
778 : };
779 0 :
780 0 : class CShaderProgramFFP_GuiSolid : public CShaderProgramFFP_Gui_Base
781 : {
782 0 : public:
783 0 : using CShaderProgramFFP_Gui_Base::Uniform;
784 :
785 : CShaderProgramFFP_GuiSolid() :
786 : CShaderProgramFFP_Gui_Base(STREAM_POS)
787 : {
788 : }
789 :
790 : virtual void Uniform(Binding id, float v0, float v1, float v2, float v3)
791 0 : {
792 0 : if (id.second == ID_color)
793 : glColor4f(v0, v1, v2, v3);
794 : }
795 :
796 0 : virtual void Bind()
797 : {
798 0 : CShaderProgramFFP_Gui_Base::Bind();
799 0 :
800 0 : pglActiveTextureARB(GL_TEXTURE0);
801 : glDisable(GL_TEXTURE_2D);
802 0 : }
803 : };
804 0 :
805 : //////////////////////////////////////////////////////////////////////////
806 0 :
807 0 : /**
808 0 : * Common functionality for model rendering in the fixed renderpath.
809 : */
810 : class CShaderProgramFFP_Model_Base : public CShaderProgramFFP
811 : {
812 : protected:
813 : // Uniforms
814 : enum
815 : {
816 : ID_transform,
817 : ID_objectColor,
818 : ID_playerColor,
819 : ID_losTransform
820 : };
821 :
822 : bool m_IgnoreLos;
823 :
824 : public:
825 : CShaderProgramFFP_Model_Base(const CShaderDefines& defines, int streamflags)
826 : : CShaderProgramFFP(streamflags)
827 : {
828 : SetUniformIndex("transform", ID_transform);
829 : SetUniformIndex("losTransform", ID_losTransform);
830 :
831 0 : if (defines.GetInt("USE_OBJECTCOLOR"))
832 0 : SetUniformIndex("objectColor", ID_objectColor);
833 :
834 0 : if (defines.GetInt("USE_PLAYERCOLOR"))
835 0 : SetUniformIndex("playerColor", ID_playerColor);
836 :
837 0 : m_IgnoreLos = (defines.GetInt("IGNORE_LOS") != 0);
838 0 :
839 : // Texture units:
840 0 : SetUniformIndex("baseTex", 0);
841 0 : SetUniformIndex("losTex", 3);
842 : }
843 0 :
844 : virtual void Uniform(Binding id, const CMatrix3D& v)
845 : {
846 0 : if (id.second == ID_transform)
847 0 : glLoadMatrixf(&v._11);
848 0 : }
849 :
850 0 : virtual void Uniform(Binding id, float v0, float v1, float UNUSED(v2), float UNUSED(v3))
851 : {
852 0 : if (id.second == ID_losTransform)
853 0 : {
854 0 : pglActiveTextureARB(GL_TEXTURE3);
855 : GLfloat texgenS1[4] = { v0, 0, 0, v1 };
856 0 : GLfloat texgenT1[4] = { 0, 0, v0, v1 };
857 : glTexGenfv(GL_S, GL_OBJECT_PLANE, texgenS1);
858 0 : glTexGenfv(GL_T, GL_OBJECT_PLANE, texgenT1);
859 : }
860 0 : }
861 0 :
862 0 : virtual void Bind()
863 0 : {
864 0 : glMatrixMode(GL_PROJECTION);
865 : glPushMatrix();
866 0 : glLoadIdentity();
867 : glMatrixMode(GL_MODELVIEW);
868 0 : glPushMatrix();
869 :
870 0 : // -----------------------------------------------------------------------------
871 0 :
872 0 : pglActiveTextureARB(GL_TEXTURE3);
873 0 : glEnable(GL_TEXTURE_2D);
874 0 : glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
875 :
876 : if (m_IgnoreLos)
877 : {
878 0 : // RGB pass through
879 0 : glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
880 0 : glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
881 : glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
882 0 : }
883 : else
884 : {
885 0 : // Multiply RGB result up till now with LoS texture alpha channel
886 0 : glEnable(GL_TEXTURE_GEN_S);
887 0 : glEnable(GL_TEXTURE_GEN_T);
888 : glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
889 : glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
890 : // Overridden implementation of Uniform() sets GL_OBJECT_PLANE values
891 :
892 0 : glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
893 0 : glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
894 0 : glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
895 0 : glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
896 : glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_ALPHA);
897 : }
898 0 :
899 0 : // alpha pass through
900 0 : glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
901 0 : glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS);
902 0 : glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
903 :
904 : // -----------------------------------------------------------------------------
905 :
906 0 : BindClientStates();
907 0 : }
908 0 :
909 : virtual void Unbind()
910 : {
911 : UnbindClientStates();
912 0 :
913 0 : pglActiveTextureARB(GL_TEXTURE3);
914 : glDisable(GL_TEXTURE_2D);
915 0 :
916 : glDisable(GL_TEXTURE_GEN_S);
917 0 : glDisable(GL_TEXTURE_GEN_T);
918 :
919 0 : pglActiveTextureARB(GL_TEXTURE0);
920 0 :
921 : glMatrixMode(GL_PROJECTION);
922 0 : glPopMatrix();
923 0 : glMatrixMode(GL_MODELVIEW);
924 : glPopMatrix();
925 0 : }
926 : };
927 0 :
928 0 : /**
929 0 : * Basic non-recolored diffuse-textured model rendering.
930 0 : */
931 0 : class CShaderProgramFFP_Model : public CShaderProgramFFP_Model_Base
932 : {
933 : public:
934 : CShaderProgramFFP_Model(const CShaderDefines& defines)
935 : : CShaderProgramFFP_Model_Base(defines, STREAM_POS | STREAM_COLOR | STREAM_UV0)
936 : {
937 : }
938 :
939 : virtual void Bind()
940 : {
941 0 : // Set up texture environment for base pass - modulate texture and vertex color
942 : pglActiveTextureARB(GL_TEXTURE0);
943 : glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
944 : glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
945 0 : glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
946 : glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
947 : glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PRIMARY_COLOR);
948 0 : glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
949 0 :
950 0 : // Copy alpha channel from texture
951 0 : glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
952 0 : glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
953 0 : glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
954 0 :
955 : // The vertex color is scaled by 0.5 to permit overbrightness without clamping.
956 : // We therefore need to scale by 2.0 after the modulation, and before any
957 0 : // further clamping, to get the right color.
958 0 : float scale2[] = { 2.0f, 2.0f, 2.0f };
959 0 : glTexEnvfv(GL_TEXTURE_ENV, GL_RGB_SCALE, scale2);
960 :
961 : CShaderProgramFFP_Model_Base::Bind();
962 : }
963 :
964 0 : virtual void Unbind()
965 0 : {
966 : CShaderProgramFFP_Model_Base::Unbind();
967 0 :
968 0 : pglActiveTextureARB(GL_TEXTURE0);
969 :
970 0 : // Revert the scaling to default
971 : float scale1[] = { 1.0f, 1.0f, 1.0f };
972 0 : glTexEnvfv(GL_TEXTURE_ENV, GL_RGB_SCALE, scale1);
973 : }
974 0 : };
975 :
976 : /**
977 0 : * Player-coloring diffuse-textured model rendering.
978 0 : */
979 0 : class CShaderProgramFFP_ModelColor : public CShaderProgramFFP_Model_Base
980 : {
981 : public:
982 : CShaderProgramFFP_ModelColor(const CShaderDefines& defines)
983 : : CShaderProgramFFP_Model_Base(defines, STREAM_POS | STREAM_COLOR | STREAM_UV0)
984 : {
985 : }
986 :
987 : virtual void Uniform(Binding id, float v0, float v1, float v2, float v3)
988 : {
989 0 : if (id.second == ID_objectColor || id.second == ID_playerColor)
990 : {
991 : // (Player color and object color are mutually exclusive)
992 : float color[] = { v0, v1, v2, v3 };
993 0 : glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
994 : }
995 0 : }
996 :
997 : virtual void Bind()
998 0 : {
999 0 : // Player color uses a single pass with three texture environments
1000 : // Note: This uses ARB_texture_env_crossbar (which is checked in GameSetup),
1001 0 : // and it requires MAX_TEXTURE_IMAGE_UNITS >= 3 (which only excludes GF2MX/GF4MX)
1002 : //
1003 0 : // We calculate: Result = Color*Texture*(PlayerColor*(1-Texture.a) + 1.0*Texture.a)
1004 : // Algebra gives us:
1005 : // Result = (1 - ((1 - PlayerColor) * (1 - Texture.a)))*Texture*Color
1006 :
1007 : // TexEnv #0
1008 : pglActiveTextureARB(GL_TEXTURE0);
1009 : glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
1010 : glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
1011 : glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
1012 : glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_ONE_MINUS_SRC_ALPHA);
1013 : glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_CONSTANT);
1014 0 : glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_ONE_MINUS_SRC_COLOR);
1015 0 :
1016 0 : // Don't care about alpha; set it to something harmless
1017 0 : glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
1018 0 : glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
1019 0 : glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
1020 0 :
1021 : // TexEnv #1
1022 : pglActiveTextureARB(GL_TEXTURE1);
1023 0 : glEnable(GL_TEXTURE_2D);
1024 0 : glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
1025 0 : glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
1026 : glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
1027 : glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_ONE_MINUS_SRC_COLOR);
1028 0 : glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PRIMARY_COLOR);
1029 0 : glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
1030 0 :
1031 0 : // Don't care about alpha; set it to something harmless
1032 0 : glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
1033 0 : glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
1034 0 : glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
1035 0 :
1036 : // TexEnv #2
1037 : pglActiveTextureARB(GL_TEXTURE2);
1038 0 : glEnable(GL_TEXTURE_2D);
1039 0 : glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
1040 0 : glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
1041 : glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
1042 : glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
1043 0 : glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE0);
1044 0 : glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
1045 0 :
1046 0 : // Don't care about alpha; set it to something harmless
1047 0 : glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
1048 0 : glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
1049 0 : glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
1050 0 :
1051 : float color[] = { 1.0f, 1.0f, 1.0f, 1.0f };
1052 : glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
1053 0 :
1054 0 : // Scale colors at the end of all the computation (see CShaderProgramFFP_Model::Bind)
1055 0 : float scale[] = { 2.0f, 2.0f, 2.0f };
1056 : glTexEnvfv(GL_TEXTURE_ENV, GL_RGB_SCALE, scale);
1057 0 :
1058 0 : // Need to bind some kind of texture to enable the texture units.
1059 : // Unit 0 has baseTex, but the others need a texture.
1060 : g_Renderer.GetTextureManager().GetErrorTexture()->Bind(1);
1061 0 : g_Renderer.GetTextureManager().GetErrorTexture()->Bind(2);
1062 0 :
1063 : CShaderProgramFFP_Model_Base::Bind();
1064 : }
1065 :
1066 0 : virtual void Unbind()
1067 0 : {
1068 : CShaderProgramFFP_Model_Base::Unbind();
1069 0 :
1070 0 : pglActiveTextureARB(GL_TEXTURE2);
1071 : glDisable(GL_TEXTURE_2D);
1072 0 :
1073 : float scale[] = { 1.0f, 1.0f, 1.0f };
1074 0 : glTexEnvfv(GL_TEXTURE_ENV, GL_RGB_SCALE, scale);
1075 :
1076 0 : pglActiveTextureARB(GL_TEXTURE1);
1077 0 : glDisable(GL_TEXTURE_2D);
1078 :
1079 0 : pglActiveTextureARB(GL_TEXTURE0);
1080 0 : }
1081 : };
1082 0 :
1083 0 : /**
1084 : * Optionally-player-colored untextured model rendering.
1085 0 : */
1086 0 : class CShaderProgramFFP_ModelSolid : public CShaderProgramFFP_Model_Base
1087 : {
1088 : public:
1089 : CShaderProgramFFP_ModelSolid(const CShaderDefines& defines)
1090 : : CShaderProgramFFP_Model_Base(defines, STREAM_POS)
1091 : {
1092 : }
1093 :
1094 : virtual void Uniform(Binding id, float v0, float v1, float v2, float v3)
1095 : {
1096 0 : if (id.second == ID_playerColor)
1097 : {
1098 : float color[] = { v0, v1, v2, v3 };
1099 : glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
1100 0 : }
1101 : }
1102 0 :
1103 : virtual void Bind()
1104 0 : {
1105 0 : float color[] = { 1.0f, 1.0f, 1.0f, 1.0f };
1106 : glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
1107 0 :
1108 : pglActiveTextureARB(GL_TEXTURE0);
1109 0 : glEnable(GL_TEXTURE_2D);
1110 : glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
1111 0 : glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
1112 0 : glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_CONSTANT);
1113 : glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
1114 0 : glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
1115 0 : glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_CONSTANT);
1116 0 : glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
1117 0 :
1118 0 : CShaderProgramFFP_Model_Base::Bind();
1119 0 : }
1120 0 : };
1121 0 :
1122 0 : /**
1123 : * Plain unlit texture model rendering, for e.g. alpha-blended shadow casters.
1124 0 : */
1125 0 : class CShaderProgramFFP_ModelSolidTex : public CShaderProgramFFP_Model_Base
1126 : {
1127 : public:
1128 : CShaderProgramFFP_ModelSolidTex(const CShaderDefines& defines)
1129 : : CShaderProgramFFP_Model_Base(defines, STREAM_POS | STREAM_UV0)
1130 : {
1131 : }
1132 :
1133 : virtual void Bind()
1134 : {
1135 0 : pglActiveTextureARB(GL_TEXTURE0);
1136 : glEnable(GL_TEXTURE_2D);
1137 : glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1138 :
1139 0 : CShaderProgramFFP_Model_Base::Bind();
1140 : }
1141 0 : };
1142 0 :
1143 0 : //////////////////////////////////////////////////////////////////////////
1144 :
1145 0 : /*static*/ CShaderProgram* CShaderProgram::ConstructFFP(const std::string& id, const CShaderDefines& defines)
1146 0 : {
1147 : LOGWARNING("CShaderProgram::ConstructFFP: '%s': fixed pipeline is going to be removed soon, don't use its programs", id.c_str());
1148 : if (id == "dummy")
1149 : return new CShaderProgramFFP_Dummy();
1150 : if (id == "overlayline")
1151 0 : return new CShaderProgramFFP_OverlayLine(defines);
1152 : if (id == "gui_text")
1153 0 : return new CShaderProgramFFP_GuiText();
1154 0 : if (id == "gui_basic")
1155 0 : return new CShaderProgramFFP_GuiBasic();
1156 0 : if (id == "gui_add")
1157 0 : return new CShaderProgramFFP_GuiAdd();
1158 0 : if (id == "gui_grayscale")
1159 0 : return new CShaderProgramFFP_GuiGrayscale();
1160 0 : if (id == "gui_solid")
1161 0 : return new CShaderProgramFFP_GuiSolid();
1162 0 : if (id == "minimap")
1163 0 : return new CShaderProgramFFP_GuiMinimap(defines);
1164 0 : if (id == "solid")
1165 0 : return new CShaderProgramFFP_GuiSolid(); // works for non-GUI objects too
1166 0 : if (id == "model")
1167 0 : return new CShaderProgramFFP_Model(defines);
1168 0 : if (id == "model_color")
1169 0 : return new CShaderProgramFFP_ModelColor(defines);
1170 0 : if (id == "model_solid")
1171 0 : return new CShaderProgramFFP_ModelSolid(defines);
1172 0 : if (id == "model_solid_tex")
1173 0 : return new CShaderProgramFFP_ModelSolidTex(defines);
1174 0 :
1175 0 : LOGERROR("CShaderProgram::ConstructFFP: '%s': Invalid id", id.c_str());
1176 0 : debug_warn(L"CShaderProgram::ConstructFFP: Invalid id");
1177 0 : return NULL;
1178 0 : }
1179 0 :
1180 : #else // CONFIG2_GLES
1181 0 :
1182 0 : /*static*/ CShaderProgram* CShaderProgram::ConstructFFP(const std::string& UNUSED(id), const CShaderDefines& UNUSED(defines))
1183 : {
1184 : debug_warn(L"CShaderProgram::ConstructFFP: FFP not supported on this device");
1185 : return NULL;
1186 : }
1187 :
1188 : #endif // CONFIG2_GLES
|