Terrain Texture Splatting

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
trivtn
Posts: 132
Joined: Tue Jan 17, 2006 12:30 pm
Location: Viet Nam
Contact:

Post by trivtn »

Great ! I'll try to make a demo for this.
There's something is fantastic, there's nothing is absolute.
trivtn
Posts: 132
Joined: Tue Jan 17, 2006 12:30 pm
Location: Viet Nam
Contact:

Post by trivtn »

- I've made small demo for the first post ( thanks jarhead :D !)
- This is screenShot : Image
- This is my Demo :
http://www.4shared.com/file/140766249/e ... ng_DX.html
There's something is fantastic, there's nothing is absolute.
yamashi
Posts: 82
Joined: Sat Jan 03, 2009 4:53 am

Post by yamashi »

Thanks a bunch !
yamashi
Posts: 82
Joined: Sat Jan 03, 2009 4:53 am

Post by yamashi »

Btw did anyone find a way to have more than 3 textures ?
I tried the multipass technique but couldn't get it to work...
Thx
grunt
Posts: 96
Joined: Tue Aug 17, 2004 9:14 pm
Contact:

Post by grunt »

I just used the last example to do splatting. How can i edit the alpha map on the fly? I tried making an image using red green and blue for the different heights but that doesnt work. how can i edit the channels directly?
floxXx
Posts: 9
Joined: Tue Mar 16, 2010 9:30 am

Post by floxXx »

Hi everyone,

I'm new and have a problem using this code.

If I use the example made by trivtn with a heigtmap (ITerrainSceneNode) everything works fine.

But I don't wanna use a heigtmap. Actually I use a b3d file (IAnimatedMeshSceneNode)

But IAnimatedMeshSceneNode doesen't offer the method scaleTexture() to give it more detail.

Questions:
1 ) Can a b3d file be converted into an ITerrainSceneNode so that i can scale the texture? How?
2 ) If 1) is not possible, is IAnimatedMeshSceneNode the best solution to cast the b3d file?
3) How can I reach the goal with an IAnimatedMeshSceneNode so that the texture is scaled by factor 20.f as in this example to get more detail and not this fuzzy looking thing...

Any Code appreciated.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Just use the texture matrix of the texture. setTextureScale(20,20) should work
floxXx
Posts: 9
Joined: Tue Mar 16, 2010 9:30 am

Post by floxXx »

I think you mean something like this:?

Code: Select all


//load my Terrain
	IAnimatedMesh* levelMesh = (IAnimatedMesh*) smgr->getMesh("../Media/map/island.b3d");
	core::vector3df scaleFactor = core::vector3df(80,30,80);
	smgr->getMeshManipulator()->scaleMesh(levelMesh, scaleFactor);

	IAnimatedMeshSceneNode* level = (IAnimatedMeshSceneNode*) smgr->addAnimatedMeshSceneNode(levelMesh);
	level->setMaterialFlag(video::EMF_LIGHTING, false);
	level->setMaterialFlag(EMF_ANISOTROPIC_FILTER, true);
	level->setMaterialFlag(EMF_BILINEAR_FILTER, true);
	level->setMaterialFlag(EMF_TRILINEAR_FILTER, true);
	level->setMaterialFlag(EMF_ANTI_ALIASING, true);


irr::video::ITexture* grass = driver->getTexture("grass_1.jpg");
	level->setMaterialTexture(0,driver->getTexture("Sample.jpg"));
	level->setMaterialTexture(1,driver->getTexture("sandstone.jpg"));
	level->setMaterialTexture(2,grass);
	level->setMaterialTexture(3,driver->getTexture("SANDSHOR.JPG"));
	level->setMaterialType((video::E_MATERIAL_TYPE)newMaterialType);	
	

	level->getMaterial(0).getTextureMatrix(1).setTextureScale(20,20);
	level->getMaterial(0).getTextureMatrix(2).setTextureScale(20,20);
	level->getMaterial(0).getTextureMatrix(3).setTextureScale(20,20);
but it doesn't work
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Which driver and shader do you use? It's not necessarily propagated to all shader versions. Maybe check what happens when rendering with material detail_map. At least the second texture should repeat more often.
floxXx
Posts: 9
Joined: Tue Mar 16, 2010 9:30 am

Post by floxXx »

I use DirectX9.

Isn't it already rendered with video::EMT_DETAIL_MAP?

Here is the full code I use in this example

Code: Select all

#include <iostream>
#include <Irrlicht.h>

using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
using namespace std;

#ifdef _MSC_VER
#pragma comment(lib, "Irrlicht.lib")
#endif


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// SETTINGS /////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// setup key engine objects
//IrrlichtDevice* device = createDevice(EDT_OPENGL,core::dimension2d<u32>(800, 600),32,false,false,false);
//IVideoDriver* driver = device->getVideoDriver();
//ISceneManager* smgr = device->getSceneManager();
//IGUIEnvironment* guienv = device->getGUIEnvironment();
ICursorControl* CursorControl;


// keyboard registry
bool keys[irr::KEY_KEY_CODES_COUNT];
   





/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CLASS : MyEventReceiver //////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  


class MyEventReceiver : public IEventReceiver
{
public:


private:
	scene::ISceneNode* Terrain;
	scene::ISceneNode* Skybox;
	scene::ISceneNode* Skydome;
	bool showBox;
};

bool UseHighLevelShaders = true;
class MyShaderCallBack : public video::IShaderConstantSetCallBack
{
public:
        virtual void OnSetConstants(video::IMaterialRendererServices* services,
                        s32 userData)
        {
                video::IVideoDriver* driver = services->getVideoDriver();
                // set clip matrix
                core::matrix4 worldViewProj;
                worldViewProj = driver->getTransform(video::ETS_PROJECTION);
                worldViewProj *= driver->getTransform(video::ETS_VIEW);
                worldViewProj *= driver->getTransform(video::ETS_WORLD);
                if (UseHighLevelShaders)
                        services->setVertexShaderConstant("matViewProjection", worldViewProj.pointer(), 16);
                else
                        services->setVertexShaderConstant(worldViewProj.pointer(), 4, 4);
		}
};


scene::ICameraSceneNode* camera = 0; 

int main()
{
	IrrlichtDevice *device = createDevice(EDT_DIRECT3D9, dimension2d<u32>(640, 480), 32, false, true, false);

	if (device == 0)
		return 1; 

	video::IVideoDriver* driver = device->getVideoDriver();
	scene::ISceneManager* smgr = device->getSceneManager();
	gui::IGUIEnvironment* env = device->getGUIEnvironment();

	driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, true);

	// add camera
	scene::ICameraSceneNode* camera =
		smgr->addCameraSceneNodeFPS(0,100.0f,1.2f);
	camera->setPosition(core::vector3df(0,1230,0));
	camera->setTarget(core::vector3df(3000,100,0));
	camera->setFarValue(42000.0f);

	device->getCursorControl()->setVisible(false);
	smgr->getParameters()->setAttribute(scene::B3D_LOADER_IGNORE_MIPMAP_FLAG,true);
	driver->setTextureCreationFlag(ETCF_CREATE_MIP_MAPS,true);

	
	//load my Terrain
	IAnimatedMesh* levelMesh = (IAnimatedMesh*) smgr->getMesh("../Media/map/island.b3d");
	core::vector3df scaleFactor = core::vector3df(80,30,80);
	smgr->getMeshManipulator()->scaleMesh(levelMesh, scaleFactor);

	IAnimatedMeshSceneNode* level = (IAnimatedMeshSceneNode*) smgr->addAnimatedMeshSceneNode(levelMesh);
	
	level->setMaterialFlag(video::EMF_LIGHTING, false);
	level->setMaterialFlag(EMF_ANISOTROPIC_FILTER, true);
	level->setMaterialFlag(EMF_BILINEAR_FILTER, true);
	level->setMaterialFlag(EMF_TRILINEAR_FILTER, true);
	level->setMaterialFlag(EMF_ANTI_ALIASING, true);
	

	//// create light

	ISceneNode* node = smgr->addLightSceneNode(0, core::vector3df(300,300,1000),
		video::SColorf(1.0f, 0.6f, 0.7f, 1.0f), 6000.0f);
	scene::ISceneNodeAnimator* animlight = 0;
	animlight = smgr->createFlyCircleAnimator (core::vector3df(4560,2000,1060),1250.0f);
	node->addAnimator(animlight);
	animlight->drop();


	//// attach billboard to light

	node = smgr->addBillboardSceneNode(node, core::dimension2d<f32>(250, 250));
	node->setMaterialFlag(video::EMF_LIGHTING, false);
	node->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR);
	node->setMaterialTexture(0, driver->getTexture("../../../media/particlewhite.bmp"));



	// create skybox and skydome
    driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false);
       scene::ISceneNode* skydome=smgr->addSkyDomeSceneNode(driver->getTexture("../../../media/skydome.jpg"),16,8,0.95f,2.0f);
     driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, true);
	

	// create event receiver
	 io::path vsFileName = "Dx_Shader.hlsl";
	 io::path psFileName = "Dx_Shader.hlsl";
	 if (!driver->queryFeature(video::EVDF_PIXEL_SHADER_2_0))
	 {
                device->getLogger()->log("WARNING: Pixel shaders disabled "\
                        "because of missing driver/hardware support.");
                psFileName = "";
        }

        if (!driver->queryFeature(video::EVDF_VERTEX_SHADER_2_0))
        {
                device->getLogger()->log("WARNING: Vertex shaders disabled "\
                        "because of missing driver/hardware support.");
                vsFileName = "";
        }
	// create materials

    video::IGPUProgrammingServices* gpu = driver->getGPUProgrammingServices();
    s32 newMaterialType = 0;        
    if (gpu)
    {
            MyShaderCallBack* mc = new MyShaderCallBack();
            // create the shaders depending on if the user wanted high level
            // or low level shaders:
            if (UseHighLevelShaders)
            {
                    // create material from high level shaders (hlsl or glsl)
                    newMaterialType = gpu->addHighLevelShaderMaterialFromFiles(
                            vsFileName, "vs_main", video::EVST_VS_2_0,
                            psFileName, "ps_main", video::EPST_PS_2_0,
							mc, video::EMT_DETAIL_MAP);                        
            }                
            mc->drop();
    }
	

	irr::video::ITexture* grass = driver->getTexture("grass_1.jpg");
	level->setMaterialTexture(0,driver->getTexture("Sample.jpg"));
	level->setMaterialTexture(1,driver->getTexture("sandstone.jpg"));
	level->setMaterialTexture(2,grass);
	level->setMaterialTexture(3,driver->getTexture("SANDSHOR.JPG"));
	level->setMaterialType((video::E_MATERIAL_TYPE)newMaterialType);	
	
	
	level->getMaterial(0).getTextureMatrix(1).setTextureScale(20,20);
	level->getMaterial(0).getTextureMatrix(2).setTextureScale(20,20);
	level->getMaterial(0).getTextureMatrix(3).setTextureScale(20,20);
	level->getMaterial(0).getTextureMatrix(0).setTextureScale(20,20);
	level->getMaterial(1).getTextureMatrix(0).setTextureScale(20,20);
	level->getMaterial(1).getTextureMatrix(1).setTextureScale(20,20);
	level->getMaterial(1).getTextureMatrix(2).setTextureScale(20,20);
	level->getMaterial(1).getTextureMatrix(3).setTextureScale(20,20);


	int lastFPS = -1;

	while(device->run())
	if (device->isWindowActive())
	{
		driver->beginScene(true, true, 0 );

		smgr->drawAll();

		driver->endScene();

		// display frames per second in window title
		int fps = driver->getFPS();
		if (lastFPS != fps)
		{
			core::stringw str = L"Terrain Renderer - Irrlicht Engine [";
			str += driver->getName();
			str += "] FPS:";
			str += fps;

			device->setWindowCaption(str.c_str());
			lastFPS = fps;
		}
	}

	device->drop();
	
	return 0;
}

hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Well, obviously not. You do use your own shader based material, which will be used throughout the rendering. If you set the MaterialType to EMT_DETAIL_MAP instead, it would use the fixed function detail map material.
The thing is, that certain things have to be done manually in shaders. IIRC, for Direct3D this applies to texture matrices. But I'm not that familiar with HLSL, so let's hope someone with more knowledge in this area will chime in. Or just search on your own for this topic. I guess there's also code on the net how to get access to the matrices (maybe you have to pass them via uniforms) and multiply the texture values by the matrix.
floxXx
Posts: 9
Joined: Tue Mar 16, 2010 9:30 am

Post by floxXx »

Three additional questions:

1) Is there really no way to cast the b3d file to ITerrainSceneNode?

2) If I change the driver to OpelGL the whole map is dark as there is no light. But in my code i defined a light.

3) How to implement the material render type with the detail_map you mentioned.


Sry I'm new to this.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

No

HLSL does not work for OpenGL

Simply do it as shown in example 12
grunt
Posts: 96
Joined: Tue Aug 17, 2004 9:14 pm
Contact:

Post by grunt »

ok. I got what i want done working good. I also followed tvtn's demo. What if the alpha map changes. How can i make the terrain textures update to reflect the new alpha map.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Simply change the texture, or update it. Doesn't that work?
Post Reply