|
|
@ -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) |
|
|
|
{ |
|
|
|