
#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;

#define NUM_TEXTURES 9

// Anything with a ::Ptr is a pointer-like type.  
IGLUFramebuffer::Ptr    myTexArray               = 0;
IGLUShaderProgram::Ptr  createTexArray           = 0;
IGLUShaderProgram::Ptr  useTexArray              = 0;
IGLUTexture2D::Ptr      textures[NUM_TEXTURES];
IGLUInt                 curTex ( 0, IGLURange<int>(0,NUM_TEXTURES-1), 1, "Current texture:" );

// List of textures to use as our input
char fNames[NUM_TEXTURES][128] = {
	"../../CommonSampleFiles/images/dragonCaustic.ppm",
	"../../CommonSampleFiles/images/iowaLogo.ppm",
	"../../CommonSampleFiles/images/lake.ppm",
	"../../CommonSampleFiles/images/newZealand_512.ppm",
	"../../CommonSampleFiles/images/glassDragon.ppm",
	"../../CommonSampleFiles/images/niceSunset.ppm",
	"../../CommonSampleFiles/images/ruinedRomanBath.ppm",
	"../../CommonSampleFiles/images/lena512x512.ppm",
	"../../CommonSampleFiles/images/voxelShadowsFairy.jpg"
};


void display ( void )
{
	useTexArray[ "curLayer" ] = int(curTex);
	IGLUDraw::Fullscreen( useTexArray, myTexArray[0] );
}

void OpenGLInitialization( void )
{
	// Load our textures
	for (int i=0; i<NUM_TEXTURES; i++)
		textures[i] = new IGLUTexture2D( fNames[i] );

	// Create a Texture2DArray to hold all of our textures...  We'll create it by rendering into it.
	myTexArray = new IGLUFramebuffer();
	myTexArray->AttachTexture( IGLU_COLOR0, new IGLURenderTexture2DArray( 512, 512, NUM_TEXTURES ) );

	// Load the shader that will create our texture array out of the individual textures.
	createTexArray = new IGLUShaderProgram( "toArray.vert.glsl", "toArray.geom.glsl", "toArray.frag.glsl" );
	createTexArray->SetProgramDisables( IGLU_GLSL_DEPTH_TEST | IGLU_GLSL_BLEND ); 

	// Load the shader we'll use to draw from the texture array
	useTexArray = new IGLUShaderProgram( "fromArray.vert.glsl", "fromArray.frag.glsl" );
	useTexArray->SetProgramDisables( IGLU_GLSL_DEPTH_TEST | IGLU_GLSL_BLEND ); 

	// Store our textures into the texture array
	myTexArray->Bind();
	for (int i=0; i<NUM_TEXTURES; i++)
	{
		createTexArray[ "outputLayer" ] = i;
		IGLUDraw::Fullscreen( createTexArray, textures[i] );
	}
	myTexArray->Unbind();

	// Now that we have our texture array, free the Texture2Ds
	for (int i=0; i<NUM_TEXTURES; i++)
		delete textures[i];
}

int main(int argc, char** argv)
{
	// Put together our main window
	IGLUWindow::Ptr myWin = new IGLUWindow( 512, 512, "Simple IGLU Example:  Texture Array Generator" );
	myWin->SetWindowProperties( IGLU_WINDOW_NO_RESIZE |	
								IGLU_WINDOW_DOUBLE |
								IGLU_WINDOW_BLEND |
								IGLU_WINDOW_REDRAW_ON_IDLE ); 
	myWin->SetDisplayCallback( display );  
	myWin->SetIdleCallback( IGLUWindow::NullIdle );
	myWin->SetPreprocessOnGLInit( OpenGLInitialization );
	myWin->CreateWindow( argc, argv );     

	// Create a widget window to allow us to interact/change our IGLUVariables
	IGLUWidgetWindow::Ptr uiWin = new IGLUWidgetWindow( 300, 100, "UI Widget Window" );
	uiWin->AddWidget( &curTex );

	// Tell our main window about the widget window... 
	myWin->SetWidgetWindow( uiWin );

	// Start interaction.
	IGLUWindow::Run();
	return 0;
}
