Wang Tile的Shader简易实现
在使用大面积的平铺纹理时,会导致重复感较强的贴图呈现在画面中。我们可以通过许多方法进行优化,WangTile就是其中一种。
WangTile(王浩瓷砖)方法通过对每条边标记颜色,并在平铺时将相同颜色的边拼接在一起,最终铺满整个平面。
参考《GPU Gems2》中的做法,但这里使用一组预先设定好的可循环组合值,以及一个4x4的瓷砖纹理。
4x4纹理图:

假设y坐标朝向为从下到上,x坐标朝向为从左到右,则索引(0,0)表示数字16的色块,索引(2,3)表示数字3的色块,以此类推。
这里首先配置好可循环的组合,他们的x轴和y轴不同的序列为:
X_seq: 1, 2, 2, 3, 0, 1, 3, 1, 2, 3, 0, 0, 1, 2, 3, 1, 2, 3, 1, 2, 3
Y_seq: 0, 1, 2, 3, 0, 1, 3, 1, 2, 3, 1, 2, 2, 2, 3, 0, 1, 3, 0, 1, 3
这个序列可以给不同的瓷砖贴图重复使用,我们把这个作为数组传入Shader,数组长度写死为21,其Shader如下:
Shader "Unlit/WangTileTesGPU"
{
Properties
{
_TileTex("Tile Texture", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100 Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc" struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
}; struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
}; sampler2D _TileTex; uniform float _WangTile_X_Seq[21];
uniform float _WangTile_Y_Seq[21]; #define MAIN_TEX_TILE_SIZE half2(21, 21)
#define TILE_TEX_SIZE half2(4, 4) v2f vert (appdata v)
{
v2f o = (v2f)0;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
} fixed4 SampleTile(half2 uv, half2 index, half2 mainTexTileTexSize, half2 tileTexSize)
{
float xIndex = _WangTile_X_Seq[index.x % 21] / tileTexSize.x;
float yIndex = _WangTile_Y_Seq[index.y % 21] / tileTexSize.y; half2 large_uv = frac(uv * mainTexTileTexSize);
half2 sub_uv = large_uv / tileTexSize; return tex2D(_TileTex, half2(xIndex, yIndex) + sub_uv, ddx(uv), ddy(uv));
//使用ddx,ddy参数去除接缝问题
} fixed4 frag (v2f i) : SV_Target
{
half2 sub_uv_index = floor(i.uv * MAIN_TEX_TILE_SIZE);//Index: 1,2,3,4... return SampleTile(i.uv, sub_uv_index, MAIN_TEX_TILE_SIZE, TILE_TEX_SIZE);
}
ENDCG
}
}
}
传入数组的csharp脚本如下:
public class WangTileGPU : MonoBehaviour
{
public Material mat; void Start()
{
float[] index_x_loop = new float[] { 1, 2, 2, 3, 0, 1, 3, 1, 2, 3, 0, 0, 1, 2, 3, 1, 2, 3, 1, 2, 3 };
float[] index_y_loop = new float[] { 0, 1, 2, 3, 0, 1, 3, 1, 2, 3, 1, 2, 2, 2, 3, 0, 1, 3, 0, 1, 3 }; mat.SetFloatArray("_WangTile_X_Seq", index_x_loop);
mat.SetFloatArray("_WangTile_Y_Seq", index_y_loop);
}
}
最终效果:

带贴图的效果(未做连续处理):

Wang Tile的Shader简易实现的更多相关文章
- Stage3d 由浅到深理解AGAL的管线vertex shader和fragment shader || 简易教程 学习心得 AGAL 非常非常好的入门文章
Everyday Stage3D (一) Everyday Stage3D (二) Triangle Everyday Stage3D (三) AGAL的基本概念 Everyday Stage3D ( ...
- 基于OpenGL编写一个简易的2D渲染框架-09 重构渲染器-Shader
Shader 只是进行一些简单的封装,主要功能: 1.编译着色程序 2.绑定 Uniform 数据 3.根据着色程序的顶点属性传递顶点数据到 GPU 着色程序的编译 GLuint Shader::cr ...
- 关于着色器LinearGradient的使用
LinearGradient我们可以将之译为线型渐变.线型渲染等,译成什么不重要,重要的是它的显示效果是什么样子,今天我们就一起来看看. 先来看看LinearGradient的构造方法: /** Cr ...
- Android Paint、Canvas、Matrix使用讲解(一、Paint)
http://blog.csdn.net/tianjian4592/article/details/44336949 好了,前面主要讲了Animation,Animator 的使用,以及桌面火箭效果和 ...
- Paint、Canvas、Matrix使用解说(一、Paint)
username=tianjian4592">我正在參加 CSDN 2015博客之星评选 感恩分享活动,假设认为文章还不错,请投个票鼓舞下吧:http://vote.blog.csdn ...
- 自定义View实战
PS:上一篇从0开始学自定义View有博友给我留言说要看实战,今天我特意写了几个例子,供大家参考,所画的图案加上动画看着确实让人舒服,喜欢的博友可以直接拿到自己的项目中去使用,由于我这个写的是demo ...
- opengl之vsh、fsh简易介绍+cocos2dx 3.0 shader 变灰
认识着色器 理解OpenGL渲染管线,对于学习OpenGL非常重要.下面是OpenGL渲染管线的示意图:(图中淡蓝色区域是可以编程的阶段) 此图是从wiki中拿过来的,OpenGL的渲染管线主要包括: ...
- 【Unity Shader】(十) ------ UV动画原理及简易实现
笔者使用的是 Unity 2018.2.0f2 + VS2017,建议读者使用与 Unity 2018 相近的版本,避免一些因为版本不一致而出现的问题. [Unity Shader](三) ----- ...
- libgdx自制简易版Don't Touch The White Tile
Don't Toutch The White说来也奇快,本来没什么难的,但是在欧美ios榜上却雄踞榜首好长时间.即使是在国内,也很火,还真是想不通,谁能解释下,难道真是所谓的抓住了用户的G点,或是这些 ...
- metal tile shader
刚发现了个问题 tileshader的memory不需要和attachement对应 imageblock被tileshader读写 fragmentshader也可以写imageblock 还可以正 ...
随机推荐
- 基于Java NIO 写的一个简单版 Netty 服务端
A Simple Netty Based On JAVA NIO 基于Java NIO 写的一个简单版 Netty 服务端 前置知识 NIO NIO 一般指 同步非阻塞 IO,同样用于**描述程序访问 ...
- JVM—对象的创建流程与内存分配
JVM-对象的创建流程与内存分配 创建流程 对象创建的流程图如下: 对象的内存分配方式 内存分配的方式有两种: 指针碰撞(Bump the Pointer) 空闲列表(Free List) 分配方式 ...
- Go 语言中结构体的使用和示例
结构体(简称struct)用于创建不同数据类型的成员集合,放入一个单一的变量中.虽然数组用于将相同数据类型的多个值存储在单一变量中,但结构体用于将不同数据类型的多个值存储在单一变量中.结构体对于将数据 ...
- 【Kotlin】扩展属性、扩展函数
1 类的扩展 Kotlin 提供了扩展类或接口的操作,而无需通过类继承或使用装饰器等设计模式,来为某个类添加一些额外的属性或函数,我们只需要通过一个被称为扩展的特殊声明来完成.通过这种机制,我们可 ...
- 【开发者说】XstoryMaker快速书写剧本场景动画
原文:https://mp.weixin.qq.com/s/63V0dfD2IufbX92JeD-G_A,点击链接查看更多技术内容. [开发者说]栏目是为HarmonyOS开发者提供的展示和分享平台, ...
- k8s之Pod
什么是Pod 通俗的来讲就是以pause为基础容器,其它容器共享pause容器的网络名称空间.主机名以及进程间通信,组成的一个逻辑的容器集合. • Kubernetes Pod是Kubernetes的 ...
- 第十三篇:HTML和CSS入门
一.HTML本质以及在WEB程序中的作用 1.一套规则,浏览器认识的规则. 2.开发者: 学习html规则 开发后台程序 - 写html文件(充当模板的作用) - 数据库获取数据,然后替换到html文 ...
- mmcls/mmdet模型部署至 TorchServe
mmcls/mmdet模型部署至 TorchServe 官方教程:模型部署至 TorchServe - MMClassification 0.23.2 文档 接口说明: serve/inference ...
- React中的setState执行机制
一.是什么 一个组件的显示形态可以由数据状态和外部参数所决定,而数据状态就是state 当需要修改里面的值的状态需要通过调用setState来改变,从而达到更新组件内部数据的作用 如下例子: impo ...
- Django框架——路由分发、名称空间、虚拟环境、视图层三板斧、JsonResponse对象、request获取文件、FBV与CBV、CBV源码剖析、模版层
路由分发 # Django支持每个应用都可以有自己独立的路由层.静态文件.模版层.基于该特性多人开发项目就可以完全解耦合,之后利用路由分发还可以整合到一起 多个应用都有很多路由与视图函数的对应关系 这 ...