TESSELLATION 1 OUTLINE Tessellation in OpenGL Tessellation of - - PowerPoint PPT Presentation

tessellation
SMART_READER_LITE
LIVE PREVIEW

TESSELLATION 1 OUTLINE Tessellation in OpenGL Tessellation of - - PowerPoint PPT Presentation

TESSELLATION 1 OUTLINE Tessellation in OpenGL Tessellation of Bezier Surfaces Tessellation for Terrain/Height Maps Level of Detail 2 THE EXAMPLE TESSELLATION SHADING Instead of specifying vertices, you specify a


slide-1
SLIDE 1

1

TESSELLATION

slide-2
SLIDE 2

OUTLINE

2

  • Tessellation in OpenGL
  • Tessellation of Bezier Surfaces
  • Tessellation for Terrain/Height Maps
  • Level of Detail
slide-3
SLIDE 3

THE EXAMPLE

slide-4
SLIDE 4

TESSELLATION SHADING

  • Instead of specifying vertices, you specify a “patch”
  • Just an ordered set of vertices
  • Tessellation control shader determines how much geometry is generated from patch
  • Other primitives are processed by vertex, fragment and geometry shaders and

bypass tessellation

  • You specify the total number of vertices in the patch (with primitives, OpenGL already

knows how many vertices to expect) glPatchParameteri(GLenum pname, Glint value);

  • pname is set to GL_PATCH_VERTICES
  • value is number of vertices

glPatchParameteri(GL_PATCH_VERTICES, 4); glDrawArrays(GL_PATCHES, 0, 8);

slide-5
SLIDE 5

VERTEX SHADER

#version 430 uniform mat4 mvp; void main(void) { }

slide-6
SLIDE 6

TESSELLATION CONTROL SHADER

#version 430 uniform mat4 mvp; layout (vertices = 1) out; void main(void) { gl_TessLevelOuter[0] = 6; gl_TessLevelOuter[2] = 6; gl_TessLevelOuter[1] = 6; gl_TessLevelOuter[3] = 6; gl_TessLevelInner[0] = 12; gl_TessLevelInner[1] = 12; }

Specifies the number of output-patch vertices and specifies how many times the TCS will execute – once for each

  • utput vertex.
slide-7
SLIDE 7

TESSELLATION LEVELS

slide-8
SLIDE 8

QUAD TESSELLATION

slide-9
SLIDE 9

TRIANGLE TESSELLATION

slide-10
SLIDE 10

TESSELLATION EVALUATION SHADER

  • Executed once for each tessellation coordinate that the tessellator generates
  • Determines the position of the vertex derived from the coordinate
  • Looks similar to vertex shader
  • Transforming vertices into screen positions
  • (Unless we will use a geometry shader – but that’s at least one

lecture away)

slide-11
SLIDE 11

TESSELLATION EVALUATION SHADER

#version 430 layout (quads, equal_spacing, ccw) in; uniform mat4 mvp; void main (void) { float u = gl_TessCoord.x; float v = gl_TessCoord.y; gl_Position = mvp * vec4(u,0,v,1); }

Primitive type can be quads, triangles or isolines cw or ccw for winding order equal_spacing, fractional_even_spacing or fractional_odd_spacing

slide-12
SLIDE 12

SPACING

  • equal_spacing is the default
  • It subdivides the perimeter into the number of segments you specified
  • Looks best here, but has the disadvantage that it rounds up to the nearest integer so

if your object changes size you can get visible differences

  • fractional_even…and fractional_odd round down – but you are left with a fractional

triangle somewhere

slide-13
SLIDE 13

FRAGMENT SHADER

#version 430

  • ut vec4 color;

uniform mat4 mvp; void main(void) { color = vec4(1.0, 1.0, 0.0, 1.0); }

slide-14
SLIDE 14

TESSELLATION FOR BEZIER SURFACES

slide-15
SLIDE 15

VERTEX SHADER

#version 430

  • ut vec2 tc;

uniform mat4 mvp; layout (binding = 0) uniform sampler2D tex_color; void main(void) { const vec4 vertices[] = vec4[] (vec4(-1.0, 0.5, -1.0, 1.0), vec4(-0.5, 0.5, -1.0, 1.0), vec4( 0.5, 0.5, -1.0, 1.0), vec4( 1.0, 0.5, -1.0, 1.0), vec4(-1.0, 0.0, -0.5, 1.0), vec4(-0.5, 0.0, -0.5, 1.0), vec4( 0.5, 0.0, -0.5, 1.0), vec4( 1.0, 0.0, -0.5, 1.0), vec4(-1.0, 0.0, 0.5, 1.0), vec4(-0.5, 0.0, 0.5, 1.0), vec4( 0.5, 0.0, 0.5, 1.0), vec4( 1.0, 0.0, 0.5, 1.0), vec4(-1.0,-0.5, 1.0, 1.0), vec4(-0.5, 0.3, 1.0, 1.0), vec4( 0.5, 0.3, 1.0, 1.0), vec4( 1.0, 0.3, 1.0, 1.0)); tc = vec2((vertices[gl_VertexID].x + 1.0)/2.0, (vertices[gl_VertexID].z + 1.0)/2.0); gl_Position = vertices[gl_VertexID]; }

slide-16
SLIDE 16

TESSELLATION CONTROL SHADER

#version 430 in vec2 tc[];

  • ut vec2 tcs_out[];

uniform mat4 mvp; layout (binding=0) uniform sampler2D tex_color; layout (vertices = 16) out; void main(void) { int TL = 32; // tessellation levels if (gl_InvocationID ==0) { gl_TessLevelOuter[0] = TL; gl_TessLevelOuter[2] = TL; gl_TessLevelOuter[1] = TL; gl_TessLevelOuter[3] = TL; gl_TessLevelInner[0] = TL; gl_TessLevelInner[1] = TL; } tcs_out[gl_InvocationID] = tc[gl_InvocationID]; gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position; }

16 control points per patch

slide-17
SLIDE 17

TESSELLATION EVALUATION SHADER

#version 430 layout (quads, equal_spacing,ccw) in; uniform mat4 mvp; layout (binding = 0) uniform sampler2D tex_color; in vec2 tcs_out[];

  • ut vec2 tes_out;

slide-18
SLIDE 18

TESSELLATION EVALUATION SHADER

void main (void) { vec3 p00 = (gl_in[0].gl_Position).xyz; vec3 p10 = (gl_in[1].gl_Position).xyz; vec3 p20 = (gl_in[2].gl_Position).xyz; vec3 p30 = (gl_in[3].gl_Position).xyz; vec3 p01 = (gl_in[4].gl_Position).xyz; vec3 p11 = (gl_in[5].gl_Position).xyz; vec3 p21 = (gl_in[6].gl_Position).xyz; vec3 p31 = (gl_in[7].gl_Position).xyz; vec3 p02 = (gl_in[8].gl_Position).xyz; vec3 p12 = (gl_in[9].gl_Position).xyz; vec3 p22 = (gl_in[10].gl_Position).xyz; vec3 p32 = (gl_in[11].gl_Position).xyz; vec3 p03 = (gl_in[12].gl_Position).xyz; vec3 p13 = (gl_in[13].gl_Position).xyz; vec3 p23 = (gl_in[14].gl_Position).xyz; vec3 p33 = (gl_in[15].gl_Position).xyz;

slide-19
SLIDE 19

TESSELLATION EVALUATION SHADER

float u = gl_TessCoord.x; float v = gl_TessCoord.y; // cubic Bezier basis functions float bu0 = (1.0-u) * (1.0-u) * (1.0-u); //(1-u)^3 float bu1 = 3.0 * u * (1.0-u) * (1.0-u); //3u(1-u)^2 float bu2 = 3. * u * u * (1.0-u); //3u^2(1-u) float bu3 = u * u * u; //u^3 float bv0 = (1.0-v) * (1.0-v) * (1.0-v); //(1-v)^3 float bv1 = 3.0 * v * (1.0-v) * (1.0-v); //3v(1-v)^2 float bv2 = 3. * v * v * (1.0-v); //3v^2(1-v) float bv3 = v * v * v; //v^3

slide-20
SLIDE 20

TESSELLATION EVALUATION SHADER

// output the position of this vertex in the tessellated patch vec3 outputPosition = bu0 * ( bv0*p00 + bv1*p01 + bv2*p02 + bv3*p03 ) + bu1 * ( bv0*p10 + bv1*p11 + bv2*p12 + bv3*p13 ) + bu2 * ( bv0*p20 + bv1*p21 + bv2*p22 + bv3*p23 ) + bu3 * ( bv0*p30 + bv1*p31 + bv2*p32 + bv3*p33 ); gl_Position = mvp * vec4(outputPosition,1.0f); // shows bezier curve // gl_Position = mvp * vec4(u,0,v,1); // shows original grid (pick one) // output the interpolated texture coordinates vec2 tc1 = mix(tcs_out[0], tcs_out[3], gl_TessCoord.x); vec2 tc2 = mix(tcs_out[12], tcs_out[15], gl_TessCoord.x); vec2 tc = mix(tc2, tc1, gl_TessCoord.y); tes_out = tc; }

slide-21
SLIDE 21

FRAGMENT SHADER

#version 430 in vec2 tes_out;

  • ut vec4 color;

uniform mat4 mvp; layout (binding=0) uniform sampler2D tex_color; void main(void) { color = texture(tex_color, tes_out); }

slide-22
SLIDE 22

TESSELLATION FOR TERRAIN / HEIGHT MAPS

  • Height mapping from the vertex shader can lose detail
  • Tesselation shaders introduce additional vertices
  • Can use this to flesh out the detail
  • Matches object geometry better
  • Improves silhouette / edge detail
  • Strategy:
  • Place a tesselated grid in the x-z plane
  • Use height map to set y coordinates
  • Doesn’t require any patches
  • Use grey scale image for both texture and height map
  • Initial result?
slide-23
SLIDE 23

TESSELLATION FOR TERRAIN / HEIGHT MAPS

  • White areas should be higher and black areas lower
  • Does not correspond on the result
  • Even by adding vertices with tessellation, the resolution is too low to capture details
slide-24
SLIDE 24

TESSELLATION FOR TERRAIN / HEIGHT MAPS

  • The solution:
  • Use instancing
  • Remember instancing from way early on?
  • Rendering multiple Java objects with a single Java call
  • Build a patch in the vertex shader
  • Instance the picture with 64x64 patches - results in over 4 million vertices
slide-25
SLIDE 25

VERTEX SHADER

#version 430

  • ut vec2 tc;

uniform mat4 mvp; layout (binding = 0) uniform sampler2D tex_color; void main(void) { vec2 patchTexCoords[] = vec2[] (vec2(0,0), vec2(1,0), vec2(0,1), vec2(1,1)); // compute an offset for coordinates based on which instance this is int x = gl_InstanceID % 64; int y = gl_InstanceID / 64; // texture coordinates are distributed across 64 patches tc = vec2( (x+patchTexCoords[gl_VertexID].x)/64.0, (y+patchTexCoords[gl_VertexID].y)/64.0 ); // vertex locations range from -0.5 to +0.5 gl_Position = vec4(tc.x-0.5, 0.0, (1.0-tc.y)-0.5, 1.0); }

slide-26
SLIDE 26

TESSELLATION CONTROL SHADER

#version 430 layout (vertices = 4) out; in vec2 tc[];

  • ut vec2 tcs_out[];

uniform mat4 mvp; layout (binding=0) uniform sampler2D tex_color; void main(void) { int TL = 32; if (gl_InvocationID == 0) { gl_TessLevelOuter[0] = TL; gl_TessLevelOuter[2] = TL; gl_TessLevelOuter[1] = TL; gl_TessLevelOuter[3] = TL; gl_TessLevelInner[0] = TL; gl_TessLevelInner[1] = TL; } tcs_out[gl_InvocationID] = tc[gl_InvocationID]; gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position; }

slide-27
SLIDE 27

TESSELLATION EVALUATION SHADER

#version 430 layout (quads, equal_spacing,ccw) in; uniform mat4 mvp; layout (binding = 0) uniform sampler2D tex_color; in vec2 tcs_out[];

  • ut vec2 tes_out;

void main (void) { // map the texture coordinates onto the sub-grid specified by the incoming control points vec2 tc = vec2(tcs_out[0].x+(gl_TessCoord.x)/64.0, tcs_out[0].y+(1.0-gl_TessCoord.y)/64.0); // map the tessellated grid onto the sub-grid specified by the incoming control points vec4 tessellatedPoint = vec4(gl_in[0].gl_Position.x + gl_TessCoord.x / 64.0, 0.0, gl_in[0].gl_Position.z + gl_TessCoord.y / 64.0, 1.0); // add the height from the height map to the vertex: tessellatedPoint.y += (texture(tex_color, tc).r) / 40.0; gl_Position = mvp * tessellatedPoint; tes_out = tc; }

slide-28
SLIDE 28

FRAGMENT SHADER

#version 430 in vec2 tes_out;

  • ut vec4 color;

uniform mat4 mvp; layout (binding=0) uniform sampler2D tex_color; void main(void) { color = texture(tex_color, tes_out); }

And the result? …

slide-29
SLIDE 29

OVERLY JAGGED

slide-30
SLIDE 30

ANOTHER ATTEMPT

  • Height mapping detail is somewhat correct, but areas not quite right
  • One problem is using a greyscale texture image for height doesn’t quite work
  • Not all variations in greyscale images are due to height- some are just color
  • Another problem – we don’t have normals so we can do the lighting
  • Solution – use a true height map and a normal map
  • Bonus – the image now responds to lighting
slide-31
SLIDE 31

HEIGHT MAP AND NORMAL MAP

slide-32
SLIDE 32

WITH NORMAL MAP AND LIGHTING

slide-33
SLIDE 33

SO …WHAT’S THE DRAWBACK?

  • Imagery is great, but we have over 4 million vertices just to draw the moon surface
  • Any additional graphic objects are going to start taxing the system
  • Solution – Only use high resolution in the areas that matter
  • Those that are closer to the viewer
  • Level of Detail:
  • Changing the number of vertices based on the distance from the camera
  • One catch… changing detail level, as the object/camera moves can make parts
  • f the image “pop” or wiggle
  • The fix? Use fractional_even_spacing instead of equal_spacing
slide-34
SLIDE 34

LEVEL OF DETAIL

slide-35
SLIDE 35

SUMMARY

35

  • Tessellation in OpenGL
  • Tessellation of Bezier Surfaces
  • Tessellation for Terrain/Height Maps
  • Level of Detail