添加代码

This commit is contained in:
playbar 2017-09-22 11:01:51 +08:00
parent e635a3fda4
commit 4037e38d49
54 changed files with 21447 additions and 0 deletions

View File

@ -239,6 +239,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fbomsaa", "..\examples\fbom
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fbostencil", "..\examples\fbostencil\fbostencil.vcxproj", "{8F030B44-DFBF-4975-90ED-59815D2FC6B4}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DeferredRendering", "..\examples\DeferredRendering\DeferredRendering.vcxproj", "{88A62A12-3C14-42BF-838C-EB8FB54F6E2D}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ShadowMapsDR", "..\examples\ShadowMaps\ShadowMapsDR.vcxproj", "{9D24251F-FD72-4A76-9B1C-999ED22D4DCA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@ -751,6 +755,34 @@ Global
{8F030B44-DFBF-4975-90ED-59815D2FC6B4}.RelWithDebInfo|Win32.Build.0 = Release|Win32
{8F030B44-DFBF-4975-90ED-59815D2FC6B4}.RelWithDebInfo|x64.ActiveCfg = Release|x64
{8F030B44-DFBF-4975-90ED-59815D2FC6B4}.RelWithDebInfo|x64.Build.0 = Release|x64
{88A62A12-3C14-42BF-838C-EB8FB54F6E2D}.Debug|Win32.ActiveCfg = Debug|Win32
{88A62A12-3C14-42BF-838C-EB8FB54F6E2D}.Debug|Win32.Build.0 = Debug|Win32
{88A62A12-3C14-42BF-838C-EB8FB54F6E2D}.Debug|x64.ActiveCfg = Debug|Win32
{88A62A12-3C14-42BF-838C-EB8FB54F6E2D}.MinSizeRel|Win32.ActiveCfg = Release|Win32
{88A62A12-3C14-42BF-838C-EB8FB54F6E2D}.MinSizeRel|Win32.Build.0 = Release|Win32
{88A62A12-3C14-42BF-838C-EB8FB54F6E2D}.MinSizeRel|x64.ActiveCfg = Release|x64
{88A62A12-3C14-42BF-838C-EB8FB54F6E2D}.MinSizeRel|x64.Build.0 = Release|x64
{88A62A12-3C14-42BF-838C-EB8FB54F6E2D}.Release|Win32.ActiveCfg = Release|Win32
{88A62A12-3C14-42BF-838C-EB8FB54F6E2D}.Release|Win32.Build.0 = Release|Win32
{88A62A12-3C14-42BF-838C-EB8FB54F6E2D}.Release|x64.ActiveCfg = Release|Win32
{88A62A12-3C14-42BF-838C-EB8FB54F6E2D}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32
{88A62A12-3C14-42BF-838C-EB8FB54F6E2D}.RelWithDebInfo|Win32.Build.0 = Release|Win32
{88A62A12-3C14-42BF-838C-EB8FB54F6E2D}.RelWithDebInfo|x64.ActiveCfg = Release|x64
{88A62A12-3C14-42BF-838C-EB8FB54F6E2D}.RelWithDebInfo|x64.Build.0 = Release|x64
{9D24251F-FD72-4A76-9B1C-999ED22D4DCA}.Debug|Win32.ActiveCfg = Debug|Win32
{9D24251F-FD72-4A76-9B1C-999ED22D4DCA}.Debug|Win32.Build.0 = Debug|Win32
{9D24251F-FD72-4A76-9B1C-999ED22D4DCA}.Debug|x64.ActiveCfg = Debug|Win32
{9D24251F-FD72-4A76-9B1C-999ED22D4DCA}.MinSizeRel|Win32.ActiveCfg = Release|Win32
{9D24251F-FD72-4A76-9B1C-999ED22D4DCA}.MinSizeRel|Win32.Build.0 = Release|Win32
{9D24251F-FD72-4A76-9B1C-999ED22D4DCA}.MinSizeRel|x64.ActiveCfg = Release|Win32
{9D24251F-FD72-4A76-9B1C-999ED22D4DCA}.MinSizeRel|x64.Build.0 = Release|Win32
{9D24251F-FD72-4A76-9B1C-999ED22D4DCA}.Release|Win32.ActiveCfg = Release|Win32
{9D24251F-FD72-4A76-9B1C-999ED22D4DCA}.Release|Win32.Build.0 = Release|Win32
{9D24251F-FD72-4A76-9B1C-999ED22D4DCA}.Release|x64.ActiveCfg = Release|Win32
{9D24251F-FD72-4A76-9B1C-999ED22D4DCA}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32
{9D24251F-FD72-4A76-9B1C-999ED22D4DCA}.RelWithDebInfo|Win32.Build.0 = Release|Win32
{9D24251F-FD72-4A76-9B1C-999ED22D4DCA}.RelWithDebInfo|x64.ActiveCfg = Release|Win32
{9D24251F-FD72-4A76-9B1C-999ED22D4DCA}.RelWithDebInfo|x64.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -797,5 +829,7 @@ Global
{487BB169-F91A-4436-BF55-68568636FE35} = {46666672-CE20-3D1B-9180-1909006B3676}
{114E9625-4259-4C6E-84D1-F854FC0C4E28} = {46666672-CE20-3D1B-9180-1909006B3676}
{8F030B44-DFBF-4975-90ED-59815D2FC6B4} = {46666672-CE20-3D1B-9180-1909006B3676}
{88A62A12-3C14-42BF-838C-EB8FB54F6E2D} = {46666672-CE20-3D1B-9180-1909006B3676}
{9D24251F-FD72-4A76-9B1C-999ED22D4DCA} = {46666672-CE20-3D1B-9180-1909006B3676}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,116 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="DeferredRendering\DeferredRendering.cpp" />
<ClCompile Include="DeferredRendering\FBORenderTexture.cpp" />
<ClCompile Include="GLApplication.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="Model\CubeModel.cpp" />
<ClCompile Include="Model\GLSLShaderData.cpp" />
<ClCompile Include="Model\IModel.cpp" />
<ClCompile Include="Model\PlaneModel.cpp" />
<ClCompile Include="Model\SphereModel.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="DeferredRendering\DeferredRendering.h" />
<ClInclude Include="DeferredRendering\FBORenderTexture.h" />
<ClInclude Include="GLApplication.h" />
<ClInclude Include="Model\CubeModel.h" />
<ClInclude Include="Model\GLSLShaderData.h" />
<ClInclude Include="Model\IModel.h" />
<ClInclude Include="Model\PlaneModel.h" />
<ClInclude Include="Model\SphereModel.h" />
</ItemGroup>
<ItemGroup>
<None Include="data\deferredRendering.frag" />
<None Include="data\deferredRendering.vert" />
<None Include="data\deferredShading.frag" />
<None Include="data\deferredShading.vert" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{88A62A12-3C14-42BF-838C-EB8FB54F6E2D}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>OpenGL3Project</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>D:\Programmi\OpenGL\glew-1.7.0\include;$(IncludePath)</IncludePath>
<LibraryPath>D:\Programmi\OpenGL\glew-1.7.0\lib;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>D:\Programmi\OpenGL\glew-1.7.0\include;$(IncludePath)</IncludePath>
<LibraryPath>D:\Programmi\OpenGL\glew-1.7.0\lib;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\..\glew;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>glew32.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\..\glew\lib</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>glew32.lib;opengl32.lib;glu32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,77 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Model">
<UniqueIdentifier>{194f9210-1c9b-4617-94f4-1db0f1ab129c}</UniqueIdentifier>
</Filter>
<Filter Include="DeferredRendering">
<UniqueIdentifier>{197942dc-0c5d-4dc1-8509-94bbec59e11b}</UniqueIdentifier>
</Filter>
<Filter Include="data">
<UniqueIdentifier>{68752574-5107-46f3-9ad7-28e9d41efab8}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="GLApplication.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="Model\CubeModel.cpp">
<Filter>Model</Filter>
</ClCompile>
<ClCompile Include="Model\GLSLShaderData.cpp">
<Filter>Model</Filter>
</ClCompile>
<ClCompile Include="Model\IModel.cpp">
<Filter>Model</Filter>
</ClCompile>
<ClCompile Include="Model\PlaneModel.cpp">
<Filter>Model</Filter>
</ClCompile>
<ClCompile Include="Model\SphereModel.cpp">
<Filter>Model</Filter>
</ClCompile>
<ClCompile Include="DeferredRendering\DeferredRendering.cpp">
<Filter>DeferredRendering</Filter>
</ClCompile>
<ClCompile Include="DeferredRendering\FBORenderTexture.cpp">
<Filter>DeferredRendering</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="GLApplication.h" />
<ClInclude Include="Model\CubeModel.h">
<Filter>Model</Filter>
</ClInclude>
<ClInclude Include="Model\GLSLShaderData.h">
<Filter>Model</Filter>
</ClInclude>
<ClInclude Include="Model\IModel.h">
<Filter>Model</Filter>
</ClInclude>
<ClInclude Include="Model\PlaneModel.h">
<Filter>Model</Filter>
</ClInclude>
<ClInclude Include="Model\SphereModel.h">
<Filter>Model</Filter>
</ClInclude>
<ClInclude Include="DeferredRendering\DeferredRendering.h">
<Filter>DeferredRendering</Filter>
</ClInclude>
<ClInclude Include="DeferredRendering\FBORenderTexture.h">
<Filter>DeferredRendering</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="data\deferredRendering.frag">
<Filter>data</Filter>
</None>
<None Include="data\deferredRendering.vert">
<Filter>data</Filter>
</None>
<None Include="data\deferredShading.frag">
<Filter>data</Filter>
</None>
<None Include="data\deferredShading.vert">
<Filter>data</Filter>
</None>
</ItemGroup>
</Project>

View File

@ -0,0 +1,90 @@
#include "FBORenderTexture.h"
#include "DeferredRendering.h"
#include <exception>
/**
* Create the deferred rendering object. I have hardcoded the shader's name here.
*/
DeferredRendering::DeferredRendering(int _dWidth, int _dHeight, FBORenderTexture* fboRenderTexture)
: m_shader("data/deferredRendering.vert", "data/deferredRendering.frag")
, m_fboRenderTexture(fboRenderTexture)
, m_width(_dWidth)
, m_height(_dHeight)
{
// Get the handles from the shader
m_diffuseID = glGetUniformLocationARB(m_shader.m_programHandler,"tDiffuse");
m_positionID = glGetUniformLocationARB(m_shader.m_programHandler,"tPosition");
m_normalsID = glGetUniformLocationARB(m_shader.m_programHandler,"tNormals");
}
/**
* Render the big quad with the deferred rendering shader on it
*/
void DeferredRendering::render()
{
//Projection setup
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0,m_width,0,m_height,0.1f,2);
//Model setup
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glUseProgramObjectARB(m_shader.m_programHandler);
glActiveTextureARB(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, m_fboRenderTexture->getDiffuseTexture());
glUniform1iARB ( m_diffuseID, 0 );
glActiveTextureARB(GL_TEXTURE1_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, m_fboRenderTexture->getPositionTexture());
glUniform1iARB ( m_positionID, 1 );
glActiveTextureARB(GL_TEXTURE2_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, m_fboRenderTexture->getNormalsTexture());
glUniform1iARB ( m_normalsID, 2 );
// Render the quad
glLoadIdentity();
glColor3f(1,1,1);
glTranslatef(0,0,-1.0);
glBegin(GL_QUADS);
glTexCoord2f( 0, 0 );
glVertex3f( 0.0f, 0.0f, 0.0f);
glTexCoord2f( 1, 0 );
glVertex3f( (float) m_width, 0.0f, 0.0f);
glTexCoord2f( 1, 1 );
glVertex3f( (float) m_width, (float) m_height, 0.0f);
glTexCoord2f( 0, 1 );
glVertex3f( 0.0f, (float) m_height, 0.0f);
glEnd();
// Reset OpenGL state
glActiveTextureARB(GL_TEXTURE0_ARB);
glDisable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTextureARB(GL_TEXTURE1_ARB);
glDisable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTextureARB(GL_TEXTURE2_ARB);
glDisable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
glUseProgramObjectARB(0);
//Reset to the matrices
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}

View File

@ -0,0 +1,32 @@
#pragma once
#include <windows.h>
#include <gl/glew.h>
#include <gl/gl.h>
#include <gl/glu.h>
#include "../Model/GLSLShaderData.h"
#include "FBORenderTexture.h"
/**
* This object is used to render a big screen sized quad with the deferred rendering shader applied on it.
*/
class DeferredRendering
{
public:
// Ctors/Dtors
DeferredRendering(int width, int height, FBORenderTexture* fboRenderTexture);
// Methods
void render();
private:
// Variables
GLSLShaderData m_shader; // Deferred rendering shader
FBORenderTexture* m_fboRenderTexture; // A pointer to the FBO render texture that contains diffuse, normals and positions
unsigned int m_width; // width
unsigned int m_height; // height
GLuint m_diffuseID; // Diffuse texture handle for the shader
GLuint m_positionID; // Position texture handle for the shader
GLuint m_normalsID; // Normals texture handle for the shader
};

View File

@ -0,0 +1,175 @@
#include "FBORenderTexture.h"
#include <exception>
/**
* Create the FBO render texture initializing all the stuff that we need
*/
FBORenderTexture::FBORenderTexture(int _dWidth, int _dHeight)
{
// Save extensions
m_width = _dWidth;
m_height = _dHeight;
// Generate the OGL resources for what we need
glGenFramebuffersEXT(1, &m_fbo);
glGenRenderbuffersEXT(1, &m_diffuseRT);
glGenRenderbuffersEXT(1, &m_positionRT);
glGenRenderbuffersEXT(1, &m_normalsRT);
glGenRenderbuffersEXT(1, &m_depthBuffer);
// Bind the FBO so that the next operations will be bound to it
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
// Bind the diffuse render target
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_diffuseRT);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA, m_width, m_height);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, m_diffuseRT);
// Bind the position render target
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_positionRT);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA32F_ARB, m_width, m_height);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_RENDERBUFFER_EXT, m_positionRT);
// Bind the normal render target
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_normalsRT);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA16F_ARB, m_width, m_height);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_RENDERBUFFER_EXT, m_normalsRT);
// Bind the depth buffer
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_depthBuffer);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, m_width, m_height);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthBuffer);
// Generate and bind the OGL texture for diffuse
glGenTextures(1, &m_diffuseTexture);
glBindTexture(GL_TEXTURE_2D, m_diffuseTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// Attach the texture to the FBO
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_diffuseTexture, 0);
// Generate and bind the OGL texture for positions
glGenTextures(1, &m_positionTexture);
glBindTexture(GL_TEXTURE_2D, m_positionTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, m_width, m_height, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// Attach the texture to the FBO
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, m_positionTexture, 0);
// Generate and bind the OGL texture for normals
glGenTextures(1, &m_normalsTexture);
glBindTexture(GL_TEXTURE_2D, m_normalsTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, m_width, m_height, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// Attach the texture to the FBO
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_TEXTURE_2D, m_normalsTexture, 0);
// Check if all worked fine and unbind the FBO
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
if( status != GL_FRAMEBUFFER_COMPLETE_EXT)
throw new std::exception("Can't initialize an FBO render texture. FBO initialization failed.");
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}
/**
* Destructor
*/
FBORenderTexture::~FBORenderTexture(){
glDeleteTextures(1, &m_normalsTexture);
glDeleteTextures(1, &m_positionTexture);
glDeleteTextures(1, &m_diffuseTexture);
glDeleteFramebuffersEXT(1, &m_fbo);
glDeleteRenderbuffersEXT(1, &m_diffuseRT);
glDeleteRenderbuffersEXT(1, &m_positionRT);
glDeleteRenderbuffersEXT(1, &m_normalsRT);
glDeleteRenderbuffersEXT(1, &m_depthBuffer);
}
/**
* Start rendering to the texture
* Both color and depth buffers are cleared.
*/
void FBORenderTexture::start(){
// Bind our FBO and set the viewport to the proper size
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
glPushAttrib(GL_VIEWPORT_BIT);
glViewport(0,0,m_width, m_height);
// Clear the render targets
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
glActiveTextureARB(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
// Specify what to render an start acquiring
GLenum buffers[] = { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT2_EXT };
glDrawBuffers(3, buffers);
}
/**
* Stop rendering to this texture.
*/
void FBORenderTexture::stop(){
// Stop acquiring and unbind the FBO
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glPopAttrib();
}
/**
* Show the texture to screen. It is just for debug purposes.
*/
void FBORenderTexture::showTexture(unsigned int i, float fSizeX, float fSizeY, float x, float y) const {
GLuint texture = m_diffuseTexture;
if(i == 1) texture = m_positionTexture;
else
if(i == 2) texture = m_normalsTexture;
//Projection setup
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0,m_width,0,m_height,0.1f,2);
//Model setup
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glActiveTextureARB(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture);
// Render the quad
glLoadIdentity();
glTranslatef(x,-y,-1.0);
glColor3f(1,1,1);
glBegin(GL_QUADS);
glTexCoord2f( 0, 1 );
glVertex3f( 0.0f, (float) m_height, 0.0f);
glTexCoord2f( 0, 0 );
glVertex3f( 0.0f, m_height-fSizeY, 0.0f);
glTexCoord2f( 1, 0 );
glVertex3f( fSizeX, m_height-fSizeY, 0.0f);
glTexCoord2f( 1, 1 );
glVertex3f( fSizeX, (float) m_height, 0.0f);
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
//Reset to the matrices
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}

View File

@ -0,0 +1,42 @@
#pragma once
#include <windows.h>
#include <gl/glew.h>
#include <gl/gl.h>
#include <gl/glu.h>
/**
* A Frame Buffer Object is used by OpenGL to render into a texture. Specifically this implementation assumes that the
* rendered model will provide diffuse, position and normal at the same time in a MRT fashion
*/
class FBORenderTexture
{
public:
// Ctors/Dtors
FBORenderTexture(int width, int height);
~FBORenderTexture();
// Methods
void start();
void stop();
void showTexture(unsigned int i, float fSizeX = 400, float fSizeY = 400, float x = 0, float y = 0) const;
GLuint getDiffuseTexture() const { return m_diffuseTexture; }
GLuint getPositionTexture() const { return m_positionTexture; }
GLuint getNormalsTexture() const { return m_normalsTexture; }
private:
// Variables
GLuint m_fbo; // The FBO ID
GLuint m_diffuseRT; // The diffuse render target
unsigned int m_diffuseTexture; // The OpenGL texture for the diffuse render target
GLuint m_positionRT; // The position render target
unsigned int m_positionTexture; // The OpenGL texture for the position render target
GLuint m_normalsRT; // The normals render target
unsigned int m_normalsTexture; // The OpenGL texture for the normals render target
GLuint m_depthBuffer; // Depth buffer handle
unsigned int m_width; // FBO width
unsigned int m_height; // FBO height
};

View File

@ -0,0 +1,187 @@
#include <windows.h>
#include "GLApplication.h"
#include "Model/SphereModel.h"
#include "Model/CubeModel.h"
#include "Model/PlaneModel.h"
/**
* Initialize our GL application
*/
bool GLApplication::initialize(HWND hwnd, int width, int height)
{
GLuint pixelFormat;
m_windowHeight = height;
m_windowWidth = width;
m_hWnd = hwnd;
static PIXELFORMATDESCRIPTOR pfd=
{
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW |
PFD_SUPPORT_OPENGL |
PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
16,
0, 0, 0, 0, 0, 0,
0,
0,
0,
0, 0, 0, 0,
16,
0,
0,
PFD_MAIN_PLANE,
0,
0, 0, 0
};
if (!(m_hdc=GetDC(m_hWnd)))
return FALSE;
if (!(pixelFormat=ChoosePixelFormat(m_hdc,&pfd)))
return FALSE;
if(!SetPixelFormat(m_hdc,pixelFormat,&pfd))
return FALSE;
if (!(m_hrc=wglCreateContext(m_hdc)))
return FALSE;
if(!wglMakeCurrent(m_hdc,m_hrc))
return FALSE;
ShowWindow(m_hWnd,SW_SHOW);
SetForegroundWindow(m_hWnd);
SetFocus(m_hWnd);
setSize(width, height);
glDisable(GL_LIGHTING);
glEnable(GL_TEXTURE_2D);
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
GLenum err = glewInit();
if (GLEW_OK != err)
return false;
loadAssets();
return true;
}
/**
* Set window's size
*/
void GLApplication::setSize(int w, int h)
{
m_windowWidth = w;
m_windowHeight = h;
glViewport(0,0,m_windowWidth,m_windowHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f,(GLfloat)m_windowWidth/(GLfloat)m_windowHeight,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
/**
* Update
*/
void GLApplication::update()
{
float time = (GetTickCount() - m_lastTick) * 0.01f;
m_lastTick = GetTickCount();
m_models[0]->addRotation( time, time*2, 0 );
m_models[1]->addRotation( 0, time*2, time );
}
/**
* Render the scene
*/
void GLApplication::render()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.2f, 0.3f, 0.8f, 1.0f);
glLoadIdentity();
glRotatef(20, 1, 0, 0);
glTranslatef(0.0f,-4.6f,-10.0f);
// Render our geometry into the FBO
m_multipleRenderTarget->start();
for(int i=0; i<c_modelsCount; ++i)
m_models[i]->render();
m_multipleRenderTarget->stop();
// Render to the screen
if(m_state == 0)
{
// Render to screen using the deferred rendering shader
m_deferredRendering->render();
}
else if(m_state == 1)
{
m_multipleRenderTarget->showTexture( 0, 512, 384, 0);
m_multipleRenderTarget->showTexture( 1, 512, 384, 512);
m_multipleRenderTarget->showTexture( 2, 512, 384, 0, 384);
}
SwapBuffers(m_hdc);
}
/**
* Release all the GL resources we have allocated
*/
void GLApplication::release()
{
releaseAssets();
wglMakeCurrent(m_hdc, 0);
wglDeleteContext(m_hrc);
ReleaseDC(m_hWnd, m_hdc);
}
/**
* Load all the required assets
*/
void GLApplication::loadAssets()
{
m_state = 0;
m_multipleRenderTarget = new FBORenderTexture(m_windowWidth, m_windowHeight);
m_deferredRendering = new DeferredRendering(m_windowWidth, m_windowHeight, m_multipleRenderTarget);
m_models[0] = new SphereModel("data/deferredShading.vert", "data/deferredShading.frag", 1, 64);
m_models[0]->loadTexture("data/earth.raw");
m_models[0]->setPosition(2,2.5f,0);
m_models[1] = new CubeModel("data/deferredShading.vert", "data/deferredShading.frag", 1);
m_models[1]->loadTexture("data/box.raw");
m_models[1]->setPosition(-2,2.5f,0);
m_models[2] = new PlaneModel("data/deferredShading.vert", "data/deferredShading.frag", 5);
m_models[2]->loadTexture("data/plane.raw");
m_models[2]->setPosition(0,0,0);
}
/**
* Release all the assets
*/
void GLApplication::releaseAssets()
{
delete m_multipleRenderTarget;
delete m_deferredRendering;
for(int i=0; i<c_modelsCount; ++i)
delete m_models[i];
}

View File

@ -0,0 +1,46 @@
#pragma once
#include <windows.h>
#include "DeferredRendering/DeferredRendering.h"
#include "DeferredRendering/FBORenderTexture.h"
//Fwd
class IModel;
/**
* This class contains all the system stuff that we need to render with OpenGL
*/
class GLApplication {
public:
// Methods
bool initialize(HWND hwnd, int w, int h);
void setSize(int w, int h);
void update();
void render();
void release();
void showDeferredRendering(){ m_state = 0; }
void showRenderTargets(){ m_state = 1; }
private:
// Methods
void loadAssets();
void releaseAssets();
// Static consts
static const int c_modelsCount = 3;
// Fields
IModel* m_models[c_modelsCount];
DeferredRendering* m_deferredRendering;
FBORenderTexture* m_multipleRenderTarget;
int m_windowWidth;
int m_windowHeight;
HGLRC m_hrc; // Rendering's context
HDC m_hdc; // Device's context
HWND m_hWnd; // Window's handle
unsigned int m_lastTick;
unsigned char m_state; // 0 - Normal render, 1 - Show render targets
};

View File

@ -0,0 +1,73 @@
#include "CubeModel.h"
#include <math.h>
/**
* Construct the cube
*/
CubeModel::CubeModel(const std::string& sVSFileName, const std::string& sFSFileName, float side)
: IModel(sVSFileName, sFSFileName)
, m_side(side)
{
}
/**
* Render
*/
void CubeModel::render() const
{
glPushMatrix();
// Save the current world matrix to compensate the normals in the shader
float worldMatrix[16];
glGetFloatv(GL_MODELVIEW_MATRIX, worldMatrix);
glScalef(m_side,m_side,m_side);
glTranslatef(m_posX, m_posY, m_posZ);
glRotatef(m_rotX, 1, 0, 0);
glRotatef(m_rotY, 0, 1, 0);
glRotatef(m_rotZ, 0, 0, 1);
glUseProgramObjectARB(m_shader.m_programHandler);
glBindTexture(GL_TEXTURE_2D, m_texture);
glUniform1iARB ( m_textureID, 0);
glUniformMatrix4fvARB ( m_worldMatrixID, 1, false, worldMatrix);
glBegin(GL_QUADS);
// Front Face
glTexCoord2f(0.0f, 0.0f); glNormal3f(0.0f, 0.0f, 1.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glNormal3f(0.0f, 0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glNormal3f(0.0f, 0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glNormal3f(0.0f, 0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
// Back Face
glTexCoord2f(1.0f, 0.0f); glNormal3f(0.0f, 0.0f, -1.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 1.0f); glNormal3f(0.0f, 0.0f, -1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f); glNormal3f(0.0f, 0.0f, -1.0f); glVertex3f( 1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f); glNormal3f(0.0f, 0.0f, -1.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
// Top Face
glTexCoord2f(0.0f, 1.0f); glNormal3f(0.0f, 1.0f, 0.0f); glVertex3f(-1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f); glNormal3f(0.0f, 1.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glNormal3f(0.0f, 1.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glNormal3f(0.0f, 1.0f, 0.0f); glVertex3f( 1.0f, 1.0f, -1.0f);
// Bottom Face
glTexCoord2f(1.0f, 1.0f); glNormal3f(0.0f, -1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f); glNormal3f(0.0f, -1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f); glNormal3f(0.0f, -1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glNormal3f(0.0f, -1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
// Right face
glTexCoord2f(1.0f, 0.0f); glNormal3f(1.0f, 0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 1.0f); glNormal3f(1.0f, 0.0f, 0.0f); glVertex3f( 1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f); glNormal3f(1.0f, 0.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 0.0f); glNormal3f(1.0f, 0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
// Left Face
glTexCoord2f(0.0f, 0.0f); glNormal3f(-1.0f, 0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 0.0f); glNormal3f(-1.0f, 0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glNormal3f(-1.0f, 0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glNormal3f(-1.0f, 0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, -1.0f);
glEnd();
glUseProgramObjectARB(0);
glPopMatrix();
}

View File

@ -0,0 +1,19 @@
#pragma once
#include "IModel.h"
/**
* A simple cube model that is easy to render
*/
class CubeModel : public IModel
{
public:
// Methods
CubeModel(const std::string& sVSFileName, const std::string& sFSFileName, float side);
void render() const;
protected:
// Fields
float m_side;
};

View File

@ -0,0 +1,82 @@
#include <windows.h>
#include "gl/glew.h"
#include <gl/gl.h>
#include <gl/glu.h>
#include "GLSLShaderData.h"
/**
* Constructor
*/
GLSLShaderData::GLSLShaderData(const std::string& _sVSFileName, const std::string& _sFSFileName)
: m_VSFileName(_sVSFileName)
, m_FSFileName(_sFSFileName)
{
// Create OGL resources
m_vertexShader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
m_fragmentShader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
//Read out the shader data from the given files
char *sVSData, *sFSData;
//Read out the vertex shader data
FILE *file;
fopen_s(&file, m_VSFileName.c_str(),"r");
if(!file)
throw new std::exception( std::string("Can't load GLSL Vertex Shader from file: " + m_VSFileName).c_str() );
fseek(file, 0, SEEK_END);
long count = ftell(file);
rewind(file);
sVSData = new char[count+1];
memset(sVSData,0,count+1);
fread(sVSData, 1, count, file);
fclose(file);
file = NULL;
//Read out the fragment shader data
fopen_s(&file, m_FSFileName.c_str(),"r");
if(!file)
throw new std::exception( std::string("Can't load GLSL Fragment Shader from file: "+m_FSFileName).c_str() );
fseek(file, 0, SEEK_END);
count = ftell(file);
rewind(file);
sFSData = new char[count+1];
memset(sFSData,0,count+1);
fread(sFSData, 1, count, file);
fclose(file);
// Now that we have the two shaders in memory we can compile them
const char * pVS = sVSData;
const char * pFS = sFSData;
int bCompiled = false;
glShaderSourceARB(m_vertexShader, 1, &pVS, NULL);
glCompileShaderARB(m_vertexShader);
glGetObjectParameterivARB( m_vertexShader, GL_OBJECT_COMPILE_STATUS_ARB, &bCompiled );
if( bCompiled == false )
throw new std::exception("Vertex shader compilation failed.");
glShaderSourceARB(m_fragmentShader, 1, &pFS, NULL);
glCompileShaderARB(m_fragmentShader);
glGetObjectParameterivARB( m_fragmentShader, GL_OBJECT_COMPILE_STATUS_ARB, &bCompiled );
if( bCompiled == false )
throw new std::exception("Fragment shader compilation failed.");
// Once compiled we can bind everything together for OpenGL to use
m_programHandler = glCreateProgramObjectARB();
glAttachObjectARB(m_programHandler,m_vertexShader);
glAttachObjectARB(m_programHandler,m_fragmentShader);
glLinkProgramARB(m_programHandler);
// We release the shader data read from file since we now have everything compiled in memory
delete [] sFSData;
delete [] sVSData;
}

View File

@ -0,0 +1,22 @@
#pragma once
#include <string>
/**
* GLSLShaderData encapsulate all the GLSL data.<br>
* Constructor initialize data from files.
*/
class GLSLShaderData
{
public:
// Functions
//------------------------------------------------------------
GLSLShaderData(const std::string& sVSFileName, const std::string& sFSFileName);
// Variables
//------------------------------------------------------------
GLhandleARB m_vertexShader; // Vertex shader handle
GLhandleARB m_fragmentShader; // Fragment shader handle
GLhandleARB m_programHandler; // Shader handle
std::string m_VSFileName; // Vertex shader filename
std::string m_FSFileName; // Fragment shader filename
};

View File

@ -0,0 +1,79 @@
#include "IModel.h"
#include <math.h>
/**
* This method assumes that the file passed as parameter is a raw block of data made of RGB components (one byte per channel)
* It is *NOT* a good way to load/store textures, but for sake of simplicity I've decided to use it for this tutorial.
*/
bool IModel::loadTexture(const std::string& textureName)
{
byte* data = NULL;
FILE* f;
fopen_s(&f, textureName.c_str(), "r");
if(f != NULL)
{
fseek (f, 0, SEEK_END);
unsigned int size = ftell (f);
fseek (f, 0, SEEK_SET);
data = new byte[size];
fread( data, sizeof(byte), size, f);
fclose(f);
// Assuming that the raw image is square and RGB; don't fancy doing anything more complicated since the tutorial is not focused on textures loading
GLuint side = (GLuint)sqrt(size/3.0f);
// Generate the texture
if(m_texture != 0)
glDeleteTextures(1, &m_texture);
glGenTextures(1, &m_texture);
glBindTexture(GL_TEXTURE_2D, m_texture);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexImage2D(GL_TEXTURE_2D, 0, 3, side, side, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
}
else
return false;
return true;
}
/**
* Set position
*/
void IModel::setPosition(float x, float y, float z)
{
m_posX = x;
m_posY = y;
m_posZ = z;
}
/**
* Set rotation
*/
void IModel::setRotation(float x, float y, float z)
{
m_rotX = x;
m_rotY = y;
m_rotZ = z;
}
/**
* Add a delta to the current rotation
*/
void IModel::addRotation(float x, float y, float z)
{
m_rotX += x;
m_rotY += y;
m_rotZ += z;
}

View File

@ -0,0 +1,45 @@
#pragma once
#include <windows.h>
#include "gl/glew.h"
#include <gl/gl.h>
#include <gl/glu.h>
#include <string>
#include "GLSLShaderData.h"
/**
* Every renderable object inherits from this interface for simplicity
*/
class IModel
{
public:
// Methods
IModel(const std::string& sVSFileName, const std::string& sFSFileName)
: m_shader(sVSFileName, sFSFileName)
, m_texture(0)
{
m_rotX = m_rotY = m_rotZ = 0;
m_posX = m_posY = m_posZ = 0;
m_worldMatrixID = glGetUniformLocationARB(m_shader.m_programHandler,"WorldMatrix");
m_textureID = glGetUniformLocationARB(m_shader.m_programHandler,"tDiffuse");
}
virtual ~IModel(){}
bool loadTexture(const std::string& textureName);
void setPosition(float x, float y, float z);
void setRotation(float x, float y, float z);
void addRotation(float x, float y, float z);
virtual void render() const = 0;
protected:
// Fields
GLSLShaderData m_shader; // Every model must have a shader associated (both vertex and fragment)
GLuint m_worldMatrixID; // This ID is used to pass the world matrix into the shader
float m_rotX, m_rotY, m_rotZ; // Rotations
float m_posX, m_posY, m_posZ; // Positions
GLuint m_textureID; // Texture ID used to pass the texture into the shader
GLuint m_texture; // OpenGL texture ID
};

View File

@ -0,0 +1,57 @@
#include "PlaneModel.h"
#include <math.h>
/**
* Construct the plane
*/
PlaneModel::PlaneModel(const std::string& sVSFileName, const std::string& sFSFileName, float side)
: IModel(sVSFileName, sFSFileName)
, m_side(side)
{}
/**
* Render
*/
void PlaneModel::render() const
{
glPushMatrix();
// Save the current world matrix to compensate the normals in the shader
float worldMatrix[16];
glGetFloatv(GL_MODELVIEW_MATRIX, worldMatrix);
glTranslatef(m_posX, m_posY, m_posZ);
glRotatef(m_rotX, 1, 0, 0);
glRotatef(m_rotY, 0, 1, 0);
glRotatef(m_rotZ, 0, 0, 1);
glScalef(m_side,m_side,m_side);
glUseProgramObjectARB(m_shader.m_programHandler);
glBindTexture(GL_TEXTURE_2D, m_texture);
glUniform1iARB ( m_textureID, 0);
glUniformMatrix4fvARB ( m_worldMatrixID, 1, false, worldMatrix);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 1.0f);
glNormal3f(0.0f, 1.0f, 0.0f);
glVertex3f(-1.0f, 0.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f);
glNormal3f(0.0f, 1.0f, 0.0f);
glVertex3f(-1.0f, 0.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f);
glNormal3f(0.0f, 1.0f, 0.0f);
glVertex3f( 1.0f, 0.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f);
glNormal3f(0.0f, 1.0f, 0.0f);
glVertex3f( 1.0f, 0.0f, -1.0f);
glEnd();
glUseProgramObjectARB(0);
glPopMatrix();
}

View File

@ -0,0 +1,19 @@
#pragma once
#include "IModel.h"
/**
* A plane model that is easy to render
*/
class PlaneModel : public IModel
{
public:
// Methods
PlaneModel(const std::string& sVSFileName, const std::string& sFSFileName, float side);
void render() const;
protected:
// Fields
float m_side;
};

View File

@ -0,0 +1,45 @@
#include "SphereModel.h"
#include <math.h>
/**
* Construct the sphere
*/
SphereModel::SphereModel(const std::string& sVSFileName, const std::string& sFSFileName, float radius, unsigned int meshPrecision)
: IModel(sVSFileName, sFSFileName)
{
m_radius = radius;
m_meshPrecision = meshPrecision;
}
/**
* Render
*/
void SphereModel::render() const
{
glPushMatrix();
// Save the current world matrix to compensate the normals in the shader
float worldMatrix[16];
glGetFloatv(GL_MODELVIEW_MATRIX, worldMatrix);
glTranslatef(m_posX, m_posY, m_posZ);
glRotatef(m_rotX, 1, 0, 0);
glRotatef(m_rotY, 0, 1, 0);
glRotatef(m_rotZ, 0, 0, 1);
glUseProgramObjectARB(m_shader.m_programHandler);
glBindTexture(GL_TEXTURE_2D, m_texture);
glUniform1iARB ( m_textureID, 0);
glUniformMatrix4fvARB ( m_worldMatrixID, 1, false, worldMatrix);
GLUquadricObj *sphere = gluNewQuadric();
gluQuadricTexture(sphere, true);
gluSphere(sphere, m_radius, m_meshPrecision, m_meshPrecision);
gluDeleteQuadric(sphere);
glUseProgramObjectARB(0);
glPopMatrix();
}

View File

@ -0,0 +1,20 @@
#pragma once
#include "IModel.h"
/**
* A simple sphere model that is easy to render
*/
class SphereModel : public IModel
{
public:
// Methods
SphereModel(const std::string& sVSFileName, const std::string& sFSFileName, float radius, unsigned int meshPrecision);
void render() const;
private:
// Fields
float m_radius;
unsigned int m_meshPrecision;
};

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,22 @@
uniform sampler2D tDiffuse;
uniform sampler2D tPosition;
uniform sampler2D tNormals;
uniform vec3 cameraPosition;
void main( void )
{
vec4 image = texture2D( tDiffuse, gl_TexCoord[0].xy );
vec4 position = texture2D( tPosition, gl_TexCoord[0].xy );
vec4 normal = texture2D( tNormals, gl_TexCoord[0].xy );
vec3 light = vec3(50,100,50);
vec3 lightDir = light - position.xyz ;
normal = normalize(normal);
lightDir = normalize(lightDir);
vec3 eyeDir = normalize(cameraPosition-position.xyz);
vec3 vHalfVector = normalize(lightDir.xyz+eyeDir);
gl_FragColor = max(dot(normal,lightDir),0) * image + pow(max(dot(normal,vHalfVector),0.0), 100) * 1.5;
}

View File

@ -0,0 +1,7 @@
void main( void )
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_FrontColor = vec4(1.0, 1.0, 1.0, 1.0);
}

View File

@ -0,0 +1,11 @@
varying vec4 position;
varying vec3 normals;
varying mat4 TBN;
uniform sampler2D tDiffuse;
void main( void )
{
gl_FragData[0] = vec4(texture2D(tDiffuse,gl_TexCoord[0].st).rgb, 0);
gl_FragData[1] = vec4(position.xyz,0);
gl_FragData[2] = vec4(normals.xyz,0);
}

View File

@ -0,0 +1,16 @@
varying vec3 normals;
varying vec4 position;
uniform mat4 ModelMatrix;
uniform mat4 WorldMatrix;
void main( void )
{
// Move the normals back from the camera space to the world space
mat3 worldRotationInverse = transpose(mat3(WorldMatrix));
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_TexCoord[0] = gl_MultiTexCoord0;
normals = normalize(worldRotationInverse * gl_NormalMatrix * gl_Normal);
position = gl_ModelViewMatrix * gl_Vertex;
gl_FrontColor = vec4(1.0, 1.0, 1.0, 1.0);
}

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -0,0 +1,102 @@
#include <windows.h>
#include <iostream>
#include <stdio.h>
#include "GLApplication.h"
GLApplication application;
bool running = true;
HINSTANCE hInstance;
// The window callback function
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) {
case WM_SIZE:
{
application.setSize(LOWORD(lParam), HIWORD(lParam));
break;
}
case WM_KEYDOWN:
{
if((unsigned short) wParam == 112) application.showDeferredRendering();
if((unsigned short) wParam == 113) application.showRenderTargets();
break;
}
case WM_DESTROY:
{
PostQuitMessage(0);
break;
}
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
// Main entry point
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
WNDCLASS windowClass;
HWND hWnd;
DWORD dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
const int width = 1024;
const int height = 768;
hInstance = GetModuleHandle(NULL);
windowClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
windowClass.lpfnWndProc = (WNDPROC) WndProc;
windowClass.cbClsExtra = 0;
windowClass.cbWndExtra = 0;
windowClass.hInstance = hInstance;
windowClass.hIcon = LoadIcon(NULL, IDI_WINLOGO);
windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
windowClass.hbrBackground = NULL;
windowClass.lpszMenuName = NULL;
windowClass.lpszClassName = L"DeferredRenderingClass";
if (!RegisterClass(&windowClass)) {
return false;
}
hWnd = CreateWindowEx(dwExStyle, L"DeferredRenderingClass", L"Deferred rendering tutorial", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, width, height, NULL, NULL, hInstance, NULL);
if(!application.initialize(hWnd, width, height))
return 0;
ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);
bool running = true;
while (running)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
{
running = false;
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else
{
application.update();
application.render();
}
}
application.release();
return (int) msg.wParam;
}

View File

@ -0,0 +1,112 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="source\DeferredRendering\DeferredRendering.cpp" />
<ClCompile Include="source\DeferredRendering\DepthRenderTexture.cpp" />
<ClCompile Include="source\DeferredRendering\FBORenderTexture.cpp" />
<ClCompile Include="source\GLApplication.cpp" />
<ClCompile Include="source\main.cpp" />
<ClCompile Include="source\Model\CubeModel.cpp" />
<ClCompile Include="source\Model\GLSLShaderData.cpp" />
<ClCompile Include="source\Model\IModel.cpp" />
<ClCompile Include="source\Model\PlaneModel.cpp" />
<ClCompile Include="source\Model\SphereModel.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="source\DeferredRendering\DeferredRendering.h" />
<ClInclude Include="source\DeferredRendering\DepthRenderTexture.h" />
<ClInclude Include="source\DeferredRendering\FBORenderTexture.h" />
<ClInclude Include="source\GLApplication.h" />
<ClInclude Include="source\Model\CubeModel.h" />
<ClInclude Include="source\Model\GLSLShaderData.h" />
<ClInclude Include="source\Model\IModel.h" />
<ClInclude Include="source\Model\PlaneModel.h" />
<ClInclude Include="source\Model\SphereModel.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{9D24251F-FD72-4A76-9B1C-999ED22D4DCA}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>OpenGL3Project</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>D:\Programmi\OpenGL\glew-1.7.0\include;$(IncludePath)</IncludePath>
<LibraryPath>D:\Programmi\OpenGL\glew-1.7.0\lib;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>D:\Programmi\OpenGL\glew-1.7.0\include;$(IncludePath)</IncludePath>
<LibraryPath>D:\Programmi\OpenGL\glew-1.7.0\lib;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\..\glew;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>glew32.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\..\glew\lib</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>glew32.lib;opengl32.lib;glu32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,46 @@
uniform sampler2D tDiffuse;
uniform sampler2D tPosition;
uniform sampler2D tNormals;
uniform sampler2D tShadowMap;
uniform vec3 cameraPosition;
uniform mat4 worldToLightViewMatrix;
uniform mat4 lightViewToProjectionMatrix;
uniform mat4 worldToCameraViewMatrix;
float readShadowMap(vec3 eyeDir)
{
mat4 cameraViewToWorldMatrix = inverse(worldToCameraViewMatrix);
mat4 cameraViewToProjectedLightSpace = lightViewToProjectionMatrix * worldToLightViewMatrix * cameraViewToWorldMatrix;
vec4 projectedEyeDir = cameraViewToProjectedLightSpace * vec4(eyeDir,1);
projectedEyeDir = projectedEyeDir/projectedEyeDir.w;
vec2 textureCoordinates = projectedEyeDir.xy * vec2(0.5,0.5) + vec2(0.5,0.5);
const float bias = 0.0001;
float depthValue = texture2D( tShadowMap, textureCoordinates ) - bias;
return projectedEyeDir.z * 0.5 + 0.5 < depthValue;
}
void main( void )
{
// Read the data from the textures
vec4 image = texture2D( tDiffuse, gl_TexCoord[0].xy );
vec4 position = texture2D( tPosition, gl_TexCoord[0].xy );
vec4 normal = texture2D( tNormals, gl_TexCoord[0].xy );
mat4 lightViewToWolrdMatrix = inverse(worldToLightViewMatrix);
vec3 light = lightViewToWolrdMatrix[3].xyz;
vec3 lightDir = light - position.xyz;
normal = normalize(normal);
lightDir = normalize(lightDir);
vec3 eyeDir = position.xyz - cameraPosition;
vec3 reflectedEyeVector = normalize(reflect(eyeDir, normal));
float shadow = readShadowMap(eyeDir);
float diffuseLight = max(dot(normal,lightDir),0) * shadow;
float ambientLight = 0.1;
gl_FragColor = (diffuseLight + ambientLight ) * image + pow(max(dot(lightDir,reflectedEyeVector),0.0), 100) * 1.5 * shadow;
}

View File

@ -0,0 +1,7 @@
void main( void )
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_FrontColor = vec4(1.0, 1.0, 1.0, 1.0);
}

View File

@ -0,0 +1,11 @@
varying vec4 position;
varying vec3 normals;
varying mat4 TBN;
uniform sampler2D tDiffuse;
void main( void )
{
gl_FragData[0] = vec4(texture2D(tDiffuse,gl_TexCoord[0].st).rgb, 0);
gl_FragData[1] = vec4(position.xyz,0);
gl_FragData[2] = vec4(normals.xyz,0);
}

View File

@ -0,0 +1,16 @@
varying vec3 normals;
varying vec4 position;
uniform mat4 ModelMatrix;
uniform mat4 WorldMatrix;
void main( void )
{
// Move the normals back from the camera space to the world space
mat3 worldRotationInverse = transpose(mat3(WorldMatrix));
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_TexCoord[0] = gl_MultiTexCoord0;
normals = normalize(worldRotationInverse * gl_NormalMatrix * gl_Normal);
position = gl_ModelViewMatrix * gl_Vertex;
gl_FrontColor = vec4(1.0, 1.0, 1.0, 1.0);
}

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -0,0 +1,167 @@
#include "FBORenderTexture.h"
#include "DeferredRendering.h"
#include <exception>
/**
* Create the deferred rendering object. I have hardcoded the shader's name here.
*/
DeferredRendering::DeferredRendering(int _dWidth, int _dHeight)
: m_shader("data/deferredRendering.vert", "data/deferredRendering.frag")
, m_fboRenderTexture(_dWidth, _dHeight)
, m_shadowMap(1024, 1024)
, m_width(_dWidth)
, m_height(_dHeight)
{
// Get the handles from the shader
m_diffuseID = glGetUniformLocationARB(m_shader.m_programHandler,"tDiffuse");
m_positionID = glGetUniformLocationARB(m_shader.m_programHandler,"tPosition");
m_normalsID = glGetUniformLocationARB(m_shader.m_programHandler,"tNormals");
m_shadowMapID = glGetUniformLocationARB(m_shader.m_programHandler,"tShadowMap");
m_worldToLightViewMatrix_shaderID = glGetUniformLocationARB(m_shader.m_programHandler,"worldToLightViewMatrix");
m_lightViewToProjectionMatrix_shaderID = glGetUniformLocationARB(m_shader.m_programHandler,"lightViewToProjectionMatrix");
m_worldToCameraViewMatrix_shaderID = glGetUniformLocationARB(m_shader.m_programHandler,"worldToCameraViewMatrix");
}
/**
* Acquire the light matrices
*/
void DeferredRendering::setLightMatrices(float worldToLightViewMatrix[16], float lightViewToProjectionMatrix[16], float worldToCameraViewMatrix[16])
{
memcpy(m_worldToLightViewMatrix, worldToLightViewMatrix, sizeof(float) * 16);
memcpy(m_lightViewToProjectionMatrix, lightViewToProjectionMatrix, sizeof(float) * 16);
memcpy(m_worldToCameraViewMatrix, worldToCameraViewMatrix, sizeof(float) * 16);
}
/**
* Start rendering to the FBO
*/
void DeferredRendering::startRenderToFBO()
{
m_fboRenderTexture.start();
}
/**
* Stop rendering to the FBO
*/
void DeferredRendering::stopRenderToFBO()
{
m_fboRenderTexture.stop();
}
/**
* Render the debug texture
*/
void DeferredRendering::showTexture(unsigned int i, float fWindowsWidth, float fWindowsHeight, float fSizeX, float fSizeY, float x, float y) const
{
m_fboRenderTexture.showTexture(i, fWindowsWidth, fWindowsHeight, fSizeX, fSizeY, x, y);
}
/**
* Render the depth into the shadow map
*/
void DeferredRendering::startRenderToShadowMap()
{
m_shadowMap.start();
}
/**
* Stop to render the depth into the shadow map
*/
void DeferredRendering::stopRenderToShadowMap()
{
m_shadowMap.stop();
}
/**
* Render the debug texture for the shadow map
*/
void DeferredRendering::showShadowMap( float fWindowsWidth, float fWindowsHeight, float fSizeX, float fSizeY, float x, float y) const
{
m_shadowMap.showTexture(fWindowsWidth, fWindowsHeight, fSizeX, fSizeY, x, y);
}
/**
* Render the big quad with the deferred rendering shader on it
*/
void DeferredRendering::render()
{
//Projection setup
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0,m_width,0,m_height,0.1f,2);
//Model setup
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glUseProgramObjectARB(m_shader.m_programHandler);
glActiveTextureARB(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, m_fboRenderTexture.getDiffuseTexture());
glUniform1iARB ( m_diffuseID, 0 );
glActiveTextureARB(GL_TEXTURE1_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, m_fboRenderTexture.getPositionTexture());
glUniform1iARB ( m_positionID, 1 );
glActiveTextureARB(GL_TEXTURE2_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, m_fboRenderTexture.getNormalsTexture());
glUniform1iARB ( m_normalsID, 2 );
glActiveTextureARB(GL_TEXTURE3_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, m_shadowMap.getTexture());
glUniform1iARB ( m_shadowMapID, 3 );
glUniformMatrix4fv ( m_worldToCameraViewMatrix_shaderID, 1, GL_FALSE, m_worldToCameraViewMatrix );
glUniformMatrix4fv ( m_lightViewToProjectionMatrix_shaderID, 1, GL_FALSE, m_lightViewToProjectionMatrix );
glUniformMatrix4fv ( m_worldToLightViewMatrix_shaderID, 1, GL_FALSE, m_worldToLightViewMatrix );
// Render the quad
glLoadIdentity();
glColor3f(1,1,1);
glTranslatef(0,0,-1.0);
glBegin(GL_QUADS);
glTexCoord2f( 0, 0 );
glVertex3f( 0.0f, 0.0f, 0.0f);
glTexCoord2f( 1, 0 );
glVertex3f( (float) m_width, 0.0f, 0.0f);
glTexCoord2f( 1, 1 );
glVertex3f( (float) m_width, (float) m_height, 0.0f);
glTexCoord2f( 0, 1 );
glVertex3f( 0.0f, (float) m_height, 0.0f);
glEnd();
// Reset OpenGL state
glActiveTextureARB(GL_TEXTURE0_ARB);
glDisable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTextureARB(GL_TEXTURE1_ARB);
glDisable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTextureARB(GL_TEXTURE2_ARB);
glDisable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTextureARB(GL_TEXTURE3_ARB);
glDisable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
glUseProgramObjectARB(0);
//Reset to the matrices
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}

View File

@ -0,0 +1,50 @@
#pragma once
#include <windows.h>
#include <gl/glew.h>
#include <gl/gl.h>
#include <gl/glu.h>
#include "../Model/GLSLShaderData.h"
#include "FBORenderTexture.h"
#include "DepthRenderTexture.h"
/**
* This object is used to render a big screen sized quad with the deferred rendering shader applied on it.
*/
class DeferredRendering
{
public:
// Ctors/Dtors
DeferredRendering(int width, int height);
// Methods
void setLightMatrices(float worldToLightViewMatrix[16], float lightViewToProjectionMatrix[16], float worldToCameraViewMatrix[16]);
void startRenderToFBO();
void stopRenderToFBO();
void startRenderToShadowMap();
void stopRenderToShadowMap();
void showTexture(unsigned int i, float fWindowsWidth, float fWindowsHeight, float fSizeX = 400, float fSizeY = 400, float x = 0, float y = 0) const;
void showShadowMap(float fWindowsWidth, float fWindowsHeight, float fSizeX = 400, float fSizeY = 400, float x = 0, float y = 0) const;
void render();
private:
// Variables
GLSLShaderData m_shader; // Deferred rendering shader
FBORenderTexture m_fboRenderTexture; // A pointer to the FBO render texture that contains diffuse, normals and positions
DepthRenderTexture m_shadowMap; // A pointer to the FBO that renders the depth into the shadow map
unsigned int m_width; // width
unsigned int m_height; // height
float m_worldToLightViewMatrix[16]; // Matrix that takes a vector from World Space into Light View Space
float m_lightViewToProjectionMatrix[16]; // Matrix that takes a vector from View Space into Projection Space (Clip Space)
float m_worldToCameraViewMatrix[16]; // Matrix that takes a vector from World Space into Camera View Space
GLuint m_diffuseID; // Diffuse texture handle for the shader
GLuint m_positionID; // Position texture handle for the shader
GLuint m_normalsID; // Normals texture handle for the shader
GLuint m_shadowMapID; // Shadow Map texture handle for the shader
GLuint m_worldToLightViewMatrix_shaderID; // Shader ID for the specified matrix
GLuint m_lightViewToProjectionMatrix_shaderID; // Shader ID for the specified matrix
GLuint m_worldToCameraViewMatrix_shaderID; // Shader ID for the specified matrix
};

View File

@ -0,0 +1,120 @@
#include "DepthRenderTexture.h"
#include <exception>
/**
* Create the FBO render texture initializing all the stuff that we need
*/
DepthRenderTexture::DepthRenderTexture(int _dWidth, int _dHeight)
{
// Save extensions
m_width = _dWidth;
m_height = _dHeight;
// Generate the OGL resources for what we need
glGenFramebuffersEXT(1, &m_fbo);
glGenRenderbuffersEXT(1, &m_depthBufferRT);
// Bind the FBO so that the next operations will be bound to it
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
// Bind the depth buffer
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_depthBufferRT);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, m_width, m_height);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthBufferRT);
// Generate and bind the OGL texture for diffuse
glGenTextures(1, &m_depthTexture);
glBindTexture(GL_TEXTURE_2D, m_depthTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, m_width, m_height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0);
// Attach the texture to the FBO
glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthTexture, 0);
// Check if all worked fine and unbind the FBO
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
if( status != GL_FRAMEBUFFER_COMPLETE_EXT)
throw new std::exception("Can't initialize an FBO render texture. FBO initialization failed.");
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}
/**
* Destructor
*/
DepthRenderTexture::~DepthRenderTexture(){
glDeleteFramebuffersEXT(1, &m_fbo);
glDeleteRenderbuffersEXT(1, &m_depthBufferRT);
glDeleteTextures(1, &m_depthTexture);
}
/**
* Start rendering to the texture
* Both color and depth buffers are cleared.
*/
void DepthRenderTexture::start(){
// Bind our FBO and set the viewport to the proper size
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
glPushAttrib(GL_VIEWPORT_BIT);
glViewport(0,0,m_width, m_height);
// Clear the render target
glClear( GL_DEPTH_BUFFER_BIT );
// Specify that we need no colours
glDrawBuffer(GL_NONE);
}
/**
* Stop rendering to this texture.
*/
void DepthRenderTexture::stop(){
// Stop acquiring and unbind the FBO
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glPopAttrib();
}
/**
* Show the texture to screen. It is just for debug purposes.
*/
void DepthRenderTexture::showTexture(float fWindowsWidth, float fWindowsHeight, float fSizeX, float fSizeY, float x, float y) const {
//Projection setup
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0,fWindowsWidth,0,fWindowsHeight,0.1f,2);
//Model setup
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glActiveTextureARB(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, m_depthTexture);
// Render the quad
glLoadIdentity();
glTranslatef(x, fWindowsHeight - y - fSizeY,-1.0);
glColor3f(1,1,1);
glBegin(GL_QUADS);
glTexCoord2f( 0, 1 );
glVertex3f( 0.0f, (float) fSizeY, 0.0f);
glTexCoord2f( 0, 0 );
glVertex3f( 0.0f, 0.0f, 0.0f);
glTexCoord2f( 1, 0 );
glVertex3f( fSizeX, 0.0f, 0.0f);
glTexCoord2f( 1, 1 );
glVertex3f( fSizeX, (float) fSizeY, 0.0f);
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
//Reset to the matrices
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}

View File

@ -0,0 +1,33 @@
#pragma once
#include <windows.h>
#include <gl/glew.h>
#include <gl/gl.h>
#include <gl/glu.h>
/**
* With this class we wrap the ability of OpenGL to render into a Depth Texture. We need this to create the shadow map.
*/
class DepthRenderTexture
{
public:
// Ctors/Dtors
DepthRenderTexture(int width, int height);
~DepthRenderTexture();
// Methods
void start();
void stop();
void showTexture(float fWindowsWidth, float fWindowsHeight, float fSizeX = 400, float fSizeY = 400, float x = 0, float y = 0) const;
GLuint getTexture() const { return m_depthTexture; }
private:
// Variables
GLuint m_fbo; // The FBO ID
GLuint m_depthBufferRT; // Depth buffer handle
GLuint m_depthTexture; // Texture
unsigned int m_width; // FBO width
unsigned int m_height; // FBO height
};

View File

@ -0,0 +1,175 @@
#include "FBORenderTexture.h"
#include <exception>
/**
* Create the FBO render texture initializing all the stuff that we need
*/
FBORenderTexture::FBORenderTexture(int _dWidth, int _dHeight)
{
// Save extensions
m_width = _dWidth;
m_height = _dHeight;
// Generate the OGL resources for what we need
glGenFramebuffersEXT(1, &m_fbo);
glGenRenderbuffersEXT(1, &m_diffuseRT);
glGenRenderbuffersEXT(1, &m_positionRT);
glGenRenderbuffersEXT(1, &m_normalsRT);
glGenRenderbuffersEXT(1, &m_depthBuffer);
// Bind the FBO so that the next operations will be bound to it
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
// Bind the diffuse render target
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_diffuseRT);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA, m_width, m_height);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, m_diffuseRT);
// Bind the position render target
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_positionRT);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA32F_ARB, m_width, m_height);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_RENDERBUFFER_EXT, m_positionRT);
// Bind the normal render target
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_normalsRT);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA16F_ARB, m_width, m_height);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_RENDERBUFFER_EXT, m_normalsRT);
// Bind the depth buffer
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_depthBuffer);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, m_width, m_height);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthBuffer);
// Generate and bind the OGL texture for diffuse
glGenTextures(1, &m_diffuseTexture);
glBindTexture(GL_TEXTURE_2D, m_diffuseTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// Attach the texture to the FBO
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_diffuseTexture, 0);
// Generate and bind the OGL texture for positions
glGenTextures(1, &m_positionTexture);
glBindTexture(GL_TEXTURE_2D, m_positionTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, m_width, m_height, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// Attach the texture to the FBO
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, m_positionTexture, 0);
// Generate and bind the OGL texture for normals
glGenTextures(1, &m_normalsTexture);
glBindTexture(GL_TEXTURE_2D, m_normalsTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, m_width, m_height, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// Attach the texture to the FBO
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_TEXTURE_2D, m_normalsTexture, 0);
// Check if all worked fine and unbind the FBO
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
if( status != GL_FRAMEBUFFER_COMPLETE_EXT)
throw new std::exception("Can't initialize an FBO render texture. FBO initialization failed.");
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}
/**
* Destructor
*/
FBORenderTexture::~FBORenderTexture(){
glDeleteTextures(1, &m_normalsTexture);
glDeleteTextures(1, &m_positionTexture);
glDeleteTextures(1, &m_diffuseTexture);
glDeleteFramebuffersEXT(1, &m_fbo);
glDeleteRenderbuffersEXT(1, &m_diffuseRT);
glDeleteRenderbuffersEXT(1, &m_positionRT);
glDeleteRenderbuffersEXT(1, &m_normalsRT);
glDeleteRenderbuffersEXT(1, &m_depthBuffer);
}
/**
* Start rendering to the texture
* Both color and depth buffers are cleared.
*/
void FBORenderTexture::start(){
// Bind our FBO and set the viewport to the proper size
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
glPushAttrib(GL_VIEWPORT_BIT);
glViewport(0,0,m_width, m_height);
// Clear the render targets
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
glActiveTextureARB(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
// Specify what to render an start acquiring
GLenum buffers[] = { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT2_EXT };
glDrawBuffers(3, buffers);
}
/**
* Stop rendering to this texture.
*/
void FBORenderTexture::stop(){
// Stop acquiring and unbind the FBO
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glPopAttrib();
}
/**
* Show the texture to screen. It is just for debug purposes.
*/
void FBORenderTexture::showTexture(unsigned int i, float fWindowsWidth, float fWindowsHeight, float fSizeX, float fSizeY, float x, float y) const {
GLuint texture = m_diffuseTexture;
if(i == 1) texture = m_positionTexture;
else
if(i == 2) texture = m_normalsTexture;
//Projection setup
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0,fWindowsWidth,0,fWindowsHeight,0.1f,2);
//Model setup
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glActiveTextureARB(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture);
// Render the quad
glLoadIdentity();
glTranslatef(x,fWindowsHeight - y - fSizeY,-1.0);
glColor3f(1,1,1);
glBegin(GL_QUADS);
glTexCoord2f( 0, 1 );
glVertex3f( 0.0f, (float) fSizeY, 0.0f);
glTexCoord2f( 0, 0 );
glVertex3f( 0.0f, 0.0f, 0.0f);
glTexCoord2f( 1, 0 );
glVertex3f( fSizeX, 0.0f, 0.0f);
glTexCoord2f( 1, 1 );
glVertex3f( fSizeX, (float) fSizeY, 0.0f);
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
//Reset to the matrices
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}

View File

@ -0,0 +1,41 @@
#pragma once
#include <windows.h>
#include <gl/glew.h>
#include <gl/gl.h>
#include <gl/glu.h>
/**
* A Frame Buffer Object is used by OpenGL to render into a texture. Specifically this implementation assumes that the
* rendered model will provide diffuse, position and normal at the same time in a MRT fashion
*/
class FBORenderTexture
{
public:
// Ctors/Dtors
FBORenderTexture(int width, int height);
~FBORenderTexture();
// Methods
void start();
void stop();
void showTexture(unsigned int i, float fWindowsWidth, float fWindowsHeight, float fSizeX = 400, float fSizeY = 400, float x = 0, float y = 0) const;
GLuint getDiffuseTexture() const { return m_diffuseTexture; }
GLuint getPositionTexture() const { return m_positionTexture; }
GLuint getNormalsTexture() const { return m_normalsTexture; }
private:
// Variables
GLuint m_fbo; // The FBO ID
GLuint m_diffuseRT; // The diffuse render target
unsigned int m_diffuseTexture; // The OpenGL texture for the diffuse render target
GLuint m_positionRT; // The position render target
unsigned int m_positionTexture; // The OpenGL texture for the position render target
GLuint m_normalsRT; // The normals render target
unsigned int m_normalsTexture; // The OpenGL texture for the normals render target
GLuint m_depthBuffer; // Depth buffer handle
unsigned int m_width; // FBO width
unsigned int m_height; // FBO height
};

View File

@ -0,0 +1,243 @@
#include <windows.h>
#include "GLApplication.h"
#include "Model/SphereModel.h"
#include "Model/CubeModel.h"
#include "Model/PlaneModel.h"
/**
* Initialize our GL application
*/
bool GLApplication::initialize(HWND hwnd, int width, int height)
{
GLuint pixelFormat;
m_windowHeight = height;
m_windowWidth = width;
m_hWnd = hwnd;
m_lightRotation = 0.0f;
static PIXELFORMATDESCRIPTOR pfd=
{
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW |
PFD_SUPPORT_OPENGL |
PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
16,
0, 0, 0, 0, 0, 0,
0,
0,
0,
0, 0, 0, 0,
16,
0,
0,
PFD_MAIN_PLANE,
0,
0, 0, 0
};
if (!(m_hdc=GetDC(m_hWnd)))
return FALSE;
if (!(pixelFormat=ChoosePixelFormat(m_hdc,&pfd)))
return FALSE;
if(!SetPixelFormat(m_hdc,pixelFormat,&pfd))
return FALSE;
if (!(m_hrc=wglCreateContext(m_hdc)))
return FALSE;
if(!wglMakeCurrent(m_hdc,m_hrc))
return FALSE;
ShowWindow(m_hWnd,SW_SHOW);
SetForegroundWindow(m_hWnd);
SetFocus(m_hWnd);
setSize(width, height);
glDisable(GL_LIGHTING);
glEnable(GL_TEXTURE_2D);
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glEnable(GL_CULL_FACE);
GLenum err = glewInit();
if (GLEW_OK != err)
return false;
loadAssets();
return true;
}
/**
* Set window's size
*/
void GLApplication::setSize(int w, int h)
{
m_windowWidth = w;
m_windowHeight = h;
glViewport(0,0,m_windowWidth,m_windowHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(40.0f,(GLfloat)m_windowWidth/(GLfloat)m_windowHeight,1.0f,30.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
/**
* Update
*/
void GLApplication::update()
{
float time = (GetTickCount() - m_lastTick) * 0.01f;
m_lastTick = GetTickCount();
m_models[3]->addRotation( time, time*2, 0 );
m_models[4]->addRotation( 0.2f + time, 0.1f + time*2, 0 );
m_lightRotation += time;
if(m_lightRotation > 360)
m_lightRotation -= 360;
}
/**
* Render the scene
*/
void GLApplication::render()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.2f, 0.3f, 0.8f, 1.0f);
// We move the near plane just a bit to make the depth texture a bit more visible.
// It also increases the precision.
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluPerspective(20.0f, 1, 40.0f, 70.0f);
// Set the light position
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(55, 1, 0, 0);
glRotatef(-45, 0, 1, 0);
glTranslatef(-25.0f, -50.0f, -25.0f);
glRotatef(m_lightRotation, 0, 1, 0);
glFrontFace(GL_CW);
// Render the shadow map
m_deferredRendering->startRenderToShadowMap();
for(int i=0; i<c_modelsCount; ++i)
m_models[i]->render();
m_deferredRendering->stopRenderToShadowMap();
// We then save out the matrices and send them to the deferred rendering, so when it comes to do the deferred pass
// it can project the pixel it's rendering to the light and see if it's in shadows
float worldToLightViewMatrix[16];
float lightViewToProjectionMatrix[16];
glGetFloatv(GL_MODELVIEW_MATRIX, worldToLightViewMatrix);
glGetFloatv(GL_PROJECTION_MATRIX, lightViewToProjectionMatrix);
// Re-set the projection to the default one we have pushed on the stack
glMatrixMode(GL_PROJECTION);
glPopMatrix();
// Set the camera position
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(20, 1, 0, 0);
glTranslatef(0.0f,-6.5f,-11.0f);
glFrontFace(GL_CCW);
float worldToCameraViewMatrix[16];
glGetFloatv(GL_MODELVIEW_MATRIX, worldToCameraViewMatrix);
// Render our geometry into the FBO
m_deferredRendering->startRenderToFBO();
for(int i=0; i<c_modelsCount; ++i)
m_models[i]->render();
m_deferredRendering->stopRenderToFBO();
// Render to the screen
if(m_state == 0)
{
// Render to screen using the deferred rendering shader
m_deferredRendering->setLightMatrices(worldToLightViewMatrix, lightViewToProjectionMatrix, worldToCameraViewMatrix);
m_deferredRendering->render();
}
else if(m_state == 1)
{
m_deferredRendering->showTexture( 0, (float)m_windowWidth, (float)m_windowHeight, 512, 384, 0);
m_deferredRendering->showTexture( 1, (float)m_windowWidth, (float)m_windowHeight, 512, 384, 512);
m_deferredRendering->showTexture( 2, (float)m_windowWidth, (float)m_windowHeight, 512, 384, 0, 384);
m_deferredRendering->showShadowMap( (float)m_windowWidth, (float)m_windowHeight, 384, 384, 512, 384);
}
SwapBuffers(m_hdc);
}
/**
* Release all the GL resources we have allocated
*/
void GLApplication::release()
{
releaseAssets();
wglMakeCurrent(m_hdc, 0);
wglDeleteContext(m_hrc);
ReleaseDC(m_hWnd, m_hdc);
}
/**
* Load all the required assets
*/
void GLApplication::loadAssets()
{
m_state = 0;
m_deferredRendering = new DeferredRendering(m_windowWidth, m_windowHeight);
m_models[0] = new PlaneModel("data/deferredShading.vert", "data/deferredShading.frag", 5);
m_models[0]->loadTexture("data/plane.raw");
m_models[0]->setPosition(0,0,0);
m_models[1] = new CubeModel("data/deferredShading.vert", "data/deferredShading.frag", 1);
m_models[1]->loadTexture("data/box.raw");
m_models[1]->setPosition(-1.0f,3.0f,-1);
m_models[2] = new CubeModel("data/deferredShading.vert", "data/deferredShading.frag", 1);
m_models[2]->loadTexture("data/box.raw");
m_models[2]->setPosition(-1.0f,1.0f,-1);
m_models[2]->setRotation(0, 20.0f, 0.0f);
m_models[3] = new SphereModel("data/deferredShading.vert", "data/deferredShading.frag", 1, 64);
m_models[3]->loadTexture("data/earth.raw");
m_models[3]->setPosition(1.5f, 2.0f, 0.5f);
m_models[4] = new SphereModel("data/deferredShading.vert", "data/deferredShading.frag", 1, 64);
m_models[4]->loadTexture("data/earth.raw");
m_models[4]->setPosition(1.5f, 5.0f, 0.5f);
}
/**
* Release all the assets
*/
void GLApplication::releaseAssets()
{
delete m_deferredRendering;
for(int i=0; i<c_modelsCount; ++i)
delete m_models[i];
}

View File

@ -0,0 +1,47 @@
#pragma once
#include <windows.h>
#include "DeferredRendering/DeferredRendering.h"
#include "DeferredRendering/FBORenderTexture.h"
//Fwd
class IModel;
/**
* This class contains all the system stuff that we need to render with OpenGL
*/
class GLApplication {
public:
// Methods
bool initialize(HWND hwnd, int w, int h);
void setSize(int w, int h);
void update();
void render();
void release();
void showDeferredRendering(){ m_state = 0; }
void showRenderTargets(){ m_state = 1; }
private:
// Methods
void loadAssets();
void releaseAssets();
// Static consts
static const int c_modelsCount = 5;
// Fields
IModel* m_models[c_modelsCount];
DeferredRendering* m_deferredRendering;
int m_windowWidth;
int m_windowHeight;
HGLRC m_hrc; // Rendering's context
HDC m_hdc; // Device's context
HWND m_hWnd; // Window's handle
unsigned int m_lastTick;
unsigned char m_state; // 0 - Normal render, 1 - Show render targets
float m_lightRotation;
};

View File

@ -0,0 +1,73 @@
#include "CubeModel.h"
#include <math.h>
/**
* Construct the cube
*/
CubeModel::CubeModel(const std::string& sVSFileName, const std::string& sFSFileName, float side)
: IModel(sVSFileName, sFSFileName)
, m_side(side)
{
}
/**
* Render
*/
void CubeModel::render() const
{
glPushMatrix();
// Save the current world matrix to compensate the normals in the shader
float worldMatrix[16];
glGetFloatv(GL_MODELVIEW_MATRIX, worldMatrix);
glScalef(m_side,m_side,m_side);
glTranslatef(m_posX, m_posY, m_posZ);
glRotatef(m_rotX, 1, 0, 0);
glRotatef(m_rotY, 0, 1, 0);
glRotatef(m_rotZ, 0, 0, 1);
glUseProgramObjectARB(m_shader.m_programHandler);
glBindTexture(GL_TEXTURE_2D, m_texture);
glUniform1iARB ( m_textureID, 0);
glUniformMatrix4fvARB ( m_worldMatrixID, 1, false, worldMatrix);
glBegin(GL_QUADS);
// Front Face
glTexCoord2f(0.0f, 0.0f); glNormal3f(0.0f, 0.0f, 1.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glNormal3f(0.0f, 0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glNormal3f(0.0f, 0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glNormal3f(0.0f, 0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
// Back Face
glTexCoord2f(1.0f, 0.0f); glNormal3f(0.0f, 0.0f, -1.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 1.0f); glNormal3f(0.0f, 0.0f, -1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f); glNormal3f(0.0f, 0.0f, -1.0f); glVertex3f( 1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f); glNormal3f(0.0f, 0.0f, -1.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
// Top Face
glTexCoord2f(0.0f, 1.0f); glNormal3f(0.0f, 1.0f, 0.0f); glVertex3f(-1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f); glNormal3f(0.0f, 1.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glNormal3f(0.0f, 1.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glNormal3f(0.0f, 1.0f, 0.0f); glVertex3f( 1.0f, 1.0f, -1.0f);
// Bottom Face
glTexCoord2f(1.0f, 1.0f); glNormal3f(0.0f, -1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f); glNormal3f(0.0f, -1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f); glNormal3f(0.0f, -1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glNormal3f(0.0f, -1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
// Right face
glTexCoord2f(1.0f, 0.0f); glNormal3f(1.0f, 0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 1.0f); glNormal3f(1.0f, 0.0f, 0.0f); glVertex3f( 1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f); glNormal3f(1.0f, 0.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 0.0f); glNormal3f(1.0f, 0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
// Left Face
glTexCoord2f(0.0f, 0.0f); glNormal3f(-1.0f, 0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 0.0f); glNormal3f(-1.0f, 0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glNormal3f(-1.0f, 0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glNormal3f(-1.0f, 0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, -1.0f);
glEnd();
glUseProgramObjectARB(0);
glPopMatrix();
}

View File

@ -0,0 +1,19 @@
#pragma once
#include "IModel.h"
/**
* A simple cube model that is easy to render
*/
class CubeModel : public IModel
{
public:
// Methods
CubeModel(const std::string& sVSFileName, const std::string& sFSFileName, float side);
void render() const;
protected:
// Fields
float m_side;
};

View File

@ -0,0 +1,82 @@
#include <windows.h>
#include "gl/glew.h"
#include <gl/gl.h>
#include <gl/glu.h>
#include "GLSLShaderData.h"
/**
* Constructor
*/
GLSLShaderData::GLSLShaderData(const std::string& _sVSFileName, const std::string& _sFSFileName)
: m_VSFileName(_sVSFileName)
, m_FSFileName(_sFSFileName)
{
// Create OGL resources
m_vertexShader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
m_fragmentShader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
//Read out the shader data from the given files
char *sVSData, *sFSData;
//Read out the vertex shader data
FILE *file;
fopen_s(&file, m_VSFileName.c_str(),"r");
if(!file)
throw new std::exception( std::string("Can't load GLSL Vertex Shader from file: " + m_VSFileName).c_str() );
fseek(file, 0, SEEK_END);
long count = ftell(file);
rewind(file);
sVSData = new char[count+1];
memset(sVSData,0,count+1);
fread(sVSData, 1, count, file);
fclose(file);
file = NULL;
//Read out the fragment shader data
fopen_s(&file, m_FSFileName.c_str(),"r");
if(!file)
throw new std::exception( std::string("Can't load GLSL Fragment Shader from file: "+m_FSFileName).c_str() );
fseek(file, 0, SEEK_END);
count = ftell(file);
rewind(file);
sFSData = new char[count+1];
memset(sFSData,0,count+1);
fread(sFSData, 1, count, file);
fclose(file);
// Now that we have the two shaders in memory we can compile them
const char * pVS = sVSData;
const char * pFS = sFSData;
int bCompiled = false;
glShaderSourceARB(m_vertexShader, 1, &pVS, NULL);
glCompileShaderARB(m_vertexShader);
glGetObjectParameterivARB( m_vertexShader, GL_OBJECT_COMPILE_STATUS_ARB, &bCompiled );
if( bCompiled == false )
throw new std::exception("Vertex shader compilation failed.");
glShaderSourceARB(m_fragmentShader, 1, &pFS, NULL);
glCompileShaderARB(m_fragmentShader);
glGetObjectParameterivARB( m_fragmentShader, GL_OBJECT_COMPILE_STATUS_ARB, &bCompiled );
if( bCompiled == false )
throw new std::exception("Fragment shader compilation failed.");
// Once compiled we can bind everything together for OpenGL to use
m_programHandler = glCreateProgramObjectARB();
glAttachObjectARB(m_programHandler,m_vertexShader);
glAttachObjectARB(m_programHandler,m_fragmentShader);
glLinkProgramARB(m_programHandler);
// We release the shader data read from file since we now have everything compiled in memory
delete [] sFSData;
delete [] sVSData;
}

View File

@ -0,0 +1,22 @@
#pragma once
#include <string>
/**
* GLSLShaderData encapsulate all the GLSL data.<br>
* Constructor initialize data from files.
*/
class GLSLShaderData
{
public:
// Functions
//------------------------------------------------------------
GLSLShaderData(const std::string& sVSFileName, const std::string& sFSFileName);
// Variables
//------------------------------------------------------------
GLhandleARB m_vertexShader; // Vertex shader handle
GLhandleARB m_fragmentShader; // Fragment shader handle
GLhandleARB m_programHandler; // Shader handle
std::string m_VSFileName; // Vertex shader filename
std::string m_FSFileName; // Fragment shader filename
};

View File

@ -0,0 +1,79 @@
#include "IModel.h"
#include <math.h>
/**
* This method assumes that the file passed as parameter is a raw block of data made of RGB components (one byte per channel)
* It is *NOT* a good way to load/store textures, but for sake of simplicity I've decided to use it for this tutorial.
*/
bool IModel::loadTexture(const std::string& textureName)
{
byte* data = NULL;
FILE* f;
fopen_s(&f, textureName.c_str(), "r");
if(f != NULL)
{
fseek (f, 0, SEEK_END);
unsigned int size = ftell (f);
fseek (f, 0, SEEK_SET);
data = new byte[size];
fread( data, sizeof(byte), size, f);
fclose(f);
// Assuming that the raw image is square and RGB; don't fancy doing anything more complicated since the tutorial is not focused on textures loading
GLuint side = (GLuint)sqrt(size/3.0f);
// Generate the texture
if(m_texture != 0)
glDeleteTextures(1, &m_texture);
glGenTextures(1, &m_texture);
glBindTexture(GL_TEXTURE_2D, m_texture);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexImage2D(GL_TEXTURE_2D, 0, 3, side, side, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
}
else
return false;
return true;
}
/**
* Set position
*/
void IModel::setPosition(float x, float y, float z)
{
m_posX = x;
m_posY = y;
m_posZ = z;
}
/**
* Set rotation
*/
void IModel::setRotation(float x, float y, float z)
{
m_rotX = x;
m_rotY = y;
m_rotZ = z;
}
/**
* Add a delta to the current rotation
*/
void IModel::addRotation(float x, float y, float z)
{
m_rotX += x;
m_rotY += y;
m_rotZ += z;
}

View File

@ -0,0 +1,45 @@
#pragma once
#include <windows.h>
#include "gl/glew.h"
#include <gl/gl.h>
#include <gl/glu.h>
#include <string>
#include "GLSLShaderData.h"
/**
* Every renderable object inherits from this interface for simplicity
*/
class IModel
{
public:
// Methods
IModel(const std::string& sVSFileName, const std::string& sFSFileName)
: m_shader(sVSFileName, sFSFileName)
, m_texture(0)
{
m_rotX = m_rotY = m_rotZ = 0;
m_posX = m_posY = m_posZ = 0;
m_worldMatrixID = glGetUniformLocationARB(m_shader.m_programHandler,"WorldMatrix");
m_textureID = glGetUniformLocationARB(m_shader.m_programHandler,"tDiffuse");
}
virtual ~IModel(){}
bool loadTexture(const std::string& textureName);
void setPosition(float x, float y, float z);
void setRotation(float x, float y, float z);
void addRotation(float x, float y, float z);
virtual void render() const = 0;
protected:
// Fields
GLSLShaderData m_shader; // Every model must have a shader associated (both vertex and fragment)
GLuint m_worldMatrixID; // This ID is used to pass the world matrix into the shader
float m_rotX, m_rotY, m_rotZ; // Rotations
float m_posX, m_posY, m_posZ; // Positions
GLuint m_textureID; // Texture ID used to pass the texture into the shader
GLuint m_texture; // OpenGL texture ID
};

View File

@ -0,0 +1,57 @@
#include "PlaneModel.h"
#include <math.h>
/**
* Construct the plane
*/
PlaneModel::PlaneModel(const std::string& sVSFileName, const std::string& sFSFileName, float side)
: IModel(sVSFileName, sFSFileName)
, m_side(side)
{}
/**
* Render
*/
void PlaneModel::render() const
{
glPushMatrix();
// Save the current world matrix to compensate the normals in the shader
float worldMatrix[16];
glGetFloatv(GL_MODELVIEW_MATRIX, worldMatrix);
glTranslatef(m_posX, m_posY, m_posZ);
glRotatef(m_rotX, 1, 0, 0);
glRotatef(m_rotY, 0, 1, 0);
glRotatef(m_rotZ, 0, 0, 1);
glScalef(m_side,m_side,m_side);
glUseProgramObjectARB(m_shader.m_programHandler);
glBindTexture(GL_TEXTURE_2D, m_texture);
glUniform1iARB ( m_textureID, 0);
glUniformMatrix4fvARB ( m_worldMatrixID, 1, false, worldMatrix);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 1.0f);
glNormal3f(0.0f, 1.0f, 0.0f);
glVertex3f(-1.0f, 0.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f);
glNormal3f(0.0f, 1.0f, 0.0f);
glVertex3f(-1.0f, 0.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f);
glNormal3f(0.0f, 1.0f, 0.0f);
glVertex3f( 1.0f, 0.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f);
glNormal3f(0.0f, 1.0f, 0.0f);
glVertex3f( 1.0f, 0.0f, -1.0f);
glEnd();
glUseProgramObjectARB(0);
glPopMatrix();
}

View File

@ -0,0 +1,19 @@
#pragma once
#include "IModel.h"
/**
* A plane model that is easy to render
*/
class PlaneModel : public IModel
{
public:
// Methods
PlaneModel(const std::string& sVSFileName, const std::string& sFSFileName, float side);
void render() const;
protected:
// Fields
float m_side;
};

View File

@ -0,0 +1,45 @@
#include "SphereModel.h"
#include <math.h>
/**
* Construct the sphere
*/
SphereModel::SphereModel(const std::string& sVSFileName, const std::string& sFSFileName, float radius, unsigned int meshPrecision)
: IModel(sVSFileName, sFSFileName)
{
m_radius = radius;
m_meshPrecision = meshPrecision;
}
/**
* Render
*/
void SphereModel::render() const
{
glPushMatrix();
// Save the current world matrix to compensate the normals in the shader
float worldMatrix[16];
glGetFloatv(GL_MODELVIEW_MATRIX, worldMatrix);
glTranslatef(m_posX, m_posY, m_posZ);
glRotatef(m_rotX, 1, 0, 0);
glRotatef(m_rotY, 0, 1, 0);
glRotatef(m_rotZ, 0, 0, 1);
glUseProgramObjectARB(m_shader.m_programHandler);
glBindTexture(GL_TEXTURE_2D, m_texture);
glUniform1iARB ( m_textureID, 0);
glUniformMatrix4fvARB ( m_worldMatrixID, 1, false, worldMatrix);
GLUquadricObj *sphere = gluNewQuadric();
gluQuadricTexture(sphere, true);
gluSphere(sphere, m_radius, m_meshPrecision, m_meshPrecision);
gluDeleteQuadric(sphere);
glUseProgramObjectARB(0);
glPopMatrix();
}

View File

@ -0,0 +1,20 @@
#pragma once
#include "IModel.h"
/**
* A simple sphere model that is easy to render
*/
class SphereModel : public IModel
{
public:
// Methods
SphereModel(const std::string& sVSFileName, const std::string& sFSFileName, float radius, unsigned int meshPrecision);
void render() const;
private:
// Fields
float m_radius;
unsigned int m_meshPrecision;
};

View File

@ -0,0 +1,102 @@
#include <windows.h>
#include <iostream>
#include <stdio.h>
#include "GLApplication.h"
GLApplication application;
bool running = true;
HINSTANCE hInstance;
// The window callback function
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) {
case WM_SIZE:
{
application.setSize(LOWORD(lParam), HIWORD(lParam));
break;
}
case WM_KEYDOWN:
{
if((unsigned short) wParam == 112) application.showDeferredRendering();
if((unsigned short) wParam == 113) application.showRenderTargets();
break;
}
case WM_DESTROY:
{
PostQuitMessage(0);
break;
}
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
// Main entry point
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
WNDCLASS windowClass;
HWND hWnd;
DWORD dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
const int width = 1024;
const int height = 768;
hInstance = GetModuleHandle(NULL);
windowClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
windowClass.lpfnWndProc = (WNDPROC) WndProc;
windowClass.cbClsExtra = 0;
windowClass.cbWndExtra = 0;
windowClass.hInstance = hInstance;
windowClass.hIcon = LoadIcon(NULL, IDI_WINLOGO);
windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
windowClass.hbrBackground = NULL;
windowClass.lpszMenuName = NULL;
windowClass.lpszClassName = L"DeferredRenderingClass";
if (!RegisterClass(&windowClass)) {
return false;
}
hWnd = CreateWindowEx(dwExStyle, L"DeferredRenderingClass", L"Deferred Rendering Shadow Mapping tutorial", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, width, height, NULL, NULL, hInstance, NULL);
if(!application.initialize(hWnd, width, height))
return 0;
ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);
bool running = true;
while (running)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
{
running = false;
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else
{
application.update();
application.render();
}
}
application.release();
return (int) msg.wParam;
}