Terrain component shaders

Problems building or running the engine, queries about how to use features etc.
Post Reply
Kenshido
Gremlin
Posts: 153
Joined: Tue Jun 09, 2009 9:31 am
Location: Russia
x 12
Contact:

Terrain component shaders

Post by Kenshido »

Hello!

I need to do two things:
1. change shader of terrain composite map - add specular (or more) settings.
2. change texture blending shader.

the simpliest way I've found is to use Nauk's code from here http://www.ogre3d.org/forums/viewtopic.php?f=5&t=72455, but it downgrades 1.7+ terrain to 1.6 one, so I lose all advanced features like composite map etc.
I think, that depth texture blending is more realistik, so I'd like to change only blending and don't touch other shader and component features. What should I look at?
Attachments
texture blending example
texture blending example
User avatar
c6burns
Beholder
Posts: 1512
Joined: Fri Feb 22, 2013 4:44 am
Location: Deep behind enemy lines
x 138

Re: Terrain component shaders

Post by c6burns »

Check out OgreTerrainMaterialGeneratorA.h in the Terrain component. You will see that for each type of shader, a class derived from ShaderHelper is created (eg. ShaderHelperCg, ShaderHelperGLSL, etc). These classes generate the actual shader code based on which type of shader is required. You can see the call order is:
1) generateVpHeader / generateFpHeader
2) generateVpLayer / generateFpLayer
3) generateVpFooter / generateFpFooter

Also each method is called with a TechniqueType param, so you could change just composite map generation, or just per-layer settings for the highlod shaders, or whatever you need.
Kenshido
Gremlin
Posts: 153
Joined: Tue Jun 09, 2009 9:31 am
Location: Russia
x 12
Contact:

Re: Terrain component shaders

Post by Kenshido »

Thank you for suggestion!

I copied TerrainMaterialGeneratorA and renamed it to TerrainMaterialGeneratorB, after this I copied shader helper classes. I think it would be enough to take just shader helper classes, but TerrainMaterialGeneratorA declares them with _OgreTerrainExport, so my project tries to be compiled to .lib with lots of linker mistakes, but not to .exe.
Attachments
BOF_Screenshot_07152014_105209137.jpg
User avatar
tod
Troll
Posts: 1394
Joined: Wed Aug 02, 2006 9:41 am
Location: Bucharest
x 94
Contact:

Re: Terrain component shaders

Post by tod »

Look here for an example on how to change the material generator.
User avatar
c6burns
Beholder
Posts: 1512
Joined: Fri Feb 22, 2013 4:44 am
Location: Deep behind enemy lines
x 138

Re: Terrain component shaders

Post by c6burns »

Just get rid of _OgreTerrainExport (search and replace with blank in your own project) because it will be defined as __declspec( dllexport ). Then replace OgreTerrainMaterialGeneratorA with OgreTerrainMaterialGeneratorB (or whatever your new name is) in all files. This is what I did to create my first Material Generator. Then I went into TerrainMaterialGeneratorB::SM2Profile::ShaderHelper::generateVertexProgram and generateFragmentProgram and made sure it was always outputting the final shaders into my ogre log. It's hard at first to get a sense of how the shaders work as a whole because of how broken up they are in the shader generator. From there I was able to make the necessary changes for my own project.
Kenshido
Gremlin
Posts: 153
Joined: Tue Jun 09, 2009 9:31 am
Location: Russia
x 12
Contact:

Re: Terrain component shaders

Post by Kenshido »

Yes, I did it the way you say. It works correctly.
Now I can't figure out how they send samplers to shader. I tried to add globalNormal sampler to LOW_LOD technique (in order to calculare specular for composite map), but I don't know where in material I should set this texture. And how to work with terrain's material at all.

setting for LOW_LOD in TerrainMaterialGeneratorB:

Code: Select all

params->setNamedConstant("globalNormal", (int)numSamplers++);
couses correct shader code:

Code: Select all

uniform sampler2D globalNormal : register(s0)
, uniform sampler2D compositeMap : register(s1)
but of course this sampler is empty.
Kenshido
Gremlin
Posts: 153
Joined: Tue Jun 09, 2009 9:31 am
Location: Russia
x 12
Contact:

Re: Terrain component shaders

Post by Kenshido »

The answer is here:

Code: Select all

    void TerrainMaterialGeneratorB::SM2Profile::addTechnique(
        const MaterialPtr& mat, const Terrain* terrain, TechniqueType tt)

...

		// global normal map
		TextureUnitState* tu = pass->createTextureUnitState();
		tu->setTextureName(terrain->getTerrainNormalMap()->getName());

Kenshido
Gremlin
Posts: 153
Joined: Tue Jun 09, 2009 9:31 am
Location: Russia
x 12
Contact:

Re: Terrain component shaders

Post by Kenshido »

Good surprise was, that composite map already contains specular (that take into account shadowmap) in it's alpha channel.
Attachments
BOF_Screenshot_07162014_102630705.jpg
BOF_Screenshot_07162014_102703293.jpg
User avatar
insider
Orc
Posts: 462
Joined: Thu Sep 15, 2011 12:50 pm
x 31

Re: Terrain component shaders

Post by insider »

Kenshido wrote:The answer is here:

Code: Select all

    void TerrainMaterialGeneratorB::SM2Profile::addTechnique(
        const MaterialPtr& mat, const Terrain* terrain, TechniqueType tt)

...

		// global normal map
		TextureUnitState* tu = pass->createTextureUnitState();
		tu->setTextureName(terrain->getTerrainNormalMap()->getName());

Could you post the full code, I am breaking my head over this. :)
Kenshido
Gremlin
Posts: 153
Joined: Tue Jun 09, 2009 9:31 am
Location: Russia
x 12
Contact:

Re: Terrain component shaders

Post by Kenshido »

Find this method in TerrainMaterialGeneratorB.cpp:

Code: Select all

    void TerrainMaterialGeneratorB::SM2Profile::addTechnique(
        const MaterialPtr& mat, const Terrain* terrain, TechniqueType tt)
find code:

Code: Select all

        else
        {
            // LOW_LOD textures
            // composite map
            TextureUnitState* tu = pass->createTextureUnitState();
            tu->setTextureName(terrain->getCompositeMap()->getName());
            tu->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);

            // That's it!

        }
as you can see, global normal map texture is set for HIGH_LOD and RENDER_COMPOSITE_MAP techniques.
So change the code to:

Code: Select all

        else
        {
            // LOW_LOD textures
            // global normal map
            TextureUnitState* tu = pass->createTextureUnitState();
            tu->setTextureName(terrain->getTerrainNormalMap()->getName());
            // composite map
            TextureUnitState* tu = pass->createTextureUnitState();
            tu->setTextureName(terrain->getCompositeMap()->getName());
            tu->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);

            // That's it!

        }
Now in the method:

Code: Select all

    void TerrainMaterialGeneratorB::SM2Profile::ShaderHelper::defaultFpParams(
        const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, const HighLevelGpuProgramPtr& prog)
find code:

Code: Select all

            if (tt == LOW_LOD)
            {
                params->setNamedConstant("compositeMap", (int)numSamplers++);
            }
and change it to:

Code: Select all

            if (tt == LOW_LOD)
            {
                params->setNamedConstant("globalNormal", (int)numSamplers++);
                params->setNamedConstant("compositeMap", (int)numSamplers++);
            }
Now in TerrainMaterialShaderHelperCg.cpp find method:

Code: Select all

    void TerrainMaterialGeneratorB::SM2Profile::ShaderHelperCg::generateFpHeader(
        const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringStream& outStream)
the code:

Code: Select all

        if (tt == LOW_LOD)
        {
            // single composite map covers all the others below
            outStream << 
                "uniform sampler2D compositeMap : register(s" << currentSamplerIdx++ << ")\n";
        }
change to:

Code: Select all

        if (tt == LOW_LOD)
        {
            // single composite map covers all the others below
            outStream << 
                "uniform sampler2D globalNormal : register(s" << currentSamplerIdx++ << ")\n";
            outStream << 
                ", uniform sampler2D compositeMap : register(s" << currentSamplerIdx++ << ")\n";
        }
Now you have globalNormal texture in low_lod shader, and can use normals to calculate specular for composite map.
User avatar
insider
Orc
Posts: 462
Joined: Thu Sep 15, 2011 12:50 pm
x 31

Re: Terrain component shaders

Post by insider »

Kenshido wrote:Find this method in TerrainMaterialGeneratorB.cpp:
Brilliant it worked :D
Kenshido
Gremlin
Posts: 153
Joined: Tue Jun 09, 2009 9:31 am
Location: Russia
x 12
Contact:

Re: Terrain component shaders

Post by Kenshido »

well... there's a lot should be done with TerrainMaterialGeneratorB, if you want terrain look good at close and in the far...
Inspired by
http://udn.epicgames.com/Three/TerrainA ... tures.html
and
http://www.gamasutra.com/blogs/AndreyMi ... atting.php
Attachments
BOF_Screenshot_07222014_004812288.jpg
BOF_Screenshot_07222014_004758019.jpg
BOF_Screenshot_07222014_004726835.jpg
Kenshido
Gremlin
Posts: 153
Joined: Tue Jun 09, 2009 9:31 am
Location: Russia
x 12
Contact:

Re: Terrain component shaders

Post by Kenshido »

Hello again!

How can I obtain access to custom members of class TerrainMaterialGeneratorB?

Code: Select all

typedef SharedPtr<TerrainMaterialGenerator> TerrainMaterialGeneratorPtr;

mTerrainGlobals = OGRE_NEW Ogre::TerrainGlobalOptions();
mTerrainGlobals->setDefaultMaterialGenerator(Ogre::TerrainMaterialGeneratorPtr(new Ogre::TerrainMaterialGeneratorB));
so, if I later want to get material generator object:

Code: Select all

mTerrainGlobals->getDefaultMaterialGenerator();
I get a pointer to TerrainMaterialGenerator (derived class), of course is does not know anything about interiting class TerrainMaterialGeneratorB.

I need to get something like this:

Code: Select all

Ogre::TerrainMaterialGeneratorB *object = (convert to Ogre::TerrainMaterialGeneratorB)mTerrainGlobals->getDefaultMaterialGenerator();
object ->myCustomMethod();
Post Reply