Beispiel #1
0
	void RenderOffscreen(double time)
	{
		fbo.Bind();

		gl.Clear().ColorBuffer().DepthBuffer();

		gl.BlendFunc(BlendFn::One, BlendFn::One);
		gl.Enable(Capability::Blend);
		gl.Enable(Capability::DepthTest);

		draw_prog.Use();
		draw_prog.camera_matrix.Set(
			CamMatrixf::Orbiting(
				Vec3f(),
				27.0,
				Degrees(time * 23),
				Degrees(SineWave(time / 23.0) * 80)
			)
		);

		cube.Use();
		cube.Draw(n*n*n);

		gl.Disable(Capability::DepthTest);
		gl.Disable(Capability::Blend);

		fbo.Unbind();
	}
Beispiel #2
0
	SortingExample(void)
	 : gl()
	 , particles(4096)
	 , dist_proc(particles)
	 , sort_proc(particles)
	 , draw_proc(particles)
	{
		gl.ClearColor(0.3f, 0.3f, 0.3f, 0.0f);
		gl.Enable(Capability::DepthTest);
		gl.BlendFunc(BlendFn::SrcAlpha, BlendFn::OneMinusSrcAlpha);
	}
	SmokeExample(void)
	 : emitters()
	 , projection_matrix(prog, "ProjectionMatrix")
	 , camera_matrix(prog, "CameraMatrix")
	{
		emitters.push_back(
			ParticleSystem(
				ListOf<Vec3f>
					(Vec3f(-20.0f, -10.0f,  10.0f))
					(Vec3f( 20.0f,   0.0f, -20.0f))
					(Vec3f( 20.0f,  10.0f,  20.0f))
					(Vec3f(-20.0f,   0.0f, -10.0f))
				.As<std::vector<Vec3f>>(), 5.0, 200.0
			)
		);
		emitters.push_back(
			ParticleSystem(
				ListOf<Vec3f>
					(Vec3f( 30.0f,   0.0f,   0.0f))
					(Vec3f(-30.0f,   0.0f,   0.0f))
					(Vec3f(-20.0f,  20.0f,   0.0f))
					(Vec3f( 20.0f, -10.0f,   0.0f))
				.As<std::vector<Vec3f>>(), 3.0, 200.0
			)
		);
		emitters.push_back(
			ParticleSystem(
				ListOf<Vec3f>
					(Vec3f(  5.0f,  20.0f,  20.0f))
					(Vec3f( -5.0f,  20.0f, -20.0f))
					(Vec3f(  5.0f, -20.0f, -20.0f))
					(Vec3f( -5.0f, -20.0f,  20.0f))
				.As<std::vector<Vec3f>>(), 20.0, 100.0
			)
		);
		// Set the vertex shader source
		vs.Source(
			"#version 330\n"
			"uniform mat4 CameraMatrix;"
			"in vec4 Position;"
			"in float Age;"
			"out float vertAge;"
			"void main(void)"
			"{"
			"	gl_Position = CameraMatrix * Position;"
			"	vertAge = Age;"
			"}"
		);
		// compile it
		vs.Compile();

		// Set the geometry shader source
		gs.Source(
			"#version 330\n"
			"layout(points) in;"
			"layout(triangle_strip, max_vertices = 4) out;"
			"uniform mat4 ProjectionMatrix;"
			"in float vertAge[];"
			"out float geomAge;"
			"void main(void)"
			"{"
			"	if(vertAge[0] > 1.0) return;"
			"	float s = 0.5;"
			"	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)"
			"	{"
			"		float xoffs = xo[i]*(1.0+vertAge[0])*s;"
			"		float yoffs = yo[j]*(1.0+vertAge[0])*s;"
			"		gl_Position = ProjectionMatrix * vec4("
			"			gl_in[0].gl_Position.x-xoffs,"
			"			gl_in[0].gl_Position.y-yoffs,"
			"			gl_in[0].gl_Position.z,"
			"			1.0"
			"		);"
			"		geomAge = vertAge[0];"
			"		EmitVertex();"
			"	}"
			"	EndPrimitive();"
			"}"
		);
		// compile it
		gs.Compile();

		// set the fragment shader source
		fs.Source(
			"#version 330\n"
			"in float geomAge;"
			"out vec4 fragColor;"
			"void main(void)"
			"{"
			"	vec3 Color1 = vec3(1.0, 0.5, 0.5);"
			"	vec3 Color2 = vec3(0.3, 0.1, 0.1);"
			"	fragColor = vec4("
			"		mix(Color1, Color2, geomAge),"
			"		1.0 - geomAge"
			"	);"
			"}"
		);
		// compile it
		fs.Compile();

		// attach the shaders to the program
		prog.AttachShader(vs);
		prog.AttachShader(gs);
		prog.AttachShader(fs);
		// link and use it
		prog.Link();
		prog.Use();

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

		// bind the VBO for the particle positions
		pos_buf.Bind(Buffer::Target::Array);
		{
			Buffer::Data(Buffer::Target::Array, positions, BufferUsage::DynamicDraw);
			VertexAttribArray attr(prog, "Position");
			attr.Setup(3, DataType::Float);
			attr.Enable();
		}

		// bind the VBO for the particle ages
		age_buf.Bind(Buffer::Target::Array);
		{
			Buffer::Data(Buffer::Target::Array, ages, BufferUsage::DynamicDraw);
			VertexAttribArray attr(prog, "Age");
			attr.Setup(1, DataType::Float);
			attr.Enable();
		}
		//
		gl.ClearColor(0.9f, 0.9f, 0.9f, 0.0f);
		gl.ClearDepth(1.0f);
		gl.Enable(Capability::DepthTest);
		gl.Enable(Capability::Blend);
		gl.BlendFunc(BlendFn::SrcAlpha, BlendFn::OneMinusSrcAlpha);
	}
	GlassAndMetalExample(void)
	 : transf_prog()
	 , metal_prog()
	 , plane(transf_prog, shapes::Plane(Vec3f(9, 0, 0), Vec3f(0, 0,-9)))
	 , torus(transf_prog, shapes::WickerTorus())
	 , shadow_tex_side(1024)
	{
		NoProgram().Use();

		shadow_pp.Bind();
		shadow_pp.UseStages(transf_prog).Vertex();
		shadow_pp.UseStages(shadow_prog).Fragment();

		light_pp.Bind();
		light_pp.UseStages(transf_prog).Vertex();
		light_pp.UseStages(light_prog).Fragment();

		glass_pp.Bind();
		glass_pp.UseStages(transf_prog).Vertex();
		glass_pp.UseStages(glass_prog).Fragment();

		metal_pp.Bind();
		metal_pp.UseStages(transf_prog).Vertex();
		metal_pp.UseStages(metal_prog).Fragment();

		Texture::Active(0);
		metal_prog.metal_tex.Set(0);
		gl.Bound(Texture::Target::_2D, metal_texture)
			.MinFilter(TextureMinFilter::LinearMipmapLinear)
			.MagFilter(TextureMagFilter::Linear)
			.WrapS(TextureWrap::Repeat)
			.WrapT(TextureWrap::Repeat)
			.Image2D(
				images::BrushedMetalUByte(
					512, 512,
					5120,
					-3, +3,
					32, 128
				)
			).GenerateMipmap();

		Texture::Active(1);
		metal_prog.frame_shadow_tex.Set(1);
		glass_prog.frame_shadow_tex.Set(1);

		gl.Bound(Texture::Target::_2D, frame_shadow_tex)
			.MinFilter(TextureMinFilter::Linear)
			.MagFilter(TextureMagFilter::Linear)
			.WrapS(TextureWrap::ClampToEdge)
			.WrapT(TextureWrap::ClampToEdge)
			.CompareMode(TextureCompareMode::CompareRefToTexture)
			.Image2D(
				0,
				PixelDataInternalFormat::DepthComponent32,
				shadow_tex_side, shadow_tex_side,
				0,
				PixelDataFormat::DepthComponent,
				PixelDataType::Float,
				nullptr
			);

		gl.Bound(Framebuffer::Target::Draw, frame_shadow_fbo)
			.AttachTexture(
				FramebufferAttachment::Depth,
				frame_shadow_tex,
				0
			);

		Texture::Active(2);
		metal_prog.glass_shadow_tex.Set(2);

		gl.Bound(Texture::Target::_2D, glass_shadow_tex)
			.MinFilter(TextureMinFilter::Linear)
			.MagFilter(TextureMagFilter::Linear)
			.WrapS(TextureWrap::ClampToEdge)
			.WrapT(TextureWrap::ClampToEdge)
			.Image2D(
				0,
				PixelDataInternalFormat::RGBA,
				shadow_tex_side, shadow_tex_side,
				0,
				PixelDataFormat::RGBA,
				PixelDataType::UnsignedByte,
				nullptr
			);

		gl.Bound(Framebuffer::Target::Draw, glass_shadow_fbo)
			.AttachTexture(
				FramebufferAttachment::Color,
				glass_shadow_tex,
				0
			);

		gl.ClearDepth(1.0f);
		gl.Enable(Capability::DepthTest);
		gl.Enable(Capability::CullFace);

		gl.BlendFunc(BlendFn::SrcAlpha, BlendFn::OneMinusSrcAlpha);

		gl.PolygonOffset(1.0, 1.0);

	}
Beispiel #5
0
	SketchExample(void)
	 : transf_prog()
	 , sketch_prog()
	 , plane(
		transf_prog,
		shapes::Plane(
			Vec3f(0, 0, 0),
			Vec3f(9, 0, 0),
			Vec3f(0, 0,-9),
			9, 9
		)
	), torus(transf_prog, shapes::WickerTorus())
	 , sketch_tex_layers(8)
	 , shadow_tex_side(1024)
	{

		NoProgram().Use();

		shadow_pp.Bind();
		shadow_pp.UseStages(transf_prog).Vertex();
		shadow_pp.UseStages(shadow_prog).Fragment();

		sketch_pp.Bind();
		sketch_pp.UseStages(transf_prog).Vertex();
		sketch_pp.UseStages(sketch_prog).Fragment();

		line_pp.Bind();
		line_pp.UseStages(transf_prog).Vertex();
		line_pp.UseStages(line_prog).Geometry().Fragment();

		Texture::Active(0);
		sketch_prog.sketch_tex.Set(0);
		{
			auto bound_tex = gl.Bound(Texture::Target::_3D, sketch_texture);

			for(GLuint i=0; i<sketch_tex_layers; ++i)
			{
				auto image = images::BrushedMetalUByte(
					512, 512,
					64 + i*128,
					-(2+i*4), +(2+i*4),
					64, 256-i*4
				);
				if(i == 0)
				{
					bound_tex.Image3D(
						0,
						PixelDataInternalFormat::RGB,
						image.Width(),
						image.Height(),
						sketch_tex_layers,
						0,
						image.Format(),
						image.Type(),
						nullptr
					);
				}
				bound_tex.SubImage3D(
					0,
					0, 0, i,
					image.Width(),
					image.Height(),
					1,
					image.Format(),
					image.Type(),
					image.RawData()
				);
			}
			bound_tex.GenerateMipmap();
			bound_tex.MinFilter(TextureMinFilter::LinearMipmapLinear);
			bound_tex.MagFilter(TextureMagFilter::Linear);
			bound_tex.WrapS(TextureWrap::Repeat);
			bound_tex.WrapT(TextureWrap::Repeat);
			bound_tex.WrapR(TextureWrap::ClampToEdge);
		}

		Texture::Active(1);
		sketch_prog.shadow_tex.Set(1);

		gl.Bound(Texture::Target::_2D, shadow_tex)
			.MinFilter(TextureMinFilter::Linear)
			.MagFilter(TextureMagFilter::Linear)
			.WrapS(TextureWrap::ClampToEdge)
			.WrapT(TextureWrap::ClampToEdge)
			.CompareMode(TextureCompareMode::CompareRefToTexture)
			.Image2D(
				0,
				PixelDataInternalFormat::DepthComponent32,
				shadow_tex_side, shadow_tex_side,
				0,
				PixelDataFormat::DepthComponent,
				PixelDataType::Float,
				nullptr
			);

		gl.Bound(Framebuffer::Target::Draw, frame_shadow_fbo)
			.AttachTexture(
				FramebufferAttachment::Depth,
				shadow_tex,
				0
			);

		gl.ClearDepth(1.0f);
		gl.Enable(Capability::DepthTest);
		gl.Enable(Capability::CullFace);

		gl.DepthFunc(CompareFn::LEqual);
		gl.BlendFunc(BlendFn::SrcAlpha, BlendFn::OneMinusSrcAlpha);

		gl.PolygonOffset(1.0, 1.0);
		gl.LineWidth(1.5);

	}
Beispiel #6
0
    CloudExample(const ExampleParams& params)
        : sphere_instr(make_sphere.Instructions())
        , sphere_indices(make_sphere.Indices())
        , samples(25 + params.quality*params.quality*100)
        , positions(make_positions())
        , sizes(make_sizes())
        , cloud_tex(positions.size())
        , light_path(make_light_path_cps())
    {
        assert(positions.size() == sizes.size());
        std::srand(123456);

        light_vs.Source(
            "#version 330\n"
            "in vec3 Position;"
            "uniform vec3 LightPos;"
            "uniform mat4 CameraMatrix, ProjectionMatrix;"
            "void main(void)"
            "{"
            "	float s = 0.1;"
            "	gl_Position = "
            "		ProjectionMatrix*"
            "		CameraMatrix*"
            "		vec4(Position*s + LightPos, 1.0);"
            "}"
        ).Compile();

        light_fs.Source(
            "#version 330\n"
            "out vec4 fragLight;"
            "void main(void)"
            "{"
            "	fragLight = vec4(1.0, 1.0, 1.0, 1.0);"
            "}"
        ).Compile();

        light_prog << light_vs << light_fs;
        light_prog.Link().Use();

        light.Bind();

        buffer.Bind(Buffer::Target::Array);
        {
            std::vector<GLfloat> data;
            GLuint n_per_vertex = make_sphere.Positions(data);
            Buffer::Data(Buffer::Target::Array, data);
            (light_prog|"Position").Setup(n_per_vertex, DataType::Float).Enable();
        }

        cloud_vs.Source(
            "#version 330\n"
            "in vec4 Position;"
            "in float Size;"
            "uniform int SampleCount;"
            "uniform mat4 CameraMatrix;"
            "uniform vec4 ViewZ;"
            "out float vertZOffs;"
            "out float vertSize;"
            "void main(void)"
            "{"
            "	float hp = (SampleCount-1) * 0.5;"
            "	vertZOffs = (gl_InstanceID - hp)/hp;"
            "	vertSize = Size;"
            "	gl_Position = vec4("
            "		Position.xyz +"
            "		ViewZ.xyz*vertZOffs*Size*0.5,"
            "		1.0"
            "	);"
            "}"
        ).Compile();

        cloud_gs.Source(
            "#version 330\n"
            "layout(points) in;"
            "layout(triangle_strip, max_vertices = 4) out;"
            "in float vertZOffs[];"
            "in float vertSize[];"
            "uniform vec3 LightPos;"
            "uniform mat4 CameraMatrix, ProjectionMatrix;"
            "uniform vec4 ViewX, ViewY, ViewZ;"
            "out vec3 geomTexCoord;"
            "out vec3 geomLightDir;"
            "void main(void)"
            "{"
            "	float zo = vertZOffs[0];"
            "	float s = vertSize[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)"
            "	{"
            "		vec4 v = vec4("
            "			gl_in[0].gl_Position.xyz+"
            "			ViewX.xyz * xo[i] * s * 0.5+"
            "			ViewY.xyz * yo[j] * s * 0.5,"
            "			1.0"
            "		);"
            "		gl_Position = ProjectionMatrix * CameraMatrix * v;"
            "		geomLightDir = LightPos - v.xyz;"
            "		geomTexCoord = "
            "			vec3(0.5, 0.5, 0.5)+"
            "			ViewX.xyz*(xo[i])*0.707+"
            "			ViewY.xyz*(yo[j])*0.707+"
            "			ViewZ.xyz*(zo   )*0.707;"
            "		EmitVertex();"
            "	}"
            "	EndPrimitive();"
            "}"
        ).Compile();

        cloud_fs.Source(
            "#version 330\n"
            "uniform sampler3D CloudTex;"
            "in vec3 geomTexCoord;"
            "in vec3 geomLightDir;"
            "out vec4 fragColor;"
            "void main(void)"
            "{"
            "	float d = texture(CloudTex, geomTexCoord).r;"
            "	float o = 1.0;"
            "	float s = 2.0/128.0;"
            "	float r = s * 8.0;"
            "	vec3 sampleOffs = normalize(geomLightDir) * s;"
            "	vec3 samplePos = geomTexCoord;"
            "	if(d > 0.01) while(o > 0.0)"
            "	{"
            "		if(samplePos.x<0.0 || samplePos.x>1.0)"
            "			break;"
            "		if(samplePos.y<0.0 || samplePos.y>1.0)"
            "			break;"
            "		if(samplePos.z<0.0 || samplePos.z>1.0)"
            "			break;"
            "		o -= texture(CloudTex, samplePos).r*r;"
            "		samplePos += sampleOffs;"
            "	}"
            "	float a = 0.4 * d;"
            "	float i = mix(0.2, 1.0, o);"
            "	fragColor = vec4(i, i, i, a);"
            "}"
        ).Compile();

        cloud_prog << cloud_vs << cloud_gs << cloud_fs;
        cloud_prog.Link().Use();

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

        // bind the VBO for the cloud positions
        pos_buffer.Bind(Buffer::Target::Array);
        {
            Buffer::Data(Buffer::Target::Array, positions);
            (cloud_prog|"Position").Setup(3, DataType::Float).Enable();
        }

        // bind the VBO for the cloud sizes
        size_buffer.Bind(Buffer::Target::Array);
        {
            Buffer::Data(Buffer::Target::Array, sizes);
            (cloud_prog|"Size").Setup(1, DataType::Float).Enable();
        }

        // set the number of samples
        cloud_prog/"SampleCount" = GLint(samples);

        Texture::Active(0);
        cloud_prog/"CloudTex" = 0;
        for(std::size_t i=0, n=positions.size(); i!=n; ++i)
        {
            auto bound_tex = Bind(cloud_tex[i], Texture::Target::_3D);
            bound_tex.Image3D(
                images::Cloud(
                    128, 128, 128,
                    Vec3f(0.1f, -0.5f, 0.3f),
                    0.5f
                )
            );
            bound_tex.GenerateMipmap();
            bound_tex.MinFilter(TextureMinFilter::LinearMipmapLinear);
            bound_tex.MagFilter(TextureMagFilter::Linear);
            bound_tex.BorderColor(Vec4f(0.0f, 0.0f, 0.0f, 0.0f));
            bound_tex.WrapS(TextureWrap::ClampToBorder);
            bound_tex.WrapT(TextureWrap::ClampToBorder);
            bound_tex.WrapR(TextureWrap::ClampToBorder);
        }

        gl.ClearColor(0.0f, 0.1f, 0.2f, 0.0f);
        gl.ClearDepth(1.0f);
        gl.Disable(Capability::DepthTest);
        gl.Enable(Capability::Blend);
        gl.BlendFunc(BlendFn::SrcAlpha, BlendFn::OneMinusSrcAlpha);
    }
Beispiel #7
0
	TorusExample(void)
	 : make_torus(1.0, 0.5, 36, 24)
	 , torus_instr(make_torus.Instructions())
	 , torus_indices(make_torus.Indices())
	 , make_plane(make_plane_builders())
	 , plane_instr(make_plane[0].Instructions())
	 , plane_indices(make_plane[0].Indices())
	 , torus_vs(ShaderType::Vertex, ObjectDesc("Torus vertex"))
	 , plane_vs(ShaderType::Vertex, ObjectDesc("Plane vertex"))
	 , torus_fs(ShaderType::Fragment, ObjectDesc("Torus fragment"))
	 , plane_fs(ShaderType::Fragment, ObjectDesc("Plane fragment"))
	 , torus_prog(ObjectDesc("Torus"))
	 , plane_prog(ObjectDesc("Plane"))
	 , plane_normal(plane_prog, "Normal")
	 , plane_camera_matrix(plane_prog, "CameraMatrix")
	 , torus_camera_matrix(torus_prog, "CameraMatrix")
	 , torus_model_matrix(torus_prog, "ModelMatrix")
	 , plane(make_plane.size())
	 , plane_positions(make_plane.size())
	{
		std::stringstream plane_count_def;
		plane_count_def <<"#define PlaneCount "<<plane.size()<<'\n';

		const GLchar* torus_vs_source[3] = {
			"#version 330\n",
			plane_count_def.str().c_str(),
			"uniform mat4 ProjectionMatrix, ModelMatrix, CameraMatrix;"
			"uniform float ClipSign[PlaneCount];"
			"uniform vec4 ClipPlane[PlaneCount];"
			"in vec4 Position;"
			"in vec2 TexCoord;"
			"out vec2 vertTexCoord;"
			"void main(void)"
			"{"
			"	vertTexCoord = TexCoord;"
			"	gl_Position = "
			"		ModelMatrix *"
			"		Position;"
			"	for(int p=0; p!=PlaneCount; ++p)"
			"	{"
			"		gl_ClipDistance[p] = "
			"			ClipSign[p]* "
			"			dot(ClipPlane[p], gl_Position);"
			"	}"
			"	gl_Position = "
			"		ProjectionMatrix *"
			"		CameraMatrix *"
			"		gl_Position;"
			"}"
		};
		torus_vs.Source(torus_vs_source, 3);
		torus_vs.Compile();

		torus_fs.Source(
			"#version 330\n"
			"in vec2 vertTexCoord;"
			"out vec4 fragColor;"
			"void main(void)"
			"{"
			"	float i = ("
			"		int(vertTexCoord.x*36) % 2+"
			"		int(vertTexCoord.y*24) % 2"
			"	) % 2;"
			"	fragColor = vec4(1-i/2, 1-i/2, 1-i/2, 1.0);"
			"}"
		);
		torus_fs.Compile();

		torus_prog.AttachShader(torus_vs);
		torus_prog.AttachShader(torus_fs);
		torus_prog.Link();
		torus_prog.Use();

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

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

		// bind the VBO for the torus UV-coordinates
		torus_texcoords.Bind(Buffer::Target::Array);
		{
			std::vector<GLfloat> data;
			GLuint n_per_vertex = make_torus.TexCoordinates(data);
			// upload the data
			Buffer::Data(Buffer::Target::Array, data);
			// setup the vertex attribs array for the vertices
			VertexAttribArray attr(torus_prog, "TexCoord");
			attr.Setup(n_per_vertex, DataType::Float);
			attr.Enable();
		}

		const GLchar* plane_vs_source[3] = {
			"#version 330\n",
			plane_count_def.str().c_str(),
			"uniform mat4 ProjectionMatrix, CameraMatrix;"
			"uniform float ClipSign[PlaneCount];"
			"uniform vec4 ClipPlane[PlaneCount];"
			"uniform vec3 Normal;"
			"in vec4 Position;"
			"out vec3 vertColor;"
			"void main(void)"
			"{"
			"	gl_Position = Position;"
			"	for(int p=0; p!=PlaneCount; ++p)"
			"	{"
			"		gl_ClipDistance[p] = "
			"			ClipSign[p]* "
			"			dot(ClipPlane[p], gl_Position);"
			"	}"
			"	gl_Position = "
			"		ProjectionMatrix *"
			"		CameraMatrix *"
			"		gl_Position;"
			"	vertColor = normalize("
			"		abs(Normal) + "
			"		0.4*Position.xyz"
			"	);"
			"}"
		};
		plane_vs.Source(plane_vs_source, 3);
		plane_vs.Compile();

		plane_fs.Source(
			"#version 330\n"
			"in vec3 vertColor;"
			"out vec4 fragColor;"
			"void main(void)"
			"{"
			"	fragColor = vec4(vertColor, 0.7);"
			"}"
		);
		plane_fs.Compile();

		plane_prog.AttachShader(plane_vs);
		plane_prog.AttachShader(plane_fs);
		plane_prog.Link();
		plane_prog.Use();


		ProgramUniform<Vec4f> torus_clip_plane(torus_prog, "ClipPlane");
		ProgramUniform<Vec4f> plane_clip_plane(plane_prog, "ClipPlane");
		ProgramUniform<GLfloat> torus_clip_sign(torus_prog, "ClipSign");
		ProgramUniform<GLfloat> plane_clip_sign(plane_prog, "ClipSign");
		for(std::size_t p=0; p!=plane.size(); ++p)
		{
			plane[p].Bind();

			plane_positions[p].Bind(Buffer::Target::Array);
			{
				std::vector<GLfloat> data;
				GLuint n = make_plane[p].Positions(data);
				// upload the data
				Buffer::Data(Buffer::Target::Array, data);
				VertexAttribArray attr(plane_prog, "Position");
				attr.Setup(n, DataType::Float);
				attr.Enable();
			}
			{
				auto eq = make_plane[p].Equation();
				torus_clip_plane[p].Set(eq);
				plane_clip_plane[p].Set(eq);
			}
			{
				torus_clip_signs.push_back(torus_clip_sign[p]);
				plane_clip_signs.push_back(plane_clip_sign[p]);
			}
		}

		//
		gl.ClearColor(0.8f, 0.8f, 0.7f, 0.0f);
		gl.ClearDepth(1.0f);
		gl.FrontFace(make_torus.FaceWinding());
		gl.Enable(Capability::DepthTest);
		gl.BlendFunc(BlendFn::SrcAlpha, BlendFn::OneMinusSrcAlpha);
	}
Beispiel #8
0
	CubeExample(void)
	 : cube_instr(make_cube.Instructions())
	 , cube_indices(make_cube.Indices())
	 , projection_matrix(prog, "ProjectionMatrix")
	 , camera_matrix(prog, "CameraMatrix")
	 , model_matrix(prog, "ModelMatrix")
	{
		// Set the vertex shader source
		vs.Source(
			"#version 330\n"
			"uniform mat4 ProjectionMatrix, CameraMatrix, ModelMatrix;"
			"in vec4 Position;"
			"in vec3 Normal;"
			"in vec2 TexCoord;"
			"out vec3 vertNormal;"
			"out vec3 vertLight;"
			"out vec2 vertTexCoord;"
			"uniform vec3 LightPos;"
			"void main(void)"
			"{"
			"	vertNormal = mat3(ModelMatrix)*Normal;"
			"	gl_Position = ModelMatrix * Position;"
			"	vertLight = LightPos - gl_Position.xyz;"
			"	vertTexCoord = TexCoord * 6.0;"
			"	gl_Position = ProjectionMatrix * CameraMatrix * gl_Position;"
			"}"
		);
		// compile it
		vs.Compile();

		// set the fragment shader source
		fs.Source(
			"#version 330\n"
			"uniform sampler2D TexUnit;"
			"in vec3 vertNormal;"
			"in vec3 vertLight;"
			"in vec2 vertTexCoord;"
			"out vec4 fragColor;"
			"void main(void)"
			"{"
			"	float l = dot(vertLight, vertLight);"
			"	float d = l != 0.0 ? dot("
			"		vertNormal, "
			"		normalize(vertLight)"
			"	) / l : 0.0;"
			"	vec3 c = vec3(0.9, 0.8, 0.2);"
			"	vec4 t  = texture(TexUnit, vertTexCoord);"
			"	float a = 1.0 - sqrt(abs(d)), e;"
			"	if(gl_FrontFacing)"
			"	{"
			"		e = d >= 0.0 ?"
			"		d * mix(0.5, 1.0, t.a):"
			"		(-0.9*d) * (1.0 - t.a);"
			"	}"
			"	else"
			"	{"
			"		e = d >= 0.0 ?"
			"		(0.6*d) * (1.0 - t.a):"
			"		(-0.7*d) * mix(0.5, 1.0, t.a);"
			"	}"
			"	float i = 0.1 + 9.0*e;"
			"	fragColor = vec4("
			"		t.r*c.r*i, "
			"		t.g*c.g*i, "
			"		t.b*c.b*i, "
			"		clamp(pow(t.a,2) + a*0.4, 0.0, 1.0)"
			"	);"
			"}"
		);
		// compile it
		fs.Compile();

		// attach the shaders to the program
		prog.AttachShader(vs);
		prog.AttachShader(fs);
		// link and use it
		prog.Link();
		prog.Use();

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

		verts.Bind(Buffer::Target::Array);
		{
			std::vector<GLfloat> data;
			GLuint n_per_vertex = make_cube.Positions(data);
			Buffer::Data(Buffer::Target::Array, data);
			VertexAttribArray attr(prog, "Position");
			attr.Setup(n_per_vertex, DataType::Float);
			attr.Enable();
		}

		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(prog, "Normal");
			attr.Setup(n_per_vertex, DataType::Float);
			attr.Enable();
		}

		texcoords.Bind(Buffer::Target::Array);
		{
			std::vector<GLfloat> data;
			GLuint n_per_vertex = make_cube.TexCoordinates(data);
			Buffer::Data(Buffer::Target::Array, data);
			VertexAttribArray attr(prog, "TexCoord");
			attr.Setup(n_per_vertex, DataType::Float);
			attr.Enable();
		}

		// setup the texture
		{
			auto bound_tex = Bind(tex, Texture::Target::_2D);
			bound_tex.Image2D(images::LoadTexture("honeycomb"));
			bound_tex.GenerateMipmap();
			bound_tex.MinFilter(TextureMinFilter::LinearMipmapLinear);
			bound_tex.MagFilter(TextureMagFilter::Linear);
			bound_tex.WrapS(TextureWrap::MirroredRepeat);
			bound_tex.WrapT(TextureWrap::MirroredRepeat);
		}
		//
		UniformSampler(prog, "TexUnit").Set(0);
		Uniform<Vec3f>(prog, "LightPos").Set(Vec3f(1.0f, 2.0f, 3.0f));
		//
		gl.ClearColor(0.1f, 0.1f, 0.1f, 0.0f);
		gl.ClearDepth(1.0f);
		gl.Enable(Capability::DepthTest);
		gl.Enable(Capability::Blend);
		gl.BlendFunc(
			BlendFn::SrcAlpha,
			BlendFn::OneMinusSrcAlpha
		);

		gl.Enable(Capability::CullFace);
		gl.FrontFace(make_cube.FaceWinding());
	}
	CubeExample(void)
	 : cube_instr(make_cube.Instructions())
	 , cube_indices(make_cube.Indices())
	 , projection_matrix(prog, "ProjectionMatrix")
	 , camera_matrix(prog, "CameraMatrix")
	 , model_matrix(prog, "ModelMatrix")
	 , front_facing(prog, "FrontFacing")
	 , inst_count(32)
	{
		// Set the vertex shader source
		vs.Source(
			"#version 330\n"
			"uniform mat4 ProjectionMatrix, CameraMatrix, ModelMatrix;"
			"uniform vec3 LightPos;"
			"uniform int InstCount;"
			"uniform int FrontFacing;"
			"in vec4 Position;"
			"in vec3 Normal;"
			"out float vertMult;"
			"out vec3 vertColor;"
			"out vec3 vertWrapNormal;"
			"out vec3 vertNormal;"
			"out vec3 vertLight;"
			"void main(void)"
			"{"
			"	int inst = (FrontFacing != 0) ? "
			"		(InstCount - gl_InstanceID - 1):"
			"		gl_InstanceID;"
			"	vertMult = float(inst) / float(InstCount-1);"
			"	float sca = 1.0 - 0.3 * pow(vertMult, 2);"
			"	mat4 ScaleMatrix = mat4("
			"		sca, 0.0, 0.0, 0.0,"
			"		0.0, sca, 0.0, 0.0,"
			"		0.0, 0.0, sca, 0.0,"
			"		0.0, 0.0, 0.0, 1.0 "
			"	);"
			"	gl_Position = ModelMatrix * Position;"
			"	vertColor = Normal;"
			"	vec3 wrap = Position.xyz - Normal;"
			"	vertWrapNormal = "
			"		mat3(ModelMatrix)*"
			"		normalize(mix("
			"			Normal,"
			"			wrap,"
			"			mix(0.5, 1.0, vertMult)"
			"		));"
			"	vertNormal = mat3(ModelMatrix)*Normal;"
			"	vertLight = LightPos-gl_Position.xyz;"
			"	gl_Position = "
			"		ProjectionMatrix *"
			"		CameraMatrix *"
			"		ScaleMatrix *"
			"		gl_Position;"
			"}"
		);
		// compile it
		vs.Compile();

		// set the fragment shader source
		fs.Source(
			"#version 330\n"
			"in float vertMult;"
			"in vec3 vertColor;"
			"in vec3 vertWrapNormal;"
			"in vec3 vertNormal;"
			"in vec3 vertLight;"
			"out vec4 fragColor;"
			"uniform int InstCount;"
			"void main(void)"
			"{"
			"	float l = dot(vertLight, vertLight);"
			"	float d = l > 0.0 ? dot("
			"		vertNormal, "
			"		normalize(vertLight)"
			"	) / l : 0.0;"
			"	float s = max("
			"		dot(vertWrapNormal, vertLight)/l,"
			"		0.0"
			"	);"
			"	float intensity = clamp("
			"		0.2 + d * 3.0 + s * 5.5,"
			"		0.0,"
			"		1.0"
			"	);"
			"	fragColor = vec4("
			"		abs(vertColor) * intensity,"
			"		(2.5 + 1.5*d + 1.5*s) / InstCount"
			"	);"
			"}"
		);
		// compile it
		fs.Compile();

		// attach the shaders to the program
		prog.AttachShader(vs);
		prog.AttachShader(fs);
		// link and use it
		prog.Link();
		prog.Use();

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

		// bind the VBO for the cube vertices
		verts.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
			VertexArrayAttrib attr(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);
			// upload the data
			Buffer::Data(Buffer::Target::Array, data);
			VertexArrayAttrib attr(prog, "Normal");
			attr.Setup<GLfloat>(n_per_vertex);
			attr.Enable();
		}
		// the light position
		Uniform<Vec3f>(prog, "LightPos").Set(Vec3f(-3.0f, -2.0f, -3.0f));
		// and the instance count
		Uniform<GLint>(prog, "InstCount").Set(inst_count);
		//
		gl.ClearColor(0.5f, 0.6f, 0.5f, 0.0f);
		gl.ClearDepth(1.0f);
		gl.Enable(Capability::DepthTest);
		gl.Enable(Capability::CullFace);
		gl.FrontFace(make_cube.FaceWinding());
		gl.Enable(Capability::Blend);
		gl.BlendFunc(BlendFn::SrcAlpha, BlendFn::OneMinusSrcAlpha);
	}
Beispiel #10
0
    GraphExample(void)
        : prog()
        , projection_matrix(prog, "ProjectionMatrix")
        , camera_matrix(prog, "CameraMatrix")
        , node_count(512)
        , edge_count(0)
        , cam_path(make_cam_path_cps())
        , tgt_path(make_tgt_path_cps())
    {
        std::srand(std::time(0));

        // Vertex shader
        VertexShader vs;
        // Set the vertex shader source
        vs.Source(
            "#version 330\n"
            "uniform mat4 ProjectionMatrix, CameraMatrix;"
            "in vec4 Position;"
            "void main(void)"
            "{"
            "	gl_Position = "
            "		ProjectionMatrix *"
            "		CameraMatrix *"
            "		Position;"
            "	gl_PointSize = 4.0 * gl_Position.w / gl_Position.z;"
            "}"
        );
        // compile it
        vs.Compile();

        // Fragment shader
        FragmentShader fs;
        // set the fragment shader source
        fs.Source(
            "#version 330\n"
            "out vec4 fragColor;"
            "void main(void)"
            "{"
            "	fragColor = vec4(0.0, 0.0, 0.0, 1.0);"
            "}"
        );
        // compile it
        fs.Compile();

        // attach the shaders to the program
        prog.AttachShader(vs);
        prog.AttachShader(fs);
        // link and use it
        prog.Link();
        prog.Use();

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

        std::vector<GLfloat> positions(node_count * 3);
        // bind the VBO for the cube vertices
        verts.Bind(Buffer::Target::Array);
        {
            GLuint k = 0;
            for(GLuint p=0; p!=node_count; ++p)
            {
                positions[k++] = nrand() *120.0;
                positions[k++] = nrand() *  5.0;
                positions[k++] = nrand() *120.0;
            }
            assert(k == positions.size());

            // upload the data
            Buffer::Data(Buffer::Target::Array, positions);
            // setup the vertex attribs array for the vertices
            VertexAttribArray vert_attr(prog, "Position");
            vert_attr.Setup(3, DataType::Float).Enable();
        }

        // bind the VBO for cube edge indices
        edges.Bind(Buffer::Target::ElementArray);
        {
            std::vector<GLuint> edge_data;
            edge_data.reserve(node_count * 6);
            for(GLuint i=0; i!=node_count; ++i)
            {
                Vec3f pi(
                    positions[i*3+0],
                    positions[i*3+1],
                    positions[i*3+2]
                );
                float min_dist = 1000.0f;
                GLuint m = i;
                for(GLuint j=i+1; j!=node_count; ++j)
                {
                    Vec3f pj(
                        positions[j*3+0],
                        positions[j*3+1],
                        positions[j*3+2]
                    );
                    float dist = Distance(pi, pj);
                    if(min_dist > 1.0 && min_dist > dist)
                    {
                        min_dist = dist;
                        m = j;
                    }
                }
                min_dist *= 2.0f;
                GLuint done = 0;
                for(GLuint j=i+1; j!=node_count; ++j)
                {
                    Vec3f pj(
                        positions[j*3+0],
                        positions[j*3+1],
                        positions[j*3+2]
                    );
                    float dist = Distance(pi, pj);
                    if(min_dist > dist)
                    {
                        float x = dist/min_dist;
                        if(std::pow(nrand(), 2.0) >= x)
                        {
                            edge_data.push_back(i);
                            edge_data.push_back(j);
                            ++done;
                        }
                    }
                }
                if(done == 0)
                {
                    if(i != m)
                    {
                        edge_data.push_back(i);
                        edge_data.push_back(m);
                    }
                }
            }
            Buffer::Data(Buffer::Target::ElementArray, edge_data);
            assert(edge_data.size() % 2 == 0);
            edge_count = edge_data.size();
            positions.clear();
        }

        //
        gl.ClearColor(0.9f, 0.9f, 0.8f, 0.0f);
        gl.ClearDepth(1.0f);
        gl.Enable(Capability::DepthTest);
        gl.Enable(Capability::LineSmooth);
        gl.Enable(Capability::ProgramPointSize);
        gl.Enable(Capability::Blend);
        gl.BlendFunc(BlendFn::SrcAlpha, BlendFn::OneMinusSrcAlpha);
    }
	SmokeExample(void)
	 : emitters(
		{
			{
				{
					{-20.0f, -10.0f,  10.0f},
					{ 20.0f,   0.0f, -20.0f},
					{ 20.0f,  10.0f,  20.0f},
					{-20.0f,   0.0f, -10.0f}
				}, 15.0, 200.0
			},
			{
				{
					{ 30.0f,   0.0f,   5.0f},
					{-30.0f,   0.0f,  -5.0f},
					{-20.0f,  20.0f,   5.0f},
					{ 20.0f, -10.0f,  -5.0f}
				}, 17.0, 200.0
			},
		}
	), vs(ShaderType::Vertex, "Vertex")
	 , gs(ShaderType::Geometry, "Geometry")
	 , fs(ShaderType::Fragment, "Fragment")
	 , projection_matrix(prog, "ProjectionMatrix")
	 , camera_matrix(prog, "CameraMatrix")
	 , light_cam_pos(prog, "LightCamPos")
	{
		// Set the vertex shader source
		vs.Source(
			"#version 330\n"
			"uniform mat4 CameraMatrix;"
			"in vec4 Position;"
			"in float Age;"
			"in int Id;"
			"out float vertAge;"
			"out int vertId;"
			"void main(void)"
			"{"
			"	gl_Position = CameraMatrix * Position;"
			"	vertAge = Age;"
			"	vertId = Id;"
			"}"
		);
		// compile it
		vs.Compile();

		// Set the geometry shader source
		gs.Source(
			"#version 330\n"
			"layout(points) in;"
			"layout(triangle_strip, max_vertices = 4) out;"
			"uniform vec3 LightCamPos;"
			"uniform mat4 ProjectionMatrix;"
			"in float vertAge[];"
			"in int vertId[];"
			"out vec2 geomTexCoord;"
			"out float geomAge;"
			"out float geomLightVal;"
			"out float geomLightBias;"
			"void main(void)"
			"{"
			"	if(vertAge[0] > 1.0) return;"
			"	vec3 pos = gl_in[0].gl_Position.xyz;"
			"	vec3 lightDir = normalize(LightCamPos - pos);"
			"	float s = 0.8, g = 3.0;"
			"	float yo[2] = float[2](-1.0, 1.0);"
			"	float xo[2] = float[2](-1.0, 1.0);"
			"	float angle = vertId[0];"
			"	float cx = cos(angle), sx = sin(angle);"
			"	mat2 rot = mat2(cx, sx, -sx, cx);"
			"	for(int j=0;j!=2;++j)"
			"	for(int i=0;i!=2;++i)"
			"	{"
			"		float xoffs = xo[i]*(1.0+vertAge[0]*g)*s;"
			"		float yoffs = yo[j]*(1.0+vertAge[0]*g)*s;"
			"		vec2 offs = rot*vec2(xoffs, yoffs);"
			"		gl_Position = ProjectionMatrix * vec4("
			"			pos.x-offs.x,"
			"			pos.y-offs.y,"
			"			pos.z,"
			"			1.0"
			"		);"
			"		geomTexCoord = vec2(float(i), float(j));"
			"		geomAge = vertAge[0];"
			"		geomLightVal = lightDir.z;"
			"		geomLightBias = -dot("
			"			normalize(vec3(offs, 0.0)),"
			"			lightDir"
			"		);"
			"		EmitVertex();"
			"	}"
			"	EndPrimitive();"
			"}"
		);
		// compile it
		gs.Compile();

		// set the fragment shader source
		fs.Source(
			"#version 330\n"
			"uniform sampler2D SmokeTex;"
			"in vec2 geomTexCoord;"
			"in float geomAge;"
			"in float geomLightVal;"
			"in float geomLightBias;"
			"out vec4 fragColor;"
			"void main(void)"
			"{"
			"	vec3 c = texture(SmokeTex, geomTexCoord).rgb;"
			"	float depth = c.g - c.r;"
			"	if(depth == 0.0) discard;"
			"	float density = min(depth * c.b * 2.0, 1.0);"
			"	float intensity = min("
			"		max("
			"			geomLightVal*0.5+"
			"			geomLightBias,"
			"			0.0"
			"		)+max("
			"			-geomLightVal*"
			"			(1.0 - density)*"
			"			geomLightBias * 5.0,"
			"			0.0"
			"		),"
			"		1.0"
			"	) + 0.1;"
			"	fragColor = vec4("
			"		intensity,"
			"		intensity,"
			"		intensity,"
			"		(1.0 - geomAge)*density"
			"	);"
			"}"
		);
		// compile it
		fs.Compile();

		// attach the shaders to the program
		prog.AttachShader(vs);
		prog.AttachShader(gs);
		prog.AttachShader(fs);
		// link and use it
		prog.Link();
		prog.Use();

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

		// bind the VBO for the particle positions
		pos_buf.Bind(Buffer::Target::Array);
		{
			Buffer::Data(Buffer::Target::Array, positions);
			VertexAttribArray attr(prog, "Position");
			attr.Setup<Vec3f>();
			attr.Enable();
		}

		// bind the VBO for the particle ages
		age_buf.Bind(Buffer::Target::Array);
		{
			Buffer::Data(Buffer::Target::Array, ages);
			VertexAttribArray attr(prog, "Age");
			attr.Setup<GLfloat>();
			attr.Enable();
		}

		// bind the VBO for the particle identifiers
		id_buf.Bind(Buffer::Target::Array);
		{
			Buffer::Data(Buffer::Target::Array, ids);
			VertexAttribArray attr(prog, "Id");
			attr.Setup<GLint>();
			attr.Enable();
		}

		Texture::Active(0);
		UniformSampler(prog, "SmokeTex").Set(0);
		{
			auto bound_tex = Bind(smoke_tex, Texture::Target::_2D);
			bound_tex.Image2D(
				images::Cloud2D(
					images::Cloud(
						128, 128, 128,
						Vec3f(0.1f, -0.5f, 0.3f),
						0.5f
					)
				)
			);
			bound_tex.GenerateMipmap();
			bound_tex.MinFilter(TextureMinFilter::LinearMipmapLinear);
			bound_tex.MagFilter(TextureMagFilter::Linear);
			bound_tex.BorderColor(Vec4f(0.0f, 0.0f, 0.0f, 0.0f));
			bound_tex.WrapS(TextureWrap::ClampToBorder);
			bound_tex.WrapT(TextureWrap::ClampToBorder);
		}
		//
		gl.ClearColor(0.0f, 0.1f, 0.2f, 0.0f);
		gl.ClearDepth(1.0f);
		gl.Enable(Capability::DepthTest);
		gl.Enable(Capability::Blend);
		gl.BlendFunc(BlendFn::SrcAlpha, BlendFn::OneMinusSrcAlpha);
	}
Beispiel #12
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);
	}
	VolLightExample(void)
	 : volume_vs(ShaderType::Vertex, ObjectDesc("Volume vertex"))
	 , plane_vs(ShaderType::Vertex, ObjectDesc("Plane vertex"))
	 , volume_gs(ShaderType::Geometry, ObjectDesc("Volume geometry"))
	 , volume_fs(ShaderType::Fragment, ObjectDesc("Volume fragment"))
	 , plane_fs(ShaderType::Fragment, ObjectDesc("Plane fragment"))
	 , volume_prog(ObjectDesc("Volume"))
	 , plane_prog(ObjectDesc("Plane"))
	 , samples(150)
	{
		volume_vs.Source(
			"#version 330\n"
			"in vec4 Position;"
			"out float vertZOffs;"
			"uniform int SampleCount;"
			"uniform mat4 CameraMatrix;"
			"uniform vec3 ViewZ;"
			"uniform float Size;"
			"void main(void)"
			"{"
			"	float hp = (SampleCount-1) * 0.5;"
			"	vertZOffs = (gl_InstanceID - hp)/hp;"
			"	gl_Position = vec4("
			"		Position.xyz +"
			"		ViewZ*vertZOffs*Size*0.5,"
			"		1.0"
			"	);"
			"}"
		);
		volume_vs.Compile();

		volume_gs.Source(
			"#version 330\n"
			"layout(points) in;"
			"layout(triangle_strip, max_vertices = 4) out;"
			"uniform mat4 CameraMatrix, ProjectionMatrix;"
			"uniform mat4 TexProjectionMatrix;"
			"uniform vec3 ViewX, ViewY;"
			"uniform float Size;"
			"in float vertZOffs[];"
			"out vec4 geomTexCoord;"
			"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)"
			"	{"
			"		vec4 v = vec4("
			"			gl_in[0].gl_Position.xyz+"
			"			ViewX * xo[i] * Size+"
			"			ViewY * yo[j] * Size,"
			"			1.0"
			"		);"
			"		geomTexCoord = "
			"			TexProjectionMatrix *"
			"			v;"
			"		gl_Position = "
			"			ProjectionMatrix *"
			"			CameraMatrix * v;"
			"		EmitVertex();"
			"	}"
			"	EndPrimitive();"
			"}"
		);
		volume_gs.Compile();

		volume_fs.Source(
			"#version 330\n"
			"uniform sampler2D LightTex;"
			"uniform int SampleCount;"
			"in vec4 geomTexCoord;"
			"out vec4 fragColor;"
			"void main(void)"
			"{"
			"	vec2 coord = geomTexCoord.st/geomTexCoord.q;"
			"	float depth = geomTexCoord.z;"
			"	if(depth < 0.0) discard;"
			"	vec4 t  = texture(LightTex, coord*0.5 + 0.5);"
			"	if(t.a == 0.0) discard;"
			"	float alpha = 10.0*(1.0-t.a)/SampleCount;"
			"	alpha *= (t.r+t.g+t.b)*0.3333;"
			"	alpha /= sqrt(depth);"
			"	fragColor = vec4(t.rgb, alpha);"
			"}"
		);
		volume_fs.Compile();

		volume_prog.AttachShader(volume_vs);
		volume_prog.AttachShader(volume_gs);
		volume_prog.AttachShader(volume_fs);
		volume_prog.Link();
		volume_prog.Use();

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

		// bind the VBO for the volume positions
		volume_pos.Bind(Buffer::Target::Array);
		{
			GLfloat position[3] = {0.0, 0.0, 0.0};
			Buffer::Data(Buffer::Target::Array, 3, position);
			VertexArrayAttrib attr(volume_prog, "Position");
			attr.Setup<Vec3f>();
			attr.Enable();
		}

		Vec3f lightPos(2.0f, 4.0f, -3.0f);
		auto texProjMat =
			CamMatrixf::PerspectiveX(Degrees(30), 1.0, 0.3, 20.0) *
			CamMatrixf::LookingAt(lightPos, Vec3f(0, 0, 0));

		Uniform<GLint>(volume_prog, "SampleCount").Set(samples);
		Uniform<GLfloat>(volume_prog, "Size").Set(Length(lightPos));
		Uniform<Mat4f>(volume_prog, "TexProjectionMatrix").Set(texProjMat);

		plane_vs.Source(
			"#version 330\n"
			"in vec4 Position;"
			"uniform mat4 CameraMatrix, ProjectionMatrix;"
			"uniform mat4 TexProjectionMatrix;"
			"out vec2 vertChecker;"
			"out vec4 vertTexCoord;"
			"void main(void)"
			"{"
			"	gl_Position = "
			"		ProjectionMatrix *"
			"		CameraMatrix *"
			"		Position;"
			"	vertTexCoord = "
			"		TexProjectionMatrix *"
			"		Position;"
			"	vertChecker = Position.xz;"
			"}"
		);
		plane_vs.Compile();

		plane_fs.Source(
			"#version 330\n"
			"uniform sampler2D LightTex;"
			"in vec4 vertTexCoord;"
			"in vec2 vertChecker;"
			"out vec4 fragColor;"
			"void main(void)"
			"{"
			"	vec2 coord = vertTexCoord.st/vertTexCoord.q;"
			"	vec4 t  = texture(LightTex, coord*0.5 + 0.5);"
			"	float i = ("
			"		1 +"
			"		int(vertChecker.x+10) % 2+"
			"		int(vertChecker.y+10) % 2"
			"	) % 2;"
			"	vec3 color = vec3(0.1, 0.1, 0.1);"
			"	color += t.rgb * (1.0 - t.a);"
			"	color *= mix("
			"		vec3(0.9, 0.9, 1.0), "
			"		vec3(0.4, 0.4, 0.9), "
			"		i"
			"	);"
			"	fragColor = vec4(color, 1.0);"
			"}"
		);
		plane_fs.Compile();

		plane_prog.AttachShader(plane_vs);
		plane_prog.AttachShader(plane_fs);
		plane_prog.Link();
		plane_prog.Use();

		Uniform<Mat4f>(plane_prog, "TexProjectionMatrix").Set(texProjMat);

		plane.Bind();

		// bind the VBO for the plane vertices
		plane_pos.Bind(Buffer::Target::Array);
		{
			GLfloat data[4*3] = {
				-9.0f, -4.0f,  9.0f,
				-9.0f, -4.0f, -9.0f,
				 9.0f, -4.0f,  9.0f,
				 9.0f, -4.0f, -9.0f
			};
			Buffer::Data(Buffer::Target::Array, 4*3, data);
			plane_prog.Use();
			VertexArrayAttrib attr(plane_prog, "Position");
			attr.Setup<Vec3f>();
			attr.Enable();
		}

		Texture::Active(0);
		ProgramUniformSampler(volume_prog, "LightTex").Set(0);

		light_tex
			<< Texture::Target::_2D
			<< TextureMinFilter::LinearMipmapLinear
			<< TextureMagFilter::Linear
			<< TextureWrap::ClampToBorder
			<< Vec4f(0.0f, 0.0f, 0.0f, 0.0f)
			<< images::LoadTexture("flower_glass")
			<< TextureMipmap();

		gl.ClearColor(0.0f, 0.05f, 0.1f, 0.0f);
		gl.ClearDepth(1.0f);
		gl.BlendFunc(BlendFn::SrcAlpha, BlendFn::One);
	}
Beispiel #14
0
	CloudExample(void)
	 : projection_matrix(prog, "ProjectionMatrix")
	 , camera_matrix(prog, "CameraMatrix")
	{
		// Set the vertex shader source

		vs.Source(
			"#version 330\n"
			"in vec4 Position;"
			"uniform mat4 CameraMatrix;"
			"void main(void)"
			"{"
			"	gl_Position = "
			"		CameraMatrix *"
			"		Position;"
			"}"
		);
		// compile it
		vs.Compile();

		// Set the geometry shader source
		gs.Source(
			"#version 330\n"
			"layout(points) in;"
			"layout(triangle_strip, max_vertices = 100) out;"
			"const int p = 25;"
			"const float hp = (p-1)*0.5;"
			"uniform vec3 LightPos;"
			"uniform mat4 CameraMatrix, ProjectionMatrix;"
			"out vec3 geomTexCoord;"
			"out vec3 geomLightDir;"
			"void main(void)"
			"{"
			"	float s = 0.6;"
			"	float yo[2] = float[2](-1.0, 1.0);"
			"	float xo[2] = float[2](-1.0, 1.0);"
			"	vec3 cx = vec3("
			"		CameraMatrix[0][0],"
			"		CameraMatrix[1][0],"
			"		CameraMatrix[2][0] "
			"	);"
			"	vec3 cy = vec3("
			"		CameraMatrix[0][1],"
			"		CameraMatrix[1][1],"
			"		CameraMatrix[2][1] "
			"	);"
			"	vec3 cz = vec3("
			"		CameraMatrix[0][2],"
			"		CameraMatrix[1][2],"
			"		CameraMatrix[2][2] "
			"	);"
			"	for(int k=0;k!=p;++k)"
			"	{"
			"		for(int j=0;j!=2;++j)"
			"		for(int i=0;i!=2;++i)"
			"		{"
			"			float zo = ((k - hp) / hp);"
			"			float xoffs = xo[i]*s;"
			"			float yoffs = yo[j]*s;"
			"			float zoffs = zo   *s;"
			"			vec4 v = vec4("
			"				gl_in[0].gl_Position.x+xoffs,"
			"				gl_in[0].gl_Position.y+yoffs,"
			"				gl_in[0].gl_Position.z+zoffs,"
			"				1.0"
			"			);"
			"			gl_Position = ProjectionMatrix * v;"
			"			geomLightDir = LightPos - v.xyz;"
			"			geomTexCoord = "
			"				vec3(0.5, 0.5, 0.5)+"
			"				cx*(xo[i])*0.707+"
			"				cy*(yo[j])*0.707+"
			"				cz*(zo   )*0.707;"
			"			EmitVertex();"
			"		}"
			"		EndPrimitive();"
			"	}"
			"}"
		);
		// compile it
		gs.Compile();

		// set the fragment shader source
		fs.Source(
			"#version 330\n"
			"uniform sampler3D cloudTex;"
			"in vec3 geomTexCoord;"
			"in vec3 geomLightDir;"
			"out vec4 fragColor;"
			"void main(void)"
			"{"
			"	float d = texture(cloudTex, geomTexCoord).r;"
			"	float o = 1.0;"
			"	float s = 2.0/128.0;"
			"	float r = s * 8.0;"
			"	vec3 sampleOffs = normalize(geomLightDir) * s;"
			"	vec3 samplePos = geomTexCoord;"
			"	if(d > 0.01) while(o > 0.0)"
			"	{"
			"		if(samplePos.x<0.0 || samplePos.x>1.0)"
			"			break;"
			"		if(samplePos.y<0.0 || samplePos.y>1.0)"
			"			break;"
			"		if(samplePos.z<0.0 || samplePos.z>1.0)"
			"			break;"
			"		o -= texture(cloudTex, samplePos).r*r;"
			"		samplePos += sampleOffs;"
			"	}"
			"	float a = 0.2 * d;"
			"	float i = mix(0.4, 1.0, o);"
			"	fragColor = vec4(i, i, i, a);"
			"}"
		);
		// compile it
		fs.Compile();

		// attach the shaders to the program
		prog.AttachShader(vs);
		prog.AttachShader(gs);
		prog.AttachShader(fs);
		// link and use it
		prog.Link();
		prog.Use();

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

		// bind the VBO for the cloud positions
		buffer.Bind(Buffer::Target::Array);
		{
			GLfloat positions[3] = {0.5f, 0.1f, 0.2f};
			Buffer::Data(Buffer::Target::Array, 3, positions);
			VertexAttribArray attr(prog, "Position");
			attr.Setup(3, DataType::Float);
			attr.Enable();
		}

		{
			Texture::Active(0);
			UniformSampler(prog, "cloudTex").Set(0);
			auto bound_tex = Bind(cloud_tex, Texture::Target::_3D);
			bound_tex.Image3D(images::Cloud(128, 128, 128));
			bound_tex.GenerateMipmap();
			bound_tex.MinFilter(TextureMinFilter::LinearMipmapLinear);
			bound_tex.MagFilter(TextureMagFilter::Linear);
			bound_tex.BorderColor(Vec4f(0.0f, 0.0f, 0.0f, 0.0f));
			bound_tex.WrapS(TextureWrap::ClampToBorder);
			bound_tex.WrapT(TextureWrap::ClampToBorder);
			bound_tex.WrapR(TextureWrap::ClampToBorder);
		}

		Uniform<Vec3f>(prog, "LightPos").Set(Vec3f(10.0f, 1.0f, 5.0f));

		gl.ClearColor(0.2f, 0.3f, 0.4f, 0.0f);
		gl.ClearDepth(1.0f);
		gl.Enable(Capability::DepthTest);
		gl.Enable(Capability::Blend);
		gl.BlendFunc(BlendFn::SrcAlpha, BlendFn::OneMinusSrcAlpha);
	}
Beispiel #15
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);
	}
Beispiel #16
0
	FlareExample(void)
	 : shape(shape_prog, shapes::SpiralSphere())
	 , n_flares(32)
	 , queries(n_flares)
	{
		std::vector<Vec3f> light_positions(n_flares);
		for(GLuint i=0; i!=n_flares; ++i)
		{
			const float rand_max = float(RAND_MAX);
			auto angle = FullCircles(std::rand()/rand_max);

			light_positions[i] = Vec3f(
				7.0f*Cos(angle),
				0.2f*(std::rand()/rand_max)-0.1f,
				7.0f*Sin(angle)
			);
		}

		shape_prog.light_position.Set(light_positions);
		shape_prog.color_1 = Vec3f(0.3f, 0.3f, 0.5f);
		shape_prog.color_2 = Vec3f(0.8f, 0.8f, 1.0f);

		Texture::Active(0);
		shape_prog.metal_tex.Set(0);
		metal_texture
			<< TextureTarget::_2D
			<< TextureMinFilter::LinearMipmapLinear
			<< TextureMagFilter::Linear
			<< TextureWrap::Repeat
			<< images::BrushedMetalUByte(
				512, 512,
				5120,
				-12, +12,
				32, 64
			)
			<< TextureMipmap();

		Texture::Active(1);
		UniformSampler(flare_prog, "FlareTex").Set(1);
		flare_texture
			<< TextureTarget::_2D
			<< TextureMinFilter::LinearMipmapLinear
			<< TextureMagFilter::Linear
			<< images::LoadTexture("flare_1")
			<< TextureMipmap();

		(TextureTarget::_2D|0) << TextureWrap::MirroredRepeat;
		(TextureTarget::_2D|1) << TextureWrap::Repeat;

		lights.Bind();
		try
		{
			light_pos.Bind(Buffer::Target::Array);
			Buffer::Data(Buffer::Target::Array, light_positions);

			light_prog.Use();
			VertexArrayAttrib light_attr(light_prog, "Position");
			light_attr.Setup<Vec3f>();
			light_attr.Enable();

			flare_prog.Use();
			VertexArrayAttrib flare_attr(flare_prog, "Position");
			flare_attr.Setup<Vec3f>();
			flare_attr.Enable();
		}
		catch(Error&)
		{ }

		gl.ClearColor(0.1f, 0.1f, 0.1f, 0.0f);
		gl.ClearDepth(1.0f);
		gl.Enable(Capability::ProgramPointSize);
		gl.Enable(Capability::DepthTest);
		gl.Enable(Capability::CullFace);
		gl.CullFace(Face::Back);
		gl.BlendFunc(BlendFn::SrcAlpha, BlendFn::One);
	}
	CubeExample(void)
	 : cube_instr(make_cube.Instructions())
	 , cube_indices(make_cube.Indices())
	 , prog(make_prog())
	 , projection_matrix(prog, "ProjectionMatrix")
	 , camera_matrix(prog, "CameraMatrix")
	 , model_matrix(prog, "ModelMatrix")
	{

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

		gl.Bind(Buffer::Target::Array, verts);
		{
			std::vector<GLfloat> data;
			GLuint n_per_vertex = make_cube.Positions(data);
			Buffer::Data(Buffer::Target::Array, data);
			VertexArrayAttrib attr(prog, "Position");
			attr.Setup<GLfloat>(n_per_vertex);
			attr.Enable();
		}

		gl.Bind(Buffer::Target::Array, normals);
		{
			std::vector<GLfloat> data;
			GLuint n_per_vertex = make_cube.Normals(data);
			Buffer::Data(Buffer::Target::Array, data);
			VertexArrayAttrib attr(prog, "Normal");
			attr.Setup<GLfloat>(n_per_vertex);
			attr.Enable();
		}

		gl.Bind(Buffer::Target::Array, texcoords);
		{
			std::vector<GLfloat> data;
			GLuint n_per_vertex = make_cube.TexCoordinates(data);
			Buffer::Data(Buffer::Target::Array, data);
			VertexArrayAttrib attr(prog, "TexCoord");
			attr.Setup<GLfloat>(n_per_vertex);
			attr.Enable();
		}

		// setup the texture
		gl.Bound(Texture::Target::_2D, tex)
			.Image2D(images::LoadTexture("honeycomb"))
			.GenerateMipmap()
			.MinFilter(TextureMinFilter::LinearMipmapLinear)
			.MagFilter(TextureMagFilter::Linear)
			.WrapS(TextureWrap::MirroredRepeat)
			.WrapT(TextureWrap::MirroredRepeat)
			.Anisotropy(2);
		//
		UniformSampler(prog, "TexUnit").Set(0);
		Uniform<Vec3f>(prog, "LightPos").Set(Vec3f(1.0f, 2.0f, 3.0f));
		//
		gl.ClearColor(0.1f, 0.1f, 0.1f, 0.0f);
		gl.ClearDepth(1.0f);
		gl.Enable(Capability::DepthTest);
		gl.Enable(Capability::Blend);
		gl.BlendFunc(
			BlendFn::SrcAlpha,
			BlendFn::OneMinusSrcAlpha
		);

		gl.Enable(Capability::CullFace);
		gl.FrontFace(make_cube.FaceWinding());
	}
Beispiel #18
0
	HaloExample(void)
	 : make_shape()
	 , shape_indices(make_shape.Indices())
	 , shape_instr(make_shape.Instructions())
	 , vs_shape(ObjectDesc("Shape VS"))
	 , vs_plane(ObjectDesc("Plane VS"))
	 , fs_shape(ObjectDesc("Shape FS"))
	 , fs_plane(ObjectDesc("Plane FS"))
	 , vs_halo(ObjectDesc("Halo VS"))
	 , gs_halo(ObjectDesc("Halo GS"))
	 , fs_halo(ObjectDesc("Halo FS"))
	 , shape_projection_matrix(shape_prog, "ProjectionMatrix")
	 , shape_camera_matrix(shape_prog, "CameraMatrix")
	 , shape_model_matrix(shape_prog, "ModelMatrix")
	 , plane_projection_matrix(plane_prog, "ProjectionMatrix")
	 , plane_camera_matrix(plane_prog, "CameraMatrix")
	 , halo_projection_matrix(halo_prog, "ProjectionMatrix")
	 , halo_camera_matrix(halo_prog, "CameraMatrix")
	 , halo_model_matrix(halo_prog, "ModelMatrix")
	{
		vs_shape.Source(
			"#version 140\n"
			"in vec4 Position;"
			"in vec3 Normal;"
			"uniform mat4 ProjectionMatrix, CameraMatrix, ModelMatrix;"
			"uniform vec3 LightPos;"
			"out vec3 vertNormal;"
			"out vec3 vertViewNormal;"
			"out vec3 vertLight;"
			"void main(void)"
			"{"
			"	gl_Position = ModelMatrix * Position;"
			"	vertNormal = mat3(ModelMatrix)*Normal;"
			"	vertViewNormal = mat3(CameraMatrix)*vertNormal;"
			"	vertLight = LightPos - gl_Position.xyz;"
			"	gl_Position = ProjectionMatrix * CameraMatrix * gl_Position;"
			"}"
		);
		vs_shape.Compile();

		fs_shape.Source(
			"#version 140\n"
			"in vec3 vertNormal;"
			"in vec3 vertViewNormal;"
			"in vec3 vertLight;"
			"uniform mat4 CameraMatrix;"
			"out vec4 fragColor;"
			"void main(void)"
			"{"
			"	float ltlen = sqrt(length(vertLight));"
			"	float ltexp = dot("
			"		normalize(vertNormal),"
			"		normalize(vertLight)"
			"	);"
			"	float lview = dot("
			"		normalize(vertLight),"
			"		normalize(vec3("
			"			CameraMatrix[0][2],"
			"			CameraMatrix[1][2],"
			"			CameraMatrix[2][2] "
			"		))"
			"	);"
			"	float depth = normalize(vertViewNormal).z;"
			"	vec3 ftrefl = vec3(0.9, 0.8, 0.7);"
			"	vec3 scatter = vec3(0.9, 0.6, 0.1);"
			"	vec3 bklt = vec3(0.8, 0.6, 0.4);"
			"	vec3 ambient = vec3(0.5, 0.4, 0.3);"
			"	fragColor = vec4("
			"		pow(max(ltexp, 0.0), 8.0)*ftrefl+"
			"		( ltexp+1.0)/ltlen*pow(depth,2.0)*scatter+"
			"		(-ltexp+1.0)/ltlen*(1.0-depth)*scatter+"
			"		(-lview+1.0)*0.6*(1.0-abs(depth))*bklt+"
			"		0.2*ambient,"
			"		1.0"
			"	);"
			"}"
		);
		fs_shape.Compile();

		shape_prog.AttachShader(vs_shape);
		shape_prog.AttachShader(fs_shape);
		shape_prog.Link();

		vs_plane.Source(
			"#version 140\n"
			"in vec4 Position;"
			"in vec3 Normal;"
			"uniform mat4 ProjectionMatrix, CameraMatrix;"
			"uniform vec3 LightPos;"
			"out vec3 vertNormal;"
			"out vec3 vertLight;"
			"void main(void)"
			"{"
			"	gl_Position = "
			"		ProjectionMatrix *"
			"		CameraMatrix *"
			"		Position;"
			"	vertNormal = Normal;"
			"	vertLight = LightPos-Position.xyz;"
			"}"
		);
		vs_plane.Compile();

		fs_plane.Source(
			"#version 140\n"
			"in vec3 vertNormal;"
			"in vec3 vertLight;"
			"out vec4 fragColor;"
			"void main(void)"
			"{"
			"	float l = sqrt(length(vertLight));"
			"	float e = dot("
			"		vertNormal,"
			"		normalize(vertLight)"
			"	);"
			"	float d = l > 0.0 ? e / l : 0.0;"
			"	float i = 0.2 + 2.5 * d;"
			"	fragColor = vec4(0.8*i, 0.7*i, 0.4*i, 1.0);"
			"}"
		);
		fs_plane.Compile();

		plane_prog.AttachShader(vs_plane);
		plane_prog.AttachShader(fs_plane);
		plane_prog.Link();

		vs_halo.Source(
			"#version 150\n"
			"in vec4 Position;"
			"in vec3 Normal;"
			"uniform mat4 ModelMatrix, CameraMatrix;"
			"out vec3 vertNormal;"
			"out float vd;"
			"void main(void)"
			"{"
			"	gl_Position = "
			"		CameraMatrix *"
			"		ModelMatrix *"
			"		Position;"
			"	vertNormal = ("
			"		CameraMatrix *"
			"		ModelMatrix *"
			"		vec4(Normal, 0.0)"
			"	).xyz;"
			"	vd = vertNormal.z;"
			"}"
		);
		vs_halo.Compile();

		gs_halo.Source(
			"#version 150\n"
			"layout(triangles) in;"
			"layout(triangle_strip, max_vertices = 12) out;"

			"in vec3 vertNormal[];"
			"in float vd[];"

			"uniform mat4 CameraMatrix, ProjectionMatrix;"
			"uniform vec3 LightPos;"

			"out float geomAlpha;"

			"void main(void)"
			"{"
			"	for(int v=0; v!=3; ++v)"
			"	{"
			"		int a = v, b = (v+1)%3, c = (v+2)%3;"
			"		vec4 pa = gl_in[a].gl_Position;"
			"		vec4 pb = gl_in[b].gl_Position;"
			"		vec4 pc = gl_in[c].gl_Position;"
			"		vec4 px, py;"
			"		vec3 na = vertNormal[a];"
			"		vec3 nb = vertNormal[b];"
			"		vec3 nc = vertNormal[c];"
			"		vec3 nx, ny;"
			"		if(vd[a] == 0.0 && vd[b] == 0.0)"
			"		{"
			"			px = pa;"
			"			nx = na;"
			"			py = pb;"
			"			ny = nb;"
			"		}"
			"		else if(vd[a] > 0.0 && vd[b] < 0.0)"
			"		{"
			"			float x = vd[a]/(vd[a]-vd[b]);"
			"			float y;"
			"			px = mix(pa, pb, x);"
			"			nx = mix(na, nb, x);"
			"			if(vd[c] < 0.0)"
			"			{"
			"				y = vd[a]/(vd[a]-vd[c]);"
			"				py = mix(pa, pc, y);"
			"				ny = mix(na, nc, y);"
			"			}"
			"			else"
			"			{"
			"				y = vd[c]/(vd[c]-vd[b]);"
			"				py = mix(pc, pb, y);"
			"				ny = mix(nc, nb, y);"
			"			}"
			"		}"
			"		else continue;"
			"		vec4 gx1 = vec4(px.xyz, 1.0);"
			"		vec4 gy1 = vec4(py.xyz, 1.0);"
			"		vec4 gx2 = vec4(px.xyz + nx*0.3, 1.0);"
			"		vec4 gy2 = vec4(py.xyz + ny*0.3, 1.0);"
			"		gl_Position = ProjectionMatrix * gy1;"
			"		geomAlpha = 1.0;"
			"		EmitVertex();"
			"		gl_Position = ProjectionMatrix * gx1;"
			"		geomAlpha = 1.0;"
			"		EmitVertex();"
			"		gl_Position = ProjectionMatrix * gy2;"
			"		geomAlpha = 0.0;"
			"		EmitVertex();"
			"		gl_Position = ProjectionMatrix * gx2;"
			"		geomAlpha = 0.0;"
			"		EmitVertex();"
			"		EndPrimitive();"
			"		break;"
			"	}"
			"}"
		);
		gs_halo.Compile();

		fs_halo.Source(
			"#version 150\n"
			"in float geomAlpha;"
			"out vec4 fragColor;"
			"void main(void)"
			"{"
			"	fragColor = vec4("
			"		0.5, 0.4, 0.3,"
			"		pow(geomAlpha, 2.0)"
			"	);"
			"}"
		);
		fs_halo.Compile();

		halo_prog.AttachShader(vs_halo);
		halo_prog.AttachShader(gs_halo);
		halo_prog.AttachShader(fs_halo);
		halo_prog.Link();

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

		// bind the VBO for the shape vertices
		shape_verts.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(VertexArrayAttrib::QueryCommonLocation(
				MakeGroup(shape_prog, halo_prog),
				"Position",
				location
			))
			{
				VertexArrayAttrib attr(location);
				attr.Setup<GLfloat>(n_per_vertex);
				attr.Enable();
			}
			else OGLPLUS_ABORT("Inconsistent 'Position' location");
		}

		// bind the VBO for the shape normals
		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();
			VertexArrayAttrib attr(shape_prog, "Normal");
			attr.Setup<GLfloat>(n_per_vertex);
			attr.Enable();
		}

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

		// bind the VBO for the plane vertices
		plane_verts.Bind(Buffer::Target::Array);
		{
			GLfloat data[4*3] = {
				-9.0f, 0.0f,  9.0f,
				-9.0f, 0.0f, -9.0f,
				 9.0f, 0.0f,  9.0f,
				 9.0f, 0.0f, -9.0f
			};
			Buffer::Data(Buffer::Target::Array, 4*3, data);
			plane_prog.Use();
			VertexArrayAttrib attr(plane_prog, "Position");
			attr.Setup<Vec3f>();
			attr.Enable();
		}

		// bind the VBO for the plane normals
		plane_normals.Bind(Buffer::Target::Array);
		{
			GLfloat data[4*3] = {
				-0.1f, 1.0f,  0.1f,
				-0.1f, 1.0f, -0.1f,
				 0.1f, 1.0f,  0.1f,
				 0.1f, 1.0f, -0.1f
			};
			Buffer::Data(Buffer::Target::Array, 4*3, data);
			plane_prog.Use();
			VertexArrayAttrib attr(plane_prog, "Normal");
			attr.Setup<Vec3f>();
			attr.Enable();
		}

		Vec3f lightPos(2.0f, 2.5f, 9.0f);

		ProgramUniform<Vec3f>(shape_prog, "LightPos").Set(lightPos);
		ProgramUniform<Vec3f>(plane_prog, "LightPos").Set(lightPos);

		gl.ClearColor(0.2f, 0.2f, 0.2f, 0.0f);
		gl.ClearDepth(1.0f);
		gl.ClearStencil(0);

		gl.Enable(Capability::DepthTest);
		gl.BlendFunc(BlendFn::SrcAlpha, BlendFn::One);
	}
Beispiel #19
0
	ParticlesExample(void)
	 : projection_matrix(prog, "ProjectionMatrix")
	 , camera_matrix(prog, "CameraMatrix")
	 , particle_count(100)
	 , prev_time(0.0)
	 , prev_spawn(0.0)
	{
		// Set the vertex shader source
		vs.Source(
			"#version 330\n"
			"uniform mat4 ModelMatrix, CameraMatrix;"
			"in vec4 Position;"
			"in float Age;"
			"out float vertAge;"
			"void main(void)"
			"{"
			"	gl_Position = "
			"		CameraMatrix *"
			"		ModelMatrix *"
			"		Position;"
			"	vertAge = Age;"
			"}"
		);
		// compile it
		vs.Compile();

		// Set the geometry shader source
		gs.Source(
			"#version 330\n"
			"layout(points) in;"
			"layout(triangle_strip, max_vertices = 4) out;"
			"uniform mat4 ProjectionMatrix;"
			"in float vertAge[];"
			"out float geomAge;"
			"void main(void)"
			"{"
			"	float s = 0.5;"
			"	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)"
			"	{"
			"		float xoffs = xo[i]*(1.0+vertAge[0])*s;"
			"		float yoffs = yo[j]*(1.0+vertAge[0])*s;"
			"		gl_Position = ProjectionMatrix * vec4("
			"			gl_in[0].gl_Position.x-xoffs,"
			"			gl_in[0].gl_Position.y-yoffs,"
			"			gl_in[0].gl_Position.z,"
			"			1.0"
			"		);"
			"		geomAge = vertAge[0];"
			"		EmitVertex();"
			"	}"
			"	EndPrimitive();"
			"}"
		);
		// compile it
		gs.Compile();

		// set the fragment shader source
		fs.Source(
			"#version 330\n"
			"in float geomAge;"
			"out vec4 fragColor;"
			"void main(void)"
			"{"
			"	vec3 Color1 = vec3(1.0, 0.5, 0.5);"
			"	vec3 Color2 = vec3(0.3, 0.1, 0.1);"
			"	fragColor = vec4("
			"		mix(Color1, Color2, geomAge),"
			"		1.0 - geomAge"
			"	);"
			"}"
		);
		// compile it
		fs.Compile();

		// attach the shaders to the program
		prog.AttachShader(vs);
		prog.AttachShader(gs);
		prog.AttachShader(fs);
		// link and use it
		prog.Link();
		prog.Use();

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

		// bind the VBO for the particle positions
		pos_buf.Bind(Buffer::Target::Array);
		{
			Buffer::Data(Buffer::Target::Array, positions);
			VertexAttribArray attr(prog, "Position");
			attr.Setup(3, DataType::Float);
			attr.Enable();
		}
		positions.reserve(particle_count);
		directions.reserve(particle_count);

		// bind the VBO for the particle ages
		age_buf.Bind(Buffer::Target::Array);
		{
			Buffer::Data(Buffer::Target::Array, ages);
			VertexAttribArray attr(prog, "Age");
			attr.Setup(1, DataType::Float);
			attr.Enable();
		}
		ages.reserve(particle_count);

		Uniform<Mat4f>(prog, "ModelMatrix").Set(
			ModelMatrixf::Translation(0.0f, -10.0f, 0.0f)
		);
		//
		gl.ClearColor(0.9f, 0.9f, 0.9f, 0.0f);
		gl.ClearDepth(1.0f);
		gl.Enable(Capability::DepthTest);
		gl.Enable(Capability::Blend);
		gl.BlendFunc(BlendFn::SrcAlpha, BlendFn::OneMinusSrcAlpha);
	}