查看: 2991|回复: 19

如何使背景图片全屏?

[复制链接]

该用户从未签到

发表于 2010-10-28 14:57:52 | 显示全部楼层 |阅读模式
1. 使用创建四边形的方式加载图片,如何使其全屏?
2. 顶点坐标和像素之间的关系如何,怎么才能不使图片变形?
3. 为什么在HUD中不能使用这种方法加载,或者说怎么没有在屏幕中显示?

该用户从未签到

发表于 2010-10-28 15:54:13 | 显示全部楼层
1. 使用HUD方式即可,没有特别需要注意的
2. 我不知道您试图表达什么
3. HUD方式没有问题,有问题的只能是您自己的代码

该用户从未签到

 楼主| 发表于 2010-10-28 18:54:32 | 显示全部楼层
的确,使用HUD方式是可以实现全屏,并且利用drawPixels可以加载图片。
drawPixels->setImage(osgDB::readImagefile(""));
geode->addDrawable(drawPixels);
并且可以使用,drawpixels->setPosition(),设置多张图片间的层次关系。

但是,这样加载的图片,无法实现旋转和缩放。(不知道是不是方法问题,试过很多种都不行)
于是,我就自己构建了几何体(设置顶点、纹理、法线等)。这种方式建立的节点可以独立显示,但是加载到HUD的摄像机中就看不到,我估计的坐标系的问题,但是没有找到什么解决的方法。

该用户从未签到

发表于 2010-10-29 08:23:23 | 显示全部楼层
drawPixels是一个已经被废弃很久的OpenGL函数,我不知道您为什么还在用它……
使用四边形几何体+纹理的方法才是正确的,并且只要设置了正确的投影矩阵和观察矩阵就可以看到;您不妨把相关的代码给出让大家帮您判断错误的所在

该用户从未签到

 楼主| 发表于 2010-10-29 10:51:17 | 显示全部楼层
drawPixels的方法是从《OpenSceneGraph三维渲染引擎设计与实践》P119绘制位图的例子中学到的!

现在我调整了一下代码,可以显示了。但是显示的效果比较暗,而且提示信息:
Scaling image 'desktop.png' from (1440,900) to (1024,1024)

我加载的图片是1440*900的,显示器分辨率也一样。 代码如下,请各位分析一下:
  1. // 创建一个四边形节点
  2. osg::ref_ptr<osg::Geode> createNode()
  3. {
  4.         osg::ref_ptr<osg::Geode> geode = new osg::Geode();

  5.         osg::ref_ptr<osg::Geometry> geom = new osg::Geometry();

  6.         //设置顶点
  7.         osg::ref_ptr<osg::Vec3Array> vc = new osg::Vec3Array();
  8.         vc->push_back(osg::Vec3(0.0f,        0.0f,        -1.0f));
  9.         vc->push_back(osg::Vec3(1440.0f,0.0f,        -1.0f));
  10.         vc->push_back(osg::Vec3(1440.0f,900.0f,        -1.0f));
  11.         vc->push_back(osg::Vec3(0.0f,        900.0f,        -1.0f));

  12.         geom->setVertexArray(vc.get());

  13.         //设置纹理坐标
  14.         osg::ref_ptr<osg::Vec2Array> vt = new osg::Vec2Array();
  15.         vt->push_back(osg::Vec2(0.0f,0.0f));
  16.         vt->push_back(osg::Vec2(1.0f,0.0f));
  17.         vt->push_back(osg::Vec2(1.0f,1.0f));
  18.         vt->push_back(osg::Vec2(0.0f,1.0f));

  19.         geom->setTexCoordArray(0,vt.get());

  20.         //设置法线
  21.         osg::ref_ptr<osg::Vec3Array> nc = new osg::Vec3Array();
  22.         nc->push_back(osg::Vec3(0.0f,1.0f,0.0f));
  23.        
  24.         geom->setNormalArray(nc.get());
  25.         geom->setNormalBinding(osg::Geometry::BIND_OVERALL);

  26.         //添加图元
  27.         geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4));

  28.         //绘制
  29.         geode->addDrawable(geom.get());

  30.         return geode.get();
  31. }

  32. //创建二维纹理状态对象
  33. osg::ref_ptr<osg::StateSet> createTexture2DState(osg::ref_ptr<osg::Image> image)
  34. {
  35.         //创建状态集对象
  36.         osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet();

  37.         //创建二维纹理对象
  38.         osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D();
  39.         texture->setDataVariance(osg::Object::DYNAMIC);

  40.         //设置贴图
  41.         texture->setImage(image.get());

  42.         stateset->setTextureAttributeAndModes(0,texture.get(),osg::StateAttribute::ON);

  43.         return stateset.get();
  44. }

  45. osg::ref_ptr<osg::Camera> createBackground(void)
  46. {
  47.         osg::ref_ptr<osg::Camera> camera = new osg::Camera;
  48.         camera->setProjectionMatrix(osg::Matrix::ortho2D(0,1440,0,900));
  49.         camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
  50.         camera->setViewMatrix(osg::Matrix::identity());
  51.         camera->setClearMask(GL_DEPTH_BUFFER_BIT);
  52.         camera->setRenderOrder(osg::Camera::POST_RENDER);
  53.     camera->setAllowEventFocus(false);
  54.         camera->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::ON);

  55.         osg::ref_ptr<osg::Image> image = osgDB::readImageFile("desktop.png");

  56.         //创建几何体
  57.         osg::ref_ptr<osg::Geode> geode = createNode();

  58.         //创建状态集对象
  59.         osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet();
  60.         stateset = createTexture2DState(image.get());

  61.         //使用二维纹理
  62.         geode->setStateSet(stateset.get());
  63.         geode->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);
  64.         geode->getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);

  65.         osg::ref_ptr<osg::PositionAttitudeTransform> pos = new osg::PositionAttitudeTransform;

  66.         pos->addChild(geode.get());
  67.         pos->setPosition(osg::Vec3(0,0,-1));

  68.         camera->addChild(pos.get());

  69.         return camera.get();
  70. }

  71. int main(void)
  72. {
  73.         osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;
  74.         osg::ref_ptr<osg::Group> root = new osg::Group;

  75.         //创建背景
  76.         root->addChild(createBackground());

  77.         viewer->addEventHandler(new osgViewer::StatsHandler);

  78.         viewer->setSceneData(root.get());
  79.         viewer->run();

  80.         return 0;
  81. }
复制代码
变暗应该是和体系信息相关,大小被强制变化造成。但是我看到的情况确实是满屏显示的,应该又没有拉伸!怪了……

该用户从未签到

 楼主| 发表于 2010-10-29 11:17:27 | 显示全部楼层
明暗的问题解决了,现在还剩那个提示了!

该用户从未签到

发表于 2010-10-29 17:13:21 | 显示全部楼层
OpenGL不能渲染尺寸不为2的幂次方的图片,因此在渲染之前必须进行一次放缩,即“Scaling image 'desktop.png' from (1440,900) to (1024,1024)”,这应该是最基本的知识之一了。并且您似乎完全不用担心图片大小和全屏显示的关系

该用户从未签到

 楼主| 发表于 2010-10-29 19:34:13 | 显示全部楼层
本帖最后由 aaa696 于 2010-10-29 19:38 编辑

哦,怎么连这个都忘了!我还以为是几何体构建的问题。
可是OpenGL把1440*900的图片缩放成1024*1024的大小,又把它投影到1440*900的屏幕。是不是有点绕了!不是特别理解,该补补OpenGL的课了。

该用户从未签到

发表于 2010-11-1 08:31:58 | 显示全部楼层
如果您的显卡足够好的话,也可以直接渲染非2的幂次方的纹理,这个时候可以设置texture->setResizeNonPowerOfTwoHint(false);

该用户从未签到

 楼主| 发表于 2010-11-1 08:54:19 | 显示全部楼层
谢谢,果然没有提示了,我的显卡是GTX260的, 呵呵!

该用户从未签到

 楼主| 发表于 2010-11-1 09:00:12 | 显示全部楼层
不过这个问题有衍生出另一个问题!
在构建几何体的时候,我可以通过调整顶点矩阵使其在我设置的投影矩阵中显示。
如果是加载外部模型(如osg,ive),我想光是调整模型矩阵是不够的,
那么应该使用视图变换还是修改投影变换,才能使加载的外部模型和先前的背景同时显示呢?

该用户从未签到

发表于 2010-11-1 14:41:53 | 显示全部楼层
改变投影变换矩阵就可以了,我想这没有什么难的?

该用户从未签到

 楼主| 发表于 2010-11-2 11:34:11 | 显示全部楼层
我将模型节点加到根节点可以正常显示,但是一挂到HUD的camera就看不到了,camera本身就是用了特殊正射投影camera->setProjectionMatrix(osg::Matrix:rtho2D(0,1440,0,900));。

那么我的模型应该使用哪种投影变换呢?正射投影、特殊正射投影、透视还是对称透视?
如果我将这个节点加载到HUD的摄像机,决定显示顺序的是位置深度还是渲染顺序(setRenderBinDetails)

该用户从未签到

 楼主| 发表于 2010-11-2 11:49:14 | 显示全部楼层
以上投影变换我都试过了,还是在HUD里看不到!我就加载了一个COW.OSG

该用户从未签到

发表于 2010-11-2 12:34:35 | 显示全部楼层
这些都不是决定因素,您的投影矩阵的left/right-bottom/top能否和模型的位置对应起来,这才是关键

该用户从未签到

 楼主| 发表于 2010-11-2 15:37:54 | 显示全部楼层
通过Viewer类的三角形数量属性显示,可以知道就在VIEW中,但是不在CAMERA中,我用鼠标放大,终于看到CAMERA中的三角形数量变了,说明进入了摄像机,但是就是看不到,继续放大就三角形就消失了!

有没有渐变的方式,让我知道要怎样设置模型矩阵以配合投影矩阵。比如我的HUD是这样设置的:
camera->setProjectionMatrix(osg::Matrix:rtho2D(0,1440,0,900));

要把COW.OSG放在这个camera上,应该怎么设置呢?有什么更简洁的方法吗?我调了很久的PositionAttitudeTransform,还是没戏!

该用户从未签到

 楼主| 发表于 2010-11-2 15:44:11 | 显示全部楼层
OSG中有没有比较智能的方式使模型自动对应投影矩阵,不然实在是个麻烦事!

该用户从未签到

 楼主| 发表于 2010-11-2 16:24:12 | 显示全部楼层
终于看到了,但是看不到贴图!一片黑
变换代码如下:
pos->setPosition(osg::Vec3(500,500,0));
pos->setScale(osg::Vec3(100,100,100));
pos->setAttitude(osg:uat(-osg:I_2,0,0,1));

如果每个模型都这样调试,人都会疯的!

该用户从未签到

发表于 2010-11-2 16:55:41 | 显示全部楼层
18# aaa696

将观察矩阵与投影矩阵配合使用,如果观察一个单独的物体的话,通常可以设置观察点在物体中心,而投影矩阵的left/right/bottom/top与物体的包围体大小直接相关(例如(-width/2, -height/2) - (width/2, height/2)),我想不出这有什么可疯的

该用户从未签到

 楼主| 发表于 2010-11-2 20:29:33 | 显示全部楼层
本帖最后由 aaa696 于 2010-11-3 08:48 编辑

呵呵,终于看到贴图了,谢谢Array!
不过你说的width和height是预先知道的呢,还是通过包围体算出来的,比如:
node->getBound().radius()。
虽说是看到贴图,但是看起来和原来的有点不同。不知是什么原因!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

OSG中国官方论坛-有您OSG在中国才更好

网站简介:osgChina是国内首个三维相关技术开源社区,旨在为国内更多的技术开发人员提供最前沿的技术资讯,为更多的三维从业者提供一个学习、交流的技术平台。

联系我们

  • 工作时间:09:00--18:00
  • 反馈邮箱:1315785073@qq.com
快速回复 返回顶部 返回列表