OpenSceneGraph浮动图像
OpenSceneGraph float Image
使用C++和OSG,我试图将浮动纹理上传到着色器,但不知何故,它似乎不起作用。最后,我发布了部分代码。主要问题是如何使用浮点数组中的数据创建osg::Image对象。在OpenGL中,所需的代码是
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE32F_ARB, width, height, 0,
GL_LUMINANCE, GL_FLOAT, data);
但在这种情况下,我必须使用OSG。
使用时代码运行良好
Image* image = osgDB::readImageFile("someImage.jpg");
而不是
image = new Image;
但我需要上传生成的浮点数据。也不可能切换到无符号字符数组,因为我需要着色器代码中的GL_LUMINANCE32F_ARB数据范围。
我希望有人能在这里帮助我,因为谷歌无法帮助我(谷歌搜索了例如:osg浮动图像)。这是我的代码。
using namespace std;
using namespace osg;
//...
float* data = new float[width*height];
fill_n(data, size, 1.0); // << I actually do this for testing purposes
Texture2D* texture = new Texture2D;
Image* image = new Image;
osg::State* state = new osg::State;
Uniform* uniform = new Uniform(Uniform::SAMPLER_2D, "texUniform");
texture->setInternalFormat(GL_LUMINANCE32F_ARB);
texture->setDataVariance(osg::Object::DYNAMIC);
texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR);
texture->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR);
texture->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::CLAMP_TO_EDGE);
texture->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::CLAMP_TO_EDGE);
if (data == NULL)
cout << "texdata null" << endl; // << this is not printed
image->setImage(width, height, 1, GL_LUMINANCE32F_ARB,
GL_LUMINANCE, GL_FLOAT,
(unsigned char*)data, osg::Image::USE_NEW_DELETE);
if (image->getDataPointer() == NULL)
cout << "datapointernull" << endl; // << this is printed
if (!image->valid())
exit(1); // << here the code exits (hard exit just for testing purposes)
osgDB::writeImageFile(*image, "blah.png");
texture->setInternalFormat(GL_LUMINANCE32F_ARB);
texture->setImage(image);
camera->getOrCreateStateSet()->setTextureAttributeAndModes(4, texture);
state->setActiveTextureUnit(4);
texture->apply(*state);
uniform->set(4);
addProgrammUniform(uniform);
我在网上找到了另一种方法,让osg::Image创建数据,然后填充。但不知何故,这也不起作用。我在新XYZ之后插入了这个;线
image->setInternalTextureFormat(GL_LUMINANCE32F_ARB);
image->allocateImage(width,height,1,GL_LUMINANCE,GL_FLOAT);
if (image->data() == NULL)
cout << "null here?!" << endl; // << this is printed.
我使用以下(简化的)代码来创建和设置浮点纹理:
// Create texture and image
osg::Texture* texture = new osg::Texture2D;
osg::Image* image = new osg::Image();
image->allocateImage(size, size, 1, GL_LUMINANCE, GL_FLOAT);
texture->setInternalFormat(GL_LUMINANCE32F_ARB);
texture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
texture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
texture->setImage(image);
// Set texture to node
osg::StateSet* stateSet = node->getOrCreateStateSet();
stateSet->setTextureAttributeAndModes(TEXTURE_UNIT_NUMBER, texture);
// Set data
float* data = reinterpret_cast<float*>(image->data());
/* ...data processing... */
image->dirty();
您可能想要更改一些参数,但这应该会给您一个开始。我认为在您的情况下,TEXTURE_UNIT_NUMBER
应该设置为4。
但我需要上传生成的浮点数据。也不可能切换到无符号字符数组,因为我需要着色器代码中的GL_LUMINANCE32F_ARB数据范围。
osgDB::writeImageFile(*image, "blah.png");
png文件不支持每通道32位的数据,所以不能用这种方式将纹理写入文件。参见libpng书籍:
PNG灰度图像支持任何图像类型中最宽范围的像素深度。支持1、2、4、8和16位的深度,涵盖从简单的黑白扫描到全深度医学和原始天文图像的所有内容。[63]
[63]校准的天文图像数据通常存储为32位或64位浮点值,一些原始数据表示为32位整数。PNG直接支持这两种格式,尽管原则上可以设计一个辅助块来保存正确的转换信息。然而,转换动态范围超过16位的数据将是一种有损的转换——至少,除非滥用PNG的alpha通道或RGB功能。
对于每个通道32位,请查看OpenEXR格式。
然而,如果16位浮点(即半浮点)就足够了,那么你可以这样做:
osg::ref_ptr<osg::Image> heightImage = new osg::Image;
int pixelFormat = GL_LUMINANCE;
int type = GL_HALF_FLOAT;
heightImage->allocateImage(tex_width, tex_height, 1, pixelFormat, type);
现在,要真正使用和编写半浮点,可以使用GLM库。您可以通过包含<glm/detail/type_half.hpp>
来获得半浮点类型,然后将其称为hdata
。您现在需要从图像中获取数据指针,并将其转换为所述格式:
glm::detail::hdata *data = reinterpret_cast<glm::detail::hdata*>(heightImage->data());
然后你可以像访问一维数组一样访问它,例如
data[currentRow*tex_width+ currentColumn] = glm::detail::toFloat16(3.1415f);
并不是说,如果您将相同的数据写入bmp
或tif
文件(使用osg插件),结果将是不正确的。在我的例子中,我只是将预期图像的左半部分拉伸到全宽,而不是灰度,而是一些奇怪的颜色编码。
- C++,OpenCV,尝试显示图像时"OpenCV(4.3.0) Error: Assertion failed (size.width>0 && size.height>0)"此错误
- 如何使用OpenCV将RBG图像转换为HSV,并将H、S和V值保存为C++中的3个独立图像
- OpenCV EqualizeHist()从彩色图像创建黑白图像
- 将"打开的CV图像"中的"颜色"转换为整数格式
- 平均图像时图像损坏
- 在C++中使用GDAL可以将图像的像素坐标转换为lat,long吗
- 如何将图像传输到c++(dll)中的缓冲区,然后在c#的缓冲区中读/写
- Vulkan验证层不断在VkQueuePresentKHR()上抛出图像布局错误
- 使用FFMPEG将RGB图像序列保存到.mp4时出现问题
- 将RGB图像保存为PPM格式
- 将图像添加到资源文件夹UWP C++
- 彩色图像的卤化物处理平均值
- C++射线示踪剂ppm表示没有足够的数据来显示图像
- 重新定位图像时如何前进到下一个内存块
- 如何使用按钮更新GTK3图像以使用C++从相机捕获图片
- 为什么 BMP 图像上的 imwrite 会卡住/不返回?
- Gstreamer:每 5 秒使用多文件墨水保存图像/jpeg
- 如何使用CImg打开图像?
- 如何使用 OpenCV 解码在两个 UWP 应用之间发送的图像字节?
- 使用 CUDA 和纹理进行图像减法