use*_*617 2 video android frame-rate opengl-es glteximage2d
Android NDK可以实现最快的2D帧速率,包括我的尝试,更好的选择?
我使用NDK和OpenGL ES 2.0在GL_TRIANGLE_STRIP上将框架显示为纹理.这是在HTC Desire上完成的,与Nexus One相同.我试图加载多个GL_RGBA纹理并在纹理之间切换,因为单个纹理的正常填充率令人失望地低:
我认为即使30.32 fps RGBA仍然太慢.
那么这是实现最快2D帧速率(具有相同质量)的方法吗?有什么建议可以加快速度吗?
这是相关代码,它基于hello-gl2 NDK示例:
=== GL2JNIView.java:
init(false, 0, 0);
ConfigChooser(5, 6, 5, 0, depth, stencil);
Run Code Online (Sandbox Code Playgroud)
=== gl_code.cpp:
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <android/log.h>
#include <stdlib.h>
#include <time.h>
typedef unsigned char byte;
static int view_width, view_height;
static byte* framebuffer;
static int framebuffer_size;
static GLuint texture_id[6];
static const char* vertexSrc =
"precision highp float;\n"
"precision highp int;\n"
"attribute vec4 vertexCoords;\n"
"attribute vec2 textureCoords;\n"
"varying vec2 f_textureCoords;\n"
"void main() {\n"
" f_textureCoords = textureCoords;\n"
" gl_Position = vertexCoords;\n"
"}\n";
static const char* fragmentSrc =
"precision highp float;\n"
"precision highp int;\n"
"uniform sampler2D texture;\n"
"varying vec2 f_textureCoords;\n"
"void main() {\n"
" gl_FragColor = texture2D(texture, f_textureCoords);\n"
"}\n";
static GLuint shaderProgram;
static GLint attrib_vertexCoords;
static GLint attrib_textureCoords;
static GLint uniform_texture;
static const GLfloat vertexCoords[] = {-1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, -1.0};
static const GLfloat textureCoords[] = {0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0};
JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_init(JNIEnv * env, jobject obj, jint width, jint height) {
view_width = width;
view_height = height;
framebuffer_size = 4*view_width*view_height;
framebuffer = (byte*)calloc(framebuffer_size, sizeof(byte));
for (int i = 0; i < framebuffer_size; i++) framebuffer[i] = 0;
glViewport(0, 0, view_width, view_height);
glGenTextures(6, &texture_id[0]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture_id[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, view_width, view_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture_id[1]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, view_width, view_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, texture_id[2]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, view_width, view_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer);
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, texture_id[3]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, view_width, view_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer);
glActiveTexture(GL_TEXTURE4);
glBindTexture(GL_TEXTURE_2D, texture_id[4]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, view_width, view_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer);
glActiveTexture(GL_TEXTURE5);
glBindTexture(GL_TEXTURE_2D, texture_id[5]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, view_width, view_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer);
shaderProgram = glCreateProgram();
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexSrc, NULL);
glCompileShader(vertexShader);
glAttachShader(shaderProgram, vertexShader);
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentSrc, NULL);
glCompileShader(fragmentShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glUseProgram(shaderProgram);
uniform_texture = glGetUniformLocation(shaderProgram, "texture");
glUniform1i(uniform_texture, 0);
attrib_vertexCoords = glGetAttribLocation(shaderProgram, "vertexCoords");
glEnableVertexAttribArray(attrib_vertexCoords);
glVertexAttribPointer(attrib_vertexCoords, 2, GL_FLOAT, GL_FALSE, 0, vertexCoords);
attrib_textureCoords = glGetAttribLocation(shaderProgram, "textureCoords");
glEnableVertexAttribArray(attrib_textureCoords);
glVertexAttribPointer(attrib_textureCoords, 2, GL_FLOAT, GL_FALSE, 0, textureCoords);
}
JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_step(JNIEnv * env, jobject obj) {
static int frame_count = 0;
static clock_t last_time = clock();
static int last_frame_count = 0;
frame_count++;
if (clock()-last_time > 1e7) {
__android_log_print(ANDROID_LOG_INFO, "libgl2jni", "fps: %f", ((float)frame_count-last_frame_count)/(clock()-last_time)*1e6);
last_time = clock();
last_frame_count = frame_count;
}
static byte val = 0;
val++;
if (val == 256) val = 0;
for (int i = 0; i < framebuffer_size; i++) framebuffer[i] = val;
int tst = frame_count%6;
if (tst == 0) {
glActiveTexture(GL_TEXTURE0);
} else if (tst == 1) {
glActiveTexture(GL_TEXTURE1);
} else if (tst == 2) {
glActiveTexture(GL_TEXTURE2);
} else if (tst == 3) {
glActiveTexture(GL_TEXTURE3);
} else if (tst == 4) {
glActiveTexture(GL_TEXTURE4);
} else if (tst == 5) {
glActiveTexture(GL_TEXTURE5);
}
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, view_width, view_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
Run Code Online (Sandbox Code Playgroud)
我意识到你的问题相当陈旧,而且你可能要么已经解决了问题,要么转移到别的东西上,但如果有其他人遇到这个问题,我会给出一个建议.
首先,glTexImage2D要求图形子系统在每次调用时都执行无内存和纹理对象的重新分配,因为纹理参数可以在调用之间改变.优化的驱动程序可能会查看宽度,高度和格式,如果它们都相同,则可以跳过重新分配,但Android驱动程序实现者实际上不太可能这样做.
为了完全避免纹理重新分配,您可以使用glTexSubImage2D替换完整的位图,或仅替换其中的一部分.如果将此与上面的纹理缓冲方案结合使用,您应该会看到相当大的速度增加.您甚至可以扩展它以检测显示器的修改区域,并仅更新帧之间已更改的矩形部分.
总而言之,更改纹理初始化代码以glTexImage2D使用NULL位图指针调用,因此OpenGL仅为纹理分配内存,并且实际上不会将任何数据复制到其中,如下所示:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, view_width, view_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
Run Code Online (Sandbox Code Playgroud)
然后使用以下命令更新游戏循环中的每一帧:
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, view_width, view_height, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6390 次 |
| 最近记录: |