tags:

views:

399

answers:

2

I'm trying to draw lots of circles on a sphere using shaders. The basic alogrith is like this:

[1] - calculate the distance from the fragment (using it's texture coordinates) to the location of the circle's center (the circle's center is also specified in texture coordinates) [2] - calculate the angle from the fragent to the center of the circle. [3] - based on the angle, access a texture (which has 360 pixels in it and the red channel specifies a radius distance) and retrieve the radius for the given angle [4] - if the distance from the fragment to the circle's center is less than the retrieved radius then the fragment's color is red, otherwise blue.

I would like to draw ... say 60 red circles on a blue sphere. I got y shader to work for one circle, but how to do 60? Here's what I've tried so far....

(1) - I passed in a data texture that specifies the radius for a given angle, but I notice artifacts creep in. I believe this is due to linear interpolation when I try to retrieve information from the data texture using:

float returnV = texture2D(angles, vec2(x, y)).r;

where angles is the data texture (Sampler2D) that contains the radius for a given angle, and x = angle / 360.0 (angle is 0 to 360) and y = 0 to 60 (y is the circle number)

(2) - I tried passing in a Uniform float radii[360], but I cannot access radii with dynamic indexing. I even tried this mess ...

getArrayValue(int index) { if (index == 0) { return radii[0]; } else if (index == 1) { return radii[1]; }

and so on ...

If I create a texture and place all of the circles on that texture and then multi-texture the blue sphere with the one containing the circles it works, but as you would expect, I have really bad aliasing. I like the idea of proceduraly generating the circles based on the position of the fragment and that of the circle because of virtually no aliasing. However, I do I do ore than one?

Thx!!!

~Bolt

A: 

hi, i have a shader that makes circle on the terrain. It moves by the mouse moves. maybe you get an inspiration?

this is a fragment program. it is not the main program but you can add it to your program. try this...

for now you can give some uniform parameters in hardcode.

uniform float showCircle;
uniform float radius;
uniform vec4 mousePosition;

varying vec3 vertexCoord;

void calculateTerrainCircle(inout vec4 pixelColor)
{
 if(showCircle == 1)
 { 
 float xDist = vertexCoord.x - mousePosition.x;
 float yDist = vertexCoord.y - mousePosition.y;

 float dist = xDist * xDist + yDist * yDist;
 float radius2 = radius * radius;

 if (dist < radius2 * 1.44f && dist > radius2 * 0.64f)
 {
  vec4 temp = pixelColor;

  float diff;
  if (dist < radius2)
   diff = (radius2 - dist) / (0.36f * radius2);
  else
   diff = (dist - radius2) / (0.44f * radius2);

  pixelColor = vec4(1, 0, 0, 1.0) * (1 - diff) + pixelColor * diff; 

  pixelColor = mix(pixelColor, temp, diff);
 }     
} 
}

and in vertex shader you add:

varying vec3 vertexCoord;

void main()
{
    gl_Position = ftransform();

    vec4 v = vec4(gl_ModelViewMatrix * gl_Vertex);
    vertexCoord = vec3(gl_ModelViewMatrixInverse * v);
}
ufukgun
Thank you! I figured it would most likely have to do some of the work in the vertex program. Thx for the inspiration!
Boltimuss
I've added a comment to this answer. (It's shown as an answer below, due to formatting and size limitations).
RJFalconer
A: 

ufukgun, if you multuiply a matrix by its inverse you get the identity.
Your;

vec4 v = vec4(gl_ModelViewMatrix * gl_Vertex);
vertexCoord = vec3(gl_ModelViewMatrixInverse * v);

is therefore equivalent to

vertexCoord = vec3(gl_Vertex);
RJFalconer
actually you are right about the first comment, which is about verteCoord = vec3(gl_Vertex);but the second one is not. i use dist as dist^2 so i compared with radius^2. i did not want to calculate sqrt so i used dist^2. anyway, u can change the function as you said. (both are true)
ufukgun
Ah, nice. Ty for clarification =). I see my mistake; I will edit my answer.
RJFalconer