zoukankan      html  css  js  c++  java
  • 关于Unity中Cg的基本语法和使用

    Cg是类似于C语言的发展起来的图形编程语言,Cgraphics,它的很多表达式if...else...和C语言非常相像,也和C#非常相像。

     由于Shader是写给显卡执行的,所以没有输出语句来调试,很多地方调试不了,只能靠Unity编辑器来帮我们报错,写起来一定要小心谨慎。

    基本类型表达式
    1:语法和C语言类是,有对应的编译器,程序是给显卡运行;
    2: 可以从渲染流水线中获得对应的输入;
    3: 指定的输出能流入下一个流水线模块;
    4: 操作符号和C语言一样,可以使用 +, -, * / <, >, <=, >= 等运算;
    5: Cg提供了float half double 浮点类型;单精度,半精度,双精度
    7: Cg 支持定点数 fixed来高效处理 某些小数;
    8: Cg使用int来表示整数;
    9: bool 数据类型来表示逻辑类型;
    10:sampler*,纹理对象的句柄, sampler/1D/2D/3D/CUBE/RECT,往shader里面关联一个图片,关联纹理Texture,使用sampler
    11: 内置向量数据类型: float4(float, float, float, float), 向量长度不能超过4;
    12: 内置矩阵数据类型: float1x1 float2x3 float4x3 float4x4;不能超过4x4;
    13: 数组类型float a[10]; 10个float, float4 b[10], 10个float4;
    14: 语义绑定 float4 a : POSITION,返回值也可以语义绑定;获得上一个工位的数据和流向下一个工位的输出。只有绑定语义如Position,上一个工位才知道要传顶点的位置给它。

    fixed定点数:如有一个32bit的Int,我要把前面16位表示整数,后面16位表示小数,用来存放35.4这个数,这个数据类型叫做定点数。实质是用整数表示小数,因为35.4输出的时候是一个比较大的整数,而它的内容里面可以表示小数。

          定点数的加减法实际上也就是整数的加减法,性能比浮点数好,颜色就是用fixed类型表示fixed4。

    结构体与语义
    1: struct name {
    类型 名字;
    // 尽量不要使用;
    返回值 函数名称(参数) { // 如果成员函数里面使用,数据成员,该成员定义在函数前;
    }
    };

    2:输入语义与输出语义:
    语义: 一个阶段处理数据,然后传输给下一个阶段,那么每个阶段之间的接口, 例如:顶点处理器的输入数据是处于模型空间的顶点数据(位置、法向量),输出的是投影坐标和光照颜色;片段处理器要将光照颜色做为输入;C/C++用指针,而Cg通过语义绑定的形式;
    输入语义: 绑定接收参数,从上一个流水线获得参数;
    输出语义: 绑定输出参数到下一个流水线模块;
    语义: 入口函数上有意义(顶点着色入口,像素着色入口),普通的函数无意义;

    常用语义修饰

    1:POSITION : 位置
    2:TANGENT : 切线
    3: NORMAL: 法线
    4: TEXCOORD0: 第一套纹理
    5: TEXCOORD1: 第二套纹理
    6: TEXCOORD2: 第三套纹理
    7: TEXCOORD3: 第四套纹理
    8: COLOR: 颜色

    标准内置函数

    1:abs(num)绝对值;
    2: 三角函数;
    3: cross(a, b) 两个向量的叉积;
    4: determinant(M)矩阵的行列式;
    5: dot(a, b) 两个向量的点积;
    6: floor(x)向下取整;
    7: lerp(a, b, f), 在a, b之间线性插值;
    8: log2(x) 基于2为底的x的对数;
    9: mul(m, n): 矩阵x矩阵, 矩阵x向量, 向量x矩阵;
    10: power(x, y) x的y次方;
    11: radians(x) 度转弧度;
    12: reflect(v, n) v 关于法线n的反射向量;
    13: round(x) 靠近取整;
    14: tex2D(smapler, x) 二维纹理查找
    15: tex3Dproj(smapler, x) 投影三维纹理查找;
    16: texCUBE 立方体贴图纹理查找;

    Unity自带函数

    1: 引用Unity自带的函数库: #include “UnityCG.cginc” Unity-->Edit-->Data-->CGIncludes;
    2: TRANSFORM_TEX: 根据顶点的纹理坐标,计算出对应的纹理的真正的UV坐标;
    3: 使用属性的变量: 在shader里面需要使用属性变量还需要在shader中定义一下这个变量的类型和名字;
    名字要保持一致;
    4: 外部修改shader的编辑器上的参数值;

    例子:打开上次的那个MyShader

    1.使用编辑器的颜色对物体进行着色

    Shader "Custom/MyShader" {
        // 属性,可以在编辑器里面bind和修改的;
        Properties {
            _Color ("Color", Color) = (1,1,1,1)
            _MainTex ("Albedo (RGB)", 2D) = "white" {}
            _Glossiness ("Smoothness", Range(0,1)) = 0.5
            _Metallic ("Metallic", Range(0,1)) = 0.0
        }
    
        SubShader {
            
            Pass {
                CGPROGRAM // 插入Cg代码开始
                fixed4 _Color; //必须定义同样的变量才能使用它
    
                #pragma vertex my_vert // 把my_vert作为顶shader的入口
                // 怎么样获得这个上一个工位的参数; -->语义bind
                float4 my_vert(float4 pos : POSITION) : POSITION {
                    return mul(UNITY_MATRIX_MVP, pos);
                }
    
                #pragma fragment my_frag
                fixed4 my_frag() : COLOR{
                    return _Color;//使用编辑器选择的颜色,着色物体
                }
                ENDCG // 插入Cg代码结束
            }
        }
    
        FallBack "Diffuse"
    }

    2.使用编辑器的纹理对物体进行绘制

    Shader "Custom/MyShader" {
        // 属性,可以在编辑器里面bind和修改的;
        Properties {
            _Color ("Color", Color) = (1,1,1,1)
            _MainTex ("Albedo (RGB)", 2D) = "white" {}
            _Glossiness ("Smoothness", Range(0,1)) = 0.5
            _Metallic ("Metallic", Range(0,1)) = 0.0
        }
    
        SubShader {
            
            Pass {
                CGPROGRAM // 插入Cg代码开始
                //fixed4 _Color; // 定义同样的变量
                sampler2D _MainTex; // 定义同样名字的变量;
    
    
                #pragma vertex my_vert // 把my_vert作为顶shader的入口
                // 怎么样获得这个上一个工位的参数; -->语义bind
                float4 my_vert(float4 pos : POSITION) : POSITION {
                    return mul(UNITY_MATRIX_MVP, pos);
                }
    
                #pragma fragment my_frag
                fixed4 my_frag(float2 uv : TEXCOORD0) : COLOR{      
                    //return _Color;//使用编辑器选择的颜色,着色物体
                    return tex2D(_MainTex, uv);//根据uv来查到纹理并返回,我的理解是返回的东西就帮我们绘制了。uv---->_MainTex---->tex2D---->放回tex2D
                }
                ENDCG // 插入Cg代码结束
            }
        }
    
        FallBack "Diffuse"
    }

    编写好代码后把贴图拖进材质球MyShader的纹理属性中,视图中就显示出对应的纹理贴图。

    3.定义结构体和函数来使用

    Shader "Custom/MyShader" {
        // 属性,可以在编辑器里面bind和修改的;
        Properties {
            _Color ("Color", Color) = (1,1,1,1)
            _MainTex ("Albedo (RGB)", 2D) = "white" {}
            _Glossiness ("Smoothness", Range(0,1)) = 0.5
            _Metallic ("Metallic", Range(0,1)) = 0.0
        }
    
        SubShader {
            
            Pass {
                CGPROGRAM // 插入Cg代码开始
                struct my_struct {
                    int a;
                };
    
                float sum(float a, float b) {
                    return a + b;
                }
    
                fixed4 _Color; // 定义同样的变量
    
                #pragma vertex my_vert // 把my_vert作为顶shader的入口
                // 怎么样获得这个上一个工位的参数; -->语义bind
                float4 my_vert(float4 pos : POSITION) : POSITION {
                    return mul(UNITY_MATRIX_MVP, pos);
                }
    
                #pragma fragment my_frag
                fixed4 my_frag() : COLOR{
                    return _Color;
                }
                ENDCG // 插入Cg代码结束
            }
        }
        FallBack "Diffuse"
    }

    4.语义绑定可以绑定一个结构体,在结构体里面再指定哪个属性。Unity其实给我们定义了很多常用的结构体,可以直接使用,在 “UnityCG.cginc” Unity-->Edit-->Data-->CGIncludes;里面查看

    Shader "Custom/MyShader" {
        // 属性,可以在编辑器里面bind和修改的;
        Properties {
            _Color ("Color", Color) = (1,1,1,1)
            _MainTex ("Albedo (RGB)", 2D) = "white" {}
            _Glossiness ("Smoothness", Range(0,1)) = 0.5
            _Metallic ("Metallic", Range(0,1)) = 0.0
        }
    
        SubShader {
            
            Pass {
                CGPROGRAM // 插入Cg代码开始
    
                fixed4 _Color; // 定义同样的变量
    
           //结构体包装语义
                struct my_vert_data {
                    float4 pos : POSITION;
                };
    
                #pragma vertex my_vert // 把my_vert作为顶shader的入口
                // 怎么样获得这个上一个工位的参数; -->语义bind
                float4 my_vert(my_vert_data data) : POSITION {
                    return mul(UNITY_MATRIX_MVP, data.pos);
                }
    
                #pragma fragment my_frag
                fixed4 my_frag(float2 uv : TEXCOORD0) : COLOR{
                    return _Color;
                }
                ENDCG // 插入Cg代码结束
            }
        }
        FallBack "Diffuse"
    }

    使用C#脚本来控制和编写shader

    0.shader文件里面的代码是这样的:

    Shader "Custom/MyShader" {
        // 属性,可以在编辑器里面bind和修改的;
        Properties {
            _Color ("Color", Color) = (1,1,1,1)
            _MainTex ("Albedo (RGB)", 2D) = "white" {}
            _Glossiness ("Smoothness", Range(0,1)) = 0.5
            _Metallic ("Metallic", Range(0,1)) = 0.0
        }
    
        SubShader {
            
            Pass {
                CGPROGRAM // 插入Cg代码开始
                fixed4 _Color; //必须定义同样的变量才能使用它
    
                #pragma vertex my_vert // 把my_vert作为顶shader的入口
                // 怎么样获得这个上一个工位的参数; -->语义bind
                float4 my_vert(my_vert_data data) : POSITION {
                    return mul(UNITY_MATRIX_MVP, data.pos);
                }
    
                #pragma fragment my_frag
                fixed4 my_frag() : COLOR{
                    return _Color;//使用编辑器选择的颜色,着色物体
                }
                ENDCG // 插入Cg代码结束
            }
        }
    
        FallBack "Diffuse"
    }

    1.创建一个叫shader_ctrl的脚本

    2.挂载到Cube节点下,这个Cube的材质属性就是Myshader材质球,Myshader材质球的shader属性是MyShader.shader文件

    3.打开shader_ctrl的脚本,内容如下(记得关联public 材质属性):

    using UnityEngine;
    using System.Collections;
    
    public class shader_ctrl : MonoBehaviour {
        public Material material;
        // Use this for initialization
        void Start () {
            material.SetColor("_Color", new Color(1.0f, 0.0f, 0.0f, 1.0f));//修改颜色为红色
        }
        
        // Update is called once per frame
        void Update () {
        
        }
    }

    4.运行,发现cube变红色

  • 相关阅读:
    Spring MVC异常处理
    Spring MVC 数据校验
    Spring MVC 拦截器(Interceptor)
    Spring MVC 表单标签库
    Spring MVC 数据格式化(Formatter)
    Spring MVC 类型转换器(Converter)
    Spring MVC @ModelAttribute注解
    Spring MVC @Autowired和@Service注解
    如何在Storyboard中使用Scroll view
    学好Python的五本书
  • 原文地址:https://www.cnblogs.com/HangZhe/p/7223701.html
Copyright © 2011-2022 走看看