不久前做了六边形马赛克的效果,很有意思,乘热打铁,弄了个三角形马赛克。

首先肯定是等边三角形,这样才能真正的无缝拼接。观察发现,三角形可以拼接成之前做个的六边形。

如下图:

我们可以发现6个三角形正好组成了一个六边形。

我们要判断一个点属于哪个三角形,必须先判断它属于那个六边形,这个在之前的博文中已经提到了。

OK,我们知道在那个六边形了,也就是我们知道了上面O点的坐标。我们开始想怎么判断它在哪个三角形。

嗯,我想大家都能想到,根据点与中心点O的夹角判断在那个三角形,调用atan就OK了:

float a = atan((x-O.x)/(y-O.y));//夹角

然后根据各自的角度就能判断是属于哪一个三角形的了,这里注意一下atan算出的范围是-180至180度,对应的数值是-PI至PI。

然后算出6个三角形的中心点坐标,属于哪一个三角形就去哪一个坐标点的像素值。

碎片着色器frag shader如下:

#version 400
#extension GL_ARB_texture_rectangle : enable uniform float len;
uniform sampler2DRect colorTex0;
void main (void){
float TR = 0.866025f;
float PI6 = 0.523599f; //PI/6
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 mid = texture2DRect(colorTex0, vn);
float a = atan((x-vn.x)/(y-vn.y));//夹角
vec2 area1 = vec2(vn.x, vn.y-len/TR/2);
vec2 area2 = vec2(vn.x+len/2, vn.y-len/TR/4);
vec2 area3 = vec2(vn.x+len/2, vn.y+len/TR/4);
vec2 area4 = vec2(vn.x, vn.y+len/TR/2);
vec2 area5 = vec2(vn.x-len/2, vn.y+len/TR/4);
vec2 area6 = vec2(vn.x-len/2, vn.y-len/TR/4);
if(a>=PI6 && a<PI6*3)
vn = area1;
else if(a>=PI6*3 && a<PI6*5)
vn = area2;
else if((a>=PI6*5 && a<=PI6*6) || (a<-PI6*5 && a>-PI6*6))
vn = area3;
else if(a<-PI6*3 && a>=-PI6*5)
vn = area4;
else if(a<=-PI6 && a>-PI6*3)
vn = area5;
else if(a>-PI6 && a<PI6)
vn = area6;
vec4 color = texture2DRect(colorTex0, vn);
gl_FragColor = color;
}

其中len为传入到shader中六边形的单边长,也是三角形的单边长。TR其实是√3/2。而PI6明显就是PI/6,对应的是30度。

其实核心思想就是判断属于哪个三角形。

效果如下:

同样的,实时改变len的值,图就能动起来:

依旧很炫,^_^.

openframeworks中主要代码:

#include "testApp.h"

//--------------------------------------------------------------
void testApp::setup(){
img.loadImage("bg.jpg"); fbo.allocate(640, 480); shader.load("triangle.vert", "triangle.frag");
len = 100.0f;
bAdd = false;
} //--------------------------------------------------------------
void testApp::update(){
if(len < 10.0f)
bAdd = true;
if(len > 100.0f)
bAdd = false;
len += bAdd ? (0.05f):(-0.05f);
} //--------------------------------------------------------------
void testApp::draw(){
ofEnableAlphaBlending(); 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制作三角形马赛克效果的更多相关文章

  1. pixijs shader 制作百叶窗效果

    pixijs shader 制作百叶窗效果 直接贴代码了 const app = new PIXI.Application({ transparent: true }); document.body. ...

  2. CSS制作三角形和按钮

    CSS制作三角形和按钮 用上一篇博文中关于边框样式的知识点,能制作出三角形和按钮. 我先说如何制作三角形吧,相信大家在平时逛网站的时候都会看到一些导航栏中的三角形吧,比如说: 网易首页的头部菜单栏中, ...

  3. CSS 制作三角形原理剖析

    使用css制作三角形其实原理很简单,下面一步步解析. 1.html代码如下 <div class="triangle"> </div> 2.CSS代码 .t ...

  4. [原创] 【2014.12.02更新网盘链接】基于EasySysprep4.1的 Windows 7 x86/x64 『视频』封装

    [原创] [2014.12.02更新网盘链接]基于EasySysprep4.1的 Windows 7 x86/x64 『视频』封装 joinlidong 发表于 2014-11-29 14:25:50 ...

  5. canva实践小实例 —— 马赛克效果

    前面给大家带来了操作像素的API,此时此刻,我觉得应该配以小实例来进行进一步的说明和演示,以便给大家带来更宽广的视野和灵感,你们看了我的那么多的文章,应该是懂我的风格,废话不多说,进入正题: 这次给大 ...

  6. 用css制作三角形

    用css制作三角形,主要是利用css元素给“盒模型”设置边框得到的. 上图,上边框和做边框,以及上边框和右边框的交合处,浏览器会按照直角的二分之一处绘制交合线.这是“盒模型”有宽和高时候的效果.我们假 ...

  7. [C#]『CountdownEvent』任务并行库使用小计

    System.Threading.CountdownEvent  是一个同步基元,它在收到一定次数的信号之后,将会解除对其等待线程的锁定. CountdownEvent  专门用于以下情况:您必须使用 ...

  8. 『转载』Debussy快速上手(Verdi相似)

    『转载』Debussy快速上手(Verdi相似) Debussy 是NOVAS Software, Inc(思源科技)发展的HDL Debug & Analysis tool,这套软体主要不是 ...

  9. 用border或者div制作三角形等图形

    一般情况下, 我们设置盒子的宽高度, 及上下左右边框, 具体代码如下: 通过上述代码,div的具体样式如下: 现在在上面基础上, 我们把div的宽高度都设为0时, 现在我们再次查看效果,如下图: 这时 ...

随机推荐

  1. 还是回文(dp)

    还是回文 时间限制:2000 ms  |  内存限制:65535 KB 难度:3 描述 判断回文串很简单,把字符串变成回文串也不难.现在我们增加点难度,给出一串字符(全部是小写字母),添加或删除一个字 ...

  2. 分享:json2.js源代码解读笔记

    1. 怎样理解"json" 首先应该意识到,json是一种数据转换格式,既然是个"格式",就是个抽象的东西.它不是js对象,也不是字符串,它仅仅是一种格式,一种 ...

  3. Java中的异常详解

    一.异常定义 阻止当前方法或作用域继续执行的问题,称为异常 二.异常分析      所有不正常类都继承Throwable类,这个类主要有两个子类Error类和Exception类.Error指系统错误 ...

  4. 以前学习cisco ccna 课程的时候做的笔记

    由于学习的专业是计算机网络技术,可是在上学的时候,并没有学习到多少网络知识,所以为了对得起学的专业,在06年工作的时候,在哈工大银河教育报了个ccna的班,两个星期的课程,每天上那么几个小时. 结果依 ...

  5. C语言宏定义技巧

    出处:http://blog.chinaunix.net/uid-14022540-id-2849095.html 1.宏中"#"和"##"的用法 一.一般用法 ...

  6. 关于页ASP.NET面布局

    关于页面布局,充分利用Table和分层   从接触ASP.NET到现在已经有一段时间了,起初总是嫌麻烦,想找捷径,凡是想当然,结果导致自己反而走了不少的弯路. 起初刚开始接触ASP.NET的时候,发现 ...

  7. java--异常处理总结

    [在程序中抛出异常] 在程序中抛出异常,一定要使用关键字throw. throw+异常实例对象. public class Demo2 { public static void main(String ...

  8. Mac OSX的开机启动配置

    Login Items Mac OSX的当前用户成功登录后启动的程序,该类别的启动项配置文件存放在~/Library/Preferences/com.apple.loginitems.plist,所以 ...

  9. MySQL中select * for update锁表的问题(转)

    由于InnoDB预设是Row-Level Lock,所以只有「明确」的指定主键,MySQL才会执行Row lock (只锁住被选取的资料例) ,否则MySQL将会执行Table Lock (将整个资料 ...

  10. Ubuntu一些配置和技巧

    安装google-chrome wget https://dl.google.com/linux/direct/google-chrome-stable_current_i386.deb sudo d ...