Jump to content
  • Advertisement
Sign in to follow this  
bluehailex

OpenGL Calculating texture coordinates for tessellated terrain

This topic is 1381 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I've been trying to create a simple height map terrain renderer using tessellation shaders in OpenGL. Everything works fine, except for computing a global texture coordinate for sampling the height map. The rendering starts with a call to glDrawArraysInstanced(GL_PATCHES, 0, 4, terrainSize*terrainSize). In the vertex shader, the world position is computed from gl_InstanceID. So far, I'm then calculating a global texture coordinate by taking worldPos / terrainSize. In this coordinate system, [0,0] and [1,1] should be in opposite corners of the height field.

 

As you can see in the attached images, the coordinates on the edges are messed up and wrap around to the other side. You can see red bleeding into green, and green bleeding into red. By setting the wrap mode to ClampToEdge, the problem is "hidden". In the pictures, I'm drawing a 25 patches (5x5). I've also tried clamping the 

interpolated texture coordinates in the TES with tesOut.tc = vec2(clamp(tc.x, 0.0, 1.0), clamp(tc.y, 0.0, 1.0));, but that doesn't help either.

 

 

Vertex shader

#version 430 core

out VSOut
{
    vec2 tc;
} vsOut;

uniform int terrainSize;

void main()
{
    const float M = 1.0;
    const vec4 vertices[] = vec4[](vec4(M, 0, 0, 1.0),
    vec4(M, 0, M, 1.0),
    vec4(0, 0, 0, 1.0),
    vec4(0, 0, M, 1.0));

    vec4 worldPos;
    worldPos.x = float(gl_InstanceID % terrainSize) + vertices[gl_VertexID].x;
    worldPos.y = 0.0;
    worldPos.z = float(gl_InstanceID / terrainSize) + vertices[gl_VertexID].z;
    worldPos.w = 1.0f;

    vsOut.tc.x = worldPos.x / terrainSize;
    vsOut.tc.y = worldPos.z / terrainSize;

    gl_Position = worldPos;
}

Tessellation control shader

#version 430 core


layout (vertices = 4) out;


in VSOut
{
    vec2 tc;
} tcsIn[];


out TCSOut
{
    vec2 tc;
} tcsOut[];

void main()
{
    if (gl_InvocationID == 0)
    {
        const float inner = 1.0;
        const float outter = 1.0;

        gl_TessLevelInner[0] = inner;
        gl_TessLevelInner[1] = inner;

        gl_TessLevelOuter[0] = outter;
        gl_TessLevelOuter[1] = outter;
        gl_TessLevelOuter[2] = outter;
        gl_TessLevelOuter[3] = outter;
    }

    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
    tcsOut[gl_InvocationID].tc = tcsIn[gl_InvocationID].tc;
}

Tessellation evaluation shader

#version 430 core

layout (quads) in;

in TCSOut
{
    vec2 tc;
} tesIn[];


out TESOut
{
    vec2 tc;
} tesOut;

uniform mat4 modelViewMatrix;
uniform mat4 perspectiveMatrix;

void main()
{
    vec2 tc1 = mix(tesIn[0].tc, tesIn[1].tc, gl_TessCoord.x);
    vec2 tc2 = mix(tesIn[2].tc, tesIn[3].tc, gl_TessCoord.x);
    vec2 tc = mix(tc2, tc1, gl_TessCoord.y);

    vec4 p1 = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);
    vec4 p2 = mix(gl_in[2].gl_Position, gl_in[3].gl_Position, gl_TessCoord.x);

    gl_Position = perspectiveMatrix * modelViewMatrix * mix(p2, p1, gl_TessCoord.y);
    tesOut.tc = tc;
}

Fragment shader

#version 430 core

layout (binding = 0) uniform sampler2D sampler;

out vec4 color;

in TESOut
{
    vec2 tc;
} fsIn;

void main()
{
    color = texture(sampler, fsIn.tc);
}
Edited by bluehailex

Share this post


Link to post
Share on other sites
Advertisement
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!