Рисование кругов на сфере

Я пытаюсь нарисовать много кругов на сфере с помощью шейдеров. Базовый алогрит выглядит так:

  1. рассчитать расстояние от фрагмента (используя его координаты текстуры) до местоположения центра круга (центр круга также указывается в координатах текстуры)
  2. вычислить угол от фрагмента до центра круга.
  3. на основе угла получить доступ к текстуре (которая имеет 360 пикселей в ней, а красный канал определяет расстояние радиуса) и получить радиус для данного угла
  4. если расстояние от фрагмента до центра круга меньше полученного радиуса, то цвет фрагмента красный, в противном случае - синий.

Я хотел бы нарисовать ... скажем, 60 красных кругов на синей сфере. У меня есть шейдер y для работы с одним кругом, но как сделать 60? Вот что я пробовал до сих пор ....

  1. Я передал текстуру данных, которая определяет радиус для заданного угла, но замечаю вкрапления артефактов. Я считаю, что это происходит из-за линейной интерполяции, когда я пытаюсь получить информацию из текстуры данных, используя:

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

    где angles - это текстура данных (Sampler2D), которая содержит радиус для данного угла, а x = angle / 360.0 (угол от 0 до 360) и y = от 0 до 60 (y - номер круга)

  2. Я попытался передать Uniform float radius [360], но у меня нет доступа к радиусам с динамической индексацией. Я даже пробовал эту кашу ...

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

    и так далее ...

Если я создаю текстуру и помещаю все круги на эту текстуру, а затем смешиваю синюю сферу с сферой, содержащей круги, это работает, но, как и следовало ожидать, у меня действительно плохое сглаживание. Мне нравится идея процедурного создания кругов на основе положения фрагмента и положения круга из-за практически отсутствия наложения спектров. Тем не менее, я делаю руду, чем один?

Спасибо!!!

~ Болт


person Boltimuss    schedule 30.06.2009    source источник


Ответы (2)


У меня есть шейдер, который рисует круг на местности. Он перемещается мышью, перемещается. может ты получишь вдохновение?

это программа-фрагмент. это не основная программа, но вы можете добавить ее в свою программу. попробуй это...

пока вы можете указать некоторые единообразные параметры в жестком коде.

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);
    }               
}   
}

и в вершинном шейдере вы добавляете:

varying vec3 vertexCoord;

void main()
{
    gl_Position = ftransform();

    vec4 v = vec4(gl_ModelViewMatrix * gl_Vertex);
    vertexCoord = vec3(gl_ModelViewMatrixInverse * v);
}
person ufukgun    schedule 15.07.2009
comment
Спасибо! Я полагал, что ему, скорее всего, придется выполнять часть работы в программе вершин. Спасибо за вдохновение! - person Boltimuss; 15.07.2009
comment
Я добавил комментарий к этому ответу. (Это показано как ответ ниже из-за ограничений форматирования и размера). - person RJFalconer; 31.12.2009

ufukgun, если вы мультиплицируете матрицу по ее инверсии, вы получите идентичность .
Ваш;

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

поэтому эквивалентно

vertexCoord = vec3(gl_Vertex);
person RJFalconer    schedule 27.11.2009
comment
на самом деле вы правы насчет первого комментария, который касается verteCoord = vec3 (gl_Vertex); но второй нет. Я использую dist как dist ^ 2, поэтому я сравниваю с радиусом ^ 2. Я не хотел вычислять sqrt, поэтому использовал dist ^ 2. в любом случае, вы можете изменить функцию, как вы сказали. (оба верны) - person ufukgun; 04.01.2010
comment
Ах, хорошо. Ты для разъяснений =). Я вижу свою ошибку; Отредактирую свой ответ. - person RJFalconer; 04.01.2010