summaryrefslogtreecommitdiff
path: root/Runtime/Camera/HaloManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Runtime/Camera/HaloManager.cpp')
-rw-r--r--Runtime/Camera/HaloManager.cpp282
1 files changed, 282 insertions, 0 deletions
diff --git a/Runtime/Camera/HaloManager.cpp b/Runtime/Camera/HaloManager.cpp
new file mode 100644
index 0000000..30feb4f
--- /dev/null
+++ b/Runtime/Camera/HaloManager.cpp
@@ -0,0 +1,282 @@
+#include "UnityPrefix.h"
+#include "HaloManager.h"
+#include "Runtime/Shaders/Material.h"
+#include "RenderManager.h"
+#include "Camera.h"
+#include "CullResults.h"
+#include "RenderLoops/RenderLoop.h"
+#include "Runtime/Serialize/TransferFunctions/SerializeTransfer.h"
+#include "Runtime/Graphics/Transform.h"
+#include "Runtime/BaseClasses/ManagerContext.h"
+#include "External/shaderlab/Library/shaderlab.h"
+#include "Runtime/Shaders/Shader.h"
+#include "Runtime/GfxDevice/GfxDevice.h"
+#include "Runtime/Shaders/VBO.h"
+#include "Runtime/Shaders/GraphicsCaps.h"
+#include "Runtime/Shaders/ShaderNameRegistry.h"
+#include "Runtime/Profiler/Profiler.h"
+
+IMPLEMENT_CLASS_HAS_INIT (Halo)
+IMPLEMENT_OBJECT_SERIALIZE (Halo)
+
+static Material *s_HaloMaterial = NULL;
+
+Halo::Halo (MemLabelId label, ObjectCreationMode mode)
+: Super(label, mode)
+{
+ m_Handle = 0;
+}
+
+Halo::~Halo ()
+{
+}
+
+void Halo::Reset ()
+{
+ Super::Reset();
+ m_Color = ColorRGBA32 (128, 128, 128, 255);
+ m_Size = 5.0f;
+}
+
+void Halo::InitializeClass () {
+ REGISTER_MESSAGE_VOID (Halo, kTransformChanged, TransformChanged);
+}
+
+void Halo::CleanupClass () {
+// s_HaloMaterial is clean up by UnloadAllObjects()
+}
+
+template<class TransferFunc>
+void Halo::Transfer (TransferFunc& transfer) {
+ Super::Transfer (transfer);
+ TRANSFER_SIMPLE (m_Color);
+ TRANSFER_SIMPLE (m_Size);
+}
+
+static void LoadHaloMaterial()
+{
+ if (s_HaloMaterial)
+ return;
+
+ SET_ALLOC_OWNER(NULL);
+ Shader* shader = GetScriptMapper ().FindShader ("Hidden/Internal-Halo");
+ if (shader)
+ s_HaloMaterial = Material::CreateMaterial (*shader, Object::kHideAndDontSave);
+}
+
+void Halo::AwakeFromLoad (AwakeFromLoadMode awakeMode) {
+ Super::AwakeFromLoad (awakeMode);
+ if ((awakeMode & kDidLoadFromDisk) == 0 && m_Handle)
+ GetHaloManager().UpdateHalo (m_Handle, GetComponent (Transform).GetPosition(), m_Color, m_Size, GetGameObject ().GetLayerMask());
+
+ LoadHaloMaterial();
+}
+
+void Halo::TransformChanged () {
+ if (m_Handle)
+ GetHaloManager().UpdateHalo (m_Handle, GetComponent (Transform).GetPosition(), m_Color, m_Size, GetGameObject ().GetLayerMask());
+}
+void Halo::AddToManager () {
+ m_Handle = GetHaloManager().AddHalo ();
+ GetHaloManager().UpdateHalo (m_Handle, GetComponent (Transform).GetPosition(), m_Color, m_Size, GetGameObject ().GetLayerMask());
+}
+void Halo::RemoveFromManager () {
+ GetHaloManager().DeleteHalo (m_Handle);
+ m_Handle = 0;
+}
+
+
+HaloManager::HaloManager(MemLabelId label, ObjectCreationMode mode)
+ : Super(label, mode)
+{
+}
+
+void HaloManager::AwakeFromLoad(AwakeFromLoadMode mode)
+{
+ Super::AwakeFromLoad(mode);
+
+ GetRenderManager().AddCameraRenderable (this, kTransparentRenderQueue);
+}
+
+HaloManager::~HaloManager() {
+ RenderManager* mgr = GetRenderManagerPtr();
+ if (mgr) // render manager can be already gone
+ mgr->RemoveCameraRenderable (this);
+}
+
+HaloManager::Halo::Halo (int hdl)
+ : position (Vector3f (0,0,0)), color (ColorRGBAf(0,0,0)), size(1), handle(hdl), layers (1) {
+}
+HaloManager::Halo::Halo (const Vector3f &pos, const ColorRGBA32 &col, float s, int h, UInt32 _layers)
+ : position (pos), color (col), size(s), handle(h), layers (_layers) {
+}
+
+IMPLEMENT_CLASS (HaloManager)
+GET_MANAGER (HaloManager)
+
+struct HaloVertex {
+ Vector3f vert;
+ ColorRGBA32 color;
+ Vector2f uv;
+};
+PROFILER_INFORMATION(gHaloRenderProfile, "Halo.Render", kProfilerRender)
+PROFILER_INFORMATION(gSubmitVBOProfileHalo, "Mesh.SubmitVBO", kProfilerRender)
+
+void HaloManager::RenderRenderable (const CullResults& cullResults)
+{
+ // Just bail if we have no visible halos or using shader replace
+ if( m_Halos.empty() || !s_HaloMaterial || cullResults.shaderReplaceData.replacementShader != NULL )
+ return;
+
+ LoadHaloMaterial();
+ if (!s_HaloMaterial)
+ return;
+
+ Shader* shader = s_HaloMaterial->GetShader();
+
+ GfxDevice& device = GetGfxDevice();
+ #if UNITY_EDITOR
+ // don't draw when wireframe mode
+ if( device.GetWireframe() )
+ return;
+ #endif
+
+ PROFILER_AUTO(gHaloRenderProfile, this)
+
+
+ const int kHaloVertices = 21;
+ const int kMaxHalos = 65535 / kHaloVertices; // cap max halos to be rendered so we work on older DX hardware
+ int haloCount = m_Halos.size();
+ if( haloCount > kMaxHalos )
+ haloCount = kMaxHalos;
+
+ // Get VBO chunk
+ DynamicVBO& vbo = device.GetDynamicVBO();
+ HaloVertex* vbPtr;
+ if( !vbo.GetChunk( (1<<kShaderChannelVertex) | (1<<kShaderChannelTexCoord0) | (1<<kShaderChannelColor),
+ haloCount * kHaloVertices, 0,
+ DynamicVBO::kDrawTriangleStrip,
+ (void**)&vbPtr, NULL ) )
+ {
+ return;
+ }
+
+
+ // Write halos into VBO
+ Camera &cam = GetCurrentCamera();
+ UInt32 layers = cam.GetCullingMask();
+ Matrix4x4f mat (cam.GetWorldToCameraMatrix());
+ int halosToRender = 0;
+ for( int i = 0; i < haloCount; ++i )
+ {
+ const Halo& halo = m_Halos[i];
+ Vector3f v = mat.MultiplyPoint3( halo.position );
+ const float s = halo.size;
+
+ // Skip this halo if behind the camera or layers don't match
+ if( v.z > -s || !(halo.layers & layers) )
+ continue;
+
+ // Dim this halo if near the camera (to avoid ugly intersection thingies).
+ ColorRGBA32 c;
+ if (v.z <= -s * 2.0f ) {
+ c = halo.color;
+ } else {
+ int fac = RoundfToInt((-v.z * 255.0f / s) - 255.0f);
+ c = halo.color * fac;
+ }
+ // Swizzle color of the renderer requires it
+ c = device.ConvertToDeviceVertexColor(c);
+
+ float z2 = v.z + s * 0.333f;
+
+ // Output 21 vertices
+ vbPtr->vert.Set( v.x ,v.y , z2); vbPtr->color = c; vbPtr->uv.Set( .5f, .5f ); ++vbPtr;
+ vbPtr->vert.Set( v.x ,v.y , z2); vbPtr->color = c; vbPtr->uv.Set( .5f, .5f ); ++vbPtr;
+ vbPtr->vert.Set( v.x-s,v.y ,v.z); vbPtr->color = c; vbPtr->uv.Set( 0.0f, .5f ); ++vbPtr;
+ vbPtr->vert.Set( v.x ,v.y , z2); vbPtr->color = c; vbPtr->uv.Set( .5f, .5f ); ++vbPtr;
+ vbPtr->vert.Set( v.x-s,v.y-s,v.z); vbPtr->color = c; vbPtr->uv.Set( 0, 0 ); ++vbPtr;
+ vbPtr->vert.Set( v.x ,v.y , z2); vbPtr->color = c; vbPtr->uv.Set( .5f, .5f ); ++vbPtr;
+ vbPtr->vert.Set( v.x ,v.y-s,v.z); vbPtr->color = c; vbPtr->uv.Set( .5f, 0 ); ++vbPtr;
+ vbPtr->vert.Set( v.x ,v.y , z2); vbPtr->color = c; vbPtr->uv.Set( .5f, .5f ); ++vbPtr;
+ vbPtr->vert.Set( v.x+s,v.y-s,v.z); vbPtr->color = c; vbPtr->uv.Set( 1, 0 ); ++vbPtr;
+ vbPtr->vert.Set( v.x ,v.y , z2); vbPtr->color = c; vbPtr->uv.Set( .5f, .5f ); ++vbPtr;
+ vbPtr->vert.Set( v.x+s,v.y ,v.z); vbPtr->color = c; vbPtr->uv.Set( 1, .5f ); ++vbPtr;
+ vbPtr->vert.Set( v.x ,v.y , z2); vbPtr->color = c; vbPtr->uv.Set( .5f, .5f ); ++vbPtr;
+ vbPtr->vert.Set( v.x+s,v.y+s,v.z); vbPtr->color = c; vbPtr->uv.Set( 1, 1 ); ++vbPtr;
+ vbPtr->vert.Set( v.x ,v.y , z2); vbPtr->color = c; vbPtr->uv.Set( .5f, .5f ); ++vbPtr;
+ vbPtr->vert.Set( v.x ,v.y+s,v.z); vbPtr->color = c; vbPtr->uv.Set( .5f, 1 ); ++vbPtr;
+ vbPtr->vert.Set( v.x ,v.y , z2); vbPtr->color = c; vbPtr->uv.Set( .5f, .5f ); ++vbPtr;
+ vbPtr->vert.Set( v.x-s,v.y+s,v.z); vbPtr->color = c; vbPtr->uv.Set( 0, 1 ); ++vbPtr;
+ vbPtr->vert.Set( v.x ,v.y , z2); vbPtr->color = c; vbPtr->uv.Set( .5f, .5f ); ++vbPtr;
+ vbPtr->vert.Set( v.x-s,v.y ,v.z); vbPtr->color = c; vbPtr->uv.Set( 0.0f, .5f ); ++vbPtr;
+ vbPtr->vert.Set( v.x ,v.y , z2); vbPtr->color = c; vbPtr->uv.Set( .5f, .5f ); ++vbPtr;
+ vbPtr->vert.Set( v.x ,v.y , z2); vbPtr->color = c; vbPtr->uv.Set( .5f, .5f ); ++vbPtr;
+
+ ++halosToRender;
+ }
+
+ vbo.ReleaseChunk( halosToRender * kHaloVertices, 0 );
+
+ float matWorld[16], matView[16];
+ CopyMatrix(device.GetViewMatrix(), matView);
+ CopyMatrix(device.GetWorldMatrix(), matWorld);
+ device.SetViewMatrix (Matrix4x4f::identity.GetPtr()); // implicitly sets world to identity
+
+ // Output halos
+ const ChannelAssigns* channels = s_HaloMaterial->SetPassWithShader( 0, shader, 0 );
+
+ PROFILER_BEGIN(gSubmitVBOProfileHalo, this)
+ vbo.DrawChunk (*channels);
+ GPU_TIMESTAMP();
+ PROFILER_END
+
+ device.SetViewMatrix(matView);
+ device.SetWorldMatrix(matWorld);
+}
+
+int HaloManager::AddHalo () {
+ int handle;
+ if (!m_Halos.empty())
+ handle = m_Halos.back().handle + 1;
+ else
+ handle = 1;
+ m_Halos.push_back (Halo (handle));
+ return handle;
+}
+
+void HaloManager::UpdateHalo (int h, Vector3f position,ColorRGBA32 color,float size, UInt32 layers)
+{
+ for (HaloList::iterator i = m_Halos.begin(); i != m_Halos.end(); i++) {
+ if (i->handle == h) {
+ i->position = position;
+ i->color = color;
+ i->size = size;
+ i->layers = layers;
+ return;
+ }
+ }
+ AssertString ("Unable to find Halo to update");
+}
+
+void HaloManager::DeleteHalo (int h)
+{
+ for (HaloList::iterator i = m_Halos.begin(); i != m_Halos.end(); i++) {
+ if (i->handle == h) {
+ m_Halos.erase (i);
+ return;
+ }
+ }
+ AssertString ("Unable to find Halo to be deleted");
+}
+
+IMPLEMENT_CLASS (HaloLayer)
+
+HaloLayer::HaloLayer (MemLabelId label, ObjectCreationMode mode)
+: Super(label, mode)
+{
+}
+
+HaloLayer::~HaloLayer ()
+{
+}