Graham Long
Posted on March 28, 2020
The Aim
In order to display the same scene from two different viewpoints i.e. left eye and right eye, we need to render the scene to two different framebuffers and then apply each of these as a texture to a left and right quad.
The Setup
Prior to the development as part of this blog post, I started with a new Empty activity project targeting Android 8.1 and followed the Android developers Displaying graphics with openGL series to the point where I was drawing a triangle to the screen.
The following changes were made to the basic tutorial code:
- I created an
AbstractGameObject
class which implemented the common rendering code for the objects and the triangle class inherited from this class. - I changed the parent theme from
Theme.AppCompat.Light.DarkActionBar
toTheme.AppCompat.Light.NoActionBar
- I added the following snippet
window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE)
to the Activity's onCreate method to force full screen mode as per the [Android Developers guide to enabling full screen mode](https://developer.android.com/training/system-ui/immersive)
The source code can be found on my github repo as Tagged release B1.0
The Development
I started detailing every step of the development, but quickly decided that I would just focus on the key points, the final source code at the end of this development can be found on my github repo as Tagged release B1.1.
I did not use ThinMatrix's framebuffer objects tutorial as part of this development but when I was originally learning about rendering to framebuffers, this tutorial and others of his were great, so for anyone new to openGL the ThinMatrix youtube channel is where I would recommend starting.
As part of this development I merged the code from the following two tutorials, opengl-tutorial.org Render to texture tutorial and
pixel perfect Render to texture tutorial for the framebuffer rendering.
The AbstractTexturedGameObject
class
Similar to the Abstract Game Object class which I created in the B1.0 release, I generated an abstract class which will be inherited by any game objects which will be textured.
The Quads
Each Quad is defined in normalised device coordinates as defined in this ray casting tutorial, this means that each quad will be rendered to half the screen without applying any model, view or projection matrices Note the TexturedQuad
class inherits from the AbstractTexturedGameObject
class so an identity matrix is passed to the draw
function which has no effect on the vertices.
The Camera(s)
I created a GameCamera
class to define a camera position, look direction and up direction.
The main renderer instantiates two of these GameCamera
objects, one for the left eye and one for the right eye.
Having the GameCamera
class allowed me to reduce duplicated code by having a single drawScene
function which renders the current scene using the passed GameCamera
object Note the drawScene
function does not currently draw anything.
The Rendering
The VrRenderer
class's onDrawFrame
function has been changed to call a new drawSceneToFrameBuffer
function for each side of the screen
// Draw the left side
drawSceneToFrameBuffer(mLeftCamera,
mFrameBuffer[LEFT_FRAMEBUFFER_INDEX],
mRenderTexture[LEFT_FRAMEBUFFER_INDEX],
mDepthRenderBuffer[LEFT_FRAMEBUFFER_INDEX])
// and the right side
drawSceneToFrameBuffer(mRightCamera,
mFrameBuffer[RIGHT_FRAMEBUFFER_INDEX],
mRenderTexture[RIGHT_FRAMEBUFFER_INDEX],
mDepthRenderBuffer[RIGHT_FRAMEBUFFER_INDEX])
Each call to the drawSceneToFrameBuffer
function binds the passed framebuffer, sets the viewport to the framebuffer size, temporarily sets to clear colour for each framebuffer to a different colour, renders the scene using the drawScene
function before unbinding the framebuffer.
Finally, the viewport is reset back to the screen size before the left quad is drawn using the left texture and the right quad is rendered using the right texture.
// draw the quad with the generated textures.
mLeftQuad.draw(identityMatrix, mRenderTexture[LEFT_FRAMEBUFFER_INDEX])
mRightQuad.draw(identityMatrix, mRenderTexture[RIGHT_FRAMEBUFFER_INDEX])
The Outcome
At the end of all of this, I am rendering a green quad to the left side of the screen and a red quad to the right side of the screen, this may not look like much but it is the starting point for all the good stuff.
The next blog will detail drawing an actual 3D scene to each of the Quads.
Posted on March 28, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.