我使用OSG渲染点云。我按照OSG食谱中的示例标题为“使用绘图实例渲染点云数据”,该示例显示了如何使用多个实例创建一个点,然后通过纹理将点位置传输到图形卡。然后,它使用着色器将点拉出纹理,并将每个实例移动到正确的位置。渲染的内容似乎有两个问题。
首先,与更直接,更有效的渲染方法相比,这些点不在正确的位置。看起来它们大致从零错误缩放,在位置上有某种乘法因子。
其次,图像模糊。积分通常在正确的位置;在一个大物体应该有的地方有很多点。但是,我分不清对象是什么。使用我的工作(但速度较慢)渲染方法渲染的数据看起来很清晰。
我已经确认我在两种方法中都有相同的输入数据进入纹理和绘制列表,所以看起来它必须是渲染的东西。
以下是设置Geometry的代码,该代码几乎直接从教科书中复制过来。
osg::Geometry* geo = new osg::Geometry;
osg::ref_ptr<osg::Image> img = new osg::Image;
img->allocateImage(w,h, 1, GL_RGBA, GL_FLOAT);
osg::BoundingBox box;
float* data = (float*)img->data();
for (unsigned long int k=0; k<NPoints; k++)
{
*(data++) = cloud->x[k];
*(data++) = cloud->y[k];
*(data++) = cloud->z[k];
*(data++) = cloud->meta[0][k];
box.expandBy(cloud->x[k],cloud->y[k],cloud->z[k]);
}
geo->setUseDisplayList(false);
geo->setUseVertexBufferObjects(true);
geo->setVertexArray( new osg::Vec3Array(1));
geo->addPrimitiveSet( new osg::DrawArrays(GL_POINTS, 0, 1, stop) );
geo->setInitialBound(box);
osg::ref_ptr<osg::Texture2D> tex = new osg::Texture2D;
tex->setImage( img);
tex->setInternalFormat( GL_RGBA32F_ARB );
tex->setFilter( osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR);
tex->setFilter( osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR);
这是着色器代码。
void main () {
float row;
row = float(gl_InstanceID) / float(width);
vec2 uv = vec2( fract(row), floor(row) / float(height) );
vec4 texValue = texture2D(defaultTex,uv);
vec4 pos = gl_Vertex + vec4(texValue.xyz, 1.0);
gl_Position = gl_ModelViewProjectionMatrix * pos;
}
答案 0 :(得分:1)
经过一系列的实验,我发现OSG Cookbook的示例代码存在一些问题。
比例问题(第一个问题)在着色器中。
vec4 pos = gl_Vertex + vec4(texValue.xyz, 1.0);
应该是
vec4 pos = gl_Vertex + vec4(texValue.xyz, 0.0);
这是因为gl_Vertex是一个3向量,带有额外的1个元素以辅助矩阵变换。该元素应始终为1.该示例创建了另一个3 + 1向量并将其添加到gl_Vertex,使其成为2.将1替换为零,并且缩放问题消失。
模糊(第二个问题)是由纹理插值引起的。
tex->setFilter( osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR);
tex->setFilter( osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR);
需要
tex->setFilter( osg::Texture2D::MIN_FILTER, osg::Texture2D::NEAREST);
tex->setFilter( osg::Texture2D::MAG_FILTER, osg::Texture2D::NEAREST);
以便插值器只取纹理中的值而不是从相邻纹理像素中插入它们,相邻纹理像素可能是点云另一侧的点。在解决了这两个问题后,该示例的工作方式与广告一样,在我的有限测试中似乎更快一些。