If you have any questions, reports, suggestions, or requests about Live2D, please send them to this forum.
※We cannot guarantee statements or answers from Live2D staff. Thank you for your understanding in advance.
Live2D Cubism
Cubism Products and Downloads
Cubism product manuals and tutorials
Cubism Editor Manual
Cubism Editor Tutorial
Cubism SDK Manual
Cubism SDK Tutorial
[Regarding macOS Tahoe](Updated October 16, 2025)
macOS v26 Tahoe is now supported!
We advise against upgrading your macOS at this time as it may cause Live2D products not to function correctly.
Upgrading macOS can also cause you to lose your Cubism Editor license file.
Please make sure to deactivate your Cubism Editor license before upgrading the macOS.
For more details:
https://help.live2d.com/en/other/other_09/
For inquiries regarding issues with license purchases or license activation errors, please contact us through the email form.
Comments
const char* cc3D_PositionNormalTexOutline_vert = STRINGIFY(
attribute vec4 a_position;
attribute vec2 a_texCoord;
attribute vec3 a_normal;
varying vec2 TextureCoordOut;
varying vec3 v_normal;
void main(void)
{
vec4 ePosition = CC_MVMatrix * a_position;
v_normal = CC_NormalMatrix * a_normal;
TextureCoordOut = a_texCoord;
TextureCoordOut.y = 1.0 - TextureCoordOut.y;
gl_Position = CC_PMatrix * ePosition;
}
);
const char* cc3D_ColorNormalTexOutline_frag = STRINGIFY(
\n#ifdef GL_ES\n
varying mediump vec2 TextureCoordOut;
varying mediump vec3 v_normal;
\n#else\n
varying vec2 TextureCoordOut;
varying vec3 v_normal;
\n#endif\n
uniform vec4 u_color;
uniform float u_falloffValue;
uniform float u_powValue;
uniform vec4 u_innerColor;
void main(void)
{
vec3 normal = normalize(v_normal); // vertex normal does not calculate right here
float value = dot(normal,vec3(0.0,0.0,1.0));
vec4 texcolor = texture2D(CC_Texture0, TextureCoordOut);
vec4 finalcolor = texcolor*u_color;
value = clamp(value * u_falloffValue,0.0,1.0);
value = pow(value, u_powValue);
float inverseValue = clamp(1.0-value,0.0,1.0);
finalcolor = finalcolor*value + u_innerColor*inverseValue;
finalcolor.a = value;
gl_FragColor = finalcolor;
}
);
Could you please test this code?
void LAppModel::draw()
{
if (live2DModel == NULL)return;
live2DModel->draw(); //comment this
glFrontFace(GL_CCW);//change Front Face
}
In live2DModel::draw function, we call glFrontFace(GL_CW).
Unfortunately we forgot to restore this state in live2d::DrawProfileCocos2D::postDraw() .
This bug will be fixed next live2d SDK version.
glFrontFace(GL_CCW) does work, both live2d and Sprite3D show up correctly.
That's a great help.
/////////////////////////////////////////////////////////////////
Meanwhile, there's another problem:
We got a crash days before when using Spine and live2D object at the same time, the Spine crash during rendering,
then we add code like this:
void L2DSprite::onDraw(const cocos2d::Mat4 &transform, uint32_t flags)
{
Director * director = Director::getInstance();
MATRIX_STACK_TYPE type = MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW;
director->pushMatrix(type);
director->loadMatrix(type, transform);
LAppLive2DManager* Live2DMgr=LAppLive2DManager::getInstance();
Live2DMgr->onUpdate();
//buff error
glBindBuffer(GL_ARRAY_BUFFER, 0); //We have to set bound buffer to 0 here
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);//We have to set bound buffer to 0 here
director->popMatrix(type);
}
Finally, after buffer was rebound to 0, the crash gone.
I think something is wrong with buffer binding.
Thanks
Cocos2d-x 3.4 has fixed a bug about VAO, that VAO should be bound to 0 before VBO does. Just add GL::bindVAO(0); before glBindBuffer(GL_ARRAY_BUFFER, 0); within all cocos2d-x source code.
If you enabled VAO configuration, you should apply this patch of cocos2d-x and do the samething on your code.