首页 > 其他分享 >unityshader学习笔记4

unityshader学习笔记4

时间:2022-10-08 11:01:36浏览次数:49  
标签:1.0 SV 笔记 学习 unityshader POSITION float4 顶点 着色器

顶点/片元着色器的基本结构:

Shader "Custom/SimpleShader"
{
    SubShader {
        Pass {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            float4 vert(float4 v : POSITION) : SV_POSITION {
                return mul(UNITY_MATRIX_MVP, v);
            }
            fixed4 frag() : SV_Target {
                return fixed4(1.0, 1.0, 1.0, 1.0);
            }
            ENDCG
        }
    }
}

Properties属性不是必需的,可以选择不声明任何材质属性

编译指令: (name就是指定的函数名)

#pragma vertex name ---------告诉Untiy哪个函数包含了顶点着色器的代码

#pragma fragment name ---------告诉Unity哪个函数包含了片元着色器的代码

 

float4 vert(float4 v : POSITION) :SV_POSITION {

  return mul(UNITY_MATTIX_MVP,  v);

}

1.顶点着色器代码,它是逐顶点执行的

2.vert函数的输入v包含了这个顶点的位置,这是通过POSITION语义指定的

3.它的返回值是一个float4类型的变量,它是该顶点在裁剪空间中的位置

4.POSITION和SV_POSITION都是CG/HLSL中的语义,它们是不可忽略的,这些语义告诉系统用户需要哪些输入值,以及用户的输入是什么.如:

  *  POSITION告诉Unity,把模型的顶点坐标填充到输入参数v中

  *  SV_POSITION告诉Unity,顶点着色器的输出是裁剪空间中的顶点坐标

如果没有这些语义来限定输入和输出参数的话,渲染器就不知道用户的输入输出是什么.

语义实际上是一个赋给Shader输入和输出的字符串,这个字符串表达了这个参数的含义,可以让Shader知道从哪里读取数据,并把数据输出到哪里,Unity并没有支持所有语义.

DirectX10以后有了新的语义类型,即系统数值语义,以SV开头(system-value).

 

  *填充到POSITON,TANGENT,NORMAL等这些语义中的数据哪里来的:

 

      在Unity中,它们是由使用该材质的Mesh Render组件提供的.

 

      每帧调用Draw Call的时候,Mesh Render组件会把它负责渲染的模型数据发送给UnityShader

 

  *从应用阶段传递模型数据顶点着色器时Unity支持的常用语义:

    POSITION-----------模型空间中的顶点位置,通常float4

    NORMAL------------顶点法线,通常float3

    TANGENT------------顶点切线,通常float4

    TEXCOORDn,如TEXCOORD0,TEXCOORD1--------该顶点的纹理坐标,通常float2或float4

    COLOR---------------顶点颜色,通常fixed4或float4

  *从顶点着色器传递数据给片元着色器时Unity支持的常用语义:

    SV_POSITION-------裁剪空间中的顶点坐标,必须包含一个

    COLOR0--------------通常用于输出第一组顶点颜色,非必需

    COLOR0--------------通常用于输出第二组顶点颜色,非必需

    TEXCOORD0~TEXCOORD7-------通常用于输出纹理坐标,非必需

    通常把自定义数据从顶点着色器传递给片元着色器,一般选用TEXCOORD0等

  *片元着色器输出时Unity支持的常用语义:

    SV_Target-----------输出值将会存储到渲染目标中

 

fixed4 frag() : SV_Target {

  return fixed4(1.0, 1.0, 1.0, 1.0);

}

frag函数没有任何输入

它的输出是一个fixed4类型的变量,并使用SV_Target语义进行限定,告诉渲染器,把用户的输出颜色存储到一个渲染目标中,这里将输出到默认的帧缓存中.

 

 

上述在顶点着色器中使用了POSITION语义得到了模型的顶点位置,现在我们想要得到更多模型数据:

Shader "Custom/SimpleShader"
{
    SubShader {
        Pass {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            //使用一个结构体来定义顶点着色器的输入             struct a2v { //a2v:a表示应用(application),v表示顶点着色器(vertex shader),a2v的意思是把数据从应用阶段传递到顶点着色器中                 //POSITION语义告诉Unity,用模型空间的顶点坐标填充vertex变量                 float4 vertex : POSITION;                 //NORMAL语义告诉Unity,用模型空间的法线方向填充normal变量                 float3 normal : NORMAL;           //TEXCOORD0语义告诉Unity,用模型的第一套纹理坐标填充texcoord变量                 float4 texcoord : TEXCOORD0;             }             float4 vert(a2v v) : SV_POSITION {                 //使用v.vertex来访问模型空间的顶点坐标                 return mul(UNITY_MATRIX_MVP, v.vertex);             }             fixed4 frag() : SV_Target {                 return fixed4(1.0, 1.0, 1.0, 1.0);             }             ENDCG         }     } }

  

顶点着色器与片元着色器之间通信:

Shader "Custom/SimpleShader" {
    SubShader {
        Pass {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            struct a2v {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
                float4 texcoord : TEXCOORD0;
            };
            //使用一个结构体来定义顶点着色器的输出
            struct v2f {
             //SV_POSITION语义告诉Unity,pos里面包含了顶点在裁剪空间中的位置信息
                float4 pos : SV_POSITION;
                //COLOR0语义可以用于存储颜色信息
                fixed3 color : COLOR0;
            };
            v2f vert(a2v v) {
                //声明输出结构
                v2f o;
                o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
                //v.normal包含了顶点的法线方向,其分量范围在[-1.0, 1.0]
                //下面代码把分量范围映射到了[0.0, 1.0]
                //存储到0.color中传递给片元着色器
                o.color = v.normal * 0.5 + fixed3(0.5, 0.5, 0.5);
                return o;
            }
            fixed4 frag(v2f i) : SV_Target {
                //将插值后的i.color显示到屏幕上
                return fixed4(i.color, 1.0);
            }
            ENDCG
        }
    }
}

我们声明了一个新的结构体v2f,用于在顶点着色器和片元着色器之间传递信息

v2f中也需要定义每个变量的语义,如:

  SV_POSITION 必须包含,否则渲染器将无法得到裁剪空间中的顶点坐标,也就无法把顶点映射到屏幕上

  COLOR0 中的数据可以自行定义,一般存储颜色,类似的有COLOR1等

需要注意的是  顶点着色器是逐顶点调用的,片元着色器是逐片元调用的.

片元着色器中的输入实际上是把顶点着色器的输出进行插值后得到的结果

 

如何使用属性:

Shader "Custom/SimpleShader"
{
    Properties {
        //声明一个Color类型的属性
        _Color ("Color Tint", Color) = (1.0, 1.0, 1.0, 1.0)
    }
    SubShader {
        Pass {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            //在CG代码中,我们需要定义一个与属性名称和类型都匹配的变量
            fixed4 _Color;

            struct a2v {   
          float4 vertex : POSITION;
                float3 normal : NORMAL;
                float4 texcoord : TEXCOORD0;
            };

            struct v2f {
                float4 pos : SV_POSITION;
                fixed3 color : COLOR0;
            };

            v2f vert(a2v v) {
                v2f o;
                o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
                o.color = v.normal * 0.5 + fixed3(0.5, 0.5, 0.5);
                return o;
            }

            fixed4 frag(v2f i) : SV_Target { 
                fixed3 c = i.color;
                //使用Color属性来控制输出颜色
                c *= _Color.rgb;
                return fixed4(c, 1.0);
            }
            ENDCG
        }
    }
}

 

上面代码中,我们首先添加了Properties语义块,并在其中声明了一个属性_Color,它的类型是Color,初始值是(1.0,1.0,1.0,1.0)对应白色.

为了在CG代码中可以访问它,还需在CG代码片段中提前定义一个新的变量,这个变量的名称和类型必须与Properties语义块中的属性定义相匹配

 

           ShaderLab属性类型和CG变量类型的匹配关系:

           CG/HLSL中的3种数值类型的精度

 

标签:1.0,SV,笔记,学习,unityshader,POSITION,float4,顶点,着色器
From: https://www.cnblogs.com/xianguoguo/p/16768291.html

相关文章

  • dayjs学习笔记
    dayjs官网:https://dayjs.fenxianglu.cn/category/parse.html一、安装     npminstalldayjs--save二、引用     importdayjsfrom'dayjs'  Da......
  • C#学习第三天
      今天进行了C#的第三次学习,继续了解C#的相关知识:目录数组多维数组交错数组传递数组给函数参数数组Array类数组  声明数组并初始化的格式为Java还有C++中常用的方......
  • 狂神说学习笔记:Vue
    Vue1、概述Vue(读音/vjuː/,类似于view)是一套用于构建用户界面的渐进式JavaScript框架,发布于2014年2月。与其它大型框架不同的是,Vue被设计为可以自底向上逐层应用......
  • Java学习!
    Java应用构建工具:Ant,Maven,Jekin应用服务器:Tomcat,Jetty,Jboss,Websphere,WeblogicWeb开发:Struts,Spring,Hibernate,MyBatis大数据:Hadoop安卓 Java特性优势......
  • Java学习之路:快捷键
    常用的快捷键Ctrl+Shift:切换输入法Ctrl+C:复制Ctrl+V:粘贴Ctrl+X:剪切Ctrl+A:全选Ctrl+Z:撤销Ctrl+Y:返回撤销Ctrl+S:保存Shift+Delete:永久删除Alt+F4:退出窗口Win+R:打......
  • 狂神说学习笔记:JUC并发编程
    JUC并发编程1、什么是JUCJUC:java.util.concurrentRunnable没有返回值、效率相比入Callable相对较低!2、线程和进程进程:一个程序,QQ.exe,music.exe 本质是程序的集......
  • 前端程序员学习 Golang gin 框架实战笔记之三 panic 和 recovery
    上一节:前端程序员学习Golanggin框架实战笔记之二分析context1.Logger我把上一节main.go的代码换了:gin.New()换成了gin.Default()上一节我们说过,Default多了......
  • (八)模仿学习-展现可视化大屏
    我们通过前面的练习,完全可以完成一个返回页面的操作。首先我们准备一个action并在struts.xml中添加。创建action我们先什么数据都不返回,只返回一个页面在application......
  • 一个C#开发者学习SpringCloud搭建微服务的心路历程
    前言SpringCloud很火,很多文章都有介绍如何使用,但对于我这种初学者,我需要从创建项目开始学起,所以这些文章对于我的启蒙,帮助不大,所以只好自己写一篇文章,用于备忘。SpringC......
  • AJAX笔记
    AJAXAJAXAJAX=AsynchronousJavaScriptandXML(异步的JavaScript和XML)AJAX是一种无需重新加载整个页面的情况下能够更新部分网页的技术AJAX不是一种新的编......