『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 : enableuniform 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;elsevn = 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,还是不错的吧,原来编程也能这么有趣呢。

旅游不在乎终点,而是在意途中的人和事还有那些美好的记忆和景色。

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

相关文章:

你感兴趣的文章:

标签云: