Purpose: The purpose of this is to merge all of a landscapes splat textures in to a single cohesive texture, that is merged with the base texture map of your landscape. this will allow you to still in essence use splatting, without the fps hit; and also allow you to use detail textures on landscapes if your heart so desires.

Good luck,

almaris

P.S Thanks to Sylvain for all of your help with this. I realize that some of this is pretty specific to the way I do things, but it is commented pretty well so hopefully it won’t be too big of a challenge to figure out where I was going with things.

 
   Public Sub MergeSplats()
        If MessageBox.Show("This function is not undoable and will remove all splats permanently, are you sure you wish to continue?", "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Asterisk) = DialogResult.Yes Then
            Dim scr As New TVScreen2DImmediate
            If Me.BaseTextureMap Is Nothing Then Exit Sub
            If Me.BaseTextureMap.Index = -1 Then Exit Sub
            With Context.TextureFactory
 
                'base texturemap info struct
                Dim tinfo As TV_TEXTURE = .GetTextureInfo(Me.BaseTextureMap.Index)
 
                'base texturemap size
                Dim tsize As New Size(tinfo.RealWidth, tinfo.RealHeight)
 
                'tv_color structs
                Dim COLPIXELBASE As TV_COLOR
                Dim COLPIXELSPLAT As TV_COLOR
                Dim COLPIXELALPHA As TV_COLOR
                Dim FINALCOL As New TV_COLOR
 
                'stores width/height ratios
                Dim walpha As Single
                Dim halpha As Single
                Dim wsplat As Single
                Dim hsplat As Single
                'set up final texture rendersurface
                Dim finaltex As TVRenderSurface = Context.Scene.CreateRenderSurface(tsize.Width, tsize.Height, False, CONST_TV_RENDERSURFACEFORMAT.TV_TEXTUREFORMAT_A8R8G8B8)
 
                'draw base texture on rs
                finaltex.StartRender()
                scr.Draw_Texture(Me.BaseTextureMap.Index, 0, 0, tsize.Width, tsize.Height)
                finaltex.EndRender()
 
                'create static texture from blank rs
                Dim ifinaltex As Integer = finaltex.CreateStaticTextureFromRenderSurface(tsize.Width, tsize.Height)
                'stop landscape from rendering
                Me.Enabled = False
 
                For Each splat As Splat In Me.Splats
                    If Not splat.BaseTexture Is Nothing Then
                        If Not splat.BaseTexture.Index = -1 Then
                            If Not splat.AlphaTexture Is Nothing Then
                                'splat texturemap info struct
                                Dim splatinfo As TV_TEXTURE = .GetTextureInfo(splat.BaseTexture.Index)
                                Dim isplatalphatex As Integer = splat.AlphaTexture.CreateStaticTextureFromRenderSurface(splat.AlphaSize.Width, splat.AlphaSize.Height)
                                Dim isplattex As Integer = splat.BaseTexture.Index
                                Dim colors As New ArrayList
                                'lock textures
                                .LockTexture(ifinaltex)
                                .LockTexture(isplattex)
                                .LockTexture(isplatalphatex)
                                'set up ratios
                                walpha = tsize.Width / splat.AlphaSize.Width
                                halpha = tsize.Height / splat.AlphaSize.Height
                                wsplat = tsize.Width / splatinfo.RealWidth
                                hsplat = tsize.Height / splatinfo.RealHeight
 
                                For y As Integer = 0 To tsize.Height - 1
                                    For x As Integer = 0 To tsize.Width - 1
                                        'decode base texture map pixel
                                        COLPIXELBASE = Context.Global.DecodeRGBA(.GetPixel(ifinaltex, x, y))
                                        'decode splat texture pixel with tiling, ratio, width, height and shift
                                        COLPIXELSPLAT = Context.Global.DecodeRGBA(.GetPixel(isplattex, _
                                        (splat.ShiftU + (x / wsplat * splat.TileU)) Mod splatinfo.RealWidth, _
                                        (splat.ShiftV + (y / hsplat * splat.TileV)) Mod splatinfo.RealHeight))
                                        'decode splat alpha pixel
                                        COLPIXELALPHA = Context.Global.DecodeRGBA(.GetPixel(isplatalphatex, x / walpha, y / halpha))
                                        'set pixel values
                                        FINALCOL.r = COLPIXELBASE.r * (1 - COLPIXELALPHA.a) + COLPIXELSPLAT.r * COLPIXELALPHA.a
                                        FINALCOL.g = COLPIXELBASE.g * (1 - COLPIXELALPHA.a) + COLPIXELSPLAT.g * COLPIXELALPHA.a
                                        FINALCOL.b = COLPIXELBASE.b * (1 - COLPIXELALPHA.a) + COLPIXELSPLAT.b * COLPIXELALPHA.a
                                        FINALCOL.a = 1
                                        'add to colors arraylist
                                        colors.Add(Context.Global.RGBA(FINALCOL.r, FINALCOL.g, FINALCOL.b, FINALCOL.a))
                                    Next
                                Next
 
                                'unlock splat textures
                                .UnlockTexture(isplatalphatex)
                                .UnlockTexture(isplattex)
 
                                'write pixel array to destination image
                                .SetPixelArray(ifinaltex, 0, 0, tsize.Width, tsize.Height, colors.ToArray(GetType(Int32)))
                            End If
                        End If
                    End If
                Next
 
                'post merge steps: (these will definately be different for you, but this is where you'll want to save the texture and do anything else to it)
 
                'unlock final texture
                .UnlockTexture(ifinaltex)
                'reenable landscape rendering
                Me.Enabled = True
 
                Dim texfile As String = Me.BaseTextureMap.Filename
                'overwrites existing texture map
                Context.TextureFactory.SaveTexture(ifinaltex, texfile, CONST_TV_IMAGEFORMAT.TV_IMAGE_JPG)
                'deletes from texfac and reloads the texture file
                Me.BaseTextureMap.RefreshTexture()
                'remove all splat layers from landscape
                Me.Splats.DisposeAll()
                Me.Splats.Clear()
                'recreate landscape
                Me.Recreate()
 
                'delete splat files associated with this landscape
                For Each splatfile As String In _
                    System.IO.Directory.GetFiles(Util.StripFilenameFromPath( _
                        Util.StripExtensionAndDotFromPath(texfile)))
                    If splatfile.ToLower.EndsWith(".splat") Then
                        If System.IO.File.Exists(splatfile) Then
                            System.IO.File.Delete(splatfile)
                        End If
                    End If
                Next
            End With
        End If
    End Sub
 
tutorialsarticlesandexamples/bake_terrain_splatting_to_a_single_texture.txt · Last modified: 2013/11/22 13:32