【发布时间】:2019-09-05 00:14:07
【问题描述】:
经过数小时的谷歌、复制粘贴代码和玩耍,我仍然找不到解决问题的方法。
我尝试使用顶点和片段函数编写后处理着色器。我的问题是我不知道如何计算当前顶点到世界坐标中相机位置(或任何其他给定位置)的径向距离。
我的目标如下:
考虑一个非常大的 3D 平面,其中相机位于顶部,并且向下看该平面。我现在想要一个在平面上绘制白线的后处理着色器,这样只有那些与相机有一定径向距离的像素才会被涂成白色。预期结果将是一个白色圆圈(在此特定设置中)。
我原则上知道如何做到这一点,但问题是我不知道如何计算到顶点的径向距离。
这里的问题可能是这是一个 POSTPROCESSING 着色器。所以这个着色器不会应用于某个对象。如果我愿意,我可以使用mul(unity_ObjectToWorld, v.vertex) 获得顶点的世界坐标,但对于后处理着色器,这给出了一个无意义的值。
这是我针对这个问题的调试代码:
Shader "NonHidden/TestShader"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Transparent" "Queue"="Transparent-1"}
LOD 100
ZWrite Off
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 3.0
#include "UnityCG.cginc"
sampler2D _MainTex;
sampler2D _CameraDepthTexture;
uniform float4 _MainTex_TexelSize;
// V2F
struct v2f {
float4 outpos : SV_POSITION;
float4 worldPos : TEXCOORD0;
float3 rayDir : TEXCOORD1;
float3 camNormal : TEXCOORD2;
};
// Sample Depth
float sampleDepth(float2 uv) {
return Linear01Depth(
UNITY_SAMPLE_DEPTH(
tex2D(_CameraDepthTexture, uv)));
}
// VERTEX
v2f vert (appdata_tan v)
{
TANGENT_SPACE_ROTATION;
v2f o;
o.outpos = UnityObjectToClipPos(v.vertex);
o.worldPos = mul(unity_ObjectToWorld, v.vertex);
o.rayDir = mul(rotation, ObjSpaceViewDir(v.vertex));
o.camNormal = UNITY_MATRIX_IT_MV[2].xyz;
return o;
}
// FRAGMENT
fixed4 frag (v2f IN) : SV_Target
{
// Get uv coordinates
float2 uv = IN.outpos.xy * (_ScreenParams.zw - 1.0f);
// Flip y if necessary
#if UNITY_UV_STARTS_AT_TOP
if (_MainTex_TexelSize.y < 0)
{
uv.y = 1 - uv.y;
}
#endif
// Get depth
float depth = sampleDepth(uv);
// Set color
fixed4 color = 0;
if(depth.x < 1)
{
color.r = IN.worldPos.x;
color.g = IN.worldPos.y;
color.b = IN.worldPos.z;
}
return color;
}
ENDCG
}
}
}
当前状态
此图显示了相机俯视飞机时的结果: Image 1: Actual result 每个像素中的蓝色值(无论出于何种原因)为 25。红色和绿色区域反映了屏幕的 x-y 坐标。
即使我稍微旋转相机,我也会在相同的屏幕坐标处获得完全相同的阴影:
这表明计算出的“worldPos”坐标是屏幕坐标,与平面的世界坐标无关。
预期结果
我希望看到的结果如下:
在这里,与相机具有相同(径向)距离的像素具有相同的颜色。
我需要如何更改上面的代码才能达到这个效果?使用 rayDir(在 vert 函数中计算)我试图至少获得从相机中心到当前像素的方向矢量,这样我就可以使用深度信息计算径向距离。但是 rayDir 对所有像素都有一个恒定值...
在这一点上,我还不得不说,我并不真正理解 vert 函数内部计算的内容。这只是我在互联网上找到并尝试过的东西。
【问题讨论】:
-
请阅读如何创建minimal, complete, verifiable example 并通过编辑将缺少的信息添加到您的帖子中:) 如果您还没有阅读[如何提问](stackoverflow.com/help/how-to-ask) 但我建议这样做:) 我强烈建议遵循我链接的 2 个指南,因为当帖子遵循这些指南时,SO 上的人更有可能回答问题。我特别缺少的是 - 到目前为止你尝试了什么?您面临哪些错误/问题?您可能有有助于理解您的问题的 coden-ps 吗?欢迎使用 StackOverflow
-
@Tobias:好建议。其中一个链接在上面有点损坏 - 您可能想知道您可以在 cmets 中使用
[ask]和[mcve],它会自动扩展到这些链接。 -
@halfer 是的,我知道链接已损坏 - 但我无法再编辑此评论。而且我总是以复杂的方式将它们联系起来。这是我多年来得到的最好建议!我敢打赌我可以在任何地方找到这些“快捷方式”的列表:D
-
@Tobias:我想我已经在帮助中心看到了它们的文档,但你真的必须搜索它
;-)