Last active
December 24, 2017 03:00
-
-
Save tamarous/7250ba7c1e7f6e634228b313025f6c3d to your computer and use it in GitHub Desktop.
使用OpenGL ES以双目渲染和显示360度视频。博文地址:http://www.tamarous.com/2017/12/23/render-360-video-using-opengles/
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "GLHelper.h" | |
#include <android/native_window.h> | |
const char* TEXTURE_UNIFORMS[] = {"y_tex", "u_tex", "v_tex"}; | |
GLuint yuvTextures[3]; | |
#define glCheckError() glCheckError_(__LINE__) | |
void glCheckError_(int line) | |
{ | |
GLenum errorCode; | |
char error[100]; | |
memset(error,0,sizeof(error)); | |
while ((errorCode = glGetError()) != GL_NO_ERROR) | |
{ | |
switch (errorCode) | |
{ | |
case GL_INVALID_ENUM: sprintf(error,"GL_INVALID_ENUM"); break; | |
case GL_INVALID_VALUE: sprintf(error,"GL_INVALID_VALUE"); break; | |
case GL_INVALID_OPERATION: sprintf(error,"GL_INVALID_OPERATION"); break; | |
case GL_OUT_OF_MEMORY: sprintf(error,"GL_OUT_OF_MEMORY"); break; | |
case GL_INVALID_FRAMEBUFFER_OPERATION: sprintf(error,"GL_INVALID_FRAMEBUFFER_OPERATION"); break; | |
} | |
LOGE("Line is %d, glError: %s", line, error); | |
} | |
} | |
const GLfloat SAMPLER_VERTICES[] = { | |
0.0f, 1.0f, | |
0.0f, 0.0f, | |
1.0f, 1.0f, | |
1.0f, 0.0f, | |
}; | |
const GLfloat LEFTSCREEN_VERTICES[] = { | |
-1.0f, 1.0f, | |
-1.0f, -1.0f, | |
0.0f, 1.0f, | |
0.0f, -1.0f, | |
}; | |
const GLfloat RIGHTSCREEN_VERTICES[] = { | |
0.0f, 1.0f, | |
0.0f, -1.0f, | |
1.0f, 1.0f, | |
1.0f, -1.0f, | |
}; | |
static const char SPHERE_VERTEXSHADER[] = | |
"uniform mat4 matrix;\n" | |
"varying vec2 interp_tc;\n" | |
"attribute vec4 in_pos;\n" | |
"attribute vec2 in_tc;\n" | |
"void main() {\n" | |
" gl_Position = matrix * in_pos;\n" | |
" interp_tc = in_tc;\n" | |
"}\n"; | |
static const char SPHERE_FRAGMENTSHADER[] = | |
"precision mediump float;\n" | |
"varying vec2 interp_tc;\n" | |
"uniform sampler2D y_tex;\n" | |
"uniform sampler2D u_tex;\n" | |
"uniform sampler2D v_tex;\n" | |
"void main() {\n" | |
" float y = 1.164 * (texture2D(y_tex, interp_tc).r - 0.0625);\n" | |
" float u = texture2D(u_tex, interp_tc).r - 0.5;\n" | |
" float v = texture2D(v_tex, interp_tc).r - 0.5;\n" | |
" gl_FragColor = vec4(y + 1.596 * v, " | |
" y - 0.391 * u - 0.813 * v, " | |
" y + 2.018 * u, " | |
" 1.0);\n" | |
" | |
"}\n"; | |
static const char SCREEN_VERTEXSHADER[] = | |
"varying vec2 interp_tc;\n" | |
"attribute vec4 in_pos;\n" | |
"attribute vec2 in_tc;\n" | |
"void main() {\n" | |
" gl_Position = in_pos;\n" | |
" interp_tc = in_tc;\n" | |
"}\n"; | |
static const char SCREEN_FRAGMENTSHADER[] = | |
"precision mediump float;\n" | |
"varying vec2 interp_tc;\n" | |
"uniform sampler2D texture;\n" | |
"void main() {\n" | |
"gl_FragColor = texture2D(texture, interp_tc);\n" | |
"}\n"; | |
void addShader(int type, const char* source, int program) { | |
int shader = glCreateShader(type); | |
glShaderSource(shader, 1, &source, NULL); | |
glCompileShader(shader); | |
GLint compiled = 0; | |
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); | |
glAttachShader(program, shader); | |
glDeleteShader(shader); | |
} | |
GLHelper::GLHelper() { | |
myCamera = new MyGLCamera(FOVY,0,zNear,zFar); | |
float defaultPos[6] = {0.0,0.0,0.0,0.0,0.0,0.0}; | |
myCamera->setModelPosition(defaultPos); | |
} | |
GLHelper::~GLHelper() { | |
close(); | |
free(vertexCoordinates); | |
free(uvCoordinates); | |
} | |
void GLHelper::setWindow(ANativeWindow *window) { | |
_window = window; | |
return; | |
} | |
bool GLHelper::setupMemories() { | |
this->numberOfPatches = 64; | |
this->vertexCount = this->numberOfPatches * this->numberOfPatches/2 * 6; | |
this->vertexCoordinates = (float *)malloc(this->vertexCount * 3 * sizeof(float)); | |
if (! this->vertexCoordinates) { | |
return false; | |
} | |
this->uvCoordinates = (float *)malloc(this->vertexCount * 2 * sizeof(float)); | |
if (! this->uvCoordinates) { | |
return false; | |
} | |
return true; | |
} | |
bool GLHelper::init() | |
{ | |
// Init EGL Context. | |
EGLBoolean returnValue; | |
EGLint majorVersion; | |
EGLint minorVersion; | |
EGLConfig myConfig = {0}; | |
EGLint numConfig = 0; | |
EGLint format = 0; | |
EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; | |
EGLint s_configAttribs[] = { | |
EGL_SURFACE_TYPE, EGL_WINDOW_BIT, | |
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, | |
EGL_NONE }; | |
const EGLint RGB888Config[] = { | |
EGL_BUFFER_SIZE, 24, | |
EGL_BLUE_SIZE, 8, | |
EGL_GREEN_SIZE, 8, | |
EGL_RED_SIZE, 8, | |
EGL_DEPTH_SIZE, 0, | |
EGL_SURFACE_TYPE, EGL_WINDOW_BIT, | |
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, | |
EGL_NONE | |
}; | |
dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); | |
if (dpy == EGL_NO_DISPLAY) { | |
printf("eglGetDisplay returned EGL_NO_DISPLAY.\n"); | |
return false; | |
} | |
returnValue = eglInitialize(dpy, &majorVersion, &minorVersion); | |
if (returnValue != EGL_TRUE) { | |
printf("eglInitialize failed\n"); | |
return false; | |
} | |
returnValue = eglChooseConfig(dpy, RGB888Config, &myConfig, 1, &numConfig); | |
if (returnValue != EGL_TRUE || numConfig != 1) { | |
printf("eglInitialize failed\n"); | |
return false; | |
} | |
if (! eglGetConfigAttrib(dpy,myConfig,EGL_NATIVE_VISUAL_ID,&format) ) { | |
return false; | |
} | |
ANativeWindow_setBuffersGeometry(_window,0,0,format); | |
surface = eglCreateWindowSurface(dpy, myConfig, static_cast<EGLNativeWindowType>(_window), NULL); | |
if (surface == EGL_NO_SURFACE) { | |
return false; | |
} | |
context = eglCreateContext(dpy, myConfig, EGL_NO_CONTEXT, context_attribs); | |
if (context == EGL_NO_CONTEXT) { | |
return false; | |
} | |
returnValue = eglMakeCurrent(dpy, surface, surface, context); | |
if (returnValue != EGL_TRUE) { | |
return false; | |
} | |
eglQuerySurface(dpy, surface, EGL_WIDTH, &w); | |
eglQuerySurface(dpy, surface, EGL_HEIGHT, &h); | |
myCamera->setAspectRatio((float)(w/2)/h); | |
if (!setupMemories()) { | |
LOGE("Could not set up neccessary numbers."); | |
return false; | |
} | |
if(!setupGraphics()) { | |
LOGE( "Could not set up graphics.\n"); | |
return false; | |
} | |
if(! setupTextures()) { | |
LOGE( "Could not set up Textures.\n"); | |
return false; | |
} | |
if(! setupVertices()) { | |
LOGE( "Could not set up vertices"); | |
} | |
if(! setupMatrix()) { | |
LOGE( "Could not set up matrix"); | |
} | |
if (! setupFrameBuffer(w,h,leftEyeFrameBufferDesc)) { | |
LOGE("Error: could not create framebuffer for left eye"); | |
} | |
if (! setupFrameBuffer(w, h, rightEyeFrameBufferDesc)) { | |
LOGE("Error: could not create framebuffer for right eye"); | |
} | |
eglSwapInterval(dpy,0); | |
return true; | |
} | |
void GLHelper::close() { | |
eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); | |
eglDestroyContext(dpy, context); | |
eglDestroySurface(dpy, surface); | |
eglTerminate(dpy); | |
dpy = EGL_NO_DISPLAY; | |
surface = EGL_NO_SURFACE; | |
context = EGL_NO_CONTEXT; | |
if (sphereProgram) { | |
glDeleteProgram(sphereProgram); | |
} | |
if (leftScreenProgram) { | |
glDeleteProgram(leftScreenProgram); | |
} | |
if (rightScreenProgram) { | |
glDeleteProgram(rightScreenProgram); | |
} | |
glDeleteRenderbuffers(1, &leftEyeFrameBufferDesc.m_nDepthBufferID); | |
glDeleteTextures(1, &leftEyeFrameBufferDesc.m_nRenderTextureID); | |
glDeleteFramebuffers(1, &leftEyeFrameBufferDesc.m_nRenderFramebufferID); | |
glDeleteRenderbuffers(1, &rightEyeFrameBufferDesc.m_nDepthBufferID); | |
glDeleteTextures(1, &rightEyeFrameBufferDesc.m_nRenderTextureID); | |
glDeleteFramebuffers(1, &rightEyeFrameBufferDesc.m_nRenderFramebufferID); | |
return; | |
} | |
bool GLHelper::setupGraphics() { | |
glCheckError(); | |
sphereProgram = glCreateProgram(); | |
if (!sphereProgram) { | |
return false; | |
} | |
addShader(GL_VERTEX_SHADER, SPHERE_VERTEXSHADER, sphereProgram); | |
addShader(GL_FRAGMENT_SHADER, SPHERE_FRAGMENTSHADER, sphereProgram); | |
glLinkProgram(sphereProgram); | |
GLint linkStatus = GL_FALSE; | |
glGetProgramiv(sphereProgram, GL_LINK_STATUS, &linkStatus); | |
if (linkStatus != GL_TRUE) { | |
LOGE("Link sphereProgram failed."); | |
return false; | |
} | |
leftScreenProgram = glCreateProgram(); | |
if (!leftScreenProgram) { | |
return false; | |
} | |
linkStatus = GL_FALSE; | |
addShader(GL_VERTEX_SHADER, SCREEN_VERTEXSHADER, leftScreenProgram); | |
addShader(GL_FRAGMENT_SHADER, SCREEN_FRAGMENTSHADER, leftScreenProgram); | |
glLinkProgram(leftScreenProgram); | |
glGetProgramiv(leftScreenProgram, GL_LINK_STATUS, &linkStatus); | |
if (linkStatus != GL_TRUE) { | |
LOGE("Link leftScreenProgram failed."); | |
return false; | |
} | |
rightScreenProgram = glCreateProgram(); | |
if (! rightScreenProgram) { | |
return false; | |
} | |
linkStatus = GL_FALSE; | |
addShader(GL_VERTEX_SHADER, SCREEN_VERTEXSHADER, rightScreenProgram); | |
addShader(GL_FRAGMENT_SHADER, SCREEN_FRAGMENTSHADER, rightScreenProgram); | |
glLinkProgram(rightScreenProgram); | |
glGetProgramiv(rightScreenProgram,GL_LINK_STATUS, &linkStatus); | |
if (linkStatus != GL_TRUE) { | |
LOGE("link rightScreenProgram failed."); | |
return false; | |
} | |
return true; | |
} | |
bool GLHelper::setupTextures() { | |
glUseProgram(sphereProgram); | |
glGenTextures(3, yuvTextures); | |
for (int i = 0; i < 3; i++) { | |
glUniform1i(glGetUniformLocation(sphereProgram, TEXTURE_UNIFORMS[i]), i); | |
glActiveTexture(GL_TEXTURE0 + i); | |
glBindTexture(GL_TEXTURE_2D, yuvTextures[i]); | |
glTexParameterf(GL_TEXTURE_2D, | |
GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |
glTexParameterf(GL_TEXTURE_2D, | |
GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |
glTexParameterf(GL_TEXTURE_2D, | |
GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |
glTexParameterf(GL_TEXTURE_2D, | |
GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |
} | |
glUseProgram(0); | |
return true; | |
} | |
bool GLHelper::setupVertices() { | |
int radius = 10; | |
int pieces = this->numberOfPatches; | |
int half_pieces = this->numberOfPatches/2; | |
double step_z = M_PI/(half_pieces); | |
double step_xy = step_z; | |
double angle_z; | |
double angle_xy; | |
float z[4] = {0.0f}; | |
float x[4] = {0.0f}; | |
float y[4] = {0.0f}; | |
float u[4] = {0.0f}; | |
float v[4] = {0.0f}; | |
int m = 0, n = 0; | |
for(int i = 0; i < half_pieces; i++) { | |
angle_z = i * step_z; | |
for(int j = 0; j < pieces;j ++ ) { | |
angle_xy = j * step_xy; | |
z[0] = (float)(radius * sin(angle_z)*cos(angle_xy)); | |
x[0]= (float)(radius*sin(angle_z)*sin(angle_xy)); | |
y[0]= (float)(radius*cos(angle_z)); | |
u[0]= (float)j / pieces; | |
v[0]= (float) i/half_pieces; | |
z[1] = (float)(radius*sin(angle_z+step_z)*cos(angle_xy)); | |
x[1] = (float)(radius*sin(angle_z + step_z)*sin(angle_xy)); | |
y[1] = (float)(radius*cos(angle_z+step_z)); | |
u[1] = (float)j/pieces; | |
v[1] = (float)(i+1)/half_pieces; | |
z[2] = (float)(radius*sin(angle_z+step_z)*cos(angle_xy+step_xy)); | |
x[2] = (float)(radius *sin(angle_z+step_z)*sin(angle_xy+step_xy)); | |
y[2] = (float)(radius*cos(angle_z+step_z)); | |
u[2] = (float)(j+1)/pieces; | |
v[2] = (float)(i+1)/half_pieces; | |
z[3] = (float)(radius*sin(angle_z)*cos(angle_xy+step_xy)); | |
x[3] = (float)(radius*sin(angle_z)*sin(angle_xy+step_xy)); | |
y[3] = (float)(radius*cos(angle_z)); | |
u[3] = (float)(j+1)/pieces; | |
v[3] = (float)i/half_pieces; | |
this->vertexCoordinates[m++] = x[0]; | |
this->vertexCoordinates[m++] = y[0]; | |
this->vertexCoordinates[m++] = z[0]; | |
this->uvCoordinates[n++] = u[0]; | |
this->uvCoordinates[n++] = v[0]; | |
this->vertexCoordinates[m++] = x[1]; | |
this->vertexCoordinates[m++] = y[1]; | |
this->vertexCoordinates[m++] = z[1]; | |
this->uvCoordinates[n++] = u[1]; | |
this->uvCoordinates[n++] = v[1]; | |
this->vertexCoordinates[m++] = x[2]; | |
this->vertexCoordinates[m++] = y[2]; | |
this->vertexCoordinates[m++] = z[2]; | |
this->uvCoordinates[n++] = u[2]; | |
this->uvCoordinates[n++] = v[2]; | |
this->vertexCoordinates[m++] = x[2]; | |
this->vertexCoordinates[m++] = y[2]; | |
this->vertexCoordinates[m++] = z[2]; | |
this->uvCoordinates[n++] = u[2]; | |
this->uvCoordinates[n++] = v[2]; | |
this->vertexCoordinates[m++] = x[3]; | |
this->vertexCoordinates[m++] = y[3]; | |
this->vertexCoordinates[m++] = z[3]; | |
this->uvCoordinates[n++] = u[3]; | |
this->uvCoordinates[n++] = v[3]; | |
this->vertexCoordinates[m++] = x[0]; | |
this->vertexCoordinates[m++] = y[0]; | |
this->vertexCoordinates[m++] = z[0]; | |
this->uvCoordinates[n++] = u[0]; | |
this->uvCoordinates[n++] = v[0]; | |
} | |
} | |
gSpherePositionAttribPointer = glGetAttribLocation(sphereProgram, "in_pos"); | |
gSphereSamplerAttribPointer = glGetAttribLocation(sphereProgram, "in_tc"); | |
gSphereMatrixUniformPointer = glGetUniformLocation(sphereProgram,"matrix"); | |
return true; | |
} | |
bool GLHelper::setupMatrix() { | |
return true; | |
} | |
void GLHelper::setRotationMatrix(float *rotation, int length) { | |
if(length != 16) { | |
LOGE("wrong rotation matrix"); | |
return; | |
} | |
myCamera->setRotateModel(rotation); | |
} | |
bool GLHelper::setupFrameBuffer(int screenWidth, int screenHeight, FramebufferDesc &framebufferDesc) { | |
glCheckError(); | |
// Generate Framebuffer Object ID | |
glGenFramebuffers(1, &framebufferDesc.m_nRenderFramebufferID); | |
glGenTextures(1, &framebufferDesc.m_nRenderTextureID); | |
glGenRenderbuffers(1, &framebufferDesc.m_nDepthBufferID); | |
// Generate Texture and setup Texture Parameters | |
glBindTexture(GL_TEXTURE_2D,framebufferDesc.m_nRenderTextureID); | |
// Framebuffer 里的Texture的宽高通常为屏幕的宽高 | |
glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,screenWidth,screenHeight,0,GL_RGB,GL_UNSIGNED_BYTE,NULL); | |
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); | |
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); | |
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE); | |
glBindRenderbuffer(GL_RENDERBUFFER,framebufferDesc.m_nDepthBufferID); | |
glRenderbufferStorage(GL_RENDERBUFFER,GL_DEPTH_COMPONENT16,screenWidth,screenHeight); | |
glBindFramebuffer(GL_FRAMEBUFFER, framebufferDesc.m_nRenderFramebufferID); | |
glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,framebufferDesc.m_nRenderTextureID,0); | |
glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_RENDERBUFFER,framebufferDesc.m_nDepthBufferID); | |
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); | |
if (status != GL_FRAMEBUFFER_COMPLETE) { | |
LOGE("Error in creating framebuffer object"); | |
return false; | |
} | |
glBindFramebuffer(GL_FRAMEBUFFER, 0); | |
return true; | |
} | |
void GLHelper::renderToTexture(int yuvFrameWidth, int yuvFrameHeight, unsigned char *YData, | |
unsigned char *UData, unsigned char *VData, EYE eye) { | |
if (eye == LEFT_EYE) { | |
glBindFramebuffer(GL_FRAMEBUFFER, leftEyeFrameBufferDesc.m_nRenderFramebufferID); | |
} else if (eye == RIGHT_EYE) { | |
glBindFramebuffer(GL_FRAMEBUFFER, rightEyeFrameBufferDesc.m_nRenderFramebufferID); | |
} | |
glUseProgram(sphereProgram); | |
glm::mat4 mvpMat = myCamera->GetMVP(eye); | |
float mat[16] = {0.0f}; | |
const float *pSrc = (const float *)glm::value_ptr(mvpMat); | |
for(int i = 0; i < 16;i++) { | |
mat[i] = pSrc[i]; | |
} | |
glUniformMatrix4fv(gSphereMatrixUniformPointer,1,GL_FALSE,mat); | |
n2 = now_ms(); | |
if (eye == LEFT_EYE) { | |
LOGE("matrix convert costs %f ms.",n2-n1); | |
} | |
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); | |
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); | |
glVertexAttribPointer(gSpherePositionAttribPointer,3,GL_FLOAT,GL_FALSE,0,this->vertexCoordinates); | |
glEnableVertexAttribArray(gSpherePositionAttribPointer); | |
glVertexAttribPointer(gSphereSamplerAttribPointer,2,GL_FLOAT,GL_FALSE,0,this->uvCoordinates); | |
glEnableVertexAttribArray(gSphereSamplerAttribPointer); | |
unsigned char *yuvPlanes[3]; | |
yuvPlanes[0] = YData; | |
yuvPlanes[1] = UData; | |
yuvPlanes[2] = VData; | |
glViewport(0,0,w,h); | |
glPixelStorei(GL_UNPACK_ALIGNMENT,1); | |
for (int i = 0; i < 3; i++) { | |
int w = (i == 0 ? yuvFrameWidth : yuvFrameWidth / 2); | |
int h = (i == 0 ? yuvFrameHeight : yuvFrameHeight / 2); | |
glActiveTexture(GL_TEXTURE0 + i); | |
glBindTexture(GL_TEXTURE_2D, yuvTextures[i]); | |
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, yuvPlanes[i]); | |
} | |
glDrawArrays(GL_TRIANGLES,0,this->vertexCount); | |
glBindTexture(GL_TEXTURE_2D,0); | |
glBindFramebuffer(GL_FRAMEBUFFER,0); | |
glUseProgram(0); | |
} | |
void GLHelper::renderToScreen() { | |
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); | |
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | |
glViewport(0,0,w,h); | |
glUseProgram(leftScreenProgram); | |
gLeftScreenPositionAttribPointer = glGetAttribLocation(leftScreenProgram, "in_pos"); | |
glEnableVertexAttribArray(gLeftScreenPositionAttribPointer); | |
glVertexAttribPointer(gLeftScreenPositionAttribPointer,2,GL_FLOAT,GL_FALSE,0,LEFTSCREEN_VERTICES); | |
gLeftScreenSamplerAttribPointer = glGetAttribLocation(leftScreenProgram, "in_tc"); | |
glEnableVertexAttribArray(gLeftScreenSamplerAttribPointer); | |
glVertexAttribPointer(gLeftScreenSamplerAttribPointer,2,GL_FLOAT,GL_FALSE,0,SAMPLER_VERTICES); | |
glUniform1i(glGetUniformLocation(leftScreenProgram,"texture"),3); | |
glActiveTexture(GL_TEXTURE3); | |
glBindTexture(GL_TEXTURE_2D, leftEyeFrameBufferDesc.m_nRenderTextureID); | |
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); | |
glBindTexture(GL_TEXTURE_2D, 0); | |
glUseProgram(0); | |
glUseProgram(rightScreenProgram); | |
gRightScreenPositionAttribPointer = glGetAttribLocation(rightScreenProgram, "in_pos"); | |
glEnableVertexAttribArray(gRightScreenPositionAttribPointer); | |
glVertexAttribPointer(gRightScreenPositionAttribPointer, 2, GL_FLOAT, GL_FALSE, 0, RIGHTSCREEN_VERTICES); | |
gRightScreenSamplerAttribPointer = glGetAttribLocation(rightScreenProgram, "in_tc"); | |
glEnableVertexAttribArray(gRightScreenSamplerAttribPointer); | |
glVertexAttribPointer(gRightScreenSamplerAttribPointer,2,GL_FLOAT,GL_FALSE,0,SAMPLER_VERTICES); | |
glUniform1i(glGetUniformLocation(rightScreenProgram,"texture"),4); | |
glActiveTexture(GL_TEXTURE4); | |
glBindTexture(GL_TEXTURE_2D, rightEyeFrameBufferDesc.m_nRenderTextureID); | |
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); | |
glBindTexture(GL_TEXTURE_2D, 0); | |
glUseProgram(0); | |
} | |
void GLHelper::drawFrame(int frameWidth, int frameHeight, unsigned char *YData, | |
unsigned char *UData, | |
unsigned char *VData) { | |
renderToTexture(frameWidth,frameHeight,YData,UData,VData,LEFT_EYE); | |
renderToTexture(frameWidth,frameHeight,YData,UData,VData,RIGHT_EYE); | |
renderToScreen(); | |
eglSwapBuffers(dpy,surface); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment