I'm loading raw texture (with alpha channel) and displaying it in openGL everything is fine and texture displayed, but color is little bit darker than original. I already tried to turn of lighting, blending and dithering, but this doesn't helps.
I'm using mac osx.
Sample image
http://postimage.org/image/2wi1x5jic/
Here's openGL texture loading source code:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA , width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &bytes[0]);
EDIT:
Thats very weird, I used example from http://forums.tigsource.com/index.php?topic=9560.0
and received same glitch ... So the problem not im my code, maybe driver options? Hm ...
SOLUTION:
Thanks #datenwolf, images were saved with sRrgb color profile. Problem is solved once I removed it and converted to RGB.
Maybe you have GL_MODULATE set as texturing environment and the vertex colours are not white. Try setting the texture environment to GL_REPLACE.
glBindTexture(GL_TEXTURE_2D, your_texture);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
EDIT
Another problem may be a color profile embedded into the image. A image viewer may use this colour profile to implement color management, adjusting the colours for your monitor's colour profile. OpenGL as-it-is doesn't do color management; there is a extension, that framebuffers and textures are sRGB, this is kind of the smallest common denominator of colour management. But then you'd still have to transfer your input images to sRGB colour space.
I've a lengthy article in preparation the explains in depth how to do colour management with OpenGL. But it's far from complete.
Related
I'm trying to blend two partially overlapping textures in GLSL and am wondering if I'm misunderstanding the concept of multi-texturing. Is it required that the textures fully overlap or can you have two offset textures that blend only where they overlap?
I have two images similar to the following (minus grid lines and text):
Example image
Ideally, the overlapping sections of the image would blend together nicely so that the final result would look like one smooth image that combines the two together. Overlapping orange pixels, for example, would blend together or take the higher intensity.
I'm new to GLSL and have been using this article GLSL Shader Article which uses a fragment shader to blend the textures (fairly standard).
Following the article, I#m setting up each texture like so:
glUseProgramObjectARB( m_hProgramObject );
GLint nParamObj = glGetUniformLocationARB( m_hProgramObject, pParamName_i );
...
glActiveTexture(GL_TEXTURE0 + nTextureID_i );
glBindTexture(GL_TEXTURE_2D, nTextureID_i);
glUniform1iARB( nParamObj, nTextureID_i );
I then bind each texture and draw triangle strips. My textures are created as:
glBindTexture( GL_TEXTURE_2D, m_nTextureID );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
glTexImage2D(GL_TEXTURE_2D, 0, 4, nWidth, nHeight, 0, GL_RGBA,
GL_UNSIGNED_BYTE, pbyData);
Does that process seem reasonable or am I misunderstanding the concept? Any tips or advice on how to achieve this?
That process certainly seems adequate. The advantage of using a fragment shader is you get complete control over how the textures are combined. For the offset, you may want two sets of texture coordinates - one for each image - or you could generate them implicitly. Figuring out what you want and writing the fragment shader will probably be the difficult bit. Unfortunately if you want to blend many different textures, the fragment shader used in this way can get quite expensive or just wont work with too many textures bound.
Your example image doesn't look like any blending has occurred at all - the images are just positioned over each other. In this case, it's easier just to draw separate bits of geometry with mapped textures.
Blending is typically done by the fixed pipeline blending stage. For example using the following calls...
glEnable(GL_BLEND)
glBlendFunc(src_scale, dest_scale)
One of the most common configuration is alpha blending with the over operator: glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) in which the amount blended is given by the alpha value of the colour your drawing - possibly influenced by the A component in your GL_RGBA texture. You can further manipulate the blend equations if needed. See Blending.
I want the alpha value to be read for each pixel from the texture, so that some pixels completely disappear. The texture file(targa format) does contain the proper alpha channel.
Screenshot: http://i43.tinypic.com/2i79s1x.png
Here are the options I am using:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_BGR, //changing GL_BGR to anything else doesn't do a thing :? also tried GL_BGRA.
GL_UNSIGNED_BYTE, targaImage);
I have also tried most of the combinations of parameters for the glBlendFunc but none achieves the effect, alhtough I might have skipped it. This is the one that gets the regular blending done right(based on the alpha from glColor):
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Rectangle drawing:
glColor4f(1,1,1,0.5);
mRect->Render();
If I set alpha to 1 it is fully opaque, but there is still white in the bottom right, meaning that the alpha is read from the texture but the white polygon beneath it is visible. So I need to make the polygon disappear somehow, but the texture to remain visible.
So that's how I achieve this in the picture. I have also experimented with this:
glAlphaFunc(GL_GREATER, 0.49);
glEnable(GL_ALPHA_TEST);
It only proves that the alpha of each ,,fragment'' of my rectangle is 0.5.
This texture file has a gradient that has full red around the blue circle in the middle, but the alpha goess from 0 in the top-left to full in the bottom-right(it's not the red color fading to white).
I would supply the whole code but it has more than 2k lines and I have split everything into classes, so I am just pulling out the parts I think are important.
Do I need my own shader to do this? I have only made my first contact with OpenGL and C++ a couple of weeks ago and I'm not into them yet, so if that's the solution I would appreciate a link to a tutorial that deals with alpha and GLSL.
Thank you :)
It looks like you're using the old, fixed function pipeline. With that you must properly configure the texture environment. Specifically you want the texture to modulate or replace the base color. Either is fine, but I presume replace mode is better suited for you.
After binding the texture set the mode using glTexEnvi, in your case specifically
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
Also I want to remind you, that you actually must enable blending (glEnable(GL_BLEND);)
If you look at the reference page for glTexEnv I think you easily grasp how ridiculously complex the state space for the fixed function texture environment pipeline became. I strongly suggest you don't bother with it and go directly for using the programmable pipeline, i.e. fragment shaders. Yes, their learning curve is significantly steeper, but with shaders you can actually write something legible like
#version 330
uniform sampler3D sampler_albedo;
uniform sampler2D sampler_diffuse;
out vec4 outcolor;
main()
{
float albedo = texture(sampler_albedo, texcood);
vec4 diffuse = texture(sampler_diffuse, texcoord);
outcolor = mix(basecolor, diffuse.rgb, diffuse.a) * albedo;
}
instead of spending over 15 lines setting up the texture environment and register combiners.
I have recently implemented Awesomium into a OpenGL application.
When I load Awesomium in to a texture OpenGL includes it in its shading process regardless of whether I draw the texture onto a surface or not.
I am trying to trace down the line of code that is processing the texture into the shaders, is there a specific function OpenGL uses to access all textures or a way to tell OpenGL to ignore the texture?
Update texture block
glBindTexture(GL_TEXTURE_2D, SkypeHUD);
glTexImage2D(GL_TEXTURE_2D, 0, 4, AwesomiumW, AwesomiumH, 0, GL_BGRA, GL_UNSIGNED_BYTE, surface->buffer());
Create texture block
glBindTexture(GL_TEXTURE_2D, SkypeHUD);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
glBindTexture(GL_TEXTURE_2D, 0);
Drawing the scene without the texture being loaded: http://puu.sh/2bVTV
Drawing the scene after I have loaded the texture: http://puu.sh/2bVUb
You can see it blending the google texture in over the others.
Texture enable/disable should be controlled by the shader code, not some client binding state. Anyway, you most likely use several texture units (glActiveTexture); the texture binding is individual to each unit, so you'll have to do some leg work and unbind textures from each unit if you want to go this route.
I'm having a problem with loading a tga from a PVR.
I believe the PVR is loading correctly, but when I try and load the texture into OpenGL I'm getting issues.
I'm getting odd, incoherant drawings. I'll passing the entire texture file I'm making over to my graphics window class and then asking it to get the id which is an unsigned int and then create the texture.
This is my load texture class.
glGenTextures(animalTexture->getID(), &texture[0]);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexImage2D(GL_TEXTURE_2D, 0, 3, animalTexture->getWidth(),animalTexture->getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, animalTexture->getImageData());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
I'm wondering what the cause could be. This method does get called more than once so I'm wondering if you can overwrite a previously generated texture without any issues? Do you have to have a gluint to use to generate a texture? I'm trying to load a tga.
I know this draws successfully with a normal saved image.
Any ideas or help would be mucn appreciated.
p.s Ignore the black spot that was me.
Have a look at this post. Essentially, as PVR is compressed, you can't send the texture using glTexImage2D which assumes uncompressed texels (each texel being 4 unsigned bytes in the code you posted). You must use glCompressedTexImage2D instead which handles compressed formats. Have a look at this OpenGL es extension to know which internal format to use. If you're not too sure which one to choose or just want to view your compressed textures, PVRTexTool looks like a nice tool.
I noticed that when I'm loading a texture, it might change the current drawing color, depending on the texture's color. For example after executing
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, info.biWidth,
info.biHeight, 0, GL_RGB, GL_UNSIGNED_BYTE,bitmap);
glTexParameterf(GL_TEXTURE_2D,
GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D,
GL_TEXTURE_MAG_FILTER, GL_LINEAR);
all consecutive polygons drawn to the screen will have a color depending on the texture image loaded.
Is that standard? I didn't find this behavior documented.
Yes, it's how it works, remember that GL is a state machine, so you left the texture bound (and probably enabled), so when drawing it used the first pixel (assuming you didn't provide any texture coordinates) to color the primitive.
To solve it, disable texturing when you don't want texturing, you can do it with:
glDisable(GL_TEXTURE_2D);