Пример #1
0
	TessellationExample(void)
	 : shape_instr(make_shape.Instructions())
	 , shape_indices(make_shape.Indices())
	 , tess_level(prog, "TessLevel")
	 , viewport_dimensions(prog, "ViewportDimensions")
	 , projection_matrix(prog, "ProjectionMatrix")
	 , camera_matrix(prog, "CameraMatrix")
	 , model_matrix(prog, "ModelMatrix")
	{
		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();

		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.7f, 0.7f, 0.7f, 0.0f);
		gl.ClearDepth(1.0f);
		gl.Enable(Capability::DepthTest);

		prog.Use();
	}
Пример #2
0
	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 410\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 410\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 410\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 410\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 410\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(n_per_vertex, DataType::Float);
			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();
	}