Cocos2d-x 着色器在 texturepacker 导入的 spriteframe 上使用无效偏移
Cocos2d-x shader is using invalid offset on texturepacker imported spriteframe
我正在尝试为 cocos2d-x 中的草实现着色器。着色器在使用 Sprite::create() 加载的纹理上工作正常,看起来像这样:
http://i.stack.imgur.com/Rv4rd.png
问题是,如果我使用 Sprite::createWithSpriteFrameName() 并应用相同的着色器,那么在计算高度时偏移量似乎是错误的,因为它正在移动在更大程度上,就像它正在使用 plist 文件中的完整纹理的高度:
http://i.stack.imgur.com/of6Ku.png
这是着色器代码:
VSH
attribute vec4 a_position;
attribute vec2 a_texCoord;
attribute vec4 a_color;
#ifdef GL_ES
varying lowp vec4 v_fragmentColor;
varying mediump vec2 v_texCoord;
#else
varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
#endif
void main()
{
gl_Position = CC_PMatrix * a_position;
v_fragmentColor = a_color;
v_texCoord = a_texCoord;
}
FSH
#ifdef GL_ES
precision mediump float;
#endif
varying vec2 v_texCoord;
uniform float speed;
uniform float bendFactor;
void main()
{
float height = 1.0 - v_texCoord.y;
float offset = pow(height, 2.5);
offset *= (sin(CC_Time[1] * speed) * bendFactor);
gl_FragColor = texture2D(CC_Texture0, fract(vec2(v_texCoord.x + offset, v_texCoord.y))).rgba;
}
如果不清楚发生了什么,我可以提供一些视频。谢谢。
编辑
这里是用来生成草精灵的代码:
// Smaller grass
auto grass2 = Sprite::createWithSpriteFrameName("grass2.png");
grass2->setAnchorPoint(Vec2(0.5f, 0));
grass2->setPosition(Vec2(230, footer1->getContentSize().height * 0.25f));
// Apply "grass" shader
grass2->setGLProgramState(mat->getTechniqueByName("grass")->getPassByIndex(0)->getGLProgramState()->clone());
grass2->getGLProgramState()->setUniformFloat("speed", RandomHelper::random_real(0.5f, 3.0f));
grass2->getGLProgramState()->setUniformFloat("bendFactor", RandomHelper::random_real(0.1f, 0.2f));
如果不查看更多代码,很难判断发生了什么...
如果我猜的话,我会说这个问题与 TexturePacker 中的 trimming 有关。
如果您设置 TrimMode=Trim 精灵将不透明。这会使精灵变小。 Cocos2d-x 也只渲染精灵的较小部分,用偏移向量补偿原始精灵和 trimmed 精灵之间的差异。
我建议您要么尝试不 trim 精灵,要么尝试多边形 trim 生成。
问题出在 TexturePacker 修剪以及 v_texCoord 中的偏移。
解决方案是在 cocos2d-x 中计算偏移量并将它们传递给着色器。
我使用以下代码计算了偏移量:
Rect grass2Offset(
grass2->getTextureRect().origin.x / grass2->getTexture()->getContentSize().width,
grass2->getTextureRect().origin.y / grass2->getTexture()->getContentSize().height,
grass2->getTextureRect().size.width / grass2->getTexture()->getContentSize().width,
grass2->getTextureRect().size.height / grass2->getTexture()->getContentSize().height
);
接下来,我将高度偏移和比例作为制服传递给着色器,使用:
grass2->getGLProgramState()->setUniformFloat("heightOffset", grass2Offset.origin.y);
grass2->getGLProgramState()->setUniformFloat("heightScale", 1 / grass2Offset.size.height);
最后,着色器使用这样的偏移量:
#ifdef GL_ES
precision mediump float;
#endif
varying vec2 v_texCoord;
uniform float speed;
uniform float bendFactor;
uniform float heightOffset;
uniform float heightScale;
void main()
{
float height = 1.0 - (v_texCoord.y - heightOffset) * heightScale;
float offset = pow(height, 2.5);
offset *= (sin(CC_Time[1] * speed) * bendFactor);
gl_FragColor = texture2D(CC_Texture0, fract(vec2(v_texCoord.x + offset, v_texCoord.y))).rgba;
}
我正在尝试为 cocos2d-x 中的草实现着色器。着色器在使用 Sprite::create() 加载的纹理上工作正常,看起来像这样:
http://i.stack.imgur.com/Rv4rd.png
问题是,如果我使用 Sprite::createWithSpriteFrameName() 并应用相同的着色器,那么在计算高度时偏移量似乎是错误的,因为它正在移动在更大程度上,就像它正在使用 plist 文件中的完整纹理的高度:
http://i.stack.imgur.com/of6Ku.png
这是着色器代码:
VSH
attribute vec4 a_position;
attribute vec2 a_texCoord;
attribute vec4 a_color;
#ifdef GL_ES
varying lowp vec4 v_fragmentColor;
varying mediump vec2 v_texCoord;
#else
varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
#endif
void main()
{
gl_Position = CC_PMatrix * a_position;
v_fragmentColor = a_color;
v_texCoord = a_texCoord;
}
FSH
#ifdef GL_ES
precision mediump float;
#endif
varying vec2 v_texCoord;
uniform float speed;
uniform float bendFactor;
void main()
{
float height = 1.0 - v_texCoord.y;
float offset = pow(height, 2.5);
offset *= (sin(CC_Time[1] * speed) * bendFactor);
gl_FragColor = texture2D(CC_Texture0, fract(vec2(v_texCoord.x + offset, v_texCoord.y))).rgba;
}
如果不清楚发生了什么,我可以提供一些视频。谢谢。
编辑
这里是用来生成草精灵的代码:
// Smaller grass
auto grass2 = Sprite::createWithSpriteFrameName("grass2.png");
grass2->setAnchorPoint(Vec2(0.5f, 0));
grass2->setPosition(Vec2(230, footer1->getContentSize().height * 0.25f));
// Apply "grass" shader
grass2->setGLProgramState(mat->getTechniqueByName("grass")->getPassByIndex(0)->getGLProgramState()->clone());
grass2->getGLProgramState()->setUniformFloat("speed", RandomHelper::random_real(0.5f, 3.0f));
grass2->getGLProgramState()->setUniformFloat("bendFactor", RandomHelper::random_real(0.1f, 0.2f));
如果不查看更多代码,很难判断发生了什么...
如果我猜的话,我会说这个问题与 TexturePacker 中的 trimming 有关。
如果您设置 TrimMode=Trim 精灵将不透明。这会使精灵变小。 Cocos2d-x 也只渲染精灵的较小部分,用偏移向量补偿原始精灵和 trimmed 精灵之间的差异。
我建议您要么尝试不 trim 精灵,要么尝试多边形 trim 生成。
问题出在 TexturePacker 修剪以及 v_texCoord 中的偏移。
解决方案是在 cocos2d-x 中计算偏移量并将它们传递给着色器。
我使用以下代码计算了偏移量:
Rect grass2Offset(
grass2->getTextureRect().origin.x / grass2->getTexture()->getContentSize().width,
grass2->getTextureRect().origin.y / grass2->getTexture()->getContentSize().height,
grass2->getTextureRect().size.width / grass2->getTexture()->getContentSize().width,
grass2->getTextureRect().size.height / grass2->getTexture()->getContentSize().height
);
接下来,我将高度偏移和比例作为制服传递给着色器,使用:
grass2->getGLProgramState()->setUniformFloat("heightOffset", grass2Offset.origin.y);
grass2->getGLProgramState()->setUniformFloat("heightScale", 1 / grass2Offset.size.height);
最后,着色器使用这样的偏移量:
#ifdef GL_ES
precision mediump float;
#endif
varying vec2 v_texCoord;
uniform float speed;
uniform float bendFactor;
uniform float heightOffset;
uniform float heightScale;
void main()
{
float height = 1.0 - (v_texCoord.y - heightOffset) * heightScale;
float offset = pow(height, 2.5);
offset *= (sin(CC_Time[1] * speed) * bendFactor);
gl_FragColor = texture2D(CC_Texture0, fract(vec2(v_texCoord.x + offset, v_texCoord.y))).rgba;
}