Пример #1
0
    void TestGetNodeLocalIndex()
    {
        // Create nodes
        std::vector<Node<2>*> nodes;

        // This is a square
        nodes.push_back(new Node<2>(3, false, 0.0, 0.0));
        nodes.push_back(new Node<2>(2, false, 1.0, 0.0));
        nodes.push_back(new Node<2>(1, false, 1.0, 1.0));
        nodes.push_back(new Node<2>(0, false, 0.0, 1.0));

        // Create element
        VertexElement<2,2> vertex_element(INDEX_IS_NOT_USED, nodes);

        TS_ASSERT_EQUALS(vertex_element.GetNodeLocalIndex(0), 3u);
        TS_ASSERT_EQUALS(vertex_element.GetNodeLocalIndex(1), 2u);
        TS_ASSERT_EQUALS(vertex_element.GetNodeLocalIndex(2), 1u);
        TS_ASSERT_EQUALS(vertex_element.GetNodeLocalIndex(3), 0u);

        vertex_element.DeleteNode(3); // Removes (1,1) node

        TS_ASSERT_EQUALS(vertex_element.GetNodeLocalIndex(0), UINT_MAX);

        // Tidy up
        for (unsigned i=0; i<nodes.size(); i++)
        {
            delete nodes[i];
        }
    }
Пример #2
0
    void TestMarkAsDeleted()
    {
        // Create nodes
        std::vector<Node<2>*> nodes;
        nodes.push_back(new Node<2>(0, false, 0.0, 0.0));
        nodes.push_back(new Node<2>(1, false, 1.0, 0.0));
        nodes.push_back(new Node<2>(2, false, 1.0, 1.0));
        nodes.push_back(new Node<2>(3, false, 0.0, 1.0));

        // Create element
        VertexElement<2,2> vertex_element(0, nodes);
        vertex_element.RegisterWithNodes();

        for (unsigned i=0; i<nodes.size(); i++)
        {
            TS_ASSERT_EQUALS(vertex_element.GetNode(i)->GetNumContainingElements(), 1u);
        }

        vertex_element.MarkAsDeleted();

        for (unsigned i=0; i<nodes.size(); i++)
        {
            TS_ASSERT_EQUALS(vertex_element.GetNode(i)->GetNumContainingElements(), 0u);
        }

        // Tidy up
        for (unsigned i=0; i<nodes.size(); i++)
        {
            delete nodes[i];
        }
    }
Пример #3
0
    void TestUpdateNode()
    {
        // Create nodes
        std::vector<Node<2>*> nodes;
        nodes.push_back(new Node<2>(0, false, 0.0, 0.0));
        nodes.push_back(new Node<2>(1, false, 1.0, 0.0));
        nodes.push_back(new Node<2>(2, false, 1.0, 1.0));
        nodes.push_back(new Node<2>(3, false, 0.0, 1.0));

        // Create element
        VertexElement<2,2> vertex_element(0, nodes);
        vertex_element.RegisterWithNodes();

        TS_ASSERT_DELTA(vertex_element.GetNode(2)->rGetLocation()[0], 1.0, 1e-12);
        TS_ASSERT_DELTA(vertex_element.GetNode(2)->rGetLocation()[0], 1.0, 1e-12);

        // Update location of node 2
        Node<2>* p_node = new Node<2>(4, false, 1.2, 1.3);
        vertex_element.UpdateNode(2, p_node);

        TS_ASSERT_DELTA(vertex_element.GetNode(2)->rGetLocation()[0], 1.2, 1e-12);
        TS_ASSERT_DELTA(vertex_element.GetNode(2)->rGetLocation()[1], 1.3, 1e-12);

        // Tidy up
        for (unsigned i=0; i<nodes.size(); ++i)
        {
            delete nodes[i];
        }
        delete p_node;
    }
Пример #4
0
	void RenderableTriangle::Init()
	{
		RenderFactory& rf = Context::Instance().RenderFactoryInstance();

		RenderEffectPtr effect = SyncLoadRenderEffect("RenderableHelper.fxml");
		technique_ = simple_forward_tech_ = effect->TechniqueByName("LineTec");
		v0_ep_ = effect->ParameterByName("v0");
		v1_ep_ = effect->ParameterByName("v1");
		v2_ep_ = effect->ParameterByName("v2");
		color_ep_ = effect->ParameterByName("color");
		mvp_param_ = effect->ParameterByName("mvp");

		float vertices[] =
		{
			0, 1, 2
		};

		ElementInitData init_data;
		init_data.row_pitch = sizeof(vertices);
		init_data.slice_pitch = 0;
		init_data.data = vertices;

		rl_ = rf.MakeRenderLayout();
		rl_->TopologyType(RenderLayout::TT_TriangleList);

		GraphicsBufferPtr vb = rf.MakeVertexBuffer(BU_Static, EAH_GPU_Read | EAH_Immutable, &init_data);
		rl_->BindVertexStream(vb, make_tuple(vertex_element(VEU_Position, 0, EF_R32F)));

		tc_aabb_ = AABBox(float3(0, 0, 0), float3(0, 0, 0));

		*(effect->ParameterByName("pos_center")) = float3(0, 0, 0);
		*(effect->ParameterByName("pos_extent")) = float3(1, 1, 1);

		effect_attrs_ |= EA_SimpleForward;
	}
Пример #5
0
    void TestAltenativeConstructor()
    {
        // Create element
        VertexElement<2,2> vertex_element(5);

        // Test member variables
        TS_ASSERT_EQUALS(vertex_element.GetIndex(), 5u);
        TS_ASSERT_EQUALS(vertex_element.GetNumNodes(), 0u);
        TS_ASSERT_EQUALS(vertex_element.GetNumFaces(), 0u);
    }
Пример #6
0
void RenderableLineBox::Init()
{
    RenderFactory& rf = Context::Instance().RenderFactoryInstance();

    RenderEffectPtr effect = SyncLoadRenderEffect("RenderableHelper.fxml");
    technique_ = simple_forward_tech_ = effect->TechniqueByName("LineTec");
    v0_ep_ = effect->ParameterByName("v0");
    v1_ep_ = effect->ParameterByName("v1");
    v2_ep_ = effect->ParameterByName("v2");
    v3_ep_ = effect->ParameterByName("v3");
    v4_ep_ = effect->ParameterByName("v4");
    v5_ep_ = effect->ParameterByName("v5");
    v6_ep_ = effect->ParameterByName("v6");
    v7_ep_ = effect->ParameterByName("v7");
    color_ep_ = effect->ParameterByName("color");
    mvp_param_ = effect->ParameterByName("mvp");

    float vertices[] =
    {
        0, 1, 2, 3, 4, 5, 6, 7
    };

    uint16_t indices[] =
    {
        0, 1, 1, 3, 3, 2, 2, 0,
        4, 5, 5, 7, 7, 6, 6, 4,
        0, 4, 1, 5, 2, 6, 3, 7
    };

    rl_ = rf.MakeRenderLayout();
    rl_->TopologyType(RenderLayout::TT_LineList);

    ElementInitData init_data;
    init_data.row_pitch = sizeof(vertices);
    init_data.slice_pitch = 0;
    init_data.data = vertices;

    GraphicsBufferPtr vb = rf.MakeVertexBuffer(BU_Static, EAH_GPU_Read | EAH_Immutable, &init_data);
    rl_->BindVertexStream(vb, std::make_tuple(vertex_element(VEU_Position, 0, EF_R32F)));

    init_data.row_pitch = sizeof(indices);
    init_data.slice_pitch = 0;
    init_data.data = indices;

    GraphicsBufferPtr ib = rf.MakeIndexBuffer(BU_Static, EAH_GPU_Read | EAH_Immutable, &init_data);
    rl_->BindIndexStream(ib, EF_R16UI);

    tc_aabb_ = AABBox(float3(0, 0, 0), float3(0, 0, 0));

    *(effect->ParameterByName("pos_center")) = float3(0, 0, 0);
    *(effect->ParameterByName("pos_extent")) = float3(1, 1, 1);

    effect_attrs_ |= EA_SimpleForward;
}
Пример #7
0
    void TestVertexElementFaceConstructor()
    {
        // Create a regular hexagon
        std::vector<Node<2>*> nodes;
        std::vector<VertexElement<1,2>*> faces;
        std::vector<Node<2>*> face_nodes;
        std::vector<bool> orientations;
        unsigned num_nodes = 6;
        for (unsigned i=0; i<num_nodes; i++)
        {
            double theta = 2.0*M_PI*(double)(i)/(double)(num_nodes);
            nodes.push_back(new Node<2>(i, false, cos(theta), sin(theta)));
        }

        for (unsigned i=0; i<num_nodes-1; i++)
        {
            face_nodes.clear();
            face_nodes.push_back(nodes[i]);
            face_nodes.push_back(nodes[i+1]);

            faces.push_back(new VertexElement<1,2>(i, face_nodes));
            orientations.push_back(true);
        }

        // Create a face with negative orientation
        face_nodes.clear();
        face_nodes.push_back(nodes[0]);
        face_nodes.push_back(nodes[num_nodes-1]);
        faces.push_back(new VertexElement<1,2>(num_nodes-1, face_nodes));
        orientations.push_back(false);

        // Create element
        VertexElement<2,2> vertex_element(0, faces, orientations);

        TS_ASSERT_EQUALS(vertex_element.GetNumNodes(), 6u);
        TS_ASSERT_EQUALS(vertex_element.GetNumFaces(), 6u);

        // Test that each face has the correct orientation and number of nodes
        for (unsigned face_index=0; face_index<6; face_index++)
        {
            TS_ASSERT_EQUALS(vertex_element.GetFace(face_index)->GetNumNodes(), 2u);

            bool is_clockwise = (face_index==5) ? false : true;
            TS_ASSERT_EQUALS(vertex_element.FaceIsOrientatedClockwise(face_index), is_clockwise);
        }

        // Tidy up
        for (unsigned i=0; i<nodes.size(); i++)
        {
            delete nodes[i];
            delete faces[i];
        }
    }
Пример #8
0
	GpuFftCS4::GpuFftCS4(uint32_t width, uint32_t height, bool forward)
			: width_(width), height_(height), forward_(forward)
	{
		RenderFactory& rf = Context::Instance().RenderFactoryInstance();

		src_ = rf.MakeVertexBuffer(BU_Dynamic, EAH_GPU_Read | EAH_GPU_Unordered | EAH_GPU_Structured, nullptr, EF_GR32F);
		src_->Resize(3 * width * height * sizeof(float) * 2);

		dst_ = rf.MakeVertexBuffer(BU_Dynamic, EAH_GPU_Read | EAH_GPU_Unordered | EAH_GPU_Structured, nullptr, EF_GR32F);
		dst_->Resize(3 * width * height * sizeof(float) * 2);

		tmp_buffer_ = rf.MakeVertexBuffer(BU_Dynamic, EAH_GPU_Read | EAH_GPU_Unordered | EAH_GPU_Structured, nullptr, EF_GR32F);
		tmp_buffer_->Resize(3 * width * height * sizeof(float) * 2);

		quad_layout_ = rf.MakeRenderLayout();
		quad_layout_->TopologyType(RenderLayout::TT_TriangleStrip);

		float2 xyzs[] =
		{
			float2(-1, +1),
			float2(+1, +1),
			float2(-1, -1),
			float2(+1, -1)
		};
		ElementInitData init_data;
		init_data.row_pitch = sizeof(xyzs);
		init_data.slice_pitch = 0;
		init_data.data = xyzs;
		GraphicsBufferPtr quad_vb = rf.MakeVertexBuffer(BU_Static, EAH_GPU_Read | EAH_Immutable, &init_data);
		quad_layout_->BindVertexStream(quad_vb, std::make_tuple(vertex_element(VEU_Position, 0, EF_GR32F)));

		tex_fb_ = rf.MakeFrameBuffer();

		effect_ = SyncLoadRenderEffect("FFT.fxml");
		buf2tex_tech_ = effect_->TechniqueByName("Buf2Tex");
		radix008a_tech_ = effect_->TechniqueByName("FFTRadix008A4");
		radix008a_first_tech_ = effect_->TechniqueByName("FFTRadix008AFirst4");
		radix008a_final_tech_ = effect_->TechniqueByName("FFTRadix008AFinal4");
		real_tex_ep_ = effect_->ParameterByName("real_tex");
		imag_tex_ep_ = effect_->ParameterByName("imag_tex");

		*(effect_->ParameterByName("input_buf")) = dst_;

		*(effect_->ParameterByName("tex_width_height")) = uint2(width, height);
		uint32_t n = width * height;
		*(effect_->ParameterByName("addr_offset")) = uint3(0 * n, 1 * n, 2 * n);

		*(effect_->ParameterByName("forward")) = static_cast<int32_t>(forward_);
		*(effect_->ParameterByName("scale")) = 1.0f / (width_ * height_);
	}
Пример #9
0
	LensFlareRenderable::LensFlareRenderable()
		: RenderableHelper(L"LensFlare")
	{
		RenderFactory& rf = Context::Instance().RenderFactoryInstance();

		rl_ = rf.MakeRenderLayout();
		rl_->TopologyType(RenderLayout::TT_TriangleList);

		std::vector<float3> vertices;
		for (int i = 0; i < SUN_FLARENUM; ++ i)
		{
			vertices.push_back(float3(-1, +1, i + 0.1f));
			vertices.push_back(float3(+1, +1, i + 0.1f));
			vertices.push_back(float3(-1, -1, i + 0.1f));
			vertices.push_back(float3(+1, -1, i + 0.1f));
		}

		ElementInitData init_data;
		init_data.data = &vertices[0];
		init_data.slice_pitch = init_data.row_pitch = static_cast<uint32_t>(vertices.size() * sizeof(vertices[0]));

		GraphicsBufferPtr pos_vb = rf.MakeVertexBuffer(BU_Static, EAH_GPU_Read | EAH_Immutable, &init_data);
		rl_->BindVertexStream(pos_vb, std::make_tuple(vertex_element(VEU_Position, 0, EF_BGR32F)));

		std::vector<uint32_t> indices;
		for (int i = 0; i < SUN_FLARENUM; ++ i)
		{
			indices.push_back(i * 4 + 2);
			indices.push_back(i * 4 + 0);
			indices.push_back(i * 4 + 1);

			indices.push_back(i * 4 + 1);
			indices.push_back(i * 4 + 3);
			indices.push_back(i * 4 + 2);
		}

		init_data.data = &indices[0];
		init_data.slice_pitch = init_data.row_pitch = static_cast<uint32_t>(indices.size() * sizeof(indices[0]));

		GraphicsBufferPtr ib = rf.MakeIndexBuffer(BU_Static, EAH_GPU_Read | EAH_Immutable, &init_data);
		rl_->BindIndexStream(ib, EF_R32UI);

		simple_forward_tech_ = SyncLoadRenderEffect("LensFlare.fxml")->TechniqueByName("LensFlare");
		technique_ = simple_forward_tech_;

		effect_attrs_ |= EA_SimpleForward;
	}
Пример #10
0
	RenderableSkyBox::RenderableSkyBox()
		: RenderableHelper(L"SkyBox")
	{
		RenderFactory& rf = Context::Instance().RenderFactoryInstance();

		RenderEffectPtr effect = SyncLoadRenderEffect("SkyBox.fxml");
		if (deferred_effect_)
		{
			this->BindDeferredEffect(effect);
			depth_tech_ = effect->TechniqueByName("DepthSkyBoxTech");
			gbuffer_rt0_tech_ = effect->TechniqueByName("GBufferSkyBoxRT0Tech");
			gbuffer_rt1_tech_ = effect->TechniqueByName("GBufferSkyBoxRT1Tech");
			gbuffer_mrt_tech_ = effect->TechniqueByName("GBufferSkyBoxMRTTech");
			special_shading_tech_ = effect->TechniqueByName("SkyBoxTech");
			this->Technique(gbuffer_rt0_tech_);

			effect_attrs_ |= EA_SpecialShading;
		}
		else
		{
			this->Technique(effect->TechniqueByName("SkyBoxTech"));
		}

		float3 xyzs[] =
		{
			float3(1.0f, 1.0f, 1.0f),
			float3(1.0f, -1.0f, 1.0f),
			float3(-1.0f, 1.0f, 1.0f),
			float3(-1.0f, -1.0f, 1.0f),
		};

		ElementInitData init_data;
		init_data.row_pitch = sizeof(xyzs);
		init_data.slice_pitch = 0;
		init_data.data = xyzs;

		rl_ = rf.MakeRenderLayout();
		rl_->TopologyType(RenderLayout::TT_TriangleStrip);

		GraphicsBufferPtr vb = rf.MakeVertexBuffer(BU_Static, EAH_GPU_Read | EAH_Immutable, &init_data);
		rl_->BindVertexStream(vb, make_tuple(vertex_element(VEU_Position, 0, EF_BGR32F)));

		pos_aabb_ = MathLib::compute_aabbox(&xyzs[0], &xyzs[4]);
		tc_aabb_ = AABBox(float3(0, 0, 0), float3(0, 0, 0));
	}
Пример #11
0
	MultiResLayer::MultiResLayer()
	{
		RenderFactory& rf = Context::Instance().RenderFactoryInstance();

		{
			rl_quad_ = rf.MakeRenderLayout();
			rl_quad_->TopologyType(RenderLayout::TT_TriangleStrip);

			float3 pos[] = 
			{
				float3(+1, +1, 1),
				float3(-1, +1, 1),
				float3(+1, -1, 1),
				float3(-1, -1, 1)
			};

			ElementInitData init_data;
			init_data.row_pitch = static_cast<uint32_t>(sizeof(pos));
			init_data.slice_pitch = 0;
			init_data.data = &pos[0];
			rl_quad_->BindVertexStream(rf.MakeVertexBuffer(BU_Static, EAH_GPU_Read | EAH_Immutable, &init_data),
				make_tuple(vertex_element(VEU_Position, 0, EF_BGR32F)));
		}

		gbuffer_to_depth_derivate_pp_ = SyncLoadPostProcess("MultiRes.ppml", "GBuffer2DepthDerivate");
		depth_derivate_mipmap_pp_ =  SyncLoadPostProcess("MultiRes.ppml", "DepthDerivateMipMap");
		gbuffer_to_normal_cone_pp_ =  SyncLoadPostProcess("MultiRes.ppml", "GBuffer2NormalCone");
		normal_cone_mipmap_pp_ =  SyncLoadPostProcess("MultiRes.ppml", "NormalConeMipMap");

		RenderEffectPtr subsplat_stencil_effect = SyncLoadRenderEffect("MultiRes.fxml");
		subsplat_stencil_tech_ = subsplat_stencil_effect->TechniqueByName("SetSubsplatStencil");

		subsplat_cur_lower_level_param_ = subsplat_stencil_effect->ParameterByName("cur_lower_level");
		subsplat_is_not_first_last_level_param_ = subsplat_stencil_effect->ParameterByName("is_not_first_last_level");
		subsplat_depth_deriv_tex_param_ = subsplat_stencil_effect->ParameterByName("depth_deriv_tex");
		subsplat_normal_cone_tex_param_ = subsplat_stencil_effect->ParameterByName("normal_cone_tex");
		subsplat_depth_normal_threshold_param_ = subsplat_stencil_effect->ParameterByName("depth_normal_threshold");
		subsplat_far_plane_param_ = subsplat_stencil_effect->ParameterByName("far_plane");

		upsampling_pp_ = SyncLoadPostProcess("MultiRes.ppml", "Upsampling");
	}
Пример #12
0
    void TestVertexElementDeleteAndAddNode()
    {
        // Create nodes and Faces
        std::vector<Node<2>*> nodes;
        unsigned num_nodes = 6;
        for (unsigned i=0; i<num_nodes; i++)
        {
            double theta = 2.0*M_PI*(double)(i)/(double)(num_nodes);
            nodes.push_back(new Node<2>(i, false, cos(theta), sin(theta)));
        }

        // Create element
        VertexElement<2,2> vertex_element(0, nodes);

        TS_ASSERT_EQUALS(vertex_element.GetNumNodes(), 6u);

        vertex_element.DeleteNode(3); // Removes (-1,0) node
        vertex_element.DeleteNode(0); // Removes (1,0) node

        // Test node is removed
        TS_ASSERT_EQUALS(vertex_element.GetNumNodes(), 4u);

        // Test other nodes are updated
        TS_ASSERT_DELTA(vertex_element.GetNode(0)->GetPoint()[0], 0.5, 1e-9);
        TS_ASSERT_DELTA(vertex_element.GetNode(0)->GetPoint()[1], 0.5*sqrt(3.0), 1e-9);

        TS_ASSERT_DELTA(vertex_element.GetNode(1)->GetPoint()[0], -0.5, 1e-9);
        TS_ASSERT_DELTA(vertex_element.GetNode(1)->GetPoint()[1], 0.5*sqrt(3.0), 1e-9);

        TS_ASSERT_DELTA(vertex_element.GetNode(2)->GetPoint()[0], -0.5, 1e-9);
        TS_ASSERT_DELTA(vertex_element.GetNode(2)->GetPoint()[1], -0.5*sqrt(3.0), 1e-9);

        TS_ASSERT_DELTA(vertex_element.GetNode(3)->GetPoint()[0], 0.5, 1e-9);
        TS_ASSERT_DELTA(vertex_element.GetNode(3)->GetPoint()[1], -0.5*sqrt(3.0), 1e-9);

        // Add new node
        Node<2>* p_new_node = new Node<2>(4, false, 0.0, 0.0);
        vertex_element.AddNode(p_new_node, 3); // Add node at (0,0) between nodes 3 and 0

        // Test node is added
        TS_ASSERT_EQUALS(vertex_element.GetNumNodes(), 5u);

        // Test other nodes are updated
        TS_ASSERT_DELTA(vertex_element.GetNode(0)->GetPoint()[0], 0.5, 1e-9);
        TS_ASSERT_DELTA(vertex_element.GetNode(0)->GetPoint()[1], 0.5*sqrt(3.0), 1e-9);

        TS_ASSERT_DELTA(vertex_element.GetNode(1)->GetPoint()[0], -0.5, 1e-9);
        TS_ASSERT_DELTA(vertex_element.GetNode(1)->GetPoint()[1], 0.5*sqrt(3.0), 1e-9);

        TS_ASSERT_DELTA(vertex_element.GetNode(2)->GetPoint()[0], -0.5, 1e-9);
        TS_ASSERT_DELTA(vertex_element.GetNode(2)->GetPoint()[1], -0.5*sqrt(3.0), 1e-9);

        TS_ASSERT_DELTA(vertex_element.GetNode(3)->GetPoint()[0], 0.5, 1e-9);
        TS_ASSERT_DELTA(vertex_element.GetNode(3)->GetPoint()[1], -0.5*sqrt(3.0), 1e-9);

        TS_ASSERT_DELTA(vertex_element.GetNode(4)->GetPoint()[0], 0.0, 1e-9);
        TS_ASSERT_DELTA(vertex_element.GetNode(4)->GetPoint()[1], 0.0, 1e-9);

        // Tidy up
        for (unsigned i=0; i<nodes.size(); i++)
        {
            delete nodes[i];
        }
        delete p_new_node;
    }
Пример #13
0
// 建立渲染窗口
/////////////////////////////////////////////////////////////////////////////////
void RenderEngine::CreateRenderWindow(std::string const & name, RenderSettings& settings)
{
    if (settings.stereo_method != STM_OculusVR)
    {
        stereo_separation_ = settings.stereo_separation;
    }
    this->DoCreateRenderWindow(name, settings);
    this->CheckConfig(settings);
    RenderDeviceCaps const & caps = this->DeviceCaps();

    screen_frame_buffer_ = cur_frame_buffer_;

    uint32_t const screen_width = screen_frame_buffer_->Width();
    uint32_t const screen_height = screen_frame_buffer_->Height();
    float const screen_aspect = static_cast<float>(screen_width) / screen_height;
    if (!MathLib::equal(screen_aspect, static_cast<float>(settings.width) / settings.height))
    {
        settings.width = static_cast<uint32_t>(settings.height * screen_aspect + 0.5f);
    }

    RenderFactory& rf = Context::Instance().RenderFactoryInstance();

    pp_rl_ = rf.MakeRenderLayout();
    pp_rl_->TopologyType(RenderLayout::TT_TriangleStrip);

    float2 pos[] =
    {
        float2(-1, +1),
        float2(+1, +1),
        float2(-1, -1),
        float2(+1, -1)
    };
    GraphicsBufferPtr pp_pos_vb = rf.MakeVertexBuffer(BU_Static, EAH_GPU_Read | EAH_Immutable, sizeof(pos), &pos[0]);
    pp_rl_->BindVertexStream(pp_pos_vb, std::make_tuple(vertex_element(VEU_Position, 0, EF_GR32F)));

    uint32_t const render_width = static_cast<uint32_t>(settings.width * default_render_width_scale_ + 0.5f);
    uint32_t const render_height = static_cast<uint32_t>(settings.height * default_render_height_scale_ + 0.5f);

    hdr_enabled_ = settings.hdr;
    if (settings.hdr)
    {
        hdr_pp_ = MakeSharedPtr<HDRPostProcess>(settings.fft_lens_effects);
        skip_hdr_pp_ = SyncLoadPostProcess("Copy.ppml", "copy");
    }

    ppaa_enabled_ = settings.ppaa ? 1 : 0;
    gamma_enabled_ = settings.gamma;
    color_grading_enabled_ = settings.color_grading;
    if (settings.ppaa || settings.color_grading || settings.gamma)
    {
        for (size_t i = 0; i < 12; ++ i)
        {
            ldr_pps_[i] = SyncLoadPostProcess("PostToneMapping.ppml",
                                              "PostToneMapping" + boost::lexical_cast<std::string>(i));
        }

        ldr_pp_ = ldr_pps_[ppaa_enabled_ * 4 + gamma_enabled_ * 2 + color_grading_enabled_];
    }

    bool need_resize = false;
    if (!settings.hide_win)
    {
        need_resize = ((render_width != screen_width) || (render_height != screen_height));

        resize_pps_[0] = SyncLoadPostProcess("Resizer.ppml", "bilinear");
        resize_pps_[1] = MakeSharedPtr<BicubicFilteringPostProcess>();

        float const scale_x = static_cast<float>(screen_width) / render_width;
        float const scale_y = static_cast<float>(screen_height) / render_height;

        float2 pos_scale;
        if (scale_x < scale_y)
        {
            pos_scale.x() = 1;
            pos_scale.y() = (scale_x * render_height) / screen_height;
        }
        else
        {
            pos_scale.x() = (scale_y * render_width) / screen_width;
            pos_scale.y() = 1;
        }

        for (size_t i = 0; i < 2; ++ i)
        {
            resize_pps_[i]->SetParam(0, pos_scale);
        }
    }

    for (int i = 0; i < 4; ++ i)
    {
        default_frame_buffers_[i] = screen_frame_buffer_;
    }

    RenderViewPtr ds_view;
    if (hdr_pp_ || ldr_pp_ || (settings.stereo_method != STM_None))
    {
        ds_tex_ = this->ScreenDepthStencilTexture();
        if (ds_tex_ && (screen_width == render_width) && (screen_height == render_height))
        {
            ds_view = rf.Make2DDepthStencilRenderView(*ds_tex_, 0, 1, 0);
        }
        else
        {
            if (caps.texture_format_support(EF_D32F) || caps.texture_format_support(EF_D24S8)
                    || caps.texture_format_support(EF_D16))
            {
                ElementFormat fmt;
                if ((settings.depth_stencil_fmt != EF_Unknown)
                        && caps.texture_format_support(settings.depth_stencil_fmt))
                {
                    fmt = settings.depth_stencil_fmt;
                }
                else
                {
                    BOOST_ASSERT(caps.texture_format_support(EF_D16));

                    fmt = EF_D16;
                }
                ds_tex_ = rf.MakeTexture2D(render_width, render_height, 1, 1, fmt, 1, 0, EAH_GPU_Read | EAH_GPU_Write, nullptr);
                ds_view = rf.Make2DDepthStencilRenderView(*ds_tex_, 0, 1, 0);
            }
            else
            {
                ElementFormat fmt;
                if ((settings.depth_stencil_fmt != EF_Unknown)
                        && caps.rendertarget_format_support(settings.depth_stencil_fmt, 1, 0))
                {
                    fmt = settings.depth_stencil_fmt;
                }
                else
                {
                    BOOST_ASSERT(caps.rendertarget_format_support(EF_D16, 1, 0));

                    fmt = EF_D16;
                }
                ds_view = rf.Make2DDepthStencilRenderView(render_width, render_height, fmt, 1, 0);
            }
        }
    }

    if (settings.stereo_method != STM_None)
    {
        mono_frame_buffer_ = rf.MakeFrameBuffer();
        mono_frame_buffer_->GetViewport()->camera = cur_frame_buffer_->GetViewport()->camera;

        ElementFormat fmt;
        if (caps.texture_format_support(settings.color_fmt) && caps.rendertarget_format_support(settings.color_fmt, 1, 0))
        {
            fmt = settings.color_fmt;
        }
        else
        {
            if (caps.texture_format_support(EF_ABGR8) && caps.rendertarget_format_support(EF_ABGR8, 1, 0))
            {
                fmt = EF_ABGR8;
            }
            else
            {
                BOOST_ASSERT(caps.texture_format_support(EF_ARGB8) && caps.rendertarget_format_support(EF_ARGB8, 1, 0));

                fmt = EF_ARGB8;
            }
        }

        mono_tex_ = rf.MakeTexture2D(screen_width, screen_height, 1, 1,
                                     fmt, 1, 0, EAH_GPU_Read | EAH_GPU_Write, nullptr);
        mono_frame_buffer_->Attach(FrameBuffer::ATT_Color0, rf.Make2DRenderView(*mono_tex_, 0, 1, 0));

        default_frame_buffers_[0] = default_frame_buffers_[1]
                                    = default_frame_buffers_[2] = mono_frame_buffer_;

        overlay_frame_buffer_ = rf.MakeFrameBuffer();
        overlay_frame_buffer_->GetViewport()->camera = cur_frame_buffer_->GetViewport()->camera;

        overlay_tex_ = rf.MakeTexture2D(screen_width, screen_height, 1, 1,
                                        fmt, 1, 0, EAH_GPU_Read | EAH_GPU_Write, nullptr);
        overlay_frame_buffer_->Attach(FrameBuffer::ATT_Color0, rf.Make2DRenderView(*overlay_tex_, 0, 1, 0));

        RenderViewPtr screen_size_ds_view;
        if (need_resize)
        {
            screen_size_ds_view = rf.Make2DDepthStencilRenderView(screen_width, screen_height, ds_view->Format(), 1, 0);
        }
        else
        {
            screen_size_ds_view = ds_view;
        }
        overlay_frame_buffer_->Attach(FrameBuffer::ATT_DepthStencil, screen_size_ds_view);
    }
    else
    {
        if (need_resize)
        {
            resize_frame_buffer_ = rf.MakeFrameBuffer();
            resize_frame_buffer_->GetViewport()->camera = cur_frame_buffer_->GetViewport()->camera;

            ElementFormat fmt;
            if (caps.texture_format_support(EF_ABGR8) && caps.rendertarget_format_support(EF_ABGR8, 1, 0))
            {
                fmt = EF_ABGR8;
            }
            else
            {
                BOOST_ASSERT(caps.texture_format_support(EF_ARGB8) && caps.rendertarget_format_support(EF_ARGB8, 1, 0));

                fmt = EF_ARGB8;
            }

            resize_tex_ = rf.MakeTexture2D(render_width, render_height, 1, 1,
                                           fmt, 1, 0, EAH_GPU_Read | EAH_GPU_Write, nullptr);
            resize_frame_buffer_->Attach(FrameBuffer::ATT_Color0, rf.Make2DRenderView(*resize_tex_, 0, 1, 0));

            ElementFormat ds_fmt;
            if ((settings.depth_stencil_fmt != EF_Unknown) && caps.rendertarget_format_support(settings.depth_stencil_fmt, 1, 0))
            {
                ds_fmt = settings.depth_stencil_fmt;
            }
            else
            {
                BOOST_ASSERT(caps.rendertarget_format_support(EF_D16, 1, 0));

                ds_fmt = EF_D16;
            }
            resize_frame_buffer_->Attach(FrameBuffer::ATT_DepthStencil,
                                         rf.Make2DDepthStencilRenderView(render_width, render_height, ds_fmt, 1, 0));

            default_frame_buffers_[0] = default_frame_buffers_[1]
                                        = default_frame_buffers_[2] = resize_frame_buffer_;
        }
    }

    if (ldr_pp_)
    {
        ldr_frame_buffer_ = rf.MakeFrameBuffer();
        ldr_frame_buffer_->GetViewport()->camera = cur_frame_buffer_->GetViewport()->camera;

        ElementFormat fmt;
        if (caps.texture_format_support(EF_ABGR8) && caps.rendertarget_format_support(EF_ABGR8, 1, 0))
        {
            fmt = EF_ABGR8;
        }
        else
        {
            BOOST_ASSERT(caps.texture_format_support(EF_ARGB8) && caps.rendertarget_format_support(EF_ARGB8, 1, 0));

            fmt = EF_ARGB8;
        }
        ElementFormat fmt_srgb = MakeSRGB(fmt);
        if (caps.texture_format_support(fmt_srgb) && caps.rendertarget_format_support(fmt_srgb, 1, 0))
        {
            fmt = fmt_srgb;
        }

        ldr_tex_ = rf.MakeTexture2D(render_width, render_height, 1, 1, fmt, 1, 0, EAH_GPU_Read | EAH_GPU_Write, nullptr);
        ldr_frame_buffer_->Attach(FrameBuffer::ATT_Color0, rf.Make2DRenderView(*ldr_tex_, 0, 1, 0));
        ldr_frame_buffer_->Attach(FrameBuffer::ATT_DepthStencil, ds_view);

        default_frame_buffers_[0] = default_frame_buffers_[1] = ldr_frame_buffer_;
    }

    if (hdr_pp_)
    {
        hdr_frame_buffer_ = rf.MakeFrameBuffer();
        hdr_frame_buffer_->GetViewport()->camera = cur_frame_buffer_->GetViewport()->camera;

        ElementFormat fmt;
        if (caps.fp_color_support)
        {
            if (caps.texture_format_support(EF_B10G11R11F) && caps.rendertarget_format_support(EF_B10G11R11F, 1, 0))
            {
                fmt = EF_B10G11R11F;
            }
            else
            {
                BOOST_ASSERT(caps.texture_format_support(EF_ABGR16F) && caps.rendertarget_format_support(EF_ABGR16F, 1, 0));
                fmt = EF_ABGR16F;
            }
        }
        else
        {
            if (caps.texture_format_support(EF_ABGR8) && caps.rendertarget_format_support(EF_ABGR8, 1, 0))
            {
                fmt = EF_ABGR8;
            }
            else
            {
                BOOST_ASSERT(caps.texture_format_support(EF_ARGB8) && caps.rendertarget_format_support(EF_ARGB8, 1, 0));
                fmt = EF_ARGB8;
            }

            ElementFormat fmt_srgb = MakeSRGB(fmt);
            if (caps.rendertarget_format_support(fmt_srgb, 1, 0))
            {
                fmt = fmt_srgb;
            }
        }
        hdr_tex_ = rf.MakeTexture2D(render_width, render_height, 4, 1, fmt, 1, 0, EAH_GPU_Read | EAH_GPU_Write | EAH_Generate_Mips, nullptr);
        hdr_frame_buffer_->Attach(FrameBuffer::ATT_Color0, rf.Make2DRenderView(*hdr_tex_, 0, 1, 0));
        hdr_frame_buffer_->Attach(FrameBuffer::ATT_DepthStencil, ds_view);

        default_frame_buffers_[0] = hdr_frame_buffer_;
    }

    this->BindFrameBuffer(default_frame_buffers_[0]);
    this->Stereo(settings.stereo_method);

#ifndef KLAYGE_SHIP
    PerfProfiler& profiler = PerfProfiler::Instance();
    hdr_pp_perf_ = profiler.CreatePerfRange(0, "HDR PP");
    ldr_pp_perf_ = profiler.CreatePerfRange(0, "LDR PP");
    resize_pp_perf_ = profiler.CreatePerfRange(0, "Resize PP");
    stereoscopic_pp_perf_ = profiler.CreatePerfRange(0, "Stereoscopic PP");
#endif
}
Пример #14
0
	RenderDecal::RenderDecal(TexturePtr const & normal_tex, TexturePtr const & diffuse_tex, float3 const & diffuse_clr,
			TexturePtr const & specular_tex, float3 const & specular_level, float shininess)
		: RenderableHelper(L"Decal")
	{
		this->BindDeferredEffect(SyncLoadRenderEffect("Decal.fxml"));

		gbuffer_alpha_test_rt0_tech_ = deferred_effect_->TechniqueByName("DecalGBufferAlphaTestRT0Tech");
		gbuffer_alpha_test_rt1_tech_ = deferred_effect_->TechniqueByName("DecalGBufferAlphaTestRT1Tech");
		gbuffer_alpha_test_mrt_tech_ = deferred_effect_->TechniqueByName("DecalGBufferAlphaTestMRTTech");
		technique_ = gbuffer_alpha_test_rt0_tech_;

		pos_aabb_ = AABBox(float3(-1, -1, -1), float3(1, 1, 1));
		tc_aabb_ = AABBox(float3(0, 0, 0), float3(1, 1, 0));

		float3 xyzs[] =
		{
			pos_aabb_.Corner(0), pos_aabb_.Corner(1), pos_aabb_.Corner(2), pos_aabb_.Corner(3),
			pos_aabb_.Corner(4), pos_aabb_.Corner(5), pos_aabb_.Corner(6), pos_aabb_.Corner(7)
		};

		uint16_t indices[] =
		{
			0, 2, 3, 3, 1, 0,
			5, 7, 6, 6, 4, 5,
			4, 0, 1, 1, 5, 4,
			4, 6, 2, 2, 0, 4,
			2, 6, 7, 7, 3, 2,
			1, 3, 7, 7, 5, 1
		};

		RenderFactory& rf = Context::Instance().RenderFactoryInstance();
		rl_ = rf.MakeRenderLayout();
		rl_->TopologyType(RenderLayout::TT_TriangleList);

		ElementInitData init_data;
		init_data.row_pitch = sizeof(xyzs);
		init_data.slice_pitch = 0;
		init_data.data = xyzs;

		GraphicsBufferPtr vb = rf.MakeVertexBuffer(BU_Static, EAH_GPU_Read | EAH_Immutable, &init_data);
		rl_->BindVertexStream(vb, make_tuple(vertex_element(VEU_Position, 0, EF_BGR32F)));

		init_data.row_pitch = sizeof(indices);
		init_data.slice_pitch = 0;
		init_data.data = indices;

		GraphicsBufferPtr ib = rf.MakeIndexBuffer(BU_Static, EAH_GPU_Read | EAH_Immutable, &init_data);
		rl_->BindIndexStream(ib, EF_R16UI);

		model_mat_ = float4x4::Identity();
		effect_attrs_ |= EA_AlphaTest;

		inv_mv_ep_ = technique_->Effect().ParameterByName("inv_mv");
		g_buffer_rt0_tex_param_ = deferred_effect_->ParameterByName("g_buffer_rt0_tex");

		normal_tex_ = normal_tex;
		diffuse_tex_ = diffuse_tex;
		diffuse_clr_ = diffuse_clr;
		specular_tex_ = specular_tex;
		specular_level_ = specular_level.x();
		shininess_ = shininess;
	}
Пример #15
0
	RenderablePlane::RenderablePlane(float length, float width,
				int length_segs, int width_segs, bool has_tex_coord, bool has_tangent)
			: RenderableHelper(L"RenderablePlane")
	{
		RenderFactory& rf = Context::Instance().RenderFactoryInstance();

		rl_ = rf.MakeRenderLayout();
		rl_->TopologyType(RenderLayout::TT_TriangleList);

		std::vector<int16_t> positions;
		for (int y = 0; y < width_segs + 1; ++ y)
		{
			for (int x = 0; x < length_segs + 1; ++ x)
			{
				float3 pos(static_cast<float>(x) / length_segs, 1 - (static_cast<float>(y) / width_segs), 0.5f);
				int16_t s_pos[4] = 
				{
					static_cast<int16_t>(MathLib::clamp<int32_t>(static_cast<int32_t>(pos.x() * 65535 - 32768), -32768, 32767)),
					static_cast<int16_t>(MathLib::clamp<int32_t>(static_cast<int32_t>(pos.y() * 65535 - 32768), -32768, 32767)),
					static_cast<int16_t>(MathLib::clamp<int32_t>(static_cast<int32_t>(pos.z() * 65535 - 32768), -32768, 32767)),
					32767
				};

				positions.push_back(s_pos[0]);
				positions.push_back(s_pos[1]);
				positions.push_back(s_pos[2]);
				positions.push_back(s_pos[3]);
			}
		}

		ElementInitData init_data;
		init_data.row_pitch = static_cast<uint32_t>(positions.size() * sizeof(positions[0]));
		init_data.slice_pitch = 0;
		init_data.data = &positions[0];

		GraphicsBufferPtr pos_vb = rf.MakeVertexBuffer(BU_Static, EAH_GPU_Read | EAH_Immutable, &init_data);
		rl_->BindVertexStream(pos_vb, make_tuple(vertex_element(VEU_Position, 0, EF_SIGNED_ABGR16)));

		if (has_tex_coord)
		{
			std::vector<int16_t> tex_coords;
			for (int y = 0; y < width_segs + 1; ++ y)
			{
				for (int x = 0; x < length_segs + 1; ++ x)
				{
					float3 tex_coord(static_cast<float>(x) / length_segs * 0.5f + 0.5f,
						static_cast<float>(y) / width_segs * 0.5f + 0.5f, 0.5f);
					int16_t s_tc[2] = 
					{
						static_cast<int16_t>(MathLib::clamp<int32_t>(static_cast<int32_t>(tex_coord.x() * 65535 - 32768), -32768, 32767)),
						static_cast<int16_t>(MathLib::clamp<int32_t>(static_cast<int32_t>(tex_coord.y() * 65535 - 32768), -32768, 32767)),
					};

					tex_coords.push_back(s_tc[0]);
					tex_coords.push_back(s_tc[1]);
				}
			}

			init_data.row_pitch = static_cast<uint32_t>(tex_coords.size() * sizeof(tex_coords[0]));
			init_data.slice_pitch = 0;
			init_data.data = &tex_coords[0];

			GraphicsBufferPtr tex_vb = rf.MakeVertexBuffer(BU_Static, EAH_GPU_Read | EAH_Immutable, &init_data);
			rl_->BindVertexStream(tex_vb, make_tuple(vertex_element(VEU_TextureCoord, 0, EF_SIGNED_GR16)));
		}

		if (has_tangent)
		{
			std::vector<uint32_t> tangent(positions.size() / 4);
			ElementFormat fmt;
			if (rf.RenderEngineInstance().DeviceCaps().vertex_format_support(EF_ABGR8))
			{
				fmt = EF_ABGR8;
				tangent.assign(tangent.size(), 0x807F7FFE);
			}
			else
			{
				BOOST_ASSERT(rf.RenderEngineInstance().DeviceCaps().vertex_format_support(EF_ARGB8));

				fmt = EF_ARGB8;
				tangent.assign(tangent.size(), 0x80FE7F7F);
			}

			init_data.row_pitch = static_cast<uint32_t>(tangent.size() * sizeof(tangent[0]));
			init_data.slice_pitch = 0;
			init_data.data = &tangent[0];

			GraphicsBufferPtr tex_vb = rf.MakeVertexBuffer(BU_Static, EAH_GPU_Read | EAH_Immutable, &init_data);
			rl_->BindVertexStream(tex_vb, make_tuple(vertex_element(VEU_Tangent, 0, fmt)));
		}

		std::vector<uint16_t> index;
		for (int y = 0; y < width_segs; ++ y)
		{
			for (int x = 0; x < length_segs; ++ x)
			{
				index.push_back(static_cast<uint16_t>((y + 0) * (length_segs + 1) + (x + 0)));
				index.push_back(static_cast<uint16_t>((y + 0) * (length_segs + 1) + (x + 1)));
				index.push_back(static_cast<uint16_t>((y + 1) * (length_segs + 1) + (x + 1)));

				index.push_back(static_cast<uint16_t>((y + 1) * (length_segs + 1) + (x + 1)));
				index.push_back(static_cast<uint16_t>((y + 1) * (length_segs + 1) + (x + 0)));
				index.push_back(static_cast<uint16_t>((y + 0) * (length_segs + 1) + (x + 0)));
			}
		}

		init_data.row_pitch = static_cast<uint32_t>(index.size() * sizeof(index[0]));
		init_data.slice_pitch = 0;
		init_data.data = &index[0];

		GraphicsBufferPtr ib = rf.MakeIndexBuffer(BU_Static, EAH_GPU_Read | EAH_Immutable, &init_data);
		rl_->BindIndexStream(ib, EF_R16UI);

		pos_aabb_ = AABBox(float3(-length / 2, -width / 2, 0), float3(+length / 2, +width / 2, 0));
		tc_aabb_ = AABBox(float3(0, 0, 0), float3(1, 1, 0));
	}
Пример #16
0
	MultiResSILLayer::MultiResSILLayer()
	{
		RenderFactory& rf = Context::Instance().RenderFactoryInstance();
		RenderEngine& re = rf.RenderEngineInstance();
		RenderDeviceCaps const & caps = re.DeviceCaps();

		{
			rl_quad_ = rf.MakeRenderLayout();
			rl_quad_->TopologyType(RenderLayout::TT_TriangleStrip);

			std::vector<float3> pos;
			std::vector<uint16_t> index;

			pos.push_back(float3(+1, +1, 1));
			pos.push_back(float3(-1, +1, 1));
			pos.push_back(float3(+1, -1, 1));
			pos.push_back(float3(-1, -1, 1));

			ElementInitData init_data;
			init_data.row_pitch = static_cast<uint32_t>(pos.size() * sizeof(pos[0]));
			init_data.slice_pitch = 0;
			init_data.data = &pos[0];
			rl_quad_->BindVertexStream(rf.MakeVertexBuffer(BU_Static, EAH_GPU_Read | EAH_Immutable, &init_data),
				make_tuple(vertex_element(VEU_Position, 0, EF_BGR32F)));
		}

		vpl_tex_ = rf.MakeTexture2D(VPL_COUNT, 4, 1, 1, EF_ABGR16F, 1, 0, EAH_GPU_Read | EAH_GPU_Write, nullptr);	

		gbuffer_to_depth_derivate_pp_ = SyncLoadPostProcess("MultiRes.ppml", "GBuffer2DepthDerivate");
		depth_derivate_mipmap_pp_ =  SyncLoadPostProcess("MultiRes.ppml", "DepthDerivateMipMap");
		gbuffer_to_normal_cone_pp_ =  SyncLoadPostProcess("MultiRes.ppml", "GBuffer2NormalCone");
		normal_cone_mipmap_pp_ =  SyncLoadPostProcess("MultiRes.ppml", "NormalConeMipMap");

		RenderEffectPtr subsplat_stencil_effect = SyncLoadRenderEffect("MultiRes.fxml");
		subsplat_stencil_tech_ = subsplat_stencil_effect->TechniqueByName("SetSubsplatStencil");

		subsplat_cur_lower_level_param_ = subsplat_stencil_effect->ParameterByName("cur_lower_level");
		subsplat_is_not_first_last_level_param_ = subsplat_stencil_effect->ParameterByName("is_not_first_last_level");
		subsplat_depth_deriv_tex_param_ = subsplat_stencil_effect->ParameterByName("depth_deriv_tex");
		subsplat_normal_cone_tex_param_ = subsplat_stencil_effect->ParameterByName("normal_cone_tex");
		subsplat_depth_normal_threshold_param_ = subsplat_stencil_effect->ParameterByName("depth_normal_threshold");

		RenderEffectPtr vpls_lighting_effect = SyncLoadRenderEffect("VPLsLighting.fxml");
		vpls_lighting_instance_id_tech_ = vpls_lighting_effect->TechniqueByName("VPLsLightingInstanceID");
		vpls_lighting_no_instance_id_tech_ = vpls_lighting_effect->TechniqueByName("VPLsLightingNoInstanceID");

		vpl_view_param_ = vpls_lighting_effect->ParameterByName("view");
		vpl_proj_param_ = vpls_lighting_effect->ParameterByName("proj");
		vpl_depth_near_far_invfar_param_ = vpls_lighting_effect->ParameterByName("depth_near_far_invfar");
		vpl_light_pos_es_param_ = vpls_lighting_effect->ParameterByName("light_pos_es");
		vpl_light_color_param_ = vpls_lighting_effect->ParameterByName("light_color");
		vpl_light_falloff_param_ = vpls_lighting_effect->ParameterByName("light_falloff");
		vpl_x_coord_param_ = vpls_lighting_effect->ParameterByName("x_coord");
		vpl_gbuffer_tex_param_ = vpls_lighting_effect->ParameterByName("gbuffer_tex");
		vpl_depth_tex_param_ = vpls_lighting_effect->ParameterByName("depth_tex");
		*(vpls_lighting_effect->ParameterByName("vpls_tex")) = vpl_tex_;
		*(vpls_lighting_effect->ParameterByName("vpl_params")) = float2(1.0f / VPL_COUNT, 0.5f / VPL_COUNT);

		upsampling_pp_ = SyncLoadPostProcess("MultiRes.ppml", "Upsampling");

		rl_vpl_ = SyncLoadModel("indirect_light_proxy.meshml", EAH_GPU_Read | EAH_Immutable, CreateModelFactory<RenderModel>(), CreateMeshFactory<StaticMesh>())->Mesh(0)->GetRenderLayout();
		if (caps.instance_id_support)
		{
			rl_vpl_->NumInstances(VPL_COUNT);
		}
	}