Ver código fonte

Review VR simulator mechanism

- No default VR device parameteres inside raylib
- VR device parameter should be provided by user
- VR distortion shader should be provided by user
pull/798/head
Ray 6 anos atrás
pai
commit
5bfa675350
5 arquivos alterados com 201 adições e 326 exclusões
  1. +34
    -4
      examples/core/core_vr_simulator.c
  2. +43
    -0
      examples/core/resources/distortion.fs
  3. +0
    -2
      src/config.h
  4. +5
    -25
      src/raylib.h
  5. +119
    -295
      src/rlgl.h

+ 34
- 4
examples/core/core_vr_simulator.c Ver arquivo

@ -23,7 +23,35 @@ int main()
InitWindow(screenWidth, screenHeight, "raylib [core] example - vr simulator");
// Init VR simulator (Oculus Rift CV1 parameters)
InitVrSimulator(GetVrDeviceInfo(HMD_OCULUS_RIFT_CV1));
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
// Distortion shader (uses device lens distortion and chroma)
Shader distortion = LoadShader(0, "resources/distortion.fs");
SetVrConfiguration(hmd, distortion); // Set Vr device parameters for stereo rendering
// Define the camera to look into our 3d world
Camera camera;
@ -77,9 +105,11 @@ int main()
// De-Initialization
//--------------------------------------------------------------------------------------
CloseVrSimulator(); // Close VR simulator
CloseWindow(); // Close window and OpenGL context
UnloadShader(distortion); // Unload distortion shader
CloseVrSimulator(); // Close VR simulator
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;

+ 43
- 0
examples/core/resources/distortion.fs Ver arquivo

@ -0,0 +1,43 @@
#version 330
in vec2 fragTexCoord;
in vec4 fragColor;
out vec4 finalColor;
uniform sampler2D texture0;
uniform vec2 leftLensCenter = vec2(0.288, 0.5);
uniform vec2 rightLensCenter = vec2(0.712, 0.5);
uniform vec2 leftScreenCenter = vec2(0.25, 0.5);
uniform vec2 rightScreenCenter = vec2(0.75, 0.5);
uniform vec2 scale = vec2(0.25, 0.45);
uniform vec2 scaleIn = vec2(4, 2.2222);
uniform vec4 hmdWarpParam = vec4(1, 0.22, 0.24, 0);
uniform vec4 chromaAbParam = vec4(0.996, -0.004, 1.014, 0.0);
void main()
{
vec2 lensCenter = fragTexCoord.x < 0.5? leftLensCenter : rightLensCenter;
vec2 screenCenter = fragTexCoord.x < 0.5? leftScreenCenter : rightScreenCenter;
vec2 theta = (fragTexCoord - lensCenter)*scaleIn;
float rSq = theta.x*theta.x + theta.y*theta.y;
vec2 theta1 = theta*(hmdWarpParam.x + hmdWarpParam.y*rSq + hmdWarpParam.z*rSq*rSq + hmdWarpParam.w*rSq*rSq*rSq);
vec2 thetaBlue = theta1*(chromaAbParam.z + chromaAbParam.w*rSq);
vec2 tcBlue = lensCenter + scale*thetaBlue;
if (any(bvec2(clamp(tcBlue, screenCenter - vec2(0.25, 0.5), screenCenter + vec2(0.25, 0.5)) - tcBlue)))
{
finalColor = vec4(0.0, 0.0, 0.0, 1.0);
}
else
{
float blue = texture(texture0, tcBlue).b;
vec2 tcGreen = lensCenter + scale*theta1;
float green = texture(texture0, tcGreen).g;
vec2 thetaRed = theta1*(chromaAbParam.x + chromaAbParam.y*rSq);
vec2 tcRed = lensCenter + scale*thetaRed;
float red = texture(texture0, tcRed).r;
finalColor = vec4(red, green, blue, 1.0);
}
};

+ 0
- 2
src/config.h Ver arquivo

@ -57,8 +57,6 @@
//------------------------------------------------------------------------------------
// Support VR simulation functionality (stereo rendering)
#define SUPPORT_VR_SIMULATOR 1
// Include stereo rendering distortion shader (shader_distortion.h)
#define SUPPORT_DISTORTION_SHADER 1
//------------------------------------------------------------------------------------

+ 5
- 25
src/raylib.h Ver arquivo

@ -443,16 +443,6 @@ typedef struct VrDeviceInfo {
float chromaAbCorrection[4]; // HMD chromatic aberration correction parameters
} VrDeviceInfo;
// VR Stereo rendering configuration for simulator
typedef struct VrStereoConfig {
RenderTexture2D stereoFbo; // VR stereo rendering framebuffer
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;
//----------------------------------------------------------------------------------
// Enumerators Definition
//----------------------------------------------------------------------------------
@ -860,16 +850,6 @@ typedef enum {
CAMERA_ORTHOGRAPHIC
} CameraType;
// Head Mounted Display devices
typedef enum {
HMD_DEFAULT_DEVICE = 0,
HMD_OCULUS_RIFT_DK2,
HMD_OCULUS_RIFT_CV1,
HMD_OCULUS_GO,
HMD_VALVE_HTC_VIVE,
HMD_SONY_PSVR
} VrDeviceType;
// Type of n-patch
typedef enum {
NPT_9PATCH = 0, // Npatch defined by 3x3 tiles
@ -1330,7 +1310,7 @@ RLAPI Shader GetShaderDefault(void); // Get
RLAPI Texture2D GetTextureDefault(void); // Get default texture
// Shader configuration functions
RLAPI int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location
RLAPI int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location
RLAPI void SetShaderValue(Shader shader, int uniformLoc, const void *value, int uniformType); // Set shader uniform value
RLAPI void SetShaderValueV(Shader shader, int uniformLoc, const void *value, int uniformType, int count); // Set shader uniform value vector
RLAPI void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat); // Set shader uniform value (matrix 4x4)
@ -1344,7 +1324,7 @@ RLAPI Matrix GetMatrixModelview(); // Get
RLAPI Texture2D GenTextureCubemap(Shader shader, Texture2D skyHDR, int size); // Generate cubemap texture from HDR texture
RLAPI Texture2D GenTextureIrradiance(Shader shader, Texture2D cubemap, int size); // Generate irradiance texture using cubemap data
RLAPI Texture2D GenTexturePrefilter(Shader shader, Texture2D cubemap, int size); // Generate prefilter texture using cubemap data
RLAPI Texture2D GenTextureBRDF(Shader shader, int size); // Generate BRDF texture using cubemap data
RLAPI Texture2D GenTextureBRDF(Shader shader, int size); // Generate BRDF texture
// Shading begin/end functions
RLAPI void BeginShaderMode(Shader shader); // Begin custom shader drawing
@ -1355,10 +1335,10 @@ RLAPI void BeginScissorMode(int x, int y, int width, int height); // Beg
RLAPI void EndScissorMode(void); // End scissor mode
// VR control functions
RLAPI VrDeviceInfo GetVrDeviceInfo(int vrDeviceType); // Get VR device information for some standard devices
RLAPI void InitVrSimulator(VrDeviceInfo info); // Init VR simulator for selected device parameters
RLAPI void UpdateVrTracking(Camera *camera); // Update VR tracking (position and orientation) and camera
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

+ 119
- 295
src/rlgl.h Ver arquivo

@ -32,9 +32,6 @@
* #define SUPPORT_VR_SIMULATOR
* Support VR simulation functionality (stereo rendering)
*
* #define SUPPORT_DISTORTION_SHADER
* Include stereo rendering distortion shader (embedded)
*
* DEPENDENCIES:
* raymath - 3D math functionality (Vector3, Matrix, Quaternion)
* GLAD - OpenGL extensions loading (OpenGL 3.3 Core only)
@ -263,7 +260,6 @@ typedef unsigned char byte;
// VR Stereo rendering configuration for simulator
typedef struct VrStereoConfig {
RenderTexture2D stereoFbo; // VR stereo rendering framebuffer
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
@ -390,16 +386,6 @@ typedef unsigned char byte;
#define MAP_DIFFUSE MAP_ALBEDO
#define MAP_SPECULAR MAP_METALNESS
// VR Head Mounted Display devices
typedef enum {
HMD_DEFAULT_DEVICE = 0,
HMD_OCULUS_RIFT_DK2,
HMD_OCULUS_RIFT_CV1,
HMD_OCULUS_GO,
HMD_VALVE_HTC_VIVE,
HMD_SONY_PSVR
} VrDevice;
#endif
#if defined(__cplusplus)
@ -534,14 +520,14 @@ void BeginBlendMode(int mode); // Begin blending mode (alpha,
void EndBlendMode(void); // End blending mode (reset to default: alpha blending)
// VR control functions
VrDeviceInfo GetVrDeviceInfo(int vrDeviceType); // Get VR device information for some standard devices
kt">void InitVrSimulator(VrDeviceInfo info); // Init VR simulator for selected device parameters
void UpdateVrTracking(Camera *camera); // Update VR tracking (position and orientation) and camera
kt">void CloseVrSimulator(void); // Close VR simulator for current device
bool IsVrSimulatorReady(void); // Detect if VR simulator is ready
void ToggleVrMode(void); // Enable/Disable VR experience
void BeginVrDrawing(void); // Begin VR simulator stereo rendering
void EndVrDrawing(void); // End VR simulator stereo rendering
RLAPI void InitVrSimulator(void); // Init VR simulator for selected device parameters
n">RLAPI void CloseVrSimulator(void); // Close VR simulator for current device
RLAPI void UpdateVrTracking(Camera *camera); // Update VR tracking (position and orientation) and camera
n">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
void TraceLog(int msgType, const char *text, ...); // Show trace log messages (LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_DEBUG)
int GetPixelDataSize(int width, int height, int format);// Get pixel data size in bytes (image or texture)
@ -561,10 +547,7 @@ int GetPixelDataSize(int width, int height, int format);// Get pixel data size i
#if defined(RLGL_IMPLEMENTATION)
#if defined(RLGL_STANDALONE)
#define SUPPORT_VR_SIMULATOR
#define SUPPORT_DISTORTION_SHADER
#else
#if !defined(RLGL_STANDALONE)
// Check if config flags have been externally provided on compilation line
#if !defined(EXTERNAL_CONFIG_FLAGS)
#include "config.h" // Defines module configuration flags
@ -740,88 +723,20 @@ typedef struct DrawCall {
//Matrix modelview; // Modelview matrix for this draw
} DrawCall;
#if defined(SUPPORT_VR_SIMULATOR)
// 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
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
#if !defined(GRAPHICS_API_OPENGL_11) && defined(SUPPORT_DISTORTION_SHADER)
// Distortion shader embedded
static char distortionFShaderStr[] =
#if defined(GRAPHICS_API_OPENGL_21)
"#version 120 \n"
#elif defined(GRAPHICS_API_OPENGL_ES2)
"#version 100 \n"
"precision mediump float; \n" // precision required for OpenGL ES2 (WebGL)
#endif
#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21)
"varying vec2 fragTexCoord; \n"
"varying vec4 fragColor; \n"
#elif defined(GRAPHICS_API_OPENGL_33)
"#version 330 \n"
"in vec2 fragTexCoord; \n"
"in vec4 fragColor; \n"
"out vec4 finalColor; \n"
#endif
"uniform sampler2D texture0; \n"
#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21)
"uniform vec2 leftLensCenter; \n"
"uniform vec2 rightLensCenter; \n"
"uniform vec2 leftScreenCenter; \n"
"uniform vec2 rightScreenCenter; \n"
"uniform vec2 scale; \n"
"uniform vec2 scaleIn; \n"
"uniform vec4 hmdWarpParam; \n"
"uniform vec4 chromaAbParam; \n"
#elif defined(GRAPHICS_API_OPENGL_33)
"uniform vec2 leftLensCenter = vec2(0.288, 0.5); \n"
"uniform vec2 rightLensCenter = vec2(0.712, 0.5); \n"
"uniform vec2 leftScreenCenter = vec2(0.25, 0.5); \n"
"uniform vec2 rightScreenCenter = vec2(0.75, 0.5); \n"
"uniform vec2 scale = vec2(0.25, 0.45); \n"
"uniform vec2 scaleIn = vec2(4, 2.2222); \n"
"uniform vec4 hmdWarpParam = vec4(1, 0.22, 0.24, 0); \n"
"uniform vec4 chromaAbParam = vec4(0.996, -0.004, 1.014, 0.0); \n"
#endif
"void main() \n"
"{ \n"
" vec2 lensCenter = fragTexCoord.x < 0.5? leftLensCenter : rightLensCenter; \n"
" vec2 screenCenter = fragTexCoord.x < 0.5? leftScreenCenter : rightScreenCenter; \n"
" vec2 theta = (fragTexCoord - lensCenter)*scaleIn; \n"
" float rSq = theta.x*theta.x + theta.y*theta.y; \n"
" vec2 theta1 = theta*(hmdWarpParam.x + hmdWarpParam.y*rSq + hmdWarpParam.z*rSq*rSq + hmdWarpParam.w*rSq*rSq*rSq); \n"
" vec2 thetaBlue = theta1*(chromaAbParam.z + chromaAbParam.w*rSq); \n"
" vec2 tcBlue = lensCenter + scale*thetaBlue; \n"
" if (any(bvec2(clamp(tcBlue, screenCenter - vec2(0.25, 0.5), screenCenter + vec2(0.25, 0.5)) - tcBlue))) \n"
" { \n"
#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21)
" gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); \n"
#elif defined(GRAPHICS_API_OPENGL_33)
" finalColor = vec4(0.0, 0.0, 0.0, 1.0); \n"
#endif
" } \n"
" else \n"
" { \n"
#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21)
" float blue = texture2D(texture0, tcBlue).b; \n"
" vec2 tcGreen = lensCenter + scale*theta1; \n"
" float green = texture2D(texture0, tcGreen).g; \n"
#elif defined(GRAPHICS_API_OPENGL_33)
" float blue = texture(texture0, tcBlue).b; \n"
" vec2 tcGreen = lensCenter + scale*theta1; \n"
" float green = texture(texture0, tcGreen).g; \n"
#endif
" vec2 thetaRed = theta1*(chromaAbParam.x + chromaAbParam.y*rSq); \n"
" vec2 tcRed = lensCenter + scale*thetaRed; \n"
#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21)
" float red = texture2D(texture0, tcRed).r; \n"
" gl_FragColor = vec4(red, green, blue, 1.0); \n"
#elif defined(GRAPHICS_API_OPENGL_33)
" float red = texture(texture0, tcRed).r; \n"
" finalColor = vec4(red, green, blue, 1.0); \n"
#endif
" } \n"
"} \n";
#endif
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
static Matrix stack[MAX_MATRIX_STACK_SIZE] = { 0 };
static int stackCounter = 0;
@ -891,6 +806,7 @@ static PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArrays;
#if defined(SUPPORT_VR_SIMULATOR)
// VR global variables
static VrStereoConfig vrConfig = { 0 }; // VR stereo configuration for simulator
static RenderTexture2D stereoFbo; // VR stereo rendering framebuffer
static bool vrSimulatorReady = false; // VR simulator ready flag
static bool vrStereoRender = false; // VR stereo rendering enabled/disabled flag
// NOTE: This flag is useful to render data over stereo image (i.e. FPS)
@ -924,7 +840,6 @@ static void GenDrawCube(void); // Generate and draw cube
static void GenDrawQuad(void); // Generate and draw quad
#if defined(SUPPORT_VR_SIMULATOR)
static VrStereoConfig SetStereoConfig(VrDeviceInfo info, Shader distortion); // Configure stereo rendering (including distortion shader) with HMD device parameters
static void SetStereoView(int eye, Matrix matProjection, Matrix matModelView); // Set internal projection and modelview matrix depending on eye
#endif
@ -3577,101 +3492,17 @@ void EndScissorMode(void)
}
#if defined(SUPPORT_VR_SIMULATOR)
// Get VR device information for some standard devices
VrDeviceInfo GetVrDeviceInfo(int vrDeviceType)
{
VrDeviceInfo hmd = { 0 }; // Current VR device info
switch (vrDeviceType)
{
case HMD_DEFAULT_DEVICE:
case HMD_OCULUS_RIFT_CV1:
{
// Oculus Rift CV1 parameters
// NOTE: CV1 represents a complete HMD redesign compared to previous versions,
// new Fresnel-hybrid-asymmetric lenses have been added and, consequently,
// previous parameters (DK2) and distortion shader (DK2) doesn't work any more.
// I just defined a set of parameters for simulator that approximate to CV1 stereo rendering
// but result is not the same obtained with Oculus PC SDK.
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
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
TraceLog(LOG_INFO, "Initializing VR Simulator (Oculus Rift CV1)");
} break;
case HMD_OCULUS_RIFT_DK2:
{
// Oculus Rift DK2 parameters
hmd.hResolution = 1280; // HMD horizontal resolution in pixels
hmd.vResolution = 800; // HMD vertical resolution in pixels
hmd.hScreenSize = 0.14976f; // HMD horizontal size in meters
hmd.vScreenSize = 0.09356f; // 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.0635f; // HMD lens separation distance in meters
hmd.interpupillaryDistance = 0.064f; // HMD IPD (distance between pupils) in meters
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
TraceLog(LOG_INFO, "Initializing VR Simulator (Oculus Rift DK2)");
} break;
case HMD_OCULUS_GO:
{
// TODO: Provide device display and lens parameters
}
case HMD_VALVE_HTC_VIVE:
{
// TODO: Provide device display and lens parameters
}
case HMD_SONY_PSVR:
{
// TODO: Provide device display and lens parameters
}
default: break;
}
return hmd;
}
// Init VR simulator for selected device parameters
// NOTE: It modifies the global variable: VrStereoConfig vrConfig
void InitVrSimulator(n">VrDeviceInfo info)
// NOTE: It modifies the global variable: stereoFbo
void InitVrSimulator(void)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
Shader distortion = { 0 };
#if defined(SUPPORT_DISTORTION_SHADER)
// Load distortion shader
distortion = LoadShaderCode(NULL, distortionFShaderStr);
if (distortion.id > 0) SetShaderDefaultLocations(&distortion);
#endif
// Set VR configutarion parameters, including distortion shader
vrConfig = SetStereoConfig(info, distortion);
// Initialize framebuffer and textures for stereo rendering
// NOTE: Screen size should match HMD aspect ratio
stereoFbo = rlLoadRenderTexture(screenWidth, screenHeight, UNCOMPRESSED_R8G8B8A8, 24, false);
vrSimulatorReady = true;
#endif
#if defined(GRAPHICS_API_OPENGL_11)
#else
TraceLog(LOG_WARNING, "VR Simulator not supported on OpenGL 1.1");
#endif
}
@ -3687,14 +3518,90 @@ void UpdateVrTracking(Camera *camera)
void CloseVrSimulator(void)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
if (vrSimulatorReady)
if (vrSimulatorReady) rlDeleteRenderTextures(stereoFbo); // Unload stereo framebuffer and texture
#endif
}
// Set stereo rendering configuration parameters
void SetVrConfiguration(VrDeviceInfo hmd, Shader distortion)
{
// Reset vrConfig for a new values assignment
memset(&vrConfig, 0, sizeof(vrConfig));
// Assign distortion shader
vrConfig.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 = (float)fabs(-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;
TraceLog(LOG_DEBUG, "VR: 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 };
TraceLog(LOG_DEBUG, "VR: Distortion Shader: LeftLensCenter = { %f, %f }", leftLensCenter[0], leftLensCenter[1]);
TraceLog(LOG_DEBUG, "VR: Distortion Shader: RightLensCenter = { %f, %f }", rightLensCenter[0], rightLensCenter[1]);
TraceLog(LOG_DEBUG, "VR: Distortion Shader: Scale = { %f, %f }", scale[0], scale[1]);
TraceLog(LOG_DEBUG, "VR: Distortion Shader: ScaleIn = { %f, %f }", scaleIn[0], scaleIn[1]);
// Fovy is normally computed with: 2*atan2(hmd.vScreenSize, 2*hmd.eyeToScreenDistance)
// ...but with lens distortion it is increased (see Oculus SDK Documentation)
//float fovy = 2.0f*atan2(hmd.vScreenSize*0.5f*distortionScale, hmd.eyeToScreenDistance); // Really need distortionScale?
float fovy = 2.0f*(float)atan2(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, 0.01, 1000.0);
vrConfig.eyesProjection[0] = MatrixMultiply(proj, MatrixTranslate(projOffset, 0.0f, 0.0f));
vrConfig.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.
vrConfig.eyesViewOffset[0] = MatrixTranslate(-hmd.interpupillaryDistance*0.5f, 0.075f, 0.045f);
vrConfig.eyesViewOffset[1] = MatrixTranslate(hmd.interpupillaryDistance*0.5f, 0.075f, 0.045f);
// Compute eyes Viewports
vrConfig.eyeViewportRight[2] = hmd.hResolution/2;
vrConfig.eyeViewportRight[3] = hmd.vResolution;
vrConfig.eyeViewportLeft[0] = hmd.hResolution/2;
vrConfig.eyeViewportLeft[1] = 0;
vrConfig.eyeViewportLeft[2] = hmd.hResolution/2;
vrConfig.eyeViewportLeft[3] = hmd.vResolution;
if (vrConfig.distortionShader.id > 0)
{
rlDeleteRenderTextures(vrConfig.stereoFbo); // Unload stereo framebuffer and texture
#if defined(SUPPORT_DISTORTION_SHADER)
UnloadShader(vrConfig.distortionShader); // Unload distortion shader
#endif
// Update distortion shader with lens and distortion-scale parameters
SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "leftLensCenter"), leftLensCenter, UNIFORM_VEC2);
SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "rightLensCenter"), rightLensCenter, UNIFORM_VEC2);
SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "leftScreenCenter"), leftScreenCenter, UNIFORM_VEC2);
SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "rightScreenCenter"), rightScreenCenter, UNIFORM_VEC2);
SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "scale"), scale, UNIFORM_VEC2);
SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "scaleIn"), scaleIn, UNIFORM_VEC2);
SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "hmdWarpParam"), hmd.lensDistortionValues, UNIFORM_VEC4);
SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "chromaAbParam"), hmd.chromaAbCorrection, UNIFORM_VEC4);
}
#endif
}
// Detect if VR simulator is running
@ -3733,7 +3640,7 @@ void BeginVrDrawing(void)
if (vrSimulatorReady)
{
// Setup framebuffer for stereo rendering
rlEnableRenderTexture(vrConfig.stereoFbo.id);
rlEnableRenderTexture(stereoFbo.id);
// 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:
@ -3771,13 +3678,11 @@ void EndVrDrawing(void)
rlMatrixMode(RL_MODELVIEW); // Enable internal modelview matrix
rlLoadIdentity(); // Reset internal modelview matrix
#if defined(SUPPORT_DISTORTION_SHADER)
// Draw RenderTexture (stereoFbo) using distortion shader
currentShader = vrConfig.distortionShader;
#else
currentShader = GetShaderDefault();
#endif
rlEnableTexture(vrConfig.stereoFbo.texture.id);
// Draw RenderTexture (stereoFbo) using distortion shader if available
if (vrConfig.distortionShader.id > 0) currentShader = vrConfig.distortionShader;
else currentShader = GetShaderDefault();
rlEnableTexture(stereoFbo.texture.id);
rlPushMatrix();
rlBegin(RL_QUADS);
@ -3790,15 +3695,15 @@ void EndVrDrawing(void)
// Bottom-right corner for texture and quad
rlTexCoord2f(0.0f, 0.0f);
rlVertex2f(0.0f, (float)vrConfig.stereoFbo.texture.height);
rlVertex2f(0.0f, (float)stereoFbo.texture.height);
// Top-right corner for texture and quad
rlTexCoord2f(1.0f, 0.0f);
rlVertex2f( (float)vrConfig.stereoFbo.texture.width, (float)vrConfig.stereoFbo.texture.height);
rlVertex2f( (float)stereoFbo.texture.width, (float)stereoFbo.texture.height);
// Top-left corner for texture and quad
rlTexCoord2f(1.0f, 1.0f);
rlVertex2f( (float)vrConfig.stereoFbo.texture.width, 0.0f);
rlVertex2f( (float)stereoFbo.texture.width, 0.0f);
rlEnd();
rlPopMatrix();
@ -4472,87 +4377,6 @@ static void GenDrawCube(void)
}
#if defined(SUPPORT_VR_SIMULATOR)
// Configure stereo rendering (including distortion shader) with HMD device parameters
static VrStereoConfig SetStereoConfig(VrDeviceInfo hmd, Shader distortion)
{
VrStereoConfig config = { 0 };
// Initialize framebuffer and textures for stereo rendering
// NOTE: Screen size should match HMD aspect ratio
config.stereoFbo = rlLoadRenderTexture(screenWidth, screenHeight, UNCOMPRESSED_R8G8B8A8, 24, false);
// Assign distortion shader
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 = (float)fabs(-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;
TraceLog(LOG_DEBUG, "VR: 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 };
TraceLog(LOG_DEBUG, "VR: Distortion Shader: LeftLensCenter = { %f, %f }", leftLensCenter[0], leftLensCenter[1]);
TraceLog(LOG_DEBUG, "VR: Distortion Shader: RightLensCenter = { %f, %f }", rightLensCenter[0], rightLensCenter[1]);
TraceLog(LOG_DEBUG, "VR: Distortion Shader: Scale = { %f, %f }", scale[0], scale[1]);
TraceLog(LOG_DEBUG, "VR: Distortion Shader: ScaleIn = { %f, %f }", scaleIn[0], scaleIn[1]);
// Fovy is normally computed with: 2*atan2(hmd.vScreenSize, 2*hmd.eyeToScreenDistance)
// ...but with lens distortion it is increased (see Oculus SDK Documentation)
//float fovy = 2.0f*atan2(hmd.vScreenSize*0.5f*distortionScale, hmd.eyeToScreenDistance); // Really need distortionScale?
float fovy = 2.0f*(float)atan2(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, 0.01, 1000.0);
config.eyesProjection[0] = MatrixMultiply(proj, MatrixTranslate(projOffset, 0.0f, 0.0f));
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.
config.eyesViewOffset[0] = MatrixTranslate(-hmd.interpupillaryDistance*0.5f, 0.075f, 0.045f);
config.eyesViewOffset[1] = MatrixTranslate(hmd.interpupillaryDistance*0.5f, 0.075f, 0.045f);
// Compute eyes Viewports
//config.eyeViewportRight[0] = (int[4]){ 0, 0, hmd.hResolution/2, hmd.vResolution };
//config.eyeViewportLeft[0] = (int[4]){ hmd.hResolution/2, 0, hmd.hResolution/2, hmd.vResolution };
#if defined(SUPPORT_DISTORTION_SHADER)
// Update distortion shader with lens and distortion-scale parameters
SetShaderValue(config.distortionShader, GetShaderLocation(config.distortionShader, "leftLensCenter"), leftLensCenter, UNIFORM_VEC2);
SetShaderValue(config.distortionShader, GetShaderLocation(config.distortionShader, "rightLensCenter"), rightLensCenter, UNIFORM_VEC2);
SetShaderValue(config.distortionShader, GetShaderLocation(config.distortionShader, "leftScreenCenter"), leftScreenCenter, UNIFORM_VEC2);
SetShaderValue(config.distortionShader, GetShaderLocation(config.distortionShader, "rightScreenCenter"), rightScreenCenter, UNIFORM_VEC2);
SetShaderValue(config.distortionShader, GetShaderLocation(config.distortionShader, "scale"), scale, UNIFORM_VEC2);
SetShaderValue(config.distortionShader, GetShaderLocation(config.distortionShader, "scaleIn"), scaleIn, UNIFORM_VEC2);
SetShaderValue(config.distortionShader, GetShaderLocation(config.distortionShader, "hmdWarpParam"), hmd.lensDistortionValues, UNIFORM_VEC4);
SetShaderValue(config.distortionShader, GetShaderLocation(config.distortionShader, "chromaAbParam"), hmd.chromaAbCorrection, UNIFORM_VEC4);
#endif
return config;
}
// Set internal projection and modelview matrix depending on eyes tracking data
static void SetStereoView(int eye, Matrix matProjection, Matrix matModelView)
{

Carregando…
Cancelar
Salvar