【shaderforge学习笔记】 Geometry Data(物理信息)

shaderforge物理信息

这里写图片描述


Bitangent Dir

1. 官方说明
这里写图片描述
输出世界空间下模型网面的bitangent(副切线)方向

2. 节点输出
bitangent方向的三维向量
这里写图片描述

3. 简单介绍TBN切线空间以及Bitangent向量
切线空间,同局部空间、世界空间等一样,是3D图形学中众多的坐标系之一。切线空间基于网面的顶点由法线、切线、副切线构成一个互相垂直的三维坐标系。当模型网面变形时,切线坐标系必定跟着面一起运动,那么在这个坐标系里的某个点或向量,不需要变动。当整个面发生变化时,我们只需要计算面上的坐标系到世界坐标系的转换矩阵,那么定义在这个面上的点或坐标(固定的),乘以这个矩阵即可得到在世界中的坐标。这个坐标系术语里称为tangent space(或称TBN切线空间)。
一个右手坐标系的TBN切线坐标系如下图所示:

这里写图片描述
TBN切线空间的TBN这三个字母分别代表tangent、bitangent和normal向量。
tangent是顶点的切线,normal是顶点的法线,bitangent由tangent和normal叉乘(注意进行叉乘的N和T的先后顺序!在右手坐标系中是N × T,在左手坐标系中是T x N! 注意:Unity是左手坐标系)得到,是一个垂直于tangent和normal的向量bitangent。

切线坐标系转换到世界坐标系

切线空间到世界空间的转换矩阵T2W:

\begin{bmatrix}
T_{x} & T_{y} & T_{z} \\ 
B_{x} & B_{y} & B_{z} \\ 
N_{x} & N_{y} & N_{z} 
\end{bmatrix}

切线空间下的法线向量乘以转换矩阵,得到世界坐标系下的切线向量

normalWorld= normalize(mul(normalTangent,T2W));

4. Unity Shader获取Bitangent Dir
对于每个顶点,我们只要提供法线normal和切线tangent两个向量即可。bitangent向量可以通过tangent叉乘normal得到。

struct VertexInput {
    float4 vertex : POSITION;
    float3 normal : NORMAL;
    float4 tangent : TANGENT;
};
struct VertexOutput {
    float3 normalDir : TEXCOORD0;
    float3 tangentDir : TEXCOORD1;
    float3 bitangentDir : TEXCOORD2;
};
VertexOutput vert (VertexInput v) {
    o.normalDir = UnityObjectToWorldNormal(v.normal);
    o.tangentDir = normalize( mul( unity_ObjectToWorld, float4( v.tangent.xyz, 0.0 ) ).xyz );
    o.bitangentDir = normalize(cross(o.normalDir, o.tangentDir));
    return o;
}

参考

Unity 点乘和叉乘的原理和使用
【D3D11游戏编程】学习笔记二十四:切线空间(Tangent Space)


Depth

1. 官方说明
这里写图片描述
Depth为摄像机投影空间的近平面到物体的距离。

2. 节点输出
一个一维数据,表示从物体位置到相机投影空间近裁屏幕的距离大小
这里写图片描述

3. 简单介绍相机的投影空间
将3D的物体显示到2D的屏幕上,需要投影和剪裁,相机的投影方式一般有两种:正交投影(Orthographic)和透射投影(Perspective)。相机的正交投影空间和透视投影空间都有近平面(通过near值调节近平面位置)和远平面(通过far值调节远平面位置),我们认为投影空间近平面到物体的距离为物体的深度值。
这里写图片描述
more:
投影中的正交和透视
4. Unity Shader获取深度信息

相关语义说明
ComputeScreenPos()作用是获得一个投影点对应的屏幕坐标点
COMPUTE_EYEDEPTH()计算顶点摄像机空间的深度:距离裁剪平面的距离,线性变化;
_ProjectionParamsx=1(-1),y=near,z=far,w=1+1/far,near和far是近远裁屏幕到相机的距离
struct VertexInput {
    float4 vertex : POSITION;
};
struct VertexOutput {
    float4 pos : SV_POSITION;
    float4 projPos : TEXCOORD0;
};
VertexOutput vert (VertexInput v) {
    o.pos = UnityObjectToClipPos( v.vertex );
    o.projPos = ComputeScreenPos (o.pos);
    COMPUTE_EYEDEPTH(o.projPos.z);
    return o;
}
float4 frag(VertexOutput i) : COLOR {
    float depth = max(0,i.projPos.z - _ProjectionParams.g);
    ...
}

Face Sign

1. 官方说明
这里写图片描述
Face Sign节点用于检测当前的面是正面还是背面。根据节点下拉框中指定的内容,正面输出1,背面输出-1或0。
2. 节点输出
这里写图片描述
3. UnityShader是实现Face Sign

shader语义说明
VFACEVFACE给出面部朝向信息
float4 frag(VertexOutput i, float facing : VFACE) : SV_Target 
{
    // VFACE input positive for frontbaces,
    // negative for backfaces
    float faceSign = ( facing >= 0 ? 1 : -1 );
    ...
}

参考

Unity Shader Manual —— Shader semantics

Fresnel

1. 官方说明
这里写图片描述
输出值为表面法线与视线方向向量之间的点积结果。如果您想使用自定义法线,则使用[Nrm]。默认情况下,使用扰动的法线。[Exp]指定输出的指数。更高的数值会使菲涅尔更薄。
常用于制作光晕、描边等效果。
2. 节点输入
- [Nrm] 默认为物体在世界空间上的法线向量
- [Exp] 为对点乘法线与视线的结果进行exp次幂运算的exp值,默认为1。
3. 节点输出
法线和视线点乘的结果。
这里写图片描述
4. UnityShader实现fresnel

struct VertexInput {
    float4 vertex : POSITION;
    float3 normal : NORMAL;
};
struct VertexOutput {
    float4 pos : SV_POSITION;
    float4 posWorld : TEXCOORD0;
    float3 normalDir : TEXCOORD1;
};
VertexOutput vert (VertexInput v) {
    VertexOutput o = (VertexOutput)0;
    o.normalDir = UnityObjectToWorldNormal(v.normal);
    o.posWorld = mul(unity_ObjectToWorld, v.vertex);
    o.pos = UnityObjectToClipPos( v.vertex );
    return o;
}
float4 frag(VertexOutput i, float facing : VFACE) : COLOR {
    float3 viewDirection = normalize(_WorldSpaceCameraPos.xyz - i.posWorld.xyz);
    float3 normalDirection = i.normalDir;

    float power = 1.0;
    float fresnel = pow(1.0-max(0,dot(normalDirection, viewDirection)),power);
    ...
}

Normal Direction

1. 官方说明
这里写图片描述
Outputs the direction of the mesh normal, in world space. The 【0Perturbed checkbox makes it use the normals after having applied the “Normal” input of the main node, such as a normal map.

输出为世界空间下的模型网格的法线方。如果勾选节点的Perturbed复选框则主节点的“法线通道”数据代替模型网格法线数据。
2. 节点输出
输出为表示法线向量的三维数据
这里写图片描述

3. UnityShader获取法线信息
- 获取模型顶点的法线信息

struct VertexInput {
    float3 normal : NORMAL;
    ...
};
struct VertexOutput {
    float3 normalDir : TEXCOORD1;
};
VertexOutput vert (VertexInput v) {
    o.normalDir = UnityObjectToWorldNormal(v.normal);
    return o;
}
float4 frag(VertexOutput i) : COLOR {
    float3 normalDirection = i.normalDir;
    ...
}
  • 获取法线贴图的法线信息
Shader "Hidden/normal"
{
    Properties
    {
        _NormalTex("Normal Texture", 2D) = "white" {}
    }
    SubShader
    {
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"
            #include "Lighting.cginc"
            #include "AutoLight.cginc"
            struct appdata
            {
                ...
                float3 normal : NORMAL;
                float4 tangent : TANGENT;
            };

            struct v2f
            {
                ...
                float3 normalDir : TEXCOORD1;
                float3 tangentDir : TEXCOORD2;
                float3 bitangentDir : TEXCOORD3;
            };

            v2f vert (appdata v)
            {
                v2f o;
                ...

                o.tangentDir = normalize(mul(unity_ObjectToWorld,v.tangent.xyz));
                o.normalDir = normalize(UnityObjectToWorldNormal(v.vertex));
                o.bitangentDir = normalize(cross(o.normalDir,o.tangentDir));
                return o;
            }

            sampler2D _NormalTex;
            fixed4 frag (v2f i) : SV_Target
            {
                // 从法线贴图中获取切线向量,并将之从切线空间转换到世界空间
                float3x3 tangentTransform = float3x3( i.tangentDir, i.bitangentDir, i.normalDir);
                float3 normalFromTex = UnpackNormal(tex2D(_NormalTex,i.uv)).rgb;
                float3 normalDirection = normalize(mul(normalFromTex,tangentTransform));
                ...
            }
        }
        ENDCG
    }
}

Object Position

1. 官方说明
这里写图片描述
输出世界空间下物体锚点的位置
2. 节点输出
表示物体锚点在世界坐标系下位置的四维(xyzw)信息。
3. UnityShader获取物体锚点在世界空间在的位置
物体在自己的模型坐标系下锚点总是(0,0,0),因此直接转为世界坐标系(乘以unity_ObjectToWorld)即可。

float4 objPos_World = mul ( unity_ObjectToWorld, float4(0,0,0,1) );

Object Scale

1. 官方说明
这里写图片描述
输出物体的大小。如果勾选上节点的reciprocal(倒数)选项,可以让计算效率更高,给你的是相反的刻度(1/刻度)。请注意,如果网格被批处理,Object Scale将不起作用。
2. 节点输出
一个表示xyz三个方向上scale大小的三维数据
这里写图片描述

3. UnityShader获取物体Scale大小信息

float3 recipObjScale = float3( length(unity_WorldToObject[0].xyz), length(unity_WorldToObject[1].xyz), length(unity_WorldToObject[2].xyz) );
float3 objScale = 1.0/recipObjScale;

Screen Position

1. 官方说明
这里写图片描述
输出模型网格当前部分的屏幕位置,可作为屏幕空间映射的UV坐标。在节点下拉框中,“Normalized”将把{0,0}放在屏幕的中央,而{1,1}在右上角。“Tiled”将在中心保持{0,0},但是会根据你的纵横比在X轴上缩放。

2. 节点输出
这里写图片描述

3. UnityShader获取屏幕uv信息
- Normalized screenUV

i.screenPos = float4( i.screenPos.xy / i.screenPos.w, 0, 0 );
i.screenPos.y *= _ProjectionParams.x;
float2 screenUV = i.screenPos.xy;
  • Tiled screenUV
i.screenPos = float4( i.screenPos.xy / i.screenPos.w, 0, 0 );
i.screenPos.y *= _ProjectionParams.x;
float2 screenUV = float2(i.screenPos.x*(_ScreenParams.r/_ScreenParams.g), i.screenPos.y);

Tangent Direction

1. 官方说明
这里写图片描述
输出世界空间的,模型网格切线的方向。

2. 节点输出
表示切线方向的三维数据
3. UnityShader获取Tangent direciton

struct VertexInput {
    ...
    float4 tangent : TANGENT;
};
struct VertexOutput {
    ...
    float3 tangentDir : TEXCOORD1;
};
VertexOutput vert (VertexInput v) {
    o.tangentDir = normalize( mul( unity_ObjectToWorld, float4( v.tangent.xyz, 0.0 ) ).xyz );
    ...
}

UV Coordinate

1. 官方说明
这里写图片描述
输出物理模型的uv信息。下拉菜单允许您选择UV通道0或UV通道1。注意,光照烘焙的模型网格使用UV1作为它们的光影图UV。
2. 节点输出
uv输出模型表面的uv值,u、v分别从0匀速增加到1,uv构成一个从(0,0)到(1,1)的二维数组
这里写图片描述
3. UnityShader获取UV信息

struct VertexInput {
    float2 uv : TEXCOORD0;
    ...
};
struct VertexOutput {
    float2 uv0 : TEXCOORD0;
    ...
};
VertexOutput vert (VertexInput v) {
    o.uv0 = v.uv;
    ...
}

Vertex Color

1. 官方说明
这里写图片描述
输出顶点的颜色。如果您已经在顶点颜色中烘焙了环境光遮蔽,或者想要将网格着色为顶点颜色,或者使用顶点颜色来做其他的事情,这就是您想要的节点。

2. 节点输出
模型顶点颜色RGBA颜色四维数据

3.UnityShader获取顶点颜色

struct VertexInput {
    float4 vertexColor : COLOR;
    ...
};
struct VertexOutput {
    float4 vertexColor : COLOR;
    ...
};
VertexOutput vert (VertexInput v) {
    o.vertexColor = v.vertexColor;
    ...
}

View Direction

1. 官方说明
这里写图片描述
在世界空间中,从物体到相机的方向。
2. 节点输出
表示视角方向的三维数据

3.UnityShader获取view dir信息

struct VertexInput {
    float4 vertex : POSITION;
};
struct VertexOutput {
    float4 posWorld : TEXCOORD0;
    ...
};
VertexOutput vert (VertexInput v) {
    VertexOutput o;
    ...
    o.posWorld = mul(unity_ObjectToWorld, v.vertex);
    return o;
}
float4 frag(VertexOutput i) : COLOR {
    float3 viewDirection = normalize(_WorldSpaceCameraPos.xyz - i.posWorld.xyz);
    ...
}

View Reflection

1. 官方说明
这里写图片描述
2.节点输出
表示视角反射方向的三维数据
这里写图片描述
3. UnityShader获取view ref信息
以normal为法线,viewdirection的反方向为入射方向,得到的出射方向就是View Reflection

struct VertexInput {
    float4 vertex : POSITION;
    float3 normal : NORMAL;
};
struct VertexOutput {
    float4 pos : SV_POSITION;
    float4 posWorld : TEXCOORD0;
    float3 normalDir : TEXCOORD1;
};
VertexOutput vert (VertexInput v) {
    VertexOutput o;
    o.normalDir = UnityObjectToWorldNormal(v.normal);
    o.posWorld = mul(unity_ObjectToWorld, v.vertex);
    o.pos = UnityObjectToClipPos( v.vertex );
    return o;
}
float4 frag(VertexOutput i) : COLOR {
    i.normalDir = normalize(i.normalDir);
    float3 viewDirection = normalize(_WorldSpaceCameraPos.xyz - i.posWorld.xyz);
    float3 normalDirection = i.normalDir;
    float3 viewReflectDirection = reflect( -viewDirection, normalDirection );
    ...
}

World Position

1. 官方说明
这里写图片描述
输出物体在世界空间下的位置

2. 节点输出
物体世界坐标系下的xyzw位置信息

3. UnityShader获取物体的世界坐标位置信息

struct VertexInput {
    float4 vertex : POSITION;
    ...
};
struct VertexOutput {
    float4 posWorld : TEXCOORD0;
    ...
};
VertexOutput vert (VertexInput v) {
    VertexOutput o;
    o.posWorld = mul(unity_ObjectToWorld, v.vertex);
    ...
}
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页