1b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu/******************************************************************************
2b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
33e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens @File         OGLES3ColourGrading.cpp
4b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
5b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu @Title        Colour grading
6b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
7b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu @Version
8b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
9b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu @Copyright    Copyright (c) Imagination Technologies Limited.
10b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
11b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu @Platform     Independent
12b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
13b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu @Description  Demonstrates how to colour grade your render.
14b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
15b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu ******************************************************************************/
16b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu#include "PVRShell.h"
173e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens#include "OGLES3Tools.h"
18b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
19b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu/******************************************************************************
20b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu Constants
21b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu ******************************************************************************/
22b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetuconst char* const c_pszMaskTexture = "MaskTexture.pvr";
23b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetuconst char* const c_pszBackgroundTexture = "Background.pvr";
24b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
25b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu// Our colour lookup tables
26b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetuconst char* const c_pszLUTs[] =
27b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu{
28b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	"identity.pvr",
29b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	"bw.pvr",
30b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	"cooler.pvr",
31b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	"warmer.pvr",
32b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	"sepia.pvr",
33b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	"inverted.pvr",
34b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	"highcontrast.pvr",
35b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	"bluewhitegradient.pvr"
36b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu};
37b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
38b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu// Shader source
39b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetuconst char* const c_szFragShaderSrcFile	= "FragShader.fsh";
40b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetuconst char* const c_szVertShaderSrcFile	= "VertShader.vsh";
41b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetuconst char* const c_szSceneFragShaderSrcFile	= "SceneFragShader.fsh";
42b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetuconst char* const c_szSceneVertShaderSrcFile	= "SceneVertShader.vsh";
43b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetuconst char* const c_szBackgroundFragShaderSrcFile = "BackgroundFragShader.fsh";
44b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
45b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu// POD scene files
46b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetuconst char c_szSceneFile[] = "Mask.pod";
47b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
48b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu// Camera constants. Used for making the projection matrix
49b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetuconst float CAM_FOV  = PVRT_PI / 6;
50b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetuconst float CAM_NEAR = 4.0f;
51b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetuconst float CAM_FAR = 5000.0f;
52b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
53b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu// Index to bind the attributes to vertex shaders
54b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetuconst int VERTEX_ARRAY   = 0;
55b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetuconst int TEXCOORD_ARRAY = 1;
56b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetuconst int NORMAL_ARRAY   = 2;
57b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
58b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu// Look up table enumeration
59b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetuenum ELUTs
60b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu{
61b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	eIdentity,
62b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	eBW,
63b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	eCooler,
64b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	eWarmer,
65b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	eSepia,
66b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	eInverted,
67b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	eHighContrast,
68b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	eBlueWhiteGradient,
69b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	eLast,
70b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
71b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// The range to cycle through
72b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	eA = eBW,
73b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	eB = eBlueWhiteGradient
74b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu};
75b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
76b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetuconst char* const c_pszLUTNames[] =
77b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu{
78b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	"Identity",
79b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	"Black and white",
80b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	"Cooler",
81b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	"Warmer",
82b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	"Sepia",
83b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	"Inverted",
84b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	"High Contrast",
85b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	"Blue White Gradient"
86b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu};
87b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
88b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu/*!****************************************************************************
89b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu Class implementing the PVRShell functions.
90b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu ******************************************************************************/
913e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capensclass OGLES3ColourGrading : public PVRShell
92b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu{
93b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Print3D object
94b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	CPVRTPrint3D			m_Print3D;
95b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
96b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Texture handle
97b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	GLuint					m_uiMaskTexture;
98b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	GLuint					m_uiBackgroundTexture;
99b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	GLuint					m_uiLUTs[eLast];
100b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	int						m_iCurrentLUT;
101b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
102b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// VBO handle
103b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	GLuint					m_ui32FullScreenRectVBO;
104b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
105b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Stride for vertex data
106b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	unsigned int			m_ui32VertexStride;
107b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
108b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// 3D Model
109b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	CPVRTModelPOD	m_Mask;
110b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	GLuint* m_puiMaskVBO;
111b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	GLuint* m_puiMaskIBO;
112b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
113b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	GLuint m_ui32BackgroundVBO;
114b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
115b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Projection and view matrices
116b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	PVRTMat4 m_mViewProjection;
117b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
118b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Shaders
119b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	GLuint m_uiPostVertShader;
120b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	GLuint m_uiPostFragShader;
121b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
122b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	struct
123b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	{
124b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		GLuint uiId;
125b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	}
126b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	m_PostShaderProgram;
127b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
128b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	GLuint m_uiBackgroundFragShader;
129b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
130b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	struct
131b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	{
132b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		GLuint uiId;
133b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	}
134b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	m_BackgroundShaderProgram;
135b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
136b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	GLuint m_uiSceneVertShader;
137b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	GLuint m_uiSceneFragShader;
138b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
139b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	struct
140b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	{
141b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		GLuint uiId;
142b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		GLuint uiMVPMatrixLoc;
143b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		GLuint uiLightDirLoc;
144b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		GLuint uiMaterialBiasLoc;
145b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		GLuint uiMaterialScaleLoc;
146b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	}
147b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	m_SceneShaderProgram;
148b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
149b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Render contexts, etc
150b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	GLint	  m_i32OriginalFbo;
151b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
152b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Texture IDs used by the app
153b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	GLuint	m_uiTextureToRenderTo;
154b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
155b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Handle for our FBO and the depth buffer that it requires
156b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	GLuint m_uiFBO;
157b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
158b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Handle for our multi-sampled FBO and the depth buffer that it requires
159b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	GLuint m_uiFBOMultisampled;
160b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	GLuint m_uiDepthBufferMultisampled;
161b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	GLuint m_uiColourBufferMultisampled;
162b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
163b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Start time
164b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	unsigned long m_ulStartTime;
165b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
166b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetupublic:
167b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// PVRShell functions
168b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	virtual bool InitApplication();
169b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	virtual bool InitView();
170b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	virtual bool ReleaseView();
171b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	virtual bool QuitApplication();
172b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	virtual bool RenderScene();
173b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
174b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetuprivate:
175b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	bool LoadShaders(CPVRTString& ErrorStr);
176b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	bool CreateFBO();
177b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	void LoadVbos(const bool bRotated);
178b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	void DrawMesh(const int i32NodeIndex);
179b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu};
180b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
181b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
182b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu/*!****************************************************************************
183b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu @Function		InitApplication
184b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu @Return		bool		true if no error occurred
185b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu @Description	Code in InitApplication() will be called by PVRShell once per
186b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu                run, before the rendering context is created.
187b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu                Used to initialize variables that are not dependent on it
188b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu                (e.g. external modules, loading meshes, etc.)
189b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu                If the rendering context is lost, InitApplication() will
190b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu                not be called again.
191b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu ******************************************************************************/
1923e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capensbool OGLES3ColourGrading::InitApplication()
193b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu{
194b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Get and set the read path for content files
195b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	CPVRTResourceFile::SetReadPath((char*)PVRShellGet(prefReadPath));
196b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
197b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Get and set the load/release functions for loading external files.
198b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// In the majority of cases the PVRShell will return NULL function pointers implying that
199b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// nothing special is required to load external files.
200b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	CPVRTResourceFile::SetLoadReleaseFunctions(PVRShellGet(prefLoadFileFunc), PVRShellGet(prefReleaseFileFunc));
201b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
202b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Load the scene
203b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	if(m_Mask.ReadFromFile(c_szSceneFile) != PVR_SUCCESS)
204b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	{
205b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		PVRShellSet(prefExitMessage, "ERROR: Couldn't load the .pod file\n");
206b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		return false;
207b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	}
208b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
209b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Initialise some variables
210b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	m_puiMaskVBO = m_puiMaskIBO = 0;
211b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	m_iCurrentLUT = eA;
212b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	return true;
213b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu}
214b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
215b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu/*!****************************************************************************
216b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu @Function		QuitApplication
217b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu @Return		bool		true if no error occurred
218b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu @Description	Code in QuitApplication() will be called by PVRShell once per
219b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu                run, just before exiting the program.
220b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu                If the rendering context is lost, QuitApplication() will
221b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu                not be called.
222b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu ******************************************************************************/
2233e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capensbool OGLES3ColourGrading::QuitApplication()
224b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu{
225b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Free the memory allocated for the scene
226b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	m_Mask.Destroy();
227b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
228b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	delete[] m_puiMaskVBO;
229b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	m_puiMaskVBO = 0;
230b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
231b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	delete[] m_puiMaskIBO;
232b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	m_puiMaskIBO = 0;
233b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu    return true;
234b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu}
235b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
236b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu/*!****************************************************************************
237b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu @Function		LoadEffects
238b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu @Output		ErrorStr	A description of an error, if one occurs.
239b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu @Return		bool		true if no error occurred
240b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu @Description	Loads and parses the bundled PFX and generates the various
241b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu                effect objects.
242b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu ******************************************************************************/
2433e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capensbool OGLES3ColourGrading::LoadShaders(CPVRTString& ErrorStr)
244b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu{
245b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Load and compile the shaders from files.
246b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	if(PVRTShaderLoadFromFile(NULL, c_szVertShaderSrcFile, GL_VERTEX_SHADER, GL_SGX_BINARY_IMG, &m_uiPostVertShader, &ErrorStr) != PVR_SUCCESS)
247b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	{
248b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		return false;
249b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	}
250b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
251b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	if(PVRTShaderLoadFromFile(NULL, c_szFragShaderSrcFile, GL_FRAGMENT_SHADER, GL_SGX_BINARY_IMG, &m_uiPostFragShader, &ErrorStr) != PVR_SUCCESS)
252b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	{
253b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		return false;
254b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	}
255b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
256b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Setup and link the shader program
257b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	const char* aszAttribs[] = { "inVertex", "inTexCoord" };
258b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	if(PVRTCreateProgram(&m_PostShaderProgram.uiId, m_uiPostVertShader, m_uiPostFragShader, aszAttribs, 2, &ErrorStr) != PVR_SUCCESS)
259b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	{
260b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		return false;
261b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	}
262b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
263b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Set the sampler variables to their respective texture unit
264b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glUniform1i(glGetUniformLocation(m_PostShaderProgram.uiId, "sTexture"), 0);
265b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glUniform1i(glGetUniformLocation(m_PostShaderProgram.uiId, "sColourLUT"), 1);
266b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
267b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Background shader
268b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
269b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	if(PVRTShaderLoadFromFile(NULL, c_szBackgroundFragShaderSrcFile, GL_FRAGMENT_SHADER, GL_SGX_BINARY_IMG, &m_uiBackgroundFragShader, &ErrorStr) != PVR_SUCCESS)
270b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	{
271b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		return false;
272b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	}
273b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
274b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Set up and link the shader program re-using the vertex shader from the main shader program
275b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	const char* aszBackgroundAttribs[] = { "inVertex", "inTexCoord" };
276b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	if(PVRTCreateProgram(&m_BackgroundShaderProgram.uiId, m_uiPostVertShader, m_uiBackgroundFragShader, aszBackgroundAttribs, 2, &ErrorStr) != PVR_SUCCESS)
277b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	{
278b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		return false;
279b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	}
280b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
281b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Set the sampler2D variable to the first texture unit
282b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glUniform1i(glGetUniformLocation(m_BackgroundShaderProgram.uiId, "sTexture"), 0);
283b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
284b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Scene shaders - Used for rendering the mask
285b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	if(PVRTShaderLoadFromFile(NULL, c_szSceneVertShaderSrcFile, GL_VERTEX_SHADER, GL_SGX_BINARY_IMG, &m_uiSceneVertShader, &ErrorStr) != PVR_SUCCESS)
286b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	{
287b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		return false;
288b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	}
289b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
290b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	if(PVRTShaderLoadFromFile(NULL, c_szSceneFragShaderSrcFile, GL_FRAGMENT_SHADER, GL_SGX_BINARY_IMG, &m_uiSceneFragShader, &ErrorStr) != PVR_SUCCESS)
291b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	{
292b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		return false;
293b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	}
294b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
295b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Setup and link the shader program
296b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	const char* aszSceneAttribs[] = { "inVertex", "inTexCoord", "inNormal" };
297b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	if (PVRTCreateProgram(&m_SceneShaderProgram.uiId, m_uiSceneVertShader, m_uiSceneFragShader, aszSceneAttribs, 3, &ErrorStr) != PVR_SUCCESS)
298b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	{
299b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		return false;
300b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	}
301b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
302b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Set the sampler2D variable to the first texture unit
303b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glUniform1i(glGetUniformLocation(m_SceneShaderProgram.uiId, "sTexture"), 0);
304b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
305b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Store the location of uniforms for later use
306b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	m_SceneShaderProgram.uiMVPMatrixLoc		= glGetUniformLocation(m_SceneShaderProgram.uiId, "MVPMatrix");
307b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	m_SceneShaderProgram.uiLightDirLoc		= glGetUniformLocation(m_SceneShaderProgram.uiId, "LightDirection");
308b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	m_SceneShaderProgram.uiMaterialBiasLoc	= glGetUniformLocation(m_SceneShaderProgram.uiId, "MaterialBias");
309b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	m_SceneShaderProgram.uiMaterialScaleLoc	= glGetUniformLocation(m_SceneShaderProgram.uiId, "MaterialScale");
310b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
311b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Set default shader material uniforms
312b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	float fSpecularConcentration = 0.6f;	// a value from 0 to 1 (wider, concentrated)
313b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	float fSpecularIntensity = 0.3f;		// a value from 0 to 1
314b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
315b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Specular bias
316b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glUniform1f(m_SceneShaderProgram.uiMaterialBiasLoc, fSpecularConcentration);
317b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Specular intensity scale
318b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glUniform1f(m_SceneShaderProgram.uiMaterialScaleLoc, fSpecularIntensity / (1.0f - fSpecularConcentration));
319b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
320b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	return true;
321b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu}
322b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
323b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu/*!****************************************************************************
324b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu @Function		LoadVbos
325b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu @Description	Loads the mesh data required for this training course into
326b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu				vertex buffer objects
327b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu******************************************************************************/
3283e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capensvoid OGLES3ColourGrading::LoadVbos(const bool bRotated)
329b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu{
330b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	if(!m_puiMaskVBO)
331b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		m_puiMaskVBO = new GLuint[m_Mask.nNumMesh];
332b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
333b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	if(!m_puiMaskIBO)
334b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		m_puiMaskIBO = new GLuint[m_Mask.nNumMesh];
335b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
336b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	/*
337b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		Load vertex data of all meshes in the scene into VBOs
338b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
339b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		The meshes have been exported with the "Interleave Vectors" option,
340b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		so all data is interleaved in the buffer at pMesh->pInterleaved.
341b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		Interleaving data improves the memory access pattern and cache efficiency,
342b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		thus it can be read faster by the hardware.
343b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	*/
344b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glGenBuffers(m_Mask.nNumMesh, m_puiMaskVBO);
345b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	for(unsigned int i = 0; i < m_Mask.nNumMesh; ++i)
346b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	{
347b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		// Load vertex data into buffer object
348b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		SPODMesh& Mesh = m_Mask.pMesh[i];
349b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		unsigned int uiSize = Mesh.nNumVertex * Mesh.sVertex.nStride;
350b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		glBindBuffer(GL_ARRAY_BUFFER, m_puiMaskVBO[i]);
351b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		glBufferData(GL_ARRAY_BUFFER, uiSize, Mesh.pInterleaved, GL_STATIC_DRAW);
352b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
353b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		// Load index data into buffer object if available
354b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		m_puiMaskIBO[i] = 0;
355b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		if (Mesh.sFaces.pData)
356b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		{
357b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu			glGenBuffers(1, &m_puiMaskIBO[i]);
358b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu			uiSize = PVRTModelPODCountIndices(Mesh) * sizeof(GLshort);
359b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_puiMaskIBO[i]);
360b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu			glBufferData(GL_ELEMENT_ARRAY_BUFFER, uiSize, Mesh.sFaces.pData, GL_STATIC_DRAW);
361b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		}
362b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	}
363b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
364b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Create VBO for the fullscreen rect that we'll be rendering our FBO to
365b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
366b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Interleaved vertex data
367b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	GLfloat afVertices[] = {
368b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		// Left quad
369b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		-1.0f,  1.0f, 0.0f,	1.0f,	// Pos
370b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		0.0f,  1.0f,			    // UVs
371b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
372b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		-1.0f, -1.0f, 0.0f,	1.0f,
373b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		0.0f,  0.0f,
374b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
375b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		0.0f,  1.0f, 0.0f,	1.0f,
376b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		0.5f,  1.0f,
377b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
378b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		0.0f, -1.0f, 0.0f,	1.0f,
379b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		0.5f,  0.0f,
380b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
381b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		1.0f,  1.0f, 0.0f,	1.0f,
382b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		1.0f,  1.0f,
383b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
384b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		1.0f, -1.0f, 0.0f,	1.0f,
385b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		1.0f,  0.0f,
386b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	};
387b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
388b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	if(bRotated) // If we're rotated then pre-process the fullscreen rect's geometry to compensate
389b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	{
390b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		for(unsigned int i = 0; i < 6; ++i)
391b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		{
392b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu			float fTmp = afVertices[i * 6 + 1];
393b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu			afVertices[i * 6 + 1] = afVertices[i * 6];
394b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu			afVertices[i * 6] = fTmp;
395b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
396b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu			fTmp = afVertices[i * 6 + 5];
397b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu			afVertices[i * 6 + 5] = afVertices[i * 6 + 4];
398b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu			afVertices[i * 6 + 4] = fTmp;
399b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		}
400b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	}
401b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
402b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glGenBuffers(1, &m_ui32FullScreenRectVBO);
403b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	m_ui32VertexStride = 6 * sizeof(GLfloat); // 4 floats for the pos, 2 for the UVs
404b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
405b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Bind the VBO
406b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glBindBuffer(GL_ARRAY_BUFFER, m_ui32FullScreenRectVBO);
407b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
408b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Set the buffer's data
409b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glBufferData(GL_ARRAY_BUFFER, 6 * m_ui32VertexStride, afVertices, GL_STATIC_DRAW);
410b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
411b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Create the VBO for the background
412b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	GLfloat afBackgroundVertices[] = {
413b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		// Left quad
414b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		-1.0f,  1.0f, 0.0f,	1.0f,	// Pos
415b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		0.0f,  1.0f,			    // UVs
416b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
417b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		-1.0f, -1.0f, 0.0f,	1.0f,
418b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		0.0f,  0.0f,
419b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
420b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		1.0f,  1.0f, 0.0f,	1.0f,
421b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		1.0f,  1.0f,
422b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
423b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		1.0f, -1.0f, 0.0f,	1.0f,
424b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		1.0f,  0.0f,
425b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	};
426b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
427b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	if(bRotated) // If we're rotated then pre-process the background geometry
428b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	{
429b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		for(unsigned int i = 0; i < 4; ++i)
430b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		{
431b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu			float fTmp = afBackgroundVertices[i * 6 + 1];
432b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu			afBackgroundVertices[i * 6 + 1] = -afBackgroundVertices[i * 6];
433b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu			afBackgroundVertices[i * 6] = -fTmp;
434b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		}
435b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	}
436b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
437b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glGenBuffers(1, &m_ui32BackgroundVBO);
438b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
439b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Bind the VBO
440b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glBindBuffer(GL_ARRAY_BUFFER, m_ui32BackgroundVBO);
441b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
442b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Set the buffer's data
443b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glBufferData(GL_ARRAY_BUFFER, 4 * m_ui32VertexStride, afBackgroundVertices, GL_STATIC_DRAW);
444b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
445b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Unbind our buffers
446b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glBindBuffer(GL_ARRAY_BUFFER, 0);
447b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
448b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu}
449b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
4503e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capensbool OGLES3ColourGrading::CreateFBO()
451b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu{
452b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0 };
453b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
454b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Query the max amount of samples that are supported, we are going to use the max
455b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	GLint samples;
4563e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens	glGetIntegerv(GL_MAX_SAMPLES, &samples);
457b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
458b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Get the currently bound frame buffer object. On most platforms this just gives 0.
459b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glGetIntegerv(GL_FRAMEBUFFER_BINDING, &m_i32OriginalFbo);
460b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
461b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Create a texture for rendering to
462b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glGenTextures(1, &m_uiTextureToRenderTo);
463b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glBindTexture(GL_TEXTURE_2D, m_uiTextureToRenderTo);
4643e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, PVRShellGet(prefWidth), PVRShellGet(prefHeight), 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
465b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
466b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
467b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
468b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
469b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
470b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Create the object that will allow us to render to the aforementioned texture
471b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glGenFramebuffers(1, &m_uiFBO);
472b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glBindFramebuffer(GL_FRAMEBUFFER, m_uiFBO);
4733e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens
4743e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens	glDrawBuffers(1, drawBuffers);
4753e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens	glReadBuffer(GL_COLOR_ATTACHMENT0);
476b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
477b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Attach the texture to the FBO
478b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_uiTextureToRenderTo, 0);
479b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
480b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Check that our FBO creation was successful
481b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	GLuint uStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
482b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	if(uStatus != GL_FRAMEBUFFER_COMPLETE)
483b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	{
484b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		PVRShellSet(prefExitMessage, "ERROR: Failed to initialise FBO");
485b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		return false;
486b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	}
487b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
4883e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens	// Create and initialize the multi-sampled FBO.
489b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
4903e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens	// Create the object that will allow us to render to the aforementioned texture
4913e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens	glGenFramebuffers(1, &m_uiFBOMultisampled);
4923e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens	glBindFramebuffer(GL_FRAMEBUFFER, m_uiFBOMultisampled);
4933e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens
4943e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens	glDrawBuffers(1, drawBuffers);
4953e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens	glReadBuffer(GL_COLOR_ATTACHMENT0);
496b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
4973e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens	// Generate and bind a render buffer which will become a multisampled depth buffer shared between our two FBOs
4983e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens	glGenRenderbuffers(1, &m_uiDepthBufferMultisampled);
4993e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens	glBindRenderbuffer(GL_RENDERBUFFER, m_uiDepthBufferMultisampled);
5003e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens	glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, GL_DEPTH_COMPONENT24, PVRShellGet(prefWidth), PVRShellGet(prefHeight));
501b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
5023e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens	glGenRenderbuffers(1, &m_uiColourBufferMultisampled);
5033e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens	glBindRenderbuffer(GL_RENDERBUFFER, m_uiColourBufferMultisampled);
5043e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens	glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, GL_RGB8, PVRShellGet(prefWidth), PVRShellGet(prefHeight));
5053e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens	glBindRenderbuffer(GL_RENDERBUFFER, 0);
506b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
5073e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens	// Attach the multisampled depth buffer we created earlier to our FBO.
5083e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_uiDepthBufferMultisampled);
509b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
5103e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens	// Attach the multisampled colour renderbuffer to the FBO
5113e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_uiColourBufferMultisampled);
512b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
5133e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens	// Check that our FBO creation was successful
5143e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens	uStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
5153e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens	if(uStatus != GL_FRAMEBUFFER_COMPLETE)
5163e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens	{
5173e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens		PVRShellSet(prefExitMessage, "ERROR: Failed to initialise multisampled FBO");
5183e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens		return false;
5193e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens	}
520b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
521b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Unbind the frame buffer object so rendering returns back to the backbuffer
522b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glBindFramebuffer(GL_FRAMEBUFFER, m_i32OriginalFbo);
523b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
524b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	return true;
525b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu}
526b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
527b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu/*!****************************************************************************
528b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu @Function		InitView
529b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu @Return		bool		true if no error occurred
530b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu @Description	Code in InitView() will be called by PVRShell upon
531b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu                initialization or after a change in the rendering context.
532b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu                Used to initialize variables that are dependent on the rendering
533b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu                context (e.g. textures, vertex buffers, etc.)
534b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu ******************************************************************************/
5353e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capensbool OGLES3ColourGrading::InitView()
536b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu{
537b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Initialize the textures used by Print3D.
538b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	bool bRotate = PVRShellGet(prefIsRotated) && PVRShellGet(prefFullScreen);
539b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
540b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	if(m_Print3D.SetTextures(0, PVRShellGet(prefWidth), PVRShellGet(prefHeight), bRotate) != PVR_SUCCESS)
541b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	{
542b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		PVRShellSet(prefExitMessage, "ERROR: Cannot initialise Print3D\n");
543b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		return false;
544b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	}
545b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
546b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Create the texture
547b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	if(PVRTTextureLoadFromPVR(c_pszMaskTexture, &m_uiMaskTexture) != PVR_SUCCESS)
548b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	{
549b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		PVRShellSet(prefExitMessage, "ERROR: Failed to load mask texture\n");
550b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		return false;
551b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	}
552b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
553b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	if(PVRTTextureLoadFromPVR(c_pszBackgroundTexture, &m_uiBackgroundTexture) != PVR_SUCCESS)
554b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	{
555b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		PVRShellSet(prefExitMessage, "ERROR: Failed to load background texture\n");
556b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		return false;
557b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	}
558b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
559b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Load our 3D texture look up tables
560b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	for(unsigned int i = 0; i < eLast; ++i)
561b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	{
562b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		if(PVRTTextureLoadFromPVR(c_pszLUTs[i], &m_uiLUTs[i]) != PVR_SUCCESS)
563b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		{
564b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu			PVRShellSet(prefExitMessage, "ERROR: Failed to load a 3D texture\n");
565b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu			return false;
566b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		}
567b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
5683e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
5693e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
5703e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
571b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
5723e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5733e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
574b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	}
575b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
576b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Load the effects
577b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	CPVRTString ErrorStr;
578b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	if(!LoadShaders(ErrorStr))
579b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	{
580b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		PVRShellSet(prefExitMessage, ErrorStr.c_str());
581b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		return false;
582b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	}
583b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
584b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Create FBOs
585b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	if(!CreateFBO())
586b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	{
587b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		PVRShellSet(prefExitMessage, "Failed to create FBO");
588b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		return false;
589b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	}
590b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
591b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Initialise VBO data
592b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	LoadVbos(bRotate);
593b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
594b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Calculate the projection and view matrices
595b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	float fAspect = PVRShellGet(prefWidth) / (float)PVRShellGet(prefHeight);
596b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	m_mViewProjection = PVRTMat4::PerspectiveFovRH(CAM_FOV, fAspect, CAM_NEAR, CAM_FAR, PVRTMat4::OGL, bRotate);
597b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	m_mViewProjection *= PVRTMat4::LookAtRH(PVRTVec3(0.f, 0.f, 150.f), PVRTVec3(0.f), PVRTVec3(0.f, 1.f, 0.f));
598b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
599b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Enable backface culling and depth test
600b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glEnable(GL_CULL_FACE);
601b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glEnable(GL_DEPTH_TEST);
602b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
603b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Set the clear colour
604b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
605b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
606b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Store initial time
607b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	m_ulStartTime = PVRShellGetTime();
608b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
609b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	return true;
610b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu}
611b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
612b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu/*!****************************************************************************
613b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu @Function		ReleaseView
614b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu @Return		bool		true if no error occurred
615b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu @Description	Code in ReleaseView() will be called by PVRShell when the
616b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu                application quits or before a change in the rendering context.
617b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu ******************************************************************************/
6183e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capensbool OGLES3ColourGrading::ReleaseView()
619b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu{
620b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Frees the texture
621b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glDeleteTextures(1, &m_uiMaskTexture);
622b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glDeleteTextures(1, &m_uiBackgroundTexture);
623b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glDeleteTextures(eLast, m_uiLUTs);
624b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glDeleteTextures(1, &m_uiTextureToRenderTo);
625b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
626b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Release Vertex buffer object.
627b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glDeleteBuffers(1, &m_ui32FullScreenRectVBO);
628b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glDeleteBuffers(1, &m_ui32BackgroundVBO);
629b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
630b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Release effects
631b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glDeleteShader(m_uiPostVertShader);
632b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glDeleteShader(m_uiPostFragShader);
633b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glDeleteShader(m_uiBackgroundFragShader);
634b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glDeleteShader(m_uiSceneVertShader);
635b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glDeleteShader(m_uiSceneFragShader);
636b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
637b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glDeleteProgram(m_PostShaderProgram.uiId);
638b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glDeleteProgram(m_BackgroundShaderProgram.uiId);
639b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glDeleteProgram(m_SceneShaderProgram.uiId);
640b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
641b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Tidy up the FBOs and renderbuffers
642b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
643b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Delete frame buffer objects
644b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glDeleteFramebuffers(1, &m_uiFBO);
645b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glDeleteFramebuffers(1, &m_uiFBOMultisampled);
646b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
647b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Delete our depth buffer
648b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glDeleteRenderbuffers(1, &m_uiDepthBufferMultisampled);
649b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glDeleteRenderbuffers(1, &m_uiColourBufferMultisampled);
650b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
651b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Delete buffer objects
652b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glDeleteBuffers(m_Mask.nNumMesh, m_puiMaskVBO);
653b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glDeleteBuffers(m_Mask.nNumMesh, m_puiMaskIBO);
654b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
655b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Release Print3D Textures
656b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	m_Print3D.ReleaseTextures();
657b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
658b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	return true;
659b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu}
660b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
661b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu/*!****************************************************************************
662b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu @Function		RenderScene
663b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu @Return		bool		true if no error occurred
664b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu @Description	Main rendering loop function of the program. The shell will
665b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu                call this function every frame.
666b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu                eglSwapBuffers() will be performed by PVRShell automatically.
667b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu                PVRShell will also manage important OS events.
668b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu                Will also manage relevant OS events. The user has access to
669b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu				these events through an abstraction layer provided by PVRShell.
670b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu ******************************************************************************/
6713e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capensbool OGLES3ColourGrading::RenderScene()
672b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu{
673b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Clears the colour buffer
674b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
675b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
676b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	unsigned long ulTime = PVRShellGetTime() - m_ulStartTime;
677b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
678b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Process input to switch between tone mapping operators
679b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	if(PVRShellIsKeyPressed(PVRShellKeyNameRIGHT))
680b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	{
681b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		++m_iCurrentLUT;
682b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
683b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		if(m_iCurrentLUT > eB)
684b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu			m_iCurrentLUT = eA;
685b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	}
686b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	else if(PVRShellIsKeyPressed(PVRShellKeyNameLEFT))
687b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	{
688b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		--m_iCurrentLUT;
689b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
690b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		if(m_iCurrentLUT < eA)
691b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu			m_iCurrentLUT = eB;
692b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	}
6933e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens
694b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Render to our texture
695b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	{
696b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		// Bind our FBO
6973e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens		glBindFramebuffer(GL_FRAMEBUFFER, m_uiFBOMultisampled);
698b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
699b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		// Clear the colour and depth buffer of our FBO surface
700b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
701b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
702b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		glDisable(GL_CULL_FACE);
703b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		glDisable(GL_DEPTH_TEST);
704b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
705b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		// Bind the VBO
706b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		glBindBuffer(GL_ARRAY_BUFFER, m_ui32BackgroundVBO);
707b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
708b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		// Use shader program
709b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		glUseProgram(m_BackgroundShaderProgram.uiId);
710b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
711b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		// Enable the vertex attribute arrays
712b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		glEnableVertexAttribArray(VERTEX_ARRAY);
713b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		glEnableVertexAttribArray(TEXCOORD_ARRAY);
714b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
715b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		// Set the vertex attribute offsets
716b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		glVertexAttribPointer(VERTEX_ARRAY, 4, GL_FLOAT, GL_FALSE, m_ui32VertexStride, 0);
717b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		glVertexAttribPointer(TEXCOORD_ARRAY, 2, GL_FLOAT, GL_FALSE, m_ui32VertexStride, (void*) (4 * sizeof(GLfloat)));
718b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
719b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		// Bind texture
720b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		glActiveTexture(GL_TEXTURE0);
721b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		glBindTexture(GL_TEXTURE_2D, m_uiBackgroundTexture);
722b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
723b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		// Draw a screen-aligned quad.
724b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
725b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		// Draws a non-indexed triangle array
726b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
727b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
728b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		// Safely disable the vertex attribute arrays
729b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		glDisableVertexAttribArray(VERTEX_ARRAY);
730b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		glDisableVertexAttribArray(TEXCOORD_ARRAY);
731b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
732b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		glEnable(GL_CULL_FACE);
733b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		glEnable(GL_DEPTH_TEST);
734b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
735b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		// Use shader program
736b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		glUseProgram(m_SceneShaderProgram.uiId);
737b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
738b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		// Rotate the model matrix
739b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		PVRTMat4 mModel = PVRTMat4::RotationY(ulTime * 0.0015f);
740b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
741b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		// Calculate model view projection matrix
742b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		PVRTMat4 mMVP = m_mViewProjection * mModel;
743b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
744b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		// Feeds Projection Model View matrix to the shaders
745b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		glUniformMatrix4fv(m_SceneShaderProgram.uiMVPMatrixLoc, 1, GL_FALSE, mMVP.ptr());
746b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
747b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		PVRTVec3 vMsLightDir = (PVRTVec3(1, 1, 1) * PVRTMat3(mModel)).normalized();
748b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		glUniform3fv(m_SceneShaderProgram.uiLightDirLoc, 1, vMsLightDir.ptr());
749b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
750b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		glBindTexture(GL_TEXTURE_2D, m_uiMaskTexture);
751b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
752b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		// Now that the uniforms are set, call another function to actually draw the mesh.
753b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		DrawMesh(0);
754b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
755b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		// Unbind the VBO
756b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		glBindBuffer(GL_ARRAY_BUFFER, 0);
757b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
7583e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens		//	Give the drivers a hint that we don't want the depth and stencil information stored for future use.
7593e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens		const GLenum attachments[] = { GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT };
7603e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens		glInvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments);
761b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
762b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		// Blit and resolve the multisampled render buffer to the non-multisampled FBO
7633e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens		glBindFramebuffer(GL_READ_FRAMEBUFFER, m_uiFBOMultisampled);
7643e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_uiFBO);
7653e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens		glBlitFramebuffer(0, 0, PVRShellGet(prefWidth), PVRShellGet(prefHeight), 0, 0, PVRShellGet(prefWidth), PVRShellGet(prefHeight), GL_COLOR_BUFFER_BIT, GL_NEAREST);
766b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
767b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		// We are done with rendering to our FBO so switch back to the back buffer.
768b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu		glBindFramebuffer(GL_FRAMEBUFFER, m_i32OriginalFbo);
769b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	}
770b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
771b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glDisable(GL_CULL_FACE);
772b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glDisable(GL_DEPTH_TEST);
773b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
774b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Use shader program
775b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glUseProgram(m_PostShaderProgram.uiId);
7763e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens
777b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Bind the VBO
778b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glBindBuffer(GL_ARRAY_BUFFER, m_ui32FullScreenRectVBO);
7793e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens
780b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Enable the vertex attribute arrays
781b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glEnableVertexAttribArray(VERTEX_ARRAY);
782b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glEnableVertexAttribArray(TEXCOORD_ARRAY);
783b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
784b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Set the vertex attribute offsets
785b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glVertexAttribPointer(VERTEX_ARRAY, 4, GL_FLOAT, GL_FALSE, m_ui32VertexStride, 0);
786b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glVertexAttribPointer(TEXCOORD_ARRAY, 2, GL_FLOAT, GL_FALSE, m_ui32VertexStride, (void*) (4 * sizeof(GLfloat)));
7873e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens
788b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Bind texture
789b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glActiveTexture(GL_TEXTURE0);
790b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glBindTexture(GL_TEXTURE_2D, m_uiTextureToRenderTo);
791b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
792b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glActiveTexture(GL_TEXTURE1);
7933e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens	glBindTexture(GL_TEXTURE_3D, m_uiLUTs[m_iCurrentLUT]);
794b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
795b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Draw a screen-aligned quad.
796b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
797b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Draw the left-hand side that shows the scene with the colour grading applied
798b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
799b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
800b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Draw the right-hande side showing the scene how it looks without
8013e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens	glBindTexture(GL_TEXTURE_3D, m_uiLUTs[eIdentity]);
802b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glDrawArrays(GL_TRIANGLE_STRIP, 2, 4);
803b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
804b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Safely disable the vertex attribute arrays
805b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glDisableVertexAttribArray(VERTEX_ARRAY);
806b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glDisableVertexAttribArray(TEXCOORD_ARRAY);
807b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
808b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Unbind the VBO
809b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glBindBuffer(GL_ARRAY_BUFFER, 0);
810b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
811b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Render title
812b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	m_Print3D.DisplayDefaultTitle("Colour grading using 3D textures", c_pszLUTNames[m_iCurrentLUT], ePVRTPrint3DSDKLogo);
813b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	m_Print3D.Flush();
814b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
815b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	return true;
816b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu}
817b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
818b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu/*!****************************************************************************
819b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu @Function		DrawMesh
820b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu @Input			i32NodeIndex		Node index of the mesh to draw
821b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu @Description	Draws a SPODMesh after the model view matrix has been set and
822b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu				the material prepared.
823b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu******************************************************************************/
8243e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capensvoid OGLES3ColourGrading::DrawMesh(const int i32NodeIndex)
825b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu{
826b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	int i32MeshIndex = m_Mask.pNode[i32NodeIndex].nIdx;
827b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	SPODMesh* pMesh = &m_Mask.pMesh[i32MeshIndex];
828b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
829b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// bind the VBO for the mesh
830b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glBindBuffer(GL_ARRAY_BUFFER, m_puiMaskVBO[i32MeshIndex]);
831b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// bind the index buffer, won't hurt if the handle is 0
832b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_puiMaskIBO[i32MeshIndex]);
833b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
834b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Enable the vertex attribute arrays
835b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glEnableVertexAttribArray(VERTEX_ARRAY);
836b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glEnableVertexAttribArray(NORMAL_ARRAY);
837b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glEnableVertexAttribArray(TEXCOORD_ARRAY);
838b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
839b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Set the vertex attribute offsets
840b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glVertexAttribPointer(VERTEX_ARRAY, 3, GL_FLOAT, GL_FALSE, pMesh->sVertex.nStride, pMesh->sVertex.pData);
841b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glVertexAttribPointer(NORMAL_ARRAY, 3, GL_FLOAT, GL_FALSE, pMesh->sNormals.nStride, pMesh->sNormals.pData);
842b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glVertexAttribPointer(TEXCOORD_ARRAY, 2, GL_FLOAT, GL_FALSE, pMesh->psUVW[0].nStride, pMesh->psUVW[0].pData);
843b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
844b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Indexed Triangle list
845b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glDrawElements(GL_TRIANGLES, pMesh->nNumFaces*3, GL_UNSIGNED_SHORT, 0);
846b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
847b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	// Safely disable the vertex attribute arrays
848b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glDisableVertexAttribArray(VERTEX_ARRAY);
849b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glDisableVertexAttribArray(NORMAL_ARRAY);
850b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glDisableVertexAttribArray(TEXCOORD_ARRAY);
851b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
852b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glBindBuffer(GL_ARRAY_BUFFER, 0);
853b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
854b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu}
855b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
856b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu/*!****************************************************************************
857b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu @Function		NewDemo
858b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu @Return		PVRShell*		The demo supplied by the user
859b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu @Description	This function must be implemented by the user of the shell.
860b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu                The user should return its PVRShell object defining the
861b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu				behaviour of the application.
862b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu ******************************************************************************/
863b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis HetuPVRShell* NewDemo()
864b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu{
8653e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens	return new OGLES3ColourGrading();
866b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu}
867b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
868b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu/******************************************************************************
8693e3a025e14e5076f3be348ee42b0723889e3d2a2Nicolas Capens End of file (OGLES3ColourGrading.cpp)
870b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu ******************************************************************************/
871b027aa91f4b20c5062fbc781d0ff693bf294cbccAlexis Hetu
872