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

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

如下图:

我们可以发现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. java并发编程(五)正确使用volatile

    转载请注明出处:     volatile用处说明     在JDK1.2之前,Java的内存模型实现总是从主存(即共享内存)读取变量,是不需要进行特别的注意的.而随着JVM的成熟和优化,现在在多线程 ...

  2. iOS学习之六种传值方式

    iOS页面传值方式 应用于: 两个互动的界面:1)页面一跳转到页面二,页面一的textField的值传给页面二的label.2)A页面跳转到B页面,B页面再跳转回A页面(注册页面跟登录页面) 两个不互 ...

  3. sublime text3侧边栏主题不生效问题解决

    sublime text3主题插件: Seti_UI 插件安装: 在线安装:需要FQ window: ctrl+shift+p 找install package:之后搜索 Seti_UI 安装完成后需 ...

  4. android从应用到驱动之—camera(1)---程序调用流程[转]

    一.开篇 写博客还得写开篇介绍,可惜,这个不是我所擅长的.就按我自己的想法写吧. 话说camera模块,从上层到底层一共包含着这么几个部分: 1.apk------java语言 2.camera的ja ...

  5. 记录使用 Cake 进行构建并制作 nuget 包

    书接上一回(https://www.cnblogs.com/h82258652/p/4898983.html)?[手动狗头] 前段时间折腾了一下,总算是把我自己的图片缓存控件(https://gith ...

  6. day35

    今日内容: 1.进程间互相通信(IPC机制) 2.生产者消费者模型 3.线程理论 4.线程开启的两种方式 5.线程相关属性方法 6.守护线程 7.线程互斥锁 1.进程间相互通信(IPC机制) 主要是一 ...

  7. Linux操作系统中文件结构stat中st_size的说明以及对于文件中洞(Holes)的理解

    文件stat结构体中st_size成员 对于所有的文件类型,st_size成员对其中的普通文件.目录以及符号链接有实在的意义.其中,对于普通文件而言,st_size记录了该文件的实际大小:对于目录而言 ...

  8. &quot;iostat&quot; On Linux

    CPU是一台电脑的大脑.所有的处理命令都运行在上面.I/O(输入/输出)同样扮演了一个重要角色.硬盘用于提供数据给处理器并保存CPU处理过的数据.一种衡量处理器和I/O利用率的方法是使用iostat命 ...

  9. 【转】jquery checkbox勾选/取消勾选的诡异问题

    转:http://www.cnblogs.com/KeenLeung/p/3799895.html 第一次执行,没问题,但第二次执行就有问题了,选择不了 prop()和attr()区别: (来源:ht ...

  10. Python并发编程系列之多进程(multiprocessing)

    1 引言 本篇博文主要对Python中并发编程中的多进程相关内容展开详细介绍,Python进程主要在multiprocessing模块中,本博文以multiprocessing种Process类为中心 ...