Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 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 /
This question was closed Oct 08, 2018 at 11:53 AM by Bunny83 for the following reason:

The question is answered, right answer was accepted

avatar image
2
Question by Jiexi · Sep 26, 2013 at 08:16 AM · shaderverticesvertexvertexshader

Moving vertices in shaders

Hi there,

For my project I have to manipulate mesh at runtime, to do this without clearing and refilling the mesh array (which is very expensive) I'm going to do it in a shader, atleast, try to.

I've browsed the web, including unity answers intensely but I just can't find a tutorial or document which tells me step by step how to achieve this.

The tutorial on displaying normal colors was already a great help, but the shader documentation is still a bit confusing for me (someone who just started to delve into Unity shaders).

I have come as far as:

     Properties{
          _vertPos("VertPos", vector) = (0,0,0,1) //this to initialize
     } 

then outside the struct i define my float4 vertPos; I am able to fill in the vector from script and read it by using

set/getVector("_vertPos");

I've added

#pragma surface surf Lambert vertex:vert

to specify my vertex function, and made a function:

 float4 vert(float4 v:POSITION) : SV_POSITION
 {
 
 }

But now I'm stuck, and I honestly can't find something that simply specifies how to move a specific vertex. I got the function parameters from the unity documentation, but i'm still unclear what this does, or where i have to put the inout, because I think i have to get the appdata_base in there and find and access the vertices, and hopefully manipulate them according to their location. The main thing I want to manipulate is the height.

I am quite aware of matrix structures, it's just the syntax I'm really struggling with

Any help or an alternative way of moving vertices from a mesh would be much appreciated.

Comment
Comments Locked
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

  • Sort: 
avatar image
6
Best Answer

Answer by tanoshimi · Sep 26, 2013 at 09:33 AM

The vertex modifier function of a surface shader doesn't just have an float4 POSITION input and return a float4 SV_POSITION output - rather it operates on the entire appdata_full structure, of which "vertex" is a member. Here's an example of a vertex modifier that modifies the "height" (i.e. z value) of vertices:

   Shader "Vertex Modifier" {
     Properties {
       _MainTex ("Texture", 2D) = "white" {}
       _Amount ("Height Adjustment", Float) = 1.0
     }
     SubShader {
       Tags { "RenderType" = "Opaque" }
       CGPROGRAM
       #pragma surface surf Lambert vertex:vert
       struct Input {
           float2 uv_MainTex;
       };
 
       // Access the shaderlab properties
       float _Amount;
       sampler2D _MainTex;
 
       // Vertex modifier function
       void vert (inout appdata_full v) {
           // Do whatever you want with the "vertex" property of v here
           v.vertex.z += _Amount;
       }
 
       // Surface shader function
       void surf (Input IN, inout SurfaceOutput o) {
           o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
       }
       ENDCG
     }
   }
Comment
Comments Locked · Show 20 · 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 Fattie · Sep 26, 2013 at 09:46 AM 0
Share

"impressive"

avatar image tanoshimi · Sep 26, 2013 at 11:54 AM 1
Share

Yes you can manipulate individual vertices based on their x/y/z coordinates - these are in the model's local coordinate system. Note that these are floating point values so you might want to avoid exact equality tests like == though - best to use an approximation within a certain error range. And yes, if statements are possible in shaders (as are most C language constructs - for loops, sin/modulo/exponents etc.). They do incur a performance hit, but don't worry about that too much for now - glad you've got something working!

avatar image tanoshimi · Sep 26, 2013 at 03:08 PM 2
Share

Yes, you should never compare whether a floating point value is exactly equal to another value (in any program$$anonymous$$g language), because there is an inherent degree of approximation in floating point arithmetic (in layman's terms, exactly as you say "1.0" might actually be "0.99999987", or similar).

So, a better test might be to see whether the absolute difference between two floating point values is within a certain error tolerance. For example something like: if(abs(v.vertex.x - _Xpos) < 0.01 && ...

And, yes, debugging shaders is a pain, because they're executed on the GPU and you can't write handy "print" debug messages to see what's going on. I typically debug to see whether a certain block of code is being executed by making gross changes within that block (making the entire texture yellow, scaling the whole model by 20x or something).

avatar image Jiexi · Sep 26, 2013 at 04:27 PM 1
Share

Your tips are great and your help is so much appreciated :D I wouldn't have gotten half as far without you. $$anonymous$$udos!

I will try and test and publish my results here so future people who are as inexperienced with shaders as I am can learn from these posts.

avatar image Jiexi · Sep 30, 2013 at 08:45 AM 1
Share

Victory! (kudos to the participants in this threat, tanoshimi in particular) I've cast it to world space, and based on their coordinates (rounded) they will grow. These are my final results:

 Shader "Custom/vertexShader_program" {
 
     Properties {
         _$$anonymous$$ainTex ("Base (RGB)", 2D) = "white" {}
         _Amount ("Height", Float) = 1.0 //this will be incremented in script
         _xPos ("xPos", float) = 5.0 //just to test, these can be filled from script with desired values.
         _zPos ("zPos", float) = 3.0 //It might be wise to optimise this to a float2
     }
     SubShader {
         Tags { "RenderType"="Opaque" }
         LOD 200
         
         CGPROGRA$$anonymous$$
         #pragma surface surf Lambert vertex:vert
 
         sampler2D _$$anonymous$$ainTex;
         float _Amount;
         float _xPos;
         float _zPos;
         
         struct Input {
             float2 uv_$$anonymous$$ainTex;
         };
         
          void vert (inout appdata_full v)
          {         
              float3 castToWorld = round(mul(_Object2World, v.vertex) );
              if(castToWorld.x == 5.0 && castToWorld.y < _Amount && castToWorld.z == -1.0)
              {
                  v.vertex.y+= _Amount;
              }
           }
 
         void surf (Input IN, inout SurfaceOutput o) {
             half4 c = tex2D (_$$anonymous$$ainTex, IN.uv_$$anonymous$$ainTex);
             o.Albedo = tex2D (_$$anonymous$$ainTex, IN.uv_$$anonymous$$ainTex).rgb;
             o.Alpha = c.a;
         }
         ENDCG
     } 
     FallBack "Diffuse"
 }


Script: using UnityEngine; using System.Collections;

 public class ShaderVariables : $$anonymous$$onoBehaviour {
 
     // Use this for initialization
     GameObject target;
     Shader targetShader;
     $$anonymous$$aterial mat;
     float desired = 5.0f;
     
     void Start () {
         target = GameObject.Find("Plane"); //get my plane, I will do this later on by creating primitives.
         targetShader = target.GetComponent<$$anonymous$$eshRenderer>().material.shader; //get the shader, this is handy if you want to switch shaders. 
         mat = target.GetComponent<Renderer>().material;    //and get my material, where I can send my variables to
     }
     
     // Update is called once per frame
     void Update () {
         float tempVar =    mat.GetFloat("_Amount"); //ask for the amount of the float
         Debug.Log( mat.GetFloat("_Amount") );     //Debugging to check
         if(mat.GetFloat("_Amount") < desired)    //and if "_Amount" is less than desired
         {
             mat.SetFloat("_Amount", tempVar+=0.1f);     //I will increase the amount by 0.1 (you can manipulate 0.1 to change the grow speed;
         }
     }
 }
Show more comments

Follow this Question

Answers Answers and Comments

22 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

Related Questions

Setting and storing vertex locations in a shader 0 Answers

Getting model bounds in vertex shader 0 Answers

Shader problem: length() en distance() 1 Answer

Vertex Shader problem with _WorldSpaceCameraPos 1 Answer

How do I make a vertex invisible if its X value is > myFloat 2 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