着色器可以旋转形状以面向相机吗?

nim*_*nim 2 c# unity-game-engine

我制作了一个球出现在 3D 空间中的场景。三角球耗费大量资源。所以我使用带有球纹理的二维表面(四边形)来完成此操作。但现在我需要在每次相机移动时调整形状的方向。我使用位置变换和 LookAt 方法来完成此操作。问题是我可以优化这个吗?如果可以使用着色器旋转形状,这将有很大帮助。

在此输入图像描述

using UnityEngine;

public class WorldSurf : MonoBehaviour
{
    GameObject[] matrix;

    int xSize =  20;
    int ySize =  20;
    int zSize =  20;

    // Start is called before the first frame update
    void Start()
    {
        matrix = new GameObject[xSize * ySize * zSize];

        //var shader = Shader.Find("Legacy Shaders/Diffuse");
        var shader = Shader.Find("Sprites/Default");
        //var texture = Resources.Load<Texture>("Textures/Ball_01");

        var i = 0;

        for (var x = 0f; x < xSize; ++x)
        {
            for (var y = 0f; y < ySize; ++y)
            {
                for (var z = 0f; z < zSize; ++z)
                {
                    var texture = Resources.Load<Texture>("Textures/Ball_" + ((int)Random.Range(0, 15)).ToString("00"));

                    matrix[i++] = CreateQuad(x * 3, y * 3, z * 3, shader, texture);
                }
            }
        }
    }

    static GameObject CreateQuad(float x, float y, float z, Shader shader, Texture texture)
    {
        var quad = GameObject.CreatePrimitive(PrimitiveType.Quad);

        quad.transform.position = new Vector3(x, y, z);
        quad.transform.forward = Camera.main.transform.forward;

        var rend = quad.GetComponent<Renderer>();

        rend.material.shader      = shader;
        rend.material.mainTexture = texture;
        //rend.material.color = Color.red;

        return quad;
    }

    // Update is called once per frame
    void Update()
    {
        var pos = Camera.main.transform.position;

        foreach (var itm in matrix)
        {
            itm.transform.LookAt(pos);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Ruz*_*ihm 5

一般来说是的,在这种特定情况下,如果您希望四边形与相机对齐,那么这样做非常容易。

\n\n

你想要的叫做“广告牌着色器”。这是维基教科书中的一个例子:

\n\n
Shader "Cg  shader for billboards" {\n   Properties {\n      _MainTex ("Texture Image", 2D) = "white" {}\n      _ScaleX ("Scale X", Float) = 1.0\n      _ScaleY ("Scale Y", Float) = 1.0\n   }\n   SubShader {\n      Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}\n      ZWrite Off\n      Blend SrcAlpha OneMinusSrcAlpha\n\n      Pass {   \n         CGPROGRAM\n\n         #pragma vertex vert  \n         #pragma fragment frag\n\n         // User-specified uniforms            \n         uniform sampler2D _MainTex;        \n         uniform float _ScaleX;\n         uniform float _ScaleY;\n\n         struct vertexInput {\n            float4 vertex : POSITION;\n            float4 tex : TEXCOORD0;\n         };\n         struct vertexOutput {\n            float4 pos : SV_POSITION;\n            float4 tex : TEXCOORD0;\n         };\n\n         vertexOutput vert(vertexInput input) \n         {\n            vertexOutput output;\n\n            output.pos = mul(UNITY_MATRIX_P, \n              mul(UNITY_MATRIX_MV, float4(0.0, 0.0, 0.0, 1.0))\n              + float4(input.vertex.x, input.vertex.y, 0.0, 0.0)\n              * float4(_ScaleX, _ScaleY, 1.0, 1.0));\n\n            output.tex = input.tex;\n\n            return output;\n         }\n\n         float4 frag(vertexOutput input) : COLOR\n         {\n            return tex2D(_MainTex, float2(input.tex.xy));   \n         }\n\n         ENDCG\n      }\n   }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

以及其工作原理的解释:

\n\n
\n

基本思想是仅( 0 , 0 , 0 , 1 )使用标准模型视图变换将对象空间的原点变换为视图空间 UNITY_MATRIX_MV.(在齐次坐标中,所有点都有一个 1 作为第四个坐标;请参阅第 1 节中的讨论) xe2\x80\x9cVertex\n 变换\xe2\x80\x9d。)视图空间只是世界空间的旋转版本\n,其平面xy平行于\n 视图平面,如第 \xe2\x80\x9cVertex 变换\ 节中所述。 xe2\x80\x9d。因此,这是构建适当旋转的广告牌的正确空间。我们从视图坐标中变换后的原点减去x y对象坐标 (vertex.xvertex.y),然后用投影矩阵 变换结果UNITY_MATRIX_P

\n
\n\n

这将产生如下输出:

\n\n

广告牌四边形

\n