22726e4d |
1 | /****************************************************************************** |
2 | * Arachnoid Graphics Plugin for Mupen64Plus |
3 | * http://bitbucket.org/wahrhaft/mupen64plus-video-arachnoid/ |
4 | * |
5 | * Copyright (C) 2007 Kristofer Karlsson, Rickard Niklasson |
6 | * |
7 | * This program is free software; you can redistribute it and/or |
8 | * modify it under the terms of the GNU General Public License |
9 | * as published by the Free Software Foundation; either version 2 |
10 | * of the License, or (at your option) any later version. |
11 | * |
12 | * This program is distributed in the hope that it will be useful, |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | * GNU General Public License for more details. |
16 | * |
17 | * You should have received a copy of the GNU General Public License |
18 | * along with this program; if not, write to the Free Software |
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
20 | *****************************************************************************/ |
21 | |
22 | #include <algorithm> |
23 | using std::max; |
24 | #include "AdvancedTexEnvCombiner.h" |
25 | #include "CombinerStructs.h" |
26 | #include "MultiTexturingExt.h" //glActiveTextureARB |
27 | #include "ExtensionChecker.h" |
28 | |
29 | #ifndef GL_ATI_texture_env_combine3 |
30 | #define GL_ATI_texture_env_combine3 |
31 | #define GL_ATI_texture_env_combine3 |
32 | #define GL_MODULATE_ADD_ATI 0x8744 |
33 | #define GL_MODULATE_SIGNED_ADD_ATI 0x8745 |
34 | #define GL_MODULATE_SUBTRACT_ATI 0x8746 |
35 | #endif //GL_ATI_texture_env_combine3 |
36 | |
37 | #ifndef GL_ATIX_texture_env_route |
38 | #define GL_ATIX_texture_env_route 1 |
39 | #define GL_SECONDARY_COLOR_ATIX 0x8747 |
40 | #define GL_TEXTURE_OUTPUT_RGB_ATIX 0x8748 |
41 | #define GL_TEXTURE_OUTPUT_ALPHA_ATIX 0x8749 |
42 | #endif // GL_ATIX_texture_env_route |
43 | |
44 | static TexEnvCombinerArg TexEnvArgs[] = |
45 | { |
46 | // CMB |
47 | { GL_PREVIOUS_ARB, GL_SRC_COLOR }, |
48 | // T0 |
49 | { GL_TEXTURE, GL_SRC_COLOR }, |
50 | // T1 |
51 | { GL_TEXTURE, GL_SRC_COLOR }, |
52 | // PRIM |
53 | { GL_CONSTANT_ARB, GL_SRC_COLOR }, |
54 | // SHADE |
55 | { GL_PRIMARY_COLOR_ARB, GL_SRC_COLOR }, |
56 | // ENV |
57 | { GL_CONSTANT_ARB, GL_SRC_COLOR }, |
58 | // CENTER |
59 | { GL_CONSTANT_ARB, GL_SRC_COLOR }, |
60 | // SCALE |
61 | { GL_CONSTANT_ARB, GL_SRC_COLOR }, |
62 | // CMBALPHA |
63 | { GL_PREVIOUS_ARB, GL_SRC_ALPHA }, |
64 | // T0ALPHA |
65 | { GL_TEXTURE, GL_SRC_ALPHA }, |
66 | // T1ALPHA |
67 | { GL_TEXTURE, GL_SRC_ALPHA }, |
68 | // PRIMALPHA |
69 | { GL_CONSTANT_ARB, GL_SRC_ALPHA }, |
70 | // SHADEALPHA |
71 | { GL_PRIMARY_COLOR_ARB, GL_SRC_ALPHA }, |
72 | // ENVALPHA |
73 | { GL_CONSTANT_ARB, GL_SRC_COLOR }, |
74 | // LODFRAC |
75 | { GL_CONSTANT_ARB, GL_SRC_COLOR }, |
76 | // PRIMLODFRAC |
77 | { GL_CONSTANT_ARB, GL_SRC_COLOR }, |
78 | // NOISE |
79 | { GL_TEXTURE, GL_SRC_COLOR }, |
80 | // K4 |
81 | { GL_CONSTANT_ARB, GL_SRC_COLOR }, |
82 | // K5 |
83 | { GL_CONSTANT_ARB, GL_SRC_COLOR }, |
84 | // ONE |
85 | { GL_CONSTANT_ARB, GL_SRC_COLOR }, |
86 | // ZERO |
87 | { GL_CONSTANT_ARB, GL_SRC_COLOR } |
88 | }; |
89 | |
90 | //----------------------------------------------------------------------------- |
91 | //! Constructor |
92 | //----------------------------------------------------------------------------- |
93 | AdvancedTexEnvCombiner::AdvancedTexEnvCombiner() |
94 | { |
95 | } |
96 | |
97 | //----------------------------------------------------------------------------- |
98 | //! Destructor |
99 | //----------------------------------------------------------------------------- |
100 | AdvancedTexEnvCombiner::~AdvancedTexEnvCombiner() |
101 | { |
102 | } |
103 | |
104 | //----------------------------------------------------------------------------- |
105 | //* Initialize |
106 | //! Checks if extensions are supported |
107 | //----------------------------------------------------------------------------- |
108 | void AdvancedTexEnvCombiner::initialize() |
109 | { |
110 | #ifdef HAVE_GLES |
111 | ARB_texture_env_combine = true; |
112 | ARB_texture_env_crossbar = true; |
113 | #else |
114 | ARB_texture_env_combine = isExtensionSupported( "GL_ARB_texture_env_combine" ); |
115 | ARB_texture_env_crossbar = isExtensionSupported( "GL_ARB_texture_env_crossbar" ); |
116 | #endif |
117 | ATI_texture_env_combine3 = isExtensionSupported( "GL_ATI_texture_env_combine3" ); |
118 | ATIX_texture_env_route = isExtensionSupported( "GL_ATIX_texture_env_route" ); |
119 | NV_texture_env_combine4 = isExtensionSupported( "GL_NV_texture_env_combine4" );; |
120 | |
121 | if ( ARB_texture_env_crossbar || NV_texture_env_combine4 || ATIX_texture_env_route ) |
122 | { |
123 | TexEnvArgs[TEXEL0].source = GL_TEXTURE0_ARB; |
124 | TexEnvArgs[TEXEL0_ALPHA].source = GL_TEXTURE0_ARB; |
125 | TexEnvArgs[TEXEL1].source = GL_TEXTURE1_ARB; |
126 | TexEnvArgs[TEXEL1_ALPHA].source = GL_TEXTURE1_ARB; |
127 | } |
128 | |
129 | if ( ATI_texture_env_combine3 ) |
130 | { |
131 | TexEnvArgs[ONE].source = GL_ONE; |
132 | TexEnvArgs[ZERO].source = GL_ZERO; |
133 | } |
134 | } |
135 | |
136 | //----------------------------------------------------------------------------- |
137 | //* Begin Texture Update |
138 | //! Disables all textures |
139 | //----------------------------------------------------------------------------- |
140 | void AdvancedTexEnvCombiner::beginTextureUpdate() |
141 | { |
142 | const int openGLMaxTextureUnits = 8; |
143 | |
144 | //Disable all texture channels |
145 | for (int i = 0; i <openGLMaxTextureUnits; i++) |
146 | { |
147 | glActiveTextureARB(GL_TEXTURE0_ARB + i); |
148 | glDisable(GL_TEXTURE_2D ); |
149 | } |
150 | } |
151 | |
152 | |
153 | //----------------------------------------------------------------------------- |
154 | //* End Texture Update |
155 | //! Enables selected textures in a texture environment |
156 | //! @param texEnv Texture environment with textures to be enabled |
157 | //----------------------------------------------------------------------------- |
158 | void AdvancedTexEnvCombiner::endTextureUpdate(TexEnvCombiner* texEnv) |
159 | { |
160 | //Enable texturing |
161 | for (int i = 0; i <texEnv->usedUnits; i++) |
162 | { |
163 | glActiveTextureARB( GL_TEXTURE0_ARB + i ); |
164 | glEnable( GL_TEXTURE_2D ); |
165 | } |
166 | } |
167 | |
168 | //----------------------------------------------------------------------------- |
169 | //* Set Texture Enviroment Colors |
170 | //! Sets texture enviorment colors for all active textures |
171 | //! @param texEnv Texture environment with textures that will be assigned colors |
172 | //----------------------------------------------------------------------------- |
173 | void AdvancedTexEnvCombiner::setTextureEnviromentColors(TexEnvCombiner* texEnv) |
174 | { |
175 | float color[4]; |
176 | |
177 | int openGLMaxTextureUnits = 8; |
178 | |
179 | for (int i = 0; i < openGLMaxTextureUnits; i++) |
180 | { |
181 | this->getCombinerColor( color, texEnv->color[i].constant, texEnv->alpha[i].constant ); |
182 | |
183 | glActiveTextureARB(GL_TEXTURE0_ARB + i); |
184 | glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &color[0]); |
185 | } |
186 | } |
187 | |
188 | //----------------------------------------------------------------------------- |
189 | //* Set Texture Enviroment |
190 | //! Sets texture environment for all active textures |
191 | //! @param texEnv Texture environment with input data which will be |
192 | //! sent to OpenGL using function "glTexEnvi" using ARB extensions |
193 | //----------------------------------------------------------------------------- |
194 | void AdvancedTexEnvCombiner::setTextureEnviroment(TexEnvCombiner* texEnv) |
195 | { |
196 | const int openGLMaxTextureUnits = 8; |
197 | |
198 | for (int i=0; i<openGLMaxTextureUnits; ++i) |
199 | { |
200 | glActiveTextureARB(GL_TEXTURE0_ARB + i); |
201 | |
202 | if ( (i < texEnv->usedUnits ) || (i < 2 && texEnv->usesT1) ) |
203 | { |
204 | glEnable( GL_TEXTURE_2D ); |
205 | glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB ); |
206 | glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, texEnv->color[i].combine ); |
207 | glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, texEnv->color[i].arg0.source ); |
208 | glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, texEnv->color[i].arg0.operand ); |
209 | glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, texEnv->color[i].arg1.source ); |
210 | glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, texEnv->color[i].arg1.operand ); |
211 | glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, texEnv->color[i].arg2.source ); |
212 | glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, texEnv->color[i].arg2.operand ); |
213 | glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, texEnv->alpha[i].combine ); |
214 | glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, texEnv->alpha[i].arg0.source ); |
215 | glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, texEnv->alpha[i].arg0.operand ); |
216 | glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, texEnv->alpha[i].arg1.source ); |
217 | glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, texEnv->alpha[i].arg1.operand ); |
218 | glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_ARB, texEnv->alpha[i].arg2.source ); |
219 | glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_ARB, texEnv->alpha[i].arg2.operand ); |
220 | } |
221 | else |
222 | { |
223 | glDisable(GL_TEXTURE_2D); |
224 | } |
225 | } |
226 | } |
227 | |
228 | //----------------------------------------------------------------------------- |
229 | //* Create New Texture Enviornment |
230 | //! Allocates a new texture enviroment |
231 | //! @param[in] colorCombiner How to combine and get a color |
232 | //! @param[in] alphaCombiner How to combine and get an alpha value |
233 | //! @return The texture enviroment that was created |
234 | //----------------------------------------------------------------------------- |
235 | TexEnvCombiner* AdvancedTexEnvCombiner::createNewTextureEnviroment(Combiner* colorCombiner, Combiner *alphaCombiner) |
236 | { |
237 | TexEnvCombiner* envCombiner = new TexEnvCombiner(); |
238 | |
239 | int curUnit; |
240 | |
241 | const int openGLMaxTextureUnits = 8; |
242 | |
243 | //For each texture unit |
244 | for (int i = 0; i < openGLMaxTextureUnits; i++) |
245 | { |
246 | envCombiner->color[i].combine = GL_REPLACE; |
247 | envCombiner->alpha[i].combine = GL_REPLACE; |
248 | |
249 | SetColorCombinerValues( i, arg0, GL_PREVIOUS_ARB, GL_SRC_COLOR ); |
250 | SetColorCombinerValues( i, arg1, GL_PREVIOUS_ARB, GL_SRC_COLOR ); |
251 | SetColorCombinerValues( i, arg2, GL_PREVIOUS_ARB, GL_SRC_COLOR ); |
252 | envCombiner->color[i].constant = COMBINED; |
253 | envCombiner->color[i].outputTexture = GL_TEXTURE0_ARB + i; |
254 | |
255 | SetAlphaCombinerValues( i, arg0, GL_PREVIOUS_ARB, GL_SRC_ALPHA ); |
256 | SetAlphaCombinerValues( i, arg1, GL_PREVIOUS_ARB, GL_SRC_ALPHA ); |
257 | SetAlphaCombinerValues( i, arg2, GL_PREVIOUS_ARB, GL_SRC_ALPHA ); |
258 | envCombiner->alpha[i].constant = COMBINED; |
259 | envCombiner->alpha[i].outputTexture = GL_TEXTURE0_ARB + i; |
260 | } |
261 | |
262 | envCombiner->usesT0 = false; |
263 | envCombiner->usesT1 = false; |
264 | |
265 | envCombiner->vertex.color = COMBINED; |
266 | envCombiner->vertex.secondaryColor = COMBINED; |
267 | envCombiner->vertex.alpha = COMBINED; |
268 | |
269 | curUnit = 0; |
270 | |
271 | for (int i=0; i<alphaCombiner->numStages; i++) |
272 | { |
273 | for (int j = 0; j < alphaCombiner->stage[i].numOps; j++) |
274 | { |
275 | float sb = 0.0f; |
276 | |
277 | if (alphaCombiner->stage[i].op[j].param1 == PRIMITIVE_ALPHA) |
278 | sb = m_primColor[3]; |
279 | else if (alphaCombiner->stage[i].op[j].param1 == ENV_ALPHA) |
280 | sb = m_envColor[3]; |
281 | else if (alphaCombiner->stage[i].op[j].param1 == ONE) |
282 | sb = 1.0f; |
283 | |
284 | if (((alphaCombiner->stage[i].numOps - j) >= 3) && |
285 | (alphaCombiner->stage[i].op[j].op == SUB) && |
286 | (alphaCombiner->stage[i].op[j+1].op == MUL) && |
287 | (alphaCombiner->stage[i].op[j+2].op == ADD) && |
288 | (sb > 0.5f) && |
289 | (ARB_texture_env_combine)) |
290 | { |
291 | envCombiner->usesT0 |= alphaCombiner->stage[i].op[j].param1 == TEXEL0_ALPHA; |
292 | envCombiner->usesT1 |= alphaCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA; |
293 | |
294 | if (alphaCombiner->stage[i].op[j].param1 == ONE) |
295 | { |
296 | SetAlphaCombinerValues( curUnit, arg0, envCombiner->alpha[curUnit].arg0.source, GL_ONE_MINUS_SRC_ALPHA ); |
297 | } |
298 | else |
299 | { |
300 | envCombiner->alpha[curUnit].combine = GL_SUBTRACT_ARB; |
301 | SetAlphaCombinerValues( curUnit, arg1, envCombiner->alpha[curUnit].arg0.source, GL_SRC_ALPHA ); |
302 | SetAlphaCombinerArg( curUnit, arg0, alphaCombiner->stage[i].op[j].param1 ); |
303 | |
304 | curUnit++; |
305 | } |
306 | |
307 | j++; |
308 | |
309 | envCombiner->usesT0 |= alphaCombiner->stage[i].op[j].param1 == TEXEL0_ALPHA; |
310 | envCombiner->usesT1 |= alphaCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA; |
311 | |
312 | envCombiner->alpha[curUnit].combine = GL_MODULATE; |
313 | SetAlphaCombinerArg( curUnit, arg1, alphaCombiner->stage[i].op[j].param1 ); |
314 | |
315 | curUnit++; |
316 | j++; |
317 | |
318 | envCombiner->usesT0 |= alphaCombiner->stage[i].op[j].param1 == TEXEL0_ALPHA; |
319 | envCombiner->usesT1 |= alphaCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA; |
320 | |
321 | envCombiner->alpha[curUnit].combine = GL_SUBTRACT_ARB; |
322 | SetAlphaCombinerArg( curUnit, arg0, alphaCombiner->stage[i].op[j].param1 ); |
323 | |
324 | curUnit++; |
325 | } |
326 | else |
327 | { |
328 | envCombiner->usesT0 |= alphaCombiner->stage[i].op[j].param1 == TEXEL0_ALPHA; |
329 | envCombiner->usesT1 |= alphaCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA; |
330 | |
331 | switch (alphaCombiner->stage[i].op[j].op) |
332 | { |
333 | case LOAD: |
334 | if (!(ARB_texture_env_crossbar || NV_texture_env_combine4) && |
335 | (alphaCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA) && (curUnit == 0)) |
336 | curUnit++; |
337 | |
338 | envCombiner->alpha[curUnit].combine = GL_REPLACE; |
339 | |
340 | SetAlphaCombinerArg( curUnit, arg0, alphaCombiner->stage[i].op[j].param1 ); |
341 | break; |
342 | case SUB: |
343 | if (!ARB_texture_env_combine) |
344 | break; |
345 | |
346 | if (!(ARB_texture_env_crossbar || NV_texture_env_combine4) && |
347 | (alphaCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA) && (curUnit == 0)) |
348 | curUnit++; |
349 | |
350 | if ((j > 0) && (alphaCombiner->stage[i].op[j-1].op == LOAD) && (alphaCombiner->stage[i].op[j-1].param1 == ONE)) |
351 | { |
352 | SetAlphaCombinerArg( curUnit, arg0, alphaCombiner->stage[i].op[j].param1 ); |
353 | envCombiner->alpha[curUnit].arg0.operand = GL_ONE_MINUS_SRC_ALPHA; |
354 | } |
355 | else if ((ATI_texture_env_combine3) && (curUnit > 0) && (envCombiner->alpha[curUnit - 1].combine == GL_MODULATE)) |
356 | { |
357 | curUnit--; |
358 | SetAlphaCombinerValues( curUnit, arg2, envCombiner->alpha[curUnit].arg1.source, envCombiner->alpha[curUnit].arg1.operand ); |
359 | envCombiner->alpha[curUnit].combine = GL_MODULATE_SUBTRACT_ATI; |
360 | SetAlphaCombinerArg( curUnit, arg1, alphaCombiner->stage[i].op[j].param1 ); |
361 | curUnit++; |
362 | } |
363 | else |
364 | { |
365 | envCombiner->alpha[curUnit].combine = GL_SUBTRACT_ARB; |
366 | SetAlphaCombinerArg( curUnit, arg1, alphaCombiner->stage[i].op[j].param1 ); |
367 | curUnit++; |
368 | } |
369 | break; |
370 | case MUL: |
371 | if (!( ARB_texture_env_crossbar || NV_texture_env_combine4) && |
372 | (alphaCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA) && (curUnit == 0)) |
373 | curUnit++; |
374 | |
375 | envCombiner->alpha[curUnit].combine = GL_MODULATE; |
376 | |
377 | SetAlphaCombinerArg( curUnit, arg1, alphaCombiner->stage[i].op[j].param1 ); |
378 | curUnit++; |
379 | break; |
380 | case ADD: |
381 | if (!(ARB_texture_env_crossbar || NV_texture_env_combine4) && |
382 | (alphaCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA) && (curUnit == 0)) |
383 | curUnit++; |
384 | |
385 | if ((ATI_texture_env_combine3) && (curUnit > 0) && (envCombiner->alpha[curUnit - 1].combine == GL_MODULATE)) |
386 | { |
387 | curUnit--; |
388 | SetAlphaCombinerValues( curUnit, arg2, envCombiner->alpha[curUnit].arg1.source, envCombiner->alpha[curUnit].arg1.operand ); |
389 | envCombiner->alpha[curUnit].combine = GL_MODULATE_ADD_ATI; |
390 | SetAlphaCombinerArg( curUnit, arg1, alphaCombiner->stage[i].op[j].param1 ); |
391 | } |
392 | else |
393 | { |
394 | envCombiner->alpha[curUnit].combine = GL_ADD; |
395 | SetAlphaCombinerArg( curUnit, arg1, alphaCombiner->stage[i].op[j].param1 ); |
396 | } |
397 | curUnit++; |
398 | break; |
399 | case INTERPOLATE: |
400 | envCombiner->usesT0 |= (alphaCombiner->stage[i].op[j].param2 == TEXEL0_ALPHA) || (alphaCombiner->stage[i].op[j].param3 == TEXEL0_ALPHA); |
401 | envCombiner->usesT1 |= (alphaCombiner->stage[i].op[j].param2 == TEXEL1_ALPHA) || (alphaCombiner->stage[i].op[j].param3 == TEXEL1_ALPHA); |
402 | |
403 | envCombiner->alpha[curUnit].combine = GL_INTERPOLATE_ARB; |
404 | |
405 | SetAlphaCombinerArg( curUnit, arg0, alphaCombiner->stage[i].op[j].param1 ); |
406 | SetAlphaCombinerArg( curUnit, arg1, alphaCombiner->stage[i].op[j].param2 ); |
407 | SetAlphaCombinerArg( curUnit, arg2, alphaCombiner->stage[i].op[j].param3 ); |
408 | |
409 | curUnit++; |
410 | break; |
411 | } |
412 | } |
413 | } |
414 | } |
415 | |
416 | envCombiner->usedUnits = max( curUnit, 1 ); |
417 | |
418 | curUnit = 0; |
419 | for (int i = 0; i < colorCombiner->numStages; i++) |
420 | { |
421 | for (int j = 0; j < colorCombiner->stage[i].numOps; j++) |
422 | { |
423 | float sb = 0.0f; |
424 | |
425 | if (colorCombiner->stage[i].op[j].param1 == PRIMITIVE) |
426 | sb = (m_primColor[0] + m_primColor[2] + m_primColor[1]) / 3.0f; |
427 | else if (colorCombiner->stage[i].op[j].param1 == ENVIRONMENT) |
428 | sb = (m_envColor[0] + m_envColor[2] + m_envColor[1]) / 3.0f; |
429 | |
430 | // This helps with problems caused by not using signed values between texture units |
431 | if (((colorCombiner->stage[i].numOps - j) >= 3) && |
432 | (colorCombiner->stage[i].op[j].op == SUB) && |
433 | (colorCombiner->stage[i].op[j+1].op == MUL) && |
434 | (colorCombiner->stage[i].op[j+2].op == ADD) && |
435 | (sb > 0.5f) && |
436 | (ARB_texture_env_combine)) |
437 | { |
438 | envCombiner->usesT0 |= ((colorCombiner->stage[i].op[j].param1 == TEXEL0) || (colorCombiner->stage[i].op[j].param1 == TEXEL0_ALPHA)); |
439 | envCombiner->usesT1 |= ((colorCombiner->stage[i].op[j].param1 == TEXEL1) || (colorCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA)); |
440 | |
441 | envCombiner->color[curUnit].combine = GL_SUBTRACT_ARB; |
442 | SetColorCombinerValues( curUnit, arg1, envCombiner->color[curUnit].arg0.source, envCombiner->color[curUnit].arg0.operand ); |
443 | SetColorCombinerArg( curUnit, arg0, colorCombiner->stage[i].op[j].param1 ); |
444 | |
445 | curUnit++; |
446 | j++; |
447 | |
448 | envCombiner->usesT0 |= ((colorCombiner->stage[i].op[j].param1 == TEXEL0) || (colorCombiner->stage[i].op[j].param1 == TEXEL0_ALPHA)); |
449 | envCombiner->usesT1 |= ((colorCombiner->stage[i].op[j].param1 == TEXEL1) || (colorCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA)); |
450 | |
451 | envCombiner->color[curUnit].combine = GL_MODULATE; |
452 | SetColorCombinerArg( curUnit, arg1, colorCombiner->stage[i].op[j].param1 ); |
453 | |
454 | curUnit++; |
455 | j++; |
456 | |
457 | envCombiner->usesT0 |= ((colorCombiner->stage[i].op[j].param1 == TEXEL0) || (colorCombiner->stage[i].op[j].param1 == TEXEL0_ALPHA)); |
458 | envCombiner->usesT1 |= ((colorCombiner->stage[i].op[j].param1 == TEXEL1) || (colorCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA)); |
459 | |
460 | envCombiner->color[curUnit].combine = GL_SUBTRACT_ARB; |
461 | SetColorCombinerArg( curUnit, arg0, colorCombiner->stage[i].op[j].param1 ); |
462 | |
463 | curUnit++; |
464 | } |
465 | else |
466 | { |
467 | envCombiner->usesT0 |= ((colorCombiner->stage[i].op[j].param1 == TEXEL0) || (colorCombiner->stage[i].op[j].param1 == TEXEL0_ALPHA)); |
468 | envCombiner->usesT1 |= ((colorCombiner->stage[i].op[j].param1 == TEXEL1) || (colorCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA)); |
469 | |
470 | switch (colorCombiner->stage[i].op[j].op) |
471 | { |
472 | case LOAD: |
473 | if (!( ARB_texture_env_crossbar || NV_texture_env_combine4) && |
474 | ((colorCombiner->stage[i].op[j].param1 == TEXEL1) || (colorCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA)) && (curUnit == 0)) |
475 | curUnit++; |
476 | |
477 | envCombiner->color[curUnit].combine = GL_REPLACE; |
478 | |
479 | SetColorCombinerArg( curUnit, arg0, colorCombiner->stage[i].op[j].param1 ); |
480 | break; |
481 | case SUB: |
482 | if (!ARB_texture_env_combine) |
483 | break; |
484 | |
485 | if (!(ARB_texture_env_crossbar || NV_texture_env_combine4) && |
486 | ((colorCombiner->stage[i].op[j].param1 == TEXEL1) || (colorCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA)) && (curUnit == 0)) |
487 | curUnit++; |
488 | |
489 | if ((j > 0) && (colorCombiner->stage[i].op[j-1].op == LOAD) && (colorCombiner->stage[i].op[j-1].param1 == ONE)) |
490 | { |
491 | SetColorCombinerArg( curUnit, arg0, colorCombiner->stage[i].op[j].param1 ); |
492 | envCombiner->color[curUnit].arg0.operand = GL_ONE_MINUS_SRC_COLOR; |
493 | } |
494 | else if (( ATI_texture_env_combine3) && (curUnit > 0) && (envCombiner->color[curUnit - 1].combine == GL_MODULATE)) |
495 | { |
496 | curUnit--; |
497 | SetColorCombinerValues( curUnit, arg2, envCombiner->color[curUnit].arg1.source, envCombiner->color[curUnit].arg1.operand ); |
498 | envCombiner->color[curUnit].combine = GL_MODULATE_SUBTRACT_ATI; |
499 | SetColorCombinerArg( curUnit, arg1, colorCombiner->stage[i].op[j].param1 ); |
500 | curUnit++; |
501 | } |
502 | else |
503 | { |
504 | envCombiner->color[curUnit].combine = GL_SUBTRACT_ARB; |
505 | SetColorCombinerArg( curUnit, arg1, colorCombiner->stage[i].op[j].param1 ); |
506 | curUnit++; |
507 | } |
508 | break; |
509 | case MUL: |
510 | if (!( ARB_texture_env_crossbar || NV_texture_env_combine4) && |
511 | ((colorCombiner->stage[i].op[j].param1 == TEXEL1) || (colorCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA)) && (curUnit == 0)) |
512 | curUnit++; |
513 | |
514 | envCombiner->color[curUnit].combine = GL_MODULATE; |
515 | |
516 | SetColorCombinerArg( curUnit, arg1, colorCombiner->stage[i].op[j].param1 ); |
517 | curUnit++; |
518 | break; |
519 | case ADD: |
520 | if (!( ARB_texture_env_crossbar || NV_texture_env_combine4) && |
521 | ((colorCombiner->stage[i].op[j].param1 == TEXEL1) || (colorCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA)) && (curUnit == 0)) |
522 | curUnit++; |
523 | |
524 | // ATI_texture_env_combine3 adds GL_MODULATE_ADD_ATI; saves texture units |
525 | if (( ATI_texture_env_combine3) && (curUnit > 0) && (envCombiner->color[curUnit - 1].combine == GL_MODULATE)) |
526 | { |
527 | curUnit--; |
528 | SetColorCombinerValues( curUnit, arg2, envCombiner->color[curUnit].arg1.source, envCombiner->color[curUnit].arg1.operand ); |
529 | envCombiner->color[curUnit].combine = GL_MODULATE_ADD_ATI; |
530 | SetColorCombinerArg( curUnit, arg1, colorCombiner->stage[i].op[j].param1 ); |
531 | } |
532 | else |
533 | { |
534 | envCombiner->color[curUnit].combine = GL_ADD; |
535 | SetColorCombinerArg( curUnit, arg1, colorCombiner->stage[i].op[j].param1 ); |
536 | } |
537 | curUnit++; |
538 | break; |
539 | case INTERPOLATE: |
540 | envCombiner->usesT0 |= (colorCombiner->stage[i].op[j].param2 == TEXEL0) || (colorCombiner->stage[i].op[j].param3 == TEXEL0) || (colorCombiner->stage[i].op[j].param3 == TEXEL0_ALPHA); |
541 | envCombiner->usesT1 |= (colorCombiner->stage[i].op[j].param2 == TEXEL1) || (colorCombiner->stage[i].op[j].param3 == TEXEL1) || (colorCombiner->stage[i].op[j].param3 == TEXEL1_ALPHA); |
542 | |
543 | if (!( ARB_texture_env_crossbar || NV_texture_env_combine4) && |
544 | ((colorCombiner->stage[i].op[j].param1 == TEXEL1) || (colorCombiner->stage[i].op[j].param2 == TEXEL1) || (colorCombiner->stage[i].op[j].param3 == TEXEL1) || (colorCombiner->stage[i].op[j].param3 == TEXEL1_ALPHA)) && (curUnit == 0)) |
545 | { |
546 | if (colorCombiner->stage[i].op[j].param1 == TEXEL0) |
547 | { |
548 | envCombiner->color[curUnit].combine = GL_REPLACE; |
549 | SetColorCombinerArg( curUnit, arg0, colorCombiner->stage[i].op[j].param1 ); |
550 | colorCombiner->stage[i].op[j].param1 = COMBINED; |
551 | } |
552 | if (colorCombiner->stage[i].op[j].param2 == TEXEL0) |
553 | { |
554 | envCombiner->color[curUnit].combine = GL_REPLACE; |
555 | SetColorCombinerArg( curUnit, arg0, colorCombiner->stage[i].op[j].param2 ) |
556 | |
557 | colorCombiner->stage[i].op[j].param2 = COMBINED; |
558 | } |
559 | if (colorCombiner->stage[i].op[j].param3 == TEXEL0) |
560 | { |
561 | envCombiner->color[curUnit].combine = GL_REPLACE; |
562 | SetColorCombinerArg( curUnit, arg0, colorCombiner->stage[i].op[j].param3 ); |
563 | colorCombiner->stage[i].op[j].param3 = COMBINED; |
564 | } |
565 | if (colorCombiner->stage[i].op[j].param3 == TEXEL0_ALPHA) |
566 | { |
567 | envCombiner->color[curUnit].combine = GL_REPLACE; |
568 | SetColorCombinerArg( curUnit, arg0, colorCombiner->stage[i].op[j].param3 ); |
569 | colorCombiner->stage[i].op[j].param3 = COMBINED_ALPHA; |
570 | } |
571 | |
572 | curUnit++; |
573 | } |
574 | |
575 | envCombiner->color[curUnit].combine = GL_INTERPOLATE_ARB; |
576 | |
577 | SetColorCombinerArg( curUnit, arg0, colorCombiner->stage[i].op[j].param1 ); |
578 | SetColorCombinerArg( curUnit, arg1, colorCombiner->stage[i].op[j].param2 ); |
579 | SetColorCombinerArg( curUnit, arg2, colorCombiner->stage[i].op[j].param3 ); |
580 | |
581 | curUnit++; |
582 | break; |
583 | } |
584 | } |
585 | } |
586 | } |
587 | |
588 | envCombiner->usedUnits = max( (unsigned short)curUnit, envCombiner->usedUnits ); |
589 | return envCombiner; |
590 | } |