Наложение прозрачного цвета на текстуру с помощью GLSL

У меня есть изображение, которое я загружаю с помощью библиотеки Slick, и изображение отлично отображается без активного шейдера. Когда я использую свой шейдер для наложения прозрачного цвета на изображение, все изображение заменяется прозрачным цветом.

без шейдера

С шейдером

Вершинный шейдер

varying vec4 vertColor;

void main(){
    vec4 posMat = gl_Vertex;
    gl_Position = gl_ModelViewProjectionMatrix * posMat;
    vertColor = vec4(0.5, 1.0, 1.0, 0.2);
}

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

varying vec4 vertColor;

void main(){
    gl_FragColor = vertColor;
}

Код рендеринга спрайтов

Color.white.bind();
GL11.glBindTexture(GL11.GL_TEXTURE, image.getTextureID());
GL11.glBegin(GL11.GL_QUADS);
GL11.glTexCoord2f(0, 0);
GL11.glVertex2f(this.x, this.y);
GL11.glTexCoord2f(1, 0);
GL11.glVertex2f(x + w, y);
GL11.glTexCoord2f(1, 1);
GL11.glVertex2f(x + w, y + h);
GL11.glTexCoord2f(0, 1);
GL11.glVertex2f(x, y + h);
GL11.glEnd();
GL11.glBindTexture(GL11.GL_TEXTURE, 0);

}

Инициализация OpenGL

GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GL11.glOrtho(0, Screen.getW(), Screen.getH(), 0, -1, 1);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glEnable(GL11.GL_TEXTURE_2D);
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);

person devCorner    schedule 16.06.2015    source источник


Ответы (1)


a) vertColor = vec4(0.5, 1.0, 1.0, 0.2); b) gl_FragColor = vertColor;

шейдер делает именно то, что вы от него просили — он устанавливает цвет всех фрагментов в этот цвет. Если вы хотите смешать цвета, вы должны добавить/умножить их в шейдере каким-то образом (например, иметь атрибут цвета и/или сэмплер текстуры, а затем, после экспорта атрибута из вершинного шейдера во фрагментный шейдер, использовать gl_FragColor = vertexColor * textureColor * blendColor; и т. д.).

также обратите внимание: вы смешиваете конвейер с фиксированной функцией с немедленным режимом (glBegin/glEnd) с шейдерами... это не очень хорошая идея. Кроме того, я не вижу, где установлена ​​ваша униформа; использование шейдеров без униформы == напрашивается на неприятности.

IMO, лучшим решением было бы либо использовать обычный OpenGL >= 3.1 с правильными, совместимыми шейдерами и т. д., либо использовать только конвейер с фиксированными функциями и не использовать шейдеры с устаревшим OpenGL.


Как загрузить текстуру с помощью GLSL: (см. https://www.opengl.org/sdk/docs/tutorials/ClockworkCoders/texturing.php для получения дополнительной информации, если это необходимо)

а) вы передаете данные на графический процессор, создавая текстуру и привязывая ее к текстурному блоку графического процессора, вызывая

int id = glGenTexture();
glBindTexture( GL_TEXTURE_2D, id );
glTexImage2D( ... );
// see https://www.opengl.org/sdk/docs/man/html/glTexImage2D.xhtml for details

(что, я полагаю, вы уже сделали, так как вы уже используете glBindTexture с параметром изображения)

б) вы предоставляете координаты UV-текстуры для вашей геометрии; вы уже делаете это, предоставляя glTexCoord2f, что, вероятно, позволит вам использовать устаревшие имена атрибутов, как в https://www.opengl.org/sdk/docs/tutorials/ClockworkCoders/attributes.php, но правильнее было бы передать его как часть упакованной структуры атрибутов,

c) вы используете связанную текстуру, сэмплируя текстуру в шейдере, например. (следует устаревший GLSL)

// vertex shader
varying vec2 vTexCoord;

void main() {
   vTexCoord = gl_MultiTexCoord0;
   gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}

// fragment shader
uniform sampler2D texture;
varying vec2 vTexCoord;

void main() {
   vec4 colorMultiplier = vec4(0.5, 1.0, 1.0, 0.2);
   gl_FragColor = texture2D(texture, vTexCoord) * colorMultiplier;
}

тем не менее, если вы собираетесь изменить его во время выполнения, лучше всего передать colorMultiplier как униформу.

person Community    schedule 16.06.2015
comment
@user3140916 user3140916 Я обновил ответ, чтобы включить это; см. последний раздел для кода шейдера. - person ; 16.06.2015