『openframeworks』shader制作六边形马赛克效果

在天朝河蟹社会,许多影视作品中经常出现少儿不宜的片段,这时候有一个东西就少不了。没错,它就是马赛克!

以前弄过方块马赛克,圆形马赛克等,没有什么难度,最近看到苍蝇的研究,突然想能不能搞个六边形马赛克呢。

说着就动手!

首先看看六边形马赛克的结构,如下图:


我们要做的效果就是:让一张图片,分割成由六边形组成,让每个六边形中的颜色相同(直接取六边形中心点像素RGB较方便,我们这里采用的就是这种方法)。

将它进行分割,取每个六边形的中心点画出一个矩阵,如下:


如上图,画出很多长和宽比例为2:√3的的矩形阵。然后我们可以对每个点进行编号,如上图中,采用坐标系标记。

假如我们的屏幕的左上点为上图的(0,0)点,则屏幕上的任一点我们找到它所对应的那个矩形了。

假定我们设定的矩阵比例为2*LEN : √3*LEN,那么屏幕上的任意点(x, y)所对应的矩阵坐标为(int(x/(2*LEN)), int(y/(√3*LEN)))。

这些应该不难理解。

看图我们可以发现,每个矩阵中的点其实分为两半。如矩阵(0, 0)和矩阵(1, 1),分为左上和右下,而矩阵(1,0)和矩阵(0,1)则分为左下和右上两部分。

任一一个矩阵都由这两种布局组成。

如此,我们可以发现,只要知道是在哪个矩阵,然后计算它离矩阵两个对角点的距离那个较短,我们就能判断它是属于哪一个六边形的了。

这里需要注意的是:矩阵的横坐标和纵坐标都为奇数或者都为偶数时,要比较的点,即六边形中点分别为矩形左上点和右下点,否则为左下点和右上点。

我们只需要判断横纵坐标即可。

根据这些信息,我们写出碎片着色脚本如下:

#version 400
#extension GL_ARB_texture_rectangle : enable

uniform float len;
uniform sampler2DRect colorTex0;
void main (void){
	float TR = 0.866025f;
	float x = gl_TexCoord[0].x;
	float y = gl_TexCoord[0].y;
	int wx = int(x/1.5f/len);
	int wy = int(y/TR/len);
	vec2 v1, v2, vn;
	if(wx/2 * 2 == wx) {
		if(wy/2 * 2 == wy) {
				v1 = vec2(len*1.5f*wx, len*TR*wy);
				v2 = vec2(len*1.5f*(wx+1), len*TR*(wy+1));
			} else {
				v1 = vec2(len*1.5f*wx, len*TR*(wy+1));
				v2 = vec2(len*1.5f*(wx+1), len*TR*wy);
			}
		} else {
		if(wy/2 * 2 == wy) {
			v1 = vec2(len*1.5f*wx, len*TR*(wy+1));
			v2 = vec2(len*1.5f*(wx+1), len*TR*wy);
			} else {
				v1 = vec2(len*1.5f*wx, len*TR*wy);
				v2 = vec2(len*1.5f*(wx+1), len*TR*(wy+1));
			}
	}
	float s1 = sqrt( pow(v1.x-x, 2) + pow(v1.y-y, 2) );
	float s2 = sqrt( pow(v2.x-x, 2) + pow(v2.y-y, 2) );
	if(s1 < s2)
		vn = v1;
	else
		vn = v2;
	vec4  color = texture2DRect(colorTex0, vn);
	gl_FragColor = color;
}

其中,len为传入的六边形单边长度,我们可以在外面传递给shader。

里面的判断就是关于属于哪一个六边形的判断。

我们可以让len为固定值,以我的照片为例,效果如下:


当然,我们也可以实时改变len值,让六边形的变大变小:


是不是很炫,^_^.

下面为openframeworks中的主要代码:

#include "testApp.h"

//--------------------------------------------------------------
void testApp::setup(){
	img.loadImage("bg.jpg");

	fbo.allocate(640, 480);

	shader.load("hexagon.vert", "hexagon.frag");
	len = 20.0f;
	bAdd = false;
}

//--------------------------------------------------------------
void testApp::update(){
	if(len < 10.0f)
		bAdd = true;
	if(len > 20.0f)
		bAdd = false;
	len += bAdd ? (0.005f):(-0.005f);
}

//--------------------------------------------------------------
void testApp::draw(){
	ofEnableAlphaBlending();
	img.draw(0, 0, 640, 480);

	fbo.begin();
	img.draw(0, 0, 640, 480);
	fbo.end();

	shader.begin();
	shader.setUniform1f("len", len);
	shader.setUniformTexture("colorTex0", fbo.getTextureReference(), 0);
	fbo.draw(0, 0, 640, 480);
	shader.end();

	ofDisableAlphaBlending();
}

另外还有三角形马赛克效果

源码地址


OK,还是不错的吧,原来编程也能这么有趣呢。

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 20
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值