OSG新版GLSL语法全解析
“OSG 新版语法”其实不是 OSG(OpenSceneGraph)本身的语法变化,而是 OSG 使用的 OpenGL GLSL(OpenGL Shading Language) 的更新与封装方式变化。
OSG 只是调用 OpenGL shader 功能(即 GLSL),所以“新版语法”其实是指 GLSL 3.30+ 或 4.x 的规范,而不是 OSG 自定义语法。
下面我帮你系统总结:
🧩 一、GLSL 在 OSG 中的使用结构
OSG 使用 osg::Shader 与 osg::Program 管理 GLSL 代码:
osg::ref_ptr<osg::Program> program = new osg::Program;
program->addShader(osg::Shader::readShaderFile(osg::Shader::VERTEX, "shader.vert"));
program->addShader(osg::Shader::readShaderFile(osg::Shader::FRAGMENT, "shader.frag"));osg::StateSet* ss = geode->getOrCreateStateSet();
ss->setAttributeAndModes(program, osg::StateAttribute::ON);
ss->addUniform(new osg::Uniform("myColor", osg::Vec3(1.0f, 0.0f, 0.0f)));
🧠 二、GLSL 新版语法(以 #version 330 core 为例)
GLSL 3.30 之后有明显语法更新,与旧版(1.20、1.30)不同:
| 功能 | 旧版写法 | 新版写法(推荐) |
|---|---|---|
| 顶点输入 | attribute vec3 position; | layout(location = 0) in vec3 aPos; |
| 顶点输出 / 片元输入 | varying vec2 texCoord; | out vec2 fragTexCoord;(在顶点) / in vec2 fragTexCoord;(在片元) |
| uniform 声明 | uniform mat4 modelViewProj; | 同旧版,但更严格类型检查 |
| 颜色输出 | gl_FragColor = vec4(1.0); | layout(location=0) out vec4 FragColor; |
| 纹理采样 | texture2D(sampler, uv) | texture(sampler, uv) |
| 矩阵乘法 | gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; | 自定义 uniform: uniform mat4 MVP; gl_Position = MVP * vec4(aPos,1.0); |
| 光照等固定管线变量 | 旧版使用 gl_Normal, gl_Color 等 | 新版完全废弃,由用户自己传入 |
⚙️ 三、OSG 与 GLSL 的常见内置变量和 Uniform
新版 OSG 不再自动传递固定管线变量(如 gl_ModelViewMatrix),但你可以在 C++ 层手动设置。
下面是一些 OSG 常见自动或自定义传递的 uniform 名称与用途:
| 变量名 | 类型 | 来源 / 含义 |
|---|---|---|
osg_ModelViewMatrix | mat4 | 模型视图矩阵 |
osg_ProjectionMatrix | mat4 | 投影矩阵 |
osg_ModelViewProjectionMatrix | mat4 | 模型视图投影矩阵 |
osg_NormalMatrix | mat3 | 法线矩阵(视图空间下的法线变换) |
osg_ViewMatrix | mat4 | 摄像机视图矩阵 |
osg_Viewport | vec4 | 当前视口 |
osg_FrameTime | float | 当前帧时间(如果启用) |
osg_DeltaFrameTime | float | 帧间时间差 |
osg_FrameNumber | int | 帧编号 |
osg_SimulationTime | float | 模拟时间 |
这些变量在启用 osg::StateSet 的 setUseShaderDefines(true) 或绑定了相机的状态集时可以自动注入。
🧩 四、顶点/片元着色器常见模板
✅ 顶点着色器
#version 330 corelayout(location = 0) in vec3 aPos; // 顶点位置
layout(location = 1) in vec3 aNormal; // 顶点法线
layout(location = 2) in vec2 aTexCoord; // 纹理坐标out vec2 fragTexCoord; // 传递给片元着色器uniform mat4 osg_ModelViewProjectionMatrix;void main()
{gl_Position = osg_ModelViewProjectionMatrix * vec4(aPos, 1.0);fragTexCoord = aTexCoord;
}
✅ 片元着色器
#version 330 corein vec2 fragTexCoord;
out vec4 FragColor;uniform sampler2D diffuseMap;void main()
{vec3 color = texture(diffuseMap, fragTexCoord).rgb;FragColor = vec4(color, 1.0);
}
🧱 五、OSG 常用 Uniform 类型对应关系(C++ → GLSL)
| OSG C++ Uniform 类型 | GLSL 对应类型 | 示例 |
|---|---|---|
osg::Uniform::FLOAT | float | uniform float time; |
osg::Uniform::FLOAT_VEC2 | vec2 | uniform vec2 offset; |
osg::Uniform::FLOAT_VEC3 | vec3 | uniform vec3 lightDir; |
osg::Uniform::FLOAT_VEC4 | vec4 | uniform vec4 color; |
osg::Uniform::FLOAT_MAT4 | mat4 | uniform mat4 MVP; |
osg::Uniform::INT | int | uniform int layerIndex; |
osg::Uniform::SAMPLER_2D | sampler2D | uniform sampler2D tex; |
🔧 六、OSG 新版 Shader 开发技巧
-
保持 GLSL 版本一致(顶点与片元)
-
使用
layout(location = x)明确绑定输入 -
所有
in与out变量必须一一对应类型 -
用自定义 uniform 替代旧的固定管线矩阵
-
不要使用被弃用的变量(如
gl_Vertex,gl_Color,gl_Normal) -
调试时启用 OSG 的着色器日志
osg::DisplaySettings::instance()->setShaderHint(osg::DisplaySettings::SHADER_HINT_DEBUG);
🧾 七、完整的现代 OSG Shader 框架
osg::ref_ptr<osg::Program> program = new osg::Program;
program->addShader(new osg::Shader(osg::Shader::VERTEX, vertexSource));
program->addShader(new osg::Shader(osg::Shader::FRAGMENT, fragmentSource));osg::ref_ptr<osg::Uniform> mvpUniform = new osg::Uniform("osg_ModelViewProjectionMatrix", osg::Matrixf());
ss->addUniform(mvpUniform);ss->setAttributeAndModes(program.get(), osg::StateAttribute::ON);
🚀 八、进一步学习建议
| 主题 | 推荐版本/参考 |
|---|---|
| GLSL 标准文档 | OpenGL 4.6 Core Profile GLSL 460 Specification |
| OSG Shader 示例 | OpenSceneGraph/examples/osgshader/ |
| 现代 OSG 教程 | https://github.com/openscenegraph/OpenSceneGraph/wiki/Shaders |
