Texture Splatting

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.
jaeg
Posts: 52
Joined: Thu Jun 28, 2007 11:20 pm

Texture Splatting

Post by jaeg »

I've been working on trying to get texture splatting working on my terrain. I've been follow the code posted here: http://irrlicht.sourceforge.net/forum/v ... +splatting (The download link for which is dead. If anyone has the file still can you please send it my way?) first by using just the actual shader portions of it and then when that didn't work I just used his whole class. The heightmap and alphamap are generated from L3DT.
This is what I get:
Image

L3DT gives me 4 alpha maps and won't combine them since it's the free version so it may be my data that is causing this issue. Does anyone have a couple of heightmaps and alphamaps they know work for me to test and eliminate bad data as the source of my problem?

Also the topic is 3 years old so if there is a better way to do this now don't hesitate to point me in another direction. :)
Computer Science Major - Ball State University
jaeg
Posts: 52
Joined: Thu Jun 28, 2007 11:20 pm

Re: Texture Splatting

Post by jaeg »

I figured it out. I needed to change this function from this:

Code: Select all

void CMultiTexturingManager::OnSetConstants(video::IMaterialRendererServices* services, s32 userData)
{
    int layer0 = 0;
    int layer1 = 1;
    int layer2 = 2;
    int layer3 = 3;
    services->setPixelShaderConstant("splatMap",(float*)&layer0,1);
    services->setPixelShaderConstant("layer_red",(float*)&layer1,1);
    services->setPixelShaderConstant("layer_green",(float*)&layer2,1);
    services->setPixelShaderConstant("layer_blue",(float*)&layer3,1);
}
to this:

Code: Select all

void CMultiTexturingManager::OnSetConstants(video::IMaterialRendererServices* services, s32 userData)
{
    int layer0 = 0;
    int layer1 = 1;
    int layer2 = 2;
    int layer3 = 3;
    services->setPixelShaderConstant("splatMap",&layer0,1);
    services->setPixelShaderConstant("layer_red",&layer1,1);
    services->setPixelShaderConstant("layer_green",&layer2,1);
    services->setPixelShaderConstant("layer_blue",&layer3,1);
}
And now it works perfectly.
Image
Computer Science Major - Ball State University
jaeg
Posts: 52
Joined: Thu Jun 28, 2007 11:20 pm

Re: Texture Splatting

Post by jaeg »

Just a quick question. I'm somewhat new to shaders for Irrlicht. When setting this up the material type for the terrain is set to the splatting shader. How would I apply another shader on top of this for say, per pixel lighting or applying a lightmap? One way I thought of was to have the splatting shader be applied to a material of a quad, change the render target to a texture, take that texture and add it to the material of the terrain and apply another shader (some form of lighting) to that. Is this efficient?
Computer Science Major - Ball State University
hendu
Posts: 2600
Joined: Sat Dec 18, 2010 12:53 pm

Re: Texture Splatting

Post by hendu »

Chaining is almost always inefficient. Combine what you want in one shader.
jaeg
Posts: 52
Joined: Thu Jun 28, 2007 11:20 pm

Re: Texture Splatting

Post by jaeg »

That would work well for lighting. But I'll run into the issue of being limited to only 4 textures. So I wouldn't be able to splat a normal map too and apply it. Is there a good way to do that? Also in the original code in the topic I posted in my Original Post he mentions using a meshbuffer trick but I'm not sure what he's doing. Can anyone explain what he's doing?
Computer Science Major - Ball State University
hendu
Posts: 2600
Joined: Sat Dec 18, 2010 12:53 pm

Re: Texture Splatting

Post by hendu »

Not sure what trick he means, maybe the culling check.

Yes, you'd run into texture limitations. The usual answers are raise the limits, use an atlas, use an array texture.
jaeg
Posts: 52
Joined: Thu Jun 28, 2007 11:20 pm

Re: Texture Splatting

Post by jaeg »

I didn't know you could pass other textures to a shader like that. I thought you had to use the material's textures.

If I was to use a texture atlas in my shader I would find the appropriate piece of my textures by doing something like this:
Assuming a 1024 x 1024 atlas in a 2 x 2 grid. (0,0) is my splat map, (1,0) is the red texture, (0,1) is blue, and (1,1) is green.

Now using the current texture coords I can first divide them by 4 and then to access the texture at (0,1) offset this coord's Y by 256.

Am I correct?

Edit - I have a feeling it may be a bad idea to keep the splat map in the atlas since it might get altered by the mipmap.
Computer Science Major - Ball State University
hendu
Posts: 2600
Joined: Sat Dec 18, 2010 12:53 pm

Re: Texture Splatting

Post by hendu »

Texcoords in the shader go from 0 to 1, so you'd divide by two, and offset by 0.5.

Unless you disabled mipmaps, they get used with separate textures too.
jaeg
Posts: 52
Joined: Thu Jun 28, 2007 11:20 pm

Re: Texture Splatting

Post by jaeg »

So really the texture size doesn't matter I just need to know how many cells it has?

Also just a random question. Irrlicht automatically provides shaders with normals and tangents doesn't it?
Computer Science Major - Ball State University
hendu
Posts: 2600
Joined: Sat Dec 18, 2010 12:53 pm

Re: Texture Splatting

Post by hendu »

So really the texture size doesn't matter I just need to know how many cells it has?
Yes.
Irrlicht automatically provides shaders with normals and tangents doesn't it?
It depends on your mesh. If it has normals and tangents, then yes.
jaeg
Posts: 52
Joined: Thu Jun 28, 2007 11:20 pm

Re: Texture Splatting

Post by jaeg »

Awesome, thanks for all your help! Hopefully I'll have something interesting to show! I've written up a document on how I want to proceed using what I've learned. For right now I'm going to use a lightmap to make it look lighted but it'll have up to 4 layered splat maps each with 3 textures (One for each color channel) so hopefully up to 12 texture layers. Chances are I won't need that many but it'll be fun to try. Luckily texture splatting in general is fairly simple.
Computer Science Major - Ball State University
jaeg
Posts: 52
Joined: Thu Jun 28, 2007 11:20 pm

Re: Texture Splatting

Post by jaeg »

Well I've made progress. The image below is a successful merging of two splatmaps. I'm still fighting with some offset issues and still working on a better way to layer the maps on top of each other.

You can see that more than three textures are being used (4 of them)
Image

This shader is very much hacked together and I haven't done anything to really clean it up. The (fract(gl_TexCoord[1].xy) * 0.25) is used so I can tile the texture by scaling it from Irrlicht.
Fragment Shader:

Code: Select all

uniform sampler2D splatMap;
uniform sampler2D textureAtlas;
 
                            
void main(){
    //Layer 1
    vec4 SplatCol=texture2D(splatMap,gl_TexCoord[0].xy/4);
    vec4 RedCol=texture2D(textureAtlas,(fract(gl_TexCoord[1].xy) * 0.25));
    vec4 GreenCol=texture2D(textureAtlas,(fract(gl_TexCoord[1].xy) * 0.25) + vec2(.252,0));
    vec4 BlueCol=texture2D(textureAtlas,(fract(gl_TexCoord[1].xy) * 0.25) + vec2(.502,0));
    vec4 layer1 = (vec4(SplatCol.r*RedCol+SplatCol.g*GreenCol+SplatCol.b*BlueCol)*vec4(1,1,1,SplatCol.a));
 
    //Layer 2
    SplatCol=texture2D(splatMap,gl_TexCoord[0].xy/4 + vec2(.25,0));
    RedCol=texture2D(textureAtlas,(fract(gl_TexCoord[1].xy) * 0.25) + vec2(.751,0));
    GreenCol=texture2D(textureAtlas,(fract(gl_TexCoord[1].xy) * 0.25) + vec2(0,.252));
    BlueCol=texture2D(textureAtlas,(fract(gl_TexCoord[1].xy) * 0.25) + vec2(.252,.252));
    vec4 layer2 = (vec4(SplatCol.r*RedCol+SplatCol.g*GreenCol+SplatCol.b*BlueCol)*vec4(1,1,1,SplatCol.a));
    
 
    gl_FragColor= mix(layer1,layer2,SplatCol.a);
}
Vertex Shader:

Code: Select all

void main()
{
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_TexCoord[1] = gl_MultiTexCoord1;
gl_Position = ftransform();
}
Computer Science Major - Ball State University
jaeg
Posts: 52
Joined: Thu Jun 28, 2007 11:20 pm

Re: Texture Splatting

Post by jaeg »

Two color maps and a light map in use! I found a better tool from aligning the images in the atlas. I'm still getting some seams where it's getting portions of the texture beside it however. I have mipmaps turned off (was a lot worse before I did that).

Anyway here is some screen shots of what I have:
Image
Image

The Vertex shader hasn't changed.
The current Fragment shader:

Code: Select all

uniform sampler2D splatMap;
uniform sampler2D textureAtlas;
 
                            
void main(){
    //Layer 1
    vec4 SplatCol=texture2D(splatMap,gl_TexCoord[0].xy/4);
    vec4 RedCol=texture2D(textureAtlas,(fract(gl_TexCoord[1].xy) * 0.25));
    vec4 GreenCol=texture2D(textureAtlas,(fract(gl_TexCoord[1].xy) * 0.25) + vec2(.25,0));
    vec4 BlueCol=texture2D(textureAtlas,(fract(gl_TexCoord[1].xy) * 0.25) + vec2(.50,0));
    vec4 layer1 = (vec4(SplatCol.r*RedCol+SplatCol.g*GreenCol+SplatCol.b*BlueCol)*vec4(1,1,1,SplatCol.a));
 
    //Layer 2
    SplatCol=texture2D(splatMap,gl_TexCoord[0].xy/4 + vec2(.25,0));
    RedCol=texture2D(textureAtlas,(fract(gl_TexCoord[1].xy) * 0.25) + vec2(.75,0));
    GreenCol=texture2D(textureAtlas,(fract(gl_TexCoord[1].xy) * 0.25) + vec2(0,.25));
    BlueCol=texture2D(textureAtlas,(fract(gl_TexCoord[1].xy) * 0.25) + vec2(.25,.25));
    vec4 layer2 = (vec4(SplatCol.r*RedCol+SplatCol.g*GreenCol+SplatCol.b*BlueCol)*vec4(1,1,1,SplatCol.a));
 
    //Lightmap
    vec4 LightMapCol =texture2D(splatMap,gl_TexCoord[0].xy/4 + vec2(.50,0));
 
    gl_FragColor= mix(layer1,layer2,SplatCol.a) - LightMapCol/2;
}
I'm going to change it around so that it's looping through the splat maps rather than being manually hard coded.


EDIT -
I fixed the seams I turned of mipmaps when loading the terrain atlases and then turned it back on. I also added this line for each texture: terrain->getMaterial(0).TextureLayer[1].BilinearFilter = false;

Also I added normal mapping to the shader. It only uses one light source at the moment and its location is hard coded but it should be easy to have the class I'm using for the callback to provide it with the closest light source.
Computer Science Major - Ball State University
Distorion
Posts: 12
Joined: Thu Jul 19, 2012 1:58 am
Location: Canberra, Australia

Re: Texture Splatting

Post by Distorion »

This looks awesome so far, Any chance you could please upload your Alpha/textures. I can't see the materials on my terrain and want to see if it's my Alpha or Textures that are the problem.

Thanks!
jaeg
Posts: 52
Joined: Thu Jun 28, 2007 11:20 pm

Re: Texture Splatting

Post by jaeg »

Yah once I'm back at my home computer I can.

Something you can look at though is the way your texture atlas is set up. My texture atlas all are 4x4. Even if you have empty areas you stil have to keep it 4x4 especially for the effectAtlas (colormaps and lightmap). If you don't want 4x4 you'll need to change the offset values and the values one this line:

Code: Select all

textureAtlas,(fract(gl_TexCoord[1].xy) * 0.25)
and this line:

Code: Select all

vec4 SplatCol=texture2D(splatMap,gl_TexCoord[0].xy/4);
Computer Science Major - Ball State University
Post Reply