Send texture from spritesheet to shader

Hey, I’m currently trying to send a texture (additionaly to the main sprite texture) to the shader. Without spritesheets this is straight forward but I’m not sure how this might work with sprite sheets. Currently when I’m binding a second texture and use it with CC_Texture1 it displays the same texture as CC_Texture0(main texture), probably because cocos internally always uses the Rect of the main texture position in the spritesheet/atlas.

To create my sprite i’m using Sprite::createWithSpriteFrameName(…)

Has anyone ever tried this and can help me with this ? :slight_smile:

I’m not sure if cocos has an easy way of doing this, because the texcoords will always be the coords from the whole spritesheet.

My main test goal would be to just take the color from the second texture and use it for the main texture in the shader for whatever effect.

1 Like

I could only think of adding a UV offset and taking the color from the fragment with this offset, but I curious if there is an easier way for this

1 Like

//CustomSprite created with a texture

 glp->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_POSITION, GLProgram::VERTEX_ATTRIB_POSITION);
    glp->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_COLOR, GLProgram::VERTEX_ATTRIB_COLOR);
    glp->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_TEX_COORD, GLProgram::VERTEX_ATTRIB_TEX_COORD);
    glp->link();
    glp->updateUniforms();
    setGLProgram(glp);

   //Second external texture
    SpriteFrame* frame = SpriteFrameCache::getInstance()->getSpriteFrameByName("star_yellow.png");

// uv pos for second
    auto rect = frame->getRect();
    auto sprite_sheet_pos = rect.origin;
    auto texture_size = rect.size;
    auto sprite_sheet_texture = frame->getTexture();
    auto tex_width = sprite_sheet_texture->getPixelsWide();
    auto tex_height = sprite_sheet_texture->getPixelsHigh();

    float pos_x = sprite_sheet_pos.x / tex_width;
    float pos_y = sprite_sheet_pos.y / tex_height;
    float width = texture_size.width / tex_width;
    float height = texture_size.height / tex_height;

    float x1 = pos_x;
    float x2 = pos_x + width;
    float y1 = pos_y;
    float y2 = pos_y + height;

    auto glprogramstate = GLProgramState::getOrCreateWithGLProgram(glp);
    setGLProgramState(glprogramstate);
// uv pos of main texture
    rect = getTextureRect();
    sprite_sheet_pos = rect.origin;
    texture_size = rect.size;
    sprite_sheet_texture = getTexture();
    tex_width = sprite_sheet_texture->getPixelsWide();
    tex_height = sprite_sheet_texture->getPixelsHigh();

    pos_x = sprite_sheet_pos.x / tex_width;
    pos_y = sprite_sheet_pos.y / tex_height;
    width = texture_size.width / tex_width;
    height = texture_size.height / tex_height;

    float x1_1 = pos_x;
    float y1_1 = pos_y;

    auto loc = glGetUniformLocation(glp->getProgram(), "tex_1_offset");

//offset to main texture
    glprogramstate->setUniformVec2(loc, Vec2(x1 - x1_1, y1 - y1_1));

    auto glprogrammstate = GLProgramState::getOrCreateWithGLProgram(glp);
    glprogrammstate->setUniformFloat("blend_val", 0.5f);

shader:

varying vec2 v_texCoord;

uniform vec2 tex_1_offset;
uniform float blend_val;

void main()
{
	vec4 tex1 = texture2D(CC_Texture0, v_texCoord + tex_1_offset);
	vec4 tex2 = texture2D(CC_Texture0, v_texCoord);

	gl_FragColor = tex1 * (1. - blend_val) + tex2 * blend_val;
}

This for example does work, if the second sprite is in the same spritesheet and if it has the same size, but hopefully there is a better way?

2 Likes