<shader compiler="xmlshader" name="stat_dyn_reflect">
  <!--
      Shader for "masked reflections".
      
      Goal: Allow specification of, in addition to a diffuse texture, a 
        reflection texture and a mask texture. On white parts of the mask,
        only the diffuse texture should appear, on black parts, only the
        reflection, on gray parts they should be mixed accordingly. 
        
      This leads to the following formula for an unlit pixel:
          Cf = Cd * Cm + Cr * (1 - Cm)
      where: 
          Cf = final pixel
          Cd = diffuse texel
          Cm = mask texel
          Cr = reflection texel
        
      To have the texture lit (via "software lighting"), the right side is 
      multiplied with Cl * 2 where Cl is the light color (either from a
      lightmap or vertex lighting). The multiplication with 2 is done to 
      allow a higher range of color, a surface can appear twice as bright
      as its diffuse color.
      
      The new formula is:
          Cf = (Cd * Cm + Cr * (1 - Cm)) * Cl * 2
      This has to be mapped to a multitexturing setup. The whole thing is
      split up into multiple passes:
        1. the Cd * Cm part is drawn
            -> Cf1 = Cd * Cm
        2. the Cr * (1 - Cm) is additively drawn on top of that
            -> Cf2 = Cf1 + (Cr * (1 - Cm)) = Cd * Cm + (Cr * (1 - Cm))
        3. the lighting is applied, ie the framebuffer pixels are multiplied
           with Cl * 2
            -> Cf = Cf2 * Cl * 2 = Cd * Cm + (Cr * (1 - Cm)) * Cl * 2
      ...and we got our desired shading.
      
      Optimization: Actually, the 3rd pass above is only done for lightmaps; 
      when vertex lighting is used, we don't need a texture for that, but can 
      multiply the light value into the diffuse resp. reflection texture in the 
      first TU on each pass. Basically, we render:
          Cd * Cl * 2 * Cm + Cr * Cl * 2 * (1 - Cm)
      which is equivalent to the original formula.
      
      Note that because we have to add (Cd * Cm) and (Cr * (1 - Cm)) we can't
      make a single-pass shader with multitexturing only (MT can only do stuff
      like ((a*b) + c) * d, but not (a*b)+(c*d), which is what we need.)
      
      A further possible optimizations would be to put the mask into the alpha
      channel of the diffuse texture; this would allow to do the blending
      between the diffuse and reflection texture on one TU, and further this
      shader could be rendered single pass when 3 TUs are available.
      
      Currently, the shader needs only 2 TUs, hence runs on all but the most
      pitiful and/or old hardware.
      
      For simplicity reasons, the shader requires the definition of a mask
      texture (shadervar "tex mask") and a reflection texture 
      ("tex reflection").
    -->
  <technique priority="100">
    <pass>
      <!-- First pass, Cd*Cm -->
      <!-- Use same texcoords for mask and diffuse texture -->
      <buffer source="texture coordinate 0" destination="texture coordinate 0" />
      <buffer source="texture coordinate 0" destination="texture coordinate 1" />
      <?if !vars."tex lightmap".texture ?>
	<!-- Bind vertex colors if lightmapping isn't used -->
	<buffer source="color" destination="color" />
      <?endif?>
      <!-- Bind the textures to the TUs. "unit 0" correlates with the 1st 
           <layer> in <fixedfp>, "unit 1" with the 2nd and so on. -->
      <texture name="tex diffuse" destination="unit 0" />
      <texture name="tex mask" destination="unit 1" />
      <fp plugin="glfixed">
        <fixedfp>
          <layer>
            <colorsource num="0" source="texture" modifier="color"/>
            <?if !vars."tex lightmap".texture ?>
              <!-- The "vertex lighting trick": multiply lighting into diffuse
                   color when an LM isn't used. -->
              <colorsource num="1" source="primary color" modifier="color"/>
              <coloroperation operation="modulate" scale="2" />
            <?else?>
              <!-- Otherwise, leave unchanged. -->
              <coloroperation operation="replace" />
            <?endif?>
          </layer>
          <layer>
            <!-- The actual multiplication of Cd (from the "previous layer")
                 with Cm ("texture") -->
            <colorsource num="0" source="previous layer" modifier="color"/>
            <colorsource num="1" source="texture" modifier="color"/>
            <coloroperation operation="modulate" />
          </layer>
        </fixedfp>
      </fp>
    </pass>
    <pass>
      <!-- Pass 2, Cr*(1-Cm) -->
      <!-- As explained, we want to additively blend it into the previous 
           pass. So add the final pixel color to the framebuffer color.
           
           Also compare the mixmode of pass 3. A mixmode specifies how to
           actually apply the "final pixel color" to the framebuffer. 
           
           Notice that in the first pass the mixmode was omitted; the default
           is just "copy", which is what we wanted there. -->
      <mixmode><add /></mixmode>
      <!-- Means: "pick a Z buffer mode that allows to draw on the same 
           geometry drawn in the first pass." 
           
           Notice that in the first pass the mixmode was omitted; the default
           is "use the Zmode that was set in the _renderstep_". We just assume
           the default "zmesh" (use the Zmode that was set on the mesh) was
           specified. If something else was set, this shader may produce 
           incorrect results.
           
           Ergo, sometimes renderloop and shader have to be tuned against
           each other. Don't worry, tho; usually you don't have to mind
           that much. If you're unsure what <zmode> to use in a pass, try if
           specifying none maybe "just works". -->
      <zmode><zmesh2 /></zmode>
      <!-- Note that no texcoords are specified for TU 0. The vertex program
           below will cause texture coordinates appropriate for reflection to
           be generated by the hardware. -->
      <buffer source="texture coordinate 0" destination="texture coordinate 1" />
      <!-- However, reflection texcoord generation needs normals. -->
      <buffer source="normal" destination="normal"/>
      <?if !vars."tex lightmap".texture ?>
	<!-- Bind vertex colors if lightmapping isn't used -->
	<buffer source="color" destination="color" />
      <?endif?>
      <texture name="tex reflection" destination="unit 0" />
      <texture name="tex mask" destination="unit 1" />
      <vp plugin="glfixed">
        <!-- The "vertex program". Actually a setup for the GL fixed function
            vertex pipeline. -->
        <fixedvp>  
          <!-- The setting that causes reflection texcoords to be generated. -->
          <texgen type="reflection" mapping="cube" layer="0" />
        </fixedvp>
      </vp>
      <fp plugin="glfixed">
        <fixedfp>
          <layer>
            <colorsource num="0" source="texture" modifier="color"/>
            <?if !vars."tex lightmap".texture ?>
              <colorsource num="1" source="primary color" modifier="color"/>
              <coloroperation operation="modulate" scale="2" />
            <?else?>
              <coloroperation operation="replace" />
            <?endif?>
          </layer>
          <layer>
            <!-- "invertcolor" means we get "one minus the texel from the 
                 texture of this TU", ie (1 - Cm) (as opposed to "color" which 
                 just gives "the texture of this TU") -->
            <colorsource num="0" source="texture" modifier="invertcolor"/>
            <colorsource num="1" source="previous layer" modifier="color"/>
            <coloroperation operation="modulate" />
          </layer>
        </fixedfp>
      </fp>
    </pass>
    <?if vars."tex lightmap".texture ?>
      <pass>
        <!-- Apply the lightmap, if we have one. -->
        <!-- "Multiply the final pixel color with the framebuffer color and 2",
             that's what <multiply2 /> does. -->
        <mixmode><multiply2 /></mixmode>
        <zmode><zmesh2 /></zmode>
        <buffer source="texture coordinate lightmap" destination="texture coordinate 0" />
        <texture name="tex lightmap" destination="unit 0" />
        <!-- no special VPs or FPs needed. -->
      </pass>
    <?endif?>
    <?include snippets/fog-pass.inc ?>
  </technique>
</shader>
