Browse Source

Redesigned stereo rendering mechanism

Now it's easier for the user! Just init Oculus device and get stereo
rendering!
Ray 9 years ago
parent
commit
ee72654b55
6 changed files with 251 additions and 236 deletions
  1. 2 9
      examples/core_oculus_rift.c
  2. 5 4
      examples/resources/shaders/glsl330/distortion.fs
  3. 5 13
      src/core.c
  4. 0 2
      src/raylib.h
  5. 239 204
      src/rlgl.c
  6. 0 4
      src/rlgl.h

+ 2 - 9
examples/core_oculus_rift.c

@@ -50,22 +50,15 @@ int main()
         // Draw
         // Draw
         //----------------------------------------------------------------------------------
         //----------------------------------------------------------------------------------
         BeginDrawing();
         BeginDrawing();
-        
+
             ClearBackground(RAYWHITE);
             ClearBackground(RAYWHITE);
-            
+
             Begin3dMode(camera);
             Begin3dMode(camera);
 
 
-            for (int eye = 0; eye < 2; eye++)
-            {
-                SetOculusView(eye);
-                
                 DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED);
                 DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED);
                 DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, MAROON);
                 DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, MAROON);
                 
                 
                 DrawGrid(10, 1.0f);
                 DrawGrid(10, 1.0f);
-
-                DrawDefaultBuffers();   // Process internal dynamic buffers
-            }
             
             
             End3dMode();
             End3dMode();
             
             

+ 5 - 4
examples/resources/shaders/glsl330/distortion.fs

@@ -10,12 +10,13 @@ uniform sampler2D texture0;
 out vec4 finalColor;
 out vec4 finalColor;
 
 
 // NOTE: Add here your custom variables
 // NOTE: Add here your custom variables
-const vec2 LeftLensCenter = vec2(0.2863248, 0.5);
-const vec2 RightLensCenter = vec2(0.7136753, 0.5);
+const vec2 LeftLensCenter = vec2(0.288, 0.5);
+const vec2 RightLensCenter = vec2(0.712, 0.5);
 const vec2 LeftScreenCenter = vec2(0.25, 0.5);
 const vec2 LeftScreenCenter = vec2(0.25, 0.5);
 const vec2 RightScreenCenter = vec2(0.75, 0.5);
 const vec2 RightScreenCenter = vec2(0.75, 0.5);
-const vec2 Scale = vec2(0.25, 0.45);    //vec2(0.1469278, 0.2350845);
-const vec2 ScaleIn = vec2(4, 2.2222);
+uniform vec2 Scale = vec2(0.25, 0.45);    //vec2(0.1469278, 0.2350845);
+uniform vec2 ScaleIn = vec2(4, 2.2222);
+
 const vec4 HmdWarpParam = vec4(1, 0.22, 0.24, 0);
 const vec4 HmdWarpParam = vec4(1, 0.22, 0.24, 0);
 const vec4 ChromaAbParam = vec4(0.996, -0.004, 1.014, 0.0);
 const vec4 ChromaAbParam = vec4(0.996, -0.004, 1.014, 0.0);
 
 

+ 5 - 13
src/core.c

@@ -520,6 +520,8 @@ void BeginDrawing(void)
     currentTime = GetTime();            // Number of elapsed seconds since InitTimer() was called
     currentTime = GetTime();            // Number of elapsed seconds since InitTimer() was called
     updateTime = currentTime - previousTime;
     updateTime = currentTime - previousTime;
     previousTime = currentTime;
     previousTime = currentTime;
+    
+    if (IsOculusReady()) BeginOculusDrawing();
 
 
     rlClearScreenBuffers();             // Clear current framebuffers
     rlClearScreenBuffers();             // Clear current framebuffers
     rlLoadIdentity();                   // Reset current matrix (MODELVIEW)
     rlLoadIdentity();                   // Reset current matrix (MODELVIEW)
@@ -533,6 +535,8 @@ void BeginDrawing(void)
 void EndDrawing(void)
 void EndDrawing(void)
 {
 {
     rlglDraw();                     // Draw Buffers (Only OpenGL 3+ and ES2)
     rlglDraw();                     // Draw Buffers (Only OpenGL 3+ and ES2)
+    
+    if (IsOculusReady()) EndOculusDrawing();
 
 
     SwapBuffers();                  // Copy back buffer to front buffer
     SwapBuffers();                  // Copy back buffer to front buffer
     PollInputEvents();              // Poll user events
     PollInputEvents();              // Poll user events
@@ -608,15 +612,11 @@ void Begin3dMode(Camera camera)
     rlMultMatrixf(MatrixToFloat(cameraView));      // Multiply MODELVIEW matrix by view matrix (camera)
     rlMultMatrixf(MatrixToFloat(cameraView));      // Multiply MODELVIEW matrix by view matrix (camera)
     
     
     rlEnableDepthTest();                // Enable DEPTH_TEST for 3D
     rlEnableDepthTest();                // Enable DEPTH_TEST for 3D
-    
-    if (IsOculusReady()) BeginOculusDrawing();
 }
 }
 
 
 // Ends 3D mode and returns to default 2D orthographic mode
 // Ends 3D mode and returns to default 2D orthographic mode
 void End3dMode(void)
 void End3dMode(void)
-{
-    if (IsOculusReady()) EndOculusDrawing();
-    
+{        
     rlglDraw();                         // Process internal buffers (update + draw)
     rlglDraw();                         // Process internal buffers (update + draw)
 
 
     rlMatrixMode(RL_PROJECTION);        // Switch to projection matrix
     rlMatrixMode(RL_PROJECTION);        // Switch to projection matrix
@@ -1021,14 +1021,6 @@ Matrix GetCameraMatrix(Camera camera)
     return MatrixLookAt(camera.position, camera.target, camera.up);
     return MatrixLookAt(camera.position, camera.target, camera.up);
 }
 }
 
 
-// Update and draw default buffers vertex data
-// NOTE: This data has been stored dynamically during frame on each Draw*() call
-void DrawDefaultBuffers(void)
-{
-    rlglUpdateDefaultBuffers(); // Upload frame vertex data to GPU
-    rlglDrawDefaultBuffers();   // Draw vertex data into framebuffer
-}
-
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
 // Module Functions Definition - Input (Keyboard, Mouse, Gamepad) Functions
 // Module Functions Definition - Input (Keyboard, Mouse, Gamepad) Functions
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------

+ 0 - 2
src/raylib.h

@@ -572,7 +572,6 @@ void EndTextureMode(void);                                  // Ends drawing to r
 Ray GetMouseRay(Vector2 mousePosition, Camera camera);      // Returns a ray trace from mouse position
 Ray GetMouseRay(Vector2 mousePosition, Camera camera);      // Returns a ray trace from mouse position
 Vector2 GetWorldToScreen(Vector3 position, Camera camera);  // Returns the screen space position from a 3d world space position
 Vector2 GetWorldToScreen(Vector3 position, Camera camera);  // Returns the screen space position from a 3d world space position
 Matrix GetCameraMatrix(Camera camera);                      // Returns camera transform matrix (view matrix)
 Matrix GetCameraMatrix(Camera camera);                      // Returns camera transform matrix (view matrix)
-void DrawDefaultBuffers(void);                              // Update and draw default buffers vertex data (stored dynamically in frame)
 
 
 void SetTargetFPS(int fps);                                 // Set target FPS (maximum)
 void SetTargetFPS(int fps);                                 // Set target FPS (maximum)
 float GetFPS(void);                                         // Returns current FPS
 float GetFPS(void);                                         // Returns current FPS
@@ -853,7 +852,6 @@ void DestroyLight(Light light);                                     // Destroy a
 void InitOculusDevice(void);                // Init Oculus Rift device
 void InitOculusDevice(void);                // Init Oculus Rift device
 void CloseOculusDevice(void);               // Close Oculus Rift device
 void CloseOculusDevice(void);               // Close Oculus Rift device
 void UpdateOculusTracking(void);            // Update Oculus Rift tracking (position and orientation)
 void UpdateOculusTracking(void);            // Update Oculus Rift tracking (position and orientation)
-void SetOculusView(int eye);                // Set internal projection and modelview matrix depending on eyes tracking data
 void BeginOculusDrawing(void);              // Begin Oculus drawing configuration
 void BeginOculusDrawing(void);              // Begin Oculus drawing configuration
 void EndOculusDrawing(void);                // End Oculus drawing process (and desktop mirror)
 void EndOculusDrawing(void);                // End Oculus drawing process (and desktop mirror)
 bool IsOculusReady(void);                   // Detect if oculus device (or simulator) is ready
 bool IsOculusReady(void);                   // Detect if oculus device (or simulator) is ready

+ 239 - 204
src/rlgl.c

@@ -276,9 +276,10 @@ static unsigned int frameIndex = 0;     // Oculus frames counter, used to discar
 static bool oculusReady = false;        // Oculus device ready flag
 static bool oculusReady = false;        // Oculus device ready flag
 static bool oculusSimulator = false;    // Oculus device simulator
 static bool oculusSimulator = false;    // Oculus device simulator
 static bool vrEnabled = false;          // VR experience enabled (Oculus device or simulator)
 static bool vrEnabled = false;          // VR experience enabled (Oculus device or simulator)
+static bool vrControl = true;          // VR controlled by user code, instead of internally
 
 
 static RenderTexture2D stereoFbo;
 static RenderTexture2D stereoFbo;
-static Shader distortion;
+static Shader distortionShader;
 
 
 // Compressed textures support flags
 // Compressed textures support flags
 static bool texCompDXTSupported = false;    // DDS texture compression support
 static bool texCompDXTSupported = false;    // DDS texture compression support
@@ -315,10 +316,13 @@ static void UnloadDefaultShader(void);      // Unload default shader
 static void UnloadStandardShader(void);     // Unload standard shader
 static void UnloadStandardShader(void);     // Unload standard shader
 
 
 static void LoadDefaultBuffers(void);       // Load default internal buffers (lines, triangles, quads)
 static void LoadDefaultBuffers(void);       // Load default internal buffers (lines, triangles, quads)
-void rlglUpdateDefaultBuffers(void);     // Update default internal buffers (VAOs/VBOs) with vertex data
-void rlglDrawDefaultBuffers(void);       // Draw default internal buffers vertex data
+static void UpdateDefaultBuffers(void);     // Update default internal buffers (VAOs/VBOs) with vertex data
+static void DrawDefaultBuffers(int eyesCount); // Draw default internal buffers vertex data
 static void UnloadDefaultBuffers(void);     // Unload default internal buffers vertex data from CPU and GPU
 static void UnloadDefaultBuffers(void);     // Unload default internal buffers vertex data from CPU and GPU
 
 
+// Set internal projection and modelview matrix depending on eyes tracking data
+static void SetOculusView(int eye, Matrix matProjection, Matrix matModelView);
+
 static void SetShaderLights(Shader shader); // Sets shader uniform values for lights array
 static void SetShaderLights(Shader shader); // Sets shader uniform values for lights array
 
 
 static char *ReadTextFile(const char *fileName);
 static char *ReadTextFile(const char *fileName);
@@ -1205,15 +1209,14 @@ void rlglClose(void)
 void rlglDraw(void)
 void rlglDraw(void)
 {
 {
 #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
 #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-/*
-    for (int i = 0; i < modelsCount; i++)
-    {
-        rlglDrawMesh(models[i]->mesh, models[i]->material, models[i]->transform);
-    }
-*/
-    // NOTE: Default buffers always drawn at the end
-    rlglUpdateDefaultBuffers();
-    rlglDrawDefaultBuffers();
+    // NOTE: In a future version, models could be stored in a stack...
+    //for (int i = 0; i < modelsCount; i++) rlglDrawMesh(models[i]->mesh, models[i]->material, models[i]->transform);
+
+    // NOTE: Default buffers upload and draw
+    UpdateDefaultBuffers();
+    
+    if (vrEnabled && vrControl) DrawDefaultBuffers(2);
+    else DrawDefaultBuffers(1);
 #endif
 #endif
 }
 }
 
 
@@ -1865,26 +1868,23 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform)
 #endif
 #endif
 
 
 #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
 #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
+    int eyesCount = 1;
+    if (vrEnabled) eyesCount = 2;
+
     glUseProgram(material.shader.id);
     glUseProgram(material.shader.id);
     
     
+    // Upload to shader material.colDiffuse
+    float vColorDiffuse[4] = { (float)material.colDiffuse.r/255, (float)material.colDiffuse.g/255, (float)material.colDiffuse.b/255, (float)material.colDiffuse.a/255 };
+    glUniform4fv(material.shader.tintColorLoc, 1, vColorDiffuse);
+    
     // At this point the modelview matrix just contains the view matrix (camera)
     // At this point the modelview matrix just contains the view matrix (camera)
     // That's because Begin3dMode() sets it an no model-drawing function modifies it, all use rlPushMatrix() and rlPopMatrix()
     // That's because Begin3dMode() sets it an no model-drawing function modifies it, all use rlPushMatrix() and rlPopMatrix()
     Matrix matView = modelview;         // View matrix (camera)
     Matrix matView = modelview;         // View matrix (camera)
     Matrix matProjection = projection;  // Projection matrix (perspective)
     Matrix matProjection = projection;  // Projection matrix (perspective)
-
+    
     // Calculate model-view matrix combining matModel and matView
     // Calculate model-view matrix combining matModel and matView
     Matrix matModelView = MatrixMultiply(transform, matView);           // Transform to camera-space coordinates
     Matrix matModelView = MatrixMultiply(transform, matView);           // Transform to camera-space coordinates
 
 
-    // Calculate model-view-projection matrix (MVP)
-    Matrix matMVP = MatrixMultiply(matModelView, matProjection);        // Transform to screen-space coordinates
-
-    // Send combined model-view-projection matrix to shader
-    glUniformMatrix4fv(material.shader.mvpLoc, 1, false, MatrixToFloat(matMVP));
-    
-    // Upload to shader material.colDiffuse
-    float vColorDiffuse[4] = { (float)material.colDiffuse.r/255, (float)material.colDiffuse.g/255, (float)material.colDiffuse.b/255, (float)material.colDiffuse.a/255 };
-    glUniform4fv(material.shader.tintColorLoc, 1, vColorDiffuse);
-
     // Check if using standard shader to get location points
     // Check if using standard shader to get location points
     // NOTE: standard shader specific locations are got at render time to keep Shader struct as simple as possible (with just default shader locations)
     // NOTE: standard shader specific locations are got at render time to keep Shader struct as simple as possible (with just default shader locations)
     if (material.shader.id == standardShader.id)
     if (material.shader.id == standardShader.id)
@@ -1989,9 +1989,20 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform)
         if (mesh.indices != NULL) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quads.vboId[3]);
         if (mesh.indices != NULL) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quads.vboId[3]);
     }
     }
 
 
-    // Draw call!
-    if (mesh.indices != NULL) glDrawElements(GL_TRIANGLES, mesh.triangleCount*3, GL_UNSIGNED_SHORT, 0); // Indexed vertices draw
-    else glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount);
+    for (int eye = 0; eye < eyesCount; eye++)
+    {
+        if (eyesCount == 2) SetOculusView(eye, matProjection, matModelView);
+
+        // Calculate model-view-projection matrix (MVP)
+        Matrix matMVP = MatrixMultiply(modelview, projection);        // Transform to screen-space coordinates
+
+        // Send combined model-view-projection matrix to shader
+        glUniformMatrix4fv(material.shader.mvpLoc, 1, false, MatrixToFloat(matMVP));
+
+        // Draw call!
+        if (mesh.indices != NULL) glDrawElements(GL_TRIANGLES, mesh.triangleCount*3, GL_UNSIGNED_SHORT, 0); // Indexed vertices draw
+        else glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount);
+    }
     
     
     if (material.texNormal.id != 0)
     if (material.texNormal.id != 0)
     {
     {
@@ -2016,6 +2027,10 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform)
     }
     }
 
 
     glUseProgram(0);        // Unbind shader program
     glUseProgram(0);        // Unbind shader program
+    
+    // Restore projection/modelview matrices
+    projection = matProjection;
+    modelview = matView;
 #endif
 #endif
 }
 }
 
 
@@ -2538,7 +2553,7 @@ void InitOculusDevice(void)
         
         
         // Load oculus-distortion shader (oculus parameters setup internally)
         // Load oculus-distortion shader (oculus parameters setup internally)
         // TODO: Embed coulus distortion shader (in this function like default shader?)
         // TODO: Embed coulus distortion shader (in this function like default shader?)
-        distortion = LoadShader("resources/shaders/glsl330/base.vs", "resources/shaders/glsl330/distortion.fs");
+        distortionShader = LoadShader("resources/shaders/glsl330/base.vs", "resources/shaders/glsl330/distortion.fs");
         
         
         oculusSimulator = true;
         oculusSimulator = true;
         vrEnabled = true;
         vrEnabled = true;
@@ -2564,7 +2579,7 @@ void CloseOculusDevice(void)
         rlDeleteRenderTextures(stereoFbo);
         rlDeleteRenderTextures(stereoFbo);
         
         
         // Unload oculus-distortion shader
         // Unload oculus-distortion shader
-        UnloadShader(distortion);
+        UnloadShader(distortionShader);
     }
     }
     
     
     oculusReady = false;
     oculusReady = false;
@@ -2615,13 +2630,13 @@ void UpdateOculusTracking(void)
 }
 }
 
 
 // Set internal projection and modelview matrix depending on eyes tracking data
 // Set internal projection and modelview matrix depending on eyes tracking data
-void SetOculusView(int eye)
-{
-    Matrix eyeProjection;
-    Matrix eyeModelView;
-    
+static void SetOculusView(int eye, Matrix matProjection, Matrix matModelView)
+{   
     if (vrEnabled)
     if (vrEnabled)
     {
     {
+        Matrix eyeProjection = matProjection;
+        Matrix eyeModelView = matModelView;
+        
 #if defined(RLGL_OCULUS_SUPPORT)
 #if defined(RLGL_OCULUS_SUPPORT)
         if (oculusReady)
         if (oculusReady)
         {
         {
@@ -2639,10 +2654,8 @@ void SetOculusView(int eye)
                                                     -layer.eyeLayer.RenderPose[eye].Position.z);
                                                     -layer.eyeLayer.RenderPose[eye].Position.z);
 
 
             Matrix eyeView = MatrixMultiply(eyeTranslation, eyeOrientation);    // Matrix containing eye-head movement
             Matrix eyeView = MatrixMultiply(eyeTranslation, eyeOrientation);    // Matrix containing eye-head movement
-            eyeModelView = MatrixMultiply(modelview, eyeView);           // Combine internal camera matrix (modelview) wih eye-head movement
+            eyeModelView = MatrixMultiply(matModelView, eyeView);               // Combine internal camera matrix (modelview) wih eye-head movement
 
 
-            // TODO: Find a better way to get camera view matrix (instead of using internal modelview)
-            
             eyeProjection = layer.eyeProjections[eye];
             eyeProjection = layer.eyeProjections[eye];
         }
         }
         else
         else
@@ -2651,28 +2664,43 @@ void SetOculusView(int eye)
             // Setup viewport and projection/modelview matrices using tracking data
             // Setup viewport and projection/modelview matrices using tracking data
             rlViewport(eye*screenWidth/2, 0, screenWidth/2, screenHeight);
             rlViewport(eye*screenWidth/2, 0, screenWidth/2, screenHeight);
             
             
-            float hmdIPD = 0.064f;
-            float hmdHScreenSize = 0.14976f;
-            float hmdVScreenSize = 0.0936f;
-            //float hmdVScreenCenter = 0.04675f;
-            float hmdEyeToScreenDistance = 0.041f;
-            float hmdLensSeparationDistance = 0.064f;
+            static float IPD = 0.064f;       // InterpupillaryDistance
+            float HScreenSize = 0.14976f;
+            float VScreenSize = 0.0936f;     // HScreenSize/(1280.0f/800.0f)
+            float VScreenCenter = 0.04675f;
+            float EyeToScreenDistance = 0.041f;
+            float LensSeparationDistance = 0.064f; //0.0635f (DK1)
             
             
-            //NOTE: fovy value hardcoded to 60 degrees (Oculus Rift CV1 vertical FOV is 100 degrees)
-            //float halfScreenDistance = hmdVScreenSize/2.0f;
-            //float yfov = 2.0f*atan(halfScreenDistance/hmdEyeToScreenDistance);
-
-            float viewCenter = (float)hmdHScreenSize*0.25f;
-            float eyeProjectionShift = viewCenter - hmdLensSeparationDistance*0.5f;
-            float projectionCenterOffset = 4.0f*eyeProjectionShift/(float)hmdHScreenSize;
-
+            // NOTE: fovy value obtained from device parameters (Oculus Rift CV1)
+            float halfScreenDistance = VScreenSize/2.0f;
+            float fovy = 2.0f*atan(halfScreenDistance/EyeToScreenDistance)*RAD2DEG;
+
+            float viewCenter = (float)HScreenSize*0.25f;
+            float eyeProjectionShift = viewCenter - LensSeparationDistance*0.5f;
+            float projectionCenterOffset = 4.0f*eyeProjectionShift/(float)HScreenSize;
+/*            
+            static float scale[2] = { 0.25, 0.45 };
+
+            if (IsKeyDown(KEY_RIGHT)) scale[0] += 0.01;
+            else if (IsKeyDown(KEY_LEFT)) scale[0] -= 0.01;
+            else if (IsKeyDown(KEY_UP)) scale[1] += 0.01;
+            else if (IsKeyDown(KEY_DOWN)) scale[1] -= 0.01;
             
             
+            SetShaderValue(distortionShader, GetShaderLocation(distortionShader, "Scale"), scale, 2);
+
+            if (IsKeyDown(KEY_N)) IPD += 0.02;
+            else if (IsKeyDown(KEY_M)) IPD -= 0.02;
+*/            
             // The matrixes for offsetting the projection and view for each eye, to achieve stereo effect
             // The matrixes for offsetting the projection and view for each eye, to achieve stereo effect
             Vector3 projectionOffset = { -projectionCenterOffset, 0.0f, 0.0f };
             Vector3 projectionOffset = { -projectionCenterOffset, 0.0f, 0.0f };
-            Vector3 viewOffset = { -hmdIPD/2.0f, 0.0f, 0.0f };
+            
+            // Camera movement might seem more natural if we model the head. 
+            // Our axis of rotation is the base of our head, so we might want to add 
+            // some y (base of head to eye level) and -z (center of head to eye protrusion) to the camera positions.
+            Vector3 viewOffset = { -IPD/2.0f, 0.075f, 0.045f };
 
 
             // Negate the left eye versions
             // Negate the left eye versions
-            if (eye == 1)
+            if (eye == 0)
             {
             {
                 projectionOffset.x *= -1.0f;
                 projectionOffset.x *= -1.0f;
                 viewOffset.x *= -1.0f;
                 viewOffset.x *= -1.0f;
@@ -2680,29 +2708,18 @@ void SetOculusView(int eye)
 
 
             // Adjust the view and projection matrixes
             // Adjust the view and projection matrixes
             // View matrix is translated based on the eye offset
             // View matrix is translated based on the eye offset
-            Matrix projCenter = MatrixPerspective(60.0, (double)((float)screenWidth*0.5f)/(double)screenHeight, 0.01, 1000.0);
+            Matrix projCenter = MatrixPerspective(fovy, (double)((float)screenWidth*0.5f)/(double)screenHeight, 0.01, 1000.0);
 
 
             Matrix projTranslation = MatrixTranslate(projectionOffset.x, projectionOffset.y, projectionOffset.z);
             Matrix projTranslation = MatrixTranslate(projectionOffset.x, projectionOffset.y, projectionOffset.z);
             Matrix viewTranslation = MatrixTranslate(viewOffset.x, viewOffset.y, viewOffset.z);
             Matrix viewTranslation = MatrixTranslate(viewOffset.x, viewOffset.y, viewOffset.z);
 
 
             eyeProjection = MatrixMultiply(projCenter, projTranslation);    // projection
             eyeProjection = MatrixMultiply(projCenter, projTranslation);    // projection
-            eyeModelView = MatrixMultiply(modelview, viewTranslation);      // modelview
+            eyeModelView = MatrixMultiply(matModelView, viewTranslation);   // modelview
             
             
             MatrixTranspose(&eyeProjection);
             MatrixTranspose(&eyeProjection);
-
-            /*
-            // NOTE: fovy value hardcoded to 60 degrees (Oculus Rift CV1 vertical FOV is 100 degrees)
-            eyeProjection = MatrixPerspective(60.0, (double)(screenWidth/2)/(double)screenHeight, 0.01, 1000.0);
-            MatrixTranspose(&eyeProjection);
-            
-            // TODO: Compute eyes IPD and apply to current modelview matrix (camera)
-            Matrix eyeView = MatrixIdentity();
-            
-            eyeModelView = MatrixMultiply(modelview, eyeView);
-            */
         }
         }
 
 
-        SetMatrixModelview(eyeModelView);
+        SetMatrixModelview(eyeModelView);       // ERROR! We are modifying modelview for next eye!!!
         SetMatrixProjection(eyeProjection);
         SetMatrixProjection(eyeProjection);
     }
     }
 }
 }
@@ -2738,6 +2755,8 @@ void BeginOculusDrawing(void)
     
     
     //glViewport(0, 0, buffer.width, buffer.height);        // Useful if rendering to separate framebuffers (every eye)
     //glViewport(0, 0, buffer.width, buffer.height);        // Useful if rendering to separate framebuffers (every eye)
     rlClearScreenBuffers();             // Clear current framebuffer(s)
     rlClearScreenBuffers();             // Clear current framebuffer(s)
+    
+    vrControl = true;
 }
 }
 
 
 // End Oculus drawing process (and desktop mirror)
 // End Oculus drawing process (and desktop mirror)
@@ -2777,40 +2796,44 @@ void EndOculusDrawing(void)
         rlLoadIdentity();                                       // Reset internal modelview matrix
         rlLoadIdentity();                                       // Reset internal modelview matrix
 
 
         // Draw RenderTexture (stereoFbo) using distortion shader 
         // Draw RenderTexture (stereoFbo) using distortion shader 
-        BeginShaderMode(distortion);
+        currentShader = distortionShader;
 
 
-            rlEnableTexture(stereoFbo.texture.id);
+        rlEnableTexture(stereoFbo.texture.id);
 
 
-            rlPushMatrix();
-                rlBegin(RL_QUADS);
-                    rlColor4ub(255, 255, 255, 255);
-                    rlNormal3f(0.0f, 0.0f, 1.0f);
+        rlPushMatrix();
+            rlBegin(RL_QUADS);
+                rlColor4ub(255, 255, 255, 255);
+                rlNormal3f(0.0f, 0.0f, 1.0f);
 
 
-                    // Bottom-left corner for texture and quad
-                    rlTexCoord2f(0.0f, 1.0f);
-                    rlVertex2f(0.0f, 0.0f);
+                // Bottom-left corner for texture and quad
+                rlTexCoord2f(0.0f, 1.0f);
+                rlVertex2f(0.0f, 0.0f);
 
 
-                    // Bottom-right corner for texture and quad
-                    rlTexCoord2f(0.0f, 0.0f);
-                    rlVertex2f(0.0f, stereoFbo.texture.height);
+                // Bottom-right corner for texture and quad
+                rlTexCoord2f(0.0f, 0.0f);
+                rlVertex2f(0.0f, stereoFbo.texture.height);
 
 
-                    // Top-right corner for texture and quad
-                    rlTexCoord2f(1.0f, 0.0f);
-                    rlVertex2f(stereoFbo.texture.width, stereoFbo.texture.height);
+                // Top-right corner for texture and quad
+                rlTexCoord2f(1.0f, 0.0f);
+                rlVertex2f(stereoFbo.texture.width, stereoFbo.texture.height);
 
 
-                    // Top-left corner for texture and quad
-                    rlTexCoord2f(1.0f, 1.0f);
-                    rlVertex2f(stereoFbo.texture.width, 0.0f);
-                rlEnd();
-            rlPopMatrix();
+                // Top-left corner for texture and quad
+                rlTexCoord2f(1.0f, 1.0f);
+                rlVertex2f(stereoFbo.texture.width, 0.0f);
+            rlEnd();
+        rlPopMatrix();
 
 
-            rlDisableTexture();
-            
-            //rlglDraw();
-        EndShaderMode();
+        rlDisableTexture();
+
+        UpdateDefaultBuffers();
+        DrawDefaultBuffers(1);
+
+        currentShader = defaultShader;
     }
     }
 
 
     rlDisableDepthTest();
     rlDisableDepthTest();
+    
+    vrControl = false;
 }
 }
 
 
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
@@ -3303,7 +3326,7 @@ static void LoadDefaultBuffers(void)
 // Update default internal buffers (VAOs/VBOs) with vertex array data
 // Update default internal buffers (VAOs/VBOs) with vertex array data
 // NOTE: If there is not vertex data, buffers doesn't need to be updated (vertexCount > 0)
 // NOTE: If there is not vertex data, buffers doesn't need to be updated (vertexCount > 0)
 // TODO: If no data changed on the CPU arrays --> No need to re-update GPU arrays (change flag required)
 // TODO: If no data changed on the CPU arrays --> No need to re-update GPU arrays (change flag required)
-void rlglUpdateDefaultBuffers(void)
+static void UpdateDefaultBuffers(void)
 {
 {
     // Update lines vertex buffers
     // Update lines vertex buffers
     if (lines.vCounter > 0)
     if (lines.vCounter > 0)
@@ -3373,146 +3396,154 @@ void rlglUpdateDefaultBuffers(void)
 
 
 // Draw default internal buffers vertex data
 // Draw default internal buffers vertex data
 // NOTE: We draw in this order: lines, triangles, quads
 // NOTE: We draw in this order: lines, triangles, quads
-void rlglDrawDefaultBuffers(void)
+static void DrawDefaultBuffers(int eyesCount)
 {
 {
-    // Set current shader and upload current MVP matrix
-    if ((lines.vCounter > 0) || (triangles.vCounter > 0) || (quads.vCounter > 0))
-    {
-        glUseProgram(currentShader.id);
-        
-        // Create modelview-projection matrix
-        Matrix matMVP = MatrixMultiply(modelview, projection);
-
-        glUniformMatrix4fv(currentShader.mvpLoc, 1, false, MatrixToFloat(matMVP));
-        glUniform4f(currentShader.tintColorLoc, 1.0f, 1.0f, 1.0f, 1.0f);
-        glUniform1i(currentShader.mapTexture0Loc, 0);
-        
-        // NOTE: Additional map textures not considered for default buffers drawing
-    }
-   
-    // Draw lines buffers
-    if (lines.vCounter > 0)
+    Matrix matProjection = projection;
+    Matrix matModelView = modelview;
+    
+    for (int eye = 0; eye < eyesCount; eye++)
     {
     {
-        glBindTexture(GL_TEXTURE_2D, whiteTexture);
+        if (eyesCount == 2) SetOculusView(eye, matProjection, matModelView);
 
 
-        if (vaoSupported)
+        // Set current shader and upload current MVP matrix
+        if ((lines.vCounter > 0) || (triangles.vCounter > 0) || (quads.vCounter > 0))
         {
         {
-            glBindVertexArray(lines.vaoId);
+            glUseProgram(currentShader.id);
+            
+            // Create modelview-projection matrix
+            Matrix matMVP = MatrixMultiply(modelview, projection);
+
+            glUniformMatrix4fv(currentShader.mvpLoc, 1, false, MatrixToFloat(matMVP));
+            glUniform4f(currentShader.tintColorLoc, 1.0f, 1.0f, 1.0f, 1.0f);
+            glUniform1i(currentShader.mapTexture0Loc, 0);
+            
+            // NOTE: Additional map textures not considered for default buffers drawing
         }
         }
-        else
+       
+        // Draw lines buffers
+        if (lines.vCounter > 0)
         {
         {
-            // Bind vertex attrib: position (shader-location = 0)
-            glBindBuffer(GL_ARRAY_BUFFER, lines.vboId[0]);
-            glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
-            glEnableVertexAttribArray(currentShader.vertexLoc);
-
-            // Bind vertex attrib: color (shader-location = 3)
-            glBindBuffer(GL_ARRAY_BUFFER, lines.vboId[1]);
-            glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
-            glEnableVertexAttribArray(currentShader.colorLoc);
-        }
+            glBindTexture(GL_TEXTURE_2D, whiteTexture);
 
 
-        glDrawArrays(GL_LINES, 0, lines.vCounter);
-
-        if (!vaoSupported) glBindBuffer(GL_ARRAY_BUFFER, 0);
-        glBindTexture(GL_TEXTURE_2D, 0);
-    }
+            if (vaoSupported)
+            {
+                glBindVertexArray(lines.vaoId);
+            }
+            else
+            {
+                // Bind vertex attrib: position (shader-location = 0)
+                glBindBuffer(GL_ARRAY_BUFFER, lines.vboId[0]);
+                glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
+                glEnableVertexAttribArray(currentShader.vertexLoc);
+
+                // Bind vertex attrib: color (shader-location = 3)
+                glBindBuffer(GL_ARRAY_BUFFER, lines.vboId[1]);
+                glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
+                glEnableVertexAttribArray(currentShader.colorLoc);
+            }
 
 
-    // Draw triangles buffers
-    if (triangles.vCounter > 0)
-    {
-        glBindTexture(GL_TEXTURE_2D, whiteTexture);
+            glDrawArrays(GL_LINES, 0, lines.vCounter);
 
 
-        if (vaoSupported)
-        {
-            glBindVertexArray(triangles.vaoId);
-        }
-        else
-        {
-            // Bind vertex attrib: position (shader-location = 0)
-            glBindBuffer(GL_ARRAY_BUFFER, triangles.vboId[0]);
-            glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
-            glEnableVertexAttribArray(currentShader.vertexLoc);
-
-            // Bind vertex attrib: color (shader-location = 3)
-            glBindBuffer(GL_ARRAY_BUFFER, triangles.vboId[1]);
-            glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
-            glEnableVertexAttribArray(currentShader.colorLoc);
+            if (!vaoSupported) glBindBuffer(GL_ARRAY_BUFFER, 0);
+            glBindTexture(GL_TEXTURE_2D, 0);
         }
         }
 
 
-        glDrawArrays(GL_TRIANGLES, 0, triangles.vCounter);
+        // Draw triangles buffers
+        if (triangles.vCounter > 0)
+        {
+            glBindTexture(GL_TEXTURE_2D, whiteTexture);
 
 
-        if (!vaoSupported) glBindBuffer(GL_ARRAY_BUFFER, 0);
-        glBindTexture(GL_TEXTURE_2D, 0);
-    }
+            if (vaoSupported)
+            {
+                glBindVertexArray(triangles.vaoId);
+            }
+            else
+            {
+                // Bind vertex attrib: position (shader-location = 0)
+                glBindBuffer(GL_ARRAY_BUFFER, triangles.vboId[0]);
+                glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
+                glEnableVertexAttribArray(currentShader.vertexLoc);
+
+                // Bind vertex attrib: color (shader-location = 3)
+                glBindBuffer(GL_ARRAY_BUFFER, triangles.vboId[1]);
+                glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
+                glEnableVertexAttribArray(currentShader.colorLoc);
+            }
 
 
-    // Draw quads buffers
-    if (quads.vCounter > 0)
-    {
-        int quadsCount = 0;
-        int numIndicesToProcess = 0;
-        int indicesOffset = 0;
+            glDrawArrays(GL_TRIANGLES, 0, triangles.vCounter);
 
 
-        if (vaoSupported)
-        {
-            glBindVertexArray(quads.vaoId);
+            if (!vaoSupported) glBindBuffer(GL_ARRAY_BUFFER, 0);
+            glBindTexture(GL_TEXTURE_2D, 0);
         }
         }
-        else
+
+        // Draw quads buffers
+        if (quads.vCounter > 0)
         {
         {
-            // Bind vertex attrib: position (shader-location = 0)
-            glBindBuffer(GL_ARRAY_BUFFER, quads.vboId[0]);
-            glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
-            glEnableVertexAttribArray(currentShader.vertexLoc);
-
-            // Bind vertex attrib: texcoord (shader-location = 1)
-            glBindBuffer(GL_ARRAY_BUFFER, quads.vboId[1]);
-            glVertexAttribPointer(currentShader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0);
-            glEnableVertexAttribArray(currentShader.texcoordLoc);
-
-            // Bind vertex attrib: color (shader-location = 3)
-            glBindBuffer(GL_ARRAY_BUFFER, quads.vboId[2]);
-            glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
-            glEnableVertexAttribArray(currentShader.colorLoc);
-            
-            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quads.vboId[3]);
-        }
+            int quadsCount = 0;
+            int numIndicesToProcess = 0;
+            int indicesOffset = 0;
 
 
-        //TraceLog(DEBUG, "Draws required per frame: %i", drawsCounter);
+            if (vaoSupported)
+            {
+                glBindVertexArray(quads.vaoId);
+            }
+            else
+            {
+                // Bind vertex attrib: position (shader-location = 0)
+                glBindBuffer(GL_ARRAY_BUFFER, quads.vboId[0]);
+                glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
+                glEnableVertexAttribArray(currentShader.vertexLoc);
+
+                // Bind vertex attrib: texcoord (shader-location = 1)
+                glBindBuffer(GL_ARRAY_BUFFER, quads.vboId[1]);
+                glVertexAttribPointer(currentShader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0);
+                glEnableVertexAttribArray(currentShader.texcoordLoc);
+
+                // Bind vertex attrib: color (shader-location = 3)
+                glBindBuffer(GL_ARRAY_BUFFER, quads.vboId[2]);
+                glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
+                glEnableVertexAttribArray(currentShader.colorLoc);
+                
+                glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quads.vboId[3]);
+            }
 
 
-        for (int i = 0; i < drawsCounter; i++)
-        {
-            quadsCount = draws[i].vertexCount/4;
-            numIndicesToProcess = quadsCount*6;  // Get number of Quads * 6 index by Quad
+            //TraceLog(DEBUG, "Draws required per frame: %i", drawsCounter);
 
 
-            //TraceLog(DEBUG, "Quads to render: %i - Vertex Count: %i", quadsCount, draws[i].vertexCount);
+            for (int i = 0; i < drawsCounter; i++)
+            {
+                quadsCount = draws[i].vertexCount/4;
+                numIndicesToProcess = quadsCount*6;  // Get number of Quads * 6 index by Quad
 
 
-            glBindTexture(GL_TEXTURE_2D, draws[i].textureId);
+                //TraceLog(DEBUG, "Quads to render: %i - Vertex Count: %i", quadsCount, draws[i].vertexCount);
 
 
-            // NOTE: The final parameter tells the GPU the offset in bytes from the start of the index buffer to the location of the first index to process
-#if defined(GRAPHICS_API_OPENGL_33)
-            glDrawElements(GL_TRIANGLES, numIndicesToProcess, GL_UNSIGNED_INT, (GLvoid *)(sizeof(GLuint)*indicesOffset));
-#elif defined(GRAPHICS_API_OPENGL_ES2)
-            glDrawElements(GL_TRIANGLES, numIndicesToProcess, GL_UNSIGNED_SHORT, (GLvoid *)(sizeof(GLushort)*indicesOffset));
-#endif
-            //GLenum err;
-            //if ((err = glGetError()) != GL_NO_ERROR) TraceLog(INFO, "OpenGL error: %i", (int)err);    //GL_INVALID_ENUM!
+                glBindTexture(GL_TEXTURE_2D, draws[i].textureId);
 
 
-            indicesOffset += draws[i].vertexCount/4*6;
-        }
+                // NOTE: The final parameter tells the GPU the offset in bytes from the start of the index buffer to the location of the first index to process
+    #if defined(GRAPHICS_API_OPENGL_33)
+                glDrawElements(GL_TRIANGLES, numIndicesToProcess, GL_UNSIGNED_INT, (GLvoid *)(sizeof(GLuint)*indicesOffset));
+    #elif defined(GRAPHICS_API_OPENGL_ES2)
+                glDrawElements(GL_TRIANGLES, numIndicesToProcess, GL_UNSIGNED_SHORT, (GLvoid *)(sizeof(GLushort)*indicesOffset));
+    #endif
+                //GLenum err;
+                //if ((err = glGetError()) != GL_NO_ERROR) TraceLog(INFO, "OpenGL error: %i", (int)err);    //GL_INVALID_ENUM!
 
 
-        if (!vaoSupported)
-        {
-            glBindBuffer(GL_ARRAY_BUFFER, 0);
-            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
-        }
+                indicesOffset += draws[i].vertexCount/4*6;
+            }
 
 
-        glBindTexture(GL_TEXTURE_2D, 0);  // Unbind textures
-    }
+            if (!vaoSupported)
+            {
+                glBindBuffer(GL_ARRAY_BUFFER, 0);
+                glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+            }
 
 
-    if (vaoSupported) glBindVertexArray(0);   // Unbind VAO
+            glBindTexture(GL_TEXTURE_2D, 0);  // Unbind textures
+        }
 
 
-    glUseProgram(0);    // Unbind shader program
+        if (vaoSupported) glBindVertexArray(0);   // Unbind VAO
 
 
+        glUseProgram(0);    // Unbind shader program
+    }
+    
     // Reset draws counter
     // Reset draws counter
     drawsCounter = 1;
     drawsCounter = 1;
     draws[0].textureId = whiteTexture;
     draws[0].textureId = whiteTexture;
@@ -3529,6 +3560,10 @@ void rlglDrawDefaultBuffers(void)
     
     
     // Reset depth for next draw
     // Reset depth for next draw
     currentDepth = -1.0f;
     currentDepth = -1.0f;
+    
+    // Restore projection/modelview matrices
+    projection = matProjection;
+    modelview = matModelView;
 }
 }
 
 
 // Unload default internal buffers vertex data from CPU and GPU
 // Unload default internal buffers vertex data from CPU and GPU

+ 0 - 4
src/rlgl.h

@@ -303,9 +303,6 @@ void rlglClose(void);                           // De-init rlgl
 void rlglDraw(void);                            // Draw VAO/VBO
 void rlglDraw(void);                            // Draw VAO/VBO
 void rlglLoadExtensions(void *loader);          // Load OpenGL extensions
 void rlglLoadExtensions(void *loader);          // Load OpenGL extensions
 
 
-void rlglUpdateDefaultBuffers(void);            // Update default internal buffers (VAOs/VBOs) with vertex data
-void rlglDrawDefaultBuffers(void);              // Draw default internal buffers vertex data
-
 unsigned int rlglLoadTexture(void *data, int width, int height, int textureFormat, int mipmapCount);    // Load texture in GPU
 unsigned int rlglLoadTexture(void *data, int width, int height, int textureFormat, int mipmapCount);    // Load texture in GPU
 RenderTexture2D rlglLoadRenderTexture(int width, int height);   // Load a texture to be used for rendering (fbo with color and depth attachments)
 RenderTexture2D rlglLoadRenderTexture(int width, int height);   // Load a texture to be used for rendering (fbo with color and depth attachments)
 void rlglUpdateTexture(unsigned int id, int width, int height, int format, void *data);         // Update GPU texture with new data
 void rlglUpdateTexture(unsigned int id, int width, int height, int format, void *data);         // Update GPU texture with new data
@@ -358,7 +355,6 @@ void TraceLog(int msgType, const char *text, ...);
 void InitOculusDevice(void);                // Init Oculus Rift device
 void InitOculusDevice(void);                // Init Oculus Rift device
 void CloseOculusDevice(void);               // Close Oculus Rift device
 void CloseOculusDevice(void);               // Close Oculus Rift device
 void UpdateOculusTracking(void);            // Update Oculus Rift tracking (position and orientation)
 void UpdateOculusTracking(void);            // Update Oculus Rift tracking (position and orientation)
-void SetOculusView(int eye);                // Set internal projection and modelview matrix depending on eyes tracking data
 void BeginOculusDrawing(void);              // Begin Oculus drawing configuration
 void BeginOculusDrawing(void);              // Begin Oculus drawing configuration
 void EndOculusDrawing(void);                // End Oculus drawing process (and desktop mirror)
 void EndOculusDrawing(void);                // End Oculus drawing process (and desktop mirror)
 bool IsOculusReady(void);                   // Detect if oculus device (or simulator) is ready
 bool IsOculusReady(void);                   // Detect if oculus device (or simulator) is ready