Browse Source

BIG CHANGE: REDESIGNED: Vr device simulator #1582

Vr simulator has been moved to core module and completely redesigned. Now user is in charge of stereo-render fbo and also in full control of distortion shader. Code is a bit more complex but better aligned with other raylib examples.
Ray 4 years ago
parent
commit
a76fcaba3e
5 changed files with 301 additions and 404 deletions
  1. 54 38
      examples/core/core_vr_simulator.c
  2. 3 6
      src/config.h
  3. 154 1
      src/core.c
  4. 25 15
      src/raylib.h
  5. 65 344
      src/rlgl.h

+ 54 - 38
examples/core/core_vr_simulator.c

@@ -2,10 +2,10 @@
 *
 *
 *   raylib [core] example - VR Simulator (Oculus Rift CV1 parameters)
 *   raylib [core] example - VR Simulator (Oculus Rift CV1 parameters)
 *
 *
-*   This example has been created using raylib 1.7 (www.raylib.com)
+*   This example has been created using raylib 3.6-dev (www.raylib.com)
 *   raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
 *   raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
 *
 *
-*   Copyright (c) 2017 Ramon Santamaria (@raysan5)
+*   Copyright (c) 2017-2021 Ramon Santamaria (@raysan5)
 *
 *
 ********************************************************************************************/
 ********************************************************************************************/
 
 
@@ -25,40 +25,55 @@ int main(void)
     const int screenHeight = 450;
     const int screenHeight = 450;
 
 
     // NOTE: screenWidth/screenHeight should match VR device aspect ratio
     // NOTE: screenWidth/screenHeight should match VR device aspect ratio
-
-    SetConfigFlags(FLAG_MSAA_4X_HINT);
     InitWindow(screenWidth, screenHeight, "raylib [core] example - vr simulator");
     InitWindow(screenWidth, screenHeight, "raylib [core] example - vr simulator");
 
 
+    // VR device parameters definition
+    VrDeviceInfo device = {
+        // Oculus Rift CV1 parameters for simulator
+        .hResolution = 2160,                 // Horizontal resolution in pixels
+        .vResolution = 1200,                 // Vertical resolution in pixels
+        .hScreenSize = 0.133793f,            // Horizontal size in meters
+        .vScreenSize = 0.0669f,              // Vertical size in meters
+        .vScreenCenter = 0.04678f,           // Screen center in meters
+        .eyeToScreenDistance = 0.041f,       // Distance between eye and display in meters
+        .lensSeparationDistance = 0.07f,     // Lens separation distance in meters
+        .interpupillaryDistance = 0.07f,     // IPD (distance between pupils) in meters
+    
+        // NOTE: CV1 uses a Fresnel-hybrid-asymmetric lenses with specific distortion compute shaders
+        // Following parameters are an approximation to distortion stereo rendering but results differ from actual device
+        .lensDistortionValues[0] = 1.0f,     // Lens distortion constant parameter 0
+        .lensDistortionValues[1] = 0.22f,    // Lens distortion constant parameter 1
+        .lensDistortionValues[2] = 0.24f,    // Lens distortion constant parameter 2
+        .lensDistortionValues[3] = 0.0f,     // Lens distortion constant parameter 3
+        .chromaAbCorrection[0] = 0.996f,     // Chromatic aberration correction parameter 0
+        .chromaAbCorrection[1] = -0.004f,    // Chromatic aberration correction parameter 1
+        .chromaAbCorrection[2] = 1.014f,     // Chromatic aberration correction parameter 2
+        .chromaAbCorrection[3] = 0.0f,       // Chromatic aberration correction parameter 3
+    };
+    
     // Init VR simulator (Oculus Rift CV1 parameters)
     // Init VR simulator (Oculus Rift CV1 parameters)
-    InitVrSimulator();
-
-    VrDeviceInfo hmd = { 0 };               // VR device parameters (head-mounted-device)
-
-    // Oculus Rift CV1 parameters for simulator
-    hmd.hResolution = 2160;                 // HMD horizontal resolution in pixels
-    hmd.vResolution = 1200;                 // HMD vertical resolution in pixels
-    hmd.hScreenSize = 0.133793f;            // HMD horizontal size in meters
-    hmd.vScreenSize = 0.0669f;              // HMD vertical size in meters
-    hmd.vScreenCenter = 0.04678f;           // HMD screen center in meters
-    hmd.eyeToScreenDistance = 0.041f;       // HMD distance between eye and display in meters
-    hmd.lensSeparationDistance = 0.07f;     // HMD lens separation distance in meters
-    hmd.interpupillaryDistance = 0.07f;     // HMD IPD (distance between pupils) in meters
-
-    // NOTE: CV1 uses a Fresnel-hybrid-asymmetric lenses with specific distortion compute shaders.
-    // Following parameters are an approximation to distortion stereo rendering but results differ from actual device.
-    hmd.lensDistortionValues[0] = 1.0f;     // HMD lens distortion constant parameter 0
-    hmd.lensDistortionValues[1] = 0.22f;    // HMD lens distortion constant parameter 1
-    hmd.lensDistortionValues[2] = 0.24f;    // HMD lens distortion constant parameter 2
-    hmd.lensDistortionValues[3] = 0.0f;     // HMD lens distortion constant parameter 3
-    hmd.chromaAbCorrection[0] = 0.996f;     // HMD chromatic aberration correction parameter 0
-    hmd.chromaAbCorrection[1] = -0.004f;    // HMD chromatic aberration correction parameter 1
-    hmd.chromaAbCorrection[2] = 1.014f;     // HMD chromatic aberration correction parameter 2
-    hmd.chromaAbCorrection[3] = 0.0f;       // HMD chromatic aberration correction parameter 3
+    InitVrSimulator(device);
+    
+    // Get Vr stereo config parameters for device parameters
+    VrStereoConfig config = GetVrConfig(device);
 
 
     // Distortion shader (uses device lens distortion and chroma)
     // Distortion shader (uses device lens distortion and chroma)
     Shader distortion = LoadShader(0, TextFormat("resources/distortion%i.fs", GLSL_VERSION));
     Shader distortion = LoadShader(0, TextFormat("resources/distortion%i.fs", GLSL_VERSION));
-
-    SetVrConfiguration(hmd, distortion);    // Set Vr device parameters for stereo rendering
+    
+    // Update distortion shader with lens and distortion-scale parameters
+    SetShaderValue(distortion, GetShaderLocation(distortion, "leftLensCenter"), config.leftLensCenter, SHADER_UNIFORM_VEC2);
+    SetShaderValue(distortion, GetShaderLocation(distortion, "rightLensCenter"), config.rightLensCenter, SHADER_UNIFORM_VEC2);
+    SetShaderValue(distortion, GetShaderLocation(distortion, "leftScreenCenter"), config.leftScreenCenter, SHADER_UNIFORM_VEC2);
+    SetShaderValue(distortion, GetShaderLocation(distortion, "rightScreenCenter"), config.rightScreenCenter, SHADER_UNIFORM_VEC2);
+
+    SetShaderValue(distortion, GetShaderLocation(distortion, "scale"), config.scale, SHADER_UNIFORM_VEC2);
+    SetShaderValue(distortion, GetShaderLocation(distortion, "scaleIn"), config.scaleIn, SHADER_UNIFORM_VEC2);
+    SetShaderValue(distortion, GetShaderLocation(distortion, "deviceWarpParam"), device.lensDistortionValues, SHADER_UNIFORM_VEC4);
+    SetShaderValue(distortion, GetShaderLocation(distortion, "chromaAbParam"), device.chromaAbCorrection, SHADER_UNIFORM_VEC4);
+    
+    // Initialize framebuffer for stereo rendering
+    // NOTE: Screen size should match HMD aspect ratio
+    RenderTexture2D target = LoadRenderTexture(GetScreenWidth(), GetScreenHeight());
 
 
     // Define the camera to look into our 3d world
     // Define the camera to look into our 3d world
     Camera camera = { 0 };
     Camera camera = { 0 };
@@ -81,8 +96,6 @@ int main(void)
         // Update
         // Update
         //----------------------------------------------------------------------------------
         //----------------------------------------------------------------------------------
         UpdateCamera(&camera);          // Update camera (simulator mode)
         UpdateCamera(&camera);          // Update camera (simulator mode)
-
-        if (IsKeyPressed(KEY_SPACE)) ToggleVrMode();    // Toggle VR mode
         //----------------------------------------------------------------------------------
         //----------------------------------------------------------------------------------
 
 
         // Draw
         // Draw
@@ -91,8 +104,7 @@ int main(void)
 
 
             ClearBackground(RAYWHITE);
             ClearBackground(RAYWHITE);
 
 
-            BeginVrDrawing();
-
+            BeginVrDrawing(target);
                 BeginMode3D(camera);
                 BeginMode3D(camera);
 
 
                     DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED);
                     DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED);
@@ -101,8 +113,11 @@ int main(void)
                     DrawGrid(40, 1.0f);
                     DrawGrid(40, 1.0f);
 
 
                 EndMode3D();
                 EndMode3D();
-
             EndVrDrawing();
             EndVrDrawing();
+            
+            BeginShaderMode(distortion);
+                DrawTextureRec(target.texture, (Rectangle){ 0, 0, target.texture.width, -target.texture.height }, (Vector2){ 0.0f, 0.0f }, WHITE);
+            EndShaderMode();
 
 
             DrawFPS(10, 10);
             DrawFPS(10, 10);
 
 
@@ -112,11 +127,12 @@ int main(void)
 
 
     // De-Initialization
     // De-Initialization
     //--------------------------------------------------------------------------------------
     //--------------------------------------------------------------------------------------
-    UnloadShader(distortion);   // Unload distortion shader
+    UnloadRenderTexture(target);    // Unload stereo render fbo
+    UnloadShader(distortion);       // Unload distortion shader
 
 
-    CloseVrSimulator();         // Close VR simulator
+    CloseVrSimulator();             // Close VR simulator
 
 
-    CloseWindow();              // Close window and OpenGL context
+    CloseWindow();                  // Close window and OpenGL context
     //--------------------------------------------------------------------------------------
     //--------------------------------------------------------------------------------------
 
 
     return 0;
     return 0;

+ 3 - 6
src/config.h

@@ -57,6 +57,8 @@
 #define SUPPORT_COMPRESSION_API     1
 #define SUPPORT_COMPRESSION_API     1
 // Support saving binary data automatically to a generated storage.data file. This file is managed internally.
 // Support saving binary data automatically to a generated storage.data file. This file is managed internally.
 #define SUPPORT_DATA_STORAGE        1
 #define SUPPORT_DATA_STORAGE        1
+// Support VR simulation functionality (stereo rendering)
+#define SUPPORT_VR_SIMULATOR        1
 
 
 // core: Configuration values
 // core: Configuration values
 //------------------------------------------------------------------------------------
 //------------------------------------------------------------------------------------
@@ -78,12 +80,7 @@
 
 
 
 
 //------------------------------------------------------------------------------------
 //------------------------------------------------------------------------------------
-// Module: rlgl - Configuration Flags
-//------------------------------------------------------------------------------------
-// Support VR simulation functionality (stereo rendering)
-#define SUPPORT_VR_SIMULATOR        1
-
-// rlgl: Configuration values
+// Module: rlgl - Configuration values
 //------------------------------------------------------------------------------------
 //------------------------------------------------------------------------------------
 #if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33)
 #if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33)
     #define DEFAULT_BATCH_BUFFER_ELEMENTS   8192    // Default internal render batch limits
     #define DEFAULT_BATCH_BUFFER_ELEMENTS   8192    // Default internal render batch limits

+ 154 - 1
src/core.c

@@ -80,7 +80,10 @@
 *       for linkage
 *       for linkage
 *
 *
 *   #define SUPPORT_DATA_STORAGE
 *   #define SUPPORT_DATA_STORAGE
-*       Support saving binary data automatically to a generated storage.data file. This file is managed internally.
+*       Support saving binary data automatically to a generated storage.data file. This file is managed internally
+*
+*   #define SUPPORT_VR_SIMULATOR
+*       Support VR simulation functionality (stereo rendering)
 *
 *
 *   DEPENDENCIES:
 *   DEPENDENCIES:
 *       rglfw    - Manage graphic device, OpenGL context and inputs on PLATFORM_DESKTOP (Windows, Linux, OSX. FreeBSD, OpenBSD, NetBSD, DragonFly)
 *       rglfw    - Manage graphic device, OpenGL context and inputs on PLATFORM_DESKTOP (Windows, Linux, OSX. FreeBSD, OpenBSD, NetBSD, DragonFly)
@@ -473,6 +476,15 @@ typedef struct CoreData {
         unsigned long long base;            // Base time measure for hi-res timer
         unsigned long long base;            // Base time measure for hi-res timer
 #endif
 #endif
     } Time;
     } Time;
+#if defined(SUPPORT_VR_SIMULATOR)
+    struct {
+        VrStereoConfig config;              // VR stereo configuration for simulator
+        unsigned int stereoFboId;           // VR stereo rendering framebuffer id
+        unsigned int stereoTexId;           // VR stereo color texture (attached to framebuffer)
+        bool simulatorReady;                // VR simulator ready flag
+        bool stereoRender;                  // VR stereo rendering enabled/disabled flag
+    } Vr;               // VR simulator data
+#endif  // SUPPORT_VR_SIMULATOR
 } CoreData;
 } CoreData;
 
 
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
@@ -2000,6 +2012,147 @@ void EndTextureMode(void)
     CORE.Window.currentFbo.height = CORE.Window.screen.height;
     CORE.Window.currentFbo.height = CORE.Window.screen.height;
 }
 }
 
 
+
+#if defined(SUPPORT_VR_SIMULATOR)
+// Init VR simulator for selected device parameters
+void InitVrSimulator(VrDeviceInfo device)
+{
+#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
+    // Reset CORE.Vr.config for a new values assignment
+    memset(&CORE.Vr.config, 0, sizeof(VrStereoConfig));
+
+    // Compute aspect ratio
+    float aspect = ((float)device.hResolution*0.5f)/(float)device.vResolution;
+
+    // Compute lens parameters
+    float lensShift = (device.hScreenSize*0.25f - device.lensSeparationDistance*0.5f)/device.hScreenSize;
+    CORE.Vr.config.leftLensCenter[0] = 0.25f + lensShift;
+    CORE.Vr.config.leftLensCenter[1] = 0.5f;
+    CORE.Vr.config.rightLensCenter[0] = 0.75f - lensShift;
+    CORE.Vr.config.rightLensCenter[1] = 0.5f;
+    CORE.Vr.config.leftScreenCenter[0] = 0.25f;
+    CORE.Vr.config.leftScreenCenter[1] = 0.5f;
+    CORE.Vr.config.rightScreenCenter[0] = 0.75f;
+    CORE.Vr.config.rightScreenCenter[1] = 0.5f;
+
+    // Compute distortion scale parameters
+    // NOTE: To get lens max radius, lensShift must be normalized to [-1..1]
+    float lensRadius = fabsf(-1.0f - 4.0f*lensShift);
+    float lensRadiusSq = lensRadius*lensRadius;
+    float distortionScale = device.lensDistortionValues[0] +
+                            device.lensDistortionValues[1]*lensRadiusSq +
+                            device.lensDistortionValues[2]*lensRadiusSq*lensRadiusSq +
+                            device.lensDistortionValues[3]*lensRadiusSq*lensRadiusSq*lensRadiusSq;
+
+    float normScreenWidth = 0.5f;
+    float normScreenHeight = 1.0f;
+    CORE.Vr.config.scaleIn[0] = 2.0f/normScreenWidth;
+    CORE.Vr.config.scaleIn[1] = 2.0f/normScreenHeight/aspect;
+    CORE.Vr.config.scale[0] = normScreenWidth*0.5f/distortionScale;
+    CORE.Vr.config.scale[1] = normScreenHeight*0.5f*aspect/distortionScale;
+
+    // Fovy is normally computed with: 2*atan2f(device.vScreenSize, 2*device.eyeToScreenDistance)
+    // ...but with lens distortion it is increased (see Oculus SDK Documentation)
+    //float fovy = 2.0f*atan2f(device.vScreenSize*0.5f*distortionScale, device.eyeToScreenDistance);     // Really need distortionScale?
+    float fovy = 2.0f*(float)atan2f(device.vScreenSize*0.5f, device.eyeToScreenDistance);
+
+    // Compute camera projection matrices
+    float projOffset = 4.0f*lensShift;      // Scaled to projection space coordinates [-1..1]
+    Matrix proj = MatrixPerspective(fovy, aspect, RL_CULL_DISTANCE_NEAR, RL_CULL_DISTANCE_FAR);
+    rlSetMatrixProjectionStereo(MatrixMultiply(proj, MatrixTranslate(projOffset, 0.0f, 0.0f)), MatrixMultiply(proj, MatrixTranslate(-projOffset, 0.0f, 0.0f)));
+
+    // Compute camera transformation matrices
+    // NOTE: 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.
+    rlSetMatrixViewOffsetStereo(MatrixTranslate(-device.interpupillaryDistance*0.5f, 0.075f, 0.045f), MatrixTranslate(device.interpupillaryDistance*0.5f, 0.075f, 0.045f));
+
+    // Compute eyes Viewports
+    /*
+    CORE.Vr.config.eyeViewportRight[0] = 0;
+    CORE.Vr.config.eyeViewportRight[1] = 0;
+    CORE.Vr.config.eyeViewportRight[2] = device.hResolution/2;
+    CORE.Vr.config.eyeViewportRight[3] = device.vResolution;
+
+    CORE.Vr.config.eyeViewportLeft[0] = device.hResolution/2;
+    CORE.Vr.config.eyeViewportLeft[1] = 0;
+    CORE.Vr.config.eyeViewportLeft[2] = device.hResolution/2;
+    CORE.Vr.config.eyeViewportLeft[3] = device.vResolution;
+    */
+
+    CORE.Vr.simulatorReady = true;
+#else
+    TRACELOG(LOG_WARNING, "RLGL: VR Simulator not supported on OpenGL 1.1");
+#endif
+}
+
+// Update VR tracking (position and orientation) and camera
+// NOTE: Camera (position, target, up) gets update with head tracking information
+void UpdateVrTracking(Camera *camera)
+{
+    // TODO: Simulate 1st person camera system
+}
+
+// Close VR simulator for current device
+void CloseVrSimulator(void)
+{
+    CORE.Vr.simulatorReady = false;
+}
+
+// Get stereo rendering configuration parameters
+VrStereoConfig GetVrConfig(VrDeviceInfo device)
+{
+    VrStereoConfig config = { 0 };
+#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
+    config = CORE.Vr.config;
+#endif
+    return config;
+}
+
+// Detect if VR simulator is running
+bool IsVrSimulatorReady(void)
+{
+    return CORE.Vr.simulatorReady;
+}
+
+// Begin VR drawing configuration
+void BeginVrDrawing(RenderTexture2D target)
+{
+#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
+    if (CORE.Vr.simulatorReady)
+    {
+        rlEnableFramebuffer(target.id);     // Setup framebuffer for stereo rendering
+        //glEnable(GL_FRAMEBUFFER_SRGB);    // Enable SRGB framebuffer (only if required)
+
+        //rlViewport(0, 0, buffer.width, buffer.height); // Useful if rendering to separate framebuffers (every eye)
+        rlClearScreenBuffers();             // Clear current framebuffer
+
+        rlEnableStereoRender();
+    }
+#endif
+}
+
+// End VR drawing process (and desktop mirror)
+void EndVrDrawing(void)
+{
+#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
+    if (CORE.Vr.simulatorReady)
+    {
+        rlDisableStereoRender();
+
+        rlDisableFramebuffer();         // Unbind current framebuffer
+
+        // Reset viewport and default projection-modelview matrices
+        rlViewport(0, 0, RLGL.State.framebufferWidth, RLGL.State.framebufferHeight);
+        SetMatrixProjection(MatrixOrtho(0.0, RLGL.State.framebufferWidth, RLGL.State.framebufferHeight, 0.0, 0.0, 1.0));
+        SetMatrixModelview(MatrixIdentity());
+
+        rlDisableDepthTest();
+    }
+#endif
+}
+#endif          // SUPPORT_VR_SIMULATOR
+
 // Begin scissor mode (define screen area for following drawing)
 // Begin scissor mode (define screen area for following drawing)
 // NOTE: Scissor rec refers to bottom-left corner, we change it to upper-left
 // NOTE: Scissor rec refers to bottom-left corner, we change it to upper-left
 void BeginScissorMode(int x, int y, int width, int height)
 void BeginScissorMode(int x, int y, int width, int height)

+ 25 - 15
src/raylib.h

@@ -449,18 +449,28 @@ typedef struct Music {
 
 
 // Head-Mounted-Display device parameters
 // Head-Mounted-Display device parameters
 typedef struct VrDeviceInfo {
 typedef struct VrDeviceInfo {
-    int hResolution;                // HMD horizontal resolution in pixels
-    int vResolution;                // HMD vertical resolution in pixels
-    float hScreenSize;              // HMD horizontal size in meters
-    float vScreenSize;              // HMD vertical size in meters
-    float vScreenCenter;            // HMD screen center in meters
-    float eyeToScreenDistance;      // HMD distance between eye and display in meters
-    float lensSeparationDistance;   // HMD lens separation distance in meters
-    float interpupillaryDistance;   // HMD IPD (distance between pupils) in meters
-    float lensDistortionValues[4];  // HMD lens distortion constant parameters
-    float chromaAbCorrection[4];    // HMD chromatic aberration correction parameters
+    int hResolution;                // Horizontal resolution in pixels
+    int vResolution;                // Vertical resolution in pixels
+    float hScreenSize;              // Horizontal size in meters
+    float vScreenSize;              // Vertical size in meters
+    float vScreenCenter;            // Screen center in meters
+    float eyeToScreenDistance;      // Distance between eye and display in meters
+    float lensSeparationDistance;   // Lens separation distance in meters
+    float interpupillaryDistance;   // IPD (distance between pupils) in meters
+    float lensDistortionValues[4];  // Lens distortion constant parameters
+    float chromaAbCorrection[4];    // Chromatic aberration correction parameters
 } VrDeviceInfo;
 } VrDeviceInfo;
 
 
+// VR Stereo rendering configuration for simulator
+typedef struct VrStereoConfig {
+    float leftLensCenter[2];        // VR left lens center
+    float rightLensCenter[2];       // VR right lens center
+    float leftScreenCenter[2];      // VR left screen center
+    float rightScreenCenter[2];     // VR right screen center
+    float scale[2];                 // VR distortion scale
+    float scaleIn[2];               // VR distortion scale in
+} VrStereoConfig;
+
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
 // Enumerators Definition
 // Enumerators Definition
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
@@ -1441,14 +1451,14 @@ RLAPI void BeginBlendMode(int mode);                                      // Beg
 RLAPI void EndBlendMode(void);                                            // End blending mode (reset to default: alpha blending)
 RLAPI void EndBlendMode(void);                                            // End blending mode (reset to default: alpha blending)
 
 
 // VR control functions
 // VR control functions
-RLAPI void InitVrSimulator(void);                       // Init VR simulator for selected device parameters
+RLAPI void InitVrSimulator(VrDeviceInfo device);        // Init VR simulator for selected device parameters
 RLAPI void CloseVrSimulator(void);                      // Close VR simulator for current device
 RLAPI void CloseVrSimulator(void);                      // Close VR simulator for current device
-RLAPI void UpdateVrTracking(Camera *camera);            // Update VR tracking (position and orientation) and camera
-RLAPI void SetVrConfiguration(VrDeviceInfo info, Shader distortion);      // Set stereo rendering configuration parameters
 RLAPI bool IsVrSimulatorReady(void);                    // Detect if VR simulator is ready
 RLAPI bool IsVrSimulatorReady(void);                    // Detect if VR simulator is ready
-RLAPI void ToggleVrMode(void);                          // Enable/Disable VR experience
-RLAPI void BeginVrDrawing(void);                        // Begin VR simulator stereo rendering
+RLAPI void UpdateVrTracking(Camera *camera);            // Update VR tracking (position and orientation) and camera
+RLAPI void BeginVrDrawing(RenderTexture2D target);      // Begin VR simulator stereo rendering (using provided fbo)
 RLAPI void EndVrDrawing(void);                          // End VR simulator stereo rendering
 RLAPI void EndVrDrawing(void);                          // End VR simulator stereo rendering
+RLAPI VrStereoConfig GetVrConfig(VrDeviceInfo device);        // Get stereo rendering configuration parameters
+RLAPI Texture2D GetVrTexture(void);                     // Get VR framebuffer texture
 
 
 //------------------------------------------------------------------------------------
 //------------------------------------------------------------------------------------
 // Audio Loading and Playing Functions (Module: audio)
 // Audio Loading and Playing Functions (Module: audio)

+ 65 - 344
src/rlgl.h

@@ -29,8 +29,6 @@
 *   #define RLGL_STANDALONE
 *   #define RLGL_STANDALONE
 *       Use rlgl as standalone library (no raylib dependency)
 *       Use rlgl as standalone library (no raylib dependency)
 *
 *
-*   #define SUPPORT_VR_SIMULATOR
-*       Support VR simulation functionality (stereo rendering)
 *
 *
 *   DEPENDENCIES:
 *   DEPENDENCIES:
 *       raymath     - 3D math functionality (Vector3, Matrix, Quaternion)
 *       raymath     - 3D math functionality (Vector3, Matrix, Quaternion)
@@ -327,29 +325,6 @@ typedef enum {
         float fovy;             // Camera field-of-view apperture in Y (degrees)
         float fovy;             // Camera field-of-view apperture in Y (degrees)
     } Camera;
     } Camera;
 
 
-    // Head-Mounted-Display device parameters
-    typedef struct VrDeviceInfo {
-        int hResolution;                // HMD horizontal resolution in pixels
-        int vResolution;                // HMD vertical resolution in pixels
-        float hScreenSize;              // HMD horizontal size in meters
-        float vScreenSize;              // HMD vertical size in meters
-        float vScreenCenter;            // HMD screen center in meters
-        float eyeToScreenDistance;      // HMD distance between eye and display in meters
-        float lensSeparationDistance;   // HMD lens separation distance in meters
-        float interpupillaryDistance;   // HMD IPD (distance between pupils) in meters
-        float lensDistortionValues[4];  // HMD lens distortion constant parameters
-        float chromaAbCorrection[4];    // HMD chromatic aberration correction parameters
-    } VrDeviceInfo;
-
-    // VR Stereo rendering configuration for simulator
-    typedef struct VrStereoConfig {
-        Shader distortionShader;        // VR stereo rendering distortion shader
-        Matrix eyesProjection[2];       // VR stereo rendering eyes projection matrices
-        Matrix eyesViewOffset[2];       // VR stereo rendering eyes view offset matrices
-        int eyeViewportRight[4];        // VR stereo rendering right eye viewport [x, y, w, h]
-        int eyeViewportLeft[4];         // VR stereo rendering left eye viewport [x, y, w, h]
-    } VrStereoConfig;
-
     // TraceLog message types
     // TraceLog message types
     typedef enum {
     typedef enum {
         LOG_ALL,
         LOG_ALL,
@@ -532,6 +507,8 @@ RLAPI void rlSetLineWidth(float width);                       // Set the line dr
 RLAPI float rlGetLineWidth(void);                             // Get the line drawing width
 RLAPI float rlGetLineWidth(void);                             // Get the line drawing width
 RLAPI void rlEnableSmoothLines(void);                         // Enable line aliasing
 RLAPI void rlEnableSmoothLines(void);                         // Enable line aliasing
 RLAPI void rlDisableSmoothLines(void);                        // Disable line aliasing
 RLAPI void rlDisableSmoothLines(void);                        // Disable line aliasing
+RLAPI void rlEnableStereoRender(void);                        // Enable stereo rendering
+RLAPI void rlDisableStereoRender(void);                       // Disable stereo rendering
 
 
 RLAPI void rlClearColor(unsigned char r, unsigned char g, unsigned char b, unsigned char a);  // Clear color buffer with color
 RLAPI void rlClearColor(unsigned char r, unsigned char g, unsigned char b, unsigned char a);  // Clear color buffer with color
 RLAPI void rlClearScreenBuffers(void);                        // Clear used screen buffers (color and depth)
 RLAPI void rlClearScreenBuffers(void);                        // Clear used screen buffers (color and depth)
@@ -564,6 +541,9 @@ RLAPI void rlGenerateMipmaps(Texture2D *texture);                         // Gen
 RLAPI void *rlReadTexturePixels(Texture2D texture);                       // Read texture pixel data
 RLAPI void *rlReadTexturePixels(Texture2D texture);                       // Read texture pixel data
 RLAPI unsigned char *rlReadScreenPixels(int width, int height);           // Read screen pixel data (color buffer)
 RLAPI unsigned char *rlReadScreenPixels(int width, int height);           // Read screen pixel data (color buffer)
 
 
+RLAPI void rlSetMatrixProjectionStereo(Matrix right, Matrix left);        // Set eyes projection matrices for stereo rendering
+RLAPI void rlSetMatrixViewOffsetStereo(Matrix right, Matrix left);        // Set eyes view offsets matrices for stereo rendering
+
 // Framebuffer management (fbo)
 // Framebuffer management (fbo)
 RLAPI unsigned int rlLoadFramebuffer(int width, int height);              // Load an empty framebuffer
 RLAPI unsigned int rlLoadFramebuffer(int width, int height);              // Load an empty framebuffer
 RLAPI void rlFramebufferAttach(unsigned int fboId, unsigned int texId, int attachType, int texType);  // Attach texture/renderbuffer to a framebuffer
 RLAPI void rlFramebufferAttach(unsigned int fboId, unsigned int texId, int attachType, int texType);  // Attach texture/renderbuffer to a framebuffer
@@ -597,14 +577,15 @@ RLAPI Texture2D GetShapesTexture(void);                                   // Get
 RLAPI Rectangle GetShapesTextureRec(void);                                // Get texture rectangle to draw shapes
 RLAPI Rectangle GetShapesTextureRec(void);                                // Get texture rectangle to draw shapes
 
 
 // Shader configuration functions
 // Shader configuration functions
-RLAPI int GetShaderLocation(Shader shader, const char *uniformName);              // Get shader uniform location
-RLAPI int GetShaderLocationAttrib(Shader shader, const char *attribName);         // Get shader attribute location
+RLAPI int GetShaderLocation(Shader shader, const char *uniformName);      // Get shader uniform location
+RLAPI int GetShaderLocationAttrib(Shader shader, const char *attribName); // Get shader attribute location
 RLAPI void SetShaderValue(Shader shader, int locIndex, const void *value, int uniformType);               // Set shader uniform value
 RLAPI void SetShaderValue(Shader shader, int locIndex, const void *value, int uniformType);               // Set shader uniform value
 RLAPI void SetShaderValueV(Shader shader, int locIndex, const void *value, int uniformType, int count);   // Set shader uniform value vector
 RLAPI void SetShaderValueV(Shader shader, int locIndex, const void *value, int uniformType, int count);   // Set shader uniform value vector
-RLAPI void SetShaderValueMatrix(Shader shader, int locIndex, Matrix mat);       // Set shader uniform value (matrix 4x4)
+RLAPI void SetShaderValueMatrix(Shader shader, int locIndex, Matrix mat); // Set shader uniform value (matrix 4x4)
 RLAPI void SetMatrixProjection(Matrix proj);                              // Set a custom projection matrix (replaces internal projection matrix)
 RLAPI void SetMatrixProjection(Matrix proj);                              // Set a custom projection matrix (replaces internal projection matrix)
 RLAPI void SetMatrixModelview(Matrix view);                               // Set a custom modelview matrix (replaces internal modelview matrix)
 RLAPI void SetMatrixModelview(Matrix view);                               // Set a custom modelview matrix (replaces internal modelview matrix)
 RLAPI Matrix GetMatrixModelview(void);                                    // Get internal modelview matrix
 RLAPI Matrix GetMatrixModelview(void);                                    // Get internal modelview matrix
+RLAPI Matrix GetMatrixProjection(void);                                   // Get internal projection matrix
 
 
 // Texture maps generation (PBR)
 // Texture maps generation (PBR)
 // NOTE: Required shaders should be provided
 // NOTE: Required shaders should be provided
@@ -619,16 +600,6 @@ RLAPI void EndShaderMode(void);                         // End custom shader dra
 RLAPI void BeginBlendMode(int mode);                    // Begin blending mode (alpha, additive, multiplied)
 RLAPI void BeginBlendMode(int mode);                    // Begin blending mode (alpha, additive, multiplied)
 RLAPI void EndBlendMode(void);                          // End blending mode (reset to default: alpha blending)
 RLAPI void EndBlendMode(void);                          // End blending mode (reset to default: alpha blending)
 
 
-// VR control functions
-RLAPI void InitVrSimulator(void);                       // Init VR simulator for selected device parameters
-RLAPI void CloseVrSimulator(void);                      // Close VR simulator for current device
-RLAPI void UpdateVrTracking(Camera *camera);            // Update VR tracking (position and orientation) and camera
-RLAPI void SetVrConfiguration(VrDeviceInfo info, Shader distortion);      // Set stereo rendering configuration parameters
-RLAPI bool IsVrSimulatorReady(void);                    // Detect if VR simulator is ready
-RLAPI void ToggleVrMode(void);                          // Enable/Disable VR experience
-RLAPI void BeginVrDrawing(void);                        // Begin VR simulator stereo rendering
-RLAPI void EndVrDrawing(void);                          // End VR simulator stereo rendering
-
 RLAPI char *LoadFileText(const char *fileName);         // Load chars array from text file
 RLAPI char *LoadFileText(const char *fileName);         // Load chars array from text file
 RLAPI int GetPixelDataSize(int width, int height, int format);// Get pixel data size in bytes (image or texture)
 RLAPI int GetPixelDataSize(int width, int height, int format);// Get pixel data size in bytes (image or texture)
 #endif
 #endif
@@ -847,17 +818,6 @@ typedef struct RenderBatch {
     float currentDepth;         // Current depth value for next draw
     float currentDepth;         // Current depth value for next draw
 } RenderBatch;
 } RenderBatch;
 
 
-#if defined(SUPPORT_VR_SIMULATOR) && !defined(RLGL_STANDALONE)
-// VR Stereo rendering configuration for simulator
-typedef struct VrStereoConfig {
-    Shader distortionShader;        // VR stereo rendering distortion shader
-    Matrix eyesProjection[2];       // VR stereo rendering eyes projection matrices
-    Matrix eyesViewOffset[2];       // VR stereo rendering eyes view offset matrices
-    int eyeViewportRight[4];        // VR stereo rendering right eye viewport [x, y, w, h]
-    int eyeViewportLeft[4];         // VR stereo rendering left eye viewport [x, y, w, h]
-} VrStereoConfig;
-#endif
-
 #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
 #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
 typedef struct rlglData {
 typedef struct rlglData {
     RenderBatch *currentBatch;              // Current render batch
     RenderBatch *currentBatch;              // Current render batch
@@ -881,6 +841,10 @@ typedef struct rlglData {
         unsigned int defaultFShaderId;      // Default fragment shader Id (used by default shader program)
         unsigned int defaultFShaderId;      // Default fragment shader Id (used by default shader program)
         Shader defaultShader;               // Basic shader, support vertex color and diffuse texture
         Shader defaultShader;               // Basic shader, support vertex color and diffuse texture
         Shader currentShader;               // Shader to be used on rendering (by default, defaultShader)
         Shader currentShader;               // Shader to be used on rendering (by default, defaultShader)
+        
+        bool stereoRender;                  // Stereo rendering flag
+        Matrix eyesProjection[2];           // VR stereo rendering eyes projection matrices
+        Matrix eyesViewOffset[2];           // VR stereo rendering eyes view offset matrices
 
 
         int currentBlendMode;               // Blending mode active
         int currentBlendMode;               // Blending mode active
         int glBlendSrcFactor;               // Blending source factor
         int glBlendSrcFactor;               // Blending source factor
@@ -910,15 +874,6 @@ typedef struct rlglData {
         int maxDepthBits;                   // Maximum bits for depth component
         int maxDepthBits;                   // Maximum bits for depth component
 
 
     } ExtSupported;     // Extensions supported flags
     } ExtSupported;     // Extensions supported flags
-#if defined(SUPPORT_VR_SIMULATOR)
-    struct {
-        VrStereoConfig config;              // VR stereo configuration for simulator
-        unsigned int stereoFboId;           // VR stereo rendering framebuffer id
-        unsigned int stereoTexId;           // VR stereo color texture (attached to framebuffer)
-        bool simulatorReady;                // VR simulator ready flag
-        bool stereoRender;                  // VR stereo rendering enabled/disabled flag
-    } Vr;               // VR simulator data
-#endif  // SUPPORT_VR_SIMULATOR
 } rlglData;
 } rlglData;
 #endif  // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2
 #endif  // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2
 
 
@@ -961,11 +916,6 @@ static void SetRenderBatchDefault(void);                // Set default render ba
 
 
 static void GenDrawCube(void);              // Generate and draw cube
 static void GenDrawCube(void);              // Generate and draw cube
 static void GenDrawQuad(void);              // Generate and draw quad
 static void GenDrawQuad(void);              // Generate and draw quad
-
-#if defined(SUPPORT_VR_SIMULATOR)
-static void SetStereoView(int eye, Matrix matProjection, Matrix matModelView);  // Set internal projection and modelview matrix depending on eye
-#endif
-
 #endif  // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2
 #endif  // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2
 
 
 #if defined(GRAPHICS_API_OPENGL_11)
 #if defined(GRAPHICS_API_OPENGL_11)
@@ -1469,13 +1419,13 @@ void rlEnableBackfaceCulling(void) { glEnable(GL_CULL_FACE); }
 void rlDisableBackfaceCulling(void) { glDisable(GL_CULL_FACE); }
 void rlDisableBackfaceCulling(void) { glDisable(GL_CULL_FACE); }
 
 
 // Enable scissor test
 // Enable scissor test
-RLAPI void rlEnableScissorTest(void) { glEnable(GL_SCISSOR_TEST); }
+void rlEnableScissorTest(void) { glEnable(GL_SCISSOR_TEST); }
 
 
 // Disable scissor test
 // Disable scissor test
-RLAPI void rlDisableScissorTest(void) { glDisable(GL_SCISSOR_TEST); }
+void rlDisableScissorTest(void) { glDisable(GL_SCISSOR_TEST); }
 
 
 // Scissor test
 // Scissor test
-RLAPI void rlScissor(int x, int y, int width, int height) { glScissor(x, y, width, height); }
+void rlScissor(int x, int y, int width, int height) { glScissor(x, y, width, height); }
 
 
 // Enable wire mode
 // Enable wire mode
 void rlEnableWireMode(void)
 void rlEnableWireMode(void)
@@ -1524,6 +1474,18 @@ void rlDisableSmoothLines(void)
 #endif
 #endif
 }
 }
 
 
+// Enable stereo rendering
+void rlEnableStereoRender(void)
+{
+    RLGL.State.stereoRender = true;
+}
+
+// Disable stereo rendering
+void rlDisableStereoRender(void)
+{
+    RLGL.State.stereoRender = false;
+}
+
 // Unload framebuffer from GPU memory
 // Unload framebuffer from GPU memory
 // NOTE: All attached textures/cubemaps/renderbuffers are also deleted
 // NOTE: All attached textures/cubemaps/renderbuffers are also deleted
 void rlUnloadFramebuffer(unsigned int id)
 void rlUnloadFramebuffer(unsigned int id)
@@ -2889,16 +2851,21 @@ void rlDrawMesh(Mesh mesh, Material material, Matrix transform)
     }
     }
 
 
     int eyesCount = 1;
     int eyesCount = 1;
-#if defined(SUPPORT_VR_SIMULATOR)
-    if (RLGL.Vr.stereoRender) eyesCount = 2;
-#endif
+    if (RLGL.State.stereoRender) eyesCount = 2;
 
 
     for (int eye = 0; eye < eyesCount; eye++)
     for (int eye = 0; eye < eyesCount; eye++)
     {
     {
         if (eyesCount == 1) RLGL.State.modelview = matModelView;
         if (eyesCount == 1) RLGL.State.modelview = matModelView;
-        #if defined(SUPPORT_VR_SIMULATOR)
-        else SetStereoView(eye, matProjection, matModelView);
-        #endif
+        else
+        {
+            // Setup current eye viewport (half screen width)
+            rlViewport(eye*RLGL.State.framebufferWidth/2, 0, RLGL.State.framebufferWidth/2, RLGL.State.framebufferHeight);
+
+            // Set current eye view offset to modelview matrix
+            SetMatrixModelview(MatrixMultiply(matModelView, RLGL.State.eyesViewOffset[eye]));
+            // Set current eye projection matrix
+            SetMatrixProjection(RLGL.State.eyesProjection[eye]);
+        }
 
 
         // Calculate model-view-projection matrix (MVP)
         // Calculate model-view-projection matrix (MVP)
         Matrix matMVP = MatrixMultiply(RLGL.State.modelview, RLGL.State.projection);        // Transform to screen-space coordinates
         Matrix matMVP = MatrixMultiply(RLGL.State.modelview, RLGL.State.projection);        // Transform to screen-space coordinates
@@ -3145,6 +3112,20 @@ void *rlReadTexturePixels(Texture2D texture)
     return pixels;
     return pixels;
 }
 }
 
 
+// Set eyes projection matrices for stereo rendering
+void rlSetMatrixProjectionStereo(Matrix right, Matrix left)
+{
+    RLGL.State.eyesProjection[0] = right;
+    RLGL.State.eyesProjection[1] = left;
+}
+
+// Set eyes view offsets matrices for stereo rendering
+void rlSetMatrixViewOffsetStereo(Matrix right, Matrix left)
+{
+    RLGL.State.eyesViewOffset[0] = right;
+    RLGL.State.eyesViewOffset[1] = left;
+}
+
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
 // Module Functions Definition - Shaders Functions
 // Module Functions Definition - Shaders Functions
 // NOTE: Those functions are exposed directly to the user in raylib.h
 // NOTE: Those functions are exposed directly to the user in raylib.h
@@ -3813,250 +3794,6 @@ void EndBlendMode(void)
     BeginBlendMode(BLEND_ALPHA);
     BeginBlendMode(BLEND_ALPHA);
 }
 }
 
 
-#if defined(SUPPORT_VR_SIMULATOR)
-// Init VR simulator for selected device parameters
-// NOTE: It modifies the global variable: RLGL.Vr.stereoFboId
-void InitVrSimulator(void)
-{
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    // Initialize framebuffer and textures for stereo rendering
-    // NOTE: Screen size should match HMD aspect ratio
-    RLGL.Vr.stereoFboId = rlLoadFramebuffer(RLGL.State.framebufferWidth, RLGL.State.framebufferHeight);
-
-    // Load color/depth textures to attach to framebuffer
-    RLGL.Vr.stereoTexId = rlLoadTexture(NULL, RLGL.State.framebufferWidth, RLGL.State.framebufferHeight, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, 1);
-    unsigned int depthId = rlLoadTextureDepth(RLGL.State.framebufferWidth, RLGL.State.framebufferHeight, true);
-
-    // Attach color texture and depth renderbuffer/texture to FBO
-    rlFramebufferAttach(RLGL.Vr.stereoFboId, RLGL.Vr.stereoTexId, RL_ATTACHMENT_COLOR_CHANNEL0, RL_ATTACHMENT_TEXTURE2D);
-    rlFramebufferAttach(RLGL.Vr.stereoFboId, depthId, RL_ATTACHMENT_DEPTH, RL_ATTACHMENT_RENDERBUFFER);
-
-    RLGL.Vr.simulatorReady = true;
-#else
-    TRACELOG(LOG_WARNING, "RLGL: VR Simulator not supported on OpenGL 1.1");
-#endif
-}
-
-// Update VR tracking (position and orientation) and camera
-// NOTE: Camera (position, target, up) gets update with head tracking information
-void UpdateVrTracking(Camera *camera)
-{
-    // TODO: Simulate 1st person camera system
-}
-
-// Close VR simulator for current device
-void CloseVrSimulator(void)
-{
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    if (RLGL.Vr.simulatorReady)
-    {
-        rlUnloadTexture(RLGL.Vr.stereoTexId);       // Unload color texture
-        rlUnloadFramebuffer(RLGL.Vr.stereoFboId);   // Unload stereo framebuffer and depth texture/renderbuffer
-    }
-#endif
-}
-
-// Set stereo rendering configuration parameters
-void SetVrConfiguration(VrDeviceInfo hmd, Shader distortion)
-{
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    // Reset RLGL.Vr.config for a new values assignment
-    memset(&RLGL.Vr.config, 0, sizeof(RLGL.Vr.config));
-
-    // Assign distortion shader
-    RLGL.Vr.config.distortionShader = distortion;
-
-    // Compute aspect ratio
-    float aspect = ((float)hmd.hResolution*0.5f)/(float)hmd.vResolution;
-
-    // Compute lens parameters
-    float lensShift = (hmd.hScreenSize*0.25f - hmd.lensSeparationDistance*0.5f)/hmd.hScreenSize;
-    float leftLensCenter[2] = { 0.25f + lensShift, 0.5f };
-    float rightLensCenter[2] = { 0.75f - lensShift, 0.5f };
-    float leftScreenCenter[2] = { 0.25f, 0.5f };
-    float rightScreenCenter[2] = { 0.75f, 0.5f };
-
-    // Compute distortion scale parameters
-    // NOTE: To get lens max radius, lensShift must be normalized to [-1..1]
-    float lensRadius = fabsf(-1.0f - 4.0f*lensShift);
-    float lensRadiusSq = lensRadius*lensRadius;
-    float distortionScale = hmd.lensDistortionValues[0] +
-                            hmd.lensDistortionValues[1]*lensRadiusSq +
-                            hmd.lensDistortionValues[2]*lensRadiusSq*lensRadiusSq +
-                            hmd.lensDistortionValues[3]*lensRadiusSq*lensRadiusSq*lensRadiusSq;
-
-    TRACELOGD("RLGL: VR device configuration:");
-    TRACELOGD("    > Distortion Scale: %f", distortionScale);
-
-    float normScreenWidth = 0.5f;
-    float normScreenHeight = 1.0f;
-    float scaleIn[2] = { 2.0f/normScreenWidth, 2.0f/normScreenHeight/aspect };
-    float scale[2] = { normScreenWidth*0.5f/distortionScale, normScreenHeight*0.5f*aspect/distortionScale };
-
-    TRACELOGD("    > Distortion Shader: LeftLensCenter = { %f, %f }", leftLensCenter[0], leftLensCenter[1]);
-    TRACELOGD("    > Distortion Shader: RightLensCenter = { %f, %f }", rightLensCenter[0], rightLensCenter[1]);
-    TRACELOGD("    > Distortion Shader: Scale = { %f, %f }", scale[0], scale[1]);
-    TRACELOGD("    > Distortion Shader: ScaleIn = { %f, %f }", scaleIn[0], scaleIn[1]);
-
-    // Fovy is normally computed with: 2*atan2f(hmd.vScreenSize, 2*hmd.eyeToScreenDistance)
-    // ...but with lens distortion it is increased (see Oculus SDK Documentation)
-    //float fovy = 2.0f*atan2f(hmd.vScreenSize*0.5f*distortionScale, hmd.eyeToScreenDistance);     // Really need distortionScale?
-    float fovy = 2.0f*(float)atan2f(hmd.vScreenSize*0.5f, hmd.eyeToScreenDistance);
-
-    // Compute camera projection matrices
-    float projOffset = 4.0f*lensShift;      // Scaled to projection space coordinates [-1..1]
-    Matrix proj = MatrixPerspective(fovy, aspect, RL_CULL_DISTANCE_NEAR, RL_CULL_DISTANCE_FAR);
-    RLGL.Vr.config.eyesProjection[0] = MatrixMultiply(proj, MatrixTranslate(projOffset, 0.0f, 0.0f));
-    RLGL.Vr.config.eyesProjection[1] = MatrixMultiply(proj, MatrixTranslate(-projOffset, 0.0f, 0.0f));
-
-    // Compute camera transformation matrices
-    // NOTE: 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.
-    RLGL.Vr.config.eyesViewOffset[0] = MatrixTranslate(-hmd.interpupillaryDistance*0.5f, 0.075f, 0.045f);
-    RLGL.Vr.config.eyesViewOffset[1] = MatrixTranslate(hmd.interpupillaryDistance*0.5f, 0.075f, 0.045f);
-
-    // Compute eyes Viewports
-    RLGL.Vr.config.eyeViewportRight[2] = hmd.hResolution/2;
-    RLGL.Vr.config.eyeViewportRight[3] = hmd.vResolution;
-
-    RLGL.Vr.config.eyeViewportLeft[0] = hmd.hResolution/2;
-    RLGL.Vr.config.eyeViewportLeft[1] = 0;
-    RLGL.Vr.config.eyeViewportLeft[2] = hmd.hResolution/2;
-    RLGL.Vr.config.eyeViewportLeft[3] = hmd.vResolution;
-
-    if (RLGL.Vr.config.distortionShader.id > 0)
-    {
-        // Update distortion shader with lens and distortion-scale parameters
-        SetShaderValue(RLGL.Vr.config.distortionShader, GetShaderLocation(RLGL.Vr.config.distortionShader, "leftLensCenter"), leftLensCenter, SHADER_UNIFORM_VEC2);
-        SetShaderValue(RLGL.Vr.config.distortionShader, GetShaderLocation(RLGL.Vr.config.distortionShader, "rightLensCenter"), rightLensCenter, SHADER_UNIFORM_VEC2);
-        SetShaderValue(RLGL.Vr.config.distortionShader, GetShaderLocation(RLGL.Vr.config.distortionShader, "leftScreenCenter"), leftScreenCenter, SHADER_UNIFORM_VEC2);
-        SetShaderValue(RLGL.Vr.config.distortionShader, GetShaderLocation(RLGL.Vr.config.distortionShader, "rightScreenCenter"), rightScreenCenter, SHADER_UNIFORM_VEC2);
-
-        SetShaderValue(RLGL.Vr.config.distortionShader, GetShaderLocation(RLGL.Vr.config.distortionShader, "scale"), scale, SHADER_UNIFORM_VEC2);
-        SetShaderValue(RLGL.Vr.config.distortionShader, GetShaderLocation(RLGL.Vr.config.distortionShader, "scaleIn"), scaleIn, SHADER_UNIFORM_VEC2);
-        SetShaderValue(RLGL.Vr.config.distortionShader, GetShaderLocation(RLGL.Vr.config.distortionShader, "hmdWarpParam"), hmd.lensDistortionValues, SHADER_UNIFORM_VEC4);
-        SetShaderValue(RLGL.Vr.config.distortionShader, GetShaderLocation(RLGL.Vr.config.distortionShader, "chromaAbParam"), hmd.chromaAbCorrection, SHADER_UNIFORM_VEC4);
-    }
-#endif
-}
-
-// Detect if VR simulator is running
-bool IsVrSimulatorReady(void)
-{
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    return RLGL.Vr.simulatorReady;
-#else
-    return false;
-#endif
-}
-
-// Enable/Disable VR experience (device or simulator)
-void ToggleVrMode(void)
-{
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    RLGL.Vr.simulatorReady = !RLGL.Vr.simulatorReady;
-
-    if (!RLGL.Vr.simulatorReady)
-    {
-        RLGL.Vr.stereoRender = false;
-
-        // Reset viewport and default projection-modelview matrices
-        rlViewport(0, 0, RLGL.State.framebufferWidth, RLGL.State.framebufferHeight);
-        RLGL.State.projection = MatrixOrtho(0.0, RLGL.State.framebufferWidth, RLGL.State.framebufferHeight, 0.0, 0.0, 1.0);
-        RLGL.State.modelview = MatrixIdentity();
-    }
-    else RLGL.Vr.stereoRender = true;
-#endif
-}
-
-// Begin VR drawing configuration
-void BeginVrDrawing(void)
-{
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    if (RLGL.Vr.simulatorReady)
-    {
-        rlEnableFramebuffer(RLGL.Vr.stereoFboId);   // Setup framebuffer for stereo rendering
-        //glEnable(GL_FRAMEBUFFER_SRGB);          // Enable SRGB framebuffer (only if required)
-
-        //rlViewport(0, 0, buffer.width, buffer.height); // Useful if rendering to separate framebuffers (every eye)
-        rlClearScreenBuffers();                   // Clear current framebuffer
-
-        RLGL.Vr.stereoRender = true;
-    }
-#endif
-}
-
-// End VR drawing process (and desktop mirror)
-void EndVrDrawing(void)
-{
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    if (RLGL.Vr.simulatorReady)
-    {
-        RLGL.Vr.stereoRender = false;   // Disable stereo render
-
-        rlDisableFramebuffer();         // Unbind current framebuffer
-
-        rlClearScreenBuffers();         // Clear current framebuffer
-
-        // Set viewport to default framebuffer size (screen size)
-        rlViewport(0, 0, RLGL.State.framebufferWidth, RLGL.State.framebufferHeight);
-
-        // Let rlgl reconfigure internal matrices
-        rlMatrixMode(RL_PROJECTION);                            // Enable internal projection matrix
-        rlLoadIdentity();                                       // Reset internal projection matrix
-        rlOrtho(0.0, RLGL.State.framebufferWidth, RLGL.State.framebufferHeight, 0.0, 0.0, 1.0); // Recalculate internal RLGL.State.projection matrix
-        rlMatrixMode(RL_MODELVIEW);                             // Enable internal modelview matrix
-        rlLoadIdentity();                                       // Reset internal modelview matrix
-
-        // Draw stereo framebuffer texture using distortion shader if available
-        if (RLGL.Vr.config.distortionShader.id > 0) RLGL.State.currentShader = RLGL.Vr.config.distortionShader;
-        else RLGL.State.currentShader = GetShaderDefault();
-
-        rlEnableTexture(RLGL.Vr.stereoTexId);
-
-        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-right corner for texture and quad
-                rlTexCoord2f(0.0f, 0.0f);
-                rlVertex2f(0.0f, (float)RLGL.State.framebufferHeight);
-
-                // Top-right corner for texture and quad
-                rlTexCoord2f(1.0f, 0.0f);
-                rlVertex2f((float)RLGL.State.framebufferWidth, (float)RLGL.State.framebufferHeight);
-
-                // Top-left corner for texture and quad
-                rlTexCoord2f(1.0f, 1.0f);
-                rlVertex2f((float)RLGL.State.framebufferWidth, 0.0f);
-            rlEnd();
-        rlPopMatrix();
-
-        rlDisableTexture();
-
-        // Update and draw render texture fbo with distortion to backbuffer
-        DrawRenderBatch(RLGL.currentBatch);
-
-        // Restore RLGL.State.defaultShader
-        RLGL.State.currentShader = RLGL.State.defaultShader;
-
-        // Reset viewport and default projection-modelview matrices
-        rlViewport(0, 0, RLGL.State.framebufferWidth, RLGL.State.framebufferHeight);
-        RLGL.State.projection = MatrixOrtho(0.0, RLGL.State.framebufferWidth, RLGL.State.framebufferHeight, 0.0, 0.0, 1.0);
-        RLGL.State.modelview = MatrixIdentity();
-
-        rlDisableDepthTest();
-    }
-#endif
-}
-#endif          // SUPPORT_VR_SIMULATOR
-
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
 // Module specific Functions Definition
 // Module specific Functions Definition
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
@@ -4475,15 +4212,21 @@ static void DrawRenderBatch(RenderBatch *batch)
     Matrix matModelView = RLGL.State.modelview;
     Matrix matModelView = RLGL.State.modelview;
 
 
     int eyesCount = 1;
     int eyesCount = 1;
-#if defined(SUPPORT_VR_SIMULATOR)
-    if (RLGL.Vr.stereoRender) eyesCount = 2;
-#endif
+    if (RLGL.State.stereoRender) eyesCount = 2;
 
 
     for (int eye = 0; eye < eyesCount; eye++)
     for (int eye = 0; eye < eyesCount; eye++)
     {
     {
-#if defined(SUPPORT_VR_SIMULATOR)
-        if (eyesCount == 2) SetStereoView(eye, matProjection, matModelView);
-#endif
+        if (eyesCount == 2)
+        {
+            // Setup current eye viewport (half screen width)
+            rlViewport(eye*RLGL.State.framebufferWidth/2, 0, RLGL.State.framebufferWidth/2, RLGL.State.framebufferHeight);
+
+            // Set current eye view offset to modelview matrix
+            SetMatrixModelview(MatrixMultiply(matModelView, RLGL.State.eyesViewOffset[eye]));
+            // Set current eye projection matrix
+            SetMatrixProjection(RLGL.State.eyesProjection[eye]);
+        }
+
         // Draw buffers
         // Draw buffers
         if (batch->vertexBuffer[batch->currentBuffer].vCounter > 0)
         if (batch->vertexBuffer[batch->currentBuffer].vCounter > 0)
         {
         {
@@ -4769,28 +4512,6 @@ static void GenDrawCube(void)
     glDeleteBuffers(1, &cubeVBO);
     glDeleteBuffers(1, &cubeVBO);
     glDeleteVertexArrays(1, &cubeVAO);
     glDeleteVertexArrays(1, &cubeVAO);
 }
 }
-
-#if defined(SUPPORT_VR_SIMULATOR)
-// Set internal projection and modelview matrix depending on eyes tracking data
-static void SetStereoView(int eye, Matrix matProjection, Matrix matModelView)
-{
-    Matrix eyeProjection = matProjection;
-    Matrix eyeModelView = matModelView;
-
-    // Setup viewport and projection/modelview matrices using tracking data
-    rlViewport(eye*RLGL.State.framebufferWidth/2, 0, RLGL.State.framebufferWidth/2, RLGL.State.framebufferHeight);
-
-    // Apply view offset to modelview matrix
-    eyeModelView = MatrixMultiply(matModelView, RLGL.Vr.config.eyesViewOffset[eye]);
-
-    // Set current eye projection matrix
-    eyeProjection = RLGL.Vr.config.eyesProjection[eye];
-
-    SetMatrixModelview(eyeModelView);
-    SetMatrixProjection(eyeProjection);
-}
-#endif  // SUPPORT_VR_SIMULATOR
-
 #endif  // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2
 #endif  // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2
 
 
 #if defined(GRAPHICS_API_OPENGL_11)
 #if defined(GRAPHICS_API_OPENGL_11)