Unity中Shader观察空间推导(在Shader中实现)

本文详细介绍了如何在UnityShader中推导观察空间矩阵,包括计算基向量、平移和旋转变换,以及将世界空间坐标转换为观察空间并输出到屏幕上。最终给出了使用自定义Shader实现的效果和相关代码。
摘要由CSDN通过智能技术生成


前言

在上篇文章中,我们是实现了Shader中的观察空间推导。

我们在这篇文章中,根据上篇文章的推导,在Shader中实现观察空间矩阵的推导。


一、观察空间矩阵推导

  • Pview = [Wview] * Pworld

  • Pview = [Vworld]-1 * Pworld

  • Pview = [Vworld]T * Pworld

  • 在属性面板定义测试使用到的 摄像机坐标 和 测试顶点坐标

_ViewPos(“View Pos”,vector) = (0,0,0,0)
_ViewTarget(“View Target”,vector) = (0,0,0,0)

1、求观察空间基向量

  • Z坐标轴基向量

float3 ViewZ = normalize(_ViewPos - _ViewTarget);

  • 假设Y坐标轴基向量为(0,1,0)

float3 ViewY = float3(0,1,0);

  • 求 X 坐标基向量

float3 ViewX = cross(ViewZ,ViewY);

  • 求 Y 坐标基向量

ViewY = cross(ViewX,ViewZ);

2、求观察空间的基向量在世界空间中的矩阵 的 逆矩阵

在这里插入图片描述

float4x4 M_viewTemp = float4x4
(
ViewX.x,ViewX.y,ViewX.z,0,
ViewY.x,ViewY.y,ViewY.z,0,
ViewZ.x,ViewZ.y,ViewZ.z,0,
0,0,0,1
);

2、求平移变换矩阵

1 0 0 − T   x   0 1 0 − T   y   0 0 1 − T   z   0 0 0 1 \begin{matrix} 1&0&0&-T~x~\\ 0&1&0&-T~y~\\ 0&0&1&-T~z~\\ 0&0&0&1\\ \end{matrix} 100001000010T x T y T z 1

float4x4 M_viewTranslate = float4x4
(
1,0,0,-_ViewPos.x,
0,1,0,-_ViewPos.y,
0,0,1,-_ViewPos.z,
0,0,0,1
);

3、相乘得出 观察空间转化矩阵

float4x4 M_view = mul(M_viewTemp,M_viewTranslate);

4、得到顶点的世界空间坐标,然后转化到观察空间

float3 vertexWS = TransformObjectToWorld(v.vertexOS);
float3 vertexVS = mul(M_view,float4(vertexWS,1));

5、把观察空间坐标转化为齐次裁剪坐标输出到屏幕

o.vertexCS = TransformWViewToHClip(vertexVS);


二、最终效果

1、这是我们用默认Shader,在该摄像机坐标下的游戏界面

在这里插入图片描述

2、使用我们的Shader,并且给我们的ViewPos赋值为摄像机坐标

请添加图片描述

3、最终代码

//平移变换
//缩放变换
//旋转变换(四维)
Shader "MyShader/URP/P3_6_5"
{
    Properties
    {
        _Translate("Translate(XYZ)",Vector) = (0,0,0,0)
        _Scale("Scale(XYZ)",Vector)= (1,1,1,1)
        _Rotation("Rotation(XYZ)",Vector) = (0,0,0,0)
        [Header(View)]
        _ViewPos("View Pos",vector) = (0,0,0,0)
        _ViewTarget("View Target",vector) = (0,0,0,0)
    }
    SubShader
    {
        Tags
        {
            "PenderPipeline"="UniversalPipeline"
            "RenderType"="Opaque"
            "Queue"="Geometry"
        }
        Pass
        {
            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            
            #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"

            struct Attribute
            {
                float4 vertexOS : POSITION;
            };

            struct Varying
            {
                float4 vertexCS : SV_POSITION;
            };

            CBUFFER_START(UnityPerMaterial)
            float4 _Translate;
            float4 _Scale;
            float4 _Rotation;
            float4 _ViewPos;
            float4 _ViewTarget;
            CBUFFER_END
            Varying vert (Attribute v)
            {
                Varying o;
                //平移变换
                float4x4 M_Translate = float4x4
                    (
                    1,0,0,_Translate.x,
                    0,1,0,_Translate.y,
                    0,0,1,_Translate.z,
                    0,0,0,1
                    );
                v.vertexOS = mul(M_Translate,v.vertexOS);
                //缩放交换
                float4x4 M_Scale = float4x4
                    (
                    _Scale.x,0,0,0,
                    0,_Scale.y,0,0,
                    0,0,_Scale.z,0,
                    0,0,0,1
                    );
                v.vertexOS = mul(M_Scale,v.vertexOS);
                //旋转变换
                float4x4 M_rotateX = float4x4
                    (
                    1,0,0,0,
                    0,cos(_Rotation.x),sin(_Rotation.x),0,
                    0,-sin(_Rotation.x),cos(_Rotation.x),0,
                    0,0,0,1
                    );
                float4x4 M_rotateY = float4x4
                    (
                    cos(_Rotation.y),0,sin(_Rotation.y),0,
                    0,1,0,0,
                    -sin(_Rotation.y),0,cos(_Rotation.y),0,
                    0,0,0,1
                    );
                float4x4 M_rotateZ = float4x4
                    (
                        cos(_Rotation.z),sin(_Rotation.z),0,0,
                        -sin(_Rotation.z),cos(_Rotation.z),0,0,
                        0,0,1,0,
                        0,0,0,1
                    );
                v.vertexOS = mul(M_rotateX,v.vertexOS);
                v.vertexOS = mul(M_rotateY,v.vertexOS);
                v.vertexOS = mul(M_rotateZ,v.vertexOS);

                //观察空间矩阵推导
                //P_view = [W_view] * P_world
                //P_view = [V_world]^-1 * P_world
                //P_view = [V_world]^T * P_world
                float3 ViewZ = normalize(_ViewPos - _ViewTarget);
                float3 ViewY = float3(0,1,0);
                float3 ViewX = cross(ViewZ,ViewY);
                ViewY = cross(ViewX,ViewZ);

                float4x4 M_viewTemp = float4x4
                    (
                        ViewX.x,ViewX.y,ViewX.z,0,
                        ViewY.x,ViewY.y,ViewY.z,0,
                        ViewZ.x,ViewZ.y,ViewZ.z,0,
                        0,0,0,1
                    );

                float4x4 M_viewTranslate = float4x4
                    (
                        1,0,0,-_ViewPos.x,
                        0,1,0,-_ViewPos.y,
                        0,0,1,-_ViewPos.z,
                        0,0,0,1
                    );

                float4x4 M_view = mul(M_viewTemp,M_viewTranslate);

                float3 vertexWS = TransformObjectToWorld(v.vertexOS);
                float3 vertexVS = mul(M_view,float4(vertexWS,1));
                
                o.vertexCS = TransformWViewToHClip(vertexVS);
                
                //o.vertexCS = TransformObjectToHClip(v.vertexOS.xyz);
                return o;
            }

            half4 frag (Varying i) : SV_Target
            {
                return 1;
            }
            ENDHLSL
        }
    }
}

Unity宇宙空间场景是使用Unity引擎开发的一种虚拟现实体验,让用户可以沉浸在宇宙的广袤空间。这种场景通常包括星空、行星、恒星、银河系等元素,再加上逼真的光影效果,营造出逼真的宇宙环境。在这个场景,用户可以自由移动并探索宇宙的奥秘。 Unity宇宙空间场景不仅仅是一个视觉的体验,还可以根据使用者的需求添加互动元素。例如,可以添加一个太空飞船模型供用户操作,让他们可以驾驶飞船在宇宙飞行。用户还可以利用交互设备探索不同星球,与外星生物互动,甚至在太空进行战斗。 这种场景在教育和娱乐领域都有着广阔的应用前景。在教育方面,它可以为学生提供观察和了解宇宙的各种天体的机会。通过宇宙空间场景,学生可以亲身体验宇宙的重力、行星运动等现象,加深对天文学知识的理解。 在娱乐领域,Unity宇宙空间场景可以让用户感受到在太空的冒险和探索。他们可以驾驶飞船穿越星际,探索未知的星球,发现新的资源和生物。这样的虚拟体验能够给用户带来刺激和乐趣,让他们逃离现实世界,进入一个充满想象力的宇宙。 总的来说,Unity宇宙空间场景是一种让用户亲身体验宇宙的虚拟现实体验。它将现实世界与科学知识融合在一起,为用户创造一个无限可能的宇宙空间。无论是为教育还是娱乐,这种场景都能够给用户带来独特且难忘的体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

楠溪泽岸

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值