Generating terrain with different textures

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
badday
Posts: 102
Joined: Mon Aug 16, 2010 1:14 pm

Generating terrain with different textures

Post by badday »

Hi there,

I would like to build up a terrain from a height map and some textures.
Therefore I´d specify the textures at some heights, let´s say 0, 3, 5. I would say: Water (as ISceneNode*) at 0, gras (just a picture-file) at 3 and snow (just a picture-file) at 5. In the space between I would like to have a smooth transition (I guess that´s hard with the water, so this could be seperated).

All that should be in an ITerrainSceneNode at the end.

Can I do that with Irrlicht? If so, how?

Thanks a lot.


Greetings,

badday
sudi
Posts: 1686
Joined: Fri Aug 26, 2005 8:38 pm

Post by sudi »

yeah you can. the different textures at certain heights can be accomplished with a shader that blends the textures. but integrating a water scenenode into ITerrainSceneNode seams stupid to me bc it doesn't belong there. anyway one drawback is that irrlicht only supports 4 textures currently so you can only have 4 different terrain textures on it. or three when want a detail texture on it as well or two if you want a detail texture for every different underground. another approach would be rendering the terrain several times for every texture once for example.
We're programmers. Programmers are, in their hearts, architects, and the first thing they want to do when they get to a site is to bulldoze the place flat and build something grand. We're not excited by renovation:tinkering,improving,planting flower beds.
slavik262
Posts: 753
Joined: Sun Nov 22, 2009 9:25 pm
Location: Wisconsin, USA

Post by slavik262 »

Sudi wrote:...irrlicht only supports 4 textures...
Not if you recompile it. Then it can support up to 8, and recompiling is super easy.
DarkDepths
Posts: 126
Joined: Sun Apr 02, 2006 1:21 am
Location: Canada

Post by DarkDepths »

slavik262 wrote:
Sudi wrote:...irrlicht only supports 4 textures...
Not if you recompile it. Then it can support up to 8, and recompiling is super easy.
Just out of curiosity, if it is so easy to recompile with support for 8 textures (which I think involves changing only the value of a constant?), why do the official builds only support 4?
badday
Posts: 102
Joined: Mon Aug 16, 2010 1:14 pm

Post by badday »

the different textures at certain heights can be accomplished with a shader that blends the textures
Could you just give me an idea how to do that?
but integrating a water scenenode into ITerrainSceneNode seams stupid to me
OK, so what I´d like to accomplish is to have water up to a height of x. All over the terrain. So, adding it to the ITerrainSceneNode is out of question, how else could I do that?

Thanks a lot.

Greetings,

badday
sudi
Posts: 1686
Joined: Fri Aug 26, 2005 8:38 pm

Post by sudi »

well when the lowest point in your terrain is at Y=0 you just place a water scenenode in theheight you want it.

bc of the shaders. just do some research i am to lazy now to do it for you
We're programmers. Programmers are, in their hearts, architects, and the first thing they want to do when they get to a site is to bulldoze the place flat and build something grand. We're not excited by renovation:tinkering,improving,planting flower beds.
badday
Posts: 102
Joined: Mon Aug 16, 2010 1:14 pm

Post by badday »

Well, I did some research before posting, of coure I did. But I just have no idea how to do it (and I don´t know what to look for, shader+irrlicht+multiple+texture wasn´t right). So, first of all, here is how I do the water thing at the moment:

Code: Select all

IAnimatedMesh* plane = smgr->addHillPlaneMesh("plane", // Name of mesh
      core::dimension2d<f32>(10,10), //	Size of a tile of the mesh. (10.0f, 10.0f) would be a good value to start, for example. 
      core::dimension2d<u32>(100,100), 0, 0, // 	Specifies how much tiles there will be. If you specifiy for example that a tile has the size (10.0f, 10.0f) and the tileCount is (10,10), than you get a field of 100 tiles which has the dimension 100.0fx100.0f. 
      core::dimension2d<f32>(0,0), //material 	
      core::dimension2d<f32>(10,10)); //countHills 


    //mesh, waveheight = 0.5f, wave speed = 350.0f, wave length = 80.0f
    ISceneNode* sea = smgr->addWaterSurfaceSceneNode(plane->getMesh(0), 0.5f, 1000.0f, 0.5f);
 sea->setMaterialTexture(0, driver->getTexture("../grafik/Planet-Terrain/greysand.png"));
sea->setMaterialTexture(1, driver->getTexture("../grafik/water.png"));

sea->setMaterialFlag(EMF_LIGHTING, true);
sea->setMaterialType(video::EMT_REFLECTION_2_LAYER);
sea->setPosition(core::vector3df(0,2,0));
All right, but how can I make water over the hole terrain (at the moment it seems to be just at some positions. I´m really confused how to specify a size, or am I totally wrong?

To the shaders:

I had some look at http://irrlicht.sourceforge.net/docu/example010.html but didn´t get an Idea how to do it. Maybe someone can help me.


Thanks a lot.

Greetings,


badday
sudi
Posts: 1686
Joined: Fri Aug 26, 2005 8:38 pm

Post by sudi »

ok i guess you want something like this.
this is with hard edges you wanna perform some smothing between the textures. and you probably wanna add lightning...

PS: you will need four textures for it to work.
water.png
grass.png
mud.png
stone.png

screenshot:
Image

Code: Select all

#include "irrlicht.h"
using namespace irr;

class MyShaderCallBack : public video::IShaderConstantSetCallBack
{
public:

        virtual void OnSetConstants(video::IMaterialRendererServices* services,
                        s32 userData)
        {
                video::IVideoDriver* driver = services->getVideoDriver();

                irr::s32 t[] = {0,1,2,3};

                services->setVertexShaderConstant("Texture0", (irr::f32*)&t[0], 1);
                services->setVertexShaderConstant("Texture1", (irr::f32*)&t[1], 1);
                services->setVertexShaderConstant("Texture2", (irr::f32*)&t[2], 1);
                services->setVertexShaderConstant("Texture3", (irr::f32*)&t[3], 1);

                irr::core::matrix4 mat = driver->getTransform(irr::video::ETS_WORLD);

                services->setVertexShaderConstant("WORLD", (irr::f32*)mat.pointer(), 16);
        }
};

irr::core::stringc vertexshader =   "varying vec4 pos;"
                                    "uniform mat4 WORLD;"
                                    "void main()"
                                    "{"
                                    "   gl_TexCoord[0] = gl_MultiTexCoord0;"
                                    "   pos = WORLD * gl_Vertex;"
                                    "   gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;"
                                    "}"
                                    "";

irr::core::stringc pixelshader =   "varying vec4 pos;"
                                    "uniform sampler2D Texture0;"
                                    "uniform sampler2D Texture1;"
                                    "uniform sampler2D Texture2;"
                                    "uniform sampler2D Texture3;"
                                    "void main()"
                                    "{"
                                    "   vec4 col0 = texture2D(Texture0, vec2(gl_TexCoord[0]));"
                                    "   vec4 col1 = texture2D(Texture1, vec2(gl_TexCoord[0]));"
                                    "   vec4 col2 = texture2D(Texture2, vec2(gl_TexCoord[0]));"
                                    "   vec4 col3 = texture2D(Texture3, vec2(gl_TexCoord[0]));"
                                    "   if (pos.y >= 0 && pos.y < 30)"
                                    "       gl_FragColor = col0;"
                                    "   else if (pos.y >= 30 && pos.y < 90)"
                                    "       gl_FragColor = col1;"
                                    "   else if (pos.y >= 90 && pos.y < 160)"
                                    "       gl_FragColor = col2;"
                                    "   else if (pos.y >= 160)"
                                    "       gl_FragColor = col3;"
                                    "}"
                                    "";

int main(void)
{
    irr::IrrlichtDevice* device = irr::createDevice(irr::video::EDT_OPENGL);

    irr::scene::ISceneManager* smgr = device->getSceneManager();

    irr::video::IVideoDriver* driver = device->getVideoDriver();

    irr::scene::ICameraSceneNode* cam = smgr->addCameraSceneNodeFPS();

    irr::scene::ITerrainSceneNode* terrain = smgr->addTerrainSceneNode("terrain-heightmap.bmp");

    irr::s32 Shader = driver->getGPUProgrammingServices()->addHighLevelShaderMaterial(
             vertexshader.c_str(), "main", irr::video::EVST_VS_5_0,
             pixelshader.c_str(), "main", irr::video::EPST_PS_5_0,
             new MyShaderCallBack,
             irr::video::EMT_SOLID,
             0);

    terrain->setMaterialType((irr::video::E_MATERIAL_TYPE)Shader);

    terrain->setMaterialTexture(0, driver->getTexture("water.png"));
    terrain->setMaterialTexture(1, driver->getTexture("grass.png"));
    terrain->setMaterialTexture(2, driver->getTexture("mud.png"));
    terrain->setMaterialTexture(3, driver->getTexture("stone.png"));

    terrain->setScale(irr::core::vector3df(5,1,5));

    printf("Low: %f\n", terrain->getTransformedBoundingBox().MinEdge.Y);
    printf("High: %f\n", terrain->getTransformedBoundingBox().MaxEdge.Y);

    while (device->run())
    {
        driver->beginScene();
        smgr->drawAll();
        driver->endScene();
    }
    device->drop();
    return 0;
}
Last edited by sudi on Sun Sep 05, 2010 5:31 pm, edited 1 time in total.
We're programmers. Programmers are, in their hearts, architects, and the first thing they want to do when they get to a site is to bulldoze the place flat and build something grand. We're not excited by renovation:tinkering,improving,planting flower beds.
badday
Posts: 102
Joined: Mon Aug 16, 2010 1:14 pm

Post by badday »

Thanks a lot! That was exactly what I was looking for.

There is just one problem: It says that the lowest point is 0.0, the highest one is 255.0. But the height map is used only for the two higest textures.
If I look at the hole thing from the site I can the the following:
2 layers of textures as "stripes" and over them the two higher textures with the height map applied.

Hint: The height map colour range goes from white to black.

I´d be thankful for any advice.

Greetings,

badday
Steel Style
Posts: 168
Joined: Sun Feb 04, 2007 3:30 pm
Location: France

Post by Steel Style »

I think you should change something here :

Code: Select all

services->setVertexShaderConstant("Texture0", (irr::f32*)&t[0], 1);
                services->setVertexShaderConstant("Texture1", (irr::f32*)&t[1], 1);
                services->setVertexShaderConstant("Texture2", (irr::f32*)&t[2], 1);
                services->setVertexShaderConstant("Texture3", (irr::f32*)&t[3], 1);
Also please submit a screenshot
badday
Posts: 102
Joined: Mon Aug 16, 2010 1:14 pm

Post by badday »

I didn´t find a difference with you posted code (?).

Here the screenshot:

Image

Uploaded with ImageShack.us[/img]
Steel Style
Posts: 168
Joined: Sun Feb 04, 2007 3:30 pm
Location: France

Post by Steel Style »

Sorry I would write "setPixelShaderConstant" instead of setVertexShaderConstant

Looking at you screen shot it seem that one row of edge is undee y=30 and the neighbour one is > 160. So the transition is faster and not smooth enough to remove this strip effect.

Try the heightmap on this webpage for example (http://newbiz.developpez.com/tutoriels/ ... ghtmap.png). And if you can add you heightmap also it's would be easier I think.
sudi
Posts: 1686
Joined: Fri Aug 26, 2005 8:38 pm

Post by sudi »

i know of the issues this was just an example how it can be done. and probably only works for my heightmap....
We're programmers. Programmers are, in their hearts, architects, and the first thing they want to do when they get to a site is to bulldoze the place flat and build something grand. We're not excited by renovation:tinkering,improving,planting flower beds.
badday
Posts: 102
Joined: Mon Aug 16, 2010 1:14 pm

Post by badday »

Well, there was no black in my height map, just grey and white, so this problem is solved now.

The other thing is the smooth transition. How could I achieve that?

Thanks anyway for your great help so far.


Greetings,

badday
slavik262
Posts: 753
Joined: Sun Nov 22, 2009 9:25 pm
Location: Wisconsin, USA

Post by slavik262 »

Steel Style wrote:I think you should change something here :

Code: Select all

services->setVertexShaderConstant("Texture0", (irr::f32*)&t[0], 1);
                services->setVertexShaderConstant("Texture1", (irr::f32*)&t[1], 1);
                services->setVertexShaderConstant("Texture2", (irr::f32*)&t[2], 1);
                services->setVertexShaderConstant("Texture3", (irr::f32*)&t[3], 1);
Also please submit a screenshot
If there's a way to specify that a variable should be in a particular register in GLSL (which I'm sure there is since it's doable in HLSL), you don't need to do this ever. The textures are automatically set to registers S0 through S7 (the texture registers). Just map your samplers to those registers.
Post Reply