Shader特殊效果——物体铺满屏幕,作为像素展示

需求:
将模型作为像素格,铺满整个屏幕。并在物体上显示图像。

分析:

  1. 按照屏幕分辨率布满物体。(最终效果无关相机模式,但相机按照正交模式来设置,使创建的物体刚好作为屏幕)
  2. 所有物体共用同一个shader,同一个材质,降低消耗。
  3. 物体世界坐标映射到uv进行采样

功能点:

  1. 无论分辨率如何,在相机正交模式下,size=0.5时,视口的y长度即为unity的1个单位(放一个cube,cube的高刚好充满视口的高度)
  2. 多物体共用材质,改变单个物体材质参数,会生成材质实例;这里使用世界坐标的特殊性,避免生成材质实例
  3. 坐标重映射

效果:
在这里插入图片描述

代码

C#生成物体:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CreateCubeScreen : MonoBehaviour
{
    
    
    //屏幕中心的cube位置(0,1,0)
    //当相机为正交模式时 0.5的size    屏幕高度就是1cube

    public int xCount;
    public int yCount;

    public float space;

    Vector3 centerPos = Vector3.zero;
    public GameObject prefabObj;
    public Transform objParent;
    GameObject obj;
    // Start is called before the first frame update
    void Start()
    {
    
    
        //根据分辨率自动改x数量
        if(xCount == 0)
        {
    
    
            xCount = yCount * Screen.width / Screen.height;
        }

        Vector3 zeroPos = centerPos - new Vector3((1 + space) * (xCount / 2), (1 + space) * (yCount / 2), 0);
        for (int y = 0; y < yCount; y++)
        {
    
    
            for(int x = 0; x < xCount; x++)
            {
    
    
                obj = Instantiate(prefabObj, objParent);
                obj.transform.position = zeroPos;
                //zeroPos.x++;
                zeroPos.x += 1+space;
                //多材质实例
                //Color xx = new Color(Random.Range(0,255)/255f, Random.Range(0, 255)/255f, Random.Range(0, 255)/255f);
                //obj.GetComponent<MeshRenderer>().material.SetColor("_EmissionColor", xx);
            }
            zeroPos.y += 1+space;
            zeroPos.x = centerPos.x - (1 + space) *( xCount / 2);
        }

        //计算相机位置
        float yspaceCount = yCount - 1;
        float yspacelength = yspaceCount * space;
       // float cubesize = Mathf.Ceil(yspacelength);

        float cameraSize = (yCount + yspacelength) * 0.5f;
        Camera.main.orthographicSize = cameraSize;
        float addY = 0, addX = 0;
        if (yCount % 2 == 0)
            addY = Camera.main.transform.position.y - 0.5f - space / 2;
        if (xCount % 2 == 0)
            addX = Camera.main.transform.position.x - 0.5f - space / 2;
        Camera.main.transform.position = new Vector3(addX,addY,-10);
    }
}

shader:

Shader "Unlit/AllCubeUse"
{
    
    
    //所有cube使用同一个材质
    //根据xy格子数,和space参数  构造uv图
    //根据模型原点转换到世界坐标来决定在uv里的位置

    //奇数 0点距离为:(yCount-1)/2 * (1+space) + 0.5*1
    //偶数 0点距离为:(yCount/2 *1 + (yCount/2 - 1)*space + 0.5*space
    Properties
    {
    
    
        _MainTex ("Texture", 2D) = "white" {
    
    }
        _MapProperties("WorldPos Map",Vector)=(0,0,0,0)
        _Baohedu("baohe",Range(0,2))=1
    }
    SubShader
    {
    
    
        Tags {
    
     "RenderType"="Opaque" }
        LOD 100

        Pass
        {
    
    
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog

            #include "UnityCG.cginc"

            #define space _MapProperties.z 
            #define xCount _MapProperties.x
            #define yCount _MapProperties.y
            struct appdata
            {
    
    
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
    
    
                float2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                float4 vertex : SV_POSITION;
                float4 centerWorldPos:TEXCOORD1;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            float4 _MapProperties;
            float _Baohedu;

            float Remap(float a,float b,float c,float d,float val){
    
    
	            return (val-a)/(b-a) * (d-c) + c;
            }
            float rand(float3 z){
    
    
                return frac(sin(dot(z.xyz,float3(12.9898,78.233,53.539))) * 43758.5453);
            }

            fixed3 luminance(fixed3 colorpixel){
    
    
                fixed lumin = 0.2125 * colorpixel.r + 0.7154 * colorpixel.g + 0.0721 * colorpixel.b;
                return fixed3(lumin,lumin,lumin);
            }

            //计算map函数
            float2 newUV(float3 worldPos){
    
    
                float minX = -(1+space)*(xCount/2);
                float maxX = minX + (xCount-1)*(1+space);
                float minY = -(1 + space) * (yCount / 2);
                float maxY = minY + (yCount-1)*(1+space);

                float newX = Remap(minX,maxX,0,1,worldPos.x);
                float newY = Remap(minY,maxY,0,1,worldPos.y);
                return float2(newX,newY);
            }
            v2f vert (appdata v)
            {
    
    
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                UNITY_TRANSFER_FOG(o,o.vertex);
                //模型原点作为uv依据
                o.centerWorldPos = mul(unity_ObjectToWorld,float4(0,0,0,1));
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
    
    
                //uv映射:模型原点在世界坐标的位置&网格世界Map -->01uv
                float2 uvtemp = newUV(i.centerWorldPos);
                // sample the texture
                fixed4 col = tex2D(_MainTex, uvtemp);

                col.xyz = lerp(luminance(col),col,_Baohedu);

                float randV = rand(i.centerWorldPos);
                float addT = 0.5*sin(_Time.y*randV*2 +randV );
                col *= 1+ addT *randV;
                //col = fixed4(0.1,0.2,0.3,1) * i.centerWorldPos.x;
                // apply fog
                UNITY_APPLY_FOG(i.fogCoord, col);
                return col;
            }
            ENDCG
        }
    }
}

猜你喜欢

转载自blog.csdn.net/suixinger_lmh/article/details/125316612