尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

OsgEarth 加载CESIUM或ReadyMap 后,再加载模型,结果黑乎乎

OsgEarth 加载CESIUM或ReadyMap 后,再加载模型,结果黑乎乎 最近做了一个有关地球的OsgEarth的项目发现OsgEarth 加载CESIUM或ReadyMap 后再加载模型结果黑乎乎。。。折腾数日发现了解决方法。。。原理就不说了直接贴代码/** * file ModelShaderLoader.h * brief 模型加载自建着色器工具类解决osgEarth ReadyMap / CesiumNative模型发黑问题 * details * 两套渲染环境二选一自动选择对应着色器 * 1. ReadyMap不启用GL3RealizeOperation使用osg_*别名版本shader屏幕微分法线漫反射 * 2. CesiumNative启用GL3RealizeOperation(Core Profile)不能使用osg_*别名 * 使用显式location顶点属性Node回调实时推送MVP矩阵uniform同样屏幕微分法线漫反射。 * 功能加载模型、挂载对应shader、全局缩放。 * author xxx * date 2026-09-23 * note * - 两套环境模型加载都正常着色器分支自动切换消除模型发黑 * - CesiumNative环境禁止调用setUseModelViewAndProjectionUniforms/setUseVertexAttributeAliasing会崩溃。 * warning * - CesiumNative使用NodeCallback实时更新矩阵uniform有极小额外开销 * - 着色器状态使用OVERRIDE子节点材质无法覆盖。 */ #pragma once #include QObject #include osg/ref_ptr #include osg/NodeCallback #include string class ModelShaderLoader : public QObject { Q_OBJECT public: enum class RenderEnv { ReadyMap, CesiumNative }; explicit ModelShaderLoader(QObject* parent nullptr); void setRenderEnv(RenderEnv env); /** * brief 加载模型并自动挂载对应环境的自建shader修复发黑 * param[in] filePath 模型路径 * param[in] scale 模型缩放系数 * return osg::ref_ptrosg::Node 组装完成节点失败返回nullptr */ osg::ref_ptrosg::Node loadModel(const std::string filePath, double scale); private: RenderEnv _renderEnv RenderEnv::ReadyMap; // ReadyMap 版本shader源码osg_*别名 static const char* vertSrcReadyMap; static const char* fragSrcReadyMap; // CesiumNative CoreProfile版本shader源码无osg_*别名 static const char* vertSrcCesium; static const char* fragSrcCesium; // Cesium环境回调遍历节点更新MVP uniform struct MatrixUpdateCallback; }; /** * file ModelShaderLoader.cpp * brief ModelShaderLoader实现自建shader解决osgEarth Cesium/ReadyMap模型发黑 * author xxx * date 2026-09-23 */ #include ModelShaderLoader.h #include osgViewer/Viewer #include osg/State #include osg/Texture #include osg/NodeVisitor #include osg/MatrixTransform #include osg/Uniform #include osg/Shader #include osg/Program #include osgDB/ReadFile #include iostream // ReadyMap Shaderosg_*别名 const char* ModelShaderLoader::vertSrcReadyMap R( #version 330 core in vec4 osg_Vertex; in vec4 osg_MultiTexCoord0; uniform mat4 osg_ModelViewProjectionMatrix; uniform mat4 osg_ModelViewMatrix; out vec2 vTexCoord; out vec3 vViewPos; void main() { gl_Position osg_ModelViewProjectionMatrix * osg_Vertex; vViewPos (osg_ModelViewMatrix * osg_Vertex).xyz; vTexCoord osg_MultiTexCoord0.xy; } ); const char* ModelShaderLoader::fragSrcReadyMap R( #version 330 core uniform sampler2D tex0; in vec2 vTexCoord; in vec3 vViewPos; out vec4 fragColor; void main() { vec3 dx dFdx(vViewPos); vec3 dy dFdy(vViewPos); vec3 normal normalize(cross(dx, dy)); vec3 lightDir normalize(vec3(0.6, 0.7, 0.4)); float diff max(dot(normal, lightDir),0.0); vec4 texColor texture(tex0, vTexCoord); vec3 rgb texColor.rgb * (0.3 0.7 * diff); fragColor vec4(rgb, texColor.a); } ); // CesiumNative ShaderCoreProfile无osg_* const char* ModelShaderLoader::vertSrcCesium R( #version 330 core layout(location 0) in vec3 aPos; layout(location 1) in vec2 aTexCoord; uniform mat4 uMVP; uniform mat4 uModelView; out vec2 vTexCoord; out vec3 vViewPos; void main() { gl_Position uMVP * vec4(aPos,1.0); vViewPos (uModelView * vec4(aPos,1.0)).xyz; vTexCoord aTexCoord; } ); const char* ModelShaderLoader::fragSrcCesium R( #version 330 core uniform sampler2D tex0; in vec2 vTexCoord; in vec3 vViewPos; out vec4 fragColor; void main() { vec3 dx dFdx(vViewPos); vec3 dy dFdy(vViewPos); vec3 normal normalize(cross(dx, dy)); vec3 lightDir normalize(vec3(0.6, 0.7, 0.4)); float diff max(dot(normal, lightDir),0.0); vec4 texColor texture(tex0, vTexCoord); vec3 rgb texColor.rgb * (0.3 0.7 * diff); fragColor vec4(rgb, texColor.a); } ); // Cesium 矩阵更新回调每帧遍历获取模型矩阵上传MVP struct ModelShaderLoader::MatrixUpdateCallback : public osg::NodeCallback { osg::ref_ptrosg::Uniform _uMVP; osg::ref_ptrosg::Uniform _uModelView; MatrixUpdateCallback() { _uMVP new osg::Uniform(uMVP, osg::Matrixf()); _uModelView new osg::Uniform(uModelView, osg::Matrixf()); } void operator()(osg::Node* node, osg::NodeVisitor* nv) override { osg::Matrixd MVP node-getMatrix() * nv-getViewMatrix() * nv-getProjectionMatrix(); osg::Matrixd MV node-getMatrix() * nv-getViewMatrix(); _uMVP-set(MVP); _uModelView-set(MV); traverse(node, nv); } }; ModelShaderLoader::ModelShaderLoader(QObject* parent) : QObject(parent) { } void ModelShaderLoader::setRenderEnv(RenderEnv env) { _renderEnv env; } osg::ref_ptrosg::Node ModelShaderLoader::loadModel(const std::string filePath, double scale) { osg::ref_ptrosg::Node modelNode osgDB::readNodeFile(filePath); if (!modelNode) { std::cerr [ModelShaderLoader] load model failed: filePath std::endl; return nullptr; } osg::ref_ptrosg::Program program new osg::Program; osg::ref_ptrMatrixUpdateCallback matrixCb; if (_renderEnv RenderEnv::ReadyMap) { std::cout [ModelShaderLoader] ReadyMap env, use osg_alias shader std::endl; program-addShader(new osg::Shader(osg::Shader::VERTEX, vertSrcReadyMap)); program-addShader(new osg::Shader(osg::Shader::FRAGMENT, fragSrcReadyMap)); program-addBindAttribLocation(osg_Vertex, 0); program-addBindAttribLocation(osg_MultiTexCoord0, 1); } else { std::cout [ModelShaderLoader] CesiumNative env, use core profile shader std::endl; program-addShader(new osg::Shader(osg::Shader::VERTEX, vertSrcCesium)); program-addShader(new osg::Shader(osg::Shader::FRAGMENT, fragSrcCesium)); matrixCb new MatrixUpdateCallback(); } // 遍历Geode挂载shader struct ApplyShaderVisitor : public osg::NodeVisitor { osg::Program* _prog; MatrixUpdateCallback* _mtxCb; ApplyShaderVisitor(osg::Program* p, MatrixUpdateCallback* cb) : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN), _prog(p), _mtxCb(cb) {} void apply(osg::Geode geode) override { for (unsigned int i 0; i geode.getNumDrawables(); i) { osg::Drawable* draw geode.getDrawable(i); osg::StateSet* ss draw-getOrCreateStateSet(); ss-setAttributeAndModes(_prog, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); ss-setMode(GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE); ss-addUniform(new osg::Uniform(tex0, 0)); if (_mtxCb) { ss-addUniform(_mtxCb-_uMVP.get()); ss-addUniform(_mtxCb-_uModelView.get()); } } } }; ApplyShaderVisitor vis(program.get(), matrixCb.get()); modelNode-accept(vis); // 外层缩放节点 绑定矩阵回调Cesium环境 osg::ref_ptrosg::MatrixTransform scaleXform new osg::MatrixTransform; scaleXform-setMatrix(osg::Matrix::scale(osg::Vec3(scale, scale, scale))); scaleXform-addChild(modelNode.get()); if (matrixCb) { scaleXform-addUpdateCallback(matrixCb.get()); } return scaleXform; } // 1. CesiumNative开启GL3RealizeOperation auto loader new ModelShaderLoader(this); loader-setRenderEnv(ModelShaderLoader::RenderEnv::CesiumNative); auto modelNode loader-loadModel(xxx.obj, 1.0); // 2. ReadyMap不开启GL3RealizeOperation打开alias开关 auto loader new ModelShaderLoader(this); loader-setRenderEnv(ModelShaderLoader::RenderEnv::ReadyMap); auto modelNode loader-loadModel(xxx.obj, 1.0);
返回列表