写在前面

呜呼,好久没有写博客了,好惭愧。题外话,感觉越大就越想家,希望可以一直和家人在一起,哪怕只是坐在一起不说话也觉得很温暖,一想到要分开眼睛就开始酸,哎。开学还是爬上来老实更新博客学习吧~

今天爬上来一看,发现CSDN的博客编辑终于更新了!进步总是好的,以前的编辑器实在很捉急。使用这种标记语言的确方便了很多,但好像颜色字体没法设置?程序员果然对美观没什么追求。

ShaderToy

如果你还没听过ShaderToy,那你就真的错过了一个很好的shader学习网站。我是在群里有一次听到小伙伴们提到这个网站的。点进去就会发现里面有很多很绚丽的shader展示。

说简单点,这个网站是专门让人们分享和编写GLSL的pixel shaders的。换句话说,里面那些绚丽的效果仅仅依靠pixel shaders就可以完成了(当然还有纹理的配合),是不是很强大?里面的强人很多,就像头脑风暴一样,让你一次次发出惊叹,原来还可以这样做!但是,这里面也蕴含了很多数学和算法知识,所以你可能会经常发现自己脑袋不够用,跟不上作者的思路。。。不过,脑袋都是靠锻炼的嘛,没有捷径可走,多看多写总是没错的~

强烈建议大家先去逛一逛,有很多很好玩的东西,例如这个人写了一个莫比乌斯带,而这个人写了一个耀眼的小太阳!一开始你很难相信这些完全都是用shader计算出来的。

那些效果是怎么写出来的

很多人都在好奇那些绚丽的效果是怎么来的,比如iq刚写的这个效果:

这个效果用了什么Maya或3ds Max做出的模型吗?答案其实是没有的,没有任何外部的模型输入,纹理和模型都是由程序生成的。当你打开它的界面时,其实所有的输入和程序都一目了然:

Shadertoy的特点就是大家使用程序来产生各种模型、纹理、动画,所以让人惊叹!一个pixel shader+几张固定的简单的纹理,就能得到这么绚丽的结果!iq的这个新效果更是展示了这种方法能做到的程度——照片级的效果。

那么,他们到底是怎么做到的呢?这里简单提到一下,这种看似有建模效果的画面大部分都使用了raymarching的方法,iq的博客里有很多文章,大家可以去学习下。

特点

之前说了,这个网上的所有shader都是GLSL的pixel shaders。那么什么是pixel shader呢?如果我们需要渲染一个刚好铺盖整个屏幕的全屏的方形平板,那么这个方形的fragment shader就是一个pixel shader。这是因为此时,每一个fragment对应了屏幕上的一个pixel。也因此,pixel shader的很多输入都是相同的。在ShaderToy的每个shader上方,你都可以看到一个Shader Input:

uniform vec3      iResolution;           // viewport resolution (in pixels)
uniform float     iGlobalTime;           // shader playback time (in seconds)
uniform float     iChannelTime[4];       // channel playback time (in seconds)
uniform vec3      iChannelResolution[4]; // channel resolution (in pixels)
uniform vec4      iMouse;                // mouse pixel coords. xy: current (if MLB down), zw: click
uniform samplerXX iChannel0..3;          // input channel. XX = 2D/Cube
uniform vec4      iDate;                 // (year, month, day, time in seconds)
uniform float     iSampleRate;           // sound sample rate (i.e., 44100)

这些就是ShaderToy提供的公共变量,我们可以直接访问。例如,iResolution存储了屏幕分辨率,iGlobalTime提供了shader运行时间,iMouse提供了鼠标点击位置等等。

由于ShaderToy针对的是pixel shaders,这也意味着它们的vertex shaders都是一样的,只需要计算基本的顶点位置和屏幕位置即可。

在Unity中实践

Unity的出现的确给很多shader学习者一个方便的编译和展示平台,我们不再需要每次都用很多代码准备好顶点数据,每次都设置纹理,每次都设置MVP矩阵等等。Unity提供给我们更方便的可视化操作。

ShaderToy中很多shader都可以经过一点修改后在Unity中编译运行。当然,也有人这么干过了。例如这位博主。

为了方便后面的编写,我们可以写一个针对ShaderToy的基本模板shader。在这之前,我们有必要弄清楚ShaderToy的Shaders长什么样。如果你仔细观察,其实ShaderToy中的所有shader只有一个必不可少的函数:

void mainImage( out vec4 fragColor, in vec2 fragCoord )

它的输入是一个类型为vec2的fragCoord,对应输入的屏幕位置;输出一个vec4的fragColor,对应该pixel的颜色。很简单对不对!

那么现在我们就可以写出这个模板shader了。

Shader "Shadertoy/Template" { Properties{iMouse ("Mouse Pos", Vector) = (100, 100, 0, 0)iChannel0("iChannel0", 2D) = "white" {}  iChannelResolution0 ("iChannelResolution0", Vector) = (100, 100, 0, 0)}CGINCLUDE    #include "UnityCG.cginc"   #pragma target 3.0      #define vec2 float2#define vec3 float3#define vec4 float4#define mat2 float2x2#define mat3 float3x3#define mat4 float4x4#define iGlobalTime _Time.y#define mod fmod#define mix lerp#define fract frac#define texture2D tex2D#define iResolution _ScreenParams#define gl_FragCoord ((_iParam.scrPos.xy/_iParam.scrPos.w) * _ScreenParams.xy)#define PI2 6.28318530718#define pi 3.14159265358979#define halfpi (pi * 0.5)#define oneoverpi (1.0 / pi)fixed4 iMouse;sampler2D iChannel0;fixed4 iChannelResolution0;struct v2f {    float4 pos : SV_POSITION;    float4 scrPos : TEXCOORD0;   };              v2f vert(appdata_base v) {  v2f o;o.pos = mul (UNITY_MATRIX_MVP, v.vertex);o.scrPos = ComputeScreenPos(o.pos);return o;}  vec4 main(vec2 fragCoord);fixed4 frag(v2f _iParam) : COLOR0 { vec2 fragCoord = gl_FragCoord;return main(gl_FragCoord);}  vec4 main(vec2 fragCoord) {return vec4(1, 1, 1, 1);}ENDCG    SubShader {    Pass {    CGPROGRAM    #pragma vertex vert    #pragma fragment frag    #pragma fragmentoption ARB_precision_hint_fastest     ENDCG    }    }     FallBack Off
}

代码比较简单。主要是在开头定义了一系列宏来和ShaderToy中的GLSL衔接。其中main函数对应了之前的mainImage函数。在后面,我们只需要在CGINCLUDE中定义其他函数,并填充main函数即可。

为了可以响应鼠标操作,我们还可以写一个C#脚本,以便在鼠标进行拖拽时将鼠标位置传递给shader。

using UnityEngine;
using System.Collections;public class ShaderToyHelper : MonoBehaviour {private Material _material = null;private bool _isDragging = false;// Use this for initializationvoid Start () {Renderer render  = GetComponent<Renderer>();if (render != null) {_material = render.material;}_isDragging = false;}// Update is called once per framevoid Update () {Vector3 mousePosition = Vector3.zero;if (_isDragging) {mousePosition = new Vector3(Input.mousePosition.x, Input.mousePosition.y, 1.0f);} else {mousePosition = new Vector3(Input.mousePosition.x, Input.mousePosition.y, 0.0f);}if (_material != null) {_material.SetVector("iMouse", mousePosition);}}void OnMouseDown() {_isDragging = true;}void OnMouseUp() {_isDragging = false;}
}

代码很简单,在有鼠标拖拽时,mousePositon的Z分量为1,否则为0。这跟ShaderToy中判断鼠标的方式一致。

使用时,只要把该脚本拖拽到材质所在的物体上,同时保证该物体上有绑定Collider即可。

写在最后

ShaderToy绝大部分代码都是依靠强大的数学计算来完成的,因此真的是一次次头脑风暴。当然,一些人会觉得它对于现在火爆的移动终端来说用处不大,因为支持不了呗~不过,我还没工作,觉得锻炼下挺好的~在后面我会尽量定期每周更新一篇ShaderToy中的shader。总之,希望大家have fun~

P.S. 总觉得用新编辑器写出来的文章没原来好看。。。

【ShaderToy】开篇相关推荐

  1. 【ShaderToy】跳动的心

    http://blog.csdn.net/candycat1992/article/details/44040273 写在前面 注:如果你还不了解ShaderToy,请看开篇. 作为ShaderToy ...

  2. 【ShaderToy】基础篇之再谈抗锯齿(antialiasing,AA)

    写在前面 在之前的基础篇中,我们讲到了在绘制点线时如何处理边缘的锯齿,也就是使用smoothstep函数.而模糊参数是一些定值,或者是跟屏幕分辨率相关的数值,例如分辨率宽度的5%等等.但这种方法其实是 ...

  3. shadertoy上手指南

    一 shadertoy是什么 下面是维基百科上的定义: Shadertoy.com is a cross-browser online community and tool for creating ...

  4. 【ShaderToy】基础篇之谈谈点、线的绘制

    写在前面 写前面一篇的时候,发现还是不够基础.因此打算增加几篇基础篇,从点线面开始,希望可以更好理解. 其实用Pixel Shader的过程很像在纸上绘画的过程.屏幕上的每一个像素对应了纸上的一个方格 ...

  5. 【ShaderToy】跳动的心❤️

    写在前面 注:如果你还不了解ShaderToy,请看开篇. 作为ShaderToy系列的第一篇,我们先来点简单的.下面是效果: (CSDN目前不能传gif文件了,暂时空缺,可以看下面的原shader效 ...

  6. 一步步学敏捷开发:开篇

    一步步学敏捷开发:开篇 http://www.cnblogs.com/jetlian/p/3913687.html

  7. 【天命奇御】成就进度62/71的通关攻略(1·开篇前言)

    天命奇御于2018.8.9号在wegame上发售 先是一周目记录: 可以说一周目是熟悉最终boss技能后,靠技术过的...... 然后是二周目记录: 开篇前言: 转载于:https://www.cnb ...

  8. 开篇第一题:经典中的经典!

    开篇第一题:经典中的经典!                          --评<编程之美> 原贴地址:http://www.douban.com/review/2130819/ 应该 ...

  9. Silverlight实例教程 - Validation数据验证开篇

    Silverlight 4 Validation验证实例系列 Silverlight实例教程 - Validation数据验证开篇 Silverlight实例教程 - Validation数据验证基础 ...

最新文章

  1. HTML5实践 -- 使用css装饰你的图片画廊 - part2
  2. 老榕智能建站软件_2020年,10大最佳免费建站软件
  3. 还原软件实施更安全防护机器狗
  4. hashmap value占用空间大小_求比HashMap占用内存少的查找方法
  5. SDUT1281Cup
  6. Android--intent详解
  7. 2019ICPC(银川) - Function!(数论+数学分块)
  8. OpenCL列举平台列表以及平台属性信息
  9. Redis windows学习(一)——redis安装和基础使用
  10. 数据结构——图的C语言实现
  11. 20155230 2016-2017-2《Java程序设计》课程总结
  12. 【转载】TCP拥塞控制算法 优缺点 适用环境 性能分析
  13. 面试宝典系列-Mysql索引的区别
  14. linux安装7z到指定目录,linux下安装7zip
  15. 高质量的用户体验 推进IT运维向业务服务转变——中国移动通信集团公司
  16. UpdateProgress使用,出不来特效问题小结
  17. VS.NET(C#)-3.13_Panel控件
  18. php函数-wordwrap,sprintf,ucwords,ucfirst,substr_replace
  19. extJs 2.0学习笔记(Ext.Panel篇四)
  20. 计算智能 — 模糊计算

热门文章

  1. 前端可视化项目全国疫情地图
  2. git安装及使用教程
  3. 学习笔记(07):C++网络编程进阶-IO模型之重叠Overlapped IO(基于事件通知)
  4. java long 0_Java中的long类型和Long类型比较大小
  5. 在Excel中给不足位数的数字前面补0
  6. 视觉里程计 第一部分:前30年的发展和理论基础
  7. mysql定时任务自动备份
  8. Python日期推算实操案例
  9. 隐私政策网址 (URL)
  10. Axure 8.0 授权码