4

I'm trying to make a circular particle that looks like it's got a light shining on the top of it.

Here's what I'm trying to get it to look like:

particle 1

Here's what it currently looks like:

enter image description here

Since I'm using GL_POINTS, I get the gl_PointCoord variable which should make things easier, except I don't know how to use it properly, which led to this mess:

varying lowp vec4 DestinationColor;

void main(void) {
  lowp vec2 circCoord = 2.0 * gl_PointCoord - 1.0;
  if (dot(circCoord, circCoord) > 1.0) {
    discard;
  }
  gl_FragColor = mix(DestinationColor, vec4(1, 0.5, 0.2, 1), (1.0-gl_PointCoord.t)*(max(abs(gl_PointCoord.t-0.5),abs(gl_PointCoord.s-0.5)))); // the world's worst slowest math
}

I would highly appreciate any help, as I'm stuck thanks to my awful math skills.

MysteryPancake
  • 1,365
  • 1
  • 18
  • 47

1 Answers1

5

You can do a correct full lighting calculation. For example a lambertian diffuse would work like:

const vec3 lightDir = normalize(vec3(0, 1, -0.5));
const vec3 ambient = ...;
const vec3 lightDiffuse = ...;

vec3 normal = vec3(circCoord, sqrt(1 - dot(circCoord, circCoord)));
float c = max(dot(normal, lightDir), 0);
gl_FracColor = ambient + lightDiffuse*c;
Yakov Galka
  • 70,775
  • 16
  • 139
  • 220
  • Wow... exactly what I was after. One thing though, it's on the bottom rather than the top. I'll try changing the lightDir – MysteryPancake Dec 03 '16 at 11:43
  • Okay, changing the y to -1 worked exactly as I wanted! – MysteryPancake Dec 03 '16 at 11:45
  • Just one more question though - I don't particularly need a full lighting calculation for a simple 2D bevel. Is there a way to simplify this to what I need? All I want is a little gradient on the top, and since I'm using this for an iOS app, I need it to be fairly fast – MysteryPancake Dec 03 '16 at 11:47
  • If you need a round gradient you won't get around calculating a square root, and the rest of the calculation is really simply. If you are ok with a linear gradient you can just blend based on the y coordinate. – Yakov Galka Dec 03 '16 at 11:59
  • I tried a linear one but it looked a bit too fake. Could you give a small example for the square root? Sorry, but as I said, I'm awful at math – MysteryPancake Dec 03 '16 at 12:02
  • What I mean is I don't know how to use it for anything without the lighting direction variable... Just asking for a little example of how to use it for just the top part without the lighting variable – MysteryPancake Dec 03 '16 at 12:19
  • Why do you want to get rid of the lighting direction? It is a constant, and the calculation you see above isn't significantly heavier than the one in your question. – Yakov Galka Dec 03 '16 at 13:36
  • 2
    `P != circCoord` because `P` has to be a 3d vector whereas `circCoord` is the 2d vector within the circle. So to compute the 3d coordinates of the point we need to find its `z` coordinate given its `x` and `y`. The equation for the sphere of radius 1 is `x*x + y*y + z*z = 1`, so `z = sqrt(1 - (x*x + y*y))`. And this is exactly what I do. – Yakov Galka Dec 03 '16 at 21:00
  • 2
    Yes, and of radius 1, because this is how the OP defined it: `dot(circCoord, circCoord) > 1.0` – Yakov Galka Dec 03 '16 at 21:08