教程
OpenGL ES實(shí)踐教程1-Demo01-AVPlayer
OpenGL ES實(shí)踐教程2-Demo02-攝像頭采集數(shù)據(jù)和渲染
OpenGL ES實(shí)踐教程3-Demo03-Mirror
OpenGL ES實(shí)踐教程4-Demo04-VR全景視頻播放
OpenGL ES實(shí)踐教程5-Demo05-多重紋理實(shí)現(xiàn)圖像混合
其他教程請(qǐng)移步OpenGL ES文集。
前言
有開(kāi)發(fā)者在群里問(wèn)如何實(shí)現(xiàn):
觀看VR視頻的時(shí)候,眼神停在菜單上霎奢,稍后會(huì)觸發(fā)事件饵逐,比如暫停穆端,重放功能
說(shuō)說(shuō)可能的方案:
- 1困曙、添加外設(shè):采集眼球運(yùn)動(dòng)和眨眼操作恰矩,并通過(guò)無(wú)線通訊傳給手機(jī)记盒;
- 2、離屏渲染:新建緩沖區(qū)枢里,把像素是否能操作編碼到顏色分量(RGBA均可)孽鸡,按照屏幕渲染的流程在新的緩沖區(qū)內(nèi)渲染,然后通過(guò)
glReadPixel
讀取對(duì)應(yīng)像素的操作栏豺; - 3彬碱、模擬計(jì)算:假設(shè)有一條直線從視點(diǎn)出發(fā),經(jīng)過(guò)焦點(diǎn)奥洼,最終與全景球面相交巷疼,通過(guò)計(jì)算交點(diǎn)是否在按鈕上確定是否聚焦成功;
方案1是理想的方案灵奖,但實(shí)際應(yīng)用開(kāi)發(fā)成本嚼沿,成本太高;
方案2需要離屏渲染瓷患,首先切換幀緩存導(dǎo)致GPU等待骡尽;其次,每次聚焦都要重繪(當(dāng)用戶一直移動(dòng)屏幕的時(shí)候擅编,需要不斷重繪)攀细;最后箫踩,glReadPixel
是同步操作,對(duì)性能有較大的影響谭贪;
方案3是較為合理的實(shí)現(xiàn)方案境钟,僅需要CPU進(jìn)行少量的浮點(diǎn)變化運(yùn)算,不需要外設(shè)和離屏渲染俭识;
本文在OpenGL ES實(shí)踐教程4-Demo04-VR全景視頻播放的基礎(chǔ)上慨削,添加簡(jiǎn)單的色塊,單焦點(diǎn)進(jìn)入色塊時(shí)進(jìn)行變色套媚。
核心思路
通過(guò)計(jì)算全景球面上的點(diǎn)經(jīng)過(guò)旋轉(zhuǎn)投影后的位置缚态,來(lái)確定當(dāng)前焦點(diǎn)是否停留在按鈕上。
- 實(shí)現(xiàn)1:從攝像機(jī)的視點(diǎn)O(0,0,0)到的焦點(diǎn)P(0.5,0.5,0.5)連接一條直線PO凑阶,求出直線與全景球面X2+Y2+Z^2=1上面的交點(diǎn)T猿规。
當(dāng)攝像機(jī)旋轉(zhuǎn)的時(shí)候衷快,焦點(diǎn)P不斷變化宙橱,對(duì)新的焦點(diǎn)P’,按照上述的方式求出點(diǎn)T’蘸拔,判斷點(diǎn)T’是否在球面的按鈕區(qū)域师郑;
可以通過(guò)手寫(xiě),我們知道直線OP的方程為2x-1=2y-1=2z-1
聯(lián)合方程调窍,可以求出交點(diǎn)T(1/sqrt(3), 1/sqrt(3), 1/sqrt(3) )宝冕。
當(dāng)攝像機(jī)旋轉(zhuǎn)的時(shí)候,再求出對(duì)應(yīng)的交點(diǎn)即可邓萨。
- 實(shí)現(xiàn)2:假設(shè)點(diǎn)P是按鈕的中心地梨,對(duì)點(diǎn)P進(jìn)行旋轉(zhuǎn)、投影等變換后缔恳,求出點(diǎn)P在屏幕上的位置宝剖,如果點(diǎn)P在焦點(diǎn)范圍內(nèi),則認(rèn)為聚焦歉甚;
demo采用的是實(shí)現(xiàn)2万细。
效果展示
具體細(xì)節(jié)
先把OpenGL ES實(shí)踐教程4-Demo04-VR全景視頻播放的工程拖過(guò)來(lái)。
1纸泄、添加表示按鈕的色塊
- 在頂點(diǎn)著色器添加
varying lowp vec3 varyOtherPostion
變量赖钞,傳遞頂點(diǎn)數(shù)據(jù)到像素著色器; - 新建變量
leftBottom
聘裁、rightTop
雪营、myTexture1
表示按鈕的區(qū)域和按鈕的紋理;
varying lowp vec2 texCoordVarying;
varying lowp vec3 varyOtherPostion;
precision mediump float;
uniform sampler2D SamplerY;
uniform sampler2D SamplerUV;
uniform mat3 colorConversionMatrix;
uniform vec2 leftBottom;
uniform vec2 rightTop;
uniform sampler2D myTexture1;
void main()
{
mediump vec3 yuv;
lowp vec3 rgb;
// Subtract constants to map the video range start at 0
yuv.x = (texture2D(SamplerY, texCoordVarying).r);// - (16.0/255.0));
yuv.yz = (texture2D(SamplerUV, texCoordVarying).ra - vec2(0.5, 0.5));
rgb = colorConversionMatrix * yuv;
if (varyOtherPostion.x >= leftBottom.x && varyOtherPostion.y >= leftBottom.y && varyOtherPostion.x <= rightTop.x && varyOtherPostion.y <= rightTop.y && varyOtherPostion.z > 0.0) {
lowp vec2 test = vec2((varyOtherPostion.x - leftBottom.x) / (rightTop.x - leftBottom.x), 1.0 - (varyOtherPostion.y - leftBottom.y) / (rightTop.y - leftBottom.y));
lowp vec4 otherColor = texture2D(myTexture1, test);
otherColor.a = 0.5;
gl_FragColor = otherColor * otherColor.a + vec4(rgb, 1.0) * (1.0 - otherColor.a);
}
else {
gl_FragColor = vec4(rgb, 1.0);
}
}
- 在中LYOpenGLView.m中獲取對(duì)應(yīng)的變量并賦值衡便;
glUniform1i(uniforms[UNIFORM_TEXTURE1], 2);
glUniform2f(uniforms[UNIFORM_LEFT_BOTTOM], -0.25, -0.25);
glUniform2f(uniforms[UNIFORM_RIGHT_TOP], 0.25, 0.25);
2献起、監(jiān)聽(tīng)手指移動(dòng)并判斷聚焦
- 添加初始點(diǎn)position,我們假設(shè)是(0, 0, -1, 1);
GLKVector4 position = GLKVector4Make(0, 0, -1, 1);
- 計(jì)算變化矩陣征唬,求出變換后的點(diǎn)targetPosition捌显;
GLKMatrix4 modelViewMatrix = GLKMatrix4Identity;
modelViewMatrix = GLKMatrix4RotateX(modelViewMatrix, horizontalDegree);
modelViewMatrix = GLKMatrix4RotateY(modelViewMatrix, verticalDegree);
GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(90, CGRectGetWidth(self.bounds) * 1.0 / CGRectGetHeight(self.bounds), 0.01, 10);
GLKVector4 position = GLKVector4Make(0, 0, -1, 1);
GLKVector4 targetPosition = GLKMatrix4MultiplyVector4(GLKMatrix4Multiply(projectionMatrix, modelViewMatrix), position);
- 判斷是否聚焦成功;(點(diǎn)(0.2, -0.05, -1.0)是根據(jù)初始點(diǎn)算出來(lái)的聚焦中心位置总寒,如果初始點(diǎn)變化扶歪,這個(gè)點(diǎn)也要跟著變化)
float dif = 0.3;
if (fabs(targetPosition.x - 0.2) <= dif &&
fabs(targetPosition.y + 0.05) <= dif &&
fabs(targetPosition.z + 1.00) <= dif &&
1) {
[self setupFirstTexture:@"select"];
}
else {
[self setupFirstTexture:@"normal"];
}
總結(jié)
本文存在各種不嚴(yán)謹(jǐn)?shù)牡胤剑瑑H供參考摄闸。
中間在手動(dòng)計(jì)算空間直線方程的時(shí)候善镰,還計(jì)算錯(cuò)誤,通過(guò)空間直線方程得到糾正年枕。