
// This example is equivalent to the SimpleRandomTexture sample, except instead
//    of using a DrawArrays() call to go through the list of vertices in the
//    vertex array, a DrawElements() is used to specify a set of triangle indices
//    to be used.

#include <GL/glew.h>
#include <stdio.h>

// All headers are automatically included from "iglu.h"
#include "iglu.h"

// IGLU classes and constants are all inside the iglu namespace.
using namespace iglu;

// Our vertex and fragment shader to draw the quad with random data
static char DisplayRandomVS[] = {
	"#version 420\n"
	"in vec2 vertex;\n"
	"out vec2 fragTexCoord;\n"
	"void main( void ) {\n"
	"    gl_Position = vec4( 2.0f*vertex.xy-1.0f, 0.0f, 1.0f );\n"
	"    fragTexCoord = vertex.xy;\n"
	"}\n"
};

// Uses an integer random texture, there is only 16 bits of random data.
//    This shader displays it [0..1] in the image by dividing by 2^16-1.
static char DisplayRandomFS[] = {
	"#version 420\n"
	"uniform isampler2D randTex;\n"
	"in vec2 fragTexCoord;\n"
	"out vec4 result;\n"
	"void main( void ) {\n"
	"    result = vec4( texture( randTex, fragTexCoord ) ) / 65535.0;\n"
	"}\n"
};


// Location of the geometry on screen 
//   -> Notice how the order of the tri strip vertices has been moved around.
//   -> The triStripIndices specifies which of them should be used in which order.
static float           triStripData[]    = { 0, 0,   1, 1,   1, 0,   0, 1  };
static unsigned short  triStripIndices[] = { 0, 2, 3, 1 };

// A pointers to our IGLU classes
IGLUTexture::Ptr         tex2D     = 0;
IGLUShaderProgram::Ptr   shader    = 0;
IGLUVertexArray::Ptr     vertArray = 0;

void display ( void )
{
	shader->Enable();
		vertArray->DrawElements( GL_TRIANGLE_STRIP, 4 );  // Draw a triangle strip with 4 vertices
	shader->Disable();

	// Swap OpenGL front/back buffers to display what we just drew.
	glutSwapBuffers();
}


void keys(unsigned char key, int x, int y)
{
	// Exit whenever any key is pressed
	exit(0);
}

void idle ( void )
{
	glutPostRedisplay();
}

int main(int argc, char** argv)
{
	// Standard OpenGL/GLUT setup
	glutInit(&argc, argv);
	glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH );
	glutInitWindowSize( 512, 512 );
	glutInitWindowPosition( 20, 20 );
	glutCreateWindow( "Basic IGLU Random Texture Creation" );
	glewInit();
	glutDisplayFunc( display );
	glutIdleFunc( idle );
	glutKeyboardFunc( keys );

	// Load the texture with IGLU
	printf("(+) Creating a randomly populated texture...\n" );
	tex2D = new IGLURandomTexture2D( 512, 512 );

	// Load the shader (from code above) we'll use to draw
	printf("(+) Creating a shader to copy the texture on screen...\n");
	shader = new IGLUShaderProgram();
	shader->CreateFromString( DisplayRandomVS, DisplayRandomFS );
	shader["randTex"] = tex2D;

	// Create the geometry we'll use to render
	printf("(+) Creating a quad to texture...\n");
	vertArray = new IGLUVertexArray();
	
	// Set up a list of vertices 
	vertArray->SetVertexArray( sizeof( triStripData ),     // Array size of vertex data (in bytes)
		                       triStripData );             // Array with per-vertex data inside

	// Set up a list of vertex indices (to say which order to use the specified vertices
	vertArray->SetElementArray( GL_UNSIGNED_SHORT,         // What type of data is used to store the indices?
		                        sizeof( triStripIndices ), // Array size of index data (in bytes)
								triStripIndices );         // Array with list of vertex indices 

	// OK.  Now set this array up to use in drawing.  
	//   NOTE:  If multiple shaders are to be used, this may need to be redone when 
	//          the shader used is changed.  (Though it may not be, if you understand the 
	//          underlying OpenGL & GLSL compilation and linking process -- all that's needed
	//          to be correct is the attribute index, which is computed from shader["vertex"])
	vertArray->EnableAttribute( shader["vertex"],   // What GLSL vertex attribute is getting data?
		                        2, GL_FLOAT,        // How many bits of data will that variable get? (2 floats)
								0,                  // What is the stride between data for adjacent vertices?
								BUFFER_OFFSET(0) ); // Where in the array is the first vertex located (in bytes from start)

	// Note: EnableAttribute() can be called multiple times if there are multiple input attributes
	//       require in the shader you use!

	// Start the GLUT interaction loop
	glutMainLoop();
	return 0;
}
