void OculusWorldDemoApp::RenderGrid(ovrEyeType eye, Recti renderViewport)
{
    // Draw actual pixel grid on the RT.
    // 1:1 mapping to screen pixels, origin in top-left.
    Matrix4f ortho;
    ortho.SetIdentity();
    ortho.M[0][0] = 2.0f / (renderViewport.w);       // X scale
    ortho.M[0][3] = -1.0f;                           // X offset
    ortho.M[1][1] = -2.0f / (renderViewport.h);      // Y scale (for Y=down)
    ortho.M[1][3] = 1.0f;                            // Y offset (Y=down)
    ortho.M[2][2] = 0;
    pRender->SetProjection(ortho);
    pRender->SetViewport(renderViewport);

    pRender->SetDepthMode(false, false);
    Color cNormal ( 0, 255, 0 );        // Green is the least-smeared color from CA.
    Color cSpacer ( 255, 255, 0 );
    Color cMid ( 0, 128, 255 );

    int lineStep = 1;
    int midX = 0;
    int midY = 0;
    int limitX = 0;
    int limitY = 0;

    switch ( GridMode )
    {
    case Grid_Rendertarget4:
        lineStep = 4;
        midX    = renderViewport.w / 2;
        midY    = renderViewport.h / 2;
        limitX  = renderViewport.w / 2;
        limitY  = renderViewport.h / 2;
        break;
    case Grid_Rendertarget16:
        lineStep = 16;
        midX    = renderViewport.w / 2;
        midY    = renderViewport.h / 2;
        limitX  = renderViewport.w / 2;
        limitY  = renderViewport.h / 2;
        break;
    case Grid_Lens:
        {
            lineStep = 48;
            Vector2f rendertargetNDC = FovPort(EyeRenderDesc[eye].Fov).TanAngleToRendertargetNDC(Vector2f(0.0f));
            midX    = (int)( ( rendertargetNDC.x * 0.5f + 0.5f ) * (float)renderViewport.w + 0.5f );
            midY    = (int)( ( rendertargetNDC.y * 0.5f + 0.5f ) * (float)renderViewport.h + 0.5f );
            limitX  = Alg::Max ( renderViewport.w - midX, midX );
            limitY  = Alg::Max ( renderViewport.h - midY, midY );
        }
        break;
    default: OVR_ASSERT ( false ); break;
    }

    int spacerMask = (lineStep<<2)-1;


    for ( int xp = 0; xp < limitX; xp += lineStep )
    {
        float x[4];
        float y[4];
        x[0] = (float)( midX + xp );
        y[0] = (float)0;
        x[1] = (float)( midX + xp );
        y[1] = (float)renderViewport.h;
        x[2] = (float)( midX - xp );
        y[2] = (float)0;
        x[3] = (float)( midX - xp );
        y[3] = (float)renderViewport.h;
        if ( xp == 0 )
        {
            pRender->RenderLines ( 1, cMid, x, y );
        }
        else if ( ( xp & spacerMask ) == 0 )
        {
            pRender->RenderLines ( 2, cSpacer, x, y );
        }
        else
        {
            pRender->RenderLines ( 2, cNormal, x, y );
        }
    }
    for ( int yp = 0; yp < limitY; yp += lineStep )
    {
        float x[4];
        float y[4];
        x[0] = (float)0;
        y[0] = (float)( midY + yp );
        x[1] = (float)renderViewport.w;
        y[1] = (float)( midY + yp );
        x[2] = (float)0;
        y[2] = (float)( midY - yp );
        x[3] = (float)renderViewport.w;
        y[3] = (float)( midY - yp );
        if ( yp == 0 )
        {
            pRender->RenderLines ( 1, cMid, x, y );
        }
        else if ( ( yp & spacerMask ) == 0 )
        {
            pRender->RenderLines ( 2, cSpacer, x, y );
        }
        else
        {
            pRender->RenderLines ( 2, cNormal, x, y );
        }
    }

    // Draw diagonal lines
    {
        float x[2];
        float y[2];
        x[0] = (float)(midX - renderViewport.w);
        x[1] = (float)(midX + renderViewport.w);
        y[0] = (float)(midY - renderViewport.w);
        y[1] = (float)(midY + renderViewport.w);
        pRender->RenderLines(1, cNormal, x, y);
    }
    {
        float x[2];
        float y[2];
        x[0] = (float)(midX + renderViewport.w);
        x[1] = (float)(midX - renderViewport.w);
        y[0] = (float)(midY - renderViewport.w);
        y[1] = (float)(midY + renderViewport.w);
        pRender->RenderLines(1, cNormal, x, y);
    }
}
Esempio n. 2
0
void OculusWorldDemoApp::CalculateHmdValues()
{
    // Initialize eye rendering information for ovrHmd_Configure.
    // The viewport sizes are re-computed in case RenderTargetSize changed due to HW limitations.
    ovrFovPort eyeFov[2];
    eyeFov[0] = HmdDesc.DefaultEyeFov[0];
    eyeFov[1] = HmdDesc.DefaultEyeFov[1];

    // Clamp Fov based on our dynamically adjustable FovSideTanMax.
    // Most apps should use the default, but reducing Fov does reduce rendering cost.
    eyeFov[0] = FovPort::Min(eyeFov[0], FovPort(FovSideTanMax));
    eyeFov[1] = FovPort::Min(eyeFov[1], FovPort(FovSideTanMax));


    if (ForceZeroIpd)
    {
        // ForceZeroIpd does three things:
        //  1) Sets FOV to maximum symmetrical FOV based on both eyes
        //  2) Sets eye ViewAdjust values to 0.0 (effective IPD == 0)
        //  3) Uses only the Left texture for rendering.
        
        eyeFov[0] = FovPort::Max(eyeFov[0], eyeFov[1]);
        eyeFov[1] = eyeFov[0];

        Sizei recommenedTexSize = ovrHmd_GetFovTextureSize(Hmd, ovrEye_Left,
                                                           eyeFov[0], DesiredPixelDensity);

        Sizei textureSize = EnsureRendertargetAtLeastThisBig(Rendertarget_Left,  recommenedTexSize);

        EyeRenderSize[0] = Sizei::Min(textureSize, recommenedTexSize);
        EyeRenderSize[1] = EyeRenderSize[0];

        // Store texture pointers that will be passed for rendering.
        EyeTexture[0]                       = RenderTargets[Rendertarget_Left].Tex;
        EyeTexture[0].Header.TextureSize    = textureSize;
        EyeTexture[0].Header.RenderViewport = Recti(EyeRenderSize[0]);
        // Right eye is the same.
        EyeTexture[1] = EyeTexture[0];
    }

    else
    {
        // Configure Stereo settings. Default pixel density is 1.0f.
        Sizei recommenedTex0Size = ovrHmd_GetFovTextureSize(Hmd, ovrEye_Left,  eyeFov[0], DesiredPixelDensity);
        Sizei recommenedTex1Size = ovrHmd_GetFovTextureSize(Hmd, ovrEye_Right, eyeFov[1], DesiredPixelDensity);

        if (RendertargetIsSharedByBothEyes)
        {
            Sizei  rtSize(recommenedTex0Size.w + recommenedTex1Size.w,
                          Alg::Max(recommenedTex0Size.h, recommenedTex1Size.h));

            // Use returned size as the actual RT size may be different due to HW limits.
            rtSize = EnsureRendertargetAtLeastThisBig(Rendertarget_BothEyes, rtSize);

            // Don't draw more then recommended size; this also ensures that resolution reported
            // in the overlay HUD size is updated correctly for FOV/pixel density change.            
            EyeRenderSize[0] = Sizei::Min(Sizei(rtSize.w/2, rtSize.h), recommenedTex0Size);
            EyeRenderSize[1] = Sizei::Min(Sizei(rtSize.w/2, rtSize.h), recommenedTex1Size);

            // Store texture pointers that will be passed for rendering.
            // Same texture is used, but with different viewports.
            EyeTexture[0]                       = RenderTargets[Rendertarget_BothEyes].Tex;
            EyeTexture[0].Header.TextureSize    = rtSize;
            EyeTexture[0].Header.RenderViewport = Recti(Vector2i(0), EyeRenderSize[0]);
            EyeTexture[1]                       = RenderTargets[Rendertarget_BothEyes].Tex;
            EyeTexture[1].Header.TextureSize    = rtSize;
            EyeTexture[1].Header.RenderViewport = Recti(Vector2i((rtSize.w+1)/2, 0), EyeRenderSize[1]);
        }

        else
        {
            Sizei tex0Size = EnsureRendertargetAtLeastThisBig(Rendertarget_Left,  recommenedTex0Size);
            Sizei tex1Size = EnsureRendertargetAtLeastThisBig(Rendertarget_Right, recommenedTex1Size);

            EyeRenderSize[0] = Sizei::Min(tex0Size, recommenedTex0Size);
            EyeRenderSize[1] = Sizei::Min(tex1Size, recommenedTex1Size);

            // Store texture pointers and viewports that will be passed for rendering.
            EyeTexture[0]                       = RenderTargets[Rendertarget_Left].Tex;
            EyeTexture[0].Header.TextureSize    = tex0Size;
            EyeTexture[0].Header.RenderViewport = Recti(EyeRenderSize[0]);
            EyeTexture[1]                       = RenderTargets[Rendertarget_Right].Tex;
            EyeTexture[1].Header.TextureSize    = tex1Size;
            EyeTexture[1].Header.RenderViewport = Recti(EyeRenderSize[1]);
        }
    }

    // Hmd caps.
    unsigned hmdCaps = (VsyncEnabled ? 0 : ovrHmdCap_NoVSync) |
                       ovrHmdCap_LatencyTest;
    if (IsLowPersistence)
        hmdCaps |= ovrHmdCap_LowPersistence;
    if (DynamicPrediction)
        hmdCaps |= ovrHmdCap_DynamicPrediction;

    ovrHmd_SetEnabledCaps(Hmd, hmdCaps);


	ovrRenderAPIConfig config         = pRender->Get_ovrRenderAPIConfig();
    unsigned           distortionCaps = ovrDistortionCap_Chromatic;
    if (TimewarpEnabled)
        distortionCaps |= ovrDistortionCap_TimeWarp;

    if (!ovrHmd_ConfigureRendering( Hmd, &config, distortionCaps,
                                    eyeFov, EyeRenderDesc ))
    {
        // Fail exit? TBD
        return;
    }

    if (ForceZeroIpd)
    {
        // Remove IPD adjust
        EyeRenderDesc[0].ViewAdjust = Vector3f(0);
        EyeRenderDesc[1].ViewAdjust = Vector3f(0);
    }

    // ovrHmdCap_LatencyTest - enables internal latency feedback
    unsigned sensorCaps = ovrSensorCap_Orientation|ovrSensorCap_YawCorrection;
    if (PositionTrackingEnabled)
        sensorCaps |= ovrSensorCap_Position;
      
    if (StartSensorCaps != sensorCaps)
    {
        ovrHmd_StartSensor(Hmd, sensorCaps, 0);
        StartSensorCaps = sensorCaps;
    }    

    // Calculate projections
    Projection[0] = ovrMatrix4f_Projection(EyeRenderDesc[0].Fov,  0.01f, 10000.0f, true);
    Projection[1] = ovrMatrix4f_Projection(EyeRenderDesc[1].Fov,  0.01f, 10000.0f, true);

    float    orthoDistance = 0.8f; // 2D is 0.8 meter from camera
    Vector2f orthoScale0   = Vector2f(1.0f) / Vector2f(EyeRenderDesc[0].PixelsPerTanAngleAtCenter);
    Vector2f orthoScale1   = Vector2f(1.0f) / Vector2f(EyeRenderDesc[1].PixelsPerTanAngleAtCenter);
    
    OrthoProjection[0] = ovrMatrix4f_OrthoSubProjection(Projection[0], orthoScale0, orthoDistance,
                                                        EyeRenderDesc[0].ViewAdjust.x);
    OrthoProjection[1] = ovrMatrix4f_OrthoSubProjection(Projection[1], orthoScale1, orthoDistance,
                                                        EyeRenderDesc[1].ViewAdjust.x);
}