Search…

Tạo Hiệu Ứng Grayscale Cho Sprite (Cocos2d-x 2.x.x)

27/09/20203 min read
Hướng dẫn cách tạo hiệu ứng grayscale để hiển thị những mode chơi chưa được kích hoạt với Cocos2d-x

Phân tích

Ảnh grayscale, hay còn gọi là ảnh trắng đen, là ảnh chỉ có 1 kênh màu duy nhất. Mỗi pixel là 1 mẩu đơn giản, chứa thông tin cường độ của pixel đó. Giá trị lớn nhất tương ứng với pixel màu trắng và giá trị nhỏ nhất tương ứng với pixel màu đen. Cường độ này có giá trị thường được chọn trong khoảng từ 0 đến 1 hoặc từ 0 đến 255.

Theo nghiên cứu, mắt người nhạy cảm nhất với màu xanh lá cây và ít nhạy cảm với màu xanh dương nên có thể áp dụng công thức sau đây để tính toán cường độ xám của ảnh grayscale.

GrayFactor = 0.2126*R + 0.7152*G + 0.0722*B

Trong đó:

  • R là cường độ của kênh màu đỏ.
  • G là cường độ của kênh xanh lá cây.
  • B là cường độ của kênh xanh dương.

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

Vertex shader giữ giống như shader của Cocos2d-x Vì grayscale sprite chỉ khác sprite thông thường trong Cocos2d-x ở giai đoạn tính toán màu cho từng fragment nên sẽ tận dụng những phần có sẵn của Cocos2d-x và viết thêm fragment shader.

Để hoàn thành bài viết này, chỉ cần sử dụng hình ảnh HelloWorld.png được đính kèm trong dự án mẫu 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;

void main()
{
	vec4 texColor = texture2D(u_texture, v_texCoord);
	float grayscaleFactor = 0.2126*texColor.r + 0.7152*texColor.g + 0.0722*texColor.b;
	vec4 finalColor = vec4(grayscaleFactor, grayscaleFactor,
				grayscaleFactor, texColor.a);

	gl_FragColor = v_fragmentColor * finalColor;
}
  • Điểm mấu chốt của shader này nằm ở dòng 12. Tại dòng này đã áp dụng công thức đã được nghiên cứu đã nêu ở trên để tính toán cường độ xám của pixel màu.
  • Tại dòng 13, chọn cường độ xám trên làm giá trị cho các kênh màu đỏ, xanh lá cây, xanh dương trong màu được tạo ra.

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

bool GrayScaleSprite::init(const char *textureName)
{
	if(!CCSprite::initWithFile(textureName))
	{
		return false;
	}

	CCGLProgram* pProgram = new CCGLProgram();
	pProgram->initWithVertexShaderFilename("GrayScaleSprite.vert",
						​"GrayScaleSprite.frag");

	setShaderProgram(pProgram);

	pProgram->addAttribute(kCCAttributeNamePosition, kCCVertexAttrib_Position);
	pProgram->addAttribute(kCCAttributeNameColor, kCCVertexAttrib_Color);
	pProgram->addAttribute(kCCAttributeNameTexCoord, kCCVertexAttrib_TexCoords);

	pProgram->link();
	pProgram->updateUniforms();

	pProgram->release();

	return true;
}

Ở đây, dùng lại hàm khởi tạo với texture của CCSprite và viết thêm phần khởi tạo shader cho component.

Phần render của component hoàn toàn giống với của CCSprite nên không cần viết lại, Cocos2d-x sẽ tự liên kết component với shader đã viết thêm.

Code 

Mã nguồn đầy đủ của component: GrayScaleSprite.zip

Cách dùng Component

CCSize winSize = CCDirector::sharedDirector()->getWinSize();

GrayScaleSprite* pSprite = GrayScaleSprite::create("HelloWorld.png");
pSprite->setPosition(ccp(winSize.width/2.0f, winSize.height/2.0f));
this->addChild(pSprite);
IO Stream

IO Stream Co., Ltd

30 Trinh Dinh Thao, Hoa Thanh ward, Tan Phu district, Ho Chi Minh city, Vietnam
+84 28 22 00 11 12
developer@iostream.co

383/1 Quang Trung, ward 10, Go Vap district, Ho Chi Minh city
Business license number: 0311563559 issued by the Department of Planning and Investment of Ho Chi Minh City on February 23, 2012

©IO Stream, 2013 - 2024