GLKBaseEffect не загружает текстуру (текстура выглядит черной на объекте)
Я использую GLKit в проекте OpenGL. Все основано на GLKView и GLKBaseEffect (без пользовательских шейдеров). В моем проекте у меня есть несколько видов, которые имеют GLKView для отображения трехмерных объектов, и иногда некоторые из этих видов могут быть "открыты" одновременно (т.е. находятся в стеке модальных видов).
В то время как до сих пор все работало отлично, в новом виде, который я создавал, мне нужно было иметь прямоугольник с текстурой, чтобы имитировать измерительную ленту для трехмерного мира моего приложения. По какой-то неизвестной причине, только в этом представлении текстура не загружается прямо в контекст opengl: текстура загружается прямо GLKTextureLoader, но при рисовании прямоугольника черного цвета и при просмотре фрейма OpenGL в отладке я вижу что пустая текстура загружена (есть ссылка на текстуру, но она обнуляется или равна нулю).
Форма, которую я рисую, определяется следующим образом: (изначально это была полоса треугольника, но я переключился на треугольники, чтобы убедиться, что это не проблема)
static const GLfloat initTape[] = {
-TAPE_WIDTH / 2.0f, 0, 0,
TAPE_WIDTH / 2.0f, 0, 0,
-TAPE_WIDTH / 2.0f, TAPE_INIT_LENGTH, 0,
TAPE_WIDTH / 2.0f, 0, 0,
TAPE_WIDTH / 2.0f, TAPE_INIT_LENGTH, 0,
-TAPE_WIDTH / 2.0f, TAPE_INIT_LENGTH, 0,
};
static const GLfloat initTapeTex[] = {
0, 0,
1, 0,
0, 1.0,
1, 0,
1, 1,
0, 1,
};
Я устанавливаю переменную эффекта как:
effect.transform.modelviewMatrix = modelview;
effect.light0.enabled = GL_FALSE;
// Projection setup
GLfloat ratio = self.view.bounds.size.width/self.view.bounds.size.height;
GLKMatrix4 projection = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(self.fov), ratio, 0.1f, 1000.0f);
effect.transform.projectionMatrix = projection;
// Set the color of the wireframe.
if (tapeTex == nil) {
NSError* error;
tapeTex = [GLKTextureLoader textureWithContentsOfFile:[[[NSBundle mainBundle] URLForResource:@"ruler_texture" withExtension:@"png"] path] options:nil error:&error];
}
effect.texture2d0.enabled = GL_TRUE;
effect.texture2d0.target = GLKTextureTarget2D;
effect.texture2d0.envMode = GLKTextureEnvModeReplace;
effect.texture2d0.name = tapeTex.name;
И цикл рендеринга:
[effect prepareToDraw];
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glEnableVertexAttribArray(GLKVertexAttribPosition);
glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
glVertexAttribPointer(GLKVertexAttribPosition, COORDS, GL_FLOAT, GL_FALSE, 0, tapeVerts);
glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, 0, tapeTexCoord);
glDrawArrays(GL_TRIANGLES, 0, TAPE_VERTS);
glDisableVertexAttribArray(GLKVertexAttribPosition);
glDisableVertexAttribArray(GLKVertexAttribTexCoord0);
Я также проверил саму текстуру в другом виде с другими объектами, и она отлично работает, так что это не ошибка файла текстуры.
Любая помощь будет принята с благодарностью, так как я застрял в этом вопросе более 3 дней.
Обновление: Кроме того, в цикле рендеринга нет ошибок glErrors.
2 ответа
Спустя много дней я наконец-то нашел свою ошибку: при использовании нескольких контекстов openGL важно создать GLKTextureLoader с помощью shareGroup, иначе текстуры не обязательно будут загружены в нужный контекст.
Вместо использования метода класса textureWithContentOf для каждого контекста требуется собственный GLKTextureLoader, который инициализируется с помощью context.sharegroup, и для этого представления используется только этот загрузчик текстур. (на самом деле текстуры могут быть сохранены в разных контекстах, но мне не нужна была эта функция в группах).
Простой учебник http://games.ianterrell.com/how-to-texturize-objects-with-glkit/ Я думаю, что это поможет вам.