изменить float в вершинном шейдере (GLSL)

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

//i bind my shader
shader.bind();

// Then trying to set the value in my vertex shader like so:
GLuint test = glGetUniformLocation(shader.id(), "Test");
glUniform1f(test, 6.0f);

// Do some other stuff like rendering an object
// ...

// then unbind shader
shader.unbind();

Это значение, которое я хочу изменить в моем вершинном шейдере:

uniform float Test = 0.66; // Doesn't work
//const float Test = 0.66; // Works

Но мой шейдер не работает, когда я пытаюсь это сделать, он делает мой объект черным.

Если я закомментирую часть glGetUniform (Location) и использую float как const вместо < strong> uniform, тогда мой шейдер работает нормально. Но я хочу иметь возможность изменять значение в моем шейдере при каждом рендеринге. Я думал, мне нужно было использовать для этого форму ...?

Я что-то упускаю .. ??


РЕДАКТИРОВАТЬ:

По-видимому, я получаю следующую ошибку GLSL:

неконстантное выражение при инициализации

Так что, чтобы оно работало, оно должно быть постоянным ... Означает ли это, что нет возможности использовать это как динамическое значение ...?

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

const float FresnelPower = 1.0;
uniform float Eta;         // <---- MUST BE CONSTANT...

const float F  = ((1.0-Eta) * (1.0-Eta)) / ((1.0+Eta) * (1.0+Eta));

varying vec3  Reflect;
varying vec3  Refract;
varying float Ratio;

void main()
{
    vec4 ecPosition  = gl_ModelViewMatrix * gl_Vertex;
    vec3 ecPosition3 = ecPosition.xyz / ecPosition.w;

    vec3 i = normalize(ecPosition3);
    vec3 n = normalize(gl_NormalMatrix * gl_Normal);

    Ratio   = F + (1.0 - F) * pow((1.0 - dot(-i, n)), FresnelPower);

    Refract = refract(i, n, Eta);
    Refract = vec3(gl_TextureMatrix[0] * vec4(Refract, 1.0));

    Reflect = reflect(i, n);
    Reflect = vec3(gl_TextureMatrix[0] * vec4(Reflect, 1.0));

    gl_Position = ftransform();
}

person w00    schedule 28.01.2012    source источник


Ответы (2)


Вы должны объявить свою униформу в вершинном шейдере следующим образом:

uniform float Test;

Кроме того, вы должны вызвать glUseProgram() с помощью дескриптора вашего программного объекта перед вызовом glUniform1f(), поэтому убедитесь, что это то, что делает ваш shader.bind(). Достаточно один раз вызвать glGetUniformLocation() и кешировать результат. Также проверьте ошибки ваших вызовов OpenGL с помощью glGetError(), чтобы убедиться, что все остальное работает правильно.

Отвечая на ваше редактирование, я думаю, что эта строка - ваша проблема:

const float F  = ((1.0-Eta) * (1.0-Eta)) / ((1.0+Eta) * (1.0+Eta));

const означает постоянную времени компиляции, например, значение не может быть изменено униформой. F не может быть константой, потому что универсальная переменная не является константой (времени компиляции). Переместите строку, объявляющую F, в тело main и удалите квалификатор const. Тогда ваш шейдер должен работать.

person Antti    schedule 28.01.2012
comment
Я попробовал то, что вы сказали, я проверил с помощью glGetError (), и он дал мне ошибку, когда я попытался привязать шейдер (glUserProgram). Я немного отладил и заметил, что у меня ошибка компиляции glsl. Я отредактировал свой первый пост с более подробной информацией. Может ты знаешь ответ на это? - person w00; 28.01.2012

uniform float Eta;         // <---- MUST BE CONSTANT...

Когда GLSL говорит «константа», это означает константу времени компиляции. Значение Eta определенно одинаково в пределах конкретного вызова отрисовки. Но он не постоянный, потому что он может меняться между вызовами отрисовки. Компилятор не знает, каким будет это значение во время компиляции.

const переменная - это константа времени компиляции. Поэтому он должен быть инициализирован выражением, состоящим только из констант времени компиляции. uniform не являются константами времени компиляции, поэтому вы не можете инициализировать const переменную с их помощью.

person Nicol Bolas    schedule 28.01.2012