1 // regcombine.cpp
2 //
3 // Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
4 //
5 // Some functions for setting up the nVidia register combiners
6 // extension for pretty rendering effects.
7 //
8 // This program is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU General Public License
10 // as published by the Free Software Foundation; either version 2
11 // of the License, or (at your option) any later version.
12
13 #include "gl.h"
14 #include "glext.h"
15 #include "regcombine.h"
16
17 #if 0
18 namespace rc
19 {
20 enum {
21 Combiner0 = GL_COMBINER0_NV,
22 Combiner1 = GL_COMBINER1_NV,
23 Combiner2 = GL_COMBINER2_NV,
24 Combiner3 = GL_COMBINER3_NV,
25 };
26
27 enum {
28 A = GL_VARIABLE_A_NV,
29 B = GL_VARIABLE_B_NV,
30 C = GL_VARIABLE_C_NV,
31 D = GL_VARIABLE_D_NV,
32 E = GL_VARIABLE_E_NV,
33 F = GL_VARIABLE_F_NV,
34 G = GL_VARIABLE_G_NV,
35 };
36
37 enum {
38 RGBPortion = GL_RGB,
39 AlphaPortion = GL_ALPHA,
40 BluePortion = GL_BLUE,
41 };
42
43 enum {
44 UnsignedIdentity = GL_UNSIGNED_IDENTITY_NV,
45 UnsignedInvert = GL_UNSIGNED_INVERT_NV,
46 ExpandNormal = GL_EXPAND_NORMAL_NV,
47 };
48 };
49 #endif
50
51 namespace rc
52 {
53 void parameter(GLenum, Color);
54 };
55
56
parameter(GLenum which,Color color)57 void rc::parameter(GLenum which, Color color)
58 {
59 float f[4];
60 f[0] = color.red();
61 f[1] = color.green();
62 f[2] = color.blue();
63 f[3] = color.alpha();
64 glx::glCombinerParameterfvNV(which, f);
65 }
66
SetupCombinersBumpMap(Texture & bumpTexture,Texture & normalizationTexture,Color ambientColor)67 void SetupCombinersBumpMap(Texture& bumpTexture,
68 Texture& normalizationTexture,
69 Color ambientColor)
70 {
71 glEnable(GL_REGISTER_COMBINERS_NV);
72
73 glDisable(GL_LIGHTING);
74 glx::glActiveTextureARB(GL_TEXTURE1_ARB);
75 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
76 normalizationTexture.bind();
77
78 glx::glActiveTextureARB(GL_TEXTURE0_ARB);
79 glEnable(GL_TEXTURE_2D);
80 bumpTexture.bind();
81
82 // Just a single combiner stage required . . .
83 glx::glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, 1);
84
85 float ambient[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
86 ambient[0] = ambientColor.red();
87 ambient[1] = ambientColor.green();
88 ambient[2] = ambientColor.blue();
89 glx::glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, ambient);
90
91 // Compute N dot L in the RGB portion of combiner 0
92 // Load register A with a normal N from the normal map
93 glx::glCombinerInputNV(GL_COMBINER0_NV, GL_RGB,
94 GL_VARIABLE_A_NV, GL_TEXTURE0_ARB,
95 GL_EXPAND_NORMAL_NV, GL_RGB);
96
97 // Load register B with the normalized light direction L
98 glx::glCombinerInputNV(GL_COMBINER0_NV, GL_RGB,
99 GL_VARIABLE_B_NV, GL_TEXTURE1_ARB,
100 GL_EXPAND_NORMAL_NV, GL_RGB);
101
102 // Compute N dot L
103 glx::glCombinerOutputNV(GL_COMBINER0_NV, GL_RGB,
104 GL_SPARE0_NV, GL_DISCARD_NV, GL_DISCARD_NV,
105 GL_NONE, GL_NONE, GL_TRUE, GL_FALSE, GL_FALSE);
106
107 // Compute the self-shadowing term in the alpha portion of combiner 0
108 // A = 1
109 glx::glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_A_NV,
110 GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_ALPHA);
111 // B = L.z
112 glx::glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_B_NV,
113 GL_TEXTURE1_ARB, GL_EXPAND_NORMAL_NV, GL_BLUE);
114 // C = 1
115 glx::glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_C_NV,
116 GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_ALPHA);
117 // D = L.z
118 glx::glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_D_NV,
119 GL_TEXTURE1_ARB, GL_EXPAND_NORMAL_NV, GL_BLUE);
120
121 // Create a steep ramp function for self-shadowing
122 // SPARE0 = 4*(A*B+C*D) = 4*(1*L.z + 1*L.z) = 8 * L.z
123 glx::glCombinerOutputNV(GL_COMBINER0_NV, GL_ALPHA,
124 GL_DISCARD_NV, GL_DISCARD_NV, GL_SPARE0_NV,
125 GL_SCALE_BY_FOUR_NV, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE);
126
127 // A = SPARE0_alpha = per-pixel self-shadowing term
128 glx::glFinalCombinerInputNV(GL_VARIABLE_A_NV,
129 GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
130 glx::glFinalCombinerInputNV(GL_VARIABLE_B_NV,
131 GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
132 // C = zero
133 glx::glFinalCombinerInputNV(GL_VARIABLE_C_NV,
134 GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
135 // D = ambient color
136 glx::glFinalCombinerInputNV(GL_VARIABLE_D_NV,
137 GL_CONSTANT_COLOR0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
138 // G = diffuse illumination contribution = L dot N
139 glx::glFinalCombinerInputNV(GL_VARIABLE_G_NV,
140 GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
141 }
142
143
144 // Set up register combiners for per-pixel diffuse lighting, with a base
145 // texture, ambient color, material color, and normal cube map. We could use
146 // just a plain old color cube map, but we use a normal map instead for
147 // consistency with bump mapped surfaces. Only one pass with a single
148 // combiner is required.
SetupCombinersSmooth(Texture & baseTexture,Texture & normalizationTexture,Color ambientColor,bool invert)149 void SetupCombinersSmooth(Texture& baseTexture,
150 Texture& normalizationTexture,
151 Color ambientColor,
152 bool invert)
153 {
154 glEnable(GL_REGISTER_COMBINERS_NV);
155
156 glDisable(GL_LIGHTING);
157 glx::glActiveTextureARB(GL_TEXTURE1_ARB);
158 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
159 normalizationTexture.bind();
160 glx::glActiveTextureARB(GL_TEXTURE0_ARB);
161 glEnable(GL_TEXTURE_2D);
162 baseTexture.bind();
163
164 // Just a single combiner stage required . . .
165 glx::glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, 1);
166
167 float ambient[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
168 ambient[0] = ambientColor.red();
169 ambient[1] = ambientColor.green();
170 ambient[2] = ambientColor.blue();
171 glx::glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, ambient);
172
173 // A = primary color
174 glx::glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_A_NV,
175 GL_PRIMARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV,
176 GL_RGB);
177 // B = base texture color
178 glx::glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_B_NV,
179 GL_TEXTURE0_ARB, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
180 // SPARE1_rgb = primary * texture
181 glx::glCombinerOutputNV(GL_COMBINER0_NV, GL_RGB,
182 GL_SPARE1_NV, GL_DISCARD_NV, GL_DISCARD_NV,
183 GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE);
184
185 // A = 1
186 glx::glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_A_NV,
187 GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_ALPHA);
188 // B = L.z
189 glx::glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_B_NV,
190 GL_TEXTURE1_ARB, GL_EXPAND_NORMAL_NV,
191 GL_BLUE);
192 // SPARE0_alpha = 1 * L.z
193 glx::glCombinerOutputNV(GL_COMBINER0_NV, GL_ALPHA,
194 GL_SPARE0_NV, GL_DISCARD_NV, GL_DISCARD_NV,
195 GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE);
196
197 // E = SPARE1_rgb = base texture color * primary
198 glx::glFinalCombinerInputNV(GL_VARIABLE_E_NV,
199 GL_SPARE1_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
200 // F = ambient color
201 glx::glFinalCombinerInputNV(GL_VARIABLE_F_NV,
202 GL_CONSTANT_COLOR0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
203 // A = SPARE1_rgb = base texture color * primary
204 glx::glFinalCombinerInputNV(GL_VARIABLE_A_NV,
205 GL_SPARE1_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
206 // B = SPARE0_alpha = L.z
207 glx::glFinalCombinerInputNV(GL_VARIABLE_B_NV,
208 GL_SPARE0_NV,
209 invert ? GL_UNSIGNED_INVERT_NV : GL_UNSIGNED_IDENTITY_NV,
210 GL_ALPHA);
211 // C = zero
212 glx::glFinalCombinerInputNV(GL_VARIABLE_C_NV,
213 GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
214 // D = SPARE1_rgb = E*F = texture * primary * ambient color
215 glx::glFinalCombinerInputNV(GL_VARIABLE_D_NV,
216 GL_E_TIMES_F_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
217 // G = 1
218 glx::glFinalCombinerInputNV(GL_VARIABLE_G_NV,
219 GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_ALPHA);
220
221 }
222
223
224 // Normal map should be bound as texture 1 and the base map should be bound
225 // as texture 0.
SetupCombinersDecalAndBumpMap(Texture &,Color ambientColor,Color diffuseColor)226 void SetupCombinersDecalAndBumpMap(Texture& /*bumpTexture*/,
227 Color ambientColor,
228 Color diffuseColor)
229 {
230 glEnable(GL_REGISTER_COMBINERS_NV);
231 glx::glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, 2);
232
233 rc::parameter(GL_CONSTANT_COLOR0_NV, ambientColor);
234 rc::parameter(GL_CONSTANT_COLOR1_NV, diffuseColor);
235
236 // Compute N dot L in the RGB portion of combiner 0
237 // Load register A with a normal N from the bump map
238 glx::glCombinerInputNV(GL_COMBINER0_NV, GL_RGB,
239 GL_VARIABLE_A_NV, GL_TEXTURE1_ARB,
240 GL_EXPAND_NORMAL_NV, GL_RGB);
241
242 // Load register B with the primary color, which contains the surface
243 // space light direction L. Because the color is linearly interpolated
244 // across triangles, the direction may become denormalized; however, in
245 // Celestia, planet surfaces are tessellated finely enough that this
246 // is not a problem.
247 glx::glCombinerInputNV(GL_COMBINER0_NV, GL_RGB,
248 GL_VARIABLE_B_NV, GL_PRIMARY_COLOR_NV,
249 GL_EXPAND_NORMAL_NV, GL_RGB);
250
251 // Product C*D computes diffuse color * texture
252 glx::glCombinerInputNV(GL_COMBINER0_NV, GL_RGB,
253 GL_VARIABLE_C_NV, GL_TEXTURE0_ARB,
254 GL_UNSIGNED_IDENTITY_NV, GL_RGB);
255 glx::glCombinerInputNV(GL_COMBINER0_NV, GL_RGB,
256 GL_VARIABLE_D_NV, GL_CONSTANT_COLOR1_NV,
257 GL_UNSIGNED_IDENTITY_NV, GL_RGB);
258
259 // Compute N dot L in spare0 and diffuse * decal texture in spare1
260 glx::glCombinerOutputNV(GL_COMBINER0_NV, GL_RGB,
261 GL_SPARE0_NV, GL_SPARE1_NV, GL_DISCARD_NV,
262 GL_NONE, GL_NONE, GL_TRUE, GL_FALSE, GL_FALSE);
263
264 // Compute the self-shadowing term in the alpha portion of combiner 0
265 // A = 1
266 glx::glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_A_NV,
267 GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_ALPHA);
268 // B = L.z
269 glx::glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_B_NV,
270 GL_PRIMARY_COLOR_NV, GL_EXPAND_NORMAL_NV, GL_BLUE);
271 // C = 1
272 glx::glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_C_NV,
273 GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_ALPHA);
274 // D = L.z
275 glx::glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_D_NV,
276 GL_PRIMARY_COLOR_NV, GL_EXPAND_NORMAL_NV, GL_BLUE);
277
278 // Create a steep ramp function for self-shadowing
279 // SPARE0 = 4*(A*B+C*D) = 4*(1*L.z + 1*L.z) = 8 * L.z
280 glx::glCombinerOutputNV(GL_COMBINER0_NV, GL_ALPHA,
281 GL_DISCARD_NV, GL_DISCARD_NV, GL_SPARE0_NV,
282 GL_SCALE_BY_FOUR_NV, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE);
283
284 // In the second combiner, sum the ambient color and product of the
285 // diffuse and self-shadowing terms.
286 glx::glCombinerInputNV(GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_A_NV,
287 GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
288 glx::glCombinerInputNV(GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_B_NV,
289 GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
290 glx::glCombinerInputNV(GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_C_NV,
291 GL_CONSTANT_COLOR0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
292 glx::glCombinerInputNV(GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_D_NV,
293 GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_RGB);
294 glx::glCombinerOutputNV(GL_COMBINER1_NV, GL_RGB,
295 GL_DISCARD_NV, GL_DISCARD_NV, GL_SPARE0_NV,
296 GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE);
297
298 // E = SPARE0 = fragment brightness, including ambient, diffuse, and
299 // self shadowing.
300 glx::glFinalCombinerInputNV(GL_VARIABLE_E_NV,
301 GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
302 // F = spare1 = decal texture rgb * diffuse color
303 glx::glFinalCombinerInputNV(GL_VARIABLE_F_NV,
304 GL_SPARE1_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
305
306 // A = fog factor
307 glx::glFinalCombinerInputNV(GL_VARIABLE_A_NV,
308 GL_FOG, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
309 // B = color
310 glx::glFinalCombinerInputNV(GL_VARIABLE_B_NV,
311 GL_E_TIMES_F_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
312 // C = fog color
313 glx::glFinalCombinerInputNV(GL_VARIABLE_C_NV,
314 GL_FOG, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
315 // D = zero
316 glx::glFinalCombinerInputNV(GL_VARIABLE_D_NV,
317 GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
318
319 // G = diffuse illumination contribution = L dot N
320 glx::glFinalCombinerInputNV(GL_VARIABLE_G_NV,
321 GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
322 }
323
324
325 // Set up the combiners to a texture with gloss map in the alpha channel.
SetupCombinersGlossMap(int glossMap)326 void SetupCombinersGlossMap(int glossMap)
327 {
328 glEnable(GL_REGISTER_COMBINERS_NV);
329
330 // Just a single combiner stage required . . .
331 glx::glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, 1);
332
333 // A = primary color
334 glx::glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_A_NV,
335 GL_PRIMARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
336 // B = base texture color
337 glx::glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_B_NV,
338 GL_TEXTURE0_ARB, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
339 // C = secondary color
340 glx::glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_C_NV,
341 GL_SECONDARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
342 if (glossMap != 0)
343 {
344 // D = texture1 rgb (gloss mask)
345 glx::glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_D_NV,
346 glossMap, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
347 }
348 else
349 {
350 // D = texture alpha (gloss mask)
351 glx::glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_D_NV,
352 GL_TEXTURE0_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
353 }
354
355 // SPARE0_rgb = primary * texture.rgb + secondary * texture.alpha
356 glx::glCombinerOutputNV(GL_COMBINER0_NV, GL_RGB,
357 GL_DISCARD_NV, GL_DISCARD_NV, GL_SPARE0_NV,
358 GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE);
359
360 // A = SPARE0_rgb
361 glx::glFinalCombinerInputNV(GL_VARIABLE_A_NV,
362 GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
363 // B = 1
364 glx::glFinalCombinerInputNV(GL_VARIABLE_B_NV,
365 GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_RGB);
366 // C = zero
367 glx::glFinalCombinerInputNV(GL_VARIABLE_C_NV,
368 GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
369 // D = zero
370 glx::glFinalCombinerInputNV(GL_VARIABLE_D_NV,
371 GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
372 // G = 1
373 glx::glFinalCombinerInputNV(GL_VARIABLE_G_NV,
374 GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_ALPHA);
375 }
376
377
378 // Set up the combiners to a texture with gloss in the alpha channel.
SetupCombinersGlossMapWithFog(int glossMap)379 void SetupCombinersGlossMapWithFog(int glossMap)
380 {
381 glEnable(GL_REGISTER_COMBINERS_NV);
382
383 // Just a single combiner stage required . . .
384 glx::glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, 1);
385
386 // A = primary color
387 glx::glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_A_NV,
388 GL_PRIMARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
389 // B = base texture color
390 glx::glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_B_NV,
391 GL_TEXTURE0_ARB, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
392 // C = secondary color
393 glx::glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_C_NV,
394 GL_SECONDARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
395 if (glossMap != 0)
396 {
397 // D = texture1 rgb (gloss mask)
398 glx::glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_D_NV,
399 glossMap, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
400 }
401 else
402 {
403 // D = texture alpha (gloss mask)
404 glx::glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_D_NV,
405 GL_TEXTURE0_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
406 }
407
408 // SPARE0_rgb = primary * texture.rgb + secondary * texture.alpha
409 glx::glCombinerOutputNV(GL_COMBINER0_NV, GL_RGB,
410 GL_DISCARD_NV, GL_DISCARD_NV, GL_SPARE0_NV,
411 GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE);
412
413 // A = fog factor
414 glx::glFinalCombinerInputNV(GL_VARIABLE_A_NV,
415 GL_FOG, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
416 // B = spare0_rgb
417 glx::glFinalCombinerInputNV(GL_VARIABLE_B_NV,
418 GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
419 // C = fog color
420 glx::glFinalCombinerInputNV(GL_VARIABLE_C_NV,
421 GL_FOG, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
422 // D = zero
423 glx::glFinalCombinerInputNV(GL_VARIABLE_D_NV,
424 GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
425 // G = 1
426 glx::glFinalCombinerInputNV(GL_VARIABLE_G_NV,
427 GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_ALPHA);
428 }
429
430
DisableCombiners()431 void DisableCombiners()
432 {
433 glDisable(GL_REGISTER_COMBINERS_NV);
434 glx::glActiveTextureARB(GL_TEXTURE1_ARB);
435 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
436 glDisable(GL_TEXTURE_2D);
437 glx::glActiveTextureARB(GL_TEXTURE0_ARB);
438 }
439