Unity3d 要为Unity Canvas图像着色器剪裁的对象 TL;博士
将着色器应用于Unity3D画布中的Unity3d 要为Unity Canvas图像着色器剪裁的对象 TL;博士,unity3d,glsl,hlsl,fragment-shader,unity-ui,Unity3d,Glsl,Hlsl,Fragment Shader,Unity Ui,将着色器应用于Unity3D画布中的UI.Image对象时,UNITY\u MATRIX\u MVP似乎与画布渲染器相关,而不是绘制的图像对象本身 是否有一种方法可以计算图像对象局部空间中某点的剪辑空间坐标,而不仅仅是相对于画布根的坐标 概述 作为着色器的预处理步骤,我正在计算屏幕上出现在该实体模型中的图像四元体的x_min、x_max、y_min和y_max: 我的基本方法是使用(只使用内置变换矩阵)手动计算4个角点的剪辑空间位置,然后从中获得最小/最大值 我发现这适用于SpriteRen
UI.Image
对象时,UNITY\u MATRIX\u MVP
似乎与画布渲染器相关,而不是绘制的图像对象本身
是否有一种方法可以计算图像对象局部空间中某点的剪辑空间坐标,而不仅仅是相对于画布根的坐标
概述 作为着色器的预处理步骤,我正在计算屏幕上出现在该实体模型中的图像四元体的
x_min
、x_max
、y_min
和y_max
:
我的基本方法是使用(只使用内置变换矩阵)手动计算4个角点的剪辑空间位置,然后从中获得最小/最大值
我发现这适用于SpriteRenderer
或meshrender
组件,但适用于UI。画布UNITY\u MATRIX\u MVP
中的图像组件似乎只与画布父对象相关,而不是图像对象本身,这意味着我无法使用它来计算相对于图像的位置
细节
您可以在此处找到完整的着色器:
对于给定的对象空间,首先使用坐标获取齐次剪辑空间坐标,然后将其移动到屏幕UV空间中(在屏幕上可见时,值范围为0到1):
inline float2 ObjToScreenUV(在float3 obj_pos中)
{
float4 clip_pos4d=单位对象到lippos(对象位置);
float2 clip_pos2d=clip_pos4d.xy/clip_pos4d.w;
#如果UNITY从顶部开始
返回float2(1+clip_pos2d.x,1-clip_pos2d.y)/2;
#否则
返回(1+clip_pos2d)/2;
#恩迪夫
}
由于单位四边形的4个顶点在对象空间中很难定义(仅在对象空间X/Y轴上偏移0.5),因此屏幕上的最小值/最大值可按如下方式计算:
inline float4 GetQuadUVBounds()
{
//1.获取4个四角的相对屏幕位置
float2 bl=ObjToScreenUV(float3(-0.5,-0.5,0));
float2 tl=ObjToScreenUV(float3(-0.5,0.5,0));
float2br=ObjToScreenUV(float3(0.5,-0.5,0));
float2 tr=ObjToScreenUV(float3(0.5,0.5,0));
//2.获得x和y的最小/最大值
浮动最小值x=最小值(最小值(bl.x,tl.x),最小值(br.x,tr.x));
浮点数max_x=max(max(bl.x,tl.x),max(br.x,tr.x));
浮动最小值=最小值(最小值(bl.y,tl.y),最小值(br.y,tr.y));
浮动最大值=最大值(最大值(bl.y,tl.y),最大值(br.y,tr.y));
返回浮动4(最小值x,最小值y,最大值x,最大值y);
}
请注意,我现在不想优化最小/最大逻辑
要验证是否正确计算了最小/最大值,可以在绘制对象时将其用于红色和绿色通道
例如,要验证x_min
和y_min
是否有效,可以使用以下片段着色器:
half4框架():颜色
{
//最小值是bounds.xy,最大值是bounds.zw
float4-bounds=GetQuadUVBounds();
返回float4(bounds.xy,0,1);
}
对于MeshRenderer
quads和SpriteRenderer
对象,其结果如下:
- 随着
x_min
的增加,红色通道也会增加
- 随着
y_min
的增加,绿色通道也会增加
测试最大值也会产生预期的结果
但是,在画布中的UI.Image
组件上测试同一着色器时,该着色器无法按预期工作:
尽管在屏幕上移动了UI.Image
对象(将着色器设置为其材质),但其颜色不会改变。但是,当在编辑器场景视图中移动编辑器摄影机时,颜色会发生变化
这似乎意味着UnityObjectToClipPos
,以及它所依赖的UNITY\u矩阵\u MVP
矩阵,都与画布父对象相关,而不是与父对象内部的图像对象相关
问题
我认为UNITY\u MATRIX\u MVP
是相对于画布对象的,而不是相对于正在绘制的图像对象的假设是否正确?如果是,是否有其他方法专门为图像对象获取MVP矩阵?或者,是否有其他方法可以在着色器中计算图像局部空间中点的剪辑空间位置
- 我使用的是Unity 2017.1.2f1
禁用批处理
着色器标志已启用
矩阵表示渲染器的变换,因此画布是渲染器,而图像不是。为什么不在顶点着色器中计算颜色?变换后的顶点位置已经是图像的边界。我试图实现的效果的长短需要知道像素在可见图像XY边界内的屏幕上的位置,而不仅仅是图像局部空间UV边界的位置。例如,使用grabpass并将样本从屏幕空间的图像中心向外偏移,以实现缩放效果。要正确地缩放,需要知道图像在屏幕上的位置,而不仅仅是像素在图像中的位置。