1
$\begingroup$

I'm using vertex colors to control texture splatting on my model. Each color channel controls the blending weight of a texture:

pixel = (texture1 * vertex.r) + (texture2 * vertex.g) + (texture3 * vertex.b);

To achieve consistent results, I want the sum of all color channels to be 1.0 in all cases.

Otherwise I would sum up multiple textures resulting in brightness > 1. Here's an example of what would happen if colors aren't normalized (that lower left corner has been painted with all three color channels set to 1, so its brightness is r+g+b=3):

non-normalized weights

node-based splat material

Is there a way to "normalize" a color (just like I would normalize vertex group weights) in Blender?

$\endgroup$
2
  • $\begingroup$ I assume the code you posted there is for a GLSL shader? Could you not just use vert_NORM = normalize(vertex);? $\endgroup$ Nov 19, 2014 at 19:57
  • $\begingroup$ It's pseudocode to illustrate what the shader would do. I could normalize in the shader, but then I wouldn't get an accurate preview in Blender (no color normalize operate in Blender's node-based materials). It would also do the normalization millions of times per second whereas it could just do it once during preprocessing (but maybe I'm micro-optimizing here). $\endgroup$
    – Cygon
    Nov 22, 2014 at 18:10

1 Answer 1

0
$\begingroup$

I've managed to script myself a solution:

import bpy
import random
import math
from mathutils import Color, Vector

bl_info = {
  "name": "Vertex Color Normalizer",
  "description": "Allows the vertex colors of a mesh to be normalized (useful if colors control texture splatting).",
  "author": "Markus Ewald",
  "version": (1, 0),
  "blender": (2, 65, 0),
  "location": "View3D > Add > Mesh",
  "warning": "", # used for warning icon and text in addons panel
  "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"
              "Scripts/VertexColorNormalizer",
  "category": "Paint"
}

class VertexColorNormalizer(bpy.types.Operator):
    bl_idname = "object.normalize_vertex_colors"
    bl_label = "Normalize Vertex Colors"
    bl_description = "Normalize vertex colors to enable additive texture splatting"

    def execute(self, context):

        # What I want to do:
        # - Iterate over the colors of all the vertices in active mesh
        # - Normalize each color (divide by sqrt(r *r + g * g + b * b))
        # - Assign it back to the vertex

        for i in context.active_object.data.vertex_colors[0].data:   
            r = i.color[0]
            g = i.color[1]
            b = i.color[2]

            magnitude = math.sqrt(r * r + g * g + b * b)
            if magnitude > 1:
                normalized_color = (r / magnitude, g / magnitude, b / magnitude)
                i.color = Color((normalized_color))

        return {'FINISHED'}

def register():   
    bpy.utils.register_class(VertexColorNormalizer)   

if __name__ == "__main__":   
    register()  
  • Save as C:\Users\<Login>\AppData\Roaming\Blender Foundation\Blender\2.72\scripts\addons\NormalizeVertexColors.py
  • Start Blender, activate Preferences, Addons, Paint, "Vertex Color Normalizer"
  • Select target mesh, spacebar, type 'normalize' and pick the "Normalize Vertex Colors" entry

My knowledge of Python or the Blender object model are too limited to let this happen automatically when painting vertices, but it's better than nothing, I guess :)

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.