不描边
cocos2d-x\cocos\renderer\ccShader_Label_normal
attribute vec4 a_position;
attribute vec2 a_texCoord;
attribute vec4 a_color;
varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
void main()
{
gl_Position = CC_MVPMatrix * a_position;
v_fragmentColor = a_color;
v_texCoord = a_texCoord;
}
varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
uniform vec4 u_textColor;
void main()
{
// rgb来自u_textColor,是因为字符位图是灰度的,最终被视为Alpha了
gl_FragColor = v_fragmentColor * vec4(u_textColor.rgb,// RGB from uniform
u_textColor.a * texture2D(CC_Texture0, v_texCoord).a// A from texture & uniform
);
}
位图是灰度的
描边的shader
2dx中的描边效果是通过freetype生成的描边纹理和非描边纹理,
描边label的pixel format为AI88
cocos对应代码,对于OpenGL来说,它是GL_LUMINANCE_ALPHA
,即一个像素是由2个通道[luminance,alpha]
组成。
上图的2个纹理数据,会分别存储在luminance和alpha中,对应的cocos代码:
- luminance是带描边的纹理数据
- alpha是不带描边的纹理数据
label的渲染逻辑为:
描边label使用的渲染纹理上图中的结果正好是和这个对应的:
- 1是都不在描边纹理和非描边纹理范围,所以lum=0,alpha=0
- 2是描边纹理的范围,所以lum=255,不在非描边纹理范围,所以alpha=0
- 3是描边纹理和非描边纹理的交集,所以lum=alpha=255
另外,位图数据在轮廓边缘的值是介于0~255的
- 4是不带描边的轮廓数据,它的alpha不是255,
- 5是带描边的轮廓数据,它的Lum不是255
在shader里面,边缘是通过纹理的alpha识别的,因为位图轮廓是灰度的
GL_LUMINANCE_ALPHA的[L,A]数据最终在着色器采样后,转换为RGBA为[L,L,L,A]
此时的alpha刚好为非描边纹理的轮廓边缘
varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
uniform vec4 u_effectColor;
uniform vec4 u_textColor;
uniform int u_effectType;
void main()
{
vec4 sample = texture2D(CC_Texture0, v_texCoord);
// fontAlpha == 1 means the area of solid text (without edge)
// fontAlpha == 0 means the area outside text, including outline area
// fontAlpha == (0, 1) means the edge of text
float fontAlpha = sample.a;
// outlineAlpha == 1 means the area of 'solid text' and 'solid outline'
// outlineAlpha == 0 means the transparent area outside text and outline
// outlineAlpha == (0, 1) means the edge of outline
float outlineAlpha = sample.r;
if (u_effectType == 0) // draw text
{
gl_FragColor = v_fragmentColor * vec4(u_textColor.rgb, u_textColor.a * fontAlpha);
}
else if (u_effectType == 1) // draw outline
{
// multipy (1.0 - fontAlpha) to make the inner edge of outline smoother and make the text itself transparent.
gl_FragColor = v_fragmentColor * vec4(u_effectColor.rgb, u_effectColor.a * outlineAlpha * (1.0 - fontAlpha));
}
else // draw shadow
{
gl_FragColor = v_fragmentColor * vec4(u_effectColor.rgb, u_effectColor.a * outlineAlpha);
}
}
第一次:绘制outline
gl_FragColor = v_fragmentColor * vec4(u_effectColor.rgb, u_effectColor.a * L* (1.0 - A));
区域1因为L=A=0,alpha=effectColor.a * 0 * (1-0)=0
区域2因为L=255,A=0,alpha=effectColor.a * 1 * (1-0)=effectColor.a
区域3因为L=255,A=255,alpha=effectColor.a * 1 * (1-1) = 0
这样绘制出来的效果 = 描边纹理 - 非描边纹理
第二次:绘制字符
先重置effectType
gl_FragColor = v_fragmentColor * vec4(u_textColor.rgb, u_textColor.a * A);
只有A参与计算,那么也就只有区域3和4会显示出来了
PositionTextureColor_noMVP
ccShader_PositionTextureColor_noMVP.frag
attribute vec4 a_position;
attribute vec2 a_texCoord;
attribute vec4 a_color;
varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
void main()
{
gl_Position = CC_PMatrix * a_position;
v_fragmentColor = a_color;
v_texCoord = a_texCoord;
}
varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
void main()
{
gl_FragColor = v_fragmentColor * texture2D(CC_Texture0, v_texCoord);
}
a_color来自node.color,字符纹理变成白色即可
PositionTexture
ccShader_PositionTexture.vert
attribute vec4 a_position;
attribute vec2 a_texCoord;
#ifdef GL_ES
varying mediump vec2 v_texCoord;
#else
varying vec2 v_texCoord;
#endif
void main()
{
gl_Position = CC_MVPMatrix * a_position;
v_texCoord = a_texCoord;
}
ccShader_PositionTexture.frag
#ifdef GL_ES
precision lowp float;
#endif
varying vec2 v_texCoord;
void main()
{
gl_FragColor = texture2D(CC_Texture0, v_texCoord);
}
矩阵的源头
// 单位矩阵:相当于数的乘法中的1
const Mat4 Mat4::IDENTITY = Mat4(
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f);
void GLView::renderScene(Scene* scene, Renderer* renderer){
scene->render(renderer, Mat4::IDENTITY,nullptr);
}
Label::onDraw(const Mat4& transform)
网友评论