【Aladdin Unity3D Shader编程】之一 基本入门

OpenGL、DirectX以及GLSL、HLSL、CG

  • OpenGL和DirectX是图像应用编程接口,用于渲染二维或者三维图形。
  • GLSL着色语言是用来在OpenGL中着色编程的语言,有点在于跨平台性,可以再Windows、Linux、Mac甚至移动平台上工作。
  • HLSL是微软控制着色的编译,几乎只支持微软自己的产品,如Windows,XBox等,其他平台没有可编译HLSL的编译器。
  • CG是有英伟达公司出的真正意义上的跨平台着色器语言。

GPU渲染管线概述

1.顶点着色器

顶点着色器是流水线的第一个阶段,它的输入来自于CPU。顶点着色器的处理单位是顶点,也就是说输入进来的每个顶点都会调用一次顶点着色器。

顶点着色器需要完成的工作主要有:坐标变换和逐顶点光照。当然,除了这两个主要任务外,顶点着色器还可以输出后续阶段所需的数据。
坐标变换,顾名思义,就是对顶点的坐标进行某种变换。例如我们可以通过改变顶点位置来模拟水面,布料等。

一个最基本的顶点着色器必须完成的一个工作是:把顶点坐标从模型空间转换到齐次剪裁空间。类似下面代码:

2.裁剪

由于我们的场景可能会很大,而摄像机的视野范围很有可能不会覆盖所有的场景物体,一个很自然的想法就是,那些不在摄像机视野范围内的物体不需要被处理,而裁剪就是为了完成这个目的而被提出来的。
一个图元和摄像机的关系有3种:
* 完全在视野里
* 部分在视野里
* 完全在是野外
部分在视野内的图元需要裁剪,例如一条线段的一个顶点在视野内,而另一个顶点在视野外,那么视野外部的顶点应该使用一个新的顶点来代替,这个新的顶点位于这条线段和视野边界的交点处。

3.屏幕映射

这一步输入的坐标仍然是三维坐标系。屏幕映射的任务是把每个图元的x和y坐标转换到屏幕坐标系下,屏幕坐标系是一个二维坐标系,它和我们用于显示画面的分辨率有很大关系。

屏幕映射得到的屏幕坐标决定了这个顶点对应屏幕上哪个像素以及距离这个像素有多远。

opengl的屏幕坐标原点是左下角,而directx是左上角,如果你发现你得到的图像是倒转的,那么很有可能就是这个原因造成的。

4.三角形设置

由这一步就进入了光栅化阶段,从上一个阶段输出的信息是屏幕坐标下的顶点位置以及和它们相关的额外信息,如深度值、法线方向、视角方向等,光栅化有两个最重要的目标:计算每个图元覆盖了哪些像素,以及为这些像素计算他们的颜色。光栅化的第一个流水线阶段是三角形设置,这个阶段会计算光栅化一个三角网格所需的信息。

具体来说,上一个阶段输出的都是三角网格的顶点,即我们得到的是三角网格每条边的两个端点。但如果要得到整个三角网格对像素的覆盖情况,我们就必须计算每条边上的像素坐标。为了能够计算边界像素的坐标信息,我们就需要得到三角形边界的表示方式。这样一个计算三角形网格表示数据的过程就叫做三角形设置,它的输出是为了下一个阶段做准备。

5.三角形遍历

三角形遍历阶段将会检查每个像素是否被一个三角形网格所覆盖。如果被覆盖的话,就会生成一个片元,而这样一个找到哪些像素被三角网格覆盖的过程就是三角形遍历,这个阶段也被称为扫描变换。

三角形遍历阶段会根据上一个阶段的计算结果来判断一个三角网格覆盖了哪些像素,并使用三角网格3个顶点的顶点信息对整个覆盖区域的像素进行插值。

6.片元着色器

片元着色器是另一个非常重要的可编程着色器阶段,片元着色器的输入是上一个阶段对顶点信息插值得到的结果,更具体来说,是根据那些从顶点着色器输出的数据插值得到的。而它的输出是一个或多个颜色值。

这一阶段可以完成很多重要的的渲染技术,其中最重要的技术之一就是纹理采样。为了在片元着色器中进行纹理采样,我们通常会在顶点着色器阶段输出每个顶点对应的纹理坐标,然和经过光栅化阶段对三角网格的3个顶点对应的纹理坐标进行插值后,就可以得到其覆盖的片元的纹理坐标了。

7.逐片元操作

逐片元操作是opengl中的说法,在directx中,这一阶段被称为输出合并阶段。

这一阶段有几个主要任务:
* 决定片元的可见性。涉及很多测试工作,如深度测试,模版测试等。
* 如果一个片元通过了所有的测试,就需要把这个片元的颜色值和已经存储在颜色缓冲区中的颜色进行合并

Unity Shader的分类

  • 表面着色器 Surface Shader
  • 顶点/片元着色器 Vertex/Fragment Shader
  • 固定函数着色器 Fixed Function Shader (已弃用) 在一些低端设备使用
    表面着色器是对顶点/片元着色器做的一层封装。

Unity Shader的基本结构

Shader "Aladdin/01 First Shader" //指定Shader路径和名字
{
    Properties //属性
    {
        _Color("Color",Color)=(1,1,1,1)
    }
    SubShader //SubShader可以写很多个 显卡运行效果的时候 从第一个开始,如果第一个SubShader里面的效果都可以实现就使用第一个SubShader,如果显卡这个SubShader有的实现不了会往下找支持的SubShader
    {
        //至少含有一个Pass
        Pass {
            //在这里编写Shader代码 HLSLPROGRAM
            CGPROGRAM
            //使用CG语言编写Shader代码
            ENDCG
        }
    }
    FallBack  "VertexLit" //如果上面SubShader都不支持 则执行默认的Shader效果
}

Unity Shader属性和使用

属性

常用属性

_Color("Color",Color)=(1,1,1,1)
_Vector("Vector",Vector)=(1,2,3,4)
_Int("Int",Int)=2
_Float("Float",Float)=12.3 //不用加f
_Range("Range",Range(1.0,10.0))=1.0 //范围类型
_2D("Texture",2D)="white"{} //white是默认值,如果不选图的话 就是默认白色的图
_Cute("Cute",Cube)="red"{} //如果用天空盒就用Cube 立方体纹理
_3D("Texture",3D)="black"{} //3D纹理

这里写图片描述

使用
float4 _Color;//float4就是四个值 _Color要跟上面属性名字保持一致
float4 _Vector;
float _Int;
float _Range;
sampler2D _2D;
samplerCube _Cube;
sampler3D _3D;
float、half和fixed类型区别

float也可以用half和fixed代替
float 32位来存储
half 16位来存储 -6万~+6万
fixed 11位来存储 一般都是用fixed

顶点、片元函数编写

vert函数
//顶点函数定义 这里只是声明了顶点函数的函数名
//基本作用是完成顶点坐标从模型空间到剪裁空间的转换(从游戏环境到视野相机屏幕上)
#pragma vertex vert

//通过语义告诉系统我这个参数是干嘛的比如POSITION是模型坐标语义,告诉系统我需要顶点参数坐标  SV_POSITION是剪裁坐标语义
float4 vert(float4 v:POSITION) :SV_POSITION
{
    return mul(UNITY_MATRIX_MVP, v); //计算模型坐标转换成剪裁坐标
}
fragment函数
//片源函数定义 这里只是声明了片元函数的函数名
//基本作用是返回模型对应屏幕上的每一个像素颜色
#pragma fragment frag

//片元函数定义
float4 frag():SV_Target  //SV_target是返回颜色语义
{
    return fixed4(1,1,1,1);
}

片元可以理解成一个像素,每一个像素都会经过片元函数的处理

NORMAL、TEXCOORD0语义

//a2v  application to vertex
struct a2v 
{
    //顶点坐标
    float4 vertex:POSITION; //添加上POSITION语义,这样操作系统才知道给这个变量赋值模型坐标变量
    //法线
    float3 normal:NORMAL; //告诉unity把模型空间下的法线方向向量填充给normal变量
    //纹理坐标(模型坐标对应贴图的坐标)
    //纹理坐标一般都是0-1 不按照实际的像素来的
    float4 texcoord:TEXCOORD0; //告诉unity把模型空间下的纹理坐标填充给texcoord变量
};

//通过语义告诉系统我这个参数是干嘛的比如POSITION是模型坐标语义,告诉系统我需要顶点参数坐标  SV_POSITION是剪裁坐标语义
float4 vert(a2v v) :SV_POSITION
{
    return mul(UNITY_MATRIX_MVP, v.vertex); //计算模型坐标转换成剪裁坐标
}

片元函数和顶点函数之间传数据

使用结构体作为参数和返回值,这样可以添加任意多个返回值或者传入值,会更方便一些。
为什么要传参?
因为有些参数只能比如顶点、法线等只能在顶点函数中访问到,片元函数是访问不到的,如果片元函数要访问顶点法线等参数只能从顶点函数中返回并且作为参数传入给片元函数才行。

Shader "AladdinShader/03 Struct Shader"
{
    Properties
    {

    }
    SubShader {
        Pass 
        {
        CGPROGRAM
// Upgrade NOTE: excluded shader from DX11; has structs without semantics (struct v2f members tempNormal)
#pragma exclude_renderers d3d11
#pragma vertex vert
#pragma fragment frag 

        //a2v  application to vertex
        struct a2v 
        {
            //顶点坐标
            float4 vertex:POSITION; //添加上POSITION语义,这样操作系统才知道给这个变量赋值模型坐标变量
            //法线
            float3 normal:NORMAL; //告诉unity把模型空间下的法线方向向量填充给normal变量
            //纹理坐标(模型坐标对应贴图的坐标)
            //纹理坐标一般都是0-1 不按照实际的像素来的
            float4 texcoord:TEXCOORD0; //告诉unity把模型空间下的纹理坐标填充给texcoord变量
        };

        //v2f vertex to fragment
        struct v2f
        {
            float4 position:SV_POSITION;
            float3 tempNormal:COLOR0;
        };
        //通过语义告诉系统我这个参数是干嘛的比如POSITION是模型坐标语义,告诉系统我需要顶点参数坐标  SV_POSITION是剪裁坐标语义
        v2f vert(a2v v)
        {
            v2f f;
            f.position = mul(UNITY_MATRIX_MVP, v.vertex);//计算模型坐标转换成剪裁坐标
            f.tempNormal = v.normal;//将法线数据放到返回结构体里面供片元函数调用
            return f;
        }

        //SV_target是返回颜色语义
        fixed4 frag(v2f f):SV_Target
        {
            return fixed4(f.tempNormal,1);
        }

        ENDCG
        }
    }
    FallBack  "VertexLit"
}

效果的计算放在片元函数里面效果更好但计算量也大,片元函数的调用比顶点函数调用也多的多。
顶点之间的点的数值是经过插值运算得到的。
效果图:
这里写图片描述
解释:三个方向上的法线向量依次是(1,0,0)(0,1,0)(0,0,1),对应的颜色就是红绿蓝,也就是如图所示的效果图。

Unity中常用语义

从应用程序传递到顶点函数的语义有哪些a2v
POSITION顶点坐标(模型空间下的)
NORMAL法线(模型空间下)
TARGET切线(模型空间)
TEXCOORD0~n纹理坐标
COLOR顶点颜色

从顶点函数传递给片元函数的时候可以使用的语义
SV_POSITION剪裁空间中的顶点坐标(一般是系统直接使用)
COLOR0可以传递一组值 四个值
COLOR1可以传递一组值 四个值
TEXCOORD0~7传递纹理坐标

片元函数传递给系统
SV_TARGET颜色值,显示到屏幕上的颜色

目前最火、最具发展前景的专业游戏引擎 Unity 3D是什么?Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。 Unity3D的PC插件安装量达到2 亿 Unity全球注册用户已经达到200万,每月 Unity编辑器活跃开发者数量达到40万, Unity的PC插件安装量达到2亿! 未来游戏市场普遍呈现3D化 以手游市场为例,3D游戏占比达到80%,虽然现在还有不少2D游戏,但随着终端设备性能的提升和客户的需求增加,游戏市场最终会进入全面的3D化时代。Unity3D课程可以使你直接进入3D游戏开发领域,成为就业市场的宠儿。同时Unity3D也推出了开发2D游戏的插件,可以使我们从现在到未来都立于不败之地。 Unity 3D为什么这么火? ---真正的跨平台目前各个平台的游戏开发几乎没有通用性,开发iPhone上的游戏需要学习Objective C,开发Android上的游戏大多用Java,开发Windows Phone上的游戏用C#,……。如何只学习一种语言就能够开发出跨越多个平台的游戏呢?Unity3D使用底层Mono技术实现了真正的跨平台,而Mono是基于.NET框架开发的。他使我们使用一种语言就可以开发出基于各种平台的游戏,包括手机游戏(iPhone、Android、Windows Phone)、PC(Windows、Mac、Linux)、网页游戏(基于各种主流浏览器)、游戏机专用游戏(Wii、Xbox360、PS3) 现在Unity 3D的攻城狮的月薪基本上都在15000元以上,这是基础班,以后我再发精英班,学完后希望大家都可以找到年薪20万的工作。 这套是比较完整的课程,并且有实例课程,并且附带源码 并非其他只有基础的课程,没有实例! C#语言基础课程课时目录: 课时1 C#基础概述 课时2 创建一个C#文件 课时3 编译运行和控制台 课时4 创建你的第一个应用程序 课时5 变量 课时6 表达式 课时7 枚举 课时8 条件判断语句 课时9 for循环语句 课时10 while循环语句 课时11 函数 课时12 事件 课时13 C#进阶 课时14 类的概念 课时15 继承 课时16 MonoBehaviour 课时17 方法重写Overriding 课时18 方法重载Overloading 课时19 代理Delegates 课时20 单例设计模式Singletons 基础入门之进入Unity的世界 课时1 Unity介绍 课时2 Unity下载和安装 课时3 Unity 破解 课时4 Unity 什么是工程 课时5 Unity 学习过程介绍 课时6 Unity中的五种视图 课时7 Unity中的资源 课时8 Unity中的游戏物体 课时9 Unity中的组件Component 课时10 Unity中的场景Scene 课时11 场景中控制工具的使用 课时12 Unity中的本地坐标和世界坐标系 课时13 场景视图中的操作 课时14 向量 课时15 小结 基础入门之Roll-a-Ball滚动小球 课时1 Roll-A-Ball游戏介绍 课时2 了解基本集合体 课时3 创建游戏环境 课时4 给世界添加光 课时5 学习相机Camera 课时6 创建游戏主角 课时7 Unity中的刚体和碰撞器 课时8 Unity中的脚本编写 课时9 控制主角的移动 课时10 控制相机跟随 课时11 Transform组件 课时12 创建游戏中的食物 课时13 认识Prefab,完善场景中的食物 课时14 认识触发器 课时15 添加捡起食物功能 课时16 日志输出和错误调试 unity经典入门课程之C#基础实例讲解(打砖块实例) 课时1 开发工具Visual Studio Tools For Unity安装和介绍 课时2 项目效果预览,创建项目和第一个C#脚本 课时3 脚本挂载,控制台使用,变量声明和赋值,在舞台添加多个对象,使用脚本初始化对象 课时4 实例化方法高级应用,使用for循环语句创建多个砖块 课时5 课下作业-添加多行砖块 课时6 组件机制,刚体介绍,类型转换,函数返回值,发射小球功能实现 课时7 条件判断语句,鼠标按下事件处理,获取水平和垂直改变数值,改变对象位置,自动销毁对象 课时8 课程小结
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值