Browse Source

Starting work on VR simulator support

If Oculus device is not available or not initialized correctly,
simulated VR view is generated using stereo-rendering and distortion
raysan5 9 năm trước cách đây
mục cha
commit
b01f5ff6a7
2 tập tin đã thay đổi với 113 bổ sung39 xóa
  1. 109 36
      src/rlgl.c
  2. 4 3
      src/rlgl.h

+ 109 - 36
src/rlgl.c

@@ -76,6 +76,7 @@
     #include "standard_shader.h"    // Standard shader to embed
 #endif
 
+#define RLGL_OCULUS_SUPPORT       // Enable Oculus Rift code
 #if defined(RLGL_OCULUS_SUPPORT)
     #include "external/OculusSDK/LibOVR/Include/OVR_CAPI_GL.h"    // Oculus SDK for OpenGL
 #endif
@@ -266,6 +267,8 @@ static OculusMirror mirror;             // Oculus mirror texture and fbo
 static unsigned int frameIndex = 0;     // Oculus frames counter, used to discard frames from chain
 #endif
 
+static bool vrSimulator = false;        // VR simulator (stereo rendering on window, without vr device)
+
 // Compressed textures support flags
 static bool texCompDXTSupported = false;    // DDS texture compression support
 static bool npotSupported = false;          // NPOT textures full support
@@ -306,7 +309,7 @@ static void SetShaderLights(Shader shader); // Sets shader uniform values for li
 static char *ReadTextFile(const char *fileName);
 #endif
 
-#if defined(RLGL_OCULUS_SUPPORT)            // Oculus Rift functions
+#if defined(RLGL_OCULUS_SUPPORT)
 static OculusBuffer LoadOculusBuffer(ovrSession session, int width, int height);    // Load Oculus required buffers
 static void UnloadOculusBuffer(ovrSession session, OculusBuffer buffer);            // Unload texture required buffers
 static OculusMirror LoadOculusMirror(ovrSession session, int width, int height);    // Load Oculus mirror buffers
@@ -1158,8 +1161,8 @@ void rlglDraw(void)
     }
 */
     // NOTE: Default buffers always drawn at the end
-    UpdateDefaultBuffers();
-    DrawDefaultBuffers();
+    rlglUpdateDefaultBuffers();
+    rlglDrawDefaultBuffers();
 #endif
 }
 
@@ -2471,57 +2474,86 @@ void DestroyLight(Light light)
 #endif
 }
 
-#if defined(RLGL_OCULUS_SUPPORT)
-// Init Oculus Rift device
-// NOTE: Device initialization should be done before window creation?
+// Init Oculus Rift device (or Oculus device simulator)
 void InitOculusDevice(void)
 {
+#if defined(RLGL_OCULUS_SUPPORT)
     // Initialize Oculus device
     ovrResult result = ovr_Initialize(NULL);
-    if (OVR_FAILURE(result)) TraceLog(WARNING, "OVR: Could not initialize Oculus device");
-
-    result = ovr_Create(&session, &luid);
     if (OVR_FAILURE(result))
     {
-        TraceLog(WARNING, "OVR: Could not create Oculus session");
-        ovr_Shutdown();
+        TraceLog(WARNING, "OVR: Could not initialize Oculus device");
+        TraceLog(INFO, "VR: Initializing Oculus simulator");
+        vrSimulator = true;
     }
+    else
+    {
+        result = ovr_Create(&session, &luid);
+        if (OVR_FAILURE(result))
+        {
+            TraceLog(WARNING, "OVR: Could not create Oculus session");
+            ovr_Shutdown();
+            
+            TraceLog(INFO, "VR: Initializing Oculus simulator");
+            vrSimulator = true;
+        }
+        else
+        {
+            hmdDesc = ovr_GetHmdDesc(session);
+            
+            TraceLog(INFO, "OVR: Product Name: %s", hmdDesc.ProductName);
+            TraceLog(INFO, "OVR: Manufacturer: %s", hmdDesc.Manufacturer);
+            TraceLog(INFO, "OVR: Product ID: %i", hmdDesc.ProductId);
+            TraceLog(INFO, "OVR: Product Type: %i", hmdDesc.Type);
+            //TraceLog(INFO, "OVR: Serial Number: %s", hmdDesc.SerialNumber);
+            TraceLog(INFO, "OVR: Resolution: %ix%i", hmdDesc.Resolution.w, hmdDesc.Resolution.h);
+            
+            // NOTE: Oculus mirror is set to defined screenWidth and screenHeight...
+            // ...ideally, it should be (hmdDesc.Resolution.w/2, hmdDesc.Resolution.h/2)
+            
+            // Initialize Oculus Buffers
+            layer = InitOculusLayer(session);   
+            buffer = LoadOculusBuffer(session, layer.width, layer.height);
+            mirror = LoadOculusMirror(session, hmdDesc.Resolution.w/2, hmdDesc.Resolution.h/2);     // NOTE: hardcoded...
+            layer.eyeLayer.ColorTexture[0] = buffer.textureChain;     //SetOculusLayerTexture(eyeLayer, buffer.textureChain);
+            
+            // Recenter OVR tracking origin
+            ovr_RecenterTrackingOrigin(session);
+        }
+    }
+#else
+    vrSimulator = true;
+#endif
 
-    hmdDesc = ovr_GetHmdDesc(session);
-    
-    TraceLog(INFO, "OVR: Product Name: %s", hmdDesc.ProductName);
-    TraceLog(INFO, "OVR: Manufacturer: %s", hmdDesc.Manufacturer);
-    TraceLog(INFO, "OVR: Product ID: %i", hmdDesc.ProductId);
-    TraceLog(INFO, "OVR: Product Type: %i", hmdDesc.Type);
-    //TraceLog(INFO, "OVR: Serial Number: %s", hmdDesc.SerialNumber);
-    TraceLog(INFO, "OVR: Resolution: %ix%i", hmdDesc.Resolution.w, hmdDesc.Resolution.h);
-    
-    // NOTE: Oculus mirror is set to defined screenWidth and screenHeight...
-    // ...ideally, it should be (hmdDesc.Resolution.w/2, hmdDesc.Resolution.h/2)
-    
-    // Initialize Oculus Buffers
-    layer = InitOculusLayer(session);   
-    buffer = LoadOculusBuffer(session, layer.width, layer.height);
-    mirror = LoadOculusMirror(session, hmdDesc.Resolution.w/2, hmdDesc.Resolution.h/2);     // NOTE: hardcoded...
-    layer.eyeLayer.ColorTexture[0] = buffer.textureChain;     //SetOculusLayerTexture(eyeLayer, buffer.textureChain);
-    
-    // Recenter OVR tracking origin
-    ovr_RecenterTrackingOrigin(session);
+    if (vrSimulator)
+    {
+        // TODO: Initialize framebuffer and textures for stereo rendering
+        // TODO: Load oculus-distortion shader (oculus parameters setup internally)
+    }
 }
 
-// Close Oculus Rift device
+// Close Oculus Rift device (or Oculus device simulator)
 void CloseOculusDevice(void)
 {
+#if defined(RLGL_OCULUS_SUPPORT)
     UnloadOculusMirror(session, mirror);    // Unload Oculus mirror buffer
     UnloadOculusBuffer(session, buffer);    // Unload Oculus texture buffers
 
     ovr_Destroy(session);   // Free Oculus session data
     ovr_Shutdown();         // Close Oculus device connection
+#endif
+
+    if (vrSimulator)
+    {
+        // TODO: Unload stereo framebuffer and texture
+        // TODO: Unload oculus-distortion shader
+    }
 }
 
 // Update Oculus Rift tracking (position and orientation)
 void UpdateOculusTracking(void)
 {
+#if defined(RLGL_OCULUS_SUPPORT)
     frameIndex++;
 
     ovrPosef eyePoses[2];
@@ -2540,10 +2572,21 @@ void UpdateOculusTracking(void)
     //if (sessionStatus.DisplayLost) // HMD was unplugged or the display driver was manually disabled or encountered a TDR.
     //if (sessionStatus.HmdMounted)  // HMD is on the user's head.
     //if (sessionStatus.IsVisible)   // the game or experience has VR focus and is visible in the HMD.
+#endif
+
+    if (vrSimulator)
+    {
+        // TODO: Use alternative inputs (mouse, keyboard) to simulate tracking data (eyes position/orientation)
+    }
 }
 
+// Set internal projection and modelview matrix depending on eyes tracking data
 void SetOculusView(int eye)
 {
+    Matrix eyeProjection;
+    Matrix eyeModelView;
+
+#if defined(RLGL_OCULUS_SUPPORT)
     rlViewport(layer.eyeLayer.Viewport[eye].Pos.x, layer.eyeLayer.Viewport[eye].Pos.y, layer.eyeLayer.Viewport[eye].Size.w, layer.eyeLayer.Viewport[eye].Size.h);
 
     Quaternion eyeRenderPose = (Quaternion){ layer.eyeLayer.RenderPose[eye].Orientation.x, 
@@ -2557,16 +2600,26 @@ void SetOculusView(int eye)
                                             -layer.eyeLayer.RenderPose[eye].Position.z);
 
     Matrix eyeView = MatrixMultiply(eyeTranslation, eyeOrientation);    // Matrix containing eye-head movement
-    Matrix eyeModelView = MatrixMultiply(modelview, eyeView);           // Combine internal camera matrix (modelview) wih eye-head movement
+    eyeModelView = MatrixMultiply(modelview, 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];
+#endif
+
+    if (vrSimulator)
+    {
+        // TODO: Setup viewport and projection/modelview matrices using tracking data
+    }
+
     SetMatrixModelview(eyeModelView);
-    SetMatrixProjection(layer.eyeProjections[eye]);
+    SetMatrixProjection(eyeProjection);
 }
 
+// Begin Oculus drawing configuration
 void BeginOculusDrawing(void)
 {
+#if defined(RLGL_OCULUS_SUPPORT)
     GLuint currentTexId;
     int currentIndex;
     
@@ -2576,6 +2629,13 @@ void BeginOculusDrawing(void)
     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, buffer.fboId);
     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, currentTexId, 0);
     //glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, buffer.depthId, 0);    // Already binded
+#endif
+
+    if (vrSimulator)
+    {
+        // TODO: Setup framebuffer for stereo rendering
+        //rlEnableRenderTexture(buffer.fboId);
+    }
 
     // NOTE: If your application is configured to treat the texture as a linear format (e.g. GL_RGBA) 
     // and performs linear-to-gamma conversion in GLSL or does not care about gamma-correction, then:
@@ -2587,8 +2647,10 @@ void BeginOculusDrawing(void)
     rlClearScreenBuffers();             // Clear current framebuffer(s)
 }
 
+// End Oculus drawing process (and desktop mirror)
 void EndOculusDrawing(void)
 {
+#if defined(RLGL_OCULUS_SUPPORT)
     // Unbind current framebuffer (Oculus buffer)
     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
@@ -2600,10 +2662,21 @@ void EndOculusDrawing(void)
 
     // Blit mirror texture to back buffer
     BlitOculusMirror(session, mirror);
-    
+#endif
+
+    if (vrSimulator)
+    {
+        // Unbind current framebuffer
+        //rlDisableRenderTexture();
+
+        // TODO: Draw RenderTexture (fbo) using distortion shader 
+        //BeginShaderMode(distortion);
+            // TODO: DrawTextureRec(target.texture, (Rectangle){ 0, 0, target.texture.width, -target.texture.height }, (Vector2){ 0, 0 }, WHITE);
+        //EndShaderMode();
+    }
+
     rlDisableDepthTest();
 }
-#endif
 
 //----------------------------------------------------------------------------------
 // Module specific Functions Definition

+ 4 - 3
src/rlgl.h

@@ -48,7 +48,7 @@
 
 // Choose opengl version here or just define it at compile time: -DGRAPHICS_API_OPENGL_33
 //#define GRAPHICS_API_OPENGL_11     // Only available on PLATFORM_DESKTOP
-//#define GRAPHICS_API_OPENGL_33     // Only available on PLATFORM_DESKTOP or PLATFORM_OCULUS
+//#define GRAPHICS_API_OPENGL_33     // Only available on PLATFORM_DESKTOP and RLGL_OCULUS_SUPPORT
 //#define GRAPHICS_API_OPENGL_ES2    // Only available on PLATFORM_ANDROID or PLATFORM_RPI or PLATFORM_WEB
 
 // Security check in case no GRAPHICS_API_OPENGL_* defined
@@ -304,6 +304,9 @@ void rlglDraw(void);                            // Draw VAO/VBO
 void rlglInitGraphics(int offsetX, int offsetY, int width, int height);  // Initialize Graphics (OpenGL stuff)
 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
 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
@@ -353,14 +356,12 @@ void DestroyLight(Light light);                                     // Destroy a
 void TraceLog(int msgType, const char *text, ...);
 #endif
 
-#if defined(RLGL_OCULUS_SUPPORT)
 void InitOculusDevice(void);                // Init Oculus Rift device
 void CloseOculusDevice(void);               // Close Oculus Rift device
 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 EndOculusDrawing(void);                // End Oculus drawing process (and desktop mirror)
-#endif
 
 #ifdef __cplusplus
 }