【问题标题】:Cocos2d-x shader is using invalid offset on texturepacker imported spriteframeCocos2d-x 着色器在纹理打包器导入的 spriteframe 上使用了无效的偏移量
【发布时间】:2016-02-19 22:52:34
【问题描述】:

我正在尝试在 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));

【问题讨论】:

    标签: opengl cocos2d-x shader texturepacker


    【解决方案1】:

    如果不查看更多代码,很难判断发生了什么...

    如果我猜的话,我会说问题与 TexturePacker 中的修剪有关。

    如果您设置 TrimMode=Trim,则精灵会从透明度中去除。这使得精灵更小。 Cocos2d-x 也只渲染精灵的较小部分,用偏移向量补偿原始精灵和修剪后的精灵之间的差异。

    我建议您要么尝试不修剪精灵,要么尝试修剪多边形。

    【讨论】:

    • 是的,这确实是问题的一部分。没有修剪看起来还可以。但还有另一个问题。因为草摆动效果基于纹理高度,并且因为在生成的纹理中一个在另一个下方,所以下方的纹理具有较少的摆动效果。所以我猜测片段着色器中的高度计算错误,通过使用来自纹理打包器的整个纹理高度。有没有办法避免这种情况?
    • 您可以尝试将真实尺寸传递给着色器。它们可从grass2->getSpriteFrame() 获得。有了这个,您应该能够补偿修剪过的像素。
    【解决方案2】:

    问题在于 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;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-02-10
      • 2023-03-28
      • 1970-01-01
      • 2015-07-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-23
      相关资源
      最近更新 更多