UnityShader切线空间学习

此处连接凹凸感文章现在需要应用在立体的形状上
1、可视化切线空间

/// <summary>
/// 可视化切线空间
/// </summary>
public class TangentSpaceVisualizer : MonoBehaviour
{
    public float offset = 0.01f;
    public float scale = 0.1f;
    
    
    private void OnDrawGizmos()
    {
        MeshFilter meshFilter = GetComponent<MeshFilter>();
        if (meshFilter != null)
        {
            //meshFilter.mesh 这个只是创建一个网格副本,游戏结束不会对原有网格造成影响
            Mesh mesh = meshFilter.sharedMesh;
            if(mesh)
                ShowTangentSpace(mesh);
        }
    }

    private void ShowTangentSpace(Mesh mesh)
    {
        Vector3[] vertices = mesh.vertices;
        Vector3[] normals = mesh.normals;
        Vector4[] tangents = mesh.tangents;
        
        for (int i = 0; i < vertices.Length; i++)
        {
            ShowTangentSpace(
                transform.TransformPoint(vertices[i]),
                transform.TransformDirection(normals[i]),
                transform.TransformDirection(tangents[i]),
                tangents[i].w
            );
        }
    }
    
    private void ShowTangentSpace(Vector3 vertex, Vector3 normal, Vector3 tangent, float binormalSign)
    {
        vertex += normal * offset;
        Gizmos.color = Color.green;
        Gizmos.DrawLine(vertex, vertex + normal * scale);
        //切线
        Gizmos.color = Color.red;
        Gizmos.DrawLine(vertex, vertex + tangent * scale);
        //次法线
        Vector3 binormal = Vector3.Cross(normal, tangent) * binormalSign;
        Gizmos.color = Color.blue;
        Gizmos.DrawLine(vertex, vertex + binormal * scale);
    }   
}

代码中的切线w中存储这次切线的方向, 因为cross得到2个向量,根据切线向量第4个分量中

可视化切线空间

2、Shader中处理切线空间
切线空间中:由法线N, 切线(T)和次法线(B)组成,俗称TBN这里有一个知识点:从A空间转换到B空间的矩阵是什么?A空间的基向量在B空间的表示按列排序,就成了A到B空间的转换矩阵

float4 tangent : TANGENT; //切线 //定义
    将切线转换到世界空间
    i.tangent = float4(UnityObjectToWorldDir(v.tangent.xyz), v.tangent.w);

    初始化法线代码中
    float3 tangentSpaceNormal = BlendNormals(mainNormal, detailNormal);
    下方替换了所以注释了
    // tangentSpaceNormal = tangentSpaceNormal.xzy;
    float3 binormal = cross(i.normal, i.tangent.xyz) * i.tangent.w; 计算次法线
    从将法线从切线空间转换到世界方向
    i.normal = normalize(
        tangentSpaceNormal.x * i.tangent +
        tangentSpaceNormal.y * binormal +
        tangentSpaceNormal.z * i.normal);
    在计算次法线时候(如果需要翻转),可以利用unity_WorldTransformParams
    float3 binormal = cross(i.normal, i.tangent.xyz) * (i.tangent.w * unity_WorldTransformParams.w);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity Shader语义是一种用于定义着色器代码中变量的标识符。它们可以提供有关变量的更多信息,例如变量的作用、数据类型和使用方式。使用着色器语义可以使着色器代码更加简洁、易于阅读,并增加可维护性和可扩展性。 在Unity中,着色器语义通常用于顶点着色器和片段着色器中。在顶点着色器中,通过使用语义变量,可以将模型空间下的顶点位置换为裁剪空间下的位置,并对其他语义变量进行计算和赋值。 在代码中,UnityObjectToClipPos函数被用来进行模型空间到裁剪空间换。这个函数是Unity内置的函数,它将模型空间下的坐标换为裁剪空间下的坐标。具体实现方式可能会因Unity版本和平台而有所不同,但使用方法是一致的。 除了顶点着色器,语义还可以在片段着色器中使用。比如,在一个完整的代码案例中,我们可以使用纹理坐标和法线语义来对表面进行着色。在表面着色器函数中,我们可以将纹理坐标和主纹理的颜色值赋值给表面输出结构体,还可以将法线向量从世界空间变换到切线空间,并对其他表面输出结构体的变量进行计算和赋值。 总之,Unity Shader语义为我们提供了一种方式来定义和使用着色器代码中的变量,使其更具可读性和可维护性,并且能够方便地与其他着色器和渲染管线进行交互,同时也可以更方便地与外部程序进行交互。<span class="em">1</span><span class="em">2</span><span class="em">3</span><span class="em">4</span>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值