GLSL препроцессор - PullRequest
       23

GLSL препроцессор

4 голосов
/ 10 октября 2011

Я пытаюсь выяснить, почему следующий код GLSL не работает:

#ifndef VertexPositionType
#define VertexPositionType vec3
#endif

in StandardVertexShaderInputs {
    VertexPositionType ds_VertexPosition;
};

vec4 ProjectVertexPosition(in vec4 v);

vec4 ProjectVertexPosition(in vec3 v);

void main() {
    gl_Position = ProjectVertexPosition(ds_VertexPosition);
}

Шейдер отказывается от компиляции.Состояние информационного журнала:

ошибка C1008: неопределенная переменная "ProjectVertexPosition"

Даже если она не предупреждает о препроцессоре, я получил символ препроцессора VertexPositionType не заменяется.Если я удалю определения препроцессора, все будет в порядке.

Теперь в спецификации говорится:

# define и # undef функциональностьопределены как стандартные для препроцессоров C ++ для определений макросов как с макропараметрами, так и без них.

Возможно, следующая строка не является допустимой строкой препроцессора?

#define VertexPositionType vec3

Ответы [ 3 ]

5 голосов
/ 12 октября 2011

Ваш шейдер нелегален.Компилятор NVIDIA, возможно, не выдает правильные ошибки, но ваш шейдер делает неправильные вещи (ну, кроме того факта, что вы не предоставили объявление #version. Я предполагал #version 330, но всегда хорошо быть явнымо версиях GLSL).

Я могу только предположить, что это вершинный шейдер, поскольку вы пишете в gl_Position.Блоки входного интерфейса недопустимы в вершинных шейдерах, также как блоки выходного интерфейса недопустимы в фрагментных шейдерах.Компилятор AMD довольно явно говорит об этом:

ERROR: 0:5: error(#328) interface block should not apply in 'Vertex Shader in'.
ERROR: 0:14: error(#143) Undeclared identifier ds_VertexPosition
ERROR: 0:14: error(#202) No matching overloaded function found ProjectVertexPosition
ERROR: 0:14: error(#160) Cannot convert from 'const float' to 'Position 4-component vector of float'
ERROR: error(#273) 4 compilation errors.  No code generated

Когда я удалил определение блока интерфейса, оставив его равным in VertexPositionType ds_VertexPosition;, он скомпилировался нормально.

Если я удалюс определениями препроцессора все в порядке.

Тогда поздравляю: вы обнаружили ошибку драйвера NVIDIA.Вы должны сообщить об этом им, потому что входные блоки интерфейса не разрешены в вершинных шейдерах.

1 голос
/ 11 октября 2011

Вы объявили перегруженную функцию ProjectVertexPosition, но никогда не определяли ее, поэтому при переходе по ссылке на вашу программу вы получите неопределенную ошибку. Для ошибки может иметь смысл сказать «неопределенная функция», а не «неопределенная переменная» (поскольку вы объявили ее как функцию.), Но я предполагаю, что компоновщик не хранит достаточно информации, чтобы узнать разницу между символ функции и символ переменной.

Эта ошибка, вероятно, происходит от вызова LinkProgram, а не от вызова CompileShader, и не имеет ничего общего с препроцессором или VertexPositionType

0 голосов
/ 22 февраля 2017

Ваша программа имеет две основные проблемы.#define не ваша проблема.Первая проблема заключается в том, что вы никогда не предоставляете реализацию функций vec4 ProjectVertexPosition(in vec# v).Вам необходимо предоставить объявление, например,

vec4 ProjectVertexPosition(in vec3 v) {
    return normalize(vec4(v, 1.0));
}

, а также для версии in vec4 v.Причина, по которой удаление define решает вашу проблему, заключается в том, что шейдер игнорирует входной блок, который с самого начала недопустим.В вершинном шейдере вы не можете использовать in блоков.Вместо этого используйте макеты и структуры или униформу и структуры.Для вершинных шейдеров вам нужно использовать только униформу или макеты, а не чистые in s.Если вы хотите использовать макеты, выполните следующие действия:

layout(location = 0) in VertexPositionType ds_VertexPosition;

Для стороны C / C ++ выполните следующие действия (где pointCount - это количество точек в вашей VAO, а points - это GLfloat *, содержащий точкипо порядку x1, y1, z1, x2, y2, z2, x3 ...:

GLfloat* points = (GLfloat*) malloc(pointCount * 3 * sizeof(GLfloat));
// Set your points however you want here

GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);

GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, 3 * pointCount * sizeof(GLfloat), points, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(0);
free(points);

// Now to draw (use whatever programId is returned when you link the program)
glUseProgram(programId);
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, pointCount);
glUseProgram(0);
...