[osg-users] Render to osg::TextureRectangle fails?
Philipp Meyer
philipp.meyer at fh-bielefeld.de
Tue Jun 28 02:34:03 PDT 2016
Hi,
im using several RTT Cameras in my scene. So far, I have only rendered to osg::Texture2D and that worked fine, however, I need to render to NPOD textures now so that will no longer work.
For that, I changed my render target to a osg::TextureRectangle and left everything else pretty much unchanged. I'm displaying the texture using a custom QUAD.
Unfortunately I only see a black texture when using TextureRectangle instead of Texture2D. I checked the osg prerender example and noticed that I need to use un-normalized texture coordinates for my QUAD in this case, however, to my own surprise that didn't fix the issue either.
Does anyone have an idea whats wrong?
Some relevant code bits:
Texture creation:
Code:
osg::ref_ptr<osg::Texture> osgHelper::createDefaultRttTexture(int width,
int height, GLenum sourceFormat, GLenum sourceType,
GLint internalFormat) {
osg::ref_ptr<osg::Texture> tex;
auto texImg = osgHelper::make_osgref<osg::Image>();
texImg->setInternalTextureFormat(internalFormat);
texImg->allocateImage(width, height, 1, sourceFormat, sourceType);
if (isPowerOfTwo(width) && isPowerOfTwo(height)) {
auto specTex = make_osgref<osg::Texture2D>();
specTex->setTextureSize(width, height);
specTex->setImage(texImg);
tex = specTex;
} else {
auto specTex = make_osgref<osg::TextureRectangle>();
specTex->setTextureSize(width, height);
specTex->setImage(texImg);
tex = specTex;
}
tex->setInternalFormat(internalFormat);
tex->setSourceFormat(sourceFormat);
tex->setSourceType(sourceType);
tex->setFilter(osg::Texture::FilterParameter::MIN_FILTER,
osg::Texture::FilterMode::NEAREST);
tex->setFilter(osg::Texture::FilterParameter::MAG_FILTER,
osg::Texture::FilterMode::NEAREST);
tex->setDataVariance(osg::Object::DYNAMIC);
tex->setMaxAnisotropy(0);
return tex;
}
RTT Camera setup:
Code:
RTTCamera::RTTCamera(osg::Texture *dest, osg::Viewport *vp) :
osg::Camera() {
// set clear the color and depth buffer
this->setClearColor(osg::Vec4(1, 0, 0, 1));
//matrices get set properly later.
setProjectionMatrix(osg::Matrix::identity());
setViewMatrix(osg::Matrix::identity());
setComputeNearFarMode(ComputeNearFarMode::DO_NOT_COMPUTE_NEAR_FAR);
// set viewport
this->setViewport(vp);
// set the camera to render before the main camera.
this->setRenderOrder(osg::Camera::RenderOrder::PRE_RENDER);
// tell the camera to use OpenGL frame buffer object where supported.
this->setRenderTargetImplementation(osg::Camera::RenderTargetImplementation::FRAME_BUFFER_OBJECT);
// attach the texture and use it as the color buffer.
this->attach(osg::Camera::COLOR_BUFFER0, dest);
}
Texture display:
Code:
TextureView::TextureView() {
setViewMatrix(osg::Matrix::identity());
setProjectionMatrix(osg::Matrix::ortho2D(0, 1, 0, 1));
setClearColor(osg::Vec4(1, 0, 0, 1));
auto mt = osgHelper::make_osgref<osg::MatrixTransform>();
mt->setMatrix(osg::Matrix::identity());
mt->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
addChild(mt);
auto geode = osgHelper::make_osgref<osg::Geode>();
geometry = osgHelper::make_osgref<osg::Geometry>();
geode->addDrawable(geometry);
mt->addChild(geode);
auto quadVertices = osgHelper::make_osgref<osg::Vec3Array>();
quadVertices->push_back(osg::Vec3(0, 0, 0));
quadVertices->push_back(osg::Vec3(1, 0, 0));
quadVertices->push_back(osg::Vec3(1, 1, 0));
quadVertices->push_back(osg::Vec3(0, 1, 0));
geometry->setVertexArray(quadVertices);
auto quadPrimitiveSet = osgHelper::make_osgref<osg::DrawElementsUInt>(
osg::PrimitiveSet::QUADS, 0);
quadPrimitiveSet->push_back(0);
quadPrimitiveSet->push_back(1);
quadPrimitiveSet->push_back(2);
quadPrimitiveSet->push_back(3);
geometry->addPrimitiveSet(quadPrimitiveSet);
auto texCoords = osgHelper::make_osgref<osg::Vec2Array>();
texCoords->push_back(osg::Vec2(0, 0));
texCoords->push_back(osg::Vec2(1, 0));
texCoords->push_back(osg::Vec2(1, 1));
texCoords->push_back(osg::Vec2(0, 1));
geometry->setTexCoordArray(0, texCoords, osg::Array::BIND_PER_VERTEX);
auto ss = geode->getOrCreateStateSet();
auto program = osgHelper::make_osgref<osg::Program>();
auto vertShader = osg::Shader::readShaderFile(osg::Shader::Type::VERTEX,
"res/CustomShaders/FrameHeader.vert");
auto fragShader = osg::Shader::readShaderFile(osg::Shader::Type::FRAGMENT,
"res/CustomShaders/FrameHeader.frag");
if (!vertShader || !fragShader) {
throw MDRTExceptionBase("error loading textureview shaders");
}
bool ok = true;
ok = ok && program->addShader(vertShader);
ok = ok && program->addShader(fragShader);
if (!ok) {
throw MDRTExceptionBase(
"error adding textureview shaders to program obj");
}
ss->setAttributeAndModes(program);
ss->getOrCreateUniform("tex", osg::Uniform::Type::SAMPLER_2D, 0);
}
TextureView::~TextureView() {
// TODO Auto-generated destructor stub
}
void TextureView::setTexture(osg::Texture* tex) {
auto texRec = dynamic_cast<osg::TextureRectangle*>(tex);
if (texRec) {
auto texWidth = texRec->getImage()->s();
auto texHeight = texRec->getImage()->t();
auto texCoords = osgHelper::make_osgref<osg::Vec2Array>();
texCoords->push_back(osg::Vec2(0, 0));
texCoords->push_back(osg::Vec2(1 * texWidth, 0));
texCoords->push_back(osg::Vec2(1 * texWidth, 1 * texHeight));
texCoords->push_back(osg::Vec2(0, 1 * texHeight));
geometry->setTexCoordArray(0, texCoords, osg::Array::BIND_PER_VERTEX);
geometry->dirtyDisplayList();
}
geometry->getOrCreateStateSet()->setTextureAttributeAndModes(0, tex);
}
Thank you!
Cheers,
Philipp
------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=67873#67873
More information about the osg-users
mailing list