0
$\begingroup$

I've built a 3D environment that looks like this (I'm using the game engine Monogame; but I don't think the game engine plays a part in this problem)

enter image description here

I'm using external assets for the terrain tiles, given as FBX files (in the graphics shown there are 4 such tiles). The way the FBX files come; they need their path to their texture updated. To get around this I import them into Blender (v3.4), make necessary fixes, and re-export them as new FBX files (producing a version that the game engine is able to deal with).

Essentially, I found two ways to convert the FBX files, (1) by updating the texture file reference, or (2) removing and recreating the material. While between these options 1. is more direct and obvious, I just assumed it shouldn't be a problem to do 2. by copying over any material properties.

But I'm not able to do this perfectly, getting a slightly darker render. It looks like I'm missing a configuration somewhere; possibly expressing something interesting. Whatever it is, I'm curious to know what is wrong with this idea, or where the hidden settings are.

enter image description here

Method 1

I import the external fbx from a new Blender document deleting all existing objects, then File > Import > FBX (.fbx), choosing CPT_Terrain_M_f_13.fbx. Showing

enter image description here enter image description here

I change the file reference of the existing Image Texture node (in the Shader Editor) to point to my own copy of the terrain texture CPT_Terrain_Texture_Atlas_01.png (located in my game-engine folder, the same directory that I export to below). It is also necessary to turn the Alpha up, for some reason the import comes with Alpha = 0 (perhaps it has something to do with the problem?). The only other change I make is 'Apply all transforms' (written into the export script).

I complete the export by running this script (saving the terrain-tile directly to the game engine folder). Without any change to the game engine itself, if I now run my game it will show the top render.

import bpy
def exportFbx(filenamepath):
    bpy.ops.object.transform_apply(location=True, rotation=True, scale=True)
    bpy.ops.export_scene.fbx(filepath = filenamepath, path_mode = 'STRIP', axis_up = 'Z')
exportFbx('Z:\\github\\LSystemsMG\\LSystemsMG\\Content\\terrain-tiles\\CPT_Terrain_M_f_13.fbx')

Method 2

I start in the same way, (i) open a new Blender file (ii) delete all objects (iii) import the same FBX file. Now, instead of changing the existing texture I delete and replace the existing material; effecting a new Principled BSDF node and Material Output node, I add to this a new Image Texture node and Normal Map node so that they are the same as observed (i.e. I set Normal Map to 'Tangent Space' and draw a connection to the BSDF). With this only the Specular and Roughness components in the Principled BSDF are different, otherwise all settings are the same.

I then export the FBX using the same Python script. This leads my game to producing the second darker render.

Properties seen

All the Material properties and properties in the Shader Editor are the same in both cases at time of export.

enter image description here

$\endgroup$

1 Answer 1

0
$\begingroup$

I found the answer; there are hidden properties in the materials not used by Blender but are still exported with FBX and, evidently, used by external parties such as my game engine's shaders (Monogame). Searching with scripts I found quite a few obscure values, but there was only one that I needed to change in my case, namely, the default value for the pincipled BSDF Base Color

enter image description here

Yes, there's a hidden value behind the texture node that is exported with FBX. The value can be read

bsdf = bpy.data.objects[0].data.materials[0].node_tree.nodes['Principled BSDF']
hidden_color_value = bsdf.inputs['Base Color'].default_value

In my case the new material I created needed to be updated from (0.8,0.8,0.8,1) to (1,1,1,1) to behave the same as the other

def setPrincipledBsdfBaseColorDefaultValue(r, g, b, a):
    bsdf = bpy.data.objects[0].data.materials[0].node_tree.nodes['Principled BSDF']
    bsdf.inputs['Base Color'].default_value = (r, g, b, a)
setPrincipledBsdfBaseColorDefaultValue(1,1,1,1)
$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .