| @ -0,0 +1,280 @@ | |||||
| #include <stdio.h> | |||||
| #include <stdlib.h> | |||||
| #include <string.h> | |||||
| #include "glad.h" // Extensions loading library | |||||
| #include <GLFW/glfw3.h> | |||||
| #include "OculusSDK/LibOVR/Include/OVR_CAPI_GL.h" // Oculus SDK for OpenGL | |||||
| #define FAIL(X) printf(X); | |||||
| typedef struct Vector2 { | |||||
| float x; | |||||
| float y; | |||||
| } Vector2; | |||||
| typedef struct Matrix { | |||||
| float m0, m4, m8, m12; | |||||
| float m1, m5, m9, m13; | |||||
| float m2, m6, m10, m14; | |||||
| float m3, m7, m11, m15; | |||||
| } Matrix; | |||||
| // RiftManagerApp class | |||||
| ovrSession session; | |||||
| ovrHmdDesc hmdDesc; | |||||
| ovrGraphicsLuid luid; | |||||
| // RiftApp class | |||||
| GLuint fbo = 0; | |||||
| GLuint depthBuffer = 0; | |||||
| ovrTextureSwapChain eyeTexture; | |||||
| GLuint mirrorFbo = 0; | |||||
| ovrMirrorTexture mirrorTexture; | |||||
| ovrEyeRenderDesc eyeRenderDescs[2]; | |||||
| Matrix eyeProjections[2]; | |||||
| ovrLayerEyeFov eyeLayer; | |||||
| ovrViewScaleDesc viewScaleDesc; | |||||
| Vector2 renderTargetSize; | |||||
| Vector2 mirrorSize; | |||||
| // GlfwApp class | |||||
| GLFWwindow *window = NULL; | |||||
| unsigned int frame = 0; | |||||
| static void ErrorCallback(int error, const char* description) | |||||
| { | |||||
| fputs(description, stderr); | |||||
| } | |||||
| 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); | |||||
| } | |||||
| } | |||||
| // Execute our example class | |||||
| int main() | |||||
| { | |||||
| if (!OVR_SUCCESS(ovr_Initialize(NULL))) FAIL("Failed to initialize the Oculus SDK\n"); | |||||
| //result = ExampleApp().run(); // class ExampleApp : public RiftApp : public GlfwApp, public RiftManagerApp | |||||
| if (!OVR_SUCCESS(ovr_Create(&session, &luid))) FAIL("Unable to create HMD session\n"); | |||||
| hmdDesc = ovr_GetHmdDesc(session); | |||||
| // RiftApp() constructor | |||||
| viewScaleDesc.HmdSpaceToWorldScaleInMeters = 1.0f; | |||||
| memset(&eyeLayer, 0, sizeof(ovrLayerEyeFov)); | |||||
| eyeLayer.Header.Type = ovrLayerType_EyeFov; | |||||
| eyeLayer.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft; | |||||
| //ovr::for_each_eye([&](ovrEyeType eye) | |||||
| for (int eye = 0; eye < 2; eye++) | |||||
| { | |||||
| eyeRenderDescs[eye] = ovr_GetRenderDesc(session, eye, hmdDesc.DefaultEyeFov[eye]); | |||||
| ovrMatrix4f ovrPerspectiveProjection = ovrMatrix4f_Projection(eyeRenderDescs[eye].Fov, 0.01f, 1000.0f, ovrProjection_ClipRangeOpenGL); | |||||
| //eyeProjections[eye] = ovr::toGlm(ovrPerspectiveProjection); | |||||
| viewScaleDesc.HmdToEyeOffset[eye] = eyeRenderDescs[eye].HmdToEyeOffset; | |||||
| eyeLayer.Fov[eye] = eyeRenderDescs[eye].Fov; | |||||
| ovrSizei eyeSize = ovr_GetFovTextureSize(session, eye, eyeLayer.Fov[eye], 1.0f); | |||||
| eyeLayer.Viewport[eye].Size = eyeSize; | |||||
| eyeLayer.Viewport[eye].Pos.x = renderTargetSize.x; | |||||
| eyeLayer.Viewport[eye].Pos.y = 0; | |||||
| renderTargetSize.y = renderTargetSize.y; // std::max(renderTargetSize.y, (uint32_t)eyeSize.h); | |||||
| renderTargetSize.x += eyeSize.w; | |||||
| } | |||||
| // Make the on screen window 1/4 the resolution of the render target | |||||
| mirrorSize = renderTargetSize; | |||||
| mirrorSize.x /= 2; | |||||
| mirrorSize.y /= 2; | |||||
| // GLFWApp() constructor | |||||
| if (!glfwInit()) FAIL("Failed to initialize GLFW\n"); // Initialize the GLFW system for creating and positioning windows | |||||
| glfwSetErrorCallback(ErrorCallback); | |||||
| ////preCreate(); | |||||
| glfwWindowHint(GLFW_DEPTH_BITS, 16); | |||||
| glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); | |||||
| glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); | |||||
| glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); | |||||
| glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE); | |||||
| //***************window = createRenderingTarget(windowSize, windowPosition); //GLFWwindow *createRenderingTarget(uvec2 & size, ivec2 & pos) = 0; //glfw::createWindow(_mirrorSize); | |||||
| /* | |||||
| GLFWwindow *createWindow(const uvec2 &size, const ivec2 &position = ivec2(INT_MIN)) | |||||
| { | |||||
| GLFWwindow *window = glfwCreateWindow(size.x, size.y, "glfw", NULL, NULL); // size = mirrorSize | |||||
| if (!window) FAIL("Unable to create rendering window\n"); | |||||
| if ((position.x > INT_MIN) && (position.y > INT_MIN)) // INT_MIN = -32767 // #define INT_MIN (-2147483647 - 1) | |||||
| { | |||||
| glfwSetWindowPos(window, position.x, position.y); | |||||
| } | |||||
| return window; | |||||
| } | |||||
| */ | |||||
| window = glfwCreateWindow(mirrorSize.x, mirrorSize.y, "glfw", NULL, NULL); | |||||
| if (!window) FAIL("Unable to create OpenGL window\n"); | |||||
| ////postCreate(); | |||||
| //glfwSetWindowUserPointer(window, this); //// Useful to hack input callbacks | |||||
| glfwSetKeyCallback(window, KeyCallback); | |||||
| glfwMakeContextCurrent(window); | |||||
| // Initialize the OpenGL extensions | |||||
| if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) FAIL("GLAD failed\n"); | |||||
| /* | |||||
| glewExperimental = GL_TRUE; | |||||
| if (0 != glewInit()) FAIL("Failed to initialize GLEW\n"); | |||||
| glGetError(); | |||||
| if (GLEW_KHR_debug) | |||||
| { | |||||
| GLint v; | |||||
| glGetIntegerv(GL_CONTEXT_FLAGS, &v); | |||||
| if (v & GL_CONTEXT_FLAG_DEBUG_BIT) glDebugMessageCallback(glDebugCallbackHandler, this); | |||||
| } | |||||
| */ | |||||
| ////initGl(); | |||||
| { | |||||
| // RiftApp::InitGL() -----> | |||||
| //GlfwApp::initGl(); // virtual | |||||
| // Disable the v-sync for buffer swap | |||||
| glfwSwapInterval(0); | |||||
| ovrTextureSwapChainDesc desc = {}; | |||||
| desc.Type = ovrTexture_2D; | |||||
| desc.ArraySize = 1; | |||||
| desc.Width = renderTargetSize.x; | |||||
| desc.Height = renderTargetSize.y; | |||||
| desc.MipLevels = 1; | |||||
| desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB; | |||||
| desc.SampleCount = 1; | |||||
| desc.StaticImage = ovrFalse; | |||||
| ovrResult result = ovr_CreateTextureSwapChainGL(session, &desc, &eyeTexture); | |||||
| eyeLayer.ColorTexture[0] = eyeTexture; | |||||
| if (!OVR_SUCCESS(result)) FAIL("Failed to create swap textures"); | |||||
| int length = 0; | |||||
| result = ovr_GetTextureSwapChainLength(session, eyeTexture, &length); | |||||
| if (!OVR_SUCCESS(result) || !length) FAIL("Unable to count swap chain textures"); | |||||
| for (int i = 0; i < length; ++i) | |||||
| { | |||||
| GLuint chainTexId; | |||||
| ovr_GetTextureSwapChainBufferGL(session, eyeTexture, i, &chainTexId); | |||||
| glBindTexture(GL_TEXTURE_2D, chainTexId); | |||||
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |||||
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |||||
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |||||
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |||||
| } | |||||
| glBindTexture(GL_TEXTURE_2D, 0); | |||||
| // Set up the framebuffer object | |||||
| glGenFramebuffers(1, &fbo); | |||||
| glGenRenderbuffers(1, &depthBuffer); | |||||
| glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); | |||||
| glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer); | |||||
| glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, renderTargetSize.x, renderTargetSize.y); | |||||
| glBindRenderbuffer(GL_RENDERBUFFER, 0); | |||||
| glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer); | |||||
| glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); | |||||
| ovrMirrorTextureDesc mirrorDesc; | |||||
| memset(&mirrorDesc, 0, sizeof(mirrorDesc)); | |||||
| mirrorDesc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB; | |||||
| mirrorDesc.Width = mirrorSize.x; | |||||
| mirrorDesc.Height = mirrorSize.y; | |||||
| if (!OVR_SUCCESS(ovr_CreateMirrorTextureGL(session, &mirrorDesc, &mirrorTexture))) FAIL("Could not create mirror texture"); | |||||
| glGenFramebuffers(1, &mirrorFbo); | |||||
| // RiftApp::InitGL() <------ | |||||
| glClearColor(0.2f, 0.2f, 0.2f, 0.0f); | |||||
| glEnable(GL_DEPTH_TEST); | |||||
| ovr_RecenterTrackingOrigin(session); | |||||
| // TODO: Init cube scene --> cubeScene = std::shared_ptr<ColorCubeScene>(new ColorCubeScene()); | |||||
| } | |||||
| while (!glfwWindowShouldClose(window)) | |||||
| { | |||||
| frame++; | |||||
| glfwPollEvents(); | |||||
| //update(); | |||||
| //draw(); ------> | |||||
| ovrPosef eyePoses[2]; | |||||
| ovr_GetEyePoses(session, frame, ovrTrue, viewScaleDesc.HmdToEyeOffset, eyePoses, &eyeLayer.SensorSampleTime); | |||||
| int curIndex; | |||||
| ovr_GetTextureSwapChainCurrentIndex(session, eyeTexture, &curIndex); | |||||
| GLuint curTexId; | |||||
| ovr_GetTextureSwapChainBufferGL(session, eyeTexture, curIndex, &curTexId); | |||||
| glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); | |||||
| glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, curTexId, 0); | |||||
| glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | |||||
| for (int eye = 0; eye < 2; eye++) | |||||
| { | |||||
| glViewport(eyeLayer.Viewport[eye].Pos.x, eyeLayer.Viewport[eye].Pos.y, | |||||
| eyeLayer.Viewport[eye].Size.w, eyeLayer.Viewport[eye].Size.h); | |||||
| eyeLayer.RenderPose[eye] = eyePoses[eye]; | |||||
| //renderScene(_eyeProjections[eye], ovr::toGlm(eyePoses[eye])); --> cubeScene->render(projection, glm::inverse(headPose)); | |||||
| } | |||||
| glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); | |||||
| glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); | |||||
| ovr_CommitTextureSwapChain(session, eyeTexture); | |||||
| ovrLayerHeader *headerList = &eyeLayer.Header; | |||||
| ovr_SubmitFrame(session, frame, &viewScaleDesc, &headerList, 1); | |||||
| GLuint mirrorTextureId; | |||||
| ovr_GetMirrorTextureBufferGL(session, mirrorTexture, &mirrorTextureId); | |||||
| glBindFramebuffer(GL_READ_FRAMEBUFFER, mirrorFbo); | |||||
| glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mirrorTextureId, 0); | |||||
| glBlitFramebuffer(0, 0, mirrorSize.x, mirrorSize.y, 0, mirrorSize.y, mirrorSize.x, 0, GL_COLOR_BUFFER_BIT, GL_NEAREST); | |||||
| glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); | |||||
| //draw() <------------- | |||||
| glfwSwapBuffers(window); //finishFrame(); | |||||
| } | |||||
| //shutdownGl(); // Delete scene: cubeScene.reset(); | |||||
| glfwDestroyWindow(window); | |||||
| glfwTerminate(); | |||||
| ovr_Destroy(session); | |||||
| ovr_Shutdown(); | |||||
| return 0; | |||||
| } | |||||