GLSL color with texture ontop - colors

Is it possible to get GLSL to produce this:
This is 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, texture.a), 1);
vec4 fCol = color * texture;
gl_FragColor = fCol;
}
My results are:
finalColor = red color, no texture
fCol = no color (black), red texture
I want to set the color of the object and have that show through wherever the alpha of the texture is less than 1...

Apparently, my texture was not loaded correctly after all, as it gave me a constant alpha value of 0, so when I tried to call the Mix() in the GLSL it ended up canceling it completly out.
I loaded the texture like this:
SDL_CreateRGBSurface(NULL, rawImage->w, rawImage->h, 32, 0, 0, 0, 0);
It was solved by setting it to this, so it actually conciders the alpha channel correctly:
SDL_CreateRGBSurface(NULL, rawImage->w, rawImage->h, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
Also after that I found out my texture was loaded with reversed rgb channels (meaning it used bgr), so I also changed that when merging the texture in the shader.
From:
vec4 finalColor = vec4(mix(color.rgb, texture.rgb, texture.a), 1);
To:
vec4 finalColor = vec4(mix(color.rgb, texture.bgr, texture.a), 1);

Related

How to make elevated parts of a steep plane seem darker than the lower surface?

I made a plane in THREEjs using Mesh, PlaneGeometry and ShaderMaterial. It's a very simple/basic form.
I applied a simple phormula to make the plain more steep. Now I'm trying to make the lower surface darker than the higher surface. Here is what I tried.
Vertex shader:
varying vec3 test;
void main(void) {
float amp = 2.5;
float z = amp * sin(position.x*0.2) * cos(position.y*0.5); //this makes the surface steeper
test = vec3(1, 1, -z); //this goes to fragment shader
//test = vec3(698.0, 400.0, -z); I have tried this. first coordenates here are to normalize the vector
gl_Position = projectionMatrix * modelViewMatrix * vec4(position.x, position.y, z, 1.0);
}
Fragment shader:
precision mediump float;
varying vec3 test;
void main(void) {
vec3 st = gl_FragCoord.xyz/test;
gl_FragColor = vec4(st.xyz, 1.0);
}
Result:
This result is not desirable, since the contrast between top and down is too aggressive and I'd like the lower surface less white. What do I have to change to accomplish this?
If you want to create a brightness based on the height of the waves, then you'll need to only use the test.z value, since test.xy aren't really doing anything. The problem is that brightness needs a value between [0, 1] and due to the amplitude multiplication, you're getting a value between [-2.5, 2.5] range.
precision mediump float;
varying vec3 test;
void main(void) {
float amp = 2.5;
// Extract brightness from test.z
float brightness = test.z;
// Convert brightness from [-2.5, 2.5] to [0.0, 1.0] range
brightness = (brightness / amp) * 0.5 + 0.5;
vec3 yellow = vec3(1.0, 1.0, 0.0);
// Multiply final color by brigthness (0 brightness = black)
vec3 st = yellow * brightness;
gl_FragColor = vec4(st.xyz, 1.0);
}
That should give you a smoother transition from full yellow to black.
As an aside, to help me visualize the values I'm getting from GLSL functions, I like to use the Graphtoy tool. I recommend you give it a shot to help you write shaders!

pixi.js: how to draw outline of container while keeping its content transparent

I have a container with several graphics containing circles. I would like to only render this container's outline, without the graphics themselves.
I managed to draw the outlines using OutlineFilter, and I managed to make the container transparent using AlphaFilter, but not both at the same time, no matter in which order I added the filters.
That is technically not possible like you intend to do it. One shader (pixi.js filter) doesn't know about the previous shader, such as where the outline was painted or what is the original texture alpha.
Alternatively you can create a new filter with a new shader that achieves that effect. I'm basing this on the OutlineFilter:
varying vec2 vTextureCoord;
uniform sampler2D uSampler;
uniform vec2 thickness;
uniform vec4 outlineColor;
uniform vec4 filterClamp;
const float DOUBLE_PI = 3.14159265358979323846264 * 2.;
void main(void) {
vec4 ownColor = texture2D(uSampler, vTextureCoord);
vec4 curColor;
float maxAlpha = 0.;
vec2 displaced;
for (float angle = 0.; angle <= DOUBLE_PI; angle += 0.1) {
displaced.x = vTextureCoord.x + thickness.x * cos(angle);
displaced.y = vTextureCoord.y + thickness.y * sin(angle);
curColor = texture2D(uSampler, clamp(displaced, filterClamp.xy, filterClamp.zw));
maxAlpha = max(maxAlpha, curColor.a);
}
float resultAlpha = maxAlpha * step(ownColor.a, 0.0) > 0. ? 1. : 0.0;
gl_FragColor = vec4(outlineColor.rgb * resultAlpha, resultAlpha);
}
Example result as in the pixi-filters demos:

Using 2D metaballs to draw an outline with a constant thickness

I'm apply the concept of metaballs to a game I'm making in order to show that the player has selected a few ships, like so http://prntscr.com/klgktf
However, my goal is to keep a constant thickness of this outline, and that's not what I'm getting with the current code.
I'm using a GLSL shader to do this, and I pass to the fragmentation shader a uniform array of positions for the ships (u_metaballs).
Vertex shader:
#version 120
void main() {
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
Fragmentation shader:
#version 120
uniform vec2 u_metaballs[128];
void main() {
float intensity = 0;
for(int i = 0; i < 128 && u_metaballs[i].x != 0; i++){
float r = length(u_metaballs[i] - gl_FragCoord.xy);
intensity += 1 / r;
}
gl_FragColor = vec4(0, 0, 0, 0);
if(intensity > .2 && intensity < .21)
gl_FragColor = vec4(.5, 1, .7, .2);
}
I've tried playing around with the intensity ranges, and even changing 1 / r to 10000 / (r ^ 4) which (although it makes no sense) helps a bit, though it does not fix the problem.
Any help or suggestions would be greatly appreciated.
after some more taught it is doable even in single pass ... you just compute the distance to nearest metaball and if less or equal to the boundary thickness render fragment otherwise discard it ... Here example (assuming single quad <-1,+1> is rendered covering whole screen):
Vertex:
// Vertex
varying vec2 pos; // fragment position in world space
void main()
{
pos=gl_Vertex.xy;
gl_Position=ftransform();
}
Fragment:
// Fragment
#version 120
varying vec2 pos;
const float r=0.3; // metabal radius
const float w=0.02; // border line thickness
uniform vec2 u_metaballs[5]=
{
vec2(-0.25,-0.25),
vec2(+0.25,-0.25),
vec2( 0.00,+0.05),
vec2(+0.30,+0.35),
vec2(-1000.1,-1000.1), // end of metaballs
};
void main()
{
int i;
float d;
// d = min distance to any metaball
for (d=r+r+w+w,i=0;u_metaballs[i].x>-1000.0;i++)
d=min(d,length(pos-u_metaballs[i].xy));
// if outside range ignore fragment
if ((d<r)||(d>r+w)) discard;
// otherwise render it
gl_FragColor=vec4(1.0,1.0,1.0,1.0);
}
Preview:

Edge shader using GLSL-ES

I'm trying to do an edge shader but I have places where the edges are not shown at all. The behaviour is shown in the following image.
As you see the way I look at the model, doesn't show edges, but the other places are very sharp and looks good.
here is my attempt
uniform mat4 projection_matrix;
varying vec3 normFrag;
void main()
{
vec4 pos_transformed = modelViewProjectionMatrix * vertex;
vec3 normalizedNormal = normalize(normal);
vec3 norm = mat3(normalMatrix)* normalizedNormal ;
norm.y *=projection_matrix[2][3];
norm.x *= projection_matrix[3][2];
//norm *=-1.0;
norm = normalize(norm);
pos_transformed.xy -= pos_transformed.z*norm.xy*0.005;
gl_Position = vec4(pos_transformed);
}

Is there a faked antialiasing algorithm using the depth buffer?

Lately I implemented the FXAA algorithm into my OpenGL application. I haven't understand this algorithm completely by now but I know that it uses contrast data of the final image to selectively apply blurring. As a post processing effect that makes sense. B since I use deferred shading in my application I already have a depth texture of the scene. Using that it might be much easier and more precise to find edges for applying blur there.
So is there a known antialiasing algorithm using the depth texture instead of the final image to find the edges? By fakes I mean an antialiasing algorithm based on a pixel basis instead of a vertex basis.
After some research I found out that my idea is widely used already in deferred renderers. I decided to post this answer because I came up with my own implementation which I want to share with the community.
Based on the gradient changes of the depth and the angle changes of the normals, there is blurring applied to the pixel.
// GLSL fragment shader
#version 330
in vec2 coord;
out vec4 image;
uniform sampler2D image_tex;
uniform sampler2D position_tex;
uniform sampler2D normal_tex;
uniform vec2 frameBufSize;
void depth(out float value, in vec2 offset)
{
value = texture2D(position_tex, coord + offset / frameBufSize).z / 1000.0f;
}
void normal(out vec3 value, in vec2 offset)
{
value = texture2D(normal_tex, coord + offset / frameBufSize).xyz;
}
void main()
{
// depth
float dc, dn, ds, de, dw;
depth(dc, vec2( 0, 0));
depth(dn, vec2( 0, +1));
depth(ds, vec2( 0, -1));
depth(de, vec2(+1, 0));
depth(dw, vec2(-1, 0));
float dvertical = abs(dc - ((dn + ds) / 2));
float dhorizontal = abs(dc - ((de + dw) / 2));
float damount = 1000 * (dvertical + dhorizontal);
// normals
vec3 nc, nn, ns, ne, nw;
normal(nc, vec2( 0, 0));
normal(nn, vec2( 0, +1));
normal(ns, vec2( 0, -1));
normal(ne, vec2(+1, 0));
normal(nw, vec2(-1, 0));
float nvertical = dot(vec3(1), abs(nc - ((nn + ns) / 2.0)));
float nhorizontal = dot(vec3(1), abs(nc - ((ne + nw) / 2.0)));
float namount = 50 * (nvertical + nhorizontal);
// blur
const int radius = 1;
vec3 blur = vec3(0);
int n = 0;
for(float u = -radius; u <= +radius; ++u)
for(float v = -radius; v <= +radius; ++v)
{
blur += texture2D(image_tex, coord + vec2(u, v) / frameBufSize).rgb;
n++;
}
blur /= n;
// result
float amount = mix(damount, namount, 0.5);
vec3 color = texture2D(image_tex, coord).rgb;
image = vec4(mix(color, blur, min(amount, 0.75)), 1.0);
}
For comparison, this is the scene without any anti-aliasing.
This is the result with anti-aliasing applied.
You may need to view the images at their full resolution to judge the effect. In my view the result is adequate for the simple implementation. The best thing is that there are nearly no jagged artifacts when the camera moves.

Resources