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]); } }
/* ============= RB_RenderWarpSurface backend for R_DrawWarpSurface ============= */ void RB_RenderWarpSurface (msurface_t *fa) { float args[7] = {0,0.05,0,0,0.04,0,0}; float alpha = colorArray[0][3]; image_t *image = R_TextureAnimation (fa); qboolean light = r_warp_lighting->value && !(fa->texinfo->flags & SURF_NOLIGHTENV); qboolean texShaderWarpNV = glConfig.NV_texshaders && glConfig.multitexture && r_pixel_shader_warp->value; qboolean texShaderWarpARB = glConfig.arb_fragment_program && glConfig.multitexture && r_pixel_shader_warp->value; qboolean texShaderWarp = (texShaderWarpNV || texShaderWarpARB); if (texShaderWarpNV && texShaderWarpARB) texShaderWarpARB = (r_pixel_shader_warp->value == 1.0f); if (rb_vertex == 0 || rb_index == 0) // nothing to render return; c_brush_calls++; // Psychospaz's vertex lighting if (light) { GL_ShadeModel (GL_SMOOTH); if (!texShaderWarp) R_SetVertexRGBScale (true); } /* Texture Shader waterwarp Damn this looks fantastic WHY texture shaders? because I can! - MrG */ if (texShaderWarpARB) { GL_SelectTexture(0); GL_MBind(0, image->texnum); GL_EnableTexture(1); GL_MBind(1, dst_texture_ARB); GL_Enable (GL_FRAGMENT_PROGRAM_ARB); qglBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, fragment_programs[F_PROG_WARP]); qglProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, r_rgbscale->value, r_rgbscale->value, r_rgbscale->value, 1.0); } else if (texShaderWarpNV) { GL_SelectTexture(0); GL_MBind(0, dst_texture_NV); qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D); GL_EnableTexture(1); GL_MBind(1, image->texnum); qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D); qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_OFFSET_TEXTURE_2D_NV); qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB); qglTexEnvfv(GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV, &args[1]); // Psychospaz's lighting // use this so that the new water isnt so bright anymore // We won't bother check for the extensions availabiliy, as the hardware required // to make it this far definately supports this as well if (light) qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); GL_Enable (GL_TEXTURE_SHADER_NV); } else GL_Bind(image->texnum); RB_DrawArrays (); // MrG - texture shader waterwarp if (texShaderWarpARB) { GL_Disable (GL_FRAGMENT_PROGRAM_ARB); GL_DisableTexture(1); GL_SelectTexture(0); } else if (texShaderWarpNV) { GL_DisableTexture(1); if (light) qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); // Psychospaz's lighting GL_SelectTexture(0); GL_Disable (GL_TEXTURE_SHADER_NV); } // Psychospaz's vertex lighting if (light) { GL_ShadeModel (GL_FLAT); if (!texShaderWarp) R_SetVertexRGBScale (false); } RB_DrawMeshTris (); rb_vertex = rb_index = 0; }
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); }
// MPO : this is my version... void EmitWaterPolys (msurface_t *fa) { //============================== glpoly_t *p; glpoly_t *bp; float *v; int i; float s; float t; float os; float ot; float scroll; float rdt = r_newrefdef.time; float zValue = 0.0; // height of water qboolean waterNotFlat = false; qboolean flowing; //============================== if (g_drawing_refl) return; // we don't want any water drawn while we are doing our reflection if (fa->texinfo->flags & SURF_FLOWING) { scroll = -64.0f * ((r_newrefdef.time * 0.5f) - (int)(r_newrefdef.time * 0.5f)); flowing = true; } else { scroll = 0.0f; flowing = false; } // skip the water texture on transparent surfaces if (r_reflectivewater->value && (fa->texinfo->flags & (SURF_TRANS33|SURF_TRANS66))) { for (bp = fa->polys; bp; bp = bp->next) { p = bp; for (i = 0, v = p->verts[0]; i < p->numverts; i++, v += VERTEXSIZE) { // if it hasn't been initalized before if (zValue == 0.0f) zValue = v[2]; // Make sure polygons are on the same plane // Fix for not perfectly flat water on base1 - strange .. else if (fabs(zValue - v[2]) > 8.0f) waterNotFlat = true; } } } if (waterNotFlat || !r_reflectivewater->value || !(fa->texinfo->flags & (SURF_TRANS33|SURF_TRANS66))) { for (bp = fa->polys; bp; bp = bp->next) { p = bp; qgl.Begin(GL_TRIANGLE_FAN); c_brush_polys += p->numverts / 3; // jitrspeeds for (i = 0, v = p->verts[0]; i < p->numverts; i++, v += VERTEXSIZE) { os = v[3]; ot = v[4]; #if !id386 s = os + r_turbsin[(int)((ot * 0.125f + r_newrefdef.time) * TURBSCALE) & 255]; #else s = os + r_turbsin[Q_ftol(((ot * 0.125f + rdt) * TURBSCALE)) & 255]; #endif s += scroll; s *= 0.015625f; // 1/64 #if !id386 t = ot + r_turbsin[(int)((os * 0.125f + rdt) * TURBSCALE) & 255]; #else t = ot + r_turbsin[Q_ftol(((os * 0.125f + rdt) * TURBSCALE)) & 255]; #endif t *= 0.015625f; // 1/64 // if it hasn't been initalized before if (zValue == 0.0f) zValue = v[2]; // Make sure polygons are on the same plane // Fix for not perfectly flat water on base1 - strange .. else if (fabs(zValue - v[2]) > 0.1f) waterNotFlat = true; qgl.TexCoord2f(s, t); qgl.Vertex3f(v[0], v[1], v[2]); } qgl.End(); } } if (waterNotFlat) return; if (r_reflectivewater->value) { #if 0 //==================== vec3_t distanceVector; float distance; //==================== #endif v = p->verts[0]; #if 0 VectorSubtract(v, r_newrefdef.vieworg, distanceVector); distance = VectorLength(distanceVector); //R_add_refl(zValue, distance); #endif R_add_refl(v[0], v[1], zValue); g_refl_enabled = true; } // find out which reflection we have that corresponds to the surface that we're drawing for (g_active_refl = 0; g_active_refl < g_num_refl; g_active_refl++) { // if we find which reflection to bind if (fabs(g_refl_Z[g_active_refl] - zValue) < 8.0f) { // === jitwater if (gl_state.fragment_program) { qgl.Enable(GL_VERTEX_PROGRAM_ARB); qgl.BindProgramARB(GL_VERTEX_PROGRAM_ARB, g_water_vertex_program_id); qgl.Enable(GL_FRAGMENT_PROGRAM_ARB); qgl.BindProgramARB(GL_FRAGMENT_PROGRAM_ARB, g_water_fragment_program_id); GL_MBind(QGL_TEXTURE1, distort_tex->texnum); // Distortion texture GL_MBind(QGL_TEXTURE2, water_normal_tex->texnum); // Normal texture } GL_MBind(QGL_TEXTURE0, g_refl_images[g_active_refl]->texnum); // Reflection texture // jitwater === break; } } // if we found a reflective surface correctly, then go ahead and draw it if (g_active_refl != g_num_refl) { qgl.Color4f(1.0f, 1.0f, 1.0f, 1.0f); if (!gl_state.blend) qgl.Enable(GL_BLEND); GL_TexEnv(GL_MODULATE); qgl.ShadeModel(GL_SMOOTH); if (gl_state.fragment_program) { float w, h; R_GetReflTexScale(&w, &h); // Probably unnecessary qgl.ProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, 0, w, h, rs_realtime * (flowing ? -0.3f : 0.2f), rs_realtime * -0.2f); qgl.ProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, 1, r_newrefdef.vieworg[0], r_newrefdef.vieworg[1], r_newrefdef.vieworg[2], 1.0f); } else { // Put UV coords in screen space for rendering the reflection texture. Only need to do this when fragment programs are disabled. It's handled in the vertex shader otherwise. R_LoadReflMatrix(); } // draw reflected water layer on top of regular for (bp = fa->polys; bp; bp = bp->next) { p = bp; qgl.Begin(GL_TRIANGLE_FAN); c_brush_polys += p->numverts / 3; // jitrspeeds for (i = 0, v = p->verts[0]; i < p->numverts; ++i, v += VERTEXSIZE) { if (gl_state.fragment_program) { qgl.MultiTexCoord3fvARB(QGL_TEXTURE0, v); // Used for world space qgl.MultiTexCoord3fvARB(QGL_TEXTURE1, v + 3); // Actual texture UV's. } else { vec3_t vAngle; qgl.TexCoord3f(v[0], v[1] + CalcWave(v[0], v[1]), v[2]); if (r_newrefdef.rdflags & RDF_UNDERWATER) { VectorSubtract(v, r_newrefdef.vieworg, vAngle); VectorNormalize(vAngle); if (vAngle[2] > 0.55f) vAngle[2] = 0.55f; qgl.Color4f(1.0f, 1.0f, 1.0f, 0.9f - (vAngle[2] * 1.0f)); } else { VectorSubtract(r_newrefdef.vieworg, v, vAngle); VectorNormalize(vAngle); if (vAngle[2] > 0.55f) vAngle[2] = 0.55f; qgl.Color4f(1.0f, 1.0f, 1.0f, 0.9f - (vAngle[2] * 1.0f)); } } qgl.Vertex3f(v[0], v[1], v[2]); } qgl.End(); } R_ClearReflMatrix(); if (!gl_state.blend) qgl.Disable(GL_BLEND); if (gl_state.fragment_program) // jitwater { qgl.Disable(GL_FRAGMENT_PROGRAM_ARB); qgl.Disable(GL_VERTEX_PROGRAM_ARB); } } }