cocosd-x vr原理解析

一.先上渲染部分的代碼數組

const float eyeOffset = 40.f;app

    auto headRotation = _headTracker->getLocalRotation();rest

    headRotation = Mat4::IDENTITY;orm

    Mat4 leftTransform;圖片

    

    Mat4::createTranslation(eyeOffset, 0, 0, &leftTransform);get

    leftTransform *= headRotation;it

 

    Mat4 rightTransform;io

    Mat4::createTranslation(-eyeOffset, 0, 0, &rightTransform);form

    rightTransform *= headRotation;原理

 

    _fb->applyFBO();

    auto defaultVP = Camera::getDefaultViewport();

    Camera::setDefaultViewport(_leftEye.viewport);

    scene->render(renderer, leftTransform, nullptr);

    Camera::setDefaultViewport(_rightEye.viewport);

    scene->render(renderer, rightTransform, nullptr);

    Camera::setDefaultViewport(defaultVP);

    _fb->restoreFBO();

 

    auto texture = _fb->getRenderTarget()->getTexture();

    GL::bindTexture2D(texture->getName());

    _glProgramState->apply(Mat4::IDENTITY);

 

    GLint origViewport[4];

    glGetIntegerv(GL_VIEWPORT, origViewport);

    glViewport(0, 0, _texSize.width, _texSize.height);

 

    renderDistortionMesh(_leftDistortionMesh, texture->getName());

    renderDistortionMesh(_rightDistortionMesh, texture->getName());

 

 

    glViewport(origViewport[0], origViewport[1], origViewport[2], origViewport[3]);

 

    glBindBuffer(GL_ARRAY_BUFFER, 0);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

二.詳解

1.原理:經過調整攝像頭的x偏移模擬2個眼睛,渲染(拍攝)出2個不一樣角度的圖片,講2個圖片渲染到一漲紋理。對該渲染的紋理進行網格處理畸變(桶型)後,再渲染到屏幕上。

2.參數解析

eyeOffset:兩眼間距(更準確的說是 左右攝像頭的x偏移).

最核心的是tDistortionMesh的生成。貼上關鍵代碼

    const int rows = 40;//行

    const int cols = 40;//列

 

    GLfloat vertexData[rows * cols * 5];//頂點數組

 

    int vertexOffset = 0;

 

    const float vignetteSizeTanAngle = 0.05f;

 

    const float maxDistance = sqrtf(textureWidth * textureWidth + textureHeight * textureHeight) / 4;.//我的認爲是cocos的一個bug  應該是   const float maxDistance = sqrtf(textureWidth/2 * textureWidth/2+ textureHeight * textureHeight) / 2纔是半徑

 

 

    for (int row = 0; row < rows; row++)

    {

        for (int col = 0; col < cols; col++)

        {

            const float uTexture = col / (cols-1.0f) * (viewportWidthTexture / textureWidth) + viewportXTexture / textureWidth;//u座標

            const float vTexture = row / (rows-1.0f) * (viewportHeightTexture / textureHeight) + viewportYTexture / textureHeight;//v座標

 

            const float xTexture = uTexture * textureWidth - xEyeOffsetTexture;

            const float yTexture = vTexture * textureHeight - yEyeOffsetTexture;

//很關鍵這裏 xEyeOffsetTexture 和yEyeOffsetTexture 其實就是畸變中心位置

            const float rTexture = sqrtf(xTexture * xTexture + yTexture * yTexture) / maxDistance;

    //計算r

            const float textureToScreen = (rTexture > 0.0f) ? distortion->distortInverse(rTexture) / rTexture : 1.0f;

//畸變處理

            const float xScreen = xTexture * textureToScreen;//畸變處理後在紋理中的x位置(以中心點爲座標原點的座標系)

            const float yScreen = yTexture * textureToScreen;//畸變處理後在紋理中的y位置置(以中心點爲座標原點的座標系)

 

            const float uScreen = (xScreen + xEyeOffsetScreen) / screenWidth;//畸變處理後在紋理中的x位置(左下角爲圓點的座標系)

            const float vScreen = (yScreen + yEyeOffsetScreen) / screenHeight;//

畸變處理後在紋理中的y位置(以左下角爲圓點的座標系)

 

           

            // position x,y (vertices)

            // 0,1轉換到-1,1的頂點座標系

            vertexData[(vertexOffset + 0)] = 2.0f * uScreen - 1.0f;

            vertexData[(vertexOffset + 1)] = 2.0f * vScreen - 1.0f;

 

            // texture u,v

            vertexData[(vertexOffset + 2)] = uTexture;

            vertexData[(vertexOffset + 3)] = vTexture;

 

            // vignette

            vertexData[(vertexOffset + 4)] = vignette;

 

            vertexOffset += 5;

        }

    }

相關文章
相關標籤/搜索