2016-11-08 35 views
0

我正在使用OSG渲染點雲。我遵循OSG食譜中的例子,題爲「繪製實例化渲染點雲數據」,演示如何使用多個實例創建一個點,然後通過紋理將點位置傳輸到圖形卡。然後使用着色器將紋理拖出紋理,並將每個實例移動到正確的位置。呈現內容似乎有兩個問題。從OSG Cookbook不能正常工作的繪製實例渲染點雲數據

首先,與比較直接的工作方法相比,點不在正確的位置。它看起來像是從零錯誤大致縮放,某種位置乘法因素。

二,圖像模糊。積分一般都在正確的地方;在大型物體應該存在的地方有很多點。但是,我不能說出什麼是對象。用我的工作(但速度較慢)呈現方法呈現的數據看起來很清晰。

我已經驗證過,我在兩種方法中都有相同的輸入數據進入紋理和繪圖列表,所以它似乎必須是渲染的東西。

下面是設置幾何直接從教科書中複製的幾何代碼。

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

經過一番試驗後,我發現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); 

,以便插器將只取值從質地,而不是從它可以是對點雲的另一邊點周邊的紋理像素插值他們。解決了這兩個問題之後,該示例就像廣告一樣工作,在我的有限測試中似乎更快一些。