Opengl es 利用opengles实现图像旋转

Opengl es 利用opengles实现图像旋转,opengl-es,image-rotation,Opengl Es,Image Rotation,我正在使用WindowsCE7上的OMAP3530开发板开发OpenGLES2.0 我的任务是加载一个24位图像文件,并将其沿z轴旋转一个角度,然后导出图像文件(缓冲区) 对于此任务,我创建了一个用于屏幕外渲染的FBO,并使用glTexImage2D()将此图像文件作为纹理加载&我已将此纹理应用于四边形,并使用PVRTMat4::RotationZ()API旋转该四边形,使用ReadPixels()API回读。因为这是一个单帧过程,所以我只做了一个循环 以下是我现在面临的问题。 1) 所有API

我正在使用WindowsCE7上的OMAP3530开发板开发OpenGLES2.0

我的任务是加载一个24位图像文件,并将其沿z轴旋转一个角度,然后导出图像文件(缓冲区)

对于此任务,我创建了一个用于屏幕外渲染的FBO,并使用glTexImage2D()将此图像文件作为纹理加载&我已将此纹理应用于四边形,并使用PVRTMat4::RotationZ()API旋转该四边形,使用ReadPixels()API回读。因为这是一个单帧过程,所以我只做了一个循环

以下是我现在面临的问题。 1) 所有API在每次运行时都会占用不同的处理时间。也就是说,有时当我运行应用程序时,所有API的处理时间都不同

2) glDrawArrays()占用的时间太长(~50毫秒-80毫秒)

3) glReadPixels()对图像(800x600)也花费了太多时间~95毫秒

4) 加载32位图像比加载24位图像快得多,因此需要进行转换

我想问大家,如果有人遇到/解决了类似的问题,请给我一些建议

下面是我的应用程序的代码片段

[code]
[i]
void BindTexture(){
glGenTextures(1, &m_uiTexture);
glBindTexture(GL_TEXTURE_2D, m_uiTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ImageWidth, ImageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, pTexData);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR );
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, TCHAR *lpCmdLine, int nCmdShow)
{
// Fragment and vertex shaders code
char* pszFragShader = "Same as in RenderToTexture sample;
char* pszVertShader = "Same as in RenderToTexture sample;

CreateWindow(Imagewidth, ImageHeight);//For this i've referred OGLES2HelloTriangle_Windows.cpp example
LoadImageBuffers();
BindTexture();

Generate& BindFrame,Render Buffer();
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_auiFbo, 0);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, ImageWidth, ImageHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_auiDepthBuffer);
BindTexture();

GLfloat Angle = 0.02f;
GLfloat afVertices[] = {Vertices to Draw a QUAD};

glGenBuffers(1, &ui32Vbo);
LoadVBO's();//Aps's to load VBO's refer

// Draws a triangle for 1 frames
while(g_bDemoDone==false)
{
glBindFramebuffer(GL_FRAMEBUFFER, m_auiFbo);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

PVRTMat4 mRot,mTrans, mMVP;
mTrans = PVRTMat4::Translation(0,0,0);
mRot = PVRTMat4::RotationZ(Angle);

glBindBuffer(GL_ARRAY_BUFFER, ui32Vbo);
glDisable(GL_CULL_FACE);

int i32Location = glGetUniformLocation(uiProgramObject, "myPMVMatrix");
mMVP = mTrans * mRot ;

glUniformMatrix4fv(i32Location, 1, GL_FALSE, mMVP.ptr());

// Pass the vertex data
glEnableVertexAttribArray(VERTEX_ARRAY);
glVertexAttribPointer(VERTEX_ARRAY, 3, GL_FLOAT, GL_FALSE, m_ui32VertexStride, 0);

// Pass the texture coordinates data
glEnableVertexAttribArray(TEXCOORD_ARRAY);
glVertexAttribPointer(TEXCOORD_ARRAY, 2, GL_FLOAT, GL_FALSE, m_ui32VertexStride, (void*) (3 * sizeof(GLfloat)));

glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);//

glReadPixels(0,0,ImageWidth ,ImageHeight,GL_RGBA,GL_UNSIGNED_BYTE,pOutTexData) ;

glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);

eglSwapBuffers(eglDisplay, eglSurface);

}

DeInitAll();[/i][/code]
InitGL()
GenerateShaders();
Generate3Textures();//Generate 3 Null Textures
Generate3FBO();//Generate 3 FBO & Attach each Texture to 1 FBO.
Generate3PBO();//Generate 3 PBO & to readback from FBO.

DrawGL()
{
 BindFBO1;
 BindTexture1;
 UploadtoTexture1;
 Do Some Processing & Draw it in FBO1;

 BindFBO2;
 BindTexture2;
 UploadtoTexture2;
 Do Some Processing & Draw it in FBO2;

 BindFBO3;
 BindTexture3;
 UploadtoTexture3;
 Do Some Processing & Draw it in FBO3;


 BindFBO1;
 ReadPixelfromFBO1;
 UnpackToPBO1;

 BindFBO2;
 ReadPixelfromFBO2;
 UnpackToPBO2;

 BindFBO3;
 ReadPixelfromFBO3;
 UnpackToPBO3;
}


DeinitGL();
DeallocateALL();

PowerVR体系结构无法渲染单个帧并允许ARM快速读回。它并不是为了快速工作而设计的——它是一种基于延迟渲染分片的体系结构。您看到的执行时间太长,这是意料之中的,使用FBO也不会使执行速度更快。另外,请注意,OMAP for Windows CE上的OpenGL ES驱动程序的质量非常差。如果他们工作的话,想想自己是幸运的。


更好的设计是直接向DSS显示OpenGL ES渲染,并避免完全使用glReadPixels()和FBO。

我已经改进了使用多个FBO和PBO旋转图像缓冲区的性能。 下面是我的应用程序的伪代码片段

[code]
[i]
void BindTexture(){
glGenTextures(1, &m_uiTexture);
glBindTexture(GL_TEXTURE_2D, m_uiTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ImageWidth, ImageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, pTexData);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR );
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, TCHAR *lpCmdLine, int nCmdShow)
{
// Fragment and vertex shaders code
char* pszFragShader = "Same as in RenderToTexture sample;
char* pszVertShader = "Same as in RenderToTexture sample;

CreateWindow(Imagewidth, ImageHeight);//For this i've referred OGLES2HelloTriangle_Windows.cpp example
LoadImageBuffers();
BindTexture();

Generate& BindFrame,Render Buffer();
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_auiFbo, 0);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, ImageWidth, ImageHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_auiDepthBuffer);
BindTexture();

GLfloat Angle = 0.02f;
GLfloat afVertices[] = {Vertices to Draw a QUAD};

glGenBuffers(1, &ui32Vbo);
LoadVBO's();//Aps's to load VBO's refer

// Draws a triangle for 1 frames
while(g_bDemoDone==false)
{
glBindFramebuffer(GL_FRAMEBUFFER, m_auiFbo);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

PVRTMat4 mRot,mTrans, mMVP;
mTrans = PVRTMat4::Translation(0,0,0);
mRot = PVRTMat4::RotationZ(Angle);

glBindBuffer(GL_ARRAY_BUFFER, ui32Vbo);
glDisable(GL_CULL_FACE);

int i32Location = glGetUniformLocation(uiProgramObject, "myPMVMatrix");
mMVP = mTrans * mRot ;

glUniformMatrix4fv(i32Location, 1, GL_FALSE, mMVP.ptr());

// Pass the vertex data
glEnableVertexAttribArray(VERTEX_ARRAY);
glVertexAttribPointer(VERTEX_ARRAY, 3, GL_FLOAT, GL_FALSE, m_ui32VertexStride, 0);

// Pass the texture coordinates data
glEnableVertexAttribArray(TEXCOORD_ARRAY);
glVertexAttribPointer(TEXCOORD_ARRAY, 2, GL_FLOAT, GL_FALSE, m_ui32VertexStride, (void*) (3 * sizeof(GLfloat)));

glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);//

glReadPixels(0,0,ImageWidth ,ImageHeight,GL_RGBA,GL_UNSIGNED_BYTE,pOutTexData) ;

glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);

eglSwapBuffers(eglDisplay, eglSurface);

}

DeInitAll();[/i][/code]
InitGL()
GenerateShaders();
Generate3Textures();//Generate 3 Null Textures
Generate3FBO();//Generate 3 FBO & Attach each Texture to 1 FBO.
Generate3PBO();//Generate 3 PBO & to readback from FBO.

DrawGL()
{
 BindFBO1;
 BindTexture1;
 UploadtoTexture1;
 Do Some Processing & Draw it in FBO1;

 BindFBO2;
 BindTexture2;
 UploadtoTexture2;
 Do Some Processing & Draw it in FBO2;

 BindFBO3;
 BindTexture3;
 UploadtoTexture3;
 Do Some Processing & Draw it in FBO3;


 BindFBO1;
 ReadPixelfromFBO1;
 UnpackToPBO1;

 BindFBO2;
 ReadPixelfromFBO2;
 UnpackToPBO2;

 BindFBO3;
 ReadPixelfromFBO3;
 UnpackToPBO3;
}


DeinitGL();
DeallocateALL();

通过这种方式,我的整体处理性能提高了50%。

谢谢@ClayMontgomery的回复。我会考虑你的建议。如果你指定了直接渲染到DSS的方法,那么DSS是在OMAP上显示OpenGL ES渲染图形的正常路径。这不需要什么特别的东西。