GLSL/C++ 实现滤镜效果

本文介绍了如何使用GLSL和C++实现图像滤镜效果,包括浮雕、马赛克、锐化模糊、描边和伪HDR/Blow效果。通过滤波器概念和模板操作,展示了图像平滑、边缘检测和亮度调整的原理及代码实现,同时也探讨了水彩画效果的模拟方法。
摘要由CSDN通过智能技术生成

入门效果之浮雕

"浮雕"图象效果是指图像的前景前向凸出背景。常见于一些纪念碑的雕刻上,要实现浮雕其实非常简单。我们把图象的一个象素和左上方的象素进行求差运算,并加上一个灰度。这个灰度就是表示背景颜色。这里我们设置这个插值为128 (图象RGB的值是0-255)。同时,我们还应该把这两个颜色的差值转换为亮度信息.否则浮雕图像会出现彩色。

    "precision mediump float;      \n"
	"varying vec2 v_texCoord;      \n"
	"uniform sampler2D s_baseMap;     \n"
	"uniform vec2 TexSize;            \n"
	"void main()                 \n"
	"{                             \n"
	"   vec2 tex =v_texCoord;   \n"
	"	vec2 upLeftUV = vec2(tex.x-1.0/TexSize.x,tex.y-1.0/TexSize.y);           \n"
	"	vec4 curColor = texture2D(s_baseMap,v_texCoord);                           \n"
	"	vec4 upLeftColor = texture2D(s_baseMap,upLeftUV);                  \n"
	"	vec4 delColor = curColor - upLeftColor;                           \n"
	"	float h = 0.3*delColor.x + 0.59*delColor.y + 0.11*delColor.z;                  \n"
	"   vec4 bkColor = vec4(0.5, 0.5, 0.5, 1.0);                   \n"
	"	gl_FragColor = vec4(h,h,h,0.0) +bkColor;                             \n"
	"}                           \n";

C++版

void relief(int x,int y,BYTE *pre,BYTE *now,int Stride,int index){
	int upperleft;
	upperleft=(y-1)*Stride+4*(x-1);
	Vec4 Pixel,NowPixel;
	NowPixel.SetPixel(pre,index);
	Pixel.SetPixel(pre,upperleft);
	Pixel=NowPixel-Pixel;
	BeGray(Pixel);
	Pixel.GetPixelToNow(now,index);
}

   


入门效果之马赛克

接下来我们完成一个更加常见的效果—马赛克.图片的马赛克就是把图片的一个相当大小的区域用同一个点的颜色来表示.可以认为是大规模的降低图像的分辨率,而让图像的一些细节隐藏起来, 比如电视中要秀一下某个罪犯的身材,却又不能展示他的脸,这个时候我们就可以给他的脸加一个马赛克.

用HLSL代码实现马赛克是非常简单的,但是同样的,我们需要一些额外的步骤,第一步就是先把纹理坐标转换成图像实际大小的整数坐标.接下来,我们要把图像这个坐标量化---比如马赛克块的大小是8x8象素。那么我们可以用下列方法来得到马赛克后的图像采样值,假设[x.y]为图像的整数坐标:

[x,y]mosaic = [ int(x/8)*8 , int(y/8)*8].

    "precision mediump float;    \n"
	"varying vec2 v_texCoord;    \n"
	"uniform sampler2D s_baseMap;\n"
	"uniform vec2 TexSize;       \n"
	"vec2 mosaicSize = vec2(8,8);\n"
	"void main()                 \n"
	"{                           \n"
	"	vec2 intXY = vec2(v_texCoord.x*TexSize.x, v_texCoord.y*TexSize.y);   \n"
	"	vec2 XYMosaic = vec2(floor(intXY.x/mosaicSize.x)*mosaicSize.x,floor(intXY.y/mosaicSize.y)*mosaicSize.y);  \n"
	"	vec2 UVMosaic = vec2(XYMosaic.x/TexSize.x,XYMosaic.y/TexSize.y);     \n"
	"	vec4 baseMap = texture2D(s_baseMap,UVMosaic);                        \n"
	"	gl_FragColor = baseMap;                                              \n"
	"}                                                                       \n";

C++ 版

void Mosaic(int x,int y,BYTE *pre,BYTE *now,int Stride,int index){
	Vec4 Pixel,Pixel_UpperLeft;
	Pixel.SetPixel(pre,index);
	if (x%8==0&&y%8==0)
	{
		Pixel.GetPixelToNow(now,index);
	} 
	else
	{
		int tmpX,tmpY;
		tmpX=x/8*8;
		tmpY=y/8*8;
		int index_UpperLeft;
		index_UpperLeft=tmpY*Stride+4*(tmpX);
		Pixel_UpperLeft.SetPixel(pre,index_UpperLeft);
		Pixel_UpperLeft.GetPixelToNow(now,index);
	}
}



读者可能会发现这个马赛克太普通了,确实它不够新颖,下面我们来改良一下,我们希望达到这样一个效果:马赛克区域不是方的,而是圆的,圆形区域以外,我们用图像原来的颜色覆盖。这样我们需要改变一下代码。

首先求出原来马赛克区域的正中心(原来是左上角):然后计算图像采样点到这个中心的距离,如果在马赛克圆内,就用区域的中心颜色,否则就用原来的颜色。改良后的代码如下,这里我们把马赛克区域大小调节成16x16。这样效果更明显。

    "precision highp float;            \n"
	"varying vec2 v_texCoord;            \n"
	"uniform sampler2D s_baseMap;        \n"
	"uniform vec2 TexSize;               \n"
	"vec2 mosaicSize = vec2(8,8);      \n"
	"void main()                         \n"
	"{                                   \n"
	"	vec2 intXY = vec2(v_texCoord.x*TexSize.x, v_texCoord.y*TexSize.y);    \n"
	"	vec2 XYMosaic = vec2(floor(intXY.x/mosaicSize.x)*mosaicSize.x,floor(intXY.y/mosaicSize.y)*mosaicSize.y) + 0.5*mosaicSize; \n"
	"	vec2 delXY = XYMosaic - intXY;   \n"
	"	float delL = length(delXY);      \n"
	"	vec2 UVMosaic = vec2(XYMosaic.x/TexSize.x,XYMosaic.y/TexSize.y); \n"
	"	vec4 _finalColor;                \n"
	"	if(delL< 0.5*mosaicSize.x)       \n"
	"		_finalColor = texture2D(s_baseMap,UVMosaic);  \n"
	"	else                             \n"
	"		_finalColor = texture2D(s_baseMap,v_texCoord);  \n"
	"	gl_FragColor = _finalColor;      \n"
	"}                                   \n"  ;

C++版

void Mosaic_Point(int x,int y,BYTE *pre,BYTE *now,int Stride,int index){
	Vec4 Pixel,Pixel_UpperLeft;
	Pixel.SetPixel(pre,index);
	int i,j;
	i=x%8;
	j=y%8;
	do
  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值