How do I assign colours to specific vertices on a mesh and interpolate between them?
I have a mesh with ~44000 vertices representing a real world object with 144 sensors arranged around it giving realtime data. I need to map the data from these sensors onto the unity model, with an associated colour, and interpolate linearly between them to give a smooth colour map.
I have so far managed to assign colours to the 144 sensors, but I am struggling to interpolate correctly. I have tried using 'Lerp' in the main Unity code but as my vertex numbers are not ordered in terms of location I end up with a bit of a mess. Is there a way to do this in the Shader on with the colours?
Please find my code below
Shader:
Shader "custom/MyShader" {
Properties{
_Color("Color", Color) = (1,1,1,1)
_MainTex("Albedo (RGB)", 2D) = "white" {}
_Glossiness("Smoothness", Range(0,1)) = 0.5
_Metallic("Metallic", Range(0,1)) = 0.0
}
SubShader{
pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float4 color : COLOR;
};
struct v2f
{
float2 uv : TEXCOORD0;
UNITY_FOG_COORDS(1)
float4 vertex : SV_POSITION;
float4 color : COLOR;
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert(appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.color = v.color;
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}
float4 frag(v2f i) : SV_Target
{
return i.color;
}
ENDCG
}
}
FallBack "Diffuse"
}
Unity:
public class VertexHighlighter : MonoBehaviour
{
private static int[] _sensorVertices = { /*144 numbers in an array*/ };
private static Mesh _mesh;
private static Vector3[] _vertices;
private static Color32[] _colors;
void Start()
{
_mesh = GetComponent<MeshFilter>().mesh;
_vertices = _mesh.vertices;
//Create new colors array where the colors will be created.
_colors = _mesh.colors32;
System.Random rnd = new System.Random();
foreach (var vertex in _sensorVertices)
{
byte r = (byte)rnd.Next(0, 255);
byte g = (byte)rnd.Next(0, 255);
byte b = (byte)rnd.Next(0, 255);
var x = new Color32();
_colors[vertex] = new Color32(r, g, b, 255);
}
}
Answer by Ryan_Sharax · Apr 09, 2018 at 07:42 AM
Firstly you are creating an 'x' var in your foreach loop, which is never use.
That can go away.
Secondly from what I can see, you are never re-assigning the altered _colours array back to the mesh. heres my modified version of your start function (im not at my unity computer to test right now but hopefully this will at least point you in the right direction)
void Start()
{
_mesh = GetComponent<MeshFilter>().mesh;
_vertices = _mesh.vertices;
//Create new colors array where the colors will be created.
_colors = _mesh.colors32;
System.Random rnd = new System.Random();
foreach (var vertex in _sensorVertices)
{
byte r = (byte)rnd.Next(0, 255);
byte g = (byte)rnd.Next(0, 255);
byte b = (byte)rnd.Next(0, 255);
_colors[vertex] = new Color32(r, g, b, 255);
}
_mesh.colors32 = _colors;
}
I dont know much about shaders either to be fair but I know that this shader is a simple surface shader and should do the interpolation just fine:
Shader "Custom/MyShaders/VertexColorShader"
{
Properties
{
}
SubShader
{
Tags { "RenderType"="Opaque" }
CGPROGRAM
#pragma surface surf Lambert vertex:vert
struct Input
{
float4 vertColor;
};
void vert(inout appdata_full v, out Input o)
{
UNITY_INITIALIZE_OUTPUT(Input, o);
o.vertColor = v.color;
}
void surf (Input IN, inout SurfaceOutput o)
{
o.Albedo = IN.vertColor.rgb;
}
ENDCG
}
}
You might be fine using your shader, just by making sure you re-assign the _colors array back to the mesh, but if not, just check using this shader.
Thanks for your response. I understand the comments about the 'Unity' part of the code and have adjusted accordingly.
I'm just still a bit stumped on the shaders part. The code that you've written gives me pretty much exactly what I have currently: a black model, with some vertices coloured (as per the unity code). Is there something that I am implementing wrong?
Well, if you are only giving some of the verts a colour then only those verts will be coloured. the interpolation / bleed for the colour will only interpolate to the next vertex. and as most of your vertices are going to be 'black' or have no colour your interpolation from a sensor vertex is going to go from 'bright colour' to black only from that one vertex, to all neighboring ones.
If you want the colour to bleed more or have a more gradual interpolation you'll have to consider colouring more than just the sensor verts.
(if I'm understanding correctly)
Ah okay - that makes sense. I didn't realise that the interpolation would only go to the neighbourghing vertices. Unfortunately, I only have the data for the 144 sensors so I won't be able to assign more vertices with a colour.
I was hoping there would be a way to create a colour gradient between the vertices which are coloured to begin with so that the whole model is coloured, to give something similar to a heat map.
Your answer
Follow this Question
Related Questions
Artifacts Shader Graph vertex colors 0 Answers
Vertex Shader bug in Mobile with noise screen effects 0 Answers
Trying to add dither to shader with vertex color 2 Answers
Add fog to vertex shader 0 Answers