Unity中HLSL几何着色器硬编码三角形无法显示的问题求助
问题分析与解决方案
嘿,我一眼就瞅出几个关键问题,这就是你的几何着色器输出全黑的原因:
- 顶点没转成裁剪空间坐标:你在几何着色器里直接写的是局部空间的数值,但Unity的GPU需要的是经过MVP变换后的裁剪空间坐标,不然它根本不知道该把这些点画在屏幕的哪个位置。
- 顶点的w分量设错了:你写的
float4(0.1, 0.1, 0, 0)里w是0,GPU会把这个当成方向向量,而不是实际的位置点,正确的位置点w分量得是1.0才行。
另外,你现在只输出了3个顶点(一个三角形),如果要画四边形的话得输出6个顶点(两个三角形),不过先把显示问题解决再说~
修改后的完整Shader
Shader "foo/bar" { SubShader{ Cull Off Lighting Off ZWrite Off Pass{ CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma geometry geom // 引入Unity内置的工具函数和矩阵 #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; }; struct v2g { float4 vertex : POSITION; }; struct g2f { float4 vertex : SV_POSITION; // 这里必须用SV_POSITION,这是GPU识别裁剪空间位置的标准语义 }; v2g vert(appdata v) { v2g o = (v2g)0; o.vertex = v.vertex; return o; } [maxvertexcount(4)] void geom(point v2g p[1], inout TriangleStream<g2f> tristream) { g2f o = (g2f)0; // 定义四边形的四个局部空间顶点,w分量设为1.0 float4 quadVerts[4] = { float4(0.1, 0.1, 0, 1.0), float4(0.1, 0.9, 0, 1.0), float4(0.9, 0.9, 0, 1.0), float4(0.9, 0.1, 0, 1.0) }; // 把每个顶点从局部空间转换到裁剪空间 for (int i = 0; i < 4; i++) { o.vertex = UnityObjectToClipPos(quadVerts[i]); tristream.Append(o); } // 重启三角带,让四个顶点组成一个四边形(两个三角形) tristream.RestartStrip(); } fixed4 frag(g2f i) : COLOR { return fixed4(1,1,1,1); } ENDCG } } }
关键修改点说明
- 引入
UnityCG.cginc:这个内置文件帮我们封装了常用的变换函数,比如UnityObjectToClipPos,不用自己手动写复杂的矩阵乘法。 g2f的顶点语义改成SV_POSITION:原来的POSITION在顶点着色器里是局部空间坐标,但几何着色器输出给片元着色器的必须是裁剪空间坐标,SV_POSITION是GPU认可的标准语义。- 把顶点w分量改成1.0:确保这些坐标被GPU当成实际的位置点,而不是方向向量。
- 添加裁剪空间变换:用
UnityObjectToClipPos()把我们定义的局部空间顶点转换成GPU能识别的裁剪空间坐标,这样才能正确渲染到屏幕上。 - 补全第四个顶点并调用
RestartStrip():这样四个顶点就能组成一个完整的四边形,符合你最初想用几何着色器把点转成四边形的需求。
额外要检查的点
- 确认你的GameObject用的是点网格(Point Mesh):因为你的几何着色器声明的是
point输入类型,只有当Mesh的拓扑是Points时,几何着色器才会接收到输入。如果你的Mesh是三角形或者其他拓扑,几何着色器根本不会触发哦。 - 检查相机的视锥体范围:确保你定义的四边形坐标在相机能看到的范围内,比如如果是正交相机,要和相机的Size参数匹配,不然可能会被裁切掉。
内容的提问来源于stack exchange,提问作者Fraser
相关产品推荐
相关产品推荐

