Пример #1
0
	DOFExample(const ExampleParams& params)
	 : face_instr(make_cube.Instructions())
	 , edge_instr(make_cube.EdgeInstructions())
	 , face_indices(make_cube.Indices())
	 , edge_indices(make_cube.EdgeIndices())
	 , cube_matrices(MakeCubeMatrices(100, 10.0))
	 , viewport_width(dof_prog, "ViewportWidth")
	 , viewport_height(dof_prog, "ViewportHeight")
	 , projection_matrix(main_prog, "ProjectionMatrix")
	 , camera_matrix(main_prog, "CameraMatrix")
	 , model_matrix(main_prog, "ModelMatrix")
	 , ambient_color(main_prog, "AmbientColor")
	 , diffuse_color(main_prog, "DiffuseColor")
	 , focus_depth(dof_prog, "FocusDepth")
	 , color_tex(Texture::Target::Rectangle)
	 , depth_tex(Texture::Target::Rectangle)
	 , width(800)
	 , height(600)
	{
		main_vs.Source(
			"#version 330\n"
			"uniform mat4 ProjectionMatrix, CameraMatrix, ModelMatrix;"
			"uniform vec3 LightPos;"
			"in vec4 Position;"
			"in vec3 Normal;"
			"out vec3 vertLightDir;"
			"out vec3 vertNormal;"
			"void main(void)"
			"{"
			"	gl_Position = ModelMatrix * Position;"
			"	vertLightDir = normalize(LightPos - gl_Position.xyz);"
			"	vertNormal = normalize(mat3(ModelMatrix)*Normal);"
			"	gl_Position = ProjectionMatrix * CameraMatrix * gl_Position;"
			"}"
		);
		// compile it
		main_vs.Compile();

		// set the fragment shader source
		main_fs.Source(
			"#version 330\n"
			"uniform vec3 AmbientColor, DiffuseColor;"
			"in vec3 vertLightDir;"
			"in vec3 vertNormal;"
			"out vec4 fragColor;"
			"void main(void)"
			"{"
			"	float d = max(dot(vertLightDir,vertNormal),0.0);"
			"	float e = sin("
			"		10.0*vertLightDir.x + "
			"		20.0*vertLightDir.y + "
			"		25.0*vertLightDir.z   "
			"	)*0.9;"
			"	fragColor = vec4("
			"		mix(AmbientColor, DiffuseColor, d+e),"
			"		1.0"
			"	);"
			"}"
		);
		// compile it
		main_fs.Compile();

		// attach the shaders to the program
		main_prog.AttachShader(main_vs);
		main_prog.AttachShader(main_fs);
		// link and use it
		main_prog.Link();
		main_prog.Use();

		// bind the VAO for the cube
		cube.Bind();

		// bind the VBO for the cube vertices
		positions.Bind(Buffer::Target::Array);
		{
			std::vector<GLfloat> data;
			GLuint n_per_vertex = make_cube.Positions(data);
			// upload the data
			Buffer::Data(Buffer::Target::Array, data);
			// setup the vertex attribs array for the vertices
			VertexAttribArray attr(main_prog, "Position");
			attr.Setup<GLfloat>(n_per_vertex);
			attr.Enable();
		}

		// bind the VBO for the cube normals
		normals.Bind(Buffer::Target::Array);
		{
			std::vector<GLfloat> data;
			GLuint n_per_vertex = make_cube.Normals(data);
			Buffer::Data(Buffer::Target::Array, data);
			VertexAttribArray attr(main_prog, "Normal");
			attr.Setup<GLfloat>(n_per_vertex);
			attr.Enable();
		}

		Uniform<Vec3f>(main_prog, "LightPos").Set(30.0, 50.0, 20.0);

		dof_vs.Source(
			"#version 330\n"
			"uniform uint ViewportWidth, ViewportHeight;"
			"in vec4 Position;"
			"out vec2 vertTexCoord;"
			"void main(void)"
			"{"
			"	gl_Position = Position;"
			"	vertTexCoord = vec2("
			"		(Position.x*0.5 + 0.5)*ViewportWidth,"
			"		(Position.y*0.5 + 0.5)*ViewportHeight"
			"	);"
			"}"
		);
		dof_vs.Compile();

		dof_fs.Source(
			"#version 330\n"
			"uniform sampler2DRect ColorTex;"
			"uniform sampler2DRect DepthTex;"
			"uniform float FocusDepth;"
			"uniform uint SampleMult;"
			"in vec2 vertTexCoord;"
			"out vec4 fragColor;"
			"const float strength = 16.0;"
			"void main(void)"
			"{"
			"	float fragDepth = texture(DepthTex, vertTexCoord).r;"
			"	vec3 color = texture(ColorTex, vertTexCoord).rgb;"
			"	float of = abs(fragDepth - FocusDepth);"
			"	int nsam = int(of*SampleMult);"
			"	float inv_nsam = 1.0 / (1.0 + nsam);"
			"	float astep = (3.14151*4.0)/nsam;"
			"	for(int i=0; i!=nsam; ++i)"
			"	{"
			"		float a = i*astep;"
			"		float d = sqrt(i*inv_nsam);"
			"		float sx = cos(a)*of*strength*d;"
			"		float sy = sin(a)*of*strength*d;"
			"		vec2 samTexCoord = vertTexCoord + vec2(sx, sy) + noise2(vec2(sx, sy));"
			"		color += texture(ColorTex, samTexCoord).rgb;"
			"	}"
			"	fragColor = vec4(color * inv_nsam , 1.0);"
			"}"
		);
		dof_fs.Compile();

		dof_prog.AttachShader(dof_vs);
		dof_prog.AttachShader(dof_fs);
		dof_prog.Link();
		dof_prog.Use();

		GLuint sample_mult = params.HighQuality()?512:128;
		Uniform<GLuint>(dof_prog, "SampleMult") = sample_mult;

		// bind the VAO for the screen
		screen.Bind();

		corners.Bind(Buffer::Target::Array);
		{
			GLfloat screen_verts[8] = {
				-1.0f, -1.0f,
				-1.0f,  1.0f,
				 1.0f, -1.0f,
				 1.0f,  1.0f
			};
			Buffer::Data(Buffer::Target::Array, 8, screen_verts);
			VertexAttribArray attr(dof_prog, "Position");
			attr.Setup<Vec2f>();
			attr.Enable();
		}

		Texture::Active(0);
		UniformSampler(dof_prog, "ColorTex").Set(0);
		{
			auto bound_tex = Bind(color_tex, Texture::Target::Rectangle);
			bound_tex.MinFilter(TextureMinFilter::Linear);
			bound_tex.MagFilter(TextureMagFilter::Linear);
			bound_tex.WrapS(TextureWrap::ClampToEdge);
			bound_tex.WrapT(TextureWrap::ClampToEdge);
			bound_tex.Image2D(
				0,
				PixelDataInternalFormat::RGB,
				width, height,
				0,
				PixelDataFormat::RGB,
				PixelDataType::UnsignedByte,
				nullptr
			);
		}

		Texture::Active(1);
		UniformSampler(dof_prog, "DepthTex").Set(1);
		{
			auto bound_tex = Bind(depth_tex, Texture::Target::Rectangle);
			bound_tex.MinFilter(TextureMinFilter::Linear);
			bound_tex.MagFilter(TextureMagFilter::Linear);
			bound_tex.WrapS(TextureWrap::ClampToEdge);
			bound_tex.WrapT(TextureWrap::ClampToEdge);
			bound_tex.Image2D(
				0,
				PixelDataInternalFormat::DepthComponent,
				width, height,
				0,
				PixelDataFormat::DepthComponent,
				PixelDataType::Float,
				nullptr
			);
		}

		{
			auto bound_fbo = Bind(
				fbo,
				Framebuffer::Target::Draw
			);
			bound_fbo.AttachTexture(
				FramebufferAttachment::Color,
				color_tex,
				0
			);
			bound_fbo.AttachTexture(
				FramebufferAttachment::Depth,
				depth_tex,
				0
			);
		}

		//
		gl.ClearColor(0.9f, 0.9f, 0.9f, 0.0f);
		gl.ClearDepth(1.0f);
		gl.Enable(Capability::DepthTest);
		gl.DepthFunc(CompareFn::LEqual);
		gl.Enable(Capability::LineSmooth);
		gl.BlendFunc(BlendFn::SrcAlpha, BlendFn::OneMinusSrcAlpha);
	}
Пример #2
0
	ShadowVolExample(const ExampleParams& params)
	 : shape_instr(make_shape.Instructions())
	 , shape_indices(make_shape.Indices())
	 , shape_vs(ShaderType::Vertex, ObjectDesc("Shape vertex"))
	 , depth_vs(ShaderType::Vertex, ObjectDesc("Depth vertex"))
	 , light_vs(ShaderType::Vertex, ObjectDesc("Light vertex"))
	 , depth_gs(ShaderType::Geometry, ObjectDesc("Depth geometry"))
	 , light_gs(ShaderType::Geometry, ObjectDesc("Light geometry"))
	 , shape_fs(ShaderType::Fragment, ObjectDesc("Shape fragment"))
	 , depth_fs(ShaderType::Fragment, ObjectDesc("Depthfragment"))
	 , light_fs(ShaderType::Fragment, ObjectDesc("Light fragment"))
	 , shape_prog(ObjectDesc("Shape"))
	 , depth_prog(ObjectDesc("Depth"))
	 , light_prog(ObjectDesc("Light"))
	 , tex_side(128)
	 , sample_count(params.HighQuality()?1024:128)
	{
		shape_vs.Source(
			"#version 330\n"
			"uniform mat4 ProjectionMatrix, CameraMatrix, ModelMatrix;"
			"in vec4 Position;"
			"in vec3 Normal;"
			"in vec2 TexCoord;"
			"out vec3 vertNormal;"
			"out vec3 vertLightDir;"
			"out vec3 vertLightRefl;"
			"out vec3 vertViewDir;"
			"out vec3 vertViewRefl;"
			"uniform vec3 LightPos;"
			"void main(void)"
			"{"
			"	gl_Position = ModelMatrix * Position;"
			"	vertNormal = mat3(ModelMatrix)*Normal;"
			"	vertLightDir = LightPos - gl_Position.xyz;"
			"	vertLightRefl = reflect("
			"		-normalize(vertLightDir),"
			"		normalize(vertNormal)"
			"	);"
			"	vertViewDir = (vec4(0.0, 0.0, 1.0, 1.0)* CameraMatrix).xyz;"
			"	vertViewRefl = reflect("
			"		normalize(vertViewDir),"
			"		normalize(vertNormal)"
			"	);"
			"	gl_Position = ProjectionMatrix * CameraMatrix * gl_Position;"
			"}"
		);
		shape_vs.Compile();

		shape_fs.Source(
			"#version 330\n"
			"in vec3 vertNormal;"
			"in vec3 vertLightDir;"
			"in vec3 vertLightRefl;"
			"in vec3 vertViewDir;"
			"in vec3 vertViewRefl;"
			"out vec4 fragColor;"
			"void main(void)"
			"{"
			"	float l = length(vertLightDir);"
			"	float d = dot("
			"		normalize(vertNormal), "
			"		normalize(vertLightDir)"
			"	) / l;"
			"	float s = dot("
			"		normalize(vertLightRefl),"
			"		normalize(vertViewDir)"
			"	);"
			"	vec3 ambi = vec3(0.6, 0.3, 0.5);"
			"	vec3 diff = vec3(0.9, 0.7, 0.8);"
			"	vec3 spec = vec3(1.0, 0.9, 0.95);"
			"	fragColor = vec4("
			"		ambi * 0.3 + "
			"		diff * 0.7 * max(d, 0.0) + "
			"		spec * pow(max(s, 0.0), 64), "
			"		1.0"
			"	);"
			"}"
		);
		shape_fs.Compile();

		shape_prog.AttachShader(shape_vs);
		shape_prog.AttachShader(shape_fs);
		shape_prog.Link();

		depth_vs.Source(
			"#version 330\n"
			"uniform mat4 ModelMatrix;"
			"uniform vec3 LightPos;"
			"in vec4 Position;"
			"void main(void)"
			"{"
			"	gl_Position = "
			"		mat4("
			"			1.0, 0.0, 0.0, -LightPos.x,"
			"			0.0, 1.0, 0.0, -LightPos.y,"
			"			0.0, 0.0, 1.0, -LightPos.z,"
			"			0.0, 0.0, 0.0,  1.0"
			"		)*"
			"		ModelMatrix *"
			"		mat4("
			"			10.0,  0.0,  0.0,  0.0,"
			"			 0.0, 10.0,  0.0,  0.0,"
			"			 0.0,  0.0, 10.0,  0.0,"
			"			 0.0,  0.0,  0.0,  1.0 "
			"		)*"
			"		Position;"
			"}"
		);
		depth_vs.Compile();

		depth_gs.Source(
			"#version 330\n"
			"layout(triangles) in;"
			"layout(triangle_strip, max_vertices = 18) out;"

			"uniform mat4 ProjectionMatrix;"

			"const mat4 CubeFaceMatrix[6] = mat4[6]("
			"	mat4("
			"		 0.0,  0.0, -1.0,  0.0,"
			"		 0.0, -1.0,  0.0,  0.0,"
			"		-1.0,  0.0,  0.0,  0.0,"
			"		 0.0,  0.0,  0.0,  1.0 "
			"	), mat4("
			"		 0.0,  0.0,  1.0,  0.0,"
			"		 0.0, -1.0,  0.0,  0.0,"
			"		 1.0,  0.0,  0.0,  0.0,"
			"		 0.0,  0.0,  0.0,  1.0 "
			"	), mat4("
			"		 1.0,  0.0,  0.0,  0.0,"
			"		 0.0,  0.0, -1.0,  0.0,"
			"		 0.0,  1.0,  0.0,  0.0,"
			"		 0.0,  0.0,  0.0,  1.0 "
			"	), mat4("
			"		 1.0,  0.0,  0.0,  0.0,"
			"		 0.0,  0.0,  1.0,  0.0,"
			"		 0.0, -1.0,  0.0,  0.0,"
			"		 0.0,  0.0,  0.0,  1.0 "
			"	), mat4("
			"		 1.0,  0.0,  0.0,  0.0,"
			"		 0.0, -1.0,  0.0,  0.0,"
			"		 0.0,  0.0, -1.0,  0.0,"
			"		 0.0,  0.0,  0.0,  1.0 "
			"	), mat4("
			"		-1.0,  0.0,  0.0,  0.0,"
			"		 0.0, -1.0,  0.0,  0.0,"
			"		 0.0,  0.0,  1.0,  0.0,"
			"		 0.0,  0.0,  0.0,  1.0 "
			"	)"
			");"

			"void main(void)"
			"{"
			"	for(gl_Layer=0; gl_Layer!=6; ++gl_Layer)"
			"	{"
			"		for(int i=0; i!=3; ++i)"
			"		{"
			"			gl_Position = "
			"				ProjectionMatrix *"
			"				CubeFaceMatrix[gl_Layer]*"
			"				gl_in[i].gl_Position;"
			"			EmitVertex();"
			"		}"
			"		EndPrimitive();"
			"	}"
			"}"
		);
		depth_gs.Compile();

		depth_fs.Source(
			"#version 330\n"
			"void main(void)"
			"{"
			"	gl_FragDepth = gl_FragCoord.z;"
			"}"
		);
		depth_fs.Compile();

		depth_prog.AttachShader(depth_vs);
		depth_prog.AttachShader(depth_gs);
		depth_prog.AttachShader(depth_fs);
		depth_prog.Link();
		depth_prog.Use();

		Uniform<Mat4f>(depth_prog, "ProjectionMatrix").Set(
			CamMatrixf::PerspectiveX(
				RightAngles(1.0),
				1.0,
				0.1,
				10.0
			)
		);

		// bind the VAO for the shape
		shape.Bind();

		shape_positions.Bind(Buffer::Target::Array);
		{
			std::vector<GLfloat> data;
			GLuint n_per_vertex = make_shape.Positions(data);
			Buffer::Data(Buffer::Target::Array, data);

			VertexAttribSlot location;
			if(VertexAttribArray::QueryCommonLocation(
				"Position",
				location,
				shape_prog,
				depth_prog
			))
			{
				VertexAttribArray shape_attr(location);
				shape_attr.Setup(n_per_vertex, DataType::Float);
				shape_attr.Enable();
			}
			else assert(!"Inconsistent 'Position' location");
		}

		shape_normals.Bind(Buffer::Target::Array);
		{
			std::vector<GLfloat> data;
			GLuint n_per_vertex = make_shape.Normals(data);
			Buffer::Data(Buffer::Target::Array, data);

			shape_prog.Use();
			VertexAttribArray attr(shape_prog, "Normal");
			attr.Setup(n_per_vertex, DataType::Float);
			attr.Enable();
		}

		light_vs.Source(
			"#version 330\n"
			"in vec3 Position;"
			"out float vertZOffs;"
			"uniform vec3 LightPos;"
			"uniform int SampleCount;"
			"void main(void)"
			"{"
			"	float hp = (SampleCount-1) * 0.5;"
			"	vertZOffs = (gl_InstanceID - hp)/hp;"
			"	gl_Position = vec4(Position + LightPos, 1.0);"
			"}"
		);
		light_vs.Compile();

		light_gs.Source(
			"#version 330\n"
			"layout(points) in;"
			"layout(triangle_strip, max_vertices = 4) out;"
			"in float vertZOffs[];"
			"out vec4 geomPosition;"
			"uniform mat4 CameraMatrix, ProjectionMatrix;"
			"uniform vec3 ViewX, ViewY, ViewZ;"
			"uniform float LightVolSize;"
			"void main(void)"
			"{"
			"	float zo = vertZOffs[0];"
			"	float yo[2] = float[2](-1.0, 1.0);"
			"	float xo[2] = float[2](-1.0, 1.0);"
			"	for(int j=0;j!=2;++j)"
			"	for(int i=0;i!=2;++i)"
			"	{"
			"		geomPosition = vec4("
			"			gl_in[0].gl_Position.xyz+"
			"			ViewX * xo[i] * LightVolSize+"
			"			ViewY * yo[j] * LightVolSize+"
			"			ViewZ * zo    * LightVolSize,"
			"			1.0"
			"		);"
			"		gl_Position = "
			"			ProjectionMatrix *"
			"			CameraMatrix *"
			"			geomPosition;"
			"		EmitVertex();"
			"	}"
			"	EndPrimitive();"
			"}"
		);
		light_gs.Compile();

		light_fs.Source(
			"#version 330\n"
			"in vec4 geomPosition;"
			"out vec4 fragColor;"
			"uniform samplerCubeShadow ShadowMap;"
			"uniform int SampleCount;"
			"uniform vec3 LightPos;"
			"void main(void)"
			"{"
			"	vec3 LightDir = geomPosition.xyz - LightPos;"
			"	vec4 ShadowCoord = vec4("
			"		normalize(LightDir),"
			"		length(LightDir)"
			"	);"
			"	float s = texture(ShadowMap, ShadowCoord);"
			"	float alpha = s / (SampleCount * pow(length(LightDir), 2));"
			"	fragColor = vec4(1.0, 1.0, 1.0, alpha);"
			"}"
		);
		light_fs.Compile();

		light_prog.AttachShader(light_vs);
		light_prog.AttachShader(light_gs);
		light_prog.AttachShader(light_fs);
		light_prog.Link();
		light_prog.Use();

		// bind the VAO for the light volume
		light.Bind();

		// bind the VBO for the light volume plane positions
		light_positions.Bind(Buffer::Target::Array);
		{
			GLfloat position[3] = {0.0, 0.0, 0.0};
			Buffer::Data(Buffer::Target::Array, 3, position);
			VertexAttribArray attr(light_prog, "Position");
			attr.Setup(3, DataType::Float);
			attr.Enable();
		}

		Uniform<GLint>(light_prog, "SampleCount").Set(sample_count);
		Uniform<GLfloat>(light_prog, "LightVolSize").Set(4);
		UniformSampler(light_prog, "ShadowMap").Set(0);

		// Setup the texture and the offscreen FBO
		Texture::Active(0);
		{
			auto bound_tex = Bind(depth_tex, Texture::Target::CubeMap);
			bound_tex.MinFilter(TextureMinFilter::Linear);
			bound_tex.MagFilter(TextureMagFilter::Linear);
			bound_tex.WrapS(TextureWrap::ClampToEdge);
			bound_tex.WrapT(TextureWrap::ClampToEdge);
			bound_tex.WrapR(TextureWrap::ClampToEdge);
			bound_tex.CompareFunc(CompareFunction::LEqual);
			bound_tex.CompareMode(
				TextureCompareMode::CompareRefToTexture
			);

			for(int i=0; i!=6; ++i)
			{
				Texture::Image2D(
					Texture::CubeMapFace(i),
					0,
					PixelDataInternalFormat::DepthComponent,
					tex_side, tex_side,
					0,
					PixelDataFormat::DepthComponent,
					PixelDataType::Float,
					nullptr
				);
			}

			auto bound_fbo = Bind(
				depth_fbo,
				Framebuffer::Target::Draw
			);
			bound_fbo.AttachTexture(
				FramebufferAttachment::Depth,
				depth_tex,
				0
			);
		}
		//
		gl.ClearColor(0.2f, 0.05f, 0.1f, 0.0f);
		gl.ClearDepth(1.0f);
		gl.Enable(Capability::DepthTest);

		gl.Enable(Capability::CullFace);
		gl.FrontFace(make_shape.FaceWinding());
		gl.CullFace(Face::Back);

		gl.BlendFunc(BlendFunction::SrcAlpha, BlendFunction::One);
	}