title: How is Texture Splatting in OpenGL implemented?
body: <p>I have been reading for a while the different techniques used to texture terrains and came across <a href="http://en.wikipedia.org/wiki/Texture_splatting" rel="nofollow">texture splatting</a>. I have found a lot of articles that discuss how to do this in OpenGL, but most only discuss it theoretically and provide little to no code that I can study. Does anyone know/have some code that illustrates this in OpenGL? </p>
  
  <p>Just to clarify, I want to be able to load four different textures, and based on the height of the quad/vertices, change the texture from one gradually to the next. </p>
  
  <p>Edit: Below is a quick bit of code to help show what I want to know</p>
  
  <pre><code>#include &lt;windows.h&gt;
  #include &lt;SFML/Graphics.hpp&gt;
  #include &lt;gl/gl.h&gt;
  #include &lt;gl/glu.h&gt;
  
  #define GL_CLAMP_TO_EDGE 0x812F
  
  class Scene {
  public:
      void resize( int w, int h ) {
          // OpenGL Reshape
          glViewport( 0, 0, w, h );
          glMatrixMode( GL_PROJECTION );
          glLoadIdentity();
          gluPerspective( 120.0, (GLdouble)w/(GLdouble)h, 0.5, 500.0 );
          glMatrixMode( GL_MODELVIEW );
      }
  };
  
  int main() {
  
      sf::RenderWindow window(sf::VideoMode(800, 600, 32), "Test");
  
      ///Setup the scene, materials, lighting
      Scene scene;
      scene.resize(800,600);
      glEnable(GL_DEPTH_TEST);
      glEnable(GL_LIGHTING);
      glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
      glEnable(GL_COLOR_MATERIAL);
      glShadeModel(GL_SMOOTH);
      glEnable(GL_BLEND);
      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
      glEnable(GL_LIGHT0);
      float XL = .5, YL = .1, ZL = 1;
      GLfloat ambientLight[] = { 0.2f, 0.2f, 0.2f, 1.0f };
      GLfloat diffuseLight[] = { 0.8f, 0.8f, 0.8, 1.0f };
      GLfloat specularLight[] = { 0.5f, 0.5f, 0.5f, 1.0f };
      GLfloat lightpos[] = {XL, YL, ZL, 0.};
      glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
      glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
      glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);
      glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
  
      ///Test terrain texture splatting
  
      ///Load the textures
      sf::Image tex1;
      tex1.loadFromFile("texture1.png");
      sf::Image tex2;
      tex2.loadFromFile("texture2.png");
  
      ///Set the first texture
      GLuint grass;
      glGenTextures(1, &amp;grass);
      glBindTexture(GL_TEXTURE_2D, grass);
      glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
      glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
      glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
      glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, tex1.getSize().x, tex1.getSize().y, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const GLvoid*)tex1.getPixelsPtr() );
  
      ///Set the second texture
      GLuint dirt;
      glGenTextures(1, &amp;dirt);
      glBindTexture(GL_TEXTURE_2D, dirt);
      glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
      glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
      glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
      glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, tex2.getSize().x, tex2.getSize().y, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const GLvoid*)tex2.getPixelsPtr() );
  
      ///Start loop
      while( window.isOpen() ) {
          sf::Event event;
          while( window.pollEvent( event ) ) {
              if( event.type == sf::Event::Closed )
                  window.close();
          }
  
          ///Clear buffer and set camera
          glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
          glMatrixMode(GL_PROJECTION);
          glLoadIdentity();
          gluPerspective(50.0, 1.0, 1.0, 50);
          glMatrixMode(GL_MODELVIEW);
          glLoadIdentity();
          gluLookAt(1, 0, 1, 0, 0, 0, 0, 1, 0);
  
          ///Begin rendering quad             
          glEnable(GL_TEXTURE_2D);
          glBindTexture(GL_TEXTURE_2D, grass);
          ///I know that around here I should enable blending in order to get my two textures to mix, but I am not certain
          glBegin(GL_QUADS);
  
              glTexCoord2f(0, 0);
              glVertex3f(-0.5, -0.5, 0.0);
  
              glTexCoord2f(1, 0);
              glVertex3f(-0.5, 0.5, 0.0);
  
              glTexCoord2f(1, 1);
              glVertex3f(0.5, 0.5, 0.0);
  
              glTexCoord2f(0, 1);
              glVertex3f(0.5, -0.5, 0.0);
          glEnd();
  
          ///Reset env settings for SFML
          glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  
          window.display();
      }
      return 1;
  }
  </code></pre>