一.先上渲染部分的代码数组
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;
}
}