Textures

How Textures Work In FuncGodot

If you take a look at a .map file, you'll see that it's just a text file describing the makeup of your map and doesn't actually store any other data, including texture images. Let's look at this example of a Solid Entity in a map file:

Solid Entity Example

// entity 1
{
"classname" "func_detail"
// brush 0
{
( -32 -64 -16 ) ( -32 -63 -16 ) ( -32 -64 -15 ) __TB_empty [ 0 -1 0 0 ] [ 0 0 -1 0 ] 0 1 1
( -64 -32 -16 ) ( -64 -32 -15 ) ( -63 -32 -16 ) __TB_empty [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1
( -64 -64 -32 ) ( -63 -64 -32 ) ( -64 -63 -32 ) special/clip [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1
( 64 64 32 ) ( 64 65 32 ) ( 65 64 32 ) __TB_empty [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1
( 64 32 16 ) ( 65 32 16 ) ( 64 32 17 ) special/clip [ -1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1
( 32 64 16 ) ( 32 64 17 ) ( 32 65 16 ) special/clip [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 1 1
}
}

This is a func_detail entity from the default FuncGodot.fgd. As you can see, the map file structure is pretty straight-forward. This particular map uses the Valve 220 format, having additional options for UV mapping. Each line in a brush definition describes a face on the brush, and within that you can see that our texture is defined as just its location relative to the game's texture folder or map's WAD file.

But if that's the case, how does FuncGodot know what file to use?

FuncGodot Map Settings have several properties that help define and apply textures to your meshes on build:

FuncGodotMapSettings properties

FuncGodot's first step is to search the Base Texture Dir for a prebuilt material as defined by the brush face's texture name in the format defined by Material File Extension.

If it does not find this prebuilt material, it will search the Base Texture Dir for the Texture2D resource by the brush face's texture name using any one of the extensions defined by Texture File Extensions. If it finds the Texture2D, it will create a copy of the Default Material and apply the Texture2D as the duplicated material's albedo.

If it does not find the Texture2D, then it will use the default_texture.png found in the addons/func_godot/textures/ folder.

Default texture

Once the material generation is completed, you can optionally have FuncGodot save generated materials so they can be reused by multiple FuncGodotMaps. Otherwise each FuncGodotMap will have its own unique material for each texture used in the map.

Automatic PBR Generation

You may have noticed that we skipped over a few settings before, all of them with the suffic "Map Pattern". FuncGodot has the ability to automatically generate PBR materials on build. Each of the "Map Pattern" properties tell FuncGodot's Texture Loader how to find each PBR map for our texture.

What's with all the %s everywhere?

It's a placeholder token that gets replaced during texture loading. Each pattern requires two %s tokens. The first token is for the texture's name as it appears in the map file. The second token is for the file extension; this is replaced as the Texture Loader cycles through the Map Settings' Texture File Extensions searching for your texture. So if Texture Loader is looking for the normal map of a texture with the name "rock" and our Map Settings' Normal Map Pattern is "%s_normal.%s" and it is currently checking for the "png" Texture File Extension, then it will be looking to see if the texture resource "rock_normal.png" exists, and if so it will be applied to the Map Settings' Default Material if it is a StandardMaterial3D.

Clip and Skip Textures

Mapping for Quake Godot

We started off this manual with the point that FuncGodot is not a BSP compiler. If we map like we do in traditional Quake mapping...

... we don't get the same result.

Instead we need to change our approach.

For those not familiar with traditional Quake mapping, the finished MAP gets compiled into a BSP file to be read by the engine. The compiling process calculates visibility between all of the rooms of your map and removes all faces that won't be viewed due to being outside the map. That means maps must be sealed completely, but you're also allowed to be lazy with brush texturing since if a face is "outside" the map it will get culled.

With Godot we need to think of these brushes as what they'll become in-engine: composited MeshInstance3Ds and CollisionShape3Ds. If we want to achieve the culled result on the left, we'll need to change the way we do things on the right.

Skip It

Clip texture Skip texture

The Clip and Skip textures are arguably our most important textures when mapping for Godot. You can assign any texture's name to the Clip and Skip properties of the FuncGodotMapSettings resource. But what do they do?

The Clip texture will remove any face textured with it from the generated MeshInstance3D. The Skip texture behaves the same way if the Solid Entity's Collision Type is set to Convex. However, if the Solid Entity's Collision Type is set to Concave, this also removes the Skip textured faces from the generated CollisionPolygonShape3D.

Just keep in mind the general rule of thumb: if you want your entities to collide with the brush, use Clip...

... and if you want them to pass through, use Skip (with Concave collision).

WAD Files

FuncGodot provides the option to use Texture WAD files for your map materials. It's generally not recommended if it can be helped, but support for loose texture images varies from map editor to map editor.

To use a WAD file with your FuncGodotMap just add your imported WAD resource to the map node's Texture Wads array.

The neat thing about how FuncGodot handles map textures is that we can technically use a completely different folder in TrenchBroom and even different image formats than the location and formats we keep them in Godot. This can be useful for advanced users, but you may want to just keep all of your textures unified.

Why Are My Textures Blurry!?

You may be encountering at least one of two issues: texture compression and / or material sampling settings.

Make sure your texture resource is set to either Lossless or VRAM uncompressed. Please refer to the Godot documentation on texture compression.

If you had created your own materials for your map, check that the material's or texture's Sampling Filter is set to Nearest Mipmap. Please refer to the Godot documentation on texture filtering.