#include "AftrOpenGLIncludes.h" #include "OVR_CAPI_GL.h" #include "Extras/OVR_Math.h" #include #include using namespace OVR; struct Aftr::OculusTextureBuffer { ovrSession Session; ovrTextureSwapChain ColorTextureChain; ovrTextureSwapChain DepthTextureChain; GLuint fboId; Sizei texSize; OculusTextureBuffer( ovrSession session, Sizei size, int sampleCount ) : Session( session ), ColorTextureChain( nullptr ), DepthTextureChain( nullptr ), fboId( 0 ), texSize( 0, 0 ) { assert( sampleCount <= 1 ); // The code doesn't currently handle MSAA textures. texSize = size; // This texture isn't necessarily going to be a render target, but it usually is. if( ! session ) // No HMD? A little odd. { std::cout << "ERROR: " << AFTR_FILE_LINE_STR << "No HMD found...\n"; } ovrTextureSwapChainDesc desc = {}; desc.Type = ovrTexture_2D; desc.ArraySize = 1; desc.Width = size.w; desc.Height = size.h; desc.MipLevels = 1; desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB; desc.SampleCount = sampleCount; desc.StaticImage = ovrFalse; { ovrResult result = ovr_CreateTextureSwapChainGL( Session, &desc, &ColorTextureChain ); int length = 0; ovr_GetTextureSwapChainLength( session, ColorTextureChain, &length ); if( OVR_SUCCESS( result ) ) { for( int i = 0; i < length; ++i ) { GLuint chainTexId; ovr_GetTextureSwapChainBufferGL( Session, ColorTextureChain, i, &chainTexId ); glBindTexture( GL_TEXTURE_2D, chainTexId ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); } } } desc.Format = OVR_FORMAT_D32_FLOAT; { ovrResult result = ovr_CreateTextureSwapChainGL( Session, &desc, &DepthTextureChain ); int length = 0; ovr_GetTextureSwapChainLength( session, DepthTextureChain, &length ); if( OVR_SUCCESS( result ) ) { for( int i = 0; i < length; ++i ) { GLuint chainTexId; ovr_GetTextureSwapChainBufferGL( Session, DepthTextureChain, i, &chainTexId ); glBindTexture( GL_TEXTURE_2D, chainTexId ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); } } } glGenFramebuffers( 1, &fboId ); } ~OculusTextureBuffer() { if( ColorTextureChain ) { ovr_DestroyTextureSwapChain( Session, ColorTextureChain ); ColorTextureChain = nullptr; } if( DepthTextureChain ) { ovr_DestroyTextureSwapChain( Session, DepthTextureChain ); DepthTextureChain = nullptr; } if( fboId ) { glDeleteFramebuffers( 1, &fboId ); fboId = 0; } } Sizei GetSize() const { return texSize; } void SetAndClearRenderSurface() { GLuint curColorTexId; GLuint curDepthTexId; { int curIndex; ovr_GetTextureSwapChainCurrentIndex( Session, ColorTextureChain, &curIndex ); ovr_GetTextureSwapChainBufferGL( Session, ColorTextureChain, curIndex, &curColorTexId ); } { int curIndex; ovr_GetTextureSwapChainCurrentIndex( Session, DepthTextureChain, &curIndex ); ovr_GetTextureSwapChainBufferGL( Session, DepthTextureChain, curIndex, &curDepthTexId ); } glBindFramebuffer( GL_FRAMEBUFFER, fboId ); glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, curColorTexId, 0 ); glFramebufferTexture2D( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, curDepthTexId, 0 ); glViewport( 0, 0, texSize.w, texSize.h ); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glEnable( GL_FRAMEBUFFER_SRGB ); } void UnsetRenderSurface() { glBindFramebuffer( GL_FRAMEBUFFER, fboId ); glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0 ); glFramebufferTexture2D( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0 ); } void Commit() { ovr_CommitTextureSwapChain( Session, ColorTextureChain ); ovr_CommitTextureSwapChain( Session, DepthTextureChain ); } };