powroupi / blender_mmd_tools

mmd_tools is a blender addon for importing Models and Motions of MikuMikuDance.
GNU General Public License v3.0
1.83k stars 277 forks source link

gamma correction? #139

Closed Hogarth-MMD closed 4 years ago

Hogarth-MMD commented 6 years ago

In mmd_tools, what is the correct mathematical formula for gamma correction? Apparently this should be done as an approximate square root of a color to convert it from color management sRGB to the color management None of MMD. This issue arises when converting Cookie Flex Rig or Sintel models to MMD, for example. These models appear excessively dark after exporting them to MMD. In mmd_tools, the Blender diffuse color is calculated as the average of the mmd ambient color and the mmd diffuse color. Is that really a mathematically correct formula? How should I program the gamma correction of the mmd diffuse color and the mmd ambient color?

nathanvasil commented 6 years ago

Raise the RGB values to the 1/2.2 power (0.4545) to import sRGB textures into uncorrected color spaces like MMD. (Yes, sRGB has a few details past that, but they're not very important.) For example, RGB (1,0.5, 0) would become RGB (1, 0.73, 0).

Is that really a mathematically correct formula?

No, but there is no mathematically correct formula; Blender and MMD do different things with lighting. In a huge number of different ways. It's not apples-to-apples.

How should I program the gamma correction of the mmd diffuse color and the mmd ambient color?

MMD does no gamma correction. If you want to emulate the MMD look in Blender perfectly, you need to load textures as non-color data (not passed through the sRGB conversion) and output without any gamma, via the settings on the scene/color management tab. If you want to emulate Blender accurately in MMD-- well, you need to write shaders to do that, and even then, you can only do so much. But at least making a gamma-correction shader is relatively simple.

For importing MMD models, probably the best thing to do is to multiply the texture value by the diffuse/ambient value before degamma on the product of the two (translation into sRGB). Ambient can be handled by emission that is added to diffuse/specular. But there's not really a single right answer, because MMD models weren't designed for gamma correction.

If you're using BI renderer, I'm not sure about how everything is done (I've been using Cycles; BI is getting tossed in 2.8). Cycles nodes are perfectly capable of adding color, clamping color, doing gamma manually, all that stuff (although no buffer shadows, so if I ever make an MMD shader for Cycles, it'll have to be through compositing through a shadow mask.)

powroupi commented 6 years ago

In my experience, the formula of MMD default lighting looks like (lightColor x diffuseColor + ambientColor) x textureColor, it is not guarantee to be correct though.

In Blender, I set material.diffuseColor = 0.5 x mmd.diffuseColor + mmd.ambientColor, assuming lightColor is (0.5, 0.5, 0.5). Click [Shadeless] of MMD Shading panel, the result is almost the same as MMD (when set MMD light color to (128, 128, 128)).

When converting model, I set mmd.diffuseColor = material.diffuseColor mmd.ambientColor = 0.5 x material.diffuseColor (Ambient Color Source Diffuse) So, original material.diffuseColor will not be changed. (0.5 x mmd.diffuseColor + mmd.ambientColor = 0.5 x material.diffuseColor + 0.5 x material.diffuseColor = material.diffuseColor)

You may try modifying the script operators/model.py to adjust the conversion of mmd.diffuseColor and mmd.ambientColor as you want. There is no gamma correction issue of the conversion I think. :yum:

Hogarth-MMD commented 6 years ago

I have a problem with the Blender diffuse color being defined as the average of mmd diffuse color and mmd ambient color. By definition, ambient color is shadow color, diffuse color is midtones color and specular color is color of highlights. In terms of MMD models, the toon texture is like an ambient texture and the sphere texture is like a specular texture. What I would like to do is make a gamma correction which caused an attractive-looking and correct color correction in BOTH Blender and MMD. But this is impossible with a defective mathematical formula. Logically the ambient color should be the lowest color of a diffuse color ramp, or similar.

Hogarth-MMD commented 6 years ago

"For importing MMD models, probably the best thing to do is to multiply the texture value by the diffuse/ambient value before degamma on the product of the two (translation into sRGB)."

In the case, it seems to me that a gamma correction might require an automated correction of texture images. Not so easy or convenient to program that.

Hogarth-MMD commented 6 years ago

"BI (Blender Internal Renderer) is getting tossed in 2.8"

That would cause countless tutorials and add-ons to get messed up and become obsolete. I sincerely hope that this insane stupidity will not happen.

powroupi commented 6 years ago

By definition, ambient color is shadow color, diffuse color is midtones color and specular color is color of highlights.

The default shading of MMD (without MME) doesn't look like following the definition, and I think it is better to do some correction in rendering (shaders) instead of correcting the PMX materials. :sunglasses:

nathanvasil commented 6 years ago

In the case, it seems to me that a gamma correction might require an automated correction of texture images. Not so easy or convenient to program that.

It's convenient if you use nodes. You can do any math operations you want. Load a tex, separate RGB, use a math node to raise to a power, then combine RGB. You can use these nodes for rendering or to bake new textures. Checking quickly in BI, it has all that you need for that (and I know from experience that Cycles does as well.)

Note that, outside of some material morphs, there's really little reason for a model to use both colored diffuse and a texture at the same time. Most MMD models you'll see will have a grayscale ambient and diffuse, at a fixed ratio for all non-emissive materials. Since Blender tonemaps, from unclamped floats, actual brightness values can't be directly compared, MMD's use of per-material ambient (rather than per-scene ambient) has probably always been a bad idea, but if it's something you want to capture, try treating MMD ambient as emissive and leaving it out of the diffuse calculation.

re: BI: https://twitter.com/tonroosendaal/status/986993540105457666/photo/1

Hogarth-MMD commented 6 years ago

"It's convenient if you use nodes." The nodes can't be exported to MMD.

Wow shocking news about 2.8! Thanks for the link. I'll be using 2 versions of Blender for some time to come, instead of updating Blender from 2.79b.

Hogarth-MMD commented 6 years ago

"Note that, outside of some material morphs, there's really little reason for a model to use both colored diffuse and a texture at the same time."

I agree with this statement. In a competently-designed render engine, I think that texture images should completely replace materials in rendering, if a texture image is present on a material. That simplification would give the user much tighter control over rendering, instead of randomly experimenting for hours until the user accidentally stumbles onto settings that look good.

nathanvasil commented 6 years ago

Here's a demo; http://www.mediafire.com/file/ngbwe26sq6jd2n6/gammademo.blend . Just hit bake. Or run bpy.ops.object.bake(type='EMIT') from a script.

It's just a cycles material that raises colors to the 1/2.2 power and outputs as emission. By baking this to texture-- which can be done programmatically-- you convert the texture.

Note that in Cycles, you designate the output image tex by having an image tex node referencing that image be the active selection in the nodes. It's a little awkward. Just letting you know because its different than BI and it's easy to just select some other node and have it suddenly stop working and not know why.

Note that while baking can be used to automate this, it's not really ideal, because baking involves a lot of other slow and unnecesssary (to this process) calculations.

Edit: regarding mat settings, yeah, a lot of mat-wide settings are designed to create things simply and rapidly. If you're having trouble getting good settings for stuff you're making, just give it a 1.0 white (oor whatever you want, just be consisent) diffuse if you're giving it a texture. Most anything referencing either just references diffuse*tex anyways, eliminating diffuse as a variable is a good idea whenever you're using textures. In Blender or in MMD.

nathanvasil commented 6 years ago

@Hogarth-MMD if you're still thinking about (un)doing automated gamma correction, doing it via compositing is probably better than doing it via baking-- it allows the exact same mathematical operations on colors, can be done through reasonably high level Blender operations, and skips a lot of the unnecessary calculations involved in baking textures.

Set everything to not render, set up compositing to ignore the render and just use an image (texture) as your source, and you can do things like color correction at reasonably high speed. Same kind of nodes, separate RGB, math, combine RGB. Set resolution to texture res, disable scene/color correction as necessary because compositing uses it whereas baking doesn't.

You'd still be doing things faster if you could go lower level and make direct edits to color values.

Hogarth-MMD commented 6 years ago

Thank you for your interesting ideas @nathanvasil , but Blender composited color change can't be exported to MMD, I don't think.

nathanvasil commented 6 years ago

Yes they can, by rendering and saving the image.

You tell MMD how to draw the surface by providing a texture. You can edit source textures by running them through compositing and saving those images.