2015-11-15 4 views
1

Я пытаюсь сделать glsl-шейдер, который может отключить текстурирование и/или раскраску (я хочу, чтобы можно было оттенять текстуру). Я могу отключить атрибут, выполнив glDisableVertexAttribArray(x), но мне интересно, как будут выглядеть значения в шейдере. будут ли они 0?Значение для отключенных атрибутов в glsl-шейдере

Кроме того, есть ли способ проверить, включен ли атрибут внутри шейдерного кода? Я думал о форме (возможно, int) для хранения флагов и проверки их в шейдере, но для этого потребовались бы if заявлениях, и я думаю, что слышал, что это не рекомендуется.

Вот мои шейдеры, если вы хотите сослаться на них, я сейчас работаю над флагом int, о котором я говорил.

Vertex шейдеров:

#version 450 

layout(location=0) uniform mat4 projection_matrix; 
layout(location=1) uniform mat4 view_matrix; 
layout(location=2) uniform mat4 model_matrix; 

// 0b0000 0000 0000 0  unused 
//     0  textures 
//     0  colors 
//      0 2d/3d 
layout(location=3) uniform uint mode; 

layout(location=0) in vec4 vert_tex_coord; 
layout(location=1) in vec4 vert_color; 
layout(location=2) in vec3 vert_2_position; 
layout(location=3) in vec3 vert_3_position; 

out vec4 vert_frag_color; 
out vec2 vert_frag_tex_coord; 

vec4 transform(vec4 v) 
{ 
    return projection_matrix * view_matrix * model_matrix * v; 
} 

void main() 
{ 
    if ((mode & 1) > 0) 
    { 
     gl_Position = transform(vec4(vert_3_position, 1.0)); 
    } 
    else 
    { 
     gl_Position = transform(vec4(vert_2_position, 0.0, 1.0)); 
    } 

    if ((mode & 2) > 0) 
    { 
     vert_frag_color = vert_color; 
    } 

    if ((mode) & 4) > 0) 
    { 
     vert_frag_tex_coord = vert_tex_coord; 
    } 
} 

Фрагмент шейдеры:

#version 450 

layout(location=3) uniform uint mode; 

uniform sampler2D texture_0; 

in vec4 vert_frag_color; 
out vec2 vert_frag_tex_coord; 

out vec4 frag_color; 

void main() 
{ 
    if ((mode & 2) > 1) 
    { 
     frag_color = vert_frag_color; 
    } 

    if ((mode) & 4) > 1) 
    { 
     frag_color = texture(texture_0, vert_frag_tex_coord); 
    } 
} 

ответ

2

можно отключить атрибут, выполнив glDisableVertexAttribArray(x), но мне интересно, что значения будут выглядеть в шейдере , будут ли они be 0?

Нет, фактически, «текущее» значение каждого атрибута является частью глобального состояния GL. Вы можете установить значение для каждого атрибута, где массив отключен через семейство функций glVertexAttrib*(). Существует лишь незначительное завихрение: всякий раз, когда вы рисуете что-то с включенным массивом атрибутов и позже отключите массив атрибутов, текущее значение этого атрибута будет undefined, поэтому вам нужно снова указать его через glVertexAttrib*().

Следующая построить в своем коде не имеет смысла:

if ((mode & 1) > 1) 
{ 
    gl_Position = transform(vec4(vert_3_position, 1.0)); 
} 
else 
{ 
    gl_Position = transform(vec4(vert_2_position, 0.0, 1.0)); 
} 

mode & 1 будет либо 1 или 0, поэтому Comparision> 1 всегда будет ложным. Однако этот режим вообще не нужен. GL автоматически расширяет векторы входных атрибутов до формы (0, 0, 0, 1), если не указаны все элементы. Так что это будет достаточно, чтобы использовать

in vec4 vert_position; 
// ... 
gl_Position = transform (vert_position); 

и вы можете просто указать 1, 2, 3 или 4 компонента в glVertexAttribPointer() вызова, и он будет работать, как ожидалось. Идиома in vec3 position; /* ... */ matrix * vec4(position, 1.0); обычно используется в учебниках, но не нужна вообще. Можно утверждать, что он делает более ясным то, что происходит на самом деле.

Кроме того, есть ли способ проверить, включен ли атрибут внутри кода шейдера ?

Нет, не существует. Для каждого атрибута всегда есть текущее значение. Если это произошло из массива или нет, это совершенно не важно для шейдера.

Я подумал о форме (возможно int) для хранения флагов и протестировать их в затенении, но это потребует if заявления, и я думаю, что я слышал, это не рекомендуется.

Ну, ветка, основанная на равномерном значении, все равно приведет к равномерному потоку управления, так что это не худшая вещь, которая может произойти. Но он не будет свободен от накладных расходов. Если это стоит того, что зависит от реальных требований на вашей сцене. Возможно, лучше использовать разные шейдеры и переключиться между ними. Но все зависит от того, сколько таких переключателей состояния произойдет, и сколько будет работать каждый шейдер между коммутаторами, а также, сколько комбинаций шейдеров вам понадобится. Это то, что вам нужно проверить/профиль, предпочтительнее в разных реализациях GL.

+0

Итак, если я правильно понимаю, я могу установить значение по умолчанию для моих атрибутов, когда они отключены с помощью 'glVertexAttrib2 (,,)' (для vec2) и использовать это в моем шейдере? Это немного упростит мои шейдеры. Что бы сказать, если бы у меня были 'vec2 pos2' и' vec3 pos3', добавьте их вместе, чтобы получить окончательную выемку вершин? Я бы установил тот, который не используется для '0', и это не повлияет на другое. –

+0

Я не понимаю, почему вам нужно 'pos2' и' pos3' вообще. В вашем шейдере вы никогда не нуждаетесь в них одновременно, поэтому нет необходимости когда-либо иметь два атрибута позиции. – derhass

+0

Я хочу сделать шейдер, который может обрабатывать 2d и 3d модели! Смогу ли я использовать атрибут vec3 для моей модели vec2? –

 Смежные вопросы

  • Нет связанных вопросов^_^