123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767 |
- /******************************************************************************
- @File OGLES2ShadowMapping.cpp
- @Title Introducing the POD 3D file format
- @Version
- @Copyright Copyright (C) Imagination Technologies Limited.
- @Platform Independent
- @Description Shows how to load POD files and play the animation with basic
- lighting
- ******************************************************************************/
- #include <string.h>
- #include "PVRShell.h"
- #include "OGLES2Tools.h"
- /******************************************************************************
- Defines
- ******************************************************************************/
- // Index to bind the attributes to vertex shaders
- #define VERTEX_ARRAY 0
- #define NORMAL_ARRAY 1
- #define TEXCOORD_ARRAY 2
- /******************************************************************************
- Consts
- ******************************************************************************/
- // Camera constants. Used for making the projection matrix
- const float g_fCameraNear = 5.0f;
- const float g_fCameraFar = 400.0f;
- // Const for the shadow map texture size
- const unsigned int m_ui32ShadowMapSize = 512;
- /******************************************************************************
- Content file names
- ******************************************************************************/
- // Source and binary shaders
- const char c_szFragShaderSrcFile[] = "FragShader.fsh";
- const char c_szFragShaderBinFile[] = "FragShader.fsc";
- const char c_szVertShaderSrcFile[] = "VertShader.vsh";
- const char c_szVertShaderBinFile[] = "VertShader.vsc";
- const char c_szShadowMapppingFragSrcFile[] = "ShadowFragShader.fsh";
- const char c_szShadowMapppingFragBinFile[] = "ShadowFragShader.fsc";
- const char c_szShadowMapppingVertSrcFile[] = "ShadowVertShader.vsh";
- const char c_szShadowMapppingVertBinFile[] = "ShadowVertShader.vsc";
- // POD scene files
- const char c_szSceneFile[] = "Scene.pod";
- const char c_szMaskTex[] = "Mask.pvr";
- const char c_szTableCoverTex[] = "TableCover.pvr";
- const char c_szTorusTex[] = "Torus.pvr";
- /*!****************************************************************************
- Class implementing the PVRShell functions.
- ******************************************************************************/
- class OGLES2ShadowMapping : public PVRShell
- {
- // Print3D class used to display text
- CPVRTPrint3D m_Print3D;
- // 3D Model
- CPVRTModelPOD m_Scene;
- // OpenGL handles for shaders, textures and VBOs
- GLuint m_uiSimpleVertShader;
- GLuint m_uiSimpleFragShader;
- GLuint m_uiShadowVertShader;
- GLuint m_uiShadowFragShader;
- GLuint* m_puiVbo;
- GLuint* m_puiIndexVbo;
- GLuint* m_puiTextureIDs;
- GLuint m_uiMask;
- GLuint m_uiTableCover;
- GLuint m_uiTorus;
- GLuint m_uiShadowMapTexture;
- GLuint m_uiFrameBufferObject;
- float m_fLightDistance;
- float m_fLightAngle;
- // Group shader programs and their uniform locations together
- struct
- {
- GLuint uiId;
- GLuint uiLightDirLoc;
- GLuint uiProjectionMatrixLoc;
- GLuint uiTexProjMatrixLoc;
- GLuint uiModelViewMatrixLoc;
- }
- m_ShadowShaderProgram;
- struct
- {
- GLuint uiId;
- GLuint uiModelViewMatrixLoc;
- GLuint uiProjectionMatrixLoc;
- }
- m_SimpleShaderProgram;
- PVRTVec4 m_vLightDirection;
- PVRTVec3 m_vLightPosition;
- PVRTMat4 m_View, m_Projection;
- PVRTMat4 m_LightProjection, m_LightView;
- PVRTMat4 m_BiasMatrix;
- // Screen orientation variable
- bool m_bRotate;
- public:
- virtual bool InitApplication();
- virtual bool InitView();
- virtual bool ReleaseView();
- virtual bool QuitApplication();
- virtual bool RenderScene();
- bool LoadTextures(CPVRTString* pErrorStr);
- bool LoadShaders(CPVRTString* pErrorStr);
- bool LoadVbos(CPVRTString* pErrorStr);
- void SetUpMatrices();
- void DrawSceneWithShadow(PVRTMat4 viewMat);
- void DrawMesh(int i32NodeIndex);
- void RenderWorld();
- };
- /*!****************************************************************************
- @Function LoadTextures
- @Output pErrorStr A CPVRTString describing the error on failure
- @Return bool true if no error occured
- @Description Loads the textures required for this training course
- ******************************************************************************/
- bool OGLES2ShadowMapping::LoadTextures(CPVRTString* const pErrorStr)
- {
- /*
- Loads the textures.
- For a more detailed explanation, see Texturing and IntroducingPVRTools
- */
- /*
- Initialises an array to lookup the textures
- for each material in the scene.
- */
- m_puiTextureIDs = new GLuint[m_Scene.nNumMaterial];
- if(!m_puiTextureIDs)
- {
- *pErrorStr = "ERROR: Insufficient memory.";
- return false;
- }
- if(PVRTTextureLoadFromPVR(c_szTableCoverTex, &m_uiTableCover) != PVR_SUCCESS)
- return false;
- if(PVRTTextureLoadFromPVR(c_szTorusTex, &m_uiTorus) != PVR_SUCCESS)
- return false;
- if(PVRTTextureLoadFromPVR(c_szMaskTex, &m_uiMask) != PVR_SUCCESS)
- return false;
-
- for(unsigned int i = 0; i < m_Scene.nNumMaterial; ++i)
- {
- m_puiTextureIDs[i] = 0;
- SPODMaterial* pMaterial = &m_Scene.pMaterial[i];
- if(!strcmp(pMaterial->pszName, "Material #1"))
- m_puiTextureIDs[i] = m_uiTableCover;
- else if(!strcmp(pMaterial->pszName, "Material #2"))
- m_puiTextureIDs[i] = m_uiTorus;
- else
- m_puiTextureIDs[i] = m_uiMask;
- }
- //Create the shadow map texture
- glGenTextures(1, &m_uiShadowMapTexture);
- glBindTexture(GL_TEXTURE_2D, m_uiShadowMapTexture);
-
- // Create the depth texture.
- glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, m_ui32ShadowMapSize, m_ui32ShadowMapSize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
- // Set the textures parameters
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- return true;
- }
- /*!****************************************************************************
- @Function SetUpMatrices
- @Description Creates the view and projection matrices for the light and camera
- ******************************************************************************/
- void OGLES2ShadowMapping::SetUpMatrices()
- {
- PVRTVec3 vFrom = PVRTVec3(-130.0f, 130.0f, -130.0f ),
- vTo = PVRTVec3( 0, 10, 0 ),
- vUp = PVRTVec3( 0, 1, 0 );
- float fFOV= 0.78539819f;
- m_BiasMatrix = PVRTMat4(0.5f, 0.0f, 0.0f, 0.0f,
- 0.0f, 0.5f, 0.0f, 0.0f,
- 0.0f, 0.0f, 0.5f, 0.0f,
- 0.5f, 0.5f, 0.5f, 1.0f);
-
- bool bRotate = PVRShellGet(prefIsRotated) && PVRShellGet(prefFullScreen);
- m_Projection = PVRTMat4::PerspectiveFovRH(fFOV, (float)PVRShellGet(prefWidth)/(float)PVRShellGet(prefHeight), g_fCameraNear, g_fCameraFar, PVRTMat4::OGL, bRotate);
-
- m_View = PVRTMat4::LookAtRH(vFrom, vTo, vUp);
-
- m_LightProjection = PVRTMat4::PerspectiveFovRH(fFOV, 1.0f, 70.0f, 270.0f, PVRTMat4::OGL, m_bRotate);
-
- m_LightView = PVRTMat4::LookAtRH(m_vLightPosition, vTo, vUp);
- }
- /*!****************************************************************************
- @Function LoadShaders
- @Output pErrorStr A string describing the error on failure
- @Return bool true if no error occured
- @Description Loads and compiles the shaders and links the shader programs
- required for this training course
- ******************************************************************************/
- bool OGLES2ShadowMapping::LoadShaders(CPVRTString* pErrorStr)
- {
- const char* aszAttribs[] = { "inVertex", "inNormal", "inTexCoord" };
- /*
- Load and compile the shaders from files.
- Binary shaders are tried first, source shaders
- are used as fallback.
- */
- if(PVRTShaderLoadFromFile(
- c_szVertShaderBinFile, c_szVertShaderSrcFile, GL_VERTEX_SHADER, GL_SGX_BINARY_IMG, &m_uiSimpleVertShader, pErrorStr) != PVR_SUCCESS)
- {
- return false;
- }
- if(PVRTShaderLoadFromFile(
- c_szFragShaderBinFile, c_szFragShaderSrcFile, GL_FRAGMENT_SHADER, GL_SGX_BINARY_IMG, &m_uiSimpleFragShader, pErrorStr) != PVR_SUCCESS)
- {
- return false;
- }
- if(PVRTCreateProgram(&m_SimpleShaderProgram.uiId, m_uiSimpleVertShader, m_uiSimpleFragShader, aszAttribs, 3, pErrorStr) != PVR_SUCCESS)
- {
- PVRShellSet(prefExitMessage, pErrorStr->c_str());
- return false;
- }
- m_SimpleShaderProgram.uiModelViewMatrixLoc = glGetUniformLocation(m_SimpleShaderProgram.uiId, "ModelViewMatrix");
- m_SimpleShaderProgram.uiProjectionMatrixLoc = glGetUniformLocation(m_SimpleShaderProgram.uiId, "ProjectionMatrix");
-
- if(PVRTShaderLoadFromFile(
- c_szShadowMapppingVertBinFile, c_szShadowMapppingVertSrcFile, GL_VERTEX_SHADER, GL_SGX_BINARY_IMG, &m_uiShadowVertShader, pErrorStr) != PVR_SUCCESS)
- {
- return false;
- }
- if(PVRTShaderLoadFromFile(
- c_szShadowMapppingFragBinFile, c_szShadowMapppingFragSrcFile, GL_FRAGMENT_SHADER, GL_SGX_BINARY_IMG, &m_uiShadowFragShader, pErrorStr) != PVR_SUCCESS)
- {
- return false;
- }
- if(PVRTCreateProgram(&m_ShadowShaderProgram.uiId, m_uiShadowVertShader, m_uiShadowFragShader, aszAttribs, 3, pErrorStr) != PVR_SUCCESS)
- {
- PVRShellSet(prefExitMessage, pErrorStr->c_str());
- return false;
- }
-
- m_ShadowShaderProgram.uiTexProjMatrixLoc = glGetUniformLocation(m_ShadowShaderProgram.uiId, "TexProjectionMatrix");
- m_ShadowShaderProgram.uiModelViewMatrixLoc = glGetUniformLocation(m_ShadowShaderProgram.uiId, "ModelViewMatrix");
- m_ShadowShaderProgram.uiProjectionMatrixLoc = glGetUniformLocation(m_ShadowShaderProgram.uiId, "ProjectionMatrix");
- m_ShadowShaderProgram.uiLightDirLoc = glGetUniformLocation(m_ShadowShaderProgram.uiId, "LightDirection");
- glUniform1i(glGetUniformLocation(m_ShadowShaderProgram.uiId, "sShadow"), 0);
- glUniform1i(glGetUniformLocation(m_ShadowShaderProgram.uiId, "sTexture"), 1);
- return true;
- }
- /*!****************************************************************************
- @Function LoadVbos
- @Description Loads the mesh data required for this training course into
- vertex buffer objects
- ******************************************************************************/
- bool OGLES2ShadowMapping::LoadVbos(CPVRTString* pErrorStr)
- {
- if(!m_Scene.pMesh[0].pInterleaved)
- {
- *pErrorStr = "ERROR: IntroducingPOD requires the pod data to be interleaved. Please re-export with the interleaved option enabled.";
- return false;
- }
- if (!m_puiVbo) m_puiVbo = new GLuint[m_Scene.nNumMesh];
- if (!m_puiIndexVbo) m_puiIndexVbo = new GLuint[m_Scene.nNumMesh];
- /*
- Load vertex data of all meshes in the scene into VBOs
- The meshes have been exported with the "Interleave Vectors" option,
- so all data is interleaved in the buffer at pMesh->pInterleaved.
- Interleaving data improves the memory access pattern and cache efficiency,
- thus it can be read faster by the hardware.
- */
- glGenBuffers(m_Scene.nNumMesh, m_puiVbo);
- for (unsigned int i = 0; i < m_Scene.nNumMesh; ++i)
- {
- // Load vertex data into buffer object
- SPODMesh& Mesh = m_Scene.pMesh[i];
- unsigned int uiSize = Mesh.nNumVertex * Mesh.sVertex.nStride;
- glBindBuffer(GL_ARRAY_BUFFER, m_puiVbo[i]);
- glBufferData(GL_ARRAY_BUFFER, uiSize, Mesh.pInterleaved, GL_STATIC_DRAW);
- // Load index data into buffer object if available
- m_puiIndexVbo[i] = 0;
- if (Mesh.sFaces.pData)
- {
- glGenBuffers(1, &m_puiIndexVbo[i]);
- uiSize = PVRTModelPODCountIndices(Mesh) * sizeof(GLshort);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_puiIndexVbo[i]);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, uiSize, Mesh.sFaces.pData, GL_STATIC_DRAW);
- }
- }
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- return true;
- }
- /*!****************************************************************************
- @Function InitApplication
- @Return bool true if no error occured
- @Description Code in InitApplication() will be called by PVRShell once per
- run, before the rendering context is created.
- Used to initialize variables that are not dependant on it
- (e.g. external modules, loading meshes, etc.)
- If the rendering context is lost, InitApplication() will
- not be called again.
- ******************************************************************************/
- bool OGLES2ShadowMapping::InitApplication()
- {
- m_puiVbo = 0;
- m_puiIndexVbo = 0;
- m_puiTextureIDs = 0;
- // Get and set the read path for content files
- CPVRTResourceFile::SetReadPath((char*)PVRShellGet(prefReadPath));
- // Load the scene
- if (m_Scene.ReadFromFile(c_szSceneFile) != PVR_SUCCESS)
- {
- PVRShellSet(prefExitMessage, "ERROR: Couldn't load the .pod file\n");
- return false;
- }
- m_vLightPosition.x = 0.f;
- m_vLightPosition.y = 90.f;
- m_vLightPosition.z = 0.f;
- m_vLightDirection.x = -m_vLightPosition.x;
- m_vLightDirection.y = -m_vLightPosition.y;
- m_vLightDirection.z = -m_vLightPosition.z;
- m_vLightDirection.w = 1.0f;
- // Specify the light distance from origin. This should be at a distance to fit everything into the viewport
- // when rendering from the lights POV.
- m_fLightDistance = 100.0f;
- m_fLightAngle = PVRT_PI;
- return true;
- }
- /*!****************************************************************************
- @Function QuitApplication
- @Return bool true if no error occured
- @Description Code in QuitApplication() will be called by PVRShell once per
- run, just before exiting the program.
- If the rendering context is lost, QuitApplication() will
- not be called.
- ******************************************************************************/
- bool OGLES2ShadowMapping::QuitApplication()
- {
- // Free the memory allocated for the scene
- m_Scene.Destroy();
- delete [] m_puiVbo;
- delete [] m_puiIndexVbo;
- return true;
- }
- /*!****************************************************************************
- @Function InitView
- @Return bool true if no error occured
- @Description Code in InitView() will be called by PVRShell upon
- initialization or after a change in the rendering context.
- Used to initialize variables that are dependant on the rendering
- context (e.g. textures, vertex buffers, etc.)
- ******************************************************************************/
- bool OGLES2ShadowMapping::InitView()
- {
- CPVRTString ErrorStr;
- if(!CPVRTgles2Ext::IsGLExtensionSupported("GL_OES_depth_texture"))
- {
- PVRShellSet(prefExitMessage, "Error: Unable to run this training course as it requires extension 'GL_OES_depth_texture'");
- return false;
- }
- m_bRotate = PVRShellGet(prefIsRotated) && PVRShellGet(prefFullScreen);
- // Initialize VBO data
- if(!LoadVbos(&ErrorStr))
- {
- PVRShellSet(prefExitMessage, ErrorStr.c_str());
- return false;
- }
- // Load textures
- if (!LoadTextures(&ErrorStr))
- {
- PVRShellSet(prefExitMessage, ErrorStr.c_str());
- return false;
- }
- // Load and compile the shaders & link programs
- if (!LoadShaders(&ErrorStr))
- {
- PVRShellSet(prefExitMessage, ErrorStr.c_str());
- return false;
- }
- // Create a frame buffer with only the depth buffer attached
- glGenFramebuffers(1, &m_uiFrameBufferObject);
- glBindFramebuffer(GL_FRAMEBUFFER, m_uiFrameBufferObject);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_uiShadowMapTexture, 0);
-
- /*if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
- {
- PVRShellSet(prefExitMessage, "ERROR: Frame buffer not set up correctly\n");
- return false;
-
- }*/
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
- // Initialize Print3D
- if(m_Print3D.SetTextures(0,PVRShellGet(prefWidth),PVRShellGet(prefHeight),m_bRotate) != PVR_SUCCESS)
- {
- PVRShellSet(prefExitMessage, "ERROR: Cannot initialise Print3D\n");
- return false;
- }
- // Use a nice bright blue as clear colour
- glClearColor(0.6f, 0.8f, 1.0f, 1.0f);
- return true;
- }
- /*!****************************************************************************
- @Function ReleaseView
- @Return bool true if no error occured
- @Description Code in ReleaseView() will be called by PVRShell when the
- application quits or before a change in the rendering context.
- ******************************************************************************/
- bool OGLES2ShadowMapping::ReleaseView()
- {
- // Deletes the textures
- glDeleteTextures(m_Scene.nNumMaterial, &m_puiTextureIDs[0]);
- // Frees the texture lookup array
- delete[] m_puiTextureIDs;
- m_puiTextureIDs = 0;
- // Delete program and shader objects
- glDeleteProgram(m_ShadowShaderProgram.uiId);
- glDeleteShader(m_uiShadowVertShader);
- glDeleteShader(m_uiShadowFragShader);
- // Delete program and shader objects
- glDeleteProgram(m_SimpleShaderProgram.uiId);
- glDeleteShader(m_uiSimpleVertShader);
- glDeleteShader(m_uiSimpleFragShader);
- // Delete buffer objects
- glDeleteBuffers(m_Scene.nNumMesh, m_puiVbo);
- glDeleteBuffers(m_Scene.nNumMesh, m_puiIndexVbo);
- // Release Print3D Textures
- m_Print3D.ReleaseTextures();
- return true;
- }
- /*!****************************************************************************
- @Function RenderScene
- @Return bool true if no error occured
- @Description Main rendering loop function of the program. The shell will
- call this function every frame.
- eglSwapBuffers() will be performed by PVRShell automatically.
- PVRShell will also manage important OS events.
- Will also manage relevent OS events. The user has access to
- these events through an abstraction layer provided by PVRShell.
- ******************************************************************************/
- bool OGLES2ShadowMapping::RenderScene()
- {
- //rotate light position
- m_fLightAngle += 0.01f;
- m_vLightPosition.x = m_fLightDistance * (float) cos(m_fLightAngle);
- m_vLightPosition.z = m_fLightDistance * (float) sin(m_fLightAngle);
- m_vLightDirection.x = -m_vLightPosition.x;
- m_vLightDirection.z = -m_vLightPosition.z;
- SetUpMatrices();
- glEnable(GL_DEPTH_TEST);
- // Bind the frame buffer object
- glBindFramebuffer(GL_FRAMEBUFFER, m_uiFrameBufferObject);
- if(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE)
- {
- // Clear the screen and depth buffer so we can render from the light's view
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- // Set the current viewport to our texture size
- glViewport(0, 0, m_ui32ShadowMapSize, m_ui32ShadowMapSize);
- // Since we don't care about colour when rendering the depth values to
- // the shadow-map texture, we disable color writing to increase speed.
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
- // Enable the simple shader for the light view pass. This render will not be shown to the user
- // so only the simplest render needs to be implemented
- glUseProgram(m_SimpleShaderProgram.uiId);
- // Set the light projection matrix
- glUniformMatrix4fv(m_SimpleShaderProgram.uiProjectionMatrixLoc, 1, GL_FALSE, m_LightProjection.f);
- // Draw everything that we would like to cast a shadow
- for(unsigned int i = 2; i < m_Scene.nNumMeshNode; ++i)
- {
- SPODNode& Node = m_Scene.pNode[i];
- PVRTMat4 mWorld, mModelView;
- m_Scene.GetWorldMatrix(mWorld, Node);
- PVRTMatrixMultiply(mModelView, mWorld, m_LightView);
- glUniformMatrix4fv(m_SimpleShaderProgram.uiModelViewMatrixLoc, 1, GL_FALSE, mModelView.f);
-
- DrawMesh(i);
- }
- // We can turn color writing back on since we already stored the depth values
- #if defined(__PALMPDK__)
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); // The alpha part is false as we don't want to blend with the video layer on the Palm Pre
- #else
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- #endif
- // Restore our normal viewport size to our screen width and height
- glViewport(0, 0,PVRShellGet(prefWidth),PVRShellGet(prefHeight));
- }
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
- // Clear the colour and depth buffers, we are now going to render the scene again from scratch
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
- // Load the shadow shader. This shader requires additional parameters; texProjMatrix for the depth buffer
- // look up and the light direction for diffuse light (the effect is a lot nicer with the additon of the
- // diffuse light).
- glUseProgram(m_ShadowShaderProgram.uiId);
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, m_uiShadowMapTexture);
- glUniformMatrix4fv(m_ShadowShaderProgram.uiProjectionMatrixLoc, 1, GL_FALSE, m_Projection.f);
- PVRTMat4 mViewInv, mTextureMatrix, mMatrix;
- mViewInv = m_View.inverse();
- // We need to calculate the texture projection matrix. This matrix takes the pixels from world space to previously rendered light projection space
- //where we can look up values from our saved depth buffer. The matrix is constructed from the light view and projection matrices as used for the previous render and
- //then multiplied by the inverse of the current view matrix.
- mTextureMatrix = m_BiasMatrix * m_LightProjection * m_LightView * mViewInv;
- glUniformMatrix4fv(m_ShadowShaderProgram.uiTexProjMatrixLoc, 1, GL_FALSE, mTextureMatrix.f);
- DrawSceneWithShadow(m_View);
- // Re-enable the simple shader to draw the light source object
- glUseProgram(m_SimpleShaderProgram.uiId);
- SPODNode& Node = m_Scene.pNode[1];
- PVRTMat4 mWorld, mModelView;
- m_Scene.GetWorldMatrix(mWorld, Node);
- mWorld.f[12] = m_vLightPosition.x;
- mWorld.f[13] = m_vLightPosition.y;
- mWorld.f[14] = m_vLightPosition.z;
- mModelView = m_View * mWorld;
- glUniformMatrix4fv(m_SimpleShaderProgram.uiModelViewMatrixLoc, 1, GL_FALSE, mModelView.f);
- glUniformMatrix4fv(m_SimpleShaderProgram.uiProjectionMatrixLoc, 1, GL_FALSE, m_LightProjection.f);
- DrawMesh(1);
- m_Print3D.DisplayDefaultTitle("ShadowMap", "", ePVRTPrint3DSDKLogo);
- m_Print3D.Flush();
- return true;
- }
- /*!****************************************************************************
- @Function DrawSceneWithShadow
- @Input viewMat The view matrix to use for rendering
- @Description Draws the scene with the shadow
- ******************************************************************************/
- void OGLES2ShadowMapping::DrawSceneWithShadow(PVRTMat4 viewMat)
- {
- for (unsigned int i = 0; i < m_Scene.nNumMeshNode; ++i)
- {
- if(i == 1) continue;
- SPODNode& Node = m_Scene.pNode[i];
- PVRTMat4 mWorld, mModelView;
- m_Scene.GetWorldMatrix(mWorld, Node);
- PVRTMatrixMultiply(mModelView, mWorld, viewMat);
- glUniformMatrix4fv(m_ShadowShaderProgram.uiModelViewMatrixLoc, 1, GL_FALSE, mModelView.f);
- // Calculate the light direction for the diffuse lighting
- PVRTVec4 vLightDir;
- PVRTTransformBack(&vLightDir, &m_vLightDirection, &mWorld);
- PVRTVec3 vLightDirModel = *(PVRTVec3*)&vLightDir;
- PVRTMatrixVec3Normalize(vLightDirModel, vLightDirModel);
- glUniform3fv(m_ShadowShaderProgram.uiLightDirLoc, 1, &vLightDirModel.x);
- // Load the correct texture using our texture lookup table
- GLuint uiTex = 0;
- if (Node.nIdxMaterial != -1)
- uiTex = m_puiTextureIDs[Node.nIdxMaterial];
- glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_2D, uiTex);
- DrawMesh(i);
- }
- }
- /*!****************************************************************************
- @Function DrawMesh
- @Input i32NodeIndex Node index of the mesh to draw
- @Description Draws a SPODMesh after the model view matrix has been set and
- the meterial prepared.
- ******************************************************************************/
- void OGLES2ShadowMapping::DrawMesh(int i32NodeIndex)
- {
- int i32MeshIndex = m_Scene.pNode[i32NodeIndex].nIdx;
- SPODMesh* pMesh = &m_Scene.pMesh[i32MeshIndex];
- // bind the VBO for the mesh
- glBindBuffer(GL_ARRAY_BUFFER, m_puiVbo[i32MeshIndex]);
- // bind the index buffer, won't hurt if the handle is 0
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_puiIndexVbo[i32MeshIndex]);
- // Enable the vertex attribute arrays
- glEnableVertexAttribArray(VERTEX_ARRAY);
- glEnableVertexAttribArray(NORMAL_ARRAY);
- glEnableVertexAttribArray(TEXCOORD_ARRAY);
- // Set the vertex attribute offsets
- glVertexAttribPointer(VERTEX_ARRAY, 3, GL_FLOAT, GL_FALSE, pMesh->sVertex.nStride, pMesh->sVertex.pData);
- glVertexAttribPointer(NORMAL_ARRAY, 3, GL_FLOAT, GL_FALSE, pMesh->sNormals.nStride, pMesh->sNormals.pData);
- glVertexAttribPointer(TEXCOORD_ARRAY, 2, GL_FLOAT, GL_FALSE, pMesh->psUVW[0].nStride, pMesh->psUVW[0].pData);
- /*
- The geometry can be exported in 4 ways:
- - Indexed Triangle list
- - Non-Indexed Triangle list
- - Indexed Triangle strips
- - Non-Indexed Triangle strips
- */
- if(pMesh->nNumStrips == 0)
- {
- if(m_puiIndexVbo[i32MeshIndex])
- {
- // Indexed Triangle list
- glDrawElements(GL_TRIANGLES, pMesh->nNumFaces*3, GL_UNSIGNED_SHORT, 0);
- }
- else
- {
- // Non-Indexed Triangle list
- glDrawArrays(GL_TRIANGLES, 0, pMesh->nNumFaces*3);
- }
- }
- else
- {
- int offset = 0;
- for(int i = 0; i < (int)pMesh->nNumStrips; ++i)
- {
- if(m_puiIndexVbo[i32MeshIndex])
- {
- // Indexed Triangle strips
- glDrawElements(GL_TRIANGLE_STRIP, pMesh->pnStripLength[i]+2, GL_UNSIGNED_SHORT, &((GLshort*)0)[offset]);
- }
- else
- {
- // Non-Indexed Triangle strips
- glDrawArrays(GL_TRIANGLE_STRIP, offset, pMesh->pnStripLength[i]+2);
- }
- offset += pMesh->pnStripLength[i]+2;
- }
- }
- // Safely disable the vertex attribute arrays
- glDisableVertexAttribArray(VERTEX_ARRAY);
- glDisableVertexAttribArray(NORMAL_ARRAY);
- glDisableVertexAttribArray(TEXCOORD_ARRAY);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- }
- /*!****************************************************************************
- @Function NewDemo
- @Return PVRShell* The demo supplied by the user
- @Description This function must be implemented by the user of the shell.
- The user should return its PVRShell object defining the
- behaviour of the application.
- ******************************************************************************/
- PVRShell* NewDemo()
- {
- return new OGLES2ShadowMapping();
- }
- /******************************************************************************
- End of file (OGLES2ShadowMapping.cpp)
- ******************************************************************************/
|