GLSL - вычисление нормалей от фрагментов - PullRequest
2 голосов
/ 23 мая 2011

Я пытаюсь создать программу, которая отображает земной шар с ландшафтом и выполняет все широты / долготы / Alt в XYZ (ECEF) на графическом процессоре.

Я уже написал рабочий вершинный шейдер, который переводит XYZ, который представляет долготу, широту и высоту (соответственно), в их правильный XYZ (используя ECEF).

Что я не могу сделать правильно, так это освещение.

Мне удалось правильно осветить каждую вершину, используя направленное освещение, пока нет данных о местности. Данные местности не освещены правильно, и я не могу получить разные склоны, чтобы иметь правильные оттенки.

Это вершинный шейдер, который я использую:

const float a = 6378137.0;
const float f = 0.003352810664747480719845528618;

varying vec3 Normal;
varying vec3 ecPos;

vec3 LatLonAltToEcef(in vec3 latLonAlt)
{
    vec3 v = latLonAlt;

    float cosLat = cos(radians(v.y));
    float sinLat = sin(radians(v.y));
    float nfs = (1.0 - f) * (1.0 - f);

    float C = 1.0 / (sqrt(cosLat * cosLat + nfs * sinLat * sinLat));
    float S = nfs * C;

    float lon = radians(v.x);
    float h = v.z;

    v.x = (a * C + h) * cosLat * cos(lon) / a;
    v.y = (a * C + h) * cosLat * sin(lon) / a;
    v.z = (a * S + h) * sinLat / a;

    return v;
}

vec4 LatLonAltToEcef(in vec4 latLonAlt)
{
    vec3 ecef = LatLonAltToEcef(latLonAlt.xyz);
    return vec4(ecef.x, ecef.y, ecef.z, latLonAlt.w);
}

void main(void)
{
    vec4 v = LatLonAltToEcef(gl_Vertex); //x=lon, y=lat, z=alt
    ecPos = vec3(gl_ModelViewMatrix * v);

    Normal = normalize(gl_NormalMatrix * v.xyz);
    vec4 lightPos = LatLonAltToEcef(gl_LightSource[0].position);
    vec3 lightDir = normalize(gl_NormalMatrix * lightPos.xyz);
    float NdotL = max(dot(Normal, lightDir), 0.0);
    vec4 diffuse = gl_FrontMaterial.diffuse * gl_LightSource[0].diffuse;

    gl_FrontColor =  NdotL * diffuse;
    gl_Position = gl_ModelViewProjectionMatrix * v;
}

Чтобы нарисовать сетку глобуса, вот что нужно сделать:

for (float lat = -90; lat < 90; lat += 5)
{
    glBegin(GL_LINE_LOOP);
    for (float lon = -180; lon < 180; lon += 5)
        glVertex3f(lon, lat, 0);
    glEnd();
}

for (float lon = -180; lat < 180; lon += 5)
{
    glBegin(GL_LINE_LOOP);
    for (float lat = -90; lon < 90; lon += 5)
        glVertex3f(lon, lat, 0);
    glEnd();
}

Может ли кто-нибудь подсказать мне, как правильно затенять местность?

Ответы [ 2 ]

5 голосов
/ 23 мая 2011

Я чувствую, что вам нужно больше изучать компьютерную графику, поскольку в ваших базовых знаниях по компьютерной геометрии, похоже, есть некоторые пробелы.

В любом случае:

Получение нормалей (направление поверхности) в любой точке обычно требуется смотреть на окрестности, если у вас нет информации об уклоне с самого начала.

Во-вторых, вы, вероятно, хотите рисовать треугольники, а не линии.

Треугольники имеют поверхность.Поверхности имеет нормали.Нормалы - это векторы, которые могут иметь углы относительно других векторов.Направление света - это вектор.Точечный продукт - ваш друг.:)

Таким образом, наличие набора треугольников, соединяющих ваши вершины, поможет вам в достижении чего-либо.

Кроме того, избегайте вычислений в шейдере, который можно вычислить раз и навсегда перед любым рендерингом..

4 голосов
/ 23 мая 2011

Ваша проблема здесь:

Normal = normalize(gl_NormalMatrix * v.xyz);

К счастью, вы обнаружили редкий случай, когда использование положения вершины также дает вам нормальное: сферу (но поскольку Земля не является сферой, вашахотя освещение не на 100% правильно)

Когда вы добавляете горы, это больше не так.Нормалы перпендикулярны земле, поэтому на горе она изогнута.

Вам нужна строка, подобная этой:

Normal = normalize(gl_NormalMatrix * gl_Normal.xyz);

gl_Normal дается вызовами glNormal3f, непосредственно перед glVertex3f.Но вы не говорите, как вы предоставляете данные о местности, поэтому вам придется самостоятельно найти параметры для glNormal3f.Они должны быть выражены в модельном пространстве (т. Е. НЕ по долготе / широте, а по XYZ относительно центра Земли, в декартовом пространстве. Опять же: декартовое пространство.)

...