From b0d86ebe5a3c2330307a5c383f0136377338336c Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Mon, 25 Feb 2013 21:58:01 +0100 Subject: Better light sorting Should fix lighting issue (#62) --- test/unit/graphics/core/device_mock.h | 107 ++++++++++++++++++++ test/unit/graphics/engine/engine_mock.h | 14 +++ test/unit/graphics/engine/lightman_test.cpp | 145 ++++++++++++++++++++++++++++ 3 files changed, 266 insertions(+) create mode 100644 test/unit/graphics/core/device_mock.h create mode 100644 test/unit/graphics/engine/engine_mock.h create mode 100644 test/unit/graphics/engine/lightman_test.cpp (limited to 'test/unit/graphics') diff --git a/test/unit/graphics/core/device_mock.h b/test/unit/graphics/core/device_mock.h new file mode 100644 index 0000000..80e214f --- /dev/null +++ b/test/unit/graphics/core/device_mock.h @@ -0,0 +1,107 @@ +#pragma once + +#include "graphics/core/device.h" + +#include + +class CDeviceMock : public Gfx::CDevice +{ +public: + CDeviceMock() {} + + MOCK_METHOD0(DebugHook, void()); + + MOCK_METHOD0(Create, bool()); + MOCK_METHOD0(Destroy, void()); + + MOCK_METHOD0(BeginScene, void()); + MOCK_METHOD0(EndScene, void()); + + MOCK_METHOD0(Clear, void()); + + MOCK_METHOD2(SetTransform, void(Gfx::TransformType type, const Math::Matrix &matrix)); + MOCK_METHOD1(GetTransform, const Math::Matrix& (Gfx::TransformType type)); + MOCK_METHOD2(MultiplyTransform, void(Gfx::TransformType type, const Math::Matrix &matrix)); + + MOCK_METHOD1(SetMaterial, void(const Gfx::Material &material)); + MOCK_METHOD0(GetMaterial, const Gfx::Material&()); + + MOCK_METHOD0(GetMaxLightCount, int()); + + MOCK_METHOD2(SetLight, void(int index, const Gfx::Light &light)); + MOCK_METHOD1(GetLight, const Gfx::Light&(int index)); + + MOCK_METHOD2(SetLightEnabled, void(int index, bool enabled)); + MOCK_METHOD1(GetLightEnabled, bool(int index)); + + MOCK_METHOD2(CreateTexture, Gfx::Texture(CImage *image, const Gfx::TextureCreateParams ¶ms)); + MOCK_METHOD2(CreateTexture, Gfx::Texture(ImageData *data, const Gfx::TextureCreateParams ¶ms)); + + MOCK_METHOD1(DestroyTexture, void(const Gfx::Texture &texture)); + MOCK_METHOD0(DestroyAllTextures, void()); + + MOCK_METHOD0(GetMaxTextureStageCount, int()); + + MOCK_METHOD2(SetTexture, void(int index, const Gfx::Texture &texture)); + MOCK_METHOD2(SetTexture, void(int index, unsigned int textureId)); + MOCK_METHOD1(GetTexture, Gfx::Texture(int index)); + + MOCK_METHOD2(SetTextureEnabled, void(int index, bool enabled)); + MOCK_METHOD1(GetTextureEnabled, bool(int index)); + + MOCK_METHOD2(SetTextureStageParams, void(int index, const Gfx::TextureStageParams ¶ms)); + MOCK_METHOD1(GetTextureStageParams, Gfx::TextureStageParams(int index)); + + MOCK_METHOD3(SetTextureStageWrap, void(int index, Gfx::TexWrapMode wrapS, Gfx::TexWrapMode wrapT)); + + MOCK_METHOD4(DrawPrimitive, void(Gfx::PrimitiveType type, const Gfx::Vertex *vertices, int vertexCount, Gfx::Color color)); + MOCK_METHOD4(DrawPrimitive, void(Gfx::PrimitiveType type, const Gfx::VertexTex2 *vertices, int vertexCount, Gfx::Color color)); + MOCK_METHOD3(DrawPrimitive, void(Gfx::PrimitiveType type, const Gfx::VertexCol *vertices, int vertexCount)); + + MOCK_METHOD3(CreateStaticBuffer, unsigned int(Gfx::PrimitiveType primitiveType, const Gfx::Vertex* vertices, int vertexCount)); + MOCK_METHOD3(CreateStaticBuffer, unsigned int(Gfx::PrimitiveType primitiveType, const Gfx::VertexTex2* vertices, int vertexCount)); + MOCK_METHOD3(CreateStaticBuffer, unsigned int(Gfx::PrimitiveType primitiveType, const Gfx::VertexCol* vertices, int vertexCount)); + + MOCK_METHOD4(UpdateStaticBuffer, void(unsigned int bufferId, Gfx::PrimitiveType primitiveType, const Gfx::Vertex* vertices, int vertexCount)); + MOCK_METHOD4(UpdateStaticBuffer, void(unsigned int bufferId, Gfx::PrimitiveType primitiveType, const Gfx::VertexTex2* vertices, int vertexCount)); + MOCK_METHOD4(UpdateStaticBuffer, void(unsigned int bufferId, Gfx::PrimitiveType primitiveType, const Gfx::VertexCol* vertices, int vertexCount)); + + MOCK_METHOD1(DrawStaticBuffer, void(unsigned int bufferId)); + + MOCK_METHOD1(DestroyStaticBuffer, void(unsigned int bufferId)); + + MOCK_METHOD2(ComputeSphereVisibility, int(const Math::Vector ¢er, float radius)); + + MOCK_METHOD2(SetRenderState, void(Gfx::RenderState state, bool enabled)); + MOCK_METHOD1(GetRenderState, bool(Gfx::RenderState state)); + + MOCK_METHOD1(SetDepthTestFunc, void(Gfx::CompFunc func)); + MOCK_METHOD0(GetDepthTestFunc, Gfx::CompFunc()); + + MOCK_METHOD1(SetDepthBias, void(float factor)); + MOCK_METHOD0(GetDepthBias, float()); + + MOCK_METHOD2(SetAlphaTestFunc, void(Gfx::CompFunc func, float refValue)); + MOCK_METHOD2(GetAlphaTestFunc, void(Gfx::CompFunc &func, float &refValue)); + + MOCK_METHOD2(SetBlendFunc, void(Gfx::BlendFunc srcBlend, Gfx::BlendFunc dstBlend)); + MOCK_METHOD2(GetBlendFunc, void(Gfx::BlendFunc &srcBlend, Gfx::BlendFunc &dstBlend)); + + MOCK_METHOD1(SetClearColor, void(const Gfx::Color &color)); + MOCK_METHOD0(GetClearColor, Gfx::Color()); + + MOCK_METHOD1(SetGlobalAmbient, void(const Gfx::Color &color)); + MOCK_METHOD0(GetGlobalAmbient, Gfx::Color()); + + MOCK_METHOD5(SetFogParams, void(Gfx::FogMode mode, const Gfx::Color &color, float start, float end, float density)); + MOCK_METHOD5(GetFogParams, void(Gfx::FogMode &mode, Gfx::Color &color, float &start, float &end, float &density)); + + MOCK_METHOD1(SetCullMode, void(Gfx::CullMode mode)); + MOCK_METHOD0(GetCullMode, Gfx::CullMode()); + + MOCK_METHOD1(SetShadeModel, void(Gfx::ShadeModel model)); + MOCK_METHOD0(GetShadeModel, Gfx::ShadeModel()); + + MOCK_METHOD1(SetFillMode, void(Gfx::FillMode mode)); + MOCK_METHOD0(GetFillMode, Gfx::FillMode()); +}; diff --git a/test/unit/graphics/engine/engine_mock.h b/test/unit/graphics/engine/engine_mock.h new file mode 100644 index 0000000..1a15eca --- /dev/null +++ b/test/unit/graphics/engine/engine_mock.h @@ -0,0 +1,14 @@ +#include "graphics/engine/engine.h" + +#include + +class CEngineMock : public Gfx::CEngine +{ +public: + CEngineMock() : Gfx::CEngine(nullptr) {} + + MOCK_METHOD0(GetPause, bool()); + + MOCK_METHOD0(GetEyePt, Math::Vector()); + MOCK_METHOD0(GetLookatPt, Math::Vector()); +}; diff --git a/test/unit/graphics/engine/lightman_test.cpp b/test/unit/graphics/engine/lightman_test.cpp new file mode 100644 index 0000000..529cee8 --- /dev/null +++ b/test/unit/graphics/engine/lightman_test.cpp @@ -0,0 +1,145 @@ +#include "graphics/engine/lightman.h" + +#include "graphics/core/device_mock.h" +#include "graphics/engine/engine_mock.h" + +#include + +using namespace Gfx; + +using testing::_; +using testing::Invoke; +using testing::Return; + +class LightManagerUT : public testing::Test +{ +protected: + LightManagerUT() + : lightManager(&engine) + {} + + void PrepareLightTesting(int maxLights, Math::Vector eyePos); + void CheckLightSorting(EngineObjectType objectType, const std::vector& expectedLights); + void CheckLight(int index, const Light& light); + void AddLight(int type, LightPriority priority, bool used, bool enabled, + Math::Vector pos, EngineObjectType includeType, EngineObjectType excludeType); + + + CLightManager lightManager; + CEngineMock engine; + CDeviceMock device; + +private: + std::vector dynamicLights; + std::vector expectedLightTypes; + int maxLightsCount; +}; + +void LightManagerUT::PrepareLightTesting(int maxLights, Math::Vector eyePos) +{ + maxLightsCount = maxLights; + + EXPECT_CALL(device, GetMaxLightCount()).WillOnce(Return(maxLights)); + lightManager.SetDevice(&device); + + ON_CALL(device, SetLight(_, _)).WillByDefault(Invoke(this, &LightManagerUT::CheckLight)); + + EXPECT_CALL(engine, GetEyePt()).WillRepeatedly(Return(eyePos)); +} + +void LightManagerUT::CheckLightSorting(EngineObjectType objectType, const std::vector& expectedLights) +{ + expectedLightTypes = expectedLights; + + EXPECT_CALL(device, SetLight(_, _)).Times(expectedLights.size()); + + for (int i = 0; i < static_cast( expectedLights.size() ); ++i) + EXPECT_CALL(device, SetLightEnabled(i, true)); + + for (int i = expectedLights.size(); i < maxLightsCount; ++i) + EXPECT_CALL(device, SetLightEnabled(i, false)); + + lightManager.UpdateDeviceLights(objectType); +} + +void LightManagerUT::CheckLight(int index, const Light& light) +{ + ASSERT_TRUE(index >= 0 && index < static_cast( expectedLightTypes.size() )); + ASSERT_EQ(expectedLightTypes[index], light.type); +} + +void LightManagerUT::AddLight(int type, LightPriority priority, bool used, bool enabled, + Math::Vector pos, EngineObjectType includeType, EngineObjectType excludeType) +{ + int rank = lightManager.CreateLight(priority); + + Light light; + light.type = static_cast(type); + lightManager.SetLight(rank, light); + + lightManager.SetLightEnabled(rank, enabled); + lightManager.SetLightIncludeType(rank, includeType); + lightManager.SetLightExcludeType(rank, excludeType); + + if (!used) + lightManager.DeleteLight(rank); +} + +TEST_F(LightManagerUT, LightSorting_UnusedOrDisabledAreSkipped) +{ + const int lightCount = 10; + const Math::Vector eyePos(0.0f, 0.0f, 0.0f); + PrepareLightTesting(lightCount, eyePos); + + AddLight(1, LIGHT_PRI_LOW, false, true, Math::Vector(0.0f, 0.0f, 0.0f), ENG_OBJTYPE_NULL, ENG_OBJTYPE_NULL); + AddLight(2, LIGHT_PRI_LOW, true, false, Math::Vector(0.0f, 0.0f, 0.0f), ENG_OBJTYPE_NULL, ENG_OBJTYPE_NULL); + AddLight(3, LIGHT_PRI_LOW, false, false, Math::Vector(0.0f, 0.0f, 0.0f), ENG_OBJTYPE_NULL, ENG_OBJTYPE_NULL); + + std::vector expectedLights; + CheckLightSorting(ENG_OBJTYPE_TERRAIN, expectedLights); +} + +TEST_F(LightManagerUT, LightSorting_IncludeTypesAreIncluded) +{ + const int lightCount = 10; + const Math::Vector eyePos(0.0f, 0.0f, 0.0f); + PrepareLightTesting(lightCount, eyePos); + + AddLight(1, LIGHT_PRI_LOW, true, true, Math::Vector(0.0f, 0.0f, 0.0f), ENG_OBJTYPE_NULL, ENG_OBJTYPE_NULL); + AddLight(2, LIGHT_PRI_LOW, true, true, Math::Vector(0.0f, 0.0f, 0.0f), ENG_OBJTYPE_TERRAIN, ENG_OBJTYPE_NULL); + AddLight(3, LIGHT_PRI_LOW, true, true, Math::Vector(0.0f, 0.0f, 0.0f), ENG_OBJTYPE_QUARTZ, ENG_OBJTYPE_NULL); + + std::vector expectedLights = { 1, 2 }; + CheckLightSorting(ENG_OBJTYPE_TERRAIN, expectedLights); +} + +TEST_F(LightManagerUT, LightSorting_ExcludeTypesAreExcluded) +{ + const int lightCount = 10; + const Math::Vector eyePos(0.0f, 0.0f, 0.0f); + PrepareLightTesting(lightCount, eyePos); + + AddLight(1, LIGHT_PRI_LOW, true, true, Math::Vector(0.0f, 0.0f, 0.0f), ENG_OBJTYPE_NULL, ENG_OBJTYPE_NULL); + AddLight(2, LIGHT_PRI_LOW, true, true, Math::Vector(0.0f, 0.0f, 0.0f), ENG_OBJTYPE_NULL, ENG_OBJTYPE_TERRAIN); + AddLight(3, LIGHT_PRI_LOW, true, true, Math::Vector(0.0f, 0.0f, 0.0f), ENG_OBJTYPE_NULL, ENG_OBJTYPE_QUARTZ); + + std::vector expectedLights = { 1, 3 }; + CheckLightSorting(ENG_OBJTYPE_TERRAIN, expectedLights); +} + +TEST_F(LightManagerUT, LightSorting_SortingAccordingToDistance) +{ + const int lightCount = 3; + const Math::Vector eyePos(0.0f, 0.0f, 0.0f); + PrepareLightTesting(lightCount, eyePos); + + AddLight(1, LIGHT_PRI_HIGH, true, true, Math::Vector(10.0f, 0.0f, 0.0f), ENG_OBJTYPE_NULL, ENG_OBJTYPE_NULL); + AddLight(2, LIGHT_PRI_LOW, true, true, Math::Vector(4.0f, 0.0f, 0.0f), ENG_OBJTYPE_NULL, ENG_OBJTYPE_NULL); + AddLight(3, LIGHT_PRI_HIGH, true, true, Math::Vector(20.0f, 0.0f, 0.0f), ENG_OBJTYPE_NULL, ENG_OBJTYPE_NULL); + AddLight(4, LIGHT_PRI_LOW, true, true, Math::Vector(11.0f, 0.0f, 0.0f), ENG_OBJTYPE_NULL, ENG_OBJTYPE_NULL); + AddLight(5, LIGHT_PRI_LOW, true, true, Math::Vector(100.0f, 0.0f, 0.0f), ENG_OBJTYPE_NULL, ENG_OBJTYPE_NULL); + AddLight(6, LIGHT_PRI_HIGH, true, true, Math::Vector(21.0f, 0.0f, 0.0f), ENG_OBJTYPE_NULL, ENG_OBJTYPE_NULL); + + std::vector expectedLights = { 1, 2, 3 }; + CheckLightSorting(ENG_OBJTYPE_TERRAIN, expectedLights); +} -- cgit v1.2.3-1-g7c22