1
votes

I can set my fragment shader to showing colors of the object or the texture color of the object. My question is, how can I combine those two so that I can have a transparrent picture with lines for bricks, and then show the different colors underneath, so that by changing the color of the object, you change the color of the bricks.

I tried using mix() for that in the fragment shader, but it only shows me the glClearColor where it is transparent insteath of the red color I have assigned it!

My fragment shader:

#version 120

uniform sampler2D diffuse;

varying vec3 shared_colors;
varying vec2 shared_texCoords;

void main() {
    vec4 color = vec4(shared_colors, 1);
    vec4 texture = texture2D(diffuse, shared_texCoords);
    vec4 finalColor = vec4(mix(color.rgb, texture.rgb, 1), 1);

    gl_FragColor = finalColor;
}

EDIT: Added texture loader func:

void Texture::createTexture(SDL_Surface *rawImage, GLenum format) {
    //Convert to a texture of pure color pixels for OpenGL
    SDL_Surface *image = SDL_CreateRGBSurface(NULL, rawImage->w, rawImage->h, 32, 0, 0, 0, 0);
    SDL_BlitSurface(rawImage, NULL, image, NULL);

    //Generate texture
    glGenTextures(1, &m_texture);

    //Tell OpenGL to use this texture
    glBindTexture(GL_TEXTURE_2D, m_texture);

    //Set texture parameters
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    //Generate texture from image
    glTexImage2D(GL_TEXTURE_2D, 0, 4, image->w, image->h, 0, format, GL_UNSIGNED_BYTE, image->pixels);

    m_dimension = new PixelSize(image->w, image->h);

    //Free loaded images
    SDL_FreeSurface(rawImage);
    SDL_FreeSurface(image);
}
1
You should not use 4 for the internal format. In older versions of OpenGL this was allowed (and it meant to pick any format with 4 components), but the proper thing to use is really GL_RGBA or better yet, GL_RGBA8. Your shader is GLSL 1.20, so your implementation may not support GL_RGBA8 but it will definitely understand GL_RGBA.Andon M. Coleman
I'll try that and see if that helps =)Aleksander Fimreite
Well, it didn't change my situation. They both ran perfectly, but nothing different happened.Aleksander Fimreite
I didn't think it would change anything to be honest. But the spec. does not allow using the number of components anymore, so at least your code is more portable now :P I believe the masks you are passing to SDL_CreateRGBSurface (...) are to blame for your constant alpha value. On a little-endian machine (e.g. x86), I think you need an alpha mask (last parameter) of 0xff000000. For all other color channels, you can use a mask of 0, but alpha needs an explicit mask.Andon M. Coleman
I managed to find the problem! I did actually need the masks for the RGB components. I used 0x00ff0000, 0x0000ff00, 0x000000ffAleksander Fimreite

1 Answers

2
votes

You should take a closer look at mix (...) to understand why using 1 for a effectively does nothing meaningful (it returns y).

Let us start by considering the usual alpha blending function: GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA.

This means to take the alpha channel of the source and multiply it by the source color (fragment color) and add that to the inverse of the alpha channel multiplied by the destination color (framebuffer).

  AlphaBlend = SrcRGBA * SrcA + DstRGBA * (1.0 - SrcA)

Now, if you look at the implementation of mix (...) it should look quite familiar:

  x * (1.0 - a) + y * a

Clearly, this is order dependent for any value of a != 0.5 (1.0 - 0.5 = 0.5) and more importantly in this case it completely throws out one of your colors if you use a value of 1.0 for a (as this multiplies x by 0.0).