void Reshape(GLuint vp_width, GLuint vp_height) {
        width = vp_width;
        height = vp_height;

        float aspect = float(width) / height;

        auto projection = CamMatrixf::PerspectiveX(Degrees(60), aspect, 1, 20);

        plane_projection_matrix.Set(projection);
        shape_projection_matrix.Set(projection);

        gl.Bound(Texture::Target::Rectangle, depth_tex)
          .Image2D(
            0,
            PixelDataInternalFormat::DepthComponent,
            width / tex_size_div,
            height / tex_size_div,
            0,
            PixelDataFormat::DepthComponent,
            PixelDataType::Float,
            nullptr);
        gl.Bound(Texture::Target::Rectangle, reflect_tex)
          .Image2D(
            0,
            PixelDataInternalFormat::RGB,
            width / tex_size_div,
            height / tex_size_div,
            0,
            PixelDataFormat::RGB,
            PixelDataType::UnsignedByte,
            nullptr);
    }
	Particles(GLuint n)
	 : count(n)
	 , sort_nw(n)
	{
		Context gl;
		const GLfloat irm = 1.0f/RAND_MAX;
		std::vector<GLfloat> pos_data(count*3);

		for(GLuint p=0; p!=count; ++p)
		{
			for(GLuint c=0; c!=3; ++c)
			{
				pos_data[p*3+c] = 2.0f*(0.5f-std::rand()*irm);
			}
		}

		gl.Bound(BufferTarget::Array, positions).Data(pos_data);
		gl.Bound(BufferTarget::Uniform, distances).Data<GLfloat>(
			count,
			nullptr,
			BufferUsage::DynamicDraw
		);
		gl.Bound(BufferTarget::CopyRead, indices_f).Data<GLuint>(
			count,
			nullptr,
			BufferUsage::DynamicRead
		);
		gl.Bound(BufferTarget::CopyWrite,indices_d).Data<GLuint>(
			count,
			nullptr,
			BufferUsage::DynamicDraw
		);

	}
Exemple #3
0
    BlobExample(const ExampleParams& params)
      : blob_prog()
      , metal_prog()
      , grid(blob_prog, params.quality)
      , plane(metal_prog) {
        std::srand(234);
        for(GLuint i = 0; i != 24; ++i) {
            GLuint j = 0, n = 3 + std::rand() % 3;
            std::vector<Vec4f> points(n);
            GLfloat ball_size = 0.15f * std::rand() / GLfloat(RAND_MAX) + 0.25f;

            while(j != n) {
                points[j] = Vec4f(
                  1.2f * std::rand() / GLfloat(RAND_MAX) - 0.6f,
                  1.2f * std::rand() / GLfloat(RAND_MAX) - 0.6f,
                  1.2f * std::rand() / GLfloat(RAND_MAX) - 0.6f,
                  ball_size);
                ++j;
            }
            ball_paths.push_back(CubicBezierLoop<Vec4f, double>(points));
        }
        //
        Texture::Active(1);
        blob_prog.metaballs.Set(1);
        gl.Bound(Texture::Target::_1D, metaballs_tex)
          .Filter(TextureFilter::Nearest)
          .Wrap(TextureWrap::ClampToEdge)
          .Image1D(
            0,
            PixelDataInternalFormat::RGBA32F,
            ball_paths.size(),
            0,
            PixelDataFormat::RGBA,
            PixelDataType::Float,
            nullptr);

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

        const Vec3f light_position(12.0, 1.0, 8.0);
        blob_prog.light_position.Set(light_position);
        metal_prog.light_position.Set(light_position);

        gl.ClearColor(0.8f, 0.7f, 0.6f, 0.0f);
        gl.ClearDepth(1.0f);
        gl.Enable(Capability::DepthTest);

        gl.Enable(Capability::CullFace);
        gl.FrontFace(FaceOrientation::CW);
        gl.CullFace(Face::Back);
    }
    ParallaxExample()
      : prog(make_prog())
      , projection_matrix(prog, "ProjectionMatrix")
      , camera_matrix(prog, "CameraMatrix")
      , camera_position(prog, "CameraPosition")
      , light_position(prog, "LightPosition")
      , shape(
          List("Position")("TexCoord").Get(),
          shapes::Plane(
            Vec3f(),
            Vec3f(1.0f, 0.0f, 0.0f),
            Vec3f(0.0f, 0.0f, -1.0f),
            32,
            32)) {
        shape.UseInProgram(prog);

        auto tex_image = images::LoadTexture("stones_color_hmap");

        Texture::Active(0);
        try {
            UniformSampler(prog, "ColorMap").Set(0);
            gl.Bound(Texture::Target::_2D, color_tex)
              .MinFilter(TextureMinFilter::LinearMipmapLinear)
              .MagFilter(TextureMagFilter::Linear)
              .WrapS(TextureWrap::Repeat)
              .WrapT(TextureWrap::Repeat)
              .Image2D(tex_image)
              .GenerateMipmap();
        } catch(Error&) {
        }

        Texture::Active(1);
        try {
            UniformSampler(prog, "BumpMap").Set(1);
            gl.Bound(Texture::Target::_2D, bump_tex)
              .MinFilter(TextureMinFilter::LinearMipmapLinear)
              .MagFilter(TextureMagFilter::Linear)
              .WrapS(TextureWrap::Repeat)
              .WrapT(TextureWrap::Repeat)
              .Image2D(
                images::NormalMap(tex_image, images::NormalMap::FromAlpha()))
              .GenerateMipmap();
        } catch(Error&) {
        }

        gl.ClearColor(0.1f, 0.1f, 0.1f, 0.0f);
        gl.ClearDepth(1.0f);

        (Capability::DepthTest) << true;
        (Capability::CullFace) << false;

        (Functionality::ClipDistance | 0) << true;
        (Functionality::ClipDistance | 1) << true;
        (Functionality::ClipDistance | 2) << true;
    }
void ShadowMapRenderer::SetupFramebuffers(const unsigned &w,
        const unsigned &h)
{
    using namespace oglplus;
    static Context gl;
    // save size
    shadowMapSize = glm::uvec2(w, h);
    // setup shadow framebuffer
    shadowFramebuffer.Bind(FramebufferTarget::Draw);
    // create render buffer for depth testing
    depthRender.Bind(RenderbufferTarget::Renderbuffer);
    depthRender.Storage(RenderbufferTarget::Renderbuffer,
                        PixelDataInternalFormat::DepthComponent24, w, h);
    // create variance shadow mapping texture, z and z * z
    gl.Bound(TextureTarget::_2D, shadowMap)
    .Image2D(0, PixelDataInternalFormat::RGBA32F, w, h, 0,
             PixelDataFormat::RGBA, PixelDataType::Float, nullptr);
    Filtering(filtering);
    Anisotropy(8);
    shadowFramebuffer.AttachColorTexture(FramebufferTarget::Draw, 0, shadowMap, 0);
    shadowFramebuffer.AttachRenderbuffer(FramebufferTarget::Draw,
                                         FramebufferAttachment::Depth,
                                         depthRender);
    gl.DrawBuffer(FramebufferColorAttachment::_0);

    // check if success building frame buffer
    if (!Framebuffer::IsComplete(FramebufferTarget::Draw))
    {
        auto status = Framebuffer::Status(FramebufferTarget::Draw);
        Framebuffer::HandleIncompleteError(FramebufferTarget::Draw, status);
    }

    Framebuffer::Bind(Framebuffer::Target::Draw, FramebufferName(0));
    // setup shadow blur framebuffer
    blurFramebuffer.Bind(FramebufferTarget::Draw);
    // create variance shadow mapping texture, z and z * z
    gl.Bound(TextureTarget::_2D, blurShadow)
    .Image2D(0, PixelDataInternalFormat::RGBA32F, w, h, 0,
             PixelDataFormat::RGBA, PixelDataType::Float, nullptr)
    .MinFilter(TextureMinFilter::Linear).MagFilter(TextureMagFilter::Linear)
    .WrapS(TextureWrap::ClampToEdge).WrapT(TextureWrap::ClampToEdge).Anisotropy(8);
    blurFramebuffer.AttachColorTexture(FramebufferTarget::Draw, 0, blurShadow, 0);
    gl.DrawBuffer(FramebufferColorAttachment::_0);

    // check if success building frame buffer
    if (!Framebuffer::IsComplete(FramebufferTarget::Draw))
    {
        auto status = Framebuffer::Status(FramebufferTarget::Draw);
        Framebuffer::HandleIncompleteError(FramebufferTarget::Draw, status);
    }

    Framebuffer::Bind(Framebuffer::Target::Draw, FramebufferName(0));
}
    ParallaxMapExample()
      : prog(make())
      , projection_matrix(prog, "ProjectionMatrix")
      , camera_matrix(prog, "CameraMatrix")
      , model_matrix(prog, "ModelMatrix")
      , camera_position(prog, "CameraPosition")
      , light_position(prog, "LightPosition")
      , shape(
          List("Position")("Normal")("Tangent")("TexCoord").Get(),
          shapes::Torus(1.0f, 0.5, 72, 48)) {
        shape.UseInProgram(prog);

        auto tex_image = images::LoadTexture("bricks_color_hmap");

        Texture::Active(0);
        try {
            UniformSampler(prog, "ColorMap").Set(0);
            gl.Bound(Texture::Target::_2D, color_tex)
              .MinFilter(TextureMinFilter::LinearMipmapLinear)
              .MagFilter(TextureMagFilter::Linear)
              .WrapS(TextureWrap::Repeat)
              .WrapT(TextureWrap::Repeat)
              .Image2D(tex_image)
              .GenerateMipmap();
        } catch(Error&) {
        }

        Texture::Active(1);
        try {
            UniformSampler(prog, "BumpMap").Set(1);
            gl.Bound(Texture::Target::_2D, bump_tex)
              .MinFilter(TextureMinFilter::LinearMipmapLinear)
              .MagFilter(TextureMagFilter::Linear)
              .WrapS(TextureWrap::Repeat)
              .WrapT(TextureWrap::Repeat)
              .Image2D(
                images::NormalMap(tex_image, images::NormalMap::FromAlpha()))
              .GenerateMipmap();
        } catch(Error&) {
        }

        gl.ClearColor(0.1f, 0.1f, 0.1f, 0.0f);
        gl.ClearDepth(1.0f);
        gl.Enable(Capability::DepthTest);
        gl.Disable(Capability::CullFace);

        gl.Enable(Functionality::ClipDistance, 0);
        gl.Enable(Functionality::ClipDistance, 1);
        gl.Enable(Functionality::ClipDistance, 2);
    }
Exemple #7
0
	LiquidExample(const ExampleParams& params)
	 : liquid_prog()
	 , grid(liquid_prog, params.quality)
	 , grid_repeat(int(1 + params.quality*2))
	{
		Texture::Active(1);
		{
			auto image = images::Squares(512, 512, 0.9f, 8, 8);
			auto bound_tex = gl.Bound(Texture::Target::CubeMap, env_map);
			for(int i=0; i!=6; ++i)
				Texture::ImageCM(i, image);
			bound_tex.GenerateMipmap();
			bound_tex.MinFilter(TextureMinFilter::LinearMipmapLinear);
			bound_tex.MagFilter(TextureMagFilter::Linear);
			bound_tex.WrapS(TextureWrap::ClampToEdge);
			bound_tex.WrapT(TextureWrap::ClampToEdge);
			bound_tex.WrapR(TextureWrap::ClampToEdge);
			bound_tex.SwizzleG(TextureSwizzle::Red);
			bound_tex.SwizzleB(TextureSwizzle::Red);
		}
		ProgramUniformSampler(liquid_prog, "EnvMap").Set(1);

		const Vec3f light_position(12.0, 1.0, 8.0);
		liquid_prog.light_position.Set(light_position);

		gl.ClearColor(0.7f, 0.65f, 0.55f, 0.0f);
		gl.ClearDepth(1.0f);
		gl.Enable(Capability::DepthTest);

		gl.Enable(Capability::CullFace);
		gl.FrontFace(FaceOrientation::CW);
		gl.CullFace(Face::Back);
	}
Exemple #8
0
llvm_value CompileExpression::DoName(Name *what)
// ----------------------------------------------------------------------------
//   Compile a name
// ----------------------------------------------------------------------------
{
    Prefix_p   where;
    Infix_p    rewrite;
    Context   *context  = unit->context;
    Tree      *existing = context->Bound(what, true, &rewrite, &where);

    assert(existing || !"Type checking didn't realize a name is missing");
    Tree *from = RewriteDefined(rewrite->left);
    if (where == context->CurrentScope())
        if (llvm_value result = unit->Known(from))
            return result;

    // Check true and false values
    if (existing == eliot_true)
        return ConstantInt::get(unit->compiler->booleanTy, 1);
    if (existing == eliot_false)
        return ConstantInt::get(unit->compiler->booleanTy, 0);

    // Check if it is a global
    if (llvm_value global = unit->Global(existing))
        return global;
    if (llvm_value global = unit->Global(from))
        return global;

    // If we are in a context building a closure, record dependency
    if (unit->closureTy)
        return unit->NeedClosure(from);

    return DoCall(what);
}
Exemple #9
0
llvm_value CompileExpression::DoName(Name *what)
// ----------------------------------------------------------------------------
//   Compile a name
// ----------------------------------------------------------------------------
{
    Context_p  where;
    Rewrite_p  rewrite;
    Context   *context  = unit->context;
    Tree      *existing = context->Bound(what, Context::SCOPE_LOOKUP,
                                         &where, &rewrite);
    assert(existing || !"Type checking didn't realize a name is missing");
    if (where == context)
        if (llvm_value result = unit->Known(rewrite->from))
            return result;

    // Check true and false values
    if (existing == xl_true)
        return ConstantInt::get(unit->compiler->booleanTy, 1);
    if (existing == xl_false)
        return ConstantInt::get(unit->compiler->booleanTy, 0);

    // Check if it is a global
    if (llvm_value global = unit->Global(existing))
        return global;

    // If we are in a context building a closure, record dependency
    if (unit->closureTy)
        return unit->NeedClosure(rewrite->from);

    return DoCall(what);
}
void ShadowMapRenderer::Anisotropy(const int &val) const
{
    using namespace oglplus;
    static Context gl;
    gl.Bound(TextureTarget::_2D, shadowMap)
    .Anisotropy(static_cast<float>(val));
}
	FBTexThread(FBTexExample& example)
	 : gl()
	 , prog(make_prog(example))
	 , projection_matrix(prog, "ProjectionMatrix")
	 , camera_matrix(prog, "CameraMatrix")
	 , model_matrix(prog, "ModelMatrix")
	 , shape(List("Position")("Normal")("TexCoord").Get(), shapes::TwistedTorus(), prog)
	 , tex_side(512)
	 , parent_ready(example.parent_ready)
	{
		example.thread_ready = &thread_ready;

		Uniform<Vec3f>(prog, "LightPos").Set(20.0f, 30.0f, 40.0f);

		Texture::Active(0);
		gl.Bound(Texture::Target::_2D, example.tex)
			.MinFilter(TextureMinFilter::Linear)
			.MagFilter(TextureMagFilter::Linear)
			.WrapS(TextureWrap::Repeat)
			.WrapT(TextureWrap::Repeat)
			.Image2D(
				0,
				PixelDataInternalFormat::RGBA,
				tex_side, tex_side,
				0,
				PixelDataFormat::RGBA,
				PixelDataType::UnsignedByte,
				nullptr
			);

		gl.Bound(Renderbuffer::Target::Renderbuffer, rbo)
 			.Storage(
				PixelDataInternalFormat::DepthComponent,
				tex_side,
				tex_side
			);

		gl.Bound(Framebuffer::Target::Draw, fbo)
			.AttachTexture(FramebufferAttachment::Color, example.tex, 0)
			.AttachRenderbuffer(FramebufferAttachment::Depth, rbo);

		Use();
	}
	SortNWTex(GLuint n)
	{
		images::Image sort_nw_map = images::SortNWMap(n);
		pass_count = sort_nw_map.Height();

		Context gl;
		Texture::Active(0);
		gl.Bound(TextureTarget::Rectangle, self())
			.Filter(TextureFilter::Nearest)
			.WrapS(TextureWrap::ClampToEdge)
			.WrapT(TextureWrap::ClampToEdge)
			.Image2D(sort_nw_map);
	}
void ShadowMapRenderer::Filtering(const int &val)
{
    using namespace oglplus;
    static Context gl;
    filtering = glm::clamp(val, 0, 2);

    if(filtering == 0)
        gl.Bound(TextureTarget::_2D, shadowMap)
        .MagFilter(TextureMagFilter::Nearest)
        .MinFilter(TextureMinFilter::Nearest);

    if(filtering == 1)
        gl.Bound(TextureTarget::_2D, shadowMap)
        .MagFilter(TextureMagFilter::Linear)
        .MinFilter(TextureMinFilter::Linear);

    if(filtering == 2)
        gl.Bound(TextureTarget::_2D, shadowMap)
        .MagFilter(TextureMagFilter::Linear)
        .MinFilter(TextureMinFilter::LinearMipmapLinear)
        .GenerateMipmap();
}
Exemple #14
0
    void UpdateMetaballs(double time) {
        std::size_t metaball_count = ball_paths.size(), k = 0;
        std::vector<GLfloat> metaballs(metaball_count * 4);
        for(std::size_t ball = 0; ball != metaball_count; ++ball) {
            Vec4f pos = ball_paths[ball].Position(time / 21.0);

            for(GLuint coord = 0; coord != 4; ++coord)
                metaballs[k++] = pos.At(coord);
        }

        gl.Bound(Texture::Target::_1D, metaballs_tex)
          .Image1D(
            0,
            PixelDataInternalFormat::RGBA32F,
            metaball_count,
            0,
            PixelDataFormat::RGBA,
            PixelDataType::Float,
            metaballs.data());
    }
Exemple #15
0
	CubeExample(void)
	 : cube(
		List("Position")("Normal")("TexCoord").Get(),
		shapes::Cube(),
		cube_prog
	)
	{
		// setup the texture
		{
			GLuint tex_side = 512;
			auto image = images::NewtonFractal(
				tex_side, tex_side,
				Vec3f(0.2f, 0.1f, 0.4f),
				Vec3f(0.8f, 0.8f, 1.0f),
				Vec2f(-1.0f, -1.0f),
				Vec2f( 1.0f,  1.0f),
				images::NewtonFractal::X4Minus1(),
				images::NewtonFractal::DefaultMixer()
			);

			gl.Bound(Texture::Target::_2D, cube_tex)
				.Image2D(image)
				.GenerateMipmap()
				.BorderColor(Vec4f(0.8f, 0.8f, 1.0f, 1.0f))
				.MinFilter(TextureMinFilter::LinearMipmapLinear)
				.MagFilter(TextureMagFilter::Linear)
				.WrapS(TextureWrap::Repeat)
				.WrapT(TextureWrap::Repeat);
		}

		cube_prog.cube_tex = 0;
		cube_prog.light_position.Set(4.0f, 4.0f, -8.0f);

		gl.ClearColor(0.8f, 0.8f, 0.7f, 0.0f);
		gl.ClearDepth(1.0f);
		gl.Enable(Capability::DepthTest);
		gl.Enable(Capability::CullFace);
		gl.CullFace(Face::Back);
	}
    CubeExample()
      : cube_instr(make_cube.Instructions())
      , cube_indices(make_cube.Indices())
      , prog(make())
      , projection_matrix(prog, "ProjectionMatrix")
      , camera_matrix(prog, "CameraMatrix")
      , model_matrix(prog, "ModelMatrix")
      , light_pos(prog, "LightPos") {
        // 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);
            (prog | "Position").Setup<GLfloat>(n_per_vertex).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);
            (prog | "Normal").Setup<GLfloat>(n_per_vertex).Enable();
        }

        gl.Bind(Buffer::Target::Array, tangents);
        {
            std::vector<GLfloat> data;
            GLuint n_per_vertex = make_cube.Tangents(data);
            Buffer::Data(Buffer::Target::Array, data);
            (prog | "Tangent").Setup<GLfloat>(n_per_vertex).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);
            (prog | "TexCoord").Setup<GLfloat>(n_per_vertex).Enable();
        }

        {
            auto img = images::SphereBumpMap(512, 512, 2, 2);
            Uniform<GLsizei>(prog, "BumpTexWidth").Set(img.Width());
            Uniform<GLsizei>(prog, "BumpTexHeight").Set(img.Height());
            UniformSampler(prog, "BumpTex").Set(0);
            Texture::Active(0);

            gl.Bound(Texture::Target::_2D, bumpTex)
              .MinFilter(TextureMinFilter::LinearMipmapLinear)
              .MagFilter(TextureMagFilter::Linear)
              .WrapS(TextureWrap::Repeat)
              .WrapT(TextureWrap::Repeat)
              .Image2D(img)
              .GenerateMipmap();
        }
        //
        gl.ClearColor(0.1f, 0.1f, 0.1f, 0.0f);
        gl.ClearDepth(1.0f);
        gl.Enable(Capability::DepthTest);

        gl.Enable(Capability::CullFace);
        gl.FrontFace(make_cube.FaceWinding());
    }
Exemple #17
0
    SkyBoxExample()
      : sky_box(List("Position").Get(), shapes::SkyBox())
      , shape(List("Position")("Normal").Get(), shapes::WickerTorus())
      , sky_box_prog()
      , sky_box_projection_matrix(sky_box_prog, "ProjectionMatrix")
      , sky_box_camera_matrix(sky_box_prog, "CameraMatrix")
      , shape_projection_matrix(shape_prog, "ProjectionMatrix")
      , shape_camera_matrix(shape_prog, "CameraMatrix")
      , shape_model_matrix(shape_prog, "ModelMatrix")
      , sky_box_sun_position(sky_box_prog, "SunPosition")
      , shape_sun_position(shape_prog, "SunPosition")
      , shape_camera_position(shape_prog, "CameraPosition") {
        VertexShader sky_box_vs;
        sky_box_vs.Source(
          "#version 140\n"
          "uniform mat4 ProjectionMatrix, CameraMatrix;"
          "mat4 Matrix = ProjectionMatrix*CameraMatrix;"

          "in vec3 Position;"
          "out vec3 vertTexCoord;"
          "void main()"
          "{"
          "	gl_Position = Matrix * vec4(Position * 100.0, 1.0);"
          "	vertTexCoord = Position;"
          "}");
        sky_box_vs.Compile();
        sky_box_prog.AttachShader(sky_box_vs);

        VertexShader shape_vs;
        shape_vs.Source(
          "#version 140\n"

          "uniform vec3 SunPosition;"
          "uniform vec3 CameraPosition;"
          "uniform mat4  ProjectionMatrix,CameraMatrix,ModelMatrix;"

          "in vec4 Position;"
          "in vec3 Normal;"

          "out vec3 vertNormal, vertViewRefl, vertLightDir;"

          "void main()"
          "{"
          "	gl_Position = ModelMatrix * Position;"
          "	vertNormal = mat3(ModelMatrix)*Normal;"
          "	vertViewRefl = reflect("
          "		gl_Position.xyz - CameraPosition,"
          "		vertNormal"
          "	);"
          "	vertLightDir = SunPosition - gl_Position.xyz;"
          "	gl_Position = ProjectionMatrix*CameraMatrix*gl_Position;"
          "}");
        shape_vs.Compile();
        shape_prog.AttachShader(shape_vs);

        FragmentShader sky_box_fs;
        sky_box_fs.Source(
          "#version 140\n"

          "in vec3 vertTexCoord;"

          "out vec3 fragColor;"

          "vec3 sky_color(vec3 vd);"

          "void main()"
          "{"
          "	fragColor = sky_color(normalize(vertTexCoord));"
          "}");
        sky_box_fs.Compile();
        sky_box_prog.AttachShader(sky_box_fs);

        FragmentShader shape_fs;
        shape_fs.Source(
          "#version 140\n"

          "in vec3 vertNormal, vertViewRefl, vertLightDir;"

          "out vec3 fragColor;"

          "vec3 sky_color(vec3 vd);"

          "void main()"
          "{"
          "	float l = max(dot(normalize(vertNormal), "
          "normalize(vertLightDir))+0.1, 0.0);"
          "	float a = 0.1;"
          "	fragColor = "
          "		0.1*vec3(1.0, 1.0, 1.0)*(a+l)+"
          "		0.9*sky_color(normalize(vertViewRefl));"
          "}");
        shape_fs.Compile();
        shape_prog.AttachShader(shape_fs);

        FragmentShader sky_fs;
        sky_fs.Source(
          "#version 140\n"

          "const float WorldRadius = 6371000;"
          "const float AtmThickness = 50000;"
          "const vec3 AirColor = vec3(0.32, 0.36, 0.45);"
          "const vec3 LightColor = vec3(1.0, 1.0, 1.0);"

          "uniform vec3 SunPosition;"

          "uniform samplerCube EnvMap;"

          "float atm_intersection(vec3 v)"
          "{"
          "	const vec3 c = vec3(0.0, -WorldRadius, 0.0);"
          "	const float r = WorldRadius + AtmThickness;"
          "	const float c_c = dot(-c, -c);"
          "	float v_c = dot( v, -c);"
          "	return (-v_c + sqrt(v_c*v_c - c_c + r*r))/AtmThickness;"
          "}"

          "vec3 sky_color(vec3 vd)"
          "{"
          "	vec3 up = vec3(0.0, 1.0, 0.0);"
          "	vec3 ld = normalize(SunPosition);"
          "	vec4 cl = texture(EnvMap, vd);"
          "	float ai = atm_intersection(vd);"
          "	float al = max(dot(ld, up) + 0.12, 0.0);"
          "	float vl = max(dot(vd, ld), 0.0);"
          "	float ct = (1.0-cl.a)*cl.b;"
          "	vec3 ac = max(LightColor-AirColor*pow(ai, 0.33), vec3(0.0, 0.0, "
          "0.0));"

          "	vec3 Sun = "
          "		ac*(vl>0.995+0.004*al ? 1.0:0.0);"

          "	vec3 Air = "
          "		min(AirColor*sqrt(pow(al,0.25)*ai), vec3(al, al, al)*1.5)+"
          "		ac*pow(min(vl+0.001*ai, 1.0), 1024.0/pow(ai, 2.0))+"
          "		ac*(vl/(1.0+pow(3.0*al, 8.0)))*pow(ai, 0.6)*0.5;"

          "	vec3 Clouds ="
          "		ac*pow(min(vl*(cl.g+cl.b), 1.015), 64.0)*pow(ct, 2.0)+"
          "		ac*pow(min(vl*cl.g+cl.b, 1.020), 32.0)*ct+"
          "		ac*pow(min(vl*cl.g*cl.b, 1.010), 16.0)*pow(ct, 0.5)+"
          "		ac*0.7*min(cl.g + cl.b*0.5, 1.0)*al+"
          "		ac*(cl.g*(1.0-cl.b*0.2)*5.0)*pow(1.0-al, 2.0)*(al)+"
          "		LightColor*0.5*min(al + cl.g*0.4+cl.b*0.1, 1.0)*sqrt(al);"

          "	return mix(Air, Clouds, cl.a*(1.0-cl.r*0.8))+Sun*(1.0-cl.a);"
          "}");
        sky_fs.Compile();
        sky_box_prog.AttachShader(sky_fs);
        shape_prog.AttachShader(sky_fs);

        sky_box_prog.Link();
        sky_box.UseInProgram(sky_box_prog);

        shape_prog.Link();
        shape.UseInProgram(shape_prog);

        {
            ProgramUniformSampler(sky_box_prog, "EnvMap").Set(0);
            ProgramUniformSampler(shape_prog, "EnvMap").Set(0);
            Texture::Active(0);

            gl.Bound(Texture::Target::CubeMap, env_map)
              .MinFilter(TextureMinFilter::Linear)
              .MagFilter(TextureMagFilter::Linear)
              .WrapS(TextureWrap::ClampToEdge)
              .WrapT(TextureWrap::ClampToEdge)
              .WrapR(TextureWrap::ClampToEdge);

            Texture::ImageCM(
              0, images::LoadTexture("clouds01-cm_0", false, false));
            Texture::ImageCM(
              1, images::LoadTexture("clouds01-cm_1", false, false));
            Texture::ImageCM(
              2, images::LoadTexture("clouds01-cm_2", false, false));
            Texture::ImageCM(
              3, images::LoadTexture("clouds01-cm_3", false, false));
            Texture::ImageCM(
              4, images::LoadTexture("clouds01-cm_4", false, false));
            Texture::ImageCM(
              5, images::LoadTexture("clouds01-cm_5", false, false));
        }

        gl.ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        gl.ClearDepth(1.0f);
        gl.Enable(Capability::DepthTest);
    }
    MetaballExample(void)
    {
        for(GLuint i=0; i!=64; ++i)
        {
            GLuint j = 0, n = 3+std::rand()%3;
            std::vector<Vec4f> points(n);
            while(j != n)
            {
                points[j] = Vec4f(
                                1.4*std::rand()/GLdouble(RAND_MAX) - 0.7,
                                1.4*std::rand()/GLdouble(RAND_MAX) - 0.7,
                                0.0,
                                0.1*std::rand()/GLdouble(RAND_MAX) + 0.1
                            );
                ++j;
            }
            ball_paths.push_back(CubicBezierLoop<Vec4f, double>(points));
            ++i;
        }

        // Set the vertex shader source
        vs.Source(
            "#version 330\n"
            "in vec2 Position;"
            "out vec3 vertPosition;"
            "void main(void)"
            "{"
            "	vertPosition = vec3(Position, 0.0);"
            "	gl_Position = vec4(vertPosition, 1.0);"
            "}"
        );
        // compile it
        vs.Compile();

        // set the fragment shader source
        fs.Source(
            "#version 330\n"
            "uniform sampler1D Metaballs;"
            "in vec3 vertPosition;"
            "out vec3 fragColor;"

            "const vec3 AmbientColor = vec3(0.3, 0.4, 0.9);"
            "const vec3 DiffuseColor = vec3(0.5, 0.6, 1.0);"
            "const vec3 LightDir = normalize(vec3(1.0, 1.0, 1.0));"

            "void main(void)"
            "{"
            "	int i = 0, n = textureSize(Metaballs, 0);"

            "	float InvN = 1.0/n;"
            "	float Value = 0.0;"
            "	vec3 Normal = vec3(0.0, 0.0, 0.0);"
            "	while(i != n)"
            "	{"
            "		vec4 Metaball = texelFetch(Metaballs, i, 0);"
            "		float Radius = Metaball.w;"
            "		vec3 Vect = vertPosition - Metaball.xyz;"
            "		float Tmp = pow(Radius,2.0)/dot(Vect, Vect)-0.25;"
            "		Value += Tmp;"
            "		float Mul = max(Tmp, 0.0);"
            "		Normal += Mul*vec3(Vect.xy, Mul*InvN/Radius);"
            "		++i;"
            "	}"
            "	if(Value > 0.0)"
            "	{"
            "		float Diffuse = 1.4*max(dot("
            "			LightDir,"
            "			normalize(Normal)"
            "		), 0.0);"
            "		float Ambient = 0.3;"
            "		fragColor = "
            "			Ambient*AmbientColor+"
            "			Diffuse*DiffuseColor;"
            "	}"
            "	else fragColor = vec3(0.4, 0.4, 0.4);"
            "}"
        );
        // compile it
        fs.Compile();

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

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

        GLfloat rectangle_verts[8] = {
            -1.0f, -1.0f,
            -1.0f,  1.0f,
            1.0f, -1.0f,
            1.0f,  1.0f
        };
        // bind the VBO for the rectangle vertices
        verts.Bind(Buffer::Target::Array);
        // upload the data
        Buffer::Data(Buffer::Target::Array, rectangle_verts);
        // setup the vertex attribs array for the vertices
        VertexArrayAttrib vert_attr(prog, "Position");
        vert_attr.Setup<Vec2f>().Enable();
        //
        Texture::Active(0);
        UniformSampler(prog, "Metaballs").Set(0);

        gl.Bound(Texture::Target::_1D, metaballs_tex)
        .MinFilter(TextureMinFilter::Nearest)
        .MagFilter(TextureMagFilter::Nearest)
        .WrapS(TextureWrap::MirroredRepeat)
        .Image1D(
            0,
            InternalFormat::RGBA32F,
            ball_paths.size(),
            0,
            Format::RGBA,
            DataType::Float,
            nullptr
        );

        gl.Disable(Capability::DepthTest);
    }
	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());
	}
    ReflectionExample()
      : make_plane(
          Vec3f(), Vec3f(3.0f, 0.0f, 0.0f), Vec3f(0.0f, 0.0f, -3.0f), 15, 15)
      , plane_instr(make_plane.Instructions())
      , plane_indices(make_plane.Indices())
      , make_shape()
      , shape_instr(make_shape.Instructions())
      , shape_indices(make_shape.Indices())
      , plane_vs(ObjectDesc("Plane vertex"))
      , shape_vs(ObjectDesc("Shape vertex"))
      , plane_fs(ObjectDesc("Plane fragment"))
      , shape_fs(ObjectDesc("Shape fragment"))
      , plane_projection_matrix(plane_prog)
      , plane_camera_matrix(plane_prog)
      , plane_model_matrix(plane_prog)
      , shape_projection_matrix(shape_prog)
      , shape_camera_matrix(shape_prog)
      , shape_model_matrix(shape_prog)
      , width(800)
      , height(600)
      , tex_size_div(2) {
        plane_vs.Source(
          "#version 140\n"
          "uniform vec3 LightPosition;"
          "uniform mat4 ProjectionMatrix, CameraMatrix, ModelMatrix;"
          "in vec4 Position;"
          "out vec3 vertLightDir;"
          "out vec4 vertTexCoord;"
          "void main()"
          "{"
          "	gl_Position = ModelMatrix*Position;"
          "	vertLightDir = LightPosition - gl_Position.xyz;"
          "	gl_Position = ProjectionMatrix * CameraMatrix * gl_Position;"
          "	vertTexCoord = gl_Position;"
          "}");
        plane_vs.Compile();

        plane_fs.Source(
          "#version 140\n"
          "uniform sampler2DRect ReflectTex;"
          "uniform vec3 Normal;"
          "in vec3 vertLightDir;"
          "in vec4 vertTexCoord;"
          "out vec3 fragColor;"
          "const int n = 5;"
          "const int ns = (n*n);"
          "const float blur = 0.15/n;"
          "void main()"
          "{"
          "	float d = dot(Normal, normalize(vertLightDir));"
          "	float intensity = 0.5 + pow(1.4*d, 2.0);"
          "	vec3 color = vec3(0.0, 0.0, 0.0);"
          "	int n = 2;"
          "	float pct = 0.5/vertTexCoord.w;"
          "	for(int y=-n; y!=(n+1); ++y)"
          "	for(int x=-n; x!=(n+1); ++x)"
          "	{"
          "		vec2 coord = vertTexCoord.xy;"
          "		coord += vec2(blur*x, blur*y);"
          "		coord *= pct;"
          "		coord += vec2(0.5, 0.5);"
          "		coord *= textureSize(ReflectTex);"
          "		color += texture(ReflectTex, coord).rgb/ns;"
          "	}"
          "	fragColor = color*intensity;"
          "}");
        plane_fs.Compile();

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

        plane_projection_matrix.BindTo("ProjectionMatrix");
        plane_camera_matrix.BindTo("CameraMatrix");
        plane_model_matrix.BindTo("ModelMatrix");

        Vec3f lightPos(3.0f, 0.5f, 2.0f);
        Uniform<Vec3f>(plane_prog, "LightPosition").Set(lightPos);
        Uniform<Vec3f>(plane_prog, "Normal").Set(make_plane.Normal());

        plane.Bind();

        plane_verts.Bind(Buffer::Target::Array);
        {
            std::vector<GLfloat> data;
            GLuint n_per_vertex = make_plane.Positions(data);
            Buffer::Data(Buffer::Target::Array, data);
            VertexArrayAttrib attr(plane_prog, "Position");
            attr.Setup<GLfloat>(n_per_vertex);
            attr.Enable();
        }
        //
        Texture::Active(1);
        gl.Bound(Texture::Target::Rectangle, depth_tex)
          .MinFilter(TextureMinFilter::Linear)
          .MagFilter(TextureMagFilter::Linear)
          .WrapS(TextureWrap::ClampToEdge)
          .WrapT(TextureWrap::ClampToEdge);

        Texture::Active(0);
        ProgramUniformSampler(plane_prog, "ReflectTex").Set(0);
        gl.Bound(Texture::Target::Rectangle, reflect_tex)
          .MinFilter(TextureMinFilter::Linear)
          .MagFilter(TextureMagFilter::Linear)
          .WrapS(TextureWrap::ClampToEdge)
          .WrapT(TextureWrap::ClampToEdge);

        gl.Bound(Framebuffer::Target::Draw, fbo)
          .AttachTexture(FramebufferAttachment::Color, reflect_tex, 0)
          .AttachTexture(FramebufferAttachment::Depth, depth_tex, 0);

        shape_vs.Source(
          "#version 140\n"
          "uniform vec3 LightPosition;"
          "uniform mat4 ProjectionMatrix, ModelMatrix, CameraMatrix;"
          "in vec4 Position;"
          "in vec3 Normal;"
          "out vec3 vertNormal;"
          "out vec3 vertLightDir;"
          "out vec3 vertLightRefl;"
          "out vec3 vertViewDir;"
          "out vec3 vertColor;"
          "void main()"
          "{"
          "	gl_Position = ModelMatrix * Position;"
          "	vertLightDir = LightPosition - gl_Position.xyz;"
          "	vertNormal = mat3(ModelMatrix)*Normal;"
          "	vertLightRefl = reflect("
          "		-normalize(vertLightDir),"
          "		normalize(vertNormal)"
          "	);"
          "	vertViewDir = (vec4(0.0, 0.0, 1.0, 1.0)*CameraMatrix).xyz;"
          "	vertColor = vec3(1, 1, 1) - vertNormal;"
          "	gl_Position = ProjectionMatrix * CameraMatrix * gl_Position;"
          "}");
        shape_vs.Compile();

        shape_fs.Source(
          "#version 140\n"
          "in vec3 vertNormal;"
          "in vec3 vertLightDir;"
          "in vec3 vertLightRefl;"
          "in vec3 vertViewDir;"
          "in vec3 vertColor;"
          "out vec3 fragColor;"

          "void main()"
          "{"
          "	float l = length(vertLightDir);"
          "	float d = dot("
          "		normalize(vertNormal), "
          "		normalize(vertLightDir)"
          "	) / l;"
          "	float s = dot("
          "		normalize(vertLightRefl),"
          "		normalize(vertViewDir)"
          "	);"
          "	vec3 lt = vec3(1.0, 1.0, 1.0);"
          "	fragColor = "
          "		vertColor * 0.4 + "
          "		(lt + vertColor)*pow(max(2.5*d, 0.0), 3) + "
          "		lt * pow(max(s, 0.0), 64);"
          "}");
        shape_fs.Compile();

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

        shape_projection_matrix.BindTo("ProjectionMatrix");
        shape_camera_matrix.BindTo("CameraMatrix");
        shape_model_matrix.BindTo("ModelMatrix");

        Uniform<Vec3f>(shape_prog, "LightPosition").Set(lightPos);

        shape.Bind();

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

        shape_normals.Bind(Buffer::Target::Array);
        {
            std::vector<GLfloat> data;
            GLuint n_per_vertex = make_shape.Normals(data);
            Buffer::Data(Buffer::Target::Array, data);
            VertexArrayAttrib attr(shape_prog, "Normal");
            attr.Setup<GLfloat>(n_per_vertex);
            attr.Enable();
        }
        //
        gl.ClearColor(0.5f, 0.5f, 0.4f, 0.0f);
        gl.ClearDepth(1.0f);
        gl.Enable(Capability::DepthTest);
        gl.Enable(Capability::CullFace);
    }
	GlassExample(void)
	 : make_plane(Vec3f(2.0f, 0.0f, 0.0f), Vec3f(0.0f, 0.0f, -2.0f))
	 , plane_instr(make_plane.Instructions())
	 , plane_indices(make_plane.Indices())
	 , make_shape()
	 , shape_instr(make_shape.Instructions())
	 , shape_indices(make_shape.Indices())
	 , plane_vs(ObjectDesc("Plane vertex"))
	 , shape_vs(ObjectDesc("Shape vertex"))
	 , plane_fs(ObjectDesc("Plane fragment"))
	 , shape_fs(ObjectDesc("Shape fragment"))
	 , plane_proj_matrix(plane_prog)
	 , plane_camera_matrix(plane_prog)
	 , plane_model_matrix(plane_prog)
	 , shape_proj_matrix(shape_prog)
	 , shape_camera_matrix(shape_prog)
	 , shape_model_matrix(shape_prog)
	 , shape_clip_plane(shape_prog)
	 , shape_clip_direction(shape_prog)
	 , width(512)
	 , height(512)
	 , tex_side(512)
	{
		plane_vs.Source(
			"#version 140\n"
			"uniform vec3 LightPosition;"
			"uniform mat4 ProjectionMatrix, CameraMatrix, ModelMatrix;"
			"in vec4 Position;"
			"in vec2 TexCoord;"
			"out vec3 vertLightDir;"
			"out vec2 vertTexCoord;"
			"void main(void)"
			"{"
			"	gl_Position = "
			"		ModelMatrix* "
			"		Position;"
			"	vertLightDir = normalize("
			"		LightPosition - gl_Position.xyz"
			"	);"
			"	gl_Position = "
			"		ProjectionMatrix *"
			"		CameraMatrix *"
			"		gl_Position;"
			"	vertTexCoord = TexCoord;"
			"}"
		);
		plane_vs.Compile();

		plane_fs.Source(
			"#version 140\n"
			"uniform vec3 Normal;"
			"in vec3 vertLightDir;"
			"in vec2 vertTexCoord;"
			"out vec4 fragColor;"
			"void main(void)"
			"{"
			"	float checker = ("
			"		int(vertTexCoord.x*18) % 2+"
			"		int(vertTexCoord.y*18) % 2"
			"	) % 2;"
			"	vec3 color = mix("
			"		vec3(0.2, 0.4, 0.9),"
			"		vec3(0.2, 0.2, 0.7),"
			"		checker"
			"	);"
			"	float d = dot("
			"		Normal, "
			"		vertLightDir"
			"	);"
			"	float intensity = 0.5 + pow(1.4*d, 2.0);"
			"	fragColor = vec4(color*intensity, 1.0);"
			"}"
		);
		plane_fs.Compile();

		plane_prog.AttachShader(plane_vs);
		plane_prog.AttachShader(plane_fs);
		plane_prog.Link();
		plane_prog.Use();
		plane_proj_matrix.BindTo("ProjectionMatrix");
		plane_camera_matrix.BindTo("CameraMatrix");
		plane_model_matrix.BindTo("ModelMatrix");

		Vec3f lightPos(3.0f, 3.0f, 3.0f);
		Uniform<Vec3f>(plane_prog, "LightPosition").Set(lightPos);
		Uniform<Vec3f>(plane_prog, "Normal").Set(make_plane.Normal());

		gl.Bind(plane);

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

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

		shape_vs.Source(
			"#version 140\n"
			"uniform vec3 LightPosition;"
			"uniform mat4 ProjectionMatrix, ModelMatrix, CameraMatrix;"
			"uniform vec4 ClipPlane;"
			"uniform float ClipDirection;"
			"in vec4 Position;"
			"in vec3 Normal;"
			"out vec3 vertNormal;"
			"out vec3 vertLightDir;"
			"out vec3 vertLightRefl;"
			"out vec3 vertViewDir;"
			"out vec2 vertTexCoord;"
			"void main(void)"
			"{"
			"	gl_Position = "
			"		ModelMatrix *"
			"		Position;"
			"	gl_ClipDistance[0] = "
			"		ClipDirection* "
			"		dot(ClipPlane, gl_Position);"
			"	vertLightDir = LightPosition - gl_Position.xyz;"
			"	vertNormal = mat3(ModelMatrix)*Normal;"
			"	vertLightRefl = reflect("
			"		-normalize(vertLightDir),"
			"		normalize(vertNormal)"
			"	);"
			"	vertViewDir = (vec4(0.0, 0.0, 1.0, 1.0)*CameraMatrix).xyz;"
			"	gl_Position = ProjectionMatrix * CameraMatrix * gl_Position;"
			"	vec3 TexOffs = mat3(CameraMatrix)*vertNormal*0.05;"
			"	vertTexCoord = "
			"		vec2(0.5, 0.5) +"
			"		(gl_Position.xy/gl_Position.w)*0.5 +"
			"		(TexOffs.z<0.0 ? TexOffs.xy : -TexOffs.xy);"
			"}"
		);
		shape_vs.Compile();

		shape_fs.Source(
			"#version 140\n"
			"uniform sampler2D RefractTex;"
			"in vec3 vertNormal;"
			"in vec3 vertLightDir;"
			"in vec3 vertLightRefl;"
			"in vec3 vertViewDir;"
			"in vec2 vertTexCoord;"
			"out vec4 fragColor;"

			"float adj_lt(float i)"
			"{"
			"	return i > 0.0 ? i : -0.7*i;"
			"}"

			"void main(void)"
			"{"
			"	float l = length(vertLightDir);"
			"	float d = dot("
			"		normalize(vertNormal), "
			"		normalize(vertLightDir)"
			"	) / l;"
			"	float s = dot("
			"		normalize(vertLightRefl),"
			"		normalize(vertViewDir)"
			"	);"
			"	vec3 lt = vec3(1.0, 1.0, 1.0);"
			"	vec3 tex = texture(RefractTex, vertTexCoord).rgb;"
			"	fragColor = vec4("
			"		tex * 0.5 + "
			"		(lt + tex) * 1.5 * adj_lt(d) + "
			"		lt * pow(adj_lt(s), 64), "
			"		1.0"
			"	);"
			"}"
		);
		shape_fs.Compile();

		shape_prog.AttachShader(shape_vs);
		shape_prog.AttachShader(shape_fs);
		shape_prog.Link();
		shape_prog.Use();
		shape_proj_matrix.BindTo("ProjectionMatrix");
		shape_camera_matrix.BindTo("CameraMatrix");
		shape_model_matrix.BindTo("ModelMatrix");
		shape_clip_plane.BindTo("ClipPlane");
		shape_clip_direction.BindTo("ClipDirection");

		Uniform<Vec3f>(shape_prog, "LightPosition").Set(lightPos);

		gl.Bind(shape);

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

		gl.Bind(Buffer::Target::Array, shape_normals);
		{
			std::vector<GLfloat> data;
			GLuint n_per_vertex = make_shape.Normals(data);
			Buffer::Data(Buffer::Target::Array, data);
			VertexArrayAttrib attr(shape_prog, "Normal");
			attr.Setup<GLfloat>(n_per_vertex);
			attr.Enable();
		}
		//
		Texture::Active(0);
		UniformSampler(shape_prog, "RefractTex").Set(0);
		{
			gl.Bound(Texture::Target::_2D, refract_tex)
				.MinFilter(TextureMinFilter::Linear)
				.MagFilter(TextureMagFilter::Linear)
				.WrapS(TextureWrap::MirroredRepeat)
				.WrapT(TextureWrap::MirroredRepeat)
				.Image2D(
					0,
					PixelDataInternalFormat::RGB,
					tex_side, tex_side,
					0,
					PixelDataFormat::RGB,
					PixelDataType::UnsignedByte,
					nullptr
				);
		}
		//
		gl.ClearColor(0.8f, 0.8f, 0.7f, 0.0f);
		gl.ClearDepth(1.0f);
		gl.Enable(Capability::DepthTest);
	}
	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);

	}
void GIDeferredRenderer::SetupGeometryBuffer(unsigned windowWidth,
        unsigned windowHeight)
{
    using namespace oglplus;
    static Context gl;
    // initialize geometry buffer
    geometryBuffer.Bind(FramebufferTarget::Draw);
    // build textures -- normal
    gl.Bound(TextureTarget::_2D, bufferTextures[0])
    .Image2D(0, PixelDataInternalFormat::RGBA16F, windowWidth, windowHeight,
             0, PixelDataFormat::RGB, PixelDataType::Float, nullptr)
    .MinFilter(TextureMinFilter::Nearest)
    .MagFilter(TextureMagFilter::Nearest);
    geometryBuffer.AttachColorTexture(FramebufferTarget::Draw, 0, bufferTextures[0],
                                      0);
    // build textures -- albedo
    gl.Bound(TextureTarget::_2D, bufferTextures[1])
    .Image2D(0, PixelDataInternalFormat::RGB8, windowWidth, windowHeight,
             0, PixelDataFormat::RGB, PixelDataType::UnsignedByte, nullptr)
    .MinFilter(TextureMinFilter::Nearest)
    .MagFilter(TextureMagFilter::Nearest);
    geometryBuffer.AttachColorTexture(FramebufferTarget::Draw, 1, bufferTextures[1],
                                      0);
    // build textures -- specular color and shininess
    gl.Bound(TextureTarget::_2D, bufferTextures[2])
    .Image2D(0, PixelDataInternalFormat::RGBA8, windowWidth, windowHeight,
             0, PixelDataFormat::RGBA, PixelDataType::UnsignedByte, nullptr)
    .MinFilter(TextureMinFilter::Nearest)
    .MagFilter(TextureMagFilter::Nearest);
    geometryBuffer.AttachColorTexture(FramebufferTarget::Draw, 2, bufferTextures[2],
                                      0);
    // emissivenes
    gl.Bound(TextureTarget::_2D, bufferTextures[3])
    .Image2D(0, PixelDataInternalFormat::RGB8, windowWidth, windowHeight,
             0, PixelDataFormat::RGB, PixelDataType::UnsignedByte, nullptr)
    .MinFilter(TextureMinFilter::Nearest)
    .MagFilter(TextureMagFilter::Nearest);
    geometryBuffer.AttachColorTexture(FramebufferTarget::Draw, 3, bufferTextures[3],
                                      0);
    // attach depth texture for depth testing
    gl.Bound(TextureTarget::_2D, bufferTextures[4])
    .Image2D(0, PixelDataInternalFormat::DepthComponent24, windowWidth,
             windowHeight, 0, PixelDataFormat::DepthComponent,
             PixelDataType::Float, nullptr)
    .MinFilter(TextureMinFilter::Nearest)
    .MagFilter(TextureMagFilter::Nearest);
    geometryBuffer.AttachTexture(FramebufferTarget::Draw,
                                 FramebufferAttachment::Depth,
                                 bufferTextures[4], 0);
    // color textures
    auto attachments = std::vector<Context::ColorBuffer>
    {
        FramebufferColorAttachment::_0 ,
        FramebufferColorAttachment::_1,
        FramebufferColorAttachment::_2,
        FramebufferColorAttachment::_3
    };
    // set draw buffers
    gl.DrawBuffers(attachments);

    // check if success building frame buffer
    if (!Framebuffer::IsComplete(FramebufferTarget::Draw))
    {
        auto status = Framebuffer::Status(FramebufferTarget::Draw);
        Framebuffer::HandleIncompleteError(FramebufferTarget::Draw, status);
    }

    Framebuffer::Bind(Framebuffer::Target::Draw, FramebufferName(0));
}
Exemple #24
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);

	}