Primeros pasos con Unity Shader, parte 1

Este artículo es un resumen simple después de estudiar un conjunto de tutoriales de Shader de Manniu ( http://www.unitytrain.cn/course/96 ). Personalmente, creo que este conjunto de tutoriales no está dirigido a la programación avanzada de Shader. más bien el propósito de enseñar a un hombre a pescar. Lo dividiré en tres partes a continuación: una breve introducción a Shader, conceptos básicos de gráficos y una introducción a Cg para presentarle el contenido relevante de Shader, que también puede considerarse como un resumen.

1: Breve descripción de Shader

    R. Primero hablemos de la diferencia entre GPU y CPU. En pocas palabras: la GPU es la principal responsable del procesamiento de datos relacionados con la visualización, mientras que la CPU es la principal responsable del sistema operativo y las aplicaciones. ¿Por qué no entregar los datos relacionados con la visualización directamente a la CPU para su procesamiento? Adjunto a continuación la explicación:

imagen

     b.Clasificación de sombreadores. Shader se traduce como "shader" en chino, que significa: canalización de gráficos programables. Dividido principalmente en: Vertex Shader y fragment Shader, es decir, Shader de punto fijo y fragment Shader. Uno de los conceptos anteriores es el "canal de gráficos", la explicación simple es: el canal de procesamiento de la pantalla de gráficos de procesamiento de la computadora.

imagen

      c.El lenguaje de programación principal de Shader. Los principales lenguajes de programación Shader incluyen principalmente HLSL, GLSL y CG. Hablemos brevemente de la diferencia: HLSL (High Level Shader Language) es un trabajo de Microsoft basado en DX y solo puede ejecutarse en la plataforma Windows. GLSL (OpenGL Shading Language), lenguaje de sombreado OpenGL, es un lenguaje utilizado para la programación de sombreado en OpenGL (OpenGL es una interfaz de programa de gráficos profesional que define un lenguaje de programación cruzada y una especificación de interfaz de programación multiplataforma ). Lenguaje de máquina de sombreado. En este punto, ya podemos encontrar que ha surgido un problema más problemático, es decir, nuestro controlador de gráficos subyacente limita el lenguaje de programación de nivel superior. Una vez que queremos cambiar la biblioteca del controlador de gráficos, tenemos que reescribir todos los archivos Shader. En este momento, CG ha surgido como lo requieren los tiempos y se ha encapsulado aún más en HLSL y GLSL, protegiendo la dependencia del lenguaje de sombreado de la capa superior de la biblioteca de gráficos subyacente.

      d.Unity Shader. ShaderLab es en realidad un paquete de la estructura de sintaxis Shader de Unity, que admite tres tipos de Shader: sombreador de superficie, sombreador de vértices y fragmentos y sombreador de función fija. El sombreador de función fija es un sombreador relativamente "conservador" (con la mejor compatibilidad). El sombreador de vértices y fragmentos solo se puede escribir en el área de lenguaje HLSL, GLSL o CG. El sombreador de superficies es un contenedor de sintaxis para vértices y fragmentos y, en última instancia, se traducirá. en Vertex y fragmento Shader. (Para obtener información más específica anterior, consulte el documento oficial http://docs.unity3d.com/Manual/index.html )

2: Conceptos básicos de gráficos

     Personalmente, creo que el contenido de esta sección es bastante valioso para las personas que no han estado expuestas a los gráficos, ya que aclara puntos ciegos anteriores sobre la conversión de coordenadas y los procesos de renderizado en Untiy. A continuación se divide en dos subsecciones para describir el contenido de esta parte.

    a.Fundamentos matemáticos 3D. De hecho, las matemáticas 3D no son más que operaciones relacionadas con matrices, lo que definitivamente no es un problema para los estudiantes que han estudiado generación de líneas, lo presentaré brevemente aquí.

    1. Sistemas de coordenadas y vectores. 3D se divide en sistemas de coordenadas izquierda y derecha, puede consultar ( http://www.cnblogs.com/mythou/p/3327046.html ) El diagrama esquemático es el siguiente:

imagen

    2. No entraré en detalles sobre cosas relacionadas con vectores. Los más importantes son los productos punto y cruzados vectoriales. Aquí hay un artículo de referencia ( http://blog.csdn.net/augusdi/article/details/20037851 ).

    3. Correlación matricial. En matemáticas 3D, una matriz a menudo representa una transformación, que también es el principio matemático en el que se basa la transformación del sistema de coordenadas. Todo el mundo debe haber oído hablar de la "matriz MVP" en Unity. La matriz MVP es en realidad una forma de transformar el sistema de coordenadas mediante operaciones matriciales. En Unity, existen tres tipos de sistemas de coordenadas: sistema de coordenadas del modelo, sistema de coordenadas mundial, sistema de coordenadas de la cámara y sistema de coordenadas de la pantalla. En realidad, este es un proceso para la visualización de imágenes en 3D: use _ObjectToWorld (es decir, la matriz M) para convertir las coordenadas del propio modelo al sistema de coordenadas mundial, luego use _WorldToCamera (es decir, la matriz V) para convertir del sistema de coordenadas mundial al sistema de coordenadas de la cámara. Y finalmente use _ Projection (matriz P) para realizar la conversión de la cámara al sistema de coordenadas de la pantalla y finalmente muestre la imagen 3D en la pantalla. Adjunto un artículo de Baidu Wenku (http://wenku.baidu.com/link ?url=A3AGV805UK5rcsEjkaL1h6QjnxsktvCscyNJqaHvfe2cIhwXMam6ZzH4Gxbu_XB7Jd7ripxjd0eR51Q6cP t9xPxTiX3MeHtFaWkwexBlZti ).

Varias operaciones importantes en matrices incluyen: determinante matricial, transposición matricial, cuatro operaciones aritméticas matriciales, inversión matricial... Estos conocimientos no se discutirán aquí. Aquí hay una breve introducción a varias transformaciones matriciales comunes.

Girar la matriz alrededor de los ejes de coordenadas:

2015-12-06_100936

Matriz de escala:

imagen

matriz de proyección

imagen

matriz de traducción

imagen

Las anteriores son varias matrices de uso común. Para obtener más información, debe confiar en Du Niang y Google.

     b. A continuación se presentan varias aplicaciones gráficas simples: selección de iluminación, reflexión difusa e implementación de luces.

     1. Eliminación ligera. En este punto debemos entender el "concepto de normal" (una línea de puntos que siempre es perpendicular a un determinado plano ). Nuestra perspectiva es el vector del objeto a la cámara. Si el ángulo formado por la normal N y la línea de visión E es menor a 90 grados, entonces el observador debe estar aproximadamente en el lado frontal, por el contrario, si es mayor a 90 grados, debe estar en el lado opuesto de la superficie. El objeto no debe observarse (la normal se puede obtener mediante la multiplicación de diferencias vectoriales y el ángulo se puede calcular mediante la multiplicación de puntos vectoriales). En este momento, es necesario Después de eliminarlo, las siguientes dos imágenes explican brevemente:

imagen

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

imagen

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

imagen

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

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

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

 

Copiar código
//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"
}
Copiar código

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

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

imagen

下面贴上该Shader 的源码

Copiar código
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
        }
    }
}
Copiar código

Ok, este intercambio termina aquí. A continuación se adjunta una demostración escrita en C# para simular el proceso de renderizado de imágenes 3D y la demostración del Shader anterior (enlace: http://pan.baidu.com/s/1c0Yk3KG Contraseña :  1j1k)

Supongo que te gusta

Origin blog.csdn.net/qq_25189313/article/details/78075527
Recomendado
Clasificación