void OVR_Present(qboolean loading) { int fade = vr_ovr_distortion_fade->value != 0.0f; float desaturate = 0.0; if (positionTracked && trackingState.StatusFlags & ovrStatus_PositionConnected && vr_ovr_trackingloss->value > 0) { if (hasPositionLock) { float yawDiff = (fabsf(cameraYaw) - 105.0f) * 0.04; float xBound,yBound,zBound; vec_t temp[4][4], fin[4][4]; int i = 0; vec3_t euler; vec4_t pos = {0.0,0.0,0.0,1.0}; vec4_t out = {0,0,0,0}; ovrPosef camera, head; vec4_t quat; camera = trackingState.CameraPose; head = trackingState.HeadPose.ThePose; pos[0] = -(head.Position.x - camera.Position.x); pos[1] = head.Position.y - camera.Position.y; pos[2] = -(head.Position.z - camera.Position.z); VR_OVR_QuatToEuler(camera.Orientation,euler); EulerToQuat(euler,quat); QuatToRotation(quat,temp); MatrixMultiply (cameraFrustum,temp,fin); for (i=0; i<4; i++) { out[i] = fin[i][0]*pos[0] + fin[i][1]*pos[1] + fin[i][2]*pos[2] + fin[i][3]*pos[3]; } xBound = (fabsf(out[0]) - 0.6f) * 6.25f; yBound = (fabsf(out[1]) - 0.45f) * 6.25f; zBound = (fabsf(out[2] - 0.5f) - 0.5f) * 10.0f; yawDiff = clamp(yawDiff,0.0,1.0); xBound = clamp(xBound,0.0,1.0); yBound = clamp(yBound,0.0,1.0); zBound = clamp(zBound,0.0,1.0); desaturate = max(max(max(xBound,yBound),zBound),yawDiff); } else { desaturate = 1.0; } } GL_ClearColor(0.0, 0.0, 0.0, 1.0); R_Clear(); GL_SetDefaultClearColor(); { int i = 0; r_ovr_shader_t *currentShader; qboolean warp =(qboolean) (!loading && withinFrame && vr_ovr_timewarp->value); if (warp) { currentShader = &ovr_timewarp_shaders[useChroma]; ovr_WaitTillTime(frameTime.TimewarpPointSeconds); } else { currentShader = &ovr_distortion_shaders[useChroma]; } glDisableClientState (GL_COLOR_ARRAY); glDisableClientState (GL_TEXTURE_COORD_ARRAY); glDisableClientState (GL_VERTEX_ARRAY); glEnableVertexAttribArray (0); glEnableVertexAttribArray (1); glEnableVertexAttribArray (2); glEnableVertexAttribArray (3); glEnableVertexAttribArray (4); glUseProgram(currentShader->shader->program); if (hmd->Type >= ovrHmd_DK2 && vr_ovr_lumoverdrive->value) { int lastFrame = (currentFrame ? 0 : 1); static float overdriveScaleRegularRise = 0.1f; static float overdriveScaleRegularFall = 0.05f; // falling issues are hardly visible GL_MBind(1,offscreen[lastFrame].texture); glUniform2f(currentShader->uniform.OverdriveScales,overdriveScaleRegularRise, overdriveScaleRegularFall); } else { glUniform2f(currentShader->uniform.OverdriveScales,0,0); } glUniform2f(currentShader->uniform.InverseResolution,1.0/glState.currentFBO->width,1.0/glState.currentFBO->height); glUniform1i(currentShader->uniform.VignetteFade,fade); glUniform1f(currentShader->uniform.Desaturate, desaturate); for (i = 0; i < 2; i++) { // hook for rendering in different order int eye = i; GL_MBind(0,renderInfo[eye].eyeFBO.texture); R_BindIVBO(&renderInfo[eye].eye,distortion_attribs,5); glUniform2f(currentShader->uniform.EyeToSourceUVScale, renderInfo[eye].UVScaleOffset[0].x, renderInfo[eye].UVScaleOffset[0].y); glUniform2f(currentShader->uniform.EyeToSourceUVOffset, renderInfo[eye].UVScaleOffset[1].x, renderInfo[eye].UVScaleOffset[1].y); if (warp) { ovrPosef framePose = trackingState.HeadPose.ThePose; ovrMatrix4f timeWarpMatrices[2]; ovrHmd_GetEyeTimewarpMatrices(hmd, (ovrEyeType)eye, framePose, timeWarpMatrices); glUniformMatrix4fv(currentShader->uniform.EyeRotationStart,1,GL_TRUE,(GLfloat *) timeWarpMatrices[0].M); glUniformMatrix4fv(currentShader->uniform.EyeRotationEnd,1,GL_TRUE,(GLfloat *) timeWarpMatrices[1].M); } R_DrawIVBO(&renderInfo[eye].eye); R_ReleaseIVBO(); } if (vr_ovr_lumoverdrive->value) { GL_MBind(1,0); currentFrame = (currentFrame ? 0 : 1); } GL_MBind(0,0); glUseProgram(0); glDisableVertexAttribArray (0); glDisableVertexAttribArray (1); glDisableVertexAttribArray (2); glDisableVertexAttribArray (3); glDisableVertexAttribArray (4); glEnableClientState (GL_COLOR_ARRAY); glEnableClientState (GL_TEXTURE_COORD_ARRAY); glEnableClientState (GL_VERTEX_ARRAY); // glTexCoordPointer (2, GL_FLOAT, sizeof(texCoordArray[0][0]), texCoordArray[0][0]); // glVertexPointer (3, GL_FLOAT, sizeof(vertexArray[0]), vertexArray[0]); } }
void R_VR_GenerateHud() { int i, j; float numsegments = floor(vr_hud_segments->value); float horizFOV = vr_hud_fov->value; float depth = vr_hud_depth->value; float horizInterval = 2.0 / numsegments; float vertBounds = (float) hud.height / (float) hud.width; float vertInterval = horizInterval * vertBounds; int numindices = (numsegments) * (numsegments + 1) * 2 + (numsegments * 2); int numverts = (numsegments) * (numsegments + 1) * 2; vert_t *hudverts = NULL; GLushort *indices = NULL; uint32_t hudNumVerts = 0; GLushort currIndex = 0; uint32_t iboSize = sizeof(GLushort) * numindices; uint32_t vboSize = sizeof(vert_t) * numverts; // calculate coordinates for hud float xoff = tanf(horizFOV * (M_PI / 180.0f) * 0.5) * (depth); float zoff = depth * cosf(horizFOV * (M_PI / 180.0f) * 0.5); vec3_t offsetScale; VectorSet(offsetScale, xoff, xoff, zoff); hudverts = (vert_t *) malloc(vboSize); memset(hudverts, 0, vboSize); indices = (GLushort *) malloc(iboSize); memset(indices, 0, iboSize); for (j = 0; j < numsegments; j++) { float ypos, ypos1; qboolean verticalHalf = (j >= numsegments / 2); ypos = j * vertInterval - vertBounds; ypos1 = (j + 1) * vertInterval - vertBounds; for (i = 0; i <= numsegments; i++) { float xpos; vert_t vert1, vert2; GLushort vertNum1, vertNum2; qboolean horizontalHalf = (i >= (numsegments+1) / 2); xpos = i * horizInterval - 1; VectorSet(vert1.position, xpos, ypos, -1); sphereProject(vert1.position, offsetScale, vert1.position); vert1.texCoords[0] = (float) i / (float) (numsegments); vert1.texCoords[1] = (float) j / (float) (numsegments); VectorSet(vert2.position, xpos, ypos1, -1); sphereProject(vert2.position, offsetScale, vert2.position); vert2.texCoords[0] = (float) i / (float) (numsegments); vert2.texCoords[1] = (float) (j + 1) / (float) (numsegments); vertNum1 = hudNumVerts++; vertNum2 = hudNumVerts++; if (verticalHalf) { hudverts[vertNum2] = vert1; hudverts[vertNum1] = vert2; } else { hudverts[vertNum1] = vert1; hudverts[vertNum2] = vert2; } if (j > 0 && i == 0) { indices[currIndex++] = vertNum1; } indices[currIndex++] = vertNum1; indices[currIndex++] = vertNum2; if (i == numsegments && j < (numsegments - 1)) { indices[currIndex++] = vertNum2; } } } R_BindIVBO(&hudVBO,NULL,0); R_VertexData(&hudVBO,hudNumVerts * sizeof(vert_t),hudverts); R_IndexData(&hudVBO,GL_TRIANGLE_STRIP,GL_UNSIGNED_SHORT,currIndex,currIndex * sizeof(GLushort),indices); R_ReleaseIVBO(); free(hudverts); free(indices); }
void OVR_CalculateState(vr_param_t *state) { vr_param_t ovrState; float ovrScale = vr_ovr_supersample->value; int eye = 0; for (eye = 0; eye < 2; eye++) { ovrDistortionMesh meshData; ovr_vert_t *mesh = NULL; ovr_vert_t *v = NULL; ovrDistortionVertex *ov = NULL; unsigned int i = 0; float vignette_factor; if (vr_ovr_maxfov->value) { renderInfo[eye].eyeFov = hmd->MaxEyeFov[eye]; } else { renderInfo[eye].eyeFov = hmd->DefaultEyeFov[eye]; } ovrState.eyeFBO[eye] = &renderInfo[eye].eyeFBO; ovrState.renderParams[eye].projection.x.scale = 2.0f / ( renderInfo[eye].eyeFov.LeftTan + renderInfo[eye].eyeFov.RightTan ); ovrState.renderParams[eye].projection.x.offset = ( renderInfo[eye].eyeFov.LeftTan - renderInfo[eye].eyeFov.RightTan ) * ovrState.renderParams[eye].projection.x.scale * 0.5f; ovrState.renderParams[eye].projection.y.scale = 2.0f / ( renderInfo[eye].eyeFov.UpTan + renderInfo[eye].eyeFov.DownTan ); ovrState.renderParams[eye].projection.y.offset = ( renderInfo[eye].eyeFov.UpTan - renderInfo[eye].eyeFov.DownTan ) * ovrState.renderParams[eye].projection.y.scale * 0.5f; // set up rendering info eyeDesc[eye] = ovrHmd_GetRenderDesc(hmd,(ovrEyeType) eye,renderInfo[eye].eyeFov); VectorSet(ovrState.renderParams[eye].viewOffset, -eyeDesc[eye].HmdToEyeViewOffset.x, eyeDesc[eye].HmdToEyeViewOffset.y, eyeDesc[eye].HmdToEyeViewOffset.z); ovrHmd_CreateDistortionMesh(hmd, eyeDesc[eye].Eye, eyeDesc[eye].Fov, ovrDistortionCap_Chromatic | ovrDistortionCap_SRGB | ovrDistortionCap_TimeWarp | ovrDistortionCap_Vignette, &meshData); mesh = (ovr_vert_t *) Z_TagMalloc(sizeof(ovr_vert_t) * meshData.VertexCount, TAG_RENDERER); v = mesh; ov = meshData.pVertexData; for (i = 0; i < meshData.VertexCount; i++) { // DK2 display not rotated - rotate the coordinates manually if (vid.width < vid.height) { v->pos.x = -ov->ScreenPosNDC.y; v->pos.y = ov->ScreenPosNDC.x; } else { v->pos.x = ov->ScreenPosNDC.x; v->pos.y = ov->ScreenPosNDC.y; } v->texR = (*(ovrVector2f*)&ov->TanEyeAnglesR); v->texG = (*(ovrVector2f*)&ov->TanEyeAnglesG); v->texB = (*(ovrVector2f*)&ov->TanEyeAnglesB); vignette_factor = ov->VignetteFactor; if (vignette_factor < 0) vignette_factor = 0; v->color[0] = v->color[1] = v->color[2] = (GLubyte)(vignette_factor * 255.99f); v->color[3] = (GLubyte)( ov->TimeWarpFactor * 255.99f ); v++; ov++; } R_BindIVBO(&renderInfo[eye].eye,NULL,0); R_VertexData(&renderInfo[eye].eye,sizeof(ovr_vert_t) * meshData.VertexCount, mesh); R_IndexData(&renderInfo[eye].eye,GL_TRIANGLES,GL_UNSIGNED_SHORT,meshData.IndexCount,sizeof(uint16_t) * meshData.IndexCount,meshData.pIndexData); R_ReleaseIVBO(); Z_Free(mesh); ovrHmd_DestroyDistortionMesh( &meshData ); } { // calculate this to give the engine a rough idea of the fov float combinedTanHalfFovHorizontal = max ( max ( renderInfo[0].eyeFov.LeftTan, renderInfo[0].eyeFov.RightTan ), max ( renderInfo[1].eyeFov.LeftTan, renderInfo[1].eyeFov.RightTan ) ); float combinedTanHalfFovVertical = max ( max ( renderInfo[0].eyeFov.UpTan, renderInfo[0].eyeFov.DownTan ), max ( renderInfo[1].eyeFov.UpTan, renderInfo[1].eyeFov.DownTan ) ); float horizontalFullFovInRadians = 2.0f * atanf ( combinedTanHalfFovHorizontal ); float fovX = RAD2DEG(horizontalFullFovInRadians); float fovY = RAD2DEG(2.0 * atanf(combinedTanHalfFovVertical)); ovrState.aspect = combinedTanHalfFovHorizontal / combinedTanHalfFovVertical; ovrState.viewFovY = fovY; ovrState.viewFovX = fovX; ovrState.pixelScale = ovrScale * vid.width / (float) hmd->Resolution.w; } *state = ovrState; }
void R_VR_DrawHud() { float fov = vr_hud_fov->value; float depth = vr_hud_depth->value; int numsegments = vr_hud_segments->value; int index = 0; vec_t mat[4][4], temp[4][4]; if (!vr_enabled->value) return; // enable alpha testing so only pixels that have alpha info get written out // prevents black pixels from being rendered into the view GL_Enable(GL_ALPHA_TEST); GL_AlphaFunc(GL_GREATER, 0.0f); // if hud transparency is enabled, enable blending if (vr_hud_transparency->value) { GL_Enable(GL_BLEND); GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } // bind the texture GL_MBind(0, hud.texture); // disable this for the loading screens since they are not at 60fps if ((vr_hud_bounce->value > 0) && !loadingScreen && ((int32_t) vr_aimmode->value > 0)) { // load the quaternion directly into a rotation matrix vec4_t q; VR_GetOrientationEMAQuat(q); q[2] = -q[2]; QuatToRotation(q, mat); } else { // identity matrix TranslationMatrix(0,0,0,mat); } // set proper mode // glEnableClientState (GL_TEXTURE_COORD_ARRAY); // glEnableClientState (GL_VERTEX_ARRAY); glDisableClientState (GL_COLOR_ARRAY); // bind vertex buffer and set tex coord parameters R_BindIVBO(&hudVBO,NULL,0); glTexCoordPointer(2,GL_FLOAT,sizeof(vert_t),(void *)( sizeof(GL_FLOAT) * 3)); glVertexPointer(3,GL_FLOAT,sizeof(vert_t),NULL); for (index = 0; index < 2; index++) { // bind the eye FBO R_BindFBO(vrState.eyeFBO[index]); // set the perspective matrix for that eye R_PerspectiveScale(vrState.renderParams[index].projection, 0.24, 251.0); // build the eye translation matrix if (vr_autoipd->value) { TranslationMatrix(-vrState.renderParams[index].viewOffset[0], vrState.renderParams[index].viewOffset[1], vrState.renderParams[index].viewOffset[2], temp); } else { float viewOffset = (vr_ipd->value / 2000.0); TranslationMatrix((-1 + index * 2) * -viewOffset, 0, 0, temp); } // load the view matrix MatrixMultiply(temp, mat, temp); GL_LoadMatrix(GL_MODELVIEW, temp); // draw the hud for that eye R_DrawIVBO(&hudVBO); } // teardown R_ReleaseIVBO(); GL_MBind(0, 0); glEnableClientState (GL_COLOR_ARRAY); glTexCoordPointer (2, GL_FLOAT, sizeof(texCoordArray[0][0]), texCoordArray[0][0]); glVertexPointer (3, GL_FLOAT, sizeof(vertexArray[0]), vertexArray[0]); GL_Disable(GL_BLEND); GL_Disable(GL_ALPHA_TEST); }