osg::PolygonMode --- 设置多边形模式
osg::AnimationPathCallback: 派生自 osg::NodeCallback
可以创建一个旋转动画(构造函数设置旋转的中心, 轴和旋转速度)
osg::Node::getBound() --- 可以获取包围球
osg::BoundingBox::expandBy() --- 可以从包围球获取包围盒
osg::ClipNode
osg::MatrixTransform 设置动画(使用更新回调)
setUpdateCallback
添加 osg::ClipNode 然后移动它可以实现其 stateset 的变化
osg::Group 可以设置为一个 osg::ClipNode 所带的 osg::StateSet, 而后该 group 所添加的子节点都会应用该 ClipNode 的状态, 至于之前 osg::ClipNode 节点可以添加在其他地方
创建纹理对象
osg::Texture2D
setDataVariance
setImage
setFilter
演示多重纹理, 第二个纹理使用了纹理坐标球面生成的方式, 并和第一重纹理进行混合
osg::TexGen: 设置纹理坐标生成
osg::TexEnv: 映射模式
setMode --- 设置模式为混合
setColor
演示不同 mipmap level 使用不同的图像裸数据
osg::Image::MipmapDataType 类型变量是一个列表, 可以保存每一级别的图像偏移位置
osg::Image::setImage() 设置包含裸数据的图像数据
创建一个带有 Mipmap 的图像数据, 而后将其作为纹理
osg::Image
setImage 根据图像裸数据设置图像
setMipmapLevels 可以放置上面的变量, 而后设置 Mipmap 即可
05.05 TextureRectangle 纹理映射
纹理坐标不需要被单元化, 纹理的大小不需要是2的幂次方, 不支持 REPEAT 环绕模式, 过滤不支持 Mipmap, 不支持纹理边框
osg::TexMat 设置纹理矩阵, 在纹理属性里面设置其对象
setScaleByTextureRectangleSize: 设置纹理矩阵,并设置为根据矩阵纹理(TextureRectangle)的大小自动缩放
osg::TexGen
osg::StateSet::setTextureMode 设置 GL_TEXTURE_GEN_S, GL_TEXTURE_GEN_T 的开关模式
通过一个纹理坐标生成器(继承自 osg::NodeVisitor 访问器的派生类)遍历模型的所有顶点及法线, 然后根据顶点,法线及一定的比例来确定纹理坐标
osg::Geometry
getVertexArray()
getNormalArray()
知识点: osg::Transform 的两个矩阵计算, 立方体纹理, 纹理坐标自动生成以及其对应的纹理矩阵, osg::ClearNode自动清理buffer节点, osg::Depth实现深度设置
通过派生 Transform, 可以预先移动子节点, 这样实现相机始终位于天空盒内的效果
创建一个节点回调, 可以在 Cull 回调中计算出新的纹理矩阵
获取当前相机的模型视图矩阵 osgUtil::CullVisitor::getModelViewMatrix
// osg::NodeCallback 派生类的重载函数
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) {
osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv);
if (cv)
{
//得到模型视图矩阵并设置旋转角度
const osg::Matrix& MV = *(cv->getModelViewMatrix());
// 先绕 x 轴旋转90度
const osg::Matrix R = osg::Matrix::rotate(osg::DegreesToRadians(112.0f), 0.0f, 0.0f, 1.0f)*
osg::Matrix::rotate(osg::DegreesToRadians(90.0f), 1.0f, 0.0f, 0.0f);
osg::Quat q = MV.getRotate();
const osg::Matrix C = osg::Matrix::rotate(q.inverse());
//设置纹理矩阵
_texMat.setMatrix(C*R);
}
traverse(node, nv);
}
上面实现了纹理矩阵的求解, 主要左乘加上相机的逆矩阵, 从而实现纹理坐标跟随相机的旋转而运动
四元数与矩阵的一些操作
从一个矩阵中获取四元数 osg::Matrix::getRotate
从一个四元数中获取逆矩阵 osg::Quat::inverse()
从一个四元数中获取矩阵 osg::Matrix::rotate(const osg::Quat&);
osg::TexEnv 设置纹理替换模式
osg::ref_ptr<osg::TexEnv> te = new osg::TexEnv;
te->setMode(osg::TexEnv::REPLACE);
stateset->setTextureAttributeAndModes(0, te.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
// NORMAL_MAP 标准模式-立方图纹理
// REFLECTION_MAP 反射模式-球体纹理
// SPHERE_MAP 球体模型-球体纹理
osg::ref_ptr<osg::TexGen> tg = new osg::TexGen;
tg->setMode(osg::TexGen::NORMAL_MAP);
stateset->setTextureAttributeAndModes(0, tg.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
//设置纹理矩阵
osg::ref_ptr<osg::TexMat> tm = new osg::TexMat;
stateset->setTextureAttribute(0, tm.get());
osg::TextureCubeMap
setImage --- 设置六个面的图像
setWrap
osg::StateSet::setRenderBinDetails --- 设置渲染顺序
osg::Depth --- 设置深度属性
通过深度设置远平面
//将深度设置为远平面
osg::ref_ptr<osg::Depth> depth = new osg::Depth;
depth->setFunction(osg::Depth::ALWAYS);
depth->setRange(1.0, 1.0);//远平面
stateset->setAttributeAndModes(depth, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
osg::ClearNode: 可以用于清除颜色和深度缓存, 子节点设置 render bin 为 -1, 确保在其他节点绘制之前绘制.
osg::Transform 可以预先计算矩阵, 其子节点先应用变换, 这里通过重载函数确保变换始终在相机位置处, 主要应用世界到局部坐标, 局部坐标到世界坐标的矩阵变换.
矩阵的求解, 按照左乘矩阵的原则, 局部到世界的矩阵计算, 原有矩阵已经实现局部到世界的变换, 在前面再乘以相机的偏移实现世界坐标下的偏移
世界到局部的计算, 先把世界乘以相机的逆向偏移, 然后再乘以原有的矩阵变换. 所以需要后乘相机的逆向偏移.
//一个变换类,使天空盒绕视点旋转
class MoveEarthySkyWithEyePointTransform : public osg::Transform
{
public:
//局部矩阵计算成世界矩阵
virtual bool computeLocalToWorldMatrix(osg::Matrix& matrix, osg::NodeVisitor* nv) const
{
osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv);
if (cv)
{
osg::Vec3 eyePointLocal = cv->getEyeLocal();
matrix.preMult(osg::Matrix::translate(eyePointLocal));
}
return true;
}
//世界矩阵计算为局部矩阵
virtual bool computeWorldToLocalMatrix(osg::Matrix& matrix, osg::NodeVisitor* nv) const
{
osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv);
if (cv)
{
osg::Vec3 eyePointLocal = cv->getEyeLocal();
matrix.postMult(osg::Matrix::translate(-eyePointLocal));
}
return true;
}
};
osg::AnimationPathCallback 根据构造函数创建动画路径回调, 用于 osg::MatrixTransform 的更新巍峨回调
osg::Geometry
setSupportsDisplayList(false): 可设置是否支持显示列表
osg::Texture
学习如何使用 VBO
osg::Geometry::setVertexArray
osg::Vec3Array::setVertexBufferObject
osg::Geometry::setUseVertexBufferObjects --- 设置该几何体使用 VBO
创建相机, 将其渲染到纹理(RTT)
osg::Camera
设置清空背景颜色, 清空标识, 参考帧, 视口, 渲染目标实现
attach() --- 挂接到纹理或图像
setRenderTargetImplementation: 可设置渲染至 FBO
setPostDrawCallback: 设置后期绘制回调
osg::Camera::DrawCallback
osg::Texture1D: 一维纹理
osg::TexGen: 生成纹理坐标
osg::ref_ptr<osg::TexGen> texgen = new osg::TexGen;
texgen->setMode(osg::TexGen::OBJECT_LINEAR);
texgen->setPlane(osg::TexGen::S, osg::Plane(0.0f, 0.0f, 1.0f, -10000));
//创建属性集
osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet;
//启用纹理生成器
stateset->setTextureAttribute(0, texgen.get(), osg::StateAttribute::OVERRIDE);
stateset->setTextureMode(0, GL_TEXTURE_GEN_S, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
osg::Light 类派生自 osg::StateAttribute 类, 继承了对模式与属性参数信息的操作接口. 在 osg::light 类中通过 apply(State& state)函数将灯光的状态参数信息应用到OpenGL的状态机中
osg::LightSource 类派生自 osg::Group 类, 将灯光作为一个节点可以加入到场景图中进行渲染.
void setReferenceFrame(ReferenceFrame rf) // 设置帧引用
帧引用有两个枚举变量: RELATIVE_RF(相对帧引用), ABSOLUTE_RF(绝对帧引用)
推荐在场景的顶部使用绝对的光源
法线的重缩放, 可以改善光照结果的明亮
osg::StateSet* state = geode->getOrCreateStateSet();
state->setMode(GL_RESCALE_NORMAL, osg::StateAttribute::ON);
自动单元化法线
osg::StateSet* state = geode->getOrCreateStateSet();
state->setMode(GL_NORMALIZE, osg::StateAttribute::ON);
允许根节点的光照以及两个光源
osg::StateSet* state = root->getOrCreateStateSet();
state->setMode(GL_LIGHTING, osg::StateAttribute::ON);
state->setMode(GL_LIGHT0, osg::StateAttribute::ON);
state->setMode(GL_LIGHT1, osg::StateAttribute::ON);
使用 osg::Light 设置光的属性, osg::LightSource 添加该对象
创建一张图像, 自中心逐渐衰减
创建动画路径: osg::AnimationPath
设置循环模式 setLoopMode
插入控制点(时间, 位置, 旋转) insert
osg::MatrixTransform 可以设置矩阵变换, 例如
positioned->setMatrix(osg::Matrix::translate(-bs.center())*
osg::Matrix::scale(size, size, size)*
osg::Matrix::rotate(osg::inDegrees(180.0f), 0.0f, 0.0f, 2.0f));
osg::MatrixTransform 可以设置更新回调为 osg::AnimationPathCallback 以实现路径动画
使用网格高度域创建高低不平的平面 osg::HeightField
osg::TexGenNode 用于创建一个节点, 可以自动生成纹理坐标
osg::TexGen 设置纹理坐标生成方法
setMode 和 setPlanesFromMatrix
osg::Texture2D 可以设置边框颜色, wrap
osg::StateSet 可以用 setTextureMode 设置某个纹理单元的模式, 如纹理每个方向的生成是否打开
本例设置的是点光源, 所以没有聚光灯的效果, 要实现聚光灯的效果, 需要通过创建第二个纹理的方式实现, 在目标处自动生成纹理坐标
osg::Material 派生自 osg::StateAttribute 类, 其封装了 OpenGL 的 glMaterial() 和 glColorMaterial() 函数
设置节点的材质属性, 首先创建一个 osg::Material, 而后设置颜色和其他参数, 在关联到场景图形的 StateSet 中
osg::StateSet* state = node->getOrCreateStateSet();
osg::ref_ptr<osg::Material> mat = new osg::Material;
state->setAttribute(mat.get());
几个枚举类型: Face, ColorMode
要颜色跟踪材质需要调用 setColorMode()(内部应该是 glColorMaterial 函数), 不需要客户使用 setAttributeAndeModes() 来控制 GL_COLOR_MATERIAL
代码设置 osg::Material 属性
程序看起来是用了默认光照