美文网首页
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