Is there something unusual about how the alpha component is handled in a pixel shader? I have a WPF application for which my artist is giving me grayscale images to use as backgrounds, and the application colorizes those images according to the current state. So I wrote a pixel shader (using the WPF Pixel Shader Effects Library infrastructure) to use as an effect on an Image element. The shader takes a color as a parameter, which it converts to HSL so it can manipulate brightness. Then for each grey pixel, it computes a color whose brightness is interpolated between the color parameter and white in proportion to the brightness of the source pixel.
float4 main(float2 uv : TEXCOORD) : COLOR
{
float4 src = tex2D(implicitInputSampler, uv);
// ...Do messy computation involving src brightness and color parameter...
float4 dst;
dst.r = ...
dst.g = ...
dst.b = ...
dst.a = src.a;
return dst;
}
This works just fine on the pixels where alpha = 1. But where alpha = 0, the resultant pixels come out white, rather than having the window's background show through. So I made a tiny change:
float4 main(float2 uv : TEXCOORD) : COLOR
{
float4 src = tex2D(implicitInputSampler, uv);
if (src.a == 0)
return src;
...
and now the transparent parts really are transparent. Why? Why didn't the dst.a = src.a statement in the first version accomplish that? Unfortunately, even this is only a partial fix, because it looks to me like the pixels with 0 < alpha < 1 are coming out white.
Does anyone know what I'm not understanding about alpha?
After some more web searching, I discovered the piece I was missing.
According to an article on MSDN: "WPF uses pre-multiplied alpha everywhere internally for a number of performance reasons, so that's also the way we interpret the color values in the custom pixel shader."
So the fix turns out to be to throw in a multiplication by alpha:
float4 main(float2 uv : TEXCOORD) : COLOR
{
...
dst.rgb *= src.a;
return dst;
}
And now my output looks as I expect it to.
0 < alpha < 1 are coming out white
What ranges are you expecting here?
All values are going to be in the range 0.0 and 1.0... pixel shaders do not work in discrete 256 colour ranges, they are floating point where 1.0 is the maximum intensity.
If your calculations end up setting r/g/b values to >1.0 you are going to get white...
http://www.facewound.com/tutorials/shader1/
Dude I am working on a XNA game, and I had to use a grayscale pixel shader and I got the same problem you are facing.
I donno if you are familiar with XNA environment or not, but I solved the problem by changing the SpriteBatch drawing SpriteBlendMode from SpriteBlendMode.None to SpriteBlendMode.AlphaBlend, I hope this can help you knowing the reason.
regards,
Related
I want to put my noise texture(like perlin noise or something else) on image texture,
when i add noise texture and image texture directly,it will make the src image texture light,
fragColor = vec4(image_texture+noise_texture,1.0);
when i use mix func, some arear will be darker,
fragColor = mix(image_texture,noise_texture,factor)
neither effect is good.
I've referred to a code that use the alpha channel for overlay directly,but it seems to change the background of the GLFW window directly to the image texture,because its shader doesn't use texture,just use alpha channel like this:
gl_FragColor = vec4(1.0, 1.0, 1.0, alpha);
which I don't know how to do too. So,is there any good way to mix noise and texture?
I would like to have a gradient which goes from black to transparent (not white). How can I achieve this?
From my attempt below I assume the gradient style color's alpha value is not considered:
gui_Footer.allStyles.apply {
backgroundType = Style.BACKGROUND_GRADIENT_LINEAR_VERTICAL
border = RoundRectBorder.create().topOnlyMode(true).cornerRadius(1f)
backgroundGradientEndColor = ColorUtil.BLACK
backgroundGradientStartColor = ColorUtil.argb(0, 255, 255, 255)
}
Gradients in Codename One ignore the alpha byte. While we could technically add support for alpha gradients it's not something that's planned at this time. You can probably generate such an image by manipulating the RGB data but it would be more efficient to just generate an RGB image of a gradient and draw it scaled.
Notice that this is generally the most efficient approach since the GPU works by drawing textures very efficiently. If an image is a power of 2 (e.g. 256x128 pixels) it can fit perfectly in a texture and it's drawn very fast. Much faster than our builtin gradients.
I want to detect an Eye, I have some code where I can detect blue color object, so if I made changes(how I can?) then it would be possible for me to detect an eye. As the below color has its own specific range value so, if I specify the eye color HSV value then can I detect EYE with this method.
In this below code I am going to detect BLUE Color Object, please tell me that where I do changes in my code so that I could get EYE using Open CV.
IplImage* GetThresholdedImage(IplImage* img)
{
// Convert the image into an HSV image
IplImage* imgHSV = cvCreateImage(cvGetSize(img), 8, 3);
cvCvtColor(img, imgHSV, CV_BGR2HSV);
IplImage* imgThreshed = cvCreateImage(cvGetSize(img), 8, 1);
//For detecting BLUE color i have this HSV value,
cvInRangeS(imgHSV, cvScalar(112, 100, 100), cvScalar(124, 255, 255), imgThreshed);//this will not recognize the yellow color
cvReleaseImage(&imgHSV);
return imgThreshed;
}
Eye detection is much easier with Haar classifier.
link here
Such a simple method may work at extracting a blue object using some thresholding but even if it could be adapted using a different colour black? blue? green? Everyone has different eye colours. I don't see a non hacky method working for you using blob extraction like this based on a HSV threshold value. This method works well on large blocks of the same colour, i.e. removing a blue background.
Look more at shape, everyone has different coloured eyes but the shape is circular/ellipse ish. There are varients of the Hough Transform for detecting circles.
...the Hough transform has been extended to identifying positions of
arbitrary shapes, most commonly circles or ellipses.
I have a sheet of black shapes surrounded by transparency. I have successfully loaded this texture with GLKit and I can draw the shapes using GLKBaseEffect into rectangles. Is there a way to change the color of the black (ie non-transparent) pixels, so I can draw yellow shapes or blue shapes etc? Or do I need a custom shader to do this?
It seems like you'll need a custom shader (which I highly recommend working with) as you need to check individual texel color values, but here are some suggestions to try first:
You can pass color as per-vertex data in a vertex attribute array pointing to GLKVertexAttribColor. This will allow you to individually set the color of each vertex (and ultimately, faces) but it will be difficult to see where they line up against your texture.
You can try enabling the following property on your effect:
effect.colorMaterialEnabled = YES;
But, for both cases, if your texels are completely black then I don't think any changes in color will show.
I think a custom shader is definitely the way to go, as you'll need to do something like this:
highp vec4 finalColor;
highp vec4 textureColor = texture2D(uTexture, vTexel);
highp vec4 surfaceColor = uColor;
// If texel is non-transparent (check alpha channel)
if(textureColor.a > 0.001)
finalColor = surfaceColor;
else
finalColor = vec4(0.0, 0.0, 0.0, 0.0);
gl_FragColor = finalColor;
Where anything prefixed with u is a uniform variable passed into the shader.
To get fully colorized textures, use:
self.effect.texture2d0.envMode = GLKTextureEnvModeModulate;
Which tells OpenGL to take whatever color is in your texture and multiply it by whatever color the underlying geometry is. You can then use vertex coloring to get neat fades and whatnot.
NOTE: You'll want to change your texture from black to white (1, 1, 1, 1), so multiplication works correctly.
NOTE: Here are some other settings that you should already have in place:
self.effect.texture2d0.enabled = GL_TRUE;
self.effect.texture2d0.target = GLKTextureTarget2D;
self.effect.texture2d0.name = self.texture.name;
self.effect.colorMaterialEnabled = GL_TRUE;
NOTE: You can experiment with GLKTextureEnvModeDecal, too, which blends your texture on top of colored geometry (as when applying a decal), so the transparent parts of the texture show the geometry underneath.
I need to write an application with Silverlight 4 and need to show images like wrapped on cylinder. I need some HLSL code, as I wont to do that with Effects of Silverlight.
I don't wont to do that with 3D libarries for silverlight. I only need HLSL code for changing pixels.
I need for my image to look like this
Thanks.
This seems to be the effect you want, you may wish to change the 0.2 value to increase or decrease the effect or make this adjustable in your shader but that's a simple change to do. I'd recommend Shazzam if your not using it for writing shaders for WPF or Silverlight.
sampler2D input : register(s0);
float4 main(float2 uv : TEXCOORD) : COLOR
{
float y = uv.y+(sin(uv.x*3.14) * lerp(-1,1,uv.y) * 0.2);
if(y < 0 || y > 1)
return float4(0,0,0,0);
else
return tex2D(input,float2(uv.x,y));
}
While you could do this with HLSL if you really wanted to, you'd normally do it by creating a mesh in the shape you want, then applying the picture to the mesh as a texture.