Add specular mapping for terrain

move
scrawl 9 years ago
parent 171e293641
commit 0db7163363

@ -197,8 +197,9 @@ namespace MWRender
mWater.reset(new Water(mRootNode, sceneRoot, mResourceSystem, mViewer->getIncrementalCompileOperation(), fallback, resourcePath)); mWater.reset(new Water(mRootNode, sceneRoot, mResourceSystem, mViewer->getIncrementalCompileOperation(), fallback, resourcePath));
mTerrain.reset(new Terrain::TerrainGrid(sceneRoot, mResourceSystem, mViewer->getIncrementalCompileOperation(), mTerrain.reset(new Terrain::TerrainGrid(sceneRoot, mResourceSystem, mViewer->getIncrementalCompileOperation(),
new TerrainStorage(mResourceSystem->getVFS(), Settings::Manager::getString("normal map pattern", "Shaders"), Settings::Manager::getBool("auto use terrain normal maps", "Shaders")), new TerrainStorage(mResourceSystem->getVFS(), Settings::Manager::getString("normal map pattern", "Shaders"), Settings::Manager::getBool("auto use terrain normal maps", "Shaders"),
Mask_Terrain, &mResourceSystem->getSceneManager()->getShaderManager(), mUnrefQueue.get())); Settings::Manager::getString("terrain specular map pattern", "Shaders"), Settings::Manager::getBool("auto use terrain specular maps", "Shaders")),
Mask_Terrain, &mResourceSystem->getSceneManager()->getShaderManager(), mUnrefQueue.get()));
mCamera.reset(new Camera(mViewer->getCamera())); mCamera.reset(new Camera(mViewer->getCamera()));

@ -9,8 +9,8 @@
namespace MWRender namespace MWRender
{ {
TerrainStorage::TerrainStorage(const VFS::Manager* vfs, const std::string& normalMapPattern, bool autoUseNormalMaps) TerrainStorage::TerrainStorage(const VFS::Manager* vfs, const std::string& normalMapPattern, bool autoUseNormalMaps, const std::string& specularMapPattern, bool autoUseSpecularMaps)
: ESMTerrain::Storage(vfs, normalMapPattern, autoUseNormalMaps) : ESMTerrain::Storage(vfs, normalMapPattern, autoUseNormalMaps, specularMapPattern, autoUseSpecularMaps)
{ {
} }

@ -14,7 +14,7 @@ namespace MWRender
virtual const ESM::LandTexture* getLandTexture(int index, short plugin); virtual const ESM::LandTexture* getLandTexture(int index, short plugin);
public: public:
TerrainStorage(const VFS::Manager* vfs, const std::string& normalMapPattern = "", bool autoUseNormalMaps = false); TerrainStorage(const VFS::Manager* vfs, const std::string& normalMapPattern = "", bool autoUseNormalMaps = false, const std::string& specularMapPattern = "", bool autoUseSpecularMaps = false);
/// Get bounds of the whole terrain in cell units /// Get bounds of the whole terrain in cell units
virtual void getBounds(float& minX, float& maxX, float& minY, float& maxY); virtual void getBounds(float& minX, float& maxX, float& minY, float& maxY);

@ -18,10 +18,12 @@ namespace ESMTerrain
const float defaultHeight = -2048; const float defaultHeight = -2048;
Storage::Storage(const VFS::Manager *vfs, const std::string& normalMapPattern, bool autoUseNormalMaps) Storage::Storage(const VFS::Manager *vfs, const std::string& normalMapPattern, bool autoUseNormalMaps, const std::string& specularMapPattern, bool autoUseSpecularMaps)
: mVFS(vfs) : mVFS(vfs)
, mNormalMapPattern(normalMapPattern) , mNormalMapPattern(normalMapPattern)
, mAutoUseNormalMaps(autoUseNormalMaps) , mAutoUseNormalMaps(autoUseNormalMaps)
, mSpecularMapPattern(specularMapPattern)
, mAutoUseSpecularMaps(autoUseSpecularMaps)
{ {
} }
@ -510,7 +512,7 @@ namespace ESMTerrain
return found->second; return found->second;
Terrain::LayerInfo info; Terrain::LayerInfo info;
info.mParallax = false; //info.mParallax = false;
info.mSpecular = false; info.mSpecular = false;
info.mDiffuseMap = texture; info.mDiffuseMap = texture;
@ -532,17 +534,16 @@ namespace ESMTerrain
info.mNormalMap = texture_; info.mNormalMap = texture_;
} }
/* if (mAutoUseSpecularMaps)
{ {
std::string texture_ = texture; std::string texture_ = texture;
boost::replace_last(texture_, ".", "_diffusespec."); boost::replace_last(texture_, ".", mSpecularMapPattern + ".");
if (mVFS->exists(texture_)) if (mVFS->exists(texture_))
{ {
info.mDiffuseMap = texture_; info.mDiffuseMap = texture_;
info.mSpecular = true; info.mSpecular = true;
} }
} }
*/
mLayerInfoMap[texture] = info; mLayerInfoMap[texture] = info;
@ -553,7 +554,7 @@ namespace ESMTerrain
{ {
Terrain::LayerInfo info; Terrain::LayerInfo info;
info.mDiffuseMap = "textures\\_land_default.dds"; info.mDiffuseMap = "textures\\_land_default.dds";
info.mParallax = false; //info.mParallax = false;
info.mSpecular = false; info.mSpecular = false;
return info; return info;
} }

@ -27,7 +27,7 @@ namespace ESMTerrain
virtual const ESM::LandTexture* getLandTexture(int index, short plugin) = 0; virtual const ESM::LandTexture* getLandTexture(int index, short plugin) = 0;
public: public:
Storage(const VFS::Manager* vfs, const std::string& normalMapPattern = "", bool autoUseNormalMaps = false); Storage(const VFS::Manager* vfs, const std::string& normalMapPattern = "", bool autoUseNormalMaps = false, const std::string& specularMapPattern = "", bool autoUseSpecularMaps = false);
/// Data is loaded first, if necessary. Will return a 0-pointer if there is no data for /// Data is loaded first, if necessary. Will return a 0-pointer if there is no data for
/// any of the data types specified via \a flags. Will also return a 0-pointer if there /// any of the data types specified via \a flags. Will also return a 0-pointer if there
@ -112,6 +112,9 @@ namespace ESMTerrain
std::string mNormalMapPattern; std::string mNormalMapPattern;
bool mAutoUseNormalMaps; bool mAutoUseNormalMaps;
std::string mSpecularMapPattern;
bool mAutoUseSpecularMaps;
Terrain::LayerInfo getLayerInfo(const std::string& texture); Terrain::LayerInfo getLayerInfo(const std::string& texture);
}; };

@ -18,8 +18,10 @@ namespace Terrain
{ {
std::string mDiffuseMap; std::string mDiffuseMap;
std::string mNormalMap; std::string mNormalMap;
bool mParallax; // Height info in normal map alpha channel? //bool mParallax; // Height info in normal map alpha channel?
bool mSpecular; // Specular info in diffuse map alpha channel? bool mSpecular; // Specular info in diffuse map alpha channel?
bool requiresShaders() const { return !mNormalMap.empty() || mSpecular; }
}; };
} }

@ -129,6 +129,7 @@ namespace Terrain
defineMap["normalMap"] = (it->mNormalMap) ? "1" : "0"; defineMap["normalMap"] = (it->mNormalMap) ? "1" : "0";
defineMap["blendMap"] = !firstLayer ? "1" : "0"; defineMap["blendMap"] = !firstLayer ? "1" : "0";
defineMap["colorMode"] = "2"; defineMap["colorMode"] = "2";
defineMap["specularMap"] = it->mSpecular ? "1" : "0";
osg::ref_ptr<osg::Shader> vertexShader = shaderManager.getShader("terrain_vertex.glsl", defineMap, osg::Shader::VERTEX); osg::ref_ptr<osg::Shader> vertexShader = shaderManager.getShader("terrain_vertex.glsl", defineMap, osg::Shader::VERTEX);
osg::ref_ptr<osg::Shader> fragmentShader = shaderManager.getShader("terrain_fragment.glsl", defineMap, osg::Shader::FRAGMENT); osg::ref_ptr<osg::Shader> fragmentShader = shaderManager.getShader("terrain_fragment.glsl", defineMap, osg::Shader::FRAGMENT);

@ -23,6 +23,7 @@ namespace Terrain
{ {
osg::ref_ptr<osg::Texture2D> mDiffuseMap; osg::ref_ptr<osg::Texture2D> mDiffuseMap;
osg::ref_ptr<osg::Texture2D> mNormalMap; // optional osg::ref_ptr<osg::Texture2D> mNormalMap; // optional
bool mSpecular;
}; };
class FixedFunctionTechnique : public osgFX::Technique class FixedFunctionTechnique : public osgFX::Technique

@ -162,6 +162,7 @@ osg::ref_ptr<osg::Node> TerrainGrid::buildTerrain (osg::Group* parent, float chu
for (std::vector<LayerInfo>::const_iterator it = layerList.begin(); it != layerList.end(); ++it) for (std::vector<LayerInfo>::const_iterator it = layerList.begin(); it != layerList.end(); ++it)
{ {
TextureLayer textureLayer; TextureLayer textureLayer;
textureLayer.mSpecular = it->mSpecular;
osg::ref_ptr<osg::Texture2D> texture = mTextureCache[it->mDiffuseMap]; osg::ref_ptr<osg::Texture2D> texture = mTextureCache[it->mDiffuseMap];
if (!texture) if (!texture)
{ {
@ -187,9 +188,11 @@ osg::ref_ptr<osg::Node> TerrainGrid::buildTerrain (osg::Group* parent, float chu
} }
textureCompileDummy->getOrCreateStateSet()->setTextureAttributeAndModes(dummyTextureCounter++, texture); textureCompileDummy->getOrCreateStateSet()->setTextureAttributeAndModes(dummyTextureCounter++, texture);
textureLayer.mNormalMap = texture; textureLayer.mNormalMap = texture;
useShaders = true;
} }
if (it->requiresShaders())
useShaders = true;
layers.push_back(textureLayer); layers.push_back(textureLayer);
} }
} }

@ -189,6 +189,8 @@ auto use object specular maps = false
# See 'auto use object normal maps'. Affects terrain. # See 'auto use object normal maps'. Affects terrain.
auto use terrain normal maps = false auto use terrain normal maps = false
# If a file with pattern 'terrain specular map pattern' exists, use that file as a 'diffuse specular' map. The texture
# must contain the layer color in the RGB channel (as usual), and a specular multiplier in the alpha channel.
auto use terrain specular maps = false auto use terrain specular maps = false
# The filename pattern to probe for when detecting normal maps (see 'auto use object normal maps', 'auto use terrain normal maps') # The filename pattern to probe for when detecting normal maps (see 'auto use object normal maps', 'auto use terrain normal maps')
@ -196,6 +198,8 @@ normal map pattern = _n
specular map pattern = _spec specular map pattern = _spec
terrain specular map pattern = _diffusespec
[Input] [Input]
# Capture control of the cursor prevent movement outside the window. # Capture control of the cursor prevent movement outside the window.

@ -19,10 +19,10 @@ varying float depth;
#if !PER_PIXEL_LIGHTING #if !PER_PIXEL_LIGHTING
varying vec4 lighting; varying vec4 lighting;
#else #else
varying vec3 passViewPos;
varying vec3 passViewNormal;
varying vec4 passColor; varying vec4 passColor;
#endif #endif
varying vec3 passViewPos;
varying vec3 passViewNormal;
#include "lighting.glsl" #include "lighting.glsl"
@ -30,16 +30,15 @@ void main()
{ {
vec2 diffuseMapUV = (gl_TextureMatrix[0] * vec4(uv, 0.0, 1.0)).xy; vec2 diffuseMapUV = (gl_TextureMatrix[0] * vec4(uv, 0.0, 1.0)).xy;
gl_FragData[0] = vec4(texture2D(diffuseMap, diffuseMapUV).xyz, 1.0); vec4 diffuseTex = texture2D(diffuseMap, diffuseMapUV);
gl_FragData[0] = vec4(diffuseTex.xyz, 1.0);
#if @blendMap #if @blendMap
vec2 blendMapUV = (gl_TextureMatrix[1] * vec4(uv, 0.0, 1.0)).xy; vec2 blendMapUV = (gl_TextureMatrix[1] * vec4(uv, 0.0, 1.0)).xy;
gl_FragData[0].a *= texture2D(blendMap, blendMapUV).a; gl_FragData[0].a *= texture2D(blendMap, blendMapUV).a;
#endif #endif
#if PER_PIXEL_LIGHTING
vec3 viewNormal = passViewNormal; vec3 viewNormal = passViewNormal;
#endif
#if @normalMap #if @normalMap
vec3 normalTex = texture2D(normalMap, diffuseMapUV).xyz; vec3 normalTex = texture2D(normalMap, diffuseMapUV).xyz;
@ -59,6 +58,16 @@ void main()
gl_FragData[0] *= doLighting(passViewPos, normalize(viewNormal), passColor); gl_FragData[0] *= doLighting(passViewPos, normalize(viewNormal), passColor);
#endif #endif
#if @specularMap
float shininess = 128; // TODO: make configurable
vec3 matSpec = vec3(diffuseTex.a, diffuseTex.a, diffuseTex.a);
#else
float shininess = gl_FrontMaterial.shininess;
vec3 matSpec = gl_FrontMaterial.specular.xyz;
#endif
gl_FragData[0].xyz += getSpecular(normalize(viewNormal), normalize(passViewPos), shininess, matSpec);
float fogValue = clamp((depth - gl_Fog.start) * gl_Fog.scale, 0.0, 1.0); float fogValue = clamp((depth - gl_Fog.start) * gl_Fog.scale, 0.0, 1.0);
gl_FragData[0].xyz = mix(gl_FragData[0].xyz, gl_Fog.color.xyz, fogValue); gl_FragData[0].xyz = mix(gl_FragData[0].xyz, gl_Fog.color.xyz, fogValue);
} }

@ -8,10 +8,10 @@ varying float depth;
#if !PER_PIXEL_LIGHTING #if !PER_PIXEL_LIGHTING
varying vec4 lighting; varying vec4 lighting;
#else #else
varying vec3 passViewPos;
varying vec3 passViewNormal;
varying vec4 passColor; varying vec4 passColor;
#endif #endif
varying vec3 passViewPos;
varying vec3 passViewNormal;
#include "lighting.glsl" #include "lighting.glsl"
@ -27,10 +27,10 @@ void main(void)
#if !PER_PIXEL_LIGHTING #if !PER_PIXEL_LIGHTING
lighting = doLighting(viewPos.xyz, viewNormal, gl_Color); lighting = doLighting(viewPos.xyz, viewNormal, gl_Color);
#else #else
passViewPos = viewPos.xyz;
passViewNormal = viewNormal;
passColor = gl_Color; passColor = gl_Color;
#endif #endif
passViewNormal = viewNormal;
passViewPos = viewPos.xyz;
uv = gl_MultiTexCoord0.xy; uv = gl_MultiTexCoord0.xy;
} }

Loading…
Cancel
Save