mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-29 22:15:32 +00:00
Merge remote branch 'scrawl/graphics'
This commit is contained in:
commit
a4fb71a0fc
29 changed files with 1634 additions and 238 deletions
|
@ -228,6 +228,9 @@ endif (APPLE)
|
|||
configure_file(${OpenMW_SOURCE_DIR}/files/settings-default.cfg
|
||||
"${OpenMW_BINARY_DIR}/settings-default.cfg")
|
||||
|
||||
configure_file(${OpenMW_SOURCE_DIR}/files/transparency-overrides.cfg
|
||||
"${OpenMW_BINARY_DIR}/transparency-overrides.cfg")
|
||||
|
||||
configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg.local
|
||||
"${OpenMW_BINARY_DIR}/openmw.cfg")
|
||||
configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg
|
||||
|
@ -309,6 +312,7 @@ if(DPKG_PROGRAM)
|
|||
|
||||
#Install global configuration files
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/settings-default.cfg" DESTINATION "../etc/openmw/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/transparency-overrides.cfg" DESTINATION "../etc/openmw/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "../etc/openmw/" RENAME "openmw.cfg" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/plugins.cfg" DESTINATION "../etc/openmw/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ source_group(game FILES ${GAME} ${GAME_HEADER})
|
|||
|
||||
add_openmw_dir (mwrender
|
||||
renderingmanager debugging sky player animation npcanimation creatureanimation actors objects
|
||||
renderinginterface localmap occlusionquery terrain terrainmaterial water
|
||||
renderinginterface localmap occlusionquery terrain terrainmaterial water shadows shaderhelper
|
||||
)
|
||||
|
||||
add_openmw_dir (mwinput
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <components/files/fixedpath.hpp>
|
||||
#include <components/files/configurationmanager.hpp>
|
||||
#include <components/settings/settings.hpp>
|
||||
#include <components/nifoverrides/nifoverrides.hpp>
|
||||
|
||||
#include <components/nifbullet/bullet_nif_loader.hpp>
|
||||
#include <components/nifogre/ogre_nif_loader.hpp>
|
||||
|
@ -350,6 +351,13 @@ void OMW::Engine::go()
|
|||
|
||||
mFpsLevel = settings.getInt("fps", "HUD");
|
||||
|
||||
// load nif overrides
|
||||
NifOverrides::Overrides nifOverrides;
|
||||
if (boost::filesystem::exists(mCfgMgr.getLocalPath().string() + "/transparency-overrides.cfg"))
|
||||
nifOverrides.loadTransparencyOverrides(mCfgMgr.getLocalPath().string() + "/transparency-overrides.cfg");
|
||||
else if (boost::filesystem::exists(mCfgMgr.getGlobalPath().string() + "/transparency-overrides.cfg"))
|
||||
nifOverrides.loadTransparencyOverrides(mCfgMgr.getGlobalPath().string() + "/transparency-overrides.cfg");
|
||||
|
||||
mOgre->configure(!boost::filesystem::is_regular_file(mCfgMgr.getOgreConfigPath()),
|
||||
mCfgMgr.getOgreConfigPath().string(),
|
||||
mCfgMgr.getLogPath().string(),
|
||||
|
@ -363,6 +371,7 @@ void OMW::Engine::go()
|
|||
addResourcesDirectory(mResDir / "mygui");
|
||||
addResourcesDirectory(mResDir / "water");
|
||||
addResourcesDirectory(mResDir / "gbuffer");
|
||||
addResourcesDirectory(mResDir / "shadows");
|
||||
|
||||
// Create the window
|
||||
mOgre->createWindow("OpenMW");
|
||||
|
|
|
@ -225,7 +225,9 @@ void LocalMap::render(const float x, const float y,
|
|||
vp->setShadowsEnabled(false);
|
||||
vp->setBackgroundColour(ColourValue(0, 0, 0));
|
||||
vp->setVisibilityMask(RV_Map);
|
||||
vp->setMaterialScheme("Map");
|
||||
|
||||
// use fallback techniques without shadows and without mrt
|
||||
vp->setMaterialScheme("Fallback");
|
||||
|
||||
rtt->update();
|
||||
|
||||
|
|
|
@ -193,6 +193,8 @@ void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh)
|
|||
|
||||
sg->setVisibilityFlags(small ? RV_StaticsSmall : RV_Statics);
|
||||
|
||||
sg->setCastShadows(true);
|
||||
|
||||
sg->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main);
|
||||
|
||||
mRenderer.getScene()->destroyEntity(ent);
|
||||
|
|
|
@ -60,6 +60,7 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod
|
|||
mBBNodeReal = mRendering->getScene()->getRootSceneNode()->createChildSceneNode();
|
||||
|
||||
mBBQueryTotal = mRendering->getScene()->createBillboardSet(1);
|
||||
mBBQueryTotal->setCastShadows(false);
|
||||
mBBQueryTotal->setDefaultDimensions(150, 150);
|
||||
mBBQueryTotal->createBillboard(Vector3::ZERO);
|
||||
mBBQueryTotal->setMaterialName("QueryTotalPixels");
|
||||
|
@ -67,6 +68,7 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod
|
|||
mBBNodeReal->attachObject(mBBQueryTotal);
|
||||
|
||||
mBBQueryVisible = mRendering->getScene()->createBillboardSet(1);
|
||||
mBBQueryVisible->setCastShadows(false);
|
||||
mBBQueryVisible->setDefaultDimensions(150, 150);
|
||||
mBBQueryVisible->createBillboard(Vector3::ZERO);
|
||||
mBBQueryVisible->setMaterialName("QueryVisiblePixels");
|
||||
|
@ -75,6 +77,7 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod
|
|||
|
||||
mBBQuerySingleObject = mRendering->getScene()->createBillboardSet(1);
|
||||
/// \todo ideally this should occupy exactly 1 pixel on the screen
|
||||
mBBQuerySingleObject->setCastShadows(false);
|
||||
mBBQuerySingleObject->setDefaultDimensions(0.003, 0.003);
|
||||
mBBQuerySingleObject->createBillboard(Vector3::ZERO);
|
||||
mBBQuerySingleObject->setMaterialName("QueryVisiblePixels");
|
||||
|
|
|
@ -14,6 +14,10 @@
|
|||
#include <components/esm/loadstat.hpp>
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
#include "shadows.hpp"
|
||||
#include "shaderhelper.hpp"
|
||||
#include "localmap.hpp"
|
||||
#include "water.hpp"
|
||||
|
||||
using namespace MWRender;
|
||||
using namespace Ogre;
|
||||
|
@ -21,11 +25,9 @@ using namespace Ogre;
|
|||
namespace MWRender {
|
||||
|
||||
RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const boost::filesystem::path& resDir, OEngine::Physic::PhysicEngine* engine, MWWorld::Environment& environment)
|
||||
:mRendering(_rend), mObjects(mRendering), mActors(mRendering, environment), mAmbientMode(0)
|
||||
:mRendering(_rend), mObjects(mRendering), mActors(mRendering, environment), mAmbientMode(0), mSunEnabled(0)
|
||||
{
|
||||
mRendering.createScene("PlayerCam", Settings::Manager::getFloat("field of view", "General"), 5);
|
||||
mTerrainManager = new TerrainManager(mRendering.getScene(),
|
||||
environment);
|
||||
|
||||
mWater = 0;
|
||||
|
||||
|
@ -86,6 +88,12 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
|
|||
Ogre::SceneNode *cameraPitchNode = cameraYawNode->createChildSceneNode();
|
||||
cameraPitchNode->attachObject(mRendering.getCamera());
|
||||
|
||||
mShadows = new Shadows(&mRendering);
|
||||
mShaderHelper = new ShaderHelper(this);
|
||||
|
||||
mTerrainManager = new TerrainManager(mRendering.getScene(), this,
|
||||
environment);
|
||||
|
||||
//mSkyManager = 0;
|
||||
mSkyManager = new SkyManager(mMwRoot, mRendering.getCamera(), &environment);
|
||||
|
||||
|
@ -412,6 +420,7 @@ void RenderingManager::skipAnimation (const MWWorld::Ptr& ptr)
|
|||
|
||||
void RenderingManager::setSunColour(const Ogre::ColourValue& colour)
|
||||
{
|
||||
if (!mSunEnabled) return;
|
||||
mSun->setDiffuseColour(colour);
|
||||
mSun->setSpecularColour(colour);
|
||||
mTerrainManager->setDiffuse(colour);
|
||||
|
@ -425,12 +434,21 @@ void RenderingManager::setAmbientColour(const Ogre::ColourValue& colour)
|
|||
|
||||
void RenderingManager::sunEnable()
|
||||
{
|
||||
if (mSun) mSun->setVisible(true);
|
||||
// Don't disable the light, as the shaders assume the first light to be directional.
|
||||
//if (mSun) mSun->setVisible(true);
|
||||
mSunEnabled = true;
|
||||
}
|
||||
|
||||
void RenderingManager::sunDisable()
|
||||
{
|
||||
if (mSun) mSun->setVisible(false);
|
||||
// Don't disable the light, as the shaders assume the first light to be directional.
|
||||
//if (mSun) mSun->setVisible(false);
|
||||
mSunEnabled = false;
|
||||
if (mSun)
|
||||
{
|
||||
mSun->setDiffuseColour(ColourValue(0,0,0));
|
||||
mSun->setSpecularColour(ColourValue(0,0,0));
|
||||
}
|
||||
}
|
||||
|
||||
void RenderingManager::setSunDirection(const Ogre::Vector3& direction)
|
||||
|
@ -475,4 +493,9 @@ const bool RenderingManager::useMRT()
|
|||
return Settings::Manager::getBool("shader", "Water");
|
||||
}
|
||||
|
||||
Shadows* RenderingManager::getShadows()
|
||||
{
|
||||
return mShadows;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -25,8 +25,6 @@
|
|||
#include "objects.hpp"
|
||||
#include "actors.hpp"
|
||||
#include "player.hpp"
|
||||
#include "water.hpp"
|
||||
#include "localmap.hpp"
|
||||
#include "occlusionquery.hpp"
|
||||
|
||||
namespace Ogre
|
||||
|
@ -45,7 +43,10 @@ namespace MWWorld
|
|||
namespace MWRender
|
||||
{
|
||||
|
||||
|
||||
class Shadows;
|
||||
class ShaderHelper;
|
||||
class LocalMap;
|
||||
class Water;
|
||||
|
||||
class RenderingManager: private RenderingInterface {
|
||||
|
||||
|
@ -114,6 +115,8 @@ class RenderingManager: private RenderingInterface {
|
|||
bool occlusionQuerySupported() { return mOcclusionQuery->supported(); };
|
||||
OcclusionQuery* getOcclusionQuery() { return mOcclusionQuery; };
|
||||
|
||||
Shadows* getShadows();
|
||||
|
||||
void setGlare(bool glare);
|
||||
void skyEnable ();
|
||||
void skyDisable ();
|
||||
|
@ -149,6 +152,8 @@ class RenderingManager: private RenderingInterface {
|
|||
|
||||
void setAmbientMode();
|
||||
|
||||
bool mSunEnabled;
|
||||
|
||||
SkyManager* mSkyManager;
|
||||
|
||||
OcclusionQuery* mOcclusionQuery;
|
||||
|
@ -180,6 +185,10 @@ class RenderingManager: private RenderingInterface {
|
|||
MWRender::Debugging *mDebugging;
|
||||
|
||||
MWRender::LocalMap* mLocalMap;
|
||||
|
||||
MWRender::Shadows* mShadows;
|
||||
|
||||
MWRender::ShaderHelper* mShaderHelper;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
308
apps/openmw/mwrender/shaderhelper.cpp
Normal file
308
apps/openmw/mwrender/shaderhelper.cpp
Normal file
|
@ -0,0 +1,308 @@
|
|||
#include "shaderhelper.hpp"
|
||||
#include "renderingmanager.hpp"
|
||||
#include "shadows.hpp"
|
||||
|
||||
#include <OgreHighLevelGpuProgramManager.h>
|
||||
#include <OgreHighLevelGpuProgram.h>
|
||||
#include <OgreGpuProgramParams.h>
|
||||
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
using namespace Ogre;
|
||||
using namespace MWRender;
|
||||
|
||||
ShaderHelper::ShaderHelper(RenderingManager* rend)
|
||||
{
|
||||
mRendering = rend;
|
||||
applyShaders();
|
||||
}
|
||||
|
||||
void ShaderHelper::applyShaders()
|
||||
{
|
||||
if (!Settings::Manager::getBool("shaders", "Objects")) return;
|
||||
|
||||
bool mrt = RenderingManager::useMRT();
|
||||
bool shadows = Settings::Manager::getBool("enabled", "Shadows");
|
||||
bool split = Settings::Manager::getBool("split", "Shadows");
|
||||
|
||||
// shader for normal rendering
|
||||
createShader(mrt, shadows, split, "main");
|
||||
|
||||
// fallback shader without mrt and without shadows
|
||||
// (useful for reflection and for minimap)
|
||||
createShader(false, false, false, "main_fallback");
|
||||
}
|
||||
|
||||
void ShaderHelper::createShader(const bool mrt, const bool shadows, const bool split, const std::string& name)
|
||||
{
|
||||
HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton();
|
||||
|
||||
const int numsplits = 3;
|
||||
|
||||
// the number of lights to support.
|
||||
// when rendering an object, OGRE automatically picks the lights that are
|
||||
// closest to the object being rendered. unfortunately this mechanism does
|
||||
// not work perfectly for objects batched together (they will all use the same
|
||||
// lights). to work around this, we are simply pushing the maximum number
|
||||
// of lights here in order to minimize disappearing lights.
|
||||
int num_lights = Settings::Manager::getInt("num lights", "Objects");
|
||||
|
||||
{
|
||||
// vertex
|
||||
HighLevelGpuProgramPtr vertex;
|
||||
if (!mgr.getByName(name+"_vp").isNull())
|
||||
mgr.remove(name+"_vp");
|
||||
|
||||
vertex = mgr.createProgram(name+"_vp", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||
"cg", GPT_VERTEX_PROGRAM);
|
||||
vertex->setParameter("profiles", "vs_4_0 vs_2_x vp40 arbvp1");
|
||||
vertex->setParameter("entry_point", "main_vp");
|
||||
StringUtil::StrStreamType outStream;
|
||||
outStream <<
|
||||
"void main_vp( \n"
|
||||
" float4 position : POSITION, \n"
|
||||
" float4 normal : NORMAL, \n"
|
||||
" float4 colour : COLOR, \n"
|
||||
" in float2 uv : TEXCOORD0, \n"
|
||||
" out float2 oUV : TEXCOORD0, \n"
|
||||
" out float4 oPosition : POSITION, \n"
|
||||
" out float4 oPositionObjSpace : TEXCOORD1, \n"
|
||||
" out float4 oNormal : TEXCOORD2, \n"
|
||||
" out float oDepth : TEXCOORD3, \n"
|
||||
" out float4 oVertexColour : TEXCOORD4, \n";
|
||||
if (shadows && !split) outStream <<
|
||||
" out float4 oLightSpacePos0 : TEXCOORD5, \n"
|
||||
" uniform float4x4 worldMatrix, \n"
|
||||
" uniform float4x4 texViewProjMatrix0, \n";
|
||||
else
|
||||
{
|
||||
for (int i=0; i<numsplits; ++i)
|
||||
{
|
||||
outStream <<
|
||||
" out float4 oLightSpacePos"<<i<<" : TEXCOORD"<<i+5<<", \n"
|
||||
" uniform float4x4 texViewProjMatrix"<<i<<", \n";
|
||||
}
|
||||
outStream <<
|
||||
" uniform float4x4 worldMatrix, \n";
|
||||
}
|
||||
outStream <<
|
||||
" uniform float4x4 worldViewProj \n"
|
||||
") \n"
|
||||
"{ \n"
|
||||
" oVertexColour = colour; \n"
|
||||
" oUV = uv; \n"
|
||||
" oNormal = normal; \n"
|
||||
" oPosition = mul( worldViewProj, position ); \n"
|
||||
" oDepth = oPosition.z; \n"
|
||||
" oPositionObjSpace = position; \n";
|
||||
if (shadows && !split) outStream <<
|
||||
" oLightSpacePos0 = mul(texViewProjMatrix0, mul(worldMatrix, position)); \n";
|
||||
else
|
||||
{
|
||||
outStream <<
|
||||
" float4 wPos = mul(worldMatrix, position); \n";
|
||||
for (int i=0; i<numsplits; ++i)
|
||||
{
|
||||
outStream <<
|
||||
" oLightSpacePos"<<i<<" = mul(texViewProjMatrix"<<i<<", wPos); \n";
|
||||
}
|
||||
}
|
||||
outStream <<
|
||||
"}";
|
||||
vertex->setSource(outStream.str());
|
||||
vertex->load();
|
||||
vertex->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
|
||||
if (shadows)
|
||||
{
|
||||
vertex->getDefaultParameters()->setNamedAutoConstant("worldMatrix", GpuProgramParameters::ACT_WORLD_MATRIX);
|
||||
if (!split)
|
||||
vertex->getDefaultParameters()->setNamedAutoConstant("texViewProjMatrix0", GpuProgramParameters::ACT_TEXTURE_VIEWPROJ_MATRIX, 0);
|
||||
else
|
||||
{
|
||||
for (int i=0; i<numsplits; ++i)
|
||||
{
|
||||
vertex->getDefaultParameters()->setNamedAutoConstant("texViewProjMatrix"+StringConverter::toString(i), GpuProgramParameters::ACT_TEXTURE_VIEWPROJ_MATRIX, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// fragment
|
||||
HighLevelGpuProgramPtr fragment;
|
||||
if (!mgr.getByName(name+"_fp").isNull())
|
||||
mgr.remove(name+"_fp");
|
||||
|
||||
fragment = mgr.createProgram(name+"_fp", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||
"cg", GPT_FRAGMENT_PROGRAM);
|
||||
fragment->setParameter("profiles", "ps_4_0 ps_2_x fp40 arbfp1");
|
||||
fragment->setParameter("entry_point", "main_fp");
|
||||
StringUtil::StrStreamType outStream;
|
||||
|
||||
if (shadows) outStream <<
|
||||
"float depthShadow(sampler2D shadowMap, float4 shadowMapPos, float2 offset) \n"
|
||||
"{ \n"
|
||||
" shadowMapPos /= shadowMapPos.w; \n"
|
||||
" float3 o = float3(offset.xy, -offset.x) * 0.3f; \n"
|
||||
" float c = (shadowMapPos.z <= tex2D(shadowMap, shadowMapPos.xy - o.xy).r) ? 1 : 0; // top left \n"
|
||||
" c += (shadowMapPos.z <= tex2D(shadowMap, shadowMapPos.xy + o.xy).r) ? 1 : 0; // bottom right \n"
|
||||
" c += (shadowMapPos.z <= tex2D(shadowMap, shadowMapPos.xy + o.zy).r) ? 1 : 0; // bottom left \n"
|
||||
" c += (shadowMapPos.z <= tex2D(shadowMap, shadowMapPos.xy - o.zy).r) ? 1 : 0; // top right \n"
|
||||
" return c / 4; \n"
|
||||
"} \n";
|
||||
|
||||
outStream <<
|
||||
"void main_fp( \n"
|
||||
" in float2 uv : TEXCOORD0, \n"
|
||||
" out float4 oColor : COLOR, \n"
|
||||
" uniform sampler2D texture : register(s0), \n"
|
||||
" float4 positionObjSpace : TEXCOORD1, \n"
|
||||
" float4 normal : TEXCOORD2, \n"
|
||||
" float iDepth : TEXCOORD3, \n"
|
||||
" float4 vertexColour : TEXCOORD4, \n"
|
||||
" uniform float4 fogColour, \n"
|
||||
" uniform float4 fogParams, \n";
|
||||
|
||||
if (shadows) outStream <<
|
||||
" uniform float4 shadowFar_fadeStart, \n";
|
||||
|
||||
if (shadows && !split) outStream <<
|
||||
" uniform sampler2D shadowMap : register(s1), \n"
|
||||
" float4 lightSpacePos0 : TEXCOORD5, \n"
|
||||
" uniform float4 invShadowmapSize0, \n";
|
||||
else
|
||||
{
|
||||
outStream <<
|
||||
" uniform float4 pssmSplitPoints, \n";
|
||||
for (int i=0; i<numsplits; ++i)
|
||||
{
|
||||
outStream <<
|
||||
" uniform sampler2D shadowMap"<<i<<" : register(s"<<i+1<<"), \n"
|
||||
" float4 lightSpacePos"<<i<<" : TEXCOORD"<<i+5<<", \n"
|
||||
" uniform float4 invShadowmapSize"<<i<<", \n";
|
||||
}
|
||||
}
|
||||
|
||||
if (mrt) outStream <<
|
||||
" out float4 oColor1 : COLOR1, \n"
|
||||
" uniform float far, \n";
|
||||
|
||||
for (int i=0; i<num_lights; ++i)
|
||||
{
|
||||
outStream <<
|
||||
" uniform float4 lightDiffuse"<<i<<", \n"
|
||||
" uniform float4 lightPositionObjSpace"<<i<<", \n"
|
||||
" uniform float4 lightAttenuation"<<i<<", \n";
|
||||
}
|
||||
outStream <<
|
||||
" uniform float4 lightAmbient, \n"
|
||||
" uniform float4 ambient, \n"
|
||||
" uniform float4 diffuse, \n"
|
||||
" uniform float4 emissive \n"
|
||||
") \n"
|
||||
"{ \n"
|
||||
" float4 tex = tex2D(texture, uv); \n"
|
||||
" float d; \n"
|
||||
" float attn; \n"
|
||||
" float3 lightDir; \n"
|
||||
" float3 lightColour = float3(0, 0, 0); \n";
|
||||
|
||||
for (int i=0; i<num_lights; ++i)
|
||||
{
|
||||
outStream <<
|
||||
" lightDir = lightPositionObjSpace"<<i<<".xyz - (positionObjSpace.xyz * lightPositionObjSpace"<<i<<".w); \n"
|
||||
|
||||
// pre-multiply light color with attenuation factor
|
||||
" d = length( lightDir ); \n"
|
||||
" attn = ( 1.0 / (( lightAttenuation"<<i<<".y ) + ( lightAttenuation"<<i<<".z * d ) + ( lightAttenuation"<<i<<".w * d * d ))); \n"
|
||||
" lightDiffuse"<<i<<" *= attn; \n";
|
||||
|
||||
if (i == 0 && shadows)
|
||||
{
|
||||
outStream <<
|
||||
" float shadow; \n";
|
||||
if (!split) outStream <<
|
||||
" shadow = depthShadow(shadowMap, lightSpacePos0, invShadowmapSize0.xy); \n";
|
||||
else
|
||||
{
|
||||
for (int j=0; j<numsplits; ++j)
|
||||
{
|
||||
std::string channel;
|
||||
if (j==0) channel = "x";
|
||||
else if (j==1) channel = "y";
|
||||
else if (j==2) channel = "z";
|
||||
|
||||
if (j==0)
|
||||
outStream << " if (iDepth <= pssmSplitPoints." << channel << ") \n";
|
||||
else if (j < numsplits - 1)
|
||||
outStream << " else if (iDepth <= pssmSplitPoints." << channel << ") \n";
|
||||
else
|
||||
outStream << " else \n";
|
||||
|
||||
outStream <<
|
||||
" { \n"
|
||||
" shadow = depthShadow(shadowMap" << j << ", lightSpacePos" << j << ", invShadowmapSize" << j << ".xy); \n"
|
||||
" } \n";
|
||||
}
|
||||
}
|
||||
outStream <<
|
||||
" float fadeRange = shadowFar_fadeStart.x - shadowFar_fadeStart.y; \n"
|
||||
" float fade = 1-((iDepth - shadowFar_fadeStart.y) / fadeRange); \n"
|
||||
" shadow = (iDepth > shadowFar_fadeStart.x) ? 1 : ((iDepth > shadowFar_fadeStart.y) ? 1-((1-shadow)*fade) : shadow); \n"
|
||||
" lightColour.xyz += shadow * lit(dot(normalize(lightDir), normalize(normal)), 0, 0).y * lightDiffuse"<<i<<".xyz;\n";
|
||||
}
|
||||
else outStream <<
|
||||
" lightColour.xyz += lit(dot(normalize(lightDir), normalize(normal)), 0, 0).y * lightDiffuse"<<i<<".xyz;\n";
|
||||
}
|
||||
|
||||
outStream <<
|
||||
" float3 lightingFinal = lightColour.xyz * diffuse.xyz * vertexColour.xyz + ambient.xyz * lightAmbient.xyz + emissive.xyz; \n"
|
||||
" float fogValue = saturate((iDepth - fogParams.y) * fogParams.w); \n"
|
||||
" oColor.xyz = lerp(lightingFinal * tex.xyz, fogColour, fogValue); \n"
|
||||
" oColor.a = tex.a * diffuse.a * vertexColour.a; \n";
|
||||
|
||||
if (mrt) outStream <<
|
||||
" oColor1 = float4(iDepth / far, 0, 0, (oColor.a == 1)); \n"; // only write to MRT if alpha is 1
|
||||
|
||||
outStream <<
|
||||
"}";
|
||||
fragment->setSource(outStream.str());
|
||||
fragment->load();
|
||||
|
||||
for (int i=0; i<num_lights; ++i)
|
||||
{
|
||||
fragment->getDefaultParameters()->setNamedAutoConstant("lightPositionObjSpace"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_POSITION_OBJECT_SPACE, i);
|
||||
fragment->getDefaultParameters()->setNamedAutoConstant("lightDiffuse"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_DIFFUSE_COLOUR, i);
|
||||
fragment->getDefaultParameters()->setNamedAutoConstant("lightAttenuation"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_ATTENUATION, i);
|
||||
}
|
||||
fragment->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR);
|
||||
fragment->getDefaultParameters()->setNamedAutoConstant("diffuse", GpuProgramParameters::ACT_SURFACE_DIFFUSE_COLOUR);
|
||||
fragment->getDefaultParameters()->setNamedAutoConstant("ambient", GpuProgramParameters::ACT_SURFACE_AMBIENT_COLOUR);
|
||||
fragment->getDefaultParameters()->setNamedAutoConstant("lightAmbient", GpuProgramParameters::ACT_AMBIENT_LIGHT_COLOUR);
|
||||
fragment->getDefaultParameters()->setNamedAutoConstant("fogColour", GpuProgramParameters::ACT_FOG_COLOUR);
|
||||
fragment->getDefaultParameters()->setNamedAutoConstant("fogParams", GpuProgramParameters::ACT_FOG_PARAMS);
|
||||
|
||||
if (shadows)
|
||||
{
|
||||
fragment->getDefaultParameters()->setNamedConstant("shadowFar_fadeStart", Vector4(mRendering->getShadows()->getShadowFar(), mRendering->getShadows()->getFadeStart()*mRendering->getShadows()->getShadowFar(), 0, 0));
|
||||
for (int i=0; i < (split ? numsplits : 1); ++i)
|
||||
{
|
||||
fragment->getDefaultParameters()->setNamedAutoConstant("invShadowmapSize" + StringConverter::toString(i), GpuProgramParameters::ACT_INVERSE_TEXTURE_SIZE, i+1);
|
||||
}
|
||||
if (split)
|
||||
{
|
||||
Vector4 splitPoints;
|
||||
const PSSMShadowCameraSetup::SplitPointList& splitPointList = mRendering->getShadows()->getPSSMSetup()->getSplitPoints();
|
||||
// Populate from split point 1, not 0, since split 0 isn't useful (usually 0)
|
||||
for (int i = 1; i < numsplits; ++i)
|
||||
{
|
||||
splitPoints[i-1] = splitPointList[i];
|
||||
}
|
||||
fragment->getDefaultParameters()->setNamedConstant("pssmSplitPoints", splitPoints);
|
||||
}
|
||||
}
|
||||
|
||||
if (mrt)
|
||||
fragment->getDefaultParameters()->setNamedAutoConstant("far", GpuProgramParameters::ACT_FAR_CLIP_DISTANCE);
|
||||
}
|
||||
}
|
29
apps/openmw/mwrender/shaderhelper.hpp
Normal file
29
apps/openmw/mwrender/shaderhelper.hpp
Normal file
|
@ -0,0 +1,29 @@
|
|||
#ifndef GAME_SHADERHELPER_H
|
||||
#define GAME_SHADERHELPER_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace MWRender
|
||||
{
|
||||
class RenderingManager;
|
||||
|
||||
///
|
||||
/// \brief manages the main shader
|
||||
///
|
||||
class ShaderHelper
|
||||
{
|
||||
public:
|
||||
ShaderHelper(RenderingManager* rend);
|
||||
|
||||
void applyShaders();
|
||||
///< apply new settings
|
||||
|
||||
private:
|
||||
RenderingManager* mRendering;
|
||||
|
||||
void createShader(const bool mrt, const bool shadows, const bool split, const std::string& name);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
175
apps/openmw/mwrender/shadows.cpp
Normal file
175
apps/openmw/mwrender/shadows.cpp
Normal file
|
@ -0,0 +1,175 @@
|
|||
#include "shadows.hpp"
|
||||
|
||||
#include <components/settings/settings.hpp>
|
||||
#include <openengine/ogre/renderer.hpp>
|
||||
|
||||
#include <OgreSceneManager.h>
|
||||
#include <OgreColourValue.h>
|
||||
#include <OgreShadowCameraSetupLiSPSM.h>
|
||||
#include <OgreShadowCameraSetupPSSM.h>
|
||||
#include <OgreHardwarePixelBuffer.h>
|
||||
|
||||
#include <OgreOverlayContainer.h>
|
||||
#include <OgreOverlayManager.h>
|
||||
|
||||
#include "renderconst.hpp"
|
||||
|
||||
using namespace Ogre;
|
||||
using namespace MWRender;
|
||||
|
||||
Shadows::Shadows(OEngine::Render::OgreRenderer* rend) :
|
||||
mShadowFar(1000), mFadeStart(0.9)
|
||||
{
|
||||
mRendering = rend;
|
||||
mSceneMgr = mRendering->getScene();
|
||||
recreate();
|
||||
}
|
||||
|
||||
void Shadows::recreate()
|
||||
{
|
||||
bool enabled = Settings::Manager::getBool("enabled", "Shadows");
|
||||
|
||||
// Split shadow maps are currently disabled because the terrain cannot cope with them
|
||||
// (Too many texture units) Solution would be a multi-pass terrain material
|
||||
bool split = Settings::Manager::getBool("split", "Shadows");
|
||||
//const bool split = false;
|
||||
|
||||
if (!enabled)
|
||||
{
|
||||
mSceneMgr->setShadowTechnique(SHADOWTYPE_NONE);
|
||||
return;
|
||||
}
|
||||
|
||||
int texsize = Settings::Manager::getInt("texture size", "Shadows");
|
||||
mSceneMgr->setShadowTextureSize(texsize);
|
||||
|
||||
mSceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_MODULATIVE_INTEGRATED);
|
||||
|
||||
// no point light shadows, i'm afraid. might revisit this with Deferred Shading
|
||||
mSceneMgr->setShadowTextureCountPerLightType(Light::LT_POINT, 0);
|
||||
|
||||
mSceneMgr->setShadowTextureCountPerLightType(Light::LT_DIRECTIONAL, split ? 3 : 1);
|
||||
mSceneMgr->setShadowTextureCount(split ? 3 : 1);
|
||||
|
||||
mSceneMgr->setShadowTextureSelfShadow(true);
|
||||
mSceneMgr->setShadowCasterRenderBackFaces(true);
|
||||
mSceneMgr->setShadowTextureCasterMaterial("depth_shadow_caster");
|
||||
mSceneMgr->setShadowTexturePixelFormat(PF_FLOAT32_R);
|
||||
mSceneMgr->setShadowDirLightTextureOffset(0.9);
|
||||
mSceneMgr->setShadowDirectionalLightExtrusionDistance(1000000);
|
||||
mSceneMgr->setShowDebugShadows(true);
|
||||
|
||||
mShadowFar = split ? Settings::Manager::getInt("split shadow distance", "Shadows") : Settings::Manager::getInt("shadow distance", "Shadows");
|
||||
mSceneMgr->setShadowFarDistance(mShadowFar);
|
||||
|
||||
mFadeStart = Settings::Manager::getFloat("fade start", "Shadows");
|
||||
|
||||
ShadowCameraSetupPtr shadowCameraSetup;
|
||||
if (split)
|
||||
{
|
||||
mPSSMSetup = new PSSMShadowCameraSetup();
|
||||
mPSSMSetup->setSplitPadding(5);
|
||||
mPSSMSetup->calculateSplitPoints(3, mRendering->getCamera()->getNearClipDistance(), mShadowFar);
|
||||
|
||||
const Real adjustFactors[3] = {64, 64, 64};
|
||||
for (int i=0; i < 3; ++i)
|
||||
{
|
||||
mPSSMSetup->setOptimalAdjustFactor(i, adjustFactors[i]);
|
||||
/*if (i==0)
|
||||
mSceneMgr->setShadowTextureConfig(i, texsize, texsize, Ogre::PF_FLOAT32_R);
|
||||
else if (i ==1)
|
||||
mSceneMgr->setShadowTextureConfig(i, texsize/2, texsize/2, Ogre::PF_FLOAT32_R);
|
||||
else if (i ==2)
|
||||
mSceneMgr->setShadowTextureConfig(i, texsize/4, texsize/4, Ogre::PF_FLOAT32_R);*/
|
||||
}
|
||||
|
||||
shadowCameraSetup = ShadowCameraSetupPtr(mPSSMSetup);
|
||||
}
|
||||
else
|
||||
{
|
||||
LiSPSMShadowCameraSetup* lispsmSetup = new LiSPSMShadowCameraSetup();
|
||||
lispsmSetup->setOptimalAdjustFactor(2);
|
||||
//lispsmSetup->setCameraLightDirectionThreshold(Degree(0));
|
||||
//lispsmSetup->setUseAggressiveFocusRegion(false);
|
||||
shadowCameraSetup = ShadowCameraSetupPtr(lispsmSetup);
|
||||
}
|
||||
mSceneMgr->setShadowCameraSetup(shadowCameraSetup);
|
||||
|
||||
// Set visibility mask for the shadow render textures
|
||||
int visibilityMask = RV_Actors * Settings::Manager::getBool("actor shadows", "Shadows")
|
||||
+ (RV_Statics + RV_StaticsSmall) * Settings::Manager::getBool("statics shadows", "Shadows")
|
||||
+ RV_Misc * Settings::Manager::getBool("misc shadows", "Shadows");
|
||||
|
||||
for (int i = 0; i < (split ? 3 : 1); ++i)
|
||||
{
|
||||
TexturePtr shadowTexture = mSceneMgr->getShadowTexture(i);
|
||||
Viewport* vp = shadowTexture->getBuffer()->getRenderTarget()->getViewport(0);
|
||||
vp->setVisibilityMask(visibilityMask);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// --------------------------- Debug overlays to display the content of shadow maps -----------------------------------
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
/*
|
||||
OverlayManager& mgr = OverlayManager::getSingleton();
|
||||
Overlay* overlay;
|
||||
|
||||
// destroy if already exists
|
||||
if (overlay = mgr.getByName("DebugOverlay"))
|
||||
mgr.destroy(overlay);
|
||||
|
||||
overlay = mgr.create("DebugOverlay");
|
||||
for (size_t i = 0; i < (split ? 3 : 1); ++i) {
|
||||
TexturePtr tex = mRendering->getScene()->getShadowTexture(i);
|
||||
|
||||
// Set up a debug panel to display the shadow
|
||||
|
||||
if (MaterialManager::getSingleton().resourceExists("Ogre/DebugTexture" + StringConverter::toString(i)))
|
||||
MaterialManager::getSingleton().remove("Ogre/DebugTexture" + StringConverter::toString(i));
|
||||
MaterialPtr debugMat = MaterialManager::getSingleton().create(
|
||||
"Ogre/DebugTexture" + StringConverter::toString(i),
|
||||
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
|
||||
|
||||
debugMat->getTechnique(0)->getPass(0)->setLightingEnabled(false);
|
||||
TextureUnitState *t = debugMat->getTechnique(0)->getPass(0)->createTextureUnitState(tex->getName());
|
||||
t->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
|
||||
|
||||
OverlayContainer* debugPanel;
|
||||
|
||||
// destroy container if exists
|
||||
try
|
||||
{
|
||||
if (debugPanel =
|
||||
static_cast<OverlayContainer*>(
|
||||
mgr.getOverlayElement("Ogre/DebugTexPanel" + StringConverter::toString(i)
|
||||
)))
|
||||
mgr.destroyOverlayElement(debugPanel);
|
||||
}
|
||||
catch (Ogre::Exception&) {}
|
||||
|
||||
debugPanel = (OverlayContainer*)
|
||||
(OverlayManager::getSingleton().createOverlayElement("Panel", "Ogre/DebugTexPanel" + StringConverter::toString(i)));
|
||||
debugPanel->_setPosition(0.8, i*0.25);
|
||||
debugPanel->_setDimensions(0.2, 0.24);
|
||||
debugPanel->setMaterialName(debugMat->getName());
|
||||
debugPanel->show();
|
||||
overlay->add2D(debugPanel);
|
||||
overlay->show();
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
PSSMShadowCameraSetup* Shadows::getPSSMSetup()
|
||||
{
|
||||
return mPSSMSetup;
|
||||
}
|
||||
|
||||
float Shadows::getShadowFar() const
|
||||
{
|
||||
return mShadowFar;
|
||||
}
|
||||
|
||||
float Shadows::getFadeStart() const
|
||||
{
|
||||
return mFadeStart;
|
||||
}
|
39
apps/openmw/mwrender/shadows.hpp
Normal file
39
apps/openmw/mwrender/shadows.hpp
Normal file
|
@ -0,0 +1,39 @@
|
|||
#ifndef GAME_SHADOWS_H
|
||||
#define GAME_SHADOWS_H
|
||||
|
||||
// forward declares
|
||||
namespace Ogre
|
||||
{
|
||||
class SceneManager;
|
||||
class PSSMShadowCameraSetup;
|
||||
}
|
||||
namespace OEngine{
|
||||
namespace Render{
|
||||
class OgreRenderer;
|
||||
}
|
||||
}
|
||||
|
||||
namespace MWRender
|
||||
{
|
||||
class Shadows
|
||||
{
|
||||
public:
|
||||
Shadows(OEngine::Render::OgreRenderer* rend);
|
||||
|
||||
void recreate();
|
||||
|
||||
Ogre::PSSMShadowCameraSetup* getPSSMSetup();
|
||||
float getShadowFar() const;
|
||||
float getFadeStart() const;
|
||||
|
||||
protected:
|
||||
OEngine::Render::OgreRenderer* mRendering;
|
||||
Ogre::SceneManager* mSceneMgr;
|
||||
|
||||
Ogre::PSSMShadowCameraSetup* mPSSMSetup;
|
||||
float mShadowFar;
|
||||
float mFadeStart;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -102,6 +102,7 @@ void BillboardObject::init(const String& textureName,
|
|||
mNode->setPosition(finalPosition);
|
||||
mNode->attachObject(mBBSet);
|
||||
mBBSet->createBillboard(0,0,0);
|
||||
mBBSet->setCastShadows(false);
|
||||
|
||||
mMaterial = MaterialManager::getSingleton().create("BillboardMaterial"+StringConverter::toString(bodyCount), ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
|
||||
mMaterial->removeAllTechniques();
|
||||
|
@ -450,6 +451,7 @@ void SkyManager::create()
|
|||
Entity* night1_ent = mSceneMgr->createEntity("meshes\\sky_night_01.nif");
|
||||
night1_ent->setRenderQueueGroup(RQG_SkiesEarly+1);
|
||||
night1_ent->setVisibilityFlags(RV_Sky);
|
||||
night1_ent->setCastShadows(false);
|
||||
|
||||
mAtmosphereNight = mRootNode->createChildSceneNode();
|
||||
mAtmosphereNight->attachObject(night1_ent);
|
||||
|
@ -525,6 +527,7 @@ void SkyManager::create()
|
|||
// Atmosphere (day)
|
||||
mesh = NifOgre::NIFLoader::load("meshes\\sky_atmosphere.nif");
|
||||
Entity* atmosphere_ent = mSceneMgr->createEntity("meshes\\sky_atmosphere.nif");
|
||||
atmosphere_ent->setCastShadows(false);
|
||||
|
||||
ModVertexAlpha(atmosphere_ent, 0);
|
||||
|
||||
|
@ -596,6 +599,7 @@ void SkyManager::create()
|
|||
SceneNode* clouds_node = mRootNode->createChildSceneNode();
|
||||
clouds_node->attachObject(clouds_ent);
|
||||
mCloudMaterial = clouds_ent->getSubEntity(0)->getMaterial();
|
||||
clouds_ent->setCastShadows(false);
|
||||
|
||||
// Clouds vertex shader
|
||||
HighLevelGpuProgramPtr vshader2 = mgr.createProgram("Clouds_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||
|
@ -677,6 +681,8 @@ void SkyManager::create()
|
|||
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA);
|
||||
mCloudMaterial->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA);
|
||||
|
||||
mCloudMaterial->getTechnique(0)->getPass(0)->removeAllTextureUnitStates();
|
||||
mCloudMaterial->getTechnique(0)->getPass(0)->createTextureUnitState("textures\\tx_sky_cloudy.dds");
|
||||
mCloudMaterial->getTechnique(0)->getPass(0)->createTextureUnitState("");
|
||||
|
||||
mCreated = true;
|
||||
|
@ -766,12 +772,14 @@ void SkyManager::disable()
|
|||
|
||||
void SkyManager::setMoonColour (bool red)
|
||||
{
|
||||
if (!mCreated) return;
|
||||
mSecunda->setColour( red ? ColourValue(1.0, 0.0784, 0.0784)
|
||||
: ColourValue(1.0, 1.0, 1.0));
|
||||
}
|
||||
|
||||
void SkyManager::setCloudsOpacity(float opacity)
|
||||
{
|
||||
if (!mCreated) return;
|
||||
mCloudMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("opacity", Real(opacity));
|
||||
}
|
||||
|
||||
|
@ -927,11 +935,13 @@ void SkyManager::setThunder(const float factor)
|
|||
|
||||
void SkyManager::setMasserFade(const float fade)
|
||||
{
|
||||
if (!mCreated) return;
|
||||
mMasser->setVisibility(fade);
|
||||
}
|
||||
|
||||
void SkyManager::setSecundaFade(const float fade)
|
||||
{
|
||||
if (!mCreated) return;
|
||||
mSecunda->setVisibility(fade);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
#include "terrainmaterial.hpp"
|
||||
#include "terrain.hpp"
|
||||
#include "renderconst.hpp"
|
||||
|
||||
#include "shadows.hpp"
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
using namespace Ogre;
|
||||
|
||||
|
@ -16,8 +17,8 @@ namespace MWRender
|
|||
|
||||
//----------------------------------------------------------------------------------------------
|
||||
|
||||
TerrainManager::TerrainManager(Ogre::SceneManager* mgr, const MWWorld::Environment& evn) :
|
||||
mEnvironment(evn), mTerrainGroup(TerrainGroup(mgr, Terrain::ALIGN_X_Z, mLandSize, mWorldSize))
|
||||
TerrainManager::TerrainManager(Ogre::SceneManager* mgr, RenderingManager* rend, const MWWorld::Environment& evn) :
|
||||
mEnvironment(evn), mTerrainGroup(TerrainGroup(mgr, Terrain::ALIGN_X_Z, mLandSize, mWorldSize)), mRendering(rend)
|
||||
{
|
||||
|
||||
TerrainMaterialGeneratorPtr matGen;
|
||||
|
@ -48,9 +49,19 @@ namespace MWRender
|
|||
mActiveProfile->setLayerSpecularMappingEnabled(false);
|
||||
mActiveProfile->setLayerNormalMappingEnabled(false);
|
||||
mActiveProfile->setLayerParallaxMappingEnabled(false);
|
||||
mActiveProfile->setReceiveDynamicShadowsEnabled(false);
|
||||
|
||||
//composite maps lead to a drastic reduction in loading time so are
|
||||
bool shadows = Settings::Manager::getBool("enabled", "Shadows");
|
||||
mActiveProfile->setReceiveDynamicShadowsEnabled(shadows);
|
||||
mActiveProfile->setReceiveDynamicShadowsDepth(shadows);
|
||||
if (Settings::Manager::getBool("split", "Shadows"))
|
||||
mActiveProfile->setReceiveDynamicShadowsPSSM(mRendering->getShadows()->getPSSMSetup());
|
||||
else
|
||||
mActiveProfile->setReceiveDynamicShadowsPSSM(0);
|
||||
|
||||
mActiveProfile->setShadowFar(mRendering->getShadows()->getShadowFar());
|
||||
mActiveProfile->setShadowFadeStart(mRendering->getShadows()->getFadeStart());
|
||||
|
||||
//composite maps lead to a drastic increase in loading time so are
|
||||
//disabled
|
||||
mActiveProfile->setCompositeMapEnabled(false);
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace MWRender{
|
|||
*/
|
||||
class TerrainManager{
|
||||
public:
|
||||
TerrainManager(Ogre::SceneManager* mgr, const MWWorld::Environment& env);
|
||||
TerrainManager(Ogre::SceneManager* mgr, RenderingManager* rend, const MWWorld::Environment& env);
|
||||
virtual ~TerrainManager();
|
||||
|
||||
void setDiffuse(const Ogre::ColourValue& diffuse);
|
||||
|
@ -37,6 +37,7 @@ namespace MWRender{
|
|||
Ogre::TerrainGroup mTerrainGroup;
|
||||
|
||||
const MWWorld::Environment& mEnvironment;
|
||||
RenderingManager* mRendering;
|
||||
|
||||
Ogre::TerrainMaterialGeneratorB::SM2Profile* mActiveProfile;
|
||||
|
||||
|
|
|
@ -86,6 +86,7 @@ namespace Ogre
|
|||
, mPSSM(0)
|
||||
, mDepthShadows(false)
|
||||
, mLowLodShadows(false)
|
||||
, mShadowFar(1300)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -102,6 +103,24 @@ namespace Ogre
|
|||
terrain->_setLightMapRequired(mLightmapEnabled, true);
|
||||
terrain->_setCompositeMapRequired(mCompositeMapEnabled);
|
||||
}
|
||||
//---------------------------------------------------------------------
|
||||
void TerrainMaterialGeneratorB::SM2Profile::setShadowFar(float far)
|
||||
{
|
||||
if (mShadowFar != far)
|
||||
{
|
||||
mShadowFar = far;
|
||||
mParent->_markChanged();
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------
|
||||
void TerrainMaterialGeneratorB::SM2Profile::setShadowFadeStart(float fadestart)
|
||||
{
|
||||
if (mShadowFadeStart != fadestart)
|
||||
{
|
||||
mShadowFadeStart = fadestart;
|
||||
mParent->_markChanged();
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------
|
||||
void TerrainMaterialGeneratorB::SM2Profile::setLayerNormalMappingEnabled(bool enabled)
|
||||
{
|
||||
|
@ -462,6 +481,7 @@ namespace Ogre
|
|||
|
||||
StringUtil::StrStreamType sourceStr;
|
||||
generateFragmentProgramSource(prof, terrain, tt, sourceStr);
|
||||
|
||||
ret->setSource(sourceStr.str());
|
||||
ret->load();
|
||||
defaultFpParams(prof, terrain, tt, ret);
|
||||
|
@ -533,8 +553,8 @@ namespace Ogre
|
|||
GpuProgramParameters::ACT_TEXTURE_VIEWPROJ_MATRIX, i);
|
||||
if (prof->getReceiveDynamicShadowsDepth())
|
||||
{
|
||||
params->setNamedAutoConstant("depthRange" + StringConverter::toString(i),
|
||||
GpuProgramParameters::ACT_SHADOW_SCENE_DEPTH_RANGE, i);
|
||||
//params->setNamedAutoConstant("depthRange" + StringConverter::toString(i),
|
||||
//GpuProgramParameters::ACT_SHADOW_SCENE_DEPTH_RANGE, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -567,6 +587,7 @@ namespace Ogre
|
|||
|
||||
if (prof->isShadowingEnabled(tt, terrain))
|
||||
{
|
||||
params->setNamedConstant("shadowFar_fadeStart", Vector4(prof->mShadowFar, prof->mShadowFadeStart * prof->mShadowFar, 0, 0));
|
||||
uint numTextures = 1;
|
||||
if (prof->getReceiveDynamicShadowsPSSM())
|
||||
{
|
||||
|
@ -732,7 +753,7 @@ namespace Ogre
|
|||
ret->unload();
|
||||
}
|
||||
|
||||
ret->setParameter("profiles", "vs_3_0 vs_2_0 arbvp1");
|
||||
ret->setParameter("profiles", "vs_3_0 vs_2_0 vp40 arbvp1");
|
||||
ret->setParameter("entry_point", "main_vp");
|
||||
|
||||
return ret;
|
||||
|
@ -790,9 +811,9 @@ namespace Ogre
|
|||
|
||||
outStream <<
|
||||
"out float4 oPos : POSITION,\n"
|
||||
"out float4 oPosObj : TEXCOORD0 \n";
|
||||
"out float4 oPosObj : COLOR \n";
|
||||
|
||||
uint texCoordSet = 1;
|
||||
uint texCoordSet = 0;
|
||||
outStream <<
|
||||
", out float4 oUVMisc : TEXCOORD" << texCoordSet++ <<" // xy = uv, z = camDepth\n";
|
||||
|
||||
|
@ -818,8 +839,8 @@ namespace Ogre
|
|||
if (fog)
|
||||
{
|
||||
outStream <<
|
||||
", uniform float4 fogParams\n"
|
||||
", out float fogVal : COLOR\n";
|
||||
", uniform float4 fogParams\n";
|
||||
//", out float fogVal : COLOR\n";
|
||||
}
|
||||
|
||||
if (prof->isShadowingEnabled(tt, terrain))
|
||||
|
@ -831,7 +852,7 @@ namespace Ogre
|
|||
if (texCoordSet > 8)
|
||||
{
|
||||
OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
|
||||
"Requested options require too many texture coordinate sets! Try reducing the number of layers.",
|
||||
"Requested options require too many texture coordinate sets! Try reducing the number of layers. requested: " + StringConverter::toString(texCoordSet),
|
||||
__FUNCTION__);
|
||||
}
|
||||
|
||||
|
@ -917,9 +938,9 @@ namespace Ogre
|
|||
|
||||
outStream <<
|
||||
"void main_fp(\n"
|
||||
"float4 position : TEXCOORD0,\n";
|
||||
"float4 position : COLOR,\n";
|
||||
|
||||
uint texCoordSet = 1;
|
||||
uint texCoordSet = 0;
|
||||
outStream <<
|
||||
"float4 uvMisc : TEXCOORD" << texCoordSet++ << ",\n";
|
||||
|
||||
|
@ -948,8 +969,8 @@ namespace Ogre
|
|||
if (fog)
|
||||
{
|
||||
outStream <<
|
||||
"uniform float3 fogColour, \n"
|
||||
"float fogVal : COLOR,\n";
|
||||
"uniform float3 fogColour, \n";
|
||||
//"float fogVal : COLOR,\n";
|
||||
}
|
||||
|
||||
uint currentSamplerIdx = 0;
|
||||
|
@ -1046,6 +1067,7 @@ namespace Ogre
|
|||
" float4 outputCol;\n"
|
||||
" float shadow = 1.0;\n"
|
||||
" float2 uv = uvMisc.xy;\n"
|
||||
" float fogVal = position.w; \n"
|
||||
// base colour
|
||||
" outputCol = float4(0,0,0,1);\n";
|
||||
|
||||
|
@ -1257,13 +1279,15 @@ namespace Ogre
|
|||
if (terrain->getSceneManager()->getFogMode() == FOG_LINEAR)
|
||||
{
|
||||
outStream <<
|
||||
" fogVal = saturate((oPos.z - fogParams.y) * fogParams.w);\n";
|
||||
" float fogVal = saturate((oPos.z - fogParams.y) * fogParams.w);\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
outStream <<
|
||||
" fogVal = saturate(1 / (exp(oPos.z * fogParams.x)));\n";
|
||||
" float fogVal = saturate(1 / (exp(oPos.z * fogParams.x)));\n";
|
||||
}
|
||||
outStream <<
|
||||
" oPosObj.w = fogVal; \n";
|
||||
}
|
||||
|
||||
if (prof->isShadowingEnabled(tt, terrain))
|
||||
|
@ -1364,7 +1388,7 @@ namespace Ogre
|
|||
outStream <<
|
||||
"// Simple PCF \n"
|
||||
"// Number of samples in one dimension (square for total samples) \n"
|
||||
"#define NUM_SHADOW_SAMPLES_1D 2.0 \n"
|
||||
"#define NUM_SHADOW_SAMPLES_1D 1.0 \n"
|
||||
"#define SHADOW_FILTER_SCALE 1 \n"
|
||||
|
||||
"#define SHADOW_SAMPLES NUM_SHADOW_SAMPLES_1D*NUM_SHADOW_SAMPLES_1D \n"
|
||||
|
@ -1377,28 +1401,18 @@ namespace Ogre
|
|||
if (prof->getReceiveDynamicShadowsDepth())
|
||||
{
|
||||
outStream <<
|
||||
"float calcDepthShadow(sampler2D shadowMap, float4 uv, float invShadowMapSize) \n"
|
||||
"{ \n"
|
||||
" // 4-sample PCF \n"
|
||||
|
||||
" float shadow = 0.0; \n"
|
||||
" float offset = (NUM_SHADOW_SAMPLES_1D/2 - 0.5) * SHADOW_FILTER_SCALE; \n"
|
||||
" for (float y = -offset; y <= offset; y += SHADOW_FILTER_SCALE) \n"
|
||||
" for (float x = -offset; x <= offset; x += SHADOW_FILTER_SCALE) \n"
|
||||
" { \n"
|
||||
" float4 newUV = offsetSample(uv, float2(x, y), invShadowMapSize);\n"
|
||||
" // manually project and assign derivatives \n"
|
||||
" // to avoid gradient issues inside loops \n"
|
||||
" newUV = newUV / newUV.w; \n"
|
||||
" float depth = tex2D(shadowMap, newUV.xy, 1, 1).x; \n"
|
||||
" if (depth >= 1 || depth >= uv.z)\n"
|
||||
" shadow += 1.0;\n"
|
||||
" } \n"
|
||||
|
||||
" shadow /= SHADOW_SAMPLES; \n"
|
||||
|
||||
" return shadow; \n"
|
||||
"} \n";
|
||||
"float calcDepthShadow(sampler2D shadowMap, float4 shadowMapPos, float2 offset) \n"
|
||||
" { \n"
|
||||
" shadowMapPos = shadowMapPos / shadowMapPos.w; \n"
|
||||
" float2 uv = shadowMapPos.xy; \n"
|
||||
" float3 o = float3(offset, -offset.x) * 0.3f; \n"
|
||||
" // Note: We using 2x2 PCF. Good enough and is alot faster. \n"
|
||||
" float c = (shadowMapPos.z <= tex2D(shadowMap, uv.xy - o.xy).r) ? 1 : 0; // top left \n"
|
||||
" c += (shadowMapPos.z <= tex2D(shadowMap, uv.xy + o.xy).r) ? 1 : 0; // bottom right \n"
|
||||
" c += (shadowMapPos.z <= tex2D(shadowMap, uv.xy + o.zy).r) ? 1 : 0; // bottom left \n"
|
||||
" c += (shadowMapPos.z <= tex2D(shadowMap, uv.xy - o.zy).r) ? 1 : 0; // top right \n"
|
||||
" return c / 4; \n"
|
||||
" } \n";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1436,7 +1450,7 @@ namespace Ogre
|
|||
{
|
||||
outStream << "\n ";
|
||||
for (uint i = 0; i < numTextures; ++i)
|
||||
outStream << "float invShadowmapSize" << i << ", ";
|
||||
outStream << "float2 invShadowmapSize" << i << ", ";
|
||||
}
|
||||
outStream << "\n"
|
||||
" float4 pssmSplitPoints, float camDepth) \n"
|
||||
|
@ -1458,7 +1472,7 @@ namespace Ogre
|
|||
if (prof->getReceiveDynamicShadowsDepth())
|
||||
{
|
||||
outStream <<
|
||||
" shadow = calcDepthShadow(shadowMap" << i << ", lsPos" << i << ", invShadowmapSize" << i << "); \n";
|
||||
" shadow = calcDepthShadow(shadowMap" << i << ", lsPos" << i << ", invShadowmapSize" << i << ".xy); \n";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1520,8 +1534,8 @@ namespace Ogre
|
|||
if (prof->getReceiveDynamicShadowsDepth())
|
||||
{
|
||||
// make linear
|
||||
outStream <<
|
||||
"oLightSpacePos" << i << ".z = (oLightSpacePos" << i << ".z - depthRange" << i << ".x) * depthRange" << i << ".w;\n";
|
||||
//outStream <<
|
||||
// "oLightSpacePos" << i << ".z = (oLightSpacePos" << i << ".z - depthRange" << i << ".x) * depthRange" << i << ".w;\n";
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1538,6 +1552,8 @@ namespace Ogre
|
|||
|
||||
// in semantics & params
|
||||
uint numTextures = 1;
|
||||
outStream <<
|
||||
", uniform float4 shadowFar_fadeStart \n";
|
||||
if (prof->getReceiveDynamicShadowsPSSM())
|
||||
{
|
||||
numTextures = prof->getReceiveDynamicShadowsPSSM()->getSplitCount();
|
||||
|
@ -1554,7 +1570,7 @@ namespace Ogre
|
|||
if (prof->getReceiveDynamicShadowsDepth())
|
||||
{
|
||||
outStream <<
|
||||
", uniform float inverseShadowmapSize" << i << " \n";
|
||||
", uniform float4 inverseShadowmapSize" << i << " \n";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1589,7 +1605,7 @@ namespace Ogre
|
|||
{
|
||||
outStream << "\n ";
|
||||
for (uint i = 0; i < numTextures; ++i)
|
||||
outStream << "inverseShadowmapSize" << i << ", ";
|
||||
outStream << "inverseShadowmapSize" << i << ".xy, ";
|
||||
}
|
||||
outStream << "\n" <<
|
||||
" pssmSplitPoints, camDepth);\n";
|
||||
|
@ -1600,7 +1616,7 @@ namespace Ogre
|
|||
if (prof->getReceiveDynamicShadowsDepth())
|
||||
{
|
||||
outStream <<
|
||||
" float rtshadow = calcDepthShadow(shadowMap0, lightSpacePos0, inverseShadowmapSize0);";
|
||||
" float rtshadow = calcDepthShadow(shadowMap0, lightSpacePos0, inverseShadowmapSize0.xy);";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1609,7 +1625,11 @@ namespace Ogre
|
|||
}
|
||||
}
|
||||
|
||||
outStream <<
|
||||
outStream <<
|
||||
" float fadeRange = shadowFar_fadeStart.x - shadowFar_fadeStart.y; \n"
|
||||
" float fade = 1-((uvMisc.z - shadowFar_fadeStart.y) / fadeRange); \n"
|
||||
" rtshadow = (uvMisc.z > shadowFar_fadeStart.x) ? 1 : ((uvMisc.z > shadowFar_fadeStart.y) ? 1-((1-rtshadow)*fade) : rtshadow); \n"
|
||||
" rtshadow = (1-(1-rtshadow)*0.6); \n" // make the shadow a little less intensive
|
||||
" shadow = min(shadow, rtshadow);\n";
|
||||
|
||||
}
|
||||
|
|
|
@ -73,6 +73,9 @@ namespace Ogre
|
|||
void updateParamsForCompositeMap(const MaterialPtr& mat, const Terrain* terrain);
|
||||
void requestOptions(Terrain* terrain);
|
||||
|
||||
void setShadowFar(float far);
|
||||
void setShadowFadeStart(float fadestart);
|
||||
|
||||
/** Whether to support normal mapping per layer in the shader (default true).
|
||||
*/
|
||||
bool isLayerNormalMappingEnabled() const { return mLayerNormalMappingEnabled; }
|
||||
|
@ -245,6 +248,8 @@ namespace Ogre
|
|||
bool mDepthShadows;
|
||||
bool mLowLodShadows;
|
||||
bool mSM3Available;
|
||||
float mShadowFar;
|
||||
float mShadowFadeStart;
|
||||
|
||||
bool isShadowingEnabled(TechniqueType tt, const Terrain* terrain) const;
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ namespace MWRender
|
|||
Water::Water (Ogre::Camera *camera, SkyManager* sky, const ESM::Cell* cell) :
|
||||
mCamera (camera), mViewport (camera->getViewport()), mSceneManager (camera->getSceneManager()),
|
||||
mIsUnderwater(false), mVisibilityFlags(0),
|
||||
mReflectionTarget(0), mActive(1)
|
||||
mReflectionTarget(0), mActive(1), mToggled(1)
|
||||
{
|
||||
mSky = sky;
|
||||
|
||||
|
@ -31,6 +31,7 @@ Water::Water (Ogre::Camera *camera, SkyManager* sky, const ESM::Cell* cell) :
|
|||
mWater = mSceneManager->createEntity("water");
|
||||
mWater->setVisibilityFlags(RV_Water);
|
||||
mWater->setRenderQueueGroup(RQG_Water);
|
||||
mWater->setCastShadows(false);
|
||||
|
||||
mVisibilityFlags = RV_Terrain * Settings::Manager::getBool("reflect terrain", "Water")
|
||||
+ RV_Statics * Settings::Manager::getBool("reflect statics", "Water")
|
||||
|
@ -42,6 +43,8 @@ Water::Water (Ogre::Camera *camera, SkyManager* sky, const ESM::Cell* cell) :
|
|||
mWaterNode = mSceneManager->getRootSceneNode()->createChildSceneNode();
|
||||
mWaterNode->setPosition(0, mTop, 0);
|
||||
|
||||
mReflectionCamera = mSceneManager->createCamera("ReflectionCamera");
|
||||
|
||||
if(!(cell->data.flags & cell->Interior))
|
||||
{
|
||||
mWaterNode->setPosition(getSceneNodeCoordinates(cell->data.gridX, cell->data.gridY));
|
||||
|
@ -51,17 +54,20 @@ Water::Water (Ogre::Camera *camera, SkyManager* sky, const ESM::Cell* cell) :
|
|||
// Create rendertarget for reflection
|
||||
int rttsize = Settings::Manager::getInt("rtt size", "Water");
|
||||
|
||||
TexturePtr tex;
|
||||
if (Settings::Manager::getBool("shader", "Water"))
|
||||
{
|
||||
TexturePtr tex = TextureManager::getSingleton().createManual("WaterReflection",
|
||||
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D, rttsize, rttsize, 0, PF_R8G8B8, TU_RENDERTARGET);
|
||||
tex = TextureManager::getSingleton().createManual("WaterReflection",
|
||||
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D, rttsize, rttsize, 0, PF_FLOAT16_RGBA, TU_RENDERTARGET);
|
||||
|
||||
RenderTarget* rtt = tex->getBuffer()->getRenderTarget();
|
||||
Viewport* vp = rtt->addViewport(mCamera);
|
||||
Viewport* vp = rtt->addViewport(mReflectionCamera);
|
||||
vp->setOverlaysEnabled(false);
|
||||
vp->setBackgroundColour(ColourValue(0.8f, 0.9f, 1.0f));
|
||||
vp->setShadowsEnabled(false);
|
||||
vp->setVisibilityMask( mVisibilityFlags );
|
||||
// use fallback techniques without shadows and without mrt (currently not implemented for sky and terrain)
|
||||
//vp->setMaterialScheme("Fallback");
|
||||
rtt->addListener(this);
|
||||
rtt->setActive(true);
|
||||
|
||||
|
@ -74,13 +80,61 @@ Water::Water (Ogre::Camera *camera, SkyManager* sky, const ESM::Cell* cell) :
|
|||
mWater->setMaterial(mMaterial);
|
||||
|
||||
mUnderwaterEffect = Settings::Manager::getBool("underwater effect", "Water");
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
// ---------------------------------- reflection debug overlay ----------------------------------
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
/*
|
||||
if (Settings::Manager::getBool("shader", "Water"))
|
||||
{
|
||||
OverlayManager& mgr = OverlayManager::getSingleton();
|
||||
Overlay* overlay;
|
||||
// destroy if already exists
|
||||
if (overlay = mgr.getByName("ReflectionDebugOverlay"))
|
||||
mgr.destroy(overlay);
|
||||
|
||||
overlay = mgr.create("ReflectionDebugOverlay");
|
||||
|
||||
if (MaterialManager::getSingleton().resourceExists("Ogre/ReflectionDebugTexture"))
|
||||
MaterialManager::getSingleton().remove("Ogre/ReflectionDebugTexture");
|
||||
MaterialPtr debugMat = MaterialManager::getSingleton().create(
|
||||
"Ogre/ReflectionDebugTexture",
|
||||
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
|
||||
|
||||
debugMat->getTechnique(0)->getPass(0)->setLightingEnabled(false);
|
||||
TextureUnitState *t = debugMat->getTechnique(0)->getPass(0)->createTextureUnitState(tex->getName());
|
||||
t->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
|
||||
|
||||
OverlayContainer* debugPanel;
|
||||
|
||||
// destroy container if exists
|
||||
try
|
||||
{
|
||||
if (debugPanel =
|
||||
static_cast<OverlayContainer*>(
|
||||
mgr.getOverlayElement("Ogre/ReflectionDebugTexPanel"
|
||||
)))
|
||||
mgr.destroyOverlayElement(debugPanel);
|
||||
}
|
||||
catch (Ogre::Exception&) {}
|
||||
|
||||
debugPanel = (OverlayContainer*)
|
||||
(OverlayManager::getSingleton().createOverlayElement("Panel", "Ogre/ReflectionDebugTexPanel"));
|
||||
debugPanel->_setPosition(0, 0.55);
|
||||
debugPanel->_setDimensions(0.3, 0.3);
|
||||
debugPanel->setMaterialName(debugMat->getName());
|
||||
debugPanel->show();
|
||||
overlay->add2D(debugPanel);
|
||||
overlay->show();
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void Water::setActive(bool active)
|
||||
{
|
||||
mActive = active;
|
||||
if (mReflectionTarget) mReflectionTarget->setActive(active && !mIsUnderwater);
|
||||
mWater->setVisible(active);
|
||||
updateVisible();
|
||||
}
|
||||
|
||||
Water::~Water()
|
||||
|
@ -112,8 +166,8 @@ void Water::setHeight(const float height)
|
|||
|
||||
void Water::toggle()
|
||||
{
|
||||
if (mActive)
|
||||
mWater->setVisible(!mWater->getVisible());
|
||||
mToggled = !mToggled;
|
||||
updateVisible();
|
||||
}
|
||||
|
||||
void Water::checkUnderwater(float y)
|
||||
|
@ -128,13 +182,10 @@ void Water::checkUnderwater(float y)
|
|||
if (pass->hasFragmentProgram() && pass->getFragmentProgramParameters()->_findNamedConstantDefinition("isUnderwater", false))
|
||||
pass->getFragmentProgramParameters()->setNamedConstant("isUnderwater", Real(0));
|
||||
|
||||
if (mReflectionTarget)
|
||||
mReflectionTarget->setActive(mActive);
|
||||
|
||||
mWater->setRenderQueueGroup(RQG_Water);
|
||||
|
||||
mIsUnderwater = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!mIsUnderwater && y < mTop && mWater->isVisible() && mCamera->getPolygonMode() == Ogre::PM_SOLID)
|
||||
{
|
||||
|
@ -146,13 +197,12 @@ void Water::checkUnderwater(float y)
|
|||
if (pass->hasFragmentProgram() && pass->getFragmentProgramParameters()->_findNamedConstantDefinition("isUnderwater", false))
|
||||
pass->getFragmentProgramParameters()->setNamedConstant("isUnderwater", Real(1));
|
||||
|
||||
if (mReflectionTarget)
|
||||
mReflectionTarget->setActive(false);
|
||||
|
||||
mWater->setRenderQueueGroup(RQG_UnderWater);
|
||||
|
||||
mIsUnderwater = true;
|
||||
}
|
||||
|
||||
updateVisible();
|
||||
}
|
||||
|
||||
Vector3 Water::getSceneNodeCoordinates(int gridX, int gridY)
|
||||
|
@ -164,7 +214,12 @@ void Water::preRenderTargetUpdate(const RenderTargetEvent& evt)
|
|||
{
|
||||
if (evt.source == mReflectionTarget)
|
||||
{
|
||||
mWater->setVisible(false);
|
||||
mReflectionCamera->setOrientation(mCamera->getDerivedOrientation());
|
||||
mReflectionCamera->setPosition(mCamera->getDerivedPosition());
|
||||
mReflectionCamera->setNearClipDistance(mCamera->getNearClipDistance());
|
||||
mReflectionCamera->setFarClipDistance(mCamera->getFarClipDistance());
|
||||
mReflectionCamera->setAspectRatio(mCamera->getAspectRatio());
|
||||
mReflectionCamera->setFOVy(mCamera->getFOVy());
|
||||
|
||||
// Some messy code to get the skybox to show up at all
|
||||
// The problem here is that it gets clipped by the water plane
|
||||
|
@ -174,21 +229,19 @@ void Water::preRenderTargetUpdate(const RenderTargetEvent& evt)
|
|||
mSky->setSkyPosition(pos);
|
||||
mSky->scaleSky(mCamera->getFarClipDistance() / 1000.f);
|
||||
|
||||
mCamera->enableCustomNearClipPlane(Plane(Vector3::UNIT_Y, mTop));
|
||||
mCamera->enableReflection(Plane(Vector3::UNIT_Y, mTop));
|
||||
mReflectionCamera->enableCustomNearClipPlane(Plane(Vector3::UNIT_Y, mTop));
|
||||
mReflectionCamera->enableReflection(Plane(Vector3::UNIT_Y, mTop));
|
||||
}
|
||||
}
|
||||
|
||||
void Water::postRenderTargetUpdate(const RenderTargetEvent& evt)
|
||||
{
|
||||
mWater->setVisible(true);
|
||||
|
||||
if (evt.source == mReflectionTarget)
|
||||
{
|
||||
mSky->resetSkyPosition();
|
||||
mSky->scaleSky(1);
|
||||
mCamera->disableReflection();
|
||||
mCamera->disableCustomNearClipPlane();
|
||||
mReflectionCamera->disableCustomNearClipPlane();
|
||||
mReflectionCamera->disableReflection();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -230,4 +283,11 @@ void Water::setViewportBackground(const ColourValue& bg)
|
|||
mReflectionTarget->getViewport(0)->setBackgroundColour(bg);
|
||||
}
|
||||
|
||||
void Water::updateVisible()
|
||||
{
|
||||
mWater->setVisible(mToggled && mActive);
|
||||
if (mReflectionTarget)
|
||||
mReflectionTarget->setActive(mToggled && mActive && !mIsUnderwater);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -24,6 +24,7 @@ namespace MWRender {
|
|||
|
||||
bool mIsUnderwater;
|
||||
bool mActive;
|
||||
bool mToggled;
|
||||
int mTop;
|
||||
|
||||
Ogre::Vector3 getSceneNodeCoordinates(int gridX, int gridY);
|
||||
|
@ -31,6 +32,7 @@ namespace MWRender {
|
|||
protected:
|
||||
void preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt);
|
||||
void postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt);
|
||||
void updateVisible();
|
||||
|
||||
SkyManager* mSky;
|
||||
|
||||
|
@ -39,6 +41,8 @@ namespace MWRender {
|
|||
void createMaterial();
|
||||
Ogre::MaterialPtr mMaterial;
|
||||
|
||||
Ogre::Camera* mReflectionCamera;
|
||||
|
||||
Ogre::RenderTarget* mReflectionTarget;
|
||||
|
||||
bool mUnderwaterEffect;
|
||||
|
|
|
@ -6,6 +6,10 @@ add_component_dir (settings
|
|||
settings
|
||||
)
|
||||
|
||||
add_component_dir (nifoverrides
|
||||
nifoverrides
|
||||
)
|
||||
|
||||
add_component_dir (bsa
|
||||
bsa_archive bsa_file
|
||||
)
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "ogre_nif_loader.hpp"
|
||||
|
||||
#include <components/settings/settings.hpp>
|
||||
#include <components/nifoverrides/nifoverrides.hpp>
|
||||
|
||||
typedef unsigned char ubyte;
|
||||
|
||||
|
@ -282,15 +283,61 @@ void NIFLoader::createMaterial(const String &name,
|
|||
// other values. 237 basically means normal transparencly.
|
||||
if (alphaFlags == 237)
|
||||
{
|
||||
// Enable transparency
|
||||
pass->setSceneBlending(SBT_TRANSPARENT_ALPHA);
|
||||
NifOverrides::TransparencyResult result = NifOverrides::Overrides::getTransparencyOverride(texName);
|
||||
if (result.first)
|
||||
{
|
||||
pass->setAlphaRejectFunction(CMPF_GREATER_EQUAL);
|
||||
pass->setAlphaRejectValue(result.second);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Enable transparency
|
||||
pass->setSceneBlending(SBT_TRANSPARENT_ALPHA);
|
||||
|
||||
//pass->setDepthCheckEnabled(false);
|
||||
pass->setDepthWriteEnabled(false);
|
||||
//pass->setDepthCheckEnabled(false);
|
||||
pass->setDepthWriteEnabled(false);
|
||||
//std::cout << "alpha 237; material: " << name << " texName: " << texName << std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
warn("Unhandled alpha setting for texture " + texName);
|
||||
}
|
||||
else
|
||||
{
|
||||
material->getTechnique(0)->setShadowCasterMaterial("depth_shadow_caster_noalpha");
|
||||
}
|
||||
}
|
||||
|
||||
if (Settings::Manager::getBool("enabled", "Shadows"))
|
||||
{
|
||||
bool split = Settings::Manager::getBool("split", "Shadows");
|
||||
const int numsplits = 3;
|
||||
for (int i = 0; i < (split ? numsplits : 1); ++i)
|
||||
{
|
||||
TextureUnitState* tu = material->getTechnique(0)->getPass(0)->createTextureUnitState();
|
||||
tu->setName("shadowMap" + StringConverter::toString(i));
|
||||
tu->setContentType(TextureUnitState::CONTENT_SHADOW);
|
||||
tu->setTextureAddressingMode(TextureUnitState::TAM_BORDER);
|
||||
tu->setTextureBorderColour(ColourValue::White);
|
||||
}
|
||||
}
|
||||
|
||||
if (Settings::Manager::getBool("shaders", "Objects"))
|
||||
{
|
||||
material->getTechnique(0)->getPass(0)->setVertexProgram("main_vp");
|
||||
material->getTechnique(0)->getPass(0)->setFragmentProgram("main_fp");
|
||||
}
|
||||
|
||||
// Create a fallback technique without shadows and without mrt
|
||||
Technique* tech2 = material->createTechnique();
|
||||
tech2->setSchemeName("Fallback");
|
||||
Pass* pass2 = tech2->createPass();
|
||||
pass2->createTextureUnitState(texName);
|
||||
pass2->setVertexColourTracking(TVC_DIFFUSE);
|
||||
if (Settings::Manager::getBool("shaders", "Objects"))
|
||||
{
|
||||
pass2->setVertexProgram("main_fallback_vp");
|
||||
pass2->setFragmentProgram("main_fallback_fp");
|
||||
}
|
||||
|
||||
// Add material bells and whistles
|
||||
|
@ -299,151 +346,6 @@ void NIFLoader::createMaterial(const String &name,
|
|||
material->setSpecular(specular.array[0], specular.array[1], specular.array[2], alpha);
|
||||
material->setSelfIllumination(emissive.array[0], emissive.array[1], emissive.array[2]);
|
||||
material->setShininess(glossiness);
|
||||
|
||||
if (Settings::Manager::getBool("shaders", "Objects"))
|
||||
{
|
||||
bool mrt = Settings::Manager::getBool("shader", "Water");
|
||||
|
||||
// Create shader for the material
|
||||
// vertex
|
||||
HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton();
|
||||
|
||||
HighLevelGpuProgramPtr vertex;
|
||||
if (mgr.getByName("main_vp").isNull())
|
||||
{
|
||||
vertex = mgr.createProgram("main_vp", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||
"cg", GPT_VERTEX_PROGRAM);
|
||||
vertex->setParameter("profiles", "vs_4_0 vs_2_x vp40 arbvp1");
|
||||
vertex->setParameter("entry_point", "main_vp");
|
||||
StringUtil::StrStreamType outStream;
|
||||
outStream <<
|
||||
"void main_vp( \n"
|
||||
" float4 position : POSITION, \n"
|
||||
" float4 normal : NORMAL, \n"
|
||||
" float4 colour : COLOR, \n"
|
||||
" in float2 uv : TEXCOORD0, \n"
|
||||
" out float2 oUV : TEXCOORD0, \n"
|
||||
" out float4 oPosition : POSITION, \n"
|
||||
" out float4 oPositionObjSpace : TEXCOORD1, \n"
|
||||
" out float4 oNormal : TEXCOORD2, \n"
|
||||
" out float oDepth : TEXCOORD3, \n"
|
||||
" out float4 oVertexColour : TEXCOORD4, \n"
|
||||
" uniform float4x4 worldViewProj \n"
|
||||
") \n"
|
||||
"{ \n"
|
||||
" oVertexColour = colour; \n"
|
||||
" oUV = uv; \n"
|
||||
" oNormal = normal; \n"
|
||||
" oPosition = mul( worldViewProj, position ); \n"
|
||||
" oDepth = oPosition.z; \n"
|
||||
" oPositionObjSpace = position; \n"
|
||||
"}";
|
||||
vertex->setSource(outStream.str());
|
||||
vertex->load();
|
||||
vertex->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
|
||||
}
|
||||
else
|
||||
vertex = mgr.getByName("main_vp");
|
||||
material->getTechnique(0)->getPass(0)->setVertexProgram(vertex->getName());
|
||||
|
||||
// the number of lights to support.
|
||||
// when rendering an object, OGRE automatically picks the lights that are
|
||||
// closest to the object being rendered. unfortunately this mechanism does
|
||||
// not work perfectly for objects batched together (they will all use the same
|
||||
// lights). to work around this, we are simply pushing the maximum number
|
||||
// of lights here in order to minimize disappearing lights.
|
||||
int num_lights = Settings::Manager::getInt("num lights", "Objects");
|
||||
|
||||
// fragment
|
||||
HighLevelGpuProgramPtr fragment;
|
||||
if (mgr.getByName("main_fp").isNull())
|
||||
{
|
||||
fragment = mgr.createProgram("main_fp", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||
"cg", GPT_FRAGMENT_PROGRAM);
|
||||
fragment->setParameter("profiles", "ps_4_0 ps_2_x fp40 arbfp1");
|
||||
fragment->setParameter("entry_point", "main_fp");
|
||||
StringUtil::StrStreamType outStream;
|
||||
outStream <<
|
||||
"void main_fp( \n"
|
||||
" in float2 uv : TEXCOORD0, \n"
|
||||
" out float4 oColor : COLOR, \n"
|
||||
" uniform sampler2D texture : TEXUNIT0, \n"
|
||||
" float4 positionObjSpace : TEXCOORD1, \n"
|
||||
" float4 normal : TEXCOORD2, \n"
|
||||
" float iDepth : TEXCOORD3, \n"
|
||||
" float4 vertexColour : TEXCOORD4, \n"
|
||||
" uniform float4 fogColour, \n"
|
||||
" uniform float4 fogParams, \n";
|
||||
|
||||
if (mrt) outStream <<
|
||||
" out float4 oColor1 : COLOR1, \n"
|
||||
" uniform float far, \n";
|
||||
|
||||
for (int i=0; i<num_lights; ++i)
|
||||
{
|
||||
outStream <<
|
||||
" uniform float4 lightDiffuse"<<i<<", \n"
|
||||
" uniform float4 lightPositionObjSpace"<<i<<", \n"
|
||||
" uniform float4 lightAttenuation"<<i<<", \n";
|
||||
}
|
||||
outStream <<
|
||||
" uniform float4 lightAmbient, \n"
|
||||
" uniform float4 ambient, \n"
|
||||
" uniform float4 diffuse, \n"
|
||||
" uniform float4 emissive \n"
|
||||
") \n"
|
||||
"{ \n"
|
||||
" float4 tex = tex2D(texture, uv); \n"
|
||||
" float d; \n"
|
||||
" float attn; \n"
|
||||
" float3 lightColour = float3(0, 0, 0); \n";
|
||||
|
||||
for (int i=0; i<num_lights; ++i)
|
||||
{
|
||||
outStream <<
|
||||
" float3 lightDir"<<i<<" = lightPositionObjSpace"<<i<<".xyz - (positionObjSpace.xyz * lightPositionObjSpace"<<i<<".w); \n"
|
||||
|
||||
// pre-multiply light color with attenuation factor
|
||||
" d = length( lightDir"<<i<<" ); \n"
|
||||
" attn = ( 1.0 / (( lightAttenuation"<<i<<".y ) + ( lightAttenuation"<<i<<".z * d ) + ( lightAttenuation"<<i<<".w * d * d ))); \n"
|
||||
" lightDiffuse"<<i<<" *= attn; \n"
|
||||
|
||||
" lightColour.xyz += lit(dot(normalize(lightDir"<<i<<"), normalize(normal)), 0, 0).y * lightDiffuse"<<i<<".xyz;\n";
|
||||
}
|
||||
|
||||
outStream <<
|
||||
" float3 lightingFinal = lightColour.xyz * diffuse.xyz * vertexColour.xyz + ambient.xyz * lightAmbient.xyz + emissive.xyz; \n"
|
||||
" float fogValue = saturate((iDepth - fogParams.y) * fogParams.w); \n"
|
||||
" oColor.xyz = lerp(lightingFinal * tex.xyz, fogColour, fogValue); \n"
|
||||
" oColor.a = tex.a * diffuse.a * vertexColour.a; \n";
|
||||
|
||||
if (mrt) outStream <<
|
||||
" oColor1 = float4(iDepth / far, 0, 0, (oColor.a == 1)); \n"; // only write to MRT if alpha is 1
|
||||
|
||||
outStream <<
|
||||
"}";
|
||||
fragment->setSource(outStream.str());
|
||||
fragment->load();
|
||||
|
||||
for (int i=0; i<num_lights; ++i)
|
||||
{
|
||||
fragment->getDefaultParameters()->setNamedAutoConstant("lightPositionObjSpace"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_POSITION_OBJECT_SPACE, i);
|
||||
fragment->getDefaultParameters()->setNamedAutoConstant("lightDiffuse"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_DIFFUSE_COLOUR, i);
|
||||
fragment->getDefaultParameters()->setNamedAutoConstant("lightAttenuation"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_ATTENUATION, i);
|
||||
}
|
||||
fragment->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR);
|
||||
fragment->getDefaultParameters()->setNamedAutoConstant("diffuse", GpuProgramParameters::ACT_SURFACE_DIFFUSE_COLOUR);
|
||||
fragment->getDefaultParameters()->setNamedAutoConstant("ambient", GpuProgramParameters::ACT_SURFACE_AMBIENT_COLOUR);
|
||||
fragment->getDefaultParameters()->setNamedAutoConstant("lightAmbient", GpuProgramParameters::ACT_AMBIENT_LIGHT_COLOUR);
|
||||
fragment->getDefaultParameters()->setNamedAutoConstant("fogColour", GpuProgramParameters::ACT_FOG_COLOUR);
|
||||
fragment->getDefaultParameters()->setNamedAutoConstant("fogParams", GpuProgramParameters::ACT_FOG_PARAMS);
|
||||
if (mrt)
|
||||
fragment->getDefaultParameters()->setNamedAutoConstant("far", GpuProgramParameters::ACT_FAR_CLIP_DISTANCE);
|
||||
}
|
||||
else
|
||||
fragment = mgr.getByName("main_fp");
|
||||
material->getTechnique(0)->getPass(0)->setFragmentProgram(fragment->getName());
|
||||
}
|
||||
}
|
||||
|
||||
// Takes a name and adds a unique part to it. This is just used to
|
||||
|
|
37
components/nifoverrides/nifoverrides.cpp
Normal file
37
components/nifoverrides/nifoverrides.cpp
Normal file
|
@ -0,0 +1,37 @@
|
|||
#include "nifoverrides.hpp"
|
||||
|
||||
#include <OgreStringConverter.h>
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
using namespace NifOverrides;
|
||||
|
||||
Ogre::ConfigFile Overrides::mTransparencyOverrides = Ogre::ConfigFile();
|
||||
|
||||
void Overrides::loadTransparencyOverrides (const std::string& file)
|
||||
{
|
||||
mTransparencyOverrides.load(file);
|
||||
}
|
||||
|
||||
TransparencyResult Overrides::getTransparencyOverride(const std::string& texture)
|
||||
{
|
||||
TransparencyResult result;
|
||||
result.first = false;
|
||||
|
||||
std::string tex = texture;
|
||||
boost::to_lower(tex);
|
||||
|
||||
Ogre::ConfigFile::SectionIterator seci = mTransparencyOverrides.getSectionIterator();
|
||||
while (seci.hasMoreElements())
|
||||
{
|
||||
Ogre::String sectionName = seci.peekNextKey();
|
||||
if (sectionName == tex)
|
||||
{
|
||||
result.first = true;
|
||||
result.second = Ogre::StringConverter::parseInt(mTransparencyOverrides.getSetting("alphaRejectValue", sectionName));
|
||||
break;
|
||||
}
|
||||
seci.getNext();
|
||||
}
|
||||
return result;
|
||||
}
|
23
components/nifoverrides/nifoverrides.hpp
Normal file
23
components/nifoverrides/nifoverrides.hpp
Normal file
|
@ -0,0 +1,23 @@
|
|||
#ifndef COMPONENTS_NIFOVERRIDES_H
|
||||
#define COMPONENTS_NIFOVERRIDES_H
|
||||
|
||||
#include <OgreConfigFile.h>
|
||||
|
||||
namespace NifOverrides
|
||||
{
|
||||
|
||||
typedef std::pair<bool, int> TransparencyResult;
|
||||
|
||||
/// \brief provide overrides for some model / texture properties that bethesda has chosen poorly
|
||||
class Overrides
|
||||
{
|
||||
public:
|
||||
static Ogre::ConfigFile mTransparencyOverrides;
|
||||
void loadTransparencyOverrides (const std::string& file);
|
||||
|
||||
static TransparencyResult getTransparencyOverride(const std::string& texture);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -11,3 +11,6 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/water.cg "${OpenMW_BINARY_DIR}/
|
|||
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)
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/shadows/depthshadowcaster.material "${OpenMW_BINARY_DIR}/resources/shadows/depthshadowcaster.material" COPYONLY)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/shadows/depthshadowcaster.cg "${OpenMW_BINARY_DIR}/resources/shadows/depthshadowcaster.cg" COPYONLY)
|
||||
|
|
|
@ -18,6 +18,32 @@ anisotropy = 4
|
|||
# Number of texture mipmaps to generate
|
||||
num mipmaps = 5
|
||||
|
||||
[Shadows]
|
||||
# Shadows are only supported when object shaders are on!
|
||||
enabled = false
|
||||
|
||||
# Split the shadow maps, allows for a larger shadow distance
|
||||
# Warning: enabling this will cause some terrain textures to disappear due to
|
||||
# hitting the texture unit limit of the terrain material
|
||||
split = false
|
||||
|
||||
# Increasing shadow distance will lower the shadow quality.
|
||||
# Uses "shadow distance" or "split shadow distance" depending on "split" setting.
|
||||
shadow distance = 1300
|
||||
# This one shouldn't be too low, otherwise you'll see artifacts. Use at least 2x max viewing distance.
|
||||
split shadow distance = 14000
|
||||
|
||||
# Size of the shadow textures, higher means higher quality
|
||||
texture size = 1024
|
||||
|
||||
# Turn on/off various shadow casters
|
||||
actor shadows = true
|
||||
misc shadows = true
|
||||
statics shadows = true
|
||||
|
||||
# Fraction of the total shadow distance after which the shadow starts to fade out
|
||||
fade start = 0.8
|
||||
|
||||
[HUD]
|
||||
# FPS counter
|
||||
# 0: not visible
|
||||
|
@ -64,15 +90,10 @@ num lights = 8
|
|||
shader = true
|
||||
|
||||
rtt size = 512
|
||||
|
||||
reflect terrain = true
|
||||
|
||||
reflect statics = false
|
||||
|
||||
reflect small statics = false
|
||||
|
||||
reflect actors = true
|
||||
|
||||
reflect misc = false
|
||||
|
||||
# Enable underwater effect. It is not resource intensive, so only disable it if you have problems.
|
||||
|
|
51
files/shadows/depthshadowcaster.cg
Normal file
51
files/shadows/depthshadowcaster.cg
Normal file
|
@ -0,0 +1,51 @@
|
|||
void main_vp(
|
||||
float4 position : POSITION,
|
||||
float2 uv : TEXCOORD0,
|
||||
|
||||
out float4 oPosition : POSITION,
|
||||
out float2 oDepth : TEXCOORD0,
|
||||
out float2 oUv : TEXCOORD1,
|
||||
|
||||
uniform float4x4 wvpMat)
|
||||
{
|
||||
// this is the view space position
|
||||
oPosition = mul(wvpMat, position);
|
||||
|
||||
// depth info for the fragment.
|
||||
oDepth.x = oPosition.z;
|
||||
oDepth.y = oPosition.w;
|
||||
|
||||
// clamp z to zero. seem to do the trick. :-/
|
||||
oPosition.z = max(oPosition.z, 0);
|
||||
|
||||
oUv = uv;
|
||||
}
|
||||
|
||||
void main_fp(
|
||||
float2 depth : TEXCOORD0,
|
||||
float2 uv : TEXCOORD1,
|
||||
uniform sampler2D texture1 : register(s0),
|
||||
|
||||
out float4 oColour : COLOR)
|
||||
{
|
||||
float finalDepth = depth.x / depth.y;
|
||||
|
||||
// use alpha channel of the first texture
|
||||
float alpha = tex2D(texture1, uv).a;
|
||||
|
||||
// discard if alpha is less than 0.5
|
||||
clip((alpha >= 0.5) ? 1 : -1);
|
||||
|
||||
oColour = float4(finalDepth, finalDepth, finalDepth, 1);
|
||||
}
|
||||
|
||||
void main_fp_noalpha(
|
||||
float2 depth : TEXCOORD0,
|
||||
float2 uv : TEXCOORD1,
|
||||
|
||||
out float4 oColour : COLOR)
|
||||
{
|
||||
float finalDepth = depth.x / depth.y;
|
||||
|
||||
oColour = float4(finalDepth, finalDepth, finalDepth, 1);
|
||||
}
|
67
files/shadows/depthshadowcaster.material
Normal file
67
files/shadows/depthshadowcaster.material
Normal file
|
@ -0,0 +1,67 @@
|
|||
vertex_program depth_shadow_caster_vs cg
|
||||
{
|
||||
source depthshadowcaster.cg
|
||||
profiles vs_1_1 arbvp1
|
||||
entry_point main_vp
|
||||
|
||||
default_params
|
||||
{
|
||||
param_named_auto wvpMat worldviewproj_matrix
|
||||
}
|
||||
}
|
||||
|
||||
fragment_program depth_shadow_caster_ps cg
|
||||
{
|
||||
source depthshadowcaster.cg
|
||||
profiles ps_2_0 arbfp1
|
||||
entry_point main_fp
|
||||
|
||||
default_params
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
fragment_program depth_shadow_caster_ps_noalpha cg
|
||||
{
|
||||
source depthshadowcaster.cg
|
||||
profiles ps_2_0 arbfp1
|
||||
entry_point main_fp_noalpha
|
||||
|
||||
default_params
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
material depth_shadow_caster
|
||||
{
|
||||
technique
|
||||
{
|
||||
pass
|
||||
{
|
||||
vertex_program_ref depth_shadow_caster_vs
|
||||
{
|
||||
}
|
||||
|
||||
fragment_program_ref depth_shadow_caster_ps
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
material depth_shadow_caster_noalpha
|
||||
{
|
||||
technique
|
||||
{
|
||||
pass
|
||||
{
|
||||
vertex_program_ref depth_shadow_caster_vs
|
||||
{
|
||||
}
|
||||
|
||||
fragment_program_ref depth_shadow_caster_ps_noalpha
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
574
files/transparency-overrides.cfg
Normal file
574
files/transparency-overrides.cfg
Normal file
|
@ -0,0 +1,574 @@
|
|||
# Bethesda has used wrong transparency settings for many textures
|
||||
# (who would have guessed)
|
||||
# This is very unfortunate because objects with real transparency:
|
||||
# - cannot cast shadows
|
||||
# - cannot receive advanced framebuffer effects like depth of field or ambient occlusion
|
||||
# - cannot cover lens flare effects (the lens flare will just shine through)
|
||||
|
||||
# This file lists textures that should be using alpha rejection instead of transparency
|
||||
# basically these are textures that are not translucent (i.e. at one spot on the texture, either transparent or opaque)
|
||||
|
||||
# Note: all the texture names here have to be lowercase
|
||||
|
||||
# fauna
|
||||
[textures\tx_wickwheat_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_wickwheat_03.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_red_lichen_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_stone_flower_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_ivy_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_ivy_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_saltrice_04.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_black_lichen_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_leaves_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_leaves_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_leaves_03.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_leaves_04.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_leaves_06.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_leaves_07.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_ai_heather_01.dds]
|
||||
alphaRejectValue = 96
|
||||
|
||||
[textures\tx_goldkanet_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_goldkanet_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_plant_tails00.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_vine_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_comberry_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_willow_flower_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_cork_bulb_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_green_lichen_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_roobrush_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_bittergreen_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_chokeweed_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_branches_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_branches_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_guarskin_hut_03.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_hackle-lo_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_bc_fern_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_bc_fern_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_bc_leaves_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_marshmerrow_03.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_bc_moss_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_bc_moss_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_bc_lilypad_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_bc_lilypad_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_bc_lilypad_03.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_fire_fern_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
# banners and flags
|
||||
[textures\tx_flag_imp_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_v_b_arena_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_v_b_comfort_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_v_b_child_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_v_b_count_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_v_b_faith_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_v_b_walk_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_v_b_imp_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_v_b_redoran_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_v_b_avs_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_v_b_serving_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_v_b_speak_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_v_b_stdeyln_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_v_b_stolms_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_v_b_thin_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_v_b_vivec_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_v_b_vivec_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_ashl_banner_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_ashl_banner_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_ashl_banner_04.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_ashl_banner_05.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_ashl_banner_06.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_ashl_banner_07.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_ashl_a_banner.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_ashl_e_banner.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_ashl_u_banner.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_ashl_z_banner.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_banner_6th.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_banner_6th_tall.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_banner_gnisis_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_banner_gnisis_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_tapestry_bhm_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_tapestry_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_tapestry_03.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_tapestry_04.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_tapestry_05.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_tapestry_06.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_tapestry_07.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_tapestry_08.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_tapestry_08.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_tapestry_09.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_tapestry_10.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_tapestry_11.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_tapestry_12.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_tapestry_13.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_lutestrings_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_fabric_imp_altar_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_c_t_akatosh_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_c_t_apprentice_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_c_t_arkay_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_c_t_dibella_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_c_t_golem_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_c_t_julianos_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_c_t_kynareth_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_c_t_lady_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_c_t_lord_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_c_t_lover_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_c_t_mara_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_c_t_ritual_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_c_t_shadow_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_c_t_steed_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_c_t_stendarr_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_c_t_thief_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_c_t_tower_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_c_t_warrior_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_c_t_wizard_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_c_t_zenithar_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_banner_dagoth_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_bannerd_tavern_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_bannerd_goods_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_bannerd_danger_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_bannerd_welcome_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_bannerd_clothing_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_bannerd_alchemy_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_banner_hlaalu_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_banner_redoran_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_banner_temple_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_banner_temple_03.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_banner_book_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_banner_ald_velothi.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_banner_gnaar_mok.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_banner_hla_oad.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_banner_khull.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_banner_pawn_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_banner_sadrith_mora.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_banner_tel_aruhn.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_banner_tel_branora.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_banner_tel_fyr.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_banner_tel_mora.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_banner_telvani_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_banner_tel_vos.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_banner_vos.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_bannerd_w_a_shop_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_banner_temple_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_mural1_00.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_mural1_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_mural4_00.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_mural4_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_mural5_00.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_v_b_telvanni_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_v_b_hlaalu_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_fabric_tapestry.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_fabric_tapestry_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_fabric_tapestry_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_fabric_tapestry_03.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_fabric_tapestry_04.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
# characters
|
||||
[textures\tx_netchgod00.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_b_n_argonian_f_hair02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_b_n_argonian_f_hair03.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_b_n_argonian_m_hair01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_b_n_argonian_m_hair04.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_b_n_argonian_m_hair05.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_b_n_khajiit_f_hair01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_b_n_khajiit_f_hair02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_b_n_khajiit_m_hair01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_corprus_stalker12.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_a_clavicus02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_b_n_dark elf_m_hair11.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_b_n_dark elf_f_hair10.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
# misc items
|
||||
[textures\tx_sail.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_longboatsail01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_longboatsail01a.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_longboatsail01b.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_longboatsail02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_quill.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_note_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_note_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_parchment_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_parchment_03.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_scroll_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_scroll_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_scroll_03.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_alpha_small_edge.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_alpha_shadow_circular.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
# building materials
|
||||
[textures\tx_shack_thatch_strip.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_rug00.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_rug_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_rug_edge_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_awning_thatch_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_awning_woven_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_bridgeropes.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_rope_woven_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_rope_woven_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_ashl_tent_06.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_guar_tarp.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_velothi_glyph00.dds]
|
||||
alphaRejectValue = 128
|
|
@ -92,7 +92,7 @@ material Water
|
|||
}
|
||||
technique
|
||||
{
|
||||
scheme Map
|
||||
scheme Fallback
|
||||
pass
|
||||
{
|
||||
cull_hardware none
|
||||
|
|
Loading…
Reference in a new issue