Browse Source

REDESIGNED: Vr stereo rendering

pull/1711/head
Ray 3 years ago
parent
commit
71b86bf4d0
4 changed files with 174 additions and 220 deletions
  1. +8
    -11
      examples/core/core_vr_simulator.c
  2. +0
    -2
      src/config.h
  3. +156
    -194
      src/core.c
  4. +10
    -13
      src/raylib.h

+ 8
- 11
examples/core/core_vr_simulator.c View File

@ -12,9 +12,9 @@
#include "raylib.h"
#if defined(PLATFORM_DESKTOP)
#define GLSL_VERSION 330
#define GLSL_VERSION 330
#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB
#define GLSL_VERSION 100
#define GLSL_VERSION 100
#endif
int main(void)
@ -51,11 +51,8 @@ int main(void)
.chromaAbCorrection[3] = 0.0f, // Chromatic aberration correction parameter 3
};
// Init VR simulator (Oculus Rift CV1 parameters)
InitVrSimulator(device);
// Get Vr stereo config parameters for device parameters
VrStereoConfig config = GetVrConfig(device);
// Load VR stereo config for VR device parameteres (Oculus Rift CV1 parameters)
VrStereoConfig config = LoadVrStereoMode(device);
// Distortion shader (uses device lens distortion and chroma)
Shader distortion = LoadShader(0, TextFormat("resources/distortion%i.fs", GLSL_VERSION));
@ -104,7 +101,7 @@ int main(void)
ClearBackground(RAYWHITE);
BeginVrDrawing(target);
BeginVrStereoMode(target, config);
BeginMode3D(camera);
DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED);
@ -113,7 +110,7 @@ int main(void)
DrawGrid(40, 1.0f);
EndMode3D();
EndVrDrawing();
EndVrStereoMode();
BeginShaderMode(distortion);
DrawTextureRec(target.texture, (Rectangle){ 0, 0, (float)target.texture.width, (float)-target.texture.height }, (Vector2){ 0.0f, 0.0f }, WHITE);
@ -127,11 +124,11 @@ int main(void)
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadVrStereoConfig(config); // Unload stereo config
UnloadRenderTexture(target); // Unload stereo render fbo
UnloadShader(distortion); // Unload distortion shader
CloseVrSimulator(); // Close VR simulator
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------

+ 0
- 2
src/config.h View File

@ -57,8 +57,6 @@
#define SUPPORT_COMPRESSION_API 1
// Support saving binary data automatically to a generated storage.data file. This file is managed internally.
#define SUPPORT_DATA_STORAGE 1
// Support VR simulation functionality (stereo rendering)
#define SUPPORT_VR_SIMULATOR 1
// core: Configuration values
//------------------------------------------------------------------------------------

+ 156
- 194
src/core.c View File

@ -82,8 +82,6 @@
* #define SUPPORT_DATA_STORAGE
* 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:
* rglfw - Manage graphic device, OpenGL context and inputs on PLATFORM_DESKTOP (Windows, Linux, OSX. FreeBSD, OpenBSD, NetBSD, DragonFly)
@ -165,7 +163,7 @@
#include <stdio.h> // Required for: sprintf() [Used in OpenURL()]
#include <string.h> // Required for: strrchr(), strcmp(), strlen()
#include <time.h> // Required for: time() [Used in InitTimer()]
#include <math.h> // Required for: tan() [Used in BeginMode3D()], atan2f() [Used in InitVrSimulator()]
#include <math.h> // Required for: tan() [Used in BeginMode3D()], atan2f() [Used in LoadVrStereoMode()]
#include <sys/stat.h> // Required for: stat() [Used in GetFileModTime()]
@ -480,15 +478,6 @@ typedef struct CoreData {
unsigned long long base; // Base time measure for hi-res timer
#endif
} 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;
//----------------------------------------------------------------------------------
@ -2035,6 +2024,161 @@ void EndTextureMode(void)
CORE.Window.currentFbo.height = CORE.Window.screen.height;
}
// Begin custom shader mode
void BeginShaderMode(Shader shader)
{
rlSetShader(shader);
}
// End custom shader mode (returns to default shader)
void EndShaderMode(void)
{
rlSetShader(rlGetShaderDefault());
}
// Begin blending mode (alpha, additive, multiplied)
// NOTE: Only 3 blending modes supported, default blend mode is alpha
void BeginBlendMode(int mode)
{
rlSetBlendMode(mode);
}
// End blending mode (reset to default: alpha blending)
void EndBlendMode(void)
{
rlSetBlendMode(BLEND_ALPHA);
}
// Begin scissor mode (define screen area for following drawing)
// NOTE: Scissor rec refers to bottom-left corner, we change it to upper-left
void BeginScissorMode(int x, int y, int width, int height)
{
rlDrawRenderBatchActive(); // Update and draw internal render batch
rlEnableScissorTest();
rlScissor(x, CORE.Window.currentFbo.height - (y + height), width, height);
}
// End scissor mode
void EndScissorMode(void)
{
rlDrawRenderBatchActive(); // Update and draw internal render batch
rlDisableScissorTest();
}
// Begin VR drawing configuration
void BeginVrStereoMode(RenderTexture2D target, VrStereoConfig config)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
rlEnableFramebuffer(target.id); // Setup framebuffer for stereo rendering
//glEnable(GL_FRAMEBUFFER_SRGB); // Enable SRGB framebuffer (only if required)
rlClearScreenBuffers(); // Clear current framebuffer
rlEnableStereoRender();
// Set stereo render matrices
rlSetMatrixProjectionStereo(config.projection[0], config.projection[1]);
rlSetMatrixViewOffsetStereo(config.viewOffset[0], config.viewOffset[1]);
#endif
}
// End VR drawing process (and desktop mirror)
void EndVrStereoMode(void)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
rlDisableStereoRender();
rlDisableFramebuffer(); // Unbind current framebuffer
// Reset viewport and default projection-modelview matrices
rlViewport(0, 0, GetScreenWidth(), GetScreenHeight());
rlSetMatrixProjection(MatrixOrtho(0.0, GetScreenWidth(), GetScreenHeight(), 0.0, 0.0, 1.0));
rlSetMatrixModelview(MatrixIdentity());
rlDisableDepthTest();
#endif
}
// Load VR stereo config for VR simulator device parameters
VrStereoConfig LoadVrStereoMode(VrDeviceInfo device)
{
VrStereoConfig config = { 0 };
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
// 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;
config.leftLensCenter[0] = 0.25f + lensShift;
config.leftLensCenter[1] = 0.5f;
config.rightLensCenter[0] = 0.75f - lensShift;
config.rightLensCenter[1] = 0.5f;
config.leftScreenCenter[0] = 0.25f;
config.leftScreenCenter[1] = 0.5f;
config.rightScreenCenter[0] = 0.75f;
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;
config.scaleIn[0] = 2.0f/normScreenWidth;
config.scaleIn[1] = 2.0f/normScreenHeight/aspect;
config.scale[0] = normScreenWidth*0.5f/distortionScale;
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);
config.projection[0] = MatrixMultiply(proj, MatrixTranslate(projOffset, 0.0f, 0.0f));
config.projection[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.
config.viewOffset[0] = MatrixTranslate(-device.interpupillaryDistance*0.5f, 0.075f, 0.045f);
config.viewOffset[1] = MatrixTranslate(device.interpupillaryDistance*0.5f, 0.075f, 0.045f);
// Compute eyes Viewports
/*
config.eyeViewportRight[0] = 0;
config.eyeViewportRight[1] = 0;
config.eyeViewportRight[2] = device.hResolution/2;
config.eyeViewportRight[3] = device.vResolution;
config.eyeViewportLeft[0] = device.hResolution/2;
config.eyeViewportLeft[1] = 0;
config.eyeViewportLeft[2] = device.hResolution/2;
config.eyeViewportLeft[3] = device.vResolution;
*/
#else
TRACELOG(LOG_WARNING, "RLGL: VR Simulator not supported on OpenGL 1.1");
#endif
return config;
}
// Unload VR stereo config properties
void UnloadVrStereoConfig(VrStereoConfig config)
{
//...
}
// Load shader from files and bind default locations
// NOTE: If shader string is NULL, using default vertex/fragment shaders
Shader LoadShader(const char *vsFileName, const char *fsFileName)
@ -2147,18 +2291,6 @@ void UnloadShader(Shader shader)
}
}
// Begin custom shader mode
void BeginShaderMode(Shader shader)
{
rlSetShader(shader);
}
// End custom shader mode (returns to default shader)
void EndShaderMode(void)
{
rlSetShader(rlGetShaderDefault());
}
// Get shader uniform location
int GetShaderLocation(Shader shader, const char *uniformName)
{
@ -2201,176 +2333,6 @@ void SetShaderValueTexture(Shader shader, int locIndex, Texture2D texture)
//rlDisableShader();
}
// Begin blending mode (alpha, additive, multiplied)
// NOTE: Only 3 blending modes supported, default blend mode is alpha
void BeginBlendMode(int mode)
{
rlSetBlendMode(mode);
}
// End blending mode (reset to default: alpha blending)
void EndBlendMode(void)
{
rlSetBlendMode(BLEND_ALPHA);
}
#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, GetScreenWidth(), GetScreenHeight());
rlSetMatrixProjection(MatrixOrtho(0.0, GetScreenWidth(), GetScreenHeight(), 0.0, 0.0, 1.0));
rlSetMatrixModelview(MatrixIdentity());
rlDisableDepthTest();
}
#endif
}
#endif // SUPPORT_VR_SIMULATOR
// Begin scissor mode (define screen area for following drawing)
// NOTE: Scissor rec refers to bottom-left corner, we change it to upper-left
void BeginScissorMode(int x, int y, int width, int height)
{
rlDrawRenderBatchActive(); // Update and draw internal render batch
rlEnableScissorTest();
rlScissor(x, CORE.Window.currentFbo.height - (y + height), width, height);
}
// End scissor mode
void EndScissorMode(void)
{
rlDrawRenderBatchActive(); // Update and draw internal render batch
rlDisableScissorTest();
}
// Returns a ray trace from mouse position
Ray GetMouseRay(Vector2 mouse, Camera camera)
{

+ 10
- 13
src/raylib.h View File

@ -463,6 +463,8 @@ typedef struct VrDeviceInfo {
// VR Stereo rendering configuration for simulator
typedef struct VrStereoConfig {
Matrix projection[2]; // VR projection matrices (per eye)
Matrix viewOffset[2]; // VR view offset matrices (per eye)
float leftLensCenter[2]; // VR left lens center
float rightLensCenter[2]; // VR right lens center
float leftScreenCenter[2]; // VR left screen center
@ -957,12 +959,18 @@ RLAPI void BeginMode3D(Camera3D camera); // Initializes
RLAPI void EndMode3D(void); // Ends 3D mode and returns to default 2D orthographic mode
RLAPI void BeginTextureMode(RenderTexture2D target); // Initializes render texture for drawing
RLAPI void EndTextureMode(void); // Ends drawing to render texture
RLAPI void BeginScissorMode(int x, int y, int width, int height); // Begin scissor mode (define screen area for following drawing)
RLAPI void EndScissorMode(void); // End scissor mode
RLAPI void BeginShaderMode(Shader shader); // Begin custom shader drawing
RLAPI void EndShaderMode(void); // End custom shader drawing (use default shader)
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 BeginScissorMode(int x, int y, int width, int height); // Begin scissor mode (define screen area for following drawing)
RLAPI void EndScissorMode(void); // End scissor mode
RLAPI void BeginVrStereoMode(RenderTexture2D target, VrStereoConfig config); // Begin stereo rendering (requires VR simulator)
RLAPI void EndVrStereoMode(void); // End stereo rendering (requires VR simulator)
// VR stereo config functions for VR simulator
RLAPI VrStereoConfig LoadVrStereoMode(VrDeviceInfo device); // Load VR stereo config for VR simulator device parameters
RLAPI void UnloadVrStereoConfig(VrStereoConfig config); // Unload VR stereo config
// Shader management functions
// NOTE: Shader functionality is not available on OpenGL 1.1
@ -1112,17 +1120,6 @@ RLAPI void SetCameraAltControl(int keyAlt); // Set camera alt key to
RLAPI void SetCameraSmoothZoomControl(int keySmoothZoom); // Set camera smooth zoom key to combine with mouse (free camera)
RLAPI void SetCameraMoveControls(int keyFront, int keyBack, int keyRight, int keyLeft, int keyUp, int keyDown); // Set camera move controls (1st person and 3rd person cameras)
//------------------------------------------------------------------------------------
// VR Simulator Functions (Module: core)
//------------------------------------------------------------------------------------
RLAPI void InitVrSimulator(VrDeviceInfo device); // Init VR simulator for selected device parameters
RLAPI void CloseVrSimulator(void); // Close VR simulator for current device
RLAPI bool IsVrSimulatorReady(void); // Detect if VR simulator is ready
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 VrStereoConfig GetVrConfig(VrDeviceInfo device); // Get stereo rendering configuration parameters
//------------------------------------------------------------------------------------
// Basic Shapes Drawing Functions (Module: shapes)
//------------------------------------------------------------------------------------

Loading…
Cancel
Save