美文网首页
Shader概述

Shader概述

作者: 最怕认真 | 来源:发表于2019-10-22 19:48 被阅读0次

什么是Shader

Shader(着色器)是一段能够针对3D对象进行操作、并被GPU所执行的程序。Shader并不是一个统一的标准,不同的图形接口的Shader并不相同。OpenGL的着色语言是GLSL, NVidia开发了Cg,而微软的Direct3D使用高级着色器语言(HLSL)。而Unity的Shader 是将传统的图形接口的Shader(由 Cg / HLSL编写)嵌入到独有的描述性结构中而形成的一种代码生成框架,最终会自动生成各硬件平台自己的Shader,从而实现跨平台。所以说Shaer其实就是一门语言,用来控制渲染的语言。

Shader种类

OpenGL和Direct3D都提供了三类着色器:

  • 顶点着色器:处理每个顶点,将顶点的空间位置投影在屏幕上,即计算顶点的二维坐标。同时,它也负责顶点的深度缓冲(Z-Buffer)的计算。顶点着色器可以掌控顶点的位置、颜色和纹理坐标等属性,但无法生成新的顶点。顶点着色器的输出传递到流水线的下一步。如果有之后定义了几何着色器,则几何着色器会处理顶点着色器的输出数据,否则,光栅化器继续流水线任务。
  • 像素着色器(Direct3D),常常又称为片断着色器(OpenGL):处理来自光栅化器的数据。光栅化器已经将多边形填满并通过流水线传送至像素着色器,后者逐像素计算颜色。像素着色器常用来处理场景光照和与之相关的效果,如凸凹纹理映射和调色。名称片断着色器似乎更为准确,因为对于着色器的调用和屏幕上像素的显示并非一一对应。举个例子,对于一个像素,片断着色器可能会被调用若干次来决定它最终的颜色,那些被遮挡的物体也会被计算,直到最后的深度缓冲才将各物体前后排序。
  • 几何着色器:可以从多边形网格中增删顶点。它能够执行对CPU来说过于繁重的生成几何结构和增加模型细节的工作。Direct3D版本10增加了支持几何着色器的API, 成为Shader Model 4.0的组成部分。OpenGL只可通过它的一个插件来使用几何着色器。

光栅化是将一个图元转变为一个二维图像的过程。二维图像上每个点都包含了颜色、深度和纹理数据。将该点和相关信息叫做一个片元(fragment)。
光栅化的目的,是找出一个几何单元(比如三角形)所覆盖的像素。


image.png

左侧有三个片元(三个顶点),将其光栅化,其实就是计算显示这个三角形需要多少个像素

Unity Shader 分为 表面着色器(Surface Shader)和 顶点片段着色器(Vertex And Fragment Shader):

  • 表面着色器(Surface Shader)是Unity提出的一个概念。编写着色器与光照的交互是复杂的,光源有很多类型,不同的阴影选项,不同的渲染路径(正向和延时渲染),表面着色器将这一部分简化。Unity建议使用表面着色器来编写和光照有关的Shader。
  • 顶点片段着色器(Vertex And Fragment Shader)和OpenGL,Direct3D中的顶点着色器和片段着色器没有什么区别。顶点片段着色器比表面着色器使用更自由也更强大,当然光照需要自行处理。Unity也允许在里面编写几何着色器,一般用得不多。

在Unity中,顶点着色器是使用最为广泛的一种

Shader的结构

image.png
  • 属性定义(Property Definition):定义Shader的输入,这些输入可以在材质编辑的时候指定
  • 子着色器(SubShader):一个Shader可以有多个子着色器。这些子着色器互不相干且只有一个会在最终的平台运行。编写多个的目的是解决兼容性问题。Unity会自己选择兼容终端平台的Shader运行。
  • 回滚(Fallback):如果子着色器在终端平台上都无法运行,那么使用Fallback指定的备用Shader,俗称备胎。
  • Pass:一个Pass就是一次绘制。对于表面着色器,只能有一个Pass,所以不存在Pass节。顶点片段着色器可以有多个Pass。多次Pass可以实现很多特殊效果,例如当人物被环境遮挡时还可以看到人物轮廓就可以用多Pass来实现。
  • Cg代码:每个Pass中都可以包含自定义的Cg代码,从CGPROGRAM开始到ENDCG结束。
//Shader语法:
Shader "name" { [Properties] Subshaders [Fallback] [CustomEditor] }
 
//Properties 语法
Properties { Property [Property ...] }
 
// Subshader 语法
Subshader { [Tags] [CommonState] Passdef [Passdef ...] }
 
// Pass 语法
Pass { [Name and Tags] [RenderSetup] }
 
// Fallback 语法
Fallback "name"

Shader示例

基本的表面着色器

Shader "Custom/NewShader" {
        Properties {
            _MainTex ("Base (RGB)", 2D) = "white" {}
        }
        SubShader {
            Tags { "RenderType" = "Opaque" }
            LOD 200
 
            CGPROGRAM
            #pragma surface surf Lambert
 
            sampler2D _MainTex;
 
            struct Input {
                float2 uv_MainTex;
            };
 
            void surf (Input IN, inout SurfaceOutput o) {
                half4 c = tex2D (_MainTex, IN.uv_MainTex);
                o.Albedo = c.rgb;
                o.Alpha = c.a;
            }
            ENDCG
        }
        FallBack "Diffuse"
    }

基本的顶点片段着色器

Shader "VertexInputSimple" {
  SubShader {
    Pass {
      CGPROGRAM
      #pragma vertex vert
      #pragma fragment frag
      #include "UnityCG.cginc"
 
      struct v2f {
          float4 pos : SV_POSITION;
          fixed4 color : COLOR;
      };
 
      v2f vert (appdata_base v)
      {
          v2f o;
          o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
          o.color.xyz = v.normal * 0.5 + 0.5;
          o.color.w = 1.0;
          return o;
      }
 
      fixed4 frag (v2f i) : SV_Target { return i.color; }
      ENDCG
    }
  } 
}

相关文章

网友评论

      本文标题:Shader概述

      本文链接:https://www.haomeiwen.com/subject/bkrcvctx.html