Unity_Shader初级篇_5_Unity Shader入门精要

这篇博客介绍了Unity Shader的基础知识,包括顶点/片元着色器的基本结构、Pass语义块、顶点着色器与片元着色器之间的通信、属性的使用,以及Unity中的语义概念。讲解了如何在Shader中处理模型数据,如顶点位置、纹理坐标、法线,并讨论了Shader中结构体和语义的重要性,以及Unity Shader和DirectX的语义差异。此外,还提及了Shader的调试方法和跨平台注意事项。
摘要由CSDN通过智能技术生成

5开始Unity Shader学习之路

在初级篇中实现的Unity Shader大多不能直接用于真是项目中,因为他们缺少了完整的光照计算,例如阴影、光照衰弱等。仅仅是为了阐述一些实现原理。

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

Shader "MyShaderName"{
  Properties{
    //属性
  }
  SubShader{
    //针对显卡a的SubShader
    Pass{
      //设置渲染状态和标签

      //开始CG代码片段
      CGPROGRAM
      //该代码片段的编译指令,例如:
      #pragma vertex vert
      #pragma fragment frag

      //CG代码写在这里
      ENDCG
      //其他设置
    }
    //针对显卡B的SubShader
  }

  //上述SubShader都失败后用于回调的Unity Shader
  Fallback "VertexLit"
}

其中,最重要的部分是Pass语义块,我们绝大部分的代码都是写在这个语义块里面的。

Shader "Custom/Test" {
    SubShader{
        Pass{
        CGPROGRAM
        #pragma vertex vert
        #pragma fragment frag
        // POSITION 和SV_POSITION都是CG/HLSl中的语义(semantics)他们是不可省略的 
        //这些语义将告诉系统用户需要哪些输入值,以及用户的输出是什么。
        //这里POSITION将告诉Unity,把模型的顶点坐标填充到输入参数v中,
        //SV_POSITION将告诉Unity,顶点着色器的输出是裁剪空间中的顶点坐标。
        //UNITY_MATRIX_MVP矩阵是Unity内置的模型.观察.投影矩阵(4.8);
        float4 vert(float4 v : POSITION) :SV_POSITION{
    return mul(UNITY_MATRIX_MVP,v);
    }
        //本例中frag没有任何输入。它的输出是一个fixed4类型的变量,并且使用了SV_Target语义进行限定。
        //SV_Target也是HLSL中的一个系统语义,他等同于告诉渲染器,把用户的输出颜色存储到一个渲染目标中,这里将输出到默认的帧缓存中。
        //片元着色器中的代码很简单,返回一个表示白色的fixed4类型的变量。
        fixed4 frag() : SV_Target{
return fixed4(1.0,1.0,1.0,0.0);
    }
        ENDCG
    }
    }
}

#pragma vertex vert

#pragma fragment frag

它们告诉Unity,哪个函数包含可顶点着色器的代码,哪个函数包含了片元着色器的代码。

在上面的例子中,在顶点着色器中我们使用POSITION语义得到了模型的顶点位置。
现在,我们想要得到模型上每个顶点的纹理坐标和法线方向。我们需要使用纹理坐标来访问纹理,而法线可用于计算光照。因此我们需要为顶点着色器定义一个新的输入参数,这个参数不在是一个简单的数据类型,而是一个结构体。

Shader "Custom/Test" {
    SubShader{
        Pass{
        CGPROGRAM
        #pragma vertex vert
        #pragma fragment frag

        //使用一个结构体来定义顶点着色器的输入
        struct a2v {
        //POSITION语义告诉Unity,用模型空间的顶点坐标填充vertex变量
        float4 vertex : POSITION;
        //NORMAL语义告诉Unity,用模型空间的法线方向填充normal变量
        float3 normal:NORMAL;
        //TEXCOORDO语义告诉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
    }
    }
}

上述代码中,我们声明了一个新的结构体a2v,它包含立顶点着色器需要的模型数据。它包含了顶点着色器需要的模型数据。Unity支持的语义有:POSITION,TANGENT,NORMAL,TEXCOORD0,TEXCOORD1,TEXCOORD2,TEXCOORD3,COLOR等。
为了创建一个自定义的结构体,我们必须使用如下格式来定义它:

struct StructName{
  Type Name:Semantic;
  Type Name:Semantic;
};

其中,语义是不可以被省略的。在5.4节中,我们将给出这些语义的含义和用法。

a表示应用(application),v表示顶点着色器(vertex shadr),a2v的意思就是把数据从应用阶段传递到顶点着色器中。
那么,填充到POSITION,TANGENT,NORMAL这些语义块中的数据究竟是从哪里来的呢?在Unity中,他们是由使用该材质的Mesh Render组件提供的。在每帧调用Draw Call的时候,Mesh Render组件会把他负责渲染的模型数据发送给Unity

  • 17
    点赞
  • 69
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值