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

标签 c# unity-game-engine

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

enter image description here

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);
        }
    }
}

最佳答案

通常是的,在这种特定情况下,如果您希望四边形与相机对齐,则这样做非常容易。

您想要的称为“广告牌着色器”。这是来自 Wikibooks 的示例:

Shader "Cg  shader for billboards" {
   Properties {
      _MainTex ("Texture Image", 2D) = "white" {}
      _ScaleX ("Scale X", Float) = 1.0
      _ScaleY ("Scale Y", Float) = 1.0
   }
   SubShader {
      Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
      ZWrite Off
      Blend SrcAlpha OneMinusSrcAlpha

      Pass {   
         CGPROGRAM

         #pragma vertex vert  
         #pragma fragment frag

         // User-specified uniforms            
         uniform sampler2D _MainTex;        
         uniform float _ScaleX;
         uniform float _ScaleY;

         struct vertexInput {
            float4 vertex : POSITION;
            float4 tex : TEXCOORD0;
         };
         struct vertexOutput {
            float4 pos : SV_POSITION;
            float4 tex : TEXCOORD0;
         };

         vertexOutput vert(vertexInput input) 
         {
            vertexOutput output;

            output.pos = mul(UNITY_MATRIX_P, 
              mul(UNITY_MATRIX_MV, float4(0.0, 0.0, 0.0, 1.0))
              + float4(input.vertex.x, input.vertex.y, 0.0, 0.0)
              * float4(_ScaleX, _ScaleY, 1.0, 1.0));

            output.tex = input.tex;

            return output;
         }

         float4 frag(vertexOutput input) : COLOR
         {
            return tex2D(_MainTex, float2(input.tex.xy));   
         }

         ENDCG
      }
   }
}

以及其工作原理的解释:

The basic idea is to transform only the origin ( 0 , 0 , 0 , 1 ) of the object space to view space with the standard model-view transformation UNITY_MATRIX_MV. (In homogeneous coordinates all points have a 1 as fourth coordinate; see the discussion in Section “Vertex Transformations”.) View space is just a rotated version of world space with the xy plane parallel to the view plane as discussed in Section “Vertex Transformations”. Thus, this is the correct space to construct an appropriately rotated billboard. We subtract the x y object coordinates (vertex.x and vertex.y) from the transformed origin in view coordinates and then transform the result with the projection matrix UNITY_MATRIX_P.

这将产生如下输出:

billboarded quads

关于c# - 着色器可以旋转形状以面向相机吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57204343/

相关文章:

c# - 谷歌播放服务 : Cloud Save

c# - 在 conn.Open() 中出错;在 Asp.net visual studio 2012 中

c# - Singleton 上的 StackOverflowException

c# - 过滤和 ICollectionView 过滤器 WPF

unity-game-engine - unity 3d 根据加速度计旋转游戏对象

javascript - 在 C# 中解析 JSON 文件 (Unity)

c# - 托管具有模板支持的 REST Web 服务器

c# - 如何在 C# 中修改 Access DB 的架构

unity-game-engine - Unity 游戏中 TextMeshPro 的本地化

c# - 从二维网格中的值获取索引