仅使用Shader如何让指定Shader获取应用另一Shader的所有GameObject世界坐标
仅Shader层面实现坐标获取的可行方案
方案1:全局结构化缓冲区传递
- 首先在Shader X和Shader Y中声明相同绑定槽位的全局缓冲区:
着色器中统一声明:Shader X用可写缓冲区RWStructuredBuffer<float3> _ObjWorldPosBuffer : register(u10);,Shader Y用只读缓冲区StructuredBuffer<float3> _ObjWorldPosBuffer : register(t10);,保持槽位一致即可 - 修改Shader X的顶点着色器逻辑,取当前对象的世界空间原点坐标写入缓冲区,使用
SV_InstanceID作为写入索引避免不同对象数据覆盖:v2f vert (appdata v, uint instanceID : SV_InstanceID) { _ObjWorldPosBuffer[instanceID] = float3(unity_ObjectToWorld[0][3], unity_ObjectToWorld[1][3], unity_ObjectToWorld[2][3]); // 原有顶点变换逻辑保持不变 } - Shader Y中直接遍历
_ObjWorldPosBuffer所有元素,即可拿到所有使用Shader X的GameObject的世界坐标,过滤掉预设的无效值(比如提前写入的float3(-9999, -9999, -9999))即可排除未使用的槽位 - 注意:缓冲区容量需要在你项目的渲染管线资源配置中提前固定分配,容量设置为场景中最多同时存在的Shader X对象数量即可,无需MonoBehaviour动态调整
方案2:全局纹理传递(适用于不支持结构化缓冲区的平台)
- 在渲染管线配置中提前创建一张1D RGBAFloat格式的全局纹理,绑定到固定采样槽位,长度匹配最大Shader X对象数量
- Shader X渲染时将自身世界坐标编码为RGBA值,写入纹理对应
instanceID位置的像素 - Shader Y采样这张全局纹理,逐像素解码出坐标值即可
通用注意事项
- 必须保证Shader X的渲染队列早于Shader Y,可在Shader的SubShader标签中设置
Queue = "Geometry-100"(Shader X)和Queue = "Geometry"(Shader Y)确保写入操作先于读取操作执行 - 如果存在视锥体剔除导致Shader X对象不渲染、没有写入数据的情况,可在Shader X中添加强制渲染的Pass,或者在管线配置中关闭对应层的视锥体剔除即可
内容的提问来源于stack exchange,提问作者Fox_score
相关产品推荐
相关产品推荐

