STDIO
Tìm kiếm gần đây
    • Nội dung
    • QR Code
    • 0
    • 0
    • Sao chép

    Vẽ Sprite Sử Dụng Mặt Nạ (Cocos2d-x 2.x)

    Hướng dẫn tạo hiệu ứng vẽ sprite sử dụng mặt nạ cho vòng ma thuật trong Cocos2d-x
    24/08/2015
    28/09/2020
    3 phút đọc
    Vẽ Sprite Sử Dụng Mặt Nạ (Cocos2d-x 2.x)

    Hiệu ứng là 1 trong những phần không thể thiếu được của các game. 

    Trong bài viết này sẽ hướng dẫn tạo hiệu ứng vẽ sprite sử dụng mặt nạ cho vòng ma thuật.

    Hiện thực

    Sau khi kết thúc bài viết này, có thể tạo được hiệu ứng có dạng như sau:

    ss_1

    Để hoàn thành bài viết này, cần sử dụng 2 hình ảnh:

    • Hình ảnh thứ nhất là hình ảnh HelloWorld.png được đính kèm trong dự án mẫu của Cocos2d-x.
    • Hình ảnh thứ 2 là hình ảnh Mask.png được đính kèm bên dưới.
    ss_2

    Để vẽ được sprite sử dụng mặt nạ, cần phải viết shader hỗ trợ multi-texture. Trong bài viết này sử dụng 2 texture:

    • texture thứ nhất để làm nền.
    • texture thứ hai để làm mặt nạ che texture nền.

    Vertex shader giữ giống như shader của Cocos2d-x:

    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_MVPMatrix * a_position;
    	v_fragmentColor = a_color;
    	v_texCoord = a_texCoord;
    }

    Fragment shader:

    #ifdef GL_ES
    precision lowp float;
    #endif
    
    varying vec4 v_fragmentColor;
    varying vec2 v_texCoord;
    uniform sampler2D u_texture;
    uniform sampler2D u_mask;
    
    void main()
    {
    	vec4 texColor = texture2D(u_texture, v_texCoord);
    	vec4 maskedColor = texture2D(u_mask, v_texCoord);
    	vec4 blendingColor = vec4(texColor.r, texColor.g,
    				texColor.b, maskedColor.a * texColor.a);
    
    	gl_FragColor = v_fragmentColor * blendingColor;
    }

    3 kênh màu đỏ, xanh lá cây, xanh dương của màu cuối cùng được tạo ra giữ giống hệt 3 kênh trong texture nền. Để tạo được hiệu ứng, kênh alpha là điểm cần lưu ý.

    Theo phương pháp hiện thực trong bài viết đã nhân giá trị của 2 kênh alpha trong texture nền và texture mặt nạ để tính toán giá trị kênh alpha trong màu cuối cùng.

    Sau khi đã viết shader cho sprite này, bắt phần hiện thực component MaskedSprite. Đây là phần khởi tạo component:

    bool MaskedSprite::init(const char* textureName, const char* maskedTextureName)
    {
    	if(!CCSprite::initWithFile(textureName))
    	{
    		return false;
    	}
    
    	_maskedTexture = CCTextureCache::sharedTextureCache()->addImage(
                                                            maskedTextureName);
    	_maskedTexture->retain();
    
    	CCGLProgram* pProgram = new CCGLProgram();
    	pProgram->initWithVertexShaderFilename("MaskedSprite.vert",
                                                               "MaskedSprite.frag");
    
    	setShaderProgram(pProgram);
    
    	pProgram->addAttribute(kCCAttributeNamePosition, kCCVertexAttrib_Position);
    	pProgram->addAttribute(kCCAttributeNameColor, kCCVertexAttrib_Color);
    	pProgram->addAttribute(kCCAttributeNameTexCoord, kCCVertexAttrib_TexCoords);
    
    	pProgram->link();
    	pProgram->updateUniforms();
    
    	_locTexture = glGetUniformLocation(pProgram->getProgram(), "u_texture");
    	_locMask = glGetUniformLocation(pProgram->getProgram(), "u_mask");
    
    	pProgram->release();
    
    	return true;
    }

    Ở phần khởi tạo này khởi tạo shader đã viết ở trên cho component và lấy giá trị 2 vị trí của 2 texture uniform (texture nền và texture làm mặt nạ). 2 vị trí này sẽ sử dụng cho bước render.

    Đây là phần render trong component:

    void MaskedSprite::draw()
    {
    	CC_NODE_DRAW_SETUP();
    
    	ccGLBlendFunc( m_sBlendFunc.src, m_sBlendFunc.dst );
    
    	glActiveTexture(GL_TEXTURE0);
    	glBindTexture( GL_TEXTURE_2D,  m_pobTexture->getName() );
    	glUniform1i(_locTexture, 0);
    
    	glActiveTexture(GL_TEXTURE1);
    	glBindTexture( GL_TEXTURE_2D,  _maskedTexture->getName() );
    	glUniform1i(_locMask, 1);
    
    
    	ccGLEnableVertexAttribs( kCCVertexAttribFlag_PosColorTex );
    
    	long offset = (long)&m_sQuad;
    
    #define kQuadSize sizeof(m_sQuad.bl)
    
    	// vertex
    	int diff = offsetof( ccV3F_C4B_T2F, vertices);
    	glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE,
                                        kQuadSize, (void*) (offset + diff));
    
    	// texCoods
    	diff = offsetof( ccV3F_C4B_T2F, texCoords);
    	glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE,
                                        kQuadSize, (void*)(offset + diff));
    
    	// color
    	diff = offsetof( ccV3F_C4B_T2F, colors);
    	glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE,
                                        kQuadSize, (void*)(offset + diff));
    
    	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    
    	CHECK_GL_ERROR_DEBUG();
    }
    • Dòng 3: thiết đặt program cho trạng thái hiện tại là program đã được khởi tạo ở trên.
    • Dòng 7-13: bind 2 texture nền và texture mặt nạ.
    • Dòng 16: enable các thuộc tính được dùng của các đỉnh (trong trường hợp này là thuộc tính vị trí, màu sắc, toạ độ của texture).
    • Dòng 18-35: vẽ component.

    Code

    Mã nguồn đầy đủ của component có thể xem tại đây: MaskedSprite.zip

    Cách dùng Component

    CCSize winSize = CCDirector::sharedDirector()->getWinSize();
    
    MaskedSprite* pSprite = MaskedSprite::create("HelloWorld.png",
                                                    "Mask.png");
    pSprite->setPosition(ccp(winSize.width/2.0f, winSize.height/2.0f));
    this->addChild(pSprite);
    0
    Lập Trình Game

    Lập Trình Game

    Kiến thức, kỹ thuật, kinh nghiệm lập trình game.

    Khi bạn nhấn vào liên kết sản phẩm do STDIO đề xuất và mua hàng, STDIO có thể nhận được hoa hồng. Điều này hỗ trợ STDIO tạo thêm nhiều nội dung hữu ích.. Tìm hiểu thêm.

    Đề xuất

    Giới Thiệu Về Sprite Trong Cocos2d-x 3.x.x
    Giới thiệu tổng quan về khái niệm cơ bản, một số cách dùng để khởi tạo ...
    Lập Trình Hiệu Ứng Trong Cocos2d-x 3.x.x
    Bài viết nằm trong loạt bài viết của chương trình Tự Học Cocos2d-x ...

    Khám phá

    Animation Trong Cocos2d-x 3.x.x
    Bài viết nằm trong loạt bài viết chương trình Tự Học Cocos2d-x 3.x.x. ...
    Xử Lý Sự Kiện Trong Cocos2d-x 3.x.x
    Bài viết nằm trong loạt bài viết chương trình Tự Học Cocos2d-x 3.x.x. ...
    Action Cho Sprite Trong Cocos2d-x 3.x.x
    Tìm hiểu về action của Sprite trong Cocos2d-x 3.x.x.
    Giới Thiệu về Scene trong Cocos2d-x 3.x.x
    Tìm hiểu về Scene và các thao tác trong Cocos2d-x 3.x.x.
    Sprite Sheet Trong Cocos2dx 3.x.x
    Giới thiệu khái niệm, tác dụng, cách tạo và sử dụng Sprite Sheets trong ...
    Làm Thế Nào Để Tạo Fixtures Cho Vật Có Hình Dạng Phức Tạp Trong Cocos2d-x?
    Hướng dẫn sử dụng phần mềm Physics Editor dùng để tạo Fixtures cho vật ...
    UI - Phần 1: Khái Niệm Và Một Số Đối Tượng Để Thiết Kế UI Trong Cocos2d-x 3.x.x
    Tìm hiểu về khái niệm UI và các đối tượng thiết kế UI trong Cocos2d-x ...
    Xử Lý Với File PLIST trong Cocos2d-x 3.x.x
    Giới thiệu những đặc điểm, cách xử lý và ứng dụng của file PLIST trong ...
    STDIO
    Trang chính
    Công ty TNHH STDIO

    30, Trịnh Đình Thảo, Hòa Thạnh, Tân Phú, Hồ Chí Minh
    +84 28.36205514 - +84 942.111912
    developer@stdio.vn

    383/1 Quang Trung, Phường 10, Quận Gò Vấp, Hồ Chí Minh
    Số giấy phép ĐKKD: 0311563559 do sở Kế hoạch và Đầu Tư TPHCM cấp ngày 23/02/2012

    ©STDIO, 2013 - 2020