开启辅助访问
 找回密码
 注册帐号

扫一扫,访问微社区

蛮牛译馆

关注:514

当前位置:游戏蛮牛 技术专区 蛮牛译馆

查看: 690|回复: 1

[Unity教程] C#渲染教程1—矩阵

[复制链接]  [移动端链接]
排名
626
昨日变化
1

3

主题

121

帖子

1767

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
86264
好友
2
蛮牛币
3569
威望
0
注册时间
2015-3-28
在线时间
649 小时
最后登录
2017-3-26
发表于 2016-11-1 12:50:25 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?注册帐号

x
本帖最后由 manew_JR 于 2016-11-1 13:46 编辑

渲染1—矩阵
创建一个立方体网格。
支持缩放、移动和旋转。
能够变换的矩阵
创建一个简单的相机投影

这是一个渲染基础教程系列的第一部分,它包含可变换矩阵。首先,了解一下网格的基础,从程式化网格来开始。然后你就会知道网格是怎么工作的。这个系列会探索这些网格如何成为像素显示出来。

1、可视化空间
你已经了解到网格是什么和它们怎么显示在场景中。但是实际上它们是怎么工作的呢?shader是怎么知道在哪里渲染呢?当然我们仅仅能够依靠Unity自带的变换组件和shader去使用它,但是如果你想进一步控制它那么了解它的原理是至关重要的,去充分地明白它的过程,我们才能够实现自己的东西。

通过操作网格的顶点来对网格进行移动、旋转和缩放。这是一个空间的变换,这些网格必须是可见的我们才能看见它。我们可以让它可见通过创建3D网格顶点。可以使用任何的预设(Unity中原有的一些组件)来创建这些点
[C#] 纯文本查看 复制代码
using UnityEngine;

public class TransformationGrid : MonoBehaviour {

        public Transform prefab;

        public int gridResolution = 10;

        Transform[] grid;

        void Awake () {
                grid = new Transform[gridResolution * gridResolution * gridResolution];
                for (int i = 0, z = 0; z < gridResolution; z++) {
                        for (int y = 0; y < gridResolution; y++) {
                                for (int x = 0; x < gridResolution; x++, i++) {
                                        grid = CreateGridPoint(x, y, z);
                                }
                        }
                }
        }
}

创建一个点,确定它的位置并给予它一个明显的颜色
[C#] 纯文本查看 复制代码
Transform CreateGridPoint (int x, int y, int z) {
                Transform point = Instantiate<Transform>(prefab);
                point.localPosition = GetCoordinates(x, y, z);
                point.GetComponent<MeshRenderer>().material.color = new Color(
                        (float)x / gridResolution,
                        (float)y / gridResolution,
                        (float)z / gridResolution
                );
                return point;
        }

在我们的网格中那些显而易见的物体就是cube,我们把它集中到原点,因此变换-旋转和缩放-都涉及到网格cube。
[C#] 纯文本查看 复制代码
Vector3 GetCoordinates (int x, int y, int z) {
                return new Vector3(
                        x - (gridResolution - 1) * 0.5f,
                        y - (gridResolution - 1) * 0.5f,
                        z - (gridResolution - 1) * 0.5f
                );
        }

我将使用默认的cube作为预制体,将长宽高变为原来的一半。

创建一个网格工程,加入我们的组件并且连接预制体,点击play,网格cube将会出现在我们工程的原点。
               
2、变换
观念上我们以为可以任意地改变我们的网格,并且任意类型的我们都可以创建,限制我们的只有定位,旋转和缩放。
如果我们为每一个变换都创建一个组件类型,只要我们愿意我们就可以把这些组件添加到我们的网格工程以任意地顺序和数量。并且每一个变换组件的细节都是不同的,他们都需要一个方法来应用空间中的一个点。

让我们为所有的变换创建一个基础的组件,以这个组件作为基类。这将会是一个抽象类,不能直接使用它。给它写一个抽象apply方法,其他的组件将会继承它去完成自己的功能。
[C#] 纯文本查看 复制代码
using UnityEngine;

public abstract class Transformation : MonoBehaviour {

        public abstract Vector3 Apply (Vector3 point);
}

一旦我们为网格工程添加一个组件,我们不得不以某种方式检索它们来应用到我们的网格工程,我们将会用一个普通的列表来存储这些组件的引用。
[C#] 纯文本查看 复制代码
using UnityEngine;
using System.Collections.Generic;

public class TransformationGrid : MonoBehaviour {
        
        …
        List<Transformation> transformations;

        void Awake () {
                …
                transformations = new List<Transformation>();
        }
}
现在我们可以添加update方法去获得transformation组件,然后遍历所有点的全部的网格和变换。void Update () {
                GetComponents<Transformation>(transformations);
                for (int i = 0, z = 0; z < gridResolution; z++) {
                        for (int y = 0; y < gridResolution; y++) {
                                for (int x = 0; x < gridResolution; x++, i++) {
                                        grid.localPosition = TransformPoint(x, y, z);
                                }
                        }
                }
        }

通过所有点的原始坐标已经完成了变换,然后应用所有的transformation.我们不能够依靠所有点的实际位置,以为这些都已经改变了并且我们不能记录每一帧的变换。
[C#] 纯文本查看 复制代码
        Vector3 TransformPoint (int x, int y, int z) {
                Vector3 coordinates = GetCoordinates(x, y, z);
                for (int i = 0; i < transformations.Count; i++) {
                        coordinates = transformations.Apply(coordinates);
                }
                return coordinates;
        }

2.1、平移
我们的第一个组件将被平移,这似乎非常简单。因此创建一个新的组件继承于Transformation,位置将被当做局部偏移。
[C#] 纯文本查看 复制代码
using UnityEngine;

public class PositionTransformation : Transformation {

        public Vector3 position;

}

此时编辑器将会提示我们没有提供apply的具体的信息,接下来我们这样,为原点添加一个简单的位置。
[C#] 纯文本查看 复制代码
public override Vector3 Apply (Vector3 point) {
                return point + position;
        }

现在可以添加一个位置变换组件为我们的网格工程,我们就可以移动这些点,不会移动实际的网格对象,因为我们所有的转换发生在局部空间的对象。

2.2、缩放比例
接下来要讲的是尺度变换,和位置变换比较类似,除了组件规模是成倍增加而不是添加到原点
[C#] 纯文本查看 复制代码
using UnityEngine;

public class ScaleTransformation : Transformation {

        public Vector3 scale;

        public override Vector3 Apply (Vector3 point) {
                point.x *= scale.x;
                point.y *= scale.y;
                point.z *= scale.z;
                return point;
        }
}

将这个组件添加到我们的网格组件,现在我们就可以缩放这些网格,注意我们只能调整这些网格点,所以缩放并不能改变它们可见的尺寸

一旦你试图改变位置和比例,你会发现比例也会影响位置,这是因为我们第一次定义位置,然后设定比例,Unity的变换组件用其他方式实现了它,那是有用的,我们也应该这么做,重新附加组件的时候就会实现,它被放置在每个组件的右上角齿轮图标上。





原文标题:Rendering 1 Matrices
原文连接:http://catlikecoding.com/unity/tutorials/rendering/part-1/


扫描下方二维码关注游戏蛮牛官方微信~每日都有精选干货与你分享呦~1/


回复

使用道具 举报

4四处流浪
450/500
排名
5269
昨日变化
37

5

主题

148

帖子

450

积分

Rank: 4

UID
158249
好友
1
蛮牛币
1029
威望
0
注册时间
2016-7-22
在线时间
125 小时
最后登录
2017-3-30
发表于 2016-12-6 14:44:04 | 显示全部楼层
好东西 收藏收藏

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册帐号

本版积分规则

快速回复 返回顶部 返回列表