Unity基础(19)-Camera类

1. 摄像机组件

照相机是玩家观察世界的装置,屏幕空间点按像素定义,屏幕的左下为(0,0);右上是(pixelwidth,pixelHeight),z位置在照相机的世界单位中。

相机组件
Clear Flags :
清除标识:确定了屏幕哪些部分将被清除,方便多个摄像机画不同的游戏元素
Background:背景色
Culling Mask:包含或省略要由相机呈现的对象层。在检查器中将图层分配给您的对象。
Projection:  切换相机的功能来模拟透视。
    Perspective(透视):  相机将完整地呈现透视物体。拍摄角度为0-180°(最高)
Field of View: 设置为“正交”时,“相机”的视口大小。
Orthographic(正交):  相机将统一渲染对象,没有视角。注:正交模式下不支持延迟渲染。正向渲染总是被使用。
Size:设置为“正交”时,“相机”的视口大小。
Cliping Planes:从相机到开始和停止渲染的距离。
     Near :相对于相机的最近点将出现绘图。
     Far  :相对于相机的最远点将出现绘图。
ViewportRect:视口矩形 四个值指示屏幕上的相机视图将被绘制的位置。在视口坐标中测量(值为0-1)。
Depth:相机的位置按照画图顺序。具有较大值的相机将被绘制在具有较小值的相机之上。
Rendering Path:用于定义相机将使用什么渲染方法的选项
    渲染路径 :定义什么绘制方法被用于相机的选项
    Use Graphics Settings 使用玩家设置:在玩家设置(Player Settings.)相机使用哪个渲染路径。 
     Forward 正向渲染:所有对象每材质渲染只渲染一次,快速渲染
     Deferred 延迟照明:所有物体将在无光照的环境渲染一次,然后在渲染队列尾部将物体的光照一起渲染出来。
    Legacy Vertex Lit 顶点光照 :所有被这个相机渲染的物体都将渲染成Vertex-Lit物体。
    Legacy Deferred : 旧的延迟光照 
Target Texture : 目标纹理:渲染纹理 (Render Texture)包含相机视图输出。这会使相机渲染在屏幕上的能力被禁止。可用于实现画中画或者画面特效。
Occlusion Culling : 是否剔除物体背向摄像机的部分
Allow HDR:高动态光照渲染,启动相机高动态范围渲染功能。让场景更真实。
Allow MSAA: 这台相机应该使用MSAA渲染目标吗?如果当前质量设置MSAA级别支持,将只使用MSAA。
Allow Dynamic Resolution:动态分辨率缩放。
如果相机使用动态分辨率渲染,则为true,否则为false。即使此属性为true,动态分辨率也只能在当前图形设备支持的情况下使用。
Target Display:设置此摄像机的目标显示。
此设置使摄像机呈现在指定的显示中。显示器(例如监视器)支持的最大数目是8. 

Clear Flags
Clear Flags :
清除标识:确定了屏幕哪些部分将被清除,方便多个摄像机画不同的游戏元素
Skybox  :
天空盒:这是默认设置。屏幕上的任何空的部分将显示当前相机的天空盒。
如果当前的相机没有设置天空盒,它会默认在渲染设置(Render Settings )选择天空盒
Solid Color :
纯色,屏幕上的空白部分将显示当前摄像机的背景色
Depth Only :
深度相机,只渲染采集到的画面
如果你想绘制一个玩家的枪,又不让它内部环境被裁剪,你会设置深度为0的相机绘制环境,
和另一个深度为1的相机单独绘制武器。武器相机的清除标志(Clear Flags )应设置 为depth only。
Don't Clear :
不清除,此模式不清除颜色或深度缓存。每帧的渲染画面叠加在上一帧画面之上。
Culling Mask
Culling Mask:包含或省略要由相机呈现的对象层。在检查器中将图层分配给您的对象。
Nothing:什么层都不剔除
Everything:什么层都剔除
Default:默认层剔除
TransparentFX:隐形层,系统不会渲染贴图和模型
Ignore Raycast:射线层剔除
Water:水层剔除
UI:UI层剔除
Rendering Path
Rendering Path:用于定义相机将使用什么渲染方法的选项
渲染路径 :定义什么绘制方法被用于相机的选项
Use Graphics Settings 使用玩家设置:在玩家设置(Player Settings.)相机使用哪个渲染路径。 
  Forward 正向渲染:所有对象每材质渲染只渲染一次,快速渲染
  Deferred 延迟照明:所有物体将在无光照的环境渲染一次,然后在渲染队列尾部将物体的光照一起渲染出来。
Legacy Vertex Lit 顶点光照 :所有被这个相机渲染的物体都将渲染成Vertex-Lit物体。
Legacy Deferred : 旧的延迟光照 
Traget Texture 目标纹理:渲染纹理 (Render Texture)包含相机视图输出。
这会使相机渲染在屏幕上的能力被禁止。可用于实现画中画或者画面特效与
Occlusion Culling : 是否剔除物体背向摄像机的部分
Allow HDR:高动态光照渲染,启动相机高动态范围渲染功能。让场景更真实。
Allow MSAA: 这台相机应该使用MSAA渲染目标吗?如果当前质量设置MSAA级别支持,将只使用MSAA。
Allow Dynamic Resolution:动态分辨率缩放。
如果相机使用动态分辨率渲染,则为true,否则为false。即使此属性为true,动态分辨率也只能在当前图形设备支持的情况下使用。
Target Display:设置此摄像机的目标显示。
此设置使摄像机呈现在指定的显示中。显示器(例如监视器)支持的最大数目是8. 

2. Camera实例

  • aspect : 获取或者设置Camera视口的宽高比例值。例如:camera.aspect =2.0f,则视口的宽度、高度 = 2.0f,当硬件显示器屏幕的宽度与高度比例不为2.0f时,视图的显示将会发生变形。aspect只处理摄像机camera可以看到的视图的宽高比例,而硬件显示屏的作用只是把摄像机camera看到的内容显示出来,当硬件显示屏的宽高比例与aspect的比例值不同时,视图将发生变形。
using UnityEngine;

public class aspect : MonoBehaviour {

    void Start () {
        Debug.Log("默认值" + Camera.main.aspect);
    }
    private void OnGUI()
    {
        if (GUI.Button(new Rect(10f, 10f, 200f, 45f), "aspect = 1.0"))
        {
            Camera.main.ResetAspect();
            Camera.main.aspect = 1.0f;
        }

        if (GUI.Button(new Rect(10f, 60f, 200f, 45f), "aspect = 2.0"))
        {
            Camera.main.ResetAspect();
            Camera.main.aspect = 2.0f;
        }
        if (GUI.Button(new Rect(10f, 110f, 200f, 45f), "aspect = 3.0"))
        {
            Camera.main.ResetAspect();
            Camera.main.aspect = 3.0f;
        }
        if (GUI.Button(new Rect(10f, 160f, 200f, 45f), "aspect = 0.0"))
        {
            Camera.main.ResetAspect();
        }
    }
}
  • cameraToWorldMatrix : 变换矩阵
using UnityEngine;

public class cameratoworldmatrix : MonoBehaviour {

    // Use this for initialization
    void Start () {
        Debug.Log("Camera旋转前位置" + transform.position);
        Matrix4x4 m = Camera.main.cameraToWorldMatrix;
        // 向量的位置转换为世界坐标中的位置
        //v3 的值为沿着Camera局部坐标系的-z轴方向前移5个单位的位置在世界坐标系中的位置
        Vector3 v3 = m.MultiplyPoint(Vector3.forward * 5.0f);
        //v4 的值为沿着Camera世界坐标系的-z轴方向前移5个单位的位置在世界坐标系中的位置
        Vector3 v4 = m.MultiplyPoint(transform.forward * 5.0f);
        Debug.Log("旋转前,V3坐标值:"+v3);
        Debug.Log("旋转前,V4坐标值:"+v4);
        // 将摄像机沿着Y轴正向旋转90度(此时摄像机局部坐标系的z轴方向和世界坐标的X轴方向一致),
        transform.Rotate(Vector3.up * 90f);
        m = Camera.main.cameraToWorldMatrix;
        v3 = m.MultiplyPoint(Vector3.forward * 5.0f);
        v4 = m.MultiplyPoint(transform.forward * 5.0f);
        Debug.Log("旋转后, v3坐标值"+v3);
        Debug.Log("旋转后, v4坐标值"+v4);
    }
}
  • CullingMask 按层渲染,此属性用于按层(GameObject.layer)有选择性地渲染场景中的物体。通过cullingMask可以使得当前摄像机有选择性地渲染场景中的部分物体,默认cullingMask =-1即渲染场景中的任何物体,cullingMask = 0时不渲染场景中的任何物体。若只渲染2,3,4,可以使用cullingMask = (1<<2)+ (1<<3)+(1<<4)来进行。
using UnityEngine;

public class cullingMask : MonoBehaviour {

    void Start () {
        Debug.Log("默认值" + Camera.main.aspect);
    }
    private void OnGUI()
    {
        if (GUI.Button(new Rect(10f, 10f, 200f, 45f), "CullingMask = -1"))
        {
            Camera.main.cullingMask = -1;
        }

        if (GUI.Button(new Rect(10f, 60f, 200f, 45f), "CullingMask = 0"))
        {
           Camera.main.cullingMask = 0;
        }
        if (GUI.Button(new Rect(10f, 110f, 200f, 45f), "aspect = 3.0"))
        {
            Camera.main.cullingMask =1 << 0;
        }
        if (GUI.Button(new Rect(10f, 160f, 200f, 45f), "aspect = 1<<8"))
        {
            Camera.main.cullingMask =1 << 8;
        }
         //渲染第8层与第0层
       if (GUI.Button(new Rect(10f, 160f, 200f, 45f), "aspect = 0&&8"))
        {
            // 注意运算符优先排序
            Camera.main.cullingMask =1+(1 << 8);
        }
    }
}
  • eventMask属性:按层响应事件,选择哪个层(layer)的物体可以响应鼠标事件

1.必须满足两个条件:

  • 1.物体在摄像机的视野范围内。
  • 2.在2的layer次方的值与eventMask进行运算(&)后结果仍为2的layer次方的值,如:defalult ,layer值为0,2的0次方=1,如果1与eventMask进行与运算后扔为1,则此物体响应鼠标事件。由于EventMask为奇数时,与1的与运算结果都为1,所以若物体层为defalut并且eventMask为奇数时物体会响应鼠标事件。

2.如果想要多个不同层的物体响应鼠标事件,则需要把所有层的2的layer次方值相加,再与eventMask做与运算。例如,2个物体,layer值分贝为1,3,当event与9进行与运算后结果仍为9,则这两个物体都会响应鼠标事件。

3.此属性有一个特殊情况,但固体layer选择IgnoreRaycast(其为系统内置,值为2)时,无论EventMask值为多少,物体都无法响应鼠标事件。

using UnityEngine;
using System.Collections;

public class EventMask_ts : MonoBehaviour
{
    bool is_rotate = false;//控制物体旋转
    public Camera c;//指向场景中摄像机
    //记录摄像机的eventMask值,可以在程序运行时在Inspector面板中修改其值的大小
    public int eventMask_now = -1;
    //记录当前物体的层
    int layer_now;
    int layerTemp;//记录2的layer次方的值
    int ad;//记录与运算(&)的结果
    string str = null;

    void Update()
    {
        //记录当前对象的层,可以在程序运行时在Inspector面板中选择不同的层
        layer_now = gameObject.layer;
        //求2的layer_now次方的值
        layerTemp= (int)Mathf.Pow(2.0f, layer_now);
        //与运算(&)
        ad = eventMask_now & layerTemp;
        c.eventMask = eventMask_now;
        //当is_rotate为true时旋转物体
        if (is_rotate)
        {
            transform.Rotate(Vector3.up * 15.0f * Time.deltaTime);
        }
    }
    //当鼠标左键按下时,物体开始旋转
    void OnMouseDown()
    {
        is_rotate = true;
    }
    //当鼠标左键抬起时,物体结束旋转
    void OnMouseUp()
    {
        is_rotate = false;
    }
    void OnGUI()
    {
        GUI.Label(new Rect(10.0f, 10.0f, 300.0f, 45.0f), "当前对象的layer值为:" + layer_now + " , 2的layer次方的值为" + layerTemp);
        GUI.Label(new Rect(10.0f, 60.0f, 300.0f, 45.0f), "当前摄像机eventMask的值为:" + eventMask_now);
        GUI.Label(new Rect(10.0f, 110.0f, 500.0f, 45.0f), "根据算法,当eventMask的值与" + layerTemp+ "进行与运算(&)后, 若结果为" + tp + ",则物体相应OnMousexxx方法,否则不响应!");

        if (ad == tp)
        {
            str = " ,所以物体会相应OnMouseDown方法!";
        }
        else
        {
            str = " ,所以物体不会相应OnMouseDown方法!";
        }
        GUI.Label(new Rect(10.0f, 160.0f, 500.0f, 45.0f), "而当前eventMask与" + layerTemp+ "进行与运算(&)的结果为" + ad + str);
    }
}
  • LayerCullDistances:层消隐的距离

摄像机可以通过基于层(GameObject.layer)的方式来设置不同层物体的消隐距离,但这个距离必须小于或者等于摄像机的farClipPlane才有效。

public class LayerCullDistances : MonoBehaviour
{
// 拿到要消除的物体
    public Transform obj;
    void Start()
    {
        //定义大小为32的一维数组,用来存储所有层的剔除距离
        float[] distances = new float[32];
        //设置第12层的剔除距离
        distances[11] = Vector3.Distance(transform.position,obj.position);
        //将数组赋给摄像机的layerCullDistances,首先这个获取的是layer所有的层距离
        Camera.main.layerCullDistances = distances;
    }
    void Update()
    {
        //摄像机远离物体,会发现设置了蹭的
        transform.Translate(transform.right * Time.deltaTime);
    }
}
  • layerCullSpherical:基于球面距离剔除

基于球面距离的剔除方式。属性默认为false,即不使用球面剔除,表示只要有一点没有超出物体所在层的远视口平面,物体就是可见的。当设置此属性为True时,只要物体的世界坐标点Position与摄像机的距离大于所在层的剔除距离,物体就不可见。

public class layerCullSpherical : MonoBehaviour
{
    public Transform cb1, cb2, cb3;
    void Start()
    {
        //定义大小为32的一维数组,用来存储所有层的剔除距离
        float[] distances = new float[32];
        //设置第9层的剔除距离
        distances[8] = Vector3.Distance(transform.position, cb1.position);
        //将数组赋给摄像机的layerCullDistances
        Camera.main.layerCullDistances = distances;
        //打印出三个物体距离摄像机的距离
        Debug.Log("Cube1距离摄像机的距离:" + Vector3.Distance(transform.position, cb1.position));
        Debug.Log("Cube2距离摄像机的距离:" + Vector3.Distance(transform.position, cb2.position));
        Debug.Log("Cube3距离摄像机的距离:" + Vector3.Distance(transform.position, cb3.position));
    }

    void OnGUI()
    {
        //使用球形距离剔除
        if (GUI.Button(new Rect(10.0f, 20.0f, 180.0f, 45.0f), "使用球形距离剔除"))
        {
            Camera.main.layerCullSpherical = true;
        }
        //取消球形距离剔除
        if (GUI.Button(new Rect(10.0f, 70.0f, 180.0f, 45.0f), "取消球形距离剔除"))
        {
            Camera.main.layerCullSpherical = false;
        }
    }
}
  • orthographic :摄像机投影模式

用来设置相机投影模式, 模式有两种:正交投影(orthographic),与透视投影模式(perspective)若值为true,正交模式,反之投影模式。正交模式下:物体在视口的代销至于正交视口的大小有关,与摄像机到物体的距离无关,主要呈现2D效果。透视模式下,有远小近大的效果。呈现3D效果

public class orthographic : MonoBehaviour
{
    float len = 5.5f;
    void OnGUI()
    {
        if (GUI.Button(new Rect(10.0f, 10.0f, 120.0f, 45.0f), "正交投影"))
        {
            Camera.main.orthographic = true;
            len = 4.5f;
        }
        if (GUI.Button(new Rect(150.0f, 10.0f, 120.0f, 45.0f), "透视投影"))
        {
            Camera.main.orthographic = false;
            len = 60.0f;
        }
        if (Camera.main.orthographic)
        {
            //正交投影模式下,物体没有远大近小的效果,
            //orthographicSize的大小无限制,当orthographicSize为负数时视口的内容会颠倒,
            //orthographicSize的绝对值为摄像机视口的高度值,即上下两条边之间的距离
            len = GUI.HorizontalSlider(new Rect(10.0f, 60.0f, 300.0f, 45.0f), len, -20.0f, 20.0f);
            Camera.main.orthographicSize = len;
        }
        else
        {
            //透视投影模式下,物体有远大近小的效果,
            //fieldOfViewd的取值范围为1.0-179.0
            len = GUI.HorizontalSlider(new Rect(10.0f, 60.0f, 300.0f, 45.0f), len, 1.0f, 179.0f);
            Camera.main.fieldOfView = len;
        }
        //实时显示len大小
        GUI.Label(new Rect(320.0f, 60.0f, 120.0f, 45.0f), len.ToString());
    }
}
  • pixelRect:摄像机渲染区间
    设置Camera被渲染到屏幕中的坐标位置。以实际像素大小来设置显示视口的位置。如下图:A为原始平面大小,B为变换后的视口大小,则X0的值为视口右移的像素大小,Y0的值为视口上移的像素大小,w为Camera.pixelWidth,h的值为Camera.pixelHeight。这里要注意:Screen.width和Screen.height为模拟硬件屏幕的宽高值,不随Camera.pixelWidth和Camera.pixelHeight的改变而改变。


    pixelRect
public class PixelRect : MonoBehaviour
{
    int which_change = -1;
    float temp_x = 0.0f, temp_y = 0.0f;
    void Update()
    {
        //Screen.width和Screen.height为模拟硬件屏幕的宽高值,
        //其返回值不随camera.pixelWidth和camera.pixelHeight的改变而改变
        Debug.Log("Screen.width:" + Screen.width);
        Debug.Log("Screen.height:" + Screen.height);
        Debug.Log("pixelWidth:" + Camera.main.pixelWidth);
        Debug.Log("pixelHeight:" + Camera.main.pixelHeight);
        //通过改变Camera的坐标位置而改变视口的区间
        if (which_change == 0)
        {
            if (Camera.main.pixelWidth > 1.0f)
            {
                temp_x += Time.deltaTime * 20.0f;
            }
            //取消以下注释察看平移状况
            //if (Camera.main.pixelHeight > 1.0f)
            //{
            //    temp_y += Time.deltaTime * 20.0f;
            //}
            Camera.main.pixelRect = new Rect(temp_x, temp_y, Camera.main.pixelWidth, Camera.main.pixelHeight);
        }
        //通过改变Camera的视口宽度和高度来改变视口的区间
        else if (which_change == 1)
        {
            if (Camera.main.pixelWidth > 1.0f)
            {
                temp_x = Camera.main.pixelWidth - Time.deltaTime * 20.0f;
            }
            //取消以下注释察看平移状况
            //if (camera.pixelHeight > 1.0f)
            //{
            //    temp_y = camera.pixelHeight - Time.deltaTime * 20.0f;
            //}
            Camera.main.pixelRect = new Rect(0, 0, temp_x, temp_y);
        }
    }
    void OnGUI()
    {
        if (GUI.Button(new Rect(10.0f, 10.0f, 200.0f, 45.0f), "视口改变方式1"))
        {
            Camera.main.rect = new Rect(0.0f, 0.0f, 1.0f, 1.0f);
            which_change = 0;
            temp_x = 0.0f;
            temp_y = 0.0f;
        }
        if (GUI.Button(new Rect(10.0f, 60.0f, 200.0f, 45.0f), "视口改变方式2"))
        {
            Camera.main.rect = new Rect(0.0f, 0.0f, 1.0f, 1.0f);
            which_change = 1;
            temp_x = 0.0f;
            temp_y = Camera.main.pixelHeight;
        }
        if (GUI.Button(new Rect(10.0f, 110.0f, 200.0f, 45.0f), "视口还原"))
        {
            Camera.main.rect = new Rect(0.0f, 0.0f, 1.0f, 1.0f);
            which_change = -1;
        }
    }
}
  • projectionMatrix属性:自定义投影矩阵
    此属性的功能是设置摄像机的自定义投影矩阵。此属性常在一些特效场景下用到,在切换变换矩阵是通常需要先用Camera.ResetProjectionMatrix()重置Camera的变换矩阵。
public class ProjectionMatrix : MonoBehaviour
{
    public Transform sp, cb;
    public Matrix4x4 originalProjection;
    float q=0.1f;//晃动振幅
    float p=1.5f;//晃动频率
    int which_change = -1;
    void Start()
    {
        //记录原始投影矩阵
        originalProjection = Camera.main.projectionMatrix;
    }
    void Update()
    {
        sp.RotateAround(cb.position, cb.up, 45.0f * Time.deltaTime);
        Matrix4x4 pr = originalProjection;
        switch (which_change)
        {
            case -1:
                break;
            case 0:
                //绕摄像机X轴晃动
                pr.m11 += Mathf.Sin(Time.time * p) * q;
                break;
            case 1:
                //绕摄像机Y轴晃动
                pr.m01 += Mathf.Sin(Time.time * p) * q;
                break;
            case 2:
                //绕摄像机Z轴晃动
                pr.m10 += Mathf.Sin(Time.time * p) * q;
                break;
            case 3:
                //绕摄像机左右移动
                pr.m02 += Mathf.Sin(Time.time * p) * q;
                break;
            case 4:
                //摄像机视口放缩运动
                pr.m00 += Mathf.Sin(Time.time * p) * q;
                break;
        }
        //设置Camera的变换矩阵
        Camera.main.projectionMatrix = pr;
    }
    void OnGUI()
    {
        if (GUI.Button(new Rect(10.0f, 10.0f, 200.0f, 45.0f), "绕摄像机X轴晃动"))
        {
            Camera.main.ResetProjectionMatrix();
            which_change = 0;
        }
        if (GUI.Button(new Rect(10.0f, 60.0f, 200.0f, 45.0f), "绕摄像机Y轴晃动"))
        {
            Camera.main.ResetProjectionMatrix();
            which_change = 1;
        }
        if (GUI.Button(new Rect(10.0f, 110.0f, 200.0f, 45.0f), "绕摄像机Z轴晃动"))
        {
            Camera.main.ResetProjectionMatrix();
            which_change = 2;
        }
        if (GUI.Button(new Rect(10.0f, 160.0f, 200.0f, 45.0f), "绕摄像机左右移动"))
        {
            Camera.main.ResetProjectionMatrix();
            which_change = 3;
        }
        if (GUI.Button(new Rect(10.0f, 210.0f, 200.0f, 45.0f), "视口放缩运动"))
        {
            Camera.main.ResetProjectionMatrix();
            which_change = 4;
        }
    }
}
  • Rect属性:摄像机视图的位置和大小
public class Rect : MonoBehaviour
{
    int which_change = -1;
    float temp_x = 0.0f, temp_y = 0.0f;
    void Update()
    {
        //视口平移
        if (which_change == 0)
        {
            if (Camera.main.rect.x < 1.0f)
            {
                //沿着X轴平移
                temp_x = Camera.main.rect.x + Time.deltaTime * 0.2f;
            }
            //取消下面注释察看平移的变化
            //if (camera.rect.y< 1.0f)
            //{
            //沿着Y轴平移
            //    temp_y = camera.rect.y + Time.deltaTime * 0.2f;
            //}
            Camera.main.rect = new Rect(temp_x, temp_y, Camera.main.rect.width, Camera.main.rect.height);
        }
         //视口放缩
        else if (which_change == 1)
        {
            if (Camera.main.rect.width > 0.0f)
            {
                //沿着X轴放缩
                temp_x = Camera.main.rect.width - Time.deltaTime * 0.2f;
            }
            if (Camera.main.rect.height > 0.0f)
            {
                //沿着Y轴放缩
                temp_y = Camera.main.rect.height - Time.deltaTime * 0.2f;
            }
            Camera.main.rect = new Rect(Camera.main.rect.x, Camera.main.rect.y, temp_x, temp_y);
        }
    }
    void OnGUI()
    {
        if (GUI.Button(new Rect(10.0f, 10.0f, 200.0f, 45.0f), "视口平移"))
        {
            //重置视口
            Camera.main.rect = new Rect(0.0f, 0.0f, 1.0f, 1.0f);
            which_change = 0;
            temp_y = 0.0f;
        }
        if (GUI.Button(new Rect(10.0f, 60.0f, 200.0f, 45.0f), "视口放缩"))
        {
            Camera.main.rect = new Rect(0.0f, 0.0f, 1.0f, 1.0f);
            which_change = 1;
        }
        if (GUI.Button(new Rect(10.0f, 110.0f, 200.0f, 45.0f), "视口还原"))
        {
            Camera.main.rect = new Rect(0.0f, 0.0f, 1.0f, 1.0f);
            which_change = -1;
        }
    }
}
  • RenderingPath : 渲染路径


    RenderingPath

用于获取和设置摄像机渲染路径。Unity中渲染路径RenderingPath为枚举类型
VertexLit:使用顶点光照。最低消耗的渲染路径,不支持实时阴影,适用于移动及老式设备。
forward:使用正向光照,基于着色器的渲染路径。支持逐像素计算光照(包括法线贴图和灯光Cookies)和来自一个平行光的实时阴影。
DeferredLighting:使用延迟光照,支持实时阴影,计算消耗大,对硬件要求高,不支持移动设备,仅专业版可用。

public class renderingPath: MonoBehaviour
{
    void OnGUI()
    {
        if (GUI.Button(new Rect(10.0f, 10.0f, 120.0f, 45.0f), "UsePlayerSettings"))
        {
            Camera.main.renderingPath = RenderingPath.UsePlayerSettings;
        }
        if (GUI.Button(new Rect(10.0f, 60.0f, 120.0f, 45.0f), "VertexLit"))
        {
            Camera.main.renderingPath = RenderingPath.VertexLit;
        }
        if (GUI.Button(new Rect(10.0f, 110.0f, 120.0f, 45.0f), "Forward"))
        {
            Camera.main.renderingPath = RenderingPath.Forward;
        }
        if (GUI.Button(new Rect(10.0f, 160.0f, 120.0f, 45.0f), "DeferredLighting"))
        {
            Camera.main.renderingPath = RenderingPath.DeferredLighting;
        }
    }
}

  • WorldToCameramatrix:变换矩阵

返回或设置当前从世界坐标系到当前Camera自身坐标系的变换矩阵。重设矩阵时,摄像机的Transform组件数据不会同步更新。如果想回到Transform的可控状态,需要调用ResetWorldToCameraMatrix方法重置摄像机旋转矩阵。

public class WorldToCameraMatrix : MonoBehaviour
{
    public Camera c_test;
    void OnGUI()
    {
        if (GUI.Button(new Rect(10.0f, 10.0f, 200.0f, 45.0f), "更改变换矩阵"))
        {
            //使用c_test的变换矩阵
            Camera.main.worldToCameraMatrix = c_test.worldToCameraMatrix;
            //也可使用如下代码实现同样功能
            // camera.CopyFrom(c_test);
        }
        if (GUI.Button(new Rect(10.0f, 60.0f, 200.0f, 45.0f), "重置变换矩阵"))
        {
            Camera.main.ResetWorldToCameraMatrix();
        }
    }
}
  • RenderToCubMap:生成Cubemap静态贴图。
  • RenderWithShader:使用其他shader渲染
    使用指定shader来代替当前物体的shader渲染一帧。当replacementTag为空时会替换视口中所有物体的shader
public class RenderWithShader : MonoBehaviour
{
    bool is_use = false;
    void OnGUI()
    {
        if (is_use)
        {
            //使用高光shader:Specular来渲染Camera
            Camera.main.RenderWithShader(Shader.Find("Specular"), "RenderType");
        }
        if (GUI.Button(new Rect(10.0f, 10.0f, 300.0f, 45.0f), "使用RenderWithShader启用高光"))
        {
            //RenderWithShader每调用一次只渲染一帧,所以不可将其直接放到这儿
            //camera.RenderWithShader(Shader.Find("Specular"), "RenderType");
            is_use = true;
        }
        if (GUI.Button(new Rect(10.0f, 60.0f, 300.0f, 45.0f), "使用SetReplacementShader启用高光"))
        {
            //SetReplacementShader方法用来替换已有shader,调用一次即可
            Camera.main.SetReplacementShader(Shader.Find("Specular"), "RenderType");
            is_use = false;
        }
        if (GUI.Button(new Rect(10.0f, 110.0f, 300.0f, 45.0f), "关闭高光"))
        {
            Camera.main.ResetReplacementShader();
            is_use = false;
        }
    }
}
  • SetReplacementShader 使用指定的shader来替换物体当前的shader,被替换后每一帧都会替换shader来渲染物体,与上面的方法刚好不同。
  • ScreenPointToRay:近视口到屏幕的射线
public class ScreenPointToRay_ts : MonoBehaviour
{
    Ray ray;
    RaycastHit hit;
    Vector3 v3 = new Vector3(Screen.width / 2.0f, Screen.height / 2.0f, 0.0f);
    Vector3 hitpoint = Vector3.zero;
    void Update()
    {
        //射线沿着屏幕X轴从左向右循环扫描
        v3.x = v3.x >= Screen.width ? 0.0f : v3.x + 1.0f;
        //生成射线
        ray = Camera.main.ScreenPointToRay(v3);
        if (Physics.Raycast(ray, out hit, 100.0f))
        {
            //绘制线,在Scene视图中可见
            Debug.DrawLine(ray.origin, hit.point, Color.green);
            //输出射线探测到的物体的名称
            Debug.Log("射线探测到的物体名称:" + hit.transform.name);
        }
    }
}
  • ScreenToViewPortPoint 坐标系转换
    实现坐标点从屏幕坐标系向摄像机视口的单元化坐标系转换。但是是像素
public class ScreenToViewportPoint_ts : MonoBehaviour
{
    void Start()
    {
        transform.position = new Vector3(0.0f, 0.0f, 1.0f);
        transform.rotation = Quaternion.identity;
        //从屏幕的实际坐标点向视口的单位化比例值转换
        Debug.Log("1:" + Camera.main.ScreenToViewportPoint(new Vector3(Screen.width / 2.0f, Screen.height / 2.0f, 100.0f)));
        //从视口的单位化比例值向屏幕的实际坐标点转换
        Debug.Log("2:" + Camera.main.ViewportToScreenPoint(new Vector3(0.5f, 0.5f, 100.0f)));
        Debug.Log("屏幕宽:" + Screen.width + "  屏幕高:" + Screen.height);
    }
}
  • ScreenToworldPoint : 坐标系转换,从屏幕坐标系到世界坐标系,实际单位像素组值,而非比例值。
public class ScreenToWorldPoint_ts : MonoBehaviour
{
    void Start()
    {
        transform.position = new Vector3(0.0f, 0.0f, 1.0f);
        Camera.main.fieldOfView = 60.0f;
        Camera.main.aspect = 16.0f / 10.0f;
        //Z轴前方100处对应的屏幕的左下角的世界坐标值
        Debug.Log("1:" + Camera.main.ScreenToWorldPoint(new Vector3(0.0f, 0.0f, 100.0f)));
        //Z轴前方100处对应的屏幕的中间的世界坐标值
        Debug.Log("2:" + Camera.main.ScreenToWorldPoint(new Vector3(Screen.width / 2.0f, Screen.height / 2.0f, 100.0f)));
        //Z轴前方100处对应的屏幕的右上角的世界坐标值
        Debug.Log("3:" + Camera.main.ScreenToWorldPoint(new Vector3(Screen.width, Screen.height, 100.0f)));
    }
}
  • ViewPortToWorldpoint 视口坐标点向世界坐标点转换。

此方法的返回值受当前摄像机在世界坐标系的位置Camera的FieldOfView的值以及Position的共同影响

ublic class ViewportToWorldPoint : MonoBehaviour
{
    void Start()
    {
        transform.position = new Vector3(1.0f, 0.0f, 1.0f);
        Camera.main.fieldOfView = 60.0f;
        Camera.main.aspect = 16.0f / 10.0f;
        //屏幕左下角
        Debug.Log("1:" + Camera.main.ViewportToWorldPoint(new Vector3(0.0f, 0.0f, 100.0f)));
        //屏幕中间
        Debug.Log("2:" + Camera.main.ViewportToWorldPoint(new Vector3(0.5f, 0.5f, 100.0f)));
        //屏幕右上角
        Debug.Log("3:" + Camera.main.ViewportToWorldPoint(new Vector3(1.0f, 1.0f, 100.0f)));
    }
}
  • WorldToScreenPoint:世界坐标转成屏幕坐标。
public class WorldToScreenPoint : MonoBehaviour
{
    public Transform cb, sp;
    public Texture2D t2;
    Vector3 v3 = Vector3.zero;
    float sg;
    void Start()
    {
        //记录屏幕高度
        sg = Screen.height;
    }
    void Update()
    {
        //sp绕着cb的Y轴旋转
        sp.RotateAround(cb.position, cb.up, 30.0f * Time.deltaTime);
        //获取sp在屏幕上的坐标点
        v3 = Camera.main.WorldToScreenPoint(sp.position);
    }
    void OnGUI()
    {
        //绘制纹理
        GUI.DrawTexture(new Rect(0.0f, sg - v3.y, v3.x, sg), t2);
    }
}
  • WorldToViewPoint:从世界坐标转换屏幕单位化坐标中。
public class WorldToViewportPoint : MonoBehaviour
{
    public Transform cb, sp;
    public Texture2D t2;
    Vector3 v3 = Vector3.zero;
    float sw, sh;
    void Start()
    {
        //记录屏幕的宽度和高度
        sw = Screen.width;
        sh = Screen.height;
    }
    void Update()
    {
        //物体sp始终绕cb的Y轴旋转
        sp.RotateAround(cb.position, cb.up, 30.0f * Time.deltaTime);
        //记录sp映射到屏幕上的比例值
        v3 = Camera.main.WorldToViewportPoint(sp.position);
    }
    void OnGUI()
    {
        //绘制纹理,由于方法WorldToViewportPoint的返回值的y分量是从屏幕下方向上方递增的,
        //所以需要先计算1.0f - v3.y的值,然后再和sh相乘。
        GUI.DrawTexture(new Rect(0.0f, sh * (1.0f - v3.y), sw * v3.x, sh), t2);
    }
}
  • SetTargetBuffers:重设摄像机到TargetTexture的渲染

SetTargetBuffers(RenderBuffer colorBuffer,RenderBuffer depthBuffer)其中参数ColorBuffer为纹理颜色缓存,depthBuffer为纹理的深度缓存。

SetTargetBuffers(RenderBuffer [] colorBuffer,RenderBuffer depthBuffer)其中参数ColorBuffer为纹理颜色缓存,depthBuffer为纹理的深度缓存,这个方法可以将摄像机的渲染一次赋给多个colorBuffer.

public class SetTargetBuffers : MonoBehaviour
{
    //声明两个RendererTexture变量
    public RenderTexture RT_1, RT_2;
    public Camera c;//指定Camera

    void OnGUI()
    {
        //设置RT_1的buffer为摄像机c的渲染
        if (GUI.Button(new Rect(10.0f, 10.0f, 180.0f, 45.0f), "set target buffers"))
        {
            c.SetTargetBuffers(RT_1.colorBuffer, RT_1.depthBuffer);
        }
        //设置RT_2的buffer为摄像机c的渲染,此时RT_1的buffer变为场景中Camera1的渲染
        if (GUI.Button(new Rect(10.0f, 60.0f, 180.0f, 45.0f), "Reset target buffers"))
        {
            c.SetTargetBuffers(RT_2.colorBuffer, RT_2.depthBuffer);
        }
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,194评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,058评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,780评论 0 346
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,388评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,430评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,764评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,907评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,679评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,122评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,459评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,605评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,270评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,867评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,734评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,961评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,297评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,472评论 2 348

推荐阅读更多精彩内容

  • 转载请注明出处(//www.greatytc.com/p/5f538820e370),您的打赏是小编继续...
    福later阅读 26,999评论 8 70
  • 1、通过CocoaPods安装项目名称项目信息 AFNetworking网络请求组件 FMDB本地数据库组件 SD...
    阳明先生_X自主阅读 15,969评论 3 119
  • 夜伴孤身徘徊在车站 还来不及防备初冬的寒冷 走在寒风瑟瑟中 脑海不断荡起曾经的画面 明眸已模糊 岁月的年轮毫不客气...
    丹青珝阅读 252评论 0 0
  • 有人说,一个人走着很潇洒。以前我也这么想。 后来的某天,我独自一人在商场里逛街买衣服,那种孤独感竟升华成一种无助感...
    秦岭影武者阅读 335评论 0 1
  • 一开始,我们给自己的婚姻定位为何?我的答案是获得不断的成长。 不错,我希望在婚姻的漫长路上收获学习的过程,即便可能...
    荆棘里盛开的花阅读 284评论 0 2