如何渲染令人信服的天穹?

2022-09-04 04:44:37

我正在编写一个OpenGL ES 2.0应用程序,它可以渲染一个3D岛。我已经有了代码来生成岛屿周围的天空穹顶。这是一个由三角形组成的半球,这些三角形位于岛屿上,z点朝上。

穹顶有一些非常基本的移动云,使用覆盖在自身上并移动不同速度的柏林噪声纹理创建。

但最终我需要穹顶来渲染:

  • 太阳(在天空中跟踪)月亮(包括相位)
  • 星星(晚上)
  • 作为静态纹理的遥远土地
  • 不同的颜色来模拟夜晚,黎明,黄昏,白天

我需要非常有效地做到这一点,因为它最终会在Android上结束,尽管目前它在测试工具中运行。因此,例如,太阳,月亮和星星将只是纹理,尽管它们的点可以以合理的精度绘制。

我已经有了生成圆顶的代码,以及根据日期和时间绘制太阳的代码。因此,主要是我需要的着色器以及它们提供的内容。

有没有例子可以证明这些事情?我发现了很多基本的立方体贴图,或者有限的东西,但没有达到我需要的复杂程度。显然,由于这是OpenGL ES 2.0,因此必须在着色器中完成。

我现有天空穹顶的着色器会渲染 2 层柏林噪声来模拟云彩。纹理连续包裹,因此我可以根据圆顶顶点与xy平面的角度(通过将x和y馈送到atan中)以及使用圆顶顶点z的v偏移来计算u偏移。

顶点着色器演示了我如何做到这一点:

#ifdef GL_ES
precision mediump float;
precision mediump int;
#endif

attribute vec4 aVertex;

uniform mat4 uPMVMatrix;
uniform float uTime;
uniform float uSkyDomeRadius;

const float PI = 3.1415926535897932384626433832795;

varying vec2 texCoord0, texCoord1;

void main()
{
    vec2 centre = vec2(600., 600.);

    gl_Position = uPMVMatrix * aVertex;

    float slow_time = uTime / 100.;

    vec2 dome_point = aVertex.xy - centre;
    float tex_u = atan(dome_point.x, dome_point.y);// / (.25 * PI);
    float tex_v = aVertex.z / (uSkyDomeRadius * .5);

    texCoord0 = vec2(tex_u / 2.0 + slow_time, tex_v / 2.0);
    texCoord1 = vec2(tex_u + slow_time / 2.0, tex_v);
}

我还使用时间在每帧偏移u位,以便云移动。这工作正常,除了 atan 从 -PI 到 PI,突然 texCoord0 和 texCoord1 值片段着色器插值被一个软管插值的很远的距离隔开。

描述它的最好方法是,如果我的底部有16个三角形,那么从0/16到1/16的插值有效,1/16到2/16有效,依此类推。但是,当我到达 15/16 到 0/16 时,插值器会向后移动,较大的变化会导致 frag 着色器在小空间中一遍又一遍地重复纹理,从而导致条纹,如图所示。

Interpolation goes haywire as angle goes into reverse

我看不到任何方法来获得无缝的360度视图,我认为解决这个问题的唯一方法是旋转整个圆顶,以便接缝始终在相机后面,但它仍然可能显示相机是否直指向圆顶的顶部。

使用源代码的工作示例会很棒,特别是如果它解决了这类问题。


答案 1

问题是,您在 0° 和 360° 的角度使用相同的顶点。因此,您现在有一个三角形,其中第一个顶点的纹理坐标为 15/16, 0,第二个顶点的纹理坐标为 0, 0 而不是 1,0。要解决此问题,您必须打开球体,以便在相同的空间位置有一对顶点,一个用于0°,一个用于360°。这样,两个顶点可以具有不同的纹理坐标,并且不会有任何受干扰的纹理。

要旋转它们,您必须使用包装模式,确保将纹理包装设置为重复。如果您没有更改它,则应正确设置它,但是可以使用函数进行设置,参数为和,并且值必须是。然后,如果纹理值> 1,则不会环绕,而是重复纹理。现在,您只需要能够分辨球体起点的顶点(对于0°处的顶点)和终点处的顶点(对于360°处的顶点),这样您就可以更正,您可能需要一个额外的属性。glTexParameterGL_TEXTURE_WRAP_SGL_TEXTURE_WRAP_TGL_REPEATtex_u


答案 2

推荐