ShaderLab学习笔记

论坛 期权论坛 脚本     
匿名技术用户   2021-1-6 19:56   11   0

笔记:

18.mesh Filter 存储一个Mesh(网格,模型的网络,即模型的所有三角面信息)

19.mesh Render 用来渲染模型外观 (贴图+shader)
20.游戏程序(shader命令)->图形接口(OpenGL,DirectX)->显卡驱动->显卡渲染
21.GLSL OpenGL HLSL DirectX
CG语言 Nvidia 在两个平台都可以使用
Unity中ShaderLab(对CG封装)
22.Shader分类:1)表面着色器 Surface 2)顶点片元着色器 Vertex/Fragment Shader 3)固定函数着色器(弃用)
23.shader中的属性:Color,Vector,Int,Float,Range,2D,Cube,3D
对应shader代码中数据结构:float4,float3,float2,float,half,fixed,sampler2D,sampler3D
float 32 half 16 fixed 11
24.shader中的语义
从应用程序传递到顶点函数的语义包括:POSITION 顶点坐标(模型空间下)
NORMAL 法线(模型空间下)
TANGENT 切线(模型空间下)
TEXCOORD 0-n 纹理坐标
COLOR 顶点颜色
从顶点函数传递给片元函数的时候可以使用的语义
SV_POSITION 剪裁空间中的顶点坐标(一般是系统直接使用)
COLOR0 可以传递一组值
TEXCOORD 0-7 传递纹理坐标
片元函数传递给系统
SV_Target 颜色值,显示到屏幕上的颜色
25.标准光照模型
标准光照模型中,我们把进入摄像机的光分为四个部分
自发光:
高光反射:specular=直射光*pow(cosθ,高光参数x) θ是反射光和摄像机方向的夹角 x值越大光圈越小
漫反射:diffuse =直射光颜色*max(0,cosθ(光和法线的夹角))
环境光:abmbient
26.Tags{"LightMode"="ForwardBase"}
只有定义了正确的LightMode才能得到一些Unity的内置光照变量
#include "Lighting.cginc"
包含Unity的内置的文件,擦恶意使用Unity内置的一些变量


27.normalize()用来把一个向量单位化
max()用来取得最大值
dot 用来取得两个向量的点积
_WorldSpaceLightPos() 取得平行光的位置
_LightColor()取得平行光的颜色
UNITY_MATRIX_MVP 这个矩阵用来把一个坐标从模型空间转换到剪裁空间
_World2Object 这个矩阵用来把一个方向向量从世界空间转换到模型空间
UNITY_LIGHTMODEL_AMBITENT 用来获取环境光
reflect(a,b) a为入射光,b为法向量,得到的是反射光

29.兰伯特光照模型
Diffuse=直射光颜色*max(0,cosθ) cosθ即光和法线的夹角 cosθ=光方向*法线方向
半兰伯特光照模型
Diffuse=直射光颜色*max(cosθ*0.5+0.5)
半兰伯特光照模型可以让背光面不是完全的黑暗,效果较好


30.Blinn光照模型
Specular=直射光*pow(max(cosθ,0),高光参数)
Blinn-Phong 光照模型
Specular=直射光*pow(max(cosβ,0),高光参数) β是视野方向与反射光方向夹角的一半


31.UnityCG.cginc 中一些常用函数
摄像机方向(视角方向)
float3 WorldSpaceViewDir(float4 v) 根据模型空间中的顶点坐标得到(世界空间)从这个点到摄像机的观察方向
float3 UnityWorldSpaceViewDir(float4 v) 世界空间中的顶点坐标==>世界空间从这个点到摄像机的观察方向
float3 ObjSpaceViewDir(float4 v) 模型空间中的顶点坐标==>模型空间从这个点到摄像机的观察方向
光源方向
float3 WorldSpaceLightDir(float4 v) 模型空间中的顶点坐标==>世界空间中从这个点到光源的方向
float3 UnityWorldSpaceLightDir(float4 v) 世界空间中的顶点坐标==>世界空间中从这个点到光源的方向
float3 ObjSpaceLightDir(float4 v) 模型空间中的顶点坐标==>模型空间从这个点到光源的方向
方向转换
float3 UnityObjectToWorldNormal(float3 norm) 法线方向 模型空间==>世界空间
float3 UnityObjectToWorldDir(float3 dir) 方向 模型空间==>世界空间
float4 UnityWorldToObjectDir(float3 dir) 方向 世界空间==>模型空间

32.纹理贴图及法线映射
tex2D(贴图,纹理坐标) 返回像素点的颜色
贴图偏移量及缩放
贴图名+_ST中xy存储着偏移,zw存储着缩放
法线映射用一张贴图上的rgb值存储该点坐标的法线向量,使用法线映射可以在不用修改模型情况下产生立体感
切线空间贴图为蓝色;模型空间贴图包含各种颜色
由于法线向量取值为-1到+1,rgb存储0到1 所以使用算法 pixel=(normal+1)/2
使用预设的宏TANGENT_SPACE_ROTATION会在rotation(内置的字段)生成矩阵,使用该矩阵可以把模型空间中光

的方向转换到切线空间中


代码及注释:

// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Custom/myShader6" {
    Properties{
   _Color("Color",COLOR)=(1,1,1,1)
   _Specular("Specular",Range(8,200))=8
   _MainTex("Texture",2D)="white"{}
   _NormalMap("NormalTex",2D)="bump"{}
   _BumpScale("BumpScale",Float)=1
 }
 SubShader {
 Pass{
     Tags{"LightMode"="ForwardBase"}
  CGPROGRAM
#include "Lighting.cginc"
#pragma vertex vert
#pragma fragment frag

        //向顶点函数传递变量的结构体,包括:
  //POSITION 顶点坐标(模型空间下)
        //NORMAL 法线(模型空间下)
        //TANGENT 切线(模型空间下)
        //TEXCOORD 0-n 纹理坐标
        //COLOR 顶点颜色
  sampler2D _MainTex;
  sampler2D _NormalMap;
  float4 _NormalMap_ST;
  float4 _MainTex_ST;
  float4 _Color;
  int _Specular;
  float _BumpScale;
        struct a2v
  {
    float4 vertex:POSITION;
    float3 normal:NORMAL;
    float4 tangent:TANGENT;  //tangent.w用来确定切线空间中坐标轴的方向
    float4 texcoord:TEXCOORD;
  };
  //顶点函数向片元函数传递的结构体,包括:
  //SV_POSITION 剪裁空间中的顶点坐标(一般是系统直接使用)
        //COLOR0 可以传递一组值
        //TEXCOORD 0-7 传递纹理坐标
  struct v2f
  {
    float4 position:SV_POSITION;
    fixed3 worldNormalDir:COLOR0;
    fixed3 lightDir:TEXCOORD1;
    fixed4 vertex:COLOR1;
    fixed4 uv:TEXCOORD;
  };
        v2f vert (a2v v){
    v2f f;
    f.position=UnityObjectToClipPos(v.vertex);                 //顶点坐标转剪裁空间
    f.worldNormalDir=mul(v.normal,(float3x3)unity_WorldToObject);    //法线向量从模型空间转到世界空间
    f.vertex=v.vertex;
    f.uv.xy=v.texcoord.xy*_MainTex_ST.xy+_MainTex_ST.zw;       //xy来存储主贴图的纹理坐标
    f.uv.zw=v.texcoord.xy*_NormalMap_ST+_NormalMap_ST.zw;      //zw来存储法线贴图的纹理坐标
    TANGENT_SPACE_ROTATION;                                    //获得用于转换切线空间的矩阵
    f.lightDir=mul(rotation,ObjSpaceLightDir(v.vertex));       //获得切线空间中光的方向
    return f;
  };
  fixed4 frag(v2f f):SV_TARGET {
    fixed3 ambient=UNITY_LIGHTMODEL_AMBIENT.rgb;               //环境光
    fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
    fixed3 normalDir = normalize(f.worldNormalDir);            
    fixed3 reflectDir=normalize(reflect(-lightDir,normalDir));
    fixed3 viewDir=normalize( _WorldSpaceCameraPos.xyz-mul(f.vertex,unity_WorldToObject).xyz);
    fixed3 halfDir=normalize(reflectDir+viewDir);
    fixed3 specular=_LightColor0.rgb*pow(max( dot(reflectDir,halfDir),0),_Specular);  //Blinn-Phong高光反射
    fixed3 normalColor =UnpackNormal(tex2D(_NormalMap,f.uv.zw));//先取得rgb值然后转化为法线向量
    normalColor.xy=normalColor.xy*_BumpScale;                  //添加凹凸属性
    fixed3 tangentNormal=normalize(normalColor);               //归一化
    fixed3 texColor=tex2D(_MainTex,f.uv.xy)*_Color;            //主贴图像素点颜色
    fixed3 diffuse=_LightColor0.rgb*(dot(tangentNormal,f.lightDir)*0.5+0.5)*texColor; //漫反射光合成
    float3 tempColor=diffuse+specular+ambient*texColor;        //对环境光处理
    return fixed4(tempColor,1);
  }
  ENDCG
 } 
}
 FallBack "VertexLit"
}

吐槽一下VS对Shader的支持,排个版都排不好,花了几天时间大概学习了一下shader的基础,暂时也不准备深入了,毕竟不当技美,就到这里吧。



分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:7942463
帖子:1588486
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP