Hello,
So I am trying to run some sample code for working with an Oculus Rift and I get an Access Violation error on this line (also marked in code below) when I run the example.
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, l_TextureId, 0);
The code compiles without issue.
Any ideas?
Thank you.
// OpenGLOculusRift.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <Windows.h>
#include <GL/glew.h>
#define GLFW_EXPOSE_NATIVE_WIN32
#define GLFW_EXPOSE_NATIVE_WGL
#include <GLFW/glfw3.h>
#include <GLFW/glfw3native.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <OVR_CAPI.h>
#include <OVR_CAPI_GL.h>
#include <OVR.h>
// =============================================================================
static void ErrorCallback(int p_Error, const char* p_Description)
{
fputs(p_Description, stderr);
}
// =============================================================================
static void KeyCallback(GLFWwindow* p_Window, int p_Key, int p_Scancode, int p_Action, int p_Mods)
{
if (p_Key == GLFW_KEY_ESCAPE && p_Action == GLFW_PRESS)
glfwSetWindowShouldClose(p_Window, GL_TRUE);
}
// =============================================================================
static void RenderCube(float p_Size)
{
const float l_SizeDiv2 = p_Size*0.5f;
// A cube...
glBegin(GL_QUADS);
glNormal3f(0.0f, 0.0f, 1.0f);
glVertex3f(l_SizeDiv2, l_SizeDiv2, l_SizeDiv2);
glVertex3f(-l_SizeDiv2, l_SizeDiv2, l_SizeDiv2);
glVertex3f(-l_SizeDiv2, -l_SizeDiv2, l_SizeDiv2);
glVertex3f(l_SizeDiv2, -l_SizeDiv2, l_SizeDiv2);
glEnd();
glBegin(GL_QUADS);
glNormal3f(0.0f, 0.0f, -1.0f);
glVertex3f(-l_SizeDiv2, -l_SizeDiv2, -l_SizeDiv2);
glVertex3f(-l_SizeDiv2, l_SizeDiv2, -l_SizeDiv2);
glVertex3f(l_SizeDiv2, l_SizeDiv2, -l_SizeDiv2);
glVertex3f(l_SizeDiv2, -l_SizeDiv2, -l_SizeDiv2);
glEnd();
glBegin(GL_QUADS);
glNormal3f(0.0f, 1.0f, 0.0f);
glVertex3f(l_SizeDiv2, l_SizeDiv2, l_SizeDiv2);
glVertex3f(l_SizeDiv2, l_SizeDiv2, -l_SizeDiv2);
glVertex3f(-l_SizeDiv2, l_SizeDiv2, -l_SizeDiv2);
glVertex3f(-l_SizeDiv2, l_SizeDiv2, l_SizeDiv2);
glEnd();
glBegin(GL_QUADS);
glNormal3f(0.0f, -1.0f, 0.0f);
glVertex3f(-l_SizeDiv2, -l_SizeDiv2, -l_SizeDiv2);
glVertex3f(l_SizeDiv2, -l_SizeDiv2, -l_SizeDiv2);
glVertex3f(l_SizeDiv2, -l_SizeDiv2, l_SizeDiv2);
glVertex3f(-l_SizeDiv2, -l_SizeDiv2, l_SizeDiv2);
glEnd();
glBegin(GL_QUADS);
glNormal3f(1.0f, 0.0f, 0.0f);
glVertex3f(l_SizeDiv2, l_SizeDiv2, l_SizeDiv2);
glVertex3f(l_SizeDiv2, -l_SizeDiv2, l_SizeDiv2);
glVertex3f(l_SizeDiv2, -l_SizeDiv2, -l_SizeDiv2);
glVertex3f(l_SizeDiv2, l_SizeDiv2, -l_SizeDiv2);
glEnd();
glBegin(GL_QUADS);
glNormal3f(-1.0f, 0.0f, 0.0f);
glVertex3f(-l_SizeDiv2, -l_SizeDiv2, -l_SizeDiv2);
glVertex3f(-l_SizeDiv2, -l_SizeDiv2, l_SizeDiv2);
glVertex3f(-l_SizeDiv2, l_SizeDiv2, l_SizeDiv2);
glVertex3f(-l_SizeDiv2, l_SizeDiv2, -l_SizeDiv2);
glEnd();
}
// ============================================================================
static void SetOpenGLState(void)
{
// Some state...
glEnable(GL_CULL_FACE);
glEnable(GL_LIGHTING);
glDisable(GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// Some (stationary) lights...
GLfloat l_Light0Position[] = { 5.0f, 6.0f, 3.0f, 0.0f };
GLfloat l_Light0Diffuse[] = { 1.0f, 0.8f, 0.6f, 1.0f };
glLightfv(GL_LIGHT0, GL_POSITION, l_Light0Position);
glLightfv(GL_LIGHT0, GL_DIFFUSE, l_Light0Diffuse);
glEnable(GL_LIGHT0);
GLfloat l_Light1Position[] = { -5.0f, -6.0f, 5.0f, 0.0f };
GLfloat l_Light1Diffuse[] = { 0.6f, 0.8f, 1.0f, 1.0f };
glLightfv(GL_LIGHT1, GL_POSITION, l_Light1Position);
glLightfv(GL_LIGHT1, GL_DIFFUSE, l_Light1Diffuse);
glEnable(GL_LIGHT1);
// Material...
GLfloat l_MaterialSpecular[] = { 0.3f, 0.3f, 0.3f, 1.0f };
GLfloat l_MaterialShininess[] = { 10.0f };
glMaterialfv(GL_FRONT, GL_SPECULAR, l_MaterialSpecular);
glMaterialfv(GL_FRONT, GL_SHININESS, l_MaterialShininess);
}
// =============================================================================
int _tmain(int argc, _TCHAR* argv[])
{
// Initialize LibOVR...
ovr_Initialize();
ovrHmd l_Hmd = ovrHmd_Create(0);
if (!l_Hmd) l_Hmd = ovrHmd_CreateDebug(ovrHmd_DK1);
ovrHmdDesc l_HmdDesc;
ovrHmd_GetDesc(l_Hmd, &l_HmdDesc);
ovrHmd_StartSensor(l_Hmd, ovrHmdCap_Orientation, 0);
GLFWwindow* l_Window;
glfwSetErrorCallback(ErrorCallback);
if (!glfwInit()) exit(EXIT_FAILURE);
ovrSizei l_ClientSize;
l_ClientSize.w = l_HmdDesc.Resolution.w; // 1280 for DK1...
l_ClientSize.h = l_HmdDesc.Resolution.h; // 800 for DK1...
// Create a fullscreen window with the Oculus Rift resolution...
l_Window = glfwCreateWindow(l_ClientSize.w, l_ClientSize.h, "GLFW Oculus Rift Test", NULL, NULL);
if (!l_Window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
// Print the OpenGL version we are using...
int l_Major = glfwGetWindowAttrib(l_Window, GLFW_CONTEXT_VERSION_MAJOR);
int l_Minor = glfwGetWindowAttrib(l_Window, GLFW_CONTEXT_VERSION_MINOR);
printf("OpenGL: %d.%d
", l_Major, l_Minor);
// Make the context current for this window...
glfwMakeContextCurrent(l_Window);
// Create some lights, materials, etc...
SetOpenGLState();
// Don't forget to initialize Glew...
glewInit();
// We will do some offscreen rendering, setup FBO...
ovrSizei l_TextureSizeLeft = ovrHmd_GetFovTextureSize(l_Hmd, ovrEye_Left, l_HmdDesc.DefaultEyeFov[0], 1.0f);
ovrSizei l_TextureSizeRight = ovrHmd_GetFovTextureSize(l_Hmd, ovrEye_Right, l_HmdDesc.DefaultEyeFov[1], 1.0f);
ovrSizei l_TextureSize;
l_TextureSize.w = l_TextureSizeLeft.w + l_TextureSizeRight.w;
l_TextureSize.h = (l_TextureSizeLeft.h>l_TextureSizeRight.h ? l_TextureSizeLeft.h : l_TextureSizeRight.h);
// Create FBO...
GLuint l_FBOId;
glGenFramebuffers(1, &l_FBOId);
glBindFramebuffer(GL_FRAMEBUFFER, l_FBOId);
// The texture we're going to render to...
GLuint l_TextureId;
glGenTextures(1, &l_TextureId);
// "Bind" the newly created texture : all future texture functions will modify this texture...
glBindTexture(GL_TEXTURE_2D, l_TextureId);
// Give an empty image to OpenGL (the last "0")
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, l_TextureSize.w, l_TextureSize.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
// Linear filtering...
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// Create Depth Buffer...
GLuint l_DepthBufferId;
glGenRenderbuffers(1, &l_DepthBufferId);
glBindRenderbuffer(GL_RENDERBUFFER, l_DepthBufferId);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, l_TextureSize.w, l_TextureSize.h);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, l_DepthBufferId);
// Set the texture as our colour attachment #0...
/*
Access Violation Occurs Here.
*/
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, l_TextureId, 0);
/*
End Access Violation
*/
// Set the list of draw buffers...
GLenum l_GLDrawBuffers[1] = { GL_COLOR_ATTACHMENT0 };
glDrawBuffers(1, l_GLDrawBuffers); // "1" is the size of DrawBuffers
// Unbind...
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// Oculus Rift eye configurations...
ovrEyeDesc l_Eyes[2];
l_Eyes[0].Eye = ovrEye_Left;
l_Eyes[1].Eye = ovrEye_Right;
l_Eyes[0].Fov = l_HmdDesc.DefaultEyeFov[0];
l_Eyes[1].Fov = l_HmdDesc.DefaultEyeFov[1];
l_Eyes[0].TextureSize.w = l_TextureSize.w;
l_Eyes[0].TextureSize.h = l_TextureSize.h;
l_Eyes[1].TextureSize.w = l_TextureSize.w;
l_Eyes[1].TextureSize.h = l_TextureSize.h;
l_Eyes[0].RenderViewport.Pos.x = 0;
l_Eyes[0].RenderViewport.Pos.y = 0;
l_Eyes[1].RenderViewport.Pos.x = (l_TextureSize.w + 1) / 2;
l_Eyes[1].RenderViewport.Pos.y = 0;
l_Eyes[0].RenderViewport.Size.w = l_TextureSize.w / 2;
l_Eyes[0].RenderViewport.Size.h = l_TextureSize.h;
l_Eyes[1].RenderViewport.Size.w = l_Eyes[0].RenderViewport.Size.w;
l_Eyes[1].RenderViewport.Size.h = l_Eyes[0].RenderViewport.Size.h;
ovrGLConfig l_Cfg;
l_Cfg.OGL.Header.API = ovrRenderAPI_OpenGL;
l_Cfg.OGL.Header.Multisample = 0;
l_Cfg.OGL.Header.RTSize.w = l_ClientSize.w;
l_Cfg.OGL.Header.RTSize.h = l_ClientSize.h;
l_Cfg.OGL.WglContext = glfwGetWGLContext(l_Window);
l_Cfg.OGL.Window = glfwGetWin32Window(l_Window);
l_Cfg.OGL.GdiDc = GetDC(l_Cfg.OGL.Window);
int l_RenderCaps = 0;
int l_DistortionCaps = ovrDistortion_Chromatic | ovrDistortion_TimeWarp;
ovrEyeRenderDesc l_EyeRenderDesc[2];
ovrHmd_ConfigureRendering(l_Hmd, &l_Cfg.Config, l_RenderCaps, l_DistortionCaps, l_Eyes, l_EyeRenderDesc);
ovrGLTexture l_EyeTexture[2];
l_EyeTexture[0].OGL.Header.API = ovrRenderAPI_OpenGL;
l_EyeTexture[0].OGL.Header.TextureSize.w = l_TextureSize.w;
l_EyeTexture[0].OGL.Header.TextureSize.h = l_TextureSize.h;
l_EyeTexture[0].OGL.Header.RenderViewport = l_Eyes[0].RenderViewport;
l_EyeTexture[0].OGL.TexId = l_TextureId;
// Right eye uses the same texture, but a different rendering viewport...
l_EyeTexture[1] = l_EyeTexture[0];
l_EyeTexture[1].OGL.Header.RenderViewport = l_Eyes[1].RenderViewport;
glfwSetKeyCallback(l_Window, KeyCallback);
GLfloat l_SpinX;
GLfloat l_SpinY;
while (!glfwWindowShouldClose(l_Window))
{
l_SpinX = (GLfloat)fmod(glfwGetTime()*17.0, 360.0);
l_SpinY = (GLfloat)fmod(glfwGetTime()*23.0, 360.0);
ovrFrameTiming m_HmdFrameTiming = ovrHmd_BeginFrame(l_Hmd, 0);
// Bind the FBO...
glBindFramebuffer(GL_FRAMEBUFFER, l_FBOId);
// Clear...
glClearColor(0.2f, 0.3f, 0.4f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
for (int l_EyeIndex = 0; l_EyeIndex<ovrEye_Count; l_EyeIndex++)
{
ovrEyeType l_Eye = l_HmdDesc.EyeRenderOrder[l_EyeIndex];
ovrPosef l_EyePose = ovrHmd_BeginEyeRender(l_Hmd, l_Eye);
glViewport(l_EyeRenderDesc[l_Eye].Desc.RenderViewport.Pos.x, // StartX
l_EyeRenderDesc[l_Eye].Desc.RenderViewport.Pos.y, // StartY
l_EyeRenderDesc[l_Eye].Desc.RenderViewport.Size.w, // Width
l_EyeRenderDesc[l_Eye].Desc.RenderViewport.Size.h // Height
);
// Get Projection and ModelView matrici from the device...
OVR::Matrix4f l_ProjectionMatrix = ovrMatrix4f_Projection(
l_EyeRenderDesc[l_Eye].Desc.Fov, 0.3f, 100.0f, true);
OVR::Quatf l_Orientation = OVR::Quatf(l_EyePose.Orientation);
OVR::Matrix4f l_ModelViewMatrix = OVR::Matrix4f(l_Orientation.Inverted());
// Pass matrici on to OpenGL...
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMultMatrixf(&(l_ProjectionMatrix.Transposed().M[0][0]));
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// Translate for specific eye based on IPD...
glTranslatef(l_EyeRenderDesc[l_Eye].ViewAdjust.x,
l_EyeRenderDesc[l_Eye].ViewAdjust.y,
l_EyeRenderDesc[l_Eye].ViewAdjust.z);
// Multiply with orientation retrieved from sensor...
glMultMatrixf(&(l_ModelViewMatrix.Transposed().M[0][0]));
// Move back a bit to show scene in front of us...
glTranslatef(0.0f, 0.0f, -3.0f);
// Make the cube spin...
glRotatef(l_SpinX, 1.0f, 0.0f, 0.0f);
glRotatef(l_SpinY, 0.0f, 1.0f, 0.0f);
// Render...
RenderCube(1.0f);
ovrHmd_EndEyeRender(l_Hmd, l_Eye, l_EyePose, &l_EyeTexture[l_Eye].Texture);
}
// Unbind the FBO, back to normal drawing...
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// Oculus wants CW orientations, avoid the problem by turning of culling...
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
ovrHmd_EndFrame(l_Hmd);
// Restore state after Oculus did it's work (-sigh-)...
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glClearDepth(1);
glUseProgramObjectARB(0);
glfwPollEvents();
}
glfwDestroyWindow(l_Window);
glfwTerminate();
ovrHmd_Destroy(l_Hmd);
ovr_Shutdown();
exit(EXIT_SUCCESS);
return 0;
}