1
\$\begingroup\$

I am trying to implement planetary rendering and I am trying to use OpenGL tessellation to model the terrain. Here is an overview picture using cube faces projected onto a sphere:

Planet Earth far view

If I use the following code for the tessellation evaluation shader, I get a smooth sphere even when rendering a near view.

#version 410 core
layout(quads, equal_spacing, ccw) in;
in mediump vec2 texcoord_tes[];
out mediump vec2 texcoord_geo;
uniform mat4 projection;
uniform mat4 transform;
void main()
{
  vec2 c = mix(texcoord_tes[0], texcoord_tes[1], gl_TessCoord.x);
  vec2 d = mix(texcoord_tes[3], texcoord_tes[2], gl_TessCoord.x);
  texcoord_geo = mix(c, d, gl_TessCoord.y);
  vec4 a = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);
  vec4 b = mix(gl_in[3].gl_Position, gl_in[2].gl_Position, gl_TessCoord.x);
  vec4 p = mix(a, b, gl_TessCoord.y);
  float s = 1.0 / sqrt(p.x * p.x + p.y * p.y + p.z * p.z);
  gl_Position = projection * transform * vec4(p.xyz * s * 6388000, 1);
}

Here is a near view using the computed scaling factor (float s = 1.0 / sqrt(p.x ...)):

Near view with computed height

However if I take the scale factors from a floating-point texture, I can see quantisation artifacts. The scale factors (or heightmap values) are extracted from the texture using float s = texture(hf, texcoord_geo).r. The code for the tessellation evaluation shader in this case is as follows:

#version 410 core
layout(quads, equal_spacing, ccw) in;
in mediump vec2 texcoord_tes[];
out mediump vec2 texcoord_geo;
uniform sampler2D hf;
uniform mat4 projection;
uniform mat4 transform;
void main()
{
  vec2 c = mix(texcoord_tes[0], texcoord_tes[1], gl_TessCoord.x);
  vec2 d = mix(texcoord_tes[3], texcoord_tes[2], gl_TessCoord.x);
  texcoord_geo = mix(c, d, gl_TessCoord.y);
  float s = texture(hf, texcoord_geo).r;
  vec4 a = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);
  vec4 b = mix(gl_in[3].gl_Position, gl_in[2].gl_Position, gl_TessCoord.x);
  vec4 p = mix(a, b, gl_TessCoord.y);
  gl_Position = projection * transform * vec4(p.xyz * s * 6388000, 1);
}

In this case the near view looks like this and shows artifacts:

Near view when using height map texture

My question is, what am I doing wrong? Or is it normal that OpenGL textures are less accurate than 4-byte floating point numbers? Any help is appreciated.

\$\endgroup\$
7
  • 2
    \$\begingroup\$ What specific pixel format are you using? And what's the resolution of your floating-point texture? What happens if you increase that resolution? How are you computing the contents of the texture? \$\endgroup\$ May 15, 2021 at 22:47
  • \$\begingroup\$ @JonathanS. I use GL_RED as texture format and GL_FLOAT as texture type (see scratch.clj). The tesselation level is 32 and the 33x33 textures are computed and saved as floating point arrays (see globe.clj). Increasing the resolution of the texture is an interesting suggestion. I can try that. \$\endgroup\$
    – wedesoft
    May 15, 2021 at 23:22
  • 1
    \$\begingroup\$ What units are you working with? Floating point values lose precision the larger the magnitude, but for computer graphics, losing milliliter precision on numbers representing thousands of kilometers is not usually an issue. If precision is not working for you, how about changing the magnitude of the units? For example, kilometers instead of centimeters. \$\endgroup\$ May 16, 2021 at 11:12
  • 1
    \$\begingroup\$ Wild idea: have you tried using a GPU debugger to see exactly what's going on? \$\endgroup\$ May 17, 2021 at 0:34
  • 2
    \$\begingroup\$ Sorry mate. I tried looking through your source code, but not only it's in a language I don't know, but with no comments whatsoever, it's cherry difficult to know what you're doing, and what you're expecting to happen. Some points to keep in mind: float textures have to be float from the source; sampling goes through a sampler which might damage your expected values; 33x33 might give incorrect sampling locations (prefer powers of two sizes); run the program through a GPU debugger. \$\endgroup\$ May 17, 2021 at 0:45

1 Answer 1

0
\$\begingroup\$

Thanks everybody for looking into it! I found the solution now. The problem was that I was using GL11/GL_RGB for the internal texture format of the heightmap:

(GL11/glTexImage2D GL11/GL_TEXTURE_2D 0 GL11/GL_RGB tilesize tilesize 0 tex-format tex-type buffer)

Instead I had to use GL30/GL_R32F as the internal texture format.

(GL11/glTexImage2D GL11/GL_TEXTURE_2D 0 GL30/GL_R32F tilesize tilesize 0 tex-format tex-type buffer)

Also see OpenGL documentation for glTexImage2D.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .