• Unity Shader基础


    Unity Shader基础

    先上代码,代码一般是这样的。

    void Initialization(){
    	//先从硬盘加载代码再加载到GPU中
    	string vertexShaderCode = LoadShaderFormFile(VertexShader.shader);
    	string fragmentShaderCode = LoadShaderFormFile(FragmentShader.shader);
    	LoadVertexShaderFromString(vertexShaderCode);
    	LoadVertexShaderFromString(fragmentShaderCode);
    	//设置各种属性输入
    	SetVertexShaderProperty("vertexPosition", vertices);
    	SetVertexShaderProperty("MainTex", someTexture);
    	SetVertexShaderProperty("MVP", MVP);
    	Disable(Blend);			/关闭混合
    	Enable(ZText);			//设置深度测试
    	SetZTextFunction(LessOrEqual);
    	//其他
    }
    void Onrendering(){
    	//调用渲染命令
    	DrawCall();
    }
    

    VertexShader.shader

    in float3 vertexPosition;
    in sampler2D MainTex;
    in Mateix4x4 MVP;
    
    out float4 position;
    
    void main(){
    	position = MVP * vertexPosition;
    }
    

    FragmentShader.shader

    in float4 position;
    
    out float4 fragColor;
    
    void main(){
    	fragColor = float4(1.0, 1.0, 1.0, 1.0);
    }
    

    Unity Shader 概述

    Unity中shader需要和材质(Material)】配合使用才能达到需要的效果,一般流程:

    • 创建一个材质
    • 创建一个Unity Shader,并把它赋给上一步的材质
    • 把材质赋给给需要渲染的对象
    • 在材质面板中调整Unity Shader的属性,以得到满意的效果

    单独的shader是无法发挥任何作用的,它必须和材质结合起来,才能产生效果。

    ShaderLab

    ShaderLab 是Unity提供的一种专门为Unity Shader服务的语言。

    一般结构如下:

     Shader "Example/Diffuse Simple" {
        Properties {
        	//属性
        }
        SubShader {
        	//显卡A使用的子着色器
        }
        SubShader {
        	//显卡B使用的子着色器
        }
        Fallback "Diffuse"
    }
    

    材质和Unity Shader 的桥梁:Properties

    Properties语义块的定义通常如下:

    Properties {
    	_Name ("Display Name", PropertyType) = DefaultValue
    }
    

    _Name 是属性的名字,在Shader中访问,通常以一个下划线开始。
    "Display Name" 是显示的名称,会在材质面板中显示。
    PropertyType 是指定它的类型,类型表如下:

    属性类型 默认定义语法 例子
    Int number _Int("Int", Int) = 2
    Float number _Float("Float", Float) = 1.5
    Range(min, max) number _Range("Range", Range(0.0, 5.0)) = 3.0
    Color (number,number,number, number) _Color("Color", Color) = (1.0, 1.0, 1.0, 1.0)
    Vector (number,number,number, number) _Vector("Vector", Vector) = (2, 3, 4, 5)
    2D "defaulttexture"{} _2D("2D", 2D) = "white" {}
    Cube "defaulttexture"{} _Cube("Cube", Cube) = "white" {}
    3D "defaulttexture"{} _3D("3D", 3D) = "white" {}

    SubShader语义块

    定义模板:

    SubShader {
    	[Tags] //可选
    
    	[RenderSetup]
    
    	Pass {
    	}
    }
    

    ** 状态设置 **

    ShaderLab中常见渲染状态设置选项

    状态名称 设置指令 解释
    Cull Cull Back/Front/Off 设置提出模式:剔除背面/正面/关闭剔除
    ZTest ZTest Less Greater/LEqual/GEqual/NotEqual/Always 设置深度测试时使用的函数
    ZWrite ZWriteON/Off 开启/关闭深度写入
    Blend Blend SrcFactor DstFactor 开启并设置混合模式

    ** SubShader **

    SubShader的标签(Tags)是一个键值对(Key/Value Pair),它的键和值都是字符串类型。
    标签的结构如下:

    Tags { "TagNamel" = "Valuel" "TagName2" = "Value2" }
    

    SubShader的标签列表:

    标签类型 说明 例子
    Queue 控制渲染顺序 Tags { "Queue" = "Transparent" }
    RenderType 对着色器分类 Tags { "RenderType" = "Opaque" }
    DisableBatching Unity的SubShader批处理功能 Tags { "DisableBatching" = "True"}
    ForceNoShadowCasting 控制使用该SubShader的物体是否投射阴影 Tags { "ForceNoShadowCasting" = "True"}
    IgnoreProjector 使SubShader的物体不受Projector影响。通常用于半透明物体 Tags { "IgnoreProjector" = "True"}
    CanUseSpriteAtlas 用于精灵时,设为false Tags { "CanUseSpriteAtlas" = "False"}
    PreviewType 指明材质面板将如何预览该材质 Tags { "PreviewType" = "Plane"}

    ** 注意 ** 上述标签仅能在SubShader中声明,而不能在Pass中声明。Pass的标签与SubShader不同。

    ** Pass语义块 **

    定义:

    Pass {
    	[Name]
    	[Tags]
    	[RenderSetup]
    	//其他
    }
    

    Pass的标签类型:

    标签类型 说明 例子
    LightMode 定义该Pass在Unity的渲染流水线中的角色 Tags { "LightMode" = "ForwordBase"}
    RequireOptions 用于指定当满足某些条件时才渲染该Pass,它的值是由空格分隔的字符串。目前,Unity只支持SoftVegetation Tags { "RequireOptions" = "SoftVegetation"}

    ** Fallback **

    在SubShader后面的是一个Fallback指令,如果上面的SubShader在显卡上都不能运行,就运行这个最低级的Shader。相当于一个保险。

    Unity Shader的形式

    一般有三种Shader:

    • 表面着色器(Surface Shader)
    • 顶点着色器(Vertex Shader)
    • 固定函数着色器(Fixed Funtion Shader)

    表面着色器

    原来学OpenGL的时候,没听说个有什么表面着色器,因为这是Unity自己创建的一种着色器代码类型。

    来看看官网的一个表面着色器代码:

    Shader "Example/Diffuse Simple" {
        SubShader {
    		Tags { "RenderType" = "Opaque" }
    		CGPROGRAM
    		#pragma surface surf Lambert
    		struct Input {
    			float4 color : COLOR;
    		};
    		void surf (Input IN, inout SurfaceOutput o) {
    			o.Albedo = 1;
    		}
    		ENDCG
        }
        Fallback "Diffuse"
    }
    

    这段代码将材质的表面设置为白色。

    CGPROGRRAM 和 ENDCG之间的代码是使用CG/HLSL编写的,这里需要将CG/HLSL语言嵌套在ShaderLab语言中。值得注意的是,这里的CG/HLSL语言跟原生的CG/HLSL语言有着细微的不同,例如有些原生的函数和用法Unity并没有支持。

    顶点着色器

    格式:

    Shader "VertexAndFragment Shader" {
    	  Pass {
    	      // ... the usual pass state setup ...
    	      
    	      CGPROGRAM
    	      // compilation directives for this snippet, e.g.:
    	      #pragma vertex vert
    	      #pragma fragment frag
    	      
    	      // the Cg/HLSL code itself
    	      
    	      ENDCG
    	      // ... the rest of pass setup ...
    	  }	
    }
    

    固定函数着色器

    格式:

    Shader "Basic" {
    	Properties{
    		_Color("Color", Color) = (1.0, 0.5, 0.5, 1.0)
    	}
    	SubShader {
    		Pass {
    			Material {
    				Diffuse [_Color]
    			}
    			Lighting On
    		}
    	}
    }
    

    结束语:

    Unity SHader 的选择:

    • 除非你有非常明确的需求必须要使用固定函数着色器,否则别用。
    • 如果要和各种灯光打交道,可能更需要表面着色器,但需要小心它在移动平台的性能表现。
    • 如果需要使用的光照数目非常少,顶点着色器是首选。
    • 最重要的是,如果有很多自定义的渲染效果,那么请选择顶点着色器。
  • 相关阅读:
    Spring配置自动加载执行多次的解决方法
    获取Excel文件内容,0307通用
    将Json转实体
    将实体转换为map
    Json数据转Map
    获取随机字符串
    将长内容分割,用双主键进行存储
    解决win10开机出现C:WIndowssystem32configsystemprofileDesktop不可用 问题
    2016.2.22
    云中行走
  • 原文地址:https://www.cnblogs.com/yoyo-sincerely/p/7898373.html
Copyright © 2020-2023  润新知