From 8fd450784799d553a649a69df92497d32415140b Mon Sep 17 00:00:00 2001 From: raysan5 Date: Wed, 6 Jul 2016 20:02:15 +0200 Subject: Corrected bug on Raspberry Pi with strcat() --- src/text.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/text.c b/src/text.c index b5f7ad0c..ec2480e3 100644 --- a/src/text.c +++ b/src/text.c @@ -782,12 +782,15 @@ static SpriteFont LoadBMFont(const char *fileName) char *texPath = NULL; char *lastSlash = NULL; - lastSlash = strrchr(fileName, '/'); // you need escape character - texPath = malloc(strlen(fileName) - strlen(lastSlash) + 1 + strlen(texFileName) + 1); - memcpy(texPath, fileName, strlen(fileName) - strlen(lastSlash)); - strcat(texPath, "/"); - strcat(texPath, texFileName); - strcat(texPath, "\0"); + lastSlash = strrchr(fileName, '/'); + + // NOTE: We need some extra space to avoid memory corruption on next allocations! + texPath = malloc(strlen(fileName) - strlen(lastSlash) + strlen(texFileName) + 4); + + // NOTE: strcat() and strncat() required a '\0' terminated string to work! + *texPath = '\0'; + strncat(texPath, fileName, strlen(fileName) - strlen(lastSlash) + 1); + strncat(texPath, texFileName, strlen(texFileName)); TraceLog(DEBUG, "[%s] Font texture loading path: %s", fileName, texPath); @@ -828,7 +831,7 @@ static SpriteFont LoadBMFont(const char *fileName) else if (unorderedChars) TraceLog(WARNING, "BMFont not supported: unordered chars data, falling back to default font"); // NOTE: Font data could be not ordered by charId: 32,33,34,35... raylib does not support unordered BMFonts - if ((firstChar != FONT_FIRST_CHAR) || (unorderedChars)) + if ((firstChar != FONT_FIRST_CHAR) || (unorderedChars) || (font.texture.id == 0)) { UnloadSpriteFont(font); font = GetDefaultFont(); -- cgit v1.2.3 From e2a3a52ad6acaacf8c839fcefd405ff3258dcad9 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Wed, 6 Jul 2016 20:02:33 +0200 Subject: Edited comment --- src/rlgl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/rlgl.c b/src/rlgl.c index a71142b0..089e2809 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -260,7 +260,7 @@ static bool texCompASTCSupported = false; // ASTC texture compression support // Lighting data static Light lights[MAX_LIGHTS]; // Lights pool -static int lightsCount; // Counts current enabled physic objects +static int lightsCount; // Enabled lights counter #endif #if defined(RLGL_OCULUS_SUPPORT) -- cgit v1.2.3 From 7cefbd8a947551f6c63dba88117099d6c0f4998b Mon Sep 17 00:00:00 2001 From: raysan5 Date: Wed, 6 Jul 2016 20:33:46 +0200 Subject: Updated lighting system... ...to avoid dynamic conditions on for loop (lightsCount) on standard shader, it seems GLSL 100 doesn't support that feature... on some GPUs like RaspberryPi... --- src/raylib.h | 2 +- src/rlgl.c | 196 +++++++++++++++++++++++++++----------------------- src/rlgl.h | 4 +- src/standard_shader.h | 3 +- 4 files changed, 109 insertions(+), 96 deletions(-) (limited to 'src') diff --git a/src/raylib.h b/src/raylib.h index 227f83f2..1d160492 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -431,8 +431,8 @@ typedef struct Model { // Light type typedef struct LightData { unsigned int id; // Light unique id - int type; // Light type: LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT bool enabled; // Light enabled + int type; // Light type: LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT Vector3 position; // Light position Vector3 target; // Light target: LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction target) diff --git a/src/rlgl.c b/src/rlgl.c index 089e2809..aa729824 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -260,7 +260,7 @@ static bool texCompASTCSupported = false; // ASTC texture compression support // Lighting data static Light lights[MAX_LIGHTS]; // Lights pool -static int lightsCount; // Enabled lights counter +static int lightsCount = 0; // Enabled lights counter #endif #if defined(RLGL_OCULUS_SUPPORT) @@ -2454,24 +2454,28 @@ Light CreateLight(int type, Vector3 position, Color diffuse) Light light = NULL; #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - // Allocate dynamic memory - light = (Light)malloc(sizeof(LightData)); - - // Initialize light values with generic values - light->id = lightsCount; - light->type = type; - light->enabled = true; - - light->position = position; - light->target = (Vector3){ 0.0f, 0.0f, 0.0f }; - light->intensity = 1.0f; - light->diffuse = diffuse; - - // Add new light to the array - lights[lightsCount] = light; - - // Increase enabled lights count - lightsCount++; + if (lightsCount < MAX_LIGHTS) + { + // Allocate dynamic memory + light = (Light)malloc(sizeof(LightData)); + + // Initialize light values with generic values + light->id = lightsCount; + light->type = type; + light->enabled = true; + + light->position = position; + light->target = (Vector3){ 0.0f, 0.0f, 0.0f }; + light->intensity = 1.0f; + light->diffuse = diffuse; + + // Add new light to the array + lights[lightsCount] = light; + + // Increase enabled lights count + lightsCount++; + } + else TraceLog(WARNING, "Too many lights, only supported up to %i lights", MAX_LIGHTS); #else // TODO: Support OpenGL 1.1 lighting system TraceLog(WARNING, "Lighting currently not supported on OpenGL 1.1"); @@ -2484,23 +2488,26 @@ Light CreateLight(int type, Vector3 position, Color diffuse) void DestroyLight(Light light) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - // Free dynamic memory allocation - free(lights[light->id]); - - // Remove *obj from the pointers array - for (int i = light->id; i < lightsCount; i++) + if (light != NULL) { - // Resort all the following pointers of the array - if ((i + 1) < lightsCount) + // Free dynamic memory allocation + free(lights[light->id]); + + // Remove *obj from the pointers array + for (int i = light->id; i < lightsCount; i++) { - lights[i] = lights[i + 1]; - lights[i]->id = lights[i + 1]->id; + // Resort all the following pointers of the array + if ((i + 1) < lightsCount) + { + lights[i] = lights[i + 1]; + lights[i]->id = lights[i + 1]->id; + } + else free(lights[i]); } - else free(lights[i]); + + // Decrease enabled physic objects count + lightsCount--; } - - // Decrease enabled physic objects count - lightsCount--; #endif } @@ -3625,72 +3632,79 @@ static void UnloadDefaultBuffers(void) // NOTE: It would be far easier with shader UBOs but are not supported on OpenGL ES 2.0f static void SetShaderLights(Shader shader) { - int locPoint = glGetUniformLocation(shader.id, "lightsCount"); - glUniform1i(locPoint, lightsCount); - + int locPoint = -1; char locName[32] = "lights[x].position\0"; - for (int i = 0; i < lightsCount; i++) + for (int i = 0; i < MAX_LIGHTS; i++) { locName[7] = '0' + i; - - memcpy(&locName[10], "enabled\0", strlen("enabled\0") + 1); - locPoint = GetShaderLocation(shader, locName); - glUniform1i(locPoint, lights[i]->enabled); - - memcpy(&locName[10], "type\0", strlen("type\0") + 1); - locPoint = GetShaderLocation(shader, locName); - glUniform1i(locPoint, lights[i]->type); - - memcpy(&locName[10], "diffuse\0", strlen("diffuse\0") + 2); - locPoint = glGetUniformLocation(shader.id, locName); - glUniform4f(locPoint, (float)lights[i]->diffuse.r/255, (float)lights[i]->diffuse.g/255, (float)lights[i]->diffuse.b/255, (float)lights[i]->diffuse.a/255); - - memcpy(&locName[10], "intensity\0", strlen("intensity\0")); - locPoint = glGetUniformLocation(shader.id, locName); - glUniform1f(locPoint, lights[i]->intensity); - - switch (lights[i]->type) + + if (lights[i] != NULL) // Only upload registered lights data { - case LIGHT_POINT: - { - memcpy(&locName[10], "position\0", strlen("position\0") + 1); - locPoint = GetShaderLocation(shader, locName); - glUniform3f(locPoint, lights[i]->position.x, lights[i]->position.y, lights[i]->position.z); - - memcpy(&locName[10], "radius\0", strlen("radius\0") + 2); - locPoint = GetShaderLocation(shader, locName); - glUniform1f(locPoint, lights[i]->radius); - } break; - case LIGHT_DIRECTIONAL: - { - memcpy(&locName[10], "direction\0", strlen("direction\0") + 2); - locPoint = GetShaderLocation(shader, locName); - Vector3 direction = { lights[i]->target.x - lights[i]->position.x, lights[i]->target.y - lights[i]->position.y, lights[i]->target.z - lights[i]->position.z }; - VectorNormalize(&direction); - glUniform3f(locPoint, direction.x, direction.y, direction.z); - } break; - case LIGHT_SPOT: + memcpy(&locName[10], "enabled\0", strlen("enabled\0") + 1); + locPoint = GetShaderLocation(shader, locName); + glUniform1i(locPoint, lights[i]->enabled); + + memcpy(&locName[10], "type\0", strlen("type\0") + 1); + locPoint = GetShaderLocation(shader, locName); + glUniform1i(locPoint, lights[i]->type); + + memcpy(&locName[10], "diffuse\0", strlen("diffuse\0") + 2); + locPoint = glGetUniformLocation(shader.id, locName); + glUniform4f(locPoint, (float)lights[i]->diffuse.r/255, (float)lights[i]->diffuse.g/255, (float)lights[i]->diffuse.b/255, (float)lights[i]->diffuse.a/255); + + memcpy(&locName[10], "intensity\0", strlen("intensity\0")); + locPoint = glGetUniformLocation(shader.id, locName); + glUniform1f(locPoint, lights[i]->intensity); + + switch (lights[i]->type) { - memcpy(&locName[10], "position\0", strlen("position\0") + 1); - locPoint = GetShaderLocation(shader, locName); - glUniform3f(locPoint, lights[i]->position.x, lights[i]->position.y, lights[i]->position.z); - - memcpy(&locName[10], "direction\0", strlen("direction\0") + 2); - locPoint = GetShaderLocation(shader, locName); - - Vector3 direction = { lights[i]->target.x - lights[i]->position.x, lights[i]->target.y - lights[i]->position.y, lights[i]->target.z - lights[i]->position.z }; - VectorNormalize(&direction); - glUniform3f(locPoint, direction.x, direction.y, direction.z); - - memcpy(&locName[10], "coneAngle\0", strlen("coneAngle\0")); - locPoint = GetShaderLocation(shader, locName); - glUniform1f(locPoint, lights[i]->coneAngle); - } break; - default: break; + case LIGHT_POINT: + { + memcpy(&locName[10], "position\0", strlen("position\0") + 1); + locPoint = GetShaderLocation(shader, locName); + glUniform3f(locPoint, lights[i]->position.x, lights[i]->position.y, lights[i]->position.z); + + memcpy(&locName[10], "radius\0", strlen("radius\0") + 2); + locPoint = GetShaderLocation(shader, locName); + glUniform1f(locPoint, lights[i]->radius); + } break; + case LIGHT_DIRECTIONAL: + { + memcpy(&locName[10], "direction\0", strlen("direction\0") + 2); + locPoint = GetShaderLocation(shader, locName); + Vector3 direction = { lights[i]->target.x - lights[i]->position.x, lights[i]->target.y - lights[i]->position.y, lights[i]->target.z - lights[i]->position.z }; + VectorNormalize(&direction); + glUniform3f(locPoint, direction.x, direction.y, direction.z); + } break; + case LIGHT_SPOT: + { + memcpy(&locName[10], "position\0", strlen("position\0") + 1); + locPoint = GetShaderLocation(shader, locName); + glUniform3f(locPoint, lights[i]->position.x, lights[i]->position.y, lights[i]->position.z); + + memcpy(&locName[10], "direction\0", strlen("direction\0") + 2); + locPoint = GetShaderLocation(shader, locName); + + Vector3 direction = { lights[i]->target.x - lights[i]->position.x, lights[i]->target.y - lights[i]->position.y, lights[i]->target.z - lights[i]->position.z }; + VectorNormalize(&direction); + glUniform3f(locPoint, direction.x, direction.y, direction.z); + + memcpy(&locName[10], "coneAngle\0", strlen("coneAngle\0")); + locPoint = GetShaderLocation(shader, locName); + glUniform1f(locPoint, lights[i]->coneAngle); + } break; + default: break; + } + + // TODO: Pass to the shader any other required data from LightData struct + } + else // Not enabled lights + { + memcpy(&locName[10], "enabled\0", strlen("enabled\0") + 1); + locPoint = GetShaderLocation(shader, locName); + glUniform1i(locPoint, 0); } - - // TODO: Pass to the shader any other required data from LightData struct } } diff --git a/src/rlgl.h b/src/rlgl.h index f984c0c6..9afafc52 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -218,9 +218,9 @@ typedef enum { OPENGL_11 = 1, OPENGL_21, OPENGL_33, OPENGL_ES_20 } GlVersion; // Light type typedef struct LightData { unsigned int id; // Light unique id - int type; // Light type: LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT bool enabled; // Light enabled - + int type; // Light type: LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT + Vector3 position; // Light position Vector3 target; // Light target: LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction target) float radius; // Light attenuation radius light intensity reduced with distance (world distance) diff --git a/src/standard_shader.h b/src/standard_shader.h index e1668ae7..deae7fe1 100644 --- a/src/standard_shader.h +++ b/src/standard_shader.h @@ -78,7 +78,6 @@ static const char fStandardShaderStr[] = " float radius; \n" " float coneAngle; }; \n" "const int maxLights = 8; \n" -"uniform int lightsCount; \n" "uniform Light lights[maxLights]; \n" "\n" "vec3 CalcPointLight(Light l, vec3 n, vec3 v, float s) \n" @@ -157,7 +156,7 @@ static const char fStandardShaderStr[] = #elif defined(GRAPHICS_API_OPENGL_33) " if (useSpecular == 1) spec *= normalize(texture(texture2, fragTexCoord).r);\n" #endif -" for (int i = 0; i < lightsCount; i++)\n" +" for (int i = 0; i < maxLights; i++)\n" " {\n" " if (lights[i].enabled == 1)\n" " {\n" -- cgit v1.2.3 From 3922bc27cda94e4d174f079ea04f0eeca8b364ab Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 8 Jul 2016 00:57:27 +0200 Subject: Supporting multiple HMD configurations -IN PROGRESS- --- src/rlgl.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 94 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/rlgl.c b/src/rlgl.c index aa729824..25a6745c 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -188,6 +188,20 @@ typedef struct { //Guint fboId; } DrawCall; +// Head-Mounted-Display device parameters +typedef struct { + int hResolution; // HMD horizontal resolution in pixels + int vResolution; // HMD vertical resolution in pixels + float hScreenSize; // HMD horizontal size in meters + float vScreenSize; // HMD vertical size in meters + float vScreenCenter; // HMD screen center in meters + float eyeToScreenDistance; // HMD distance between eye and display in meters + float lensSeparationDistance; // HMD lens separation distance in meters + float interpupillaryDistance; // HMD IPD (distance between pupils) in meters + float distortionK[4]; // HMD lens distortion constant parameters + float chromaAbCorrection[4]; // HMD chromatic aberration correction parameters +} VrDeviceInfo; + #if defined(RLGL_OCULUS_SUPPORT) typedef struct OculusBuffer { ovrTextureSwapChain textureChain; @@ -324,6 +338,9 @@ static void UnloadDefaultBuffers(void); // Unload default internal buffers v // Set internal projection and modelview matrix depending on eyes tracking data static void SetStereoView(int eye, Matrix matProjection, Matrix matModelView); +// Configure stereo rendering (including distortion shader) with HMD device parameters +static void SetupVrDevice(VrDeviceInfo hmd); + static void SetShaderLights(Shader shader); // Sets shader uniform values for lights array static char *ReadTextFile(const char *fileName); @@ -2535,7 +2552,7 @@ void InitVrDevice(int hmdDevice) 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); @@ -2685,10 +2702,10 @@ static void SetStereoView(int eye, Matrix matProjection, Matrix matModelView) static float IPD = 0.064f; // InterpupillaryDistance float HScreenSize = 0.14976f; - float VScreenSize = 0.0936f; // HScreenSize/(1280.0f/800.0f) (DK2) + float VScreenSize = 0.09356f; // HScreenSize/(1280.0f/800.0f) (DK2) float VScreenCenter = 0.04675f; // VScreenSize/2 float EyeToScreenDistance = 0.041f; - float LensSeparationDistance = 0.064f; //0.0635f (DK1) + float LensSeparationDistance = 0.0635f; //0.0635f (DK2) // NOTE: fovy value obtained from device parameters (Oculus Rift CV1) float halfScreenDistance = VScreenSize/2.0f; @@ -3870,7 +3887,81 @@ static Color *GenNextMipmap(Color *srcData, int srcWidth, int srcHeight) } #endif +// Configure stereo rendering (including distortion shader) with HMD device parameters +static void SetupVrDevice(VrDeviceInfo hmd) +{ + // Compute aspect ratio and FOV + float aspect = ((float)hmd.hResolution/2.0f)/(float)hmd.vResolution; + + // Fov-y is normally computed with: 2*atan2(hmd.vScreenSize, 2*hmd.eyeToScreenDistance)*RAD2DEG + // ...but with lens distortion it is increased (see Oculus SDK Documentation) + float radius = -1.0 - (4*(hmd.hScreenSize/4 - hmd.lensSeparationDistance/2)/hmd.hScreenSize); + float distScale = (hmd.distortionK[0] + hmd.distortionK[1]*pow(radius, 2) + hmd.distortionK[2]*pow(radius, 4) + hmd.distortionK[3]*pow(radius, 6)); + float fovy = 2*atan2(hmd.vScreenSize*distScale, 2*hmd.eyeToScreenDistance)*RAD2DEG; + + // Compute camera projection matrices + Matrix proj = MatrixPerspective(fovy, aspect, 0.1, 10000); + float projOffset = 4*(hmd.hScreenSize/4 - hmd.interpupillaryDistance/2)/hmd.hScreenSize; + + //Matrix projLeft = MatrixMultiply(MatrixTranslation(projOffset, 0.0, 0.0), proj); + //matrix projRight = MatrixMultiply(MatrixTranslation(-projOffset, 0.0, 0.0)), proj); + + // Compute camera transformation matrices + //Matrix viewTransformLeft = MatrixTranslation(-hmd.interpupillaryDistance/2, 0.0, 0.0 ); + //Matrix viewTransformRight = MatrixTranslation(hmd.interpupillaryDistance/2, 0.0, 0.0 ); + + // Compute eyes Viewports + // Rectangle viewportLeft = { 0, 0, hmd.hResolution/2, hmd.vResolution }; + // Rectangle viewportRight = { hmd.hResolution/2, 0, hmd.hResolution/2, hmd.vResolution }; + + // Distortion shader parameters + float lensShift = 4*(hmd.hScreenSize/4 - hmd.lensSeparationDistance/2)/hmd.hScreenSize; + float leftLensCenter[2] = { lensShift, 0.0f }; + float rightLensCenter[2] = { -lensShift, 0.0f }; + float leftScreenCenter[2] = { 0.25f, 0.5f }; + float rightScreenCenter[2] = { 0.75f, 0.5f }; + + float scaleIn[2] = { 1.0f, 1.0f/aspect }; + float scale[2] = { 1.0f/distScale, 1.0f*aspect/distScale }; + + // Distortion shader parameters update + SetShaderValue(distortionShader, GetShaderLocation(distortionShader, "leftLensCenter"), leftLensCenter, 2); + SetShaderValue(distortionShader, GetShaderLocation(distortionShader, "rightLensCenter"), rightLensCenter, 2); + SetShaderValue(distortionShader, GetShaderLocation(distortionShader, "leftScreenCenter"), leftScreenCenter, 2); + SetShaderValue(distortionShader, GetShaderLocation(distortionShader, "rightScreenCenter"), rightScreenCenter, 2); + + SetShaderValue(distortionShader, GetShaderLocation(distortionShader, "scale"), scale, 2); + SetShaderValue(distortionShader, GetShaderLocation(distortionShader, "scaleIn"), scaleIn, 2); + SetShaderValue(distortionShader, GetShaderLocation(distortionShader, "hmdWarpParam"), hmd.distortionK, 4); + SetShaderValue(distortionShader, GetShaderLocation(distortionShader, "chromaAbParam"), hmd.chromaAbCorrection, 4); +} + #if defined(RLGL_OCULUS_SUPPORT) +static void InitOculusDevice(void) +{ + +} + +static void CloseOculusDevice(void) +{ + +} + +static void UpdateOculusTracking(void) +{ + +} + +static void BeginOculusDrawing(void) +{ + +} + +static void EndOculusDrawing(void) +{ + +} + // Load Oculus required buffers: texture-swap-chain, fbo, texture-depth static OculusBuffer LoadOculusBuffer(ovrSession session, int width, int height) { -- cgit v1.2.3 From bcc2b17701f70015498ee2e51d7b35ffdd22f8d5 Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 8 Jul 2016 17:22:37 +0200 Subject: Rename standard_shader.h to shader_standard.h --- src/shader_standard.h | 173 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/standard_shader.h | 173 -------------------------------------------------- 2 files changed, 173 insertions(+), 173 deletions(-) create mode 100644 src/shader_standard.h delete mode 100644 src/standard_shader.h (limited to 'src') diff --git a/src/shader_standard.h b/src/shader_standard.h new file mode 100644 index 00000000..deae7fe1 --- /dev/null +++ b/src/shader_standard.h @@ -0,0 +1,173 @@ + +// Vertex shader definition to embed, no external file required +static const char vStandardShaderStr[] = +#if defined(GRAPHICS_API_OPENGL_21) +"#version 120 \n" +#elif defined(GRAPHICS_API_OPENGL_ES2) +"#version 100 \n" +#endif +#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21) +"attribute vec3 vertexPosition; \n" +"attribute vec3 vertexNormal; \n" +"attribute vec2 vertexTexCoord; \n" +"attribute vec4 vertexColor; \n" +"varying vec3 fragPosition; \n" +"varying vec3 fragNormal; \n" +"varying vec2 fragTexCoord; \n" +"varying vec4 fragColor; \n" +#elif defined(GRAPHICS_API_OPENGL_33) +"#version 330 \n" +"in vec3 vertexPosition; \n" +"in vec3 vertexNormal; \n" +"in vec2 vertexTexCoord; \n" +"in vec4 vertexColor; \n" +"out vec3 fragPosition; \n" +"out vec3 fragNormal; \n" +"out vec2 fragTexCoord; \n" +"out vec4 fragColor; \n" +#endif +"uniform mat4 mvpMatrix; \n" +"void main() \n" +"{ \n" +" fragPosition = vertexPosition; \n" +" fragNormal = vertexNormal; \n" +" fragTexCoord = vertexTexCoord; \n" +" fragColor = vertexColor; \n" +" gl_Position = mvpMatrix*vec4(vertexPosition, 1.0); \n" +"} \n"; + +// Fragment shader definition to embed, no external file required +static const char fStandardShaderStr[] = +#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 vec3 fragPosition; \n" +"varying vec3 fragNormal; \n" +"varying vec2 fragTexCoord; \n" +"varying vec4 fragColor; \n" +#elif defined(GRAPHICS_API_OPENGL_33) +"#version 330 \n" +"in vec3 fragPosition; \n" +"in vec3 fragNormal; \n" +"in vec2 fragTexCoord; \n" +"in vec4 fragColor; \n" +"out vec4 finalColor; \n" +#endif +"uniform sampler2D texture0; \n" +"uniform sampler2D texture1; \n" +"uniform sampler2D texture2; \n" +"uniform vec4 colAmbient; \n" +"uniform vec4 colDiffuse; \n" +"uniform vec4 colSpecular; \n" +"uniform float glossiness; \n" +"uniform int useNormal; \n" +"uniform int useSpecular; \n" +"uniform mat4 modelMatrix; \n" +"uniform vec3 viewDir; \n" +"struct Light { \n" +" int enabled; \n" +" int type; \n" +" vec3 position; \n" +" vec3 direction; \n" +" vec4 diffuse; \n" +" float intensity; \n" +" float radius; \n" +" float coneAngle; }; \n" +"const int maxLights = 8; \n" +"uniform Light lights[maxLights]; \n" +"\n" +"vec3 CalcPointLight(Light l, vec3 n, vec3 v, float s) \n" +"{\n" +" vec3 surfacePos = vec3(modelMatrix*vec4(fragPosition, 1));\n" +" vec3 surfaceToLight = l.position - surfacePos;\n" +" float brightness = clamp(float(dot(n, surfaceToLight)/(length(surfaceToLight)*length(n))), 0.0, 1.0);\n" +" float diff = 1.0/dot(surfaceToLight/l.radius, surfaceToLight/l.radius)*brightness*l.intensity;\n" +" float spec = 0.0;\n" +" if (diff > 0.0)\n" +" {\n" +" vec3 h = normalize(-l.direction + v);\n" +" spec = pow(dot(n, h), 3.0 + glossiness)*s;\n" +" }\n" +" return (diff*l.diffuse.rgb + spec*colSpecular.rgb);\n" +"}\n" +"\n" +"vec3 CalcDirectionalLight(Light l, vec3 n, vec3 v, float s)\n" +"{\n" +" vec3 lightDir = normalize(-l.direction);\n" +" float diff = clamp(float(dot(n, lightDir)), 0.0, 1.0)*l.intensity;\n" +" float spec = 0.0;\n" +" if (diff > 0.0)\n" +" {\n" +" vec3 h = normalize(lightDir + v);\n" +" spec = pow(dot(n, h), 3.0 + glossiness)*s;\n" +" }\n" +" return (diff*l.intensity*l.diffuse.rgb + spec*colSpecular.rgb);\n" +"}\n" +"\n" +"vec3 CalcSpotLight(Light l, vec3 n, vec3 v, float s)\n" +"{\n" +" vec3 surfacePos = vec3(modelMatrix*vec4(fragPosition, 1.0));\n" +" vec3 lightToSurface = normalize(surfacePos - l.position);\n" +" vec3 lightDir = normalize(-l.direction);\n" +" float diff = clamp(float(dot(n, lightDir)), 0.0, 1.0)*l.intensity;\n" +" float attenuation = clamp(float(dot(n, lightToSurface)), 0.0, 1.0);\n" +" attenuation = dot(lightToSurface, -lightDir);\n" +" float lightToSurfaceAngle = degrees(acos(attenuation));\n" +" if (lightToSurfaceAngle > l.coneAngle) attenuation = 0.0;\n" +" float falloff = (l.coneAngle - lightToSurfaceAngle)/l.coneAngle;\n" +" float diffAttenuation = diff*attenuation;\n" +" float spec = 0.0;\n" +" if (diffAttenuation > 0.0)\n" +" {\n" +" vec3 h = normalize(lightDir + v);\n" +" spec = pow(dot(n, h), 3.0 + glossiness)*s;\n" +" }\n" +" return (falloff*(diffAttenuation*l.diffuse.rgb + spec*colSpecular.rgb));\n" +"}\n" +"\n" +"void main()\n" +"{\n" +" mat3 normalMatrix = mat3(modelMatrix);\n" +" vec3 normal = normalize(normalMatrix*fragNormal);\n" +" vec3 n = normalize(normal);\n" +" vec3 v = normalize(viewDir);\n" +#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21) +" vec4 texelColor = texture2D(texture0, fragTexCoord);\n" +#elif defined(GRAPHICS_API_OPENGL_33) +" vec4 texelColor = texture(texture0, fragTexCoord);\n" +#endif +" vec3 lighting = colAmbient.rgb;\n" +" if (useNormal == 1)\n" +" {\n" +#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21) +" n *= texture2D(texture1, fragTexCoord).rgb;\n" +#elif defined(GRAPHICS_API_OPENGL_33) +" n *= texture(texture1, fragTexCoord).rgb;\n" +#endif +" n = normalize(n);\n" +" }\n" +" float spec = 1.0;\n" +#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21) +" if (useSpecular == 1) spec *= normalize(texture2D(texture2, fragTexCoord).r);\n" +#elif defined(GRAPHICS_API_OPENGL_33) +" if (useSpecular == 1) spec *= normalize(texture(texture2, fragTexCoord).r);\n" +#endif +" for (int i = 0; i < maxLights; i++)\n" +" {\n" +" if (lights[i].enabled == 1)\n" +" {\n" +" if(lights[i].type == 0) lighting += CalcPointLight(lights[i], n, v, spec);\n" +" else if(lights[i].type == 1) lighting += CalcDirectionalLight(lights[i], n, v, spec);\n" +" else if(lights[i].type == 2) lighting += CalcSpotLight(lights[i], n, v, spec);\n" +" }\n" +" }\n" +#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21) +" gl_FragColor = vec4(texelColor.rgb*lighting*colDiffuse.rgb, texelColor.a*colDiffuse.a); \n" +#elif defined(GRAPHICS_API_OPENGL_33) +" finalColor = vec4(texelColor.rgb*lighting*colDiffuse.rgb, texelColor.a*colDiffuse.a); \n" +#endif +"}\n"; diff --git a/src/standard_shader.h b/src/standard_shader.h deleted file mode 100644 index deae7fe1..00000000 --- a/src/standard_shader.h +++ /dev/null @@ -1,173 +0,0 @@ - -// Vertex shader definition to embed, no external file required -static const char vStandardShaderStr[] = -#if defined(GRAPHICS_API_OPENGL_21) -"#version 120 \n" -#elif defined(GRAPHICS_API_OPENGL_ES2) -"#version 100 \n" -#endif -#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21) -"attribute vec3 vertexPosition; \n" -"attribute vec3 vertexNormal; \n" -"attribute vec2 vertexTexCoord; \n" -"attribute vec4 vertexColor; \n" -"varying vec3 fragPosition; \n" -"varying vec3 fragNormal; \n" -"varying vec2 fragTexCoord; \n" -"varying vec4 fragColor; \n" -#elif defined(GRAPHICS_API_OPENGL_33) -"#version 330 \n" -"in vec3 vertexPosition; \n" -"in vec3 vertexNormal; \n" -"in vec2 vertexTexCoord; \n" -"in vec4 vertexColor; \n" -"out vec3 fragPosition; \n" -"out vec3 fragNormal; \n" -"out vec2 fragTexCoord; \n" -"out vec4 fragColor; \n" -#endif -"uniform mat4 mvpMatrix; \n" -"void main() \n" -"{ \n" -" fragPosition = vertexPosition; \n" -" fragNormal = vertexNormal; \n" -" fragTexCoord = vertexTexCoord; \n" -" fragColor = vertexColor; \n" -" gl_Position = mvpMatrix*vec4(vertexPosition, 1.0); \n" -"} \n"; - -// Fragment shader definition to embed, no external file required -static const char fStandardShaderStr[] = -#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 vec3 fragPosition; \n" -"varying vec3 fragNormal; \n" -"varying vec2 fragTexCoord; \n" -"varying vec4 fragColor; \n" -#elif defined(GRAPHICS_API_OPENGL_33) -"#version 330 \n" -"in vec3 fragPosition; \n" -"in vec3 fragNormal; \n" -"in vec2 fragTexCoord; \n" -"in vec4 fragColor; \n" -"out vec4 finalColor; \n" -#endif -"uniform sampler2D texture0; \n" -"uniform sampler2D texture1; \n" -"uniform sampler2D texture2; \n" -"uniform vec4 colAmbient; \n" -"uniform vec4 colDiffuse; \n" -"uniform vec4 colSpecular; \n" -"uniform float glossiness; \n" -"uniform int useNormal; \n" -"uniform int useSpecular; \n" -"uniform mat4 modelMatrix; \n" -"uniform vec3 viewDir; \n" -"struct Light { \n" -" int enabled; \n" -" int type; \n" -" vec3 position; \n" -" vec3 direction; \n" -" vec4 diffuse; \n" -" float intensity; \n" -" float radius; \n" -" float coneAngle; }; \n" -"const int maxLights = 8; \n" -"uniform Light lights[maxLights]; \n" -"\n" -"vec3 CalcPointLight(Light l, vec3 n, vec3 v, float s) \n" -"{\n" -" vec3 surfacePos = vec3(modelMatrix*vec4(fragPosition, 1));\n" -" vec3 surfaceToLight = l.position - surfacePos;\n" -" float brightness = clamp(float(dot(n, surfaceToLight)/(length(surfaceToLight)*length(n))), 0.0, 1.0);\n" -" float diff = 1.0/dot(surfaceToLight/l.radius, surfaceToLight/l.radius)*brightness*l.intensity;\n" -" float spec = 0.0;\n" -" if (diff > 0.0)\n" -" {\n" -" vec3 h = normalize(-l.direction + v);\n" -" spec = pow(dot(n, h), 3.0 + glossiness)*s;\n" -" }\n" -" return (diff*l.diffuse.rgb + spec*colSpecular.rgb);\n" -"}\n" -"\n" -"vec3 CalcDirectionalLight(Light l, vec3 n, vec3 v, float s)\n" -"{\n" -" vec3 lightDir = normalize(-l.direction);\n" -" float diff = clamp(float(dot(n, lightDir)), 0.0, 1.0)*l.intensity;\n" -" float spec = 0.0;\n" -" if (diff > 0.0)\n" -" {\n" -" vec3 h = normalize(lightDir + v);\n" -" spec = pow(dot(n, h), 3.0 + glossiness)*s;\n" -" }\n" -" return (diff*l.intensity*l.diffuse.rgb + spec*colSpecular.rgb);\n" -"}\n" -"\n" -"vec3 CalcSpotLight(Light l, vec3 n, vec3 v, float s)\n" -"{\n" -" vec3 surfacePos = vec3(modelMatrix*vec4(fragPosition, 1.0));\n" -" vec3 lightToSurface = normalize(surfacePos - l.position);\n" -" vec3 lightDir = normalize(-l.direction);\n" -" float diff = clamp(float(dot(n, lightDir)), 0.0, 1.0)*l.intensity;\n" -" float attenuation = clamp(float(dot(n, lightToSurface)), 0.0, 1.0);\n" -" attenuation = dot(lightToSurface, -lightDir);\n" -" float lightToSurfaceAngle = degrees(acos(attenuation));\n" -" if (lightToSurfaceAngle > l.coneAngle) attenuation = 0.0;\n" -" float falloff = (l.coneAngle - lightToSurfaceAngle)/l.coneAngle;\n" -" float diffAttenuation = diff*attenuation;\n" -" float spec = 0.0;\n" -" if (diffAttenuation > 0.0)\n" -" {\n" -" vec3 h = normalize(lightDir + v);\n" -" spec = pow(dot(n, h), 3.0 + glossiness)*s;\n" -" }\n" -" return (falloff*(diffAttenuation*l.diffuse.rgb + spec*colSpecular.rgb));\n" -"}\n" -"\n" -"void main()\n" -"{\n" -" mat3 normalMatrix = mat3(modelMatrix);\n" -" vec3 normal = normalize(normalMatrix*fragNormal);\n" -" vec3 n = normalize(normal);\n" -" vec3 v = normalize(viewDir);\n" -#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21) -" vec4 texelColor = texture2D(texture0, fragTexCoord);\n" -#elif defined(GRAPHICS_API_OPENGL_33) -" vec4 texelColor = texture(texture0, fragTexCoord);\n" -#endif -" vec3 lighting = colAmbient.rgb;\n" -" if (useNormal == 1)\n" -" {\n" -#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21) -" n *= texture2D(texture1, fragTexCoord).rgb;\n" -#elif defined(GRAPHICS_API_OPENGL_33) -" n *= texture(texture1, fragTexCoord).rgb;\n" -#endif -" n = normalize(n);\n" -" }\n" -" float spec = 1.0;\n" -#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21) -" if (useSpecular == 1) spec *= normalize(texture2D(texture2, fragTexCoord).r);\n" -#elif defined(GRAPHICS_API_OPENGL_33) -" if (useSpecular == 1) spec *= normalize(texture(texture2, fragTexCoord).r);\n" -#endif -" for (int i = 0; i < maxLights; i++)\n" -" {\n" -" if (lights[i].enabled == 1)\n" -" {\n" -" if(lights[i].type == 0) lighting += CalcPointLight(lights[i], n, v, spec);\n" -" else if(lights[i].type == 1) lighting += CalcDirectionalLight(lights[i], n, v, spec);\n" -" else if(lights[i].type == 2) lighting += CalcSpotLight(lights[i], n, v, spec);\n" -" }\n" -" }\n" -#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21) -" gl_FragColor = vec4(texelColor.rgb*lighting*colDiffuse.rgb, texelColor.a*colDiffuse.a); \n" -#elif defined(GRAPHICS_API_OPENGL_33) -" finalColor = vec4(texelColor.rgb*lighting*colDiffuse.rgb, texelColor.a*colDiffuse.a); \n" -#endif -"}\n"; -- cgit v1.2.3 From 884e13ac2faea7ea91af1fa5a4c1cfaf44dfb4af Mon Sep 17 00:00:00 2001 From: raysan5 Date: Fri, 8 Jul 2016 20:32:06 +0200 Subject: Updated VR support -IN PROGRESS- - Embedded VR distortion shader - Ready to support multiple VR devices - Fallback to VR Simulator if device not ready - Support mono rendering over stereo rendering --- examples/resources/shaders/glsl100/distortion.fs | 20 +- examples/resources/shaders/glsl330/distortion.fs | 21 +- src/rlgl.c | 505 +++++++++++++---------- src/shader_distortion.h | 91 ++++ 4 files changed, 376 insertions(+), 261 deletions(-) create mode 100644 src/shader_distortion.h (limited to 'src') diff --git a/examples/resources/shaders/glsl100/distortion.fs b/examples/resources/shaders/glsl100/distortion.fs index a0a6cc18..f19c88ae 100644 --- a/examples/resources/shaders/glsl100/distortion.fs +++ b/examples/resources/shaders/glsl100/distortion.fs @@ -8,28 +8,16 @@ varying vec2 fragTexCoord; // Input uniform values uniform sampler2D texture0; -// NOTE: Add here your custom variables +// NOTE: Default parameters for Oculus Rift device const vec2 LeftLensCenter = vec2(0.2863248, 0.5); const vec2 RightLensCenter = vec2(0.7136753, 0.5); const vec2 LeftScreenCenter = vec2(0.25, 0.5); const vec2 RightScreenCenter = vec2(0.75, 0.5); -const vec2 Scale = vec2(0.25, 0.45); //vec2(0.1469278, 0.2350845); -const vec2 ScaleIn = vec2(4, 2.2222); -const vec4 HmdWarpParam = vec4(1, 0.22, 0.24, 0); +const vec2 Scale = vec2(0.25, 0.45); +const vec2 ScaleIn = vec2(4.0, 2.2222); +const vec4 HmdWarpParam = vec4(1.0, 0.22, 0.24, 0.0); const vec4 ChromaAbParam = vec4(0.996, -0.004, 1.014, 0.0); -/* -// Another set of default values -ChromaAbCorrection = {1.0, 0.0, 1.0, 0} -DistortionK = {1.0, 0.22, 0.24, 0} -Scale = {0.25, 0.5*AspectRatio, 0, 0} -ScaleIn = {4.0, 2/AspectRatio, 0, 0} -Left Screen Center = {0.25, 0.5, 0, 0} -Left Lens Center = {0.287994117, 0.5, 0, 0} -Right Screen Center = {0.75, 0.5, 0, 0} -Right Lens Center = {0.712005913, 0.5, 0, 0} -*/ - void main() { // The following two variables need to be set per eye diff --git a/examples/resources/shaders/glsl330/distortion.fs b/examples/resources/shaders/glsl330/distortion.fs index 62856341..635b86ac 100644 --- a/examples/resources/shaders/glsl330/distortion.fs +++ b/examples/resources/shaders/glsl330/distortion.fs @@ -9,29 +9,16 @@ uniform sampler2D texture0; // Output fragment color out vec4 finalColor; -// NOTE: Add here your custom variables +// NOTE: Default parameters for Oculus Rift device const vec2 LeftLensCenter = vec2(0.288, 0.5); const vec2 RightLensCenter = vec2(0.712, 0.5); const vec2 LeftScreenCenter = vec2(0.25, 0.5); const vec2 RightScreenCenter = vec2(0.75, 0.5); -uniform vec2 Scale = vec2(0.25, 0.45); //vec2(0.1469278, 0.2350845); -uniform vec2 ScaleIn = vec2(4, 2.2222); - -const vec4 HmdWarpParam = vec4(1, 0.22, 0.24, 0); +const vec2 Scale = vec2(0.25, 0.45); +const vec2 ScaleIn = vec2(4.0, 2.2222); +const vec4 HmdWarpParam = vec4(1.0, 0.22, 0.24, 0.0); const vec4 ChromaAbParam = vec4(0.996, -0.004, 1.014, 0.0); -/* -// Another set of default values -ChromaAbCorrection = {1.0, 0.0, 1.0, 0} -DistortionK = {1.0, 0.22, 0.24, 0} -Scale = {0.25, 0.5*AspectRatio, 0, 0} -ScaleIn = {4.0, 2/AspectRatio, 0, 0} -Left Screen Center = {0.25, 0.5, 0, 0} -Left Lens Center = {0.287994117, 0.5, 0, 0} -Right Screen Center = {0.75, 0.5, 0, 0} -Right Lens Center = {0.712005913, 0.5, 0, 0} -*/ - void main() { // The following two variables need to be set per eye diff --git a/src/rlgl.c b/src/rlgl.c index 25a6745c..7cb6a751 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -74,7 +74,11 @@ #endif #if !defined(GRAPHICS_API_OPENGL_11) && !defined(RLGL_NO_STANDARD_SHADER) - #include "standard_shader.h" // Standard shader to embed + #include "shader_standard.h" // Standard shader to be embedded +#endif + +#if !defined(GRAPHICS_API_OPENGL_11) && !defined(RLGL_NO_DISTORTION_SHADER) + #include "shader_distortion.h" // Distortion shader to be embedded #endif //#define RLGL_OCULUS_SUPPORT // Enable Oculus Rift code @@ -288,13 +292,14 @@ 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 oculusReady = false; // Oculus device ready flag -static bool oculusSimulator = false; // Oculus device simulator -static bool vrEnabled = false; // VR experience enabled (Oculus device or simulator) -static bool vrControl = true; // VR controlled by user code, instead of internally +static bool vrDeviceReady = false; // VR device ready flag +static bool vrSimulator = false; // VR simulator enabled flag +static bool vrEnabled = false; // VR experience enabled (device or simulator) +static bool vrRendering = true; // VR stereo rendering enabled/disabled flag + // NOTE: This flag is useful to render data over stereo image (i.e. FPS) -static RenderTexture2D stereoFbo; -static Shader distortionShader; +static RenderTexture2D stereoFbo; // Stereo rendering framebuffer +static Shader distortionShader; // Stereo rendering distortion shader (simulator) // Compressed textures support flags static bool texCompDXTSupported = false; // DDS texture compression support @@ -335,12 +340,12 @@ static void UpdateDefaultBuffers(void); // Update default internal buffers ( static void DrawDefaultBuffers(int eyesCount); // Draw default internal buffers vertex data static void UnloadDefaultBuffers(void); // Unload default internal buffers vertex data from CPU and GPU +// Configure stereo rendering (including distortion shader) with HMD device parameters +static void SetupVrDevice(VrDeviceInfo info); + // Set internal projection and modelview matrix depending on eyes tracking data static void SetStereoView(int eye, Matrix matProjection, Matrix matModelView); -// Configure stereo rendering (including distortion shader) with HMD device parameters -static void SetupVrDevice(VrDeviceInfo hmd); - static void SetShaderLights(Shader shader); // Sets shader uniform values for lights array static char *ReadTextFile(const char *fileName); @@ -1233,7 +1238,7 @@ void rlglDraw(void) // NOTE: Default buffers upload and draw UpdateDefaultBuffers(); - if (vrEnabled && vrControl) DrawDefaultBuffers(2); + if (vrEnabled && vrRendering) DrawDefaultBuffers(2); else DrawDefaultBuffers(1); #endif } @@ -2532,66 +2537,65 @@ void DestroyLight(Light light) // NOTE: If device is not available, it fallbacks to default device (simulator) void InitVrDevice(int hmdDevice) { -#if defined(RLGL_OCULUS_SUPPORT) - // Initialize Oculus device - ovrResult result = ovr_Initialize(NULL); - if (OVR_FAILURE(result)) + switch (hmdDevice) { - TraceLog(WARNING, "OVR: Could not initialize Oculus device"); - oculusReady = false; - } - else - { - result = ovr_Create(&session, &luid); - if (OVR_FAILURE(result)) + case HMD_DEFAULT_DEVICE: TraceLog(INFO, "Initializing default VR Device (Oculus Rift CV1)"); + case HMD_OCULUS_RIFT_DK2: + case HMD_OCULUS_RIFT_CV1: { - TraceLog(WARNING, "OVR: Could not create Oculus session"); - ovr_Shutdown(); - oculusReady = false; - } - 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); - - oculusReady = true; - vrEnabled = true; - } - } +#if defined(RLGL_OCULUS_SUPPORT) + vrDeviceReady = InitOculusDevice(); #else - oculusReady = false; + TraceLog(WARNING, "Oculus Rift not supported by default, recompile raylib with Oculus support"); #endif + } break; + case HMD_VALVE_HTC_VIVE: + case HMD_SAMSUNG_GEAR_VR: + case HMD_GOOGLE_CARDBOARD: + case HMD_SONY_PLAYSTATION_VR: + case HMD_RAZER_OSVR: + case HMD_FOVE_VR: TraceLog(WARNING, "VR Device not supported"); + default: break; + } - if (!oculusReady) + if (!vrDeviceReady) { - TraceLog(WARNING, "HMD Device not found: Initializing VR simulator"); + TraceLog(WARNING, "VR Device not found: Initializing VR Simulator"); // Initialize framebuffer and textures for stereo rendering stereoFbo = rlglLoadRenderTexture(screenWidth, screenHeight); - // Load oculus-distortion shader (oculus parameters setup internally) - // TODO: Embed coulus distortion shader (in this function like default shader?) - distortionShader = LoadShader("resources/shaders/glsl330/base.vs", "resources/shaders/glsl330/distortion.fs"); + // Load distortion shader (initialized by default with Oculus Rift CV1 parameters) + distortionShader.id = LoadShaderProgram(vDistortionShaderStr, fDistortionShaderStr); + if (distortionShader.id != 0) LoadDefaultShaderLocations(&distortionShader); + + VrDeviceInfo info = { 0 }; - oculusSimulator = true; + if ((hmdDevice == HMD_DEFAULT_DEVICE) || + (hmdDevice == HMD_OCULUS_RIFT_DK2) || + (hmdDevice == HMD_OCULUS_RIFT_CV1)) + { + info.hResolution = 1280; // HMD horizontal resolution in pixels + info.vResolution = 800; // HMD vertical resolution in pixels + info.hScreenSize = 0.14976f;; // HMD horizontal size in meters + info.vScreenSize = 0.09356f; // HMD vertical size in meters + info.vScreenCenter = 0.04675f; // HMD screen center in meters + info.eyeToScreenDistance = 0.041f; // HMD distance between eye and display in meters + info.lensSeparationDistance = 0.0635f; // HMD lens separation distance in meters + info.interpupillaryDistance = 0.064f; // HMD IPD (distance between pupils) in meters + info.distortionK[0] = 1.0f; // HMD lens distortion constant parameter 0 + info.distortionK[1] = 0.22f; // HMD lens distortion constant parameter 1 + info.distortionK[2] = 0.24f; // HMD lens distortion constant parameter 2 + info.distortionK[3] = 0.0f; // HMD lens distortion constant parameter 3 + info.chromaAbCorrection[0] = 0.996f; // HMD chromatic aberration correction parameter 0 + info.chromaAbCorrection[1] = -0.004f; // HMD chromatic aberration correction parameter 1 + info.chromaAbCorrection[2] = 1.014f; // HMD chromatic aberration correction parameter 2 + info.chromaAbCorrection[3] = 0.0f; // HMD chromatic aberration correction parameter 3 + } + + SetupVrDevice(info); + + vrSimulator = true; vrEnabled = true; } } @@ -2600,14 +2604,7 @@ void InitVrDevice(int hmdDevice) void CloseVrDevice(void) { #if defined(RLGL_OCULUS_SUPPORT) - if (oculusReady) - { - 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 - } + if (vrDeviceReady) CloseOculusDevice(); else #endif { @@ -2618,13 +2615,13 @@ void CloseVrDevice(void) UnloadShader(distortionShader); } - oculusReady = false; + vrDeviceReady = false; } // Detect if VR device is available bool IsVrDeviceReady(void) { - return (oculusReady || oculusSimulator) && vrEnabled; + return (vrDeviceReady || vrSimulator) && vrEnabled; } // Enable/Disable VR experience (device or simulator) @@ -2637,27 +2634,7 @@ void ToggleVrMode(void) void UpdateVrTracking(void) { #if defined(RLGL_OCULUS_SUPPORT) - if (oculusReady) - { - frameIndex++; - - ovrPosef eyePoses[2]; - ovr_GetEyePoses(session, frameIndex, ovrTrue, layer.viewScaleDesc.HmdToEyeOffset, eyePoses, &layer.eyeLayer.SensorSampleTime); - - layer.eyeLayer.RenderPose[0] = eyePoses[0]; - layer.eyeLayer.RenderPose[1] = eyePoses[1]; - - // Get session status information - ovrSessionStatus sessionStatus; - ovr_GetSessionStatus(session, &sessionStatus); - - if (sessionStatus.ShouldQuit) TraceLog(WARNING, "OVR: Session should quit..."); - if (sessionStatus.ShouldRecenter) ovr_RecenterTrackingOrigin(session); - //if (sessionStatus.HmdPresent) // HMD is present. - //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. - } + if (vrDeviceReady) UpdateOculusTracking(); else #endif { @@ -2665,116 +2642,13 @@ void UpdateVrTracking(void) } } -// Set internal projection and modelview matrix depending on eyes tracking data -static void SetStereoView(int eye, Matrix matProjection, Matrix matModelView) -{ - if (vrEnabled) - { - Matrix eyeProjection = matProjection; - Matrix eyeModelView = matModelView; - -#if defined(RLGL_OCULUS_SUPPORT) - if (oculusReady) - { - 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, - layer.eyeLayer.RenderPose[eye].Orientation.y, - layer.eyeLayer.RenderPose[eye].Orientation.z, - layer.eyeLayer.RenderPose[eye].Orientation.w }; - QuaternionInvert(&eyeRenderPose); - Matrix eyeOrientation = QuaternionToMatrix(eyeRenderPose); - Matrix eyeTranslation = MatrixTranslate(-layer.eyeLayer.RenderPose[eye].Position.x, - -layer.eyeLayer.RenderPose[eye].Position.y, - -layer.eyeLayer.RenderPose[eye].Position.z); - - Matrix eyeView = MatrixMultiply(eyeTranslation, eyeOrientation); // Matrix containing eye-head movement - eyeModelView = MatrixMultiply(matModelView, eyeView); // Combine internal camera matrix (modelview) wih eye-head movement - - eyeProjection = layer.eyeProjections[eye]; - } - else -#endif - { - // Setup viewport and projection/modelview matrices using tracking data - rlViewport(eye*screenWidth/2, 0, screenWidth/2, screenHeight); - - static float IPD = 0.064f; // InterpupillaryDistance - float HScreenSize = 0.14976f; - float VScreenSize = 0.09356f; // HScreenSize/(1280.0f/800.0f) (DK2) - float VScreenCenter = 0.04675f; // VScreenSize/2 - float EyeToScreenDistance = 0.041f; - float LensSeparationDistance = 0.0635f; //0.0635f (DK2) - - // NOTE: fovy value obtained from device parameters (Oculus Rift CV1) - float halfScreenDistance = VScreenSize/2.0f; - float fovy = 2.0f*atan(halfScreenDistance/EyeToScreenDistance)*RAD2DEG; - - float viewCenter = (float)HScreenSize*0.25f; - float eyeProjectionShift = viewCenter - LensSeparationDistance*0.5f; - float projectionCenterOffset = eyeProjectionShift/(float)HScreenSize; //4.0f*eyeProjectionShift/(float)HScreenSize; -/* - static float scale[2] = { 0.25, 0.45 }; - - if (IsKeyDown(KEY_RIGHT)) scale[0] += 0.01; - else if (IsKeyDown(KEY_LEFT)) scale[0] -= 0.01; - else if (IsKeyDown(KEY_UP)) scale[1] += 0.01; - else if (IsKeyDown(KEY_DOWN)) scale[1] -= 0.01; - - SetShaderValue(distortionShader, GetShaderLocation(distortionShader, "Scale"), scale, 2); - - if (IsKeyDown(KEY_N)) IPD += 0.02; - else if (IsKeyDown(KEY_M)) IPD -= 0.02; -*/ - // The matrixes for offsetting the projection and view for each eye, to achieve stereo effect - Vector3 projectionOffset = { -projectionCenterOffset, 0.0f, 0.0f }; - - // 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. - Vector3 viewOffset = { -IPD/2.0f, 0.075f, 0.045f }; - - // Negate the left eye versions - if (eye == 0) - { - projectionOffset.x *= -1.0f; - viewOffset.x *= -1.0f; - } - - // Adjust the view and projection matrixes - // View matrix is translated based on the eye offset - Matrix projCenter = MatrixPerspective(fovy, (double)((float)screenWidth*0.5f)/(double)screenHeight, 0.01, 1000.0); - - Matrix projTranslation = MatrixTranslate(projectionOffset.x, projectionOffset.y, projectionOffset.z); - Matrix viewTranslation = MatrixTranslate(viewOffset.x, viewOffset.y, viewOffset.z); - - eyeProjection = MatrixMultiply(projCenter, projTranslation); // projection - eyeModelView = MatrixMultiply(matModelView, viewTranslation); // modelview - - MatrixTranspose(&eyeProjection); - } - - SetMatrixModelview(eyeModelView); - SetMatrixProjection(eyeProjection); - } -} - // Begin Oculus drawing configuration void BeginVrDrawing(void) { #if defined(RLGL_OCULUS_SUPPORT) - if (oculusReady) + if (vrDeviceReady) { - GLuint currentTexId; - int currentIndex; - - ovr_GetTextureSwapChainCurrentIndex(session, buffer.textureChain, ¤tIndex); - ovr_GetTextureSwapChainBufferGL(session, buffer.textureChain, currentIndex, ¤tTexId); - - 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 + BeginOculusDrawing(); } else #endif @@ -2792,26 +2666,16 @@ void BeginVrDrawing(void) //glViewport(0, 0, buffer.width, buffer.height); // Useful if rendering to separate framebuffers (every eye) rlClearScreenBuffers(); // Clear current framebuffer(s) - vrControl = true; + vrRendering = true; } // End Oculus drawing process (and desktop mirror) void EndVrDrawing(void) { #if defined(RLGL_OCULUS_SUPPORT) - if (oculusReady) + if (vrDeviceReady) { - // Unbind current framebuffer (Oculus buffer) - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - - ovr_CommitTextureSwapChain(session, buffer.textureChain); - - ovrLayerHeader *layers = &layer.eyeLayer.Header; - ovr_SubmitFrame(session, frameIndex, &layer.viewScaleDesc, &layers, 1); - - // Blit mirror texture to back buffer - BlitOculusMirror(session, mirror); + EndOculusDrawing(); } else #endif @@ -2869,7 +2733,7 @@ void EndVrDrawing(void) rlDisableDepthTest(); - vrControl = false; + vrRendering = false; } //---------------------------------------------------------------------------------- @@ -3890,25 +3754,34 @@ static Color *GenNextMipmap(Color *srcData, int srcWidth, int srcHeight) // Configure stereo rendering (including distortion shader) with HMD device parameters static void SetupVrDevice(VrDeviceInfo hmd) { + // NOTE: fovy value obtained from device parameters (Oculus Rift CV1) + //float fovy = 2.0f*atan((VScreenSize*0.5f)/EyeToScreenDistance)*RAD2DEG; + + //float eyeProjectionShift = ; + //float projectionOffset = (HScreenSize*0.25f - LensSeparationDistance*0.5f)/(float)HScreenSize; + // Compute aspect ratio and FOV - float aspect = ((float)hmd.hResolution/2.0f)/(float)hmd.vResolution; + //float aspect = ((float)hmd.hResolution/2.0f)/(float)hmd.vResolution; + float aspect = (float)screenWidth*0.5f/(float)screenHeight; // Fov-y is normally computed with: 2*atan2(hmd.vScreenSize, 2*hmd.eyeToScreenDistance)*RAD2DEG // ...but with lens distortion it is increased (see Oculus SDK Documentation) float radius = -1.0 - (4*(hmd.hScreenSize/4 - hmd.lensSeparationDistance/2)/hmd.hScreenSize); float distScale = (hmd.distortionK[0] + hmd.distortionK[1]*pow(radius, 2) + hmd.distortionK[2]*pow(radius, 4) + hmd.distortionK[3]*pow(radius, 6)); - float fovy = 2*atan2(hmd.vScreenSize*distScale, 2*hmd.eyeToScreenDistance)*RAD2DEG; + //float fovy = 2.0f*atan2(hmd.vScreenSize*distScale, 2*hmd.eyeToScreenDistance)*RAD2DEG; + float fovy = 2.0f*atan((hmd.vScreenSize*0.5f)/hmd.eyeToScreenDistance)*RAD2DEG; // Compute camera projection matrices - Matrix proj = MatrixPerspective(fovy, aspect, 0.1, 10000); - float projOffset = 4*(hmd.hScreenSize/4 - hmd.interpupillaryDistance/2)/hmd.hScreenSize; + Matrix proj = MatrixPerspective(fovy, aspect, 0.01, 1000.0); + //float projOffset = 4.0f*(hmd.hScreenSize/4 - hmd.interpupillaryDistance/2)/hmd.hScreenSize; + float projOffset = (hmd.hScreenSize*0.25f - hmd.lensSeparationDistance*0.5f)/hmd.hScreenSize; - //Matrix projLeft = MatrixMultiply(MatrixTranslation(projOffset, 0.0, 0.0), proj); - //matrix projRight = MatrixMultiply(MatrixTranslation(-projOffset, 0.0, 0.0)), proj); + //Matrix projLeft = MatrixMultiply(MatrixTranslate(projOffset, 0.0, 0.0), proj); + //matrix projRight = MatrixMultiply(MatrixTranslate(-projOffset, 0.0, 0.0)), proj); // Compute camera transformation matrices - //Matrix viewTransformLeft = MatrixTranslation(-hmd.interpupillaryDistance/2, 0.0, 0.0 ); - //Matrix viewTransformRight = MatrixTranslation(hmd.interpupillaryDistance/2, 0.0, 0.0 ); + //Matrix viewTransformLeft = MatrixTranslate(-hmd.interpupillaryDistance/2, 0.0, 0.0 ); + //Matrix viewTransformRight = MatrixTranslate(hmd.interpupillaryDistance/2, 0.0, 0.0 ); // Compute eyes Viewports // Rectangle viewportLeft = { 0, 0, hmd.hResolution/2, hmd.vResolution }; @@ -3916,50 +3789,226 @@ static void SetupVrDevice(VrDeviceInfo hmd) // Distortion shader parameters float lensShift = 4*(hmd.hScreenSize/4 - hmd.lensSeparationDistance/2)/hmd.hScreenSize; - float leftLensCenter[2] = { lensShift, 0.0f }; - float rightLensCenter[2] = { -lensShift, 0.0f }; + float leftLensCenter[2] = { lensShift, 0.0f }; // REVIEW!!! + float rightLensCenter[2] = { -lensShift, 0.0f }; // REVIEW!!! float leftScreenCenter[2] = { 0.25f, 0.5f }; float rightScreenCenter[2] = { 0.75f, 0.5f }; - float scaleIn[2] = { 1.0f, 1.0f/aspect }; - float scale[2] = { 1.0f/distScale, 1.0f*aspect/distScale }; + float scaleIn[2] = { 1.0f, 1.0f/aspect }; // REVIEW!!! + float scale[2] = { 1.0f/distScale, 1.0f*aspect/distScale }; // REVIEW!!! // Distortion shader parameters update - SetShaderValue(distortionShader, GetShaderLocation(distortionShader, "leftLensCenter"), leftLensCenter, 2); - SetShaderValue(distortionShader, GetShaderLocation(distortionShader, "rightLensCenter"), rightLensCenter, 2); + //SetShaderValue(distortionShader, GetShaderLocation(distortionShader, "leftLensCenter"), leftLensCenter, 2); + //SetShaderValue(distortionShader, GetShaderLocation(distortionShader, "rightLensCenter"), rightLensCenter, 2); SetShaderValue(distortionShader, GetShaderLocation(distortionShader, "leftScreenCenter"), leftScreenCenter, 2); SetShaderValue(distortionShader, GetShaderLocation(distortionShader, "rightScreenCenter"), rightScreenCenter, 2); - SetShaderValue(distortionShader, GetShaderLocation(distortionShader, "scale"), scale, 2); - SetShaderValue(distortionShader, GetShaderLocation(distortionShader, "scaleIn"), scaleIn, 2); + //SetShaderValue(distortionShader, GetShaderLocation(distortionShader, "scale"), scale, 2); + //SetShaderValue(distortionShader, GetShaderLocation(distortionShader, "scaleIn"), scaleIn, 2); SetShaderValue(distortionShader, GetShaderLocation(distortionShader, "hmdWarpParam"), hmd.distortionK, 4); SetShaderValue(distortionShader, GetShaderLocation(distortionShader, "chromaAbParam"), hmd.chromaAbCorrection, 4); } +// Set internal projection and modelview matrix depending on eyes tracking data +static void SetStereoView(int eye, Matrix matProjection, Matrix matModelView) +{ + if (vrEnabled) + { + Matrix eyeProjection = matProjection; + Matrix eyeModelView = matModelView; + #if defined(RLGL_OCULUS_SUPPORT) -static void InitOculusDevice(void) + if (vrDeviceReady) + { + 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, + layer.eyeLayer.RenderPose[eye].Orientation.y, + layer.eyeLayer.RenderPose[eye].Orientation.z, + layer.eyeLayer.RenderPose[eye].Orientation.w }; + QuaternionInvert(&eyeRenderPose); + Matrix eyeOrientation = QuaternionToMatrix(eyeRenderPose); + Matrix eyeTranslation = MatrixTranslate(-layer.eyeLayer.RenderPose[eye].Position.x, + -layer.eyeLayer.RenderPose[eye].Position.y, + -layer.eyeLayer.RenderPose[eye].Position.z); + + Matrix eyeView = MatrixMultiply(eyeTranslation, eyeOrientation); // Matrix containing eye-head movement + eyeModelView = MatrixMultiply(matModelView, eyeView); // Combine internal camera matrix (modelview) wih eye-head movement + + eyeProjection = layer.eyeProjections[eye]; + } + else +#endif + { + // Setup viewport and projection/modelview matrices using tracking data + rlViewport(eye*screenWidth/2, 0, screenWidth/2, screenHeight); + + float HScreenSize = 0.14976f; + float VScreenSize = 0.09356f; // HScreenSize/(1280.0f/800.0f) (DK2) + float VScreenCenter = 0.04675f; // VScreenSize/2 + float EyeToScreenDistance = 0.041f; + float LensSeparationDistance = 0.0635f; // DK2 + float InterpupillaryDistance = 0.064f; // IPD + + // NOTE: fovy value obtained from device parameters (Oculus Rift CV1) + float halfScreenDistance = VScreenSize/2.0f; + float fovy = 2.0f*atan(halfScreenDistance/EyeToScreenDistance)*RAD2DEG; + + float viewCenter = (float)HScreenSize*0.25f; + float eyeProjectionShift = viewCenter - LensSeparationDistance*0.5f; + float projectionCenterOffset = eyeProjectionShift/(float)HScreenSize; //4.0f*eyeProjectionShift/(float)HScreenSize; +/* + static float scale[2] = { 0.25, 0.45 }; + + if (IsKeyDown(KEY_RIGHT)) scale[0] += 0.01; + else if (IsKeyDown(KEY_LEFT)) scale[0] -= 0.01; + else if (IsKeyDown(KEY_UP)) scale[1] += 0.01; + else if (IsKeyDown(KEY_DOWN)) scale[1] -= 0.01; + + SetShaderValue(distortionShader, GetShaderLocation(distortionShader, "Scale"), scale, 2); + + if (IsKeyDown(KEY_N)) IPD += 0.02; + else if (IsKeyDown(KEY_M)) IPD -= 0.02; +*/ + // The matrixes for offsetting the projection and view for each eye, to achieve stereo effect + Vector3 projectionOffset = { -projectionCenterOffset, 0.0f, 0.0f }; + + // 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. + Vector3 viewOffset = { -InterpupillaryDistance/2.0f, 0.075f, 0.045f }; + + // Negate the left eye versions + if (eye == 0) + { + projectionOffset.x *= -1.0f; + viewOffset.x *= -1.0f; + } + + // Adjust the view and projection matrixes + // View matrix is translated based on the eye offset + Matrix projCenter = MatrixPerspective(fovy, (double)((float)screenWidth*0.5f)/(double)screenHeight, 0.01, 1000.0); + + Matrix projTranslation = MatrixTranslate(projectionOffset.x, projectionOffset.y, projectionOffset.z); + Matrix viewTranslation = MatrixTranslate(viewOffset.x, viewOffset.y, viewOffset.z); + + eyeProjection = MatrixMultiply(projCenter, projTranslation); // projection + eyeModelView = MatrixMultiply(matModelView, viewTranslation); // modelview + + MatrixTranspose(&eyeProjection); + } + + SetMatrixModelview(eyeModelView); + SetMatrixProjection(eyeProjection); + } +} + +#if defined(RLGL_OCULUS_SUPPORT) +// Initialize Oculus device +static bool InitOculusDevice(void) { + bool oculusReady = false; + + ovrResult result = ovr_Initialize(NULL); + + if (OVR_FAILURE(result)) TraceLog(WARNING, "OVR: Could not initialize Oculus device"); + else + { + result = ovr_Create(&session, &luid); + if (OVR_FAILURE(result)) + { + TraceLog(WARNING, "OVR: Could not create Oculus session"); + ovr_Shutdown(); + } + 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); + + oculusReady = true; + vrEnabled = true; + } + } + return oculusReady; } static void CloseOculusDevice(void) { - + 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 } static void UpdateOculusTracking(void) { + frameIndex++; + + ovrPosef eyePoses[2]; + ovr_GetEyePoses(session, frameIndex, ovrTrue, layer.viewScaleDesc.HmdToEyeOffset, eyePoses, &layer.eyeLayer.SensorSampleTime); + + layer.eyeLayer.RenderPose[0] = eyePoses[0]; + layer.eyeLayer.RenderPose[1] = eyePoses[1]; + // Get session status information + ovrSessionStatus sessionStatus; + ovr_GetSessionStatus(session, &sessionStatus); + + if (sessionStatus.ShouldQuit) TraceLog(WARNING, "OVR: Session should quit..."); + if (sessionStatus.ShouldRecenter) ovr_RecenterTrackingOrigin(session); + //if (sessionStatus.HmdPresent) // HMD is present. + //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. } static void BeginOculusDrawing(void) { + GLuint currentTexId; + int currentIndex; + ovr_GetTextureSwapChainCurrentIndex(session, buffer.textureChain, ¤tIndex); + ovr_GetTextureSwapChainBufferGL(session, buffer.textureChain, currentIndex, ¤tTexId); + + 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 } static void EndOculusDrawing(void) { + // Unbind current framebuffer (Oculus buffer) + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + ovr_CommitTextureSwapChain(session, buffer.textureChain); + + ovrLayerHeader *layers = &layer.eyeLayer.Header; + ovr_SubmitFrame(session, frameIndex, &layer.viewScaleDesc, &layers, 1); + + // Blit mirror texture to back buffer + BlitOculusMirror(session, mirror); } // Load Oculus required buffers: texture-swap-chain, fbo, texture-depth diff --git a/src/shader_distortion.h b/src/shader_distortion.h new file mode 100644 index 00000000..e4ce5d6c --- /dev/null +++ b/src/shader_distortion.h @@ -0,0 +1,91 @@ + +// Vertex shader definition to embed, no external file required +static const char vDistortionShaderStr[] = +#if defined(GRAPHICS_API_OPENGL_21) +"#version 120 \n" +#elif defined(GRAPHICS_API_OPENGL_ES2) +"#version 100 \n" +#endif +#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21) +"attribute vec3 vertexPosition; \n" +"attribute vec2 vertexTexCoord; \n" +"attribute vec4 vertexColor; \n" +"varying vec2 fragTexCoord; \n" +"varying vec4 fragColor; \n" +#elif defined(GRAPHICS_API_OPENGL_33) +"#version 330 \n" +"in vec3 vertexPosition; \n" +"in vec2 vertexTexCoord; \n" +"in vec4 vertexColor; \n" +"out vec2 fragTexCoord; \n" +"out vec4 fragColor; \n" +#endif +"uniform mat4 mvpMatrix; \n" +"void main() \n" +"{ \n" +" fragTexCoord = vertexTexCoord; \n" +" fragColor = vertexColor; \n" +" gl_Position = mvpMatrix*vec4(vertexPosition, 1.0); \n" +"} \n"; + +// Fragment shader definition to embed, no external file required +static const char fDistortionShaderStr[] = +#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" +"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" +"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" +" finalColor = vec4(0.0, 0.0, 0.0, 1.0); \n" +" } \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"; -- cgit v1.2.3 From 17331258738229ca087437c31bbfc3c9495fe42e Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 8 Jul 2016 23:17:18 +0200 Subject: Do not expose raw audio context to final user... ...at least, directly, available if using directly audio module... --- src/audio.h | 4 ++-- src/raylib.h | 11 ++--------- 2 files changed, 4 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/audio.h b/src/audio.h index fe72d866..3ffe575c 100644 --- a/src/audio.h +++ b/src/audio.h @@ -100,10 +100,10 @@ void PauseMusicStream(int index); // Pause music p void ResumeMusicStream(int index); // Resume playing paused music bool IsMusicPlaying(int index); // Check if music is playing void SetMusicVolume(int index, float volume); // Set volume for music (1.0 is max level) +void SetMusicPitch(int index, float pitch); // Set pitch for a music (1.0 is base level) float GetMusicTimeLength(int index); // Get music time length (in seconds) float GetMusicTimePlayed(int index); // Get current music time played (in seconds) -int GetMusicStreamCount(void); -void SetMusicPitch(int index, float pitch); +int GetMusicStreamCount(void); // Get number of streams loaded // used to output raw audio streams, returns negative numbers on error // if floating point is false the data size is 16bit short, otherwise it is float 32bit diff --git a/src/raylib.h b/src/raylib.h index 1d160492..9225c5ee 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -895,17 +895,10 @@ void PauseMusicStream(int index); // Pause music p void ResumeMusicStream(int index); // Resume playing paused music bool IsMusicPlaying(int index); // Check if music is playing void SetMusicVolume(int index, float volume); // Set volume for music (1.0 is max level) +void SetMusicPitch(int index, float pitch); // Set pitch for a music (1.0 is base level) float GetMusicTimeLength(int index); // Get current music time length (in seconds) float GetMusicTimePlayed(int index); // Get current music time played (in seconds) -int GetMusicStreamCount(void); -void SetMusicPitch(int index, float pitch); - -// used to output raw audio streams, returns negative numbers on error -// if floating point is false the data size is 16bit short, otherwise it is float 32bit -RawAudioContext InitRawAudioContext(int sampleRate, int channels, bool floatingPoint); - -void CloseRawAudioContext(RawAudioContext ctx); -int BufferRawAudioContext(RawAudioContext ctx, void *data, unsigned short numberElements); // returns number of elements buffered +int GetMusicStreamCount(void); // Get number of streams loaded #ifdef __cplusplus } -- cgit v1.2.3 From 24c267d32499c35c5cd61e52e9e32f15cc79faad Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 10 Jul 2016 20:09:18 +0200 Subject: Compute stereo config from device parameters Simulator configuration is directly obtained from VR device parameters! --- src/rlgl.c | 249 +++++++++++++++++++++++++++---------------------------------- 1 file changed, 108 insertions(+), 141 deletions(-) (limited to 'src') diff --git a/src/rlgl.c b/src/rlgl.c index 7cb6a751..65249f5e 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -31,7 +31,7 @@ #include // Required for: fopen(), fclose(), fread()... [Used only on ReadTextFile()] #include // Required for: malloc(), free(), rand() #include // Required for: strcmp(), strlen(), strtok() -#include // Required for: atan() +#include // Required for: atan2() #ifndef RLGL_STANDALONE #include "raymath.h" // Required for Vector3 and Matrix functions @@ -206,6 +206,15 @@ typedef struct { float chromaAbCorrection[4]; // HMD chromatic aberration correction parameters } VrDeviceInfo; +// VR Stereo rendering configuration for simulator +typedef struct { + RenderTexture2D stereoFbo; // VR stereo rendering framebuffer + Shader distortionShader; // VR stereo rendering distortion shader + //Rectangle eyesViewport[2]; // VR stereo rendering eyes viewports + Matrix eyesProjection[2]; // VR stereo rendering eyes projection matrices + Matrix eyesViewOffset[2]; // VR stereo rendering eyes view offset matrices +} VrStereoConfig; + #if defined(RLGL_OCULUS_SUPPORT) typedef struct OculusBuffer { ovrTextureSwapChain textureChain; @@ -292,19 +301,15 @@ static OculusMirror mirror; // Oculus mirror texture and fbo static unsigned int frameIndex = 0; // Oculus frames counter, used to discard frames from chain #endif +// VR global variables +static VrDeviceInfo hmd; // Current VR device info +static VrStereoConfig vrConfig; // VR stereo configuration for simulator static bool vrDeviceReady = false; // VR device ready flag static bool vrSimulator = false; // VR simulator enabled flag static bool vrEnabled = false; // VR experience enabled (device or simulator) static bool vrRendering = true; // VR stereo rendering enabled/disabled flag // NOTE: This flag is useful to render data over stereo image (i.e. FPS) -static RenderTexture2D stereoFbo; // Stereo rendering framebuffer -static Shader distortionShader; // Stereo rendering distortion shader (simulator) - -// Compressed textures support flags -static bool texCompDXTSupported = false; // DDS texture compression support -static bool npotSupported = false; // NPOT textures full support - #if defined(GRAPHICS_API_OPENGL_ES2) // NOTE: VAO functionality is exposed through extensions (OES) static PFNGLGENVERTEXARRAYSOESPROC glGenVertexArrays; @@ -313,6 +318,10 @@ static PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArrays; //static PFNGLISVERTEXARRAYOESPROC glIsVertexArray; // NOTE: Fails in WebGL, omitted #endif +// Compressed textures support flags +static bool texCompDXTSupported = false; // DDS texture compression support +static bool npotSupported = false; // NPOT textures full support + static int blendMode = 0; // Track current blending mode // White texture useful for plain color polys (required by shader) @@ -341,7 +350,7 @@ static void DrawDefaultBuffers(int eyesCount); // Draw default internal buffers static void UnloadDefaultBuffers(void); // Unload default internal buffers vertex data from CPU and GPU // Configure stereo rendering (including distortion shader) with HMD device parameters -static void SetupVrDevice(VrDeviceInfo info); +static void SetStereoConfig(VrDeviceInfo info); // Set internal projection and modelview matrix depending on eyes tracking data static void SetStereoView(int eye, Matrix matProjection, Matrix matModelView); @@ -2535,6 +2544,7 @@ void DestroyLight(Light light) // Init VR device (or simulator) // NOTE: If device is not available, it fallbacks to default device (simulator) +// NOTE: It modifies the global variable: VrDeviceInfo hmd void InitVrDevice(int hmdDevice) { switch (hmdDevice) @@ -2560,40 +2570,39 @@ void InitVrDevice(int hmdDevice) if (!vrDeviceReady) { - TraceLog(WARNING, "VR Device not found: Initializing VR Simulator"); + TraceLog(WARNING, "VR Device not found: Initializing VR Simulator (Oculus Rift DK2)"); // Initialize framebuffer and textures for stereo rendering - stereoFbo = rlglLoadRenderTexture(screenWidth, screenHeight); + vrConfig.stereoFbo = rlglLoadRenderTexture(screenWidth, screenHeight); // Load distortion shader (initialized by default with Oculus Rift CV1 parameters) - distortionShader.id = LoadShaderProgram(vDistortionShaderStr, fDistortionShaderStr); - if (distortionShader.id != 0) LoadDefaultShaderLocations(&distortionShader); - - VrDeviceInfo info = { 0 }; - + vrConfig.distortionShader.id = LoadShaderProgram(vDistortionShaderStr, fDistortionShaderStr); + if (vrConfig.distortionShader.id != 0) LoadDefaultShaderLocations(&vrConfig.distortionShader); + if ((hmdDevice == HMD_DEFAULT_DEVICE) || (hmdDevice == HMD_OCULUS_RIFT_DK2) || (hmdDevice == HMD_OCULUS_RIFT_CV1)) { - info.hResolution = 1280; // HMD horizontal resolution in pixels - info.vResolution = 800; // HMD vertical resolution in pixels - info.hScreenSize = 0.14976f;; // HMD horizontal size in meters - info.vScreenSize = 0.09356f; // HMD vertical size in meters - info.vScreenCenter = 0.04675f; // HMD screen center in meters - info.eyeToScreenDistance = 0.041f; // HMD distance between eye and display in meters - info.lensSeparationDistance = 0.0635f; // HMD lens separation distance in meters - info.interpupillaryDistance = 0.064f; // HMD IPD (distance between pupils) in meters - info.distortionK[0] = 1.0f; // HMD lens distortion constant parameter 0 - info.distortionK[1] = 0.22f; // HMD lens distortion constant parameter 1 - info.distortionK[2] = 0.24f; // HMD lens distortion constant parameter 2 - info.distortionK[3] = 0.0f; // HMD lens distortion constant parameter 3 - info.chromaAbCorrection[0] = 0.996f; // HMD chromatic aberration correction parameter 0 - info.chromaAbCorrection[1] = -0.004f; // HMD chromatic aberration correction parameter 1 - info.chromaAbCorrection[2] = 1.014f; // HMD chromatic aberration correction parameter 2 - info.chromaAbCorrection[3] = 0.0f; // HMD chromatic aberration correction parameter 3 + // NOTE: 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.04675f; // 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.distortionK[0] = 1.0f; // HMD lens distortion constant parameter 0 + hmd.distortionK[1] = 0.22f; // HMD lens distortion constant parameter 1 + hmd.distortionK[2] = 0.24f; // HMD lens distortion constant parameter 2 + hmd.distortionK[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 } - SetupVrDevice(info); + SetStereoConfig(hmd); vrSimulator = true; vrEnabled = true; @@ -2608,11 +2617,8 @@ void CloseVrDevice(void) else #endif { - // Unload stereo framebuffer and texture - rlDeleteRenderTextures(stereoFbo); - - // Unload oculus-distortion shader - UnloadShader(distortionShader); + rlDeleteRenderTextures(vrConfig.stereoFbo); // Unload stereo framebuffer and texture + UnloadShader(vrConfig.distortionShader); // Unload distortion shader } vrDeviceReady = false; @@ -2654,7 +2660,7 @@ void BeginVrDrawing(void) #endif { // Setup framebuffer for stereo rendering - rlEnableRenderTexture(stereoFbo.id); + rlEnableRenderTexture(vrConfig.stereoFbo.id); } // NOTE: If your application is configured to treat the texture as a linear format (e.g. GL_RGBA) @@ -2696,9 +2702,9 @@ void EndVrDrawing(void) rlLoadIdentity(); // Reset internal modelview matrix // Draw RenderTexture (stereoFbo) using distortion shader - currentShader = distortionShader; + currentShader = vrConfig.distortionShader; - rlEnableTexture(stereoFbo.texture.id); + rlEnableTexture(vrConfig.stereoFbo.texture.id); rlPushMatrix(); rlBegin(RL_QUADS); @@ -2711,15 +2717,15 @@ void EndVrDrawing(void) // Bottom-right corner for texture and quad rlTexCoord2f(0.0f, 0.0f); - rlVertex2f(0.0f, stereoFbo.texture.height); + rlVertex2f(0.0f, vrConfig.stereoFbo.texture.height); // Top-right corner for texture and quad rlTexCoord2f(1.0f, 0.0f); - rlVertex2f(stereoFbo.texture.width, stereoFbo.texture.height); + rlVertex2f(vrConfig.stereoFbo.texture.width, vrConfig.stereoFbo.texture.height); // Top-left corner for texture and quad rlTexCoord2f(1.0f, 1.0f); - rlVertex2f(stereoFbo.texture.width, 0.0f); + rlVertex2f(vrConfig.stereoFbo.texture.width, 0.0f); rlEnd(); rlPopMatrix(); @@ -3752,61 +3758,71 @@ static Color *GenNextMipmap(Color *srcData, int srcWidth, int srcHeight) #endif // Configure stereo rendering (including distortion shader) with HMD device parameters -static void SetupVrDevice(VrDeviceInfo hmd) +static void SetStereoConfig(VrDeviceInfo hmd) { - // NOTE: fovy value obtained from device parameters (Oculus Rift CV1) - //float fovy = 2.0f*atan((VScreenSize*0.5f)/EyeToScreenDistance)*RAD2DEG; - - //float eyeProjectionShift = ; - //float projectionOffset = (HScreenSize*0.25f - LensSeparationDistance*0.5f)/(float)HScreenSize; - - // Compute aspect ratio and FOV - //float aspect = ((float)hmd.hResolution/2.0f)/(float)hmd.vResolution; + // Compute aspect ratio + //float aspect = ((float)hmd.hResolution*0.5f)/(float)hmd.vResolution; float aspect = (float)screenWidth*0.5f/(float)screenHeight; - - // Fov-y is normally computed with: 2*atan2(hmd.vScreenSize, 2*hmd.eyeToScreenDistance)*RAD2DEG + + // Compute lens parameters + float lensShift = (hmd.hScreenSize*0.25f - hmd.lensSeparationDistance*0.5f)/hmd.hScreenSize; + float leftLensCenter[2] = { 0.25 + lensShift, 0.5f }; + float rightLensCenter[2] = { 0.75 - lensShift, 0.5f }; + float leftScreenCenter[2] = { 0.25f, 0.5f }; + float rightScreenCenter[2] = { 0.75f, 0.5f }; + + // Compute distortion scale parameters + // NOTE: To get lens max radius, lensShift must be normalized to [-1..1] + float lensRadius = fabsf(-1.0f - 4.0f*lensShift); + float lensRadiusSq = lensRadius*lensRadius; + float distortionScale = hmd.distortionK[0] + + hmd.distortionK[1]*lensRadiusSq + + hmd.distortionK[2]*lensRadiusSq*lensRadiusSq + + hmd.distortionK[3]*lensRadiusSq*lensRadiusSq*lensRadiusSq; + + float normScreenWidth = 0.5f; + float normScreenHeight = 1.0f; + float scaleIn[2] = { 2/normScreenWidth, 2/normScreenHeight/aspect }; + float scale[2] = { normScreenWidth*0.5/distortionScale, normScreenHeight*0.5*aspect/distortionScale }; + + // Update distortion shader with lens and distortion-scale parameters + SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "leftLensCenter"), leftLensCenter, 2); + SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "rightLensCenter"), rightLensCenter, 2); + SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "leftScreenCenter"), leftScreenCenter, 2); + SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "rightScreenCenter"), rightScreenCenter, 2); + + SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "scale"), scale, 2); + SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "scaleIn"), scaleIn, 2); + SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "hmdWarpParam"), hmd.distortionK, 4); + SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "chromaAbParam"), hmd.chromaAbCorrection, 4); + + // Fovy is normally computed with: 2*atan2(hmd.vScreenSize, 2*hmd.eyeToScreenDistance)*RAD2DEG // ...but with lens distortion it is increased (see Oculus SDK Documentation) - float radius = -1.0 - (4*(hmd.hScreenSize/4 - hmd.lensSeparationDistance/2)/hmd.hScreenSize); - float distScale = (hmd.distortionK[0] + hmd.distortionK[1]*pow(radius, 2) + hmd.distortionK[2]*pow(radius, 4) + hmd.distortionK[3]*pow(radius, 6)); - //float fovy = 2.0f*atan2(hmd.vScreenSize*distScale, 2*hmd.eyeToScreenDistance)*RAD2DEG; - float fovy = 2.0f*atan((hmd.vScreenSize*0.5f)/hmd.eyeToScreenDistance)*RAD2DEG; + float fovy = 2.0f*atan2(hmd.vScreenSize*0.5f*distortionScale, hmd.eyeToScreenDistance)*RAD2DEG; // Really need distortionScale? // 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); - //float projOffset = 4.0f*(hmd.hScreenSize/4 - hmd.interpupillaryDistance/2)/hmd.hScreenSize; - float projOffset = (hmd.hScreenSize*0.25f - hmd.lensSeparationDistance*0.5f)/hmd.hScreenSize; + vrConfig.eyesProjection[0] = MatrixMultiply(proj, MatrixTranslate(projOffset, 0.0f, 0.0f)); + vrConfig.eyesProjection[1] = MatrixMultiply(proj, MatrixTranslate(-projOffset, 0.0f, 0.0f)); + + // NOTE: Projection matrices must be transposed due to raymath convention + MatrixTranspose(&vrConfig.eyesProjection[0]); + MatrixTranspose(&vrConfig.eyesProjection[1]); - //Matrix projLeft = MatrixMultiply(MatrixTranslate(projOffset, 0.0, 0.0), proj); - //matrix projRight = MatrixMultiply(MatrixTranslate(-projOffset, 0.0, 0.0)), proj); - // Compute camera transformation matrices - //Matrix viewTransformLeft = MatrixTranslate(-hmd.interpupillaryDistance/2, 0.0, 0.0 ); - //Matrix viewTransformRight = MatrixTranslate(hmd.interpupillaryDistance/2, 0.0, 0.0 ); - - // Compute eyes Viewports - // Rectangle viewportLeft = { 0, 0, hmd.hResolution/2, hmd.vResolution }; - // Rectangle viewportRight = { hmd.hResolution/2, 0, hmd.hResolution/2, hmd.vResolution }; - - // Distortion shader parameters - float lensShift = 4*(hmd.hScreenSize/4 - hmd.lensSeparationDistance/2)/hmd.hScreenSize; - float leftLensCenter[2] = { lensShift, 0.0f }; // REVIEW!!! - float rightLensCenter[2] = { -lensShift, 0.0f }; // REVIEW!!! - float leftScreenCenter[2] = { 0.25f, 0.5f }; - float rightScreenCenter[2] = { 0.75f, 0.5f }; + // 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); - float scaleIn[2] = { 1.0f, 1.0f/aspect }; // REVIEW!!! - float scale[2] = { 1.0f/distScale, 1.0f*aspect/distScale }; // REVIEW!!! - - // Distortion shader parameters update - //SetShaderValue(distortionShader, GetShaderLocation(distortionShader, "leftLensCenter"), leftLensCenter, 2); - //SetShaderValue(distortionShader, GetShaderLocation(distortionShader, "rightLensCenter"), rightLensCenter, 2); - SetShaderValue(distortionShader, GetShaderLocation(distortionShader, "leftScreenCenter"), leftScreenCenter, 2); - SetShaderValue(distortionShader, GetShaderLocation(distortionShader, "rightScreenCenter"), rightScreenCenter, 2); + // Compute eyes Viewports + //vrConfig.eyesViewport[0] = (Rectangle){ 0, 0, hmd.hResolution/2, hmd.vResolution }; + //vrConfig.eyesViewport[1] = (Rectangle){ hmd.hResolution/2, 0, hmd.hResolution/2, hmd.vResolution }; - //SetShaderValue(distortionShader, GetShaderLocation(distortionShader, "scale"), scale, 2); - //SetShaderValue(distortionShader, GetShaderLocation(distortionShader, "scaleIn"), scaleIn, 2); - SetShaderValue(distortionShader, GetShaderLocation(distortionShader, "hmdWarpParam"), hmd.distortionK, 4); - SetShaderValue(distortionShader, GetShaderLocation(distortionShader, "chromaAbParam"), hmd.chromaAbCorrection, 4); + //https://forums.oculus.com/vip/discussion/3413/calculating-the-distortion-shader-parameters + //https://vrwiki.wikispaces.com/Theory+%26+practice } // Set internal projection and modelview matrix depending on eyes tracking data @@ -3844,59 +3860,10 @@ static void SetStereoView(int eye, Matrix matProjection, Matrix matModelView) // Setup viewport and projection/modelview matrices using tracking data rlViewport(eye*screenWidth/2, 0, screenWidth/2, screenHeight); - float HScreenSize = 0.14976f; - float VScreenSize = 0.09356f; // HScreenSize/(1280.0f/800.0f) (DK2) - float VScreenCenter = 0.04675f; // VScreenSize/2 - float EyeToScreenDistance = 0.041f; - float LensSeparationDistance = 0.0635f; // DK2 - float InterpupillaryDistance = 0.064f; // IPD - - // NOTE: fovy value obtained from device parameters (Oculus Rift CV1) - float halfScreenDistance = VScreenSize/2.0f; - float fovy = 2.0f*atan(halfScreenDistance/EyeToScreenDistance)*RAD2DEG; - - float viewCenter = (float)HScreenSize*0.25f; - float eyeProjectionShift = viewCenter - LensSeparationDistance*0.5f; - float projectionCenterOffset = eyeProjectionShift/(float)HScreenSize; //4.0f*eyeProjectionShift/(float)HScreenSize; -/* - static float scale[2] = { 0.25, 0.45 }; - - if (IsKeyDown(KEY_RIGHT)) scale[0] += 0.01; - else if (IsKeyDown(KEY_LEFT)) scale[0] -= 0.01; - else if (IsKeyDown(KEY_UP)) scale[1] += 0.01; - else if (IsKeyDown(KEY_DOWN)) scale[1] -= 0.01; - - SetShaderValue(distortionShader, GetShaderLocation(distortionShader, "Scale"), scale, 2); - - if (IsKeyDown(KEY_N)) IPD += 0.02; - else if (IsKeyDown(KEY_M)) IPD -= 0.02; -*/ - // The matrixes for offsetting the projection and view for each eye, to achieve stereo effect - Vector3 projectionOffset = { -projectionCenterOffset, 0.0f, 0.0f }; - - // 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. - Vector3 viewOffset = { -InterpupillaryDistance/2.0f, 0.075f, 0.045f }; - - // Negate the left eye versions - if (eye == 0) - { - projectionOffset.x *= -1.0f; - viewOffset.x *= -1.0f; - } - - // Adjust the view and projection matrixes - // View matrix is translated based on the eye offset - Matrix projCenter = MatrixPerspective(fovy, (double)((float)screenWidth*0.5f)/(double)screenHeight, 0.01, 1000.0); - - Matrix projTranslation = MatrixTranslate(projectionOffset.x, projectionOffset.y, projectionOffset.z); - Matrix viewTranslation = MatrixTranslate(viewOffset.x, viewOffset.y, viewOffset.z); - - eyeProjection = MatrixMultiply(projCenter, projTranslation); // projection - eyeModelView = MatrixMultiply(matModelView, viewTranslation); // modelview + // Apply view offset to modelview matrix + eyeModelView = MatrixMultiply(matModelView, vrConfig.eyesViewOffset[eye]); - MatrixTranspose(&eyeProjection); + eyeProjection = vrConfig.eyesProjection[eye]; } SetMatrixModelview(eyeModelView); -- cgit v1.2.3 From 84d1b19f61865d1bad32c9e159955a30efa57103 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 11 Jul 2016 14:43:58 +0200 Subject: Added custom Oculus CV1 parameters Matching the same stereo rendering result given by Oculus PC SDK for Oculus Rift CV1 is very difficult because hardware has changed a lot and DK2 distortion shader and parameters don't fit on CV1. Some custom parameters have been calculated to simulate kind of CV1 stereo rendering. Further work is required on this point. --- examples/core_oculus_rift.c | 6 ++- src/rlgl.c | 94 +++++++++++++++++++++++++++++---------------- 2 files changed, 65 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/examples/core_oculus_rift.c b/examples/core_oculus_rift.c index b8a60f7a..88e411d4 100644 --- a/examples/core_oculus_rift.c +++ b/examples/core_oculus_rift.c @@ -18,8 +18,10 @@ int main() { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 1280; - int screenHeight = 800; + int screenWidth = 1080; + int screenHeight = 600; + + // NOTE: screenWidth/screenHeight should match VR device aspect ratio InitWindow(screenWidth, screenHeight, "raylib [core] example - oculus rift"); diff --git a/src/rlgl.c b/src/rlgl.c index 65249f5e..25005870 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -2570,38 +2570,62 @@ void InitVrDevice(int hmdDevice) if (!vrDeviceReady) { - TraceLog(WARNING, "VR Device not found: Initializing VR Simulator (Oculus Rift DK2)"); + TraceLog(WARNING, "VR Device not found: Initializing VR Simulator (Oculus Rift CV1)"); + if (hmdDevice == 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.distortionK[0] = 1.0f; // HMD lens distortion constant parameter 0 + hmd.distortionK[1] = 0.22f; // HMD lens distortion constant parameter 1 + hmd.distortionK[2] = 0.24f; // HMD lens distortion constant parameter 2 + hmd.distortionK[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 + } + else if ((hmdDevice == HMD_DEFAULT_DEVICE) || (hmdDevice == 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.0669; // 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.distortionK[0] = 1.0f; // HMD lens distortion constant parameter 0 + hmd.distortionK[1] = 0.22f; // HMD lens distortion constant parameter 1 + hmd.distortionK[2] = 0.24f; // HMD lens distortion constant parameter 2 + hmd.distortionK[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 + } + // Initialize framebuffer and textures for stereo rendering + // NOTE: screen size should match HMD aspect ratio vrConfig.stereoFbo = rlglLoadRenderTexture(screenWidth, screenHeight); // Load distortion shader (initialized by default with Oculus Rift CV1 parameters) vrConfig.distortionShader.id = LoadShaderProgram(vDistortionShaderStr, fDistortionShaderStr); if (vrConfig.distortionShader.id != 0) LoadDefaultShaderLocations(&vrConfig.distortionShader); - if ((hmdDevice == HMD_DEFAULT_DEVICE) || - (hmdDevice == HMD_OCULUS_RIFT_DK2) || - (hmdDevice == HMD_OCULUS_RIFT_CV1)) - { - // NOTE: 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.04675f; // 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.distortionK[0] = 1.0f; // HMD lens distortion constant parameter 0 - hmd.distortionK[1] = 0.22f; // HMD lens distortion constant parameter 1 - hmd.distortionK[2] = 0.24f; // HMD lens distortion constant parameter 2 - hmd.distortionK[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 - } - SetStereoConfig(hmd); vrSimulator = true; @@ -3761,9 +3785,8 @@ static Color *GenNextMipmap(Color *srcData, int srcWidth, int srcHeight) static void SetStereoConfig(VrDeviceInfo hmd) { // Compute aspect ratio - //float aspect = ((float)hmd.hResolution*0.5f)/(float)hmd.vResolution; - float aspect = (float)screenWidth*0.5f/(float)screenHeight; - + 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.25 + lensShift, 0.5f }; @@ -3779,12 +3802,19 @@ static void SetStereoConfig(VrDeviceInfo hmd) hmd.distortionK[1]*lensRadiusSq + hmd.distortionK[2]*lensRadiusSq*lensRadiusSq + hmd.distortionK[3]*lensRadiusSq*lensRadiusSq*lensRadiusSq; - + + TraceLog(DEBUG, "VR: Distortion Scale: %f", distortionScale); + float normScreenWidth = 0.5f; float normScreenHeight = 1.0f; float scaleIn[2] = { 2/normScreenWidth, 2/normScreenHeight/aspect }; float scale[2] = { normScreenWidth*0.5/distortionScale, normScreenHeight*0.5*aspect/distortionScale }; + TraceLog(DEBUG, "VR: Distortion Shader: LeftLensCenter = { %f, %f }", leftLensCenter[0], leftLensCenter[1]); + TraceLog(DEBUG, "VR: Distortion Shader: RightLensCenter = { %f, %f }", rightLensCenter[0], rightLensCenter[1]); + TraceLog(DEBUG, "VR: Distortion Shader: Scale = { %f, %f }", scale[0], scale[1]); + TraceLog(DEBUG, "VR: Distortion Shader: ScaleIn = { %f, %f }", scaleIn[0], scaleIn[1]); + // Update distortion shader with lens and distortion-scale parameters SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "leftLensCenter"), leftLensCenter, 2); SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "rightLensCenter"), rightLensCenter, 2); @@ -3798,8 +3828,9 @@ static void SetStereoConfig(VrDeviceInfo hmd) // Fovy is normally computed with: 2*atan2(hmd.vScreenSize, 2*hmd.eyeToScreenDistance)*RAD2DEG // ...but with lens distortion it is increased (see Oculus SDK Documentation) - float fovy = 2.0f*atan2(hmd.vScreenSize*0.5f*distortionScale, hmd.eyeToScreenDistance)*RAD2DEG; // Really need distortionScale? - + //float fovy = 2.0f*atan2(hmd.vScreenSize*0.5f*distortionScale, hmd.eyeToScreenDistance)*RAD2DEG; // Really need distortionScale? + float fovy = 2.0f*atan2(hmd.vScreenSize*0.5f, hmd.eyeToScreenDistance)*RAD2DEG; + // 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); @@ -3820,9 +3851,6 @@ static void SetStereoConfig(VrDeviceInfo hmd) // Compute eyes Viewports //vrConfig.eyesViewport[0] = (Rectangle){ 0, 0, hmd.hResolution/2, hmd.vResolution }; //vrConfig.eyesViewport[1] = (Rectangle){ hmd.hResolution/2, 0, hmd.hResolution/2, hmd.vResolution }; - - //https://forums.oculus.com/vip/discussion/3413/calculating-the-distortion-shader-parameters - //https://vrwiki.wikispaces.com/Theory+%26+practice } // Set internal projection and modelview matrix depending on eyes tracking data -- cgit v1.2.3 From 56ec22f5c9291427efd59af37af4e78fbf80190c Mon Sep 17 00:00:00 2001 From: raysan5 Date: Mon, 11 Jul 2016 17:34:12 +0200 Subject: Corrected some issues on OpenGL 1.1 Corrected lighting system crash and VR variables not found... --- src/rlgl.c | 270 ++++++++++++++++++++++++++++++++----------------------------- 1 file changed, 141 insertions(+), 129 deletions(-) (limited to 'src') diff --git a/src/rlgl.c b/src/rlgl.c index 25005870..18c0b929 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -284,10 +284,6 @@ static bool texCompETC1Supported = false; // ETC1 texture compression support static bool texCompETC2Supported = false; // ETC2/EAC texture compression support static bool texCompPVRTSupported = false; // PVR texture compression support static bool texCompASTCSupported = false; // ASTC texture compression support - -// Lighting data -static Light lights[MAX_LIGHTS]; // Lights pool -static int lightsCount = 0; // Enabled lights counter #endif #if defined(RLGL_OCULUS_SUPPORT) @@ -331,6 +327,10 @@ static unsigned int whiteTexture; static int screenWidth; // Default framebuffer width static int screenHeight; // Default framebuffer height +// Lighting data +static Light lights[MAX_LIGHTS]; // Lights pool +static int lightsCount = 0; // Enabled lights counter + //---------------------------------------------------------------------------------- // Module specific Functions Declaration //---------------------------------------------------------------------------------- @@ -1880,6 +1880,8 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform) glTexCoordPointer(2, GL_FLOAT, 0, mesh.texcoords); // Pointer to texture coords array if (mesh.normals != NULL) glNormalPointer(GL_FLOAT, 0, mesh.normals); // Pointer to normals array if (mesh.colors != NULL) glColorPointer(4, GL_UNSIGNED_BYTE, 0, mesh.colors); // Pointer to colors array + + // TODO: Support OpenGL 1.1 lighting system rlPushMatrix(); rlMultMatrixf(MatrixToFloat(transform)); @@ -2484,7 +2486,6 @@ Light CreateLight(int type, Vector3 position, Color diffuse) { Light light = NULL; -#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) if (lightsCount < MAX_LIGHTS) { // Allocate dynamic memory @@ -2506,9 +2507,15 @@ Light CreateLight(int type, Vector3 position, Color diffuse) // Increase enabled lights count lightsCount++; } - else TraceLog(WARNING, "Too many lights, only supported up to %i lights", MAX_LIGHTS); -#else - // TODO: Support OpenGL 1.1 lighting system + else + { + TraceLog(WARNING, "Too many lights, only supported up to %i lights", MAX_LIGHTS); + + // NOTE: Returning latest created light to avoid crashes + light = lights[lightsCount]; + } + +#if defined(GRAPHICS_API_OPENGL_11) TraceLog(WARNING, "Lighting currently not supported on OpenGL 1.1"); #endif @@ -2518,7 +2525,6 @@ Light CreateLight(int type, Vector3 position, Color diffuse) // Destroy a light and take it out of the list void DestroyLight(Light light) { -#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) if (light != NULL) { // Free dynamic memory allocation @@ -2539,7 +2545,6 @@ void DestroyLight(Light light) // Decrease enabled physic objects count lightsCount--; } -#endif } // Init VR device (or simulator) @@ -2547,6 +2552,7 @@ void DestroyLight(Light light) // NOTE: It modifies the global variable: VrDeviceInfo hmd void InitVrDevice(int hmdDevice) { +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) switch (hmdDevice) { case HMD_DEFAULT_DEVICE: TraceLog(INFO, "Initializing default VR Device (Oculus Rift CV1)"); @@ -2631,11 +2637,13 @@ void InitVrDevice(int hmdDevice) vrSimulator = true; vrEnabled = true; } +#endif } // Close VR device (or simulator) void CloseVrDevice(void) { +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) #if defined(RLGL_OCULUS_SUPPORT) if (vrDeviceReady) CloseOculusDevice(); else @@ -2644,7 +2652,7 @@ void CloseVrDevice(void) rlDeleteRenderTextures(vrConfig.stereoFbo); // Unload stereo framebuffer and texture UnloadShader(vrConfig.distortionShader); // Unload distortion shader } - +#endif vrDeviceReady = false; } @@ -2675,6 +2683,7 @@ void UpdateVrTracking(void) // Begin Oculus drawing configuration void BeginVrDrawing(void) { +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) #if defined(RLGL_OCULUS_SUPPORT) if (vrDeviceReady) { @@ -2697,11 +2706,13 @@ void BeginVrDrawing(void) rlClearScreenBuffers(); // Clear current framebuffer(s) vrRendering = true; +#endif } // End Oculus drawing process (and desktop mirror) void EndVrDrawing(void) { +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) #if defined(RLGL_OCULUS_SUPPORT) if (vrDeviceReady) { @@ -2764,6 +2775,7 @@ void EndVrDrawing(void) rlDisableDepthTest(); vrRendering = false; +#endif } //---------------------------------------------------------------------------------- @@ -3652,6 +3664,124 @@ static char *ReadTextFile(const char *fileName) return text; } + +// Configure stereo rendering (including distortion shader) with HMD device parameters +static void SetStereoConfig(VrDeviceInfo hmd) +{ + // 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.25 + lensShift, 0.5f }; + float rightLensCenter[2] = { 0.75 - lensShift, 0.5f }; + float leftScreenCenter[2] = { 0.25f, 0.5f }; + float rightScreenCenter[2] = { 0.75f, 0.5f }; + + // Compute distortion scale parameters + // NOTE: To get lens max radius, lensShift must be normalized to [-1..1] + float lensRadius = fabsf(-1.0f - 4.0f*lensShift); + float lensRadiusSq = lensRadius*lensRadius; + float distortionScale = hmd.distortionK[0] + + hmd.distortionK[1]*lensRadiusSq + + hmd.distortionK[2]*lensRadiusSq*lensRadiusSq + + hmd.distortionK[3]*lensRadiusSq*lensRadiusSq*lensRadiusSq; + + TraceLog(DEBUG, "VR: Distortion Scale: %f", distortionScale); + + float normScreenWidth = 0.5f; + float normScreenHeight = 1.0f; + float scaleIn[2] = { 2/normScreenWidth, 2/normScreenHeight/aspect }; + float scale[2] = { normScreenWidth*0.5/distortionScale, normScreenHeight*0.5*aspect/distortionScale }; + + TraceLog(DEBUG, "VR: Distortion Shader: LeftLensCenter = { %f, %f }", leftLensCenter[0], leftLensCenter[1]); + TraceLog(DEBUG, "VR: Distortion Shader: RightLensCenter = { %f, %f }", rightLensCenter[0], rightLensCenter[1]); + TraceLog(DEBUG, "VR: Distortion Shader: Scale = { %f, %f }", scale[0], scale[1]); + TraceLog(DEBUG, "VR: Distortion Shader: ScaleIn = { %f, %f }", scaleIn[0], scaleIn[1]); + + // Update distortion shader with lens and distortion-scale parameters + SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "leftLensCenter"), leftLensCenter, 2); + SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "rightLensCenter"), rightLensCenter, 2); + SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "leftScreenCenter"), leftScreenCenter, 2); + SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "rightScreenCenter"), rightScreenCenter, 2); + + SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "scale"), scale, 2); + SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "scaleIn"), scaleIn, 2); + SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "hmdWarpParam"), hmd.distortionK, 4); + SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "chromaAbParam"), hmd.chromaAbCorrection, 4); + + // Fovy is normally computed with: 2*atan2(hmd.vScreenSize, 2*hmd.eyeToScreenDistance)*RAD2DEG + // ...but with lens distortion it is increased (see Oculus SDK Documentation) + //float fovy = 2.0f*atan2(hmd.vScreenSize*0.5f*distortionScale, hmd.eyeToScreenDistance)*RAD2DEG; // Really need distortionScale? + float fovy = 2.0f*atan2(hmd.vScreenSize*0.5f, hmd.eyeToScreenDistance)*RAD2DEG; + + // 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)); + + // NOTE: Projection matrices must be transposed due to raymath convention + MatrixTranspose(&vrConfig.eyesProjection[0]); + MatrixTranspose(&vrConfig.eyesProjection[1]); + + // 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.eyesViewport[0] = (Rectangle){ 0, 0, hmd.hResolution/2, hmd.vResolution }; + //vrConfig.eyesViewport[1] = (Rectangle){ hmd.hResolution/2, 0, hmd.hResolution/2, hmd.vResolution }; +} + +// Set internal projection and modelview matrix depending on eyes tracking data +static void SetStereoView(int eye, Matrix matProjection, Matrix matModelView) +{ + if (vrEnabled) + { + Matrix eyeProjection = matProjection; + Matrix eyeModelView = matModelView; + +#if defined(RLGL_OCULUS_SUPPORT) + if (vrDeviceReady) + { + 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, + layer.eyeLayer.RenderPose[eye].Orientation.y, + layer.eyeLayer.RenderPose[eye].Orientation.z, + layer.eyeLayer.RenderPose[eye].Orientation.w }; + QuaternionInvert(&eyeRenderPose); + Matrix eyeOrientation = QuaternionToMatrix(eyeRenderPose); + Matrix eyeTranslation = MatrixTranslate(-layer.eyeLayer.RenderPose[eye].Position.x, + -layer.eyeLayer.RenderPose[eye].Position.y, + -layer.eyeLayer.RenderPose[eye].Position.z); + + Matrix eyeView = MatrixMultiply(eyeTranslation, eyeOrientation); // Matrix containing eye-head movement + eyeModelView = MatrixMultiply(matModelView, eyeView); // Combine internal camera matrix (modelview) wih eye-head movement + + eyeProjection = layer.eyeProjections[eye]; + } + else +#endif + { + // Setup viewport and projection/modelview matrices using tracking data + rlViewport(eye*screenWidth/2, 0, screenWidth/2, screenHeight); + + // Apply view offset to modelview matrix + eyeModelView = MatrixMultiply(matModelView, vrConfig.eyesViewOffset[eye]); + + eyeProjection = vrConfig.eyesProjection[eye]; + } + + SetMatrixModelview(eyeModelView); + SetMatrixProjection(eyeProjection); + } +} #endif //defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) #if defined(GRAPHICS_API_OPENGL_11) @@ -3781,124 +3911,6 @@ static Color *GenNextMipmap(Color *srcData, int srcWidth, int srcHeight) } #endif -// Configure stereo rendering (including distortion shader) with HMD device parameters -static void SetStereoConfig(VrDeviceInfo hmd) -{ - // 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.25 + lensShift, 0.5f }; - float rightLensCenter[2] = { 0.75 - lensShift, 0.5f }; - float leftScreenCenter[2] = { 0.25f, 0.5f }; - float rightScreenCenter[2] = { 0.75f, 0.5f }; - - // Compute distortion scale parameters - // NOTE: To get lens max radius, lensShift must be normalized to [-1..1] - float lensRadius = fabsf(-1.0f - 4.0f*lensShift); - float lensRadiusSq = lensRadius*lensRadius; - float distortionScale = hmd.distortionK[0] + - hmd.distortionK[1]*lensRadiusSq + - hmd.distortionK[2]*lensRadiusSq*lensRadiusSq + - hmd.distortionK[3]*lensRadiusSq*lensRadiusSq*lensRadiusSq; - - TraceLog(DEBUG, "VR: Distortion Scale: %f", distortionScale); - - float normScreenWidth = 0.5f; - float normScreenHeight = 1.0f; - float scaleIn[2] = { 2/normScreenWidth, 2/normScreenHeight/aspect }; - float scale[2] = { normScreenWidth*0.5/distortionScale, normScreenHeight*0.5*aspect/distortionScale }; - - TraceLog(DEBUG, "VR: Distortion Shader: LeftLensCenter = { %f, %f }", leftLensCenter[0], leftLensCenter[1]); - TraceLog(DEBUG, "VR: Distortion Shader: RightLensCenter = { %f, %f }", rightLensCenter[0], rightLensCenter[1]); - TraceLog(DEBUG, "VR: Distortion Shader: Scale = { %f, %f }", scale[0], scale[1]); - TraceLog(DEBUG, "VR: Distortion Shader: ScaleIn = { %f, %f }", scaleIn[0], scaleIn[1]); - - // Update distortion shader with lens and distortion-scale parameters - SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "leftLensCenter"), leftLensCenter, 2); - SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "rightLensCenter"), rightLensCenter, 2); - SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "leftScreenCenter"), leftScreenCenter, 2); - SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "rightScreenCenter"), rightScreenCenter, 2); - - SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "scale"), scale, 2); - SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "scaleIn"), scaleIn, 2); - SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "hmdWarpParam"), hmd.distortionK, 4); - SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "chromaAbParam"), hmd.chromaAbCorrection, 4); - - // Fovy is normally computed with: 2*atan2(hmd.vScreenSize, 2*hmd.eyeToScreenDistance)*RAD2DEG - // ...but with lens distortion it is increased (see Oculus SDK Documentation) - //float fovy = 2.0f*atan2(hmd.vScreenSize*0.5f*distortionScale, hmd.eyeToScreenDistance)*RAD2DEG; // Really need distortionScale? - float fovy = 2.0f*atan2(hmd.vScreenSize*0.5f, hmd.eyeToScreenDistance)*RAD2DEG; - - // 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)); - - // NOTE: Projection matrices must be transposed due to raymath convention - MatrixTranspose(&vrConfig.eyesProjection[0]); - MatrixTranspose(&vrConfig.eyesProjection[1]); - - // 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.eyesViewport[0] = (Rectangle){ 0, 0, hmd.hResolution/2, hmd.vResolution }; - //vrConfig.eyesViewport[1] = (Rectangle){ hmd.hResolution/2, 0, hmd.hResolution/2, hmd.vResolution }; -} - -// Set internal projection and modelview matrix depending on eyes tracking data -static void SetStereoView(int eye, Matrix matProjection, Matrix matModelView) -{ - if (vrEnabled) - { - Matrix eyeProjection = matProjection; - Matrix eyeModelView = matModelView; - -#if defined(RLGL_OCULUS_SUPPORT) - if (vrDeviceReady) - { - 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, - layer.eyeLayer.RenderPose[eye].Orientation.y, - layer.eyeLayer.RenderPose[eye].Orientation.z, - layer.eyeLayer.RenderPose[eye].Orientation.w }; - QuaternionInvert(&eyeRenderPose); - Matrix eyeOrientation = QuaternionToMatrix(eyeRenderPose); - Matrix eyeTranslation = MatrixTranslate(-layer.eyeLayer.RenderPose[eye].Position.x, - -layer.eyeLayer.RenderPose[eye].Position.y, - -layer.eyeLayer.RenderPose[eye].Position.z); - - Matrix eyeView = MatrixMultiply(eyeTranslation, eyeOrientation); // Matrix containing eye-head movement - eyeModelView = MatrixMultiply(matModelView, eyeView); // Combine internal camera matrix (modelview) wih eye-head movement - - eyeProjection = layer.eyeProjections[eye]; - } - else -#endif - { - // Setup viewport and projection/modelview matrices using tracking data - rlViewport(eye*screenWidth/2, 0, screenWidth/2, screenHeight); - - // Apply view offset to modelview matrix - eyeModelView = MatrixMultiply(matModelView, vrConfig.eyesViewOffset[eye]); - - eyeProjection = vrConfig.eyesProjection[eye]; - } - - SetMatrixModelview(eyeModelView); - SetMatrixProjection(eyeProjection); - } -} - #if defined(RLGL_OCULUS_SUPPORT) // Initialize Oculus device static bool InitOculusDevice(void) -- cgit v1.2.3 From 22672bc738ee0923fd43c431cb41d0bf4d8dd96c Mon Sep 17 00:00:00 2001 From: raysan5 Date: Mon, 11 Jul 2016 19:01:13 +0200 Subject: Added Oculus functions declaration and comments --- src/rlgl.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/rlgl.c b/src/rlgl.c index 18c0b929..b50e1a45 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -361,6 +361,12 @@ static char *ReadTextFile(const char *fileName); #endif #if defined(RLGL_OCULUS_SUPPORT) +static bool InitOculusDevice(void); // Initialize Oculus device (returns true if success) +static void CloseOculusDevice(void); // Close Oculus device +static void UpdateOculusTracking(void); // Update Oculus head position-orientation tracking +static void BeginOculusDrawing(void); // Setup Oculus buffers for drawing +static void EndOculusDrawing(void); // Finish Oculus drawing and blit framebuffer to mirror + 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 @@ -3912,7 +3918,7 @@ static Color *GenNextMipmap(Color *srcData, int srcWidth, int srcHeight) #endif #if defined(RLGL_OCULUS_SUPPORT) -// Initialize Oculus device +// Initialize Oculus device (returns true if success) static bool InitOculusDevice(void) { bool oculusReady = false; @@ -3959,6 +3965,7 @@ static bool InitOculusDevice(void) return oculusReady; } +// Close Oculus device (and unload buffers) static void CloseOculusDevice(void) { UnloadOculusMirror(session, mirror); // Unload Oculus mirror buffer @@ -3968,6 +3975,7 @@ static void CloseOculusDevice(void) ovr_Shutdown(); // Close Oculus device connection } +// Update Oculus head position-orientation tracking static void UpdateOculusTracking(void) { frameIndex++; @@ -3990,6 +3998,7 @@ static void UpdateOculusTracking(void) //if (sessionStatus.IsVisible) // the game or experience has VR focus and is visible in the HMD. } +// Setup Oculus buffers for drawing static void BeginOculusDrawing(void) { GLuint currentTexId; @@ -4003,6 +4012,7 @@ static void BeginOculusDrawing(void) //glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, buffer.depthId, 0); // Already binded } +// Finish Oculus drawing and blit framebuffer to mirror static void EndOculusDrawing(void) { // Unbind current framebuffer (Oculus buffer) -- cgit v1.2.3 From 31b64d46898e536a963b1c891cb7e0d9cd3881f7 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Tue, 12 Jul 2016 17:10:31 +0200 Subject: Updated for GLSL 100 --- src/shader_distortion.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'src') diff --git a/src/shader_distortion.h b/src/shader_distortion.h index e4ce5d6c..75653e12 100644 --- a/src/shader_distortion.h +++ b/src/shader_distortion.h @@ -46,6 +46,16 @@ static const char fDistortionShaderStr[] = "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" @@ -54,6 +64,7 @@ static const char fDistortionShaderStr[] = "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" @@ -65,7 +76,11 @@ static const char fDistortionShaderStr[] = " 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" -- cgit v1.2.3 From 9d6d68f00a154796682589458bce944f7b58dc14 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Tue, 12 Jul 2016 18:44:45 +0200 Subject: Support VR mode disable on Oculus device --- src/rlgl.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/rlgl.c b/src/rlgl.c index b50e1a45..1d5d6157 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -2671,7 +2671,17 @@ bool IsVrDeviceReady(void) // Enable/Disable VR experience (device or simulator) void ToggleVrMode(void) { - vrEnabled = !vrEnabled; + if (vrDeviceReady || vrSimulator) vrEnabled = !vrEnabled; + else vrEnabled = false; + + if (!vrEnabled) + { + // Reset viewport and default projection-modelview matrices + rlViewport(0, 0, GetScreenWidth(), GetScreenHeight()); + projection = MatrixOrtho(0, GetScreenWidth(), GetScreenHeight(), 0, 0.0f, 1.0f); + MatrixTranspose(&projection); + modelview = MatrixIdentity(); + } } // Update VR tracking (position and orientation) @@ -3745,12 +3755,12 @@ static void SetStereoConfig(VrDeviceInfo hmd) // Set internal projection and modelview matrix depending on eyes tracking data static void SetStereoView(int eye, Matrix matProjection, Matrix matModelView) -{ +{ if (vrEnabled) { Matrix eyeProjection = matProjection; Matrix eyeModelView = matModelView; - + #if defined(RLGL_OCULUS_SUPPORT) if (vrDeviceReady) { -- cgit v1.2.3 From 11172118d10e193afade9816e145f0d57bcd4bb8 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Wed, 13 Jul 2016 20:05:00 +0200 Subject: Review comments --- src/core.c | 11 +++++------ src/rlgl.c | 15 ++++++++------- 2 files changed, 13 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/core.c b/src/core.c index 107fc0a0..a3253d79 100644 --- a/src/core.c +++ b/src/core.c @@ -181,11 +181,10 @@ static uint64_t baseTime; // Base time measure for hi-res timer static bool windowShouldClose = false; // Flag to set window for closing #endif -static unsigned int displayWidth, displayHeight; // Display width and height (monitor, device-screen, LCD, ...) +// Display size-related data +static unsigned int displayWidth, displayHeight; // Display width and height (monitor, device-screen, LCD, ...) static int screenWidth, screenHeight; // Screen width and height (used render area) -static int renderWidth, renderHeight; // Framebuffer width and height (render area) - // NOTE: Framebuffer could include black bars - +static int renderWidth, renderHeight; // Framebuffer width and height (render area, including black bars if required) static int renderOffsetX = 0; // Offset X from render area (must be divided by 2) static int renderOffsetY = 0; // Offset Y from render area (must be divided by 2) static bool fullscreen = false; // Fullscreen mode (useful only for PLATFORM_DESKTOP) @@ -214,7 +213,7 @@ static bool cursorHidden; // Track if cursor is hidden #endif static Vector2 mousePosition; // Mouse position on screen -static Vector2 touchPosition[MAX_TOUCH_POINTS]; // Touch position on screen +static Vector2 touchPosition[MAX_TOUCH_POINTS]; // Touch position on screen #if defined(PLATFORM_DESKTOP) static char **dropFilesPath; // Store dropped files paths as strings @@ -226,7 +225,7 @@ static double updateTime, drawTime; // Time measures for update and draw static double frameTime; // Time measure for one frame static double targetTime = 0.0; // Desired time for one frame, if 0 not applied -static char configFlags = 0; // Configuration flags (bit based) +static char configFlags = 0; // Configuration flags (bit based) static bool showLogo = false; // Track if showing logo at init is enabled //---------------------------------------------------------------------------------- diff --git a/src/rlgl.c b/src/rlgl.c index 1d5d6157..586c15e3 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -257,9 +257,9 @@ static DrawMode currentDrawMode; static float currentDepth = -1.0f; -static DynamicBuffer lines; -static DynamicBuffer triangles; -static DynamicBuffer quads; +static DynamicBuffer lines; // Default dynamic buffer for lines data +static DynamicBuffer triangles; // Default dynamic buffer for triangles data +static DynamicBuffer quads; // Default dynamic buffer for quads data (used to draw textures) // Default buffers draw calls static DrawCall *draws; @@ -271,9 +271,10 @@ static int tempBufferCount = 0; static bool useTempBuffer = false; // Shader Programs -static Shader defaultShader; -static Shader standardShader; // Lazy initialization when GetStandardShader() -static Shader currentShader; // By default, defaultShader +static Shader defaultShader; // Basic shader, support vertex color and diffuse texture +static Shader standardShader; // Shader with support for lighting and materials + // NOTE: Lazy initialization when GetStandardShader() +static Shader currentShader; // Shader to be used on rendering (by default, defaultShader) static bool standardShaderLoaded = false; // Flag to track if standard shader has been loaded // Flags for supported extensions @@ -357,7 +358,7 @@ static void SetStereoView(int eye, Matrix matProjection, Matrix matModelView); static void SetShaderLights(Shader shader); // Sets shader uniform values for lights array -static char *ReadTextFile(const char *fileName); +static char *ReadTextFile(const char *fileName); // Read chars array from text file #endif #if defined(RLGL_OCULUS_SUPPORT) -- cgit v1.2.3 From 338bb3fd9c0d26f181072f68552432702b8ce6dd Mon Sep 17 00:00:00 2001 From: raysan5 Date: Wed, 13 Jul 2016 20:05:53 +0200 Subject: Review variables to raylib naming conventions Some review work still required... --- src/audio.c | 302 ++++++++++++++++++++++++++++++------------------------------ 1 file changed, 151 insertions(+), 151 deletions(-) (limited to 'src') diff --git a/src/audio.c b/src/audio.c index a76a453f..2941b9fb 100644 --- a/src/audio.c +++ b/src/audio.c @@ -69,7 +69,7 @@ // Defines and Macros //---------------------------------------------------------------------------------- #define MAX_STREAM_BUFFERS 2 // Number of buffers for each alSource -#define MAX_MIX_CHANNELS 4 // Number of open AL sources +#define MAX_MIX_CHANNELS 4 // Number of OpenAL sources #define MAX_MUSIC_STREAMS 2 // Number of simultanious music sources #if defined(PLATFORM_RPI) || defined(PLATFORM_ANDROID) @@ -86,10 +86,10 @@ // Types and Structures Definition //---------------------------------------------------------------------------------- -// Used to create custom audio streams that are not bound to a specific file. There can be -// no more than 4 concurrent mixchannels in use. This is due to each active mixc being tied to -// a dedicated mix channel. -typedef struct MixChannel_t { +// Used to create custom audio streams that are not bound to a specific file. +// There can be no more than 4 concurrent mixchannels in use. +// This is due to each active mixc being tied to a dedicated mix channel. +typedef struct MixChannel { unsigned short sampleRate; // default is 48000 unsigned char channels; // 1=mono,2=stereo unsigned char mixChannel; // 0-3 or mixA-mixD, each mix channel can receive up to one dedicated audio stream @@ -99,40 +99,40 @@ typedef struct MixChannel_t { ALenum alFormat; // OpenAL format specifier ALuint alSource; // OpenAL source ALuint alBuffer[MAX_STREAM_BUFFERS]; // OpenAL sample buffer -} MixChannel_t; +} MixChannel; // Music type (file streaming from memory) // NOTE: Anything longer than ~10 seconds should be streamed into a mix channel... typedef struct Music { stb_vorbis *stream; - jar_xm_context_t *xmctx; // XM chiptune context - jar_mod_context_t modctx; // MOD chiptune context - MixChannel_t *mixc; // mix channel + jar_xm_context_t *xmctx; // XM chiptune context + jar_mod_context_t modctx; // MOD chiptune context + MixChannel *mixc; // Mix channel unsigned int totalSamplesLeft; float totalLengthSeconds; bool loop; - bool chipTune; // chiptune is loaded? + bool chipTune; // chiptune is loaded? bool enabled; } Music; // Audio errors registered typedef enum { - ERROR_RAW_CONTEXT_CREATION = 1, - ERROR_XM_CONTEXT_CREATION = 2, - ERROR_MOD_CONTEXT_CREATION = 4, - ERROR_MIX_CHANNEL_CREATION = 8, - ERROR_MUSIC_CHANNEL_CREATION = 16, - ERROR_LOADING_XM = 32, - ERROR_LOADING_MOD = 64, - ERROR_LOADING_WAV = 128, - ERROR_LOADING_OGG = 256, - ERROR_OUT_OF_MIX_CHANNELS = 512, - ERROR_EXTENSION_NOT_RECOGNIZED = 1024, - ERROR_UNABLE_TO_OPEN_RRES_FILE = 2048, - ERROR_INVALID_RRES_FILE = 4096, - ERROR_INVALID_RRES_RESOURCE = 8192, - ERROR_UNINITIALIZED_CHANNELS = 16384 + ERROR_RAW_CONTEXT_CREATION = 1, + ERROR_XM_CONTEXT_CREATION = 2, + ERROR_MOD_CONTEXT_CREATION = 4, + ERROR_MIX_CHANNEL_CREATION = 8, + ERROR_MUSIC_CHANNEL_CREATION = 16, + ERROR_LOADING_XM = 32, + ERROR_LOADING_MOD = 64, + ERROR_LOADING_WAV = 128, + ERROR_LOADING_OGG = 256, + ERROR_OUT_OF_MIX_CHANNELS = 512, + ERROR_EXTENSION_NOT_RECOGNIZED = 1024, + ERROR_UNABLE_TO_OPEN_RRES_FILE = 2048, + ERROR_INVALID_RRES_FILE = 4096, + ERROR_INVALID_RRES_RESOURCE = 8192, + ERROR_UNINITIALIZED_CHANNELS = 16384 } AudioError; #if defined(AUDIO_STANDALONE) @@ -142,10 +142,10 @@ typedef enum { INFO = 0, ERROR, WARNING, DEBUG, OTHER } TraceLogType; //---------------------------------------------------------------------------------- // Global Variables Definition //---------------------------------------------------------------------------------- -static Music musicChannels_g[MAX_MUSIC_STREAMS]; // Current music loaded, up to two can play at the same time -static MixChannel_t *mixChannels_g[MAX_MIX_CHANNELS]; // What mix channels are currently active +static Music musicStreams[MAX_MUSIC_STREAMS]; // Current music loaded, up to two can play at the same time +static MixChannel *mixChannels[MAX_MIX_CHANNELS]; // What mix channels are currently active -static int lastAudioError = 0; // Registers last audio error +static int lastAudioError = 0; // Registers last audio error //---------------------------------------------------------------------------------- // Module specific Functions Declaration @@ -157,10 +157,10 @@ static void UnloadWave(Wave wave); // Unload wave data static bool BufferMusicStream(int index, int numBuffers); // Fill music buffers with data static void EmptyMusicStream(int index); // Empty music buffers -static MixChannel_t *InitMixChannel(unsigned short sampleRate, unsigned char mixChannel, unsigned char channels, bool floatingPoint); // For streaming into mix channels. -static void CloseMixChannel(MixChannel_t *mixc); // Frees mix channel -static int BufferMixChannel(MixChannel_t *mixc, void *data, int numberElements); // Pushes more audio data into mixc mix channel, if NULL is passed it pauses -static int FillAlBufferWithSilence(MixChannel_t *mixc, ALuint buffer); // Fill buffer with zeros, returns number processed +static MixChannel *InitMixChannel(unsigned short sampleRate, unsigned char mixChannel, unsigned char channels, bool floatingPoint); // For streaming into mix channels. +static void CloseMixChannel(MixChannel *mixc); // Frees mix channel +static int BufferMixChannel(MixChannel *mixc, void *data, int numberElements); // Pushes more audio data into mixc mix channel, if NULL is passed it pauses +static int FillAlBufferWithSilence(MixChannel *mixc, ALuint buffer); // Fill buffer with zeros, returns number processed static void ResampleShortToFloat(short *shorts, float *floats, unsigned short len); // Pass two arrays of the same legnth in static void ResampleByteToFloat(char *chars, float *floats, unsigned short len); // Pass two arrays of same length in static int IsMusicStreamReadyForBuffering(int index); // Checks if music buffer is ready to be refilled @@ -206,7 +206,7 @@ void CloseAudioDevice(void) { for (int index=0; index= MAX_MIX_CHANNELS) return NULL; if (!IsAudioDeviceReady()) InitAudioDevice(); - if (!mixChannels_g[mixChannel]) + if (!mixChannels[mixChannel]) { - MixChannel_t *mixc = (MixChannel_t *)malloc(sizeof(MixChannel_t)); + MixChannel *mixc = (MixChannel *)malloc(sizeof(MixChannel)); mixc->sampleRate = sampleRate; mixc->channels = channels; mixc->mixChannel = mixChannel; mixc->floatingPoint = floatingPoint; - mixChannels_g[mixChannel] = mixc; + mixChannels[mixChannel] = mixc; // Setup OpenAL format if (channels == 1) @@ -293,7 +293,7 @@ static MixChannel_t *InitMixChannel(unsigned short sampleRate, unsigned char mix } // Frees buffer in mix channel -static void CloseMixChannel(MixChannel_t *mixc) +static void CloseMixChannel(MixChannel *mixc) { if (mixc) { @@ -314,7 +314,7 @@ static void CloseMixChannel(MixChannel_t *mixc) // Delete source and buffers alDeleteSources(1, &mixc->alSource); alDeleteBuffers(MAX_STREAM_BUFFERS, mixc->alBuffer); - mixChannels_g[mixc->mixChannel] = NULL; + mixChannels[mixc->mixChannel] = NULL; free(mixc); mixc = NULL; } @@ -323,9 +323,9 @@ static void CloseMixChannel(MixChannel_t *mixc) // Pushes more audio data into mixc mix channel, only one buffer per call // Call "BufferMixChannel(mixc, NULL, 0)" if you want to pause the audio. // @Returns number of samples that where processed. -static int BufferMixChannel(MixChannel_t *mixc, void *data, int numberElements) +static int BufferMixChannel(MixChannel *mixc, void *data, int numberElements) { - if (!mixc || (mixChannels_g[mixc->mixChannel] != mixc)) return 0; // When there is two channels there must be an even number of samples + if (!mixc || (mixChannels[mixc->mixChannel] != mixc)) return 0; // When there is two channels there must be an even number of samples if (!data || !numberElements) { @@ -369,7 +369,7 @@ static int BufferMixChannel(MixChannel_t *mixc, void *data, int numberElements) } // fill buffer with zeros, returns number processed -static int FillAlBufferWithSilence(MixChannel_t *mixc, ALuint buffer) +static int FillAlBufferWithSilence(MixChannel *mixc, ALuint buffer) { if (mixc->floatingPoint) { @@ -418,7 +418,7 @@ RawAudioContext InitRawAudioContext(int sampleRate, int channels, bool floatingP int mixIndex; for (mixIndex = 0; mixIndex < MAX_MIX_CHANNELS; mixIndex++) // find empty mix channel slot { - if (mixChannels_g[mixIndex] == NULL) break; + if (mixChannels[mixIndex] == NULL) break; else if (mixIndex == (MAX_MIX_CHANNELS - 1)) return ERROR_OUT_OF_MIX_CHANNELS; // error } @@ -428,7 +428,7 @@ RawAudioContext InitRawAudioContext(int sampleRate, int channels, bool floatingP void CloseRawAudioContext(RawAudioContext ctx) { - if (mixChannels_g[ctx]) CloseMixChannel(mixChannels_g[ctx]); + if (mixChannels[ctx]) CloseMixChannel(mixChannels[ctx]); } // if 0 is returned, the buffers are still full and you need to keep trying with the same data until a + number is returned. @@ -440,7 +440,7 @@ int BufferRawAudioContext(RawAudioContext ctx, void *data, unsigned short number if (ctx >= 0) { - MixChannel_t* mixc = mixChannels_g[ctx]; + MixChannel* mixc = mixChannels[ctx]; numBuffered = BufferMixChannel(mixc, data, numberElements); } @@ -809,20 +809,20 @@ int PlayMusicStream(int index, char *fileName) { int mixIndex; - if (musicChannels_g[index].stream || musicChannels_g[index].xmctx) return ERROR_UNINITIALIZED_CHANNELS; // error + if (musicStreams[index].stream || musicStreams[index].xmctx) return ERROR_UNINITIALIZED_CHANNELS; // error for (mixIndex = 0; mixIndex < MAX_MIX_CHANNELS; mixIndex++) // find empty mix channel slot { - if (mixChannels_g[mixIndex] == NULL) break; + if (mixChannels[mixIndex] == NULL) break; else if (mixIndex == (MAX_MIX_CHANNELS - 1)) return ERROR_OUT_OF_MIX_CHANNELS; // error } if (strcmp(GetExtension(fileName),"ogg") == 0) { // Open audio stream - musicChannels_g[index].stream = stb_vorbis_open_filename(fileName, NULL, NULL); + musicStreams[index].stream = stb_vorbis_open_filename(fileName, NULL, NULL); - if (musicChannels_g[index].stream == NULL) + if (musicStreams[index].stream == NULL) { TraceLog(WARNING, "[%s] OGG audio file could not be opened", fileName); return ERROR_LOADING_OGG; // error @@ -830,53 +830,53 @@ int PlayMusicStream(int index, char *fileName) else { // Get file info - stb_vorbis_info info = stb_vorbis_get_info(musicChannels_g[index].stream); + stb_vorbis_info info = stb_vorbis_get_info(musicStreams[index].stream); TraceLog(INFO, "[%s] Ogg sample rate: %i", fileName, info.sample_rate); TraceLog(INFO, "[%s] Ogg channels: %i", fileName, info.channels); TraceLog(DEBUG, "[%s] Temp memory required: %i", fileName, info.temp_memory_required); - musicChannels_g[index].loop = true; // We loop by default - musicChannels_g[index].enabled = true; + musicStreams[index].loop = true; // We loop by default + musicStreams[index].enabled = true; - musicChannels_g[index].totalSamplesLeft = (unsigned int)stb_vorbis_stream_length_in_samples(musicChannels_g[index].stream) * info.channels; - musicChannels_g[index].totalLengthSeconds = stb_vorbis_stream_length_in_seconds(musicChannels_g[index].stream); + musicStreams[index].totalSamplesLeft = (unsigned int)stb_vorbis_stream_length_in_samples(musicStreams[index].stream) * info.channels; + musicStreams[index].totalLengthSeconds = stb_vorbis_stream_length_in_seconds(musicStreams[index].stream); if (info.channels == 2) { - musicChannels_g[index].mixc = InitMixChannel(info.sample_rate, mixIndex, 2, false); - musicChannels_g[index].mixc->playing = true; + musicStreams[index].mixc = InitMixChannel(info.sample_rate, mixIndex, 2, false); + musicStreams[index].mixc->playing = true; } else { - musicChannels_g[index].mixc = InitMixChannel(info.sample_rate, mixIndex, 1, false); - musicChannels_g[index].mixc->playing = true; + musicStreams[index].mixc = InitMixChannel(info.sample_rate, mixIndex, 1, false); + musicStreams[index].mixc->playing = true; } - if (!musicChannels_g[index].mixc) return ERROR_LOADING_OGG; // error + if (!musicStreams[index].mixc) return ERROR_LOADING_OGG; // error } } else if (strcmp(GetExtension(fileName),"xm") == 0) { // only stereo is supported for xm - if (!jar_xm_create_context_from_file(&musicChannels_g[index].xmctx, 48000, fileName)) + if (!jar_xm_create_context_from_file(&musicStreams[index].xmctx, 48000, fileName)) { - musicChannels_g[index].chipTune = true; - musicChannels_g[index].loop = true; - jar_xm_set_max_loop_count(musicChannels_g[index].xmctx, 0); // infinite number of loops - musicChannels_g[index].totalSamplesLeft = (unsigned int)jar_xm_get_remaining_samples(musicChannels_g[index].xmctx); - musicChannels_g[index].totalLengthSeconds = ((float)musicChannels_g[index].totalSamplesLeft) / 48000.f; - musicChannels_g[index].enabled = true; + musicStreams[index].chipTune = true; + musicStreams[index].loop = true; + jar_xm_set_max_loop_count(musicStreams[index].xmctx, 0); // infinite number of loops + musicStreams[index].totalSamplesLeft = (unsigned int)jar_xm_get_remaining_samples(musicStreams[index].xmctx); + musicStreams[index].totalLengthSeconds = ((float)musicStreams[index].totalSamplesLeft) / 48000.f; + musicStreams[index].enabled = true; - TraceLog(INFO, "[%s] XM number of samples: %i", fileName, musicChannels_g[index].totalSamplesLeft); - TraceLog(INFO, "[%s] XM track length: %11.6f sec", fileName, musicChannels_g[index].totalLengthSeconds); + TraceLog(INFO, "[%s] XM number of samples: %i", fileName, musicStreams[index].totalSamplesLeft); + TraceLog(INFO, "[%s] XM track length: %11.6f sec", fileName, musicStreams[index].totalLengthSeconds); - musicChannels_g[index].mixc = InitMixChannel(48000, mixIndex, 2, true); + musicStreams[index].mixc = InitMixChannel(48000, mixIndex, 2, true); - if (!musicChannels_g[index].mixc) return ERROR_XM_CONTEXT_CREATION; // error + if (!musicStreams[index].mixc) return ERROR_XM_CONTEXT_CREATION; // error - musicChannels_g[index].mixc->playing = true; + musicStreams[index].mixc->playing = true; } else { @@ -886,24 +886,24 @@ int PlayMusicStream(int index, char *fileName) } else if (strcmp(GetExtension(fileName),"mod") == 0) { - jar_mod_init(&musicChannels_g[index].modctx); + jar_mod_init(&musicStreams[index].modctx); - if (jar_mod_load_file(&musicChannels_g[index].modctx, fileName)) + if (jar_mod_load_file(&musicStreams[index].modctx, fileName)) { - musicChannels_g[index].chipTune = true; - musicChannels_g[index].loop = true; - musicChannels_g[index].totalSamplesLeft = (unsigned int)jar_mod_max_samples(&musicChannels_g[index].modctx); - musicChannels_g[index].totalLengthSeconds = ((float)musicChannels_g[index].totalSamplesLeft) / 48000.f; - musicChannels_g[index].enabled = true; + musicStreams[index].chipTune = true; + musicStreams[index].loop = true; + musicStreams[index].totalSamplesLeft = (unsigned int)jar_mod_max_samples(&musicStreams[index].modctx); + musicStreams[index].totalLengthSeconds = ((float)musicStreams[index].totalSamplesLeft) / 48000.f; + musicStreams[index].enabled = true; - TraceLog(INFO, "[%s] MOD number of samples: %i", fileName, musicChannels_g[index].totalSamplesLeft); - TraceLog(INFO, "[%s] MOD track length: %11.6f sec", fileName, musicChannels_g[index].totalLengthSeconds); + TraceLog(INFO, "[%s] MOD number of samples: %i", fileName, musicStreams[index].totalSamplesLeft); + TraceLog(INFO, "[%s] MOD track length: %11.6f sec", fileName, musicStreams[index].totalLengthSeconds); - musicChannels_g[index].mixc = InitMixChannel(48000, mixIndex, 2, false); + musicStreams[index].mixc = InitMixChannel(48000, mixIndex, 2, false); - if (!musicChannels_g[index].mixc) return ERROR_MOD_CONTEXT_CREATION; // error + if (!musicStreams[index].mixc) return ERROR_MOD_CONTEXT_CREATION; // error - musicChannels_g[index].mixc->playing = true; + musicStreams[index].mixc->playing = true; } else { @@ -920,26 +920,26 @@ int PlayMusicStream(int index, char *fileName) return 0; // normal return } -// Stop music playing for individual music index of musicChannels_g array (close stream) +// Stop music playing for individual music index of musicStreams array (close stream) void StopMusicStream(int index) { - if (index < MAX_MUSIC_STREAMS && musicChannels_g[index].mixc) + if (index < MAX_MUSIC_STREAMS && musicStreams[index].mixc) { - CloseMixChannel(musicChannels_g[index].mixc); + CloseMixChannel(musicStreams[index].mixc); - if (musicChannels_g[index].xmctx) - jar_xm_free_context(musicChannels_g[index].xmctx); - else if (musicChannels_g[index].modctx.mod_loaded) - jar_mod_unload(&musicChannels_g[index].modctx); + if (musicStreams[index].xmctx) + jar_xm_free_context(musicStreams[index].xmctx); + else if (musicStreams[index].modctx.mod_loaded) + jar_mod_unload(&musicStreams[index].modctx); else - stb_vorbis_close(musicChannels_g[index].stream); + stb_vorbis_close(musicStreams[index].stream); - musicChannels_g[index].enabled = false; + musicStreams[index].enabled = false; - if (musicChannels_g[index].stream || musicChannels_g[index].xmctx) + if (musicStreams[index].stream || musicStreams[index].xmctx) { - musicChannels_g[index].stream = NULL; - musicChannels_g[index].xmctx = NULL; + musicStreams[index].stream = NULL; + musicStreams[index].xmctx = NULL; } } } @@ -952,7 +952,7 @@ int GetMusicStreamCount(void) // Find empty music slot for (int musicIndex = 0; musicIndex < MAX_MUSIC_STREAMS; musicIndex++) { - if(musicChannels_g[musicIndex].stream != NULL || musicChannels_g[musicIndex].chipTune) musicCount++; + if(musicStreams[musicIndex].stream != NULL || musicStreams[musicIndex].chipTune) musicCount++; } return musicCount; @@ -962,11 +962,11 @@ int GetMusicStreamCount(void) void PauseMusicStream(int index) { // Pause music stream if music available! - if (index < MAX_MUSIC_STREAMS && musicChannels_g[index].mixc && musicChannels_g[index].enabled) + if (index < MAX_MUSIC_STREAMS && musicStreams[index].mixc && musicStreams[index].enabled) { TraceLog(INFO, "Pausing music stream"); - alSourcePause(musicChannels_g[index].mixc->alSource); - musicChannels_g[index].mixc->playing = false; + alSourcePause(musicStreams[index].mixc->alSource); + musicStreams[index].mixc->playing = false; } } @@ -976,15 +976,15 @@ void ResumeMusicStream(int index) // Resume music playing... if music available! ALenum state; - if (index < MAX_MUSIC_STREAMS && musicChannels_g[index].mixc) + if (index < MAX_MUSIC_STREAMS && musicStreams[index].mixc) { - alGetSourcei(musicChannels_g[index].mixc->alSource, AL_SOURCE_STATE, &state); + alGetSourcei(musicStreams[index].mixc->alSource, AL_SOURCE_STATE, &state); if (state == AL_PAUSED) { TraceLog(INFO, "Resuming music stream"); - alSourcePlay(musicChannels_g[index].mixc->alSource); - musicChannels_g[index].mixc->playing = true; + alSourcePlay(musicStreams[index].mixc->alSource); + musicStreams[index].mixc->playing = true; } } } @@ -995,9 +995,9 @@ bool IsMusicPlaying(int index) bool playing = false; ALint state; - if (index < MAX_MUSIC_STREAMS && musicChannels_g[index].mixc) + if (index < MAX_MUSIC_STREAMS && musicStreams[index].mixc) { - alGetSourcei(musicChannels_g[index].mixc->alSource, AL_SOURCE_STATE, &state); + alGetSourcei(musicStreams[index].mixc->alSource, AL_SOURCE_STATE, &state); if (state == AL_PLAYING) playing = true; } @@ -1008,18 +1008,18 @@ bool IsMusicPlaying(int index) // Set volume for music void SetMusicVolume(int index, float volume) { - if (index < MAX_MUSIC_STREAMS && musicChannels_g[index].mixc) + if (index < MAX_MUSIC_STREAMS && musicStreams[index].mixc) { - alSourcef(musicChannels_g[index].mixc->alSource, AL_GAIN, volume); + alSourcef(musicStreams[index].mixc->alSource, AL_GAIN, volume); } } // Set pitch for music void SetMusicPitch(int index, float pitch) { - if (index < MAX_MUSIC_STREAMS && musicChannels_g[index].mixc) + if (index < MAX_MUSIC_STREAMS && musicStreams[index].mixc) { - alSourcef(musicChannels_g[index].mixc->alSource, AL_PITCH, pitch); + alSourcef(musicStreams[index].mixc->alSource, AL_PITCH, pitch); } } @@ -1028,8 +1028,8 @@ float GetMusicTimeLength(int index) { float totalSeconds; - if (musicChannels_g[index].chipTune) totalSeconds = (float)musicChannels_g[index].totalLengthSeconds; - else totalSeconds = stb_vorbis_stream_length_in_seconds(musicChannels_g[index].stream); + if (musicStreams[index].chipTune) totalSeconds = (float)musicStreams[index].totalLengthSeconds; + else totalSeconds = stb_vorbis_stream_length_in_seconds(musicStreams[index].stream); return totalSeconds; } @@ -1039,24 +1039,24 @@ float GetMusicTimePlayed(int index) { float secondsPlayed = 0.0f; - if (index < MAX_MUSIC_STREAMS && musicChannels_g[index].mixc) + if (index < MAX_MUSIC_STREAMS && musicStreams[index].mixc) { - if (musicChannels_g[index].chipTune && musicChannels_g[index].xmctx) + if (musicStreams[index].chipTune && musicStreams[index].xmctx) { uint64_t samples; - jar_xm_get_position(musicChannels_g[index].xmctx, NULL, NULL, NULL, &samples); - secondsPlayed = (float)samples / (48000.f * musicChannels_g[index].mixc->channels); // Not sure if this is the correct value + jar_xm_get_position(musicStreams[index].xmctx, NULL, NULL, NULL, &samples); + secondsPlayed = (float)samples / (48000.f * musicStreams[index].mixc->channels); // Not sure if this is the correct value } - else if(musicChannels_g[index].chipTune && musicChannels_g[index].modctx.mod_loaded) + else if(musicStreams[index].chipTune && musicStreams[index].modctx.mod_loaded) { - long numsamp = jar_mod_current_samples(&musicChannels_g[index].modctx); + long numsamp = jar_mod_current_samples(&musicStreams[index].modctx); secondsPlayed = (float)numsamp / (48000.f); } else { - int totalSamples = stb_vorbis_stream_length_in_samples(musicChannels_g[index].stream) * musicChannels_g[index].mixc->channels; - int samplesPlayed = totalSamples - musicChannels_g[index].totalSamplesLeft; - secondsPlayed = (float)samplesPlayed / (musicChannels_g[index].mixc->sampleRate * musicChannels_g[index].mixc->channels); + int totalSamples = stb_vorbis_stream_length_in_samples(musicStreams[index].stream) * musicStreams[index].mixc->channels; + int samplesPlayed = totalSamples - musicStreams[index].totalSamplesLeft; + secondsPlayed = (float)samplesPlayed / (musicStreams[index].mixc->sampleRate * musicStreams[index].mixc->channels); } } @@ -1076,30 +1076,30 @@ static bool BufferMusicStream(int index, int numBuffers) int size = 0; // Total size of data steamed in L+R samples for xm floats, individual L or R for ogg shorts bool active = true; // We can get more data from stream (not finished) - if (musicChannels_g[index].chipTune) // There is no end of stream for xmfiles, once the end is reached zeros are generated for non looped chiptunes. + if (musicStreams[index].chipTune) // There is no end of stream for xmfiles, once the end is reached zeros are generated for non looped chiptunes. { for (int i = 0; i < numBuffers; i++) { - if (musicChannels_g[index].modctx.mod_loaded) + if (musicStreams[index].modctx.mod_loaded) { - if (musicChannels_g[index].totalSamplesLeft >= MUSIC_BUFFER_SIZE_SHORT) size = MUSIC_BUFFER_SIZE_SHORT/2; - else size = musicChannels_g[index].totalSamplesLeft/2; + if (musicStreams[index].totalSamplesLeft >= MUSIC_BUFFER_SIZE_SHORT) size = MUSIC_BUFFER_SIZE_SHORT/2; + else size = musicStreams[index].totalSamplesLeft/2; - jar_mod_fillbuffer(&musicChannels_g[index].modctx, pcm, size, 0 ); - BufferMixChannel(musicChannels_g[index].mixc, pcm, size*2); + jar_mod_fillbuffer(&musicStreams[index].modctx, pcm, size, 0 ); + BufferMixChannel(musicStreams[index].mixc, pcm, size*2); } - else if (musicChannels_g[index].xmctx) + else if (musicStreams[index].xmctx) { - if (musicChannels_g[index].totalSamplesLeft >= MUSIC_BUFFER_SIZE_FLOAT) size = MUSIC_BUFFER_SIZE_FLOAT/2; - else size = musicChannels_g[index].totalSamplesLeft/2; + if (musicStreams[index].totalSamplesLeft >= MUSIC_BUFFER_SIZE_FLOAT) size = MUSIC_BUFFER_SIZE_FLOAT/2; + else size = musicStreams[index].totalSamplesLeft/2; - jar_xm_generate_samples(musicChannels_g[index].xmctx, pcmf, size); // reads 2*readlen shorts and moves them to buffer+size memory location - BufferMixChannel(musicChannels_g[index].mixc, pcmf, size*2); + jar_xm_generate_samples(musicStreams[index].xmctx, pcmf, size); // reads 2*readlen shorts and moves them to buffer+size memory location + BufferMixChannel(musicStreams[index].mixc, pcmf, size*2); } - musicChannels_g[index].totalSamplesLeft -= size; + musicStreams[index].totalSamplesLeft -= size; - if (musicChannels_g[index].totalSamplesLeft <= 0) + if (musicStreams[index].totalSamplesLeft <= 0) { active = false; break; @@ -1108,16 +1108,16 @@ static bool BufferMusicStream(int index, int numBuffers) } else { - if (musicChannels_g[index].totalSamplesLeft >= MUSIC_BUFFER_SIZE_SHORT) size = MUSIC_BUFFER_SIZE_SHORT; - else size = musicChannels_g[index].totalSamplesLeft; + if (musicStreams[index].totalSamplesLeft >= MUSIC_BUFFER_SIZE_SHORT) size = MUSIC_BUFFER_SIZE_SHORT; + else size = musicStreams[index].totalSamplesLeft; for (int i = 0; i < numBuffers; i++) { - int streamedBytes = stb_vorbis_get_samples_short_interleaved(musicChannels_g[index].stream, musicChannels_g[index].mixc->channels, pcm, size); - BufferMixChannel(musicChannels_g[index].mixc, pcm, streamedBytes * musicChannels_g[index].mixc->channels); - musicChannels_g[index].totalSamplesLeft -= streamedBytes * musicChannels_g[index].mixc->channels; + int streamedBytes = stb_vorbis_get_samples_short_interleaved(musicStreams[index].stream, musicStreams[index].mixc->channels, pcm, size); + BufferMixChannel(musicStreams[index].mixc, pcm, streamedBytes * musicStreams[index].mixc->channels); + musicStreams[index].totalSamplesLeft -= streamedBytes * musicStreams[index].mixc->channels; - if (musicChannels_g[index].totalSamplesLeft <= 0) + if (musicStreams[index].totalSamplesLeft <= 0) { active = false; break; @@ -1134,11 +1134,11 @@ static void EmptyMusicStream(int index) ALuint buffer = 0; int queued = 0; - alGetSourcei(musicChannels_g[index].mixc->alSource, AL_BUFFERS_QUEUED, &queued); + alGetSourcei(musicStreams[index].mixc->alSource, AL_BUFFERS_QUEUED, &queued); while (queued > 0) { - alSourceUnqueueBuffers(musicChannels_g[index].mixc->alSource, 1, &buffer); + alSourceUnqueueBuffers(musicStreams[index].mixc->alSource, 1, &buffer); queued--; } @@ -1148,7 +1148,7 @@ static void EmptyMusicStream(int index) static int IsMusicStreamReadyForBuffering(int index) { ALint processed = 0; - alGetSourcei(musicChannels_g[index].mixc->alSource, AL_BUFFERS_PROCESSED, &processed); + alGetSourcei(musicStreams[index].mixc->alSource, AL_BUFFERS_PROCESSED, &processed); return processed; } @@ -1159,22 +1159,22 @@ void UpdateMusicStream(int index) bool active = true; int numBuffers = IsMusicStreamReadyForBuffering(index); - if (musicChannels_g[index].mixc->playing && (index < MAX_MUSIC_STREAMS) && musicChannels_g[index].enabled && musicChannels_g[index].mixc && numBuffers) + if (musicStreams[index].mixc->playing && (index < MAX_MUSIC_STREAMS) && musicStreams[index].enabled && musicStreams[index].mixc && numBuffers) { active = BufferMusicStream(index, numBuffers); - if (!active && musicChannels_g[index].loop) + if (!active && musicStreams[index].loop) { - if (musicChannels_g[index].chipTune) + if (musicStreams[index].chipTune) { - if(musicChannels_g[index].modctx.mod_loaded) jar_mod_seek_start(&musicChannels_g[index].modctx); + if(musicStreams[index].modctx.mod_loaded) jar_mod_seek_start(&musicStreams[index].modctx); - musicChannels_g[index].totalSamplesLeft = musicChannels_g[index].totalLengthSeconds * 48000.f; + musicStreams[index].totalSamplesLeft = musicStreams[index].totalLengthSeconds * 48000.f; } else { - stb_vorbis_seek_start(musicChannels_g[index].stream); - musicChannels_g[index].totalSamplesLeft = stb_vorbis_stream_length_in_samples(musicChannels_g[index].stream) * musicChannels_g[index].mixc->channels; + stb_vorbis_seek_start(musicStreams[index].stream); + musicStreams[index].totalSamplesLeft = stb_vorbis_stream_length_in_samples(musicStreams[index].stream) * musicStreams[index].mixc->channels; } active = BufferMusicStream(index, IsMusicStreamReadyForBuffering(index)); @@ -1182,9 +1182,9 @@ void UpdateMusicStream(int index) if (alGetError() != AL_NO_ERROR) TraceLog(WARNING, "Error buffering data..."); - alGetSourcei(musicChannels_g[index].mixc->alSource, AL_SOURCE_STATE, &state); + alGetSourcei(musicStreams[index].mixc->alSource, AL_SOURCE_STATE, &state); - if (state != AL_PLAYING && active) alSourcePlay(musicChannels_g[index].mixc->alSource); + if (state != AL_PLAYING && active) alSourcePlay(musicStreams[index].mixc->alSource); if (!active) StopMusicStream(index); -- cgit v1.2.3 From 7959ccd84dd9eedd7aad10fe8b6bea988f828f40 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Fri, 15 Jul 2016 18:16:34 +0200 Subject: Review some functions, formatting and comments --- src/audio.c | 240 ++++++++++++++++++++++++++++++++--------------------------- src/audio.h | 31 +++++--- src/raylib.h | 2 - 3 files changed, 148 insertions(+), 125 deletions(-) (limited to 'src') diff --git a/src/audio.c b/src/audio.c index 2941b9fb..38fefd12 100644 --- a/src/audio.c +++ b/src/audio.c @@ -2,13 +2,26 @@ * * raylib.audio * -* Basic functions to manage Audio: InitAudioDevice, LoadAudioFiles, PlayAudioFiles +* Basic functions to manage Audio: +* Manage audio device (init/close) +* Load and Unload audio files +* Play/Stop/Pause/Resume loaded audio +* Manage mixing channels +* Manage raw audio context * * Uses external lib: * OpenAL Soft - Audio device management lib (http://kcat.strangesoft.net/openal.html) * stb_vorbis - Ogg audio files loading (http://www.nothings.org/stb_vorbis/) +* jar_xm - XM module file loading +* jar_mod - MOD audio file loading * -* Copyright (c) 2014 Ramon Santamaria (@raysan5) +* Many thanks to Joshua Reisenauer (github: @kd7tck) for the following additions: +* XM audio module support (jar_xm) +* MOD audio module support (jar_mod) +* Mixing channels support +* Raw audio context support +* +* Copyright (c) 2014-2016 Ramon Santamaria (@raysan5) * * This software is provided "as-is", without any express or implied warranty. In no event * will the authors be held liable for any damages arising from the use of this software. @@ -68,9 +81,9 @@ //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- -#define MAX_STREAM_BUFFERS 2 // Number of buffers for each alSource -#define MAX_MIX_CHANNELS 4 // Number of OpenAL sources +#define MAX_STREAM_BUFFERS 2 // Number of buffers for each source #define MAX_MUSIC_STREAMS 2 // Number of simultanious music sources +#define MAX_MIX_CHANNELS 4 // Number of mix channels (OpenAL sources) #if defined(PLATFORM_RPI) || defined(PLATFORM_ANDROID) // NOTE: On RPI and Android should be lower to avoid frame-stalls @@ -143,7 +156,7 @@ typedef enum { INFO = 0, ERROR, WARNING, DEBUG, OTHER } TraceLogType; // Global Variables Definition //---------------------------------------------------------------------------------- static Music musicStreams[MAX_MUSIC_STREAMS]; // Current music loaded, up to two can play at the same time -static MixChannel *mixChannels[MAX_MIX_CHANNELS]; // What mix channels are currently active +static MixChannel *mixChannels[MAX_MIX_CHANNELS]; // Mix channels currently active (from music streams) static int lastAudioError = 0; // Registers last audio error @@ -157,13 +170,11 @@ static void UnloadWave(Wave wave); // Unload wave data static bool BufferMusicStream(int index, int numBuffers); // Fill music buffers with data static void EmptyMusicStream(int index); // Empty music buffers -static MixChannel *InitMixChannel(unsigned short sampleRate, unsigned char mixChannel, unsigned char channels, bool floatingPoint); // For streaming into mix channels. +static MixChannel *InitMixChannel(unsigned short sampleRate, unsigned char mixChannel, unsigned char channels, bool floatingPoint); static void CloseMixChannel(MixChannel *mixc); // Frees mix channel -static int BufferMixChannel(MixChannel *mixc, void *data, int numberElements); // Pushes more audio data into mixc mix channel, if NULL is passed it pauses -static int FillAlBufferWithSilence(MixChannel *mixc, ALuint buffer); // Fill buffer with zeros, returns number processed -static void ResampleShortToFloat(short *shorts, float *floats, unsigned short len); // Pass two arrays of the same legnth in -static void ResampleByteToFloat(char *chars, float *floats, unsigned short len); // Pass two arrays of same length in -static int IsMusicStreamReadyForBuffering(int index); // Checks if music buffer is ready to be refilled +static int BufferMixChannel(MixChannel *mixc, void *data, int numberElements); // Pushes more audio data into mix channel +//static void ResampleShortToFloat(short *shorts, float *floats, unsigned short len); // Pass two arrays of the same legnth in +//static void ResampleByteToFloat(char *chars, float *floats, unsigned short len); // Pass two arrays of same length in #if defined(AUDIO_STANDALONE) const char *GetExtension(const char *fileName); // Get the extension for a filename @@ -204,7 +215,7 @@ void InitAudioDevice(void) // Close the audio device for all contexts void CloseAudioDevice(void) { - for (int index=0; index= MAX_MIX_CHANNELS) return NULL; @@ -280,7 +291,20 @@ static MixChannel *InitMixChannel(unsigned short sampleRate, unsigned char mixCh alGenBuffers(MAX_STREAM_BUFFERS, mixc->alBuffer); // Fill buffers - for (int i = 0; i < MAX_STREAM_BUFFERS; i++) FillAlBufferWithSilence(mixc, mixc->alBuffer[i]); + for (int i = 0; i < MAX_STREAM_BUFFERS; i++) + { + // Initialize buffer with zeros by default + if (mixc->floatingPoint) + { + float pcm[MUSIC_BUFFER_SIZE_FLOAT] = { 0.0f }; + alBufferData(mixc->alBuffer[i], mixc->alFormat, pcm, MUSIC_BUFFER_SIZE_FLOAT*sizeof(float), mixc->sampleRate); + } + else + { + short pcm[MUSIC_BUFFER_SIZE_SHORT] = { 0 }; + alBufferData(mixc->alBuffer[i], mixc->alFormat, pcm, MUSIC_BUFFER_SIZE_SHORT*sizeof(short), mixc->sampleRate); + } + } alSourceQueueBuffers(mixc->alSource, MAX_STREAM_BUFFERS, mixc->alBuffer); mixc->playing = true; @@ -320,9 +344,9 @@ static void CloseMixChannel(MixChannel *mixc) } } -// Pushes more audio data into mixc mix channel, only one buffer per call +// Pushes more audio data into mix channel, only one buffer per call // Call "BufferMixChannel(mixc, NULL, 0)" if you want to pause the audio. -// @Returns number of samples that where processed. +// Returns number of samples that where processed. static int BufferMixChannel(MixChannel *mixc, void *data, int numberElements) { if (!mixc || (mixChannels[mixc->mixChannel] != mixc)) return 0; // When there is two channels there must be an even number of samples @@ -368,28 +392,11 @@ static int BufferMixChannel(MixChannel *mixc, void *data, int numberElements) return numberElements; } -// fill buffer with zeros, returns number processed -static int FillAlBufferWithSilence(MixChannel *mixc, ALuint buffer) -{ - if (mixc->floatingPoint) - { - float pcm[MUSIC_BUFFER_SIZE_FLOAT] = { 0.0f }; - alBufferData(buffer, mixc->alFormat, pcm, MUSIC_BUFFER_SIZE_FLOAT*sizeof(float), mixc->sampleRate); - - return MUSIC_BUFFER_SIZE_FLOAT; - } - else - { - short pcm[MUSIC_BUFFER_SIZE_SHORT] = { 0 }; - alBufferData(buffer, mixc->alFormat, pcm, MUSIC_BUFFER_SIZE_SHORT*sizeof(short), mixc->sampleRate); - - return MUSIC_BUFFER_SIZE_SHORT; - } -} - +/* +// Convert data from short to float // example usage: -// short sh[3] = {1,2,3};float fl[3]; -// ResampleShortToFloat(sh,fl,3); +// short sh[3] = {1,2,3};float fl[3]; +// ResampleShortToFloat(sh,fl,3); static void ResampleShortToFloat(short *shorts, float *floats, unsigned short len) { for (int i = 0; i < len; i++) @@ -399,9 +406,10 @@ static void ResampleShortToFloat(short *shorts, float *floats, unsigned short le } } +// Convert data from float to short // example usage: -// char ch[3] = {1,2,3};float fl[3]; -// ResampleByteToFloat(ch,fl,3); +// char ch[3] = {1,2,3};float fl[3]; +// ResampleByteToFloat(ch,fl,3); static void ResampleByteToFloat(char *chars, float *floats, unsigned short len) { for (int i = 0; i < len; i++) @@ -410,43 +418,55 @@ static void ResampleByteToFloat(char *chars, float *floats, unsigned short len) else floats[i] = (float)chars[i]/128.0f; } } +*/ -// used to output raw audio streams, returns negative numbers on error, + number represents the mix channel index -// if floating point is false the data size is 16bit short, otherwise it is float 32bit -RawAudioContext InitRawAudioContext(int sampleRate, int channels, bool floatingPoint) +// Initialize raw audio mix channel for audio buffering +// NOTE: Returns mix channel index or -1 if it fails (errors are registered on lastAudioError) +int InitRawMixChannel(int sampleRate, int channels, bool floatingPoint) { int mixIndex; + for (mixIndex = 0; mixIndex < MAX_MIX_CHANNELS; mixIndex++) // find empty mix channel slot { if (mixChannels[mixIndex] == NULL) break; - else if (mixIndex == (MAX_MIX_CHANNELS - 1)) return ERROR_OUT_OF_MIX_CHANNELS; // error + else if (mixIndex == (MAX_MIX_CHANNELS - 1)) + { + lastAudioError = ERROR_OUT_OF_MIX_CHANNELS; + return -1; + } } if (InitMixChannel(sampleRate, mixIndex, channels, floatingPoint)) return mixIndex; - else return ERROR_RAW_CONTEXT_CREATION; // error -} - -void CloseRawAudioContext(RawAudioContext ctx) -{ - if (mixChannels[ctx]) CloseMixChannel(mixChannels[ctx]); + else + { + lastAudioError = ERROR_RAW_CONTEXT_CREATION; + return -1; + } } -// if 0 is returned, the buffers are still full and you need to keep trying with the same data until a + number is returned. -// any + number returned is the number of samples that was processed and passed into buffer. -// data either needs to be array of floats or shorts. -int BufferRawAudioContext(RawAudioContext ctx, void *data, unsigned short numberElements) +// Buffers data directly to raw mix channel +// if 0 is returned, buffers are still full and you need to keep trying with the same data +// otherwise it will return number of samples buffered. +// NOTE: Data could be either be an array of floats or shorts, depending on the created context +int BufferRawAudioContext(int ctx, void *data, unsigned short numberElements) { int numBuffered = 0; if (ctx >= 0) { - MixChannel* mixc = mixChannels[ctx]; + MixChannel *mixc = mixChannels[ctx]; numBuffered = BufferMixChannel(mixc, data, numberElements); } return numBuffered; } +// Closes and frees raw mix channel +void CloseRawAudioContext(int ctx) +{ + if (mixChannels[ctx]) CloseMixChannel(mixChannels[ctx]); +} + //---------------------------------------------------------------------------------- // Module Functions Definition - Sounds loading and playing (.WAV) //---------------------------------------------------------------------------------- @@ -804,7 +824,7 @@ void SetSoundPitch(Sound sound, float pitch) //---------------------------------------------------------------------------------- // Start music playing (open stream) -// returns 0 on success +// returns 0 on success or error code int PlayMusicStream(int index, char *fileName) { int mixIndex; @@ -866,7 +886,7 @@ int PlayMusicStream(int index, char *fileName) musicStreams[index].loop = true; jar_xm_set_max_loop_count(musicStreams[index].xmctx, 0); // infinite number of loops musicStreams[index].totalSamplesLeft = (unsigned int)jar_xm_get_remaining_samples(musicStreams[index].xmctx); - musicStreams[index].totalLengthSeconds = ((float)musicStreams[index].totalSamplesLeft) / 48000.f; + musicStreams[index].totalLengthSeconds = ((float)musicStreams[index].totalSamplesLeft)/48000.0f; musicStreams[index].enabled = true; TraceLog(INFO, "[%s] XM number of samples: %i", fileName, musicStreams[index].totalSamplesLeft); @@ -893,7 +913,7 @@ int PlayMusicStream(int index, char *fileName) musicStreams[index].chipTune = true; musicStreams[index].loop = true; musicStreams[index].totalSamplesLeft = (unsigned int)jar_mod_max_samples(&musicStreams[index].modctx); - musicStreams[index].totalLengthSeconds = ((float)musicStreams[index].totalSamplesLeft) / 48000.f; + musicStreams[index].totalLengthSeconds = ((float)musicStreams[index].totalSamplesLeft)/48000.0f; musicStreams[index].enabled = true; TraceLog(INFO, "[%s] MOD number of samples: %i", fileName, musicStreams[index].totalSamplesLeft); @@ -944,6 +964,51 @@ void StopMusicStream(int index) } } +// Update (re-fill) music buffers if data already processed +void UpdateMusicStream(int index) +{ + ALenum state; + bool active = true; + ALint processed = 0; + + // Determine if music stream is ready to be written + alGetSourcei(musicStreams[index].mixc->alSource, AL_BUFFERS_PROCESSED, &processed); + + if (musicStreams[index].mixc->playing && (index < MAX_MUSIC_STREAMS) && musicStreams[index].enabled && musicStreams[index].mixc && (processed > 0)) + { + active = BufferMusicStream(index, processed); + + if (!active && musicStreams[index].loop) + { + if (musicStreams[index].chipTune) + { + if(musicStreams[index].modctx.mod_loaded) jar_mod_seek_start(&musicStreams[index].modctx); + + musicStreams[index].totalSamplesLeft = musicStreams[index].totalLengthSeconds*48000.0f; + } + else + { + stb_vorbis_seek_start(musicStreams[index].stream); + musicStreams[index].totalSamplesLeft = stb_vorbis_stream_length_in_samples(musicStreams[index].stream)*musicStreams[index].mixc->channels; + } + + // Determine if music stream is ready to be written + alGetSourcei(musicStreams[index].mixc->alSource, AL_BUFFERS_PROCESSED, &processed); + + active = BufferMusicStream(index, processed); + } + + if (alGetError() != AL_NO_ERROR) TraceLog(WARNING, "Error buffering data..."); + + alGetSourcei(musicStreams[index].mixc->alSource, AL_SOURCE_STATE, &state); + + if (state != AL_PLAYING && active) alSourcePlay(musicStreams[index].mixc->alSource); + + if (!active) StopMusicStream(index); + + } +} + //get number of music channels active at this time, this does not mean they are playing int GetMusicStreamCount(void) { @@ -1045,18 +1110,18 @@ float GetMusicTimePlayed(int index) { uint64_t samples; jar_xm_get_position(musicStreams[index].xmctx, NULL, NULL, NULL, &samples); - secondsPlayed = (float)samples / (48000.f * musicStreams[index].mixc->channels); // Not sure if this is the correct value + secondsPlayed = (float)samples/(48000.0f*musicStreams[index].mixc->channels); // Not sure if this is the correct value } else if(musicStreams[index].chipTune && musicStreams[index].modctx.mod_loaded) { long numsamp = jar_mod_current_samples(&musicStreams[index].modctx); - secondsPlayed = (float)numsamp / (48000.f); + secondsPlayed = (float)numsamp/(48000.0f); } else { - int totalSamples = stb_vorbis_stream_length_in_samples(musicStreams[index].stream) * musicStreams[index].mixc->channels; + int totalSamples = stb_vorbis_stream_length_in_samples(musicStreams[index].stream)*musicStreams[index].mixc->channels; int samplesPlayed = totalSamples - musicStreams[index].totalSamplesLeft; - secondsPlayed = (float)samplesPlayed / (musicStreams[index].mixc->sampleRate * musicStreams[index].mixc->channels); + secondsPlayed = (float)samplesPlayed/(musicStreams[index].mixc->sampleRate*musicStreams[index].mixc->channels); } } @@ -1144,53 +1209,6 @@ static void EmptyMusicStream(int index) } } -// Determine if a music stream is ready to be written -static int IsMusicStreamReadyForBuffering(int index) -{ - ALint processed = 0; - alGetSourcei(musicStreams[index].mixc->alSource, AL_BUFFERS_PROCESSED, &processed); - return processed; -} - -// Update (re-fill) music buffers if data already processed -void UpdateMusicStream(int index) -{ - ALenum state; - bool active = true; - int numBuffers = IsMusicStreamReadyForBuffering(index); - - if (musicStreams[index].mixc->playing && (index < MAX_MUSIC_STREAMS) && musicStreams[index].enabled && musicStreams[index].mixc && numBuffers) - { - active = BufferMusicStream(index, numBuffers); - - if (!active && musicStreams[index].loop) - { - if (musicStreams[index].chipTune) - { - if(musicStreams[index].modctx.mod_loaded) jar_mod_seek_start(&musicStreams[index].modctx); - - musicStreams[index].totalSamplesLeft = musicStreams[index].totalLengthSeconds * 48000.f; - } - else - { - stb_vorbis_seek_start(musicStreams[index].stream); - musicStreams[index].totalSamplesLeft = stb_vorbis_stream_length_in_samples(musicStreams[index].stream) * musicStreams[index].mixc->channels; - } - - active = BufferMusicStream(index, IsMusicStreamReadyForBuffering(index)); - } - - if (alGetError() != AL_NO_ERROR) TraceLog(WARNING, "Error buffering data..."); - - alGetSourcei(musicStreams[index].mixc->alSource, AL_SOURCE_STATE, &state); - - if (state != AL_PLAYING && active) alSourcePlay(musicStreams[index].mixc->alSource); - - if (!active) StopMusicStream(index); - - } -} - // Load WAV file into Wave structure static Wave LoadWAV(const char *fileName) { diff --git a/src/audio.h b/src/audio.h index 3ffe575c..f4a82a55 100644 --- a/src/audio.h +++ b/src/audio.h @@ -2,13 +2,26 @@ * * raylib.audio * -* Basic functions to manage Audio: InitAudioDevice, LoadAudioFiles, PlayAudioFiles +* Basic functions to manage Audio: +* Manage audio device (init/close) +* Load and Unload audio files +* Play/Stop/Pause/Resume loaded audio +* Manage mixing channels +* Manage raw audio context * * Uses external lib: * OpenAL Soft - Audio device management lib (http://kcat.strangesoft.net/openal.html) * stb_vorbis - Ogg audio files loading (http://www.nothings.org/stb_vorbis/) +* jar_xm - XM module file loading +* jar_mod - MOD audio file loading * -* Copyright (c) 2015 Ramon Santamaria (@raysan5) +* Many thanks to Joshua Reisenauer (github: @kd7tck) for the following additions: +* XM audio module support (jar_xm) +* MOD audio module support (jar_mod) +* Mixing channels support +* Raw audio context support +* +* Copyright (c) 2014-2016 Ramon Santamaria (@raysan5) * * This software is provided "as-is", without any express or implied warranty. In no event * will the authors be held liable for any damages arising from the use of this software. @@ -63,9 +76,6 @@ typedef struct Wave { short channels; } Wave; -typedef int RawAudioContext; - - #ifdef __cplusplus extern "C" { // Prevents name mangling of functions #endif @@ -80,7 +90,7 @@ extern "C" { // Prevents name mangling of functions //---------------------------------------------------------------------------------- void InitAudioDevice(void); // Initialize audio device and context void CloseAudioDevice(void); // Close the audio device and context (and music stream) -bool IsAudioDeviceReady(void); // True if call to InitAudioDevice() was successful and CloseAudioDevice() has not been called yet +bool IsAudioDeviceReady(void); // Check if device has been initialized successfully Sound LoadSound(char *fileName); // Load sound to memory Sound LoadSoundFromWave(Wave wave); // Load sound to memory from wave data @@ -105,12 +115,9 @@ float GetMusicTimeLength(int index); // Get music tim float GetMusicTimePlayed(int index); // Get current music time played (in seconds) int GetMusicStreamCount(void); // Get number of streams loaded -// used to output raw audio streams, returns negative numbers on error -// if floating point is false the data size is 16bit short, otherwise it is float 32bit -RawAudioContext InitRawAudioContext(int sampleRate, int channels, bool floatingPoint); - -void CloseRawAudioContext(RawAudioContext ctx); -int BufferRawAudioContext(RawAudioContext ctx, void *data, unsigned short numberElements); // returns number of elements buffered +int InitRawMixChannel(int sampleRate, int channels, bool floatingPoint); // Initialize raw audio mix channel for audio buffering +int BufferRawMixChannel(int mixc, void *data, unsigned short numberElements); // Buffers data directly to raw mix channel +void CloseRawMixChannel(int mixc); // Closes and frees raw mix channel #ifdef __cplusplus } diff --git a/src/raylib.h b/src/raylib.h index 9225c5ee..e3a17ebb 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -468,8 +468,6 @@ typedef struct Wave { short channels; } Wave; -typedef int RawAudioContext; - // Texture formats // NOTE: Support depends on OpenGL version and platform typedef enum { -- cgit v1.2.3 From 0fbd48a8890d5f3e2158dbec12a6e452b6fb81b0 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sat, 16 Jul 2016 14:58:53 +0200 Subject: Corrected bug on OpenGL 1.1 Set makefile to default OpenGL 3.3 compilation --- src/Makefile | 6 +++--- src/rlgl.c | 6 ++++++ 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 33b666b4..b37cccf8 100644 --- a/src/Makefile +++ b/src/Makefile @@ -49,10 +49,10 @@ ifeq ($(PLATFORM),PLATFORM_RPI) # define raylib graphics api to use (on RPI, OpenGL ES 2.0 must be used) GRAPHICS = GRAPHICS_API_OPENGL_ES2 else - # define raylib graphics api to use (OpenGL 1.1 by default) - GRAPHICS ?= GRAPHICS_API_OPENGL_11 + # define raylib graphics api to use (OpenGL 3.3 by default) + GRAPHICS ?= GRAPHICS_API_OPENGL_33 + #GRAPHICS = GRAPHICS_API_OPENGL_11 # Uncomment to use OpenGL 1.1 #GRAPHICS = GRAPHICS_API_OPENGL_21 # Uncomment to use OpenGL 2.1 - #GRAPHICS = GRAPHICS_API_OPENGL_33 # Uncomment to use OpenGL 3.3 endif ifeq ($(PLATFORM),PLATFORM_WEB) GRAPHICS = GRAPHICS_API_OPENGL_ES2 diff --git a/src/rlgl.c b/src/rlgl.c index 586c15e3..adccb0c7 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -2645,6 +2645,10 @@ void InitVrDevice(int hmdDevice) vrEnabled = true; } #endif + +#if defined(GRAPHICS_API_OPENGL_11) + TraceLog(WARNING, "VR device or simulator not supported on OpenGL 1.1"); +#endif } // Close VR device (or simulator) @@ -2672,6 +2676,7 @@ bool IsVrDeviceReady(void) // Enable/Disable VR experience (device or simulator) void ToggleVrMode(void) { +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) if (vrDeviceReady || vrSimulator) vrEnabled = !vrEnabled; else vrEnabled = false; @@ -2683,6 +2688,7 @@ void ToggleVrMode(void) MatrixTranspose(&projection); modelview = MatrixIdentity(); } +#endif } // Update VR tracking (position and orientation) -- cgit v1.2.3 From a05150392a14ded407ffbf8c735dd4f92354fcb8 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sat, 16 Jul 2016 19:24:08 +0200 Subject: Added audio standalone sample --- examples/audio_standalone.c | 74 +++++++++++++++++++++++++++++++++++++++++++++ src/audio.h | 9 +++--- 2 files changed, 78 insertions(+), 5 deletions(-) create mode 100644 examples/audio_standalone.c (limited to 'src') diff --git a/examples/audio_standalone.c b/examples/audio_standalone.c new file mode 100644 index 00000000..1ae6324a --- /dev/null +++ b/examples/audio_standalone.c @@ -0,0 +1,74 @@ +/******************************************************************************************* +* +* raylib [audio] example - Using audio module as standalone module +* +* NOTE: This example does not require any graphic device, it can run directly on console. +* +* [audio] module requires some external libs: +* OpenAL Soft - Audio device management lib (http://kcat.strangesoft.net/openal.html) +* stb_vorbis - Ogg audio files loading (http://www.nothings.org/stb_vorbis/) +* jar_xm - XM module file loading +* jar_mod - MOD audio file loading +* +* Compile audio module using: +* gcc -c audio.c stb_vorbis.c -DAUDIO_STANDALONE +* +* Compile example using: +* gcc -o $(NAME_PART).exe $(FILE_NAME) audio.o stb_vorbis.o -lopenal32 -std=c99 +* +* This example has been created using raylib 1.5 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2015 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include +#include // Windows only, no stardard library + +#include "audio.h" + +#define KEY_ESCAPE 27 + +int main() +{ + unsigned char key; + + InitAudioDevice(); + + Sound fxWav = LoadSound("resources/audio/weird.wav"); // Load WAV audio file + Sound fxOgg = LoadSound("resources/audio/tanatana.ogg"); // Load OGG audio file + + PlayMusicStream(0, "resources/audio/guitar_noodling.ogg"); + + printf("\nPress s or d to play sounds...\n"); + + while (key != KEY_ESCAPE) + { + if (kbhit()) key = getch(); + + if (key == 's') + { + PlaySound(fxWav); + key = 0; + } + + if (key == 'd') + { + PlaySound(fxOgg); + key = 0; + } + + UpdateMusicStream(0); + } + + UnloadSound(fxWav); // Unload sound data + UnloadSound(fxOgg); // Unload sound data + + CloseAudioDevice(); + + printf("\n\nPress ENTER to close..."); + getchar(); + + return 0; +} \ No newline at end of file diff --git a/src/audio.h b/src/audio.h index f4a82a55..b6850911 100644 --- a/src/audio.h +++ b/src/audio.h @@ -62,17 +62,16 @@ // Sound source type typedef struct Sound { - unsigned int source; - unsigned int buffer; - AudioError error; // if there was any error during the creation or use of this Sound + unsigned int source; // Sound audio source id + unsigned int buffer; // Sound audio buffer id } Sound; // Wave type, defines audio wave data typedef struct Wave { void *data; // Buffer data pointer unsigned int dataSize; // Data size in bytes - unsigned int sampleRate; - short bitsPerSample; + unsigned int sampleRate; // Samples per second to be played + short bitsPerSample; // Sample size in bits short channels; } Wave; -- cgit v1.2.3 From bfb5ffedda8ba9a9be41c6210e72cd5c98e1c702 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sat, 16 Jul 2016 19:25:15 +0200 Subject: Added rlgl standalone sample --- examples/rlgl_standalone.c | 389 +++++++++++++++++++++++++++++++++++++++++++++ src/rlgl.c | 4 +- src/rlgl.h | 13 ++ 3 files changed, 404 insertions(+), 2 deletions(-) create mode 100644 examples/rlgl_standalone.c (limited to 'src') diff --git a/examples/rlgl_standalone.c b/examples/rlgl_standalone.c new file mode 100644 index 00000000..f5ec3cb4 --- /dev/null +++ b/examples/rlgl_standalone.c @@ -0,0 +1,389 @@ +/******************************************************************************************* +* +* raylib [rlgl] example - Using rlgl module as standalone module +* +* NOTE: This example requires OpenGL 3.3 or ES2 versions for shaders support, +* OpenGL 1.1 does not support shaders but it can also be used. +* +* Compile rlgl module using: +* gcc -c rlgl.c -Wall -std=c99 -DRLGL_STANDALONE -DRAYMATH_IMPLEMENTATION -DGRAPHICS_API_OPENGL_33 +* +* Compile example using: +* gcc -o $(NAME_PART).exe $(FILE_NAME) rlgl.o -lglfw3 -lopengl32 -lgdi32 -std=c99 +* +* This example has been created using raylib 1.5 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2015 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include // Windows/Context and inputs management + +#define RLGL_STANDALONE +#include "rlgl.h" // rlgl library: OpenGL 1.1 immediate-mode style coding + +#define RED (Color){ 230, 41, 55, 255 } // Red +#define RAYWHITE (Color){ 245, 245, 245, 255 } // My own White (raylib logo) +#define DARKGRAY (Color){ 80, 80, 80, 255 } // Dark Gray + +//---------------------------------------------------------------------------------- +// Module specific Functions Declaration +//---------------------------------------------------------------------------------- +static void ErrorCallback(int error, const char* description); +static void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); + +// Drawing functions (uses rlgl functionality) +static void DrawGrid(int slices, float spacing); +static void DrawCube(Vector3 position, float width, float height, float length, Color color); +static void DrawCubeWires(Vector3 position, float width, float height, float length, Color color); +static void DrawRectangleV(Vector2 position, Vector2 size, Color color); + +//---------------------------------------------------------------------------------- +// Main Entry point +//---------------------------------------------------------------------------------- +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + // GLFW3 Initialization + OpenGL 3.3 Context + Extensions + //-------------------------------------------------------- + glfwSetErrorCallback(ErrorCallback); + + if (!glfwInit()) + { + TraceLog(WARNING, "GLFW3: Can not initialize GLFW"); + return 1; + } + else TraceLog(INFO, "GLFW3: GLFW initialized successfully"); + + glfwWindowHint(GLFW_SAMPLES, 4); + glfwWindowHint(GLFW_DEPTH_BITS, 16); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE); + + GLFWwindow *window = glfwCreateWindow(screenWidth, screenHeight, "rlgl standalone", NULL, NULL); + + if (!window) + { + glfwTerminate(); + return 2; + } + else TraceLog(INFO, "GLFW3: Window created successfully"); + + glfwSetWindowPos(window, 200, 200); + + glfwSetKeyCallback(window, KeyCallback); + + glfwMakeContextCurrent(window); + glfwSwapInterval(1); + + // Initialize supported extensions + rlglLoadExtensions(glfwGetProcAddress); + //-------------------------------------------------------- + + // Initialize OpenGL context (states and resources) + rlglInit(screenWidth, screenHeight); + + // Initialize viewport and internal projection/modelview matrices + rlViewport(0, 0, screenWidth, screenHeight); + rlMatrixMode(RL_PROJECTION); // Switch to PROJECTION matrix + rlLoadIdentity(); // Reset current matrix (PROJECTION) + rlOrtho(0, screenWidth, screenHeight, 0, 0.0f, 1.0f); // Orthographic projection with top-left corner at (0,0) + rlMatrixMode(RL_MODELVIEW); // Switch back to MODELVIEW matrix + rlLoadIdentity(); // Reset current matrix (MODELVIEW) + + rlClearColor(245, 245, 245, 255); // Define clear color + rlEnableDepthTest(); // Enable DEPTH_TEST for 3D + + Vector3 cubePosition = { 0.0f, 0.0f, 0.0f }; // Cube default position (center) + + Camera camera; + camera.position = (Vector3){ 5.0f, 5.0f, 5.0f }; // Camera position + camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point + camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target) + camera.fovy = 45.0f; // Camera field-of-view Y + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!glfwWindowShouldClose(window)) + { + // Update + //---------------------------------------------------------------------------------- + // ... + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + rlClearScreenBuffers(); // Clear current framebuffer + + // Calculate projection matrix (from perspective) and view matrix from camera look at + Matrix matProj = MatrixPerspective(camera.fovy, (double)screenWidth/(double)screenHeight, 0.01, 1000.0); + MatrixTranspose(&matProj); + Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up); + + SetMatrixModelview(matView); // Replace internal modelview matrix by a custom one + SetMatrixProjection(matProj); // Replace internal projection matrix by a custom one + + DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED); + DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, RAYWHITE); + DrawGrid(10, 1.0f); + + // NOTE: Internal buffers drawing (3D data) + rlglDraw(); + + // Draw '2D' elements in the scene (GUI) +#define RLGL_CREATE_MATRIX_MANUALLY +#if defined(RLGL_CREATE_MATRIX_MANUALLY) + matProj = MatrixOrtho(0.0, screenWidth, screenHeight, 0.0, 0.0, 1.0); + MatrixTranspose(&matProj); + matView = MatrixIdentity(); + + SetMatrixModelview(matView); // Replace internal modelview matrix by a custom one + SetMatrixProjection(matProj); // Replace internal projection matrix by a custom one + +#else // Let rlgl generate and multiply matrix internally + + rlMatrixMode(RL_PROJECTION); // Enable internal projection matrix + rlLoadIdentity(); // Reset internal projection matrix + rlOrtho(0.0, screenWidth, screenHeight, 0.0, 0.0, 1.0); // Recalculate internal projection matrix + rlMatrixMode(RL_MODELVIEW); // Enable internal modelview matrix + rlLoadIdentity(); // Reset internal modelview matrix +#endif + DrawRectangleV((Vector2){ 10.0f, 10.0f }, (Vector2){ 780.0f, 20.0f }, DARKGRAY); + + // NOTE: Internal buffers drawing (2D data) + rlglDraw(); + + glfwSwapBuffers(window); + glfwPollEvents(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + rlglClose(); // Unload rlgl internal buffers and default shader/texture + + glfwDestroyWindow(window); + glfwTerminate(); + //-------------------------------------------------------------------------------------- + + return 0; +} + +//---------------------------------------------------------------------------------- +// Module specific Functions Definitions +//---------------------------------------------------------------------------------- + +// GLFW3: Error callback +static void ErrorCallback(int error, const char* description) +{ + TraceLog(ERROR, description); +} + +// GLFW3: Keyboard callback +static void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) +{ + if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) + { + glfwSetWindowShouldClose(window, GL_TRUE); + } +} + +// Draw rectangle using rlgl OpenGL 1.1 style coding (translated to OpenGL 3.3 internally) +static void DrawRectangleV(Vector2 position, Vector2 size, Color color) +{ + rlBegin(RL_TRIANGLES); + rlColor4ub(color.r, color.g, color.b, color.a); + + rlVertex2i(position.x, position.y); + rlVertex2i(position.x, position.y + size.y); + rlVertex2i(position.x + size.x, position.y + size.y); + + rlVertex2i(position.x, position.y); + rlVertex2i(position.x + size.x, position.y + size.y); + rlVertex2i(position.x + size.x, position.y); + rlEnd(); +} + +// Draw a grid centered at (0, 0, 0) +static void DrawGrid(int slices, float spacing) +{ + int halfSlices = slices / 2; + + rlBegin(RL_LINES); + for(int i = -halfSlices; i <= halfSlices; i++) + { + if (i == 0) + { + rlColor3f(0.5f, 0.5f, 0.5f); + rlColor3f(0.5f, 0.5f, 0.5f); + rlColor3f(0.5f, 0.5f, 0.5f); + rlColor3f(0.5f, 0.5f, 0.5f); + } + else + { + rlColor3f(0.75f, 0.75f, 0.75f); + rlColor3f(0.75f, 0.75f, 0.75f); + rlColor3f(0.75f, 0.75f, 0.75f); + rlColor3f(0.75f, 0.75f, 0.75f); + } + + rlVertex3f((float)i*spacing, 0.0f, (float)-halfSlices*spacing); + rlVertex3f((float)i*spacing, 0.0f, (float)halfSlices*spacing); + + rlVertex3f((float)-halfSlices*spacing, 0.0f, (float)i*spacing); + rlVertex3f((float)halfSlices*spacing, 0.0f, (float)i*spacing); + } + rlEnd(); +} + +// Draw cube +// NOTE: Cube position is the center position +void DrawCube(Vector3 position, float width, float height, float length, Color color) +{ + float x = 0.0f; + float y = 0.0f; + float z = 0.0f; + + rlPushMatrix(); + + // NOTE: Be careful! Function order matters (rotate -> scale -> translate) + rlTranslatef(position.x, position.y, position.z); + //rlScalef(2.0f, 2.0f, 2.0f); + //rlRotatef(45, 0, 1, 0); + + rlBegin(RL_TRIANGLES); + rlColor4ub(color.r, color.g, color.b, color.a); + + // Front Face ----------------------------------------------------- + rlVertex3f(x-width/2, y-height/2, z+length/2); // Bottom Left + rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Right + rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left + + rlVertex3f(x+width/2, y+height/2, z+length/2); // Top Right + rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left + rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Right + + // Back Face ------------------------------------------------------ + rlVertex3f(x-width/2, y-height/2, z-length/2); // Bottom Left + rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left + rlVertex3f(x+width/2, y-height/2, z-length/2); // Bottom Right + + rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Right + rlVertex3f(x+width/2, y-height/2, z-length/2); // Bottom Right + rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left + + // Top Face ------------------------------------------------------- + rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left + rlVertex3f(x-width/2, y+height/2, z+length/2); // Bottom Left + rlVertex3f(x+width/2, y+height/2, z+length/2); // Bottom Right + + rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Right + rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left + rlVertex3f(x+width/2, y+height/2, z+length/2); // Bottom Right + + // Bottom Face ---------------------------------------------------- + rlVertex3f(x-width/2, y-height/2, z-length/2); // Top Left + rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Right + rlVertex3f(x-width/2, y-height/2, z+length/2); // Bottom Left + + rlVertex3f(x+width/2, y-height/2, z-length/2); // Top Right + rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Right + rlVertex3f(x-width/2, y-height/2, z-length/2); // Top Left + + // Right face ----------------------------------------------------- + rlVertex3f(x+width/2, y-height/2, z-length/2); // Bottom Right + rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Right + rlVertex3f(x+width/2, y+height/2, z+length/2); // Top Left + + rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Left + rlVertex3f(x+width/2, y-height/2, z-length/2); // Bottom Right + rlVertex3f(x+width/2, y+height/2, z+length/2); // Top Left + + // Left Face ------------------------------------------------------ + rlVertex3f(x-width/2, y-height/2, z-length/2); // Bottom Right + rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left + rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Right + + rlVertex3f(x-width/2, y-height/2, z+length/2); // Bottom Left + rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left + rlVertex3f(x-width/2, y-height/2, z-length/2); // Bottom Right + rlEnd(); + rlPopMatrix(); +} + +// Draw cube wires +void DrawCubeWires(Vector3 position, float width, float height, float length, Color color) +{ + float x = 0.0f; + float y = 0.0f; + float z = 0.0f; + + rlPushMatrix(); + + rlTranslatef(position.x, position.y, position.z); + //rlRotatef(45, 0, 1, 0); + + rlBegin(RL_LINES); + rlColor4ub(color.r, color.g, color.b, color.a); + + // Front Face ----------------------------------------------------- + // Bottom Line + rlVertex3f(x-width/2, y-height/2, z+length/2); // Bottom Left + rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Right + + // Left Line + rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Right + rlVertex3f(x+width/2, y+height/2, z+length/2); // Top Right + + // Top Line + rlVertex3f(x+width/2, y+height/2, z+length/2); // Top Right + rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left + + // Right Line + rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left + rlVertex3f(x-width/2, y-height/2, z+length/2); // Bottom Left + + // Back Face ------------------------------------------------------ + // Bottom Line + rlVertex3f(x-width/2, y-height/2, z-length/2); // Bottom Left + rlVertex3f(x+width/2, y-height/2, z-length/2); // Bottom Right + + // Left Line + rlVertex3f(x+width/2, y-height/2, z-length/2); // Bottom Right + rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Right + + // Top Line + rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Right + rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left + + // Right Line + rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left + rlVertex3f(x-width/2, y-height/2, z-length/2); // Bottom Left + + // Top Face ------------------------------------------------------- + // Left Line + rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left Front + rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left Back + + // Right Line + rlVertex3f(x+width/2, y+height/2, z+length/2); // Top Right Front + rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Right Back + + // Bottom Face --------------------------------------------------- + // Left Line + rlVertex3f(x-width/2, y-height/2, z+length/2); // Top Left Front + rlVertex3f(x-width/2, y-height/2, z-length/2); // Top Left Back + + // Right Line + rlVertex3f(x+width/2, y-height/2, z+length/2); // Top Right Front + rlVertex3f(x+width/2, y-height/2, z-length/2); // Top Right Back + rlEnd(); + rlPopMatrix(); +} diff --git a/src/rlgl.c b/src/rlgl.c index adccb0c7..ae016be9 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -2683,8 +2683,8 @@ void ToggleVrMode(void) if (!vrEnabled) { // Reset viewport and default projection-modelview matrices - rlViewport(0, 0, GetScreenWidth(), GetScreenHeight()); - projection = MatrixOrtho(0, GetScreenWidth(), GetScreenHeight(), 0, 0.0f, 1.0f); + rlViewport(0, 0, screenWidth, screenHeight); + projection = MatrixOrtho(0, screenWidth, screenHeight, 0, 0.0f, 1.0f); MatrixTranspose(&projection); modelview = MatrixIdentity(); } diff --git a/src/rlgl.h b/src/rlgl.h index 9afafc52..6608b4b2 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -239,6 +239,19 @@ typedef enum { OPENGL_11 = 1, OPENGL_21, OPENGL_33, OPENGL_ES_20 } GlVersion; // TraceLog message types typedef enum { INFO = 0, ERROR, WARNING, DEBUG, OTHER } TraceLogType; + + // Head Mounted Display devices + typedef enum { + HMD_DEFAULT_DEVICE = 0, + HMD_OCULUS_RIFT_DK2, + HMD_OCULUS_RIFT_CV1, + HMD_VALVE_HTC_VIVE, + HMD_SAMSUNG_GEAR_VR, + HMD_GOOGLE_CARDBOARD, + HMD_SONY_PLAYSTATION_VR, + HMD_RAZER_OSVR, + HMD_FOVE_VR, + } HmdDevice; #endif #ifdef __cplusplus -- cgit v1.2.3 From 55b9a2479ad51ed02a1d231169c81f7cb81fa193 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sat, 16 Jul 2016 22:41:13 +0200 Subject: Expose Oculus Rift functionality directly --- src/rlgl.c | 31 ++++++++++++++++++++----------- src/rlgl.h | 8 ++++++++ 2 files changed, 28 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/rlgl.c b/src/rlgl.c index ae016be9..defbe04f 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -54,12 +54,11 @@ #include // OpenGL 3 library for OSX #else #define GLAD_IMPLEMENTATION -#if defined(RLGL_STANDALONE) - #include "glad.h" // GLAD extensions loading library, includes OpenGL headers -#else - #include "external/glad.h" // GLAD extensions loading library, includes OpenGL headers -#endif - + #if defined(RLGL_STANDALONE) + #include "glad.h" // GLAD extensions loading library, includes OpenGL headers + #else + #include "external/glad.h" // GLAD extensions loading library, includes OpenGL headers + #endif #endif #endif @@ -86,6 +85,12 @@ #include "external/OculusSDK/LibOVR/Include/OVR_CAPI_GL.h" // Oculus SDK for OpenGL #endif +#if defined(RLGL_STANDALONE) + #define OCULUSAPI +#else + #define OCULUSAPI static +#endif + //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- @@ -362,11 +367,13 @@ static char *ReadTextFile(const char *fileName); // Read chars array from text f #endif #if defined(RLGL_OCULUS_SUPPORT) +#if !defined(RLGL_STANDALONE) static bool InitOculusDevice(void); // Initialize Oculus device (returns true if success) static void CloseOculusDevice(void); // Close Oculus device static void UpdateOculusTracking(void); // Update Oculus head position-orientation tracking static void BeginOculusDrawing(void); // Setup Oculus buffers for drawing static void EndOculusDrawing(void); // Finish Oculus drawing and blit framebuffer to mirror +#endif static OculusBuffer LoadOculusBuffer(ovrSession session, int width, int height); // Load Oculus required buffers static void UnloadOculusBuffer(ovrSession session, OculusBuffer buffer); // Unload texture required buffers @@ -377,6 +384,8 @@ static OculusLayer InitOculusLayer(ovrSession session); static Matrix FromOvrMatrix(ovrMatrix4f ovrM); // Convert from Oculus ovrMatrix4f struct to raymath Matrix struct #endif + + #if defined(GRAPHICS_API_OPENGL_11) static int GenerateMipmaps(unsigned char *data, int baseWidth, int baseHeight); static Color *GenNextMipmap(Color *srcData, int srcWidth, int srcHeight); @@ -3936,7 +3945,7 @@ static Color *GenNextMipmap(Color *srcData, int srcWidth, int srcHeight) #if defined(RLGL_OCULUS_SUPPORT) // Initialize Oculus device (returns true if success) -static bool InitOculusDevice(void) +OCULUSAPI bool InitOculusDevice(void) { bool oculusReady = false; @@ -3983,7 +3992,7 @@ static bool InitOculusDevice(void) } // Close Oculus device (and unload buffers) -static void CloseOculusDevice(void) +OCULUSAPI void CloseOculusDevice(void) { UnloadOculusMirror(session, mirror); // Unload Oculus mirror buffer UnloadOculusBuffer(session, buffer); // Unload Oculus texture buffers @@ -3993,7 +4002,7 @@ static void CloseOculusDevice(void) } // Update Oculus head position-orientation tracking -static void UpdateOculusTracking(void) +OCULUSAPI void UpdateOculusTracking(void) { frameIndex++; @@ -4016,7 +4025,7 @@ static void UpdateOculusTracking(void) } // Setup Oculus buffers for drawing -static void BeginOculusDrawing(void) +OCULUSAPI void BeginOculusDrawing(void) { GLuint currentTexId; int currentIndex; @@ -4030,7 +4039,7 @@ static void BeginOculusDrawing(void) } // Finish Oculus drawing and blit framebuffer to mirror -static void EndOculusDrawing(void) +OCULUSAPI void EndOculusDrawing(void) { // Unbind current framebuffer (Oculus buffer) glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); diff --git a/src/rlgl.h b/src/rlgl.h index 6608b4b2..306e5361 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -363,6 +363,7 @@ Light CreateLight(int type, Vector3 position, Color diffuse); // Create a void DestroyLight(Light light); // Destroy a light and take it out of the list void TraceLog(int msgType, const char *text, ...); +float *MatrixToFloat(Matrix mat); void InitVrDevice(int hmdDevice); // Init VR device void CloseVrDevice(void); // Close VR device @@ -371,6 +372,13 @@ void BeginVrDrawing(void); // Begin VR drawing configuration void EndVrDrawing(void); // End VR drawing process (and desktop mirror) bool IsVrDeviceReady(void); // Detect if VR device (or simulator) is ready void ToggleVrMode(void); // Enable/Disable VR experience (device or simulator) + +// Oculus Rift API for direct access the device (no simulator) +bool InitOculusDevice(void); // Initialize Oculus device (returns true if success) +void CloseOculusDevice(void); // Close Oculus device +void UpdateOculusTracking(void); // Update Oculus head position-orientation tracking +void BeginOculusDrawing(void); // Setup Oculus buffers for drawing +void EndOculusDrawing(void); // Finish Oculus drawing and blit framebuffer to mirror #endif #ifdef __cplusplus -- cgit v1.2.3 From a36cc7075ab714cee7efdc8b15380656488d87d4 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 17 Jul 2016 12:40:56 +0200 Subject: Corrected issue on drawing order --- src/shapes.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/shapes.c b/src/shapes.c index 2a4e19c2..d9b172f1 100644 --- a/src/shapes.c +++ b/src/shapes.c @@ -276,12 +276,29 @@ void DrawRectangleLines(int posX, int posY, int width, int height, Color color) // Draw a triangle void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color) { - rlBegin(RL_TRIANGLES); - rlColor4ub(color.r, color.g, color.b, color.a); - rlVertex2f(v1.x, v1.y); - rlVertex2f(v2.x, v2.y); - rlVertex2f(v3.x, v3.y); - rlEnd(); + if (rlGetVersion() == OPENGL_11) + { + rlBegin(RL_TRIANGLES); + rlColor4ub(color.r, color.g, color.b, color.a); + rlVertex2f(v1.x, v1.y); + rlVertex2f(v2.x, v2.y); + rlVertex2f(v3.x, v3.y); + rlEnd(); + } + else if ((rlGetVersion() == OPENGL_21) || (rlGetVersion() == OPENGL_33) || (rlGetVersion() == OPENGL_ES_20)) + { + rlEnableTexture(GetDefaultTexture().id); // Default white texture + + rlBegin(RL_QUADS); + rlColor4ub(color.r, color.g, color.b, color.a); + rlVertex2f(v1.x, v1.y); + rlVertex2f(v2.x, v2.y); + rlVertex2f(v2.x, v2.y); + rlVertex2f(v3.x, v3.y); + rlEnd(); + + rlDisableTexture(); + } } void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color) -- cgit v1.2.3