Shader中矩阵的一些用法
来源:互联网 发布:python shadowsockt 编辑:程序博客网 时间:2024/05/22 03:46
1.从世界的变换矩阵中提取仅带有旋转缩放那部分信息的矩阵:
因为平移信息仅存放在矩阵的m41,m42,m43这些位置上,所以该矩阵中左上方的3*3矩阵既为旋转缩放矩阵。
代码如下:
float4x4 WorldViewXf : WorldView; // 世界*视变换矩阵
float3x3 modelViewRotXf; // 世界矩阵中的旋转缩放矩阵
modelViewRotXf[0] = WorldViewXf[0].xyz;
modelViewRotXf[1] = WorldViewXf[1].xyz;
modelViewRotXf[2] = WorldViewXf[2].xyz;
注意:Shader中通过"[]"取出的是该矩阵的一列
2.对正交矩阵进行快速的逆变换
我们经常会遇到通过A空间到B空间的矩阵实现从B变换到A的这种情况,一般为了省事就直接从外部传一个A空间到B空间的矩阵的你矩阵就行了。但我前不久看到了一个这样的写法:
float4x4 tbnXf; // 模型空间->切向空间的变换矩阵
float3 vec_model; // 模型空间的一条向量
float3 vec_tbn; // 切向空间的一条向量
vec_model = mul(tbnXf,vec_tbn); // 变换
你也许还没看出什么特别来,注意mul中两个参数的位置,变换矩阵放在了前面!而向量却在后面!要知道矩阵乘法是不支持交换率的!!如果我们想把vec_tbn变换到模型空间,正常的方法应该是:
vec_model = mul(vec_tbn, tbnXf_INVERT); // tbnXf_INVERT是tbnXf的逆矩阵
但事实上两个运算的结果完全一致!其实这里的实现方法是用到了正交矩阵的一个特性以及转置矩阵的一个运算定理,其分别是:
-正交矩阵的转置矩阵就是该矩阵的逆矩阵
-() =
所以mul(tbnXf,vec_tbn)表达的含义是用vec_tbn的转置矩阵乘上tbnXf的逆矩阵,由于对向量转置这个操作貌似HLSL有不错的保护,结果就等同于了mul(vec_tbn, tbnXf_INVERT),这的确是一个非常非常机的方法orz。
3.将几个运算整合到一个矩阵中
由于矩阵乘法是支持结合率的,所以假如我们可以把一组运算写成矩阵的形式,那么我们就能把这些表达运算的矩阵预先乘到一起(甚至可以和变换矩阵乘到一起),这样仅需一次矩阵乘法就可以解决所有的问题,大大缩减了运算量!不过不是所有的算法都可以抽象成矩阵的(反正我是做不到orz),下面这个是我见到的比较典型的。
在实现ShadowMap时,我们需要计算一个模型空间下的3维坐标它所对应的在ShadowMap这张深度图的贴图坐标系下所对应的UV坐标。一般的步骤是:
预先计算的部分:
float g_fTexOffset = 0.5 + ( 0.5 / SHADOW_MAP_SIZE ); // 贴图空间变换到纹理空间需要的偏移量
PixelShader中的片段:
float4 UV = mul( vPos, WorldViewProjXf ); // 变换到投影后的视空间
UV.xy = g_fTexOffset + float2( UV.x * 0.5f, UV.y * -0.5f); // 变换到纹理空间
float4 color = tex2Dproj( sampler, UV ); // tex2Dproj在取样前会先进行规格化(UV.xyz / UV.w)
// DO SOMETHING
下面我们把变换到纹理空间的这段运算写成矩阵的形式以便预先和WorldViewProjXf矩阵整合到一起:
float4x4 MatTexAdj = {0.5, 0, 0, 0
0, -0.5, 0, 0
0, 0, 1, 0
g_fTexOffset, g_fTexOffset, 0, 1 }
float4x4 WorldViewProjTexadjXf = WorldViewProjXf * MatTexAdj;
于是在Shader中我们只需要这些运算就足够了
float4 UV = mul( vPos, WorldViewProjTexadjXf ); // 一次完成所有的运算,COOL?
float4 color = tex2Dproj( sampler, UV );
// DO SOMETHING
因为平移信息仅存放在矩阵的m41,m42,m43这些位置上,所以该矩阵中左上方的3*3矩阵既为旋转缩放矩阵。
代码如下:
float4x4 WorldViewXf : WorldView; // 世界*视变换矩阵
float3x3 modelViewRotXf; // 世界矩阵中的旋转缩放矩阵
modelViewRotXf[0] = WorldViewXf[0].xyz;
modelViewRotXf[1] = WorldViewXf[1].xyz;
modelViewRotXf[2] = WorldViewXf[2].xyz;
注意:Shader中通过"[]"取出的是该矩阵的一列
2.对正交矩阵进行快速的逆变换
我们经常会遇到通过A空间到B空间的矩阵实现从B变换到A的这种情况,一般为了省事就直接从外部传一个A空间到B空间的矩阵的你矩阵就行了。但我前不久看到了一个这样的写法:
float4x4 tbnXf; // 模型空间->切向空间的变换矩阵
float3 vec_model; // 模型空间的一条向量
float3 vec_tbn; // 切向空间的一条向量
vec_model = mul(tbnXf,vec_tbn); // 变换
你也许还没看出什么特别来,注意mul中两个参数的位置,变换矩阵放在了前面!而向量却在后面!要知道矩阵乘法是不支持交换率的!!如果我们想把vec_tbn变换到模型空间,正常的方法应该是:
vec_model = mul(vec_tbn, tbnXf_INVERT); // tbnXf_INVERT是tbnXf的逆矩阵
但事实上两个运算的结果完全一致!其实这里的实现方法是用到了正交矩阵的一个特性以及转置矩阵的一个运算定理,其分别是:
-正交矩阵的转置矩阵就是该矩阵的逆矩阵
-() =
所以mul(tbnXf,vec_tbn)表达的含义是用vec_tbn的转置矩阵乘上tbnXf的逆矩阵,由于对向量转置这个操作貌似HLSL有不错的保护,结果就等同于了mul(vec_tbn, tbnXf_INVERT),这的确是一个非常非常机的方法orz。
3.将几个运算整合到一个矩阵中
由于矩阵乘法是支持结合率的,所以假如我们可以把一组运算写成矩阵的形式,那么我们就能把这些表达运算的矩阵预先乘到一起(甚至可以和变换矩阵乘到一起),这样仅需一次矩阵乘法就可以解决所有的问题,大大缩减了运算量!不过不是所有的算法都可以抽象成矩阵的(反正我是做不到orz),下面这个是我见到的比较典型的。
在实现ShadowMap时,我们需要计算一个模型空间下的3维坐标它所对应的在ShadowMap这张深度图的贴图坐标系下所对应的UV坐标。一般的步骤是:
预先计算的部分:
float g_fTexOffset = 0.5 + ( 0.5 / SHADOW_MAP_SIZE ); // 贴图空间变换到纹理空间需要的偏移量
PixelShader中的片段:
float4 UV = mul( vPos, WorldViewProjXf ); // 变换到投影后的视空间
UV.xy = g_fTexOffset + float2( UV.x * 0.5f, UV.y * -0.5f); // 变换到纹理空间
float4 color = tex2Dproj( sampler, UV ); // tex2Dproj在取样前会先进行规格化(UV.xyz / UV.w)
// DO SOMETHING
下面我们把变换到纹理空间的这段运算写成矩阵的形式以便预先和WorldViewProjXf矩阵整合到一起:
float4x4 MatTexAdj = {0.5, 0, 0, 0
0, -0.5, 0, 0
0, 0, 1, 0
g_fTexOffset, g_fTexOffset, 0, 1 }
float4x4 WorldViewProjTexadjXf = WorldViewProjXf * MatTexAdj;
于是在Shader中我们只需要这些运算就足够了
float4 UV = mul( vPos, WorldViewProjTexadjXf ); // 一次完成所有的运算,COOL?
float4 color = tex2Dproj( sampler, UV );
// DO SOMETHING
0 0
- Shader中矩阵的一些用法
- Unity3d中Shader的一些关于矩阵变换的基本信息
- Unity3d中Shader的一些常用方法
- shader中法线向量为什么要乘以模型视图矩阵的逆转置矩阵
- shader中法线向量为什么要乘以模型视图矩阵的逆转置矩阵
- 【转载】Shader中为何法线转换要用视图矩阵的转逆矩阵
- shader中一些光照模型
- Unity Shader 编程中一些需要记住的技术点
- opencv中矩阵计算的一些函数
- unity shader的一些基本知识
- 一些shader的基本规则
- 第4章 学习Shader所需的数学基础(中)(矩阵)
- 一些shader
- 矩阵的一些操作
- 矩阵的一些运算
- Unity3D中常见的三类Shader的区别与用法
- 网页中一些比较隐蔽的用法
- webForm中dropDownList的一些用法
- 各个行业应用的算法
- 怎样查出SQLServer的性能瓶颈
- qt程序的发布
- not an rpm package
- 2015年上半年主要目标
- Shader中矩阵的一些用法
- 防止订单重复提交
- 蜡笔小新-spring-ContextLoaderListener
- 下拉状态栏增加wifi热点开关
- 利用Wget 直接将数据Put到HDFS 上
- 计算机专业硕士研究生培养方案
- C++ 友元
- nyoj 488 素数环
- mysql列与注释修改SQL语句