着色器

时间:2017-12-03 22:42:09

标签: c# unity3d matrix geometry shader

我在Unity中有一个场景:

  • 一个空的游戏对象,让我们称之为" 中心"
  • 通过着色器投影到球面上(以中心为球体中心)的网格

工作正常。 我尝试添加基于3dnoise的 center - >顶点(让我们称之为" 方向")。 它也可以正常工作。 现在我尝试使用基于方向的相同3d噪声,但相对于中心方向。 Unity有一个名为 transform.WorldToLocalMatrix 的功能(在C#中运行良好),但由于它无法在Unity着色器中将矩阵作为属性传递,因此我将其作为四个分隔符传递给它*的Vector4 * S:

void Update() {
    terrainMaterial.SetVector("_Center", transform.position);
    terrainMaterial.SetVector("_Matrix1", new Vector4(transform.worldToLocalMatrix.m00, transform.worldToLocalMatrix.m01, transform.worldToLocalMatrix.m02, 0.0f));
    terrainMaterial.SetVector("_Matrix2", new Vector4(transform.worldToLocalMatrix.m10, transform.worldToLocalMatrix.m11, transform.worldToLocalMatrix.m12, 0.0f));
    terrainMaterial.SetVector("_Matrix3", new Vector4(transform.worldToLocalMatrix.m20, transform.worldToLocalMatrix.m21, transform.worldToLocalMatrix.m22, 0.0f));
    terrainMaterial.SetVector("_Matrix4", new Vector4(0.0f, 0.0f, 0.0f, 0.0f));
}

然后,在着色器中:

Shader "Custom/testShader"

{     属性     {         _Color("颜色",颜色)=(1,1,1,1)         _MainTex(" Albedo(RGB)",2D)=" white" {}         _Glossiness("平滑度",范围(0,1))= 0.5         _Metallic("金属",范围(0,1))= 0.0

    _Center("Center of the Planet", Vector) = (0.0, 0.0, 0.0)
    _Matrix1("1", Vector) = (0.0, 0.0, 0.0, 0.0)
    _Matrix2("2", Vector) = (0.0, 0.0, 0.0, 0.0)
    _Matrix3("3", Vector) = (0.0, 0.0, 0.0, 0.0)
    _Matrix4("4", Vector) = (0.0, 0.0, 0.0, 0.0)

    _Scale("Scale of Noise", Range(0.001, 200.0)) = 1.0
    _Height("Height of Noise", Range(1.0, 500.0)) = 5.0
}

    SubShader
    {
        Tags{ "RenderType" = "Opaque" }

        CGPROGRAM

        #pragma target 3.0
        #pragma surface surf Standard vertex:vert

        #include "libs/noiseSimplex.cginc"

        sampler2D _MainTex;
        half _Glossiness;
        half _Metallic;
        fixed4 _Color;

        float3 _Center;
        float4 _Matrix1;
        float4 _Matrix2;
        float4 _Matrix3;
        float4 _Matrix4;

        float _Scale;
        float _Height;

        struct Input {
            float2 uv_MainTex;
        };

        void vert(inout appdata_full v)
        {
            float3 direction = mul(unity_ObjectToWorld, v.vertex) - _Center;
            float4x4 worldToLocal_matrix = (_Matrix1.x, _Matrix1.y, _Matrix1.z, _Matrix1.w,
                                            _Matrix2.x, _Matrix2.y, _Matrix2.z, _Matrix2.w,
                                            _Matrix3.x, _Matrix3.y, _Matrix3.z, _Matrix3.w,
                                            _Matrix4.x, _Matrix4.y, _Matrix4.z, _Matrix4.w);

            float3 local_direction = mul(worldToLocal_matrix, direction);

            direction = _Center + normalize(direction) * (_Radius + snoise(local_direction * _Scale) * _Height);
            v.vertex = mul(unity_WorldToObject, float4(direction, 1));
        }

        void surf(Input IN, inout SurfaceOutputStandard o)
        {
            fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
            o.Albedo = c.rgb;

            o.Metallic = _Metallic;
            o.Smoothness = _Glossiness;
            o.Alpha = c.a;
        }

        ENDCG
}

Fallback "Diffuse"
}

我根本不理解的是......在不改变任何其他内容的情况下,这条线路可以运行:

direction = _Center + normalize(direction) * (_Radius + snoise(direction * _Scale) * _Height);

这个没有:

direction = _Center + normalize(direction) * (_Radius + snoise(local_direction * _Scale) * _Height);

对我做错了什么的想法?

1 个答案:

答案 0 :(得分:0)

<强>解决:

通过SetMatrix()传递WorldToLocalMatrix很好,但拆分它并在着色器中重建不起作用。我很困惑