TessellationExample(void) : shape_instr(make_shape.Instructions(PrimitiveType::Patches)) , shape_indices(make_shape.Indices()) , vs(ObjectDesc("Vertex")) , cs(ObjectDesc("Tessellation Control")) , es(ObjectDesc("Tessellation Evaluation")) , gs(ObjectDesc("Geometry")) , fs(ObjectDesc("Fragment")) , projection_matrix(prog, "ProjectionMatrix") , camera_matrix(prog, "CameraMatrix") , model_matrix(prog, "ModelMatrix") , offset(prog, "Offset") , view_position(prog, "ViewPosition") , viewport_dimensions(prog, "ViewportDimensions") { vs.Source( "#version 330\n" "uniform vec3 ViewPosition;" "in vec3 Position;" "out vec3 vertPosition;" "out float vertDistance;" "void main(void)" "{" " vertPosition = Position;" " vertDistance = length(ViewPosition - vertPosition);" "}" ); vs.Compile(); cs.Source( "#version 330\n" "#extension ARB_tessellation_shader : enable\n" "layout(vertices = 3) out;" "in vec3 vertPosition[];" "in float vertDistance[];" "out vec3 tecoPosition[];" "int tessLevel(float dist)" "{" " return int(9.0 / sqrt(dist+0.1));" "}" "void main(void)" "{" " tecoPosition[gl_InvocationID] =" " vertPosition[gl_InvocationID];" " if(gl_InvocationID == 0)" " {" " gl_TessLevelInner[0] = tessLevel((" " vertDistance[0]+" " vertDistance[1]+" " vertDistance[2] " " )*0.333);" " gl_TessLevelOuter[0] = tessLevel((" " vertDistance[1]+" " vertDistance[2] " " )*0.5);" " gl_TessLevelOuter[1] = tessLevel((" " vertDistance[2]+" " vertDistance[0] " " )*0.5);" " gl_TessLevelOuter[2] = tessLevel((" " vertDistance[0]+" " vertDistance[1] " " )*0.5);" " }" "}" ); cs.Compile(); es.Source( "#version 330\n" "#extension ARB_tessellation_shader : enable\n" "layout(triangles, equal_spacing, ccw) in;" "const vec3 LightPosition = vec3(12.0, 10.0, 7.0);" "uniform mat4 ProjectionMatrix, CameraMatrix, ModelMatrix;" "in vec3 tecoPosition[];" "out vec3 teevNormal;" "out vec3 teevLightDir;" "void main(void)" "{" " vec3 p0 = gl_TessCoord.x * tecoPosition[0];" " vec3 p1 = gl_TessCoord.y * tecoPosition[1];" " vec3 p2 = gl_TessCoord.z * tecoPosition[2];" " vec4 tempPosition = vec4(normalize(p0+p1+p2), 0.0);" " teevNormal = (ModelMatrix * tempPosition).xyz;" " tempPosition.w = 1.0;" " tempPosition = ModelMatrix * tempPosition;" " teevLightDir = LightPosition - tempPosition.xyz;" " gl_Position = " " ProjectionMatrix *" " CameraMatrix *" " tempPosition;" "}" ); es.Compile(); gs.Source( "#version 330\n" "layout (triangles) in;" "layout (triangle_strip, max_vertices = 3) out;" "uniform vec3 Offset;" "uniform vec2 ViewportDimensions;" "in vec3 teevNormal[], teevLightDir[];" "noperspective out vec3 geomDist;" "flat out vec3 geomNormal;" "out vec3 geomColor;" "out vec3 geomLightDir;" "void main(void)" "{" " geomNormal = normalize(" " teevNormal[0]+" " teevNormal[1]+" " teevNormal[2]" " );" " vec2 ScreenPos[3];" " for(int i=0; i!=3; ++i)" " {" " ScreenPos[i] = " " ViewportDimensions*" " gl_in[i].gl_Position.xy/" " gl_in[i].gl_Position.w;" " }" " vec2 TmpVect[3];" " for(int i=0; i!=3; ++i)" " {" " TmpVect[i] = " " ScreenPos[(i+2)%3]-" " ScreenPos[(i+1)%3];" " }" " const vec3 EdgeMask[3] = vec3[3](" " vec3(1.0, 0.0, 0.0)," " vec3(0.0, 1.0, 0.0)," " vec3(0.0, 0.0, 1.0) " " );" " for(int i=0; i!=3; ++i)" " {" " float Dist = abs(" " TmpVect[(i+1)%3].x*TmpVect[(i+2)%3].y-" " TmpVect[(i+1)%3].y*TmpVect[(i+2)%3].x " " ) / length(TmpVect[i]);" " vec3 DistVect = vec3(Dist, Dist, Dist);" " gl_Position = gl_in[i].gl_Position;" " geomColor = normalize(abs(" " vec3(2.0, 2.0, 2.0)-" " teevNormal[i]-" " Offset" " ));" " geomLightDir = teevLightDir[i];" " geomDist = EdgeMask[i] * DistVect;" " EmitVertex();" " }" " EndPrimitive();" "}" ); gs.Compile(); fs.Source( "#version 330\n" "noperspective in vec3 geomDist;" "flat in vec3 geomNormal;" "in vec3 geomColor;" "in vec3 geomLightDir;" "out vec3 fragColor;" "void main(void)" "{" " float MinDist = min(min(geomDist.x,geomDist.y),geomDist.z);" " float EdgeAlpha = exp2(-pow(MinDist, 2.0));" " const float Ambient = 0.8;" " float Diffuse = max(dot(" " normalize(geomNormal)," " normalize(geomLightDir)" " ), 0.0);" " vec3 FaceColor = geomColor * (Diffuse + Ambient);" " const vec3 EdgeColor = vec3(0.0, 0.0, 0.0);" " fragColor = mix(FaceColor, EdgeColor, EdgeAlpha);" "}" ); fs.Compile(); prog.AttachShader(vs); prog.AttachShader(cs); prog.AttachShader(es); prog.AttachShader(gs); prog.AttachShader(fs); prog.Link(); prog.Use(); shape.Bind(); verts.Bind(Buffer::Target::Array); { std::vector<GLfloat> data; GLuint n_per_vertex = make_shape.Positions(data); Buffer::Data(Buffer::Target::Array, data); VertexAttribArray attr(prog, "Position"); attr.Setup<GLfloat>(n_per_vertex); attr.Enable(); indices.Bind(Buffer::Target::ElementArray); Buffer::Data(Buffer::Target::ElementArray, shape_indices); shape_indices.clear(); } // gl.ClearColor(0.8f, 0.8f, 0.8f, 0.0f); gl.ClearDepth(1.0f); gl.Enable(Capability::DepthTest); prog.Use(); }
TessellationExample(void) : shape_instr(make_shape.Instructions()) , shape_indices(make_shape.Indices()) , tess_level(prog) , viewport_dimensions(prog) , projection_matrix(prog) , camera_matrix(prog) , model_matrix(prog) { vs.Source( "#version 330\n" "in vec4 Position;" "void main(void)" "{" " gl_Position = Position;" "}" ); vs.Compile(); gs.Source( "#version 330\n" "layout (triangles) in;" "layout (triangle_strip, max_vertices = 48) out;" "const vec3 LightPosition = vec3(12.0, 10.0, 7.0);" "uniform mat4 ProjectionMatrix, CameraMatrix, ModelMatrix;" "uniform vec2 ViewportDimensions;" "uniform int TessLevel;" "noperspective out vec3 geomDist;" "flat out vec3 geomNormal;" "out vec3 geomColor;" "out vec3 geomLightDir;" "void make_triangle(vec4 p0, vec4 p1, vec4 p2)" "{" " vec3 n0 = (ModelMatrix*vec4(p0.xyz, 0)).xyz;" " vec3 n1 = (ModelMatrix*vec4(p1.xyz, 0)).xyz;" " vec3 n2 = (ModelMatrix*vec4(p2.xyz, 0)).xyz;" " vec4 m0 = ModelMatrix*p0;" " vec4 m1 = ModelMatrix*p1;" " vec4 m2 = ModelMatrix*p2;" " vec4 c0 = ProjectionMatrix*CameraMatrix*m0;" " vec4 c1 = ProjectionMatrix*CameraMatrix*m1;" " vec4 c2 = ProjectionMatrix*CameraMatrix*m2;" " vec2 s0 = ViewportDimensions * c0.xy/c0.w;" " vec2 s1 = ViewportDimensions * c1.xy/c1.w;" " vec2 s2 = ViewportDimensions * c2.xy/c2.w;" " vec2 v0 = s2 - s1;" " vec2 v1 = s0 - s2;" " vec2 v2 = s1 - s0;" " float d0 = abs(v1.x*v2.y-v1.y*v2.x)/length(v0);" " float d1 = abs(v2.x*v0.y-v2.y*v0.x)/length(v1);" " float d2 = abs(v0.x*v1.y-v0.y*v1.x)/length(v2);" " geomNormal = normalize(n0+n1+n2);" " gl_Position = c0;" " geomColor = normalize(abs(vec3(1, 1, 1) - n0));" " geomLightDir = LightPosition - m0.xyz;" " geomDist = vec3(d0, 0.0, 0.0);" " EmitVertex();" " gl_Position = c1;" " geomColor = normalize(abs(vec3(1, 1, 1) - n1));" " geomLightDir = LightPosition - m1.xyz;" " geomDist = vec3(0.0, d1, 0.0);" " EmitVertex();" " gl_Position = c2;" " geomColor = normalize(abs(vec3(1, 1, 1) - n2));" " geomLightDir = LightPosition - m2.xyz;" " geomDist = vec3(0.0, 0.0, d2);" " EmitVertex();" " EndPrimitive();" "}" "void do_tess_1(vec4 p_0, vec4 p_1, vec4 p_2, int l)" "{" " if(l == 1) make_triangle(p_0, p_1, p_2);" " else" " {" " vec4 p01 = vec4(normalize(p_0.xyz+p_1.xyz), 1.0);" " vec4 p12 = vec4(normalize(p_1.xyz+p_2.xyz), 1.0);" " vec4 p20 = vec4(normalize(p_2.xyz+p_0.xyz), 1.0);" " make_triangle(p_0, p01, p20);" " make_triangle(p01, p_1, p12);" " make_triangle(p20, p12, p_2);" " make_triangle(p01, p12, p20);" " }" "}" "void do_tess_0(vec4 p_0, vec4 p_1, vec4 p_2, int l)" "{" " if(l == 0) make_triangle(p_0, p_1, p_2);" " else" " {" " vec4 p01 = vec4(normalize(p_0.xyz+p_1.xyz), 1.0);" " vec4 p12 = vec4(normalize(p_1.xyz+p_2.xyz), 1.0);" " vec4 p20 = vec4(normalize(p_2.xyz+p_0.xyz), 1.0);" " do_tess_1(p_0, p01, p20, l);" " do_tess_1(p01, p_1, p12, l);" " do_tess_1(p20, p12, p_2, l);" " do_tess_1(p01, p12, p20, l);" " }" "}" "void main(void)" "{" " do_tess_0(" " gl_in[0].gl_Position," " gl_in[1].gl_Position," " gl_in[2].gl_Position," " TessLevel" " );" "}" ); gs.Compile(); fs.Source( "#version 330\n" "noperspective in vec3 geomDist;" "flat in vec3 geomNormal;" "in vec3 geomColor;" "in vec3 geomLightDir;" "out vec3 fragColor;" "void main(void)" "{" " float MinDist = min(min(geomDist.x,geomDist.y),geomDist.z);" " float EdgeAlpha = exp2(-pow(MinDist, 2.0));" " const float Ambient = 0.7;" " float Diffuse = max(dot(" " normalize(geomNormal)," " normalize(geomLightDir)" " )+0.1, 0.0)*1.4;" " vec3 FaceColor = geomColor * (Diffuse + Ambient);" " const vec3 EdgeColor = vec3(0.0, 0.0, 0.0);" " fragColor = mix(FaceColor, EdgeColor, EdgeAlpha);" "}" ); fs.Compile(); prog.AttachShader(vs); prog.AttachShader(gs); prog.AttachShader(fs); prog.Link(); prog.Use(); tess_level.BindTo("TessLevel"); viewport_dimensions.BindTo("ViewportDimensions"); projection_matrix.BindTo("ProjectionMatrix"); camera_matrix.BindTo("CameraMatrix"); model_matrix.BindTo("ModelMatrix"); shape.Bind(); verts.Bind(Buffer::Target::Array); { std::vector<GLfloat> data; GLuint n_per_vertex = make_shape.Positions(data); Buffer::Data(Buffer::Target::Array, data); VertexArrayAttrib attr(prog, "Position"); attr.Setup<GLfloat>(n_per_vertex); attr.Enable(); indices.Bind(Buffer::Target::ElementArray); Buffer::Data(Buffer::Target::ElementArray, shape_indices); shape_indices.clear(); } // gl.ClearColor(0.7f, 0.7f, 0.7f, 0.0f); gl.ClearDepth(1.0f); gl.Enable(Capability::DepthTest); prog.Use(); }