You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity中使用高版本GLSL着色器出现顶点坐标异常如何解决

Unity中直接运行高版本GLSL着色器的问题修复

问题复现

初始可正常运行的legacy GLSL测试着色器代码:

GLSLPROGRAM 

#ifdef VERTEX 
   void main()
   {
      gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
   }
#endif 

#ifdef FRAGMENT             
   void main() 
   {
      gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); 
   }
#endif 

ENDGLSL  

添加#version 450声明后触发编译报错:

error C7616: global variable gl_Vertex is removed after version 140

按照现代GLSL规范修改后代码无编译报错,但渲染坐标完全错乱,修改后的问题代码:

GLSLPROGRAM 

#version 450 

#ifdef VERTEX 
   layout(location = 0) in vec4 pos;

   void main()
   {
      gl_Position = gl_ModelViewProjectionMatrix * pos;
   }
#endif 

#ifdef FRAGMENT         
   out vec4 FragColor;

   void main() 
   {
      FragColor = vec4(1.0, 0.0, 0.0, 1.0); 
   }
#endif 

ENDGLSL 

错乱原因

坐标异常来自两个适配错误:

  1. 顶点属性类型和绑定规则不匹配:Unity高版本GLSL模式下,顶点位置属性绑定在location = 0,但该属性是3分量float类型,直接声明为vec4读取时,会把后续顶点法线属性的第一个分量错误读为pos.w,导致顶点坐标数据错位。
  2. 废弃内置变量未替换:版本140以上的core profile GLSL中,Unity不会自动注入gl_ModelViewProjectionMatrix、gl_Vertex这类legacy内置变量,直接调用会读取到未初始化的脏数据,矩阵计算结果完全错误。

可行修复方案

无需转译HLSL,直接按Unity的GLSL适配规则修改代码即可批量复用现有GLSL资源,核心适配规则如下:

  • 顶点属性固定location映射:
    • layout(location = 0) in vec3 _pos:顶点位置
    • layout(location = 1) in vec3 _normal:顶点法线
    • layout(location = 2) in vec2 _uv:顶点纹理坐标
    • layout(location = 3) in vec4 _tangent:顶点切线
  • 手动声明Unity内置变换uniform,替换所有legacy GLSL内置矩阵:
    • uniform mat4 unity_ObjectToWorld:模型空间到世界空间变换矩阵
    • uniform mat4 unity_MatrixVP:世界空间到裁剪空间变换矩阵
    • MVP矩阵计算逻辑为unity_MatrixVP * unity_ObjectToWorld * vec4(顶点位置, 1.0)
  • 片元阶段废弃gl_FragColor,自定义out vec4类型的输出变量即可。

修复后可正常运行的450版本GLSL测试代码:

GLSLPROGRAM 

#version 450 

#ifdef VERTEX 
   layout(location = 0) in vec3 pos;
   uniform mat4 unity_ObjectToWorld;
   uniform mat4 unity_MatrixVP;

   void main()
   {
      vec4 worldPos = unity_ObjectToWorld * vec4(pos, 1.0);
      gl_Position = unity_MatrixVP * worldPos;
   }
#endif 

#ifdef FRAGMENT         
   out vec4 FragColor;

   void main() 
   {
      FragColor = vec4(1.0, 0.0, 0.0, 1.0); 
   }
#endif 

ENDGLSL 
  • 批量适配现有GLSL的注意事项:
    • 所有legacy内置属性、状态变量、矩阵全部替换为上述自定义顶点输入和手动声明的Unity内置uniform,不要依赖140版本前的隐式注入逻辑
    • 顶点属性严格按照映射表的类型声明,避免多读取分量导致的顶点流错位
    • 不要使用GLSL core profile之外的非标准扩展,否则会在Windows等平台触发编译失败

内容的提问来源于stack exchange,提问作者rheadio

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 03:48:22