regcombine.cpp
上传用户:center1979
上传日期:2022-07-26
资源大小:50633k
文件大小:18k
源码类别:

OpenGL

开发平台:

Visual C++

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