diff --git a/CubismSDK/Framework/CMakeLists.txt b/CubismSDK/Framework/CMakeLists.txt index 74b1159..af07f01 100644 --- a/CubismSDK/Framework/CMakeLists.txt +++ b/CubismSDK/Framework/CMakeLists.txt @@ -4,19 +4,9 @@ include_directories(src) include_directories(../Core/include) -# アプリケーション側で設定したgl系のincludeパスをセットする -include_directories("${FRAMEWORK_GLFW_PATH}") -include_directories("${FRAMEWORK_GLEW_PATH}") - -# プリプロセッサ定義の追加 -add_definitions(${FRAMEWORK_DEFINITIOINS}) -# ここにプロジェクトに追加するソースファイルを追加 -set(Framework - - src/CubismDefaultParameterId.cpp - src/CubismFramework.cpp - src/CubismModelSettingJson.cpp +# 各プラットフォーム共通ファイル +set(commonfiles src/Effect/CubismBreath.cpp src/Effect/CubismEyeBlink.cpp @@ -32,25 +22,24 @@ set(Framework src/Math/CubismVector2.cpp src/Math/CubismViewMatrix.cpp - src/Model/CubismMoc.cpp src/Model/CubismModel.cpp src/Model/CubismModelUserData.cpp src/Model/CubismModelUserDataJson.cpp src/Model/CubismUserModel.cpp + src/Model/CubismMoc.cpp - src/Motion/ACubismMotion.cpp src/Motion/CubismExpressionMotion.cpp src/Motion/CubismMotion.cpp src/Motion/CubismMotionJson.cpp src/Motion/CubismMotionManager.cpp src/Motion/CubismMotionQueueEntry.cpp src/Motion/CubismMotionQueueManager.cpp + src/Motion/ACubismMotion.cpp - src/Physics/CubismPhysics.cpp src/Physics/CubismPhysicsJson.cpp + src/Physics/CubismPhysics.cpp src/Rendering/CubismRenderer.cpp - src/Rendering/OpenGL/CubismRenderer_OpenGLES2.cpp src/Type/csmRectF.cpp src/Type/csmString.cpp @@ -62,7 +51,47 @@ set(Framework src/CubismDefaultParameterId.cpp src/CubismFramework.cpp src/CubismModelSettingJson.cpp + +) + +if (${FRAMEWORK_SOURCE} MATCHES "D3D9" ) + +# ここにプロジェクトに追加するソースファイルを追加 DirectX9 + +# アプリケーション側で設定したgl系のincludeパスをセットする +include_directories("${FRAMEWORK_DX9_INCLUDE_PATH}") + +set(Framework + + ${commonfiles} + + src/Rendering/D3D9/CubismRenderer_D3D9.cpp + src/Rendering/D3D9/CubismRenderState_D3D9.cpp + src/Rendering/D3D9/CubismShader_D3D9.cpp + src/Rendering/D3D9/CubismOffscreenSurface_D3D9.cpp + ) +else () + +# ここにプロジェクトに追加するソースファイルを追加 OpenGL + +# アプリケーション側で設定したgl系のincludeパスをセットする +include_directories("${FRAMEWORK_GLFW_PATH}") +include_directories("${FRAMEWORK_GLEW_PATH}") + +# プリプロセッサ定義の追加 +add_definitions(${FRAMEWORK_DEFINITIOINS}) + +set(Framework + + ${commonfiles} + + src/Rendering/OpenGL/CubismRenderer_OpenGLES2.cpp + +) + +endif () + # staticライブラリとして追加 add_library (Framework STATIC ${Framework}) diff --git a/CubismSDK/Framework/src/CubismFramework.cpp b/CubismSDK/Framework/src/CubismFramework.cpp index c68eaec..893651d 100644 --- a/CubismSDK/Framework/src/CubismFramework.cpp +++ b/CubismSDK/Framework/src/CubismFramework.cpp @@ -171,7 +171,7 @@ void CubismFramework::Dispose() for (csmUint32 i = 0; i < s_allocationList->size(); ++i) { - CubismLogInfo("Memory leaking: 0x%x", s_allocationList->at(i)); + CubismLogInfo("Memory leaking: 0x%p", s_allocationList->at(i)); } if (s_allocationList->size() == 0) @@ -224,7 +224,7 @@ void* CubismFramework::Allocate(csmSizeType size, const csmChar* fileName, csmIn { void* address = GetAllocator()->Allocate(size); - CubismLogVerbose("CubismFramework::Allocate(0x%x, %dbytes) %s(%d)", address, size, fileName, lineNumber); + CubismLogVerbose("CubismFramework::Allocate(0x%p, %dbytes) %s(%d)", address, size, fileName, lineNumber); if (s_allocationList) { @@ -238,7 +238,7 @@ void* CubismFramework::AllocateAligned(csmSizeType size, csmUint32 alignment, co { void* address = GetAllocator()->AllocateAligned(size, alignment); - CubismLogVerbose("CubismFramework::AllocateAligned(0x%x, a:%d, %dbytes) %s(%d)", address, alignment, size, fileName, lineNumber); + CubismLogVerbose("CubismFramework::AllocateAligned(0x%p, a:%d, %dbytes) %s(%d)", address, alignment, size, fileName, lineNumber); if (s_allocationList) { @@ -255,7 +255,7 @@ void CubismFramework::Deallocate(void* address, const csmChar* fileName, csmInt3 return; } - CubismLogVerbose("CubismFramework::Deallocate(0x%x) %s(%d)", address, fileName, lineNumber); + CubismLogVerbose("CubismFramework::Deallocate(0x%p) %s(%d)", address, fileName, lineNumber); if (s_allocationList) { @@ -281,7 +281,7 @@ void CubismFramework::DeallocateAligned(void* address, const csmChar* fileName, return; } - CubismLogVerbose("CubismFramework::DeallocateAligned(0x%x) %s(%d)", address, fileName, lineNumber); + CubismLogVerbose("CubismFramework::DeallocateAligned(0x%p) %s(%d)", address, fileName, lineNumber); if (s_allocationList) { diff --git a/CubismSDK/Framework/src/Effect/CubismPose.cpp b/CubismSDK/Framework/src/Effect/CubismPose.cpp index 0d984b1..08cee84 100644 --- a/CubismSDK/Framework/src/Effect/CubismPose.cpp +++ b/CubismSDK/Framework/src/Effect/CubismPose.cpp @@ -62,7 +62,6 @@ void CubismPose::PartData::Initialize(CubismModel* model) } CubismPose::CubismPose() : _fadeTimeSeconds(DefaultFadeInSeconds) - , _lastTimeSeconds(0.0f) , _lastModel(NULL) { } diff --git a/CubismSDK/Framework/src/Effect/CubismPose.hpp b/CubismSDK/Framework/src/Effect/CubismPose.hpp index ef5399a..e891640 100644 --- a/CubismSDK/Framework/src/Effect/CubismPose.hpp +++ b/CubismSDK/Framework/src/Effect/CubismPose.hpp @@ -149,7 +149,6 @@ class CubismPose csmVector _partGroups; ///< パーツグループ csmVector _partGroupCounts; ///< それぞれのパーツグループの個数 csmFloat32 _fadeTimeSeconds; ///< フェード時間[秒] - csmFloat32 _lastTimeSeconds; ///< 最後に実行した時刻[秒] CubismModel* _lastModel; ///< 前回操作したモデル }; diff --git a/CubismSDK/Framework/src/Model/CubismUserModel.cpp b/CubismSDK/Framework/src/Model/CubismUserModel.cpp index 9dc5fa8..6897b13 100644 --- a/CubismSDK/Framework/src/Model/CubismUserModel.cpp +++ b/CubismSDK/Framework/src/Model/CubismUserModel.cpp @@ -17,10 +17,12 @@ CubismUserModel::CubismUserModel() , _motionManager(NULL) , _expressionManager(NULL) , _eyeBlink(NULL) + , _breath(NULL) , _modelMatrix(NULL) , _pose(NULL) , _dragManager(NULL) , _physics(NULL) + , _modelUserData(NULL) , _initialized(false) , _updating(false) , _opacity(1.0f) @@ -33,7 +35,6 @@ CubismUserModel::CubismUserModel() , _accelerationZ(0.0f) , _debugMode(false) , _renderer(NULL) - , _modelUserData(NULL) { // モーションマネージャーを作成 // MotionQueueManagerクラスからの継承なので使い方は同じ diff --git a/CubismSDK/Framework/src/Motion/CubismMotion.cpp b/CubismSDK/Framework/src/Motion/CubismMotion.cpp index d6a2a68..a6b0abc 100644 --- a/CubismSDK/Framework/src/Motion/CubismMotion.cpp +++ b/CubismSDK/Framework/src/Motion/CubismMotion.cpp @@ -183,9 +183,9 @@ void CubismMotion::DoUpdateParameters(CubismModel* model, csmFloat32 userTimeSec { CubismLogDebug("too many eye blink targets : %d", _eyeBlinkParameterIds.GetSize()); } - if (_eyeBlinkParameterIds.GetSize() > MaxTargetSize) + if (_lipSyncParameterIds.GetSize() > MaxTargetSize) { - CubismLogDebug("too many lip sync targets : %d", _eyeBlinkParameterIds.GetSize()); + CubismLogDebug("too many lip sync targets : %d", _lipSyncParameterIds.GetSize()); } const csmFloat32 tmpFadeIn = (_fadeInSeconds <= 0.0f) diff --git a/CubismSDK/Framework/src/Motion/CubismMotionInternal.hpp b/CubismSDK/Framework/src/Motion/CubismMotionInternal.hpp index 4f2448a..9206e60 100644 --- a/CubismSDK/Framework/src/Motion/CubismMotionInternal.hpp +++ b/CubismSDK/Framework/src/Motion/CubismMotionInternal.hpp @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license @@ -136,8 +136,8 @@ struct CubismMotionData : Duration(0.0f) , Loop(0) , CurveCount(0) - , Fps(0.0f) , EventCount(0) + , Fps(0.0f) { } csmFloat32 Duration; ///< モーションの長さ[秒] diff --git a/CubismSDK/Framework/src/Motion/CubismMotionQueueManager.cpp b/CubismSDK/Framework/src/Motion/CubismMotionQueueManager.cpp index ff5896e..d555c09 100644 --- a/CubismSDK/Framework/src/Motion/CubismMotionQueueManager.cpp +++ b/CubismSDK/Framework/src/Motion/CubismMotionQueueManager.cpp @@ -218,16 +218,6 @@ void CubismMotionQueueManager::StopAllMotions() continue; } - ACubismMotion* motion = motionQueueEntry->_motion; - - if (motion == NULL) - { - CSM_DELETE(motionQueueEntry); - ite = _motions.Erase(ite); - - continue; - } - // ----- 終了済みの処理があれば削除する ------ CSM_DELETE(motionQueueEntry); ite = _motions.Erase(ite); //削除 diff --git a/CubismSDK/Framework/src/Rendering/D3D9/CubismNativeInclude_D3D9.hpp b/CubismSDK/Framework/src/Rendering/D3D9/CubismNativeInclude_D3D9.hpp new file mode 100644 index 0000000..8a09065 --- /dev/null +++ b/CubismSDK/Framework/src/Rendering/D3D9/CubismNativeInclude_D3D9.hpp @@ -0,0 +1,18 @@ +/* + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#pragma once + +#include "CubismFrameworkConfig.hpp" + +#ifdef CSM_DEBUG +// d3dヘッダの前にこれを定義するとデバッグ情報が増える 必要に応じてOn +#define D3D_DEBUG_INFO +#endif + +#include +#include diff --git a/CubismSDK/Framework/src/Rendering/D3D9/CubismOffscreenSurface_D3D9.cpp b/CubismSDK/Framework/src/Rendering/D3D9/CubismOffscreenSurface_D3D9.cpp new file mode 100644 index 0000000..cdf4e7a --- /dev/null +++ b/CubismSDK/Framework/src/Rendering/D3D9/CubismOffscreenSurface_D3D9.cpp @@ -0,0 +1,173 @@ +/* + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#include "CubismOffscreenSurface_D3D9.hpp" + +#include "CubismRenderer_D3D9.hpp" +#include "CubismShader_D3D9.hpp" + +//------------ LIVE2D NAMESPACE ------------ +namespace Live2D { namespace Cubism { namespace Framework { namespace Rendering { + +CubismOffscreenFrame_D3D9::CubismOffscreenFrame_D3D9() + : _texture(NULL) + , _textureSurface(NULL) + , _depthSurface(NULL) + , _backupRender(NULL) + , _backupDepth(NULL) +{ +} + + +void CubismOffscreenFrame_D3D9::BeginDraw(LPDIRECT3DDEVICE9 device) +{ + if(_depthSurface==NULL || _texture==NULL) + { + return; + } + + // オフスクリーン描画は一度通常描画を打ち切る必要がある + device->EndScene(); + + device->BeginScene(); + + _backupRender = NULL; + _backupDepth = NULL; + + // バックバッファのサーフェイスを記憶しておく + device->GetRenderTarget(0, &_backupRender); + // ステンシルバッファを取得しておく + device->GetDepthStencilSurface(&_backupDepth); + + + LPDIRECT3DSURFACE9 surface; + _textureSurface = NULL; + if (SUCCEEDED(_texture->GetSurfaceLevel(0, &surface))) + { + // 記憶しておく + _textureSurface = surface; + + // マスク描画レンダーターゲットセット + device->SetRenderTarget(0, surface); + device->SetDepthStencilSurface(_depthSurface); + + // マスクをクリアする + //(仮仕様) 1が無効(描かれない)領域、0が有効(描かれる)領域。(シェーダで Cd*Csで0に近い値をかけてマスクを作る。1をかけると何も起こらない) + device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(255, 255, 255, 255), 1.0f, 0); + } +} + +void CubismOffscreenFrame_D3D9::EndDraw(LPDIRECT3DDEVICE9 device) +{ + if (_depthSurface == NULL || _texture == NULL) + { + return; + } + + device->EndScene(); + + // 元に戻す + if (_textureSurface) + { + device->SetRenderTarget(0, _backupRender); + device->SetDepthStencilSurface(_backupDepth); + // GetSurfaceLevelでincされたものを下げる必要がある + { + _textureSurface->Release(); + _textureSurface = NULL; + } + } + + // BeginでGetした分のRelease + if(_backupDepth) + { + _backupDepth->Release(); + _backupDepth = NULL; + } + if(_backupRender) + { + _backupRender->Release(); + _backupRender = NULL; + } + + device->BeginScene(); +} + +csmBool CubismOffscreenFrame_D3D9::CreateOffscreenFrame(LPDIRECT3DDEVICE9 device, csmUint32 displayBufferWidth, csmUint32 displayBufferHeight) +{ + // 一旦削除 + DestroyOffscreenFrame(); + + if (FAILED(D3DXCreateTexture( + device, + displayBufferWidth, + displayBufferHeight, + 0, + D3DUSAGE_RENDERTARGET, + D3DFMT_A8R8G8B8, + D3DPOOL_DEFAULT, + &_texture))) + { + return false; + } + + if (FAILED(device->CreateDepthStencilSurface( + displayBufferWidth, + displayBufferHeight, + D3DFMT_D16, + D3DMULTISAMPLE_NONE, + 0, + TRUE, + &_depthSurface, + NULL))) + { + if(_texture) + { + _texture->Release(); + _texture = NULL; + } + return false; + } + + return true; +} + +void CubismOffscreenFrame_D3D9::DestroyOffscreenFrame() +{ + // これらがあるのはEndDrawが来なかった場合 + if(_backupDepth) + { + _backupDepth->Release(); + _backupDepth = NULL; + } + if (_backupRender) + { + _backupRender->Release(); + _backupRender = NULL; + } + if (_textureSurface) + { + _textureSurface->Release(); + _textureSurface = NULL; + } + + + if(_depthSurface) + { + _depthSurface->Release(); + _depthSurface = NULL; + } + if (_texture) + { + _texture->Release(); + _texture = NULL; + } +} + +}}}} + +//------------ LIVE2D NAMESPACE ------------ diff --git a/CubismSDK/Framework/src/Rendering/D3D9/CubismOffscreenSurface_D3D9.hpp b/CubismSDK/Framework/src/Rendering/D3D9/CubismOffscreenSurface_D3D9.hpp new file mode 100644 index 0000000..0524014 --- /dev/null +++ b/CubismSDK/Framework/src/Rendering/D3D9/CubismOffscreenSurface_D3D9.hpp @@ -0,0 +1,67 @@ +/* + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#pragma once + +#include "CubismNativeInclude_D3D9.hpp" + +#include "Math/CubismMatrix44.hpp" + +//------------ LIVE2D NAMESPACE ------------ +namespace Live2D { namespace Cubism { namespace Framework { namespace Rendering { + + +/** + * @brief オフスクリーン描画用構造体 + */ +struct CubismOffscreenFrame_D3D9 +{ +public: + + CubismOffscreenFrame_D3D9(); + + /** + * @brief 指定の描画ターゲットに向けて描画開始 + * + * @param device[in] D3dデバイス + */ + void BeginDraw(LPDIRECT3DDEVICE9 device); + + /** + * @brief 描画終了 + * + * @param device[in] D3dデバイス + */ + void EndDraw(LPDIRECT3DDEVICE9 device); + + /** + * @brief CubismOffscreenFrame作成 + * @param device[in] D3dデバイス + * @param displayBufferWidth[in] 作成するバッファ幅 + * @param displayBufferHeight[in] 作成するバッファ高さ + */ + csmBool CreateOffscreenFrame(LPDIRECT3DDEVICE9 device, csmUint32 displayBufferWidth, csmUint32 displayBufferHeight); + + /** + * @brief CubismOffscreenFrameの削除 + */ + void DestroyOffscreenFrame(); + + + LPDIRECT3DTEXTURE9 _texture; ///< 生成テクスチャ + LPDIRECT3DSURFACE9 _textureSurface; ///< レンダリングサーフェス + LPDIRECT3DSURFACE9 _depthSurface; ///< Z + + LPDIRECT3DSURFACE9 _backupRender; ///< 元々のターゲットを退避 + LPDIRECT3DSURFACE9 _backupDepth; ///< 元々のZを退避 + +}; + + +}}}} + +//------------ LIVE2D NAMESPACE ------------ diff --git a/CubismSDK/Framework/src/Rendering/D3D9/CubismRenderState_D3D9.cpp b/CubismSDK/Framework/src/Rendering/D3D9/CubismRenderState_D3D9.cpp new file mode 100644 index 0000000..9353fb2 --- /dev/null +++ b/CubismSDK/Framework/src/Rendering/D3D9/CubismRenderState_D3D9.cpp @@ -0,0 +1,293 @@ +/* + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#include "CubismRenderState_D3D9.hpp" +#include "CubismShader_D3D9.hpp" +#include "CubismRenderer_D3D9.hpp" +#include "Type/csmVector.hpp" + +//------------ LIVE2D NAMESPACE ------------ +namespace Live2D { namespace Cubism { namespace Framework { namespace Rendering { + +CubismRenderState_D3D9::CubismRenderState_D3D9() +{ + // + memset(_stored._valid, 0, sizeof(_stored._valid)); +} + +CubismRenderState_D3D9::~CubismRenderState_D3D9() +{ + _pushed.Clear(); +} + +void CubismRenderState_D3D9::StartFrame() +{ + memset(_stored._valid, 0, sizeof(_stored._valid)); + + _pushed.Clear(); +} + + +void CubismRenderState_D3D9::Save() +{ + // 現時点のステートをPush + _pushed.PushBack(_stored); +} + +void CubismRenderState_D3D9::Restore(LPDIRECT3DDEVICE9 device) +{ + const csmUint32 size = _pushed.GetSize(); + + if (size == 0) + { + return; + } + + //forで辿って最後に設定した個所までチェック + csmBool isSet[State_Max]; + memset(isSet, 0, sizeof(isSet)); + + for (csmInt32 i = static_cast(_pushed.GetSize())-1; i>=0; i--) + { + Stored ¤t = _pushed[i]; + + if (_pushed[i]._valid[State_Blend] && !isSet[State_Blend]) + { + SetBlend(device, current.BlendEnable, current.BlendAlphaSeparateEnable, current.BlendSourceMul, current.BlendBlendFunc, current.BlendDestMul, + current.BlendSourceAlpha, current.BlendAlphaFunc, current.BlendDestAlpha, true); + isSet[State_Blend] = true; + } + if (_pushed[i]._valid[State_Viewport] && !isSet[State_Viewport]) + { + SetViewport(device, current.ViewportX, current.ViewportY, current.ViewportWidth, current.ViewportHeight, current.ViewportMinZ, current.ViewportMaxZ, true); + isSet[State_Viewport] = true; + } + if (_pushed[i]._valid[State_ColorMask] && !isSet[State_ColorMask]) + { + SetColorMask(device, current.ColorMaskMask, true); + isSet[State_ColorMask] = true; + } + if (_pushed[i]._valid[State_ZEnable] && !isSet[State_ZEnable]) + { + SetZEnable(device, current.ZEnable, current.ZFunc, true); + isSet[State_ZEnable] = true; + } + if (_pushed[i]._valid[State_CullMode] && !isSet[State_CullMode]) + { + SetCullMode(device, current.CullModeFaceMode, true); + isSet[State_CullMode] = true; + } + if (_pushed[i]._valid[State_TextureFilter] && !isSet[State_TextureFilter]) + { + SetTextureFilter(device, current.MinFilter, current.MagFilter, current.MipFilter, current.AddressU, current.AddressV, true); + isSet[State_TextureFilter] = true; + } + } + + Stored store = _pushed[size - 1]; + _pushed.Remove(size - 1); + if(_pushed.GetSize()==0) + { + _pushed.Clear(); + } + _stored = store; +} + + +void CubismRenderState_D3D9::SetBlend(LPDIRECT3DDEVICE9 device, bool enable, bool alphaSeparateEnable, + D3DBLEND srcmul, D3DBLENDOP blendFunc, D3DBLEND destmul, + D3DBLEND srcalpha, D3DBLENDOP alphaFunc, D3DBLEND destalpha, + csmBool force) +{ + if (!_stored._valid[State_Blend] || force || + _stored.BlendEnable != enable || _stored.BlendAlphaSeparateEnable != alphaSeparateEnable || + _stored.BlendSourceMul != srcmul || _stored.BlendBlendFunc != blendFunc || _stored.BlendDestMul != destmul || + _stored.BlendSourceAlpha != srcalpha || _stored.BlendAlphaFunc != alphaFunc || _stored.BlendDestAlpha != destalpha) + { + device->SetRenderState(D3DRS_SRCBLEND, srcmul); + device->SetRenderState(D3DRS_BLENDOP, blendFunc); + device->SetRenderState(D3DRS_DESTBLEND, destmul); + + device->SetRenderState(D3DRS_SRCBLENDALPHA, srcalpha); + device->SetRenderState(D3DRS_BLENDOPALPHA, alphaFunc); + device->SetRenderState(D3DRS_DESTBLENDALPHA, destalpha); + + device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, alphaSeparateEnable); + device->SetRenderState(D3DRS_ALPHABLENDENABLE, enable); + } + + _stored.BlendEnable = enable; + _stored.BlendAlphaSeparateEnable = alphaSeparateEnable; + _stored.BlendSourceMul = srcmul; + _stored.BlendBlendFunc = blendFunc; + _stored.BlendDestMul = destmul; + _stored.BlendSourceAlpha = srcalpha; + _stored.BlendAlphaFunc = alphaFunc; + _stored.BlendDestAlpha = destalpha; + + _stored._valid[State_Blend] = true; +} + +void CubismRenderState_D3D9::SetViewport(LPDIRECT3DDEVICE9 device, DWORD left, DWORD top, DWORD width, DWORD height, float zMin, float zMax, csmBool force) +{ + if (!_stored._valid[State_Blend] || force || + _stored.ViewportX != left || _stored.ViewportY != top || _stored.ViewportWidth != width || _stored.ViewportHeight != height || + _stored.ViewportMinZ != zMin || _stored.ViewportMaxZ != zMax) + { + // コンテキストにセット + D3DVIEWPORT9 viewport; + viewport.X = left; + viewport.Y = top; + viewport.Width = width; + viewport.Height = height; + viewport.MinZ = zMin; + viewport.MaxZ = zMax; + device->SetViewport(&viewport); + } + + _stored.ViewportX = left; + _stored.ViewportY = top; + _stored.ViewportWidth = width; + _stored.ViewportHeight = height; + _stored.ViewportMinZ = zMin; + _stored.ViewportMaxZ = zMax; + + _stored._valid[State_Viewport] = true; +} + +void CubismRenderState_D3D9::SetColorMask(LPDIRECT3DDEVICE9 device, DWORD mask, csmBool force) +{ + if (!_stored._valid[State_Blend] || force || + _stored.ColorMaskMask != mask) + { + device->SetRenderState(D3DRS_COLORWRITEENABLE, mask); + } + + _stored.ColorMaskMask = mask; + + _stored._valid[State_ColorMask] = true; +} + +void CubismRenderState_D3D9::SetZEnable(LPDIRECT3DDEVICE9 device, D3DZBUFFERTYPE enable, D3DCMPFUNC zfunc, csmBool force) +{ + if (!_stored._valid[State_ZEnable] || force || + _stored.ZEnable != enable || _stored.ZFunc != zfunc) + { + device->SetRenderState(D3DRS_ZENABLE, enable); + device->SetRenderState(D3DRS_ZFUNC, zfunc); + } + + _stored.ZEnable = enable; + _stored.ZFunc = zfunc; + + _stored._valid[State_ZEnable] = true; +} + +void CubismRenderState_D3D9::SetCullMode(LPDIRECT3DDEVICE9 device, D3DCULL cullFace, csmBool force) +{ + if (!_stored._valid[State_CullMode] || force || + _stored.CullModeFaceMode != cullFace) + { + device->SetRenderState(D3DRS_CULLMODE, cullFace); + } + + _stored.CullModeFaceMode = cullFace; + + _stored._valid[State_CullMode] = true; +} + +void CubismRenderState_D3D9::SetTextureFilter(LPDIRECT3DDEVICE9 device, D3DTEXTUREFILTERTYPE minFilter, D3DTEXTUREFILTERTYPE magFilter, D3DTEXTUREFILTERTYPE mipFilter, D3DTEXTUREADDRESS addressU, D3DTEXTUREADDRESS addressV, csmBool force) +{ + if (!_stored._valid[State_TextureFilter] || force || + _stored.MinFilter != minFilter || + _stored.MagFilter != magFilter || + _stored.MipFilter != mipFilter || + _stored.AddressU != addressU || + _stored.AddressV != addressV) + { + device->SetSamplerState(0, D3DSAMP_MINFILTER, minFilter); + device->SetSamplerState(0, D3DSAMP_MAGFILTER, magFilter); + device->SetSamplerState(0, D3DSAMP_MIPFILTER, mipFilter); + device->SetSamplerState(0, D3DSAMP_ADDRESSU, addressU); + device->SetSamplerState(0, D3DSAMP_ADDRESSV, addressV); + } + + _stored.MinFilter = minFilter; + _stored.MagFilter = magFilter; + _stored.MipFilter = mipFilter; + _stored.AddressU = addressU; + _stored.AddressV = addressV; + + _stored._valid[State_TextureFilter] = true; +} + +void CubismRenderState_D3D9::SaveCurrentNativeState(LPDIRECT3DDEVICE9 device) +{ + // まずは全破棄 + _pushed.Clear(); + // 未設定扱いに + memset(_stored._valid, 0, sizeof(_stored._valid)); + + DWORD setting[16]; // 数は適当 +// Blend + device->GetRenderState(D3DRS_ALPHABLENDENABLE, &setting[0]); + device->GetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, &setting[1]); + device->GetRenderState(D3DRS_SRCBLEND, &setting[2]); + device->GetRenderState(D3DRS_BLENDOP, &setting[3]); + device->GetRenderState(D3DRS_DESTBLEND, &setting[4]); + device->GetRenderState(D3DRS_SRCBLENDALPHA, &setting[5]); + device->GetRenderState(D3DRS_BLENDOPALPHA, &setting[6]); + device->GetRenderState(D3DRS_DESTBLENDALPHA, &setting[7]); + SetBlend(device, + (setting[0] ? true : false), + (setting[1] ? true : false), + static_cast(setting[2]), static_cast(setting[3]), static_cast(setting[4]), + static_cast(setting[5]), static_cast(setting[6]), static_cast(setting[7]), true); + +// Viewport + D3DVIEWPORT9 viewport; + device->GetViewport(&viewport); + SetViewport(device, viewport.X, viewport.Y, viewport.Width, viewport.Height, viewport.MinZ, viewport.MaxZ, true); + +// ColorMask + device->GetRenderState(D3DRS_COLORWRITEENABLE, &setting[0]); + SetColorMask(device, setting[0], true); + +// ZEnable + device->GetRenderState(D3DRS_ZENABLE, &setting[0]); + device->GetRenderState(D3DRS_ZFUNC, &setting[1]); + SetZEnable(device, static_cast(setting[0]), static_cast(setting[1]), true); + +// Cull + device->GetRenderState(D3DRS_CULLMODE, &setting[0]); + SetCullMode(device, static_cast(setting[0]), true); + +// TextureFilter + device->GetSamplerState(0, D3DSAMP_MINFILTER, &setting[0]); + device->GetSamplerState(0, D3DSAMP_MAGFILTER, &setting[1]); + device->GetSamplerState(0, D3DSAMP_MIPFILTER, &setting[2]); + device->GetSamplerState(0, D3DSAMP_ADDRESSU, &setting[3]); + device->GetSamplerState(0, D3DSAMP_ADDRESSV, &setting[4]); + SetTextureFilter(device, static_cast(setting[0]), static_cast(setting[1]), static_cast(setting[2]), + static_cast(setting[3]), static_cast(setting[4]), true); + + // 最後に上記の値を保存 + Save(); +} + +void CubismRenderState_D3D9::RestoreNativeState(LPDIRECT3DDEVICE9 device) +{ + // 全て再現 + for (csmInt32 i = static_cast(_pushed.GetSize()) - 1; i >= 0; i--) + { + Restore(device); + } +} + +}}}} + +//------------ LIVE2D NAMESPACE ------------ diff --git a/CubismSDK/Framework/src/Rendering/D3D9/CubismRenderState_D3D9.hpp b/CubismSDK/Framework/src/Rendering/D3D9/CubismRenderState_D3D9.hpp new file mode 100644 index 0000000..2667786 --- /dev/null +++ b/CubismSDK/Framework/src/Rendering/D3D9/CubismRenderState_D3D9.hpp @@ -0,0 +1,225 @@ +/* + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#pragma once + +#include "CubismNativeInclude_D3D9.hpp" + +#include "Type/csmVector.hpp" +#include "Type/csmMap.hpp" + +//------------ LIVE2D NAMESPACE ------------ +namespace Live2D { namespace Cubism { namespace Framework { namespace Rendering { + +class CubismRenderer_D3D9; + +/** + * @brief CubismD3D9内部で設定するステートのうち、途中で変更する可能性のあるものを管理。 + * CubismRenderer_D3D9がシングルトンとして管理。 + */ +class CubismRenderState_D3D9 +{ + friend class CubismRenderer_D3D9; +public: + enum + { + State_None, + State_Blend, ///< ブレンドモード + State_Viewport, ///< ビューポート + State_ColorMask, ///< カラーマスク + State_RenderTarget, ///< レンダーターゲット + State_DepthTarget, ///< 深度ターゲット + State_ZEnable, ///< Z有効無効 + State_CullMode, ///< カリングモード + State_TextureFilter,///< テクスチャフィルター + State_Max, + }; + + /** + * @notice デフォルトの=でコピーします + */ + struct Stored + { + Stored() + { + BlendEnable = false; + BlendAlphaSeparateEnable = false; + BlendSourceMul = D3DBLEND_ZERO; + BlendBlendFunc = D3DBLENDOP_ADD; + BlendDestMul = D3DBLEND_ZERO; + BlendSourceAlpha = D3DBLEND_ZERO; + BlendAlphaFunc = D3DBLENDOP_ADD; + BlendDestAlpha = D3DBLEND_ZERO; + + ViewportX = 0; + ViewportY = 0; + ViewportWidth = 0; + ViewportHeight = 0; + ViewportMinZ = 0.0f; + ViewportMaxZ = 0.0f; + + ColorMaskMask = 0; + + ZEnable = D3DZB_FALSE; + ZFunc = D3DCMP_NEVER; + + CullModeFaceMode = D3DCULL_NONE; + + MinFilter = D3DTEXF_NONE; + MagFilter = D3DTEXF_NONE; + MipFilter = D3DTEXF_NONE; + AddressU = D3DTADDRESS_WRAP; + AddressV = D3DTADDRESS_WRAP; + + memset(_valid, 0, sizeof(_valid)); + } + + // State_Blend + bool BlendEnable; + bool BlendAlphaSeparateEnable; + D3DBLEND BlendSourceMul; + D3DBLENDOP BlendBlendFunc; + D3DBLEND BlendDestMul; + D3DBLEND BlendSourceAlpha; + D3DBLENDOP BlendAlphaFunc; + D3DBLEND BlendDestAlpha; + + // State_Viewport + DWORD ViewportX; + DWORD ViewportY; + DWORD ViewportWidth; + DWORD ViewportHeight; + float ViewportMinZ; + float ViewportMaxZ; + + // State_ColorMask + DWORD ColorMaskMask; + + // State_ZEnable + D3DZBUFFERTYPE ZEnable; + D3DCMPFUNC ZFunc; + + // State_CullMode + D3DCULL CullModeFaceMode; // 消す面を指定 CWだと時計回りが消える + + // State_TextureFilter サンプラー0番フィルター + D3DTEXTUREFILTERTYPE MinFilter; + D3DTEXTUREFILTERTYPE MagFilter; + D3DTEXTUREFILTERTYPE MipFilter; + D3DTEXTUREADDRESS AddressU; + D3DTEXTUREADDRESS AddressV; + + csmBool _valid[State_Max]; ///< 設定したかどうか。現在はStartFrameで一通りは呼んでいる + }; + + /** + * @brief フレーム先頭で呼び出す処理 + */ + void StartFrame(); + + /** + * @brief 管理中のステートをPush + */ + void Save(); + + + /** + * @brief Push下ステートをPop + * @notice Saveの際にCubismRenderState_D3D9で設定していなかった項目は戻せないことに注意 + */ + void Restore(LPDIRECT3DDEVICE9 device); + + + /** + * @brief ブレンドモードセット + * + * @param device[in] 描画デバイス + * @param enable[in] αブレンド有効無効 + * @param alphaSeparateEnable[in] αブレンドのうち、rgbとaの計算式を分離するかどうか + * @param srcmul[in] Srcカラー + * @param blendFunc[in] ブレンド関数 + * @param destmul[in] Destカラー + * @param srcalpha[in] Srcアルファ + * @param alphaFunc[in] α値ブレンド関数 + * @param destalpha[in] Destアルファ + * @param force[in] trueの場合は今の設定が何であろうと強制設定 + */ + void SetBlend(LPDIRECT3DDEVICE9 device, bool enable, bool alphaSeparateEnable, + D3DBLEND srcmul, D3DBLENDOP blendFunc, D3DBLEND destmul, + D3DBLEND srcalpha, D3DBLENDOP alphaFunc, D3DBLEND destalpha, + csmBool force=false); + + /** + * @brief ビューポートセット + * + * @param device[in] 描画デバイス + * @param left[in] ビューポート左座標 + * @param top[in] ビューポート上座標 + * @param width[in] ビューポート右座標 + * @param height[in] ビューポート下座標 + * @param zMin[in] Z最小値 + * @param zMax[in] Z最大値 + * @param force[in] trueの場合は今の設定が何であろうと強制設定 + */ + void SetViewport(LPDIRECT3DDEVICE9 device, DWORD left, DWORD top, DWORD width, DWORD height, float zMin, float zMax, csmBool force = false); + + /** + * @brief カラーマスクセット + */ + void SetColorMask(LPDIRECT3DDEVICE9 device, DWORD mask, csmBool force = false); + + /** + * @brief Z有効無効セット + * + * @param device[in] 描画デバイス + * @param force[in] trueの場合は今の設定が何であろうと強制設定 + */ + void SetZEnable(LPDIRECT3DDEVICE9 device, D3DZBUFFERTYPE enable, D3DCMPFUNC zfunc, csmBool force = false); + + /** + * @brief カリングモードセット + * + * @param device[in] 描画デバイス + * @param cullFace[in] 切除するべき面 指定された面を切る Cwだと時計回りを切除 + * @param force[in] trueの場合は今の設定が何であろうと強制設定 + */ + void SetCullMode(LPDIRECT3DDEVICE9 device, D3DCULL cullFace, csmBool force = false); + + /** + * @brief テクスチャサンプラー0番フィルタセット + * + * @param device[in] 描画デバイス + * @param minFilter[in] 縮小時フィルタ + * @param magFilter[in] 拡大時フィルタ + * @param mipFilter[in] ミップフィルタ + * @param addressU[in] アドレッシングモードU + * @param addressV[in] アドレッシングモードV + */ + void SetTextureFilter(LPDIRECT3DDEVICE9 device, D3DTEXTUREFILTERTYPE minFilter, D3DTEXTUREFILTERTYPE magFilter, D3DTEXTUREFILTERTYPE mipFilter, D3DTEXTUREADDRESS addressU, D3DTEXTUREADDRESS addressV, csmBool force = false); + +private: + CubismRenderState_D3D9(); + ~CubismRenderState_D3D9(); + + /** + * @brief D3DDeviceから、Cubismに関係する値を取得したうえでCubismRenderState_D3D9に反映しSaveを呼び出し、_pushedは破棄 + * Cubismフレーム処理の最初、StartFrameの後で呼んでいる + */ + void SaveCurrentNativeState(LPDIRECT3DDEVICE9 device); + + /** + * @brief 最初にPushしたステートまで戻す + */ + void RestoreNativeState(LPDIRECT3DDEVICE9 device); + + Stored _stored; ///< ストアされた各種設定 + + csmVector _pushed; +}; + +}}}} +//------------ LIVE2D NAMESPACE ------------ diff --git a/CubismSDK/Framework/src/Rendering/D3D9/CubismRenderer_D3D9.cpp b/CubismSDK/Framework/src/Rendering/D3D9/CubismRenderer_D3D9.cpp new file mode 100644 index 0000000..6a03d2b --- /dev/null +++ b/CubismSDK/Framework/src/Rendering/D3D9/CubismRenderer_D3D9.cpp @@ -0,0 +1,1273 @@ +/* + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#include "CubismRenderer_D3D9.hpp" + +#include // FLT_MAX,MIN + +#include "Math/CubismMatrix44.hpp" +#include "Type/csmVector.hpp" +#include "Model/CubismModel.hpp" +#include "CubismShader_D3D9.hpp" +#include "CubismRenderState_D3D9.hpp" + +//------------ LIVE2D NAMESPACE ------------ +namespace Live2D { namespace Cubism { namespace Framework { namespace Rendering { + +D3DXMATRIX ConvertToD3DX(CubismMatrix44& mtx) +{ + D3DXMATRIX retMtx; + retMtx._11 = mtx.GetArray()[ 0]; + retMtx._12 = mtx.GetArray()[ 1]; + retMtx._13 = mtx.GetArray()[ 2]; + retMtx._14 = mtx.GetArray()[ 3]; + + retMtx._21 = mtx.GetArray()[ 4]; + retMtx._22 = mtx.GetArray()[ 5]; + retMtx._23 = mtx.GetArray()[ 6]; + retMtx._24 = mtx.GetArray()[ 7]; + + retMtx._31 = mtx.GetArray()[ 8]; + retMtx._32 = mtx.GetArray()[ 9]; + retMtx._33 = mtx.GetArray()[10]; + retMtx._34 = mtx.GetArray()[11]; + + retMtx._41 = mtx.GetArray()[12]; + retMtx._42 = mtx.GetArray()[13]; + retMtx._43 = mtx.GetArray()[14]; + retMtx._44 = mtx.GetArray()[15]; + + return retMtx; +} + +/********************************************************************************************************************* +* CubismClippingManager_DX9 +********************************************************************************************************************/ +///< ファイルスコープの変数宣言 +namespace { +const csmInt32 ColorChannelCount = 4; ///< 実験時に1チャンネルの場合は1、RGBだけの場合は3、アルファも含める場合は4 +} + +CubismClippingManager_DX9::CubismClippingManager_DX9() + : _colorBuffer(NULL) + , _currentFrameNo(0) + , _clippingMaskBufferSize(256) +{ + CubismRenderer::CubismTextureColor* tmp = NULL; + tmp = CSM_NEW CubismRenderer::CubismTextureColor(); + tmp->R = 1.0f; + tmp->G = 0.0f; + tmp->B = 0.0f; + tmp->A = 0.0f; + _channelColors.PushBack(tmp); + tmp = CSM_NEW CubismRenderer::CubismTextureColor(); + tmp->R = 0.0f; + tmp->G = 1.0f; + tmp->B = 0.0f; + tmp->A = 0.0f; + _channelColors.PushBack(tmp); + tmp = CSM_NEW CubismRenderer::CubismTextureColor(); + tmp->R = 0.0f; + tmp->G = 0.0f; + tmp->B = 1.0f; + tmp->A = 0.0f; + _channelColors.PushBack(tmp); + tmp = CSM_NEW CubismRenderer::CubismTextureColor(); + tmp->R = 0.0f; + tmp->G = 0.0f; + tmp->B = 0.0f; + tmp->A = 1.0f; + _channelColors.PushBack(tmp); + +} + +CubismClippingManager_DX9::~CubismClippingManager_DX9() +{ + for (csmUint32 i = 0; i < _clippingContextListForMask.GetSize(); i++) + { + if (_clippingContextListForMask[i]) CSM_DELETE_SELF(CubismClippingContext, _clippingContextListForMask[i]); + _clippingContextListForMask[i] = NULL; + } + + // _clippingContextListForDrawは_clippingContextListForMaskにあるインスタンスを指している。上記の処理により要素ごとのDELETEは不要。 + for (csmUint32 i = 0; i < _clippingContextListForDraw.GetSize(); i++) + { + _clippingContextListForDraw[i] = NULL; + } + + for (csmUint32 i = 0; i < _channelColors.GetSize(); i++) + { + if (_channelColors[i]) CSM_DELETE(_channelColors[i]); + _channelColors[i] = NULL; + } +} + +void CubismClippingManager_DX9::Initialize(CubismModel& model, csmInt32 drawableCount, const csmInt32** drawableMasks, const csmInt32* drawableMaskCounts) +{ + //クリッピングマスクを使う描画オブジェクトを全て登録する + //クリッピングマスクは、通常数個程度に限定して使うものとする + for (csmInt32 i = 0; i < drawableCount; i++) + { + if (drawableMaskCounts[i] <= 0) + { + //クリッピングマスクが使用されていないアートメッシュ(多くの場合使用しない) + _clippingContextListForDraw.PushBack(NULL); + continue; + } + + // 既にあるClipContextと同じかチェックする + CubismClippingContext* cc = FindSameClip(drawableMasks[i], drawableMaskCounts[i]); + if (cc == NULL) + { + // 同一のマスクが存在していない場合は生成する + cc = CSM_NEW CubismClippingContext(this, drawableMasks[i], drawableMaskCounts[i]); + _clippingContextListForMask.PushBack(cc); + } + + cc->AddClippedDrawable(i); + + _clippingContextListForDraw.PushBack(cc); + } +} + +CubismClippingContext* CubismClippingManager_DX9::FindSameClip(const csmInt32* drawableMasks, csmInt32 drawableMaskCounts) const +{ + // 作成済みClippingContextと一致するか確認 + for (csmUint32 i = 0; i < _clippingContextListForMask.GetSize(); i++) + { + CubismClippingContext* cc = _clippingContextListForMask[i]; + const csmInt32 count = cc->_clippingIdCount; + if (count != drawableMaskCounts) continue; //個数が違う場合は別物 + csmInt32 samecount = 0; + + // 同じIDを持つか確認。配列の数が同じなので、一致した個数が同じなら同じ物を持つとする。 + for (csmInt32 j = 0; j < count; j++) + { + const csmInt32 clipId = cc->_clippingIdList[j]; + for (csmInt32 k = 0; k < count; k++) + { + if (drawableMasks[k] == clipId) + { + samecount++; + break; + } + } + } + if (samecount == count) + { + return cc; + } + } + return NULL; //見つからなかった +} + +void CubismClippingManager_DX9::SetupClippingContext(LPDIRECT3DDEVICE9 device, CubismModel& model, CubismRenderer_D3D9* renderer, CubismOffscreenFrame_D3D9& useTarget) +{ + _currentFrameNo++; + + // 全てのクリッピングを用意する + // 同じクリップ(複数の場合はまとめて1つのクリップ)を使う場合は1度だけ設定する + csmInt32 usingClipCount = 0; + for (csmUint32 clipIndex = 0; clipIndex < _clippingContextListForMask.GetSize(); clipIndex++) + { + // 1つのクリッピングマスクに関して + CubismClippingContext* cc = _clippingContextListForMask[clipIndex]; + + // このクリップを利用する描画オブジェクト群全体を囲む矩形を計算 + CalcClippedDrawTotalBounds(model, cc); + + if (cc->_isUsing) + { + usingClipCount++; //使用中としてカウント + } + } + + + // マスク作成処理 + if (usingClipCount > 0) + { + // ビューポートは退避済み + // 生成したFrameBufferと同じサイズでビューポートを設定 + CubismRenderer_D3D9::GetRenderStateManager()->SetViewport(device, + 0, + 0, + _clippingMaskBufferSize, + _clippingMaskBufferSize, + 0.0f, 1.0f); + + useTarget.BeginDraw(device); + + // 各マスクのレイアウトを決定していく + SetupLayoutBounds(usingClipCount); + + // 実際にマスクを生成する + // 全てのマスクをどの様にレイアウトして描くかを決定し、ClipContext , ClippedDrawContext に記憶する + for (csmUint32 clipIndex = 0; clipIndex < _clippingContextListForMask.GetSize(); clipIndex++) + { + // --- 実際に1つのマスクを描く --- + CubismClippingContext* clipContext = _clippingContextListForMask[clipIndex]; + csmRectF* allClippedDrawRect = clipContext->_allClippedDrawRect; //このマスクを使う、全ての描画オブジェクトの論理座標上の囲み矩形 + csmRectF* layoutBoundsOnTex01 = clipContext->_layoutBounds; //この中にマスクを収める + + // モデル座標上の矩形を、適宜マージンを付けて使う + const csmFloat32 MARGIN = 0.05f; + _tmpBoundsOnModel.SetRect(allClippedDrawRect); + _tmpBoundsOnModel.Expand(allClippedDrawRect->Width * MARGIN, allClippedDrawRect->Height * MARGIN); + //########## 本来は割り当てられた領域の全体を使わず必要最低限のサイズがよい + + // シェーダ用の計算式を求める。回転を考慮しない場合は以下のとおり + // movePeriod' = movePeriod * scaleX + offX [[ movePeriod' = (movePeriod - tmpBoundsOnModel.movePeriod)*scale + layoutBoundsOnTex01.movePeriod ]] + const csmFloat32 scaleX = layoutBoundsOnTex01->Width / _tmpBoundsOnModel.Width; + const csmFloat32 scaleY = layoutBoundsOnTex01->Height / _tmpBoundsOnModel.Height; + + // マスク生成時に使う行列を求める + { + // シェーダに渡す行列を求める <<<<<<<<<<<<<<<<<<<<<<<< 要最適化(逆順に計算すればシンプルにできる) + _tmpMatrix.LoadIdentity(); + { + // Layout0..1 を -1..1に変換 + _tmpMatrix.TranslateRelative(-1.0f, -1.0f); + _tmpMatrix.ScaleRelative(2.0f, 2.0f); + } + { + // view to Layout0..1 + _tmpMatrix.TranslateRelative(layoutBoundsOnTex01->X, layoutBoundsOnTex01->Y); //new = [translate] + _tmpMatrix.ScaleRelative(scaleX, scaleY); //new = [translate][scale] + _tmpMatrix.TranslateRelative(-_tmpBoundsOnModel.X, -_tmpBoundsOnModel.Y); + //new = [translate][scale][translate] + } + // tmpMatrixForMask が計算結果 + _tmpMatrixForMask.SetMatrix(_tmpMatrix.GetArray()); + } + + //--------- draw時の mask 参照用行列を計算 + { + // シェーダに渡す行列を求める <<<<<<<<<<<<<<<<<<<<<<<< 要最適化(逆順に計算すればシンプルにできる) + _tmpMatrix.LoadIdentity(); + { + _tmpMatrix.TranslateRelative(layoutBoundsOnTex01->X, layoutBoundsOnTex01->Y); //new = [translate] + // 上下反転 + _tmpMatrix.ScaleRelative(scaleX, scaleY * -1.0f ); //new = [translate][scale] + _tmpMatrix.TranslateRelative(-_tmpBoundsOnModel.X, -_tmpBoundsOnModel.Y); + //new = [translate][scale][translate] + } + + _tmpMatrixForDraw.SetMatrix(_tmpMatrix.GetArray()); + } + + clipContext->_matrixForMask.SetMatrix(_tmpMatrixForMask.GetArray()); + + clipContext->_matrixForDraw.SetMatrix(_tmpMatrixForDraw.GetArray()); + + const csmInt32 clipDrawCount = clipContext->_clippingIdCount; + for (csmInt32 i = 0; i < clipDrawCount; i++) + { + const csmInt32 clipDrawIndex = clipContext->_clippingIdList[i]; + + renderer->IsCulling(model.GetDrawableCulling(clipDrawIndex) != 0); + + // 今回専用の変換を適用して描く + // チャンネルも切り替える必要がある(A,R,G,B) + renderer->SetClippingContextBufferForMask(clipContext); + renderer->DrawMeshDX9(clipDrawIndex, + model.GetDrawableTextureIndices(clipDrawIndex), + model.GetDrawableVertexIndexCount(clipDrawIndex), + model.GetDrawableVertexCount(clipDrawIndex), + const_cast(model.GetDrawableVertexIndices(clipDrawIndex)), + const_cast(model.GetDrawableVertices(clipDrawIndex)), + reinterpret_cast(const_cast(model.GetDrawableVertexUvs(clipDrawIndex))), + model.GetDrawableOpacity(clipDrawIndex), + CubismRenderer::CubismBlendMode::CubismBlendMode_Normal); //クリッピングは通常描画を強制 + } + } + + useTarget.EndDraw(device); + + renderer->SetClippingContextBufferForMask(NULL); + } +} + +void CubismClippingManager_DX9::CalcClippedDrawTotalBounds(CubismModel& model, CubismClippingContext* clippingContext) +{ + // 被クリッピングマスク(マスクされる描画オブジェクト)の全体の矩形 + csmFloat32 clippedDrawTotalMinX = FLT_MAX, clippedDrawTotalMinY = FLT_MAX; + csmFloat32 clippedDrawTotalMaxX = FLT_MIN, clippedDrawTotalMaxY = FLT_MIN; + + // このマスクが実際に必要か判定する + // このクリッピングを利用する「描画オブジェクト」がひとつでも使用可能であればマスクを生成する必要がある + + const csmInt32 clippedDrawCount = clippingContext->_clippedDrawableIndexList->GetSize(); + for (csmInt32 clippedDrawableIndex = 0; clippedDrawableIndex < clippedDrawCount; clippedDrawableIndex++) + { + // マスクを使用する描画オブジェクトの描画される矩形を求める + const csmInt32 drawableIndex = (*clippingContext->_clippedDrawableIndexList)[clippedDrawableIndex]; + + const csmInt32 drawableVertexCount = model.GetDrawableVertexCount(drawableIndex); + const csmFloat32* drawableVertexes = const_cast(model.GetDrawableVertices(drawableIndex)); + + csmFloat32 minX = FLT_MAX, minY = FLT_MAX; + csmFloat32 maxX = FLT_MIN, maxY = FLT_MIN; + + csmInt32 loop = drawableVertexCount * Constant::VertexStep; + for (csmInt32 pi = Constant::VertexOffset; pi < loop; pi += Constant::VertexStep) + { + csmFloat32 x = drawableVertexes[pi]; + csmFloat32 y = drawableVertexes[pi + 1]; + if (x < minX) minX = x; + if (x > maxX) maxX = x; + if (y < minY) minY = y; + if (y > maxY) maxY = y; + } + + // + if (minX == FLT_MAX) continue; //有効な点がひとつも取れなかったのでスキップする + + // 全体の矩形に反映 + if (minX < clippedDrawTotalMinX) clippedDrawTotalMinX = minX; + if (minY < clippedDrawTotalMinY) clippedDrawTotalMinY = minY; + if (maxX > clippedDrawTotalMaxX) clippedDrawTotalMaxX = maxX; + if (maxY > clippedDrawTotalMaxY) clippedDrawTotalMaxY = maxY; + } + if (clippedDrawTotalMinX == FLT_MAX) + { + clippingContext->_allClippedDrawRect->X = 0.0f; + clippingContext->_allClippedDrawRect->Y = 0.0f; + clippingContext->_allClippedDrawRect->Width = 0.0f; + clippingContext->_allClippedDrawRect->Height = 0.0f; + clippingContext->_isUsing = false; + } + else + { + clippingContext->_isUsing = true; + csmFloat32 w = clippedDrawTotalMaxX - clippedDrawTotalMinX; + csmFloat32 h = clippedDrawTotalMaxY - clippedDrawTotalMinY; + clippingContext->_allClippedDrawRect->X = clippedDrawTotalMinX; + clippingContext->_allClippedDrawRect->Y = clippedDrawTotalMinY; + clippingContext->_allClippedDrawRect->Width = w; + clippingContext->_allClippedDrawRect->Height = h; + } +} + +void CubismClippingManager_DX9::SetupLayoutBounds(csmInt32 usingClipCount) const +{ + // ひとつのRenderTextureを極力いっぱいに使ってマスクをレイアウトする + // マスクグループの数が4以下ならRGBA各チャンネルに1つずつマスクを配置し、5以上6以下ならRGBAを2,2,1,1と配置する + + // RGBAを順番に使っていく。 + const csmInt32 div = usingClipCount / ColorChannelCount; //1チャンネルに配置する基本のマスク個数 + const csmInt32 mod = usingClipCount % ColorChannelCount; //余り、この番号のチャンネルまでに1つずつ配分する + + // RGBAそれぞれのチャンネルを用意していく(0:R , 1:G , 2:B, 3:A, ) + csmInt32 curClipIndex = 0; //順番に設定していく + + for (csmInt32 channelNo = 0; channelNo < ColorChannelCount; channelNo++) + { + // このチャンネルにレイアウトする数 + const csmInt32 layoutCount = div + (channelNo < mod ? 1 : 0); + + // 分割方法を決定する + if (layoutCount == 0) + { + // 何もしない + } + else if (layoutCount == 1) + { + //全てをそのまま使う + CubismClippingContext* cc = _clippingContextListForMask[curClipIndex++]; + cc->_layoutChannelNo = channelNo; + cc->_layoutBounds->X = 0.0f; + cc->_layoutBounds->Y = 0.0f; + cc->_layoutBounds->Width = 1.0f; + cc->_layoutBounds->Height = 1.0f; + } + else if (layoutCount == 2) + { + for (csmInt32 i = 0; i < layoutCount; i++) + { + const csmInt32 xpos = i % 2; + + CubismClippingContext* cc = _clippingContextListForMask[curClipIndex++]; + cc->_layoutChannelNo = channelNo; + + cc->_layoutBounds->X = xpos * 0.5f; + cc->_layoutBounds->Y = 0.0f; + cc->_layoutBounds->Width = 0.5f; + cc->_layoutBounds->Height = 1.0f; + //UVを2つに分解して使う + } + } + else if (layoutCount <= 4) + { + //4分割して使う + for (csmInt32 i = 0; i < layoutCount; i++) + { + const csmInt32 xpos = i % 2; + const csmInt32 ypos = i / 2; + + CubismClippingContext* cc = _clippingContextListForMask[curClipIndex++]; + cc->_layoutChannelNo = channelNo; + + cc->_layoutBounds->X = xpos * 0.5f; + cc->_layoutBounds->Y = ypos * 0.5f; + cc->_layoutBounds->Width = 0.5f; + cc->_layoutBounds->Height = 0.5f; + } + } + else if (layoutCount <= 9) + { + //9分割して使う + for (csmInt32 i = 0; i < layoutCount; i++) + { + const csmInt32 xpos = i % 3; + const csmInt32 ypos = i / 3; + + CubismClippingContext* cc = _clippingContextListForMask[curClipIndex++]; + cc->_layoutChannelNo = channelNo; + + cc->_layoutBounds->X = xpos / 3.0f; + cc->_layoutBounds->Y = ypos / 3.0f; + cc->_layoutBounds->Width = 1.0f / 3.0f; + cc->_layoutBounds->Height = 1.0f / 3.0f; + } + } + else + { + CubismLogError("not supported mask count : %d", layoutCount); + } + } +} + +CubismRenderer::CubismTextureColor* CubismClippingManager_DX9::GetChannelFlagAsColor(csmInt32 channelNo) +{ + return _channelColors[channelNo]; +} + +CubismOffscreenFrame_D3D9* CubismClippingManager_DX9::GetColorBuffer() const +{ + return _colorBuffer; +} + +csmVector* CubismClippingManager_DX9::GetClippingContextListForDraw() +{ + return &_clippingContextListForDraw; +} + +void CubismClippingManager_DX9::SetClippingMaskBufferSize(csmInt32 size) +{ + _clippingMaskBufferSize = size; +} + +csmInt32 CubismClippingManager_DX9::GetClippingMaskBufferSize() const +{ + return _clippingMaskBufferSize; +} + +/********************************************************************************************************************* +* CubismClippingContext +********************************************************************************************************************/ +CubismClippingContext::CubismClippingContext(CubismClippingManager_DX9* manager, const csmInt32* clippingDrawableIndices, csmInt32 clipCount) +{ + _isUsing = false; + + _owner = manager; + + // クリップしている(=マスク用の)Drawableのインデックスリスト + _clippingIdList = clippingDrawableIndices; + + // マスクの数 + _clippingIdCount = clipCount; + + _layoutChannelNo = 0; + + _allClippedDrawRect = CSM_NEW csmRectF(); + _layoutBounds = CSM_NEW csmRectF(); + + _clippedDrawableIndexList = CSM_NEW csmVector(); +} + +CubismClippingContext::~CubismClippingContext() +{ + if (_layoutBounds != NULL) + { + CSM_DELETE(_layoutBounds); + _layoutBounds = NULL; + } + + if (_allClippedDrawRect != NULL) + { + CSM_DELETE(_allClippedDrawRect); + _allClippedDrawRect = NULL; + } + + if (_clippedDrawableIndexList != NULL) + { + CSM_DELETE(_clippedDrawableIndexList); + _clippedDrawableIndexList = NULL; + } +} + +void CubismClippingContext::AddClippedDrawable(csmInt32 drawableIndex) +{ + _clippedDrawableIndexList->PushBack(drawableIndex); +} + +CubismClippingManager_DX9* CubismClippingContext::GetClippingManager() +{ + return _owner; +} + + +/********************************************************************************************************************* + * CubismRenderer_D3D9 + ********************************************************************************************************************/ + +namespace { + CubismRenderState_D3D9* s_renderStateManagerInstance; ///< レンダーステートの管理 + CubismShader_D3D9* s_shaderManagerInstance; ///< シェーダー管理 + + csmUint32 s_bufferSetNum; ///< 作成コンテキストの数。モデルロード前に設定されている必要あり。 + LPDIRECT3DDEVICE9 s_useDevice; ///< 使用デバイス。モデルロード前に設定されている必要あり。 + + csmUint32 s_viewportWidth; ///< 描画ターゲット幅 CubismRenderer_D3D9::startframeで渡されます + csmUint32 s_viewportHeight; ///< 描画ターゲット高さ CubismRenderer_D3D9::startframeで渡されます +} + +CubismRenderer* CubismRenderer::Create() +{ + return CSM_NEW CubismRenderer_D3D9(); +} + +void CubismRenderer::StaticRelease() +{ + CubismRenderer_D3D9::DoStaticRelease(); +} + +CubismRenderState_D3D9* CubismRenderer_D3D9::GetRenderStateManager() +{ + if (s_renderStateManagerInstance == NULL) + { + s_renderStateManagerInstance = CSM_NEW CubismRenderState_D3D9(); + } + return s_renderStateManagerInstance; +} + +void CubismRenderer_D3D9::DeleteRenderStateManager() +{ + if (s_renderStateManagerInstance) + { + CSM_DELETE_SELF(CubismRenderState_D3D9, s_renderStateManagerInstance); + s_renderStateManagerInstance = NULL; + } +} + +CubismShader_D3D9* CubismRenderer_D3D9::GetShaderManager() +{ + if (s_shaderManagerInstance == NULL) + { + s_shaderManagerInstance = CSM_NEW CubismShader_D3D9(); + } + return s_shaderManagerInstance; +} + +void CubismRenderer_D3D9::DeleteShaderManager() +{ + if (s_shaderManagerInstance) + { + CSM_DELETE_SELF(CubismShader_D3D9, s_shaderManagerInstance); + s_shaderManagerInstance = NULL; + } +} + +void CubismRenderer_D3D9::GenerateShader(LPDIRECT3DDEVICE9 device) +{ + CubismShader_D3D9* shaderManager = GetShaderManager(); + if(shaderManager) + { + shaderManager->GenerateShaders(device); + } +} + +void CubismRenderer_D3D9::OnDeviceLost() +{ + // シェーダー・頂点宣言開放 + ReleaseShader(); +} + +void CubismRenderer_D3D9::ReleaseShader() +{ + CubismShader_D3D9* shaderManager = GetShaderManager(); + if (shaderManager) + { + shaderManager->ReleaseShaderProgram(); + } +} + +CubismRenderer_D3D9::CubismRenderer_D3D9() + : _drawableNum(0) + , _vertexStore(NULL) + , _indexStore(NULL) + , _clippingManager(NULL) + , _clippingContextBufferForMask(NULL) + , _clippingContextBufferForDraw(NULL) +{ + _commandBufferNum = 0; + _commandBufferCurrent = 0; + + // テクスチャ対応マップの容量を確保しておく. + _textures.PrepareCapacity(32, true); +} + +CubismRenderer_D3D9::~CubismRenderer_D3D9() +{ + { + // オフスクリーンを作成していたのなら開放 + for (csmUint32 i = 0; i < _offscreenFrameBuffer.GetSize(); i++) + { + _offscreenFrameBuffer[i].DestroyOffscreenFrame(); + } + _offscreenFrameBuffer.Clear(); + } + + const csmInt32 drawableCount = _drawableNum; //GetModel()->GetDrawableCount(); + + for (csmInt32 drawAssign = 0; drawAssign < drawableCount; drawAssign++) + { + // インデックス + if (_indexStore[drawAssign]) + { + CSM_FREE(_indexStore[drawAssign]); + } + // 頂点 + if (_vertexStore[drawAssign]) + { + CSM_FREE(_vertexStore[drawAssign]); + } + } + + CSM_FREE(_indexStore); + CSM_FREE(_vertexStore); + _indexStore = NULL; + _vertexStore = NULL; + + CSM_DELETE_SELF(CubismClippingManager_DX9, _clippingManager); +} + +void CubismRenderer_D3D9::DoStaticRelease() +{ + // レンダーステートマネージャ削除 + DeleteRenderStateManager(); + // シェーダマネージャ削除 + DeleteShaderManager(); +} + + +void CubismRenderer_D3D9::Initialize(CubismModel* model) +{ + // 0は許されず ここに来るまでに設定しなければならない + if (s_bufferSetNum == 0) + { + CubismLogError("ContextNum has not been set."); + CSM_ASSERT(0); + return; + } + if (s_useDevice == 0) + { + CubismLogError("Device has not been set."); + CSM_ASSERT(0); + return; + } + + if (model->IsUsingMasking()) + { + _clippingManager = CSM_NEW CubismClippingManager_DX9(); //クリッピングマスク・バッファ前処理方式を初期化 + _clippingManager->Initialize( + *model, + model->GetDrawableCount(), + model->GetDrawableMasks(), + model->GetDrawableMaskCounts() + ); + } + + _sortedDrawableIndexList.Resize(model->GetDrawableCount(), 0); + + CubismRenderer::Initialize(model); //親クラスの処理を呼ぶ + + // モデルパーツごとに確保 + const csmInt32 drawableCount = GetModel()->GetDrawableCount(); + _drawableNum = drawableCount; + + _vertexStore = static_cast(CSM_MALLOC(sizeof(CubismVertexD3D9*) * drawableCount)); + _indexStore = static_cast(CSM_MALLOC(sizeof(csmUint16*) * drawableCount)); + + for (csmInt32 drawAssign = 0; drawAssign < drawableCount; drawAssign++) + { + // 頂点 + const csmInt32 vcount = GetModel()->GetDrawableVertexCount(drawAssign); + if (vcount != 0) + { + _vertexStore[drawAssign] = static_cast(CSM_MALLOC(sizeof(CubismVertexD3D9) * vcount)); + } + else + { + _vertexStore[drawAssign] = NULL; + } + + // インデックスはここで要素コピーを済ませる + const csmInt32 icount = GetModel()->GetDrawableVertexIndexCount(drawAssign); + if (icount != 0) + { + _indexStore[drawAssign] = static_cast(CSM_MALLOC(sizeof(csmUint16) * icount)); + const csmUint16* idxarray = GetModel()->GetDrawableVertexIndices(drawAssign); + for (csmInt32 ct = 0; ct < icount; ct++) + {// モデルデータからのコピー + _indexStore[drawAssign][ct] = idxarray[ct]; + } + } + else + { + _indexStore[drawAssign] = NULL; + } + } + + _commandBufferNum = s_bufferSetNum; + _commandBufferCurrent = 0; + + if (model->IsUsingMasking()) + { + const csmInt32 bufferHeight = _clippingManager->GetClippingMaskBufferSize(); + + // バックバッファ分確保 + for (csmUint32 i = 0; i < s_bufferSetNum; i++) + { + CubismOffscreenFrame_D3D9 push; + _offscreenFrameBuffer.PushBack(push); + } + // オフスクリーン + for (csmUint32 i = 0; i < s_bufferSetNum; i++) + { + _offscreenFrameBuffer[i].CreateOffscreenFrame( + s_useDevice, + bufferHeight, bufferHeight); + } + } +} + +void CubismRenderer_D3D9::FrameRenderingInit() +{ +} + +void CubismRenderer_D3D9::PreDraw() +{ + SetDefaultRenderState(); +} + +void CubismRenderer_D3D9::PostDraw() +{ + _commandBufferCurrent++; + if (_commandBufferNum <= _commandBufferCurrent) + { + _commandBufferCurrent = 0; + } +} + +void CubismRenderer_D3D9::DoDrawModel() +{ + // NULLは許されず + CSM_ASSERT(s_useDevice != NULL); + + PreDraw(); + + //------------ クリッピングマスク・バッファ前処理方式の場合 ------------ + if (_clippingManager != NULL) + { + _clippingManager->SetupClippingContext(s_useDevice, *GetModel(), this, _offscreenFrameBuffer[_commandBufferCurrent]); + _clippingManager->_colorBuffer = &_offscreenFrameBuffer[_commandBufferCurrent]; + + // ビューポート + GetRenderStateManager()->SetViewport(s_useDevice, + 0, + 0, + s_viewportWidth, + s_viewportHeight, + 0.0f, 1.0); + } + + const csmInt32 drawableCount = GetModel()->GetDrawableCount(); + const csmInt32* renderOrder = GetModel()->GetDrawableRenderOrders(); + + // インデックスを描画順でソート + for (csmInt32 i = 0; i < drawableCount; ++i) + { + const csmInt32 order = renderOrder[i]; + _sortedDrawableIndexList[order] = i; + } + + // 描画 + for (csmInt32 i = 0; i < drawableCount; ++i) + { + const csmInt32 drawableIndex = _sortedDrawableIndexList[i]; + + // クリッピングマスクをセットする + SetClippingContextBufferForDraw((_clippingManager != NULL) + ? (*_clippingManager->GetClippingContextListForDraw())[drawableIndex] + : NULL); + + IsCulling(GetModel()->GetDrawableCulling(drawableIndex) != 0); + + DrawMeshDX9(drawableIndex, + GetModel()->GetDrawableTextureIndices(drawableIndex), + GetModel()->GetDrawableVertexIndexCount(drawableIndex), + GetModel()->GetDrawableVertexCount(drawableIndex), + const_cast(GetModel()->GetDrawableVertexIndices(drawableIndex)), + const_cast(GetModel()->GetDrawableVertices(drawableIndex)), + reinterpret_cast(const_cast(GetModel()->GetDrawableVertexUvs(drawableIndex))), + GetModel()->GetDrawableOpacity(drawableIndex), + GetModel()->GetDrawableBlendMode(drawableIndex)); + } + + // + PostDraw(); + +} + +void CubismRenderer_D3D9::ExecuteDraw(LPDIRECT3DDEVICE9 device, CubismVertexD3D9* vertexArray, csmUint16* indexArray, + const csmInt32 vertexCount, const csmInt32 triangleCount, + const csmInt32 textureNo, CubismTextureColor& modelColorRGBA, CubismBlendMode colorBlendMode) +{ + // 使用シェーダエフェクト取得 + CubismShader_D3D9* shaderManager = Live2D::Cubism::Framework::Rendering::CubismRenderer_D3D9::GetShaderManager(); + if(!shaderManager) + { + return; + } + + // テクスチャセット + LPDIRECT3DTEXTURE9 texture = NULL; + if (textureNo >= 0) + { + texture = _textures[textureNo]; + } + + if (texture == NULL) + { + return; // モデルが参照するテクスチャがバインドされていない場合は描画をスキップする + } + + if (GetClippingContextBufferForMask() != NULL) // マスク生成時 + { + ID3DXEffect* shaderEffect = shaderManager->GetShaderEffect(); + if (shaderEffect) + { + UINT numPass = 0; + shaderEffect->SetTechnique("ShaderNames_SetupMask"); + + // numPassには指定のtechnique内に含まれるpassの数が返る + shaderEffect->Begin(&numPass, 0); + shaderEffect->BeginPass(0); + + + // チャンネル + const csmInt32 channelNo = GetClippingContextBufferForMask()->_layoutChannelNo; + // チャンネルをRGBAに変換 + CubismTextureColor* colorChannel = GetClippingContextBufferForMask()->GetClippingManager()->GetChannelFlagAsColor(channelNo); + + GetRenderStateManager()->SetBlend(device, + true, + true, + D3DBLEND_ZERO, + D3DBLENDOP_ADD, + D3DBLEND_INVSRCCOLOR, + D3DBLEND_ZERO, + D3DBLENDOP_ADD, + D3DBLEND_INVSRCALPHA); + + // 定数バッファ + { + csmRectF* rect = GetClippingContextBufferForMask()->_layoutBounds; + + CubismMatrix44 modelToWorldF = GetClippingContextBufferForMask()->_matrixForMask; + D3DXMATRIX proj = ConvertToD3DX(modelToWorldF); + shaderEffect->SetMatrix("projectMatrix", &proj); + + D3DXVECTOR4 color(rect->X * 2.0f - 1.0f, rect->Y * 2.0f - 1.0f, rect->GetRight() * 2.0f - 1.0f, rect->GetBottom() * 2.0f - 1.0f); + shaderEffect->SetVector("baseColor", &color); + + D3DXVECTOR4 channel(colorChannel->R, colorChannel->G, colorChannel->B, colorChannel->A); + shaderEffect->SetVector("channelFlag", &channel); + + + // テクスチャセット + shaderEffect->SetTexture("mainTexture", texture); + // 使わない場合はNULLを必ず代入 + shaderEffect->SetTexture("maskTexture", NULL); + + // パラメータ反映 + shaderEffect->CommitChanges(); + } + + + // 描画 + device->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, vertexCount, triangleCount, indexArray, D3DFMT_INDEX16, vertexArray, sizeof(CubismVertexD3D9)); + + shaderEffect->EndPass(); + shaderEffect->End(); + + } + } + else // マスク生成以外の場合 + { + const csmBool masked = GetClippingContextBufferForDraw() != NULL; // この描画オブジェクトはマスク対象か + const csmBool premult = IsPremultipliedAlpha(); + const csmInt32 offset = (masked ? 1 : 0) + (IsPremultipliedAlpha() ? 2 : 0); + + switch (colorBlendMode) + { + case CubismRenderer::CubismBlendMode::CubismBlendMode_Normal: + default: + GetRenderStateManager()->SetBlend(device, + true, + true, + D3DBLEND_ONE, + D3DBLENDOP_ADD, + D3DBLEND_INVSRCALPHA, + D3DBLEND_ONE, + D3DBLENDOP_ADD, + D3DBLEND_INVSRCALPHA); + break; + + case CubismRenderer::CubismBlendMode::CubismBlendMode_Additive: + GetRenderStateManager()->SetBlend(device, + true, + true, + D3DBLEND_ONE, + D3DBLENDOP_ADD, + D3DBLEND_ONE, + D3DBLEND_ZERO, + D3DBLENDOP_ADD, + D3DBLEND_ONE); + break; + + case CubismRenderer::CubismBlendMode::CubismBlendMode_Multiplicative: + GetRenderStateManager()->SetBlend(device, + true, + true, + D3DBLEND_DESTCOLOR, + D3DBLENDOP_ADD, + D3DBLEND_INVSRCALPHA, + D3DBLEND_ZERO, + D3DBLENDOP_ADD, + D3DBLEND_ONE); + break; + } + + ID3DXEffect* shaderEffect = shaderManager->GetShaderEffect(); + if (shaderEffect) + { + UINT numPass = 0; + if (masked) + { + if(premult) + { + shaderEffect->SetTechnique("ShaderNames_NormalMaskedPremultipliedAlpha"); + } + else + { + shaderEffect->SetTechnique("ShaderNames_NormalMasked"); + } + } + else + { + if(premult) + { + shaderEffect->SetTechnique("ShaderNames_NormalPremultipliedAlpha"); + } + else + { + shaderEffect->SetTechnique("ShaderNames_Normal"); + } + } + + // numPassには指定のtechnique内に含まれるpassの数が返る + shaderEffect->Begin(&numPass, 0); + shaderEffect->BeginPass(0); + + if (!masked) + { + // テクスチャセット + shaderEffect->SetTexture("mainTexture", texture); + // 使わない場合はNULLを必ず代入 + shaderEffect->SetTexture("maskTexture", NULL); + } + else + { + // テクスチャセット メイン + shaderEffect->SetTexture("mainTexture", texture); + // テクスチャセット マスク + shaderEffect->SetTexture("maskTexture", _clippingManager->_colorBuffer->_texture); + } + + // 定数バッファ + { + if (masked) + { + // View座標をClippingContextの座標に変換するための行列を設定 + + CubismMatrix44 ClipF = GetClippingContextBufferForDraw()->_matrixForDraw; + D3DXMATRIX clipM = ConvertToD3DX(ClipF); + shaderEffect->SetMatrix("clipMatrix", &clipM); + + // 使用するカラーチャンネルを設定 + const csmInt32 channelNo = GetClippingContextBufferForDraw()->_layoutChannelNo; + CubismRenderer::CubismTextureColor* colorChannel = GetClippingContextBufferForDraw()->GetClippingManager()->GetChannelFlagAsColor(channelNo); + + D3DXVECTOR4 channel(colorChannel->R, colorChannel->G, colorChannel->B, colorChannel->A); + shaderEffect->SetVector("channelFlag", &channel); + } + + CubismMatrix44 mvp = GetMvpMatrix(); + D3DXMATRIX proj = ConvertToD3DX(mvp); + shaderEffect->SetMatrix("projectMatrix", &proj); + D3DXVECTOR4 color(modelColorRGBA.R, modelColorRGBA.G, modelColorRGBA.B, modelColorRGBA.A); + shaderEffect->SetVector("baseColor", &color); + } + + // パラメータ反映 + shaderEffect->CommitChanges(); + + // 描画 + device->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, vertexCount, triangleCount, indexArray, D3DFMT_INDEX16, vertexArray, sizeof(CubismVertexD3D9)); + + shaderEffect->EndPass(); + shaderEffect->End(); + } + } +} + +void CubismRenderer_D3D9::DrawMesh(csmInt32 textureNo, csmInt32 indexCount, csmInt32 vertexCount + , csmUint16* indexArray, csmFloat32* vertexArray, csmFloat32* uvArray + , csmFloat32 opacity, CubismBlendMode colorBlendMode) +{ + CubismLogWarning("Use 'DrawMeshDX9' function"); + CSM_ASSERT(0); +} + +void CubismRenderer_D3D9::DrawMeshDX9( csmInt32 drawableIndex + , csmInt32 textureNo, csmInt32 indexCount, csmInt32 vertexCount + , csmUint16* indexArray, csmFloat32* vertexArray, csmFloat32* uvArray + , csmFloat32 opacity, CubismBlendMode colorBlendMode) +{ + if (s_useDevice == NULL) + {// デバイス未設定 + return; + } + if(indexCount==0) + {// 描画物無し + return; + } + // 描画不要なら描画処理をスキップする + if (opacity <= 0.0f && GetClippingContextBufferForMask() == NULL) + { + return; + } + + // テクスチャセット + LPDIRECT3DTEXTURE9 texture = NULL; + if (textureNo >= 0) + { + texture = _textures[textureNo]; + } + + if (texture == NULL) return; // モデルが参照するテクスチャがバインドされていない場合は描画をスキップする + + + // 裏面描画の有効・無効 + if (IsCulling()) + { + GetRenderStateManager()->SetCullMode(s_useDevice, + D3DCULL_CW); // CWを消す + } + else + { + GetRenderStateManager()->SetCullMode(s_useDevice, + D3DCULL_NONE); // カリング無し + } + + CubismTextureColor modelColorRGBA = GetModelColor(); + + if (GetClippingContextBufferForMask() == NULL) // マスク生成時以外 + { + modelColorRGBA.A *= opacity; + if (IsPremultipliedAlpha()) + { + modelColorRGBA.R *= modelColorRGBA.A; + modelColorRGBA.G *= modelColorRGBA.A; + modelColorRGBA.B *= modelColorRGBA.A; + } + } + + // 頂点バッファにコピー + CopyToBuffer(drawableIndex, vertexCount, vertexArray, uvArray); + + // シェーダーセット + ExecuteDraw(s_useDevice, _vertexStore[drawableIndex], _indexStore[drawableIndex], + vertexCount, indexCount/3, + textureNo, modelColorRGBA, colorBlendMode); + + SetClippingContextBufferForDraw(NULL); + SetClippingContextBufferForMask(NULL); +} + +void CubismRenderer_D3D9::SaveProfile() +{ + // NULLは許されず + CSM_ASSERT(s_useDevice != NULL); + + // 現在のレンダリングステートをPush + GetRenderStateManager()->SaveCurrentNativeState(s_useDevice); +} + +void CubismRenderer_D3D9::RestoreProfile() +{ + // NULLは許されず + CSM_ASSERT(s_useDevice != NULL); + + // SaveCurrentNativeStateと対 + GetRenderStateManager()->RestoreNativeState(s_useDevice); +} + +void CubismRenderer_D3D9::BindTexture(csmUint32 modelTextureAssign, LPDIRECT3DTEXTURE9 texture) +{ + _textures[modelTextureAssign] = texture; +} + +const csmMap& CubismRenderer_D3D9::GetBindedTextures() const +{ + return _textures; +} + +void CubismRenderer_D3D9::SetClippingMaskBufferSize(csmInt32 size) +{ + //FrameBufferのサイズを変更するためにインスタンスを破棄・再作成する + CSM_DELETE_SELF(CubismClippingManager_DX9, _clippingManager); + + _clippingManager = CSM_NEW CubismClippingManager_DX9(); + + _clippingManager->SetClippingMaskBufferSize(size); + + _clippingManager->Initialize( + *GetModel(), + GetModel()->GetDrawableCount(), + GetModel()->GetDrawableMasks(), + GetModel()->GetDrawableMaskCounts() + ); +} + +csmInt32 CubismRenderer_D3D9::GetClippingMaskBufferSize() const +{ + return _clippingManager->GetClippingMaskBufferSize(); +} + +void CubismRenderer_D3D9::InitializeConstantSettings(csmUint32 bufferSetNum, LPDIRECT3DDEVICE9 device) +{ + s_bufferSetNum = bufferSetNum; + s_useDevice = device; +} + +void CubismRenderer_D3D9::SetDefaultRenderState() +{ + // Zは無効 描画順で制御 + GetRenderStateManager()->SetZEnable(s_useDevice, + D3DZB_FALSE, + D3DCMP_LESS); + + // ビューポート + GetRenderStateManager()->SetViewport(s_useDevice, + 0, + 0, + s_viewportWidth, + s_viewportHeight, + 0.0f, 1.0); + + // カラーマスク + GetRenderStateManager()->SetColorMask(s_useDevice, + D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED); + + // カリング + GetRenderStateManager()->SetCullMode(s_useDevice, + D3DCULL_CW); // CWを消す + + // フィルタ + GetRenderStateManager()->SetTextureFilter(s_useDevice, + D3DTEXF_LINEAR, D3DTEXF_LINEAR, D3DTEXF_LINEAR, D3DTADDRESS_WRAP, D3DTADDRESS_WRAP + ); +} + +void CubismRenderer_D3D9::StartFrame(LPDIRECT3DDEVICE9 device, csmUint32 viewportWidth, csmUint32 viewportHeight) +{ + // フレームで使用するデバイス設定 + s_useDevice = device; + s_viewportWidth = viewportWidth; + s_viewportHeight = viewportHeight; + + // レンダーステートフレーム先頭処理 + GetRenderStateManager()->StartFrame(); + + // シェーダ・頂点宣言 + GetShaderManager()->SetupShader(s_useDevice); +} + +void CubismRenderer_D3D9::EndFrame(LPDIRECT3DDEVICE9 device) +{ + // 使用シェーダエフェクト取得 + Live2D::Cubism::Framework::Rendering::CubismShader_D3D9* shaderManager = Live2D::Cubism::Framework::Rendering::CubismRenderer_D3D9::GetShaderManager(); + { + ID3DXEffect* shaderEffect = shaderManager->GetShaderEffect(); + // テクスチャの参照を外しておく + if (shaderEffect) + { + shaderEffect->SetTexture("mainTexture", NULL); + shaderEffect->SetTexture("maskTexture", NULL); + shaderEffect->CommitChanges(); + } + } +} + +void CubismRenderer_D3D9::SetClippingContextBufferForDraw(CubismClippingContext* clip) +{ + _clippingContextBufferForDraw = clip; +} + +CubismClippingContext* CubismRenderer_D3D9::GetClippingContextBufferForDraw() const +{ + return _clippingContextBufferForDraw; +} + +void CubismRenderer_D3D9::SetClippingContextBufferForMask(CubismClippingContext* clip) +{ + _clippingContextBufferForMask = clip; +} + +CubismClippingContext* CubismRenderer_D3D9::GetClippingContextBufferForMask() const +{ + return _clippingContextBufferForMask; +} + +void CubismRenderer_D3D9::CopyToBuffer(csmInt32 drawAssign, const csmInt32 vcount, const csmFloat32* varray, const csmFloat32* uvarray) +{ + for (csmInt32 ct = 0; ct < vcount * 2; ct += 2) + {// モデルデータからのコピー + _vertexStore[drawAssign][ct / 2].x = varray[ct + 0]; + _vertexStore[drawAssign][ct / 2].y = varray[ct + 1]; + + _vertexStore[drawAssign][ct / 2].u = uvarray[ct + 0]; + _vertexStore[drawAssign][ct / 2].v = uvarray[ct + 1]; + } +} + +}}}} + +//------------ LIVE2D NAMESPACE ------------ diff --git a/CubismSDK/Framework/src/Rendering/D3D9/CubismRenderer_D3D9.hpp b/CubismSDK/Framework/src/Rendering/D3D9/CubismRenderer_D3D9.hpp new file mode 100644 index 0000000..74dd7e9 --- /dev/null +++ b/CubismSDK/Framework/src/Rendering/D3D9/CubismRenderer_D3D9.hpp @@ -0,0 +1,462 @@ +/* + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#pragma once + +#include "CubismNativeInclude_D3D9.hpp" + +#include "../CubismRenderer.hpp" +#include "CubismFramework.hpp" +#include "Type/csmVector.hpp" +#include "Type/csmRectF.hpp" +#include "Type/csmMap.hpp" +#include "Rendering/D3D9/CubismOffscreenSurface_D3D9.hpp" +#include "CubismRenderState_D3D9.hpp" +#include "CubismType_D3D9.hpp" + +//------------ LIVE2D NAMESPACE ------------ +namespace Live2D { namespace Cubism { namespace Framework { namespace Rendering { + +// 前方宣言 +class CubismRenderer_D3D9; +class CubismShader_D3D9; +class CubismClippingContext; + +/** + * @brief D3DXMATRIXに変換 + */ +D3DXMATRIX ConvertToD3DX(CubismMatrix44& mtx); + +/** + * @brief クリッピングマスクの処理を実行するクラス + * + */ +class CubismClippingManager_DX9 +{ + friend class CubismShader_D3D9; + friend class CubismRenderer_D3D9; + +private: + + /** + * @brief カラーチャンネル(RGBA)のフラグを取得する + * + * @param[in] channelNo -> カラーチャンネル(RGBA)の番号(0:R , 1:G , 2:B, 3:A) + */ + CubismRenderer::CubismTextureColor* GetChannelFlagAsColor(csmInt32 channelNo); + + /** + * @brief マスクされる描画オブジェクト群全体を囲む矩形(モデル座標系)を計算する + * + * @param[in] model -> モデルのインスタンス + * @param[in] clippingContext -> クリッピングマスクのコンテキスト + */ + void CalcClippedDrawTotalBounds(CubismModel& model, CubismClippingContext* clippingContext); + + /** + * @brief コンストラクタ + */ + CubismClippingManager_DX9(); + + /** + * @brief デストラクタ + */ + virtual ~CubismClippingManager_DX9(); + + /** + * @brief マネージャの初期化処理
+ * クリッピングマスクを使う描画オブジェクトの登録を行う + * + * @param[in] model -> モデルのインスタンス + * @param[in] drawableCount -> 描画オブジェクトの数 + * @param[in] drawableMasks -> 描画オブジェクトをマスクする描画オブジェクトのインデックスのリスト + * @param[in] drawableMaskCounts -> 描画オブジェクトをマスクする描画オブジェクトの数 + */ + void Initialize(CubismModel& model, csmInt32 drawableCount, const csmInt32** drawableMasks, const csmInt32* drawableMaskCounts); + + /** + * @brief クリッピングコンテキストを作成する。モデル描画時に実行する。 + * + * @param[in] model -> モデルのインスタンス + * @param[in] renderer -> レンダラのインスタンス + */ + void SetupClippingContext(LPDIRECT3DDEVICE9 device, CubismModel& model, CubismRenderer_D3D9* renderer, CubismOffscreenFrame_D3D9& useTarget); + + /** + * @brief 既にマスクを作っているかを確認。
+ * 作っているようであれば該当するクリッピングマスクのインスタンスを返す。
+ * 作っていなければNULLを返す + * + * @param[in] drawableMasks -> 描画オブジェクトをマスクする描画オブジェクトのリスト + * @param[in] drawableMaskCounts -> 描画オブジェクトをマスクする描画オブジェクトの数 + * @return 該当するクリッピングマスクが存在すればインスタンスを返し、なければNULLを返す。 + */ + CubismClippingContext* FindSameClip(const csmInt32* drawableMasks, csmInt32 drawableMaskCounts) const; + + /** + * @brief クリッピングコンテキストを配置するレイアウト。
+ * ひとつのレンダーテクスチャを極力いっぱいに使ってマスクをレイアウトする。
+ * マスクグループの数が4以下ならRGBA各チャンネルに1つずつマスクを配置し、5以上6以下ならRGBAを2,2,1,1と配置する。 + * + * @param[in] usingClipCount -> 配置するクリッピングコンテキストの数 + */ + void SetupLayoutBounds(csmInt32 usingClipCount) const; + + /** + * @breif カラーバッファのアドレスを取得する + * + * @return カラーバッファのアドレス + */ + CubismOffscreenFrame_D3D9* GetColorBuffer() const; + + /** + * @brief 画面描画に使用するクリッピングマスクのリストを取得する + * + * @return 画面描画に使用するクリッピングマスクのリスト + */ + csmVector* GetClippingContextListForDraw(); + + /** + *@brief クリッピングマスクバッファのサイズを設定する + * + *@param size -> クリッピングマスクバッファのサイズ + * + */ + void SetClippingMaskBufferSize(csmInt32 size); + + /** + *@brief クリッピングマスクバッファのサイズを取得する + * + *@return クリッピングマスクバッファのサイズ + * + */ + csmInt32 GetClippingMaskBufferSize() const; + + CubismOffscreenFrame_D3D9* _colorBuffer; ///< マスク用カラーバッファーのアドレス + csmInt32 _currentFrameNo; ///< マスクテクスチャに与えるフレーム番号 + + csmVector _channelColors; + csmVector _clippingContextListForMask; ///< マスク用クリッピングコンテキストのリスト + csmVector _clippingContextListForDraw; ///< 描画用クリッピングコンテキストのリスト + csmInt32 _clippingMaskBufferSize; ///< クリッピングマスクのバッファサイズ(初期値:256) + + CubismMatrix44 _tmpMatrix; ///< マスク計算用の行列 + CubismMatrix44 _tmpMatrixForMask; ///< マスク計算用の行列 + CubismMatrix44 _tmpMatrixForDraw; ///< マスク計算用の行列 + csmRectF _tmpBoundsOnModel; ///< マスク配置計算用の矩形 + +}; + +/** + * @brief クリッピングマスクのコンテキスト + */ +class CubismClippingContext +{ + friend class CubismClippingManager_DX9; + friend class CubismShader_D3D9; + friend class CubismRenderer_D3D9; + +private: + /** + * @brief 引数付きコンストラクタ + * + */ + CubismClippingContext(CubismClippingManager_DX9* manager, const csmInt32* clippingDrawableIndices, csmInt32 clipCount); + + /** + * @brief デストラクタ + */ + virtual ~CubismClippingContext(); + + /** + * @brief このマスクにクリップされる描画オブジェクトを追加する + * + * @param[in] drawableIndex -> クリッピング対象に追加する描画オブジェクトのインデックス + */ + void AddClippedDrawable(csmInt32 drawableIndex); + + /** + * @brief このマスクを管理するマネージャのインスタンスを取得する。 + * + * @return クリッピングマネージャのインスタンス + */ + CubismClippingManager_DX9* GetClippingManager(); + + csmBool _isUsing; ///< 現在の描画状態でマスクの準備が必要ならtrue + const csmInt32* _clippingIdList; ///< クリッピングマスクのIDリスト + csmInt32 _clippingIdCount; ///< クリッピングマスクの数 + csmInt32 _layoutChannelNo; ///< RGBAのいずれのチャンネルにこのクリップを配置するか(0:R , 1:G , 2:B , 3:A) + csmRectF* _layoutBounds; ///< マスク用チャンネルのどの領域にマスクを入れるか(View座標-1..1, UVは0..1に直す) + csmRectF* _allClippedDrawRect; ///< このクリッピングで、クリッピングされる全ての描画オブジェクトの囲み矩形(毎回更新) + CubismMatrix44 _matrixForMask; ///< マスクの位置計算結果を保持する行列 + CubismMatrix44 _matrixForDraw; ///< 描画オブジェクトの位置計算結果を保持する行列 + csmVector* _clippedDrawableIndexList; ///< このマスクにクリップされる描画オブジェクトのリスト + + CubismClippingManager_DX9* _owner; ///< このマスクを管理しているマネージャのインスタンス +}; + + +/** + * @brief DirectX9用の描画命令を実装したクラス + * + */ +class CubismRenderer_D3D9 : public CubismRenderer +{ + friend class CubismRenderer; + friend class CubismClippingManager_DX9; + friend class CubismShader_D3D9; + +public: + + /** +  * @brief レンダラを作成するための各種設定 +  * モデルロードの前に一度だけ呼び出す +  * +  * @param[in] bufferSetNum -> 1パーツに付き作成するバッファ数 + * @param[in] device -> 使用デバイス +  */ + static void InitializeConstantSettings(csmUint32 bufferSetNum, LPDIRECT3DDEVICE9 device); + + /** + * @brief CubismRenderStateにデフォルトの設定をセットする + */ + static void SetDefaultRenderState(); + + /** + * @brief Cubism描画関連の先頭で行う処理。 + * 各フレームでのCubism処理前にこれを呼んでもらう + * + * @param[in] device -> 使用デバイス + */ + static void StartFrame(LPDIRECT3DDEVICE9 device, csmUint32 viewportWidth, csmUint32 viewportHeight); + + /** + * @brief Cubism描画関連の終了時行う処理。 + * 各フレームでのCubism処理前にこれを呼んでもらう + * + * @param[in] device -> 使用デバイス + */ + static void EndFrame(LPDIRECT3DDEVICE9 device); + + /** + * @brief CubismRenderer_D3D9で使用するレンダーステート管理マネージャ取得 + */ + static CubismRenderState_D3D9* GetRenderStateManager(); + + /** + * @brief レンダーステート管理マネージャ削除 + */ + static void DeleteRenderStateManager(); + + /** + * @brief シェーダ管理機構の取得 + */ + static CubismShader_D3D9* GetShaderManager(); + + /** + * @brief シェーダ管理機構の削除 + */ + static void DeleteShaderManager(); + + /** + * @brief デバイスロスト・デバイス再作成時コールする + */ + static void OnDeviceLost(); + + /** + * @brief 使用シェーダー作成 + */ + static void GenerateShader(LPDIRECT3DDEVICE9 device); + + + /** + * @brief レンダラの初期化処理を実行する
+ * 引数に渡したモデルからレンダラの初期化処理に必要な情報を取り出すことができる + * + * @param[in] model -> モデルのインスタンス + */ + virtual void Initialize(Framework::CubismModel* model) override; + + /** + * @brief レンダリング前のフレーム先頭で呼ばれる + */ + void FrameRenderingInit(); + + /** + * @brief テクスチャのバインド処理
+ * CubismRendererにテクスチャを設定し、CubismRenderer中でその画像を参照するためのIndex値を戻り値とする + * + * @param[in] modelTextureAssign -> セットするモデルテクスチャのアサイン番号 + * @param[in] texture -> 描画に使用するテクスチャ + * + */ + void BindTexture(csmUint32 modelTextureAssign, const LPDIRECT3DTEXTURE9 texture); + + /** + * @brief バインドされたテクスチャのリストを取得する + * + * @return テクスチャのアドレスのリスト + */ + const csmMap& GetBindedTextures() const; + + /** + * @brief クリッピングマスクバッファのサイズを設定する
+ * マスク用のFrameBufferを破棄・再作成するため処理コストは高い。 + * + * @param[in] size -> クリッピングマスクバッファのサイズ + * + */ + void SetClippingMaskBufferSize(csmInt32 size); + + /** + * @brief クリッピングマスクバッファのサイズを取得する + * + * @return クリッピングマスクバッファのサイズ + * + */ + csmInt32 GetClippingMaskBufferSize() const; + + /** + * @brief 使用するシェーダの設定・コンスタントバッファの設定などを行い、描画を実行 + * + * @param[in] device -> 使用デバイス + * @param[in] textureNo -> 使用テクスチャ番号。基本的にCubismModel::GetDrawableTextureIndicesで返されたもの + * @param[in] modelColorRGBA -> 描画カラー + * @param[in] colorBlendMode -> ブレンドモード + * + */ + void ExecuteDraw(LPDIRECT3DDEVICE9 device, CubismVertexD3D9* vertexArray, csmUint16* indexArray, + const csmInt32 vertexCount, const csmInt32 triangleCount, + const csmInt32 textureNo, CubismTextureColor& modelColorRGBA, CubismBlendMode colorBlendMode); + +protected: + /** + * @brief コンストラクタ + */ + CubismRenderer_D3D9(); + + /** + * @brief デストラクタ + */ + virtual ~CubismRenderer_D3D9(); + + /** + * @brief モデルを描画する実際の処理 + * + */ + virtual void DoDrawModel() override; + + + void DrawMesh(csmInt32 textureNo, csmInt32 indexCount, csmInt32 vertexCount + , csmUint16* indexArray, csmFloat32* vertexArray, csmFloat32* uvArray + , csmFloat32 opacity, CubismBlendMode colorBlendMode) override; + + /** + * @brief [オーバーライド]
+ * 描画オブジェクト(アートメッシュ)を描画する。
+ * ポリゴンメッシュとテクスチャ番号をセットで渡す。 + * + * @param[in] gfxc -> レンダリングコンテキスト + * @param[in] drawableIndex -> 描画パーツ番号 + * @param[in] colorBlendMode -> カラー合成タイプ + * + */ + void DrawMeshDX9(csmInt32 drawableIndex + , csmInt32 textureNo, csmInt32 indexCount, csmInt32 vertexCount + , csmUint16* indexArray, csmFloat32* vertexArray, csmFloat32* uvArray + , csmFloat32 opacity, CubismBlendMode colorBlendMode); + + +private: + + /** + * @brief レンダラが保持する静的なリソースを解放する
+ */ + static void DoStaticRelease(); + + /** + * @brief 使用シェーダーと頂点定義の削除 + */ + static void ReleaseShader(); + + // Prevention of copy Constructor + CubismRenderer_D3D9(const CubismRenderer_D3D9&); + CubismRenderer_D3D9& operator=(const CubismRenderer_D3D9&); + + /** + * @brief 描画開始時の追加処理。
+ * モデルを描画する前にクリッピングマスクに必要な処理を実装している。 + */ + void PreDraw(); + + /** + * @brief 描画完了後の追加処理。 + * + */ + void PostDraw(); + + /** + * @brief モデル描画直前のステートを保持する + */ + virtual void SaveProfile() override; + + /** + * @brief モデル描画直前のステートを保持する + */ + virtual void RestoreProfile() override; + + /** + * @brief マスクテクスチャに描画するクリッピングコンテキストをセットする。 + */ + void SetClippingContextBufferForMask(CubismClippingContext* clip); + + /** + * @brief マスクテクスチャに描画するクリッピングコンテキストを取得する。 + * + * @return マスクテクスチャに描画するクリッピングコンテキスト + */ + CubismClippingContext* GetClippingContextBufferForMask() const; + + /** + * @brief 画面上に描画するクリッピングコンテキストをセットする。 + */ + void SetClippingContextBufferForDraw(CubismClippingContext* clip); + + /** + * @brief 画面上に描画するクリッピングコンテキストを取得する。 + * + * @return 画面上に描画するクリッピングコンテキスト + */ + CubismClippingContext* GetClippingContextBufferForDraw() const; + + /** + * @brief GetDrawableVertices,GetDrawableVertexUvsの内容を内部バッファへコピー + */ + void CopyToBuffer(csmInt32 drawAssign, const csmInt32 vcount, const csmFloat32* varray, const csmFloat32* uvarray); + + + csmUint32 _drawableNum; ///< _vertexBuffers, _indexBuffersの確保数 + + CubismVertexD3D9** _vertexStore; ///< 頂点をストアしておく領域 + csmUint16** _indexStore; ///< インデックスをストアしておく領域 + + csmInt32 _commandBufferNum; ///< 描画バッファを複数作成する場合の数 + csmInt32 _commandBufferCurrent; ///< 現在使用中のバッファ番号 + + csmVector _sortedDrawableIndexList; ///< 描画オブジェクトのインデックスを描画順に並べたリスト + + csmMap_textures; ///< モデルが参照するテクスチャとレンダラでバインドしているテクスチャとのマップ + + csmVector_offscreenFrameBuffer; ///< マスク描画用のフレームバッファ + + CubismClippingManager_DX9* _clippingManager; ///< クリッピングマスク管理オブジェクト + CubismClippingContext* _clippingContextBufferForMask; ///< マスクテクスチャに描画するためのクリッピングコンテキスト + CubismClippingContext* _clippingContextBufferForDraw; ///< 画面上描画するためのクリッピングコンテキスト +}; + +}}}} +//------------ LIVE2D NAMESPACE ------------ diff --git a/CubismSDK/Framework/src/Rendering/D3D9/CubismShader_D3D9.cpp b/CubismSDK/Framework/src/Rendering/D3D9/CubismShader_D3D9.cpp new file mode 100644 index 0000000..97bc258 --- /dev/null +++ b/CubismSDK/Framework/src/Rendering/D3D9/CubismShader_D3D9.cpp @@ -0,0 +1,235 @@ +/* + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#include "CubismShader_D3D9.hpp" + +#include "CubismRenderer_D3D9.hpp" + +//------------ LIVE2D NAMESPACE ------------ +namespace Live2D { namespace Cubism { namespace Framework { namespace Rendering { + +static const csmChar* CubismShaderEffectSrc = + "float4x4 projectMatrix;"\ + "float4x4 clipMatrix;"\ + "float4 baseColor;"\ + "float4 channelFlag;"\ + "texture mainTexture;"\ + "texture maskTexture;"\ + \ + "sampler mainSampler = sampler_state{"\ + "texture = ;"\ + "};"\ + "sampler maskSampler = sampler_state{"\ + "texture = ;"\ + "};"\ + \ + "struct VS_IN {"\ + "float2 pos : POSITION;"\ + "float2 uv : TEXCOORD0;"\ + "};"\ + "struct VS_OUT {"\ + "float4 Position : POSITION0;"\ + "float2 uv : TEXCOORD0;"\ + "float4 clipPosition : TEXCOORD1;"\ + "};"\ + \ +"/* Setup mask shader */"\ + "VS_OUT VertSetupMask(VS_IN In) {"\ + "VS_OUT Out = (VS_OUT)0;"\ + "Out.Position = mul(float4(In.pos, 0.0f, 1.0f), projectMatrix);"\ + "Out.clipPosition = mul(float4(In.pos, 0.0f, 1.0f), projectMatrix);"\ + "Out.uv.x = In.uv.x;"\ + "Out.uv.y = 1.0 - +In.uv.y;"\ + "return Out;"\ + "}"\ + "float4 PixelSetupMask(VS_OUT In) : COLOR0{"\ + "float isInside ="\ + "step(baseColor.x, In.clipPosition.x / In.clipPosition.w)"\ + "* step(baseColor.y, In.clipPosition.y / In.clipPosition.w)"\ + "* step(In.clipPosition.x / In.clipPosition.w, baseColor.z)"\ + "* step(In.clipPosition.y / In.clipPosition.w, baseColor.w);"\ + "return channelFlag * tex2D(mainSampler, In.uv).a * isInside;"\ + "}"\ + \ +"/* Vertex Shader */"\ + "/* normal */"\ + "VS_OUT VertNormal(VS_IN In) {"\ + "VS_OUT Out = (VS_OUT)0;"\ + "Out.Position = mul(float4(In.pos, 0.0f, 1.0f), projectMatrix);"\ + "Out.uv.x = In.uv.x;"\ + "Out.uv.y = 1.0 - +In.uv.y;"\ + "return Out;"\ + "}"\ + "/* masked */"\ + "VS_OUT VertMasked(VS_IN In) {"\ + "VS_OUT Out = (VS_OUT)0;"\ + "Out.Position = mul(float4(In.pos, 0.0f, 1.0f), projectMatrix);"\ + "Out.clipPosition = mul(float4(In.pos, 0.0f, 1.0f), clipMatrix);"\ + "Out.uv.x = In.uv.x;"\ + "Out.uv.y = 1.0 - In.uv.y;"\ + "return Out;"\ + "}"\ + \ +"/* Pixel Shader */"\ + "/* normal */"\ + "float4 PixelNormal(VS_OUT In) : COLOR0{"\ + "float4 color = tex2D(mainSampler, In.uv) * baseColor;"\ + "color.xyz *= color.w;"\ + "return color;"\ + "}"\ + \ + "/* normal premult alpha */"\ + "float4 PixelNormalPremult(VS_OUT In) : COLOR0{"\ + "float4 color = tex2D(mainSampler, In.uv) * baseColor;"\ + "return color;"\ + "}"\ + \ + "/* masked */"\ + "float4 PixelMasked(VS_OUT In) : COLOR0{"\ + "float4 color = tex2D(mainSampler, In.uv) * baseColor;"\ + "color.xyz *= color.w;"\ + "float4 clipMask = (1.0 - tex2D(maskSampler, In.clipPosition.xy / In.clipPosition.w)) * channelFlag;"\ + "float maskVal = clipMask.r + clipMask.g + clipMask.b + clipMask.a;"\ + "color = color * maskVal;"\ + "return color;"\ + "}"\ + "/* masked premult alpha */"\ + "float4 PixelMaskedPremult(VS_OUT In) : COLOR0{"\ + "float4 color = tex2D(mainSampler, In.uv) * baseColor;"\ + "float4 clipMask = (1.0 - tex2D(maskSampler, In.clipPosition.xy / In.clipPosition.w)) * channelFlag;"\ + "float maskVal = clipMask.r + clipMask.g + clipMask.b + clipMask.a;"\ + "color = color * maskVal;"\ + "return color;"\ + "}"\ + \ +"/* Technique */"\ + "technique ShaderNames_SetupMask {"\ + "pass p0{"\ + "VertexShader = compile vs_2_0 VertSetupMask();"\ + "PixelShader = compile ps_2_0 PixelSetupMask();"\ + "}"\ + "}"\ + \ + "technique ShaderNames_Normal {"\ + "pass p0{"\ + "VertexShader = compile vs_2_0 VertNormal();"\ + "PixelShader = compile ps_2_0 PixelNormal();"\ + "}"\ + "}"\ + \ + "technique ShaderNames_NormalMasked {"\ + "pass p0{"\ + "VertexShader = compile vs_2_0 VertMasked();"\ + "PixelShader = compile ps_2_0 PixelMasked();"\ + "}"\ + "}"\ + \ + "technique ShaderNames_NormalPremultipliedAlpha {"\ + "pass p0{"\ + "VertexShader = compile vs_2_0 VertNormal();"\ + "PixelShader = compile ps_2_0 PixelNormalPremult();"\ + "}"\ + "}"\ + \ + "technique ShaderNames_NormalMaskedPremultipliedAlpha {"\ + "pass p0{"\ + "VertexShader = compile vs_2_0 VertMasked();"\ + "PixelShader = compile ps_2_0 PixelMaskedPremult();"\ + "}"\ + "}"; + + +void CubismShader_D3D9::ReleaseShaderProgram() +{ + if(_vertexFormat) + { + _vertexFormat->Release(); + _vertexFormat = NULL; + } + if(_shaderEffect) + { + _shaderEffect->Release(); + _shaderEffect = NULL; + } +} + +CubismShader_D3D9::CubismShader_D3D9() + : _shaderEffect(NULL) + , _vertexFormat(NULL) +{ +} + +CubismShader_D3D9::~CubismShader_D3D9() +{ + ReleaseShaderProgram(); +} + +void CubismShader_D3D9::GenerateShaders(LPDIRECT3DDEVICE9 device) +{ + if(_shaderEffect || _vertexFormat) + {// 既に有る + return; + } + + if(!device) + { + return; + } + + // + if(!LoadShaderProgram(device)) + { + CubismLogError("CreateShader failed"); + CSM_ASSERT(0); + } + + + // この描画で使用する頂点フォーマット + D3DVERTEXELEMENT9 elems[] = { + { 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, + { 0, sizeof(float) * 2, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 }, + D3DDECL_END() + }; + if (device->CreateVertexDeclaration(elems, &_vertexFormat)) + { + CubismLogError("CreateVertexDeclaration failed"); + CSM_ASSERT(0); + } +} + +Csm::csmBool CubismShader_D3D9::LoadShaderProgram(LPDIRECT3DDEVICE9 device) +{ + if (!device) return false; + + ID3DXBuffer* error = NULL; + if (FAILED(D3DXCreateEffect(device, CubismShaderEffectSrc, static_cast(strlen(CubismShaderEffectSrc)), 0, 0, 0, 0, &_shaderEffect, &error))) + { + return false; + } + + return true; +} + +ID3DXEffect* CubismShader_D3D9::GetShaderEffect() const +{ + return _shaderEffect; +} + +void CubismShader_D3D9::SetupShader(LPDIRECT3DDEVICE9 device) +{ + // まだシェーダ・頂点宣言未作成ならば作成する + GenerateShaders(device); + + if (!device || !_vertexFormat) return; + + device->SetVertexDeclaration(_vertexFormat); +} + +}}}} + +//------------ LIVE2D NAMESPACE ------------ + diff --git a/CubismSDK/Framework/src/Rendering/D3D9/CubismShader_D3D9.hpp b/CubismSDK/Framework/src/Rendering/D3D9/CubismShader_D3D9.hpp new file mode 100644 index 0000000..b1636e0 --- /dev/null +++ b/CubismSDK/Framework/src/Rendering/D3D9/CubismShader_D3D9.hpp @@ -0,0 +1,97 @@ +/* + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#pragma once + +#include "CubismNativeInclude_D3D9.hpp" + +#include "../CubismRenderer.hpp" +#include "CubismType_D3D9.hpp" +#include "CubismFramework.hpp" + +//------------ LIVE2D NAMESPACE ------------ +namespace Live2D { namespace Cubism { namespace Framework { namespace Rendering { + +// 前方宣言 +class CubismRenderer_D3D9; +class CubismClippingContext; + +/** + * @bref DX9シェーダエフェクト + * + */ +class CubismShaderSet +{ +public: + CubismShaderSet() + : _shaderEffect(NULL) + { + } + + ID3DXEffect* _shaderEffect; +}; + +/** +* @brief Cubismで使用するシェーダ管理クラス +* CubismRenderer_D3D9のstatic変数として一つだけ実体化される +* +*/ +class CubismShader_D3D9 +{ + friend class CubismRenderer_D3D9; + +public: + + /** + * @brief privateなコンストラクタ + */ + CubismShader_D3D9(); + + /** + * @brief privateなデストラクタ + */ + virtual ~CubismShader_D3D9(); + + /** + * @brief シェーダプログラムを解放する + */ + void ReleaseShaderProgram(); + + /** + * @brief シェーダプログラムエフェクトの取得 + * + */ + ID3DXEffect* GetShaderEffect() const; + + /** + * @brief 頂点宣言のデバイスへの設定、シェーダがまだ未設定ならロード + */ + void SetupShader(LPDIRECT3DDEVICE9 pD3dDevice); + +private: + + /** + * @brief シェーダプログラムを初期化する + */ + void GenerateShaders(LPDIRECT3DDEVICE9 pD3dDevice); + + /** + * @brief シェーダプログラムをロード + * + * @param[in] pD3dDevice 使用デバイス + * + * @return 成功時はtrue、失敗時はfalse + */ + Csm::csmBool LoadShaderProgram(LPDIRECT3DDEVICE9 pD3dDevice); + + + ID3DXEffect* _shaderEffect; ///< CubismD3dでは一つのシェーダで内部テクニックの変更をする + IDirect3DVertexDeclaration9* _vertexFormat; ///< 描画で使用する型宣言 +}; + +}}}} +//------------ LIVE2D NAMESPACE ------------ diff --git a/CubismSDK/Framework/src/Rendering/D3D9/CubismType_D3D9.hpp b/CubismSDK/Framework/src/Rendering/D3D9/CubismType_D3D9.hpp new file mode 100644 index 0000000..a6d3a4e --- /dev/null +++ b/CubismSDK/Framework/src/Rendering/D3D9/CubismType_D3D9.hpp @@ -0,0 +1,29 @@ +/* + * Copyright(c) Live2D Inc. All rights reserved. + * + * Use of this source code is governed by the Live2D Open Software license + * that can be found at http://live2d.com/eula/live2d-open-software-license-agreement_en.html. + */ + +#pragma once + +//------------ LIVE2D NAMESPACE ------------ +namespace Live2D { namespace Cubism { namespace Framework { + +/** + * @brief D3D9基本頂点 + */ + +struct CubismVertexD3D9 +{ + float x, y; // Position + float u, v; // UVs +}; +enum CubismD3D9VertexElem +{ + CubismD3D9VertexElem_Position = 0, + CubismD3D9VertexElem_UV, + CubismD3D9VertexElem_Max +}; + +}}} diff --git a/CubismSDK/Framework/src/Rendering/OpenGL/CubismRenderer_OpenGLES2.cpp b/CubismSDK/Framework/src/Rendering/OpenGL/CubismRenderer_OpenGLES2.cpp index a65fc6c..72e6661 100644 --- a/CubismSDK/Framework/src/Rendering/OpenGL/CubismRenderer_OpenGLES2.cpp +++ b/CubismSDK/Framework/src/Rendering/OpenGL/CubismRenderer_OpenGLES2.cpp @@ -30,6 +30,7 @@ CubismClippingManager_OpenGLES2::CubismClippingManager_OpenGLES2() : _maskRenderTexture(0) , _colorBuffer(0) , _currentFrameNo(0) + , _maskTexture(NULL) , _clippingMaskBufferSize(256) { CubismRenderer::CubismTextureColor* tmp; @@ -73,11 +74,11 @@ CubismClippingManager_OpenGLES2::~CubismClippingManager_OpenGLES2() { _clippingContextListForDraw[i] = NULL; } - for (csmUint32 i = 0; i < _maskTextures.GetSize(); i++) + if (_maskTexture) { - glDeleteFramebuffers(1, &_maskTextures[i]->Texture); - if (_maskTextures[i]) CSM_DELETE_SELF(CubismRenderTextureResource, _maskTextures[i]); - _maskTextures[i] = NULL; + glDeleteFramebuffers(1, &_maskTexture->Texture); + CSM_DELETE_SELF(CubismRenderTextureResource, _maskTexture); + _maskTexture = NULL; } for (csmUint32 i = 0; i < _channelColors.GetSize(); i++) @@ -151,14 +152,10 @@ GLuint CubismClippingManager_OpenGLES2::GetMaskRenderTexture() GLuint ret = 0; // テンポラリのRenderTexutreを取得する - for (csmUint32 i = 0; i < _maskTextures.GetSize(); i++) + if (_maskTexture && _maskTexture->Texture != 0) { - if (_maskTextures[i]->Texture != 0) //前回使ったものを返す - { - _maskTextures[i]->FrameNo = _currentFrameNo; - ret = _maskTextures[i]->Texture; - break; - } + _maskTexture->FrameNo = _currentFrameNo; + ret = _maskTexture->Texture; } if (ret == 0) @@ -182,7 +179,7 @@ GLuint CubismClippingManager_OpenGLES2::GetMaskRenderTexture() glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _colorBuffer, 0); glBindFramebuffer(GL_FRAMEBUFFER, tmpFramebufferObject); - _maskTextures.PushBack(CSM_NEW CubismRenderTextureResource(_currentFrameNo, ret)); + _maskTexture = CSM_NEW CubismRenderTextureResource(_currentFrameNo, ret); } return ret; @@ -797,55 +794,8 @@ static const csmChar* FragShaderSrcPremultipliedAlpha = "gl_FragColor = texture2D(s_texture0 , v_texCoord) * u_baseColor;" "}"; -// Normal (クリッピングされたものの描画用) -static const csmChar* FragShaderSrcNormalMask = -#ifdef CSM_TARGET_IPHONE_ES2 - "precision mediump float;" -#endif -#ifdef CSM_TARGET_ANDROID_ES2 - "precision mediump float;" -#endif - "varying vec2 v_texCoord;" - "varying vec4 v_clipPos;" - "uniform sampler2D s_texture0;" - "uniform sampler2D s_texture1;" - "uniform vec4 u_channelFlag;" - "uniform vec4 u_baseColor;" - "void main()" - "{" - "vec4 col_formask = texture2D(s_texture0 , v_texCoord) * u_baseColor;" - "col_formask.rgb = col_formask.rgb * col_formask.a ;" - "vec4 clipMask = (1.0 - texture2D(s_texture1, v_clipPos.xy / v_clipPos.w)) * u_channelFlag;" - "float maskVal = clipMask.r + clipMask.g + clipMask.b + clipMask.a;" - "col_formask = col_formask * maskVal;" - "gl_FragColor = col_formask;" - "}"; - -// Normal (クリッピングされたものの描画用、PremultipliedAlpha兼用) -static const csmChar* FragShaderSrcNormalMaskPremultipliedAlpha = -#ifdef CSM_TARGET_IPHONE_ES2 - "precision mediump float;" -#endif -#ifdef CSM_TARGET_ANDROID_ES2 - "precision mediump float;" -#endif - "varying vec2 v_texCoord;" - "varying vec4 v_clipPos;" - "uniform sampler2D s_texture0;" - "uniform sampler2D s_texture1;" - "uniform vec4 u_channelFlag;" - "uniform vec4 u_baseColor;" - "void main()" - "{" - "vec4 col_formask = texture2D(s_texture0 , v_texCoord) * u_baseColor;" - "vec4 clipMask = (1.0 - texture2D(s_texture1, v_clipPos.xy / v_clipPos.w)) * u_channelFlag;" - "float maskVal = clipMask.r + clipMask.g + clipMask.b + clipMask.a;" - "col_formask = col_formask * maskVal;" - "gl_FragColor = col_formask;" - "}"; - -// Add (クリッピングされたものの描画用) -static const csmChar* FragShaderSrcAddMask = +// Normal & Add & Mult 共通(クリッピングされたものの描画用) +static const csmChar* FragShaderSrcMask = #ifdef CSM_TARGET_IPHONE_ES2 "precision mediump float;" #endif @@ -864,35 +814,12 @@ static const csmChar* FragShaderSrcAddMask = "col_formask.rgb = col_formask.rgb * col_formask.a ;" "vec4 clipMask = (1.0 - texture2D(s_texture1, v_clipPos.xy / v_clipPos.w)) * u_channelFlag;" "float maskVal = clipMask.r + clipMask.g + clipMask.b + clipMask.a;" - "col_formask.a = col_formask.a * maskVal;" - "gl_FragColor = col_formask;" - "}"; - -// Add (クリッピングされたものの描画用、テクスチャがPremultipliedAlphaの場合) -static const csmChar* FragShaderSrcAddMaskPremultipliedAlpha = -#ifdef CSM_TARGET_IPHONE_ES2 - "precision mediump float;" -#endif -#ifdef CSM_TARGET_ANDROID_ES2 - "precision mediump float;" -#endif - "varying vec2 v_texCoord;" - "varying vec4 v_clipPos;" - "uniform sampler2D s_texture0;" - "uniform sampler2D s_texture1;" - "uniform vec4 u_channelFlag;" - "uniform vec4 u_baseColor;" - "void main()" - "{" - "vec4 col_formask = texture2D(s_texture0 , v_texCoord) * u_baseColor;" - "vec4 clipMask = (1.0 - texture2D(s_texture1, v_clipPos.xy / v_clipPos.w)) * u_channelFlag;" - "float maskVal = clipMask.r + clipMask.g + clipMask.b + clipMask.a;" "col_formask = col_formask * maskVal;" "gl_FragColor = col_formask;" "}"; -// Mult (クリッピングされたものの描画用) -static const csmChar* FragShaderSrcMultMask = +// Normal & Add & Mult 共通(クリッピングされたものの描画用、PremultipliedAlphaの場合) +static const csmChar* FragShaderSrcMaskPremultipliedAlpha = #ifdef CSM_TARGET_IPHONE_ES2 "precision mediump float;" #endif @@ -908,36 +835,12 @@ static const csmChar* FragShaderSrcMultMask = "void main()" "{" "vec4 col_formask = texture2D(s_texture0 , v_texCoord) * u_baseColor;" - "col_formask.rgb = col_formask.rgb * col_formask.a ;" "vec4 clipMask = (1.0 - texture2D(s_texture1, v_clipPos.xy / v_clipPos.w)) * u_channelFlag;" "float maskVal = clipMask.r + clipMask.g + clipMask.b + clipMask.a;" "col_formask = col_formask * maskVal;" "gl_FragColor = col_formask;" "}"; -// Mult (クリッピングされたものの描画用、テクスチャがPremultipliedAlphaの場合) -static const csmChar* FragShaderSrcMultMaskPremultipliedAlpha = -#ifdef CSM_TARGET_IPHONE_ES2 - "precision mediump float;" -#endif -#ifdef CSM_TARGET_ANDROID_ES2 - "precision mediump float;" -#endif - "varying vec2 v_texCoord;" - "varying vec4 v_clipPos;" - "uniform sampler2D s_texture0;" - "uniform sampler2D s_texture1;" - "uniform vec4 u_channelFlag;" - "uniform vec4 u_baseColor;" //v2f.color - "void main()" - "{" - "vec4 tex = texture2D(s_texture0 , v_texCoord) * u_baseColor;" - "vec4 col_formask = tex;" - "vec4 clipMask = (1.0 - texture2D(s_texture1, v_clipPos.xy / v_clipPos.w)) * u_channelFlag;" - "float maskVal = clipMask.r + clipMask.g + clipMask.b + clipMask.a;" - "col_formask = col_formask * maskVal;" - "gl_FragColor = col_formask;" - "}"; //テクスチャを使わないデバッグ用の表示 static const csmChar* VertShaderSrcDebug = @@ -1159,19 +1062,21 @@ void CubismShader_OpenGLES2::GenerateShaders() _shaderSets[0]->ShaderProgram = LoadShaderProgram(VertShaderSrcSetupMask, FragShaderSrcSetupMask); _shaderSets[1]->ShaderProgram = LoadShaderProgram(VertShaderSrc, FragShaderSrc); - _shaderSets[2]->ShaderProgram = LoadShaderProgram(VertShaderSrcMasked, FragShaderSrcNormalMask); + _shaderSets[2]->ShaderProgram = LoadShaderProgram(VertShaderSrcMasked, FragShaderSrcMask); _shaderSets[3]->ShaderProgram = LoadShaderProgram(VertShaderSrc, FragShaderSrcPremultipliedAlpha); - _shaderSets[4]->ShaderProgram = LoadShaderProgram(VertShaderSrcMasked, FragShaderSrcNormalMaskPremultipliedAlpha); - - _shaderSets[5]->ShaderProgram = LoadShaderProgram(VertShaderSrc, FragShaderSrc); - _shaderSets[6]->ShaderProgram = LoadShaderProgram(VertShaderSrcMasked, FragShaderSrcAddMask); - _shaderSets[7]->ShaderProgram = LoadShaderProgram(VertShaderSrc, FragShaderSrcPremultipliedAlpha); - _shaderSets[8]->ShaderProgram = LoadShaderProgram(VertShaderSrcMasked, FragShaderSrcAddMaskPremultipliedAlpha); - - _shaderSets[9]->ShaderProgram = LoadShaderProgram(VertShaderSrc, FragShaderSrc); - _shaderSets[10]->ShaderProgram = LoadShaderProgram(VertShaderSrcMasked, FragShaderSrcMultMask); - _shaderSets[11]->ShaderProgram = LoadShaderProgram(VertShaderSrc, FragShaderSrcPremultipliedAlpha); - _shaderSets[12]->ShaderProgram = LoadShaderProgram(VertShaderSrcMasked, FragShaderSrcMultMaskPremultipliedAlpha); + _shaderSets[4]->ShaderProgram = LoadShaderProgram(VertShaderSrcMasked, FragShaderSrcMaskPremultipliedAlpha); + + // 加算も通常と同じシェーダーを利用する + _shaderSets[5]->ShaderProgram = _shaderSets[1]->ShaderProgram; + _shaderSets[6]->ShaderProgram = _shaderSets[2]->ShaderProgram; + _shaderSets[7]->ShaderProgram = _shaderSets[3]->ShaderProgram; + _shaderSets[8]->ShaderProgram = _shaderSets[4]->ShaderProgram; + + // 乗算も通常と同じシェーダーを利用する + _shaderSets[9]->ShaderProgram = _shaderSets[1]->ShaderProgram; + _shaderSets[10]->ShaderProgram = _shaderSets[2]->ShaderProgram; + _shaderSets[11]->ShaderProgram = _shaderSets[3]->ShaderProgram; + _shaderSets[12]->ShaderProgram = _shaderSets[4]->ShaderProgram; } #else @@ -1179,19 +1084,21 @@ void CubismShader_OpenGLES2::GenerateShaders() _shaderSets[0]->ShaderProgram = LoadShaderProgram(VertShaderSrcSetupMask, FragShaderSrcSetupMask); _shaderSets[1]->ShaderProgram = LoadShaderProgram(VertShaderSrc, FragShaderSrc); - _shaderSets[2]->ShaderProgram = LoadShaderProgram(VertShaderSrcMasked, FragShaderSrcNormalMask); + _shaderSets[2]->ShaderProgram = LoadShaderProgram(VertShaderSrcMasked, FragShaderSrcMask); _shaderSets[3]->ShaderProgram = LoadShaderProgram(VertShaderSrc, FragShaderSrcPremultipliedAlpha); - _shaderSets[4]->ShaderProgram = LoadShaderProgram(VertShaderSrcMasked, FragShaderSrcNormalMaskPremultipliedAlpha); - - _shaderSets[5]->ShaderProgram = LoadShaderProgram(VertShaderSrc, FragShaderSrc); - _shaderSets[6]->ShaderProgram = LoadShaderProgram(VertShaderSrcMasked, FragShaderSrcAddMask); - _shaderSets[7]->ShaderProgram = LoadShaderProgram(VertShaderSrc, FragShaderSrcPremultipliedAlpha); - _shaderSets[8]->ShaderProgram = LoadShaderProgram(VertShaderSrcMasked, FragShaderSrcAddMaskPremultipliedAlpha); - - _shaderSets[9]->ShaderProgram = LoadShaderProgram(VertShaderSrc, FragShaderSrc); - _shaderSets[10]->ShaderProgram = LoadShaderProgram(VertShaderSrcMasked, FragShaderSrcMultMask); - _shaderSets[11]->ShaderProgram = LoadShaderProgram(VertShaderSrc, FragShaderSrcPremultipliedAlpha); - _shaderSets[12]->ShaderProgram = LoadShaderProgram(VertShaderSrcMasked, FragShaderSrcMultMaskPremultipliedAlpha); + _shaderSets[4]->ShaderProgram = LoadShaderProgram(VertShaderSrcMasked, FragShaderSrcMaskPremultipliedAlpha); + + // 加算も通常と同じシェーダーを利用する + _shaderSets[5]->ShaderProgram = _shaderSets[1]->ShaderProgram; + _shaderSets[6]->ShaderProgram = _shaderSets[2]->ShaderProgram; + _shaderSets[7]->ShaderProgram = _shaderSets[3]->ShaderProgram; + _shaderSets[8]->ShaderProgram = _shaderSets[4]->ShaderProgram; + + // 乗算も通常と同じシェーダーを利用する + _shaderSets[9]->ShaderProgram = _shaderSets[1]->ShaderProgram; + _shaderSets[10]->ShaderProgram = _shaderSets[2]->ShaderProgram; + _shaderSets[11]->ShaderProgram = _shaderSets[3]->ShaderProgram; + _shaderSets[12]->ShaderProgram = _shaderSets[4]->ShaderProgram; #endif // SetupMask diff --git a/CubismSDK/Framework/src/Rendering/OpenGL/CubismRenderer_OpenGLES2.hpp b/CubismSDK/Framework/src/Rendering/OpenGL/CubismRenderer_OpenGLES2.hpp index a392e10..2bae72f 100644 --- a/CubismSDK/Framework/src/Rendering/OpenGL/CubismRenderer_OpenGLES2.hpp +++ b/CubismSDK/Framework/src/Rendering/OpenGL/CubismRenderer_OpenGLES2.hpp @@ -185,7 +185,7 @@ class CubismClippingManager_OpenGLES2 csmInt32 _currentFrameNo; ///< マスクテクスチャに与えるフレーム番号 csmVector _channelColors; - csmVector _maskTextures; ///< マスク用のテクスチャリソースのリスト + CubismRenderTextureResource* _maskTexture; ///< マスク用のテクスチャリソース csmVector _clippingContextListForMask; ///< マスク用クリッピングコンテキストのリスト csmVector _clippingContextListForDraw; ///< 描画用クリッピングコンテキストのリスト csmInt32 _clippingMaskBufferSize; ///< クリッピングマスクのバッファサイズ(初期値:256) diff --git a/CubismSDK/Framework/src/Utils/CubismJson.cpp b/CubismSDK/Framework/src/Utils/CubismJson.cpp index 465f24a..d3270f7 100644 --- a/CubismSDK/Framework/src/Utils/CubismJson.cpp +++ b/CubismSDK/Framework/src/Utils/CubismJson.cpp @@ -49,14 +49,14 @@ void Value::StaticInitializeNotForClientCall() } CubismJson::CubismJson() - : _lineCount(0) - , _error(NULL) + : _error(NULL) + , _lineCount(0) , _root(NULL) { } CubismJson::CubismJson(const csmByte* buffer, csmInt32 length) - : _lineCount(0) - , _error(NULL) + : _error(NULL) + , _lineCount(0) , _root(NULL) { ParseBytes(buffer, length); @@ -108,7 +108,7 @@ csmBool CubismJson::ParseBytes(const csmByte* buffer, csmInt32 size) if (_error) { -#if defined(CSM_TARGET_WIN_GL) +#if defined(CSM_TARGET_WIN_GL) || defined(_MSC_VER) csmChar strbuf[256] = {'\0'}; _snprintf_s(strbuf, 256, 256, "Json parse error : @line %d\n", (_lineCount + 1)); _root = CSM_NEW String(strbuf); diff --git a/CubismSDK/Framework/src/Utils/CubismJson.hpp b/CubismSDK/Framework/src/Utils/CubismJson.hpp index c1d7b21..9d76ef0 100644 --- a/CubismSDK/Framework/src/Utils/CubismJson.hpp +++ b/CubismSDK/Framework/src/Utils/CubismJson.hpp @@ -376,7 +376,7 @@ class Float : public Value */ virtual const csmString& GetString(const csmString& defaultValue = "", const csmString& indent = "") { -#if defined(CSM_TARGET_WIN_GL) +#if defined(CSM_TARGET_WIN_GL) || defined(_MSC_VER) csmChar strbuf[32] = {'\0'}; _snprintf_s(strbuf, 32, 32, "%f", this->_value); _stringBuffer = csmString(strbuf); diff --git a/setup.py b/setup.py index 9bd80a0..d1ba9dd 100644 --- a/setup.py +++ b/setup.py @@ -71,7 +71,8 @@ def recursive_glob(search_path, filename_glob): matching_filenames = set() for root, dirs, files in os.walk(search_path): matching_filenames.update([os.path.join(root, filename) for filename in fnmatch.filter(files, filename_glob)]) - return list(matching_filenames) + # Quick hack to exclude D3D9 from build process as we has not support for D3D9 yet. + return [x for x in list(matching_filenames) if "D3D9" not in x] setup(name='live2d', cmdclass = {'build_ext': build_ext},