SLProject  4.2.000
A platform independent 3D computer graphics framework for desktop OS, Android, iOS and online in web browsers
SLGLOculusFB.cpp
Go to the documentation of this file.
1 /**
2  * \file SLGLOculusFB.cpp
3  * \brief OpenGL Frame Buffer Object for the Oculus Rift Display
4  * \date August 2014
5  * \authors Marc Wacker, Roman Kuehne, Marcus Hudritsch
6  * \copyright http://opensource.org/licenses/GPL-3.0
7  * \remarks Please use clangformat to format the code. See more code style on
8  * https://github.com/cpvrlab/SLProject4/wiki/SLProject-Coding-Style
9 */
10 
11 #include <SLGLState.h>
12 #include <SLGLOculusFB.h>
13 #include <SLGLProgram.h>
14 #include <SLScene.h>
15 
16 //-----------------------------------------------------------------------------
17 /*! Constructor initializing with default values
18  */
20  : _width(0),
21  _height(0),
22  _halfWidth(0),
23  _halfHeight(0),
24  _fbID(0),
25  _depthRbID(0),
26  _texID(0)
27 {
28 }
29 //-----------------------------------------------------------------------------
30 /*! Destructor calling dispose
31  */
33 {
34  dispose();
35 }
36 //-----------------------------------------------------------------------------
37 /*! Deletes the buffer object
38  */
40 {
41  if (_fbID) glDeleteFramebuffers(1, &_fbID);
42  if (_texID) glDeleteTextures(1, &_texID);
43  if (_depthRbID) glDeleteRenderbuffers(1, &_depthRbID);
44 }
45 //-----------------------------------------------------------------------------
46 /*! Activates the frame buffer. On the first time it calls the updateSize to
47 determine the size and then creates the FBO.
48 */
51 {
52  if (!_fbID)
54  if (_fbID)
55  glBindFramebuffer(GL_FRAMEBUFFER, _fbID);
56 }
57 //-----------------------------------------------------------------------------
58 /*! Frame Buffer generation. This is called from within updateSize because the
59 frame buffer size has to be calculated first
60 */
62 {
63  // generate the intermediate screen texture
64  glGenTextures(1, &_texID);
65  glBindTexture(GL_TEXTURE_2D, _texID);
66  glTexParameteri(GL_TEXTURE_2D,
67  GL_TEXTURE_MAG_FILTER,
68  GL_LINEAR);
69  glTexParameteri(GL_TEXTURE_2D,
70  GL_TEXTURE_MIN_FILTER,
71  GL_LINEAR);
72  glTexParameteri(GL_TEXTURE_2D,
73  GL_TEXTURE_WRAP_S,
74  GL_CLAMP_TO_EDGE);
75  glTexParameteri(GL_TEXTURE_2D,
76  GL_TEXTURE_WRAP_T,
77  GL_CLAMP_TO_EDGE);
78  glTexImage2D(GL_TEXTURE_2D,
79  0,
80  PF_rgba,
81  _width,
82  _height,
83  0,
84  PF_rgba,
85  GL_UNSIGNED_BYTE,
86  nullptr);
87  glBindTexture(GL_TEXTURE_2D, 0);
88 
89  // generate the renderbuffer for the depth component
90  glGenRenderbuffers(1, &_depthRbID);
91  glBindRenderbuffer(GL_RENDERBUFFER, _depthRbID);
92 #if defined(SL_OS_MACIOS) || defined(SL_OS_ANDROID) || defined(SL_EMSCRIPTEN)
93  glRenderbufferStorage(GL_RENDERBUFFER,
94  GL_DEPTH_COMPONENT16,
95  _width,
96  _height);
97 #else
98  glRenderbufferStorage(GL_RENDERBUFFER,
99  GL_DEPTH_COMPONENT32,
100  _width,
101  _height);
102 #endif
103  glBindRenderbuffer(GL_RENDERBUFFER, 0);
104 
105  // finally generate the frame buffer and bind the targets
106  glGenFramebuffers(1, &_fbID);
107  glBindFramebuffer(GL_FRAMEBUFFER,
108  _fbID);
109  glFramebufferTexture2D(GL_FRAMEBUFFER,
110  GL_COLOR_ATTACHMENT0,
111  GL_TEXTURE_2D,
112  _texID,
113  0);
114  glFramebufferRenderbuffer(GL_FRAMEBUFFER,
115  GL_DEPTH_ATTACHMENT,
116  GL_RENDERBUFFER,
117  _depthRbID);
118 
119  // test if the generated fbo is valid
120  if ((glCheckFramebufferStatus(GL_FRAMEBUFFER)) != GL_FRAMEBUFFER_COMPLETE)
121  SL_EXIT_MSG("Frame buffer creation failed!");
122 
123  glBindFramebuffer(GL_FRAMEBUFFER, 0);
124  GET_GL_ERROR;
125 }
126 //-----------------------------------------------------------------------------
127 /*! Updates everything when the screen gets resized:
128 - Recalculates the stereo parameters
129 - Creates or updates the FBO
130 - Updates the shader uniforms
131 */
134 {
135  _width = scrWidth;
136  _height = scrHeight;
137  _halfWidth = scrWidth >> 1;
138  _halfHeight = scrHeight >> 1;
139 
140  // Create FBO or resize it
141  if (!_fbID)
142  generateFBO();
143  else
144  { // Resize the intermediate render targets
145  glBindTexture(GL_TEXTURE_2D, _texID);
146  glTexImage2D(GL_TEXTURE_2D,
147  0,
148  PF_rgba,
149  _width,
150  _height,
151  0,
152  PF_rgba,
153  GL_UNSIGNED_BYTE,
154  nullptr);
155  glBindTexture(GL_TEXTURE_2D, 0);
156 
157  // Resize the depth render buffer
158  glBindRenderbuffer(GL_RENDERBUFFER, _depthRbID);
159 
160 #if defined(SL_OS_MACIOS) || defined(SL_OS_ANDROID) || defined(SL_EMSCRIPTEN)
161  glRenderbufferStorage(GL_RENDERBUFFER,
162  GL_DEPTH_COMPONENT16,
163  _width,
164  _height);
165 #else
166  glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT32, _width, _height);
167 #endif
168 
169  glBindRenderbuffer(GL_RENDERBUFFER, 0);
170  }
171 
172  GET_GL_ERROR;
173 }
174 //-----------------------------------------------------------------------------
175 /*! Draws the intermediate render target (the texture) into the real
176  * framebuffer.
177  */
178 void SLGLOculusFB::drawFramebuffer(SLGLProgram* stereoOculusProgram)
179 {
180  glViewport(0, 0, _width, _height);
181  glBindFramebuffer(GL_FRAMEBUFFER, 0);
182  glClear(GL_COLOR_BUFFER_BIT);
183  glDisable(GL_DEPTH_TEST);
184 
185  // bind the rift shader
186  SLGLProgram* sp = stereoOculusProgram;
187  sp->useProgram();
188  SLint location = AT_position;
189 
190  // Create VBO for screen quad once
191  if (!_vao.vaoID())
192  {
193  SLfloat P[] = {-1, -1, 1, -1, -1, 1, 1, 1};
194  _vao.setAttrib(AT_position, 2, location, P);
195  _vao.generate(4);
196  }
197 
198  glActiveTexture(GL_TEXTURE0);
199  glBindTexture(GL_TEXTURE_2D, _texID);
200 
202 
203  glEnable(GL_DEPTH_TEST);
204 }
205 //-----------------------------------------------------------------------------
static SLint scrHeight
Window height at start up.
Definition: AppGLFW.cpp:38
static SLint scrWidth
Window width at start up.
Definition: AppGLFW.cpp:37
@ PF_rgba
Definition: CVImage.h:37
float SLfloat
Definition: SL.h:173
#define SL_EXIT_MSG(message)
Definition: SL.h:240
int SLint
Definition: SL.h:170
@ AT_position
Vertex position as a 2, 3 or 4 component vectors.
Definition: SLGLEnums.h:58
@ PT_triangleStrip
Definition: SLGLEnums.h:36
OpenGL Frame Buffer Object for the Oculus Rift Display.
Singleton class for global render state.
#define GET_GL_ERROR
Definition: SLGLState.h:56
void generateFBO()
void updateSize(SLint scrWidth, SLint scrHeight)
SLint _halfHeight
Half the width of the buffer.
Definition: SLGLOculusFB.h:49
SLuint _fbID
Half the height of the buffer.
Definition: SLGLOculusFB.h:50
SLint _height
Width of the buffer.
Definition: SLGLOculusFB.h:47
void bindFramebuffer(SLint scrWidth, SLint scrHeight)
void drawFramebuffer(SLGLProgram *stereoOculusProgram)
SLGLVertexArray _vao
OpenGL id of.
Definition: SLGLOculusFB.h:53
SLuint _depthRbID
OpenGL id of frame buffer.
Definition: SLGLOculusFB.h:51
SLint _halfWidth
Height of the buffer.
Definition: SLGLOculusFB.h:48
SLuint _texID
OpenGL id of depth render buffer.
Definition: SLGLOculusFB.h:52
Encapsulation of an OpenGL shader program object.
Definition: SLGLProgram.h:56
void useProgram()
void setAttrib(SLGLAttributeType type, SLint elementSize, SLint location, void *dataPointer, SLGLBufferType dataType=BT_float)
Adds a vertex attribute with data pointer and an element size.
void drawArrayAs(SLGLPrimitiveType primitiveType, SLint firstVertex=0, SLsizei countVertices=0)
Draws the VAO as an array with a primitive type.
SLuint vaoID() const
Returns either the VAO id or the VBO id.
void generate(SLuint numVertices, SLGLBufferUsage usage=BU_static, SLbool outputInterleaved=true, SLuint divisor=0)
Generates the VA & VB objects for a NO. of vertices.