2

地形のある地球儀を表示し、GPUですべてのLat / Long / Alt to XYZ(ECEF)を実行するプログラムを作成しようとしています。

経度、緯度、高度を(それぞれ)表すXYZを(ECEFを使用して)正しいXYZに変換する動作する頂点シェーダーを既に作成しました。

私が正しくできないのは照明です。

地形データがない限り、指向性ライトを使用して各頂点を正しく照らすことができました。地形データが正しく照らされておらず、正しい色合いを持つためにさまざまな勾配を取得できません。

これは私が使用している頂点シェーダーです:

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

地形を正しくシェーディングする方法を教えてもらえますか?

4

2 に答える 2

5

コンピュータでレンダリングされたジオメトリに関する基本的な知識にギャップがあるように見えるので、コンピュータ グラフィックスをもっと勉強する必要があると思います。

ともかく:

最初から傾斜情報がない場合、任意の点で法線 (サーフェス方向) を取得するには、通常、周囲を調べる必要があります。

次に、線ではなく三角形を描きたいと思うでしょう。

三角形には面があります。サーフェスには法線があります。法線はベクトルであり、他のベクトルに対して角度を持つことができます。光の方向はベクトルです。内積はあなたの友達です。:)

したがって、頂点を結ぶ一連の三角形を用意すると、どこかに到達するのに役立ちます。

また、レンダリングの前に一度だけ計算できるものをシェーダーで計算することは避けてください。

于 2011-05-23T09:37:20.747 に答える
4

あなたの問題はここにあります:

Normal = normalize(gl_NormalMatrix * v.xyz);

運が良ければ、頂点の位置を使用すると法線も得られるというまれなケースが見つかりました: 球体 (ただし、地球は球体ではないため、照明は 100% 正しいわけではありません)

山を追加すると、これは当てはまりません。法線は地面に対して垂直なので、山では曲がっています。

次のような行が必要です。

Normal = normalize(gl_NormalMatrix * gl_Normal.xyz);

gl_Normal は、glVertex3f の直前に glNormal3f を呼び出すことによって与えられます。しかし、地形データをどのように与えるかは言わないので、glNormal3f へのパラメーターを自分で見つける必要があります。モデル空間で表現する必要があります (つまり、経度/緯度ではなく、デカルト空間で地球の中心を基準とした XYZです。これもデカルト空間です)。

于 2011-05-23T14:18:00.340 に答える