渲染流水线笔记2
3D应用、OpenGL/DirectX、显卡驱动的关系
什么是HLSL、GLSL、Cg这些都是高级着色语言(Shading Language)。
DirectX——HLSL(High Level Shading Language):支持它的平台多是微软自己的产品,在相同版本下编译结果是一样的
OpenGL——GLSL(OpenGL Shading Language):由显卡驱动来完成着色器编译,GLSL依赖硬件提供商,可能会造成编译结果不一致的情况。
Nvidia——Cg(C for Language):真正意义的跨平台,语法和HLSL很像,可能无法完全发挥出OpenGL的最新特性。
这些语言称为“高级”语言是相对汇编语言来说的,而不是像C#相对于C的高级那样。这些语言会被编译成与机器无关的汇编语言,被称为中间语言(Intermediate Language,IL),中间语言再交给显卡驱动来翻译成真正的机器语言。
在Unity中可以选择使用“Cg/HLSL”或者“GLSL”,Unity的着色语言和它们语法几乎一样,但是有一些不支持和不一样的地方。
DrawCallD ...
渲染流水线笔记
综述在理论上,一个渲染流程分3个阶段:
应用阶段
应用阶段就是各种3D软件游戏等,在此阶段还有一个剔除(culling)工作,把不可见的剔除出去。在这一阶段设置模型的渲染状态(每个模型的材质、纹理、Shader)。并且在这一阶段还要输出渲染所需的几何信息,即渲染图元(rendering primitives)。渲染图元可以是点、线、三角面。
几何阶段
几何阶段和后面的光栅化阶段都属于GPU流水线阶段,几何阶段的一个重要目的就是将顶点坐标转换到屏幕空间中,每个顶点还包含着深度值、着色等相关信息。
光栅化阶段
使用几何阶段产生的数据来产生屏幕上的像素,在这一阶段决定渲染图元中的哪些像素应该被绘制在屏幕上,对几何阶段得到的逐顶点数据进行插值(包括纹理坐标信息,顶点颜色信息),然后再进行逐像素处理。
CPU和GPU之间的通信渲染流水线的起点是CPU,即应用阶段,此时CPU要干的事是:
把数据加载到显存中
设置渲染状态
调用DrawCall
把数据加载到显存中渲染数据先从硬盘(Hard Disk Drive,HDD)加载到内存(Random Access Memory,RAM) ...
IOC的优点和生命周期
DI容器的职责先了解一下DI容器的职责是什么。
职责一般情况下DI容器会提供如下API:
注册类型:Register<TSource,TTarget>
注入:Inject(object obj)
解析:Resolve<T>()
上一篇的例子中,我们使用了Register和Inject,剩下的Resolve在DIContainer中,作用就是根据type返回对应的实例。
上一篇我们用Inject方法,其内部就是调用了Resolve来返回实例的。
在决定版架构中,Resolve方法就是IOCCointainer里面的Get方法
1234567891011public T Get<T>() where T : class{ var key = typeof(T); if (mInstances.TryGetValue(key, out var retInstance)) { return retInstance as T; } return null;}
这个方法很简 ...
IOCKit与DI简介
IOC简介IOC全称为Inversion of Control,即控制反转。
控制反转是一种设计思想,而不是一个具体的技术实现。这种设计思想用大白话解释就是“我们想要什么就自己拿什么,而不是看给什么”
一种设计思想可以有多种方式去实现,其中最常见的一个实现方式是DI。
DIDI,全称为Dependency Injection,即依赖注入。
依赖这个概念,我们在对象之间的交互里接触过,当时说过一种单向依赖,即自顶向下的依赖。具体是:父节点持有子节点的对象。
1234public class A{ public B b = new B();}
我们可以说A依赖B,这就是关于依赖的意思,可以理解成持有另一个对象的引用或者在方法中获取另一个对象。
注入的意思,我们通过下面的代码体会:
12345678910111213public class A{ public B b = null;}public class B {}void Main(){ var a = new A(); var b = ne ...
命令模式(六)小结
我们第一次解除命令模式是在第一季的时候,决定版架构总的Command对象撑起了整个Controller的交互逻辑的职责。
其职责如下:
操作Model、System
可以发送Event
命令模式定义最开始,我们学习了命令模式的定义,如下:
将请求封装成对象,可以将客户端的不同请求参数化,并配合队列、记录、复原等方法来执行请求操作。
接着简单聊了一下架构中的Command,其优点如下
专注操作Model与System,使Controller不再那么臃肿
逻辑以对象为单位进行管理,可以实现比较复杂的功能
命令模式的参数化和撤销Command参数化非常简单,仅仅只是在Command构造上传参即可。
接着我们用Command实现了撤销功能,也非常简单,仅仅是在ICommand上增加Undo即可。
命令与执行隔离我们从命令与执行隔离的角度介绍了:方法、事件机制、Command的实现,三者区别如下:
方法:命令与执行在一起(没有分离)
Command:执行在Command内部实现(有分离)
事件机制:执行在事件注册中实现(有分离)
以上是空间上的隔离,我们还介绍了时间上的隔离,比如 ...
命令模式(五)命令模式与开闭原则
开闭原则简介开闭原则,即OCP(Open-Close Principle)
其定义如下:
一个类应该对拓展开放,对修改关闭
当一个结构或者系统成型之后,除非遇到一些Bug或者一些软件缺陷,就不应该对系统或结构中的类进行修改,这就是对修改关闭。如果需要增加一些功能,或者扩展一些功能时,这个系统或结构应该通过扩展的方式来增加或扩展一些功能,这就是对扩展开放。
命令模式与开闭原则这是因为,在经典的命令模式中,有关闭修改的部分,也有开放扩展的部分。
经典命令中的几个角色:
Invoker
Receiver
Command
ConcreteCommand
其中的ConcreteCommand是我们可以不断扩展的部分,也就是整个命令系统中,ConcreteCommand是开放出来的扩展,而Command是扩展的标准。
而在系统成型时,Invoker则是不推荐修改的部分,Receiver也许会根据Command的扩展为自己增加一些方法,或者增加Receiver的实现类型,所以也算是开放出来的扩展,但是Receiver的内部代码是不推荐修改的,所以也有对修改关闭的部分。
总结如下:
Invo ...
命令模式(四)经典命令模式
经典命令模式实现我们前面介绍了命令模式中命令与执行分离的特性,这个特性是我们理解经典命令模式设计的重点。经典命令模式的提出非常地早,而且为了表示通用性,没有使用现代语言的特点,(比如说Java,没有接口或委托),经典命令模式包含一些概念,这些概念都是围绕命令与执行分离的特性展开的。
经典命令模式包含四个概念:Command(抽象命令)、ConcreteCommand(具体命令)、Invoker(命令的调用者、管理者)、Receiver(被Command访问和操作)
我们先看一下之前的简单命令模式
123456789101112131415161718192021public interface ICommand{ void Execute();}public class OpenLightCommand : ICommand{ public void Execute() { var light = GameObject.Find("Light"); light.SetActive( ...
命令模式(三)命令与执行分离
命令与执行分离特性命令模式有一个特性就是“命令”与“执行”分离。
在日常编程中,命令 与 执行 不分离的代码是很常见的,其中最典型的就是方法直接调用
123456void SayHello(){ Debug.Log("Say Hello");}void Start(){ SayHello();}
如果想要让命令与执行分离,我们可以用消息机制:
1234567891011public class SayHelloEvent{}void Start(){ SimpleEventSystem.GetEvent<SayHelloEvent>() .Subscribe(sayHello =>{ Debug.Log("Say Hello");//执行 }) .AddTo(this);//相当于`UnregisterWhenGameObjectDestroyed(th ...
命令模式(二)参数化和撤销
参数化参数化是在命令模式的定义中出现的:
将请求封装成对象,让你可以将客户端的不同请求参数化,并配合队列、记录、复原等方法来执行请求操作。
定义中说到,我们可以将命令模式参数化,其实就是在命令对象构造时传参。
1234567891011121314151617181920212223242526public interface ICommand{ void Execute();}public class AttackHeroCommand{ private int mHP; public AttackHeroCommand(int hp) { mHP = hp; } public void Execute() { var heroModel = HeroModel.Get(); heroModel.HP -= mHP; MsgSender.Send("UPDATE_HP",heroModel.HP) ...
命令模式(一)简介
命令模式 简介定义:
将请求封装成对象,让你可以将客户端的不同请求参数化,并配合队列、记录、复原等方法来执行请求操作。
其核心就是,将逻辑封装到一个对象中。
命令模式是在开发编辑器类应用时常见的模式,它能很好地处理此类应用的“撤销、重做”操作。在游戏开发中这类模式并不常见,框架中引入命令模式是为了减少表现层的代码量。
要注意,命令模式的概念中不包含“撤销、重做”的概念,不要把命令模式的概念局限化了
Command模式快速入门Command模式有经典的实现,不过经典实现一般都有一点门槛。这里给出一个比较容易理解的实现:
123456789101112131415161718192021public interface ICommand{ void Execute();}public class OpenLightCommand : ICommand{ public void Execute() { var light = GameObject.Find("Light"); l ...