一.先上渲染部分的代碼數組
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;
}
}