Alpha blending with OpenGL ES 2.0? - iphone

What's the best way?
I tried to do this naïvely with a fragment shader that looks like this:
varying lowp vec4 color;
void main()
{
lowp vec4 alpha = colorVarying.wwww;
const lowp vec4 one = vec4(1.0, 1.0, 1.0, 1.0);
lowp vec4 oneMinusAlpha = one-alpha;
gl_FragColor = gl_FragColor*oneMinusAlpha + colorVarying*alpha;
gl_FragColor.w = 1.0;
}
But this doesn't work, because it seems gl_FragColor does not contain anything meaningful before the shader runs.
What's the correct approach?

Alpha blending is done for you. On shader exit, gl_FragColor should hold the alpha value in w component and you have to set the blending mode with the normal API just like there is no shader at all. For example gl_FragColor = vec4(0,1,0,0.5) will result in a green, 50% transparent fragment.

Related

How to flex a 3D texture with OpenGL ES?

I have tried to draw some 3D squares (with OpenGL on iPhone) and make them rotate around, now they look like a sphere.
http://i618.photobucket.com/albums/tt265/LoyalMoral/Post/ScreenShot2013-05-15at23249PM.png
But the square is flat (the first one on image below), and I want to flex it:
http://i618.photobucket.com/albums/tt265/LoyalMoral/Post/Untitled-1.jpg
someone told me that I have to use glsl, but I don't know shading language.
this is my vertex and fragment (follow Ray Wenderlich's tutorial):
// Vertex.glsl
attribute vec4 Position;
attribute vec4 SourceColor;
varying vec4 DestinationColor;
uniform mat4 Projection;
uniform mat4 Modelview;
attribute vec2 TexCoordIn;
varying vec2 TexCoordOut;
void main(void) {
DestinationColor = SourceColor;
gl_Position = Projection * Modelview * Position;
TexCoordOut = TexCoordIn;
}
// Fragment.glsl
varying lowp vec4 DestinationColor;
varying lowp vec2 TexCoordOut;
uniform sampler2D Texture;
void main(void) {
gl_FragColor = DestinationColor * texture2D(Texture, TexCoordOut);
}
could somebody help me? :)
Instead of using a quad (pair of triangles) for a square use a grid for it. Thus you will be able to place vertices of the grid manually resulting in the shape you want.

Blur image with GPUImage framework [duplicate]

I am trying to learn Shaders to implement something in my iPhone app. So far I have understood easy examples like making a color image to gray scale, thresholding, etc. Most of the examples involve simple operations in where processing input image pixel I(x,y) results in a simple modification of the colors of the same pixel
But, how about Convolutions?. For example, the easiest example would the Gaussian filter,
in where output image pixel O(x,y) depends not only on I(x,y) but also on surrounding 8 pixels.
O(x,y) = (I(x,y)+ surrounding 8 pixels values)/9;
Normally, this cannot be done with one single image buffer or input pixels will change as the filter is performed. How can I do this with shaders? Also, should I handle the borders myself? or there is a built-it function or something that check invalid pixel access like I(-1,-1) ?
Thanks in advance
PS: I will be generous(read:give a lot of points) ;)
A highly optimized shader-based approach for performing a nine-hit Gaussian blur was presented by Daniel Rákos. His process uses the underlying interpolation provided by texture filtering in hardware to perform a nine-hit filter using only five texture reads per pass. This is also split into separate horizontal and vertical passes to further reduce the number of texture reads required.
I rolled an implementation of this, tuned for OpenGL ES and the iOS GPUs, into my image processing framework (under the GPUImageFastBlurFilter class). In my tests, it can perform a single blur pass of a 640x480 frame in 2.0 ms on an iPhone 4, which is pretty fast.
I used the following vertex shader:
attribute vec4 position;
attribute vec2 inputTextureCoordinate;
uniform mediump float texelWidthOffset;
uniform mediump float texelHeightOffset;
varying mediump vec2 centerTextureCoordinate;
varying mediump vec2 oneStepLeftTextureCoordinate;
varying mediump vec2 twoStepsLeftTextureCoordinate;
varying mediump vec2 oneStepRightTextureCoordinate;
varying mediump vec2 twoStepsRightTextureCoordinate;
void main()
{
gl_Position = position;
vec2 firstOffset = vec2(1.3846153846 * texelWidthOffset, 1.3846153846 * texelHeightOffset);
vec2 secondOffset = vec2(3.2307692308 * texelWidthOffset, 3.2307692308 * texelHeightOffset);
centerTextureCoordinate = inputTextureCoordinate;
oneStepLeftTextureCoordinate = inputTextureCoordinate - firstOffset;
twoStepsLeftTextureCoordinate = inputTextureCoordinate - secondOffset;
oneStepRightTextureCoordinate = inputTextureCoordinate + firstOffset;
twoStepsRightTextureCoordinate = inputTextureCoordinate + secondOffset;
}
and the following fragment shader:
precision highp float;
uniform sampler2D inputImageTexture;
varying mediump vec2 centerTextureCoordinate;
varying mediump vec2 oneStepLeftTextureCoordinate;
varying mediump vec2 twoStepsLeftTextureCoordinate;
varying mediump vec2 oneStepRightTextureCoordinate;
varying mediump vec2 twoStepsRightTextureCoordinate;
// const float weight[3] = float[]( 0.2270270270, 0.3162162162, 0.0702702703 );
void main()
{
lowp vec3 fragmentColor = texture2D(inputImageTexture, centerTextureCoordinate).rgb * 0.2270270270;
fragmentColor += texture2D(inputImageTexture, oneStepLeftTextureCoordinate).rgb * 0.3162162162;
fragmentColor += texture2D(inputImageTexture, oneStepRightTextureCoordinate).rgb * 0.3162162162;
fragmentColor += texture2D(inputImageTexture, twoStepsLeftTextureCoordinate).rgb * 0.0702702703;
fragmentColor += texture2D(inputImageTexture, twoStepsRightTextureCoordinate).rgb * 0.0702702703;
gl_FragColor = vec4(fragmentColor, 1.0);
}
to perform this. The two passes can be achieved by sending a 0 value for the texelWidthOffset (for the vertical pass), and then feeding that result into a run where you give a 0 value for the texelHeightOffset (for the horizontal pass).
I also have some more advanced examples of convolutions in the above-linked framework, including Sobel edge detection.
Horizontal Blur using advantage of bilinear interpolation. Vertical blur pass is analog. Unroll to optimise.
//5 offsets for 10 pixel sampling!
float[5] offset = [-4.0f, -2.0f, 0.0f, 2.0f, 4.0f];
//int[5] weight = [1, 4, 6, 4, 1]; //sum = 16
float[5] weightInverse = [0.0625f, 0.25f, 0.375, 0.25f, 0.0625f];
vec4 finalColor = vec4(0.0f);
for(int i = 0; i < 5; i++)
finalColor += texture2D(inputImage, vec2(offset[i], 0.5f)) * weightInverse[i];

How do I modify a GPUImageGaussianSelectiveBlurFilter to operate over a rectangle instead of a circle?

I have used the GPUImage framework for a blur effect similar to that of the Instagram application, where I have made a view for getting a picture from the photo library and then I put an effect on it.
One of the effects is a selective blur effect in which only a small part of the image is clear the rest is blurred. The GPUImageGaussianSelectiveBlurFilter chooses the circular part of the image to not be blurred.
How can I alter this to make the sharp region be rectangular in shape instead?
Because Gill's answer isn't exactly correct, and since this seems to be getting asked over and over, I'll clarify my comment above.
The fragment shader for the selective blur by default has the following code:
varying highp vec2 textureCoordinate;
varying highp vec2 textureCoordinate2;
uniform sampler2D inputImageTexture;
uniform sampler2D inputImageTexture2;
uniform lowp float excludeCircleRadius;
uniform lowp vec2 excludeCirclePoint;
uniform lowp float excludeBlurSize;
uniform highp float aspectRatio;
void main()
{
lowp vec4 sharpImageColor = texture2D(inputImageTexture, textureCoordinate);
lowp vec4 blurredImageColor = texture2D(inputImageTexture2, textureCoordinate2);
highp vec2 textureCoordinateToUse = vec2(textureCoordinate2.x, (textureCoordinate2.y * aspectRatio + 0.5 - 0.5 * aspectRatio));
highp float distanceFromCenter = distance(excludeCirclePoint, textureCoordinateToUse);
gl_FragColor = mix(sharpImageColor, blurredImageColor, smoothstep(excludeCircleRadius - excludeBlurSize, excludeCircleRadius, distanceFromCenter));
}
This fragment shader takes in a pixel color value from both the original sharp image and a Gaussian blurred version of the image. It then blends between these based on the logic of the last three lines.
The first and second of these lines calculate the distance from the center coordinate that you specify ((0.5, 0.5) in normalized coordinates by default for the dead center of the image) to the current pixel's coordinate. The last line uses the smoothstep() GLSL function to smoothly interpolate between 0 and 1 when the distance from the center point travels between two thresholds, the inner clear circle, and the outer fully blurred circle. The mix() operator then takes the output from the smoothstep() and fades between the blurred and sharp color pixel colors to produce the appropriate output.
If you just want to modify this to produce a square shape instead of the circular one, you need to adjust the two center lines in the fragment shader to base the distance on linear X or Y coordinates, not a Pythagorean distance from the center point. To do this, change the shader to read:
varying highp vec2 textureCoordinate;
varying highp vec2 textureCoordinate2;
uniform sampler2D inputImageTexture;
uniform sampler2D inputImageTexture2;
uniform lowp float excludeCircleRadius;
uniform lowp vec2 excludeCirclePoint;
uniform lowp float excludeBlurSize;
uniform highp float aspectRatio;
void main()
{
lowp vec4 sharpImageColor = texture2D(inputImageTexture, textureCoordinate);
lowp vec4 blurredImageColor = texture2D(inputImageTexture2, textureCoordinate2);
highp vec2 textureCoordinateToUse = vec2(textureCoordinate2.x, (textureCoordinate2.y * aspectRatio + 0.5 - 0.5 * aspectRatio));
textureCoordinateToUse = abs(excludeCirclePoint - textureCoordinateToUse);
highp float distanceFromCenter = max(textureCoordinateToUse.x, textureCoordinateToUse.y);
gl_FragColor = mix(sharpImageColor, blurredImageColor, smoothstep(excludeCircleRadius - excludeBlurSize, excludeCircleRadius, distanceFromCenter));
}
The lines that Gill mentions are just input parameters for the filter, and don't control its circularity at all.
I leave modifying this further to produce a generic rectangular shape as an exercise for the reader, but this should provide a basis for how you could do this and a bit more explanation of what the lines in this shader do.
Did it ... the code for the rectangular effect is just in these 2 lines
blurFilter = [[GPUImageGaussianSelectiveBlurFilter alloc] init];
[(GPUImageGaussianSelectiveBlurFilter*)blurFilter setExcludeCircleRadius:80.0/320.0];
[(GPUImageGaussianSelectiveBlurFilter*)blurFilter setExcludeCirclePoint:CGPointMake(0.5f, 0.5f)];
// [(GPUImageGaussianSelectiveBlurFilter*)blurFilter setBlurSize:0.0f]; [(GPUImageGaussianSelectiveBlurFilter*)blurFilter setAspectRatio:0.0f];

change rgb values of a point in opengles

i want to make gray scale filter on runtime i succeed to make it by this code
NSString *const kGPUImageLuminanceFragmentShaderString = SHADER_STRING
(
precision highp float;
varying vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
const highp vec3 W = vec3(0.2125, 0.7154, 0.0721);
void main()
{
float luminance = dot(texture2D(inputImageTexture, textureCoordinate).rgb, W);
gl_FragColor = vec4(vec3(luminance), 1.0);
}
);
what i want now is to access the rgb values of each point and apply on it my algorithm then change the point rgb values based on my algorithm
my question in other word
i want to access the rgb values of a point and set the rgb values of the same point
vec3 pixel = texture2D(inputImageTexture, textureCoordinate).rgb;
float red = pixel.r;
float green = pixel.g;
float blue = pixel.b;
.
. manipulate the values as needed
.
gl_FragColor = vec4(red, green, blue, 1.0);
OR this to maintain the alpha of the original pixel:
vec4 pixel = texture2D(inputImageTexture, textureCoordinate).rgba;
.
.
.
gl_FragColor = vec4(red, green, blue, pixel.a);
If by point you mean pixel, then I think what you are looking for is a framebuffer object (FBO). It will allow you to render a scene to an image, which then you can feed back into a shader to do whatever you want to it, then you can render that as the final output.

Earth Day/Night side shaders in OpneGL ES 2.0

I have an iPhone application what models the Planet Earth! I would like to make it realistic: There is a sphere object, and a Nightside and Dayside texture and shader, but it doesn't work!
My Sphere object's draw method:
-(bool)execute:(GLuint)texture;
{
glBindTexture(GL_TEXTURE_2D, texture);
glBindVertexArrayOES(m_VertexArrayName);
glDrawArrays(GL_TRIANGLE_STRIP, 0, m_NumVertices);
glBindTexture(GL_TEXTURE_2D, 0);
return true;
}
My ViewController call method:
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m);
glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m);
glUseProgram(m_NightsideProgram);
[m_Sphere setBlendMode:0];
[m_Sphere execute:m_EarthNightTexture.name];
glUseProgram(m_DaysideProgram);
[m_Sphere setBlendMode:1];
[m_Sphere execute:m_EarthDayTexture.name];
glCullFace(GL_FRONT);
glEnable(GL_CULL_FACE);
glFrontFace(GL_CW);
}
Blendmodes:
0: glBlendFunc(GL_SRC_COLOR, GL_DST_COLOR);
1: glBlendFunc(GL_ONE, GL_CONSTANT_COLOR); //The constant is a mid blue, for make it lighter a bit
Nightside fragmentshader:
precision mediump float;
varying lowp vec4 colorVarying;
varying vec2 v_texCoord;
uniform sampler2D s_texture;
void main() {
vec4 newColor;
newColor=1.0-colorVarying;
gl_FragColor = texture2D(s_texture, v_texCoord)*newColor;
}
DaySide Fragmentshader:
precision mediump float;
varying lowp vec4 colorVarying;
varying lowp vec4 specularColorVarying;
varying vec2 v_texCoord;
uniform sampler2D s_texture;
void main() {
vec4 finalSpecular=vec4(0,0,0,1);
vec4 surfaceColor;
float halfBlue;
surfaceColor=texture2D(s_texture,v_texCoord);
halfBlue=0.5*surfaceColor[2];
if(halfBlue>1.0)
halfBlue=1.0;
if((surfaceColor[0]<halfBlue) && (surfaceColor[1]<halfBlue))
finalSpecular=specularColorVarying;
gl_FragColor = surfaceColor*colorVarying+colorVarying*finalSpecular;
}
If I use the only one of the shaders, it seens to be good, but it won't work together!
For a glUniform... call to take effect, there has to be a valid program bound/used, and even then it only changes the uniform value for that specific program's uniform (indentified by the uniform location). So you have to call your glUniform... functions for each program after the respective glUseProgram.
This is why it works with only one shader program, because you don't ever bind any other program. But it is still conceptually wrong, as in this case you are relying on a specific program being already bound, which is always a source for errors (like when adding a second program), as OpenGL is a state machine.
On the other hand a uniform variable keeps its value even when its corresponding program gets unbound (glUseProgram(0_or_any_other_program)).