Загадка мне это,Android OpenGL ES 2.0 - текстуры не отображаются на некоторых устройствах
Я недавно опубликовал игру для Android (play.google.com/store/apps/details?id=com.quackers, если вы хотите чтобы убедиться в проблемах из первых рук), а первоначальная обратная связь предполагает, что эта вещь не работает должным образом на некоторых устройствах. С тех пор у меня есть одна из оскорбительных таблеток (Samsung Galaxy Tab 2 7.0), и получается, что она делает run, она просто не отображала вещи должным образом.
Несколько раскопок позже, и я обнаружил, что это проблема текстурирования. Текстуры загружаются нормально, но они не обрабатываются - не обычные черные квадраты, которые вы часто получаете с OpenGL, когда что-то идет не так - ничего.
Это OpenGL ES 2.0, выполняющий SDL/C++/ndk. Хотя в сети есть аналогичные проблемы, большая часть из них связана с ES 1.0 и рассматривает другую проблему - размеры текстур не являются степенями двух (например, 64x64, 128x128, 256x256 и т. Д.) Или некоторыми дурацкими материалами сжатия, которые здесь не применяются.
Я удалил весь свой код рендеринга и вернулся к основам - рендеринг текстурированного квадрата (не особенно оптимизированным образом).
код Pre-петля:
SDL_Init(SDL_INIT_VIDEO);
SDL_LogSetAllPriority(SDL_LOG_PRIORITY_VERBOSE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
SDL_DisplayMode mode;
SDL_GetDisplayMode(0,0, &mode);
_currentWidth = mode.w;
_currentHeight = mode.h;
SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
_screen = SDL_CreateWindow("window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, _currentWidth, _currentHeight, SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN | SDL_WINDOW_RESIZABLE);
SDL_GLContext context = SDL_GL_CreateContext(_screen);
SDL_GL_MakeCurrent(_screen, context);
glViewport(0, 0, _currentWidth, _currentHeight);
//---
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
const char *vs_source = "attribute highp vec2 coord2d; "
"attribute highp vec2 texcoord;"
"varying highp vec2 f_texcoord;"
"void main(void) { "
"gl_Position = vec4(coord2d, 0.0, 1.0); "
"f_texcoord = texcoord;"
"}";
glShaderSource(vs, 1, &vs_source, NULL);
glCompileShader(vs);
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
const char *fs_source = "varying highp vec2 f_texcoord;"
"uniform sampler2D texture;"
"void main(void) { "
"vec2 flipped_texcoord = vec2(f_texcoord.x, 1.0 - f_texcoord.y);"
"gl_FragColor = texture2D(texture, flipped_texcoord);"
"}";
glShaderSource(fs, 1, &fs_source, NULL);
glCompileShader(fs);
_program = glCreateProgram();
glAttachShader(_program, vs);
glAttachShader(_program, fs);
glLinkProgram(_program);
//---
GLuint vs2 = glCreateShader(GL_VERTEX_SHADER);
const char *vs_source2 = "attribute vec2 coord2d; "
"void main(void) { "
"gl_Position = vec4(coord2d, 0.0, 1.0); "
"}";
glShaderSource(vs2, 1, &vs_source2, NULL);
glCompileShader(vs2);
GLuint fs2 = glCreateShader(GL_FRAGMENT_SHADER);
const char *fs_source2 = "uniform lowp vec4 u_colour;"
"void main(void) { "
"gl_FragColor = u_colour;"
"}";
glShaderSource(fs2, 1, &fs_source2, NULL);
glCompileShader(fs2);
_flatProgram = glCreateProgram();
glAttachShader(_flatProgram, vs2);
glAttachShader(_flatProgram, fs2);
glLinkProgram(_flatProgram);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
//---------------------------------------
_screenRect.x = -1.0;
_screenRect.y = -1.0;
_screenRect.w = 2.0;
_screenRect.h = 2.0;
_superDuperFrameBuffer = 0;
_depthRenderBuffer = 0;
glGenTextures(1, &_screenTexture);
glBindTexture(GL_TEXTURE_2D, _screenTexture);
if(_currentWidth < SCREENWIDTH*2 || _currentHeight < SCREENHEIGHT*2) {
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
else {
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_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);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SCREENWIDTH, SCREENHEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glGenRenderbuffers(1, &_depthRenderBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, _depthRenderBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, SCREENWIDTH, SCREENHEIGHT);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
// create a framebuffer object
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glGenFramebuffers(1, &_superDuperFrameBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, _superDuperFrameBuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _screenTexture, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthRenderBuffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _depthRenderBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
_defaultFrameBuffer = 0;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &_defaultFrameBuffer);
glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
glEnable(GL_BLEND);
glEnable(GL_TEXTURE_2D);
SDL_Surface* testSurface = IMG_Load("graphics/bg_01_0.png");
uint32_t rmask;
uint32_t gmask;
uint32_t bmask;
uint32_t amask;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
rmask = 0xff000000;
gmask = 0x00ff0000;
bmask = 0x0000ff00;
amask = 0x000000ff;
#else
rmask = 0x000000ff;
gmask = 0x0000ff00;
bmask = 0x00ff0000;
amask = 0xff000000;
#endif
SDL_Surface *tempSurface = SDL_CreateRGBSurface(0, testSurface->w, testSurface->h, 32, rmask, gmask, bmask, amask);
SDL_SetSurfaceBlendMode(tempSurface, SDL_BLENDMODE_BLEND);
SDL_BlitSurface(testSurface, NULL, tempSurface, NULL);
testSurface = tempSurface;
SDL_FreeSurface(tempSurface);
GLint uniformTexture = glGetUniformLocation(_program, "texture");
_testTexture = 0;
glGenTextures(1, &_testTexture);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, _testTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glUniform1i(uniformTexture, /*GL_TEXTURE*/0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, testSurface->pixels);
_vboTest = 0;
_vbo_cube_texcoords = 0;
glGenBuffers(1, &_vboTest);
glGenBuffers(1, &_vbo_cube_texcoords);
петля:
...
_quadColour[0] = 0.0f;
_quadColour[1] = 255.0f;
_quadColour[2] = 0.0f;
_quadColour[3] = 1.0f;
drawSquare(0, 0, 20, 20);
glViewport(0, 0, SCREENWIDTH, SCREENHEIGHT);
GLfloat x1 = 0, x2 = 8, y1 = 0, y2 = 8;
glUseProgram(_program);
GLint attributeCoord2d = glGetAttribLocation(_program, "coord2d");
GLint attributeTexcoord = glGetAttribLocation(_program, "texcoord");
glEnableVertexAttribArray(attributeTexcoord);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, _testTexture);
GLfloat cube_texcoords[] = {
0.0, 1.0,
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
};
glBindBuffer(GL_ARRAY_BUFFER, _vbo_cube_texcoords);
glVertexAttribPointer(attributeTexcoord, 2, GL_FLOAT, GL_FALSE, 0, 0);
glBufferData(GL_ARRAY_BUFFER, sizeof(cube_texcoords), cube_texcoords, GL_STATIC_DRAW);
glEnableVertexAttribArray(attributeCoord2d);
GLfloat triangle_vertices[] = {
x1, y2,
x1, y1,
x2, y1,
x2, y2,
};
glBindBuffer(GL_ARRAY_BUFFER, _vboTest);
glVertexAttribPointer(attributeCoord2d, 2, GL_FLOAT, GL_FALSE, 0, 0);
glBufferData(GL_ARRAY_BUFFER, sizeof(triangle_vertices), triangle_vertices, GL_STATIC_DRAW);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
SDL_GL_SwapWindow(_screen);
...
, очевидно, есть некоторые вещи, я только добавил для целей тестирования, как преобразование текстуры RGBA и любой другой. Он рисует маленький зеленый квадрат, а затем текстурированный квадрат.
код может быть грязным, но дело это - два разных результата:
Galaxy Tab 2 7.0 (Bork) http://i.imgur.com/ht6LvFV.png
Nexus 7 (правильный) http://i.imgur.com/p4acmIq.png
Как исправить это?
Испытывали ли вы свои попытки на других устройствах и получали аналогичные результаты из-за архитектур графического процессора? (Не знаю, связано ли это с немедленным отсроченным рендерингом) –
Я не достаточно богат, чтобы позволить себе использовать устройства bazillion: P Но он работает на все остальное. Я считаю, что могут быть подобные ошибки на старых Kindle HDXes - Amazon просто сообщает «черный экран». Мне также сказали, что это не удается на 2012 Nexus 7 (но не в 2013 году, который у меня есть). На нескольких устройствах HTC были достигнуты успехи, так что это очень популярно. –
Сила 2 текстур по-прежнему требуется на Opengl ES 2. На некоторых устройствах может работать неэнергия из двух текстур. –