/**
*  @brief
*    Constructor
*/
SPRTTShaders::SPRTTShaders(Renderer &cRenderer) : SPRTT(cRenderer),
	m_pRenderTarget(nullptr),
	m_pColorTarget1(nullptr),
	m_pColorTarget2(nullptr),
	m_pColorTarget3(nullptr),
	m_pSceneVertexShader(nullptr),
	m_pSceneFragmentShader(nullptr),
	m_pSceneProgram(nullptr),
	m_pVertexShader(nullptr),
	m_pFragmentShader(nullptr),
	m_pProgram(nullptr)
{
	// Check/get number of supported color render targets
	uint8 nMaxColorTargets = 4;
	if (nMaxColorTargets > cRenderer.GetCapabilities().nMaxColorRenderTargets)
		nMaxColorTargets = cRenderer.GetCapabilities().nMaxColorRenderTargets;

	{ // Render targets
		// Create the render target. We will create a very low resolution 2D texture buffer to see funny pixels.
		m_pRenderTarget = cRenderer.CreateSurfaceTextureBuffer2D(Vector2i(64, 64), TextureBuffer::R8G8B8, SurfaceTextureBuffer::Depth|SurfaceTextureBuffer::NoMultisampleAntialiasing, nMaxColorTargets);
		if (m_pRenderTarget && nMaxColorTargets > 1) {
			// Set additional color render targets
			if (nMaxColorTargets > 1 && !m_pColorTarget1) {
				Image cImage = Image::CreateImage(DataByte, ColorRGB, Vector3i(64, 64, 1));
				m_pColorTarget1 = cRenderer.CreateTextureBuffer2D(cImage, TextureBuffer::Unknown, TextureBuffer::RenderTarget);
			}
			if (nMaxColorTargets > 2 && !m_pColorTarget2) {
				Image cImage = Image::CreateImage(DataByte, ColorRGB, Vector3i(64, 64, 1));
				m_pColorTarget2 = cRenderer.CreateTextureBuffer2D(cImage, TextureBuffer::Unknown, TextureBuffer::RenderTarget);
			}
			if (nMaxColorTargets > 3 && !m_pColorTarget3) {
				Image cImage = Image::CreateImage(DataByte, ColorRGB, Vector3i(64, 64, 1));
				m_pColorTarget3 = cRenderer.CreateTextureBuffer2D(cImage, TextureBuffer::Unknown, TextureBuffer::RenderTarget);
			}
		}
	}

	// Decide which shader language should be used (for example "GLSL" or "Cg")
	ShaderLanguage *pShaderLanguage = cRenderer.GetShaderLanguage(cRenderer.GetDefaultShaderLanguage());
	if (pShaderLanguage) {
		{ // Scene program (with MRT support)
			// Construct the string containing the fragment shader definitions
			String sDefinitions;
			if (m_pColorTarget1)
				sDefinitions += "#define MRT_1\n";
			if (m_pColorTarget2)
				sDefinitions += "#define MRT_2\n";
			if (m_pColorTarget3)
				sDefinitions += "#define MRT_3\n";

			// Shader source code
			String sVertexShaderSourceCode;
			String sFragmentShaderSourceCode;
			if (pShaderLanguage->GetShaderLanguage() == "GLSL") {
				#include "SPRTTShaders_GLSL.h"
				if (cRenderer.GetAPI() == "OpenGL ES 2.0") {
					// Get shader source codes
					sVertexShaderSourceCode   = "#version 100\n" + sSceneVertexShaderSourceCodeGLSL;
					sFragmentShaderSourceCode = "#version 100\n" + sDefinitions + sSceneFragmentShaderSourceCodeGLSL;
				} else {
					// Remove precision qualifiers so that we're able to use 120 (OpenGL 2.1 shaders) instead of 130 (OpenGL 3.0 shaders,
					// with this version we can keep the precision qualifiers) so that this shader requirements are as low as possible
					// -> In here we're using 120 instead of 110 because matrix casts are quite comfortable...
					sVertexShaderSourceCode   = "#version 120\n" + Shader::RemovePrecisionQualifiersFromGLSL(sSceneVertexShaderSourceCodeGLSL);
					sFragmentShaderSourceCode = "#version 120\n" + sDefinitions + Shader::RemovePrecisionQualifiersFromGLSL(sSceneFragmentShaderSourceCodeGLSL);
				}
			} else if (pShaderLanguage->GetShaderLanguage() == "Cg") {
				#include "SPRTTShaders_Cg.h"
				sVertexShaderSourceCode   = sSceneVertexShaderSourceCodeCg;
				sFragmentShaderSourceCode = sSceneFragmentShaderSourceCodeCg;
			}

			// Create a vertex shader instance
			// -> I define a Cg profile because when using an GLSL Cg profile (which is the default), the shader is not working correctly on my AMD/ATI ("AMD Catalyst™ 11.3") system while it worked on the tested NVIDIA system...
			m_pSceneVertexShader = pShaderLanguage->CreateVertexShader(sVertexShaderSourceCode, "arbvp1");

			// Create a fragment shader instance
			// -> I define a Cg profile because when using an GLSL Cg profile (which is the default), the shader is not working correctly on my AMD/ATI ("AMD Catalyst™ 11.3") system while it worked on the tested NVIDIA system...
			m_pSceneFragmentShader = pShaderLanguage->CreateFragmentShader(sFragmentShaderSourceCode, "arbfp1");

			// Create a program instance and assign the created vertex and fragment shaders to it
			m_pSceneProgram = pShaderLanguage->CreateProgram(m_pSceneVertexShader, m_pSceneFragmentShader);
		}

		{ // Program
			// Shader source code
			String sVertexShaderSourceCode;
			String sFragmentShaderSourceCode;
			if (pShaderLanguage->GetShaderLanguage() == "GLSL") {
				#include "SPRTTShaders_GLSL.h"
				if (cRenderer.GetAPI() == "OpenGL ES 2.0") {
					// Get shader source codes
					sVertexShaderSourceCode   = "#version 100\n" + sVertexShaderSourceCodeGLSL;
					sFragmentShaderSourceCode = "#version 100\n" + sFragmentShaderSourceCodeGLSL;
				} else {
					// Remove precision qualifiers so that we're able to use 110 (OpenGL 2.0 shaders) instead of 130 (OpenGL 3.0 shaders,
					// with this version we can keep the precision qualifiers) so that this shader requirements are as low as possible
					sVertexShaderSourceCode   = "#version 110\n" + Shader::RemovePrecisionQualifiersFromGLSL(sVertexShaderSourceCodeGLSL);
					sFragmentShaderSourceCode = "#version 110\n" + Shader::RemovePrecisionQualifiersFromGLSL(sFragmentShaderSourceCodeGLSL);
				}
			} else if (pShaderLanguage->GetShaderLanguage() == "Cg") {
				#include "SPRTTShaders_Cg.h"
				sVertexShaderSourceCode   = sVertexShaderSourceCodeCg;
				sFragmentShaderSourceCode = sFragmentShaderSourceCodeCg;
			}

			// Create a vertex shader instance
			// -> I define a Cg profile because when using an GLSL Cg profile (which is the default), the shader is not working correctly on my AMD/ATI ("AMD Catalyst™ 11.3") system while it worked on the tested NVIDIA system...
			m_pVertexShader = pShaderLanguage->CreateVertexShader(sVertexShaderSourceCode, "arbvp1");

			// Create a fragment shader instance
			// -> I define a Cg profile because when using an GLSL Cg profile (which is the default), the shader is not working correctly on my AMD/ATI ("AMD Catalyst™ 11.3") system while it worked on the tested NVIDIA system...
			m_pFragmentShader = pShaderLanguage->CreateFragmentShader(sFragmentShaderSourceCode, "arbfp1");

			// Create a program instance and assign the created vertex and fragment shaders to it
			m_pProgram = static_cast<ProgramWrapper*>(pShaderLanguage->CreateProgram(m_pVertexShader, m_pFragmentShader));
		}
	}
}