diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index cfcf9f76b..a6b712abf 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -357,6 +357,7 @@ void OMW::Engine::go() addResourcesDirectory(mResDir / "mygui"); addResourcesDirectory(mResDir / "water"); + addResourcesDirectory(mResDir / "gbuffer"); // Create the window mOgre->createWindow("OpenMW"); diff --git a/apps/openmw/mwrender/occlusionquery.cpp b/apps/openmw/mwrender/occlusionquery.cpp index ff1ce82e7..5be7202b3 100644 --- a/apps/openmw/mwrender/occlusionquery.cpp +++ b/apps/openmw/mwrender/occlusionquery.cpp @@ -40,9 +40,6 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod return; } - // This means that everything up to RQG_Main can occlude the objects that are tested - const int queue = RQG_Main+1; - MaterialPtr matBase = MaterialManager::getSingleton().getByName("BaseWhiteNoLighting"); MaterialPtr matQueryArea = matBase->clone("QueryTotalPixels"); matQueryArea->setDepthWriteEnabled(false); @@ -65,14 +62,14 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod mBBQueryTotal->setDefaultDimensions(150, 150); mBBQueryTotal->createBillboard(Vector3::ZERO); mBBQueryTotal->setMaterialName("QueryTotalPixels"); - mBBQueryTotal->setRenderQueueGroup(queue+1); + mBBQueryTotal->setRenderQueueGroup(RQG_OcclusionQuery+1); mBBNodeReal->attachObject(mBBQueryTotal); mBBQueryVisible = mRendering->getScene()->createBillboardSet(1); mBBQueryVisible->setDefaultDimensions(150, 150); mBBQueryVisible->createBillboard(Vector3::ZERO); mBBQueryVisible->setMaterialName("QueryVisiblePixels"); - mBBQueryVisible->setRenderQueueGroup(queue+1); + mBBQueryVisible->setRenderQueueGroup(RQG_OcclusionQuery+1); mBBNodeReal->attachObject(mBBQueryVisible); mBBQuerySingleObject = mRendering->getScene()->createBillboardSet(1); @@ -80,7 +77,7 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod mBBQuerySingleObject->setDefaultDimensions(0.003, 0.003); mBBQuerySingleObject->createBillboard(Vector3::ZERO); mBBQuerySingleObject->setMaterialName("QueryVisiblePixels"); - mBBQuerySingleObject->setRenderQueueGroup(queue); + mBBQuerySingleObject->setRenderQueueGroup(RQG_OcclusionQuery); mObjectNode->attachObject(mBBQuerySingleObject); mRendering->getScene()->addRenderObjectListener(this); diff --git a/apps/openmw/mwrender/renderconst.hpp b/apps/openmw/mwrender/renderconst.hpp index 6eba8d92e..113024ace 100644 --- a/apps/openmw/mwrender/renderconst.hpp +++ b/apps/openmw/mwrender/renderconst.hpp @@ -14,6 +14,8 @@ enum RenderQueueGroups RQG_Main = Ogre::RENDER_QUEUE_MAIN, + RQG_OcclusionQuery = Ogre::RENDER_QUEUE_MAIN+1, + RQG_Alpha = Ogre::RENDER_QUEUE_7, // Sky late (sun & sun flare) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 98344297f..7797d1852 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -37,6 +37,14 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const // Load resources ResourceGroupManager::getSingleton().initialiseAllResourceGroups(); + if (Settings::Manager::getBool("multiple render targets", "Render")) + { + CompositorManager::getSingleton().addCompositor(mRendering.getViewport(), "gbuffer"); + CompositorManager::getSingleton().setCompositorEnabled(mRendering.getViewport(), "gbuffer", true); + CompositorManager::getSingleton().addCompositor(mRendering.getViewport(), "gbufferFinalizer"); + CompositorManager::getSingleton().setCompositorEnabled(mRendering.getViewport(), "gbufferFinalizer", true); + } + // Turn the entire scene (represented by the 'root' node) -90 // degrees around the x axis. This makes Z go upwards, and Y go into // the screen (when x is to the right.) This is the orientation that @@ -252,11 +260,22 @@ bool RenderingManager::toggleRenderMode(int mode) { if (mRendering.getCamera()->getPolygonMode() == PM_SOLID) { + // disable compositors + CompositorManager::getSingleton().setCompositorEnabled(mRendering.getViewport(), "gbuffer", false); + CompositorManager::getSingleton().setCompositorEnabled(mRendering.getViewport(), "gbufferFinalizer", false); + mRendering.getCamera()->setPolygonMode(PM_WIREFRAME); return true; } else { + // re-enable compositors + if (Settings::Manager::getBool("multiple render targets", "Render")) + { + CompositorManager::getSingleton().setCompositorEnabled(mRendering.getViewport(), "gbuffer", true); + CompositorManager::getSingleton().setCompositorEnabled(mRendering.getViewport(), "gbufferFinalizer", true); + } + mRendering.getCamera()->setPolygonMode(PM_SOLID); return false; } diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index 1983616d6..b3db66189 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -181,6 +181,21 @@ Ogre::MaterialPtr Water::createMaterial() if (mReflectionTarget == 0) mat->removeTechnique(0); + if (Settings::Manager::getBool("multiple render targets", "Render")) + { + CompositorInstance* compositor = CompositorManager::getSingleton().getCompositorChain(mViewport)->getCompositor("gbuffer"); + + TexturePtr colorTexture = compositor->getTextureInstance("mrt_output", 0); + TextureUnitState* tus = mat->getTechnique(0)->getPass(0)->getTextureUnitState("refractionMap"); + if (tus != 0) + tus->setTexture(colorTexture); + + TexturePtr depthTexture = compositor->getTextureInstance("mrt_output", 1); + tus = mat->getTechnique(0)->getPass(0)->getTextureUnitState("depthMap"); + if (tus != 0) + tus->setTexture(depthTexture); + } + return mat; } diff --git a/files/CMakeLists.txt b/files/CMakeLists.txt index 56c3db862..377e2d1f8 100644 --- a/files/CMakeLists.txt +++ b/files/CMakeLists.txt @@ -8,3 +8,7 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/water.compositor "${OpenMW_BINA configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/water.material "${OpenMW_BINARY_DIR}/resources/water/water.material" COPYONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/WaterNormal2.tga "${OpenMW_BINARY_DIR}/resources/water/WaterNormal2.tga" COPYONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/water.cg "${OpenMW_BINARY_DIR}/resources/water/water.cg" COPYONLY) + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/gbuffer/gbuffer.cg "${OpenMW_BINARY_DIR}/resources/gbuffer/gbuffer.cg" COPYONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/gbuffer/gbuffer.material "${OpenMW_BINARY_DIR}/resources/gbuffer/gbuffer.material" COPYONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/gbuffer/gbuffer.compositor "${OpenMW_BINARY_DIR}/resources/gbuffer/gbuffer.compositor" COPYONLY) diff --git a/files/gbuffer/gbuffer.compositor b/files/gbuffer/gbuffer.compositor index e69de29bb..d51d3700c 100644 --- a/files/gbuffer/gbuffer.compositor +++ b/files/gbuffer/gbuffer.compositor @@ -0,0 +1,81 @@ +// Compositor that just controls output to the MRT textures +compositor gbuffer +{ + technique + { + // MRT output. Currently this is a color texture plus a depth texture + texture mrt_output target_width target_height PF_FLOAT16_RGBA PF_FLOAT16_RGBA chain_scope depth_pool 2 + + target mrt_output + { + input none + pass clear + { + } + pass render_scene + { + first_render_queue 0 + last_render_queue 69 + } + + } + + target_output + { + input none + + pass render_quad + { + material RenderScene + input 0 mrt_output 0 + } + } + } +} + +// Finalizer compositor to render objects that we don't want in the MRT textures (this is the case for most transparent stuff) +compositor gbufferFinalizer +{ + technique + { + texture no_mrt_output target_width target_height PF_R8G8B8A8 depth_pool 2 no_fsaa + texture previousscene target_width target_height PF_R8G8B8A8 + + target previousscene + { + input previous + } + target no_mrt_output + { + input none + shadows off + pass clear + { + buffers colour + colour_value 0 0 0 0 + } + pass render_quad + { + material RenderSceneNoDepth + input 0 previousscene + } + pass render_scene + { + first_render_queue 70 + last_render_queue 100 + } + } + target_output + { + input none + pass clear + { + } + pass render_quad + { + material RenderSceneNoDepth + input 0 no_mrt_output + } + } + } +} diff --git a/files/gbuffer/gbuffer.material b/files/gbuffer/gbuffer.material index e69de29bb..faa8dd498 100644 --- a/files/gbuffer/gbuffer.material +++ b/files/gbuffer/gbuffer.material @@ -0,0 +1,63 @@ +vertex_program RenderGBuffer_vs cg +{ + source gbuffer.cg + profiles vs_4_0 vs_1_1 arbvp1 + entry_point RenderScene_vs + default_params + { + param_named_auto wvp worldviewproj_matrix + } +} +fragment_program RenderGBuffer_ps cg +{ + source gbuffer.cg + entry_point RenderScene_ps + profiles ps_4_0 ps_2_x arbfp1 + default_params + { + } +} +material RenderScene +{ + technique + { + pass + { + vertex_program_ref RenderGBuffer_vs + { + } + + fragment_program_ref RenderGBuffer_ps + { + } + + texture_unit tex1 + { + //scenebuffer + } + } + } +} + +material RenderSceneNoDepth +{ + technique + { + pass + { + depth_write off + vertex_program_ref RenderGBuffer_vs + { + } + + fragment_program_ref RenderGBuffer_ps + { + } + + texture_unit tex1 + { + //scenebuffer + } + } + } +} diff --git a/files/water/GlassFP.cg b/files/water/GlassFP.cg index c294f6fff..0ce343b0a 100644 --- a/files/water/GlassFP.cg +++ b/files/water/GlassFP.cg @@ -1,9 +1,9 @@ -sampler RT : register(s0); -sampler NormalMap : register(s1); -sampler CausticMap : register(s2); float4 main_ps(float2 iTexCoord : TEXCOORD0, float3 noiseCoord : TEXCOORD1, + uniform sampler2D RT : register(s0), + uniform sampler2D NormalMap : register(s1), + uniform sampler2D CausticMap : register(s2), uniform float4 tintColour) : COLOR { float4 normal = tex2D(NormalMap, noiseCoord) * 2 - 1; diff --git a/files/water/water.cg b/files/water/water.cg index 70d3339b1..88515c3e8 100644 --- a/files/water/water.cg +++ b/files/water/water.cg @@ -34,7 +34,8 @@ void main_fp , uniform float renderTargetFlipping , uniform sampler2D reflectionMap : register(s0) - , uniform sampler2D normalMap : register(s1) + , uniform sampler2D refractionMap : register(s1) + , uniform sampler2D normalMap : register(s2) , uniform float time , uniform float4 fogParams , uniform float4 fogColour @@ -42,7 +43,7 @@ void main_fp { float2 screenCoords = iScreenCoords.xy / iScreenCoords.z; - screenCoords.y = (renderTargetFlipping == -1) ? (1-screenCoords.y) : screenCoords.y; + screenCoords.y = (1-saturate(renderTargetFlipping))+renderTargetFlipping*screenCoords.y; float2 uv1 = iUv + time * float2(0.5, 0); float2 uv2 = iUv + time * float2(0, 0.5); @@ -55,8 +56,11 @@ void main_fp screenCoords += normal.yx * 0.05; float4 reflection = tex2D(reflectionMap, screenCoords); + float4 refraction = tex2D(refractionMap, screenCoords); + + oColor.xyz = lerp(reflection.xyz, refraction.xyz, 1); float fogValue = saturate((iDepth - fogParams.y) * fogParams.w); - oColor.xyz = lerp(reflection.xyz, fogColour, fogValue); - oColor.a = 0.45; + oColor.xyz = lerp(oColor.xyz, fogColour, fogValue); + oColor.a = 1; } diff --git a/files/water/water.material b/files/water/water.material index bca5a9281..c964e9ae4 100644 --- a/files/water/water.material +++ b/files/water/water.material @@ -48,13 +48,13 @@ material Water vertex_program_ref Water_VP { - param_named_auto renderTargetFlipping render_target_flipping } fragment_program_ref Water_FP { param_named_auto time time 0.1 param_named_auto fogColour fog_colour param_named_auto fogParams fog_params + param_named_auto renderTargetFlipping render_target_flipping } texture_unit reflectionMap @@ -62,6 +62,12 @@ material Water texture WaterReflection tex_address_mode clamp } + + texture_unit refractionMap + { + tex_address_mode clamp + } + texture_unit normalMap { texture WaterNormal2.tga