I understand that Blender is not a realtime 3d engine, so the material values aren’t limited to these and might not be named the same way.
But what is the “correct” mapping? What I have currently is just an educated guess:
diffuse:
material.diffuse_color = [diffuse[0], diffuse[1], diffuse[2]]
material.alpha = diffuse[3]
ambient:
material.mirror_color = [ambient[0], ambient[1],ambient[2]]
material.ambient = ambient[3]
specular:
material.specular_color = [specular[0], specular[1], specular[2]]
# 4th value (alpha) not used in Blender?
emissive:
material.emit = emissive[3]
# only one value?
shininess:
material.specular_hardness = (int(shininess)) # in Blender a float is expected, is this enough?
The “mirror color” is mulitplied against reflections, none of your properties fits that, so you should leave it at white.
In Blender, there is only one (scene) ambient color, and it is added according to the ambient factor. Unless you’re doing a more elaborate (node-based) material you can’t reproduce a per-material ambient term.
I don’t know what meaning an alpha value for specularity could have, except a weighting factor. So you should use it to drive specular intensity, I think.
I don’t know what to make of “in Blender a float is expected”
Blender uses an integer specular exponent in the [1,511] range.
I don’t know what to make of “in Blender a float is expected”
I wrote the opposite, I mean its float but Blender wants an int.
I need to have the materials of the models unchanged after I’ve gotten them in Blender and exported again.
So any ideas what else to use for the values?
I don’t know the meaning of the shininess in your context. In blender, it is an exponent (as used in blinn-phong) which is clamped to the range of [1,511]. In your case, is the shininess value just a float but is it still meant to be used as an exponent? In that case, you can just round it to an int, but you will have to accept that it will be clamped. It may also be that it is a float in the range[0,1] that maps to an exponent in some other range (for example [1,511]). Also note that the same exponent used in a blinn-phong shader will be visually slightly different from a phong shader.
I need to have the materials of the models unchanged after I’ve gotten them in Blender and exported again.
So any ideas what else to use for the values?
I think it’s up to your personal taste how to establish a bijection between the values. There isn’t an obvious one. You can add custom python properties to the material if you don’t want to abuse existing material properties.
I think there is always a “closer” mapping of the values, when things will shade more similarly in Blender and DirectX/OpenGL. So I think personal taste is secondary.
I managed to find the descriptions for diffuse, ambient, specular, emissive and shininess/hardness for OpenGL.
diffuse:
params contains four integer or floating-point values that specify
the diffuse RGBA reflectance of the material.
Integer values are mapped linearly such that the most positive representable
value maps to 1.0,
and the most negative representable value maps to -1.0.
Floating-point values are mapped directly.
Neither integer nor floating-point values are clamped.
The initial diffuse reflectance for both front- and back-facing materials
is (0.8, 0.8, 0.8, 1.0).
ambient:
params contains four integer or floating-point values that specify
the ambient RGBA reflectance of the material.
Integer values are mapped linearly such that the most positive representable
value maps to 1.0,
and the most negative representable value maps to -1.0.
Floating-point values are mapped directly.
Neither integer nor floating-point values are clamped.
The initial ambient reflectance for both front- and back-facing materials
is (0.2, 0.2, 0.2, 1.0).
specular:
params contains four integer or floating-point values that specify
the specular RGBA reflectance of the material.
Integer values are mapped linearly such that the most positive representable
value maps to 1.0,
and the most negative representable value maps to -1.0.
Floating-point values are mapped directly.
Neither integer nor floating-point values are clamped.
The initial specular reflectance for both front- and back-facing materials
is (0, 0, 0, 1).
emissive:
params contains four integer or floating-point values that specify
the RGBA emitted light intensity of the material.
Integer values are mapped linearly such that the most positive representable
value maps to 1.0,
and the most negative representable value maps to -1.0.
Floating-point values are mapped directly.
Neither integer nor floating-point values are clamped.
The initial emission intensity for both front- and back-facing materials
is (0, 0, 0, 1).
shininess:
params is a single integer or floating-point value that specifies
the RGBA specular exponent of the material.
Integer and floating-point values are mapped directly.
Only values in the range [0, 128] are accepted.
The initial specular exponent for both front- and back-facing materials
is 0.
I think there is always a “closer” mapping of the values, when things will shade more similarly in Blender and DirectX/OpenGL. So I think personal taste is secondary.
As I’ve outlined, there simply is no way to have per-material ambient term in a standard (non-nodes) Blender material. It’s also not possible to specify a separate emission color, blender will instead use the diffuse color. (I forgot to mention that initially)
If you want to maintain that information on repeated exports/imports you need to store it somewhere, either in some existing property that has a different meaning (like mirror color), or in a custom property that would have to be added to a material. If you want to reproduce the ambient term visually, you need to use nodes (and GLSL display). Exactly how you achieve this is a matter of taste, because there is no nice solution.
As for the shininess, I’m surprised it’s clamped at 128 already, but arguably that’s enough for vertex lighting. From what I can see, Direct3D uses Blinn-Phong shading, so the correct method to visually reproduce it, is to use “Blinn” as specular method in Blender, not “Phong” (which is the default). You can just use the “hardness” value directly, and accept that no values larger than 128 will be maintained.
On another Note: You are using the old fixed-function vertex shader pipeline that isn’t even available in newer versions of DirectX anymore. You should consider instead writing your own shaders and think about whether you really need something like per-material ambient. Furthermore, using your own shaders you could drive all these values by textures, as you can in Blender - and the quality of shading will be much better in a pixel/fragment shader, too.