- Home /
Why do my mesh colors blend sometimes and sometimes not?
Hi Everyone,
at this moment i'm experimenting with vertex coloring and creating raycasts that change the color of vertices of an object. So far i'm doing quite well, but i still have one problem. Every time i use the shader and the rayvast the triangles that get hit are getting colored properly. I change the vertex color of the each of the 3 vertices of a triangle and the triangle changes color. As i would expect 2 triangles connected to each other are influenced by the same vertex so if 1 triangle is hit it will blend out its color to the triangle next to it. Sometimes however it doesn't. In the picture below i have created an example where one can see what i mean.
At circle 1 it is clear that the top vertex has a color around bluegreen and it perfectly blends to the color blue int he vertex below. However at circle 2 the top vertex should be somewhat bluegreen as well but below the vertex it suddenly is a lot less green. Doe someone have any clues how i can fix this or where the problem comes from?
Answer by rockin · Aug 19, 2016 at 01:28 PM
To me it looks like a problem with the mesh: - it either has normal smoothing issues => in this case if you have 3ds max you can apply a smoothing modifier with only one smoothing group - or it has a duplicate vertex somewhere and the triangles don't share the actual same edge (there are two edges overlapped) => if you have 3ds max you can check topology using X view or the STL check modifier.
Thnx for that answer, I was already thinking that something like that could be the problem. There is only one problem though, it happens on capsules as well and i dont suspect that there are problems with the (unity) built-in capsule model. I attached an extra picture of it showing it and the used code that is used to color the vertices. 
for (int j = 0; j < 3; j++)
{
if (colors[triangles[hit.triangleIndex * 3 + j]].g == 0xFF && colors[triangles[hit.triangleIndex * 3 + j]].r !=0xFF)
{
colors[triangles[hit.triangleIndex * 3 + j]].b -= 15;
colors[triangles[hit.triangleIndex * 3 + j]].r += 15;
continue;
}
if (colors[triangles[hit.triangleIndex * 3 + j]].b == 0xFF)
{
colors[triangles[hit.triangleIndex * 3 + j]].g += 15;
continue;
}
if (colors[triangles[hit.triangleIndex * 3 + j]].r == 0xFF && colors[triangles[hit.triangleIndex * 3 + j]].g != 0x00)
{
colors[triangles[hit.triangleIndex * 3 + j]].g -= 15;
continue;
}
}
I'm assu$$anonymous$$g you are using a mesh collider and not a capsule collider?
Becaue according to the docs:
Triangle index is only valid if the collider that was hit is a $$anonymous$$eshCollider.
Also, are you sure all vertex colors start with the same color value? Because if b is 254 ins$$anonymous$$d of 255 for instance your code wouldn't do anything with those points.
I dont's see a problem with your code at first sight (except for it being overly complicated for debugging purposes, for debugging I would simplify it by moving to a certain fixed color (white for instance) in all cases to make sure your error isn't about missing an if statement ;)
Also, sinse a texture needs to wrap around a capsule correctly, it should at least have one seam where there are double vertices with different uv values. (this could be that blue line you are experiencing)
Well, you'd be surprised about the Unity capsule :)
$$anonymous$$esh mesh = GetComponent<$$anonymous$$eshFilter>().mesh;
Vector3[] vertices = mesh.vertices;
int i = 0;
while (i < vertices.Length)
{
int j = i+1;
while (j < vertices.Length)
{
if (vertices[i] == vertices[j] && i != j)
overlapping++;
j++;
}
i++;
}
I ran the code above and it returns 166 cases of overlapping, so for the capsule it's definitely an issue with the mesh.
As for your own objects, if you think they are clean, you can try disabling any mesh optimization that Unity does at import:
On your asset go to $$anonymous$$odel > $$anonymous$$esh Compression: Off
Player > Other settings > change Vertex compression to Nothing and turn of Optimize $$anonymous$$esh Data.
This is suboptimal for performance, but maybe it'll make it easier for you to find out what's going on.
Answer by Bunny83 · Aug 20, 2016 at 04:15 AM
Actually pretty much any model needs some seams. Either because of vertex normals (seam required for hard edges like in a cube mesh) or because of UV seams. If the object is UV mapped you will need seams.
You can use my UVViewer to see the UV map of a mesh inside Unity. Just open the UVViewer window from the tools menu and select an object in the scene that has a MeshRenderer. Keep in mind that a mesh can even have multiple UV channels.
If you don't need any texture / lightmapping you could theoritically create a fully shared mesh with no duplicates, but such a case is extremely rare.
As actual solution you might want to setup "vertex groups" so you can easily find the other vertices which belong to the same position. To setup such a structure you can simply use an array of a small custom class like this:
public class Vertex
{
public int index; // a vertex index
public Vertex next = null; // next vertex that belongs to the same group.
}
public Vertex[] vertexGroups = new Vertex[vertices.Length];
void AddVertex(int aIndex1, int aIndex2)
{
vertexGroups[aIndex1] = new Vertex { index = aIndex2, next = vertexGroups[aIndex1]};
var n = vertexGroups[aIndex2];
while (n != null)
{
vertexGroups[n.index] = new Vertex { index = aIndex1, next = vertexGroups[n.index] };
vertexGroups[aIndex1] = new Vertex { index = n.index, next = vertexGroups[aIndex1] };
n = n.next;
}
vertexGroups[aIndex2] = new Vertex { index = aIndex1, next = vertexGroups[aIndex2]};
}
for (int i = 1; i < vertices.Length; i++)
{
Vector3 pos = vertices[i];
for(int n = 0; n < i; n++)
{
if (vertices[n] == pos)
{
AddVertex(i, n);
break;
}
}
}
Haven't tested that code for errors but it should work. You'll end up with an array where each element represents a simple linked list. If the vertex is unique, the element in the "vertexGroups" array will be "null". It's only set to something if there are "paired" vertices. The vertexGroups element for a certain vertex index only contains the "other" vertices, not itself.
So once you setup that array in Start you can simply iterate through all paired vertices.
Say you picked the vertex with index 25. You would simply set the color of vertex 25 and in addition do this:
int index = 25;
colors[25] = YourColor;
for(var n = vertexGroups[index]; n != null; n = n.next)
colors[n.index] = YourColor;
If the vertex is a unique vertex the for loop will be skipped since n is null in that case. This will set the color of all vertices which are at the same position.
ps: Just leave a comment if you want a more detailed description of what AddVertex does. I Thought about writing some comments, but then it just gets messy ^^.
Thanks as you and troien are stating it probably comes from doubles indeed. I'm going to check how to solve that and i will take into account your solution for that. Again a lot of thanks for the help.
Answer by qqqqqym · May 11, 2020 at 09:47 AM
Hey, guys. I encountered the same problem when using Mesh.colors array: the color change is not smooth.
Is your problem solved? Can you share your solution? Thanks a lot :)
I have browsed many posts and it seems that using shader instead of Mesh.color can solve this problem.
Your answer
Follow this Question
Related Questions
How can I write a custom cutout diffuse shader that supports custom vertex colors? 1 Answer
How to use mesh data in shader 0 Answers
How does appdata_base work? 0 Answers
Change mesh color with shader or Mesh.colors? 1 Answer
Geomorphing terrain with a vertex shader (custom vertex data maybe?+ 0 Answers