mirror of https://github.com/axmolengine/axmol.git
Merge pull request #7736 from dabingnn/v3_addSkinnedOutline
V3 add skinned outline
This commit is contained in:
commit
cc37780861
|
@ -28,6 +28,7 @@
|
|||
#include <unordered_map>
|
||||
|
||||
#include "3d/CCBundle3DData.h"
|
||||
#include "3d/CCSkeleton3D.h"
|
||||
|
||||
#include "base/ccMacros.h"
|
||||
#include "base/CCRef.h"
|
||||
|
@ -44,7 +45,7 @@ class Skeleton3D;
|
|||
* MeshSkin, A class maintain a collection of bones that affect Mesh vertex.
|
||||
* And it is responsible for computing matrix palletes that used by skin mesh rendering.
|
||||
*/
|
||||
class MeshSkin: public Ref
|
||||
class CC_DLL MeshSkin: public Ref
|
||||
{
|
||||
public:
|
||||
|
||||
|
|
|
@ -51,6 +51,9 @@ static std::function<Layer*()> createFunctions[] =
|
|||
CL(Sprite3DEffectTest),
|
||||
#endif
|
||||
CL(Sprite3DWithSkinTest),
|
||||
#if (CC_TARGET_PLATFORM != CC_PLATFORM_WP8) && (CC_TARGET_PLATFORM != CC_PLATFORM_WINRT)
|
||||
CL(Sprite3DWithSkinOutlineTest),
|
||||
#endif
|
||||
CL(Animate3DTest),
|
||||
CL(AttachmentTest)
|
||||
};
|
||||
|
@ -316,6 +319,7 @@ EffectSprite3D* EffectSprite3D::createFromObjFileAndTexture(const std::string &o
|
|||
if (sprite && sprite->initWithFile(objFilePath))
|
||||
{
|
||||
sprite->autorelease();
|
||||
if(textureFilePath.size() > 0)
|
||||
sprite->setTexture(textureFilePath);
|
||||
return sprite;
|
||||
}
|
||||
|
@ -323,6 +327,21 @@ EffectSprite3D* EffectSprite3D::createFromObjFileAndTexture(const std::string &o
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
EffectSprite3D* EffectSprite3D::create(const std::string &path)
|
||||
{
|
||||
if (path.length() < 4)
|
||||
CCASSERT(false, "improper name specified when creating Sprite3D");
|
||||
|
||||
auto sprite = new EffectSprite3D();
|
||||
if (sprite && sprite->initWithFile(path))
|
||||
{
|
||||
sprite->autorelease();
|
||||
return sprite;
|
||||
}
|
||||
CC_SAFE_DELETE(sprite);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
EffectSprite3D::EffectSprite3D()
|
||||
: _defaultEffect(nullptr)
|
||||
{
|
||||
|
@ -360,8 +379,24 @@ void EffectSprite3D::addEffect(Effect3DOutline* effect, ssize_t order)
|
|||
const std::string Effect3DOutline::_vertShaderFile = "Shaders3D/OutLine.vert";
|
||||
const std::string Effect3DOutline::_fragShaderFile = "Shaders3D/OutLine.frag";
|
||||
const std::string Effect3DOutline::_keyInGLProgramCache = "Effect3DLibrary_Outline";
|
||||
GLProgram* Effect3DOutline::getOrCreateProgram()
|
||||
|
||||
const std::string Effect3DOutline::_vertSkinnedShaderFile = "Shaders3D/SkinnedOutLine.vert";
|
||||
const std::string Effect3DOutline::_fragSkinnedShaderFile = "Shaders3D/OutLine.frag";
|
||||
const std::string Effect3DOutline::_keySkinnedInGLProgramCache = "Effect3DLibrary_Outline";
|
||||
GLProgram* Effect3DOutline::getOrCreateProgram(bool isSkinned /* = false */ )
|
||||
{
|
||||
if(isSkinned)
|
||||
{
|
||||
auto program = GLProgramCache::getInstance()->getGLProgram(_keySkinnedInGLProgramCache);
|
||||
if(program == nullptr)
|
||||
{
|
||||
program = GLProgram::createWithFilenames(_vertSkinnedShaderFile, _fragSkinnedShaderFile);
|
||||
GLProgramCache::getInstance()->addGLProgram(program, _keySkinnedInGLProgramCache);
|
||||
}
|
||||
return program;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto program = GLProgramCache::getInstance()->getGLProgram(_keyInGLProgramCache);
|
||||
if(program == nullptr)
|
||||
{
|
||||
|
@ -369,6 +404,8 @@ GLProgram* Effect3DOutline::getOrCreateProgram()
|
|||
GLProgramCache::getInstance()->addGLProgram(program, _keyInGLProgramCache);
|
||||
}
|
||||
return program;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Effect3DOutline* Effect3DOutline::create()
|
||||
|
@ -389,21 +426,6 @@ Effect3DOutline* Effect3DOutline::create()
|
|||
bool Effect3DOutline::init()
|
||||
{
|
||||
|
||||
GLProgram* glprogram = GLProgram::createWithFilenames(_vertShaderFile, _fragShaderFile);
|
||||
if(nullptr == glprogram)
|
||||
{
|
||||
CC_SAFE_DELETE(glprogram);
|
||||
return false;
|
||||
}
|
||||
_glProgramState = GLProgramState::create(glprogram);
|
||||
if(nullptr == _glProgramState)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
_glProgramState->retain();
|
||||
_glProgramState->setUniformVec3("OutLineColor", _outlineColor);
|
||||
_glProgramState->setUniformFloat("OutlineWidth", _outlineWidth);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -439,6 +461,7 @@ void Effect3DOutline::setOutlineColor(const Vec3& color)
|
|||
if(_outlineColor != color)
|
||||
{
|
||||
_outlineColor = color;
|
||||
if(_glProgramState)
|
||||
_glProgramState->setUniformVec3("OutLineColor", _outlineColor);
|
||||
}
|
||||
}
|
||||
|
@ -448,6 +471,7 @@ void Effect3DOutline::setOutlineWidth(float width)
|
|||
if(_outlineWidth != width)
|
||||
{
|
||||
_outlineWidth = width;
|
||||
if(_glProgramState)
|
||||
_glProgramState->setUniformFloat("OutlineWidth", _outlineWidth);
|
||||
}
|
||||
}
|
||||
|
@ -458,6 +482,19 @@ void Effect3DOutline::setTarget(EffectSprite3D *sprite)
|
|||
|
||||
if(sprite != _sprite)
|
||||
{
|
||||
GLProgram* glprogram;
|
||||
if(!sprite->getSkin())
|
||||
glprogram = GLProgram::createWithFilenames(_vertShaderFile, _fragShaderFile);
|
||||
else
|
||||
glprogram = GLProgram::createWithFilenames(_vertSkinnedShaderFile, _fragSkinnedShaderFile);
|
||||
|
||||
_glProgramState = GLProgramState::create(glprogram);
|
||||
|
||||
_glProgramState->retain();
|
||||
_glProgramState->setUniformVec3("OutLineColor", _outlineColor);
|
||||
_glProgramState->setUniformFloat("OutlineWidth", _outlineWidth);
|
||||
|
||||
|
||||
_sprite = sprite;
|
||||
|
||||
auto mesh = sprite->getMesh();
|
||||
|
@ -482,6 +519,11 @@ void Effect3DOutline::setTarget(EffectSprite3D *sprite)
|
|||
|
||||
}
|
||||
|
||||
static void MatrixPalleteCallBack( GLProgram* glProgram, Uniform* uniform, int paletteSize, const float* palette)
|
||||
{
|
||||
glUniform4fv( uniform->location, (GLsizei)paletteSize, (const float*)palette );
|
||||
}
|
||||
|
||||
void Effect3DOutline::draw(const Mat4 &transform)
|
||||
{
|
||||
//draw
|
||||
|
@ -496,7 +538,17 @@ void Effect3DOutline::draw(const Mat4 &transform)
|
|||
|
||||
auto mesh = _sprite->getMesh();
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mesh->getVertexBuffer());
|
||||
|
||||
if(_sprite && _sprite->getSkin())
|
||||
{
|
||||
auto function = std::bind(MatrixPalleteCallBack, std::placeholders::_1, std::placeholders::_2,
|
||||
_sprite->getSkin()->getMatrixPaletteSize(), (float*)_sprite->getSkin()->getMatrixPalette());
|
||||
_glProgramState->setUniformCallback("u_matrixPalette", function);
|
||||
}
|
||||
|
||||
if(_sprite)
|
||||
_glProgramState->apply(transform);
|
||||
|
||||
for (ssize_t i = 0; i < mesh->getSubMeshCount(); i++) {
|
||||
auto submesh = mesh->getSubMesh((int)i);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, submesh->getIndexBuffer());
|
||||
|
@ -569,13 +621,14 @@ void Sprite3DEffectTest::addNewSpriteWithCoords(Vec2 p)
|
|||
//option 2: load obj and assign the texture
|
||||
auto sprite = EffectSprite3D::createFromObjFileAndTexture("Sprite3DTest/boss1.obj", "Sprite3DTest/boss.png");
|
||||
Effect3DOutline* effect = Effect3DOutline::create();
|
||||
sprite->addEffect(effect, -1);
|
||||
effect->setOutlineColor(Vec3(1,0,0));
|
||||
effect->setOutlineWidth(0.01f);
|
||||
sprite->addEffect(effect, -1);
|
||||
|
||||
Effect3DOutline* effect2 = Effect3DOutline::create();
|
||||
sprite->addEffect(effect2, -2);
|
||||
effect2->setOutlineWidth(0.02f);
|
||||
effect2->setOutlineColor(Vec3(1,1,0));
|
||||
sprite->addEffect(effect2, -2);
|
||||
//sprite->setEffect3D(effect);
|
||||
sprite->setScale(6.f);
|
||||
|
||||
|
@ -634,7 +687,7 @@ std::string Sprite3DWithSkinTest::subtitle() const
|
|||
void Sprite3DWithSkinTest::addNewSpriteWithCoords(Vec2 p)
|
||||
{
|
||||
std::string fileName = "Sprite3DTest/orc.c3b";
|
||||
auto sprite = Sprite3D::create(fileName);
|
||||
auto sprite = EffectSprite3D::create(fileName);
|
||||
sprite->setScale(3);
|
||||
sprite->setRotation3D(Vec3(0,180,0));
|
||||
addChild(sprite);
|
||||
|
@ -672,6 +725,79 @@ void Sprite3DWithSkinTest::onTouchesEnded(const std::vector<Touch*>& touches, Ev
|
|||
}
|
||||
}
|
||||
|
||||
Sprite3DWithSkinOutlineTest::Sprite3DWithSkinOutlineTest()
|
||||
{
|
||||
auto listener = EventListenerTouchAllAtOnce::create();
|
||||
listener->onTouchesEnded = CC_CALLBACK_2(Sprite3DWithSkinOutlineTest::onTouchesEnded, this);
|
||||
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
|
||||
|
||||
auto s = Director::getInstance()->getWinSize();
|
||||
addNewSpriteWithCoords( Vec2(s.width/2, s.height/2) );
|
||||
}
|
||||
std::string Sprite3DWithSkinOutlineTest::title() const
|
||||
{
|
||||
return "Testing Sprite3D for skinned outline";
|
||||
}
|
||||
std::string Sprite3DWithSkinOutlineTest::subtitle() const
|
||||
{
|
||||
return "Tap screen to add more sprite3D";
|
||||
}
|
||||
|
||||
void Sprite3DWithSkinOutlineTest::addNewSpriteWithCoords(Vec2 p)
|
||||
{
|
||||
|
||||
std::string fileName = "Sprite3DTest/orc.c3b";
|
||||
auto sprite = EffectSprite3D::create(fileName);
|
||||
|
||||
Effect3DOutline* effect = Effect3DOutline::create();
|
||||
effect->setOutlineColor(Vec3(1,0,0));
|
||||
effect->setOutlineWidth(0.01f);
|
||||
sprite->addEffect(effect, -1);
|
||||
|
||||
|
||||
Effect3DOutline* effect2 = Effect3DOutline::create();
|
||||
effect2->setOutlineWidth(0.02f);
|
||||
effect2->setOutlineColor(Vec3(1,1,0));
|
||||
sprite->addEffect(effect2, -2);
|
||||
|
||||
|
||||
sprite->setScale(3);
|
||||
sprite->setRotation3D(Vec3(0,180,0));
|
||||
addChild(sprite);
|
||||
sprite->setPosition( Vec2( p.x, p.y) );
|
||||
|
||||
auto animation = Animation3D::create(fileName);
|
||||
if (animation)
|
||||
{
|
||||
auto animate = Animate3D::create(animation);
|
||||
bool inverse = (std::rand() % 3 == 0);
|
||||
|
||||
int rand2 = std::rand();
|
||||
float speed = 1.0f;
|
||||
if(rand2 % 3 == 1)
|
||||
{
|
||||
speed = animate->getSpeed() + CCRANDOM_0_1();
|
||||
}
|
||||
else if(rand2 % 3 == 2)
|
||||
{
|
||||
speed = animate->getSpeed() - 0.5 * CCRANDOM_0_1();
|
||||
}
|
||||
animate->setSpeed(inverse ? -speed : speed);
|
||||
|
||||
sprite->runAction(RepeatForever::create(animate));
|
||||
}
|
||||
}
|
||||
|
||||
void Sprite3DWithSkinOutlineTest::onTouchesEnded(const std::vector<Touch*>& touches, Event* event)
|
||||
{
|
||||
for (auto touch: touches)
|
||||
{
|
||||
auto location = touch->getLocation();
|
||||
|
||||
addNewSpriteWithCoords( location );
|
||||
}
|
||||
}
|
||||
|
||||
Animate3DTest::Animate3DTest()
|
||||
: _hurt(nullptr)
|
||||
, _swim(nullptr)
|
||||
|
|
|
@ -113,7 +113,12 @@ protected:
|
|||
static const std::string _vertShaderFile;
|
||||
static const std::string _fragShaderFile;
|
||||
static const std::string _keyInGLProgramCache;
|
||||
static GLProgram* getOrCreateProgram();
|
||||
|
||||
static const std::string _vertSkinnedShaderFile;
|
||||
static const std::string _fragSkinnedShaderFile;
|
||||
static const std::string _keySkinnedInGLProgramCache;
|
||||
|
||||
static GLProgram* getOrCreateProgram(bool isSkinned = false);
|
||||
};
|
||||
|
||||
class Sprite3DHitTest : public Sprite3DTestDemo
|
||||
|
@ -129,6 +134,8 @@ class EffectSprite3D : public Sprite3D
|
|||
{
|
||||
public:
|
||||
static EffectSprite3D* createFromObjFileAndTexture(const std::string& objFilePath, const std::string& textureFilePath);
|
||||
static EffectSprite3D* create(const std::string& path);
|
||||
|
||||
void setEffect3D(Effect3D* effect);
|
||||
void addEffect(Effect3DOutline* effect, ssize_t order);
|
||||
virtual void draw(Renderer *renderer, const Mat4 &transform, uint32_t flags) override;
|
||||
|
@ -167,6 +174,19 @@ public:
|
|||
void onTouchesEnded(const std::vector<Touch*>& touches, Event* event);
|
||||
};
|
||||
|
||||
class Sprite3DWithSkinOutlineTest : public Sprite3DTestDemo
|
||||
{
|
||||
public:
|
||||
CREATE_FUNC(Sprite3DWithSkinOutlineTest);
|
||||
Sprite3DWithSkinOutlineTest();
|
||||
virtual std::string title() const override;
|
||||
virtual std::string subtitle() const override;
|
||||
|
||||
void addNewSpriteWithCoords(Vec2 p);
|
||||
|
||||
void onTouchesEnded(const std::vector<Touch*>& touches, Event* event);
|
||||
};
|
||||
|
||||
class Animate3DTest : public Sprite3DTestDemo
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
attribute vec3 a_position;
|
||||
attribute vec3 a_normal;
|
||||
attribute vec4 a_blendWeight;
|
||||
attribute vec4 a_blendIndex;
|
||||
|
||||
attribute vec2 a_texCoord;
|
||||
uniform float OutlineWidth;
|
||||
|
||||
const int SKINNING_JOINT_COUNT = 60;
|
||||
// Uniforms
|
||||
uniform vec4 u_matrixPalette[SKINNING_JOINT_COUNT * 3];
|
||||
|
||||
// Varyings
|
||||
varying vec2 TextureCoordOut;
|
||||
|
||||
vec4 SkinnedVec3(vec3 vec)
|
||||
{
|
||||
float blendWeight = a_blendWeight[0];
|
||||
|
||||
int matrixIndex = int (a_blendIndex[0]) * 3;
|
||||
vec4 matrixPalette1 = u_matrixPalette[matrixIndex] * blendWeight;
|
||||
vec4 matrixPalette2 = u_matrixPalette[matrixIndex + 1] * blendWeight;
|
||||
vec4 matrixPalette3 = u_matrixPalette[matrixIndex + 2] * blendWeight;
|
||||
|
||||
|
||||
blendWeight = a_blendWeight[1];
|
||||
if (blendWeight > 0.0)
|
||||
{
|
||||
matrixIndex = int(a_blendIndex[1]) * 3;
|
||||
matrixPalette1 += u_matrixPalette[matrixIndex] * blendWeight;
|
||||
matrixPalette2 += u_matrixPalette[matrixIndex + 1] * blendWeight;
|
||||
matrixPalette3 += u_matrixPalette[matrixIndex + 2] * blendWeight;
|
||||
}
|
||||
|
||||
|
||||
blendWeight = a_blendWeight[2];
|
||||
if (blendWeight > 0.0)
|
||||
{
|
||||
matrixIndex = int(a_blendIndex[2]) * 3;
|
||||
matrixPalette1 += u_matrixPalette[matrixIndex] * blendWeight;
|
||||
matrixPalette2 += u_matrixPalette[matrixIndex + 1] * blendWeight;
|
||||
matrixPalette3 += u_matrixPalette[matrixIndex + 2] * blendWeight;
|
||||
}
|
||||
|
||||
|
||||
blendWeight = a_blendWeight[3];
|
||||
if (blendWeight > 0.0)
|
||||
{
|
||||
matrixIndex = int(a_blendIndex[3]) * 3;
|
||||
matrixPalette1 += u_matrixPalette[matrixIndex] * blendWeight;
|
||||
matrixPalette2 += u_matrixPalette[matrixIndex + 1] * blendWeight;
|
||||
matrixPalette3 += u_matrixPalette[matrixIndex + 2] * blendWeight;
|
||||
}
|
||||
|
||||
|
||||
vec4 _skinnedPosition;
|
||||
vec4 postion = vec4(vec, 1.0);
|
||||
_skinnedPosition.x = dot(postion, matrixPalette1);
|
||||
_skinnedPosition.y = dot(postion, matrixPalette2);
|
||||
_skinnedPosition.z = dot(postion, matrixPalette3);
|
||||
_skinnedPosition.w = postion.w;
|
||||
|
||||
return _skinnedPosition;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 pos = CC_MVPMatrix * SkinnedVec3(a_position);
|
||||
|
||||
vec4 normalproj = CC_MVPMatrix * vec4(SkinnedVec3(a_normal).xyz, 0);
|
||||
normalproj = normalize(normalproj);
|
||||
pos.xy += normalproj.xy * (OutlineWidth * (pos.z * 0.5 + 0.5));
|
||||
|
||||
gl_Position = pos;
|
||||
}
|
Loading…
Reference in New Issue