diff --git a/CMake/FeatureSummary.cmake b/CMake/FeatureSummary.cmake --- a/CMake/FeatureSummary.cmake +++ b/CMake/FeatureSummary.cmake @@ -48,6 +48,9 @@ if (OGRE_BUILD_PLUGIN_CG) set(_plugins "${_plugins} + Cg program manager\n") endif () +if (OGRE_BUILD_PLUGIN_DEFERREDSHADING) + set(_plugins "${_plugins} + Deferred shading\n") +endif () if (OGRE_BUILD_PLUGIN_OCTREE) set(_plugins "${_plugins} + Octree scene manager\n") endif () diff --git a/CMake/Packages/FindOGRE.cmake b/CMake/Packages/FindOGRE.cmake --- a/CMake/Packages/FindOGRE.cmake +++ b/CMake/Packages/FindOGRE.cmake @@ -27,7 +27,7 @@ # parts of the Ogre package: # Plugin_BSPSceneManager, Plugin_CgProgramManager, # Plugin_OctreeSceneManager, Plugin_OctreeZone, -# Plugin_ParticleFX, Plugin_PCZSceneManager, +# Plugin_ParticleFX, Plugin_PCZSceneManager, Plugin_DeferredShading # RenderSystem_GL, RenderSystem_Direct3D9, RenderSystem_Direct3D10, # Paging, Terrain # @@ -126,7 +126,7 @@ # redo search if any of the environmental hints changed set(OGRE_COMPONENTS Paging Terrain Plugin_BSPSceneManager Plugin_CgProgramManager Plugin_OctreeSceneManager - Plugin_OctreeZone Plugin_PCZSceneManager Plugin_ParticleFX + Plugin_OctreeZone Plugin_PCZSceneManager Plugin_ParticleFX Plugin_DeferredShading RenderSystem_Direct3D10 RenderSystem_Direct3D9 RenderSystem_GL RenderSystem_GLES RenderSystem_GLES2) set(OGRE_RESET_VARS OGRE_CONFIG_INCLUDE_DIR OGRE_INCLUDE_DIR @@ -467,6 +467,7 @@ ogre_find_plugin(Plugin_CgProgramManager OgreCgProgram.h PlugIns/CgProgramManager/include) ogre_find_plugin(Plugin_OctreeSceneManager OgreOctreeSceneManager.h PlugIns/OctreeSceneManager/include) ogre_find_plugin(Plugin_ParticleFX OgreParticleFXPrerequisites.h PlugIns/ParticleFX/include) +ogre_find_plugin(Plugin_DeferredShading OgreDeferredShadingPlugin.h PlugIns/DeferredShading/include) ogre_find_plugin(RenderSystem_GL OgreGLRenderSystem.h RenderSystems/GL/include) ogre_find_plugin(RenderSystem_GLES OgreGLESRenderSystem.h RenderSystems/GLES/include) ogre_find_plugin(RenderSystem_GLES2 OgreGLES2RenderSystem.h RenderSystems/GLES2/include) diff --git a/CMake/Templates/OgreBuildSettings.h.in b/CMake/Templates/OgreBuildSettings.h.in --- a/CMake/Templates/OgreBuildSettings.h.in +++ b/CMake/Templates/OgreBuildSettings.h.in @@ -16,6 +16,7 @@ #cmakedefine OGRE_BUILD_PLUGIN_PCZ #cmakedefine OGRE_BUILD_PLUGIN_PFX #cmakedefine OGRE_BUILD_PLUGIN_CG +#cmakedefine OGRE_BUILD_PLUGIN_DEFERREDSHADING #cmakedefine OGRE_CONFIG_LITTLE_ENDIAN #cmakedefine OGRE_CONFIG_BIG_ENDIAN diff --git a/CMake/Templates/SDK_CMakeLists.txt.in b/CMake/Templates/SDK_CMakeLists.txt.in --- a/CMake/Templates/SDK_CMakeLists.txt.in +++ b/CMake/Templates/SDK_CMakeLists.txt.in @@ -232,6 +232,10 @@ include_directories(${OGRE_Plugin_ParticleFX_INCLUDE_DIRS}) set(OGRE_PLUGIN_LIBRARIES ${OGRE_PLUGIN_LIBRARIES} ${OGRE_Plugin_ParticleFX_LIBRARIES}) endif () + if (OGRE_Plugin_DeferredShading_FOUND) + include_directories(${OGRE_Plugin_DeferredShading_INCLUDE_DIRS}) + set(OGRE_PLUGIN_LIBRARIES ${OGRE_PLUGIN_LIBRARIES} ${OGRE_Plugin_DeferredShading_LIBRARIES}) + endif () if (OGRE_RenderSystem_Direct3D9_FOUND) include_directories(${OGRE_RenderSystem_Direct3D9_INCLUDE_DIRS}) set(OGRE_PLUGIN_LIBRARIES ${OGRE_PLUGIN_LIBRARIES} ${OGRE_RenderSystem_Direct3D9_LIBRARIES}) diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -269,6 +269,9 @@ cmake_dependent_option(OGRE_BUILD_COMPONENT_TERRAIN "Build Terrain component" TRUE "NOT SYMBIAN" FALSE) cmake_dependent_option(OGRE_BUILD_COMPONENT_PROPERTY "Build Property component" TRUE "Boost_FOUND" FALSE) cmake_dependent_option(OGRE_BUILD_PLUGIN_CG "Build Cg plugin" TRUE "Cg_FOUND;NOT OGRE_BUILD_PLATFORM_APPLE_IOS;NOT SYMBIAN" FALSE) +#Deferred shading code is implemented with cg shaders, so require cg plugin +cmake_dependent_option(OGRE_BUILD_PLUGIN_DEFERREDSHADING "Build Deferred Shading plugin" TRUE "OGRE_BUILD_PLUGIN_CG" FALSE) + option(OGRE_BUILD_COMPONENT_RTSHADERSYSTEM "Build RTShader System component" TRUE) cmake_dependent_option(OGRE_BUILD_RTSHADERSYSTEM_CORE_SHADERS "Build RTShader System FFP core shaders" TRUE "OGRE_BUILD_COMPONENT_RTSHADERSYSTEM" FALSE) cmake_dependent_option(OGRE_BUILD_RTSHADERSYSTEM_EXT_SHADERS "Build RTShader System extensions shaders" TRUE "OGRE_BUILD_COMPONENT_RTSHADERSYSTEM" FALSE) diff --git a/PlugIns/CMakeLists.txt b/PlugIns/CMakeLists.txt --- a/PlugIns/CMakeLists.txt +++ b/PlugIns/CMakeLists.txt @@ -36,3 +36,7 @@ add_subdirectory(OctreeZone) endif (OGRE_BUILD_PLUGIN_PCZ) +if (OGRE_BUILD_PLUGIN_DEFERREDSHADING) + add_subdirectory(DeferredShading) +endif (OGRE_BUILD_PLUGIN_DEFERREDSHADING) + diff --git a/Samples/Browser/CMakeLists.txt b/Samples/Browser/CMakeLists.txt --- a/Samples/Browser/CMakeLists.txt +++ b/Samples/Browser/CMakeLists.txt @@ -253,6 +253,12 @@ ${OGRE_SAMPLE_CONTENTS_PATH}/Plugins/ ) endif() + if (OGRE_BUILD_PLUGIN_DEFERREDSHADING OR OGRE_SDK_BUILD) + add_custom_command(TARGET SampleBrowser POST_BUILD + COMMAND ln ARGS -s -f ${OGRE_BINARY_DIR}/lib/${OGRE_OSX_BUILD_CONFIGURATION}Plugin_DeferredShading.dylib + ${OGRE_SAMPLE_CONTENTS_PATH}/Plugins/ + ) + endif() if (OGRE_BUILD_PLUGIN_OCTREE OR OGRE_SDK_BUILD) add_custom_command(TARGET SampleBrowser POST_BUILD COMMAND ln ARGS -s -f ${OGRE_BINARY_DIR}/lib/${OGRE_OSX_BUILD_CONFIGURATION}Plugin_OctreeSceneManager.dylib diff --git a/Samples/CMakeLists.txt b/Samples/CMakeLists.txt --- a/Samples/CMakeLists.txt +++ b/Samples/CMakeLists.txt @@ -24,6 +24,9 @@ if (OGRE_BUILD_PLUGIN_CG) set(SAMPLE_DEPENDENCIES ${SAMPLE_DEPENDENCIES} Plugin_CgProgramManager) endif (OGRE_BUILD_PLUGIN_CG) + if (OGRE_BUILD_PLUGIN_DEFERREDSHADING) + set(SAMPLE_DEPENDENCIES ${SAMPLE_DEPENDENCIES} Plugin_DeferredShading) + endif (OGRE_BUILD_PLUGIN_DEFERREDSHADING) if (OGRE_BUILD_PLUGIN_PFX) set(SAMPLE_DEPENDENCIES ${SAMPLE_DEPENDENCIES} Plugin_ParticleFX) endif () @@ -73,6 +76,7 @@ include_directories(${OGRE_SOURCE_DIR}/PlugIns/OctreeSceneManager/include) include_directories(${OGRE_SOURCE_DIR}/PlugIns/OctreeZone/include) include_directories(${OGRE_SOURCE_DIR}/PlugIns/ParticleFX/include) + include_directories(${OGRE_SOURCE_DIR}/PlugIns/DeferredShading/include) include_directories(${OGRE_SOURCE_DIR}/PlugIns/PCZSceneManager/include) include_directories(${OGRE_SOURCE_DIR}/RenderSystems/Direct3D9/include) include_directories(${OGRE_SOURCE_DIR}/RenderSystems/Direct3D10/include) @@ -138,7 +142,9 @@ if (NOT OGRE_BUILD_RENDERSYSTEM_GLES OR OGRE_BUILD_RENDERSYSTEM_GLES2) add_subdirectory(BSP) add_subdirectory(CelShading) - add_subdirectory(DeferredShading) + if(OGRE_BUILD_PLUGIN_DEFERREDSHADING) + add_subdirectory(DeferredShading) + endif(OGRE_BUILD_PLUGIN_DEFERREDSHADING) add_subdirectory(CubeMapping) add_subdirectory(Dot3Bump) add_subdirectory(DynTex) diff --git a/Samples/Common/include/ExampleApplication.h b/Samples/Common/include/ExampleApplication.h --- a/Samples/Common/include/ExampleApplication.h +++ b/Samples/Common/include/ExampleApplication.h @@ -38,6 +38,7 @@ # define OGRE_STATIC_BSPSceneManager # define OGRE_STATIC_ParticleFX # define OGRE_STATIC_CgProgramManager +# define OGRE_STATIC_DeferredShading # ifdef OGRE_USE_PCZ # define OGRE_STATIC_PCZSceneManager # define OGRE_STATIC_OctreeZone diff --git a/Samples/Common/include/OgreStaticPluginLoader.h b/Samples/Common/include/OgreStaticPluginLoader.h --- a/Samples/Common/include/OgreStaticPluginLoader.h +++ b/Samples/Common/include/OgreStaticPluginLoader.h @@ -57,6 +57,9 @@ #ifdef OGRE_STATIC_OctreeZone # include "OgreOctreeZonePlugin.h" #endif +#ifdef OGRE_STATIC_DeferredShading +# include "OgreDeferredShadingPlugin.h" +#endif namespace Ogre { @@ -90,6 +93,9 @@ #ifdef OGRE_STATIC_OctreeZone OctreeZonePlugin* mOctreeZonePlugin; #endif +#ifdef OGRE_STATIC_DeferredShading + DeferredShadingPlugin* mDeferredShadingPlugin; +#endif #ifdef OGRE_STATIC_GL GLPlugin* mGLPlugin; #endif @@ -156,8 +162,12 @@ mOctreeZonePlugin = OGRE_NEW OctreeZonePlugin(); root.installPlugin(mOctreeZonePlugin); #endif +#ifdef OGRE_STATIC_DeferredShading + mDeferredShadingPlugin = OGRE_NEW DeferredShadingPlugin(); + root.installPlugin(mDeferredShadingPlugin); +#endif } void unload() { // don't unload plugins, since Root will have done that. Destroy here. @@ -159,8 +169,11 @@ } void unload() { // don't unload plugins, since Root will have done that. Destroy here. +#ifdef OGRE_STATIC_DeferredShading + OGRE_DELETE mDeferredShadingPlugin; +#endif #ifdef OGRE_STATIC_OctreeZone OGRE_DELETE mOctreeZonePlugin; #endif diff --git a/Samples/Common/include/SampleContext.h b/Samples/Common/include/SampleContext.h --- a/Samples/Common/include/SampleContext.h +++ b/Samples/Common/include/SampleContext.h @@ -67,7 +67,9 @@ # ifdef OGRE_BUILD_PLUGIN_CG # define OGRE_STATIC_CgProgramManager # endif - +# ifdef OGRE_BUILD_PLUGIN_DEFERREDSHADING +# define OGRE_STATIC_DeferredShading +# endif # ifdef OGRE_USE_PCZ # ifdef OGRE_BUILD_PLUGIN_PCZ # define OGRE_STATIC_PCZSceneManager diff --git a/Samples/DeferredShading/CMakeLists.txt b/Samples/DeferredShading/CMakeLists.txt --- a/Samples/DeferredShading/CMakeLists.txt +++ b/Samples/DeferredShading/CMakeLists.txt @@ -10,7 +10,4 @@ # Configure DeferredShading demo build set(HEADER_FILES - include/AmbientLight.h - include/DeferredLightCP.h - include/DeferredShading.h include/DeferredShadingDemo.h @@ -16,10 +13,2 @@ include/DeferredShadingDemo.h - include/DLight.h - include/GBufferMaterialGenerator.h - include/GBufferSchemeHandler.h - include/GeomUtils.h - include/LightMaterialGenerator.h - include/ListenerFactoryLogic.h - include/MaterialGenerator.h - include/NullSchemeHandler.h include/SharedData.h @@ -25,5 +14,4 @@ include/SharedData.h - include/SSAOLogic.h ) set(SOURCE_FILES @@ -27,7 +15,4 @@ ) set(SOURCE_FILES - src/AmbientLight.cpp - src/DeferredLightCP.cpp - src/DeferredShading.cpp src/DeferredShadingDemo.cpp @@ -33,10 +18,3 @@ src/DeferredShadingDemo.cpp - src/DLight.cpp - src/GBufferMaterialGenerator.cpp - src/GBufferSchemeHandler.cpp - src/GeomUtils.cpp - src/LightMaterialGenerator.cpp - src/MaterialGenerator.cpp - src/SSAOLogic.cpp ) @@ -41,5 +19,7 @@ ) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include + ${CMAKE_CURRENT_SOURCE_DIR}/../../PlugIns/DeferredShading/include + ) ogre_add_library(Sample_DeferredShading ${OGRE_LIB_TYPE} ${SOURCE_FILES} ${HEADER_FILES}) @@ -44,5 +24,5 @@ ogre_add_library(Sample_DeferredShading ${OGRE_LIB_TYPE} ${SOURCE_FILES} ${HEADER_FILES}) -target_link_libraries(Sample_DeferredShading ${OGRE_LIBRARIES} ${OIS_LIBRARIES}) +target_link_libraries(Sample_DeferredShading ${OGRE_LIBRARIES} ${OGRE_PLUGIN_LIBRARIES} ${OGRE_Plugin_DeferredShading_LIBRARIES} ${OIS_LIBRARIES}) ogre_config_sample_lib(Sample_DeferredShading) @@ -47,5 +27,10 @@ ogre_config_sample_lib(Sample_DeferredShading) +# need to include plugins directory in RPATH for the demo to be able to find the libs +set_property(TARGET Sample_DeferredShading APPEND PROPERTY + INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/lib/OGRE +) + if (APPLE AND NOT OGRE_BUILD_PLATFORM_APPLE_IOS) # Set the INSTALL_PATH so that Samples can be installed in the application package set_target_properties(Sample_DeferredShading @@ -54,3 +39,7 @@ ) endif() +if (SAMPLE_DEPENDENCIES) + add_dependencies(Sample_DeferredShading ${SAMPLE_DEPENDENCIES}) +endif () + diff --git a/Samples/DeferredShading/include/DeferredShadingDemo.h b/Samples/DeferredShading/include/DeferredShadingDemo.h --- a/Samples/DeferredShading/include/DeferredShadingDemo.h +++ b/Samples/DeferredShading/include/DeferredShadingDemo.h @@ -46,7 +46,8 @@ #include "OgreSceneNode.h" #include "OgreMaterial.h" #include "OgreRenderTargetListener.h" -#include "GeomUtils.h" +#include "OgreDeferredShadingManager.h" +#include "OgreDeferredShadingPlugin.h" using namespace Ogre; using namespace OgreBites; @@ -76,6 +77,7 @@ void cleanupContent(void) { + DeferredShadingManager::getSingleton().removeSceneManager(mSceneMgr); delete ( SharedData::getSingletonPtr() ); delete mSystem; @@ -258,22 +260,7 @@ new SharedData(); mSystem = 0; - RenderSystem *rs = Root::getSingleton().getRenderSystem(); - const RenderSystemCapabilities* caps = rs->getCapabilities(); - if (!caps->hasCapability(RSC_VERTEX_PROGRAM) || !(caps->hasCapability(RSC_FRAGMENT_PROGRAM))) - { - OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED, "Your card does not support vertex and fragment programs, so cannot " - "run this demo. Sorry!", - "DeferredShading::createScene"); - } - if (caps->getNumMultiRenderTargets()<2) - { - OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED, "Your card does not support at least two simultaneous render targets, so cannot " - "run this demo. Sorry!", - "DeferredShading::createScene"); - } - - + DeferredShadingManager::getSingleton().addSceneManager(mSceneMgr); // Set ambient light mSceneMgr->setAmbientLight(ColourValue(0.15, 0.00, 0.00)); @@ -295,7 +282,7 @@ mCamera->setNearClipDistance(0.5); setDragLook(true); - mSystem = new DeferredShadingSystem(mWindow->getViewport(0), mSceneMgr, mCamera); + mSystem = new DeferredShadingSystem(mWindow->getViewport(0), mCamera); SharedData::getSingleton().iSystem = mSystem; mSystem->initialize(); @@ -466,10 +453,10 @@ SharedData::getSingleton().mMLAnimState = mSceneMgr->createAnimationState("LightSwarmTrack"); SharedData::getSingleton().mMLAnimState->setEnabled(true); - /*Light* spotLight = mSceneMgr->createLight("Spotlight1"); + Light* spotLight = mSceneMgr->createLight("Spotlight1"); spotLight->setType(Light::LT_SPOTLIGHT); spotLight->setAttenuation(200, 1.0f, 0, 0); spotLight->setSpotlightRange(Degree(30.0), Degree(45.0), 0.8); spotLight->setPosition(0,120,0); spotLight->setDirection(0, -1, 0); spotLight->setDiffuseColour(1,1,1); @@ -470,10 +457,10 @@ spotLight->setType(Light::LT_SPOTLIGHT); spotLight->setAttenuation(200, 1.0f, 0, 0); spotLight->setSpotlightRange(Degree(30.0), Degree(45.0), 0.8); spotLight->setPosition(0,120,0); spotLight->setDirection(0, -1, 0); spotLight->setDiffuseColour(1,1,1); - spotLight->setSpecularColour(1,1,1);*/ + spotLight->setSpecularColour(1,1,1); } }; diff --git a/Samples/DeferredShading/include/SharedData.h b/Samples/DeferredShading/include/SharedData.h --- a/Samples/DeferredShading/include/SharedData.h +++ b/Samples/DeferredShading/include/SharedData.h @@ -16,7 +16,7 @@ #define __SHAREDDATA_H #include -#include "DeferredShading.h" +#include class SharedData : public Ogre::Singleton { @@ -40,7 +40,7 @@ Ogre::Camera *iCamera; Ogre::RenderWindow *iWindow; - DeferredShadingSystem *iSystem; + Ogre::DeferredShadingSystem *iSystem; bool iActivate; bool iGlobalActivate; diff --git a/Samples/DeferredShading/src/DeferredShadingDemo.cpp b/Samples/DeferredShading/src/DeferredShadingDemo.cpp --- a/Samples/DeferredShading/src/DeferredShadingDemo.cpp +++ b/Samples/DeferredShading/src/DeferredShadingDemo.cpp @@ -27,6 +27,7 @@ using namespace Ogre; using namespace OgreBites; +template<> SharedData* Singleton::ms_Singleton = 0; #ifndef OGRE_STATIC_LIB SamplePlugin* sp; diff --git a/Samples/Media/DeferredShadingMedia/ShadowCaster.cg b/Samples/Media/DeferredShadingMedia/ShadowCaster.cg --- a/Samples/Media/DeferredShadingMedia/ShadowCaster.cg +++ b/Samples/Media/DeferredShadingMedia/ShadowCaster.cg @@ -23,3 +23,40 @@ float depth = length(iViewPos) / cFarDistance; oColor.rgba = float4(depth, depth, depth, 1); } + + +void ShadowCasterTextureVP( + float4 iPosition : POSITION, + float2 iTexCoord : TEXCOORD0, + + out float4 oPosition : POSITION, + out float3 oViewPos : TEXCOORD0, + out float2 oTexCoord : TEXCOORD1, + + uniform float4x4 cWorldViewProj, + uniform float4x4 cWorldView + ) +{ + oPosition = mul(cWorldViewProj, iPosition); + oViewPos = mul(cWorldView, iPosition).xyz; + oTexCoord = iTexCoord; +} + +void ShadowCasterAlphaFP( + float3 iViewPos : TEXCOORD0, + float2 iTexCoord : TEXCOORD1, + + out float4 oColor : COLOR0, + + uniform float cFarDistance, + uniform float cRejectAlpha, + uniform sampler2D sAlphaTexture + ) +{ + //check if we have to reject pixel or not + if (tex2D(sAlphaTexture, iTexCoord).a <= cRejectAlpha) + discard; + + float depth = length(iViewPos) / cFarDistance; + oColor.rgba = float4(depth, depth, depth, 1); +} \ No newline at end of file diff --git a/Samples/Media/DeferredShadingMedia/ShadowCaster.material b/Samples/Media/DeferredShadingMedia/ShadowCaster.material --- a/Samples/Media/DeferredShadingMedia/ShadowCaster.material +++ b/Samples/Media/DeferredShadingMedia/ShadowCaster.material @@ -13,3 +13,28 @@ } } } + + +/*Sample of the material that will be used for alpha-rejection casters. This will however be automatically generated instead. */ +material DeferredShading/Shadows/Casters_with_alpha +{ + technique + { + pass + { + vertex_program_ref DeferredShading/Shadows/CasterTextureVP + { + } + + fragment_program_ref DeferredShading/Shadows/CasterAlphaFP + { + param_named cRejectAlpha float 0.5 + } + texture_unit + { + texture_alias alpha_texture + filtering anisotropic + } + } + } +} \ No newline at end of file diff --git a/Samples/Media/DeferredShadingMedia/ShadowCaster.program b/Samples/Media/DeferredShadingMedia/ShadowCaster.program --- a/Samples/Media/DeferredShadingMedia/ShadowCaster.program +++ b/Samples/Media/DeferredShadingMedia/ShadowCaster.program @@ -2,7 +2,7 @@ vertex_program DeferredShading/Shadows/CasterVP cg { source ShadowCaster.cg - profiles vs_1_1 arbvp1 + profiles vs_2_x arbvp1 entry_point ShadowCasterVP default_params { @@ -14,7 +14,7 @@ fragment_program DeferredShading/Shadows/CasterFP cg { source ShadowCaster.cg - profiles ps_2_0 arbfp1 + profiles ps_2_x arbfp1 entry_point ShadowCasterFP default_params @@ -22,3 +22,31 @@ param_named_auto cFarDistance far_clip_distance } } + + +//Vertex program for casters that need their first UV coordinates passed +vertex_program DeferredShading/Shadows/CasterTextureVP cg +{ + source ShadowCaster.cg + profiles vs_2_x arbvp1 + entry_point ShadowCasterTextureVP + default_params + { + param_named_auto cWorldViewProj worldviewproj_matrix + param_named_auto cWorldView worldview_matrix + } +} + +//Fragment program that uses a brightness cutoff +fragment_program DeferredShading/Shadows/CasterAlphaFP cg +{ + source ShadowCaster.cg + profiles ps_2_x arbfp1 + entry_point ShadowCasterAlphaFP + + default_params + { + param_named cRejectAlpha float 0.5 + param_named_auto cFarDistance far_clip_distance + } +} diff --git a/PlugIns/DeferredShading/CMakeLists.txt b/PlugIns/DeferredShading/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/PlugIns/DeferredShading/CMakeLists.txt @@ -0,0 +1,71 @@ +#------------------------------------------------------------------- +# This file is part of the CMake build system for OGRE +# (Object-oriented Graphics Rendering Engine) +# For the latest info, see http://www.ogre3d.org/ +# +# The contents of this file are placed in the public domain. Feel +# free to make use of it in any way you like. +#------------------------------------------------------------------- + + +set (HEADER_FILES + include/OgreDS_AmbientLight.h + include/OgreDS_DeferredLightCP.h + include/OgreDS_DeferredShading.h + include/OgreDS_DLight.h + include/OgreDS_GBufferMaterialGenerator.h + include/OgreDS_GBufferSchemeHandler.h + include/OgreDS_GeomUtils.h + include/OgreDS_LightMaterialGenerator.h + include/OgreDS_ListenerFactoryLogic.h + include/OgreDS_MaterialGenerator.h + include/OgreDS_NullSchemeHandler.h + include/OgreDeferredShadingPlugin.h + include/OgreDeferredShadingManager.h + include/OgreDS_SSAOLogic.h + include/OgreDS_Prerequisites.h +) + +set (SOURCE_FILES + src/OgreDS_AmbientLight.cpp + src/OgreDS_DeferredLightCP.cpp + src/OgreDS_DeferredShading.cpp + src/OgreDS_DLight.cpp + src/OgreDS_GBufferMaterialGenerator.cpp + src/OgreDS_GBufferSchemeHandler.cpp + src/OgreDS_GeomUtils.cpp + src/OgreDS_LightMaterialGenerator.cpp + src/OgreDS_Dll.cpp + src/OgreDS_MaterialGenerator.cpp + src/OgreDeferredShadingPlugin.cpp + src/OgreDeferredShadingManager.cpp + src/OgreDS_SSAOLogic.cpp +) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) +add_definitions(-D_USRDLL) + +add_library(Plugin_DeferredShading ${OGRE_LIB_TYPE} ${HEADER_FILES} ${SOURCE_FILES}) +target_link_libraries(Plugin_DeferredShading OgreMain) +if (NOT OGRE_STATIC) + set_target_properties(Plugin_DeferredShading PROPERTIES + COMPILE_DEFINITIONS OGRE_DSPLUGIN_EXPORTS + ) +endif (NOT OGRE_STATIC) + +if (APPLE AND NOT OGRE_BUILD_PLATFORM_APPLE_IOS) + # Set the INSTALL_PATH so that Plugins can be installed in the application package + set_target_properties(Plugin_DeferredShading + PROPERTIES BUILD_WITH_INSTALL_RPATH 1 + INSTALL_NAME_DIR "@executable_path/../Plugins" + ) + + # Copy headers into the main Ogre framework + add_custom_command(TARGET Plugin_DeferredShading POST_BUILD + COMMAND /Developer/Library/PrivateFrameworks/DevToolsCore.framework/Resources/pbxcp ARGS -exclude .DS_Store -exclude .hg -exclude 'CMakeLists.txt' -resolve-src-symlinks ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h ${OGRE_BINARY_DIR}/lib/$(CONFIGURATION)/Ogre.framework/Headers/ + ) +endif() + +ogre_config_plugin(Plugin_DeferredShading) +install(FILES ${HEADER_FILES} DESTINATION include/OGRE/Plugins/DeferredShading) + diff --git a/PlugIns/DeferredShading/include/OgreDS_AmbientLight.h b/PlugIns/DeferredShading/include/OgreDS_AmbientLight.h new file mode 100644 --- /dev/null +++ b/PlugIns/DeferredShading/include/OgreDS_AmbientLight.h @@ -0,0 +1,57 @@ +/* +----------------------------------------------------------------------------- +This source file is part of OGRE +(Object-oriented Graphics Rendering Engine) +For the latest info, see http://www.ogre3d.org/ + +Copyright (c) 2000-2009 Torus Knot Software Ltd +Also see acknowledgements in Readme.html + +You may use this sample code for anything you like, it is not covered by the +same license as the rest of the engine. +----------------------------------------------------------------------------- +*/ + +#ifndef _OGRE_DEFERREDSHADING_AMBIENTLIGHT_H +#define _OGRE_DEFERREDSHADING_AMBIENTLIGHT_H + +#include "OgreSimpleRenderable.h" +#include "OgreDS_Prerequisites.h" + +namespace Ogre +{ +// Renderable for rendering Ambient component and also to +// establish the depths + +// Just instantiation is sufficient +// Note that instantiation is necessary to at least establish the depths +// even if the current ambient colour is 0 + +// its ambient colour is same as the scene's ambient colour + +// XXX Could make this a singleton/make it private to the DeferredShadingSystem e.g. + +class AmbientLight : public Ogre::SimpleRenderable + +{ +public: + AmbientLight(); + ~AmbientLight(); + + /** @copydoc MovableObject::getBoundingRadius */ + virtual Ogre::Real getBoundingRadius(void) const; + /** @copydoc Renderable::getSquaredViewDepth */ + virtual Ogre::Real getSquaredViewDepth(const Ogre::Camera*) const; + /** @copydoc Renderable::getMaterial */ + virtual const Ogre::MaterialPtr& getMaterial(void) const; + + virtual void getWorldTransforms(Ogre::Matrix4* xform) const; + + void updateFromCamera(Ogre::Camera* camera); +protected: + Ogre::Real mRadius; + Ogre::MaterialPtr mMatPtr; +}; + +} +#endif diff --git a/PlugIns/DeferredShading/include/OgreDS_DLight.h b/PlugIns/DeferredShading/include/OgreDS_DLight.h new file mode 100644 --- /dev/null +++ b/PlugIns/DeferredShading/include/OgreDS_DLight.h @@ -0,0 +1,97 @@ +/* +----------------------------------------------------------------------------- +This source file is part of OGRE +(Object-oriented Graphics Rendering Engine) +For the latest info, see http://www.ogre3d.org/ + +Copyright (c) 2000-2009 Torus Knot Software Ltd +Also see acknowledgements in Readme.html + +You may use this sample code for anything you like, it is not covered by the +same license as the rest of the engine. +----------------------------------------------------------------------------- +*/ + +#ifndef _OGRE_DEFERREDSHADING_DLight +#define _OGRE_DEFERREDSHADING_DLight + +#include "OgreSimpleRenderable.h" +#include "OgreDS_MaterialGenerator.h" + +namespace Ogre +{ + +/** Deferred light geometry. Each instance matches a normal light. + Should not be created by the user. + XXX support other types of light other than point lights. + */ +class DLight: public Ogre::SimpleRenderable +{ +public: + DLight(MaterialGenerator *gen, Ogre::Light* parentLight); + ~DLight(); + + /** Update the information from the light that matches this one + */ + void updateFromParent(); + + /** Update the information that is related to the camera + */ + void updateFromCamera(Ogre::Camera* camera); + + /** Does this light cast shadows? + */ + virtual bool getCastChadows() const; + + /** @copydoc MovableObject::getBoundingRadius */ + virtual Ogre::Real getBoundingRadius(void) const; + /** @copydoc Renderable::getSquaredViewDepth */ + virtual Ogre::Real getSquaredViewDepth(const Ogre::Camera*) const; + /** @copydoc Renderable::getMaterial */ + virtual const Ogre::MaterialPtr& getMaterial(void) const; + /** @copydoc Renderable::getBoundingRadius */ + virtual void getWorldTransforms(Ogre::Matrix4* xform) const; +protected: + + /** Check if the camera is inside a light + */ + bool isCameraInsideLight(Ogre::Camera* camera); + + /** Create geometry for this light. + */ + void rebuildGeometry(float radius); + + /** Create a sphere geometry. + */ + void createSphere(float radius, int nRings, int nSegments); + + /** Create a rectangle. + */ + void createRectangle2D(); + + /** Create a cone. + */ + void createCone(float radius, float height, int nVerticesInBase); + + /** Set constant, linear, quadratic Attenuation terms + */ + void setAttenuation(float c, float b, float a); + + /** Set the specular colour + */ + void setSpecularColour(const Ogre::ColourValue &col); + + /// The light that this DLight renders + Ogre::Light* mParentLight; + /// Mode to ignore world orientation/position + bool bIgnoreWorld; + /// Bounding sphere radius + float mRadius; + /// Deferred shading system this minilight is part of + MaterialGenerator *mGenerator; + /// Material permutation + Ogre::uint32 mPermutation; +}; + +} +#endif diff --git a/PlugIns/DeferredShading/include/OgreDS_DeferredLightCP.h b/PlugIns/DeferredShading/include/OgreDS_DeferredLightCP.h new file mode 100644 --- /dev/null +++ b/PlugIns/DeferredShading/include/OgreDS_DeferredLightCP.h @@ -0,0 +1,81 @@ +/* +----------------------------------------------------------------------------- +This source file is part of OGRE +(Object-oriented Graphics Rendering Engine) +For the latest info, see http://www.ogre3d.org/ + +Copyright (c) 2000-2009 Torus Knot Software Ltd +Also see acknowledgements in Readme.html + +You may use this sample code for anything you like, it is not covered by the +same license as the rest of the engine. +----------------------------------------------------------------------------- +*/ + +#ifndef _OGRE_DEFERREDSHADING_DEFERRED_LIGHT_CP_H +#define _OGRE_DEFERREDSHADING_DEFERRED_LIGHT_CP_H + +#include "OgreCompositorInstance.h" +#include "OgreCustomCompositionPass.h" + +#include "OgreDS_DLight.h" +#include "OgreDS_MaterialGenerator.h" +#include "OgreDS_AmbientLight.h" + +namespace Ogre +{ +//The render operation that will be called each frame in the custom composition pass +//This is the class that will send the actual render calls of the spheres (point lights), +//cones (spotlights) and quads (directional lights) after the GBuffer has been constructed +class DeferredLightRenderOperation : public Ogre::CompositorInstance::RenderSystemOperation +{ +public: + DeferredLightRenderOperation(Ogre::CompositorInstance* instance, const Ogre::CompositionPass* pass); + + /** @copydoc CompositorInstance::RenderSystemOperation::execute */ + virtual void execute(Ogre::SceneManager *sm, Ogre::RenderSystem *rs); + + virtual ~DeferredLightRenderOperation(); +private: + + /** Create a new deferred light + */ + DLight *createDLight(Ogre::Light* light); + + //The texture names of the GBuffer components + Ogre::String mTexName0; + Ogre::String mTexName1; + + //The material generator for the light geometry + MaterialGenerator* mLightMaterialGenerator; + + //The map of deferred light geometries already constructed + typedef std::map LightsMap; + LightsMap mLights; + + //The ambient light used to render the scene + AmbientLight* mAmbientLight; + + //The viewport that we are rendering to + Ogre::Viewport* mViewport; +}; + +//The custom composition pass that is used for rendering the light geometry +//This class needs to be registered with the CompositorManager +class DeferredLightCompositionPass : public Ogre::CustomCompositionPass +{ +public: + + /** @copydoc CustomCompositionPass::createOperation */ + virtual Ogre::CompositorInstance::RenderSystemOperation* createOperation( + Ogre::CompositorInstance* instance, const Ogre::CompositionPass* pass) + { + return OGRE_NEW DeferredLightRenderOperation(instance, pass); + } + +protected: + virtual ~DeferredLightCompositionPass() {} +}; + +} +#endif diff --git a/PlugIns/DeferredShading/include/OgreDS_DeferredShading.h b/PlugIns/DeferredShading/include/OgreDS_DeferredShading.h new file mode 100644 --- /dev/null +++ b/PlugIns/DeferredShading/include/OgreDS_DeferredShading.h @@ -0,0 +1,126 @@ +/* +----------------------------------------------------------------------------- +This source file is part of OGRE +(Object-oriented Graphics Rendering Engine) +For the latest info, see http://www.ogre3d.org/ + +Copyright (c) 2000-2009 Torus Knot Software Ltd +Also see acknowledgements in Readme.html + +You may use this sample code for anything you like, it is not covered by the +same license as the rest of the engine. +----------------------------------------------------------------------------- +*/ + +/** +Implementation of a Deferred Shading engine in OGRE, using Multiple Render Targets and +CG high level language shaders. + // W.J. :wumpus: van der Laan 2005 / Noam Gat 2009 // + +Deferred shading renders the scene to a 'fat' texture format, using a shader that outputs colour, +normal, depth, and possible other attributes per fragment. Multi Render Target is required as we +are dealing with many outputs which get written into multiple render textures in the same pass. + +After rendering the scene in this format, the shading (lighting) can be done as a post process. +This means that lighting is done in screen space, using light-representing geometry (sphere for +point light, cone for spot light and quad for directional) to render their contribution. + +The wiki article explaining this demo can be found here : + http://www.ogre3d.org/wiki/index.php/Deferred_Shading +*/ + +#ifndef _OGRE_DEFERREDSHADING_DeferredShadingSystem +#define _OGRE_DEFERREDSHADING_DeferredShadingSystem + +#include "Ogre.h" +#include "OgreDS_Prerequisites.h" + +#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 +#define WIN32_LEAN_AND_MEAN +#include "windows.h" +#endif + +#include "OgreCompositorInstance.h" +#include "OgreSceneManager.h" +#include "OgreSceneNode.h" +#include "OgreMaterial.h" +#include "OgreRenderTargetListener.h" +#include "OgreDS_GeomUtils.h" + +namespace Ogre +{ + +/** System to manage Deferred Shading for a camera/render target. + * @note With the changes to the compositor framework, this class just + * selects which compositors to enable. + */ +class _OgreDsPluginExport DeferredShadingSystem : public Ogre::RenderTargetListener +{ +public: + DeferredShadingSystem(Ogre::Viewport *vp, Ogre::Camera *cam); + ~DeferredShadingSystem(); + + enum DSMode + { + DSM_SHOWLIT = 0, // The deferred shading mode + DSM_SHOWCOLOUR = 1, // Show diffuse (for debugging) + DSM_SHOWNORMALS = 2, // Show normals (for debugging) + DSM_SHOWDSP = 3, // Show depth and specular channel (for debugging) + DSM_COUNT = 4 + }; + + //The first render queue that does get rendered into the GBuffer + //place objects (like skies) that should be before gbuffer before this one. + static const Ogre::uint8 PRE_GBUFFER_RENDER_QUEUE; + + //The first render queue that does not get rendered into the GBuffer + //place transparent (or other non gbuffer) objects after this one + static const Ogre::uint8 POST_GBUFFER_RENDER_QUEUE; + + void initialize(); + + /** Set rendering mode (one of DSMode) + */ + void setMode(DSMode mode); + + DSMode getMode(void) const; + + /** Set screen space ambient occlusion mode + */ + void setSSAO(bool ssao); + + bool getSSAO() const; + + /** Activate or deactivate system + */ + void setActive(bool active); + +protected: + Ogre::Viewport *mViewport; + Ogre::Camera *mCamera; + + Ogre::CompositorInstance *mGBufferInstance; + // Filters + Ogre::CompositorInstance *mInstance[DSM_COUNT]; + Ogre::CompositorInstance* mSSAOInstance; + // Active/inactive + bool mActive; + DSMode mCurrentMode; + bool mSSAO; + + //Used to unregister compositor logics and free memory + typedef map::type CompositorLogicMap; + CompositorLogicMap mCompositorLogics; + + void createResources(); + + void logCurrentMode(void); +}; + +const ColourValue SAMPLE_COLORS[] = +{ ColourValue::Red, ColourValue::Green, ColourValue::Blue, + ColourValue::White, ColourValue(1,1,0,1), ColourValue(1,0,1,1) +}; + +} +#endif diff --git a/PlugIns/DeferredShading/include/OgreDS_GBufferMaterialGenerator.h b/PlugIns/DeferredShading/include/OgreDS_GBufferMaterialGenerator.h new file mode 100644 --- /dev/null +++ b/PlugIns/DeferredShading/include/OgreDS_GBufferMaterialGenerator.h @@ -0,0 +1,75 @@ +/* +----------------------------------------------------------------------------- +This source file is part of OGRE +(Object-oriented Graphics Rendering Engine) +For the latest info, see http://www.ogre3d.org/ + +Copyright (c) 2000-2009 Torus Knot Software Ltd +Also see acknowledgements in Readme.html + +You may use this sample code for anything you like, it is not covered by the +same license as the rest of the engine. +----------------------------------------------------------------------------- +*/ + + +#ifndef _OGRE_DEFERREDSHADING_GBUFFER_MATERIAL_GENERATOR_H_ +#define _OGRE_DEFERREDSHADING_GBUFFER_MATERIAL_GENERATOR_H_ + +#include "OgreDS_MaterialGenerator.h" + +namespace Ogre +{ + +/** Class for generating materials for objects to render themselves to the GBuffer + * @note This does not support all the possible rendering techniques out there. + * in order to support more, either expand this class or make sure that objects + * that will not get treated correctly will not have materials generated for them. + */ +class GBufferMaterialGenerator : public MaterialGenerator +{ +public: + + //Constructor + GBufferMaterialGenerator(); + + //The relevant options for objects that are rendered to the GBuffer + enum GBufferPermutations + { + //(Regular) Textures + GBP_NO_TEXTURES = 0x00000000, + GBP_ONE_TEXTURE = 0x00000001, + GBP_TWO_TEXTURES = 0x00000002, + GBP_THREE_TEXTURES = 0x00000003, + GBP_TEXTURE_MASK = 0x0000000F, + + //Material properties + GBP_HAS_DIFFUSE_COLOUR = 0x00000010, + + //The number of texture coordinate sets + GBP_NO_TEXCOORDS = 0x00000000, + GBP_ONE_TEXCOORD = 0x00000100, + GBP_TWO_TEXCOORDS = 0x00000200, + GBP_TEXCOORD_MASK = 0x00000700, + + //Do we have a normal map + GBP_NORMAL_MAP = 0x00000800, + + //Do we use alpha rejection combined with a texture? + GBP_ALPHA_REJECTION = 0x00001000, + //Are we skinned? + GBP_SKINNED = 0x00010000 + }; + + //The mask of the flags that matter for generating the fragment shader + static const Ogre::uint32 FS_MASK = 0x0000FFFF; + + //The mask of the flags that matter for generating the vertex shader + static const Ogre::uint32 VS_MASK = 0x00FFFF00; + + //The mask of the flags that matter for generating the material + static const Ogre::uint32 MAT_MASK = 0xFF00FFFF; +}; + +} +#endif diff --git a/PlugIns/DeferredShading/include/OgreDS_GBufferSchemeHandler.h b/PlugIns/DeferredShading/include/OgreDS_GBufferSchemeHandler.h new file mode 100644 --- /dev/null +++ b/PlugIns/DeferredShading/include/OgreDS_GBufferSchemeHandler.h @@ -0,0 +1,80 @@ +/* +----------------------------------------------------------------------------- +This source file is part of OGRE +(Object-oriented Graphics Rendering Engine) +For the latest info, see http://www.ogre3d.org/ + +Copyright (c) 2000-2009 Torus Knot Software Ltd +Also see acknowledgements in Readme.html + +You may use this sample code for anything you like, it is not covered by the +same license as the rest of the engine. +----------------------------------------------------------------------------- +*/ + + +#ifndef _OGRE_DEFERREDSHADING_GBUFFERSCHEMEHANDLER_H +#define _OGRE_DEFERREDSHADING_GBUFFERSCHEMEHANDLER_H + +#include +#include "OgreDS_GBufferMaterialGenerator.h" + +namespace Ogre +{ + +/** Class for handling materials who did not specify techniques for rendering + * themselves into the GBuffer. This class allows deferred shading to be used, + * without having to specify new techniques for all the objects in the scene. + * @note This does not support all the possible rendering techniques out there. + * in order to support more, either expand this class or specify the techniques + * in the materials. + */ +class GBufferSchemeHandler : public Ogre::MaterialManager::Listener +{ +public: + /** @copydoc MaterialManager::Listener::handleSchemeNotFound */ + virtual Ogre::Technique* handleSchemeNotFound(unsigned short schemeIndex, + const Ogre::String& schemeName, Ogre::Material* originalMaterial, unsigned short lodIndex, + const Ogre::Renderable* rend); +protected: + //The material generator + GBufferMaterialGenerator mMaterialGenerator; + + //The string that will be checked in textures to determine whether they are normal maps + static const Ogre::String NORMAL_MAP_PATTERN; + + //A structure for containing the properties of a material, relevant to GBuffer rendering + //You might need to expand this class to support more options + struct PassProperties + { + PassProperties() : isDeferred(true), normalMap(0), isSkinned(false), alphaRejectionTexture(0) {} + + bool isDeferred; + Ogre::vector::type regularTextures; + Ogre::TextureUnitState* normalMap; + bool isSkinned; + Ogre::TextureUnitState* alphaRejectionTexture; + bool hasDiffuseColour; + + //Example of possible extension : vertex colours + //Ogre::TrackVertexColourType vertexColourType; + }; + + //Inspect a technique and return its relevant properties + PassProperties inspectPass(Ogre::Pass* pass, + unsigned short lodIndex, const Ogre::Renderable* rend); + + //Get the permutation of material flags that fit a certain property sheet + MaterialGenerator::Perm getPermutation(const PassProperties& props); + + //Fill a pass with the specific data from the pass it is based on + void fillPass(Ogre::Pass* gBufferPass, Ogre::Pass* originalPass, const PassProperties& props); + + //Check if a texture is a normal map, and fill property sheet accordingly + bool checkNormalMap(Ogre::TextureUnitState* tus, PassProperties& props); + //Check if a texture might be the alpha_rejection texture, and fill property sheet accordingly + bool checkRejectionTexture(Ogre::TextureUnitState* tus, PassProperties& props); +}; + +} +#endif diff --git a/PlugIns/DeferredShading/include/OgreDS_GeomUtils.h b/PlugIns/DeferredShading/include/OgreDS_GeomUtils.h new file mode 100644 --- /dev/null +++ b/PlugIns/DeferredShading/include/OgreDS_GeomUtils.h @@ -0,0 +1,65 @@ +/* +----------------------------------------------------------------------------- +This source file is part of OGRE +(Object-oriented Graphics Rendering Engine) +For the latest info, see http://www.ogre3d.org/ + +Copyright (c) 2000-2009 Torus Knot Software Ltd +Also see acknowledgements in Readme.html + +You may use this sample code for anything you like, it is not covered by the +same license as the rest of the engine. +----------------------------------------------------------------------------- +*/ + +#ifndef _OGRE_DEFERREDSHADING_GEOMUTILS_H +#define _OGRE_DEFERREDSHADING_GEOMUTILS_H + +#include "OgreString.h" +#include "OgreVertexIndexData.h" + +namespace Ogre +{ + +class GeomUtils +{ +public: + // Create a sphere Mesh with a given name, radius, number of rings and number of segments + static void createSphere(const Ogre::String& strName + , float radius + , int nRings, int nSegments + , bool bNormals + , bool bTexCoords + ); + + + // Fill up a fresh copy of VertexData and IndexData with a sphere's coords given the number of rings and the number of segments + static void createSphere(Ogre::VertexData*& vertexData, Ogre::IndexData*& indexData + , float radius + , int nRings, int nSegments + , bool bNormals + , bool bTexCoords); + + // Create a cone Mesh with a given name, radius and number of vertices in base + // Created cone will have its head at 0,0,0, and will 'expand to' positive y + static void createCone(const Ogre::String& strName + , float radius + , float height + , int nVerticesInBase); + + // Fill up a fresh copy of VertexData and IndexData with a cone's coords given the radius and number of vertices in base + static void createCone(Ogre::VertexData*& vertexData, Ogre::IndexData*& indexData + , float radius + , float height + , int nVerticesInBase); + + + // Fill up a fresh copy of VertexData with a normalized quad + static void createQuad(Ogre::VertexData*& vertexData); + + +}; + + +} +#endif diff --git a/PlugIns/DeferredShading/include/OgreDS_LightMaterialGenerator.h b/PlugIns/DeferredShading/include/OgreDS_LightMaterialGenerator.h new file mode 100644 --- /dev/null +++ b/PlugIns/DeferredShading/include/OgreDS_LightMaterialGenerator.h @@ -0,0 +1,44 @@ +/* +----------------------------------------------------------------------------- +This source file is part of OGRE +(Object-oriented Graphics Rendering Engine) +For the latest info, see http://www.ogre3d.org/ + +Copyright (c) 2000-2009 Torus Knot Software Ltd +Also see acknowledgements in Readme.html + +You may use this sample code for anything you like, it is not covered by the +same license as the rest of the engine. +----------------------------------------------------------------------------- +*/ + +#ifndef _OGRE_DEFERREDSHADING_LightMaterialGenerator +#define _OGRE_DEFERREDSHADING_LightMaterialGenerator + +#include "OgreDS_MaterialGenerator.h" + +namespace Ogre +{ + +class LightMaterialGenerator: public MaterialGenerator +{ +public: + /** Permutation of light materials + */ + enum MaterialID + { + MI_POINT = 0x01, // Is a point light + MI_SPOTLIGHT = 0x02, // Is a spot light + MI_DIRECTIONAL = 0x04, // Is a directional light + + MI_ATTENUATED = 0x08, // Rendered attenuated + MI_SPECULAR = 0x10, // Specular component is calculated + MI_SHADOW_CASTER = 0x20 // Will cast shadows + }; + + LightMaterialGenerator(); + virtual ~LightMaterialGenerator(); +}; + +} +#endif diff --git a/PlugIns/DeferredShading/include/OgreDS_ListenerFactoryLogic.h b/PlugIns/DeferredShading/include/OgreDS_ListenerFactoryLogic.h new file mode 100644 --- /dev/null +++ b/PlugIns/DeferredShading/include/OgreDS_ListenerFactoryLogic.h @@ -0,0 +1,55 @@ +/* +----------------------------------------------------------------------------- +This source file is part of OGRE +(Object-oriented Graphics Rendering Engine) +For the latest info, see http://www.ogre3d.org/ + +Copyright (c) 2000-2006 Torus Knot Software Ltd +Also see acknowledgements in Readme.html + +You may use this sample code for anything you like, it is not covered by the +conditions of the standard open source license. +----------------------------------------------------------------------------- +*/ + +#ifndef _OGRE_DEFERREDSHADING_LISTENER_FACTORY_LOGIC_H +#define _OGRE_DEFERREDSHADING_LISTENER_FACTORY_LOGIC_H + +#include +#include +#include + +namespace Ogre +{ + +//The simple types of compositor logics will all do the same thing - +//Attach a listener to the created compositor +class ListenerFactoryLogic : public Ogre::CompositorLogic +{ +public: + /** @copydoc CompositorLogic::compositorInstanceCreated */ + virtual void compositorInstanceCreated(Ogre::CompositorInstance* newInstance) + { + Ogre::CompositorInstance::Listener* listener = createListener(newInstance); + newInstance->addListener(listener); + mListeners[newInstance] = listener; + } + + /** @copydoc CompositorLogic::compositorInstanceDestroyed */ + virtual void compositorInstanceDestroyed(Ogre::CompositorInstance* destroyedInstance) + { + delete mListeners[destroyedInstance]; + mListeners.erase(destroyedInstance); + } + +protected: + //This is the method that implementers will need to create + virtual Ogre::CompositorInstance::Listener* createListener(Ogre::CompositorInstance* instance) = 0; +private: + typedef std::map ListenerMap; + ListenerMap mListeners; + +}; + +} +#endif diff --git a/PlugIns/DeferredShading/include/OgreDS_MaterialGenerator.h b/PlugIns/DeferredShading/include/OgreDS_MaterialGenerator.h new file mode 100644 --- /dev/null +++ b/PlugIns/DeferredShading/include/OgreDS_MaterialGenerator.h @@ -0,0 +1,86 @@ +/* +----------------------------------------------------------------------------- +This source file is part of OGRE +(Object-oriented Graphics Rendering Engine) +For the latest info, see http://www.ogre3d.org/ + +Copyright (c) 2000-2009 Torus Knot Software Ltd +Also see acknowledgements in Readme.html + +You may use this sample code for anything you like, it is not covered by the +same license as the rest of the engine. +----------------------------------------------------------------------------- +*/ + +#ifndef _OGRE_DEFERREDSHADING_MaterialGenerator +#define _OGRE_DEFERREDSHADING_MaterialGenerator + +#include "OgreMaterial.h" +#include "OgreStringVector.h" + +namespace Ogre +{ + +/** Caching, on-the-fly material generator. This is a class that automatically + generates and stores different permutations of a material, and its shaders. + It can be used if you have a material that has lots of slightly different + variations, like whether to use a specular light, skinning, normal mapping + and other options. Writing all these out is a tedious job. Of course it is + possible to always use the material with all features, but that might result + in large, slow shader programs. This class provides an efficient solution + to that. + */ +class MaterialGenerator +{ +public: + /** Bitfield used to signify a material permutations */ + typedef Ogre::uint32 Perm; + virtual ~MaterialGenerator(); + + const Ogre::MaterialPtr &getMaterial(Perm permutation); + + /** Implementation class that takes care of actual generation or lookup + of the various constituent parts (template material, fragment shader + and vertex shader). These methods are only called once for every permutation, + after which the result is stored and re-used. + */ + class Impl + { + public: + virtual ~Impl(); + virtual Ogre::GpuProgramPtr generateVertexShader(Perm permutation) = 0; + virtual Ogre::GpuProgramPtr generateFragmentShader(Perm permutation) = 0; + virtual Ogre::MaterialPtr generateTemplateMaterial(Perm permutation) = 0; + }; +protected: + /** The constructor is protected as this base class should never be constructed + as-is. It is meant to be subclassed so that values can be assigned to + the various fields controlling material generator, and most importantly, the + mImpl field. + */ + MaterialGenerator(); + + const Ogre::GpuProgramPtr &getVertexShader(Perm permutation); + const Ogre::GpuProgramPtr &getFragmentShader(Perm permutation); + const Ogre::MaterialPtr &getTemplateMaterial(Perm permutation); + + /// Base name of materials generated by this + Ogre::String materialBaseName; + /// Mask of permutation bits that influence vertex shader choice + Perm vsMask; + /// Mask of permutation bits that influence fragment shader choice + Perm fsMask; + /// Mask of permutation bits that influence template material choice + Perm matMask; + /// Generator + Impl *mImpl; + + typedef Ogre::map::type ProgramMap; + typedef Ogre::map::type MaterialMap; + + ProgramMap mVs, mFs; + MaterialMap mTemplateMat, mMaterials; +}; + +} +#endif diff --git a/PlugIns/DeferredShading/include/OgreDS_NullSchemeHandler.h b/PlugIns/DeferredShading/include/OgreDS_NullSchemeHandler.h new file mode 100644 --- /dev/null +++ b/PlugIns/DeferredShading/include/OgreDS_NullSchemeHandler.h @@ -0,0 +1,46 @@ +/* +----------------------------------------------------------------------------- +This source file is part of OGRE +(Object-oriented Graphics Rendering Engine) +For the latest info, see http://www.ogre3d.org/ + +Copyright (c) 2000-2009 Torus Knot Software Ltd +Also see acknowledgements in Readme.html + +You may use this sample code for anything you like, it is not covered by the +same license as the rest of the engine. +----------------------------------------------------------------------------- +*/ + +#ifndef _OGRE_DEFERREDSHADING_NULLSCHEMEHANDLER_H +#define _OGRE_DEFERREDSHADING_NULLSCHEMEHANDLER_H + +#include + +namespace Ogre +{ + +/** Class for skipping materials which do not have the scheme defined + */ +class NullSchemeHandler : public Ogre::MaterialManager::Listener +{ +public: + /** @copydoc MaterialManager::Listener::handleSchemeNotFound */ + virtual Ogre::Technique* handleSchemeNotFound(unsigned short schemeIndex, + const Ogre::String& schemeName, Ogre::Material* originalMaterial, unsigned short lodIndex, + const Ogre::Renderable* rend) + { + Ogre::LogManager::getSingleton().logMessage("Creating null material for " + originalMaterial->getName()); + //Creating a technique so the handler only gets called once per material + Ogre::Technique* emptyTech = originalMaterial->createTechnique(); + emptyTech->removeAllPasses(); + emptyTech->setSchemeName(schemeName); + Pass* newPass = emptyTech->createPass(); + newPass->setDiffuse(ColourValue::Red); + newPass->setAmbient(ColourValue::Red); + return emptyTech; + } +}; + +} +#endif diff --git a/PlugIns/DeferredShading/include/OgreDS_Prerequisites.h b/PlugIns/DeferredShading/include/OgreDS_Prerequisites.h new file mode 100644 --- /dev/null +++ b/PlugIns/DeferredShading/include/OgreDS_Prerequisites.h @@ -0,0 +1,37 @@ +/* +----------------------------------------------------------------------------- +This source file is part of OGRE +(Object-oriented Graphics Rendering Engine) +For the latest info, see http://www.ogre3d.org/ + +Copyright (c) 2000-2009 Torus Knot Software Ltd +Also see acknowledgements in Readme.html + +You may use this sample code for anything you like, it is not covered by the +same license as the rest of the engine. +----------------------------------------------------------------------------- +*/ + +#ifndef _OGRE_DEFERREDSHADING_Prerequisites_H__ +#define _OGRE_DEFERREDSHADING_Prerequisites_H__ + +#include "OgrePrerequisites.h" + +#if (OGRE_PLATFORM == OGRE_PLATFORM_WIN32) && !defined(__MINGW32__) && !defined(OGRE_STATIC_LIB) +# ifdef OGRE_DSPLUGIN_EXPORTS +# define _OgreDsPluginExport __declspec(dllexport) +# else +# if defined( __MINGW32__ ) +# define _OgreDsPluginExport +# else +# define _OgreDsPluginExport __declspec(dllimport) +# endif +# endif +#elif defined ( OGRE_GCC_VISIBILITY ) +# define _OgreDsPluginExport __attribute__ ((visibility("default"))) +#else +# define _OgreDsPluginExport +#endif // OGRE_WIN32 + + +#endif diff --git a/PlugIns/DeferredShading/include/OgreDS_SSAOLogic.h b/PlugIns/DeferredShading/include/OgreDS_SSAOLogic.h new file mode 100644 --- /dev/null +++ b/PlugIns/DeferredShading/include/OgreDS_SSAOLogic.h @@ -0,0 +1,31 @@ +/* +----------------------------------------------------------------------------- +This source file is part of OGRE +(Object-oriented Graphics Rendering Engine) +For the latest info, see http://www.ogre3d.org/ + +Copyright (c) 2000-2009 Torus Knot Software Ltd +Also see acknowledgements in Readme.html + +You may use this sample code for anything you like, it is not covered by the +same license as the rest of the engine. +----------------------------------------------------------------------------- +*/ + +#ifndef _OGRE_DEFERREDSHADING_SSAOLOGIC_H +#define _OGRE_DEFERREDSHADING_SSAOLOGIC_H + +#include "OgreDS_ListenerFactoryLogic.h" + +namespace Ogre +{ + +class SSAOLogic : public ListenerFactoryLogic +{ +protected: + /** @copydoc ListenerFactoryLogic::createListener */ + virtual Ogre::CompositorInstance::Listener* createListener(Ogre::CompositorInstance* instance); +}; + +} +#endif diff --git a/PlugIns/DeferredShading/include/OgreDeferredShadingManager.h b/PlugIns/DeferredShading/include/OgreDeferredShadingManager.h new file mode 100644 --- /dev/null +++ b/PlugIns/DeferredShading/include/OgreDeferredShadingManager.h @@ -0,0 +1,55 @@ +/* +----------------------------------------------------------------------------- +This source file is part of OGRE +(Object-oriented Graphics Rendering Engine) +For the latest info, see http://www.ogre3d.org/ + +Copyright (c) 2000-2009 Torus Knot Software Ltd +Also see acknowledgements in Readme.html + +You may use this sample code for anything you like, it is not covered by the +same license as the rest of the engine. +----------------------------------------------------------------------------- +*/ + +#ifndef _OGRE_DEFERREDSHADING_DEFERREDSHADINGMANAGER_H_ +#define _OGRE_DEFERREDSHADING_DEFERREDSHADINGMANAGER_H_ + +#include +#include +#include +#include "OgreDS_Prerequisites.h" + +namespace Ogre { +class GBufferSchemeHandler; +class NullSchemeHandler; +class DeferredLightCompositionPass; + +class _OgreDsPluginExport DeferredShadingManager : public Singleton{ +protected: + HashedVector mSceneManagers; + DeferredLightCompositionPass* mDeferredLightCompositionPass; + GBufferSchemeHandler* mGBufferSchemeHandler; + NullSchemeHandler* mNullSchemeHandler; + String mDefaultMaterialSchemeName; +public: + + DeferredShadingManager(); + + /** + * Set the name of the materialscheme on which the automatically generated deferred materials should be based. + */ + void setDefaultMaterialSchemeName(const String& defaultMaterialSchemeName){mDefaultMaterialSchemeName = defaultMaterialSchemeName;} + const String& getDefaultMaterialSchemeName() const{return mDefaultMaterialSchemeName;} + + void addSceneManager(SceneManager* sm); + void removeSceneManager(SceneManager* sm); + virtual ~DeferredShadingManager(); + + static DeferredShadingManager* getSingletonPtr(void); + static DeferredShadingManager& getSingleton(void); +}; + +} + +#endif /* OGREDEFERREDSHADINGMANAGER_H_ */ diff --git a/PlugIns/DeferredShading/include/OgreDeferredShadingPlugin.h b/PlugIns/DeferredShading/include/OgreDeferredShadingPlugin.h new file mode 100644 --- /dev/null +++ b/PlugIns/DeferredShading/include/OgreDeferredShadingPlugin.h @@ -0,0 +1,49 @@ +/* +----------------------------------------------------------------------------- +This source file is part of OGRE +(Object-oriented Graphics Rendering Engine) +For the latest info, see http://www.ogre3d.org/ + +Copyright (c) 2000-2009 Torus Knot Software Ltd +Also see acknowledgements in Readme.html + +You may use this sample code for anything you like, it is not covered by the +same license as the rest of the engine. +----------------------------------------------------------------------------- +*/ + +#ifndef _OGRE_DEFERREDSHADING_DeferredShadingPlugin_H__ +#define _OGRE_DEFERREDSHADING_DeferredShadingPlugin_H__ + +#include "OgrePlugin.h" +#include "OgreDS_Prerequisites.h" +#include "OgreDeferredShadingManager.h" + +namespace Ogre +{ + /** Plugin instance for Deferred Shading technique*/ + class DeferredShadingPlugin : public Plugin + { + public: + DeferredShadingPlugin(); + + /// @copydoc Plugin::getName + const String& getName() const; + + /// @copydoc Plugin::install + void install(); + + /// @copydoc Plugin::initialise + void initialise(); + + /// @copydoc Plugin::shutdown + void shutdown(); + + /// @copydoc Plugin::uninstall + void uninstall(); + protected: + DeferredShadingManager* manager; + }; +} + +#endif diff --git a/PlugIns/DeferredShading/src/OgreDS_AmbientLight.cpp b/PlugIns/DeferredShading/src/OgreDS_AmbientLight.cpp new file mode 100644 --- /dev/null +++ b/PlugIns/DeferredShading/src/OgreDS_AmbientLight.cpp @@ -0,0 +1,100 @@ +/* +----------------------------------------------------------------------------- +This source file is part of OGRE +(Object-oriented Graphics Rendering Engine) +For the latest info, see http://www.ogre3d.org/ + +Copyright (c) 2000-2009 Torus Knot Software Ltd +Also see acknowledgements in Readme.html + +You may use this sample code for anything you like, it is not covered by the +same license as the rest of the engine. +----------------------------------------------------------------------------- +*/ + + +#include "OgreDS_AmbientLight.h" +#include "OgreDS_GeomUtils.h" +#include "OgreMaterialManager.h" +#include "OgreRoot.h" +#include "OgreRenderSystem.h" + +namespace Ogre +{ + +AmbientLight::AmbientLight() +{ + setRenderQueueGroup(RENDER_QUEUE_2); + + mRenderOp.vertexData = new VertexData(); + mRenderOp.indexData = 0; + + GeomUtils::createQuad(mRenderOp.vertexData); + + mRenderOp.operationType = RenderOperation::OT_TRIANGLE_STRIP; + mRenderOp.useIndexes = false; + + // Set bounding + setBoundingBox(AxisAlignedBox(-10000,-10000,-10000,10000,10000,10000)); + mRadius = 15000; + + mMatPtr = MaterialManager::getSingleton().getByName("DeferredShading/AmbientLight"); + assert(mMatPtr.isNull()==false); + mMatPtr->load(); + + //This shader needs to be aware if its running under OpenGL or DirectX. + //Real depthFactor = (Root::getSingleton().getRenderSystem()->getName() == + // "OpenGL Rendering Subsystem") ? 2.0 : 1.0; + //mMatPtr->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant( + // "depthFactor", depthFactor); +} + +AmbientLight::~AmbientLight() +{ + // need to release IndexData and vertexData created for renderable + delete mRenderOp.indexData; + delete mRenderOp.vertexData; +} + +/** @copydoc MovableObject::getBoundingRadius */ +Real AmbientLight::getBoundingRadius(void) const +{ + return mRadius; + +} +/** @copydoc Renderable::getSquaredViewDepth */ +Real AmbientLight::getSquaredViewDepth(const Camera*) const +{ + return 0.0; +} + +const MaterialPtr& AmbientLight::getMaterial(void) const +{ + return mMatPtr; +} + +void AmbientLight::getWorldTransforms(Ogre::Matrix4* xform) const +{ + *xform = Matrix4::IDENTITY; +} +void AmbientLight::updateFromCamera(Ogre::Camera* camera) +{ + Ogre::Technique* tech = getMaterial()->getBestTechnique(); + Ogre::Vector3 farCorner = camera->getViewMatrix(true) * camera->getWorldSpaceCorners()[4]; + + for (unsigned short i=0; igetNumPasses(); i++) + { + Ogre::Pass* pass = tech->getPass(i); + // get the vertex shader parameters + Ogre::GpuProgramParametersSharedPtr params = pass->getVertexProgramParameters(); + // set the camera's far-top-right corner + if (params->_findNamedConstantDefinition("farCorner")) + params->setNamedConstant("farCorner", farCorner); + + params = pass->getFragmentProgramParameters(); + if (params->_findNamedConstantDefinition("farCorner")) + params->setNamedConstant("farCorner", farCorner); + } +} + +} diff --git a/PlugIns/DeferredShading/src/OgreDS_DLight.cpp b/PlugIns/DeferredShading/src/OgreDS_DLight.cpp new file mode 100644 --- /dev/null +++ b/PlugIns/DeferredShading/src/OgreDS_DLight.cpp @@ -0,0 +1,356 @@ +/* +----------------------------------------------------------------------------- +This source file is part of OGRE +(Object-oriented Graphics Rendering Engine) +For the latest info, see http://www.ogre3d.org/ + +Copyright (c) 2000-2009 Torus Knot Software Ltd +Also see acknowledgements in Readme.html + +You may use this sample code for anything you like, it is not covered by the +same license as the rest of the engine. +----------------------------------------------------------------------------- +*/ + +#include "OgreDS_DLight.h" + +#include "OgreHardwareBufferManager.h" +#include "OgreCamera.h" +#include "OgreSceneNode.h" +#include "OgreLight.h" +#include "OgreDS_GeomUtils.h" +#include "OgreDS_LightMaterialGenerator.h" +#include "OgreTechnique.h" +#include "OgreSceneManager.h" + +#define ENABLE_BIT(mask, flag) (mask) |= (flag) +#define DISABLE_BIT(mask, flag) (mask) &= ~(flag) + +namespace Ogre +{ + + +//----------------------------------------------------------------------- +DLight::DLight(MaterialGenerator *sys, Ogre::Light* parentLight): + mParentLight(parentLight), bIgnoreWorld(false), mGenerator(sys), mPermutation(0) +{ + // Set up geometry + // Allocate render operation + mRenderOp.operationType = RenderOperation::OT_TRIANGLE_LIST; + mRenderOp.indexData = 0; + mRenderOp.vertexData = 0; + mRenderOp.useIndexes = true; + + updateFromParent(); +} +//----------------------------------------------------------------------- +DLight::~DLight() +{ + // need to release IndexData and vertexData created for renderable + delete mRenderOp.indexData; + delete mRenderOp.vertexData; +} +//----------------------------------------------------------------------- +void DLight::setAttenuation(float c, float b, float a) +{ + // Set Attenuation parameter to shader + //setCustomParameter(3, Vector4(c, b, a, 0)); + float outerRadius = mParentLight->getAttenuationRange(); + /// There is attenuation? Set material accordingly + if(c != 1.0f || b != 0.0f || a != 0.0f) + { + ENABLE_BIT(mPermutation, LightMaterialGenerator::MI_ATTENUATED); + if (mParentLight->getType() == Light::LT_POINT) + { + //// Calculate radius from Attenuation + int threshold_level = 10;// difference of 10-15 levels deemed unnoticeable + float threshold = 1.0f/((float)threshold_level/256.0f); + + //// Use quadratic formula to determine outer radius + c = c-threshold; + float d=sqrt(b*b-4*a*c); + outerRadius = (-2*c)/(b+d); + outerRadius *= 1.2; + } + } + else + { + DISABLE_BIT(mPermutation,LightMaterialGenerator::MI_ATTENUATED); + } + + rebuildGeometry(outerRadius); +} +//----------------------------------------------------------------------- +void DLight::setSpecularColour(const ColourValue &col) +{ + //setCustomParameter(2, Vector4(col.r, col.g, col.b, col.a)); + /// There is a specular component? Set material accordingly + + if(col.r != 0.0f || col.g != 0.0f || col.b != 0.0f) + ENABLE_BIT(mPermutation,LightMaterialGenerator::MI_SPECULAR); + else + DISABLE_BIT(mPermutation,LightMaterialGenerator::MI_SPECULAR); + +} +//----------------------------------------------------------------------- +void DLight::rebuildGeometry(float radius) +{ + //Disable all 3 bits + DISABLE_BIT(mPermutation, LightMaterialGenerator::MI_POINT); + DISABLE_BIT(mPermutation, LightMaterialGenerator::MI_SPOTLIGHT); + DISABLE_BIT(mPermutation, LightMaterialGenerator::MI_DIRECTIONAL); + + switch (mParentLight->getType()) + { + case Light::LT_DIRECTIONAL: + createRectangle2D(); + ENABLE_BIT(mPermutation,LightMaterialGenerator::MI_DIRECTIONAL); + break; + case Light::LT_POINT: + /// XXX some more intelligent expression for rings and segments + createSphere(radius, 10, 10); + ENABLE_BIT(mPermutation,LightMaterialGenerator::MI_POINT); + break; + case Light::LT_SPOTLIGHT: + Real height = mParentLight->getAttenuationRange(); + Radian coneRadiusAngle = mParentLight->getSpotlightOuterAngle() / 2; + Real rad = Math::Tan(coneRadiusAngle) * height; + createCone(rad, height, 20); + ENABLE_BIT(mPermutation,LightMaterialGenerator::MI_SPOTLIGHT); + break; + } +} +//----------------------------------------------------------------------- +void DLight::createRectangle2D() +{ + /// XXX this RenderOp should really be re-used between DLight objects, + /// not generated every time + delete mRenderOp.vertexData; + delete mRenderOp.indexData; + + mRenderOp.vertexData = new VertexData(); + mRenderOp.indexData = 0; + + GeomUtils::createQuad(mRenderOp.vertexData); + + mRenderOp.operationType = RenderOperation::OT_TRIANGLE_STRIP; + mRenderOp.useIndexes = false; + + // Set bounding + setBoundingBox(AxisAlignedBox(-10000,-10000,-10000,10000,10000,10000)); + mRadius = 15000; + bIgnoreWorld = true; +} +//----------------------------------------------------------------------- +void DLight::createSphere(float radius, int nRings, int nSegments) +{ + delete mRenderOp.vertexData; + delete mRenderOp.indexData; + mRenderOp.operationType = RenderOperation::OT_TRIANGLE_LIST; + mRenderOp.indexData = new IndexData(); + mRenderOp.vertexData = new VertexData(); + mRenderOp.useIndexes = true; + + GeomUtils::createSphere(mRenderOp.vertexData, mRenderOp.indexData + , radius + , nRings, nSegments + , false // no normals + , false // no texture coordinates + ); + + // Set bounding box and sphere + setBoundingBox( AxisAlignedBox( Vector3(-radius, -radius, -radius), Vector3(radius, radius, radius) ) ); + mRadius = radius; + bIgnoreWorld = false; +} +//----------------------------------------------------------------------- +void DLight::createCone(float radius, float height, int nVerticesInBase) +{ + delete mRenderOp.vertexData; + delete mRenderOp.indexData; + mRenderOp.operationType = RenderOperation::OT_TRIANGLE_LIST; + mRenderOp.indexData = new IndexData(); + mRenderOp.vertexData = new VertexData(); + mRenderOp.useIndexes = true; + + GeomUtils::createCone(mRenderOp.vertexData, mRenderOp.indexData + , radius + , height, nVerticesInBase); + + // Set bounding box and sphere + setBoundingBox( AxisAlignedBox( + Vector3(-radius, 0, -radius), + Vector3(radius, height, radius) ) ); + + mRadius = radius; + bIgnoreWorld = false; +} +//----------------------------------------------------------------------- +Real DLight::getBoundingRadius(void) const +{ + return mRadius; +} +//----------------------------------------------------------------------- +Real DLight::getSquaredViewDepth(const Camera* cam) const +{ + if(bIgnoreWorld) + { + return 0.0f; + } + else + { + Vector3 dist = cam->getDerivedPosition() - getParentSceneNode()->_getDerivedPosition(); + return dist.squaredLength(); + } +} +//----------------------------------------------------------------------- +const MaterialPtr& DLight::getMaterial(void) const +{ + return mGenerator->getMaterial(mPermutation); +} +//----------------------------------------------------------------------- +void DLight::getWorldTransforms(Matrix4* xform) const +{ + if (mParentLight->getType() == Light::LT_SPOTLIGHT) + { + Quaternion quat = Vector3::UNIT_Y.getRotationTo(mParentLight->getDerivedDirection()); + xform->makeTransform(mParentLight->getDerivedPosition(), + Vector3::UNIT_SCALE, quat); + } + else + { + xform->makeTransform(mParentLight->getDerivedPosition(), + Vector3::UNIT_SCALE, Quaternion::IDENTITY); + } + +} +//----------------------------------------------------------------------- +void DLight::updateFromParent() +{ + //TODO : Don't do this unless something changed + setAttenuation(mParentLight->getAttenuationConstant(), + mParentLight->getAttenuationLinear(), mParentLight->getAttenuationQuadric()); + setSpecularColour(mParentLight->getSpecularColour()); + + if (getCastChadows()) + { + ENABLE_BIT(mPermutation,LightMaterialGenerator::MI_SHADOW_CASTER); + } + else + { + DISABLE_BIT(mPermutation, LightMaterialGenerator::MI_SHADOW_CASTER); + } +} +//----------------------------------------------------------------------- +bool DLight::isCameraInsideLight(Ogre::Camera* camera) +{ + switch (mParentLight->getType()) + { + case Ogre::Light::LT_DIRECTIONAL: + return false; + case Ogre::Light::LT_POINT: + { + Ogre::Real distanceFromLight = camera->getDerivedPosition() + .distance(mParentLight->getDerivedPosition()); + //Small epsilon fix to account for the fact that we aren't a true sphere. + return distanceFromLight <= mRadius + camera->getNearClipDistance() + 0.1; + } + case Ogre::Light::LT_SPOTLIGHT: + { + Ogre::Vector3 lightPos = mParentLight->getDerivedPosition(); + Ogre::Vector3 lightDir = mParentLight->getDerivedDirection(); + Ogre::Radian attAngle = mParentLight->getSpotlightOuterAngle(); + + //Extend the analytic cone's radius by the near clip range by moving its tip accordingly. + //Some trigonometry needed here. + Ogre::Vector3 clipRangeFix = -lightDir * (camera->getNearClipDistance() / Ogre::Math::Tan(attAngle/2)); + lightPos = lightPos + clipRangeFix; + + Ogre::Vector3 lightToCamDir = camera->getDerivedPosition() - lightPos; + Ogre::Real distanceFromLight = lightToCamDir.normalise(); + + Ogre::Real cosAngle = lightToCamDir.dotProduct(lightDir); + Ogre::Radian angle = Ogre::Math::ACos(cosAngle); + //Check whether we will see the cone from our current POV. + return (distanceFromLight <= (mParentLight->getAttenuationRange() + clipRangeFix.length())) + && (angle <= attAngle); + } + default: + //Please the compiler + return false; + } +} +//----------------------------------------------------------------------- +bool DLight::getCastChadows() const +{ + return + mParentLight->_getManager()->isShadowTechniqueInUse() && + mParentLight->getCastShadows() && + (mParentLight->getType() == Light::LT_DIRECTIONAL || mParentLight->getType() == Light::LT_SPOTLIGHT); +} +//----------------------------------------------------------------------- +void DLight::updateFromCamera(Ogre::Camera* camera) +{ + //Set shader params + const Ogre::MaterialPtr& mat = getMaterial(); + if (!mat->isLoaded()) + { + mat->load(); + } + Ogre::Technique* tech = mat->getBestTechnique(); + Ogre::Vector3 farCorner = camera->getViewMatrix(true) * camera->getWorldSpaceCorners()[4]; + + for (unsigned short i=0; igetNumPasses(); i++) + { + Ogre::Pass* pass = tech->getPass(i); + // get the vertex shader parameters + Ogre::GpuProgramParametersSharedPtr params = pass->getVertexProgramParameters(); + // set the camera's far-top-right corner + if (params->_findNamedConstantDefinition("farCorner")) + params->setNamedConstant("farCorner", farCorner); + + params = pass->getFragmentProgramParameters(); + if (params->_findNamedConstantDefinition("farCorner")) + params->setNamedConstant("farCorner", farCorner); + + //If inside light geometry, render back faces with CMPF_GREATER, otherwise normally + if (mParentLight->getType() == Ogre::Light::LT_DIRECTIONAL) + { + pass->setCullingMode(Ogre::CULL_CLOCKWISE); + pass->setDepthCheckEnabled(false); + } + else + { + pass->setDepthCheckEnabled(true); + if (isCameraInsideLight(camera)) + { + pass->setCullingMode(Ogre::CULL_ANTICLOCKWISE); + pass->setDepthFunction(Ogre::CMPF_GREATER_EQUAL); + } + else + { + pass->setCullingMode(Ogre::CULL_CLOCKWISE); + pass->setDepthFunction(Ogre::CMPF_LESS_EQUAL); + } + } + + Camera shadowCam("ShadowCameraSetupCam", 0); + shadowCam._notifyViewport(camera->getViewport()); + SceneManager* sm = mParentLight->_getManager(); + sm->getShadowCameraSetup()->getShadowCamera(sm, + camera, camera->getViewport(), mParentLight, &shadowCam, 0); + + //Get the shadow camera position + if (params->_findNamedConstantDefinition("shadowCamPos")) + { + params->setNamedConstant("shadowCamPos", shadowCam.getPosition()); + } + if (params->_findNamedConstantDefinition("shadowFarClip")) + { + params->setNamedConstant("shadowFarClip", shadowCam.getFarClipDistance()); + } + + } +} + +} diff --git a/PlugIns/DeferredShading/src/OgreDS_DeferredLightCP.cpp b/PlugIns/DeferredShading/src/OgreDS_DeferredLightCP.cpp new file mode 100644 --- /dev/null +++ b/PlugIns/DeferredShading/src/OgreDS_DeferredLightCP.cpp @@ -0,0 +1,138 @@ +/* +----------------------------------------------------------------------------- +This source file is part of OGRE +(Object-oriented Graphics Rendering Engine) +For the latest info, see http://www.ogre3d.org/ + +Copyright (c) 2000-2009 Torus Knot Software Ltd +Also see acknowledgements in Readme.html + +You may use this sample code for anything you like, it is not covered by the +same license as the rest of the engine. +----------------------------------------------------------------------------- +*/ + +#include "OgreDS_DeferredLightCP.h" + +#include "Ogre.h" + +#include "OgreDS_LightMaterialGenerator.h" + +namespace Ogre +{ + +//----------------------------------------------------------------------- +DeferredLightRenderOperation::DeferredLightRenderOperation( + CompositorInstance* instance, const CompositionPass* pass) +{ + mViewport = instance->getChain()->getViewport(); + + //Get the names of the GBuffer textures + const CompositionPass::InputTex& input0 = pass->getInput(0); + mTexName0 = instance->getTextureInstanceName(input0.name, input0.mrtIndex); + const CompositionPass::InputTex& input1 = pass->getInput(1); + mTexName1 = instance->getTextureInstanceName(input1.name, input1.mrtIndex); + + // Create lights material generator + mLightMaterialGenerator = new LightMaterialGenerator(); + + // Create the ambient light + mAmbientLight = new AmbientLight(); + const MaterialPtr& mat = mAmbientLight->getMaterial(); + mat->load(); +} +//----------------------------------------------------------------------- +DLight* DeferredLightRenderOperation::createDLight(Ogre::Light* light) +{ + DLight *rv = new DLight(mLightMaterialGenerator,light); + mLights[light] = rv; + return rv; +} +//----------------------------------------------------------------------- +void injectTechnique(SceneManager* sm, Technique* tech, Renderable* rend, const Ogre::LightList* lightList) +{ + for(unsigned short i=0; igetNumPasses(); ++i) + { + Ogre::Pass* pass = tech->getPass(i); + if (lightList != 0) + { + sm->_injectRenderWithPass(pass, rend, false, false, lightList); + } + else + { + sm->_injectRenderWithPass(pass, rend, false); + } + + } +} +//----------------------------------------------------------------------- +void DeferredLightRenderOperation::execute(SceneManager *sm, RenderSystem *rs) +{ + Ogre::Camera* cam = mViewport->getCamera(); + + mAmbientLight->updateFromCamera(cam); + Technique* tech = mAmbientLight->getMaterial()->getBestTechnique(); + injectTechnique(sm, tech, mAmbientLight, 0); + + const LightList& lightList = sm->_getLightsAffectingFrustum(); + for (LightList::const_iterator it = lightList.begin(); it != lightList.end(); it++) + { + Light* light = *it; + Ogre::LightList ll; + ll.push_back(light); + + //if (++i != 2) continue; + //if (light->getType() != Light::LT_DIRECTIONAL) continue; + //if (light->getDiffuseColour() != ColourValue::Red) continue; + + LightsMap::iterator dLightIt = mLights.find(light); + DLight* dLight = 0; + if (dLightIt == mLights.end()) + { + dLight = createDLight(light); + } + else + { + dLight = dLightIt->second; + dLight->updateFromParent(); + } + dLight->updateFromCamera(cam); + tech = dLight->getMaterial()->getBestTechnique(); + + //Update shadow texture + if (dLight->getCastChadows()) + { + SceneManager::RenderContext* context = sm->_pauseRendering(); + + sm->prepareShadowTextures(cam, mViewport, &ll); + sm->_resumeRendering(context); + + Pass* pass = tech->getPass(0); + TextureUnitState* tus = pass->getTextureUnitState("ShadowMap"); + assert(tus); + const TexturePtr& shadowTex = sm->getShadowTexture(0); + if (tus->_getTexturePtr() != shadowTex) + { + tus->_setTexturePtr(shadowTex); + } + + } + + injectTechnique(sm, tech, dLight, &ll); + } +} +//----------------------------------------------------------------------- +DeferredLightRenderOperation::~DeferredLightRenderOperation() +{ + for (LightsMap::iterator it = mLights.begin(); it != mLights.end(); ++it) + { + delete it->second; + } + mLights.clear(); + + delete mAmbientLight; + delete mLightMaterialGenerator; +} +//----------------------------------------------------------------------- + +} diff --git a/PlugIns/DeferredShading/src/OgreDS_DeferredShading.cpp b/PlugIns/DeferredShading/src/OgreDS_DeferredShading.cpp new file mode 100644 --- /dev/null +++ b/PlugIns/DeferredShading/src/OgreDS_DeferredShading.cpp @@ -0,0 +1,182 @@ +/* +----------------------------------------------------------------------------- +This source file is part of OGRE +(Object-oriented Graphics Rendering Engine) +For the latest info, see http://www.ogre3d.org/ + +Copyright (c) 2000-2009 Torus Knot Software Ltd +Also see acknowledgements in Readme.html + +You may use this sample code for anything you like, it is not covered by the +same license as the rest of the engine. +----------------------------------------------------------------------------- +*/ + +#include "OgreDS_DeferredShading.h" + +#include "OgreConfigFile.h" +#include "OgreStringConverter.h" +#include "OgreException.h" + +#include "OgreRoot.h" +#include "OgreRenderSystem.h" + +#include "OgreEntity.h" +#include "OgreSubEntity.h" +#include "OgreRoot.h" + +#include "OgreCompositor.h" +#include "OgreCompositorManager.h" +#include "OgreCompositorChain.h" +#include "OgreCompositorInstance.h" + +#include "OgreLogManager.h" + +#include "OgreDS_DeferredLightCP.h" +#include "OgreDS_SSAOLogic.h" +#include "OgreDS_GBufferSchemeHandler.h" +#include "OgreDS_NullSchemeHandler.h" + + + +namespace Ogre +{ + +const uint8 DeferredShadingSystem::PRE_GBUFFER_RENDER_QUEUE = RENDER_QUEUE_1; +const uint8 DeferredShadingSystem::POST_GBUFFER_RENDER_QUEUE = RENDER_QUEUE_8; + +DeferredShadingSystem::DeferredShadingSystem( + Viewport *vp, Camera *cam + ): + mViewport(vp), mCamera(cam) +{ + +} + +void DeferredShadingSystem::initialize() +{ + for(int i=0; i_removeInstance(mInstance[i]); + CompositorManager::getSingleton().removeCompositorChain(mViewport); + + Ogre::CompositorManager& compMgr = Ogre::CompositorManager::getSingleton(); + CompositorLogicMap::const_iterator itor = mCompositorLogics.begin(); + CompositorLogicMap::const_iterator end = mCompositorLogics.end(); + while( itor != end ) + { + compMgr.unregisterCompositorLogic( itor->first ); + delete itor->second; + ++itor; + } + mCompositorLogics.clear(); +} + +void DeferredShadingSystem::setMode(DSMode mode) +{ + assert( 0 <= mode && mode < DSM_COUNT); + + // prevent duplicate setups + if (mCurrentMode == mode && mInstance[mode]->getEnabled()==mActive) + return; + + for(int i=0; isetEnabled(mActive); + } + else + { + mInstance[i]->setEnabled(false); + } + } + + mCurrentMode = mode; + + mSSAOInstance->setEnabled(mActive && mSSAO && mCurrentMode == DSM_SHOWLIT); +} + +void DeferredShadingSystem::setSSAO(bool ssao) +{ + if (ssao != mSSAO) + { + mSSAO = ssao; + if (mActive && mCurrentMode == DSM_SHOWLIT) + { + mSSAOInstance->setEnabled(ssao); + } + } +} + +bool DeferredShadingSystem::getSSAO() const +{ + return mSSAO; +} +void DeferredShadingSystem::setActive(bool active) +{ + if (mActive != active) + { + mActive = active; + mGBufferInstance->setEnabled(active); + + // mCurrentMode could have changed with a prior call to setMode, so iterate all + setMode(mCurrentMode); + } +} + +DeferredShadingSystem::DSMode DeferredShadingSystem::getMode(void) const +{ + return mCurrentMode; +} + +void DeferredShadingSystem::createResources(void) +{ + CompositorManager &compMan = CompositorManager::getSingleton(); + + mCompositorLogics["SSAOLogic"] = new SSAOLogic; + compMan.registerCompositorLogic("SSAOLogic", mCompositorLogics["SSAOLogic"]); + + // Create the main GBuffer compositor + mGBufferInstance = compMan.addCompositor(mViewport, "DeferredShading/GBuffer"); + + // Create filters + mInstance[DSM_SHOWLIT] = compMan.addCompositor(mViewport, "DeferredShading/ShowLit"); + mInstance[DSM_SHOWNORMALS] = compMan.addCompositor(mViewport, "DeferredShading/ShowNormals"); + mInstance[DSM_SHOWDSP] = compMan.addCompositor(mViewport, "DeferredShading/ShowDepthSpecular"); + mInstance[DSM_SHOWCOLOUR] = compMan.addCompositor(mViewport, "DeferredShading/ShowColour"); + + mSSAOInstance = compMan.addCompositor(mViewport, "DeferredShading/SSAO"); +} + + +void DeferredShadingSystem::logCurrentMode(void) +{ + if (mActive==false) + { + LogManager::getSingleton().logMessage("No Compositor Enabled!"); + return; + } + + CompositorInstance* ci = mInstance[mCurrentMode]; + assert(ci->getEnabled()==true); + + LogManager::getSingleton().logMessage("Current Mode: "); + LogManager::getSingleton().logMessage(ci->getCompositor()->getName()); +} + +} diff --git a/PlugIns/DeferredShading/src/OgreDS_Dll.cpp b/PlugIns/DeferredShading/src/OgreDS_Dll.cpp new file mode 100644 --- /dev/null +++ b/PlugIns/DeferredShading/src/OgreDS_Dll.cpp @@ -0,0 +1,50 @@ +/* +----------------------------------------------------------------------------- +This source file is part of OGRE + (Object-oriented Graphics Rendering Engine) +For the latest info, see http://www.ogre3d.org/ + +Copyright (c) 2000-2009 Torus Knot Software Ltd + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +----------------------------------------------------------------------------- +*/ + +#include "OgreRoot.h" +#include "OgreDS_Prerequisites.h" +#include "OgreDeferredShadingPlugin.h" + + +Ogre::DeferredShadingPlugin* dsPlugin; +//----------------------------------------------------------------------- +#ifndef OGRE_STATIC_LIB +extern "C" void _OgreDsPluginExport dllStartPlugin(void) +{ + // Create new scene manager + dsPlugin = OGRE_NEW Ogre::DeferredShadingPlugin(); + + // Register + Ogre::Root::getSingleton().installPlugin(dsPlugin); +} +extern "C" void _OgreDsPluginExport dllStopPlugin(void) +{ + Ogre::Root::getSingleton().uninstallPlugin(dsPlugin); + OGRE_DELETE dsPlugin; +} +#endif diff --git a/PlugIns/DeferredShading/src/OgreDS_GBufferMaterialGenerator.cpp b/PlugIns/DeferredShading/src/OgreDS_GBufferMaterialGenerator.cpp new file mode 100644 --- /dev/null +++ b/PlugIns/DeferredShading/src/OgreDS_GBufferMaterialGenerator.cpp @@ -0,0 +1,295 @@ +/* +----------------------------------------------------------------------------- +This source file is part of OGRE +(Object-oriented Graphics Rendering Engine) +For the latest info, see http://www.ogre3d.org/ + +Copyright (c) 2000-2009 Torus Knot Software Ltd +Also see acknowledgements in Readme.html + +You may use this sample code for anything you like, it is not covered by the +same license as the rest of the engine. +----------------------------------------------------------------------------- +*/ + +#include "OgreDS_GBufferMaterialGenerator.h" + +#include "OgreMaterialManager.h" +#include "OgreGpuProgramManager.h" +#include "OgreStringConverter.h" +#include "OgreHighLevelGpuProgramManager.h" +#include "OgreTechnique.h" + +//Use this directive to control whether you are writing projective (regular) or linear depth. +#define WRITE_LINEAR_DEPTH + +namespace Ogre +{ + +//This is the concrete implementation of the material generator. +class GBufferMaterialGeneratorImpl : public MaterialGenerator::Impl +{ +public: + GBufferMaterialGeneratorImpl(const Ogre::String& baseName) : mBaseName(baseName) {} + +protected: + Ogre::String mBaseName; + virtual Ogre::GpuProgramPtr generateVertexShader(MaterialGenerator::Perm permutation); + virtual Ogre::GpuProgramPtr generateFragmentShader(MaterialGenerator::Perm permutation); + virtual Ogre::MaterialPtr generateTemplateMaterial(MaterialGenerator::Perm permutation); + +}; + +GBufferMaterialGenerator::GBufferMaterialGenerator() { + vsMask = VS_MASK; + fsMask = FS_MASK; + matMask = MAT_MASK; + materialBaseName = "DeferredShading/GBuffer/"; + mImpl = new GBufferMaterialGeneratorImpl(materialBaseName); +} + +Ogre::GpuProgramPtr GBufferMaterialGeneratorImpl::generateVertexShader(MaterialGenerator::Perm permutation) +{ + Ogre::StringStream ss; + + ss << "void ToGBufferVP(" << std::endl; + ss << " float4 iPosition : POSITION," << std::endl; + ss << " float3 iNormal : NORMAL," << std::endl; + + Ogre::uint32 numTexCoords = (permutation & GBufferMaterialGenerator::GBP_TEXCOORD_MASK) >> 8; + for (Ogre::uint32 i=0; ilogMessage(programSource); +#endif + + // Create shader object + Ogre::HighLevelGpuProgramPtr ptrProgram = Ogre::HighLevelGpuProgramManager::getSingleton().createProgram( + programName, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, + "cg", Ogre::GPT_VERTEX_PROGRAM); + ptrProgram->setSource(programSource); + ptrProgram->setParameter("entry_point","ToGBufferVP"); + ptrProgram->setParameter("profiles","vs_1_1 arbvp1"); + + const Ogre::GpuProgramParametersSharedPtr& params = ptrProgram->getDefaultParameters(); + params->setNamedAutoConstant("cWorldViewProj", Ogre::GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); + params->setNamedAutoConstant("cWorldView", Ogre::GpuProgramParameters::ACT_WORLDVIEW_MATRIX); + ptrProgram->load(); + + return Ogre::GpuProgramPtr(ptrProgram); +} + +Ogre::GpuProgramPtr GBufferMaterialGeneratorImpl::generateFragmentShader(MaterialGenerator::Perm permutation) +{ + Ogre::StringStream ss; + + ss << "void ToGBufferFP(" << std::endl; +#ifdef WRITE_LINEAR_DEPTH + ss << " float3 iViewPos : TEXCOORD0," << std::endl; +#else + ss << " float1 iDepth : TEXCOORD0," << std::endl; +#endif + ss << " float3 iNormal : TEXCOORD1," << std::endl; + + int texCoordNum = 2; + if (permutation & GBufferMaterialGenerator::GBP_NORMAL_MAP) + { + ss << " float3 iTangent : TEXCOORD" << texCoordNum++ << ',' << std::endl; + ss << " float3 iBiNormal : TEXCOORD" << texCoordNum++ << ',' << std::endl; + } + + Ogre::uint32 numTexCoords = (permutation & GBufferMaterialGenerator::GBP_TEXCOORD_MASK) >> 8; + for (Ogre::uint32 i=0; i 0 && numTextures > 0) + { + if(permutation & GBufferMaterialGenerator::GBP_ALPHA_REJECTION) + { + // add a test for the alpha rejection, using first texture + ss << " if (tex2D(sTex0, iUV0).a <= cRejectAlpha) discard;" << std::endl; + } + ss << " oColor0.rgb = tex2D(sTex0, iUV0);" << std::endl; + if (permutation & GBufferMaterialGenerator::GBP_HAS_DIFFUSE_COLOUR) + { + ss << " oColor0.rgb *= cDiffuseColour.rgb;" << std::endl; + } + } + else + { + ss << " oColor0.rgb = cDiffuseColour.rgb;" << std::endl; + } + + + ss << " oColor0.a = cSpecularity;" << std::endl; + if (permutation & GBufferMaterialGenerator::GBP_NORMAL_MAP) + { + ss << " float3 texNormal = (tex2D(sNormalMap, iUV0)-0.5)*2;" << std::endl; + ss << " float3x3 normalRotation = float3x3(iTangent, iBiNormal, iNormal);" << std::endl; + ss << " oColor1.rgb = normalize(mul(texNormal, normalRotation));" << std::endl; + } else + { + ss << " oColor1.rgb = normalize(iNormal);" << std::endl; + } +#ifdef WRITE_LINEAR_DEPTH + ss << " oColor1.a = length(iViewPos) / cFarDistance;" << std::endl; +#else + ss << " oColor1.a = iDepth;" << std::endl; +#endif + + ss << "}" << std::endl; + + Ogre::String programSource = ss.str(); + Ogre::String programName = mBaseName + "FP_" + Ogre::StringConverter::toString(permutation); + +#if OGRE_DEBUG_MODE + Ogre::LogManager::getSingleton().getDefaultLog()->logMessage(programSource); +#endif + + // Create shader object + Ogre::HighLevelGpuProgramPtr ptrProgram = Ogre::HighLevelGpuProgramManager::getSingleton().createProgram( + programName, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, + "cg", Ogre::GPT_FRAGMENT_PROGRAM); + ptrProgram->setSource(programSource); + ptrProgram->setParameter("entry_point","ToGBufferFP"); + ptrProgram->setParameter("profiles","ps_2_0 arbfp1"); + + const Ogre::GpuProgramParametersSharedPtr& params = ptrProgram->getDefaultParameters(); + params->setNamedAutoConstant("cSpecularity", Ogre::GpuProgramParameters::ACT_SURFACE_SHININESS); + if (numTextures == 0 || permutation & GBufferMaterialGenerator::GBP_HAS_DIFFUSE_COLOUR) + { + params->setNamedAutoConstant("cDiffuseColour", Ogre::GpuProgramParameters::ACT_SURFACE_DIFFUSE_COLOUR); + } + +#ifdef WRITE_LINEAR_DEPTH + //TODO : Should this be the distance to the far corner, not the far clip distance? + params->setNamedAutoConstant("cFarDistance", Ogre::GpuProgramParameters::ACT_FAR_CLIP_DISTANCE); +#endif + + ptrProgram->load(); + return Ogre::GpuProgramPtr(ptrProgram); +} + +Ogre::MaterialPtr GBufferMaterialGeneratorImpl::generateTemplateMaterial(MaterialGenerator::Perm permutation) +{ + Ogre::String matName = mBaseName + "Mat_" + Ogre::StringConverter::toString(permutation); + + Ogre::MaterialPtr matPtr = Ogre::MaterialManager::getSingleton().create + (matName, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); + Ogre::Pass* pass = matPtr->getTechnique(0)->getPass(0); + pass->setName(mBaseName + "Pass_" + Ogre::StringConverter::toString(permutation)); + pass->setLightingEnabled(false); + if (permutation & GBufferMaterialGenerator::GBP_NORMAL_MAP) + { + pass->createTextureUnitState(); + } + Ogre::uint32 numTextures = permutation & GBufferMaterialGenerator::GBP_TEXTURE_MASK; + for (Ogre::uint32 i=0; icreateTextureUnitState(); + } + + return matPtr; +} + +} diff --git a/PlugIns/DeferredShading/src/OgreDS_GBufferSchemeHandler.cpp b/PlugIns/DeferredShading/src/OgreDS_GBufferSchemeHandler.cpp new file mode 100644 --- /dev/null +++ b/PlugIns/DeferredShading/src/OgreDS_GBufferSchemeHandler.cpp @@ -0,0 +1,304 @@ +/* +----------------------------------------------------------------------------- +This source file is part of OGRE +(Object-oriented Graphics Rendering Engine) +For the latest info, see http://www.ogre3d.org/ + +Copyright (c) 2000-2009 Torus Knot Software Ltd +Also see acknowledgements in Readme.html + +You may use this sample code for anything you like, it is not covered by the +same license as the rest of the engine. +----------------------------------------------------------------------------- +*/ + +#include "OgreDS_GBufferSchemeHandler.h" + +#include +#include +#include +#include "OgreDeferredShadingManager.h" + +namespace Ogre +{ + +const String GBufferSchemeHandler::NORMAL_MAP_PATTERN = "normalmap"; + +Technique* GBufferSchemeHandler::handleSchemeNotFound(unsigned short schemeIndex, + const String& schemeName, Material* originalMaterial, unsigned short lodIndex, + const Renderable* rend) +{ + Ogre::MaterialManager& matMgr = Ogre::MaterialManager::getSingleton(); + String curSchemeName = matMgr.getActiveScheme(); + matMgr.setActiveScheme(DeferredShadingManager::getSingleton().getDefaultMaterialSchemeName()); + Technique* originalTechnique = originalMaterial->getBestTechnique(lodIndex, rend); + matMgr.setActiveScheme(curSchemeName); + + Technique* gBufferTech = originalMaterial->createTechnique(); + gBufferTech->removeAllPasses(); + gBufferTech->setSchemeName(schemeName); + + Technique* noGBufferTech = originalMaterial->createTechnique(); + noGBufferTech->removeAllPasses(); + noGBufferTech->setSchemeName("NoGBuffer"); + + MaterialPtr shadowCaster; + Technique* shadowTech = NULL; + bool shadowCasterIsNew = false; + + for (unsigned short i=0; igetNumPasses(); i++) + { + Pass* originalPass = originalTechnique->getPass(i); + PassProperties props = inspectPass(originalPass, lodIndex, rend); + + if (!props.isDeferred) + { + //Just copy the technique so it gets rendered regularly + Pass* clonePass = noGBufferTech->createPass(); + *clonePass = *originalPass; + continue; + } + + //Check if we need a shadow caster material + if (props.alphaRejectionTexture != 0) + { + if(shadowCaster.isNull()) + { + + String shadowCasterName = originalMaterial->getName() + ".deferredshadowcaster"; + shadowCaster = matMgr.getByName(shadowCasterName, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); + if(shadowCaster.isNull()) + { + shadowCaster = matMgr.create(originalMaterial->getName() + ".deferredshadowcaster", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); + shadowTech = shadowCaster->getTechnique(0); + shadowTech->removeAllPasses(); + shadowCasterIsNew = true; + Ogre::LogManager::getSingleton().logMessage("GBufferSchemeHandler: Added shadowcaster material " + shadowCasterName); + } + } + + if(shadowCasterIsNew) //to prevent adding passes to existing caster + { + try{ + //Add a pass for this technique + Pass* newPass = shadowTech->createPass(); + newPass->setVertexProgram("DeferredShading/Shadows/CasterTextureVP"); + newPass->setFragmentProgram("DeferredShading/Shadows/CasterAlphaFP"); + GpuProgramParametersSharedPtr fragProgParams = newPass->getFragmentProgramParameters(); + fragProgParams->setNamedConstant("cRejectAlpha", Real(originalPass->getAlphaRejectValue()/255.0f)); + TextureUnitState* tus = newPass->createTextureUnitState(); + *tus = *props.alphaRejectionTexture; //copy the texture unit + Ogre::LogManager::getSingleton().logMessage("GBufferSchemeHandler: Added pass with rejection value " + StringConverter::toString(Real(originalPass->getAlphaRejectValue()/255.0f))); + } + catch(Exception& exc) + { + //e.g. the gpu programs might be failing + //don't add a pass. + } + } + } + + Pass* newPass = gBufferTech->createPass(); + MaterialGenerator::Perm perm = getPermutation(props); + + const Ogre::MaterialPtr& templateMat = mMaterialGenerator.getMaterial(perm); + + //We assume that the GBuffer technique contains only one pass. But its true. + *newPass = *(templateMat->getTechnique(0)->getPass(0)); + fillPass(newPass, originalPass, props); + } + if(!shadowCaster.isNull()) + { + originalTechnique->setShadowCasterMaterial(shadowCaster); + gBufferTech->setShadowCasterMaterial(shadowCaster); + } + + return gBufferTech; +} + +bool GBufferSchemeHandler::checkNormalMap( + TextureUnitState* tus, GBufferSchemeHandler::PassProperties& props) +{ + bool isNormal = false; + Ogre::String lowerCaseAlias = tus->getTextureNameAlias(); + Ogre::StringUtil::toLowerCase(lowerCaseAlias); + if (lowerCaseAlias.find(NORMAL_MAP_PATTERN) != Ogre::String::npos) + { + isNormal = true; + } + else + { + Ogre::String lowerCaseName = tus->getTextureName(); + Ogre::StringUtil::toLowerCase(lowerCaseName); + if (lowerCaseName.find(NORMAL_MAP_PATTERN) != Ogre::String::npos) + { + isNormal = true; + } + } + + if (isNormal) + { + if (props.normalMap == 0) + { + props.normalMap = tus; + } + else + { + OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM, + "Multiple normal map patterns matches", + "GBufferSchemeHandler::inspectPass"); + } + } + return isNormal; +} + +bool GBufferSchemeHandler::checkRejectionTexture(Ogre::TextureUnitState* tus, PassProperties& props) +{ + //TODO: add some intelligent checks. Now we just use the first texture as alpha texture. + bool isAlphaTexture = props.alphaRejectionTexture == 0; + + if(isAlphaTexture) + { + props.alphaRejectionTexture = tus; + } + + return isAlphaTexture; +} +GBufferSchemeHandler::PassProperties GBufferSchemeHandler::inspectPass( + Pass* pass, unsigned short lodIndex, const Renderable* rend) +{ + PassProperties props; + + //TODO : Use renderable to indicate wether this has skinning. + //Probably use same const cast that renderSingleObject uses. + if (pass->hasVertexProgram()) + { + props.isSkinned = pass->getVertexProgram()->isSkeletalAnimationIncluded(); + } + else + { + props.isSkinned = false; + } + + + for (unsigned short i=0; igetNumTextureUnitStates(); i++) + { + TextureUnitState* tus = pass->getTextureUnitState(i); + if (!checkNormalMap(tus, props)) + { + props.regularTextures.push_back(tus); + //check if it is alpha_rejection using texture + if (pass->getAlphaRejectFunction() != CMPF_ALWAYS_PASS) + { + checkRejectionTexture(tus, props); + } + } + if (tus->getEffects().size() > 0) + { + props.isDeferred = false; + } + } + + if (pass->getDiffuse() != ColourValue::White) + { + props.hasDiffuseColour = true; + } + + //Check transparency + if (pass->getDestBlendFactor() != Ogre::SBF_ZERO) + { + //TODO : Better ways to do this + props.isDeferred = false; + } + return props; +} + +MaterialGenerator::Perm GBufferSchemeHandler::getPermutation(const PassProperties& props) +{ + MaterialGenerator::Perm perm = 0; + switch (props.regularTextures.size()) + { + case 0: + perm |= GBufferMaterialGenerator::GBP_NO_TEXTURES; + + if (props.normalMap != 0) + { + perm |= GBufferMaterialGenerator::GBP_ONE_TEXCOORD; + } + else + { + perm |= GBufferMaterialGenerator::GBP_NO_TEXCOORDS; + } + break; + case 1: + perm |= GBufferMaterialGenerator::GBP_ONE_TEXTURE; + perm |= GBufferMaterialGenerator::GBP_ONE_TEXCOORD; + break; + case 2: + perm |= GBufferMaterialGenerator::GBP_TWO_TEXTURES; + //TODO : When do we use two texcoords? + perm |= GBufferMaterialGenerator::GBP_ONE_TEXCOORD; + break; + case 3: + perm |= GBufferMaterialGenerator::GBP_THREE_TEXTURES; + perm |= GBufferMaterialGenerator::GBP_ONE_TEXCOORD; + break; + default: + OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED, + "Can not generate G-Buffer materials for '>3 regular-texture' objects", + "GBufferSchemeHandler::inspectPass"); + } + + if (props.isSkinned) + { + perm |= GBufferMaterialGenerator::GBP_SKINNED; + } + + if (props.normalMap != 0) + { + perm |= GBufferMaterialGenerator::GBP_NORMAL_MAP; + } + + if (props.hasDiffuseColour) + { + perm |= GBufferMaterialGenerator::GBP_HAS_DIFFUSE_COLOUR; + } + + if (props.alphaRejectionTexture != 0) + { + perm |= GBufferMaterialGenerator::GBP_ALPHA_REJECTION; + } + + return perm; +} + +void GBufferSchemeHandler::fillPass( + Pass* gBufferPass, Pass* originalPass, const PassProperties& props) +{ + //Reference the correct textures. Normal map first! + int texUnitIndex = 0; + if (props.normalMap != 0) + { + *(gBufferPass->getTextureUnitState(texUnitIndex)) = *(props.normalMap); + texUnitIndex++; + } + for (size_t i=0; igetTextureUnitState(texUnitIndex)) = *(props.regularTextures[i]); + texUnitIndex++; + } + if (props.alphaRejectionTexture != 0) + { + GpuProgramParametersSharedPtr fragProgParams = gBufferPass->getFragmentProgramParameters(); + fragProgParams->setNamedConstant("cRejectAlpha", Real(originalPass->getAlphaRejectValue()/255.0f)); + } + + gBufferPass->setAmbient(originalPass->getAmbient()); + gBufferPass->setDiffuse(originalPass->getDiffuse()); + gBufferPass->setSpecular(originalPass->getSpecular()); + gBufferPass->setShininess(originalPass->getShininess()); + gBufferPass->setCullingMode(originalPass->getCullingMode()); + gBufferPass->setLightingEnabled(false); +} + +} diff --git a/PlugIns/DeferredShading/src/OgreDS_GeomUtils.cpp b/PlugIns/DeferredShading/src/OgreDS_GeomUtils.cpp new file mode 100644 --- /dev/null +++ b/PlugIns/DeferredShading/src/OgreDS_GeomUtils.cpp @@ -0,0 +1,257 @@ +/* +----------------------------------------------------------------------------- +This source file is part of OGRE +(Object-oriented Graphics Rendering Engine) +For the latest info, see http://www.ogre3d.org/ + +Copyright (c) 2000-2009 Torus Knot Software Ltd +Also see acknowledgements in Readme.html + +You may use this sample code for anything you like, it is not covered by the +same license as the rest of the engine. +----------------------------------------------------------------------------- +*/ + + +#include "OgreDS_GeomUtils.h" + +#include "OgreMeshManager.h" +#include "OgreSubMesh.h" +#include "OgreHardwareBufferManager.h" + +namespace Ogre +{ + +void GeomUtils::createSphere( const String& strName + , float radius + , int nRings, int nSegments + , bool bNormals + , bool bTexCoords) +{ + MeshPtr pSphere = MeshManager::getSingleton().createManual(strName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); + SubMesh *pSphereVertex = pSphere->createSubMesh(); + pSphere->sharedVertexData = new VertexData(); + + createSphere(pSphere->sharedVertexData, pSphereVertex->indexData + , radius + , nRings, nSegments + , bNormals // need normals + , bTexCoords // need texture co-ordinates + ); + + // Generate face list + pSphereVertex->useSharedVertices = true; + + // the original code was missing this line: + pSphere->_setBounds( AxisAlignedBox( Vector3(-radius, -radius, -radius), Vector3(radius, radius, radius) ), false ); + pSphere->_setBoundingSphereRadius(radius); + // this line makes clear the mesh is loaded (avoids memory leaks) + pSphere->load(); +} + +void GeomUtils::createSphere(VertexData*& vertexData, IndexData*& indexData + , float radius + , int nRings, int nSegments + , bool bNormals + , bool bTexCoords) +{ + assert(vertexData && indexData); + + // define the vertex format + VertexDeclaration* vertexDecl = vertexData->vertexDeclaration; + size_t currOffset = 0; + // positions + vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_POSITION); + currOffset += VertexElement::getTypeSize(VET_FLOAT3); + + if (bNormals) + { + // normals + vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_NORMAL); + currOffset += VertexElement::getTypeSize(VET_FLOAT3); + + } + // two dimensional texture coordinates + if (bTexCoords) + { + vertexDecl->addElement(0, currOffset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0); + currOffset += VertexElement::getTypeSize(VET_FLOAT2); + } + + // allocate the vertex buffer + vertexData->vertexCount = (nRings + 1) * (nSegments+1); + HardwareVertexBufferSharedPtr vBuf = HardwareBufferManager::getSingleton().createVertexBuffer(vertexDecl->getVertexSize(0), vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); + VertexBufferBinding* binding = vertexData->vertexBufferBinding; + binding->setBinding(0, vBuf); + float* pVertex = static_cast(vBuf->lock(HardwareBuffer::HBL_DISCARD)); + + // allocate index buffer + indexData->indexCount = 6 * nRings * (nSegments + 1); + indexData->indexBuffer = HardwareBufferManager::getSingleton().createIndexBuffer(HardwareIndexBuffer::IT_16BIT, indexData->indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); + HardwareIndexBufferSharedPtr iBuf = indexData->indexBuffer; + unsigned short* pIndices = static_cast(iBuf->lock(HardwareBuffer::HBL_DISCARD)); + + float fDeltaRingAngle = (Math::PI / nRings); + float fDeltaSegAngle = (2 * Math::PI / nSegments); + unsigned short wVerticeIndex = 0 ; + + // Generate the group of rings for the sphere + for( int ring = 0; ring <= nRings; ring++ ) { + float r0 = radius * sinf (ring * fDeltaRingAngle); + float y0 = radius * cosf (ring * fDeltaRingAngle); + + // Generate the group of segments for the current ring + for(int seg = 0; seg <= nSegments; seg++) { + float x0 = r0 * sinf(seg * fDeltaSegAngle); + float z0 = r0 * cosf(seg * fDeltaSegAngle); + + // Add one vertex to the strip which makes up the sphere + *pVertex++ = x0; + *pVertex++ = y0; + *pVertex++ = z0; + + if (bNormals) + { + Vector3 vNormal = Vector3(x0, y0, z0).normalisedCopy(); + *pVertex++ = vNormal.x; + *pVertex++ = vNormal.y; + *pVertex++ = vNormal.z; + } + if (bTexCoords) + { + *pVertex++ = (float) seg / (float) nSegments; + *pVertex++ = (float) ring / (float) nRings; + } + + if (ring != nRings) + { + // each vertex (except the last) has six indices pointing to it + *pIndices++ = wVerticeIndex + nSegments + 1; + *pIndices++ = wVerticeIndex; + *pIndices++ = wVerticeIndex + nSegments; + *pIndices++ = wVerticeIndex + nSegments + 1; + *pIndices++ = wVerticeIndex + 1; + *pIndices++ = wVerticeIndex; + wVerticeIndex ++; + } + }; // end for seg + } // end for ring + + // Unlock + vBuf->unlock(); + iBuf->unlock(); +} + +void GeomUtils::createQuad(VertexData*& vertexData) +{ + assert(vertexData); + + vertexData->vertexCount = 4; + vertexData->vertexStart = 0; + + VertexDeclaration* vertexDecl = vertexData->vertexDeclaration; + VertexBufferBinding* bind = vertexData->vertexBufferBinding; + + vertexDecl->addElement(0, 0, VET_FLOAT3, VES_POSITION); + + HardwareVertexBufferSharedPtr vbuf = + HardwareBufferManager::getSingleton().createVertexBuffer( + vertexDecl->getVertexSize(0), + vertexData->vertexCount, + HardwareBuffer::HBU_STATIC_WRITE_ONLY); + + // Bind buffer + bind->setBinding(0, vbuf); + // Upload data + float data[]={ + -1,1,-1, // corner 1 + -1,-1,-1, // corner 2 + 1,1,-1, // corner 3 + 1,-1,-1}; // corner 4 + vbuf->writeData(0, sizeof(data), data, true); +} + +void GeomUtils::createCone(const Ogre::String& strName , float radius , float height, int nVerticesInBase) +{ + MeshPtr pCone = MeshManager::getSingleton().createManual(strName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); + SubMesh *pConeVertex = pCone->createSubMesh(); + pCone->sharedVertexData = new VertexData(); + + createCone(pCone->sharedVertexData, pConeVertex->indexData + , radius + , height + , nVerticesInBase); + + // Generate face list + pConeVertex->useSharedVertices = true; + + // the original code was missing this line: + pCone->_setBounds( AxisAlignedBox( + Vector3(-radius, 0, -radius), + Vector3(radius, height, radius) ), false ); + + pCone->_setBoundingSphereRadius(Math::Sqrt(height*height + radius*radius)); + // this line makes clear the mesh is loaded (avoids memory leaks) + pCone->load(); +} + + +void GeomUtils::createCone(Ogre::VertexData*& vertexData, Ogre::IndexData*& indexData, + float radius , float height, int nVerticesInBase) +{ + assert(vertexData && indexData); + + // define the vertex format + VertexDeclaration* vertexDecl = vertexData->vertexDeclaration; + // positions + vertexDecl->addElement(0, 0, VET_FLOAT3, VES_POSITION); + + // allocate the vertex buffer + vertexData->vertexCount = nVerticesInBase + 1; + HardwareVertexBufferSharedPtr vBuf = HardwareBufferManager::getSingleton().createVertexBuffer(vertexDecl->getVertexSize(0), vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); + VertexBufferBinding* binding = vertexData->vertexBufferBinding; + binding->setBinding(0, vBuf); + float* pVertex = static_cast(vBuf->lock(HardwareBuffer::HBL_DISCARD)); + + // allocate index buffer - cone and base + indexData->indexCount = (3 * nVerticesInBase) + (3 * (nVerticesInBase - 2)); + indexData->indexBuffer = HardwareBufferManager::getSingleton().createIndexBuffer(HardwareIndexBuffer::IT_16BIT, indexData->indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); + HardwareIndexBufferSharedPtr iBuf = indexData->indexBuffer; + unsigned short* pIndices = static_cast(iBuf->lock(HardwareBuffer::HBL_DISCARD)); + + //Positions : cone head and base + for (int i=0; i<3; i++) + *pVertex++ = 0.0f; + + //Base : + float fDeltaBaseAngle = (2 * Math::PI) / nVerticesInBase; + for (int i=0; iunlock(); + iBuf->unlock(); +} + +} diff --git a/PlugIns/DeferredShading/src/OgreDS_LightMaterialGenerator.cpp b/PlugIns/DeferredShading/src/OgreDS_LightMaterialGenerator.cpp new file mode 100644 --- /dev/null +++ b/PlugIns/DeferredShading/src/OgreDS_LightMaterialGenerator.cpp @@ -0,0 +1,220 @@ +/****************************************************************************** +Copyright (c) W.J. van der Laan + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +Software, and to permit persons to whom the Software is furnished to do so, subject +to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies +or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +******************************************************************************/ + +#include "OgreDS_LightMaterialGenerator.h" + +#include "OgreStringConverter.h" +#include "OgreException.h" +#include "OgreMaterialManager.h" + +#include "OgrePass.h" +#include "OgreTechnique.h" + +#include "OgreHighLevelGpuProgram.h" +#include "OgreHighLevelGpuProgramManager.h" + +#include "OgreDS_DLight.h" + +namespace Ogre +{ + +//CG +class LightMaterialGeneratorCG : public MaterialGenerator::Impl +{ +public: + typedef MaterialGenerator::Perm Perm; + LightMaterialGeneratorCG(const String &baseName): + mBaseName(baseName) + { + + } + virtual ~LightMaterialGeneratorCG() + { + + } + + virtual GpuProgramPtr generateVertexShader(Perm permutation) + { + String programName = "DeferredShading/post/"; + + if (permutation & LightMaterialGenerator::MI_DIRECTIONAL) + { + programName += "vs"; + } + else + { + programName += "LightMaterial_vs"; + } + + GpuProgramPtr ptr = HighLevelGpuProgramManager::getSingleton().getByName(programName); + assert(!ptr.isNull()); + return ptr; + } + + virtual GpuProgramPtr generateFragmentShader(Perm permutation) + { + /// Create shader + if (mMasterSource.empty()) + { + DataStreamPtr ptrMasterSource = ResourceGroupManager::getSingleton().openResource( + "DeferredShading/post/LightMaterial_ps.cg" + , ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); + assert(ptrMasterSource.isNull()==false); + mMasterSource = ptrMasterSource->getAsString(); + } + + assert(mMasterSource.empty()==false); + + // Create name + String name = mBaseName+StringConverter::toString(permutation)+"_ps"; + + // Create shader object + HighLevelGpuProgramPtr ptrProgram = HighLevelGpuProgramManager::getSingleton().createProgram( + name, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, + "cg", GPT_FRAGMENT_PROGRAM); + ptrProgram->setSource(mMasterSource); + ptrProgram->setParameter("entry_point","main"); + ptrProgram->setParameter("profiles","ps_2_x arbfp1"); + // set up the preprocessor defines + // Important to do this before any call to get parameters, i.e. before the program gets loaded + ptrProgram->setParameter("compile_arguments", getPPDefines(permutation)); + + setUpBaseParameters(ptrProgram->getDefaultParameters()); + + return GpuProgramPtr(ptrProgram); + } + + virtual MaterialPtr generateTemplateMaterial(Perm permutation) + { + String materialName = mBaseName; + + if(permutation & LightMaterialGenerator::MI_DIRECTIONAL) + { + materialName += "Quad"; + } + else + { + materialName += "Geometry"; + } + + if(permutation & LightMaterialGenerator::MI_SHADOW_CASTER) + { + materialName += "Shadow"; + } + return MaterialManager::getSingleton().getByName(materialName); + } + + protected: + String mBaseName; + String mMasterSource; + // Utility method + String getPPDefines(Perm permutation) + { + String strPPD; + + //Get the type of light + String lightType; + if (permutation & LightMaterialGenerator::MI_POINT) + { + lightType = "POINT"; + } + else if (permutation & LightMaterialGenerator::MI_SPOTLIGHT) + { + lightType = "SPOT"; + } + else if (permutation & LightMaterialGenerator::MI_DIRECTIONAL) + { + lightType = "DIRECTIONAL"; + } + else + { + assert(false && "Permutation must have a light type"); + } + strPPD += "-DLIGHT_TYPE=LIGHT_" + lightType + " "; + + //Optional parameters + if (permutation & LightMaterialGenerator::MI_SPECULAR) + { + strPPD += "-DIS_SPECULAR "; + } + if (permutation & LightMaterialGenerator::MI_ATTENUATED) + { + strPPD += "-DIS_ATTENUATED "; + } + if (permutation & LightMaterialGenerator::MI_SHADOW_CASTER) + { + strPPD += "-DIS_SHADOW_CASTER "; + } + return strPPD; + } + + void setUpBaseParameters(const GpuProgramParametersSharedPtr& params) + { + assert(params.isNull()==false); + + struct AutoParamPair { String name; GpuProgramParameters::AutoConstantType type; }; + + //A list of auto params that might be present in the shaders generated + static const AutoParamPair AUTO_PARAMS[] = { + { "vpWidth", GpuProgramParameters::ACT_VIEWPORT_WIDTH }, + { "vpHeight", GpuProgramParameters::ACT_VIEWPORT_HEIGHT }, + { "worldView", GpuProgramParameters::ACT_WORLDVIEW_MATRIX }, + { "invProj", GpuProgramParameters::ACT_INVERSE_PROJECTION_MATRIX }, + { "invView", GpuProgramParameters::ACT_INVERSE_VIEW_MATRIX }, + { "flip", GpuProgramParameters::ACT_RENDER_TARGET_FLIPPING }, + { "lightDiffuseColor", GpuProgramParameters::ACT_LIGHT_DIFFUSE_COLOUR }, + { "lightSpecularColor", GpuProgramParameters::ACT_LIGHT_SPECULAR_COLOUR }, + { "lightFalloff", GpuProgramParameters::ACT_LIGHT_ATTENUATION }, + { "lightPos", GpuProgramParameters::ACT_LIGHT_POSITION_VIEW_SPACE }, + { "lightDir", GpuProgramParameters::ACT_LIGHT_DIRECTION_VIEW_SPACE }, + { "spotParams", GpuProgramParameters::ACT_SPOTLIGHT_PARAMS }, + { "farClipDistance", GpuProgramParameters::ACT_FAR_CLIP_DISTANCE }, + { "shadowViewProjMat", GpuProgramParameters::ACT_TEXTURE_VIEWPROJ_MATRIX } + }; + int numParams = sizeof(AUTO_PARAMS) / sizeof(AutoParamPair); + + for (int i=0; i_findNamedConstantDefinition(AUTO_PARAMS[i].name)) + { + params->setNamedAutoConstant(AUTO_PARAMS[i].name, AUTO_PARAMS[i].type); + } + } + } +}; + +LightMaterialGenerator::LightMaterialGenerator() +{ + vsMask = 0x00000004; + fsMask = 0x0000003F; + matMask = LightMaterialGenerator::MI_DIRECTIONAL | + LightMaterialGenerator::MI_SHADOW_CASTER; + + materialBaseName = "DeferredShading/LightMaterial/"; + mImpl = new LightMaterialGeneratorCG("DeferredShading/LightMaterial/"); +} + +LightMaterialGenerator::~LightMaterialGenerator() +{ + +} + +} diff --git a/PlugIns/DeferredShading/src/OgreDS_MaterialGenerator.cpp b/PlugIns/DeferredShading/src/OgreDS_MaterialGenerator.cpp new file mode 100644 --- /dev/null +++ b/PlugIns/DeferredShading/src/OgreDS_MaterialGenerator.cpp @@ -0,0 +1,119 @@ +/* +----------------------------------------------------------------------------- +This source file is part of OGRE +(Object-oriented Graphics Rendering Engine) +For the latest info, see http://www.ogre3d.org/ + +Copyright (c) 2000-2009 Torus Knot Software Ltd +Also see acknowledgements in Readme.html + +You may use this sample code for anything you like, it is not covered by the +same license as the rest of the engine. +----------------------------------------------------------------------------- +*/ + +#include "OgreDS_MaterialGenerator.h" + +#include "OgreStringConverter.h" +#include "OgreException.h" + +#include "OgrePass.h" +#include "OgreTechnique.h" + +#include "OgreHighLevelGpuProgram.h" +#include "OgreHighLevelGpuProgramManager.h" + +namespace Ogre +{ + +MaterialGenerator::MaterialGenerator(): + vsMask(0), fsMask(0), matMask(0), mImpl(0) +{ +} +MaterialGenerator::~MaterialGenerator() +{ + delete mImpl; +} + +const MaterialPtr &MaterialGenerator::getMaterial(Perm permutation) +{ + /// Check if material/shader permutation already was generated + MaterialMap::iterator i = mMaterials.find(permutation); + if(i != mMaterials.end()) + { + return i->second; + } + else + { + /// Create it + MaterialPtr templ = getTemplateMaterial(permutation & matMask); + GpuProgramPtr vs = getVertexShader(permutation & vsMask); + GpuProgramPtr fs = getFragmentShader(permutation & fsMask); + + /// Create material name + String name = materialBaseName + StringConverter::toString(permutation); + + std::cerr << name << " " << vs->getName() << " " << fs->getName() << std::endl; + /// Create material from template, and set shaders + MaterialPtr mat = templ->clone(name); + Technique *tech = mat->getTechnique(0); + Pass *pass = tech->getPass(0); + pass->setFragmentProgram(fs->getName()); + pass->setVertexProgram(vs->getName()); + + /// And store it + mMaterials[permutation] = mat; + return mMaterials[permutation]; + } +} + +const GpuProgramPtr &MaterialGenerator::getVertexShader(Perm permutation) +{ + ProgramMap::iterator i = mVs.find(permutation); + if(i != mVs.end()) + { + return i->second; + } + else + { + /// Create it + mVs[permutation] = mImpl->generateVertexShader(permutation); + return mVs[permutation]; + } +} + +const GpuProgramPtr &MaterialGenerator::getFragmentShader(Perm permutation) +{ + ProgramMap::iterator i = mFs.find(permutation); + if(i != mFs.end()) + { + return i->second; + } + else + { + /// Create it + mFs[permutation] = mImpl->generateFragmentShader(permutation); + return mFs[permutation]; + } +} + +const MaterialPtr &MaterialGenerator::getTemplateMaterial(Perm permutation) +{ + MaterialMap::iterator i = mTemplateMat.find(permutation); + if(i != mTemplateMat.end()) + { + return i->second; + } + else + { + /// Create it + mTemplateMat[permutation] = mImpl->generateTemplateMaterial(permutation); + return mTemplateMat[permutation]; + } +} + +MaterialGenerator::Impl::~Impl() +{ +} + +} diff --git a/PlugIns/DeferredShading/src/OgreDS_SSAOLogic.cpp b/PlugIns/DeferredShading/src/OgreDS_SSAOLogic.cpp new file mode 100644 --- /dev/null +++ b/PlugIns/DeferredShading/src/OgreDS_SSAOLogic.cpp @@ -0,0 +1,71 @@ +/* +----------------------------------------------------------------------------- +This source file is part of OGRE +(Object-oriented Graphics Rendering Engine) +For the latest info, see http://www.ogre3d.org/ + +Copyright (c) 2000-2009 Torus Knot Software Ltd +Also see acknowledgements in Readme.html + +You may use this sample code for anything you like, it is not covered by the +same license as the rest of the engine. +----------------------------------------------------------------------------- +*/ + +#include "OgreDS_SSAOLogic.h" + +#include + +namespace Ogre +{ + +class ssaoListener: public Ogre::CompositorInstance::Listener +{ +public: + + ssaoListener(Ogre::CompositorInstance* instance) : mInstance(instance) {} + + // this callback we will use to modify SSAO parameters + void notifyMaterialRender(Ogre::uint32 pass_id, Ogre::MaterialPtr &mat) + { + if (pass_id != 42) // not SSAO, return + return; + + // this is the camera you're using + Ogre::Camera *cam = mInstance->getChain()->getViewport()->getCamera(); + + // calculate the far-top-right corner in view-space + Ogre::Vector3 farCorner = cam->getViewMatrix(true) * cam->getWorldSpaceCorners()[4]; + + // get the pass + Ogre::Pass *pass = mat->getBestTechnique()->getPass(0); + + // get the vertex shader parameters + Ogre::GpuProgramParametersSharedPtr params = pass->getVertexProgramParameters(); + // set the camera's far-top-right corner + if (params->_findNamedConstantDefinition("farCorner")) + params->setNamedConstant("farCorner", farCorner); + + // get the fragment shader parameters + params = pass->getFragmentProgramParameters(); + // set the projection matrix we need + static const Ogre::Matrix4 CLIP_SPACE_TO_IMAGE_SPACE( + 0.5, 0, 0, 0.5, + 0, -0.5, 0, 0.5, + 0, 0, 1, 0, + 0, 0, 0, 1); + if (params->_findNamedConstantDefinition("ptMat")) + params->setNamedConstant("ptMat", CLIP_SPACE_TO_IMAGE_SPACE * cam->getProjectionMatrixWithRSDepth()); + if (params->_findNamedConstantDefinition("far")) + params->setNamedConstant("far", cam->getFarClipDistance()); + } +private: + Ogre::CompositorInstance* mInstance; +}; + +Ogre::CompositorInstance::Listener* SSAOLogic::createListener(Ogre::CompositorInstance* instance) +{ + return new ssaoListener(instance); +} + +} diff --git a/PlugIns/DeferredShading/src/OgreDeferredShadingManager.cpp b/PlugIns/DeferredShading/src/OgreDeferredShadingManager.cpp new file mode 100644 --- /dev/null +++ b/PlugIns/DeferredShading/src/OgreDeferredShadingManager.cpp @@ -0,0 +1,71 @@ +/* +----------------------------------------------------------------------------- +This source file is part of OGRE +(Object-oriented Graphics Rendering Engine) +For the latest info, see http://www.ogre3d.org/ + +Copyright (c) 2000-2009 Torus Knot Software Ltd +Also see acknowledgements in Readme.html + +You may use this sample code for anything you like, it is not covered by the +same license as the rest of the engine. +----------------------------------------------------------------------------- +*/ +#include +#include + +#include "OgreDeferredShadingManager.h" +#include "OgreDS_DeferredLightCP.h" +#include "OgreDS_GBufferSchemeHandler.h" +#include "OgreDS_NullSchemeHandler.h" + +namespace Ogre { + +template<> DeferredShadingManager* Singleton::ms_Singleton = 0; +DeferredShadingManager* DeferredShadingManager::getSingletonPtr(void) +{ + return ms_Singleton; +} +DeferredShadingManager& DeferredShadingManager::getSingleton(void) +{ + assert( ms_Singleton ); return ( *ms_Singleton ); +} + +DeferredShadingManager::DeferredShadingManager(): + mGBufferSchemeHandler(new GBufferSchemeHandler), + mNullSchemeHandler(new NullSchemeHandler), + mDeferredLightCompositionPass(new DeferredLightCompositionPass), + mDefaultMaterialSchemeName(MaterialManager::DEFAULT_SCHEME_NAME) +{ + MaterialManager::getSingleton().addListener(mGBufferSchemeHandler, "GBuffer"); + MaterialManager::getSingleton().addListener(mNullSchemeHandler, "NoGBuffer"); + CompositorManager::getSingleton().registerCustomCompositionPass("DeferredLight", new DeferredLightCompositionPass); +} + +void DeferredShadingManager::addSceneManager(SceneManager* sm) +{ + //apply scene manager settings that are required for Deferred Shading + sm->setShadowTechnique(SHADOWTYPE_TEXTURE_ADDITIVE); + sm->setShadowTextureCasterMaterial("DeferredShading/Shadows/Caster"); + sm->setShadowTextureCount(1); + sm->setShadowFarDistance(150); + //Use a value of "2" to use a different depth buffer pool and avoid sharing this with the Backbuffer's + sm->setShadowTextureConfig( 0, 512, 512, PF_FLOAT16_R, 2 ); + sm->setShadowDirectionalLightExtrusionDistance(75); + mSceneManagers.push_back(sm); +} +void DeferredShadingManager::removeSceneManager(SceneManager* sm) +{ + HashedVector::iterator iter; + for (iter = mSceneManagers.begin(); iter != mSceneManagers.end(); ++iter) + if(*iter == sm) + break; + mSceneManagers.erase(iter); +} + +DeferredShadingManager::~DeferredShadingManager() { + MaterialManager::getSingleton().removeListener(mGBufferSchemeHandler, "GBuffer"); + MaterialManager::getSingleton().removeListener(mNullSchemeHandler, "NoGBuffer"); +} + +} diff --git a/PlugIns/DeferredShading/src/OgreDeferredShadingPlugin.cpp b/PlugIns/DeferredShading/src/OgreDeferredShadingPlugin.cpp new file mode 100644 --- /dev/null +++ b/PlugIns/DeferredShading/src/OgreDeferredShadingPlugin.cpp @@ -0,0 +1,67 @@ +/* +----------------------------------------------------------------------------- +This source file is part of OGRE +(Object-oriented Graphics Rendering Engine) +For the latest info, see http://www.ogre3d.org/ + +Copyright (c) 2000-2009 Torus Knot Software Ltd +Also see acknowledgements in Readme.html + +You may use this sample code for anything you like, it is not covered by the +same license as the rest of the engine. +----------------------------------------------------------------------------- +*/ + +#include "OgreDeferredShadingPlugin.h" +#include "OgreRoot.h" + +namespace Ogre +{ + const String sPluginName = "Deferred Shading System"; + //--------------------------------------------------------------------- + DeferredShadingPlugin::DeferredShadingPlugin(): + manager(0) + { + + } + //--------------------------------------------------------------------- + const String& DeferredShadingPlugin::getName() const + { + return sPluginName; + } + //--------------------------------------------------------------------- + void DeferredShadingPlugin::install() + { + } + //--------------------------------------------------------------------- + void DeferredShadingPlugin::initialise() + { + RenderSystem *rs = Root::getSingleton().getRenderSystem(); + const RenderSystemCapabilities* caps = rs->getCapabilities(); + if (!caps->hasCapability(RSC_VERTEX_PROGRAM) || !(caps->hasCapability(RSC_FRAGMENT_PROGRAM))) + { + OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED, "Your card does not support vertex and fragment programs, so cannot " + "use Deferred Shading Plugin. Sorry!", + "DeferredShadingPlugin::initialise"); + } + if (caps->getNumMultiRenderTargets()<2) + { + OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED, "Your card does not support at least two simultaneous render targets, so cannot " + "use Deferred Shading Plugin. Sorry!", + "DeferredShadingPlugin::initialise"); + } + manager = new DeferredShadingManager(); + } + //--------------------------------------------------------------------- + void DeferredShadingPlugin::shutdown() + { + delete manager; + manager = 0; + } + //--------------------------------------------------------------------- + void DeferredShadingPlugin::uninstall() + { + } + + +} diff --git a/Samples/DeferredShading/include/AmbientLight.h b/Samples/DeferredShading/include/AmbientLight.h deleted file mode 100644 --- a/Samples/DeferredShading/include/AmbientLight.h +++ /dev/null @@ -1,53 +0,0 @@ -/* ------------------------------------------------------------------------------ -This source file is part of OGRE -(Object-oriented Graphics Rendering Engine) -For the latest info, see http://www.ogre3d.org/ - -Copyright (c) 2000-2009 Torus Knot Software Ltd -Also see acknowledgements in Readme.html - -You may use this sample code for anything you like, it is not covered by the -same license as the rest of the engine. ------------------------------------------------------------------------------ -*/ - -#ifndef _AMBIENTLIGHT_H -#define _AMBIENTLIGHT_H - -#include "OgreSimpleRenderable.h" - -// Renderable for rendering Ambient component and also to -// establish the depths - -// Just instantiation is sufficient -// Note that instantiation is necessary to at least establish the depths -// even if the current ambient colour is 0 - -// its ambient colour is same as the scene's ambient colour - -// XXX Could make this a singleton/make it private to the DeferredShadingSystem e.g. - -class AmbientLight : public Ogre::SimpleRenderable - -{ -public: - AmbientLight(); - ~AmbientLight(); - - /** @copydoc MovableObject::getBoundingRadius */ - virtual Ogre::Real getBoundingRadius(void) const; - /** @copydoc Renderable::getSquaredViewDepth */ - virtual Ogre::Real getSquaredViewDepth(const Ogre::Camera*) const; - /** @copydoc Renderable::getMaterial */ - virtual const Ogre::MaterialPtr& getMaterial(void) const; - - virtual void getWorldTransforms(Ogre::Matrix4* xform) const; - - void updateFromCamera(Ogre::Camera* camera); -protected: - Ogre::Real mRadius; - Ogre::MaterialPtr mMatPtr; -}; - -#endif diff --git a/Samples/DeferredShading/include/DLight.h b/Samples/DeferredShading/include/DLight.h deleted file mode 100644 --- a/Samples/DeferredShading/include/DLight.h +++ /dev/null @@ -1,93 +0,0 @@ -/* ------------------------------------------------------------------------------ -This source file is part of OGRE -(Object-oriented Graphics Rendering Engine) -For the latest info, see http://www.ogre3d.org/ - -Copyright (c) 2000-2009 Torus Knot Software Ltd -Also see acknowledgements in Readme.html - -You may use this sample code for anything you like, it is not covered by the -same license as the rest of the engine. ------------------------------------------------------------------------------ -*/ - -#ifndef H_WJ_DLight -#define H_WJ_DLight - -#include "OgreSimpleRenderable.h" -#include "MaterialGenerator.h" - -/** Deferred light geometry. Each instance matches a normal light. - Should not be created by the user. - XXX support other types of light other than point lights. - */ -class DLight: public Ogre::SimpleRenderable -{ -public: - DLight(MaterialGenerator *gen, Ogre::Light* parentLight); - ~DLight(); - - /** Update the information from the light that matches this one - */ - void updateFromParent(); - - /** Update the information that is related to the camera - */ - void updateFromCamera(Ogre::Camera* camera); - - /** Does this light cast shadows? - */ - virtual bool getCastChadows() const; - - /** @copydoc MovableObject::getBoundingRadius */ - virtual Ogre::Real getBoundingRadius(void) const; - /** @copydoc Renderable::getSquaredViewDepth */ - virtual Ogre::Real getSquaredViewDepth(const Ogre::Camera*) const; - /** @copydoc Renderable::getMaterial */ - virtual const Ogre::MaterialPtr& getMaterial(void) const; - /** @copydoc Renderable::getBoundingRadius */ - virtual void getWorldTransforms(Ogre::Matrix4* xform) const; -protected: - - /** Check if the camera is inside a light - */ - bool isCameraInsideLight(Ogre::Camera* camera); - - /** Create geometry for this light. - */ - void rebuildGeometry(float radius); - - /** Create a sphere geometry. - */ - void createSphere(float radius, int nRings, int nSegments); - - /** Create a rectangle. - */ - void createRectangle2D(); - - /** Create a cone. - */ - void createCone(float radius, float height, int nVerticesInBase); - - /** Set constant, linear, quadratic Attenuation terms - */ - void setAttenuation(float c, float b, float a); - - /** Set the specular colour - */ - void setSpecularColour(const Ogre::ColourValue &col); - - /// The light that this DLight renders - Ogre::Light* mParentLight; - /// Mode to ignore world orientation/position - bool bIgnoreWorld; - /// Bounding sphere radius - float mRadius; - /// Deferred shading system this minilight is part of - MaterialGenerator *mGenerator; - /// Material permutation - Ogre::uint32 mPermutation; -}; - -#endif diff --git a/Samples/DeferredShading/include/DeferredLightCP.h b/Samples/DeferredShading/include/DeferredLightCP.h deleted file mode 100644 --- a/Samples/DeferredShading/include/DeferredLightCP.h +++ /dev/null @@ -1,78 +0,0 @@ -/* ------------------------------------------------------------------------------ -This source file is part of OGRE -(Object-oriented Graphics Rendering Engine) -For the latest info, see http://www.ogre3d.org/ - -Copyright (c) 2000-2009 Torus Knot Software Ltd -Also see acknowledgements in Readme.html - -You may use this sample code for anything you like, it is not covered by the -same license as the rest of the engine. ------------------------------------------------------------------------------ -*/ - -#ifndef _DEFERRED_LIGHT_CP_H -#define _DEFERRED_LIGHT_CP_H - -#include "OgreCompositorInstance.h" -#include "OgreCustomCompositionPass.h" - -#include "DLight.h" -#include "MaterialGenerator.h" -#include "AmbientLight.h" - -//The render operation that will be called each frame in the custom composition pass -//This is the class that will send the actual render calls of the spheres (point lights), -//cones (spotlights) and quads (directional lights) after the GBuffer has been constructed -class DeferredLightRenderOperation : public Ogre::CompositorInstance::RenderSystemOperation -{ -public: - DeferredLightRenderOperation(Ogre::CompositorInstance* instance, const Ogre::CompositionPass* pass); - - /** @copydoc CompositorInstance::RenderSystemOperation::execute */ - virtual void execute(Ogre::SceneManager *sm, Ogre::RenderSystem *rs); - - virtual ~DeferredLightRenderOperation(); -private: - - /** Create a new deferred light - */ - DLight *createDLight(Ogre::Light* light); - - //The texture names of the GBuffer components - Ogre::String mTexName0; - Ogre::String mTexName1; - - //The material generator for the light geometry - MaterialGenerator* mLightMaterialGenerator; - - //The map of deferred light geometries already constructed - typedef std::map LightsMap; - LightsMap mLights; - - //The ambient light used to render the scene - AmbientLight* mAmbientLight; - - //The viewport that we are rendering to - Ogre::Viewport* mViewport; -}; - -//The custom composition pass that is used for rendering the light geometry -//This class needs to be registered with the CompositorManager -class DeferredLightCompositionPass : public Ogre::CustomCompositionPass -{ -public: - - /** @copydoc CustomCompositionPass::createOperation */ - virtual Ogre::CompositorInstance::RenderSystemOperation* createOperation( - Ogre::CompositorInstance* instance, const Ogre::CompositionPass* pass) - { - return OGRE_NEW DeferredLightRenderOperation(instance, pass); - } - -protected: - virtual ~DeferredLightCompositionPass() {} -}; - -#endif diff --git a/Samples/DeferredShading/include/DeferredShading.h b/Samples/DeferredShading/include/DeferredShading.h deleted file mode 100755 --- a/Samples/DeferredShading/include/DeferredShading.h +++ /dev/null @@ -1,126 +0,0 @@ -/* ------------------------------------------------------------------------------ -This source file is part of OGRE -(Object-oriented Graphics Rendering Engine) -For the latest info, see http://www.ogre3d.org/ - -Copyright (c) 2000-2009 Torus Knot Software Ltd -Also see acknowledgements in Readme.html - -You may use this sample code for anything you like, it is not covered by the -same license as the rest of the engine. ------------------------------------------------------------------------------ -*/ - -/** -Implementation of a Deferred Shading engine in OGRE, using Multiple Render Targets and -CG high level language shaders. - // W.J. :wumpus: van der Laan 2005 / Noam Gat 2009 // - -Deferred shading renders the scene to a 'fat' texture format, using a shader that outputs colour, -normal, depth, and possible other attributes per fragment. Multi Render Target is required as we -are dealing with many outputs which get written into multiple render textures in the same pass. - -After rendering the scene in this format, the shading (lighting) can be done as a post process. -This means that lighting is done in screen space, using light-representing geometry (sphere for -point light, cone for spot light and quad for directional) to render their contribution. - -The wiki article explaining this demo can be found here : - http://www.ogre3d.org/wiki/index.php/Deferred_Shading -*/ - -#ifndef H_DeferredShadingSystem -#define H_DeferredShadingSystem - -#include "Ogre.h" -#include "SdkSample.h" - -#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 -#define WIN32_LEAN_AND_MEAN -#include "windows.h" -#endif - -#include "OgreCompositorInstance.h" -#include "OgreSceneManager.h" -#include "OgreSceneNode.h" -#include "OgreMaterial.h" -#include "OgreRenderTargetListener.h" -#include "GeomUtils.h" - -using namespace Ogre; -using namespace OgreBites; - -/** System to manage Deferred Shading for a camera/render target. - * @note With the changes to the compositor framework, this class just - * selects which compositors to enable. - */ -class DeferredShadingSystem : public Ogre::RenderTargetListener -{ -public: - DeferredShadingSystem(Ogre::Viewport *vp, Ogre::SceneManager *sm, Ogre::Camera *cam); - ~DeferredShadingSystem(); - - enum DSMode - { - DSM_SHOWLIT = 0, // The deferred shading mode - DSM_SHOWCOLOUR = 1, // Show diffuse (for debugging) - DSM_SHOWNORMALS = 2, // Show normals (for debugging) - DSM_SHOWDSP = 3, // Show depth and specular channel (for debugging) - DSM_COUNT = 4 - }; - - //The first render queue that does get rendered into the GBuffer - //place objects (like skies) that should be before gbuffer before this one. - static const Ogre::uint8 PRE_GBUFFER_RENDER_QUEUE; - - //The first render queue that does not get rendered into the GBuffer - //place transparent (or other non gbuffer) objects after this one - static const Ogre::uint8 POST_GBUFFER_RENDER_QUEUE; - - void initialize(); - - /** Set rendering mode (one of DSMode) - */ - void setMode(DSMode mode); - - DSMode getMode(void) const; - - /** Set screen space ambient occlusion mode - */ - void setSSAO(bool ssao); - - bool getSSAO() const; - - /** Activate or deactivate system - */ - void setActive(bool active); - -protected: - Ogre::Viewport *mViewport; - Ogre::SceneManager *mSceneMgr; - Ogre::Camera *mCamera; - - Ogre::CompositorInstance *mGBufferInstance; - // Filters - Ogre::CompositorInstance *mInstance[DSM_COUNT]; - Ogre::CompositorInstance* mSSAOInstance; - // Active/inactive - bool mActive; - DSMode mCurrentMode; - bool mSSAO; - - //Used to unregister compositor logics and free memory - typedef map::type CompositorLogicMap; - CompositorLogicMap mCompositorLogics; - - void createResources(); - - void logCurrentMode(void); -}; - -const ColourValue SAMPLE_COLORS[] = -{ ColourValue::Red, ColourValue::Green, ColourValue::Blue, - ColourValue::White, ColourValue(1,1,0,1), ColourValue(1,0,1,1) -}; - -#endif diff --git a/Samples/DeferredShading/include/GBufferMaterialGenerator.h b/Samples/DeferredShading/include/GBufferMaterialGenerator.h deleted file mode 100644 --- a/Samples/DeferredShading/include/GBufferMaterialGenerator.h +++ /dev/null @@ -1,69 +0,0 @@ -/* ------------------------------------------------------------------------------ -This source file is part of OGRE -(Object-oriented Graphics Rendering Engine) -For the latest info, see http://www.ogre3d.org/ - -Copyright (c) 2000-2009 Torus Knot Software Ltd -Also see acknowledgements in Readme.html - -You may use this sample code for anything you like, it is not covered by the -same license as the rest of the engine. ------------------------------------------------------------------------------ -*/ - - -#ifndef _GBUFFER_MATERIAL_GENERATOR_H_ -#define _GBUFFER_MATERIAL_GENERATOR_H_ - -#include "MaterialGenerator.h" - -/** Class for generating materials for objects to render themselves to the GBuffer - * @note This does not support all the possible rendering techniques out there. - * in order to support more, either expand this class or make sure that objects - * that will not get treated correctly will not have materials generated for them. - */ -class GBufferMaterialGenerator : public MaterialGenerator -{ -public: - - //Constructor - GBufferMaterialGenerator(); - - //The relevant options for objects that are rendered to the GBuffer - enum GBufferPermutations - { - //(Regular) Textures - GBP_NO_TEXTURES = 0x00000000, - GBP_ONE_TEXTURE = 0x00000001, - GBP_TWO_TEXTURES = 0x00000002, - GBP_THREE_TEXTURES = 0x00000003, - GBP_TEXTURE_MASK = 0x0000000F, - - //Material properties - GBP_HAS_DIFFUSE_COLOUR = 0x00000010, - - //The number of texture coordinate sets - GBP_NO_TEXCOORDS = 0x00000000, - GBP_ONE_TEXCOORD = 0x00000100, - GBP_TWO_TEXCOORDS = 0x00000200, - GBP_TEXCOORD_MASK = 0x00000700, - - //Do we have a normal map - GBP_NORMAL_MAP = 0x00000800, - - //Are we skinned? - GBP_SKINNED = 0x00010000 - }; - - //The mask of the flags that matter for generating the fragment shader - static const Ogre::uint32 FS_MASK = 0x0000FFFF; - - //The mask of the flags that matter for generating the vertex shader - static const Ogre::uint32 VS_MASK = 0x00FFFF00; - - //The mask of the flags that matter for generating the material - static const Ogre::uint32 MAT_MASK = 0xFF00FFFF; -}; - -#endif diff --git a/Samples/DeferredShading/include/GBufferSchemeHandler.h b/Samples/DeferredShading/include/GBufferSchemeHandler.h deleted file mode 100644 --- a/Samples/DeferredShading/include/GBufferSchemeHandler.h +++ /dev/null @@ -1,73 +0,0 @@ -/* ------------------------------------------------------------------------------ -This source file is part of OGRE -(Object-oriented Graphics Rendering Engine) -For the latest info, see http://www.ogre3d.org/ - -Copyright (c) 2000-2009 Torus Knot Software Ltd -Also see acknowledgements in Readme.html - -You may use this sample code for anything you like, it is not covered by the -same license as the rest of the engine. ------------------------------------------------------------------------------ -*/ - - -#ifndef _GBUFFERSCHEMEHANDLER_H -#define _GBUFFERSCHEMEHANDLER_H - -#include -#include "GBufferMaterialGenerator.h" - -/** Class for handling materials who did not specify techniques for rendering - * themselves into the GBuffer. This class allows deferred shading to be used, - * without having to specify new techniques for all the objects in the scene. - * @note This does not support all the possible rendering techniques out there. - * in order to support more, either expand this class or specify the techniques - * in the materials. - */ -class GBufferSchemeHandler : public Ogre::MaterialManager::Listener -{ -public: - /** @copydoc MaterialManager::Listener::handleSchemeNotFound */ - virtual Ogre::Technique* handleSchemeNotFound(unsigned short schemeIndex, - const Ogre::String& schemeName, Ogre::Material* originalMaterial, unsigned short lodIndex, - const Ogre::Renderable* rend); -protected: - //The material generator - GBufferMaterialGenerator mMaterialGenerator; - - //The string that will be checked in textures to determine whether they are normal maps - static const Ogre::String NORMAL_MAP_PATTERN; - - //A structure for containing the properties of a material, relevant to GBuffer rendering - //You might need to expand this class to support more options - struct PassProperties - { - PassProperties() : isDeferred(true), normalMap(0), isSkinned(false) {} - - bool isDeferred; - Ogre::vector::type regularTextures; - Ogre::TextureUnitState* normalMap; - bool isSkinned; - bool hasDiffuseColour; - - //Example of possible extension : vertex colours - //Ogre::TrackVertexColourType vertexColourType; - }; - - //Inspect a technique and return its relevant properties - PassProperties inspectPass(Ogre::Pass* pass, - unsigned short lodIndex, const Ogre::Renderable* rend); - - //Get the permutation of material flags that fit a certain property sheet - MaterialGenerator::Perm getPermutation(const PassProperties& props); - - //Fill a pass with the specific data from the pass it is based on - void fillPass(Ogre::Pass* gBufferPass, Ogre::Pass* originalPass, const PassProperties& props); - - //Check if a texture is a normal map, and fill property sheet accordingly - bool checkNormalMap(Ogre::TextureUnitState* tus, PassProperties& props); -}; - -#endif diff --git a/Samples/DeferredShading/include/GeomUtils.h b/Samples/DeferredShading/include/GeomUtils.h deleted file mode 100644 --- a/Samples/DeferredShading/include/GeomUtils.h +++ /dev/null @@ -1,61 +0,0 @@ -/* ------------------------------------------------------------------------------ -This source file is part of OGRE -(Object-oriented Graphics Rendering Engine) -For the latest info, see http://www.ogre3d.org/ - -Copyright (c) 2000-2009 Torus Knot Software Ltd -Also see acknowledgements in Readme.html - -You may use this sample code for anything you like, it is not covered by the -same license as the rest of the engine. ------------------------------------------------------------------------------ -*/ - -#ifndef _GEOMUTILS_H -#define _GEOMUTILS_H - -#include "OgreString.h" -#include "OgreVertexIndexData.h" - -class GeomUtils -{ -public: - // Create a sphere Mesh with a given name, radius, number of rings and number of segments - static void createSphere(const Ogre::String& strName - , float radius - , int nRings, int nSegments - , bool bNormals - , bool bTexCoords - ); - - - // Fill up a fresh copy of VertexData and IndexData with a sphere's coords given the number of rings and the number of segments - static void createSphere(Ogre::VertexData*& vertexData, Ogre::IndexData*& indexData - , float radius - , int nRings, int nSegments - , bool bNormals - , bool bTexCoords); - - // Create a cone Mesh with a given name, radius and number of vertices in base - // Created cone will have its head at 0,0,0, and will 'expand to' positive y - static void createCone(const Ogre::String& strName - , float radius - , float height - , int nVerticesInBase); - - // Fill up a fresh copy of VertexData and IndexData with a cone's coords given the radius and number of vertices in base - static void createCone(Ogre::VertexData*& vertexData, Ogre::IndexData*& indexData - , float radius - , float height - , int nVerticesInBase); - - - // Fill up a fresh copy of VertexData with a normalized quad - static void createQuad(Ogre::VertexData*& vertexData); - - -}; - - -#endif diff --git a/Samples/DeferredShading/include/LightMaterialGenerator.h b/Samples/DeferredShading/include/LightMaterialGenerator.h deleted file mode 100755 --- a/Samples/DeferredShading/include/LightMaterialGenerator.h +++ /dev/null @@ -1,40 +0,0 @@ -/* ------------------------------------------------------------------------------ -This source file is part of OGRE -(Object-oriented Graphics Rendering Engine) -For the latest info, see http://www.ogre3d.org/ - -Copyright (c) 2000-2009 Torus Knot Software Ltd -Also see acknowledgements in Readme.html - -You may use this sample code for anything you like, it is not covered by the -same license as the rest of the engine. ------------------------------------------------------------------------------ -*/ - -#ifndef H_WJ_LightMaterialGenerator -#define H_WJ_LightMaterialGenerator - -#include "MaterialGenerator.h" - -class LightMaterialGenerator: public MaterialGenerator -{ -public: - /** Permutation of light materials - */ - enum MaterialID - { - MI_POINT = 0x01, // Is a point light - MI_SPOTLIGHT = 0x02, // Is a spot light - MI_DIRECTIONAL = 0x04, // Is a directional light - - MI_ATTENUATED = 0x08, // Rendered attenuated - MI_SPECULAR = 0x10, // Specular component is calculated - MI_SHADOW_CASTER = 0x20 // Will cast shadows - }; - - LightMaterialGenerator(); - virtual ~LightMaterialGenerator(); -}; - -#endif diff --git a/Samples/DeferredShading/include/ListenerFactoryLogic.h b/Samples/DeferredShading/include/ListenerFactoryLogic.h deleted file mode 100644 --- a/Samples/DeferredShading/include/ListenerFactoryLogic.h +++ /dev/null @@ -1,51 +0,0 @@ -/* ------------------------------------------------------------------------------ -This source file is part of OGRE -(Object-oriented Graphics Rendering Engine) -For the latest info, see http://www.ogre3d.org/ - -Copyright (c) 2000-2006 Torus Knot Software Ltd -Also see acknowledgements in Readme.html - -You may use this sample code for anything you like, it is not covered by the -conditions of the standard open source license. ------------------------------------------------------------------------------ -*/ - -#ifndef _LISTENER_FACTORY_LOGIC_H -#define _LISTENER_FACTORY_LOGIC_H - -#include -#include -#include - -//The simple types of compositor logics will all do the same thing - -//Attach a listener to the created compositor -class ListenerFactoryLogic : public Ogre::CompositorLogic -{ -public: - /** @copydoc CompositorLogic::compositorInstanceCreated */ - virtual void compositorInstanceCreated(Ogre::CompositorInstance* newInstance) - { - Ogre::CompositorInstance::Listener* listener = createListener(newInstance); - newInstance->addListener(listener); - mListeners[newInstance] = listener; - } - - /** @copydoc CompositorLogic::compositorInstanceDestroyed */ - virtual void compositorInstanceDestroyed(Ogre::CompositorInstance* destroyedInstance) - { - delete mListeners[destroyedInstance]; - mListeners.erase(destroyedInstance); - } - -protected: - //This is the method that implementers will need to create - virtual Ogre::CompositorInstance::Listener* createListener(Ogre::CompositorInstance* instance) = 0; -private: - typedef std::map ListenerMap; - ListenerMap mListeners; - -}; - -#endif diff --git a/Samples/DeferredShading/include/MaterialGenerator.h b/Samples/DeferredShading/include/MaterialGenerator.h deleted file mode 100755 --- a/Samples/DeferredShading/include/MaterialGenerator.h +++ /dev/null @@ -1,82 +0,0 @@ -/* ------------------------------------------------------------------------------ -This source file is part of OGRE -(Object-oriented Graphics Rendering Engine) -For the latest info, see http://www.ogre3d.org/ - -Copyright (c) 2000-2009 Torus Knot Software Ltd -Also see acknowledgements in Readme.html - -You may use this sample code for anything you like, it is not covered by the -same license as the rest of the engine. ------------------------------------------------------------------------------ -*/ - -#ifndef H_WJ_MaterialGenerator -#define H_WJ_MaterialGenerator - -#include "OgreMaterial.h" -#include "OgreStringVector.h" - -/** Caching, on-the-fly material generator. This is a class that automatically - generates and stores different permutations of a material, and its shaders. - It can be used if you have a material that has lots of slightly different - variations, like whether to use a specular light, skinning, normal mapping - and other options. Writing all these out is a tedious job. Of course it is - possible to always use the material with all features, but that might result - in large, slow shader programs. This class provides an efficient solution - to that. - */ -class MaterialGenerator -{ -public: - /** Bitfield used to signify a material permutations */ - typedef Ogre::uint32 Perm; - virtual ~MaterialGenerator(); - - const Ogre::MaterialPtr &getMaterial(Perm permutation); - - /** Implementation class that takes care of actual generation or lookup - of the various constituent parts (template material, fragment shader - and vertex shader). These methods are only called once for every permutation, - after which the result is stored and re-used. - */ - class Impl - { - public: - virtual ~Impl(); - virtual Ogre::GpuProgramPtr generateVertexShader(Perm permutation) = 0; - virtual Ogre::GpuProgramPtr generateFragmentShader(Perm permutation) = 0; - virtual Ogre::MaterialPtr generateTemplateMaterial(Perm permutation) = 0; - }; -protected: - /** The constructor is protected as this base class should never be constructed - as-is. It is meant to be subclassed so that values can be assigned to - the various fields controlling material generator, and most importantly, the - mImpl field. - */ - MaterialGenerator(); - - const Ogre::GpuProgramPtr &getVertexShader(Perm permutation); - const Ogre::GpuProgramPtr &getFragmentShader(Perm permutation); - const Ogre::MaterialPtr &getTemplateMaterial(Perm permutation); - - /// Base name of materials generated by this - Ogre::String materialBaseName; - /// Mask of permutation bits that influence vertex shader choice - Perm vsMask; - /// Mask of permutation bits that influence fragment shader choice - Perm fsMask; - /// Mask of permutation bits that influence template material choice - Perm matMask; - /// Generator - Impl *mImpl; - - typedef Ogre::map::type ProgramMap; - typedef Ogre::map::type MaterialMap; - - ProgramMap mVs, mFs; - MaterialMap mTemplateMat, mMaterials; -}; - -#endif diff --git a/Samples/DeferredShading/include/NullSchemeHandler.h b/Samples/DeferredShading/include/NullSchemeHandler.h deleted file mode 100644 --- a/Samples/DeferredShading/include/NullSchemeHandler.h +++ /dev/null @@ -1,38 +0,0 @@ -/* ------------------------------------------------------------------------------ -This source file is part of OGRE -(Object-oriented Graphics Rendering Engine) -For the latest info, see http://www.ogre3d.org/ - -Copyright (c) 2000-2009 Torus Knot Software Ltd -Also see acknowledgements in Readme.html - -You may use this sample code for anything you like, it is not covered by the -same license as the rest of the engine. ------------------------------------------------------------------------------ -*/ - -#ifndef _NULLSCHEMEHANDLER_H -#define _NULLSCHEMEHANDLER_H - -#include - -/** Class for skipping materials which do not have the scheme defined - */ -class NullSchemeHandler : public Ogre::MaterialManager::Listener -{ -public: - /** @copydoc MaterialManager::Listener::handleSchemeNotFound */ - virtual Ogre::Technique* handleSchemeNotFound(unsigned short schemeIndex, - const Ogre::String& schemeName, Ogre::Material* originalMaterial, unsigned short lodIndex, - const Ogre::Renderable* rend) - { - //Creating a technique so the handler only gets called once per material - Ogre::Technique* emptyTech = originalMaterial->createTechnique(); - emptyTech->removeAllPasses(); - emptyTech->setSchemeName(schemeName); - return emptyTech; - } -}; - -#endif diff --git a/Samples/DeferredShading/include/SSAOLogic.h b/Samples/DeferredShading/include/SSAOLogic.h deleted file mode 100644 --- a/Samples/DeferredShading/include/SSAOLogic.h +++ /dev/null @@ -1,27 +0,0 @@ -/* ------------------------------------------------------------------------------ -This source file is part of OGRE -(Object-oriented Graphics Rendering Engine) -For the latest info, see http://www.ogre3d.org/ - -Copyright (c) 2000-2009 Torus Knot Software Ltd -Also see acknowledgements in Readme.html - -You may use this sample code for anything you like, it is not covered by the -same license as the rest of the engine. ------------------------------------------------------------------------------ -*/ - -#ifndef _SSAOLOGIC_H -#define _SSAOLOGIC_H - -#include "ListenerFactoryLogic.h" - -class SSAOLogic : public ListenerFactoryLogic -{ -protected: - /** @copydoc ListenerFactoryLogic::createListener */ - virtual Ogre::CompositorInstance::Listener* createListener(Ogre::CompositorInstance* instance); -}; - -#endif diff --git a/Samples/DeferredShading/src/AmbientLight.cpp b/Samples/DeferredShading/src/AmbientLight.cpp deleted file mode 100644 --- a/Samples/DeferredShading/src/AmbientLight.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/* ------------------------------------------------------------------------------ -This source file is part of OGRE -(Object-oriented Graphics Rendering Engine) -For the latest info, see http://www.ogre3d.org/ - -Copyright (c) 2000-2009 Torus Knot Software Ltd -Also see acknowledgements in Readme.html - -You may use this sample code for anything you like, it is not covered by the -same license as the rest of the engine. ------------------------------------------------------------------------------ -*/ - - -#include "AmbientLight.h" -#include "GeomUtils.h" -#include "OgreMaterialManager.h" -#include "OgreRoot.h" -#include "OgreRenderSystem.h" - -using namespace Ogre; - -AmbientLight::AmbientLight() -{ - setRenderQueueGroup(RENDER_QUEUE_2); - - mRenderOp.vertexData = new VertexData(); - mRenderOp.indexData = 0; - - GeomUtils::createQuad(mRenderOp.vertexData); - - mRenderOp.operationType = RenderOperation::OT_TRIANGLE_STRIP; - mRenderOp.useIndexes = false; - - // Set bounding - setBoundingBox(AxisAlignedBox(-10000,-10000,-10000,10000,10000,10000)); - mRadius = 15000; - - mMatPtr = MaterialManager::getSingleton().getByName("DeferredShading/AmbientLight"); - assert(mMatPtr.isNull()==false); - mMatPtr->load(); - - //This shader needs to be aware if its running under OpenGL or DirectX. - //Real depthFactor = (Root::getSingleton().getRenderSystem()->getName() == - // "OpenGL Rendering Subsystem") ? 2.0 : 1.0; - //mMatPtr->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant( - // "depthFactor", depthFactor); -} - -AmbientLight::~AmbientLight() -{ - // need to release IndexData and vertexData created for renderable - delete mRenderOp.indexData; - delete mRenderOp.vertexData; -} - -/** @copydoc MovableObject::getBoundingRadius */ -Real AmbientLight::getBoundingRadius(void) const -{ - return mRadius; - -} -/** @copydoc Renderable::getSquaredViewDepth */ -Real AmbientLight::getSquaredViewDepth(const Camera*) const -{ - return 0.0; -} - -const MaterialPtr& AmbientLight::getMaterial(void) const -{ - return mMatPtr; -} - -void AmbientLight::getWorldTransforms(Ogre::Matrix4* xform) const -{ - *xform = Matrix4::IDENTITY; -} -void AmbientLight::updateFromCamera(Ogre::Camera* camera) -{ - Ogre::Technique* tech = getMaterial()->getBestTechnique(); - Ogre::Vector3 farCorner = camera->getViewMatrix(true) * camera->getWorldSpaceCorners()[4]; - - for (unsigned short i=0; igetNumPasses(); i++) - { - Ogre::Pass* pass = tech->getPass(i); - // get the vertex shader parameters - Ogre::GpuProgramParametersSharedPtr params = pass->getVertexProgramParameters(); - // set the camera's far-top-right corner - if (params->_findNamedConstantDefinition("farCorner")) - params->setNamedConstant("farCorner", farCorner); - - params = pass->getFragmentProgramParameters(); - if (params->_findNamedConstantDefinition("farCorner")) - params->setNamedConstant("farCorner", farCorner); - } -} diff --git a/Samples/DeferredShading/src/DLight.cpp b/Samples/DeferredShading/src/DLight.cpp deleted file mode 100644 --- a/Samples/DeferredShading/src/DLight.cpp +++ /dev/null @@ -1,351 +0,0 @@ -/* ------------------------------------------------------------------------------ -This source file is part of OGRE -(Object-oriented Graphics Rendering Engine) -For the latest info, see http://www.ogre3d.org/ - -Copyright (c) 2000-2009 Torus Knot Software Ltd -Also see acknowledgements in Readme.html - -You may use this sample code for anything you like, it is not covered by the -same license as the rest of the engine. ------------------------------------------------------------------------------ -*/ - -#include "DLight.h" - -#include "OgreHardwareBufferManager.h" -#include "OgreCamera.h" -#include "OgreSceneNode.h" -#include "OgreLight.h" -#include "GeomUtils.h" -#include "LightMaterialGenerator.h" -#include "OgreTechnique.h" -#include "OgreSceneManager.h" - -#define ENABLE_BIT(mask, flag) (mask) |= (flag) -#define DISABLE_BIT(mask, flag) (mask) &= ~(flag) - -using namespace Ogre; -//----------------------------------------------------------------------- -DLight::DLight(MaterialGenerator *sys, Ogre::Light* parentLight): - mParentLight(parentLight), bIgnoreWorld(false), mGenerator(sys), mPermutation(0) -{ - // Set up geometry - // Allocate render operation - mRenderOp.operationType = RenderOperation::OT_TRIANGLE_LIST; - mRenderOp.indexData = 0; - mRenderOp.vertexData = 0; - mRenderOp.useIndexes = true; - - updateFromParent(); -} -//----------------------------------------------------------------------- -DLight::~DLight() -{ - // need to release IndexData and vertexData created for renderable - delete mRenderOp.indexData; - delete mRenderOp.vertexData; -} -//----------------------------------------------------------------------- -void DLight::setAttenuation(float c, float b, float a) -{ - // Set Attenuation parameter to shader - //setCustomParameter(3, Vector4(c, b, a, 0)); - float outerRadius = mParentLight->getAttenuationRange(); - /// There is attenuation? Set material accordingly - if(c != 1.0f || b != 0.0f || a != 0.0f) - { - ENABLE_BIT(mPermutation, LightMaterialGenerator::MI_ATTENUATED); - if (mParentLight->getType() == Light::LT_POINT) - { - //// Calculate radius from Attenuation - int threshold_level = 10;// difference of 10-15 levels deemed unnoticeable - float threshold = 1.0f/((float)threshold_level/256.0f); - - //// Use quadratic formula to determine outer radius - c = c-threshold; - float d=sqrt(b*b-4*a*c); - outerRadius = (-2*c)/(b+d); - outerRadius *= 1.2; - } - } - else - { - DISABLE_BIT(mPermutation,LightMaterialGenerator::MI_ATTENUATED); - } - - rebuildGeometry(outerRadius); -} -//----------------------------------------------------------------------- -void DLight::setSpecularColour(const ColourValue &col) -{ - //setCustomParameter(2, Vector4(col.r, col.g, col.b, col.a)); - /// There is a specular component? Set material accordingly - - if(col.r != 0.0f || col.g != 0.0f || col.b != 0.0f) - ENABLE_BIT(mPermutation,LightMaterialGenerator::MI_SPECULAR); - else - DISABLE_BIT(mPermutation,LightMaterialGenerator::MI_SPECULAR); - -} -//----------------------------------------------------------------------- -void DLight::rebuildGeometry(float radius) -{ - //Disable all 3 bits - DISABLE_BIT(mPermutation, LightMaterialGenerator::MI_POINT); - DISABLE_BIT(mPermutation, LightMaterialGenerator::MI_SPOTLIGHT); - DISABLE_BIT(mPermutation, LightMaterialGenerator::MI_DIRECTIONAL); - - switch (mParentLight->getType()) - { - case Light::LT_DIRECTIONAL: - createRectangle2D(); - ENABLE_BIT(mPermutation,LightMaterialGenerator::MI_DIRECTIONAL); - break; - case Light::LT_POINT: - /// XXX some more intelligent expression for rings and segments - createSphere(radius, 10, 10); - ENABLE_BIT(mPermutation,LightMaterialGenerator::MI_POINT); - break; - case Light::LT_SPOTLIGHT: - Real height = mParentLight->getAttenuationRange(); - Radian coneRadiusAngle = mParentLight->getSpotlightOuterAngle() / 2; - Real rad = Math::Tan(coneRadiusAngle) * height; - createCone(rad, height, 20); - ENABLE_BIT(mPermutation,LightMaterialGenerator::MI_SPOTLIGHT); - break; - } -} -//----------------------------------------------------------------------- -void DLight::createRectangle2D() -{ - /// XXX this RenderOp should really be re-used between DLight objects, - /// not generated every time - delete mRenderOp.vertexData; - delete mRenderOp.indexData; - - mRenderOp.vertexData = new VertexData(); - mRenderOp.indexData = 0; - - GeomUtils::createQuad(mRenderOp.vertexData); - - mRenderOp.operationType = RenderOperation::OT_TRIANGLE_STRIP; - mRenderOp.useIndexes = false; - - // Set bounding - setBoundingBox(AxisAlignedBox(-10000,-10000,-10000,10000,10000,10000)); - mRadius = 15000; - bIgnoreWorld = true; -} -//----------------------------------------------------------------------- -void DLight::createSphere(float radius, int nRings, int nSegments) -{ - delete mRenderOp.vertexData; - delete mRenderOp.indexData; - mRenderOp.operationType = RenderOperation::OT_TRIANGLE_LIST; - mRenderOp.indexData = new IndexData(); - mRenderOp.vertexData = new VertexData(); - mRenderOp.useIndexes = true; - - GeomUtils::createSphere(mRenderOp.vertexData, mRenderOp.indexData - , radius - , nRings, nSegments - , false // no normals - , false // no texture coordinates - ); - - // Set bounding box and sphere - setBoundingBox( AxisAlignedBox( Vector3(-radius, -radius, -radius), Vector3(radius, radius, radius) ) ); - mRadius = radius; - bIgnoreWorld = false; -} -//----------------------------------------------------------------------- -void DLight::createCone(float radius, float height, int nVerticesInBase) -{ - delete mRenderOp.vertexData; - delete mRenderOp.indexData; - mRenderOp.operationType = RenderOperation::OT_TRIANGLE_LIST; - mRenderOp.indexData = new IndexData(); - mRenderOp.vertexData = new VertexData(); - mRenderOp.useIndexes = true; - - GeomUtils::createCone(mRenderOp.vertexData, mRenderOp.indexData - , radius - , height, nVerticesInBase); - - // Set bounding box and sphere - setBoundingBox( AxisAlignedBox( - Vector3(-radius, 0, -radius), - Vector3(radius, height, radius) ) ); - - mRadius = radius; - bIgnoreWorld = false; -} -//----------------------------------------------------------------------- -Real DLight::getBoundingRadius(void) const -{ - return mRadius; -} -//----------------------------------------------------------------------- -Real DLight::getSquaredViewDepth(const Camera* cam) const -{ - if(bIgnoreWorld) - { - return 0.0f; - } - else - { - Vector3 dist = cam->getDerivedPosition() - getParentSceneNode()->_getDerivedPosition(); - return dist.squaredLength(); - } -} -//----------------------------------------------------------------------- -const MaterialPtr& DLight::getMaterial(void) const -{ - return mGenerator->getMaterial(mPermutation); -} -//----------------------------------------------------------------------- -void DLight::getWorldTransforms(Matrix4* xform) const -{ - if (mParentLight->getType() == Light::LT_SPOTLIGHT) - { - Quaternion quat = Vector3::UNIT_Y.getRotationTo(mParentLight->getDerivedDirection()); - xform->makeTransform(mParentLight->getDerivedPosition(), - Vector3::UNIT_SCALE, quat); - } - else - { - xform->makeTransform(mParentLight->getDerivedPosition(), - Vector3::UNIT_SCALE, Quaternion::IDENTITY); - } - -} -//----------------------------------------------------------------------- -void DLight::updateFromParent() -{ - //TODO : Don't do this unless something changed - setAttenuation(mParentLight->getAttenuationConstant(), - mParentLight->getAttenuationLinear(), mParentLight->getAttenuationQuadric()); - setSpecularColour(mParentLight->getSpecularColour()); - - if (getCastChadows()) - { - ENABLE_BIT(mPermutation,LightMaterialGenerator::MI_SHADOW_CASTER); - } - else - { - DISABLE_BIT(mPermutation, LightMaterialGenerator::MI_SHADOW_CASTER); - } -} -//----------------------------------------------------------------------- -bool DLight::isCameraInsideLight(Ogre::Camera* camera) -{ - switch (mParentLight->getType()) - { - case Ogre::Light::LT_DIRECTIONAL: - return false; - case Ogre::Light::LT_POINT: - { - Ogre::Real distanceFromLight = camera->getDerivedPosition() - .distance(mParentLight->getDerivedPosition()); - //Small epsilon fix to account for the fact that we aren't a true sphere. - return distanceFromLight <= mRadius + camera->getNearClipDistance() + 0.1; - } - case Ogre::Light::LT_SPOTLIGHT: - { - Ogre::Vector3 lightPos = mParentLight->getDerivedPosition(); - Ogre::Vector3 lightDir = mParentLight->getDerivedDirection(); - Ogre::Radian attAngle = mParentLight->getSpotlightOuterAngle(); - - //Extend the analytic cone's radius by the near clip range by moving its tip accordingly. - //Some trigonometry needed here. - Ogre::Vector3 clipRangeFix = -lightDir * (camera->getNearClipDistance() / Ogre::Math::Tan(attAngle/2)); - lightPos = lightPos + clipRangeFix; - - Ogre::Vector3 lightToCamDir = camera->getDerivedPosition() - lightPos; - Ogre::Real distanceFromLight = lightToCamDir.normalise(); - - Ogre::Real cosAngle = lightToCamDir.dotProduct(lightDir); - Ogre::Radian angle = Ogre::Math::ACos(cosAngle); - //Check whether we will see the cone from our current POV. - return (distanceFromLight <= (mParentLight->getAttenuationRange() + clipRangeFix.length())) - && (angle <= attAngle); - } - default: - //Please the compiler - return false; - } -} -//----------------------------------------------------------------------- -bool DLight::getCastChadows() const -{ - return - mParentLight->_getManager()->isShadowTechniqueInUse() && - mParentLight->getCastShadows() && - (mParentLight->getType() == Light::LT_DIRECTIONAL || mParentLight->getType() == Light::LT_SPOTLIGHT); -} -//----------------------------------------------------------------------- -void DLight::updateFromCamera(Ogre::Camera* camera) -{ - //Set shader params - const Ogre::MaterialPtr& mat = getMaterial(); - if (!mat->isLoaded()) - { - mat->load(); - } - Ogre::Technique* tech = mat->getBestTechnique(); - Ogre::Vector3 farCorner = camera->getViewMatrix(true) * camera->getWorldSpaceCorners()[4]; - - for (unsigned short i=0; igetNumPasses(); i++) - { - Ogre::Pass* pass = tech->getPass(i); - // get the vertex shader parameters - Ogre::GpuProgramParametersSharedPtr params = pass->getVertexProgramParameters(); - // set the camera's far-top-right corner - if (params->_findNamedConstantDefinition("farCorner")) - params->setNamedConstant("farCorner", farCorner); - - params = pass->getFragmentProgramParameters(); - if (params->_findNamedConstantDefinition("farCorner")) - params->setNamedConstant("farCorner", farCorner); - - //If inside light geometry, render back faces with CMPF_GREATER, otherwise normally - if (mParentLight->getType() == Ogre::Light::LT_DIRECTIONAL) - { - pass->setCullingMode(Ogre::CULL_CLOCKWISE); - pass->setDepthCheckEnabled(false); - } - else - { - pass->setDepthCheckEnabled(true); - if (isCameraInsideLight(camera)) - { - pass->setCullingMode(Ogre::CULL_ANTICLOCKWISE); - pass->setDepthFunction(Ogre::CMPF_GREATER_EQUAL); - } - else - { - pass->setCullingMode(Ogre::CULL_CLOCKWISE); - pass->setDepthFunction(Ogre::CMPF_LESS_EQUAL); - } - } - - Camera shadowCam("ShadowCameraSetupCam", 0); - shadowCam._notifyViewport(camera->getViewport()); - SceneManager* sm = mParentLight->_getManager(); - sm->getShadowCameraSetup()->getShadowCamera(sm, - camera, camera->getViewport(), mParentLight, &shadowCam, 0); - - //Get the shadow camera position - if (params->_findNamedConstantDefinition("shadowCamPos")) - { - params->setNamedConstant("shadowCamPos", shadowCam.getPosition()); - } - if (params->_findNamedConstantDefinition("shadowFarClip")) - { - params->setNamedConstant("shadowFarClip", shadowCam.getFarClipDistance()); - } - - } -} diff --git a/Samples/DeferredShading/src/DeferredLightCP.cpp b/Samples/DeferredShading/src/DeferredLightCP.cpp deleted file mode 100644 --- a/Samples/DeferredShading/src/DeferredLightCP.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/* ------------------------------------------------------------------------------ -This source file is part of OGRE -(Object-oriented Graphics Rendering Engine) -For the latest info, see http://www.ogre3d.org/ - -Copyright (c) 2000-2009 Torus Knot Software Ltd -Also see acknowledgements in Readme.html - -You may use this sample code for anything you like, it is not covered by the -same license as the rest of the engine. ------------------------------------------------------------------------------ -*/ - -#include "DeferredLightCP.h" - -#include "Ogre.h" -using namespace Ogre; - -#include "LightMaterialGenerator.h" - -//----------------------------------------------------------------------- -DeferredLightRenderOperation::DeferredLightRenderOperation( - CompositorInstance* instance, const CompositionPass* pass) -{ - mViewport = instance->getChain()->getViewport(); - - //Get the names of the GBuffer textures - const CompositionPass::InputTex& input0 = pass->getInput(0); - mTexName0 = instance->getTextureInstanceName(input0.name, input0.mrtIndex); - const CompositionPass::InputTex& input1 = pass->getInput(1); - mTexName1 = instance->getTextureInstanceName(input1.name, input1.mrtIndex); - - // Create lights material generator - mLightMaterialGenerator = new LightMaterialGenerator(); - - // Create the ambient light - mAmbientLight = new AmbientLight(); - const MaterialPtr& mat = mAmbientLight->getMaterial(); - mat->load(); -} -//----------------------------------------------------------------------- -DLight* DeferredLightRenderOperation::createDLight(Ogre::Light* light) -{ - DLight *rv = new DLight(mLightMaterialGenerator,light); - mLights[light] = rv; - return rv; -} -//----------------------------------------------------------------------- -void injectTechnique(SceneManager* sm, Technique* tech, Renderable* rend, const Ogre::LightList* lightList) -{ - for(unsigned short i=0; igetNumPasses(); ++i) - { - Ogre::Pass* pass = tech->getPass(i); - if (lightList != 0) - { - sm->_injectRenderWithPass(pass, rend, false, false, lightList); - } - else - { - sm->_injectRenderWithPass(pass, rend, false); - } - - } -} -//----------------------------------------------------------------------- -void DeferredLightRenderOperation::execute(SceneManager *sm, RenderSystem *rs) -{ - Ogre::Camera* cam = mViewport->getCamera(); - - mAmbientLight->updateFromCamera(cam); - Technique* tech = mAmbientLight->getMaterial()->getBestTechnique(); - injectTechnique(sm, tech, mAmbientLight, 0); - - const LightList& lightList = sm->_getLightsAffectingFrustum(); - for (LightList::const_iterator it = lightList.begin(); it != lightList.end(); it++) - { - Light* light = *it; - Ogre::LightList ll; - ll.push_back(light); - - //if (++i != 2) continue; - //if (light->getType() != Light::LT_DIRECTIONAL) continue; - //if (light->getDiffuseColour() != ColourValue::Red) continue; - - LightsMap::iterator dLightIt = mLights.find(light); - DLight* dLight = 0; - if (dLightIt == mLights.end()) - { - dLight = createDLight(light); - } - else - { - dLight = dLightIt->second; - dLight->updateFromParent(); - } - dLight->updateFromCamera(cam); - tech = dLight->getMaterial()->getBestTechnique(); - - //Update shadow texture - if (dLight->getCastChadows()) - { - SceneManager::RenderContext* context = sm->_pauseRendering(); - - sm->prepareShadowTextures(cam, mViewport, &ll); - sm->_resumeRendering(context); - - Pass* pass = tech->getPass(0); - TextureUnitState* tus = pass->getTextureUnitState("ShadowMap"); - assert(tus); - const TexturePtr& shadowTex = sm->getShadowTexture(0); - if (tus->_getTexturePtr() != shadowTex) - { - tus->_setTexturePtr(shadowTex); - } - - } - - injectTechnique(sm, tech, dLight, &ll); - } -} -//----------------------------------------------------------------------- -DeferredLightRenderOperation::~DeferredLightRenderOperation() -{ - for (LightsMap::iterator it = mLights.begin(); it != mLights.end(); ++it) - { - delete it->second; - } - mLights.clear(); - - delete mAmbientLight; - delete mLightMaterialGenerator; -} -//----------------------------------------------------------------------- diff --git a/Samples/DeferredShading/src/DeferredShading.cpp b/Samples/DeferredShading/src/DeferredShading.cpp deleted file mode 100755 --- a/Samples/DeferredShading/src/DeferredShading.cpp +++ /dev/null @@ -1,203 +0,0 @@ -/* ------------------------------------------------------------------------------ -This source file is part of OGRE -(Object-oriented Graphics Rendering Engine) -For the latest info, see http://www.ogre3d.org/ - -Copyright (c) 2000-2009 Torus Knot Software Ltd -Also see acknowledgements in Readme.html - -You may use this sample code for anything you like, it is not covered by the -same license as the rest of the engine. ------------------------------------------------------------------------------ -*/ - -#include "DeferredShading.h" - -#include "OgreConfigFile.h" -#include "OgreStringConverter.h" -#include "OgreException.h" - -#include "OgreRoot.h" -#include "OgreRenderSystem.h" - -#include "OgreEntity.h" -#include "OgreSubEntity.h" -#include "OgreRoot.h" - -#include "OgreCompositor.h" -#include "OgreCompositorManager.h" -#include "OgreCompositorChain.h" -#include "OgreCompositorInstance.h" - -#include "OgreLogManager.h" - -#include "DeferredLightCP.h" -#include "SSAOLogic.h" -#include "GBufferSchemeHandler.h" -#include "NullSchemeHandler.h" - -#include "SharedData.h" - -namespace Ogre -{ - template<> SharedData* Singleton::ms_Singleton = 0; -} - -using namespace Ogre; - -const Ogre::uint8 DeferredShadingSystem::PRE_GBUFFER_RENDER_QUEUE = Ogre::RENDER_QUEUE_1; -const Ogre::uint8 DeferredShadingSystem::POST_GBUFFER_RENDER_QUEUE = Ogre::RENDER_QUEUE_8; - -DeferredShadingSystem::DeferredShadingSystem( - Viewport *vp, SceneManager *sm, Camera *cam - ): - mViewport(vp), mSceneMgr(sm), mCamera(cam) -{ - sm->setShadowTechnique(SHADOWTYPE_TEXTURE_ADDITIVE); - sm->setShadowTextureCasterMaterial("DeferredShading/Shadows/Caster"); - mSceneMgr->setShadowTextureCount(1); - mSceneMgr->setShadowFarDistance(150); - //Use a value of "2" to use a different depth buffer pool and avoid sharing this with the Backbuffer's - mSceneMgr->setShadowTextureConfig( 0, 512, 512, PF_FLOAT16_R, 2 ); - mSceneMgr->setShadowDirectionalLightExtrusionDistance(75); -} - -void DeferredShadingSystem::initialize() -{ - for(int i=0; i_removeInstance(mInstance[i]); - CompositorManager::getSingleton().removeCompositorChain(mViewport); - - Ogre::CompositorManager& compMgr = Ogre::CompositorManager::getSingleton(); - CompositorLogicMap::const_iterator itor = mCompositorLogics.begin(); - CompositorLogicMap::const_iterator end = mCompositorLogics.end(); - while( itor != end ) - { - compMgr.unregisterCompositorLogic( itor->first ); - delete itor->second; - ++itor; - } - mCompositorLogics.clear(); -} - -void DeferredShadingSystem::setMode(DSMode mode) -{ - assert( 0 <= mode && mode < DSM_COUNT); - - // prevent duplicate setups - if (mCurrentMode == mode && mInstance[mode]->getEnabled()==mActive) - return; - - for(int i=0; isetEnabled(mActive); - } - else - { - mInstance[i]->setEnabled(false); - } - } - - mCurrentMode = mode; - - mSSAOInstance->setEnabled(mActive && mSSAO && mCurrentMode == DSM_SHOWLIT); -} - -void DeferredShadingSystem::setSSAO(bool ssao) -{ - if (ssao != mSSAO) - { - mSSAO = ssao; - if (mActive && mCurrentMode == DSM_SHOWLIT) - { - mSSAOInstance->setEnabled(ssao); - } - } -} - -bool DeferredShadingSystem::getSSAO() const -{ - return mSSAO; -} -void DeferredShadingSystem::setActive(bool active) -{ - if (mActive != active) - { - mActive = active; - mGBufferInstance->setEnabled(active); - - // mCurrentMode could have changed with a prior call to setMode, so iterate all - setMode(mCurrentMode); - } -} - -DeferredShadingSystem::DSMode DeferredShadingSystem::getMode(void) const -{ - return mCurrentMode; -} - -void DeferredShadingSystem::createResources(void) -{ - CompositorManager &compMan = CompositorManager::getSingleton(); - - //Hook up the compositor logic and scheme handlers. - //This can theoretically happen in a loaded plugin, but in this case the demo contains the code. - static bool firstTime = true; - if (firstTime) - { - MaterialManager::getSingleton().addListener(new GBufferSchemeHandler, "GBuffer"); - MaterialManager::getSingleton().addListener(new NullSchemeHandler, "NoGBuffer"); - - compMan.registerCustomCompositionPass("DeferredLight", new DeferredLightCompositionPass); - - firstTime = false; - } - - mCompositorLogics["SSAOLogic"] = new SSAOLogic; - compMan.registerCompositorLogic("SSAOLogic", mCompositorLogics["SSAOLogic"]); - - // Create the main GBuffer compositor - mGBufferInstance = compMan.addCompositor(mViewport, "DeferredShading/GBuffer"); - - // Create filters - mInstance[DSM_SHOWLIT] = compMan.addCompositor(mViewport, "DeferredShading/ShowLit"); - mInstance[DSM_SHOWNORMALS] = compMan.addCompositor(mViewport, "DeferredShading/ShowNormals"); - mInstance[DSM_SHOWDSP] = compMan.addCompositor(mViewport, "DeferredShading/ShowDepthSpecular"); - mInstance[DSM_SHOWCOLOUR] = compMan.addCompositor(mViewport, "DeferredShading/ShowColour"); - - mSSAOInstance = compMan.addCompositor(mViewport, "DeferredShading/SSAO"); -} - - -void DeferredShadingSystem::logCurrentMode(void) -{ - if (mActive==false) - { - LogManager::getSingleton().logMessage("No Compositor Enabled!"); - return; - } - - CompositorInstance* ci = mInstance[mCurrentMode]; - assert(ci->getEnabled()==true); - - LogManager::getSingleton().logMessage("Current Mode: "); - LogManager::getSingleton().logMessage(ci->getCompositor()->getName()); -} diff --git a/Samples/DeferredShading/src/GBufferMaterialGenerator.cpp b/Samples/DeferredShading/src/GBufferMaterialGenerator.cpp deleted file mode 100644 --- a/Samples/DeferredShading/src/GBufferMaterialGenerator.cpp +++ /dev/null @@ -1,282 +0,0 @@ -/* ------------------------------------------------------------------------------ -This source file is part of OGRE -(Object-oriented Graphics Rendering Engine) -For the latest info, see http://www.ogre3d.org/ - -Copyright (c) 2000-2009 Torus Knot Software Ltd -Also see acknowledgements in Readme.html - -You may use this sample code for anything you like, it is not covered by the -same license as the rest of the engine. ------------------------------------------------------------------------------ -*/ - -#include "GBufferMaterialGenerator.h" - -#include "OgreMaterialManager.h" -#include "OgreGpuProgramManager.h" -#include "OgreStringConverter.h" -#include "OgreHighLevelGpuProgramManager.h" -#include "OgreTechnique.h" - -//Use this directive to control whether you are writing projective (regular) or linear depth. -#define WRITE_LINEAR_DEPTH - -//This is the concrete implementation of the material generator. -class GBufferMaterialGeneratorImpl : public MaterialGenerator::Impl -{ -public: - GBufferMaterialGeneratorImpl(const Ogre::String& baseName) : mBaseName(baseName) {} - -protected: - Ogre::String mBaseName; - virtual Ogre::GpuProgramPtr generateVertexShader(MaterialGenerator::Perm permutation); - virtual Ogre::GpuProgramPtr generateFragmentShader(MaterialGenerator::Perm permutation); - virtual Ogre::MaterialPtr generateTemplateMaterial(MaterialGenerator::Perm permutation); - -}; - -GBufferMaterialGenerator::GBufferMaterialGenerator() { - vsMask = VS_MASK; - fsMask = FS_MASK; - matMask = MAT_MASK; - materialBaseName = "DeferredShading/GBuffer/"; - mImpl = new GBufferMaterialGeneratorImpl(materialBaseName); -} - -Ogre::GpuProgramPtr GBufferMaterialGeneratorImpl::generateVertexShader(MaterialGenerator::Perm permutation) -{ - Ogre::StringStream ss; - - ss << "void ToGBufferVP(" << std::endl; - ss << " float4 iPosition : POSITION," << std::endl; - ss << " float3 iNormal : NORMAL," << std::endl; - - Ogre::uint32 numTexCoords = (permutation & GBufferMaterialGenerator::GBP_TEXCOORD_MASK) >> 8; - for (Ogre::uint32 i=0; ilogMessage(programSource); -#endif - - // Create shader object - Ogre::HighLevelGpuProgramPtr ptrProgram = Ogre::HighLevelGpuProgramManager::getSingleton().createProgram( - programName, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - "cg", Ogre::GPT_VERTEX_PROGRAM); - ptrProgram->setSource(programSource); - ptrProgram->setParameter("entry_point","ToGBufferVP"); - ptrProgram->setParameter("profiles","vs_1_1 arbvp1"); - - const Ogre::GpuProgramParametersSharedPtr& params = ptrProgram->getDefaultParameters(); - params->setNamedAutoConstant("cWorldViewProj", Ogre::GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); - params->setNamedAutoConstant("cWorldView", Ogre::GpuProgramParameters::ACT_WORLDVIEW_MATRIX); - ptrProgram->load(); - - return Ogre::GpuProgramPtr(ptrProgram); -} - -Ogre::GpuProgramPtr GBufferMaterialGeneratorImpl::generateFragmentShader(MaterialGenerator::Perm permutation) -{ - Ogre::StringStream ss; - - ss << "void ToGBufferFP(" << std::endl; -#ifdef WRITE_LINEAR_DEPTH - ss << " float3 iViewPos : TEXCOORD0," << std::endl; -#else - ss << " float1 iDepth : TEXCOORD0," << std::endl; -#endif - ss << " float3 iNormal : TEXCOORD1," << std::endl; - - int texCoordNum = 2; - if (permutation & GBufferMaterialGenerator::GBP_NORMAL_MAP) - { - ss << " float3 iTangent : TEXCOORD" << texCoordNum++ << ',' << std::endl; - ss << " float3 iBiNormal : TEXCOORD" << texCoordNum++ << ',' << std::endl; - } - - Ogre::uint32 numTexCoords = (permutation & GBufferMaterialGenerator::GBP_TEXCOORD_MASK) >> 8; - for (Ogre::uint32 i=0; i 0 && numTextures > 0) - { - ss << " oColor0.rgb = tex2D(sTex0, iUV0);" << std::endl; - if (permutation & GBufferMaterialGenerator::GBP_HAS_DIFFUSE_COLOUR) - { - ss << " oColor0.rgb *= cDiffuseColour.rgb;" << std::endl; - } - } - else - { - ss << " oColor0.rgb = cDiffuseColour.rgb;" << std::endl; - } - - - ss << " oColor0.a = cSpecularity;" << std::endl; - if (permutation & GBufferMaterialGenerator::GBP_NORMAL_MAP) - { - ss << " float3 texNormal = (tex2D(sNormalMap, iUV0)-0.5)*2;" << std::endl; - ss << " float3x3 normalRotation = float3x3(iTangent, iBiNormal, iNormal);" << std::endl; - ss << " oColor1.rgb = normalize(mul(texNormal, normalRotation));" << std::endl; - } else - { - ss << " oColor1.rgb = normalize(iNormal);" << std::endl; - } -#ifdef WRITE_LINEAR_DEPTH - ss << " oColor1.a = length(iViewPos) / cFarDistance;" << std::endl; -#else - ss << " oColor1.a = iDepth;" << std::endl; -#endif - - ss << "}" << std::endl; - - Ogre::String programSource = ss.str(); - Ogre::String programName = mBaseName + "FP_" + Ogre::StringConverter::toString(permutation); - -#if OGRE_DEBUG_MODE - Ogre::LogManager::getSingleton().getDefaultLog()->logMessage(programSource); -#endif - - // Create shader object - Ogre::HighLevelGpuProgramPtr ptrProgram = Ogre::HighLevelGpuProgramManager::getSingleton().createProgram( - programName, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - "cg", Ogre::GPT_FRAGMENT_PROGRAM); - ptrProgram->setSource(programSource); - ptrProgram->setParameter("entry_point","ToGBufferFP"); - ptrProgram->setParameter("profiles","ps_2_0 arbfp1"); - - const Ogre::GpuProgramParametersSharedPtr& params = ptrProgram->getDefaultParameters(); - params->setNamedAutoConstant("cSpecularity", Ogre::GpuProgramParameters::ACT_SURFACE_SHININESS); - if (numTextures == 0 || permutation & GBufferMaterialGenerator::GBP_HAS_DIFFUSE_COLOUR) - { - params->setNamedAutoConstant("cDiffuseColour", Ogre::GpuProgramParameters::ACT_SURFACE_DIFFUSE_COLOUR); - } - -#ifdef WRITE_LINEAR_DEPTH - //TODO : Should this be the distance to the far corner, not the far clip distance? - params->setNamedAutoConstant("cFarDistance", Ogre::GpuProgramParameters::ACT_FAR_CLIP_DISTANCE); -#endif - - ptrProgram->load(); - return Ogre::GpuProgramPtr(ptrProgram); -} - -Ogre::MaterialPtr GBufferMaterialGeneratorImpl::generateTemplateMaterial(MaterialGenerator::Perm permutation) -{ - Ogre::String matName = mBaseName + "Mat_" + Ogre::StringConverter::toString(permutation); - - Ogre::MaterialPtr matPtr = Ogre::MaterialManager::getSingleton().create - (matName, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); - Ogre::Pass* pass = matPtr->getTechnique(0)->getPass(0); - pass->setName(mBaseName + "Pass_" + Ogre::StringConverter::toString(permutation)); - pass->setLightingEnabled(false); - if (permutation & GBufferMaterialGenerator::GBP_NORMAL_MAP) - { - pass->createTextureUnitState(); - } - Ogre::uint32 numTextures = permutation & GBufferMaterialGenerator::GBP_TEXTURE_MASK; - for (Ogre::uint32 i=0; icreateTextureUnitState(); - } - - return matPtr; -} diff --git a/Samples/DeferredShading/src/GBufferSchemeHandler.cpp b/Samples/DeferredShading/src/GBufferSchemeHandler.cpp deleted file mode 100644 --- a/Samples/DeferredShading/src/GBufferSchemeHandler.cpp +++ /dev/null @@ -1,222 +0,0 @@ -/* ------------------------------------------------------------------------------ -This source file is part of OGRE -(Object-oriented Graphics Rendering Engine) -For the latest info, see http://www.ogre3d.org/ - -Copyright (c) 2000-2009 Torus Knot Software Ltd -Also see acknowledgements in Readme.html - -You may use this sample code for anything you like, it is not covered by the -same license as the rest of the engine. ------------------------------------------------------------------------------ -*/ - -#include "GBufferSchemeHandler.h" - -#include -#include - -using namespace Ogre; - -const String GBufferSchemeHandler::NORMAL_MAP_PATTERN = "normal"; - -Technique* GBufferSchemeHandler::handleSchemeNotFound(unsigned short schemeIndex, - const String& schemeName, Material* originalMaterial, unsigned short lodIndex, - const Renderable* rend) -{ - Ogre::MaterialManager& matMgr = Ogre::MaterialManager::getSingleton(); - String curSchemeName = matMgr.getActiveScheme(); - matMgr.setActiveScheme(MaterialManager::DEFAULT_SCHEME_NAME); - Technique* originalTechnique = originalMaterial->getBestTechnique(lodIndex, rend); - matMgr.setActiveScheme(curSchemeName); - - Technique* gBufferTech = originalMaterial->createTechnique(); - gBufferTech->removeAllPasses(); - gBufferTech->setSchemeName(schemeName); - - Technique* noGBufferTech = originalMaterial->createTechnique(); - noGBufferTech->removeAllPasses(); - noGBufferTech->setSchemeName("NoGBuffer"); - - for (unsigned short i=0; igetNumPasses(); i++) - { - Pass* originalPass = originalTechnique->getPass(i); - PassProperties props = inspectPass(originalPass, lodIndex, rend); - - if (!props.isDeferred) - { - //Just copy the technique so it gets rendered regularly - Pass* clonePass = noGBufferTech->createPass(); - *clonePass = *originalPass; - continue; - } - - Pass* newPass = gBufferTech->createPass(); - MaterialGenerator::Perm perm = getPermutation(props); - - const Ogre::MaterialPtr& templateMat = mMaterialGenerator.getMaterial(perm); - - //We assume that the GBuffer technique contains only one pass. But its true. - *newPass = *(templateMat->getTechnique(0)->getPass(0)); - fillPass(newPass, originalPass, props); - } - - return gBufferTech; -} - -bool GBufferSchemeHandler::checkNormalMap( - TextureUnitState* tus, GBufferSchemeHandler::PassProperties& props) -{ - bool isNormal = false; - Ogre::String lowerCaseAlias = tus->getTextureNameAlias(); - Ogre::StringUtil::toLowerCase(lowerCaseAlias); - if (lowerCaseAlias.find(NORMAL_MAP_PATTERN) != Ogre::String::npos) - { - isNormal = true; - } - else - { - Ogre::String lowerCaseName = tus->getTextureName(); - Ogre::StringUtil::toLowerCase(lowerCaseName); - if (lowerCaseName.find(NORMAL_MAP_PATTERN) != Ogre::String::npos) - { - isNormal = true; - } - } - - if (isNormal) - { - if (props.normalMap == 0) - { - props.normalMap = tus; - } - else - { - OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM, - "Multiple normal map patterns matches", - "GBufferSchemeHandler::inspectPass"); - } - } - return isNormal; -} - -GBufferSchemeHandler::PassProperties GBufferSchemeHandler::inspectPass( - Pass* pass, unsigned short lodIndex, const Renderable* rend) -{ - PassProperties props; - - //TODO : Use renderable to indicate wether this has skinning. - //Probably use same const cast that renderSingleObject uses. - if (pass->hasVertexProgram()) - { - props.isSkinned = pass->getVertexProgram()->isSkeletalAnimationIncluded(); - } - else - { - props.isSkinned = false; - } - - for (unsigned short i=0; igetNumTextureUnitStates(); i++) - { - TextureUnitState* tus = pass->getTextureUnitState(i); - if (!checkNormalMap(tus, props)) - { - props.regularTextures.push_back(tus); - } - if (tus->getEffects().size() > 0) - { - props.isDeferred = false; - } - - } - - if (pass->getDiffuse() != ColourValue::White) - { - props.hasDiffuseColour = true; - } - - //Check transparency - if (pass->getDestBlendFactor() != Ogre::SBF_ZERO) - { - //TODO : Better ways to do this - props.isDeferred = false; - } - return props; -} - -MaterialGenerator::Perm GBufferSchemeHandler::getPermutation(const PassProperties& props) -{ - MaterialGenerator::Perm perm = 0; - switch (props.regularTextures.size()) - { - case 0: - perm |= GBufferMaterialGenerator::GBP_NO_TEXTURES; - - if (props.normalMap != 0) - { - perm |= GBufferMaterialGenerator::GBP_ONE_TEXCOORD; - } - else - { - perm |= GBufferMaterialGenerator::GBP_NO_TEXCOORDS; - } - break; - case 1: - perm |= GBufferMaterialGenerator::GBP_ONE_TEXTURE; - perm |= GBufferMaterialGenerator::GBP_ONE_TEXCOORD; - break; - case 2: - perm |= GBufferMaterialGenerator::GBP_TWO_TEXTURES; - //TODO : When do we use two texcoords? - perm |= GBufferMaterialGenerator::GBP_ONE_TEXCOORD; - break; - case 3: - perm |= GBufferMaterialGenerator::GBP_THREE_TEXTURES; - perm |= GBufferMaterialGenerator::GBP_ONE_TEXCOORD; - break; - default: - OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED, - "Can not generate G-Buffer materials for '>3 regular-texture' objects", - "GBufferSchemeHandler::inspectPass"); - } - - if (props.isSkinned) - { - perm |= GBufferMaterialGenerator::GBP_SKINNED; - } - - if (props.normalMap != 0) - { - perm |= GBufferMaterialGenerator::GBP_NORMAL_MAP; - } - - if (props.hasDiffuseColour) - { - perm |= GBufferMaterialGenerator::GBP_HAS_DIFFUSE_COLOUR; - } - return perm; -} - -void GBufferSchemeHandler::fillPass( - Pass* gBufferPass, Pass* originalPass, const PassProperties& props) -{ - //Reference the correct textures. Normal map first! - int texUnitIndex = 0; - if (props.normalMap != 0) - { - *(gBufferPass->getTextureUnitState(texUnitIndex)) = *(props.normalMap); - texUnitIndex++; - } - for (size_t i=0; igetTextureUnitState(texUnitIndex)) = *(props.regularTextures[i]); - texUnitIndex++; - } - gBufferPass->setAmbient(originalPass->getAmbient()); - gBufferPass->setDiffuse(originalPass->getDiffuse()); - gBufferPass->setSpecular(originalPass->getSpecular()); - gBufferPass->setShininess(originalPass->getShininess()); - gBufferPass->setCullingMode(originalPass->getCullingMode()); - gBufferPass->setLightingEnabled(false); -} diff --git a/Samples/DeferredShading/src/GeomUtils.cpp b/Samples/DeferredShading/src/GeomUtils.cpp deleted file mode 100644 --- a/Samples/DeferredShading/src/GeomUtils.cpp +++ /dev/null @@ -1,254 +0,0 @@ -/* ------------------------------------------------------------------------------ -This source file is part of OGRE -(Object-oriented Graphics Rendering Engine) -For the latest info, see http://www.ogre3d.org/ - -Copyright (c) 2000-2009 Torus Knot Software Ltd -Also see acknowledgements in Readme.html - -You may use this sample code for anything you like, it is not covered by the -same license as the rest of the engine. ------------------------------------------------------------------------------ -*/ - - -#include "GeomUtils.h" - -#include "OgreMeshManager.h" -#include "OgreSubMesh.h" -#include "OgreHardwareBufferManager.h" - -using namespace Ogre; - -void GeomUtils::createSphere( const String& strName - , float radius - , int nRings, int nSegments - , bool bNormals - , bool bTexCoords) -{ - MeshPtr pSphere = MeshManager::getSingleton().createManual(strName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); - SubMesh *pSphereVertex = pSphere->createSubMesh(); - pSphere->sharedVertexData = new VertexData(); - - createSphere(pSphere->sharedVertexData, pSphereVertex->indexData - , radius - , nRings, nSegments - , bNormals // need normals - , bTexCoords // need texture co-ordinates - ); - - // Generate face list - pSphereVertex->useSharedVertices = true; - - // the original code was missing this line: - pSphere->_setBounds( AxisAlignedBox( Vector3(-radius, -radius, -radius), Vector3(radius, radius, radius) ), false ); - pSphere->_setBoundingSphereRadius(radius); - // this line makes clear the mesh is loaded (avoids memory leaks) - pSphere->load(); -} - -void GeomUtils::createSphere(VertexData*& vertexData, IndexData*& indexData - , float radius - , int nRings, int nSegments - , bool bNormals - , bool bTexCoords) -{ - assert(vertexData && indexData); - - // define the vertex format - VertexDeclaration* vertexDecl = vertexData->vertexDeclaration; - size_t currOffset = 0; - // positions - vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_POSITION); - currOffset += VertexElement::getTypeSize(VET_FLOAT3); - - if (bNormals) - { - // normals - vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_NORMAL); - currOffset += VertexElement::getTypeSize(VET_FLOAT3); - - } - // two dimensional texture coordinates - if (bTexCoords) - { - vertexDecl->addElement(0, currOffset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0); - currOffset += VertexElement::getTypeSize(VET_FLOAT2); - } - - // allocate the vertex buffer - vertexData->vertexCount = (nRings + 1) * (nSegments+1); - HardwareVertexBufferSharedPtr vBuf = HardwareBufferManager::getSingleton().createVertexBuffer(vertexDecl->getVertexSize(0), vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); - VertexBufferBinding* binding = vertexData->vertexBufferBinding; - binding->setBinding(0, vBuf); - float* pVertex = static_cast(vBuf->lock(HardwareBuffer::HBL_DISCARD)); - - // allocate index buffer - indexData->indexCount = 6 * nRings * (nSegments + 1); - indexData->indexBuffer = HardwareBufferManager::getSingleton().createIndexBuffer(HardwareIndexBuffer::IT_16BIT, indexData->indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); - HardwareIndexBufferSharedPtr iBuf = indexData->indexBuffer; - unsigned short* pIndices = static_cast(iBuf->lock(HardwareBuffer::HBL_DISCARD)); - - float fDeltaRingAngle = (Math::PI / nRings); - float fDeltaSegAngle = (2 * Math::PI / nSegments); - unsigned short wVerticeIndex = 0 ; - - // Generate the group of rings for the sphere - for( int ring = 0; ring <= nRings; ring++ ) { - float r0 = radius * sinf (ring * fDeltaRingAngle); - float y0 = radius * cosf (ring * fDeltaRingAngle); - - // Generate the group of segments for the current ring - for(int seg = 0; seg <= nSegments; seg++) { - float x0 = r0 * sinf(seg * fDeltaSegAngle); - float z0 = r0 * cosf(seg * fDeltaSegAngle); - - // Add one vertex to the strip which makes up the sphere - *pVertex++ = x0; - *pVertex++ = y0; - *pVertex++ = z0; - - if (bNormals) - { - Vector3 vNormal = Vector3(x0, y0, z0).normalisedCopy(); - *pVertex++ = vNormal.x; - *pVertex++ = vNormal.y; - *pVertex++ = vNormal.z; - } - if (bTexCoords) - { - *pVertex++ = (float) seg / (float) nSegments; - *pVertex++ = (float) ring / (float) nRings; - } - - if (ring != nRings) - { - // each vertex (except the last) has six indices pointing to it - *pIndices++ = wVerticeIndex + nSegments + 1; - *pIndices++ = wVerticeIndex; - *pIndices++ = wVerticeIndex + nSegments; - *pIndices++ = wVerticeIndex + nSegments + 1; - *pIndices++ = wVerticeIndex + 1; - *pIndices++ = wVerticeIndex; - wVerticeIndex ++; - } - }; // end for seg - } // end for ring - - // Unlock - vBuf->unlock(); - iBuf->unlock(); -} - -void GeomUtils::createQuad(VertexData*& vertexData) -{ - assert(vertexData); - - vertexData->vertexCount = 4; - vertexData->vertexStart = 0; - - VertexDeclaration* vertexDecl = vertexData->vertexDeclaration; - VertexBufferBinding* bind = vertexData->vertexBufferBinding; - - vertexDecl->addElement(0, 0, VET_FLOAT3, VES_POSITION); - - HardwareVertexBufferSharedPtr vbuf = - HardwareBufferManager::getSingleton().createVertexBuffer( - vertexDecl->getVertexSize(0), - vertexData->vertexCount, - HardwareBuffer::HBU_STATIC_WRITE_ONLY); - - // Bind buffer - bind->setBinding(0, vbuf); - // Upload data - float data[]={ - -1,1,-1, // corner 1 - -1,-1,-1, // corner 2 - 1,1,-1, // corner 3 - 1,-1,-1}; // corner 4 - vbuf->writeData(0, sizeof(data), data, true); -} - -void GeomUtils::createCone(const Ogre::String& strName , float radius , float height, int nVerticesInBase) -{ - MeshPtr pCone = MeshManager::getSingleton().createManual(strName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); - SubMesh *pConeVertex = pCone->createSubMesh(); - pCone->sharedVertexData = new VertexData(); - - createCone(pCone->sharedVertexData, pConeVertex->indexData - , radius - , height - , nVerticesInBase); - - // Generate face list - pConeVertex->useSharedVertices = true; - - // the original code was missing this line: - pCone->_setBounds( AxisAlignedBox( - Vector3(-radius, 0, -radius), - Vector3(radius, height, radius) ), false ); - - pCone->_setBoundingSphereRadius(Math::Sqrt(height*height + radius*radius)); - // this line makes clear the mesh is loaded (avoids memory leaks) - pCone->load(); -} - - -void GeomUtils::createCone(Ogre::VertexData*& vertexData, Ogre::IndexData*& indexData, - float radius , float height, int nVerticesInBase) -{ - assert(vertexData && indexData); - - // define the vertex format - VertexDeclaration* vertexDecl = vertexData->vertexDeclaration; - // positions - vertexDecl->addElement(0, 0, VET_FLOAT3, VES_POSITION); - - // allocate the vertex buffer - vertexData->vertexCount = nVerticesInBase + 1; - HardwareVertexBufferSharedPtr vBuf = HardwareBufferManager::getSingleton().createVertexBuffer(vertexDecl->getVertexSize(0), vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); - VertexBufferBinding* binding = vertexData->vertexBufferBinding; - binding->setBinding(0, vBuf); - float* pVertex = static_cast(vBuf->lock(HardwareBuffer::HBL_DISCARD)); - - // allocate index buffer - cone and base - indexData->indexCount = (3 * nVerticesInBase) + (3 * (nVerticesInBase - 2)); - indexData->indexBuffer = HardwareBufferManager::getSingleton().createIndexBuffer(HardwareIndexBuffer::IT_16BIT, indexData->indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); - HardwareIndexBufferSharedPtr iBuf = indexData->indexBuffer; - unsigned short* pIndices = static_cast(iBuf->lock(HardwareBuffer::HBL_DISCARD)); - - //Positions : cone head and base - for (int i=0; i<3; i++) - *pVertex++ = 0.0f; - - //Base : - float fDeltaBaseAngle = (2 * Math::PI) / nVerticesInBase; - for (int i=0; iunlock(); - iBuf->unlock(); -} diff --git a/Samples/DeferredShading/src/LightMaterialGenerator.cpp b/Samples/DeferredShading/src/LightMaterialGenerator.cpp deleted file mode 100755 --- a/Samples/DeferredShading/src/LightMaterialGenerator.cpp +++ /dev/null @@ -1,217 +0,0 @@ -/****************************************************************************** -Copyright (c) W.J. van der Laan - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the -Software, and to permit persons to whom the Software is furnished to do so, subject -to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies -or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -******************************************************************************/ - -#include "LightMaterialGenerator.h" - -#include "OgreStringConverter.h" -#include "OgreException.h" -#include "OgreMaterialManager.h" - -#include "OgrePass.h" -#include "OgreTechnique.h" - -#include "OgreHighLevelGpuProgram.h" -#include "OgreHighLevelGpuProgramManager.h" - -#include "DLight.h" - -using namespace Ogre; - -//CG -class LightMaterialGeneratorCG : public MaterialGenerator::Impl -{ -public: - typedef MaterialGenerator::Perm Perm; - LightMaterialGeneratorCG(const String &baseName): - mBaseName(baseName) - { - - } - virtual ~LightMaterialGeneratorCG() - { - - } - - virtual GpuProgramPtr generateVertexShader(Perm permutation) - { - String programName = "DeferredShading/post/"; - - if (permutation & LightMaterialGenerator::MI_DIRECTIONAL) - { - programName += "vs"; - } - else - { - programName += "LightMaterial_vs"; - } - - GpuProgramPtr ptr = HighLevelGpuProgramManager::getSingleton().getByName(programName); - assert(!ptr.isNull()); - return ptr; - } - - virtual GpuProgramPtr generateFragmentShader(Perm permutation) - { - /// Create shader - if (mMasterSource.empty()) - { - DataStreamPtr ptrMasterSource = ResourceGroupManager::getSingleton().openResource( - "DeferredShading/post/LightMaterial_ps.cg" - , ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); - assert(ptrMasterSource.isNull()==false); - mMasterSource = ptrMasterSource->getAsString(); - } - - assert(mMasterSource.empty()==false); - - // Create name - String name = mBaseName+StringConverter::toString(permutation)+"_ps"; - - // Create shader object - HighLevelGpuProgramPtr ptrProgram = HighLevelGpuProgramManager::getSingleton().createProgram( - name, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - "cg", GPT_FRAGMENT_PROGRAM); - ptrProgram->setSource(mMasterSource); - ptrProgram->setParameter("entry_point","main"); - ptrProgram->setParameter("profiles","ps_2_x arbfp1"); - // set up the preprocessor defines - // Important to do this before any call to get parameters, i.e. before the program gets loaded - ptrProgram->setParameter("compile_arguments", getPPDefines(permutation)); - - setUpBaseParameters(ptrProgram->getDefaultParameters()); - - return GpuProgramPtr(ptrProgram); - } - - virtual MaterialPtr generateTemplateMaterial(Perm permutation) - { - String materialName = mBaseName; - - if(permutation & LightMaterialGenerator::MI_DIRECTIONAL) - { - materialName += "Quad"; - } - else - { - materialName += "Geometry"; - } - - if(permutation & LightMaterialGenerator::MI_SHADOW_CASTER) - { - materialName += "Shadow"; - } - return MaterialManager::getSingleton().getByName(materialName); - } - - protected: - String mBaseName; - String mMasterSource; - // Utility method - String getPPDefines(Perm permutation) - { - String strPPD; - - //Get the type of light - String lightType; - if (permutation & LightMaterialGenerator::MI_POINT) - { - lightType = "POINT"; - } - else if (permutation & LightMaterialGenerator::MI_SPOTLIGHT) - { - lightType = "SPOT"; - } - else if (permutation & LightMaterialGenerator::MI_DIRECTIONAL) - { - lightType = "DIRECTIONAL"; - } - else - { - assert(false && "Permutation must have a light type"); - } - strPPD += "-DLIGHT_TYPE=LIGHT_" + lightType + " "; - - //Optional parameters - if (permutation & LightMaterialGenerator::MI_SPECULAR) - { - strPPD += "-DIS_SPECULAR "; - } - if (permutation & LightMaterialGenerator::MI_ATTENUATED) - { - strPPD += "-DIS_ATTENUATED "; - } - if (permutation & LightMaterialGenerator::MI_SHADOW_CASTER) - { - strPPD += "-DIS_SHADOW_CASTER "; - } - return strPPD; - } - - void setUpBaseParameters(const GpuProgramParametersSharedPtr& params) - { - assert(params.isNull()==false); - - struct AutoParamPair { String name; GpuProgramParameters::AutoConstantType type; }; - - //A list of auto params that might be present in the shaders generated - static const AutoParamPair AUTO_PARAMS[] = { - { "vpWidth", GpuProgramParameters::ACT_VIEWPORT_WIDTH }, - { "vpHeight", GpuProgramParameters::ACT_VIEWPORT_HEIGHT }, - { "worldView", GpuProgramParameters::ACT_WORLDVIEW_MATRIX }, - { "invProj", GpuProgramParameters::ACT_INVERSE_PROJECTION_MATRIX }, - { "invView", GpuProgramParameters::ACT_INVERSE_VIEW_MATRIX }, - { "flip", GpuProgramParameters::ACT_RENDER_TARGET_FLIPPING }, - { "lightDiffuseColor", GpuProgramParameters::ACT_LIGHT_DIFFUSE_COLOUR }, - { "lightSpecularColor", GpuProgramParameters::ACT_LIGHT_SPECULAR_COLOUR }, - { "lightFalloff", GpuProgramParameters::ACT_LIGHT_ATTENUATION }, - { "lightPos", GpuProgramParameters::ACT_LIGHT_POSITION_VIEW_SPACE }, - { "lightDir", GpuProgramParameters::ACT_LIGHT_DIRECTION_VIEW_SPACE }, - { "spotParams", GpuProgramParameters::ACT_SPOTLIGHT_PARAMS }, - { "farClipDistance", GpuProgramParameters::ACT_FAR_CLIP_DISTANCE }, - { "shadowViewProjMat", GpuProgramParameters::ACT_TEXTURE_VIEWPROJ_MATRIX } - }; - int numParams = sizeof(AUTO_PARAMS) / sizeof(AutoParamPair); - - for (int i=0; i_findNamedConstantDefinition(AUTO_PARAMS[i].name)) - { - params->setNamedAutoConstant(AUTO_PARAMS[i].name, AUTO_PARAMS[i].type); - } - } - } -}; - -LightMaterialGenerator::LightMaterialGenerator() -{ - vsMask = 0x00000004; - fsMask = 0x0000003F; - matMask = LightMaterialGenerator::MI_DIRECTIONAL | - LightMaterialGenerator::MI_SHADOW_CASTER; - - materialBaseName = "DeferredShading/LightMaterial/"; - mImpl = new LightMaterialGeneratorCG("DeferredShading/LightMaterial/"); -} - -LightMaterialGenerator::~LightMaterialGenerator() -{ - -} diff --git a/Samples/DeferredShading/src/MaterialGenerator.cpp b/Samples/DeferredShading/src/MaterialGenerator.cpp deleted file mode 100755 --- a/Samples/DeferredShading/src/MaterialGenerator.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/* ------------------------------------------------------------------------------ -This source file is part of OGRE -(Object-oriented Graphics Rendering Engine) -For the latest info, see http://www.ogre3d.org/ - -Copyright (c) 2000-2009 Torus Knot Software Ltd -Also see acknowledgements in Readme.html - -You may use this sample code for anything you like, it is not covered by the -same license as the rest of the engine. ------------------------------------------------------------------------------ -*/ - -#include "MaterialGenerator.h" - -#include "OgreStringConverter.h" -#include "OgreException.h" - -#include "OgrePass.h" -#include "OgreTechnique.h" - -#include "OgreHighLevelGpuProgram.h" -#include "OgreHighLevelGpuProgramManager.h" - -using namespace Ogre; - -MaterialGenerator::MaterialGenerator(): - vsMask(0), fsMask(0), matMask(0), mImpl(0) -{ -} -MaterialGenerator::~MaterialGenerator() -{ - delete mImpl; -} - -const MaterialPtr &MaterialGenerator::getMaterial(Perm permutation) -{ - /// Check if material/shader permutation already was generated - MaterialMap::iterator i = mMaterials.find(permutation); - if(i != mMaterials.end()) - { - return i->second; - } - else - { - /// Create it - MaterialPtr templ = getTemplateMaterial(permutation & matMask); - GpuProgramPtr vs = getVertexShader(permutation & vsMask); - GpuProgramPtr fs = getFragmentShader(permutation & fsMask); - - /// Create material name - String name = materialBaseName + StringConverter::toString(permutation); - - std::cerr << name << " " << vs->getName() << " " << fs->getName() << std::endl; - /// Create material from template, and set shaders - MaterialPtr mat = templ->clone(name); - Technique *tech = mat->getTechnique(0); - Pass *pass = tech->getPass(0); - pass->setFragmentProgram(fs->getName()); - pass->setVertexProgram(vs->getName()); - - /// And store it - mMaterials[permutation] = mat; - return mMaterials[permutation]; - } -} - -const GpuProgramPtr &MaterialGenerator::getVertexShader(Perm permutation) -{ - ProgramMap::iterator i = mVs.find(permutation); - if(i != mVs.end()) - { - return i->second; - } - else - { - /// Create it - mVs[permutation] = mImpl->generateVertexShader(permutation); - return mVs[permutation]; - } -} - -const GpuProgramPtr &MaterialGenerator::getFragmentShader(Perm permutation) -{ - ProgramMap::iterator i = mFs.find(permutation); - if(i != mFs.end()) - { - return i->second; - } - else - { - /// Create it - mFs[permutation] = mImpl->generateFragmentShader(permutation); - return mFs[permutation]; - } -} - -const MaterialPtr &MaterialGenerator::getTemplateMaterial(Perm permutation) -{ - MaterialMap::iterator i = mTemplateMat.find(permutation); - if(i != mTemplateMat.end()) - { - return i->second; - } - else - { - /// Create it - mTemplateMat[permutation] = mImpl->generateTemplateMaterial(permutation); - return mTemplateMat[permutation]; - } -} - -MaterialGenerator::Impl::~Impl() -{ -} - diff --git a/Samples/DeferredShading/src/SSAOLogic.cpp b/Samples/DeferredShading/src/SSAOLogic.cpp deleted file mode 100644 --- a/Samples/DeferredShading/src/SSAOLogic.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* ------------------------------------------------------------------------------ -This source file is part of OGRE -(Object-oriented Graphics Rendering Engine) -For the latest info, see http://www.ogre3d.org/ - -Copyright (c) 2000-2009 Torus Knot Software Ltd -Also see acknowledgements in Readme.html - -You may use this sample code for anything you like, it is not covered by the -same license as the rest of the engine. ------------------------------------------------------------------------------ -*/ - -#include "SSAOLogic.h" - -#include -using namespace Ogre; - -class ssaoListener: public Ogre::CompositorInstance::Listener -{ -public: - - ssaoListener(Ogre::CompositorInstance* instance) : mInstance(instance) {} - - // this callback we will use to modify SSAO parameters - void notifyMaterialRender(Ogre::uint32 pass_id, Ogre::MaterialPtr &mat) - { - if (pass_id != 42) // not SSAO, return - return; - - // this is the camera you're using - Ogre::Camera *cam = mInstance->getChain()->getViewport()->getCamera(); - - // calculate the far-top-right corner in view-space - Ogre::Vector3 farCorner = cam->getViewMatrix(true) * cam->getWorldSpaceCorners()[4]; - - // get the pass - Ogre::Pass *pass = mat->getBestTechnique()->getPass(0); - - // get the vertex shader parameters - Ogre::GpuProgramParametersSharedPtr params = pass->getVertexProgramParameters(); - // set the camera's far-top-right corner - if (params->_findNamedConstantDefinition("farCorner")) - params->setNamedConstant("farCorner", farCorner); - - // get the fragment shader parameters - params = pass->getFragmentProgramParameters(); - // set the projection matrix we need - static const Ogre::Matrix4 CLIP_SPACE_TO_IMAGE_SPACE( - 0.5, 0, 0, 0.5, - 0, -0.5, 0, 0.5, - 0, 0, 1, 0, - 0, 0, 0, 1); - if (params->_findNamedConstantDefinition("ptMat")) - params->setNamedConstant("ptMat", CLIP_SPACE_TO_IMAGE_SPACE * cam->getProjectionMatrixWithRSDepth()); - if (params->_findNamedConstantDefinition("far")) - params->setNamedConstant("far", cam->getFarClipDistance()); - } -private: - Ogre::CompositorInstance* mInstance; -}; - -Ogre::CompositorInstance::Listener* SSAOLogic::createListener(Ogre::CompositorInstance* instance) -{ - return new ssaoListener(instance); -}