shadowmage45 / TexturesUnlimited

KSP Shader, Texture, and Modeling Utilities
GNU General Public License v3.0
29 stars 17 forks source link

Incompatibility with MODEL { texture = } #50

Closed Electrocutor closed 6 years ago

Electrocutor commented 6 years ago

It seems that when TU is installed, any parts that make use of the built-in texture replacement from Squad causes a null reference.

Example: MODEL { model = model_path texture = original_tex_name,new_tex_path }

Something in the back of my head tells me that this has something to do with timing and material replacement.

shadowmage45 commented 6 years ago

Interesting....

Could be a few things, some of which I might be able to solve.

Could you provide a log file (or excerpt of the stack trace), or better yet, a simple config that triggers the problem? (even just swapping some random stock textures on stock parts) Would speed up the debugging process considerably if I know a bit more about where to start looking.

I try to support as many of the stock features as possible, in this case though there will likely be some un-resolvable conflicts due to both features trying to adjust the same thing. I thought that the stock texture-replacement code ran while the model was loaded (before TU adjusts anything), so in theory there should be no possibility for conflict at that point in model loading. If the stock code actually runs at some later point in loading, there is a much higher potential for conflict.

Electrocutor commented 6 years ago

KSP_MODEL_SHADER:NEEDS[TexturesUnlimited&SquadExpansion] { model = SquadExpansion/MakingHistory/Parts/Pods/Assets/RoundPod MATERIAL { shader = SSTU/PBR/StockMetallicBumped PROPERTY { name = _Metal float = 0.0 } } }


I suspect that if you maintain material names exactly as they were from the original material that it will not have a problem.

at PartLoader.ReplaceTextures (UnityEngine.GameObject model, System.Collections.Generic.List1 textureNames, System.Collections.Generic.List1 newTextures)

textureNames sounds like it's just a string that is stored and not a material reference.

shadowmage45 commented 6 years ago

Can confirm with the above config; thanks :)

Looking into it now. The stock texture replacement apparently happens during part-compilation (makes sense, as it is specified in the PART node), so TU has already run its model database manipulation.

Simply changing the shader shouldn't really interfere with texture replacement, as in the default setup I actually don't change the material name at all (the code is basically renderer.material.shader = newShader;).

My next ...guess... is that it might be related to the use of .material over .sharedMaterial. Unfortunately changing to use sharedMaterial is not compatible with user driven texture-switching. Will investigate if I can use sharedMaterial for prefabs, and instanced materials for editor texture switching.

shadowmage45 commented 6 years ago

This is all making even less sense. The materials appear to match exactly from both before, and after, adjustment from TU:

[LOG 10:43:15.214] Pre adjust
[LOG 10:43:15.214] rend: vostok (UnityEngine.MeshRenderer)
[LOG 10:43:15.214] tex: SquadExpansion/MakingHistory/Parts/Pods/Assets/KV1
[LOG 10:43:15.214] rend: Jettison (UnityEngine.MeshRenderer)
[LOG 10:43:15.214] tex: SquadExpansion/MakingHistory/Parts/Pods/Assets/KV1
[LOG 10:43:15.216] Post adjust
[LOG 10:43:15.216] rend: vostok (UnityEngine.MeshRenderer)
[LOG 10:43:15.216] tex: SquadExpansion/MakingHistory/Parts/Pods/Assets/KV1
[LOG 10:43:15.216] rend: Jettison (UnityEngine.MeshRenderer)
[LOG 10:43:15.216] tex: SquadExpansion/MakingHistory/Parts/Pods/Assets/KV1

My final though is that the replacement shader has more texture slots than the original shader, some of which may have null textures. Stock doesn't validate vs. null textures, and thus these error out when tested.

shadowmage45 commented 6 years ago

Yep, that is the culprit. The 'new' material has null texture references for any texture slot that did not exist on the original material (because you are using 'inheritance' mode, and have not properly assigned textures).

The original shader for that part doesn't have an BumpMap slot. The new shader does. However, you have not assigned a texture for that slot. Thus, KSP code crashes out when it tries to query properties on the texture in that slot.

This would not be a problem if using the 'new material' mode (e.g. inheritance disabled), as the material would be properly instantiated for the new shader (and would get the default flat color textures as defined in the shader source code). However, as you are using inheritance mode, it uses all of the existing properties from the original material -- which will include null/empty texture slots if they were not originally present.


The solution:

Not something that I can 'fix' any more than I already have. The solutions are available, but it is up to you to apply them to your configs.

The below config allows for the stock part to properly load:

KSP_MODEL_SHADER:NEEDS[TexturesUnlimited&SquadExpansion]
{
    model = SquadExpansion/MakingHistory/Parts/Pods/Assets/RoundPod
    MATERIAL
    {
        shader = SSTU/PBR/StockMetallicBumped
        PROPERTY
        {
            name = _Metal
            float = 0.0
        }
        PROPERTY
        {
            name = _BumpMap
            textureColor = 127,127,127,127
        }
        PROPERTY
        {
            name = _Emissive
            textureColor = 0,0,0,0
        }
    }
}

shadowmage45 commented 6 years ago

One final thought -- I might be able to add in a check to 'fix' missing textures for the texture-slots that the stock code looks for (main, bump, glow), by explicitly assigning them a texture if/when the slot is empty in the original material. (I think I had something like this in place in the 1.3.x versions, but removed them with the development of the 'non-inherited' material setup)

Electrocutor commented 6 years ago

That would be much appreciated. Just set anything null to a default black, white, or bump texture.

The above scenario doesn't work in a lot of cases because the shader is mass-applied across many models and is not specific to any particular texture. Thus, some will have normal maps and some will not.