cocos 一个描边shader

本文介绍了一种通过OpenGL ES Shader实现描边效果的方法。该方法避免了使用循环,并通过检查不同角度上的像素透明度来确定描边的位置。此外,还提供了如何在不同设备上设置描边宽度的具体代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考帖子:http://blog.youkuaiyun.com/u011281572/article/details/44999609

 优化了效率,

shader:

varying vec4 v_fragmentColor; // vertex shader传入,setColor设置的颜色
varying vec2 v_texCoord; // 纹理坐标
uniform vec2 outlineSize; // 描边宽度,以像素为单位
uniform vec3 outlineColor; // 描边颜色
uniform vec3 foregroundColor; // 主要用于字体,可传可不传,不传默认为白色
// 判断在这个角度上距离为outlineSize那一点是不是透明
int getIsStrokeWithAngel(float cosangel, float sinangel)
{
	int stroke = 0;
	float a = texture2D(CC_Texture0, vec2(v_texCoord.x + outlineSize.x * cosangel, v_texCoord.y + outlineSize.y * sinangel)).a; // 这句比较难懂,outlineSize * cos(rad)可以理解为在x轴上投影,除以textureSize.x是因为texture2D接收的是一个0~1的纹理坐标,而不是像素坐标
	if (a >= 0.5)// 我把alpha值大于0.5都视为不透明,小于0.5都视为透明
	{
		stroke = 1;
	}
	return stroke;
}

void main()
{
	vec4 myC = texture2D(CC_Texture0, vec2(v_texCoord.x, v_texCoord.y)); // 正在处理的这个像素点的颜色
	myC.rgb *= foregroundColor;
	if (myC.a >= 0.5) // 不透明,不管,直接返回
	{
		gl_FragColor = v_fragmentColor * myC;
		return;
	}
	// 这里肯定有朋友会问,一个for循环就搞定啦,怎么这么麻烦!其实我一开始也是用for的,但后来在安卓某些机型(如小米4)会直接崩溃,查找资料发现OpenGL es并不是很支持循环,while和for都不要用
	int strokeCount = 0;
	strokeCount += getIsStrokeWithAngel( 1.0, 0.0);//0
	strokeCount += getIsStrokeWithAngel( 0.9659258262, 0.2588190451);//15
	strokeCount += getIsStrokeWithAngel( 0.8660254037, 0.5);//30
	strokeCount += getIsStrokeWithAngel( 0.7071067811, 0.7071067811);//45
	strokeCount += getIsStrokeWithAngel( 0.5, 0.8660254037);//60
	strokeCount += getIsStrokeWithAngel( 0.2588190451, 0.9659258262);//75
	strokeCount += getIsStrokeWithAngel( 0.0, 1.0);//90
	strokeCount += getIsStrokeWithAngel(-0.2588190451, 0.9659258262);//105
	strokeCount += getIsStrokeWithAngel(-0.5, 0.8660254037);//120
	strokeCount += getIsStrokeWithAngel(-0.7071067811, 0.7071067811);//135
	strokeCount += getIsStrokeWithAngel(-0.8660254037, 0.5);//150
	strokeCount += getIsStrokeWithAngel(-0.9659258262, 0.2588190451);//165
	strokeCount += getIsStrokeWithAngel(-1.0, 0.0);//180
	strokeCount += getIsStrokeWithAngel(-0.9659258262, -0.2588190451);//195
	strokeCount += getIsStrokeWithAngel(-0.8660254037, -0.5);//210
	strokeCount += getIsStrokeWithAngel(-0.7071067811, -0.7071067811);//225
	strokeCount += getIsStrokeWithAngel(-0.5, -0.8660254037);//240
	strokeCount += getIsStrokeWithAngel(-0.2588190451, -0.9659258262);//255
	strokeCount += getIsStrokeWithAngel(0.0, -1.0);//270
	strokeCount += getIsStrokeWithAngel(0.2588190451, -0.9659258262);//285
	strokeCount += getIsStrokeWithAngel(0.5, -0.8660254037);//300
	strokeCount += getIsStrokeWithAngel(0.7071067811, -0.7071067811);//315
	strokeCount += getIsStrokeWithAngel(0.8660254037, -0.5);//330
	strokeCount += getIsStrokeWithAngel(0.9659258262, -0.2588190451);//345

	if (strokeCount > 0) // 四周围至少有一个点是不透明的,这个点要设成描边颜色
	{
		myC.rgb = outlineColor;
		myC.a = 1.0;
	}

	gl_FragColor = v_fragmentColor * myC;
}




使用代码:

local glProgramState = node:getGLProgramState();	
local texSize = node:getTexture():getContentSize();
if node:isTextureRectRotated() then
	glProgramState:setUniformVec2("outlineSize", cc.p(6 / texSize.height, 6 / texSize.width));
else
	glProgramState:setUniformVec2("outlineSize", cc.p(6 / texSize.width, 6 / texSize.height));
end

glProgramState:setUniformVec3("outlineColor", cc.vec3(0,0,0));
glProgramState:setUniformVec3("foregroundColor", cc.vec3(1,1,1)); 




                
### 在 Cocos Creator 3.0 中实现文本或精灵的描边效果 #### 使用自定义 Shader 实现描边效果 对于希望在 Cocos Creator 3.0 中为文本或精灵添加描边效果的需求,可以利用自定义Shader来达成这一目标。通过编写特定的着色器代码,能够有效地控制渲染过程中的颜色混合方式,从而创建出理想的描边视觉效果[^3]。 下面是一个简单的例子展示如何构建一个具有描边特性的文字组件: ```glsl // 描边材质脚本 (stroke-material.glsl) precision mediump float; uniform vec4 u_color; uniform sampler2D u_mainTex; varying vec2 v_uv; void main() { // 原始纹理采样 vec4 originalColor = texture2D(u_mainTex, v_uv); // 计算边缘检测因子 float edgeFactor = step(0.5, length(vec2(dFdx(v_uv.x), dFdy(v_uv.y)))); // 应用描边逻辑:当像素位于边界时应用不同的颜色 gl_FragColor = mix(originalColor * u_color, vec4(1., 0., 0., 1.), edgeFactor); } ``` 此片段展示了基本原理,在实际项目中可能还需要调整参数以适应不同场景下的需求。为了使上述代码生效,需将其关联至相应的UI元素上作为其使用的材质资源之一。 另一种更灵活的方法是借助第三方插件如 Spine 来间接完成类似的任务。虽然 Spine 主要用于骨骼动画制作,但它所提供的挂点机制允许开发者向现有角色模型附加额的对象,这同样适用于创造独特的装饰性特征,例如围绕对象周围的轮廓线[^2]。 然而值得注意的是,由于版本差异的存在,某些特性可能会有所变化;因此建议查阅官方文档确认最新API接口以及最佳实践指南[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值