Skip to content Skip to sidebar Skip to footer

Change Color In Middle Of Circle

I'm new to WebGL and I'm trying to create a black ring in the middle of this green circle without making additional circles. I believe I can do this by making the normal of those t

Solution 1:

I assembled some part of your task as you requested. I tried to not change your code much, so you can understand all changes I have done. First small show:

You made circle out of 100 points (vertices). Now you want to make another shape inside. It means use another 100 points, which is probably what you don't want to do. Instead of this, you would like to use normals. But from the point of view of shaders (which are responsible for drawing), normals, vertices and other things like texture coordinates are just data and you are the one who decides, if data means vertices, normals, texture coordinates or anything else.

If I understand good, you want to customize your object without adding too much additional data. I don't think normals or textures can help you.

There are few problems you will have to face with texture ...

  • First is, if circle will be too big (close to you), then it will be not that nice with just 100 points.
  • If circle will be too small (far from you), but there will be a lot circles, you will use too many points for nothing which will lower performance.
  • If you use texture for black ring inside, it will be fuzzy if you will be closer.
  • And if you use too large texture for a lot of small circles, it will again lower performance.

... and normals are used to do light reflection like this.

Way I think about the problem. You can define circle with just few params, radius and center. With webgl, you can draw only triangles (and points). But you can for example customize shader to draw inscribed circle in each triangle.

So I defined just radius and center:

var r = 0.9;
var middle = vec2(0.0, 0.0);

Then I generate 3 points of triangle around the circle (circle is inscribed circle of this new triangle):

functionbuildCircle(center, r) {
    var points = [];

    points.push(vec2((r * TRI_HEIGHT_MOD * Math.cos(0 * DEG_TO_RAD)) + center[0], (r * TRI_HEIGHT_MOD * Math.sin(0 * DEG_TO_RAD)) + center[1]));
    points.push(vec2((r * TRI_HEIGHT_MOD * Math.cos(120 * DEG_TO_RAD)) + center[0], (r * TRI_HEIGHT_MOD * Math.sin(120 * DEG_TO_RAD) + center[1])));
    points.push(vec2((r * TRI_HEIGHT_MOD * Math.cos(240 * DEG_TO_RAD)) + center[0], (r * TRI_HEIGHT_MOD * Math.sin(240 * DEG_TO_RAD)) + center[1]));

    vertexPositions = points;
}

Then I pass middle, radius and triangle to my shader:

var vPosition = gl.getAttribLocation(program, "vPosition");
gl.vertexAttribPointer(vPosition, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(vPosition);

program.middle = gl.getUniformLocation(program, "middle");
gl.uniform2f(program.middle, middle[0], middle[1]);

program.r = gl.getUniformLocation(program, "r");
gl.uniform1f(program.r, r);

And then I just render it with same as you do, except I need to allow alpha drawing, because some parts of triangle will be invisible, so it will look as circle:

gl.blendFunc(gl.SRC_ALPHA, gl.ONE);
gl.enable(gl.BLEND);
gl.disable(gl.DEPTH_TEST);

Ok now shaders.

There are few things you really need to know to continue, so please read about it here: http://webglfundamentals.org/webgl/lessons/webgl-how-it-works.html

My vertex shader is same as yours, except I need to pass interpolated vertex position to fragment shader:

varying vec4 pos;

... 

voidmain() {
    pos = vPosition;

My fragment shader needs to do only one thing and it is to decide, if pixel is in the circle or not. Simple equation: enter image description here

If the left side is smaller then the right side, then pixel is inside the circle. If not, then it is outside, so invisible:

float inside = pow(pos.r - middle.r, 2.0) + pow(pos.g - middle.g, 2.0);
    if (inside < pow(r, 2.0)) {
        gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
    } else {
        gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
    }

End

So now you might know how to make a circle just from few points. You can use similar way to draw a ring inside. Then you can draw thousands of them in any distance and make them move. Program will be still fast and shapes will be as sharp as possible.

Just one last thing. Usually you dont simplify shapes like that, but sometimes you might. Good example is Bézier curve which might help you to do crazy sharp shapes with just few points. But it all matters what would you like to do. One technique can't solve all problems and you have to keep looking for more solutions.

EDIT 1:"What is var middle = vec2(0.0, 0.0)? I meam, vec2?"

There are 3 other scripts in this question that I replicated in my solution (in jsfiddle on the left: External Resources). It wasnt part of this question, but it was easy to find theirs origin:

<scripttype="text/javascript"src="../Common/webgl-utils.js"></script><scripttype="text/javascript"src="../Common/initShaders.js"></script><scripttype="text/javascript"src="../Common/MV.js"></script>

MV.js is some supply javascript with basic math... or algebraic constructs like vectors and matrices. vec2 is function that returns array with length 2. So var middle = [0.0, 0.0]; is exactly the same thing. This is not part of native javascript, so you need some library for it (you don't need it, but it is very useful). I use glmatrix.

On the other hand in shaders, vectors and matrices are native. Find it out on your own in chapter 4.1 Basic Types.

Post a Comment for "Change Color In Middle Of Circle"