Unity中Shader裁剪空间推导(在Shader中使用)
文章目录
- 前言
- 一、在Shader中使用转化矩阵
- 1、在顶点着色器中定义转化矩阵
- 2、用 UNITY_NEAR_CLIP_VALUE 区分平台矩阵
- 3、定义一个枚举用于区分当前是处于什么相机
- 二、我们在DirectX平台下,看看效果
- 1、正交相机下
- 2、透视相机下
- 3、最终代码
前言
在上一篇文章中,我们推导得出了 透视相机到裁剪空间的转化矩阵
- Unity中Shader裁剪空间推导(透视相机到裁剪空间的转化矩阵)
我们在正交矩阵Shader的基础上,继续测试
- Unity中Shader裁剪空间推导(在Shader中实现)
在这篇文章中,我们在Shader中使用该矩阵测试一下。
- OpenGL
[ 2 n w 0 0 0 0 2 n h 0 0 0 0 n + f n − f 2 n f n − f 0 0 − 1 0 ] \begin{bmatrix} \frac{2n}{w} & 0 & 0 & 0 \\ 0 & \frac{2n}{h} & 0 &0\\ 0 & 0 & \frac{n+f}{n-f} &\frac{2nf}{n-f}\\ 0 & 0 & -1 & 0\\ \end{bmatrix} w2n0000h2n0000n−fn+f−100n−f2nf0 - DirectX
[ 2 n w 0 0 0 0 2 n h 0 0 0 0 n f − n n f f − n 0 0 − 1 0 ] \begin{bmatrix} \frac{2n}{w} & 0 & 0 & 0 \\ 0 & \frac{2n}{h} & 0 &0\\ 0 & 0 & \frac{n}{f-n} &\frac{nf}{f-n}\\ 0 & 0 & -1 & 0\\ \end{bmatrix} w2n0000h2n0000f−nn−100f−nnf0
一、在Shader中使用转化矩阵
1、在顶点着色器中定义转化矩阵
- OpenGL:
M_clipP = float4x4
(
2n/w,0,0,0,
0,2n/h,0,0,
0,0,(n+f)/(n-f),(2nf)/(n-f),
0,0,-1,0
);
- DirectX:
M_clipP = float4x4
(
2n/w,0,0,0,
0,2n/h,0,0,
0,0,n/(f-n),(n*f)/(f-n),
0,0,-1,0
);
2、用 UNITY_NEAR_CLIP_VALUE 区分平台矩阵
- 1为OpenGL
- -1为DirectX
3、定义一个枚举用于区分当前是处于什么相机
[Enum(OrthoGraphic,0,Perspective,1)]_CameraType(“CameraType”,Float) = 0
- 在手动转化矩阵时使用三目运算符来决定使用哪一个矩阵
float4x4 M_clip = _CameraType ? M_clipP : M_clipO;
o.vertexCS = mul(M_clip,float4(vertexVS,1));
二、我们在DirectX平台下,看看效果
1、正交相机下

2、透视相机下

3、最终代码
//平移变换
//缩放变换
//旋转变换(四维)
//视图空间矩阵
//正交相机视图空间 -> 裁剪空间
Shader "MyShader/URP/P3_7_6"
{Properties{[Header(MainTexx)]_MainTex("MainTex",2D) = "white"{}[Header(Transtion)]_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)[Header(Camera)]_CameraParams("Size(X),Near(Y),Far(Z) Ratio(W)",Vector) = (0,0,0,1.777)[Enum(OrthoGraphic,0,Perspective,1)]_CameraType("CameraType",Float) = 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;float2 uv : TEXCOORD0;};struct Varying{float4 vertexCS : SV_POSITION;float2 uv : TEXCOORD0;};CBUFFER_START(UnityPerMaterial)float4 _Translate;float4 _Scale;float4 _Rotation;float4 _ViewPos;float4 _ViewTarget;float4 _CameraParams;float _CameraType;CBUFFER_ENDTEXTURE2D(_MainTex);SAMPLER(sampler_MainTex);Varying vert (Attribute v){Varying o;o.uv = v.uv;//平移变换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.xyz - _ViewTarget.xyz);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.xyz);//世界空间转化到观察空间float3 vertexVS = mul(M_view,float4(vertexWS,1)).xyz;//相机参数float h = _CameraParams.x * 2;float w = h * _CameraParams.w;float n = _CameraParams.y;float f = _CameraParams.z;//正交相机投影矩阵//P_Clip = [M_Clip] * P_viewfloat4x4 M_clipO;if(UNITY_NEAR_CLIP_VALUE==-1){//OpenGLM_clipO = float4x4(2/w,0,0,0,0,2/h,0,0,0,0,2/(n - f),(n + f) / (n - f),0,0,0,1);}if(UNITY_NEAR_CLIP_VALUE==1){//DirectXM_clipO = float4x4(2/w,0,0,0,0,2/h,0,0,0,0,1/(f-n),f/(f-n),0,0,0,1);}//透视相机投影矩阵float4x4 M_clipP;if(UNITY_NEAR_CLIP_VALUE==-1){//OpenGLM_clipP = float4x4(2*n/w,0,0,0,0,2*n/h,0,0,0,0,(n+f)/(n-f),(2*n*f)/(n-f),0,0,-1,0);}if(UNITY_NEAR_CLIP_VALUE==1){//DirectXM_clipP = float4x4(2*n/w,0,0,0,0,2*n/h,0,0,0,0,n/(f-n),(n*f)/(f-n),0,0,-1,0);}//手动将观察空间下的坐标转换到裁剪空间下float4x4 M_clip = _CameraType ? M_clipP : M_clipO;o.vertexCS = mul(M_clip,float4(vertexVS,1));//观察空间 转化到 齐次裁剪空间//o.vertexCS = TransformWViewToHClip(vertexVS);//o.vertexCS = TransformObjectToHClip(v.vertexOS.xyz);return o;}half4 frag (Varying i) : SV_Target{float4 mainTex = SAMPLE_TEXTURE2D(_MainTex,sampler_MainTex,i.uv);return mainTex;}ENDHLSL}}
}相关文章:
Unity中Shader裁剪空间推导(在Shader中使用)
文章目录 前言一、在Shader中使用转化矩阵1、在顶点着色器中定义转化矩阵2、用 UNITY_NEAR_CLIP_VALUE 区分平台矩阵3、定义一个枚举用于区分当前是处于什么相机 二、我们在DirectX平台下,看看效果1、正交相机下2、透视相机下3、最终代码 前言 在上一篇文章中&…...
ES的使用(Elasticsearch)
ES的使用(Elasticsearch) es是什么? es是非关系型数据库,是分布式文档数据库,本质上是一个JSON 文本 为什么要用es? 搜索速度快,近乎是实时的存储、检索数据 怎么使用es? 1.下载es的包(环境要…...
车牌识别技术,如何用python识别车牌号
目录 一.前言 二.运行环境 三.代码 四.识别效果 五.参考 一.前言 车牌识别技术(License Plate Recognition, LPR)在交通计算机视觉(Computer Vision, CV)领域具有非常重要的研究意义。以下是该技术的一些扩展说明࿱…...
爬虫工作量由小到大的思维转变---<第二十五章 Scrapy开始很快,越来越慢(追溯篇)>
爬虫工作量由小到大的思维转变---<第二十二章 Scrapy开始很快,越来越慢(诊断篇)>-CSDN博客 爬虫工作量由小到大的思维转变---<第二十三章 Scrapy开始很快,越来越慢(医病篇)>-CSDN博客 前言: 之前提到过,很多scrapy写出来之后,不…...
Servlet入门
目录 1.Servlet介绍 1.1什么是Servlet 1.2Servlet的使用方法 1.3Servlet接口的继承结构 2.Servlet快速入门 2.1创建javaweb项目 2.1.1创建maven工程 2.1.2添加webapp目录 2.2添加依赖 2.3创建servlet实例 2.4配置servlet 2.5设置打包方式 2.6部署web项目 3.servl…...
【C#与Redis】--高级主题--Redis 哨兵
一、简介 1.1 哨兵的概述 哨兵(Sentinel)是 Redis 分布式系统中用于监控和管理多个 Redis 服务器的组件。它的主要目标是确保 Redis 系统的高可用性,通过实时监测主节点和从节点的状态,及时发现并自动处理故障,保证系…...
linux安装python
文章目录 前言一、下载安装包二、安装1.安装依赖2.解压3.安装4.软链接5.验证 总结 前言 本篇文章介绍linux环境下安装python。 一、下载安装包 下载地址:官方网站 我们以最新的标准版为例 二、安装 1.安装依赖 yum -y install openssl-devel ncurses-devel li…...
【如何破坏单例模式(详解)】
✅如何破坏单例模式 💡典型解析✅拓展知识仓✅反射破坏单例✅反序列化破坏单例✅ObjectlnputStream ✅总结✅如何避免单例被破坏✅ 避免反射破坏单例✅ 避免反序列化破坏单例 💡典型解析 单例模式主要是通过把一个类的构造方法私有化,来避免重…...
什么是 SPI,它有什么用?
文章目录 什么是 SPI,它有什么用? 什么是 SPI,它有什么用? SPI 全称是 Service Provider Interface ,它是 JDK 内置的一种动态扩展点的实现。 简单来说,就是我们可以定义一个标准的接口,然后第三…...
FolkMQ 新的消息中间件,v1.0.25
简介 采用 “多路复用” “内存运行” “快照持久化” “Broker 集群模式”(可选)基于 Socket.D 网络应用协议 开发。全新设计,自主架构! 角色功能生产端发布消息(Qos0、Qos1)、发布定时消息ÿ…...
小程序入门-登录+首页
正常新建一个登录页面 创建首页和TatBar,实现登录后底部出现两个按钮 代码 "pages": ["pages/login/index","pages/index/index","pages/logs/logs" ],"tabBar": {"list": [{"pagePath"…...
React快速入门之组件
目录 组件JSX在标签使用{}嵌入JS表达式使用组件组件嵌套以🌲树的方式管理组件间的关系组件纯粹原则 组件 文件:Profile.js export default function Profile({isPacked true,head,stlyeTmp,src,size 80}) {if (isPacked) {head head &q…...
.NET Conf 2023 回顾 – 庆祝社区、创新和 .NET 8 的发布
作者: Jon Galloway - Principal Program Manager, .NET Community Team Mehul Harry - Product Marketing Manager, .NET, Azure Marketing 排版:Alan Wang .NET Conf 2023 是有史以来规模最大的 .NET 会议,来自全球各地的演讲者进行了 100 …...
Hadoop入门学习笔记——六、连接到Hive
视频课程地址:https://www.bilibili.com/video/BV1WY4y197g7 课程资料链接:https://pan.baidu.com/s/15KpnWeKpvExpKmOC8xjmtQ?pwd5ay8 Hadoop入门学习笔记(汇总) 目录 六、连接到Hive6.1. 使用Hive的Shell客户端6.2. 使用Beel…...
【K8S 基本概念】Kurbernetes的架构和核心概念
目录 一、Kurbernetes 1.1 简介 1.2、K8S的特性: 1.3、docker和K8S: 1.4、K8S的作用: 1.5、K8S的特性: 二、K8S集群架构与组件: 三、K8S的核心组件: 一、master组件: 1、kube-apiserve…...
WPS复选框里打对号,显示小太阳或粗黑圆圈的问题解决方法
问题描述 WPS是时下最流行的字处理软件之一,是目前唯一可以和微软office办公套件相抗衡的国产软件。然而,在使用WPS的过程中也会出现一些莫名其妙的错误,如利用WPS打开docx文件时,如果文件包含复选框,经常会出…...
对“企业数据资源相关会计处理暂行规定“的个人理解
附:2023年数据资源入表白皮书下载: 关注WX公众号: commindtech77, 获得数据资产相关白皮书下载地址 1. 回复关键字:数据资源入表白皮书 下载 《2023数据资源入表白皮书》 2. 回复关键字:光大银行 下载 光…...
JavaScript:函数隐含对象arguments/剩余参数. . .c/解构赋值
除了this,在函数内部还存在着一个隐含的参数arguments arguments 是一个类数组对象(伪数组) 调用函数时传递的所有实参,都被存储在arguments中 arguments[0] 表示的是第一个实参 arguments[1] 表示的是第二个实参 以此类推..…...
MFC窗体背景颜色的设置、控件白色背景问题、控件文本显示重叠问题、被父窗体背景覆盖的问题
文章目录 设置mfc窗体背景颜色窗体设置背景颜色后解决控件白色背景解决重复修改控件文本后重叠的问题自绘控件被父窗体背景覆盖的问题 设置mfc窗体背景颜色 设置窗体的背景颜色非常简单,只需要在窗体的OnEraseBkgnd里面填充窗体背景就可以了,甚至直接画…...
c++简易AI
今天小编一时雅兴大发,做了一个c的简易AI,还是很垃圾的! 题外话(每期都会有):我的蛋仔名叫酷影kuying,大家能加我好友吗? 上代码咯! #include<bits/stdc.h> #in…...
企业智能体架构解析:从LLM集成到自动化管理实践
1. 项目概述:一个面向企业管理的智能体架构最近在开源社区里,我注意到一个挺有意思的项目:kernelshreyak/company-manager-agent。光看这个名字,你可能会联想到一个简单的任务管理工具,但深入研究后,我发现…...
基于ESP8266与ADC同步解调实现远距离反射式光电检测:ITR8307实战
1. 反射式光电检测的必要性 在智能车竞赛中,节能信标组的设计一直面临一个棘手问题:传统磁铁触发方式容易导致对抗比赛中车模相互吸附。我亲眼见过两辆精心调校的车模因为磁铁吸引力"难舍难分"的尴尬场景,这直接影响了比赛公平性和…...
微博数据接口解决方案:Python爬虫工程实践与反爬策略
1. 项目概述与核心价值最近在折腾一个挺有意思的项目,叫longlannet/weibo。乍一看,这像是一个与微博相关的代码仓库,但它的价值远不止于一个简单的爬虫或客户端。作为一个在数据工程和自动化领域摸爬滚打多年的从业者,我深知在当今…...
【Perplexity Pro深度评测】:20年AI工具实战专家拆解3大隐藏成本与5个被忽略的高阶功能值不值得?
更多请点击: https://intelliparadigm.com 第一章:Perplexity Pro订阅值不值得 核心能力对比:免费版 vs Pro版 Perplexity Pro 提供实时联网搜索、多文件上传解析(PDF/DOCX/CSV)、无限次深度追问及自定义AI工作区等关…...
Kubescape终极跨平台安装指南:Windows/Linux/macOS一键部署与实用技巧
Kubescape终极跨平台安装指南:Windows/Linux/macOS一键部署与实用技巧 Kubescape是一款开源的Kubernetes安全平台,专为IDE、CI/CD管道和集群设计,提供风险分析、安全合规检查和错误配置扫描功能,帮助Kubernetes用户和管理员节省宝…...
Python 爬虫数据处理:重复页面数据智能合并去重
前言 在规模化 Python 爬虫采集项目中,重复页面数据是高频出现的核心问题,源于站点分页逻辑错乱、镜像页面分发、动态接口返回冗余数据、多入口同源页面采集等多重因素。重复数据若不做处理,不仅会造成数据库存储冗余、占用服务器资源&#…...
告别硬件依赖:用Virtual ZPL Printer构建完整的标签打印测试环境
告别硬件依赖:用Virtual ZPL Printer构建完整的标签打印测试环境 【免费下载链接】Virtual-ZPL-Printer An ethernet based virtual Zebra Label Printer that can be used to test applications that produce bar code labels. 项目地址: https://gitcode.com/gh…...
GitHub 74.2k Star的Redis,开发者必备的内存数据库
文章目录GitHub 74.2k Star的Redis,开发者必备的内存数据库核心能力覆盖多数开发场景实际使用建议GitHub 74.2k Star的Redis,开发者必备的内存数据库 Redis是GitHub上的热门开源项目,Star数达到74223,是很多开发者日常工作中常用…...
模拟工程师必备:口袋参考指南的实战价值与核心应用
1. 为什么每个硬件工程师都需要一本“口袋参考书”?前几天整理书桌,翻出来一本2016年从TI官网下载打印的《模拟工程师口袋参考指南》,纸张已经有点发黄,边角也卷了。但就是这么一本薄薄的小册子,从毕业到现在ÿ…...
拾亩绿光纯亚麻籽微粉效果怎么样
很多人想通过亚麻籽补充营养,却常遇到传统亚麻籽难吸收、营养易流失的问题:直接嚼咽口感粗糙,普通研磨粉冲调结块,榨油后Omega-3等核心营养大量损耗。拾亩绿光纯亚麻籽微粉依托南京国英健康科技有限公司的专利技术,可解…...
