Unity Shader入门

Unity Shader入门这篇文章是我在学习蛮牛的一套关于Shader教程(http://www.unitytrain.cn/course/96)后的简单总结,个人感觉这套教程并不是以高级Shader编程为目的的,更像是授人以

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

这篇文章是我在学习蛮牛的一套关于Shader教程(http://www.unitytrain.cn/course/96)后的简单总结,个人感觉这套教程并不是以高级Shader编程为目的的,更像是授人以渔的宗旨。下面我会分为三个部分:Shader简述、图形学基础,Cg简介为大家介绍Shader的相关内容,也算是做一个总结。

一:Shader简述

    a.先说一下GPU与CPU的区别,简单说:GPU主要负责跟显示相关的数据处理,而CPU主要负责操作系统和应用程序。为什么不把显示相关的数据直接交给CPU处理呢?下面附上解释:

image

     b.Shader分类。Shader中文翻译为“着色器”,含义是:可编程图形管线。主要分为:Vertex Shader和fragment Shader,即定点Shader和片段Shader。上面有一个概念是“图形管线”,简单解释就是:计算机处理图形显示的处理流水线。

image

      c.Shader 的主流编程语言。主流的Shader编程语言主要有HLSL、GLSL、CG。下面简单说一下区别:HLSL(High Level Shader Language)是微软基于DX的作品,只能运行在Windows平台上。GLSL(OpenGL Shading Language),OpenGL着色语言,是用来在OpenGL中着色编程的语言(OpenGL是个定义了一个跨编程语言、跨平台的编程接口规格的专业的图形程序接口),是跨平台的着色器语言。到这里,我们已经可以发现有一个比较麻烦的问题出现了,就是我们底层图形驱动限制了上层的编程语言,一旦想要改动图形驱动库,那就不得不重写整个Shader Files,此时CG就应运而生了,CG在HLSL和GLSL上做了进一步封装,屏蔽了上层的着色器语言对底层图形库的依赖。

      d.Unity Shader。ShaderLab其实是Unity对Shader语法结构的一种包装,其中支持三种Shader:surface Shader、Vertex and Fragment Shader 和 Fixed function shader 。Fixed function shader 是一种比较“保守”的Shader(兼容性最好),vertex and fragment Shader可以只用HLSL或GLSL或CG语言区编写,surface shader是对Vertex and fragment的一种语法包装,最终也会被翻译中Vertex and fragment Shader。(以上更具体信息的可以参考官方文档http://docs.unity3d.com/Manual/index.html

二:图形学基础

     个人感觉这一小节的内容对于未接触过图形学的人来说是挺有价值的,扫清了以前对于在Untiy中的坐标转换和渲染过程等的盲点。下面分两个小节去描述该部分的内容。

    a.3D数学基础。其实3D数学无非就是矩阵的相关操作,对于学过线代的同学肯定都不是问题,这里我就简单介绍一下。

    1.坐标系与向量。3D分为左手和右手坐标系,可以参考(http://www.cnblogs.com/mythou/p/3327046.html),示意图如下:

image

    2.向量相关的东西就不啰嗦了,比较重要的就是向量点乘和叉乘,这里附上参考文章(http://blog.csdn.net/augusdi/article/details/20037851)。

    3.矩阵相关。在3D数学中,矩阵往往代表着一种变换,这也是坐标系转换所依赖的数学原理。大家在Unity中肯定都听过“MVP矩阵”,MVP矩阵其实就是一种通过矩阵操作实现坐标系的转换一种方式。Unity中,有3中四种坐标系:模型坐标系、世界坐标系、摄像机坐标系、屏幕坐标系。这其实是3D图像显示的一个流程:从模型本身坐标利用_ObjectToWorld(即M矩阵)转换到世界坐标系,再利用_WorldToCamera(即V矩阵)从世界坐标系转换到摄像机坐标系,最后利用_Projection(P矩阵)实现从摄像机到屏幕坐标系的转换,并最终把3D图像显示在屏幕上,下面附上一篇百度文库的资料(http://wenku.baidu.com/link?url=A3AGV805UK5rcsEjkaL1h6QjnxsktvCscyNJqaHvfe2cIhwXMam6ZzH4Gxbu_XB7Jd7ripxjd0eR51Q6cPt9xPxTiX3MeHtFaWkwexBlZti)。

矩阵几种重要的操作有:矩阵的行列式、矩阵的转置、矩阵四则运算、矩阵逆……这些知识这里就不啰嗦了,下面简单介绍一下几种常见矩阵变换。

绕坐标轴旋转矩阵:

2015-12-06_100936

缩放矩阵:

image

投影矩阵

image

平移矩阵

image

以上是几种比较常用的矩阵,更多的信息就得靠度娘和Google了。

     b.下面介绍几个简单的图形学的应用:光照剔除,漫反射和高光的实现方式。

     1.光照剔除。到这里必须了解“法线的概念”(始终垂直于某平面的虚线),我们的视角即从物体到摄像机的向量,如果法线N与视线E形成的角度小于90度,那么观察者应是大约是在正面,反之大于90度应在该面的反面,此时应是无法观察到物体的(法线的求得使用向量差乘,角度计算可以使用向量的点乘),这时候就需要将其剔除了,下面两幅图简单说明一下:

image

     2.漫反射(Diffuse 是投射在几盒体表面上的光向各个方向反射的现象),可以简单理解成光照对物体表面颜色的影响(在Unity中默认的Shader其实就是漫反射加环境光的综合作用)。那么该怎样计算光照对物体颜色的影响程度呢?此时还是需要用到法线,我们使用法线和光向量(必须先标准化)的点乘作为影响该区域颜色的因子,这样再乘以该光源的颜色信息就可以得到对应受光照影响后的颜色了,下面用简图说明一下:

image

    3.高光(Specular 光源照射到物体然后反射到人的眼睛里时,物体上最亮的那个点就是高光),从定义就可以得出高光其实和反射光与视角相互作用形成的,同样的我们在计算高光也是利用同样的原理:由入射光求反射光、再计算反射光和视向量的点乘得出影响因子,最后算出高光强度,简图说明一下:

image

以上是三种比较常见的光照相关的知识,更多资料只能依靠度娘了……

     三、最后一部分的内容就简单介绍一下Unity Shader 的语法基础和一个Demo,更具体的还是要参考Unity官方文档。

     a.ShaderLab 语法基础。Unity 其实是支持上述三种Shader的,此处介绍的是Vertex and fragment Shader ,用的是CG语法。下面先贴一段Untiy 默认的

 

//Shader 文件在选择面板以树状结构组织的
Shader "Hidden/NewImageEffectShader"
{
    //这个申明程序中所需要的变量信息
    Properties
    {
        //_MainTex 变量名 ; “Texture” 在Inspector面板上显示的名称 ; 2D 指变量类型 
        // "white" 变量默认值     
        _MainTex ("Texture", 2D) = "white" {}
    }
    // Shader 语法块,一个Shader程序至少有一个SubShader,系统在渲染时会依次调用,
    // 直到找到匹配的SubShader,否则使用最后默认指定的Shader
    SubShader
    {
        // Cull Off:关闭阴影剔除 、  ZWrite : 要将像素的深度写入深度缓存中   
        // Test Always:将当前深度值写到颜色缓冲中 
        Cull Off ZWrite Off ZTest Always
        //渲染通道,固定写法
        Pass
        {
            //Shader 代码段开始
            CGPROGRAM
            //指定顶点Shader入口
            #pragma vertex vert
            //指定片段程序入口
            #pragma fragment frag 
            //引用Unity内置的一些定义
            #include "UnityCG.cginc"
            //自定义结构体
            struct appdata
            {    
                //float4 4维向量、POSITION 语义,相当于告诉渲染引擎,这个变量是代表什么含义
                float4 vertex : POSITION;
                //TEXCOORD0 纹理语义
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };
            //Vertex Shader 对应的入口
            v2f vert (appdata v)    //appdata v 作为参数,渲染引擎会把对应语义的信息传递进来,此处会传递顶点的位置信息和纹理信息
            {
                v2f o;
                //传递进来的顶点坐标是模型坐标系中的坐标值,需要经过矩阵转换车成屏幕坐标
                o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
                o.uv = v.uv;
                //将计算后的结果输出给渲染引擎,底层会根据具体的语义去做对应的处理
                return o;
            }
            //在Properties 中定义的变量需要在此申明一下才能在程序中使用
            sampler2D _MainTex;
                
            //fragment Shader 对应的入口
            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = tex2D(_MainTex, i.uv);
                // just invert the colors
                col = 1 - col;
                return col;
            }
            ENDCG
        }
    }    
    //当上述的SubShader无法匹配硬件环境时,会调这个指定的默认Shader
    Fallback "Mobile/VertexLit"
}

以上就是对Unity中的Vertex and fragment 中使用CG 语法的简单叙述,下面贴上一个Demo

二:Shader Demo,这里贴上一个简单的Demo,Demo的整个是一个Plane,没有使用任何的贴图,仅仅是使用Shader 改变其顶点和颜色信息实现的。下面是Demo的截图

image

下面贴上该Shader 的源码

Shader "Cus/Demo_3"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        // No culling or depth
        Cull Off ZWrite Off ZTest Always

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            
            #include "UnityCG.cginc"
            //自定义结构体,包含位置和颜色语义
            struct v2f
            {
                float4 pos : POSITION;
                float4 col : COLOR;
            };
            //Vertex shader入口,颜色信息也在此一并处理了
            v2f vert (appdata_base v)
            {
                v2f o;
                //计算旋转角度,利用_SinTime.w为旋转角度加上周期变换性质(_SinTime 是Unity提供的内置变量)
                float angle = length(v.vertex)* _SinTime.w;
                //绕Y轴旋转矩阵
                float4x4 RM={
                    float4(cos(angle) , 0 , sin(angle) , 0),
                    float4(0 , 1 ,0 , 0),
                    float4(-1 * sin(angle) , 0 , cos(angle),0),
                    float4(0 , 0 ,0 ,1)
                };
                //利用RM矩阵影响顶点位置信息
                float4 pos = mul(RM , v.vertex);
                //把顶点信息转换到世界坐标系中
                o.pos = mul(UNITY_MATRIX_MVP, pos);
                
                //由顶点到中心点的距离决定颜色信息
                angle = abs(sin(length(v.vertex)));
                o.col = float4(angle , 1 , 0 ,1);
                return o;
            }
            //片段程序中直接返回顶点Shader中计算得到的颜色信息
            float4 frag (v2f v) : color
            {
                return v.col;
            }
            ENDCG
        }
    }
}

ok,到这里这篇分享就结束了,下面附上一个用C#写的模拟3D图像渲染过程的Demo和上述Shader 的Demo(链接:http://pan.baidu.com/s/1c0Yk3KG 密码:1j1k)

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/168030.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 微软OneDrive云盘5T大容量免费申请「建议收藏」

    微软OneDrive云盘5T大容量免费申请「建议收藏」博主分享一个亲测有效的OneDrive获取5T的方法,OneDrive云盘在国内的下载速度还是相当可以的,5T的大空间相信也能满足绝大部分人,教育版的子账号还是很稳的,欢迎上车,但是本人不提供任何技术支持,有需要还是请百度吧,因为我也没有搞得很明白。自助申请教程获取临时邮箱打开:http://mail.hrka.net/,获取临时邮箱地址,打开后复制右上角邮箱地址,不要关闭或刷…

  • pycharm卸载再安装_pycharm双击无法打开

    pycharm卸载再安装_pycharm双击无法打开今个发现原来下载的2017版的pycharm过期了,用一会就闪退,emmm。就想下一个新的进行迭代,结果安装好并重启了,软件就是打不开…方法一1.打开C:\Windows\System32;以管理员身份运行cmd.exe;2.在打开的cmd窗口中,输入netshwinsockreset,按回车键;3.重启电脑;博主使用这个方法后,双击后还是不行。随即用了方法二,如下:方法二只需要打开C:\Users\admin后面的admin换成你自己的当前用户名(如下图),然后把所

  • JavaScript日期格式化及解析

    JavaScript日期格式化及解析JavaScript开发经常需要对日期进行转换,把日期转成字符串或者从字符串生成日期。JavaScript日期对象内置了简单的日期格式化方法toString()和日期解析方法Date.parse(),这两个方法有较大的局限性,不能自定义自定义日期格式化和解析的字符串格式。下面列出一些常用的日期处理JS库。

  • html 下拉导航栏源码,html导航栏下拉菜单怎么制作?这里有详细的代码实例「建议收藏」

    html 下拉导航栏源码,html导航栏下拉菜单怎么制作?这里有详细的代码实例「建议收藏」元素来包裹这些元素,并使用CSS来设置下拉内容的样式。html导航栏菜单的CSS部分:.dropdown类使用position:relative,这将设置下拉菜单的内容放置在下拉按钮(使用position:absolute)的右下角位置。.dropdown-content类中是实际的下拉菜单。默认是隐藏的,在鼠标移动到指定元素后会显示。注意min-width的值设置为160px。你可以随意修改它…

  • 用matlab绘制函数图像例题_matlab绘制方程组图像

    用matlab绘制函数图像例题_matlab绘制方程组图像1.一元函数比如f(x)=x+10sin(5x)+7cos(4x)%%%%%%%%%f(x)=x+10sin(5x)+7cos(4x)%%%%%%%%%%clearall;%清除所有变量closeall;%清图clc;%清屏x=0:0.01:10;y=x+10*sin(5*x)…

  • 安卓手机修改ntp服务器,修改安卓手机ntp服务器地址「建议收藏」

    安卓手机修改ntp服务器,修改安卓手机ntp服务器地址「建议收藏」修改安卓手机ntp服务器地址内容精选换一换TTL(Time-To-Live)指解析记录在本地DNS服务器中的缓存时间。本地DNS服务器指用户客户端(手机、电脑等)连接Internet网络使用的DNS,默认使用的DNS是宽带运营商自动分配的DNS服务器,用户也可以将该DNS修改为公共DNS服务器,例如,114.114.114.114、8.8.8.8。通过华为云购买的弹性云服务器默认硬件要求如表1所…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号