【发布时间】:2019-11-13 18:43:22
【问题描述】:
想要从(0,0) 到(1,1) 的对象四边形的屏幕空间坐标
尝试不依赖于屏幕位置和摄像机角度来实现此结果
这是从特定角度进行的简单 uv 采样
我需要从另一边看到相同的结果,但是另一边有一个 uv 接缝
【问题讨论】:
想要从(0,0) 到(1,1) 的对象四边形的屏幕空间坐标
尝试不依赖于屏幕位置和摄像机角度来实现此结果
这是从特定角度进行的简单 uv 采样
我需要从另一边看到相同的结果,但是另一边有一个 uv 接缝
【问题讨论】:
对我来说听起来像是 matcap UV。您可以尝试搜索“Unity Matcap Shader”,看看是否有好的结果。这是计算的核心部分(在顶点着色器中):
o.uv = mul((float3x3)UNITY_MATRIX_V, UnityObjectToWorldNormal(v.vertex)).xy * 0.5 + 0.5;
编辑:因此,您基本上想要屏幕空间 UV,但以对象为原点除外。我认为如果您用法线代替对象空间位置,上述解决方案应该仍然有效。
o.uv = mul((float3x3)UNITY_MATRIX_V, v.vertex).xy * 0.5 + 0.5;
这将使用模型的对象空间位置,旋转到屏幕空间。只要网格原点位于其中心,它就应该工作。请注意,UV 坐标的范围取决于模型的大小(1 米 = 1 uv 瓦片),因此您可能需要将其乘以某个因子。
EDIT2:好的,所以我开始更多地了解您想要实现的目标。如果您希望屏幕空间 UV 与对象的边界相关,那么您需要以某种方式将屏幕空间边界框传递到着色器中。
我建议为材质添加一个 float4 向量属性,其中 XY 是边界中心,ZW 是框尺寸,然后使用类似 GetComponent<MeshRenderer>().material.SetProperty("_ScreenBounds", bounds); 的代码从代码中设置它。您必须在脚本的更新方法中计算对象的屏幕边界。您可以使用Renderer.bounds 获取边界,也可以使用Camera.WorldToScreenPoint() 将它们转换为屏幕空间。变换边界框的所有角并获得最小/最大点。
在着色器中,您可以计算对象的常规屏幕空间 UV,然后减去偏移量并除以尺寸。
我应该警告您,尽管将数据发送到 GPU 会有一点延迟,因此您可能会在更新边界时遇到一点延迟。
【讨论】:
_ScreenParams.xy 是屏幕大小,以像素为单位