Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by shrutiturner · Apr 09, 2018 at 02:36 PM · colorvertex shadergradient

Is it possible to create a colour gradient across an entire mesh if only a few vertices have colour?

I have been struggling to create a shader for my model of ~40,000 vertices. I have 144 vertices which I have assigned a colour to. (These 144 vertices represent real life data that I have obtained from sensors, so I can not increase the number of vertices initially coloured)

I would like to create a colour gradient between these vertices, so that the entire model is coloured, similar to a heat map.

I've tried using Lerp on the vertex matrix, but because the vertex numbers are seemingly random compared to their location, I'm not getting the interpolation between appropriate locations, rather neighbouring vertex numbers.

I have tried using something similar to this, but as I have so few vertices initially coloured, I just end up with a black model with colours spots: https://forum.unity.com/threads/standard-shader-with-vertex-colors.316529/

My question: is it possible to do it in this way? If not, is there another way? I can't seem to find one.

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image
1

Answer by Harinezumi · Apr 09, 2018 at 03:09 PM

Interesting, I've been working on something scarily similar...
Anyway, I just iterate through all the vertices of the model (mine is about 9000 vertices), and interpolate using the distance from each of my colored points. I use a Gradient object and a float[] heatValues (one value for each vertex) that stores the current "heat" value, then evaluate the gradient for each vertex, and finally assign the vertex colors.
It is faster than expected, there's no FPS drop even if I update every frame.
Does this make sense?

Comment
Add comment · Show 7 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image shrutiturner · Apr 10, 2018 at 11:03 AM 0
Share

That definitely makes me feel less crazy attempting this! Your description makes sense, just in the process of trying to write the code to do it - thank you :)

avatar image shrutiturner · Apr 11, 2018 at 09:06 AM 0
Share

For some reason, I can't get it to work. I end up with a fuzzy one coloured object. I've tried debugging and I think the logic is correct, but something (obviously) isn't right...

Here is the method I've written for the colour interpolation, I've tried to base it on your advice, but I'm not sure where I'm going wrong!

 private void ColourInterpolation()
     {
         List<$$anonymous$$eyValuePair<float, Vector3>> distances = new List<$$anonymous$$eyValuePair<float, Vector3>>();
 
         for (int i = 0; i < _vertices.Length; i++)
         {
             var skip = false;
             foreach (var sensor in _sensorLocations)
             {
                 var localVertex = transform.TransformPoint(_vertices[i]);
                 if (sensor.Value.x == $$anonymous$$ath.Round(localVertex.x, 1) &&
                     sensor.Value.y == $$anonymous$$ath.Round(localVertex.y, 1) &&
                     sensor.Value.z == $$anonymous$$ath.Round(localVertex.z, 1))
                 {
                     skip = true;
                     break;
                 }
             }
 
             if (skip)
             {
                 skip = false;
                 continue;
             }
 
             $$anonymous$$eyValuePair<int, Vector3> $$anonymous$$1 = new $$anonymous$$eyValuePair<int, Vector3>();
             $$anonymous$$eyValuePair<int, Vector3> $$anonymous$$2 = new $$anonymous$$eyValuePair<int, Vector3>();
             float $$anonymous$$1Distance = float.$$anonymous$$axValue;
             float $$anonymous$$2Distance = float.$$anonymous$$axValue;
 
             foreach ($$anonymous$$eyValuePair<int, Vector3> sensor in _sensorLocations)
             {
 
                 float distance = Vector3.Distance(_vertices[i], sensor.Value);
 
                 if (distance < $$anonymous$$1Distance)
                 {
                     $$anonymous$$2Distance = $$anonymous$$1Distance;
                     $$anonymous$$1Distance = distance;
 
                     $$anonymous$$2 = $$anonymous$$1;
                     $$anonymous$$1 = sensor;
                 }
                 else if (distance < $$anonymous$$2Distance)
                 {
                     $$anonymous$$2 = sensor;
                     $$anonymous$$2Distance = distance;
                 }
             }
 
             float proportion = $$anonymous$$ath.Abs($$anonymous$$1Distance / ($$anonymous$$1Distance + $$anonymous$$2Distance)); // Gives proprtion towards $$anonymous$$1
 
             _colors[i] = Color32.Lerp(_colors[$$anonymous$$1.$$anonymous$$ey], _colors[$$anonymous$$2.$$anonymous$$ey], proportion);
         }
avatar image Harinezumi shrutiturner · Apr 11, 2018 at 10:29 AM 1
Share

Your algorithm seems good, but I think you need the 3 closest sensors to get a uniformly interpolated color in 3D, and you might need to do interpolate using barycentric coordinates, see this article.

I think you can also simplify the check if the vertex is one of the sensors like this:

 // this works if _sensorLocations is a dictionary of vertex index to sensor vertex position
 if (_sensorLocations.Contains$$anonymous$$ey(i)) { continue; }


avatar image shrutiturner Harinezumi · Apr 11, 2018 at 01:26 PM 0
Share

Something still isn't right with my interpolation...I'm now getting multiple colours, but I'm getting a massive mess...think an explosion in a paint factory! I've adapted the barycentric equations to incorporate 3D rather than just 2D, but the results seem to be the same.

Is there something obvious I'm doing wrong?

             $$anonymous$$eyValuePair<int, Vector3> $$anonymous$$1 = new $$anonymous$$eyValuePair<int, Vector3>();
             $$anonymous$$eyValuePair<int, Vector3> $$anonymous$$2 = new $$anonymous$$eyValuePair<int, Vector3>();
             $$anonymous$$eyValuePair<int, Vector3> $$anonymous$$3 = new $$anonymous$$eyValuePair<int, Vector3>();
             float $$anonymous$$1Distance = float.$$anonymous$$axValue;
             float $$anonymous$$2Distance = float.$$anonymous$$axValue;
             float $$anonymous$$3Distance = float.$$anonymous$$axValue;
 
             foreach ($$anonymous$$eyValuePair<int, Vector3> sensor in _sensorLocations)
             {
 
                 float distance = Vector3.Distance(_vertices[i], sensor.Value);
 
                 if (distance < $$anonymous$$1Distance)
                 {
                     $$anonymous$$3Distance = $$anonymous$$2Distance;
                     $$anonymous$$2Distance = $$anonymous$$1Distance;
                     $$anonymous$$1Distance = distance;
 
                     $$anonymous$$3 = $$anonymous$$2;
                     $$anonymous$$2 = $$anonymous$$1;
                     $$anonymous$$1 = sensor;
                 }
                 else if (distance < $$anonymous$$2Distance)
                 {
                     $$anonymous$$3 = $$anonymous$$2;
                     $$anonymous$$2 = sensor;
 
                     $$anonymous$$3Distance = $$anonymous$$2Distance;
                     $$anonymous$$2Distance = distance;
                 }
                 else if (distance < $$anonymous$$3Distance)
                 {
                     $$anonymous$$3 = sensor;
                     $$anonymous$$3Distance = distance;
                 }
             }
 
             float Xv1 = $$anonymous$$1.Value.x;
             float Xv2 = $$anonymous$$2.Value.x;
             float Xv3 = $$anonymous$$3.Value.x;
 
             float Yv1 = $$anonymous$$1.Value.y;
             float Yv2 = $$anonymous$$2.Value.y;
             float Yv3 = $$anonymous$$3.Value.y;
 
             float Zv1 = $$anonymous$$1.Value.z;
             float Zv2 = $$anonymous$$2.Value.z;
             float Zv3 = $$anonymous$$3.Value.z;
 
             float Px = _vertices[i].x;
             float Py = _vertices[i].y;
             float Pz = _vertices[i].z;
 
 
             float Wv1 = ((Yv2 - Yv3) * (Px - Xv3) + (Xv3 - Xv2) * (Py - Yv3)) / ((Yv2 - Yv3) * (Xv1 - Xv3) + (Xv3 - Xv2) * (Yv1 - Yv3));
             float Wv2 = ((Yv3 - Yv1) * (Px - Xv3) + (Xv1 - Xv3) * (Py - Yv3)) / ((Yv2 - Yv3) * (Xv1 - Xv3) + (Xv3 - Xv2) * (Yv1 - Yv3));
             float Wv3 = (Pz - Wv1*Zv1 - Wv2*Zv2)/Zv3;
 
             Byte r = (Byte)((_colors[$$anonymous$$1.$$anonymous$$ey].r * Wv1 + _colors[$$anonymous$$2.$$anonymous$$ey].r * Wv2 + _colors[$$anonymous$$3.$$anonymous$$ey].r * Wv3) / 3);
             Byte g = (Byte)((_colors[$$anonymous$$1.$$anonymous$$ey].g * Wv1 + _colors[$$anonymous$$2.$$anonymous$$ey].g * Wv2 + _colors[$$anonymous$$3.$$anonymous$$ey].g * Wv3) / 3);
             Byte b = (Byte)((_colors[$$anonymous$$1.$$anonymous$$ey].b * Wv1 + _colors[$$anonymous$$2.$$anonymous$$ey].b * Wv2 + _colors[$$anonymous$$3.$$anonymous$$ey].b * Wv3) / 3);
 
             _colors[i] = new Color32(r, g, b, 255);

Show more comments

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

76 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Changing the color of individual particles 0 Answers

WaterProDaytime with color gradient 1 Answer

How do I adapt this vertex manipulation shader so that my object (point cloud) keeps its original colouring? 0 Answers

Apply gradient between two colors on x amount of objects 1 Answer

Gradient Text in Unity 5.2.2 "BaseVertexEffect is obsolete use BaseMeshEffect instead" 3 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges