微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

GLSL-计算片段的法线

如何解决GLSL-计算片段的法线

| 我正在尝试创建一个显示地球地形的程序,并在GPU上执行所有纬度/经度/纬度到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,0);
    glEnd();
}
谁能指导我如何正确着色地形?     

解决方法

我觉得您需要研究更多的计算机图形学,因为您对计算机渲染的几何学的基本知识似乎有些不足。 无论如何: 如果您从一开始就没有坡度信息,那么在任何点获取法线(表面方向)通常都需要查看周围的环境。 其次,您可能想绘制三角形而不是直线。 三角形有一个表面。表面具有法线。法线是矢量,可以与其他矢量成角度。光线方向是矢量。点积是您的朋友。 :) 因此,使用一组三角形连接您的顶点将有助于您到达某个地方。 另外,避免在着色器中计算可以在渲染之前一劳永逸地计算的东西。     ,您的问题在这里:
Normal = normalize(gl_NormalMatrix * v.xyz);
幸运的是,您发现了一种罕见的情况,即使用顶点的位置也可以为您提供法线:球体(但是由于地球不是球体,因此您的光照并非100%正确) 当您添加山脉时,这不再是事实。法线垂直于地面,因此在山上是弯曲的。 您需要这样的一行:
Normal = normalize(gl_NormalMatrix * gl_Normal.xyz);
gl_Normal是在glVertex3f之前通过调用glNormal3f给出的。但是您没有说如何提供地形数据,因此您必须自己找到glNormal3f的参数。它们必须在模型空间中表示(即,不是笛卡尔/纬度,而是在笛卡尔空间中相对于地球中心的XYZ。再次是:笛卡尔空间。)     

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?