Calculation of normals from terrain data in a fragment shader

The application loads elevation data into floating point textures. Textures are then displayed in a floating color buffer (using * GL_ARB_color_buffer_float *).

The first pass is to get the overall texture (as a result of multiple rendering of textured squares). To do this, I turn off the color clip, draw each square and copy the frame buffer (float) to the texture (float): this texture is the basis of several passes for processing elevation data.

There is no problem rendering floating texture data using false colors: indeed, the elevation information is saved during the first pass (without a color clip).

I'm having trouble calculating the normals of the terrain. Here is the sweep of the fragment shader:

// Required shader language version (compatibility profile) #version 150 compatibility //--------------------------------------------------------------------------- // SYSTEM INPUTS/OUTPUT //--------------------------------------------------------------------------- // Fragment texture coordinate (in) in vec4 gl_TexCoord[]; // Fragment color (out) vec4 gl_FragColor; // DTED elevation data as texture. // Value fetched by the texture if the altitude of the terrain, in meters. uniform sampler2D rdr_ElevationData; // Obtain fragment elevation float GetFragmentElevation(const vec2 texcoord) { // This is OK! Tested with false colors return (texture(rdr_ElevationData, gl_TexCoord[0].st).r); } vec3 GetFragmentNormal(const vec2 texcoord, const float sOffset, const float tOffset) { const vec2 texcoordN = texcoord + vec2( 0.0, +tOffset), texcoordNE = texcoord + vec2(+sOffset, +tOffset), texcoordE = texcoord + vec2(+sOffset, 0.0), texcoordSE = texcoord + vec2(+sOffset, -tOffset), texcoordS = texcoord + vec2( 0.0, -tOffset), texcoordSW = texcoord + vec2(-sOffset, -tOffset), texcoordW = texcoord + vec2(-sOffset, 0.0), texcoordNW = texcoord + vec2(-sOffset, +tOffset); float TerrainAroundHeights[9]; // Ensuring clamped texture coordinates clamp(texcoordN , 0.0, 1.0); clamp(texcoordNE, 0.0, 1.0); clamp(texcoordE , 0.0, 1.0); clamp(texcoordSE, 0.0, 1.0); clamp(texcoordS , 0.0, 1.0); clamp(texcoordSW, 0.0, 1.0); clamp(texcoordW , 0.0, 1.0); clamp(texcoordNW, 0.0, 1.0); // Fetch terrain heights around the fragment TerrainAroundHeights[0] = GetFragmentElevation(texcoord); TerrainAroundHeights[1] = GetFragmentElevation(texcoordN); TerrainAroundHeights[2] = GetFragmentElevation(texcoordNE); TerrainAroundHeights[3] = GetFragmentElevation(texcoordE); TerrainAroundHeights[4] = GetFragmentElevation(texcoordSE); TerrainAroundHeights[5] = GetFragmentElevation(texcoordS); TerrainAroundHeights[6] = GetFragmentElevation(texcoordSW); TerrainAroundHeights[7] = GetFragmentElevation(texcoordW); TerrainAroundHeights[8] = GetFragmentElevation(texcoordNW); const float NormalLength = 0.001; vec3 v0 = vec3(0.0, 0.0, 0.0), v1 = vec3(0.0, NormalLength, 0.0), v2 = vec3(NormalLength, 0.0, 0.0); // Compute averaged heights for each fragment corner /*v0.z = (TerrainAroundHeights[0] + TerrainAroundHeights[7] + TerrainAroundHeights[6] + TerrainAroundHeights[5]) / 4.0; v1.z = (TerrainAroundHeights[0] + TerrainAroundHeights[1] + TerrainAroundHeights[8] + TerrainAroundHeights[7]) / 4.0; v2.z = (TerrainAroundHeights[0] + TerrainAroundHeights[5] + TerrainAroundHeights[4] + TerrainAroundHeights[3]) / 4.0;*/ // MY TESTS... unable to understand what going on if (TerrainAroundHeights[0] < (TerrainAroundHeights[5])) v0.z = 1.0; return (v0); // Compute terrain normal return (normalize(cross(v2 - v0, v1 - v0))); } void main() { ivec2 rdr_ElevationData_Size = textureSize(rdr_ElevationData, 0); // Texture size, in textel vec3 frag_Normal; // Fragment normal float rdr_ElevationData_S_CoordStep = 1.0 / /*rdr_ElevationData_Size[0]*/ 672.0 /* Tried but not working... * 4.0 */; float rdr_ElevationData_T_CoordStep = 1.0 / /*rdr_ElevationData_Size[1]*/ 672.0 /* Tried but not working... * 4.0 */; // Determine fragment normal frag_Normal = GetFragmentNormal(gl_TexCoord[0].st, rdr_ElevationData_S_CoordStep, rdr_ElevationData_T_CoordStep); // Test purpose... (always 0.0!!!) gl_FragColor = vec4(frag_Normal.z, 0.0, 0.0, 1.0); } 

You can see in GetFragmentNormal, I'm trying to get height data from unpainted textures, but the values โ€‹โ€‹of TerrainAroundHeights always seem equal !!!

Am I missing something huge? Is there a better way to get unpainted text?

+4
source share
1 answer

You calculate the texcoord offset in GetFragmentNormal and then pass it to GetFragmentElevation, but then you do not use it in the texture search - before adding the offset you use the original texcoord.

 float GetFragmentElevation(const vec2 texcoord) { // This is OK! Tested with false colors return (texture(rdr_ElevationData, gl_TexCoord[0].st).r); } 

So not too surprisingly, you get the same elevation regardless of the offset. Change gl_TexCoord[0] to texcoord .

+6
source

All Articles