Skip to content

Commit

Permalink
Merge pull request #1404 from ericmehl/OpenGLWorldDepth
Browse files Browse the repository at this point in the history
IECoreGL::Selector : Camera-space depth sampling
  • Loading branch information
johnhaddon authored Feb 6, 2024
2 parents 373dfa2 + 6872587 commit d36ae7d
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 13 deletions.
6 changes: 6 additions & 0 deletions Changes
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
10.5.x.x (relative to 10.5.5.0)
========

API
------------

- `IECoreGL::Selector`: Added constructor overload that accepts a boolean indicating a more precise, camera-space depth sample will be used to sample depth instead of OpenGL's depth buffer.
- `IECoreGL::ColorTexture`: Added new constructor that accepts an argument specifying the internal storage format to use.



10.5.5.0 (relative to 10.5.4.2)
Expand Down
5 changes: 4 additions & 1 deletion include/IECoreGL/ColorTexture.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,11 @@ class IECOREGL_API ColorTexture : public Texture

IE_CORE_DECLARERUNTIMETYPEDEXTENSION( IECoreGL::ColorTexture, ColorTextureTypeId, Texture );

/// Constructs an empty texture of the specified dimensions.
/// \todo Remove this constructor when client code has transitioned to the one
/// specifying the internal storage format.
ColorTexture( unsigned int width, unsigned int height );
/// Constructs an empty texture of the specified dimensions and internal storage format.
ColorTexture( unsigned int width, unsigned int height, const GLint internalFormat );
/// Constructs a new ColorTexture. All channels must be of the same type, and must
/// be some form of numeric VectorData.
ColorTexture( unsigned int width, unsigned int height, const IECore::Data *r,
Expand Down
7 changes: 7 additions & 0 deletions include/IECoreGL/Selector.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,13 @@ class IECOREGL_API Selector : boost::noncopyable
/// responsibility to keep the hits vector alive for the lifetime
/// of the Selector.
Selector( const Imath::Box2f &region, Mode mode, std::vector<HitRecord> &hits );
/// Same as above, and if `useCameraDepth` is `true`, the depth
/// values in `hits` will be taken from the camera-space Z coordinate
/// instead of the less precise OpenGL depth buffer.

/// \todo Remove when client code has migrated and use the more
/// precise alternative exclusively.
Selector( const Imath::Box2f &region, Mode mode, std::vector<HitRecord> &hits, bool useCameraDepth );
/// Completes the selection operation, filling in the vector
/// of hits that was passed to the constructor.
virtual ~Selector();
Expand Down
9 changes: 7 additions & 2 deletions src/IECoreGL/ColorTexture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,12 @@ using namespace boost;

IE_CORE_DEFINERUNTIMETYPED( ColorTexture );

ColorTexture::ColorTexture( unsigned int width, unsigned int height )
ColorTexture::ColorTexture( unsigned int width, unsigned int height ) :
ColorTexture( width, height, GL_RGBA )
{
}

ColorTexture::ColorTexture( unsigned int width, unsigned int height, const GLint internalFormat )
{
glGenTextures( 1, &m_texture );
ScopedBinding binding( *this );
Expand All @@ -58,7 +63,7 @@ ColorTexture::ColorTexture( unsigned int width, unsigned int height )
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );

glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
glTexImage2D( GL_TEXTURE_2D, 0, internalFormat, width, height, 0, GL_RGBA,
GL_FLOAT, nullptr );
}

Expand Down
69 changes: 59 additions & 10 deletions src/IECoreGL/Selector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,21 @@ using namespace IECoreGL;
// Selector::Implementation
//////////////////////////////////////////////////////////////////////////

namespace
{

const int g_idBufferIndex = 0;
const int g_cameraDepthBufferIndex = 1;

}

class Selector::Implementation : public IECore::RefCounted
{

public :

Implementation( Selector *parent, const Imath::Box2f &region, Mode mode, std::vector<HitRecord> &hits )
: m_mode( mode ), m_hits( hits ), m_baseState( new State( true /* complete */ ) ), m_currentName( 0 ), m_nextGeneratedName( 1 ), m_currentIDShader( nullptr )
Implementation( Selector *parent, const Imath::Box2f &region, Mode mode, std::vector<HitRecord> &hits, bool useCameraDepth )
: m_mode( mode ), m_hits( hits ), m_baseState( new State( true /* complete */ ) ), m_currentName( 0 ), m_nextGeneratedName( 1 ), m_currentIDShader( nullptr ), m_useCameraDepth( useCameraDepth )
{
// we don't want preexisting errors to trigger exceptions
// from error checking code in the begin*() methods, because
Expand Down Expand Up @@ -225,12 +233,15 @@ class Selector::Implementation : public IECore::RefCounted
"#version 330\n"
""
"uniform uint ieCoreGLNameIn;"
"in vec3 geometryP;"
""
"layout( location=0 ) out uint ieCoreGLNameOut;"
"layout( location=1 ) out vec4 ieCoreGLCameraDepth;"
""
"void main()"
"{"
" ieCoreGLNameOut = ieCoreGLNameIn;"
" ieCoreGLCameraDepth = vec4( -geometryP.z, -geometryP.z, -geometryP.z, 1 );"
"}";

static ShaderPtr s = new Shader( "", fragmentSource );
Expand Down Expand Up @@ -305,10 +316,16 @@ class Selector::Implementation : public IECore::RefCounted
GLint m_prevViewport[4];
GLint m_nameUniformLocation;

bool m_useCameraDepth;

void beginIDRender()
{
m_frameBuffer = new FrameBuffer();
m_frameBuffer->setColor( new UIntTexture( 128, 128 ) );
m_frameBuffer->setColor( new UIntTexture( 128, 128 ), g_idBufferIndex );
if( m_useCameraDepth )
{
m_frameBuffer->setColor( new ColorTexture( 128, 128, GL_RGBA32F ), g_cameraDepthBufferIndex );
}
m_frameBuffer->setDepth( new DepthTexture( 128, 128 ) );
m_frameBuffer->validate();
m_frameBufferBinding = boost::shared_ptr<FrameBuffer::ScopedBinding>( new FrameBuffer::ScopedBinding( *m_frameBuffer ) );
Expand Down Expand Up @@ -342,13 +359,26 @@ class Selector::Implementation : public IECore::RefCounted
glViewport( m_prevViewport[0], m_prevViewport[1], m_prevViewport[2], m_prevViewport[3] );
m_frameBufferBinding.reset();

IECoreImage::ImagePrimitivePtr idsImage = m_frameBuffer->getColor()->imagePrimitive();
IECoreImage::ImagePrimitivePtr idsImage = m_frameBuffer->getColor( g_idBufferIndex )->imagePrimitive();
const IECore::UIntVectorData *idsData = static_cast<const IECore::UIntVectorData *>( idsImage->channels["Y"].get() );
const std::vector<unsigned int> ids = idsData->readable();

IECoreImage::ImagePrimitivePtr zImage = m_frameBuffer->getDepth()->imagePrimitive();
const IECore::FloatVectorData *zData = static_cast<const IECore::FloatVectorData *>( zImage->channels["Z"].get() );
const std::vector<float> z = zData->readable();
IECoreImage::ImagePrimitivePtr zImage;
std::string channelName;

if( !m_useCameraDepth )
{
zImage = m_frameBuffer->getDepth()->imagePrimitive();
channelName = "Z";
}
else
{
zImage = m_frameBuffer->getColor( g_cameraDepthBufferIndex )->imagePrimitive();
channelName = "R";
}

auto zData = static_cast<const IECore::FloatVectorData *>( zImage->channels[channelName].get() );
const std::vector<float> &z = zData->readable();

std::map<unsigned int, HitRecord> idRecords;
for( size_t i = 0, e = ids.size(); i < e; i++ )
Expand Down Expand Up @@ -396,14 +426,28 @@ class Selector::Implementation : public IECore::RefCounted
throw IECore::Exception( "ID shader does not have an ieCoreGLNameOut output" );
}

GLint depthDataLocation = 0;
if( m_useCameraDepth )
{
depthDataLocation = glGetFragDataLocation( shader->program(), "ieCoreGLCameraDepth" );
if( depthDataLocation < 0 )
{
throw IECore::Exception( "ID shader does not have ieCoreGLCameraDepth output" );
}
}

m_nameUniformLocation = nameParameter->location;

m_currentIDShader = shader;
glUseProgram( m_currentIDShader->program() );

std::vector<GLenum> buffers;
buffers.resize( fragDataLocation + 1, GL_NONE );
buffers[buffers.size()-1] = GL_COLOR_ATTACHMENT0;
buffers.resize( std::max( fragDataLocation, depthDataLocation ) + 1, GL_NONE );
buffers[fragDataLocation] = GL_COLOR_ATTACHMENT0;
if( m_useCameraDepth )
{
buffers[depthDataLocation] = GL_COLOR_ATTACHMENT1;
}
glDrawBuffers( buffers.size(), &buffers[0] );

loadNameIDRender( m_currentName );
Expand Down Expand Up @@ -482,7 +526,12 @@ Selector *Selector::Implementation::g_currentSelector = nullptr;
//////////////////////////////////////////////////////////////////////////

Selector::Selector( const Imath::Box2f &region, Mode mode, std::vector<HitRecord> &hits )
: m_implementation( new Implementation( this, region, mode, hits ) )
: m_implementation( new Implementation( this, region, mode, hits, false /* useCameraDepth */ ) )
{
}

Selector::Selector( const Imath::Box2f &region, Mode mode, std::vector<HitRecord> &hits, bool useCameraDepth )
: m_implementation( new Implementation( this, region, mode, hits, useCameraDepth ) )
{
}

Expand Down
1 change: 1 addition & 0 deletions src/IECoreGL/bindings/ColorTextureBinding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ void bindColorTexture()
{
IECorePython::RunTimeTypedClass<ColorTexture>()
.def( init<unsigned int, unsigned int>() )
.def( init<unsigned int, unsigned int, const GLint>() )
.def( init<unsigned int, unsigned int, const IECore::Data *, const IECore::Data *, const IECore::Data *, const IECore::Data *>() )
.def( init<const IECoreImage::ImagePrimitive *>() )
;
Expand Down

0 comments on commit d36ae7d

Please sign in to comment.