1
\$\begingroup\$

I want to morph between 3d models.I found a simple OpenGL code to morphing In Graphics Shaders: Theory and Practice(page 456) but I couldn't Implement it correctly in unity.

enter image description here

uniform float uBlend;
out vec4 vColor;
out float vLightIntensity;
const float SIDE = 2.;
const vec3 LIGHTPOS = vec3( 5., 10., 10. );
void main( )
{
vec4 vertex0 = aVertex;
vertex0.xyz *= 4./length(vertex0.xyz);
vertex0.xyz = clamp( vertex0.xyz, -SIDE, SIDE );
vec3 tnorm = normalize( uNormalMatrix * aNormal );
vec3 ECposition = vec3( uModelViewMatrix * aVertex );
vLightIntensity = abs( dot(normalize(LIGHTPOS - ECposition),
tnorm));
if( vLightIntensity < 0.2 )
vLightIntensity = 0.2;
vColor = aColor;
gl_Position = uModelViewProjectionMatrix *
mix( aVertex, vertex0, uBlend );
}

unity shader:

Shader "Unlit/MorphToSphere"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _Blend("Blend",Range(0,1)) = 0
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            float SIDE = 2;
            float _Blend;

            v2f vert (appdata v)
            {
                v2f o;
                float3 AnotherShape = 4./length(v.vertex.xyz);
                AnotherShape.xyz = clamp( v.vertex.xyz, -SIDE, SIDE );
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.vertex.xyz = lerp( o.vertex.xyz, AnotherShape.xyz, _Blend );

                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = tex2D(_MainTex, i.uv);
                return col;
            }
            ENDCG
        }
    }
}

enter image description here

uniform float uBlend;
out vec4 vColor;
out float vLightIntensity;
out vec2 vST;
const float TWOPI = 2.*3.14159265;
const vec3 LIGHTPOS = vec3( 5., 10., 10. );
void main( )
{
// original model coords (sphere):
vec4 vertex0 = aVertex;
vec3 norm0 = aNormal;
// circle coords:
vST = aTexCoord0.st;
float s = aTexCoord0.s;
float t = aTexCoord0.t;
float radius = 1.-t;
float theta = TWOPI*s;
vec4 circle = vec4( radius*cos(theta), radius*sin(theta),
0., 1. );
vec3 circlenorm = vec3( 0., 0., 1. );
// blend:
vec4 theVertex = mix( vertex0, circle, uBlend );
vec3 theNormal = normalize( mix( norm0, circlenorm, uBlend ));
// do the lighting:
vec3 tnorm = normalize( vec3( uNormalMatrix *
theNormal ) );
vec3 ECposition = vec3( uModelViewMatrix * theVertex );
vLightIntensity = abs( dot(normalize(LIGHTPOS -
ECposition),tnorm));
if( vLightIntensity < 0.2 )
vLightIntensity = 0.2;
vColor = aColor;
gl_Position = uModelViewProjectionMatrix * theVertex;
}

unity shader:

Shader "Unlit/MorphToCube"
{
        Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _Blend("Blend",Range(0,1)) = 0
        _Radius("Radius",Float) = 0
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
                float3 normal :NORMAL;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            float SIDE = 2;
            float _Blend;
             float TWOPI = 2.*3.14159265;
             float _Radius;

            v2f vert (appdata v)
            {
                v2f o;

                float theta = TWOPI;
                float4 circle = float4( _Radius*cos(theta), _Radius*sin(theta),0., 1. );


                o.vertex = UnityObjectToClipPos(v.vertex);
                o.vertex.xyz = lerp( o.vertex.xyz, circle.xyz, _Blend );

                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = tex2D(_MainTex, i.uv);
                return col;
            }
            ENDCG
        }
    }
}
\$\endgroup\$
  • 2
    \$\begingroup\$ How did you try to implement this in Unity? What went wrong? \$\endgroup\$ – DMGregory Feb 2 at 10:49
  • \$\begingroup\$ @DMGregory I added what I tried to my question. \$\endgroup\$ – Seyed Morteza Kamali Feb 2 at 12:34
  • \$\begingroup\$ And the second question above: "what went wrong?" In what way do these Unity examples differ from what you want? \$\endgroup\$ – DMGregory Feb 2 at 15:05
  • \$\begingroup\$ @DMGregory problem is unity shaders not work like above image.I don't know what is problem \$\endgroup\$ – Seyed Morteza Kamali Feb 2 at 15:21
1
\$\begingroup\$

The example you're working from is trying to use information encoded in the texture coordinates for some reason (something you didn't replicate in your version), invoking unnecessary trig. I'd just throw that out if all you want is cubes and spheres.

Just remember to do your morphing in object space, before you project into clip space, not after.

v2f vert (appdata v)
{
    v2f o;

    float3 anotherShape;

    // CUBE
        // We can determine the face of the cube to which we belong
        // by which component is furthest from zero
        // (this divides 3D space into 6 pyramids)
        float3 absolute = abs(v.vertex.xyz);
        float greatest = max(absolute.x, max(absolute.y, absolute.z));

        // Dividing by this greatest value snaps the vertex to one of the planes
        // x = 1, y = 1, z = 1, x = -1, y = -1, or z = -1, ie. the unit cube.
        // Scaling by a _Size parameter makes the cube however big we want it.
        anotherShape = v.vertex.xyz * _Size / greatest; 
    /* // SPHERE
        // Spheres are easier - just normalize to get a direction and scale it.
        anotherShape = _Size * normalize(v.vertex.xyz;
    */

    // Perform our blend in object space, before projection.
    float4 blended = float4(lerp(v.vertex.xyz, anotherShape, _Blend), 1.0f);

    // Project our blended result to clip space. 
    o.vertex = UnityObjectToClipPos(blended);

    o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    return o;
}
\$\endgroup\$
  • \$\begingroup\$ thanks it worked... that book confused me but your answer is easy to understand! Cow Morphing \$\endgroup\$ – Seyed Morteza Kamali Feb 2 at 18:32
  • \$\begingroup\$ Hahaha, lends new meaning to "assume a spherical cow...". :) I was able to help in this case because what you're trying to do is a common beginner's example, but you know from using this site as long as you have that a good question should contain a full description of the problem — not just "it's not working the way I want" but the specific symptoms the code is exhibiting, or the specific parts of the example that you found confusing / didn't know how to translate to your project. Please keep this in mind for future questions. \$\endgroup\$ – DMGregory Feb 2 at 18:37
  • \$\begingroup\$ I always tried to ask my questions and avoid shy even it was for beginners because embarrassment causes Ignorance this question was an old question that remained in my mind. that's right sorry I will explain my problems in future questions... \$\endgroup\$ – Seyed Morteza Kamali Feb 2 at 19:48
  • \$\begingroup\$ To be clear, there's nothing wrong with beginner questions. Those are great. But when you ask something more advanced, having the full description of the problem is important. It's only because this question was simple that I was able to help without more diagnosis details. ;) \$\endgroup\$ – DMGregory Feb 2 at 19:51

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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