From Jose Delport, a MRT example implementing stereo matching.
This commit is contained in:
parent
9cec69981d
commit
98a2289a59
@ -84,6 +84,7 @@ IF(DYNAMIC_OPENSCENEGRAPH)
|
||||
ADD_SUBDIRECTORY(osgspheresegment)
|
||||
ADD_SUBDIRECTORY(osgspotlight)
|
||||
ADD_SUBDIRECTORY(osgstereoimage)
|
||||
ADD_SUBDIRECTORY(osgstereomatch)
|
||||
ADD_SUBDIRECTORY(osgteapot)
|
||||
ADD_SUBDIRECTORY(osgterrain)
|
||||
ADD_SUBDIRECTORY(osgtessellate)#)
|
||||
|
13
examples/osgstereomatch/CMakeLists.txt
Normal file
13
examples/osgstereomatch/CMakeLists.txt
Normal file
@ -0,0 +1,13 @@
|
||||
SET(TARGET_SRC
|
||||
StereoPass.cpp
|
||||
StereoMultipass.cpp
|
||||
osgstereomatch.cpp
|
||||
)
|
||||
|
||||
SET(TARGET_H
|
||||
StereoPass.h
|
||||
StereoMultipass.h
|
||||
)
|
||||
|
||||
#### end var setup ###
|
||||
SETUP_EXAMPLE(osgstereomatch)
|
62
examples/osgstereomatch/README.txt
Normal file
62
examples/osgstereomatch/README.txt
Normal file
@ -0,0 +1,62 @@
|
||||
The osgstereomatch example illustrates how multiple render passes and multiple render targets on the GPU can be used in stereo vision disparity map calculation.
|
||||
|
||||
A simple algorithm is implemented in both a single- and multi-pass way to show the differences in speed of execution.
|
||||
|
||||
The normal osgviewer is used for display and one can obtain the time spent on the GPU by pressing the "s" key twice.
|
||||
|
||||
The sample data was downloaded from the Middlebury Stereo Vision Page at http://vision.middlebury.edu/stereo/
|
||||
|
||||
Usage examples:
|
||||
---------------
|
||||
|
||||
osgstereomatch --left tsukubaL.png --right tsukubaR.png --min 0 --max 15 --window 5
|
||||
osgstereomatch --left tsukubaL.png --right tsukubaR.png --min 0 --max 15 --window 5 --single
|
||||
osgstereomatch --left teddyL.png --right teddyR.png --min 10 --max 57 --window 7
|
||||
|
||||
|
||||
Algorithm and implementation details:
|
||||
-------------------------------------
|
||||
The algorithm uses the sum of absolute differences between pixels (often referred to as SAD in the literature) to find matching areas in the left and right stereo images. The algorithm is definitely not state of the art, but illustrates stereo matching concepts.
|
||||
|
||||
The algorithm assumes that the input images are already rectified and undistorted.
|
||||
|
||||
Inputs to the algorithm are:
|
||||
* Window size -- The size (width and height) of a rectangular window around the current pixel that is used for comparison.
|
||||
* Minimum disparity -- The minimum pixel offset at which to start searching for matching areas in the right image.
|
||||
* Maximum disparity -- The maximum pixel offset at which to stop searching for matching areas in the right image.
|
||||
|
||||
The offsets can be visualised as shifting the right stereo image to the right by the specified number of pixels.
|
||||
|
||||
The following pseudo-code describes the algorithm:
|
||||
for every pixel in the left image:
|
||||
for the complete range of disparity values:
|
||||
pixel-wise sum the absolute differences between the left and right windows
|
||||
(the right window is shifted by the current disparity value evaluated)
|
||||
store the disparity value where the sum is the smallest
|
||||
assign the stored disparity value to the disparity image pixel
|
||||
|
||||
The algorithm was implemented using GLSL shaders. Two implementation of the algorithm was created to compare the execution speed using two different approaches. The first version uses a single shader and a single rendering pass, while the second approach utilises several shaders and rendering passes to create a disparity image.
|
||||
|
||||
Single Pass
|
||||
-----------
|
||||
|
||||
The single pass algorithm implements the pseudo-code directly as presented earlier. The code for the algorithm can be found in the ``stereopass.frag'' source file.
|
||||
|
||||
Multiple Pass
|
||||
-------------
|
||||
|
||||
The single pass algorithm often re-computes the same absolute differences between left and right image pixels. For example, when shifting a 3x3 window one pixel horizontally, 6 absolute difference values would be recomputed. In the multi-pass algorithm, the absolute differences between pixels are pre-computed before doing the summation over a window.
|
||||
|
||||
The algorithm consists of 4 passes:
|
||||
|
||||
1) Clear pass -- Two floating point textures are created for storing the minimum sum (SAD) and best disparity value calculated so far (called disparity textures in the following discussion). The minimum sum is stored in the first channel of the images and the best disparity is stored in the second channel. Two textures are needed, because shaders cannot read and write to the same texture during calculation. One texture is used as input and the other as output. After a calculation, the input and output textures are swapped. The technique is known as ping-ponging or flip-flopping the textures. The clear pass initialises the two textures. The code can be found in ``clear.frag''.
|
||||
|
||||
2) Subtract pass -- Sixteen disparity values are considered and the shifted right image is subtracted from the left image. The absolute difference of the pixel values are stored in one of the four channels of one of four output images. The multiple render target (MRT) capabilities of modern graphics cards are utilised during this pass. The code can be found in ``subtract.frag''.
|
||||
|
||||
3) Aggregate pass -- The sixteen images generated during the subtract pass is used as input for this pass. For each of the images, a sum over the window centered at the current output pixel is computed and stored. The minimum sum of the sixteen images is then compared with the lowest sum calculated during previous passes (read from the input disparity texture). If it is lower, the output disparity texture is updated with the new sum and the new disparity value, if not, the old values are copied. The code can be found in ``aggregate.frag''.
|
||||
|
||||
4) Select pass -- The final disparity texture contains the best disparity value found in the second (green) channel. This pass merely copies the second channel to all the colour channels of the output image. The code can be found in ``select.frag''.
|
||||
|
||||
The subtract and aggregate passes are executed multiple times to cover the complete requested disparity range. Disparity range divided by 16 combinations of these passes are needed. Despite the apparent complexity of the algorithm, it executes faster than the single pass algorithm.
|
||||
|
||||
J.P. Delport 2008/04
|
541
examples/osgstereomatch/StereoMultipass.cpp
Normal file
541
examples/osgstereomatch/StereoMultipass.cpp
Normal file
@ -0,0 +1,541 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||
|
||||
/* OpenSceneGraph example, osgstereomatch.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "StereoMultipass.h"
|
||||
#include <osgDB/FileUtils>
|
||||
#include <iostream>
|
||||
|
||||
SubtractPass::SubtractPass(osg::TextureRectangle *left_tex,
|
||||
osg::TextureRectangle *right_tex,
|
||||
int width, int height,
|
||||
int start_disparity) :
|
||||
_TextureWidth(width),
|
||||
_TextureHeight(height),
|
||||
_StartDisparity(start_disparity)
|
||||
{
|
||||
_RootGroup = new osg::Group;
|
||||
_InTextureLeft = left_tex;
|
||||
_InTextureRight = right_tex;
|
||||
|
||||
createOutputTextures();
|
||||
|
||||
_Camera = new osg::Camera;
|
||||
setupCamera();
|
||||
_Camera->addChild(createTexturedQuad().get());
|
||||
|
||||
_RootGroup->addChild(_Camera.get());
|
||||
|
||||
setShader("shaders/stereomatch_subtract.frag");
|
||||
}
|
||||
|
||||
SubtractPass::~SubtractPass()
|
||||
{
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Group> SubtractPass::createTexturedQuad()
|
||||
{
|
||||
osg::ref_ptr<osg::Group> top_group = new osg::Group;
|
||||
|
||||
osg::ref_ptr<osg::Geode> quad_geode = new osg::Geode;
|
||||
|
||||
osg::ref_ptr<osg::Vec3Array> quad_coords = new osg::Vec3Array; // vertex coords
|
||||
// counter-clockwise
|
||||
quad_coords->push_back(osg::Vec3d(0, 0, -1));
|
||||
quad_coords->push_back(osg::Vec3d(1, 0, -1));
|
||||
quad_coords->push_back(osg::Vec3d(1, 1, -1));
|
||||
quad_coords->push_back(osg::Vec3d(0, 1, -1));
|
||||
|
||||
osg::ref_ptr<osg::Vec2Array> quad_tcoords = new osg::Vec2Array; // texture coords
|
||||
quad_tcoords->push_back(osg::Vec2(0, 0));
|
||||
quad_tcoords->push_back(osg::Vec2(_TextureWidth, 0));
|
||||
quad_tcoords->push_back(osg::Vec2(_TextureWidth, _TextureHeight));
|
||||
quad_tcoords->push_back(osg::Vec2(0, _TextureHeight));
|
||||
|
||||
osg::ref_ptr<osg::Geometry> quad_geom = new osg::Geometry;
|
||||
osg::ref_ptr<osg::DrawArrays> quad_da = new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4);
|
||||
|
||||
osg::ref_ptr<osg::Vec4Array> quad_colors = new osg::Vec4Array;
|
||||
quad_colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
|
||||
|
||||
quad_geom->setVertexArray(quad_coords.get());
|
||||
quad_geom->setTexCoordArray(0, quad_tcoords.get());
|
||||
quad_geom->addPrimitiveSet(quad_da.get());
|
||||
quad_geom->setColorArray(quad_colors.get());
|
||||
quad_geom->setColorBinding(osg::Geometry::BIND_OVERALL);
|
||||
|
||||
_StateSet = quad_geom->getOrCreateStateSet();
|
||||
_StateSet->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
|
||||
_StateSet->setTextureAttributeAndModes(0, _InTextureLeft.get(), osg::StateAttribute::ON);
|
||||
_StateSet->setTextureAttributeAndModes(1, _InTextureRight.get(), osg::StateAttribute::ON);
|
||||
|
||||
_StateSet->addUniform(new osg::Uniform("textureLeft", 0));
|
||||
_StateSet->addUniform(new osg::Uniform("textureRight", 1));
|
||||
_StateSet->addUniform(new osg::Uniform("start_disparity", _StartDisparity));
|
||||
|
||||
quad_geode->addDrawable(quad_geom.get());
|
||||
|
||||
top_group->addChild(quad_geode.get());
|
||||
|
||||
return top_group;
|
||||
}
|
||||
|
||||
void SubtractPass::setupCamera()
|
||||
{
|
||||
// clearing
|
||||
_Camera->setClearColor(osg::Vec4(0.1f,0.1f,0.3f,1.0f));
|
||||
_Camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// projection and view
|
||||
_Camera->setProjectionMatrix(osg::Matrix::ortho2D(0,1,0,1));
|
||||
_Camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
|
||||
_Camera->setViewMatrix(osg::Matrix::identity());
|
||||
|
||||
// viewport
|
||||
_Camera->setViewport(0, 0, _TextureWidth, _TextureHeight);
|
||||
|
||||
_Camera->setRenderOrder(osg::Camera::PRE_RENDER);
|
||||
_Camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
|
||||
|
||||
// attach the 4 textures
|
||||
for (int i=0; i<4; i++) {
|
||||
_Camera->attach(osg::Camera::BufferComponent(osg::Camera::COLOR_BUFFER0+i), _OutTexture[i].get());
|
||||
}
|
||||
}
|
||||
|
||||
void SubtractPass::createOutputTextures()
|
||||
{
|
||||
for (int i=0; i<4; i++) {
|
||||
_OutTexture[i] = new osg::TextureRectangle;
|
||||
|
||||
_OutTexture[i]->setTextureSize(_TextureWidth, _TextureHeight);
|
||||
_OutTexture[i]->setInternalFormat(GL_RGBA);
|
||||
_OutTexture[i]->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
|
||||
_OutTexture[i]->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
|
||||
}
|
||||
}
|
||||
|
||||
void SubtractPass::setShader(std::string filename)
|
||||
{
|
||||
osg::ref_ptr<osg::Shader> fshader = new osg::Shader( osg::Shader::FRAGMENT );
|
||||
fshader->loadShaderSourceFromFile(osgDB::findDataFile(filename));
|
||||
|
||||
_FragmentProgram = 0;
|
||||
_FragmentProgram = new osg::Program;
|
||||
|
||||
_FragmentProgram->addShader(fshader.get());
|
||||
|
||||
_StateSet->setAttributeAndModes(_FragmentProgram.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE );
|
||||
}
|
||||
|
||||
//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
|
||||
AggregatePass::AggregatePass(osg::TextureRectangle *diff_tex0,
|
||||
osg::TextureRectangle *diff_tex1,
|
||||
osg::TextureRectangle *diff_tex2,
|
||||
osg::TextureRectangle *diff_tex3,
|
||||
osg::TextureRectangle *agg_tex_in,
|
||||
osg::TextureRectangle *agg_tex_out,
|
||||
int width, int height,
|
||||
int start_disparity, int window_size):
|
||||
_TextureWidth(width),
|
||||
_TextureHeight(height),
|
||||
_StartDisparity(start_disparity),
|
||||
_WindowSize(window_size)
|
||||
{
|
||||
_RootGroup = new osg::Group;
|
||||
|
||||
_InTextureDifference[0] = diff_tex0;
|
||||
_InTextureDifference[1] = diff_tex1;
|
||||
_InTextureDifference[2] = diff_tex2;
|
||||
_InTextureDifference[3] = diff_tex3;
|
||||
|
||||
_InTextureAggregate = agg_tex_in;
|
||||
_OutTextureAggregate = agg_tex_out;
|
||||
|
||||
_OutTexture = _OutTextureAggregate;
|
||||
|
||||
_Camera = new osg::Camera;
|
||||
setupCamera();
|
||||
_Camera->addChild(createTexturedQuad().get());
|
||||
|
||||
_RootGroup->addChild(_Camera.get());
|
||||
|
||||
setShader("shaders/stereomatch_aggregate.frag");
|
||||
|
||||
}
|
||||
|
||||
AggregatePass::~AggregatePass()
|
||||
{
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Group> AggregatePass::createTexturedQuad()
|
||||
{
|
||||
osg::ref_ptr<osg::Group> top_group = new osg::Group;
|
||||
|
||||
osg::ref_ptr<osg::Geode> quad_geode = new osg::Geode;
|
||||
|
||||
osg::ref_ptr<osg::Vec3Array> quad_coords = new osg::Vec3Array; // vertex coords
|
||||
// counter-clockwise
|
||||
quad_coords->push_back(osg::Vec3d(0, 0, -1));
|
||||
quad_coords->push_back(osg::Vec3d(1, 0, -1));
|
||||
quad_coords->push_back(osg::Vec3d(1, 1, -1));
|
||||
quad_coords->push_back(osg::Vec3d(0, 1, -1));
|
||||
|
||||
osg::ref_ptr<osg::Vec2Array> quad_tcoords = new osg::Vec2Array; // texture coords
|
||||
quad_tcoords->push_back(osg::Vec2(0, 0));
|
||||
quad_tcoords->push_back(osg::Vec2(_TextureWidth, 0));
|
||||
quad_tcoords->push_back(osg::Vec2(_TextureWidth, _TextureHeight));
|
||||
quad_tcoords->push_back(osg::Vec2(0, _TextureHeight));
|
||||
|
||||
osg::ref_ptr<osg::Geometry> quad_geom = new osg::Geometry;
|
||||
osg::ref_ptr<osg::DrawArrays> quad_da = new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4);
|
||||
|
||||
osg::ref_ptr<osg::Vec4Array> quad_colors = new osg::Vec4Array;
|
||||
quad_colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
|
||||
|
||||
quad_geom->setVertexArray(quad_coords.get());
|
||||
quad_geom->setTexCoordArray(0, quad_tcoords.get());
|
||||
quad_geom->addPrimitiveSet(quad_da.get());
|
||||
quad_geom->setColorArray(quad_colors.get());
|
||||
quad_geom->setColorBinding(osg::Geometry::BIND_OVERALL);
|
||||
|
||||
_StateSet = quad_geom->getOrCreateStateSet();
|
||||
_StateSet->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
|
||||
_StateSet->setTextureAttributeAndModes(0, _InTextureDifference[0].get(), osg::StateAttribute::ON);
|
||||
_StateSet->setTextureAttributeAndModes(1, _InTextureDifference[1].get(), osg::StateAttribute::ON);
|
||||
_StateSet->setTextureAttributeAndModes(2, _InTextureDifference[2].get(), osg::StateAttribute::ON);
|
||||
_StateSet->setTextureAttributeAndModes(3, _InTextureDifference[3].get(), osg::StateAttribute::ON);
|
||||
_StateSet->setTextureAttributeAndModes(4, _InTextureAggregate.get(), osg::StateAttribute::ON);
|
||||
|
||||
_StateSet->addUniform(new osg::Uniform("textureDiff0", 0));
|
||||
_StateSet->addUniform(new osg::Uniform("textureDiff1", 1));
|
||||
_StateSet->addUniform(new osg::Uniform("textureDiff2", 2));
|
||||
_StateSet->addUniform(new osg::Uniform("textureDiff3", 3));
|
||||
_StateSet->addUniform(new osg::Uniform("textureAggIn", 4));
|
||||
_StateSet->addUniform(new osg::Uniform("start_disparity", _StartDisparity));
|
||||
_StateSet->addUniform(new osg::Uniform("window_size", _WindowSize));
|
||||
|
||||
quad_geode->addDrawable(quad_geom.get());
|
||||
|
||||
top_group->addChild(quad_geode.get());
|
||||
|
||||
return top_group;
|
||||
}
|
||||
|
||||
void AggregatePass::setupCamera()
|
||||
{
|
||||
// clearing
|
||||
_Camera->setClearColor(osg::Vec4(0.1f,0.1f,0.3f,1.0f));
|
||||
_Camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// projection and view
|
||||
_Camera->setProjectionMatrix(osg::Matrix::ortho2D(0,1,0,1));
|
||||
_Camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
|
||||
_Camera->setViewMatrix(osg::Matrix::identity());
|
||||
|
||||
// viewport
|
||||
_Camera->setViewport(0, 0, _TextureWidth, _TextureHeight);
|
||||
|
||||
_Camera->setRenderOrder(osg::Camera::PRE_RENDER);
|
||||
_Camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
|
||||
|
||||
_Camera->attach(osg::Camera::BufferComponent(osg::Camera::COLOR_BUFFER0+0), _OutTexture.get());
|
||||
}
|
||||
|
||||
void AggregatePass::setShader(std::string filename)
|
||||
{
|
||||
osg::ref_ptr<osg::Shader> fshader = new osg::Shader( osg::Shader::FRAGMENT );
|
||||
fshader->loadShaderSourceFromFile(osgDB::findDataFile(filename));
|
||||
|
||||
_FragmentProgram = 0;
|
||||
_FragmentProgram = new osg::Program;
|
||||
|
||||
_FragmentProgram->addShader(fshader.get());
|
||||
|
||||
_StateSet->setAttributeAndModes(_FragmentProgram.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE );
|
||||
}
|
||||
|
||||
// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
|
||||
SelectPass::SelectPass(osg::TextureRectangle *in_tex,
|
||||
int width, int height,
|
||||
int min_disparity, int max_disparity) :
|
||||
_TextureWidth(width),
|
||||
_TextureHeight(height),
|
||||
_MinDisparity(min_disparity),
|
||||
_MaxDisparity(max_disparity)
|
||||
{
|
||||
_RootGroup = new osg::Group;
|
||||
_InTexture = in_tex;
|
||||
|
||||
createOutputTextures();
|
||||
|
||||
_Camera = new osg::Camera;
|
||||
setupCamera();
|
||||
_Camera->addChild(createTexturedQuad().get());
|
||||
|
||||
_RootGroup->addChild(_Camera.get());
|
||||
|
||||
setShader("shaders/stereomatch_select.frag");
|
||||
}
|
||||
|
||||
SelectPass::~SelectPass()
|
||||
{
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Group> SelectPass::createTexturedQuad()
|
||||
{
|
||||
osg::ref_ptr<osg::Group> top_group = new osg::Group;
|
||||
|
||||
osg::ref_ptr<osg::Geode> quad_geode = new osg::Geode;
|
||||
|
||||
osg::ref_ptr<osg::Vec3Array> quad_coords = new osg::Vec3Array; // vertex coords
|
||||
// counter-clockwise
|
||||
quad_coords->push_back(osg::Vec3d(0, 0, -1));
|
||||
quad_coords->push_back(osg::Vec3d(1, 0, -1));
|
||||
quad_coords->push_back(osg::Vec3d(1, 1, -1));
|
||||
quad_coords->push_back(osg::Vec3d(0, 1, -1));
|
||||
|
||||
osg::ref_ptr<osg::Vec2Array> quad_tcoords = new osg::Vec2Array; // texture coords
|
||||
quad_tcoords->push_back(osg::Vec2(0, 0));
|
||||
quad_tcoords->push_back(osg::Vec2(_TextureWidth, 0));
|
||||
quad_tcoords->push_back(osg::Vec2(_TextureWidth, _TextureHeight));
|
||||
quad_tcoords->push_back(osg::Vec2(0, _TextureHeight));
|
||||
|
||||
osg::ref_ptr<osg::Geometry> quad_geom = new osg::Geometry;
|
||||
osg::ref_ptr<osg::DrawArrays> quad_da = new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4);
|
||||
|
||||
osg::ref_ptr<osg::Vec4Array> quad_colors = new osg::Vec4Array;
|
||||
quad_colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
|
||||
|
||||
quad_geom->setVertexArray(quad_coords.get());
|
||||
quad_geom->setTexCoordArray(0, quad_tcoords.get());
|
||||
quad_geom->addPrimitiveSet(quad_da.get());
|
||||
quad_geom->setColorArray(quad_colors.get());
|
||||
quad_geom->setColorBinding(osg::Geometry::BIND_OVERALL);
|
||||
|
||||
_StateSet = quad_geom->getOrCreateStateSet();
|
||||
_StateSet->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
|
||||
_StateSet->setTextureAttributeAndModes(0, _InTexture.get(), osg::StateAttribute::ON);
|
||||
|
||||
_StateSet->addUniform(new osg::Uniform("textureIn", 0));
|
||||
_StateSet->addUniform(new osg::Uniform("min_disparity", _MinDisparity));
|
||||
_StateSet->addUniform(new osg::Uniform("max_disparity", _MaxDisparity));
|
||||
|
||||
quad_geode->addDrawable(quad_geom.get());
|
||||
|
||||
top_group->addChild(quad_geode.get());
|
||||
|
||||
return top_group;
|
||||
}
|
||||
|
||||
void SelectPass::setupCamera()
|
||||
{
|
||||
// clearing
|
||||
_Camera->setClearColor(osg::Vec4(0.1f,0.1f,0.3f,1.0f));
|
||||
_Camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// projection and view
|
||||
_Camera->setProjectionMatrix(osg::Matrix::ortho2D(0,1,0,1));
|
||||
_Camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
|
||||
_Camera->setViewMatrix(osg::Matrix::identity());
|
||||
|
||||
// viewport
|
||||
_Camera->setViewport(0, 0, _TextureWidth, _TextureHeight);
|
||||
|
||||
_Camera->setRenderOrder(osg::Camera::PRE_RENDER);
|
||||
_Camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
|
||||
|
||||
_Camera->attach(osg::Camera::BufferComponent(osg::Camera::COLOR_BUFFER0+0), _OutTexture.get());
|
||||
}
|
||||
|
||||
void SelectPass::createOutputTextures()
|
||||
{
|
||||
_OutTexture = new osg::TextureRectangle;
|
||||
|
||||
_OutTexture->setTextureSize(_TextureWidth, _TextureHeight);
|
||||
_OutTexture->setInternalFormat(GL_RGBA);
|
||||
_OutTexture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
|
||||
_OutTexture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
|
||||
}
|
||||
|
||||
void SelectPass::setShader(std::string filename)
|
||||
{
|
||||
osg::ref_ptr<osg::Shader> fshader = new osg::Shader( osg::Shader::FRAGMENT );
|
||||
fshader->loadShaderSourceFromFile(osgDB::findDataFile(filename));
|
||||
|
||||
_FragmentProgram = 0;
|
||||
_FragmentProgram = new osg::Program;
|
||||
|
||||
_FragmentProgram->addShader(fshader.get());
|
||||
|
||||
_StateSet->setAttributeAndModes(_FragmentProgram.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE );
|
||||
}
|
||||
|
||||
// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
|
||||
StereoMultipass::StereoMultipass(osg::TextureRectangle *left_tex,
|
||||
osg::TextureRectangle *right_tex,
|
||||
int width, int height,
|
||||
int min_disparity, int max_disparity, int window_size) :
|
||||
_TextureWidth(width),
|
||||
_TextureHeight(height)
|
||||
{
|
||||
_RootGroup = new osg::Group;
|
||||
|
||||
createOutputTextures();
|
||||
|
||||
_Camera = new osg::Camera;
|
||||
setupCamera();
|
||||
_Camera->addChild(createTexturedQuad().get());
|
||||
|
||||
_RootGroup->addChild(_Camera.get());
|
||||
|
||||
setShader("shaders/stereomatch_clear.frag");
|
||||
|
||||
flip=1;
|
||||
flop=0;
|
||||
// we can do 16 differences in one pass,
|
||||
// but we must ping-pong the aggregate textures between passes
|
||||
// add passes until we cover the disparity range
|
||||
for (int i=min_disparity; i<=max_disparity; i+=16) {
|
||||
SubtractPass *subp = new SubtractPass(left_tex, right_tex,
|
||||
width, height,
|
||||
i);
|
||||
AggregatePass *aggp = new AggregatePass(subp->getOutputTexture(0).get(),
|
||||
subp->getOutputTexture(1).get(),
|
||||
subp->getOutputTexture(2).get(),
|
||||
subp->getOutputTexture(3).get(),
|
||||
_OutTexture[flip].get(),
|
||||
_OutTexture[flop].get(),
|
||||
width, height,
|
||||
i, window_size);
|
||||
|
||||
_RootGroup->addChild(subp->getRoot().get());
|
||||
_RootGroup->addChild(aggp->getRoot().get());
|
||||
flip = flip ? 0 : 1;
|
||||
flop = flop ? 0 : 1;
|
||||
}
|
||||
// add select pass
|
||||
_SelectPass = new SelectPass(_OutTexture[flip].get(),
|
||||
width, height,
|
||||
min_disparity, max_disparity);
|
||||
_RootGroup->addChild(_SelectPass->getRoot().get());
|
||||
}
|
||||
|
||||
StereoMultipass::~StereoMultipass()
|
||||
{
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Group> StereoMultipass::createTexturedQuad()
|
||||
{
|
||||
osg::ref_ptr<osg::Group> top_group = new osg::Group;
|
||||
|
||||
osg::ref_ptr<osg::Geode> quad_geode = new osg::Geode;
|
||||
|
||||
osg::ref_ptr<osg::Vec3Array> quad_coords = new osg::Vec3Array; // vertex coords
|
||||
// counter-clockwise
|
||||
quad_coords->push_back(osg::Vec3d(0, 0, -1));
|
||||
quad_coords->push_back(osg::Vec3d(1, 0, -1));
|
||||
quad_coords->push_back(osg::Vec3d(1, 1, -1));
|
||||
quad_coords->push_back(osg::Vec3d(0, 1, -1));
|
||||
|
||||
osg::ref_ptr<osg::Vec2Array> quad_tcoords = new osg::Vec2Array; // texture coords
|
||||
quad_tcoords->push_back(osg::Vec2(0, 0));
|
||||
quad_tcoords->push_back(osg::Vec2(_TextureWidth, 0));
|
||||
quad_tcoords->push_back(osg::Vec2(_TextureWidth, _TextureHeight));
|
||||
quad_tcoords->push_back(osg::Vec2(0, _TextureHeight));
|
||||
|
||||
osg::ref_ptr<osg::Geometry> quad_geom = new osg::Geometry;
|
||||
osg::ref_ptr<osg::DrawArrays> quad_da = new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4);
|
||||
|
||||
osg::ref_ptr<osg::Vec4Array> quad_colors = new osg::Vec4Array;
|
||||
quad_colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
|
||||
|
||||
quad_geom->setVertexArray(quad_coords.get());
|
||||
quad_geom->setTexCoordArray(0, quad_tcoords.get());
|
||||
quad_geom->addPrimitiveSet(quad_da.get());
|
||||
quad_geom->setColorArray(quad_colors.get());
|
||||
quad_geom->setColorBinding(osg::Geometry::BIND_OVERALL);
|
||||
|
||||
_StateSet = quad_geom->getOrCreateStateSet();
|
||||
_StateSet->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
|
||||
|
||||
quad_geode->addDrawable(quad_geom.get());
|
||||
|
||||
top_group->addChild(quad_geode.get());
|
||||
|
||||
return top_group;
|
||||
}
|
||||
|
||||
void StereoMultipass::setupCamera()
|
||||
{
|
||||
// clearing
|
||||
_Camera->setClearColor(osg::Vec4(10.0f,0.0f,0.0f,1.0f));
|
||||
_Camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// projection and view
|
||||
_Camera->setProjectionMatrix(osg::Matrix::ortho2D(0,1,0,1));
|
||||
_Camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
|
||||
_Camera->setViewMatrix(osg::Matrix::identity());
|
||||
|
||||
// viewport
|
||||
_Camera->setViewport(0, 0, _TextureWidth, _TextureHeight);
|
||||
|
||||
_Camera->setRenderOrder(osg::Camera::PRE_RENDER);
|
||||
_Camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
|
||||
|
||||
// attach two textures for aggregating results
|
||||
_Camera->attach(osg::Camera::BufferComponent(osg::Camera::COLOR_BUFFER0+0), _OutTexture[0].get());
|
||||
_Camera->attach(osg::Camera::BufferComponent(osg::Camera::COLOR_BUFFER0+1), _OutTexture[1].get());
|
||||
}
|
||||
|
||||
void StereoMultipass::createOutputTextures()
|
||||
{
|
||||
for (int i=0; i<2; i++) {
|
||||
_OutTexture[i] = new osg::TextureRectangle;
|
||||
|
||||
_OutTexture[i]->setTextureSize(_TextureWidth, _TextureHeight);
|
||||
_OutTexture[i]->setInternalFormat(GL_RGBA);
|
||||
_OutTexture[i]->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
|
||||
_OutTexture[i]->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
|
||||
|
||||
// hdr, we want to store floats
|
||||
_OutTexture[i]->setInternalFormat(GL_RGBA16F_ARB);
|
||||
//_OutTexture[i]->setInternalFormat(GL_FLOAT_RGBA32_NV);
|
||||
//_OutTexture[i]->setInternalFormat(GL_FLOAT_RGBA16_NV);
|
||||
_OutTexture[i]->setSourceFormat(GL_RGBA);
|
||||
_OutTexture[i]->setSourceType(GL_FLOAT);
|
||||
}
|
||||
}
|
||||
|
||||
void StereoMultipass::setShader(std::string filename)
|
||||
{
|
||||
osg::ref_ptr<osg::Shader> fshader = new osg::Shader( osg::Shader::FRAGMENT );
|
||||
fshader->loadShaderSourceFromFile(osgDB::findDataFile(filename));
|
||||
|
||||
_FragmentProgram = 0;
|
||||
_FragmentProgram = new osg::Program;
|
||||
|
||||
_FragmentProgram->addShader(fshader.get());
|
||||
|
||||
_StateSet->setAttributeAndModes(_FragmentProgram.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE );
|
||||
}
|
||||
|
154
examples/osgstereomatch/StereoMultipass.h
Normal file
154
examples/osgstereomatch/StereoMultipass.h
Normal file
@ -0,0 +1,154 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||
|
||||
/* OpenSceneGraph example, osgstereomatch.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef STEREOMULTIPASS_H
|
||||
#define STEREOMULTIPASS_H 1
|
||||
|
||||
#include <osg/ref_ptr>
|
||||
#include <osg/Group>
|
||||
#include <osg/Camera>
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osg/Projection>
|
||||
#include <osg/Geode>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/TextureRectangle>
|
||||
|
||||
class SubtractPass {
|
||||
public:
|
||||
SubtractPass(osg::TextureRectangle *left_tex,
|
||||
osg::TextureRectangle *right_tex,
|
||||
int width, int height,
|
||||
int start_disparity);
|
||||
~SubtractPass();
|
||||
osg::ref_ptr<osg::Group> getRoot() { return _RootGroup; }
|
||||
osg::ref_ptr<osg::TextureRectangle> getOutputTexture(int i) { return _OutTexture[i]; }
|
||||
void setShader(std::string filename);
|
||||
|
||||
private:
|
||||
osg::ref_ptr<osg::Group> createTexturedQuad();
|
||||
void createOutputTextures();
|
||||
void setupCamera();
|
||||
|
||||
osg::ref_ptr<osg::Group> _RootGroup;
|
||||
osg::ref_ptr<osg::Camera> _Camera;
|
||||
osg::ref_ptr<osg::TextureRectangle> _InTextureLeft;
|
||||
osg::ref_ptr<osg::TextureRectangle> _InTextureRight;
|
||||
osg::ref_ptr<osg::TextureRectangle> _OutTexture[4];
|
||||
int _TextureWidth;
|
||||
int _TextureHeight;
|
||||
int _StartDisparity;
|
||||
osg::ref_ptr<osg::Program> _FragmentProgram;
|
||||
osg::ref_ptr<osg::StateSet> _StateSet;
|
||||
};
|
||||
|
||||
class AggregatePass {
|
||||
public:
|
||||
AggregatePass(osg::TextureRectangle *diff_tex0,
|
||||
osg::TextureRectangle *diff_tex1,
|
||||
osg::TextureRectangle *diff_tex2,
|
||||
osg::TextureRectangle *diff_tex3,
|
||||
osg::TextureRectangle *agg_tex_in,
|
||||
osg::TextureRectangle *agg_tex_out,
|
||||
int width, int height,
|
||||
int start_disparity, int window_size);
|
||||
~AggregatePass();
|
||||
osg::ref_ptr<osg::Group> getRoot() { return _RootGroup; }
|
||||
osg::ref_ptr<osg::TextureRectangle> getOutputTexture() { return _OutTexture; }
|
||||
void setShader(std::string filename);
|
||||
|
||||
private:
|
||||
osg::ref_ptr<osg::Group> createTexturedQuad();
|
||||
void setupCamera();
|
||||
|
||||
osg::ref_ptr<osg::Group> _RootGroup;
|
||||
osg::ref_ptr<osg::Camera> _Camera;
|
||||
osg::ref_ptr<osg::TextureRectangle> _InTextureDifference[4];
|
||||
osg::ref_ptr<osg::TextureRectangle> _InTextureAggregate;
|
||||
osg::ref_ptr<osg::TextureRectangle> _OutTextureAggregate;
|
||||
osg::ref_ptr<osg::TextureRectangle> _OutTexture;
|
||||
int _TextureWidth;
|
||||
int _TextureHeight;
|
||||
int _StartDisparity;
|
||||
int _WindowSize;
|
||||
osg::ref_ptr<osg::Program> _FragmentProgram;
|
||||
osg::ref_ptr<osg::StateSet> _StateSet;
|
||||
};
|
||||
|
||||
class SelectPass {
|
||||
public:
|
||||
SelectPass(osg::TextureRectangle *in_tex,
|
||||
int width, int height,
|
||||
int min_disparity, int max_disparity);
|
||||
~SelectPass();
|
||||
osg::ref_ptr<osg::Group> getRoot() { return _RootGroup; }
|
||||
osg::ref_ptr<osg::TextureRectangle> getOutputTexture() { return _OutTexture; }
|
||||
void setShader(std::string filename);
|
||||
|
||||
private:
|
||||
osg::ref_ptr<osg::Group> createTexturedQuad();
|
||||
void createOutputTextures();
|
||||
void setupCamera();
|
||||
|
||||
osg::ref_ptr<osg::Group> _RootGroup;
|
||||
osg::ref_ptr<osg::Camera> _Camera;
|
||||
osg::ref_ptr<osg::TextureRectangle> _InTexture;
|
||||
osg::ref_ptr<osg::TextureRectangle> _OutTexture;
|
||||
osg::ref_ptr<osg::Image> _OutImage;
|
||||
int _TextureWidth;
|
||||
int _TextureHeight;
|
||||
int _MinDisparity;
|
||||
int _MaxDisparity;
|
||||
osg::ref_ptr<osg::Program> _FragmentProgram;
|
||||
osg::ref_ptr<osg::StateSet> _StateSet;
|
||||
};
|
||||
|
||||
class StereoMultipass {
|
||||
public:
|
||||
StereoMultipass(osg::TextureRectangle *left_tex,
|
||||
osg::TextureRectangle *right_tex,
|
||||
int width, int height,
|
||||
int min_disparity, int max_disparity, int window_size);
|
||||
~StereoMultipass();
|
||||
osg::ref_ptr<osg::Group> getRoot() { return _RootGroup; }
|
||||
osg::ref_ptr<osg::TextureRectangle> getOutputTexture() { return _SelectPass->getOutputTexture().get(); }
|
||||
void setShader(std::string filename);
|
||||
|
||||
private:
|
||||
osg::ref_ptr<osg::Group> createTexturedQuad();
|
||||
void createOutputTextures();
|
||||
void setupCamera();
|
||||
|
||||
osg::ref_ptr<osg::Group> _RootGroup;
|
||||
osg::ref_ptr<osg::Camera> _Camera;
|
||||
osg::ref_ptr<osg::TextureRectangle> _InTexture;
|
||||
osg::ref_ptr<osg::TextureRectangle> _OutTexture[2];
|
||||
int _TextureWidth;
|
||||
int _TextureHeight;
|
||||
osg::ref_ptr<osg::Program> _FragmentProgram;
|
||||
osg::ref_ptr<osg::StateSet> _StateSet;
|
||||
|
||||
SelectPass *_SelectPass;
|
||||
|
||||
int flip;
|
||||
int flop;
|
||||
};
|
||||
|
||||
#endif //STEREOMULTIPASS_H
|
141
examples/osgstereomatch/StereoPass.cpp
Normal file
141
examples/osgstereomatch/StereoPass.cpp
Normal file
@ -0,0 +1,141 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||
|
||||
/* OpenSceneGraph example, osgstereomatch.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "StereoPass.h"
|
||||
#include <osgDB/FileUtils>
|
||||
#include <iostream>
|
||||
|
||||
StereoPass::StereoPass(osg::TextureRectangle *left_tex,
|
||||
osg::TextureRectangle *right_tex,
|
||||
int width, int height,
|
||||
int min_disparity, int max_disparity, int window_size):
|
||||
_TextureWidth(width),
|
||||
_TextureHeight(height),
|
||||
_MinDisparity(min_disparity),
|
||||
_MaxDisparity(max_disparity),
|
||||
_WindowSize(window_size)
|
||||
{
|
||||
_RootGroup = new osg::Group;
|
||||
|
||||
_InTextureLeft = left_tex;
|
||||
_InTextureRight = right_tex;
|
||||
|
||||
createOutputTextures();
|
||||
|
||||
_Camera = new osg::Camera;
|
||||
setupCamera();
|
||||
_Camera->addChild(createTexturedQuad().get());
|
||||
|
||||
_RootGroup->addChild(_Camera.get());
|
||||
|
||||
setShader("shaders/stereomatch_stereopass.frag");
|
||||
}
|
||||
|
||||
StereoPass::~StereoPass()
|
||||
{
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Group> StereoPass::createTexturedQuad()
|
||||
{
|
||||
osg::ref_ptr<osg::Group> top_group = new osg::Group;
|
||||
|
||||
osg::ref_ptr<osg::Geode> quad_geode = new osg::Geode;
|
||||
|
||||
osg::ref_ptr<osg::Vec3Array> quad_coords = new osg::Vec3Array; // vertex coords
|
||||
// counter-clockwise
|
||||
quad_coords->push_back(osg::Vec3d(0, 0, -1));
|
||||
quad_coords->push_back(osg::Vec3d(1, 0, -1));
|
||||
quad_coords->push_back(osg::Vec3d(1, 1, -1));
|
||||
quad_coords->push_back(osg::Vec3d(0, 1, -1));
|
||||
|
||||
osg::ref_ptr<osg::Vec2Array> quad_tcoords = new osg::Vec2Array; // texture coords
|
||||
quad_tcoords->push_back(osg::Vec2(0, 0));
|
||||
quad_tcoords->push_back(osg::Vec2(_TextureWidth, 0));
|
||||
quad_tcoords->push_back(osg::Vec2(_TextureWidth, _TextureHeight));
|
||||
quad_tcoords->push_back(osg::Vec2(0, _TextureHeight));
|
||||
|
||||
osg::ref_ptr<osg::Geometry> quad_geom = new osg::Geometry;
|
||||
osg::ref_ptr<osg::DrawArrays> quad_da = new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4);
|
||||
|
||||
quad_geom->setVertexArray(quad_coords.get());
|
||||
quad_geom->setTexCoordArray(0, quad_tcoords.get());
|
||||
quad_geom->addPrimitiveSet(quad_da.get());
|
||||
|
||||
_StateSet = quad_geom->getOrCreateStateSet();
|
||||
_StateSet->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
|
||||
_StateSet->setTextureAttributeAndModes(0, _InTextureLeft.get(), osg::StateAttribute::ON);
|
||||
_StateSet->setTextureAttributeAndModes(1, _InTextureRight.get(), osg::StateAttribute::ON);
|
||||
|
||||
_StateSet->addUniform(new osg::Uniform("textureID0", 0));
|
||||
_StateSet->addUniform(new osg::Uniform("textureID1", 1));
|
||||
_StateSet->addUniform(new osg::Uniform("min_disparity", _MinDisparity));
|
||||
_StateSet->addUniform(new osg::Uniform("max_disparity", _MaxDisparity));
|
||||
_StateSet->addUniform(new osg::Uniform("window_size", _WindowSize));
|
||||
|
||||
quad_geode->addDrawable(quad_geom.get());
|
||||
|
||||
top_group->addChild(quad_geode.get());
|
||||
|
||||
return top_group;
|
||||
}
|
||||
|
||||
void StereoPass::setupCamera()
|
||||
{
|
||||
// clearing
|
||||
_Camera->setClearColor(osg::Vec4(1.0f,0.0f,0.0f,1.0f));
|
||||
_Camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// projection and view
|
||||
_Camera->setProjectionMatrix(osg::Matrix::ortho2D(0,1,0,1));
|
||||
_Camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
|
||||
_Camera->setViewMatrix(osg::Matrix::identity());
|
||||
|
||||
// viewport
|
||||
_Camera->setViewport(0, 0, _TextureWidth, _TextureHeight);
|
||||
|
||||
_Camera->setRenderOrder(osg::Camera::PRE_RENDER);
|
||||
_Camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
|
||||
|
||||
// attach the output texture and use it as the color buffer.
|
||||
_Camera->attach(osg::Camera::COLOR_BUFFER, _OutTexture.get());
|
||||
}
|
||||
|
||||
void StereoPass::createOutputTextures()
|
||||
{
|
||||
_OutTexture = new osg::TextureRectangle;
|
||||
|
||||
_OutTexture->setTextureSize(_TextureWidth, _TextureHeight);
|
||||
_OutTexture->setInternalFormat(GL_RGBA);
|
||||
_OutTexture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
|
||||
_OutTexture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
|
||||
}
|
||||
|
||||
void StereoPass::setShader(std::string filename)
|
||||
{
|
||||
osg::ref_ptr<osg::Shader> fshader = new osg::Shader( osg::Shader::FRAGMENT );
|
||||
fshader->loadShaderSourceFromFile(osgDB::findDataFile(filename));
|
||||
|
||||
_FragmentProgram = 0;
|
||||
_FragmentProgram = new osg::Program;
|
||||
|
||||
_FragmentProgram->addShader(fshader.get());
|
||||
|
||||
_StateSet->setAttributeAndModes(_FragmentProgram.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE );
|
||||
}
|
66
examples/osgstereomatch/StereoPass.h
Normal file
66
examples/osgstereomatch/StereoPass.h
Normal file
@ -0,0 +1,66 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||
|
||||
/* OpenSceneGraph example, osgstereomatch.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef STEREOPASS_H
|
||||
#define STEREOPASS_H 1
|
||||
|
||||
#include <osg/ref_ptr>
|
||||
#include <osg/Group>
|
||||
#include <osg/Camera>
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osg/Projection>
|
||||
#include <osg/Geode>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/TextureRectangle>
|
||||
|
||||
class StereoPass {
|
||||
public:
|
||||
StereoPass(osg::TextureRectangle *left_tex,
|
||||
osg::TextureRectangle *right_tex,
|
||||
int width, int height,
|
||||
int min_disparity, int max_disparity, int window_size);
|
||||
~StereoPass();
|
||||
osg::ref_ptr<osg::Group> getRoot() { return _RootGroup; }
|
||||
osg::ref_ptr<osg::TextureRectangle> getOutputTexture() { return _OutTexture; }
|
||||
void setShader(std::string filename);
|
||||
|
||||
private:
|
||||
osg::ref_ptr<osg::Group> createTexturedQuad();
|
||||
void createOutputTextures();
|
||||
void setupCamera();
|
||||
|
||||
osg::ref_ptr<osg::Group> _RootGroup;
|
||||
osg::ref_ptr<osg::Camera> _Camera;
|
||||
osg::ref_ptr<osg::TextureRectangle> _InTextureLeft;
|
||||
osg::ref_ptr<osg::TextureRectangle> _InTextureRight;
|
||||
osg::ref_ptr<osg::TextureRectangle> _OutTexture;
|
||||
|
||||
int _TextureWidth;
|
||||
int _TextureHeight;
|
||||
int _MinDisparity;
|
||||
int _MaxDisparity;
|
||||
int _WindowSize;
|
||||
|
||||
osg::ref_ptr<osg::Program> _FragmentProgram;
|
||||
osg::ref_ptr<osg::StateSet> _StateSet;
|
||||
};
|
||||
|
||||
#endif //STEREOPASS_H
|
194
examples/osgstereomatch/osgstereomatch.cpp
Normal file
194
examples/osgstereomatch/osgstereomatch.cpp
Normal file
@ -0,0 +1,194 @@
|
||||
/* OpenSceneGraph example, osgstereomatch.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <osg/Vec3>
|
||||
#include <osg/Vec4>
|
||||
#include <osg/Quat>
|
||||
#include <osg/Matrix>
|
||||
#include <osg/ShapeDrawable>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Geode>
|
||||
#include <osg/TextureRectangle>
|
||||
|
||||
#include <osgDB/FileUtils>
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#include <osgViewer/Viewer>
|
||||
#include <osgViewer/ViewerEventHandlers>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "StereoPass.h"
|
||||
#include "StereoMultipass.h"
|
||||
|
||||
osg::Node* createScene(osg::Image *left, osg::Image *right, unsigned int min_disp, unsigned int max_disp, unsigned int window_size, bool single_pass)
|
||||
{
|
||||
int width = left->s();
|
||||
int height = left->t();
|
||||
|
||||
osg::Group* topnode = new osg::Group;
|
||||
|
||||
// create four quads so we can display up to four images
|
||||
|
||||
osg::ref_ptr<osg::Geode> geode = new osg::Geode();
|
||||
|
||||
// each geom will contain a quad
|
||||
osg::ref_ptr<osg::DrawArrays> da = new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4);
|
||||
|
||||
osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array;
|
||||
colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
|
||||
|
||||
osg::ref_ptr<osg::Vec2Array> tcoords = new osg::Vec2Array; // texture coords
|
||||
tcoords->push_back(osg::Vec2(0, 0));
|
||||
tcoords->push_back(osg::Vec2(width, 0));
|
||||
tcoords->push_back(osg::Vec2(width, height));
|
||||
tcoords->push_back(osg::Vec2(0, height));
|
||||
|
||||
osg::ref_ptr<osg::StateSet> geomss[4]; // stateset where we can attach textures
|
||||
osg::ref_ptr<osg::TextureRectangle> texture[4];
|
||||
|
||||
for (int i=0;i<4;i++) {
|
||||
osg::ref_ptr<osg::Vec3Array> vcoords = new osg::Vec3Array; // vertex coords
|
||||
osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;
|
||||
|
||||
// tile the quads on the screen
|
||||
// 2 3
|
||||
// 0 1
|
||||
int xoff, zoff;
|
||||
xoff = (i%2);
|
||||
zoff = i>1 ? 1 : 0;
|
||||
|
||||
// initial viewer camera looks along y
|
||||
vcoords->push_back(osg::Vec3d(0+(xoff * width), 0, 0+(zoff * height)));
|
||||
vcoords->push_back(osg::Vec3d(width+(xoff * width), 0, 0+(zoff * height)));
|
||||
vcoords->push_back(osg::Vec3d(width+(xoff * width), 0, height+(zoff * height)));
|
||||
vcoords->push_back(osg::Vec3d(0+(xoff * width), 0, height+(zoff * height)));
|
||||
|
||||
geom->setVertexArray(vcoords.get());
|
||||
geom->setTexCoordArray(0,tcoords.get());
|
||||
geom->addPrimitiveSet(da.get());
|
||||
geom->setColorArray(colors.get());
|
||||
geom->setColorBinding(osg::Geometry::BIND_OVERALL);
|
||||
geomss[i] = geom->getOrCreateStateSet();
|
||||
geomss[i]->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
||||
|
||||
texture[i] = new osg::TextureRectangle;
|
||||
texture[i]->setResizeNonPowerOfTwoHint(false);
|
||||
texture[i]->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
|
||||
texture[i]->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
|
||||
|
||||
geode->addDrawable(geom.get());
|
||||
}
|
||||
|
||||
// attach the input images to the bottom textures of the view
|
||||
texture[0]->setImage(left);
|
||||
texture[1]->setImage(right);
|
||||
geomss[0]->setTextureAttributeAndModes(0, texture[0].get(), osg::StateAttribute::ON);
|
||||
geomss[1]->setTextureAttributeAndModes(0, texture[1].get(), osg::StateAttribute::ON);
|
||||
|
||||
topnode->addChild(geode.get());
|
||||
|
||||
// create the processing passes
|
||||
if (single_pass) {
|
||||
StereoPass *stereopass = new StereoPass(texture[0].get(), texture[1].get(),
|
||||
width, height,
|
||||
min_disp, max_disp, window_size);
|
||||
|
||||
topnode->addChild(stereopass->getRoot().get());
|
||||
|
||||
// attach the output of the processing to the top left geom
|
||||
geomss[2]->setTextureAttributeAndModes(0,
|
||||
stereopass->getOutputTexture().get(),
|
||||
osg::StateAttribute::ON);
|
||||
} else {
|
||||
StereoMultipass *stereomp = new StereoMultipass(texture[0].get(), texture[1].get(),
|
||||
width, height,
|
||||
min_disp, max_disp, window_size);
|
||||
topnode->addChild(stereomp->getRoot().get());
|
||||
// attach the output of the processing to the top left geom
|
||||
geomss[2]->setTextureAttributeAndModes(0,
|
||||
stereomp->getOutputTexture().get(),
|
||||
osg::StateAttribute::ON);
|
||||
}
|
||||
|
||||
return topnode;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// use an ArgumentParser object to manage the program arguments.
|
||||
osg::ArgumentParser arguments(&argc,argv);
|
||||
|
||||
// set up the usage document, in case we need to print out how to use this program.
|
||||
arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates a stereo matching algorithm. It uses multiple render targets and multiple passes with texture ping-pong.");
|
||||
arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] --left left_image --right right_image --min min_disparity --max max_disparity --window window_size");
|
||||
arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
|
||||
arguments.getApplicationUsage()->addCommandLineOption("--left","The left image of the stereo pair to load.");
|
||||
arguments.getApplicationUsage()->addCommandLineOption("--right","The right image of the stereo pair to load.");
|
||||
arguments.getApplicationUsage()->addCommandLineOption("--min","The minimum disparity to start matching pixels.");
|
||||
arguments.getApplicationUsage()->addCommandLineOption("--max","The maximum disparity to stop matching pixels.");
|
||||
arguments.getApplicationUsage()->addCommandLineOption("--window","The window size used to match areas around pixels.");
|
||||
arguments.getApplicationUsage()->addCommandLineOption("--single","Use a single pass instead on multiple passes.");
|
||||
|
||||
// if user request help write it out to cout.
|
||||
if (arguments.read("-h") || arguments.read("--help"))
|
||||
{
|
||||
arguments.getApplicationUsage()->write(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::string leftName("");
|
||||
while(arguments.read("--left", leftName)) {}
|
||||
|
||||
std::string rightName("");
|
||||
while(arguments.read("--right", rightName)) {}
|
||||
|
||||
unsigned int minDisparity = 0;
|
||||
while (arguments.read("--min", minDisparity)) {}
|
||||
|
||||
unsigned int maxDisparity = 31;
|
||||
while (arguments.read("--max", maxDisparity)) {}
|
||||
|
||||
unsigned int windowSize = 5;
|
||||
while (arguments.read("--window", windowSize)) {}
|
||||
|
||||
bool useSinglePass = false;
|
||||
while (arguments.read("--single")) { useSinglePass = true; }
|
||||
|
||||
if (leftName == "" || rightName=="") {
|
||||
arguments.getApplicationUsage()->write(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// load the images
|
||||
osg::ref_ptr<osg::Image> leftIm = osgDB::readImageFile(leftName);
|
||||
osg::ref_ptr<osg::Image> rightIm = osgDB::readImageFile(rightName);
|
||||
|
||||
osg::Node* scene = createScene(leftIm.get(), rightIm.get(), minDisparity, maxDisparity, windowSize, useSinglePass);
|
||||
|
||||
// construct the viewer.
|
||||
osgViewer::Viewer viewer;
|
||||
viewer.setThreadingModel(osgViewer::Viewer::SingleThreaded);
|
||||
|
||||
// add the stats handler
|
||||
viewer.addEventHandler(new osgViewer::StatsHandler);
|
||||
|
||||
viewer.setSceneData(scene);
|
||||
|
||||
return viewer.run();
|
||||
}
|
Loading…
Reference in New Issue
Block a user