当前位置: 首页 > news >正文

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

文章目录

  • 前言
  • 一、观察空间矩阵推导
    • 1、求观察空间基向量
    • 2、求观察空间的基向量在世界空间中的矩阵 的 逆矩阵
    • 2、求平移变换矩阵
    • 3、相乘得出 观察空间转化矩阵
    • 4、得到顶点的世界空间坐标,然后转化到观察空间
    • 5、把观察空间坐标转化为齐次裁剪坐标输出到屏幕
  • 二、最终效果
    • 1、这是我们用默认Shader,在该摄像机坐标下的游戏界面
    • 2、使用我们的Shader,并且给我们的ViewPos赋值为摄像机坐标
    • 3、最终代码


前言

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

  • Unity中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_ENDVarying 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_worldfloat3 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}}
}
http://www.lryc.cn/news/267963.html

相关文章:

  • Hive04_DDL操作
  • odoo17核心概念view4——view.js
  • Centos7 openSSL
  • Web 安全之文件下载漏洞详解
  • 搬运机器人RFID传感器CNS-RFID-01|1S的RS485(MODBUS|HS协议)通讯连接方法
  • 使用ZMQ.proxy实现ZMQ PUB消息转发
  • 若依SQL Server开发使用教程
  • Mysql5.7服务器选项、系统变量和状态变量参考
  • 【Qt-Qss-Style】
  • 基于yolov8,制作停车位计数器(附源码)
  • C++设计模式:单例模式(饿汉式、懒汉式)
  • Django 访问前端页面一直在转异常:ReferenceError:axios is not defined
  • C语言中关于指针的理解
  • MySQL MVCC精讲
  • 如何快速删除pdf周围的空白
  • 蓝桥杯c/c++程序设计——数位排序
  • 【通讯录案例-搭建登录界面 Objective-C语言】
  • 二叉搜索树、AVL、红黑树、B树
  • 格密码:傅里叶矩阵
  • flex--伸缩性
  • linux中主从复制的架构和读写分离的方式
  • Ubuntu 22.04.3 Server 设置静态IP 通过修改yaml配置文件方法
  • EasyCVR无人机推流+人数统计AI算法,助力公共场所人群密度管控
  • Kotlin 接口
  • Qt前端技术:5.QSS
  • 在Centos7中利用Shell脚本:实现MySQL的数据备份
  • 大一C语言查缺补漏 12.24
  • 程序员宝典:常用的免费好物API
  • 关于“Python”的核心知识点整理大全41
  • java进阶(二)-java小干货