- 环境
- 问题 - OpenGL ES 2.0 没有 SV_VertexID
- 解决
- UV 转 ID
- 自定义后效处理管线
- References
环境
Unity : 2019.4.30f1
Pipeline : Built-in RP
问题 - OpenGL ES 2.0 没有 SV_VertexID
在实现后效中,因为需要使用到屏幕空间的世界坐标
而为了获得屏幕空间的世界坐标,我们将 屏幕深度,转为对应的世界坐标,具体可以参考我之前的一篇:
Unity Shader - 根据片段深度重建片段的世界坐标
然后我为了更高效的获取世界坐标,因此使用到了 SV_VertexID 来得到后效中四个角落的顶点对应的ID
如果这时你在 OpenGL ES 2.0 下的话,shader lab 编译会报错:
Shader error in 'Test/MyFogOfWar_2dNoise_parallax_plane_mask': SV_VertexID semantic is not supported on GLES 2.0 (on gles)
说是 OpenGL ES 不支持 SV_VertexID
解决
UV 转 ID
因为我们的后效顶点坐标就那么四个,是可以自己根据 uv 坐标来区别的
如下图,这是我们后效的这个顶点的 UV 情况,与 ID 编号的情况
将 在 frag 中,将 uv 输出,可以查看到与上图的 UV 坐标是一致的:
所以我们可以在 顶点着色器 中这么写:
... struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; //uint vid : SV_VertexID; // jave.lin : 在 dx 没问题,在 openGL ES 2.0 有报错,在 OpenGL ES 3.0 虽然没编译报错,但是值不对,所以我们为了兼容性考虑,不适用这个特性 }; ... v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = v.uv; uint vid; if (v.uv.x < 0.5 && v.uv.y < 0.5) vid = 0; else if (v.uv.x < 0.5 && v.uv.y >= 0.5) vid = 1; else if (v.uv.x >= 0.5 && v.uv.y >= 0.5) vid = 2; else vid = 3; //o.ray = _Ray[v.vid]; // 如上述,有兼容性问题,我们使用计算 uv 坐标的方式来得到 vertex id o.ray = _Ray[vid]; return o; }
自定义后效处理管线
另一种方法就是:自己弄个 quad 来绘制 color buffer,可以参考:Unity Shader - 模仿RenderImage制作全屏Quad
方法是,在传入 quad 的顶点坐标信息时,给 .w 第四个分量设置上 ID 编号
GL.PushMatrix(); mat.SetPass(0); GL.LoadOrtho(); GL.Begin(GL.TRIANGLE_STRIP); // 注意顶点顺序,组合为:顺时针即可,Unity 逆时针为正面 // 注意顶点顺序,组合为:顺时针即可,Unity 逆时针为正面 GL.Vertex3(-1, -1, 0, 0); GL.Vertex3(1, -1, 0 3); GL.Vertex3(-1, 1, 0 1); GL.Vertex3(1, 1, 0 2); GL.End(); GL.Flush();
然后再 vs 中就可以获得 自己传入的 ID 值
struct a2v { float4 positionNDC : POSITION; // jave.lin : xyz: positionNCD xyz, w: vertex ID ... }; struct v2f { ... }; v2f vert (a2v v) { v2f o = (v2f)0; ... uint MyVertexID = (uint)v.positionNDC.w; // jave.lin : 在顶点着色器就可以拿到我们自定义后效管线传入的顶点 ID 值了 ... return o; } ...
References
-
OpenGLES 2.0: gl_VertexID equivalent? - 9年前的问题,结果只有这个回答,14 赞的:Unfortunately there is no gl_VertexID equivalent in GLES2. You must create and pass additional data yourself. - 我只能说,有点惨
-
我记得
也有运算 SV_VertexID 的方式,而且是更加高效的,因为使用到的是 bit operation (位运算) 的方式, 但是顶点就这么 4 个, 优不优化都无所谓了
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)