Convert MaterialCache2D to a component. [ci skip]

This commit is contained in:
aster2013 2014-03-25 12:09:57 +08:00
parent 4a34818c25
commit 43147fbe1d
8 changed files with 311 additions and 34 deletions

View File

@ -32,7 +32,6 @@
#include "Input.h"
#include "InputEvents.h"
#include "Log.h"
#include "MaterialCache2D.h"
#include "NavigationMesh.h"
#include "Network.h"
#include "PackageFile.h"
@ -149,7 +148,6 @@ bool Engine::Initialize(const VariantMap& parameters)
}
// 2D graphics library is dependent on 3D graphics library
context_->RegisterSubsystem(new MaterialCache2D(context_));
RegisterUrho2DLibrary(context_);
// Start logging
@ -761,10 +759,6 @@ void Engine::HandleExitRequested(StringHash eventType, VariantMap& eventData)
void Engine::DoExit()
{
MaterialCache2D* materialCache = GetSubsystem<MaterialCache2D>();
if (materialCache)
materialCache->ReleaseAllMaterials();
Graphics* graphics = GetSubsystem<Graphics>();
if (graphics)
graphics->Close();

View File

@ -274,6 +274,22 @@ ResourceRef Drawable2D::GetMaterialAttr() const
return GetResourceRef(material_, Material::GetTypeStatic());
}
void Drawable2D::OnNodeSet(Node* node)
{
Drawable::OnNodeSet(node);
if (node)
{
node->AddListener(this);
Scene* scene = GetScene();
if (scene)
{
materialCache_ = scene->GetOrCreateComponent<MaterialCache2D>();
}
}
}
void Drawable2D::OnWorldBoundingBoxUpdate()
{
if (verticesDirty_)
@ -298,8 +314,7 @@ void Drawable2D::UpdateMaterial()
batches_[0].material_ = material_;
else
{
MaterialCache2D* materialCache = GetSubsystem<MaterialCache2D>();
defaultMaterial_ = materialCache->GetMaterial(GetTexture(), blendMode_);
defaultMaterial_ = materialCache_->GetMaterial(GetTexture(), blendMode_);
batches_[0].material_ = defaultMaterial_;
}
}

View File

@ -28,6 +28,8 @@
namespace Urho3D
{
class DrawableProxy2D;
class MaterialCache2D;
class VertexBuffer;
/// Pixel size (equal 0.01f).
@ -98,6 +100,8 @@ public:
ResourceRef GetMaterialAttr() const;
protected:
/// Handle node being assigned.
virtual void OnNodeSet(Node* node);
/// Recalculate the world-space bounding box.
virtual void OnWorldBoundingBoxUpdate();
/// Update vertices.
@ -128,7 +132,12 @@ protected:
bool geometryDirty_;
/// Material update pending flag.
bool materialUpdatePending_;
/// Default material.
SharedPtr<Material> defaultMaterial_;
/// Material cache.
WeakPtr<MaterialCache2D> materialCache_;
/// Drawable proxy.
WeakPtr<DrawableProxy2D> drawableProxy_;
};
inline bool CompareDrawable2Ds(Drawable2D* lhs, Drawable2D* rhs)

View File

@ -0,0 +1,193 @@
//
// Copyright (c) 2008-2014 the Urho3D project.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#include "Precompiled.h"
#include "Camera.h"
#include "Context.h"
#include "Drawable2D.h"
#include "DrawableProxy2D.h"
#include "Geometry.h"
#include "Log.h"
#include "Material.h"
#include "Node.h"
#include "VertexBuffer.h"
#include "Sort.h"
#include "DebugNew.h"
namespace Urho3D
{
DrawableProxy2D::DrawableProxy2D(Context* context) :
Drawable(context, DRAWABLE_GEOMETRY),
vertexBuffer_(new VertexBuffer(context_)),
orderDirty_(true)
{
}
DrawableProxy2D::~DrawableProxy2D()
{
}
void DrawableProxy2D::RegisterObject(Context* context)
{
context->RegisterFactory<DrawableProxy2D>();
}
void DrawableProxy2D::UpdateBatches(const FrameInfo& frame)
{
unsigned count = materials_.Size();
batches_.Resize(count);
for (unsigned i = 0; i < count; ++i)
{
batches_[i].distance_ = 10.0f + (count - i) * 0.001f;
batches_[i].material_ = materials_[i];
batches_[i].geometry_ = geometries_[i];
batches_[i].worldTransform_ = &Matrix3x4::IDENTITY;
}
}
void DrawableProxy2D::UpdateGeometry(const FrameInfo& frame)
{
materials_.Clear();
if (orderDirty_)
{
Sort(drawables_.Begin(), drawables_.End(), CompareDrawable2Ds);
orderDirty_ = false;
}
float timeStep = frame.timeStep_;
unsigned vertexCount = 0;
for (unsigned i = 0; i < drawables_.Size(); ++i)
vertexCount += drawables_[i]->GetVertices().Size();
if (vertexCount == 0)
return;
vertexCount = vertexCount / 4 * 6;
vertexBuffer_->SetSize(vertexCount, MASK_VERTEX2D);
Vertex2D* dest = reinterpret_cast<Vertex2D*>(vertexBuffer_->Lock(0, vertexCount, true));
if (dest)
{
unsigned start = 0;
unsigned count = 0;
Material* material = 0;
for (unsigned d = 0; d < drawables_.Size(); ++d)
{
Material* currMaterial = drawables_[d]->GetUsedMaterial();
if (material != currMaterial)
{
if (material)
{
AddBatch(material, start, count);
start += count;
count = 0;
}
material = currMaterial;
}
const Vector<Vertex2D>& vertices = drawables_[d]->GetVertices();
for (unsigned i = 0; i < vertices.Size(); i += 4)
{
dest[0] = vertices[i + 0];
dest[1] = vertices[i + 1];
dest[2] = vertices[i + 2];
dest[3] = vertices[i + 0];
dest[4] = vertices[i + 2];
dest[5] = vertices[i + 3];
dest += 6;
}
count += vertices.Size() / 4 * 6;
}
if (material)
AddBatch(material, start, count);
vertexBuffer_->Unlock();
}
else
LOGERROR("Failed to lock vertex buffer");
}
UpdateGeometryType DrawableProxy2D::GetUpdateGeometryType()
{
return UPDATE_WORKER_THREAD;
}
void DrawableProxy2D::AddDrawable(Drawable2D* drawable)
{
if (!drawable)
return;
if (drawables_.Contains(drawable))
return;
drawables_.Push(drawable);
orderDirty_ = true;
}
void DrawableProxy2D::RemoveDrawable(Drawable2D* drawable)
{
if (!drawable)
return;
drawables_.Remove(drawable);
orderDirty_ = true;
}
void DrawableProxy2D::OnWorldBoundingBoxUpdate()
{
boundingBox_.Clear();
for (unsigned i = 0; i < drawables_.Size(); ++i)
boundingBox_.Merge(drawables_[i]->GetWorldBoundingBox());
worldBoundingBox_ = boundingBox_;
}
void DrawableProxy2D::AddBatch(Material* material, unsigned vertexStart, unsigned vertexCount)
{
if (!material)
return;
materials_.Push(SharedPtr<Material>(material));
unsigned batchSize = materials_.Size();
if (geometries_.Size() < batchSize)
{
SharedPtr<Geometry> geometry(new Geometry(context_));
geometry->SetVertexBuffer(0, vertexBuffer_, MASK_VERTEX2D);
geometries_.Push(geometry);
}
geometries_[batchSize - 1]->SetDrawRange(TRIANGLE_LIST, 0, 0, vertexStart, vertexCount);
}
}

View File

@ -0,0 +1,78 @@
//
// Copyright (c) 2008-2014 the Urho3D project.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#pragma once
#include "Drawable.h"
namespace Urho3D
{
class Drawable2D;
class VertexBuffer;
/// Proxy for 2D visible components.
class URHO3D_API DrawableProxy2D : public Drawable
{
OBJECT(DrawableProxy2D);
public:
/// Construct.
DrawableProxy2D(Context* context);
/// Destruct.
~DrawableProxy2D();
/// Register object factory.
static void RegisterObject(Context* context);
/// Calculate distance and prepare batches for rendering. May be called from worker thread(s), possibly re-entrantly.
virtual void UpdateBatches(const FrameInfo& frame);
/// Prepare geometry for rendering. Called from a worker thread if possible (no GPU update.)
virtual void UpdateGeometry(const FrameInfo& frame);
/// Return whether a geometry update is necessary, and if it can happen in a worker thread.
virtual UpdateGeometryType GetUpdateGeometryType();
/// Add drawable.
void AddDrawable(Drawable2D* drawable);
/// Remove drawable.
void RemoveDrawable(Drawable2D* drawable);
/// Mark order dirty.
void MarkOrderDirty() { orderDirty_ = true; }
protected:
/// Recalculate the world-space bounding box.
virtual void OnWorldBoundingBoxUpdate();
/// Add batch.
void AddBatch(Material* material, unsigned vertexStart, unsigned vertexCount);
/// Vertex buffer.
SharedPtr<VertexBuffer> vertexBuffer_;
/// Materials.
Vector<SharedPtr<Material> > materials_;
/// Geometries.
Vector<SharedPtr<Geometry> > geometries_;
/// Drawables.
PODVector<Drawable2D* > drawables_;
/// Order dirty.
bool orderDirty_;
};
}

View File

@ -33,7 +33,7 @@ namespace Urho3D
{
MaterialCache2D::MaterialCache2D(Context* context) :
Object(context)
Component(context)
{
}
@ -41,21 +41,9 @@ MaterialCache2D::~MaterialCache2D()
{
}
void MaterialCache2D::ReleaseAllMaterials()
void MaterialCache2D::RegisterObject(Context* context)
{
materials_.Clear();
}
void MaterialCache2D::ReleaseMaterial(Texture2D* texture)
{
materials_.Erase(texture);
}
void MaterialCache2D::ReleaseMaterial(Texture2D* texture, BlendMode blendMode)
{
HashMap<Texture2D*, HashMap<int, SharedPtr<Material> > >::Iterator i = materials_.Find(texture);
if (i != materials_.End())
i->second_.Erase(blendMode);
context->RegisterFactory<MaterialCache2D>();
}
Material* MaterialCache2D::GetMaterial(Texture2D* texture, BlendMode blendMode)
@ -82,7 +70,7 @@ Material* MaterialCache2D::GetMaterial(Texture2D* texture, BlendMode blendMode)
Material* MaterialCache2D::CreateMaterial(Texture2D* texture, BlendMode blendMode)
{
Material* material = new Material(context_);
Technique* tech = new Technique(context_);
Pass* pass = tech->CreatePass(PASS_ALPHA);
pass->SetBlendMode(blendMode);
@ -92,7 +80,7 @@ Material* MaterialCache2D::CreateMaterial(Texture2D* texture, BlendMode blendMod
pass->SetPixelShader("Basic");
pass->SetPixelShaderDefines("DIFFMAP VERTEXCOLOR");
pass->SetDepthWrite(false);
material->SetTechnique(0, tech);

View File

@ -22,7 +22,7 @@
#pragma once
#include "Object.h"
#include "Component.h"
#include "GraphicsDefs.h"
namespace Urho3D
@ -32,7 +32,7 @@ class Texture2D;
class Material;
/// Material cache for 2D.
class URHO3D_API MaterialCache2D : public Object
class URHO3D_API MaterialCache2D : public Component
{
OBJECT(MaterialCache2D);
@ -41,13 +41,8 @@ public:
MaterialCache2D(Context* context);
/// Destruct.
virtual ~MaterialCache2D();
/// Release all materials.
void ReleaseAllMaterials();
/// Release material by texture.
void ReleaseMaterial(Texture2D* texture);
/// Release material by texture and blend mode.
void ReleaseMaterial(Texture2D* texture, BlendMode blendMode);
/// Register object factory.
static void RegisterObject(Context* context);
/// Return material by texture and blend mode.
Material* GetMaterial(Texture2D* texture, BlendMode blendMode);

View File

@ -43,6 +43,8 @@
#include "ConstraintWheel2D.h"
#include "Context.h"
#include "Drawable2D.h"
#include "DrawableProxy2D.h"
#include "MaterialCache2D.h"
#include "ParticleEffect2D.h"
#include "ParticleEmitter2D.h"
#include "PhysicsWorld2D.h"
@ -60,6 +62,9 @@ const char* URHO2D_CATEGORY = "Urho2D";
void RegisterUrho2DLibrary(Context* context)
{
MaterialCache2D::RegisterObject(context);
DrawableProxy2D::RegisterObject(context);
// Must register objects from base to derived order
Drawable2D::RegisterObject(context);
StaticSprite2D::RegisterObject(context);