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

原创 2013年12月03日 17:41:50

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

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

说着就动手!

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


我们要做的效果就是:让一张图片,分割成由六边形组成,让每个六边形中的颜色相同(直接取六边形中心点像素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,还是不错的吧,原来编程也能这么有趣呢。

相关文章推荐

Shader特效——“马赛克”的实现【GLSL】

”圆形” 效果图: uniform sampler2D Texture0; const vec2 texSize = vec2(640., 640.); const vec2 mosaicSize...

UnityShader实例12:屏幕特效之马赛克(Mosaic)材质

马赛克(Mosaic)材质

Unity中使用MeshFilter来制作六边形属性

记得以前见过最多的六遍型属性显示就是再实况,NBA中,球员对比的时候特别清晰,前段时间项目中也需要做一个类似的属性对比,所以写出来一个简化版做记录和分享。 直接看代码 using UnityEngin...

Unity3D 实现六角形花纹效果

今天为大家分享一下,如何做一个六角形花纹效果的小Demo。     欢迎加我的学习交流群: 575561285          好吧!废话不多讲,我直接上图操作!     1.新建一...

『openframeworks』动物眼中的你-shader初试

最近要做一个关于动物眼中的世界的案例,也就演示动物眼中的世界是怎么样的。 考察了一些资料,发现已经有人做过了,看来人类的创意真是无处不在啊。。 先来张它们眼中的世界图谱吧。 这边我打算有of中的s...

使用openframeworks无需配置学习新版本opengl

因为有学弟问了怎么学习新版本的opengl更好,特别是配合第八版红宝书 这里使用的是openframeworks0.84  之所以使用这个版本而不是0.9以上是因为这个版本还支持codeblocks...

『openframeworks』shader制作三角形马赛克效果

openframeworks利用shader制作三角形马赛克效果。

教你如何制作漂亮的马赛克效果

[PhotoShop]【教程】教你如何制作漂亮的马赛克效果 通常我们会在电视上,网页上,看见各种各样的带有马赛克的图片,是不是很想知道它是怎么做的呢?今天你就能做出漂亮的马赛克图片,其实操作步骤非常...

图像处理之六边形网格分割效果

图像处理之SuperPixel算法的简单应用,特效六边形网格
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:『openframeworks』shader制作六边形马赛克效果
举报原因:
原因补充:

(最多只允许输入30个字)