我之所以这么说是因为我们的应用程序(The Elements)在Droid和Nexus One(我们的两款测试手机)上运行良好,但在我们最近收购的Atrix 4G上运行不正确。绘制的是应该绘制的偏斜版本,所有颜色都被青色,品红色和黄色(大约)的交替线替换,这使我们相信应该出现的沙粒的一种主要颜色根据它所在的行而丢失。对于不清楚的描述我很抱歉,我们有图片,但由于这个帐户没有10个声誉我们无法发布。
这是gl.c文件的代码,它执行纹理和渲染:
/*
* gl.c
* --------------------------
* Defines the gl rendering and initialization
* functions appInit, appDeinit, and appRender.
*/
#include "gl.h"
#include <android/log.h>
unsigned int textureID;
float vertices[] =
{0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f};
float texture[] =
{0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f};
unsigned char indices[] =
{0, 1, 3, 0, 3, 2};
int texWidth = 1, texHeight = 1;
void glInit()
{
//Set some properties
glShadeModel(GL_FLAT);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
//Generate the new texture
glGenTextures(1, &textureID);
//Bind the texture
glBindTexture(GL_TEXTURE_2D, textureID);
//Enable 2D texturing
glEnable(GL_TEXTURE_2D);
//Disable depth testing
glDisable(GL_DEPTH_TEST);
//Enable the vertex and coord arrays
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
//Set tex params
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
//Set up texWidth and texHeight texHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, emptyPixels);
//Free the dummy array
free(emptyPixels);
//Set the pointers
glVertexPointer(2, GL_FLOAT, 0, vertices);
glTexCoordPointer(2, GL_FLOAT, 0, texture);
}
void glRender()
{
//Check for changes in screen dimensions or work dimensions and handle them
if(dimensionsChanged)
{
vertices[2] = (float) screenWidth;
vertices[5] = (float) screenHeight;
vertices[6] = (float) screenWidth;
vertices[7] = (float) screenHeight;
texture[2] = (float) workWidth/texWidth;
texture[5] = (float) workHeight/texHeight;
texture[6] = (float) workWidth/texWidth;
texture[7] = (float) workHeight/texHeight;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (!flipped)
{
glOrthof(0, screenWidth, screenHeight, 0, -1, 1); //--Device
}
else
{
glOrthof(0, screenWidth, 0, -screenHeight, -1, 1); //--Emulator
}
dimensionsChanged = FALSE;
zoomChanged = FALSE;
}
else if(zoomChanged)
{
texture[2] = (float) workWidth/texWidth;
texture[5] = (float) workHeight/texHeight;
texture[6] = (float) workWidth/texWidth;
texture[7] = (float) workHeight/texHeight;
zoomChanged = FALSE;
}
//__android_log_write(ANDROID_LOG_INFO, "TheElements", "updateview begin");
UpdateView();
//__android_log_write(ANDROID_LOG_INFO, "TheElements", "updateview end");
//Clear the screen
glClear(GL_COLOR_BUFFER_BIT);
//Sub the work portion of the tex
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, workWidth, workHeight, GL_RGB, GL_UNSIGNED_BYTE, colors);
//Actually draw the rectangle with the text on it
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices);
}
关于Atrix 4G与其他手机在OpenGL方面的区别或者为什么我们的应用程序正在做的事情的任何想法都非常感谢!提前谢谢。
以下是一个示例:http://imgur.com/Oyw64
答案 0 :(得分:3)
我知道回复有点迟,但你看到混合颜色的真正原因是由于OpenGL的扫描线打包对齐 - 不是因为任何驱动程序错误或两个大小的纹理问题。
您的glTexSubImage2D
来电正在以GL_RGB
格式发送数据,因此我猜测您的colors
缓冲区每个像素为3个字节。赔率是Droid和Nexus One手机的默认包对齐为1,但Tegra 2默认为4的对齐。这意味着您的3字节数组可能会与驱动程序在每条扫描线之后所期望的一致,以及一个或两个字节将跳过下一个扫描线,从而产生您看到的颜色。之所以能够使用两倍大小的纹理,是因为您的缓冲区恰好在下一个扫描线上正确对齐。基本上这与加载BMP的问题相同,无论图像的位深度如何,每个扫描线都必须填充到4个字节。
您可以通过调用glPixelStorei(GL_PACK_ALIGNMENT, 1);
显式禁用任何对齐打包。请注意,更改此选项仅会影响OpenGL解释纹理数据的方式,因此更改此值时不会出现呈现性能损失。当纹理发送到图形子系统时,扫描线以任何最适合硬件的格式存储,但驱动程序仍然必须知道如何正确解压缩数据。但是,由于您每帧都在更改纹理数据,而不是驱动程序能够执行一个memcpy()
上传整个纹理,因此必须执行TextureHeight * memcpy()
才能上传它。这可能不是一个主要的瓶颈,但如果您正在寻找最佳性能,您可能希望使用glGetIntegerv(GL_PACK_ALIGNMENT, &align);
在启动时查询驱动程序的默认包对齐,并在运行时相应地调整缓冲区。
答案 1 :(得分:1)
好的,我们终于找到了实际问题。事实证明glSubTexImage2D()实际上要求WIDTH是2的幂,但不是高度,对于包括Tegra 2在内的一些GPU而言。虽然它只是纹理需要是2的幂,那就是我们错了。我们将不得不做一些重新编码,但希望这最终能够解决(最后一次!!)。
答案 2 :(得分:0)
Atrix 4G是第一款采用Nvidia Tegra GPU的着名手机。因此,它具有与以前的Android设备完全不同的OpenGL实现。要么您正在观察Tegra硬件+软件组合的错误,要么您的应用程序依赖于未定义的行为,并且您在其他设备上获得了幸运。
您可能希望向Nvidia提交错误报告。