Ошибка glUniformMatrix4fv с кодом ошибки GL_INVALID_OPERATION - PullRequest
16 голосов
/ 12 марта 2012

Мне не повезло, пытаясь связать единую матрицу 4х4.Я нацеливаюсь на OpenGL 3.3 с этой программой, но моя среда - OpenGL 4.2.У меня есть функция, которая просто связывает единичную матрицу с униформой в моем вершинном шейдере, но вызов glUniformMatrix4fv завершается неудачно с GL_INVALID_OPERATION.

Вот мой вершинный шейдер:

#version 330
in vec4 in_vertex;
uniform mat4 mvMatrix;
void main(void) {
    gl_Position = mvMatrix * in_vertex;
}

I 'Я знаю о подводных камнях, связанных с транспозицией матрицы и умножением влево / вправо, но я полагаю, что это битва, когда я действительно могу передать однородную матрицу.

Вот простая функция, на которую ссылается функция, в которой явозникли проблемы.Сейчас я использую это только для того, чтобы попытаться определить место, где произошла ошибка.Поскольку оценка glUniformMatrix4fv полностью выполняется на стороне сервера, я не могу использовать точки останова и т. Д.

inline void die_on_gl_error(const char* location) {
    GLenum error = GL_NO_ERROR;
    error = glGetError();
    if (GL_NO_ERROR != error) {
        printf("GL Error %x encountered in %s.\n", error, location);
        exit(1);
    }
}

Документы SDK говорят, что есть несколько причинпочему glMatrixUniform4fv может установить GL_INVALID_OPERATION:

  1. GL_INVALID_OPERATION генерируется, если нет текущего программного объекта.
  2. GL_INVALID_OPERATION генерируется, если размер универсальной переменной, объявленной в шейдере, не соответствуетразмер указывается командой glUniform.
  3. GL_INVALID_OPERATION генерируется, если один из целочисленных вариантов этой функции используется для загрузки универсальной переменной типа float, vec2, vec3, vec4 или их массива, или еслиодин из вариантов этой функции с плавающей запятой используется для загрузки универсальной переменной типа int, ivec2, ivec3 или ivec4, или их массив.
  4. GL_INVALID_OPERATION генерируется, если location является недопустимым универсальным местоположениемдля текущего объекта программы и местоположение не равно -1.
  5. GL_INVALID_OPERATION генерируется, если число больше 1 и указанная универсальная переменная не является переменной массива.
  6. GL_INVALID_OPERATION генерируется, если сэмплер загружается с использованием команды, отличной от glUniform1i и glUniform1iv.
  7. GL_INVALID_OPERATION генерируется, если glUniform выполняется между выполнением glBegin и соответствующим выполнением glEnd.

Для контекста, объект, из которого вызывается эта функция, имеет параметр с именем active_program, который хранит числотекущая активированная программа GLSL.identity_matrix объявляется как:

float identity_matrix[16];

и определяется как:

identity_matrix = {
            1.0f, 0.0f, 0.0f, 0.0f,
            0.0f, 1.0f, 0.0f, 0.0f,
            0.0f, 0.0f, 1.0f, 0.0f,
            0.0f, 0.0f, 0.0f, 1.0f
};

Без лишних слов, вот что доставляет мне неприятности:

void VSGL::load_identity_matrix() {
// GL_INVALID_OPERATION is generated if there is no current program object.
if (!glIsProgram(active_program)) {
    printf("Active program is not valid.\n");
    exit(1);
}

// ... active_program is a program, but is it valid?
GLint program_valid = 0;
glValidateProgram(active_program);
glGetProgramiv(active_program, GL_VALIDATE_STATUS, &program_valid);
if (GL_TRUE != program_valid) {
    printf("Program validation failed.\n");
    exit(1);
}
die_on_gl_error("GetProgram (Validate Status)");

// ... makes sure there is a program active, and the current program matches
// the value stored in active_program.
GLint current_program = 0;
glGetIntegerv(GL_CURRENT_PROGRAM, &current_program);
if (0 == current_program) {
    printf("Error, no current program is set.\n");
    exit(1);
} else if (current_program != active_program) {
    printf("Error, current program doesn't match active_program!\n");
}
die_on_gl_error("GetInteger");

// ... ensures the program actually has an active uniform, as the docs
// say that uniforms can be optimized out if they don't contribute to
// out results.
GLint num_active_uniforms = 0;
glGetProgramiv(active_program, GL_ACTIVE_UNIFORMS, &num_active_uniforms);
if (0 == num_active_uniforms) {
    printf("There are 0 uniforms active in program %d.\n", active_program);
    exit(1);
} else {
    printf("There are %d uniform(s) active in program %d.\n", num_active_uniforms, active_program);
}
die_on_gl_error("GetProgram (Active Uniforms)");

// GL_INVALID_OPERATION is generated if the size of the uniform variable
// declared in the shader does not match the size indicated by the glUniform
// command.

// GL_INVALID_OPERATION is generated if location is an invalid uniform location
// for the current program object and location is not equal to -1.

// ... gets some basic information about the active uniforms, of which there
// should be only one, a FLOAT_MAT4 of size 1.
const GLchar *uniform_name = "mvMatrix";
GLint location = glGetUniformLocation(active_program, uniform_name);
die_on_gl_error("GetUniformLocation");

GLchar *message;
GLint max_uniform_length;
glGetProgramiv(active_program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_uniform_length);
message = new GLchar[max_uniform_length];
GLint size;
GLenum type;
glGetActiveUniform(active_program, location, max_uniform_length, NULL, &size, &type, message);
printf("Uniform %s:\tType:%x\tSize:%d\n", message, type, size);
if (GL_FLOAT_MAT4 != type) {
    printf("Active uniform at location is not a 4x4 float matrix.\n");
}
die_on_gl_error("GetActiveUniform");

// GL_INVALID_OPERATION is generated if count is greater than 1 and the indicated
// uniform variable is not an array variable.

// GL_INVALID_OPERATION is generated if a sampler is loaded using a command other than
// glUniform1i and glUniform1iv.

// GL_INVALID_OPERATION is generated if glUniform is executed between the execution
// of glBegin and the corresponding execution of glEnd.

// None of the above are true, and yet the following dies with GL_INVALID_OPERATION?
glUniformMatrix4fv(location, 1, false, identity_matrix);
die_on_gl_error("UniformMatrix4f");
}

После всего этоговот что получится:

There are 1 uniform(s) active in program 3.
Uniform mvMatrix:   Type:8b5c   Size:1
GL Error 502 encountered in UniformMatrix4f.

Тип 8b5c - это, конечно, GL_FLOAT_MAT4, а размер - 1, поэтому я не вижу, какое из недопустимых условий работы меня кусает!

Редактировать:

Вот основной цикл, где вызываются UseProgram и эта функция:

    while (wm->update()) {
        wm->poll_input();
        handle_input(viewingmatrix);
        if (!gl->use_program(program))
            exit(-1);
        gl->load_identity_matrix();
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glDrawArrays(GL_TRIANGLES, 0, bananaNumVerts);
        glFlush();
        usleep(16667);
    }

gl->use_program(program) это простообертка, которая проверяет правильность переданного int и обновляет параметр active_program объекта.

Edit 2: Благодарю luke за указаниея в gDEBugger, который также обнаружил ошибку GL.В информации о вызовах в gDEBugger я отметил, что были перечислены только три аргумента.Хотя я предполагаю, что это может быть из-за того, что четвертый был указателем на массив (находится ли он на стороне клиента или передается на сервер каждый раз, когда вызывается glUniform?), Это заставило меня задуматься о том, что еще может бытьпричина.

В случае, если это доказательно, glUniformMatrix4fv, конечно, фактически является указателем функции, который получает свой адрес следующим образом:

Объявление:

PFNGLUNIFORMMATRIX4FV glUniformMatrix4fv;

Назначение:

glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC)glXGetProcAddress((const GLubyte*)"glUniform4fv");

Я избегаю GLEW по академическим причинам.Однако, когда я просматривал glext.h, я заметил, что также также представляет собой PFNGLUNIFORMMATRIX4FVARBPROC, который, как я предполагаю, существует только для кодовых баз, написанных до того, как эта функция была принята в ядро.Если это не так, пожалуйста, дайте мне знать.

1 Ответ

9 голосов
/ 13 марта 2012

Посмотрите на ваш glXGetProcAddress звонок:

glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC)glXGetProcAddress((const GLubyte*)"glUniform4fv");

Вы запрашиваете glUniform4fv вместо glUniformMatrix4fv!

Я знаю, вы сказали, что не используетебиблиотеки расширений для академических целей, но я все равно настоятельно их рекомендую.

...