Multitex Terrain + Normalmapping

Posted By: fogman

Multitex Terrain + Normalmapping - 03/02/11 11:59

HeelX was so kind to do some shaderwork for me.
I want to spend this shader as open source to the community.
Something like this has been requested many times.




Download source & example, only 1,3 MB:
http://www.vulkanware.de/stuff/Terrainshader.zip

-Three textures + Lightmap
-Up to three lights (sun + two dynlights)
-Fog is supported
-Colormask compatible to mtl_terraintex3
-Every texture got their own normalmap
-Works for models and terrain
-Use it for noncommercial or commercial projects, no credits required.

Just don´t claim that you´ve written it and don´t sell it directly. You are free to include it as asset in a project.

If you´ve any doubts, ask HeelX directly. He is the author.
I´ve got only the rights to use and spread it.


Posted By: paracharlie

Re: Multitex Terrain + Normalmapping - 03/03/11 03:01

I have been looking for something like this for a long time. Thank you, thank you...
Posted By: tzw

Re: Multitex Terrain Normalmapping - 03/03/11 05:54

thx it's very useful to my game.
Posted By: Pappenheimer

Re: Multitex Terrain Normalmapping - 03/03/11 09:18

Yes, this is a very generous contribution!
Thanks to HeelX, as well, for this great work!
Posted By: 3run

Re: Multitex Terrain Normalmapping - 03/03/11 14:30

Will this work free version.
Posted By: xxxxxxx

Re: Multitex Terrain Normalmapping - 03/03/11 16:53

how to draw the multitexture map? Sorry i never used any multitextur-terrain before
xxxxxxx
Posted By: Widi

Re: Multitex Terrain Normalmapping - 03/03/11 19:20

@7x:
Du findest im Ordner "earth2" eine Bilddatei mit dem Namen "earth2_mask.dds". Die kannst du mit einem Mahlprogramm (z.B Paint.Net) öffnen. Nun siehst du so eine farbige Fläche. Diese Farben (r,g,b) werden nun vom Shader ausgewertet. Es gibt 3 Detailmaps in diesem Shader: earth2_grass, earth2_rock und earth2_sand. Diese werden nun gekachelt und abhängig von der Blendmask "earth2_mask.dds" auf das Terrain aufgetragen. Blau = grass, Grün = sand und Rot = rock. Je stärker eine Farbe ist, desto besser ist die jeweilige Detailmap sichtbar.

Wieso wird das so gemacht?
Wenn man eine normale Skin auf ein Terrain setzen wollte, müsste diese Skin riesig sein, um einigermassen gut auszusehen. Bei einer normalen Skin würde ein Pixel im Game schnell mal 1 * 1 cm gross sein und dementsprechend schlecht wäre die Auflösung des Terrains. Deshalb arbeitet man mit Blendmask, über die eine viel höher aufgelöste Detailmap gekachelt auf das Terrain aufgetragen wird.

Male mal mit rot,grün und blau auf der "earth2_mask.dds" herum, dann siest du die Aenderungen.
Posted By: xxxxxxx

Re: Multitex Terrain Normalmapping - 03/03/11 19:36

Danke Widi, ich hatte nur nicht verstanden welche farbe für was zuständig ist, aber jetzt ist alles klar laugh
Also wenn ich das jetzt richtig verstehe hat der unterstützt dieser shader nur 3 texturen + normalmap! ich brauche leider 5-8 texturen( + normalmap) frown
gibt es da noch was anderes an multiterrain shadern(außer den standart 3dgs shader meine irgend gehört zu haben das der (zu) langsam sei oder sowas) oder kann man den shader erweitern?
xxxxxxx
Posted By: HeelX

Re: Multitex Terrain Normalmapping - 03/03/11 20:01

You can access through material- and entity skins a total of 8 textures. Using one texture as mask this means that you have access to a total of 7 texture á 4 channels => 28 monochrome texture maps which can be divided into 5 pairs of RGB textures and 5 XY normal maps (for texture, the z-component can be restored easily through arithmetics). This means, assuming you use it on terrains and / or entities, you can have a multitexture normalmapping shader with 5 texture + normalmaps max!

Since you have access to static bitmaps and if you are only using ONE terrain at a time with this shader, you can, though, use unlimited texture/normalmaps, of course, if you use then static bitmap references.

Nevertheless, there more texture/normalmaps you use, the longer calculations are to be taken into account. Are you sure that you need 5-8 textures? Can't you break your environment into pieces and use textures only where they belong?
Posted By: xxxxxxx

Re: Multitex Terrain Normalmapping - 03/03/11 20:26

The problem is: i have villige! the streets must shoult look like this:

and their will be gardens, forest and rivers too so i need much textures!
im so sorry for my englich!
HeelX i'm not able to write shaders but i think i understand what you mean i'll try tomorrow to split my terrains into parts(street and landscape)!
xxxxxxx
Posted By: HeelX

Re: Multitex Terrain Normalmapping - 03/03/11 21:09

Why don't you use then models with tiling textures for your streets?
Posted By: xxxxxxx

Re: Multitex Terrain Normalmapping - 03/03/11 21:32

i used blocks before... i think two terrains are faster then ??? models!
xxxxxxx
Posted By: xxxxxxx

Re: Multitex Terrain Normalmapping - 03/06/11 21:01

ahh... the shader splitt my terrain into parts! what's wrong?

just ignore the flying tree's grin
i asked heelX
xxxxxxx
Posted By: HeelX

Re: Multitex Terrain Normalmapping - 03/07/11 15:45

I never tried it with chunked terrain - is the regular terraintex3 shader from the Gamestudio library causing the same artifacts?
Posted By: xxxxxxx

Re: Multitex Terrain Normalmapping - 03/07/11 17:11

i havent got the same with the mtl_terraintex3 shader, but it doesn't looking nice witout normalmap!
xxxxxxx
Posted By: mireazma

Re: Multitex Terrain Normalmapping - 04/30/11 11:16

I think this is a kind of a milestone in 3DGS.
Excuse me but I don't follow: 5*3 (textures) + 5*2 (normal maps) = 25. What about the remaining 3 channels? Are they used for light mapping? Or you can use them as you like, including nothing?
As for optimization:
1. I'd only use normal mapping with some textures (small ones, if I understand correctly from HeelX that the most intensive texture "processing" is done per texel).
2. I'm saying this because I use differently sized textures for each terrain type. For grass, for example, which I think it has to be more crispy, I use a larger size, small scaling or both. And I spend a lot of time weighting the appearance/sizes balance.
3. Now it's unclear for me whether the whole terrain gets rendered (texture-wise), even if the camera only sees a corner, or it's clip space optimized (I have to dwell on the pipelines study). Cause if it were optimized, I'd consider (a little) more processing friendly to use smaller scaled textures than upscaled ones at the same texture size.
Posted By: HeelX

Re: Multitex Terrain Normalmapping - 04/30/11 11:34

Hi, I have some problems understanding your concerns. Lets try it:

Quote:
Excuse me but I don't follow: 5*3 (textures) + 5*2 (normal maps) = 25. What about the remaining 3 channels? Are they used for light mapping? Or you can use them as you like, including nothing?


You can use three textures plus their respective normal maps. The first texture is tiled over the terrain as base texture, the following two are blended, according to the weights stored in the red- and green-channel of the blendmap. The blue-channel of the blendmap stores a lightmap for the terrain.

As you can see when you open one of the samples files in MED, the order of the skins have to be:

- blendmap (or "mask")
- base texture
- texture 1
- texture 2
- base normal map
- texture 1 normal map
- texture 2 normal map

If you need even more textures, this can get quite complicated, so, it would be nice to know if you need four, five or fortyfive textures wink

Quote:
I'd only use normal mapping with some textures


This could save performance, if you would know before, which textures have no normal map. So, if it is only texture 1 or only the base texture or so, this could be hardcoded and could save performance. Checking that dynamically could work, too, but I am pretty sure that the additional conditional texture samples would cause aan additional performance loss.

Quote:
Now it's unclear for me whether the whole terrain gets rendered (texture-wise), even if the camera only sees a corner, or it's clip space optimized


If the terrain is not seen at all because it is outside the view frustrum, it is likely that it is not rendered at all, which saves performance - but since terrains are always super large objects I can not imagine any real life scenario in which that could happen. Luckily, the shader is fired only for all pixels which are going to be rendered on the screen. So, if it as big a 10² pixel, it will consume less performance, than if it would cover the whole screen smile but don't be afraid, these shaders are really quick.

Quote:
I'd consider (a little) more processing friendly to use smaller scaled textures than upscaled ones at the same texture size.


Smaller texture sizes do not affect immediately the time which is consumed to render an object. But it is related to the time which is needed per frame to push all data to the GPU so that it can actually process it. So, it is not so very clever if each texture in your game is about as big as 1024² pixel. If you use e.g. only 512² pixel textures, you reduce the bandwidth needed for transferring by a factor of 75%.
Posted By: mireazma

Re: Multitex Terrain Normalmapping - 04/30/11 20:02

Thank you for showing the interest to lend a hand. I assure you that if I didn't feel this urge to know what I have in my hands, I wouldn't insist. I know I could make a fool out of myself but I don't care.
I'll probably never need more than what this shader demonstrates in the example but it's just I'd like to fully understand it's possibilities, that's why I'm asking things grin. So,
Quote:
[...] This means, assuming you use it on terrains and / or entities, you can have a multitexture normalmapping shader with 5 texture + normalmaps max!

And you said something about a total of 28 monochrome channels, if alpha channels are considered.
The example and what you just said implies 3 textures with 3 normal maps.
I'm surely missing something here confused
Posted By: HeelX

Re: Multitex Terrain Normalmapping - 04/30/11 22:13

Of course you could code the R, G and B channel in the three alpha-channels of textures 1,2 and 3 - but this would require you to have all textures the same size. The same with the additional normal map. You could then code e.g. the blendmap of the new texture/normalmap in the blue channel and put the lightmap in the alpha-channel.

So, this way you could have a multitexture shader for four textures, but this requires you also to encode 4 RGB textures into 3 RGBA textures and 4 XYZ normal maps into 3 RGBA textures storing the normals. You could write a small application for that or do it by hand.

Do you need 4 textures or do you need more?

If you need exactly 4, I could consider modifying the shader to fit this requirement easily.

Best regards,
-Christian
Posted By: mireazma

Re: Multitex Terrain Normalmapping - 05/01/11 00:39

Thank you again so much. I'll remember the procedure you mentioned and I want to try to modify it myself for a little endorphin blush
I read the copyright so I'm allowed to modify and use it cool It took like a quarter of hour to figure out where in the fxModelTex3Nm.fx should I probably tamper and hopefully all I'll have to do is to play with some of entSkin<n> and smp<name>.
I don't know if I'll have to mess with .c or .h I went straight to .fx since I remember the file extension from the shader tutorial. After fully digesting the tutorial I'll make the attempt.

Anyway, at least for the time being I don't need that many textures as I'm very stingy with the resources. It is more of a matter of principle. Like having a 200 MpH car but you only drive with 100 max laugh
Posted By: HeelX

Re: Multitex Terrain Normalmapping - 05/01/11 12:58

You can have only 4 entity skins and 4 material skins available in a shader. Since your problem concerns only terrains, you could access the blendmap over a static bitmap (every BMAP* can be access in a shader, if the name is known, e.g. BMAP* myBitmap; is accessible in a shader via texture myBitmap_bmap;), so you could use 4 entity skins for the textures and 4 material skins for the normal maps. Since each texture has 4 channels, you have virtually (4+4)*4 = 32 channels, which would allow 6 RGB textures with their respective normal map in XY format (Z component can be restored). A special application is therefore needed to encode these 6 textures + 6 normal maps into a total of 8 RGBA images.

An alternative would be use -only- static bitmaps like

Code:
BMAP *terrainTexBase, *terrainTexBaseNm;
BMAP *terrainTex1, *terrainTex1Nm;
BMAP *terrainTex2, *terrainTex2Nm;
BMAP *terrainTex3, *terrainTex3Nm;
BMAP *terrainTex4, *terrainTex4Nm;
BMAP *terrainTex5, *terrainTex5Nm;
BMAP *terrainTex6, *terrainTex6Nm;
...



But this requires a manually loading of textures into those bitmaps.

To modify the terrain shader posted above to use 4 instead of 3 textures, while the channels are stored in base, red and green textures, you have to compose the blueColor by their alpha values:

Code:
float4 blueColor = float4(baseColor.a, redColor.a, greenColor.a, 0);



Exactly the same procedure for the normal.

Then you have to adjust the lerp's, so that you use ONLY the .rgb components of the colors and normals, so that you DON'T accidently mix something strange by using the alpha value of the colors which store a channel of the blue color / normal.

The lightmap is stored currently in the blue channel of the blendmap, you would then have to adjust it to the alpha channel then:

Code:
float  shadow = mask.a;



and, of course, use the blue channel value as weight for the color/normal of the blue texture.
Posted By: mireazma

Re: Multitex Terrain Normalmapping - 05/01/11 16:07

Well, it looks too entangled for me at the first sight but I saved the web page for offline analysis and made it a priority task.
Quote:
A special application is therefore needed to encode these 6 textures + 6 normal maps into a total of 8 RGBA images.

You mean like Photoshop?

About the static bitmaps approach:
What would the downside of using this be (besides manual loading)? slow performance?
And this sounds like the dumbest conclusion I could draw: it would allow virtually unlimited no. of textures, right?

And I almost forgot: tell me if there's a way to use this shader as it is now, with parallax or displacement? As a matter of fact, I got here starting precisely with the terrain parallax or displacement in mind. Please.
Posted By: HeelX

Re: Multitex Terrain Normalmapping - 05/01/11 20:08

This shader only allows normalmapping, parallax/displacement mapping is not supported. And Yes, theoretically, you could have unlimited textures for such a terrain shader.

I didn't meant Photoshop, though, you can do this by hand with it, too. An application I had in mind just takes in the filenames of 4 textures and their corresponding normalmaps -- and ensembles the encoded RGBA images. Like a console application or so. This way, you can simply press a button - and voila! - you have it.
Posted By: mireazma

Re: Multitex Terrain Normalmapping - 05/03/11 14:15

Thanks again.
Posted By: djfeeler

Re: Multitex Terrain Normalmapping - 06/02/11 21:29

The link est dead. could you re upload please ?
Posted By: fogman

Re: Multitex Terrain Normalmapping - 06/03/11 07:39

Done, sorry for the delay.
http://www.vulkanware.de/stuff/Terrainshader.zip


Posted By: djfeeler

Re: Multitex Terrain Normalmapping - 06/03/11 09:09

Thanks
Posted By: Anonymous

Re: Multitex Terrain Normalmapping - 07/13/11 22:59

When using this shader the terrain gets heavy fog. How do I stop that or at least less it?


EDIT* Found it by reading a German post(Thanks Google).

You have to comment out this line in the shader
//color = lerp(color, fogColor, fogDensity);
Posted By: PadMalcom

Re: Multitex Terrain Normalmapping - 05/21/12 08:18

Is there a way to turn the fog off? Even if I have no fog enabled I see a white dust everywhere.
Posted By: 3run

Re: Multitex Terrain Normalmapping - 05/21/12 15:20

You are doing something probably wrong, cause it works great without fog:

Some kind of workaround, I just edited three lines in main function:
Code:
fog_color = 4;
camera.fog_start = 0;
camera.fog_end   = 50000;



Posted By: Rei_Ayanami

Re: Multitex Terrain Normalmapping - 05/21/12 16:14

That does not turn off fog...
Posted By: 3run

Re: Multitex Terrain Normalmapping - 05/21/12 16:44

Am I saying that I've turned fog off? I've just set fog_far to default clip_far value. So thats some kind of workaround.
Posted By: thorus

Re: Multitex Terrain Normalmapping - 12/22/12 17:47

hey guys how can i scale the texture ? couse i wanna have every tile smaller for better graphic, i hope u know what i mean, i mean i need the scale of the pictures.. thanks
Posted By: PadMalcom

Re: Multitex Terrain Normalmapping - 08/09/13 09:45

I tried to use the shader that way:
Code:
ENTITY* entTerrain = ent_create("dummy.hmp", nullvector, NULL);
	
	BMAP* bmapMask = bmap_create("test_proc_terrain\\earth2_mask.dds");
	BMAP* bmapGrass = bmap_create("test_proc_terrain\\earth2_grass.dds");
	BMAP* bmapRock = bmap_create("test_proc_terrain\\earth2_rock.dds");
	BMAP* bmapSand = bmap_create("test_proc_terrain\\earth2_sand.dds");
	BMAP* bmapGrassNM = bmap_create("test_proc_terrain\\earth2_grass_nm.dds");
	BMAP* bmapRockNM = bmap_create("test_proc_terrain\\earth2_rock_nm.dds");
	BMAP* bmapSandNM = bmap_create("test_proc_terrain\\earth2_sand_nm.dds");
	
	ent_setskin(entTerrain, bmapMask, 1);
	ent_setskin(entTerrain, bmapGrass, 2);
	ent_setskin(entTerrain, bmapRock, 3);
	ent_setskin(entTerrain, bmapSand, 4);
	ent_setskin(entTerrain, bmapGrassNM, 5);
	ent_setskin(entTerrain, bmapRockNM, 6);
	ent_setskin(entTerrain, bmapSandNM, 7);		
	
	// Enable HeelX terrain shader
	init_modelTex3Nm(entTerrain);


But my terrain remains white. Any idea why? The skins use exactly the same images as the demo.
Posted By: HeelX

Re: Multitex Terrain Normalmapping - 08/09/13 20:07

Originally Posted By: PadMalcom
Is there a way to turn the fog off? Even if I have no fog enabled I see a white dust everywhere.


I just learned some time ago that vecFogColor.w carries a 0 or 1 if fog is enabled/disabled. So if you write instead:

Code:
Out.TexFog.z  = vecFogColor.w * (1 - saturate((vecFog.y - Out.Pos.z) * vecFog.z));



it should work.

Originally Posted By: thorus
hey guys how can i scale the texture ?


Use the function set_modelTex3Nm_tiling.

Originally Posted By: PadMalcom
I tried to use the shader that way (...) but my terrain remains white. Any idea why? The skins use exactly the same images as the demo.


The shader expects:

Quote:
entSkin1 = mask
entSkin2 = base texture
entSkin3 = texture 1, controlled by mask red channel
entSkin4 = texture 2, controlled by mask green channel

mtlSkin2 = base normalmap
mtlSkin3 = texture 1 normalmap
mtlSkin4 = texture 2 normalmap


whereas the blue channel of the mask in entSkin1 carries the shadowmap.

As can be seen in the .c file of the shader, mtlSkins 2, 3 and 4 are fetched automatically from entSkin 5-7:

Code:
e->material->skin2 = bmap_for_entity(e, 5);
e->material->skin3 = bmap_for_entity(e, 6);
e->material->skin4 = bmap_for_entity(e, 7);



That way you can just put all your textures, mask and normalmaps into the terrain entity file and you are done.

So, the way you are putting stuff into the terrain entity looks right. Maybe try bmap_to_mipmap(BMAP*) for each bitmap. Maybe the function bmap_for_entity fails somehow, try to replace the calls in init_modelTex3Nm with ent_getskin (don't forget the +1 shift on the index between bmap_for_entity and ent_getskin).

Please tell me if it still doesn't work. - As soon as the contest is over and I can return to my private project, I will also begin to write a new terrain shader, if you are looking forward for something fresh wink
Posted By: NeoNeper

Re: Multitex Terrain Normalmapping - 11/13/13 01:46

unearthing this topic!
Please could someone give me a hand.

I started using this shader in my terrain, but I can not add more than 3 lights dynamically in my game.
If I exceed this number, additional lights has no effect and sunlight to.

In an excerpt from the script I spotted the following:
Code:
float4 Pos		 : POSITION;
		float4 Color	 : COLOR0;
		float3 TexFog   : TEXCOORD0;
		float3 PosView  : TEXCOORD1;
		float3 Light1   : TEXCOORD2;
		float3 Light2   : TEXCOORD3;
		float3 Light3   : TEXCOORD4;
		float3 Diffuse1 : TEXCOORD5;
		float3 Diffuse2 : TEXCOORD6;
		float3 Diffuse3 : TEXCOORD7;


Intuitively I tried to add another TEXCOORDs for add more LIGHT, but no work.
It seems to me that I can not exceed this value [7], unfortunately I do not understand about shaders.

That the way I could use for more lights in my game using this shader?

Posted By: NeoNeper

Re: Multitex Terrain Normalmapping - 11/13/13 12:27

AnyBody?
Posted By: sivan

Re: Multitex Terrain Normalmapping - 11/13/13 12:39

hi,

the passable parameters are limited to (as I know) TEXCOORD0-7, COLOR0-3 (not sure), and FOG (this depends on shader model used). maybe you could combine somehow the lights in the vertex shader into the 3 parameters you are passing.

a while ago I made a terrain multitex shader handling tile normalmaps (based on the shade-c terrain shader), but it was slow for my purposes. maybe I can add this feature to my current terrain shaders in future...
Posted By: NeoNeper

Re: Multitex Terrain Normalmapping - 11/13/13 18:01

Quote:

the passable parameters are limited to (as I know) TEXCOORD0-7, COLOR0-3 (not sure), and FOG (this depends on shader model used). maybe you could combine somehow the lights in the vertex shader into the 3 parameters you are passing.


Thanks for the reply Sivan!
I do not understand shaders. Don't even know where I can start.

You know let me know if there is any more Multitexture Shader terrain that support more lights?
Posted By: sivan

Re: Multitex Terrain Normalmapping - 11/13/13 19:06

if you download my editor, or this demo: http://www.opserver.de/ubb7/ubbthreads.php?ubb=showflat&Number=430852#Post430852 , you can get some terrain shaders. they utilize vertex or pixel lights, switchable by commenting/uncommenting a #define line. in next update I will provide shader model 3.0 terrain shaders, having more instructions available, so they can work with 8 lights (maybe the shadowmapping demo already features it, I don't remember). but they lack normalmapping.
Posted By: NeoNeper

Re: Multitex Terrain Normalmapping - 11/13/13 21:27

and the mystyMood?
I tested to verify operation. This working fine in version A8.
Tests with multiple lights in the scene, and as far as I've seen, seems to work correctly. Only Shadows are in trouble. They are static and do not movimental with sunlight.


MystyMood could be an option? Or this very old and should no longer be used?
Posted By: sivan

Re: Multitex Terrain Normalmapping - 11/14/13 09:51

I think Mystimoods is limited in tile texture quantity.

-------------------------------------------------------
My terrain shaders use:
a base colormap (24bit)
max. 7 tiled textures (32b, blending on alpha)
a static lightmap.

the base colormap is used by water mirror view, and to decrease repetitivness of tiled textures, and its blending strength can be adjusted. if no lightmap, no problem, there are 2 pixel shaders to handle it automatically. if less tiled textures are set, no problem too, it works fine.
Posted By: Dooley

Re: Multitex Terrain Normalmapping - 02/08/16 07:30

Does anyone still have this shader? It seem the links are broken...
Posted By: sivan

Re: Multitex Terrain Normalmapping - 02/08/16 08:00

yeah, it is still on my C:\, I can upload the full package, but here is the terrain related stuff.
moreover I can make easily a new MapBuilder update with a terrain multitexturing shader with normal and specular map support, if there is a request from the crowd of this community...

terrain_materials.c
Code:
///////////////////////////////////////////////////////////////////////////////////////////////////
////MystyMood terrain materias. Just to keep the terrain_template more tidy!
////
////Jun 07 by www.loopix-project.com
////Nov 07 Lite-C conversion by Alexis Rozhkov aka Shadow
///////////////////////////////////////////////////////////////////////////////////////////////////

////bitmaps for terrain 1
BMAP* terr_blendtex_red_1 = "terr_red_1.bmp";
BMAP* terr_blendtex_green_1 = "terr_green_1.bmp";
BMAP* terr_blendtex_blue_1 = "terr_blue_1.bmp";
BMAP* terr_blendtex_black_1 = "terr_black_1.bmp";
BMAP* terr_colormap_1 = "terr_colormap_1.bmp";
BMAP* terr_detailmap_1 = "terr_detailmap_1.bmp";
BMAP* terr_shadowmap_1 = "terr_shadowmap_1.tga";

////bitmaps for terrain 2
//bmap terr_blendtex_red_2 = "terr_red_2.bmp";
//bmap terr_blendtex_green_2 = "terr_green_2.bmp";
//bmap terr_blendtex_blue_2 = "terr_blue_2.bmp";
//bmap terr_blendtex_black_2 = "terr_black_2.bmp";
//bmap terr_colormap_2 = "terr_colormap_2.bmp";
//bmap terr_detailmap_2 = "terr_detailmap_2.bmp";
//bmap terr_shadowmap_2 = "terr_shadowmap_2.tga";

////bitmaps for terrain 3
//bmap terr_blendtex_red_3 = "terr_red_3.bmp";
//bmap terr_blendtex_green_3 = "terr_green_3.bmp";
//bmap terr_blendtex_blue_3 = "terr_blue_3.bmp";
//bmap terr_blendtex_black_3 = "terr_black_3.bmp";
//bmap terr_colormap_3 = "terr_colormap_3.bmp";
//bmap terr_detailmap_3 = "terr_detailmap_3.bmp";
//bmap terr_shadowmap_3 = "terr_shadowmap_3.tga";

////bitmaps for terrain 4
//bmap terr_blendtex_red_4 = "terr_red_4.bmp";
//bmap terr_blendtex_green_4 = "terr_green_4.bmp";
//bmap terr_blendtex_blue_4 = "terr_blue_4.bmp";
//bmap terr_blendtex_black_4 = "terr_black_4.bmp";
//bmap terr_colormap_4 = "terr_colormap_4.bmp";
//bmap terr_detailmap_4 = "terr_detailmap_4.bmp";
//bmap terr_shadowmap_4 = "terr_shadowmap_4.tga";


//add more bitmap-sets for more terrains...


//prototype functions
function mat_terr_hlsl_refl_event();
//function mat_terr_hlsl_no_caust_refl_event();
function init_mat_terr_hlsl();
function init_mat_terr_ffe();


//HLSL MATERIALS FOR TERRAINS
MATERIAL* mat_terr_hlsl_1 =
{

	flags = tangent;
	
	skin1 = terr_blendtex_red_1;
	skin2 = terr_blendtex_green_1;
	skin3 = terr_blendtex_blue_1;
	skin4 = terr_blendtex_black_1;

	event=init_mat_terr_hlsl;
	
	effect
	"
	/////////////////////////////////////////////////////////////////////////////////////////////
	// Define your needed values
	float4x4 matWorldViewProj;	 
	float4x4 matWorld;	
	float4x4 matWorldInv;	
	float4x4 matWorldView;
	
	float4 mtlSkill1;
	float4 mtlSkill2;
	
	float4 vecSkill41;
	
	
	float4 vecSunDir;
	float4 vecFog;
	float4 vecLight;
	
	float4 vecLightPos[8];	 // preset this with light positions (xyz) and ranges (w)
	float4 vecLightColor[8]; // preset this with light colors
	float3 vecFalloff = float3(0.f, 0.f, 1.5f);
	float4 vecSunDiffuse = {1.0f, 1.0f, 0.8f, 1.0f};

	float sunStrength = 0.3f;
	float dynalightStrength = 10;

	// Define your textures
	texture mtlSkin1;					
	texture mtlSkin2;					
	texture mtlSkin3;
	texture mtlSkin4;
	
	texture entSkin1;
	texture entSkin2;	
	texture entSkin3;					
	texture entSkin4;
	
	/////////////////////////////////////////////////////////////////////////////////////////////
	// Texture settings
	
	
	sampler sTex1 = sampler_state			
	{
		Texture = <entSkin1>;   // rgb-blendmap
		MipFilter = Linear;
		MinFilter = Linear;
		MagFilter = Linear;
		AddressU = Wrap;	
		AddressV = Wrap;
	};
	sampler sTex2 = sampler_state			
	{
		Texture = <entSkin2>;   // shadowmap
		MipFilter = Linear;
		MinFilter = Linear;
		MagFilter = Linear;
		AddressU = Wrap;	
		AddressV = Wrap;
	};
	sampler sTex3 = sampler_state			
	{
		Texture = <entSkin3>;	// causticsA
		MipFilter = Linear;
		MinFilter = Linear;
		MagFilter = Linear;
		AddressU = Wrap;	
		AddressV = Wrap;
	};
	sampler sTex4= sampler_state			
	{
		Texture = <entSkin4>;	// causticsB
		MipFilter = Linear;
		MinFilter = Linear;
		MagFilter = Linear;
		AddressU = Wrap;	
		AddressV = Wrap;
	};
	

	sampler sTex5 = sampler_state			
	{
		Texture = <mtlSkin1>;	// red
		MipFilter = Linear;
		MinFilter = Linear;
		MagFilter = Linear;
		AddressU = Wrap;	
		AddressV = Wrap;
	};
	sampler sTex6 = sampler_state			
	{
		Texture = <mtlSkin2>;	// green
		MipFilter = Linear;
		MinFilter = Linear;
		MagFilter = Linear;
		AddressU = Wrap;	
		AddressV = Wrap;
	};
	sampler sTex7 = sampler_state			
	{
		Texture = <mtlSkin3>;	// blue
		MipFilter = Linear;
		MinFilter = Linear;
		MagFilter = Linear;
		AddressU = Wrap;	
		AddressV = Wrap;
	};
	sampler sTex8 = sampler_state			
	{
		Texture = <mtlSkin4>;	// black
		MipFilter = Linear;
		MinFilter = Linear;
		MagFilter = Linear;
		AddressU = Wrap;	
		AddressV = Wrap;
	};
	
	//////////////////////////////////////////////////////////////////////
	// return the sun light on the surface
	float4 DoSunLight(float3 N)
	{
		// modulate the sunlight by the surface angle
		return vecSunDiffuse * dot(N,-vecSunDir);
	}

	// return the dynamic light on the surface
	float4 DoPointLight(float3 P, float3 N, int i)
	{
		// calculate the light ray pointing from the light to the surface
		float3 D = vecLightPos[i].xyz - P;
		// calculate the angle between surface and light ray
		float NdotL = dot(N, normalize(D));
		// modulate the light by the surface angle
		float4 Color = vecLightColor[i] * NdotL;

		// calculate the light attenuation factor, DX uses a really strange formula here
		float fac = 0.f;
		if (NdotL >= 0.f && vecLightPos[i].w > 0.f)
		{
			// get the distance factor
			float LD = length(D)/vecLightPos[i].w;
			#ifdef DXLIGHTING
				if (LD < 1.3f)
				fac = 1.f/(vecFalloff.x + vecFalloff.y*LD + vecFalloff.z*LD*LD);
				#else  // linear Lighting
				if (LD < 1.f)
				fac = 1.f - LD;
			#endif
		}
		return Color * fac;
	}


	float DoFog(float4 Pos)
	{
		// convert the vector position to view space to get it's depth (.z)
		float3 P = mul(Pos,matWorldView);
		// apply the linear fog formula
		return saturate((vecFog.y-P.z) * vecFog.z);
	}
	
	
	struct TMULTI_VS_OUT // Output to the pixelshader fragment
	{
		float4 Pos 		: POSITION;
		float  Fog		: FOG;
		
		float4 tColor	: COLOR0;
		
		float2 Tex1 	: TEXCOORD0;
		float2 Tex2 	: TEXCOORD1;
		
		float2 Tex3 	: TEXCOORD2;
		float2 Tex4		: TEXCOORD3;
		
		float2 Tex5		: TEXCOORD4;
		float2 Tex6		: TEXCOORD5;	
		float2 Tex7		: TEXCOORD6;
		float2 Tex8		: TEXCOORD7;
	};
	
	TMULTI_VS_OUT TMulti_VS(
	float4 inPos : POSITION,
	float3 inNormal : NORMAL,
	float2 inTexCoord0 : TEXCOORD0)
	{
		
		TMULTI_VS_OUT Out;
		
		// transform the vector position to screen coordinates
		Out.Pos = mul(inPos, matWorldViewProj);
		float3 N = normalize(mul(inNormal, matWorldInv));
		float3 P = mul(inPos, matWorld);
		
		// Add ambient and sun light
		Out.tColor = ((DoSunLight(N) - 0.2f)*sunStrength)+0.6;
		
		// Add 8 dynamic lights (maximum for vs 1.1)
		for (int i=0; i<6; i++)
		Out.tColor += DoPointLight(P,N,i)*dynalightStrength;
		
		// Add fog
		Out.Fog = DoFog(inPos);
		
		// scale the texture coordinates for the masked textures
		Out.Tex1  = inTexCoord0.xy;		// rgb-blendmap (not tiled)
		Out.Tex2  = inTexCoord0.xy;		// shadowmap    (not tiled)
		
		Out.Tex3 = (inTexCoord0.xy*vecSkill41.w+vecSkill41.w/50)+0.1* vecSkill41.xy;//sin(vecSkill41);//moving the caustics texture	
		Out.Tex4 = (inTexCoord0.xy*vecSkill41.w)-0.1* vecSkill41.y;//moving the caustics texture
		
		Out.Tex5  = inTexCoord0.xy*40;	// tiling texture red
		Out.Tex6  = inTexCoord0.xy*60;	// tiling texture green
		Out.Tex7  = inTexCoord0.xy*20;	// tiling texture blue
		Out.Tex8  = inTexCoord0.xy*40;	// tiling texture black
		
		
		
		return Out;
	}
	
	
	//////////////////////////////////////////////////////////////////////////////////////////////////////
	// pixelshader
	float4 ps( TMULTI_VS_OUT In ) : COLOR
	{
		float4 BlendColor = tex2D(sTex1,In.Tex1);
		float4 ShadowMap = (tex2D(sTex2,In.Tex2)*1.5);
		
		float4 causticsA = tex2D(sTex3,In.Tex3);
		float4 causticsB = tex2D(sTex4,In.Tex4);
		
		float4 RedColor = tex2D(sTex5,In.Tex5);
		float4 GreenColor = tex2D(sTex6,In.Tex6);
		float4 BlueColor = tex2D(sTex7,In.Tex7);
		float4 BlackColor = tex2D(sTex8,In.Tex8);
		
		
		float4 BaseRed = lerp(BlackColor,RedColor,BlendColor.r);
		float4 BaseGreen = lerp(BaseRed,GreenColor,BlendColor.g);
		
		
		float4 FinalColor = lerp(BaseGreen,BlueColor,BlendColor.b);
		
		
		float4 BaseCaustics = lerp(FinalColor,(FinalColor*(causticsA+causticsB)),(ShadowMap.a*mtlSkill2));
		
		//////////////////////////////////////////////////////////////////////////////////////////////			
		
		
		FinalColor = In.tColor*(BaseCaustics*(ShadowMap));
		
		FinalColor = (FinalColor*mtlSkill1)*(ShadowMap);
		
		FinalColor.a = 1.0f; // prevent transparency
		
		return FinalColor;
	}
	//////////////////////////////////////////////////////////////////////////////////////////////////////
	// 
	technique mytechnique
	{
		// Define your passes
		pass p0
		{
			VertexShader = compile vs_2_0 TMulti_VS();
			PixelShader = compile ps_2_0 ps();
		}
	}
	
technique fallback{pass p0{}}
	
	";
}

//MATERIAL* mat_terr_hlsl_2 = 
//{
//
//	flags = tangent;
//	
//	skin1 = terr_blendtex_red_2;
//	skin2 = terr_blendtex_green_2;
//	skin3 = terr_blendtex_blue_2;
//	skin4 = terr_blendtex_black_2;
//
//	event=init_mat_terr_hlsl;
//	
//	effect
//	"
//	/////////////////////////////////////////////////////////////////////////////////////////////
//	// Define your needed values
//	float4x4 matWorldViewProj;	 
//	float4x4 matWorld;	
//	float4x4 matWorldInv;	
//	float4x4 matWorldView;
//	
//	float4 mtlSkill1;
//	float4 mtlSkill2;
//	
//	float4 vecSkill41;
//	
//	
//	float4 vecSunDir;
//	float4 vecFog;
//	float4 vecLight;
//	
//	float4 vecLightPos[8];	 // preset this with light positions (xyz) and ranges (w)
//	float4 vecLightColor[8]; // preset this with light colors
//	float3 vecFalloff = float3(0.f, 0.f, 1.5f);
//	float4 vecSunDiffuse = {1.0f, 1.0f, 0.8f, 1.0f};
//
//	float sunStrength = 0.3f;
//	float dynalightStrength = 10;
//
//	// Define your textures
//	texture mtlSkin1;					
//	texture mtlSkin2;					
//	texture mtlSkin3;
//	texture mtlSkin4;
//	
//	texture entSkin1;
//	texture entSkin2;	
//	texture entSkin3;					
//	texture entSkin4;
//	
//	/////////////////////////////////////////////////////////////////////////////////////////////
//	// Texture settings
//	
//	
//	sampler sTex1 = sampler_state			
//	{
//		Texture = <entSkin1>;   // rgb-blendmap
//		MipFilter = Linear;
//		MinFilter = Linear;
//		MagFilter = Linear;
//		AddressU = Wrap;	
//		AddressV = Wrap;
//	};
//	sampler sTex2 = sampler_state			
//	{
//		Texture = <entSkin2>;   // shadowmap
//		MipFilter = Linear;
//		MinFilter = Linear;
//		MagFilter = Linear;
//		AddressU = Wrap;	
//		AddressV = Wrap;
//	};
//	sampler sTex3 = sampler_state			
//	{
//		Texture = <entSkin3>;	// causticsA
//		MipFilter = Linear;
//		MinFilter = Linear;
//		MagFilter = Linear;
//		AddressU = Wrap;	
//		AddressV = Wrap;
//	};
//	sampler sTex4= sampler_state			
//	{
//		Texture = <entSkin4>;	// causticsB
//		MipFilter = Linear;
//		MinFilter = Linear;
//		MagFilter = Linear;
//		AddressU = Wrap;	
//		AddressV = Wrap;
//	};
//	
//
//	sampler sTex5 = sampler_state			
//	{
//		Texture = <mtlSkin1>;	// red
//		MipFilter = Linear;
//		MinFilter = Linear;
//		MagFilter = Linear;
//		AddressU = Wrap;	
//		AddressV = Wrap;
//	};
//	sampler sTex6 = sampler_state			
//	{
//		Texture = <mtlSkin2>;	// green
//		MipFilter = Linear;
//		MinFilter = Linear;
//		MagFilter = Linear;
//		AddressU = Wrap;	
//		AddressV = Wrap;
//	};
//	sampler sTex7 = sampler_state			
//	{
//		Texture = <mtlSkin3>;	// blue
//		MipFilter = Linear;
//		MinFilter = Linear;
//		MagFilter = Linear;
//		AddressU = Wrap;	
//		AddressV = Wrap;
//	};
//	sampler sTex8 = sampler_state			
//	{
//		Texture = <mtlSkin4>;	// black
//		MipFilter = Linear;
//		MinFilter = Linear;
//		MagFilter = Linear;
//		AddressU = Wrap;	
//		AddressV = Wrap;
//	};
//	
//	//////////////////////////////////////////////////////////////////////
//	// return the sun light on the surface
//	float4 DoSunLight(float3 N)
//	{
//		// modulate the sunlight by the surface angle
//		return vecSunDiffuse * dot(N,-vecSunDir);
//	}
//
//	// return the dynamic light on the surface
//	float4 DoPointLight(float3 P, float3 N, int i)
//	{
//		// calculate the light ray pointing from the light to the surface
//		float3 D = vecLightPos[i].xyz - P;
//		// calculate the angle between surface and light ray
//		float NdotL = dot(N, normalize(D));
//		// modulate the light by the surface angle
//		float4 Color = vecLightColor[i] * NdotL;
//
//		// calculate the light attenuation factor, DX uses a really strange formula here
//		float fac = 0.f;
//		if (NdotL >= 0.f && vecLightPos[i].w > 0.f)
//		{
//			// get the distance factor
//			float LD = length(D)/vecLightPos[i].w;
//			#ifdef DXLIGHTING
//				if (LD < 1.3f)
//				fac = 1.f/(vecFalloff.x + vecFalloff.y*LD + vecFalloff.z*LD*LD);
//				#else  // linear Lighting
//				if (LD < 1.f)
//				fac = 1.f - LD;
//			#endif
//		}
//		return Color * fac;
//	}
//
//
//	float DoFog(float4 Pos)
//	{
//		// convert the vector position to view space to get it's depth (.z)
//		float3 P = mul(Pos,matWorldView);
//		// apply the linear fog formula
//		return saturate((vecFog.y-P.z) * vecFog.z);
//	}
//	
//	
//	struct TMULTI_VS_OUT // Output to the pixelshader fragment
//	{
//		float4 Pos 		: POSITION;
//		float  Fog		: FOG;
//		
//		float4 tColor	: COLOR0;
//		
//		float2 Tex1 	: TEXCOORD0;
//		float2 Tex2 	: TEXCOORD1;
//		
//		float2 Tex3 	: TEXCOORD2;
//		float2 Tex4		: TEXCOORD3;
//		
//		float2 Tex5		: TEXCOORD4;
//		float2 Tex6		: TEXCOORD5;	
//		float2 Tex7		: TEXCOORD6;
//		float2 Tex8		: TEXCOORD7;
//	};
//	
//	TMULTI_VS_OUT TMulti_VS(
//	float4 inPos : POSITION,
//	float3 inNormal : NORMAL,
//	float2 inTexCoord0 : TEXCOORD0)
//	{
//		
//		TMULTI_VS_OUT Out;
//		
//		// transform the vector position to screen coordinates
//		Out.Pos = mul(inPos, matWorldViewProj);
//		float3 N = normalize(mul(inNormal, matWorldInv));
//		float3 P = mul(inPos, matWorld);
//		
//		// Add ambient and sun light
//		Out.tColor = ((DoSunLight(N) - 0.2f)*sunStrength)+0.6;
//		
//		// Add 8 dynamic lights (maximum for vs 1.1)
//		for (int i=0; i<6; i++)
//		Out.tColor += DoPointLight(P,N,i)*dynalightStrength;
//		
//		// Add fog
//		Out.Fog = DoFog(inPos);
//		
//		// scale the texture coordinates for the masked textures
//		Out.Tex1  = inTexCoord0.xy;		// rgb-blendmap (not tiled)
//		Out.Tex2  = inTexCoord0.xy;		// shadowmap    (not tiled)
//		
//		Out.Tex3 = (inTexCoord0.xy*vecSkill41.w+vecSkill41.w/50)+0.1* vecSkill41.xy;//sin(vecSkill41);//moving the caustics texture	
//		Out.Tex4 = (inTexCoord0.xy*vecSkill41.w)-0.1* vecSkill41.y;//moving the caustics texture
//		
//		Out.Tex5  = inTexCoord0.xy*40;	// tiling texture red
//		Out.Tex6  = inTexCoord0.xy*60;	// tiling texture green
//		Out.Tex7  = inTexCoord0.xy*20;	// tiling texture blue
//		Out.Tex8  = inTexCoord0.xy*40;	// tiling texture black
//		
//		
//		
//		return Out;
//	}
//	
//	
//	//////////////////////////////////////////////////////////////////////////////////////////////////////
//	// pixelshader
//	float4 ps( TMULTI_VS_OUT In ) : COLOR
//	{
//		float4 BlendColor = tex2D(sTex1,In.Tex1);
//		float4 ShadowMap = (tex2D(sTex2,In.Tex2)*1.5);
//		
//		float4 causticsA = tex2D(sTex3,In.Tex3);
//		float4 causticsB = tex2D(sTex4,In.Tex4);
//		
//		float4 RedColor = tex2D(sTex5,In.Tex5);
//		float4 GreenColor = tex2D(sTex6,In.Tex6);
//		float4 BlueColor = tex2D(sTex7,In.Tex7);
//		float4 BlackColor = tex2D(sTex8,In.Tex8);
//		
//		
//		float4 BaseRed = lerp(BlackColor,RedColor,BlendColor.r);
//		float4 BaseGreen = lerp(BaseRed,GreenColor,BlendColor.g);
//		
//		
//		float4 FinalColor = lerp(BaseGreen,BlueColor,BlendColor.b);
//		
//		
//		float4 BaseCaustics = lerp(FinalColor,(FinalColor*(causticsA+causticsB)),(ShadowMap.a*mtlSkill2));
//		
//		//////////////////////////////////////////////////////////////////////////////////////////////			
//		
//		
//		FinalColor = In.tColor*(BaseCaustics*(ShadowMap));
//		
//		FinalColor = (FinalColor*mtlSkill1)*(ShadowMap);
//		
//		FinalColor.a = 1.0f; // prevent transparency
//		
//		return FinalColor;
//	}
//	//////////////////////////////////////////////////////////////////////////////////////////////////////
//	// 
//	technique mytechnique
//	{
//		// Define your passes
//		pass p0
//		{
//			VertexShader = compile vs_2_0 TMulti_VS();
//			PixelShader = compile ps_2_0 ps();
//		}
//	}
//	
//technique fallback{pass p0{}}
//	
//	";
//}




//FFE FALLBACK MATERIALS FOR TERRAINS
MATERIAL* mat_terr_ffe_1 =
{
	
	skin1 = terr_colormap_1;
	skin2 = terr_detailmap_1;
	
	skin3 = terr_shadowmap_1;
	
	event = init_mat_terr_ffe;
	
	effect = "
	
	float4 mtlSkill1;

	Texture mtlSkin1;
	Texture mtlSkin2;
	
	Texture mtlSkin3;
	
	texture mtlSkin4;
	
	technique technique_two
	{	
		pass p0
		{
			Texture[0] = <mtlSkin1>;
			Texture[1] = <mtlSkin2>;
			
			Texture[2]=<mtlSkin3>;
			
			
			ColorArg1[0] = Texture; 
			ColorOp[0] = modulate2x;
			ColorArg2[0] = current;
			
			ColorArg1[1] = Texture;
			ColorOp[1] = addsigned;
			
			TextureTransformFlags[0] = Disable;
			TexCoordIndex[0] = 0;
			
			TextureTransformFlags[1] = Count2;
			TexCoordIndex[1] = 1;
			TextureTransform[1]= {
				8.0, 0.0, 0.0 ,0.0,//u-scale detailmap CHANGE THIS TO YOUR NEEDS!
				0.0, 8.0, 0.0, 0.0,//v-scale detailmap CHANGE THIS TO YOUR NEEDS!
				0.0, 0.0, 0.0, 0.0,
				0.0, 0.0, 0.0, 0.0
			};
			
			
			ColorArg1[2]=Texture;
			ColorOp[2]=Modulate;
			ColorArg2[2]=Current;
			TexCoordIndex[2]=0;
			TextureTransformFlags[2]=Count2;
			TextureTransform[2]={1.0,0.0,0.0,0.0,
				0.0,1.0,0.0,0.0,
				0.0,0.0,0.0,0.0,
			0.0,0.0,0.0,0.0};
			
			
			Texture[4] = <mtlSkin4>;//alpha in this texture makes entSkin1-texture transparent
			
			TexCoordIndex[4] = 0;
			
			ColorArg1[4] = <mtlSkill1>;//Current;// Get current texture (0)
			ColorOp[4] = Modulate2x;//ModulateAlpha_AddColor;//and add alpha to indicate transparency
			ColorArg2[4] = Current;
		}
	}
	";
}

//MATERIAL* mat_terr_ffe_2 = 
//{
//	
//	skin1 = terr_colormap_2;
//	skin2 = terr_detailmap_2;
//	
//	skin3 = terr_shadowmap_2;
//	
//	event = init_mat_terr_ffe;
//	
//	effect = "
//	
//	float4 mtlSkill1;
//
//	Texture mtlSkin1;
//	Texture mtlSkin2;
//	
//	Texture mtlSkin3;
//	
//	texture mtlSkin4;
//	
//	technique technique_two
//	{	
//		pass p0
//		{
//			Texture[0] = <mtlSkin1>;
//			Texture[1] = <mtlSkin2>;
//			
//			Texture[2]=<mtlSkin3>;
//			
//			
//			ColorArg1[0] = Texture; 
//			ColorOp[0] = modulate2x;
//			ColorArg2[0] = current;
//			
//			ColorArg1[1] = Texture;
//			ColorOp[1] = addsigned;
//			
//			TextureTransformFlags[0] = Disable;
//			TexCoordIndex[0] = 0;
//			
//			TextureTransformFlags[1] = Count2;
//			TexCoordIndex[1] = 1;
//			TextureTransform[1]= {
//				15.0, 0.0, 0.0 ,0.0,//u-scale detailmap CHANGE THIS TO YOUR NEEDS!
//				0.0, 15.0, 0.0, 0.0,//v-scale detailmap CHANGE THIS TO YOUR NEEDS!
//				0.0, 0.0, 0.0, 0.0,
//				0.0, 0.0, 0.0, 0.0
//			};
//			
//			
//			ColorArg1[2]=Texture;
//			ColorOp[2]=Modulate;
//			ColorArg2[2]=Current;
//			TexCoordIndex[2]=0;
//			TextureTransformFlags[2]=Count2;
//			TextureTransform[2]={1.0,0.0,0.0,0.0,
//				0.0,1.0,0.0,0.0,
//				0.0,0.0,0.0,0.0,
//			0.0,0.0,0.0,0.0};
//			
//			
//			Texture[4] = <mtlSkin4>;//alpha in this texture makes entSkin1-texture transparent
//			
//			TexCoordIndex[4] = 0;
//			
//			ColorArg1[4] = <mtlSkill1>;//Current;// Get current texture (0)
//			ColorOp[4] = Modulate2x;//ModulateAlpha_AddColor;//and add alpha to indicate transparency
//			ColorArg2[4] = Current;
//		}
//	}
//	";
//}

function mat_terr_hlsl_refl_event()
{		
	if(render_view != view_rr)//displays shader terrain above watersurface...the real terrain
	{	
		if(my.terr_id_number == 1){
			mtl = mat_terr_hlsl_1;
		}
//		if(my.terr_id_number == 2){
//			mtl = mat_terr_hlsl_2;
//		}	
		//		if(my.terr_id_number == 3){
			//			mtl = mat_terr_hlsl_3;
		//		}
		//		if(my.terr_id_number == 4){
			//			mtl = mat_terr_hlsl_4;
		//		}
		////add more terrain materials the same way...
		
		mtl.skill1 = pixel_for_vec (vector(clamp((d3d_fogcolor1.blue*my.terr_fogcol_fac)+(my.terr_add_blue*clamp(sun_angle.tilt/30,0.4,1))+(lightning),0,255),clamp((d3d_fogcolor1.green*my.terr_fogcol_fac)+(my.terr_add_green*clamp(sun_angle.tilt/30,0.4,1))+(lightning),0,255),clamp((d3d_fogcolor1.red*my.terr_fogcol_fac)+(my.terr_add_red*clamp(sun_angle.tilt/30,0.4,1))+(lightning),0,255)),100,8888);	
		
		if(is(my,terr_no_caustics)){
			mtl.skill2 = pixel_for_vec(vector(0,0,0),100,8888);
		}
		else{	
			mtl.skill2 = pixel_for_vec(vector(my.terr_caust_strenght,my.terr_caust_strenght,my.terr_caust_strenght),100,8888);
		}
	}
	else//displays ffe terrain on reflecting watersurface...because shader terrain doesen't display correctly in a render to texture view
	{
		if(my.terr_id_number == 1){
			mtl = mat_terr_ffe_1;
		}
//		if(my.terr_id_number == 2){
//			mtl = mat_terr_ffe_2;
//		}
		//		if(my.terr_id_number == 3){
			//			mtl = mat_terr_ffe_3;
		//		}
		//		if(my.terr_id_number == 4){
			//			mtl = mat_terr_ffe_4;
		//		}
		////add more terrain materials the same way...
		
		vec_set(mtl.ambient_blue,vector(clamp((d3d_fogcolor1.blue*my.terr_fogcol_fac)+(my.terr_add_blue*clamp(sun_angle.tilt/30,0.2,1))+(lightning),0,255),clamp((d3d_fogcolor1.green*my.terr_fogcol_fac)+(my.terr_add_green*clamp(sun_angle.tilt/30,0.2,1))+(lightning),0,255),clamp((d3d_fogcolor1.red*my.terr_fogcol_fac)+(my.terr_add_red*clamp(sun_angle.tilt/30,0.2,1))+(lightning),0,255)));
	}
}

function init_mat_terr_hlsl()
{
	
	bmap_to_mipmap(mtl.skin1);
	bmap_to_mipmap(mtl.skin2);
	bmap_to_mipmap(mtl.skin3);
	bmap_to_mipmap(mtl.skin4);
	
	if(is(view_rr,VISIBLE))
	{
		mtl.event = mat_terr_hlsl_refl_event;
	}
	else{	
		mtl.skill1 = pixel_for_vec(vector(clamp((d3d_fogcolor1.blue*my.terr_fogcol_fac)+(my.terr_add_blue*clamp(sun_angle.tilt/30,0.4,1))+(lightning),0,255),clamp((d3d_fogcolor1.green*my.terr_fogcol_fac)+(my.terr_add_green*clamp(sun_angle.tilt/30,0.4,1))+(lightning),0,255),clamp((d3d_fogcolor1.red*my.terr_fogcol_fac)+(my.terr_add_red*clamp(sun_angle.tilt/30,0.4,1))+(lightning),0,255)),100,8888);
		
		if(is(my,terr_no_caustics)){
			mtl.skill2 = pixel_for_vec(vector(0,0,0),100,8888);
		}
		else{	
			mtl.skill2 = pixel_for_vec(vector(my.terr_caust_strenght,my.terr_caust_strenght,my.terr_caust_strenght),100,8888);
		}
	}
		
	set(mtl,ENABLE_RENDER);	
}

function init_mat_terr_ffe()
{
	bmap_to_mipmap(mtl.skin1);
	bmap_to_mipmap(mtl.skin2);
	
	vec_set(mtl.ambient_blue,vector(clamp((d3d_fogcolor1.blue*my.terr_fogcol_fac)+(my.terr_add_blue*clamp(sun_angle.tilt/30,0.2,1))+(lightning),0,255),clamp((d3d_fogcolor1.green*my.terr_fogcol_fac)+(my.terr_add_green*clamp(sun_angle.tilt/30,0.2,1))+(lightning),0,255),clamp((d3d_fogcolor1.red*my.terr_fogcol_fac)+(my.terr_add_red*clamp(sun_angle.tilt/30,0.2,1))+(lightning),0,255)));

	set(mtl,ENABLE_RENDER);	
}



terrain_templte.c
Code:
///////////////////////////////////////////////////////////////////////////////////////////////////
////MystyMood multitexture-terrainshader that makes it easy to implement terrains made 
////with EarthSculptor (http://www.earthsculptor.com/) into 3dgs. It's able to blend 4 textures and 
////I also included an underwater multicaustics wave sun reflectionand and easy shadowmap generation.
////Contains ffe fallbacks, supports dynamic lights and sunlight and A6 stencil shadows
////
////NEEDS: terrain_materials.wdl
////
////Jun 07 by www.loopix-project.com
////Nov 07 Lite-C conversion by Alexis Rozhkov aka Shadow
///////////////////////////////////////////////////////////////////////////////////////////////////

#define		terr_add_red skill1 //add a color tint
#define		terr_add_green skill2
#define		terr_add_blue skill3
#define		terr_fogcol_fac skill4//factor of focgcolor1 influence
#define		terr_caust_speed  skill5//speed of the underwater caustics (sun-wave reflection)
#define		terr_caust_scale  skill6//scale of the underwater caustics
#define		terr_caust_strenght  skill7

#define		terr_id_number  skill8//scale of the underwater caustics

#define		terr_ffe_only FLAG1//check this flag if you don't want shader terrain (looks not so good)
#define		terr_shad_gen FLAG3//check this flag for generating the shadowmap (static-shadowmap...uncheck for normal terrain use)
#define		terr_no_caustics FLAG4//flag to disable underwater caustics

////this loads the terrain_material.wdl wich is needed
#include "terrain_materials.c"

//string terr_shadowmap_string = "terr_shadowmap_1.tga";
STRING* terr_shadowmap_str = "terr_shadowmap_";
STRING* terr_shadowmap_tempstr1 = "";
STRING* terr_shadowmap_tempstr2 = "";

STRING* terr_shadowmap_filetype = ".tga";//for terr_shadowmap: terr_shadowmap.tga...

////SHADOWMAP GENERATION ADJUSTMENTS TO BE MADE HERE! 
var shadow_brightness=120;//brightness of shadows...(0=black, 255=white)
var shadow_pixel_z_adjust = -1;//play with this within a range of -5 to 5! This affects the shadow offset from the object
var blur_passes = 1;//the higher the softer the borders of the shadows


BMAP* canvas_shadowmap;
VECTOR canvas_shadowmap_size;

FONT* fnt_arial = "arial#25"; 

STRING*  strg_wait_shadow_gen = "Please wait...shadowmap-generation is progressing...\n This can take some time...";
STRING*  strg_shadow_finished = "Shadowmap is now generated and saved to your project folder!";
STRING*  strg_press_shadow_gen = "Press 'G' to generate shadowmap!";


TEXT* txt_wait_shadow_gen =
{
	font = fnt_arial;
	layer = 10;
	flags = center_x,center_y,outline;
	string = strg_wait_shadow_gen;
	red = 255;
	green = 0;
	blue = 0;
}

TEXT* txt_shadow_finished =
{
	font = fnt_arial;
	layer = 10;
	flags = center_x,center_y,outline;
	string = strg_shadow_finished;
	red = 0;
	green = 255;
	blue = 0;
}

TEXT* txt_press_shadow_gen =
{
	font = fnt_arial;
	layer = 10;
	flags = center_x,center_y,outline;
	string = strg_press_shadow_gen;
	red = 0;
	green = 0;
	blue = 255;
}

var shadow_fhandle_n;
//---------------------------------------------------------write tga
function shadow_write8(var shadow_byte) // write char
{
	file_asc_write(shadow_fhandle_n,shadow_byte);
}

function shadow_write16(var shadow_short) // write unsigned shadow_short
{
	file_asc_write(shadow_fhandle_n,shadow_short&255);
	file_asc_write(shadow_fhandle_n,(shadow_short>>8)&255);
}

function write_shadowmap_tga(shadowmap_file_name)
{
	var i;
	var format;
	var pixel;
	var pixelalpha;
	VECTOR canvas_shadowmap_size;
	VECTOR temp;

	canvas_shadowmap_size.x=bmap_width(canvas_shadowmap);
	canvas_shadowmap_size.y=bmap_height(canvas_shadowmap);
	format=bmap_lock(canvas_shadowmap,0);

	shadow_fhandle_n=file_open_write(shadowmap_file_name);
	//------------------------------------write header
	shadow_write8(0);
	shadow_write8(0);
	shadow_write8(2); // image type // 10 = RLE compressed tga, 2 = uncompressed tga
	shadow_write16(0);
	shadow_write16(0);
	shadow_write8(0);
	shadow_write16(0);
	shadow_write16(0);
	shadow_write16(canvas_shadowmap_size.x); // width
	shadow_write16(canvas_shadowmap_size.y); // height
	shadow_write8(24);//or 32 for alphachanel
	shadow_write8(0);
	//------------------------------------write image data
	i=0;
	while(i<canvas_shadowmap_size.x*canvas_shadowmap_size.y)
	{
		pixel = pixel_for_bmap(canvas_shadowmap,i%canvas_shadowmap_size.x,(canvas_shadowmap_size.y-1)-integer(i/canvas_shadowmap_size.x));
		pixel_to_vec(temp,pixelalpha,format,pixel);
		shadow_write8(temp.x); // b
		shadow_write8(temp.y); // g
		shadow_write8(temp.z); // r
		i+=1;
		if(i%max_loops == 0){wait(1);}
	}
	
	wait(1);
	
	file_close(shadow_fhandle_n);
	bmap_unlock(canvas_shadowmap);
	
	reset(txt_wait_shadow_gen,VISIBLE);
	txt_shadow_finished.pos_x = screen_size.x/2;
	txt_shadow_finished.pos_y = screen_size.y/2;
	set(txt_shadow_finished,VISIBLE);
	wait(-4);
	reset(txt_shadow_finished,VISIBLE);
}

function shadow_get_xyz(shadow_px,shadow_py)
{
	VECTOR pixel_size;
	VECTOR temp;
	
	pixel_size.x=(my.max_x-my.min_x)/canvas_shadowmap_size.x;
	pixel_size.y=(my.max_y-my.min_y)/canvas_shadowmap_size.y;
	temp.x=((my.x-my.min_x)-(pixel_size.x*shadow_px))-pixel_size.x/2;
	temp.y=((my.y-my.min_y)-(pixel_size.y*shadow_py))-pixel_size.y/2;
	c_trace(vector(temp.x,temp.y,my.z+50000),vector(temp.x,temp.y,my.z-50000),IGNORE_MODELS+IGNORE_SPRITES+IGNORE_MAPS);
	temp.z=target.z;
}

////blur
function blur(var passes)
{
	var i;
	var px;
	var py;
	var format;
	var pixel;
	VECTOR pixelcolor;
	var pixelalpha;
	VECTOR sample1;
	VECTOR sample2;
	VECTOR sample3;
	VECTOR sample4;
	VECTOR sample5;
	VECTOR sample6;
	VECTOR sample7;
	VECTOR sample8;
	VECTOR sample9;
	VECTOR temp;

	i=0;

	while(i<passes)
	{
		py=0;
		while(py<canvas_shadowmap_size.y)
		{
			px=0;
			while(px<canvas_shadowmap_size.x)
			{
				format=bmap_lock(canvas_shadowmap,0);
				
				pixel=pixel_for_bmap(canvas_shadowmap,clamp((canvas_shadowmap_size.x-1)-px,0,canvas_shadowmap_size.x-1),clamp(py,0,canvas_shadowmap_size.x-1));
				pixel_to_vec(sample1,pixelalpha,format,pixel);
				
				pixel=pixel_for_bmap(canvas_shadowmap,clamp((canvas_shadowmap_size.x-1)-px-1,0,canvas_shadowmap_size.x-1),clamp(py,0,canvas_shadowmap_size.x-1));
				pixel_to_vec(sample2,pixelalpha,format,pixel);
				pixel=pixel_for_bmap(canvas_shadowmap,clamp((canvas_shadowmap_size.x-1)-px-1,0,canvas_shadowmap_size.x-1),clamp(py+1,0,canvas_shadowmap_size.x-1));
				pixel_to_vec(sample3,pixelalpha,format,pixel);
				pixel=pixel_for_bmap(canvas_shadowmap,clamp((canvas_shadowmap_size.x-1)-px,0,canvas_shadowmap_size.x-1),clamp(py+1,0,canvas_shadowmap_size.x-1));
				pixel_to_vec(sample4,pixelalpha,format,pixel);
				pixel=pixel_for_bmap(canvas_shadowmap,clamp((canvas_shadowmap_size.x-1)-px+1,0,canvas_shadowmap_size.x-1),clamp(py+1,0,canvas_shadowmap_size.x-1));
				pixel_to_vec(sample5,pixelalpha,format,pixel);
				pixel=pixel_for_bmap(canvas_shadowmap,clamp((canvas_shadowmap_size.x-1)-px+1,0,canvas_shadowmap_size.x-1),clamp(py,0,canvas_shadowmap_size.x-1));
				pixel_to_vec(sample6,pixelalpha,format,pixel);
				pixel=pixel_for_bmap(canvas_shadowmap,clamp((canvas_shadowmap_size.x-1)-px+1,0,canvas_shadowmap_size.x-1),clamp(py-1,0,canvas_shadowmap_size.x-1));
				pixel_to_vec(sample7,pixelalpha,format,pixel);
				pixel=pixel_for_bmap(canvas_shadowmap,clamp((canvas_shadowmap_size.x-1)-px,0,canvas_shadowmap_size.x-1),clamp(py-1,0,canvas_shadowmap_size.x-1));
				pixel_to_vec(sample8,pixelalpha,format,pixel);
				pixel=pixel_for_bmap(canvas_shadowmap,clamp((canvas_shadowmap_size.x-1)-px-1,0,canvas_shadowmap_size.x-1),clamp(py-1,0,canvas_shadowmap_size.x-1));
				pixel_to_vec(sample9,pixelalpha,format,pixel);
				
				pixelcolor.x=integer((sample1.x*7+sample2.x*2+sample3.x+sample4.x*2+sample5.x+sample6.x*2+sample7.x+sample8.x*2+sample9.x)/19);
				pixelcolor.y=integer((sample1.y*7+sample2.y*2+sample3.y+sample4.y*2+sample5.y+sample6.y*2+sample7.y+sample8.y*2+sample9.y)/19);
				pixelcolor.z=integer((sample1.z*7+sample2.z*2+sample3.z+sample4.z*2+sample5.z+sample6.z*2+sample7.z+sample8.z*2+sample9.z)/19);
				
				pixel=pixel_for_vec(pixelcolor,100,format);
				pixel_to_bmap(canvas_shadowmap,(canvas_shadowmap_size.x-1)-px,py,pixel);
				
				bmap_unlock(canvas_shadowmap);
				
				px+=1;
			}
			py+=1;
			wait(1); // without a wait after each line the loop could get too big if the shadow map is huge
		}
		i+=1;
	}
	
	write_shadowmap_tga(terr_shadowmap_tempstr1);
}


function shadowmap_gen()
{
	//NOTE: YOUR TERRAIN ACTION MUST INCLUDE "C_SETMINMAX(ME); MY.POLYGON=ON;" AT THE VERY BEGINING!!!
	
	reset(txt_press_shadow_gen,VISIBLE);
	
	var shadow_px;
	var shadow_py;
	var format;
	var pixel;
	var dist;
	VECTOR temp;
	
	canvas_shadowmap=bmap_for_entity(my,2); // the second texture of the terrain is the shadowmap
	canvas_shadowmap_size.x=bmap_width(canvas_shadowmap);
	canvas_shadowmap_size.y=bmap_height(canvas_shadowmap);

	you = my;//need this pointer to avoid terrain self-shadows

	shadow_py=0;
	while(shadow_py<canvas_shadowmap_size.y)
	{
		shadow_px=0;
		while(shadow_px<canvas_shadowmap_size.x)
		{
			shadow_get_xyz(shadow_px,shadow_py); // get the world coordinates of the pixel
			c_trace(sun_pos.x,vector(temp.x,temp.y,temp.z+(shadow_pixel_z_adjust)),IGNORE_PASSENTS); // trace from the sun to the pixel
			if(trace_hit && you != my) // draw shadow pixel if there is no obstacle. Only draws shadows if the you entity is not the ent_terrain
			{
				format=bmap_lock(canvas_shadowmap,0);
				pixel=pixel_for_vec(vector(shadow_brightness,shadow_brightness,shadow_brightness),100,format);
				pixel_to_bmap(canvas_shadowmap,(canvas_shadowmap_size.x-1)-shadow_px,shadow_py,pixel);
				bmap_unlock(canvas_shadowmap);
			}
			
			shadow_px+=1;
		}
		shadow_py+=1;
		
		txt_wait_shadow_gen.pos_x = screen_size.x/2;
		txt_wait_shadow_gen.pos_y = screen_size.y/2;
		set(txt_wait_shadow_gen,VISIBLE);
		
		wait(1); // without a wait after each line the loop could get too big if the shadow map is huge
	}

	blur(blur_passes); // do blur pass	
}


MATERIAL* mat_terr_shadowmap = 
{
	effect=
	"
	texture mtlSkin1;
	texture entSkin2;

	technique one_pass_shadow
	{
		pass p0
		{
			Texture[0]=<mtlSkin1>;
			Texture[1]=<entSkin2>;
			
			ColorArg1[0]=Texture;
			ColorOp[0]=Modulate2x;
			ColorArg2[0]=Diffuse;
			TexCoordIndex[0]=0;
			TextureTransformFlags[0]=Count2;
			TextureTransform[0]={1.0,0.0,0.0,0.0, // color map u scale
				0.0,1.0,0.0,0.0, // color map v scale
				0.0,0.0,0.0,0.0,
			0.0,0.0,0.0,0.0};
			
			ColorArg1[1]=Texture;
			ColorOp[1]=Modulate;
			ColorArg2[1]=Current;
			TexCoordIndex[1]=0;
			TextureTransformFlags[1]=Count2;
			TextureTransform[1]={1.0,0.0,0.0,0.0,
				0.0,1.0,0.0,0.0,
				0.0,0.0,0.0,0.0,
			0.0,0.0,0.0,0.0};
		}
	}
	";
}

//title:MystyMood Terrain Template
//image:loopix_logo.pcx
//action:act_terrain 
//skill1:terr_add_red 150
//help: terrain tint red 0-255
//skill2:terr_add_green 150
//help: terrain tint green 0-255
//skill3:terr_add_blue 150
//help: terrain tint blue 0-255
// section:
//skill4:terr_fogcol_fac 0.500
//help: influence of fogcolor1 on terrain 0...1
// section:
//skill5:terr_caust_speed 0.050
//help: underwater caustics speed
//skill6:terr_caust_scale 40.000
//help: underwater caustics scale
//section:
//skill7:terr_caust_strenght 150
//help: defines the visibility strenght of underwater caustics
//section:
//skill8:terr_id_number 1
//help: defines the terrain wich is needed to choose the corresponding material
// section:
//text: flag for non shader terrain only
//flag1:terr_ffe_only 0
// section:
//text: flag for shadow generation mode (pressing "g")...uncheck when done
//flag3:terr_shad_gen 0
// section:
//text: flag for disableing underwater caustics
//flag4:terr_no_caustics 0
//uses:terr_add_red,terr_add_green,terr_add_blue,terr_fogcol_fac,terr_ffe_only,terr_spec_pow_ffe,terr_shad_gen,terr_caust_speed,terr_caust_scale,terr_no_caustics,terr_caust_strenght,terr_id_number
action act_terrain() {
	
	ent_terrain = me;
	
	//	my.x = 0;
	//	my.y = 0;
	//	my.z = 0;
	
	c_setminmax(me);
	wait(1);
	set(my,POLYGON);
	
	//if youn want to implement a SEED_IT (www.gameus.de) object seed-action, do it right here!
	
	
	//set defaults	
	if(!my.terr_fogcol_fac){my.terr_fogcol_fac = 0.2;}
	if(!my.terr_add_blue){my.terr_add_blue = 150;}
	if(!my.terr_add_green){my.terr_add_green = 150;}
	if(!my.terr_add_red){my.terr_add_red = 150;}
	if(!my.terr_caust_speed){my.terr_caust_speed = 0.05;}
	if(!my.terr_caust_scale){my.terr_caust_scale = 40;}
	if(!my.terr_caust_strenght){my.terr_caust_strenght = 150;}
	if(!my.terr_id_number){my.terr_id_number = 1;}
	
	////this is to find the according shadowmap
	str_cpy(terr_shadowmap_tempstr1,terr_shadowmap_str);
	str_for_num(terr_shadowmap_tempstr2,ent_terrain.terr_id_number);
	str_cat(terr_shadowmap_tempstr1,terr_shadowmap_tempstr2);
	str_cat(terr_shadowmap_tempstr1,terr_shadowmap_filetype);
	
	wait(1);
	
	var count;
	var a ;
	
	if(!is(my,terr_shad_gen)){
		
		if(d3d_shaderversion >= 2020 && !is(my,terr_ffe_only)){
			
			if(my.terr_id_number == 1){
				my.material = mat_terr_hlsl_1;
			}
//			if(my.terr_id_number == 2){
//				my.material = mat_terr_hlsl_2;
//			}
//			if(my.terr_id_number == 3){
//				my.material = mat_terr_hlsl_3;
//			}
//			if(my.terr_id_number == 4){
//				my.material = mat_terr_hlsl_4;
//			}
			////add more terrain materials the same way...
			
			my.skill44 = floatv(my.terr_caust_scale);	
			
			while(1){	
				my.skill41 = floatv(count);
				my.skill42 = floatv(-count);
				a += my.terr_caust_speed*time_step;
				count = a;		
				wait(1);	
			}	
		}
		else{
			
			if(my.terr_id_number == 1){
				my.material = mat_terr_ffe_1;
			}
//			if(my.terr_id_number == 2){
//				my.material = mat_terr_ffe_2;
//			}
//			if(my.terr_id_number == 3){
//				my.material = mat_terr_ffe_3;
//			}
//			if(my.terr_id_number == 4){
//				my.material = mat_terr_ffe_4;
//			}
			////add more terrain materials the same way...
		}	
	}
	else{//when in shadowmap generation mode...
		
		dynamic_day_night = 0;
//		sun_angle.pan = sun_azimuth;
//		sun_angle.tilt = sun_elevation;
		
		my.material = mat_terr_shadowmap;
		
		txt_press_shadow_gen.pos_x = screen_size.x/2;
		txt_press_shadow_gen.pos_y = screen_size.y/2;
		
		set(txt_press_shadow_gen,VISIBLE);
		
		while(key_g == 0){wait(1);}
		
		shadowmap_gen();
		
		reset(txt_press_shadow_gen,VISIBLE);
	}
}

© 2024 lite-C Forums