Unity中的ShaderToys——将大神们写的shader搬到unity中来吧
http://lib.csdn.net/article/unity3d/38699
这篇文章翻译自国外的一篇文章(这里是原文链接),正在使用unity的你是否在shader toy上发现很多牛逼哄哄的shader却不知道如何使用,那么这篇文章就是帮助你来进行转换的。本文只是基础文章,那些对HLSL/CG/GLSL都很熟悉的大神相信已经会觉得太简单了。下面是索引和正文……
本文索引:
如果你正在试图涉猎shader编程这个领域,你可能或多或少听说过shaderToy这个网站,这个网站上有很多令人惊奇的shader效果,而这些效果有可能只用了几行代码来实现,就好像官方示例程序中提供的效果那样振奋人心。下面是这个网站上其中两个很厉害的例子:
“Seascape” by TDM
“Elevated” by iq
这个网站上提供的效果示例不仅仅令人赞叹,通过查看他们的源代码,你还可以学习到很多东西。网站上提供了可以在线实时创建和预览效果的代码框,在你的浏览器中,你可以通过修改代码,修改变量和输入来查看效果的变换。
网站上的代码只提供GLSL语言的支持,因为他们是通过在你的浏览器中运行WebGl来展现这些效果的。在本文中的这个例子是在unity5中实现的,但应该在其他版本的unity中也可以很好的运行。
一、 GLSL到HLSL的转换
理论上来说,应该是有将GLSL直接转换为HLSL的工具,但据我所知,至少目前我还没有发现这样的工具。因此,我只能手动将代码一行行转换过来。幸运的是,一般来说,一个shader文件的代码都不会很长,大部分也就一百来行吧,听起来可能只需要几分钟就可以完成这个过程。
微软已经发布过一篇文章专门介绍了GLSL和HLSL之间的差别。Unity中也有一篇类似的很有用的文章在这里。而下面是我在转换shader的过程中经常用到的一些方法:
- 将 iGlobalTime shader 输入值转换为(用来驱动shader中动画的时间,类似C#中的Time.deltaTime(单位为秒)) _Time.y
- 将 iResolution.xy (“视口的像素分辨率”) 转换为 _ScreenParams.xy
- 将元素为float2, mat2的向量 vec2 类型转换为float2x2 等.
- 将 vec3(1) 简写的构造器改写为所有分量都为1的 float3(1,1,1)
- 将 Texture2D 改写为 Tex2D
- 将 atan(x,y) 改写为 atan2(y,x) <- 注意参数的顺序!
- 将 mix() 改写为 lerp()
- 将 *= 改写为 mul()
- 将纹理Texture2D查找函数的第三个参数(偏移量bias)移除
- mainImage(out vec4 fragColor, in vec2 fragCoord) 是一个片段着色器, 在unity中等同于 float4 mainImage(float2 fragCoord : SV_POSITION) : SV_Target
- GLSL中纹理坐标Y方向的原点在顶部,而HLSL中纹理坐标Y方向的原点在底部,所以你需要使用这个公式uv.y = 1 – uv.y 对每个点重新定义纹理坐标
ShaderToys上的这些效果都没有用到顶点着色器函数,他们通过在像素着色器中计算屏幕上每个点对应的UV坐标来确定每个像素对应的颜色值。因此,shadertoy上的这些效果特别适合用来做全屏特效(或者,你可以将他们直接赋给一个面板或者四边形),只要是UV从0到1平铺开来的效果都会差不多。
二、 在Unity中实现它
写过shader的开发者应该清楚,在片段着色器(或者说顶点着色器)中对每个像素单独做计算是非常耗性能的。如果你想使你的shader以一个流畅运行的帧率来展现的话,一个比较通用的做法是将片段着色器中的像素缩小到一个合适的比率,再通过放大到屏幕比例的方式来减少计算量。以下是本文中要用到的CS代码通用框架:
using System;
using UnityEngine;
[ExecuteInEditMode]
public class ShaderToy : MonoBehaviour
{
public int horizontalResolution = 320;
public int verticalResolution = 240;
public Shader shaderToy;
private Material shaderToyMaterial = null;
public Material material
{
get
{
shaderToyMaterial = CheckShaderAndCreateMaterial(shaderToy, shaderToyMaterial);
return shaderToyMaterial;
}
}
// Called by camera to apply image effect
void OnRenderImage(RenderTexture source, RenderTexture destination)
{
// To draw the shader at full resolution, use:
// Graphics.Blit (source, destination, material);
// To draw the shader at scaled down resolution, use:
RenderTexture scaled = RenderTexture.GetTemporary(horizontalResolution, verticalResolution);
Graphics.Blit(source, scaled, material);
Graphics.Blit(scaled, destination);
RenderTexture.ReleaseTemporary(scaled);
}
protected Material CheckShaderAndCreateMaterial(Shader shader, Material material)
{
if (shader == null)
{
return null;
}
if (shader.isSupported && material && material.shader == shader)
return material;
if (!shader.isSupported)
{
return null;
}
else
{
material = new Material(shader);
material.hideFlags = HideFlags.DontSave;
if (material)
return material;
else
return null;
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
下面是ShaderToy网站上的源码:
// Created by inigo quilez - iq/2013
// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv = -1.0 + 2.0*fragCoord.xy / iResolution.xy;
uv.x *= iResolution.x / iResolution.y;
// background
vec3 color = vec3(0.8 + 0.2*uv.y);
// bubbles
for( int i=0; i<40; i++ )
{
// bubble seeds
float pha = sin(float(i)*546.13+1.0)*0.5 + 0.5;
float siz = pow( sin(float(i)*651.74+5.0)*0.5 + 0.5, 4.0 );
float pox = sin(float(i)*321.55+4.1) * iResolution.x / iResolution.y;
// buble size, position and color
float rad = 0.1 + 0.5*siz;
vec2 pos = vec2( pox, -1.0-rad + (2.0+2.0*rad)*mod(pha+0.1*iGlobalTime*(0.2+0.8*siz),1.0));
float dis = length( uv - pos );
vec3 col = mix( vec3(0.94,0.3,0.0), vec3(0.1,0.4,0.8), 0.5+0.5*sin(float(i)*1.2+1.9));
// col+= 8.0*smoothstep( rad*0.95, rad, dis );
// render
float f = length(uv-pos)/rad;
f = sqrt(clamp(1.0-f*f,0.0,1.0));
color -= col.zyx *(1.0-smoothstep( rad*0.95, rad, dis )) * f;
}
// vigneting
color *= sqrt(1.5-0.5*length(uv));
fragColor = vec4(color,1.0);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
下面是转换过来在Unity中使用的Shader代码:
// See https://www.shadertoy.com/view/4dl3zn
// GLSL -> HLSL reference: https://msdn.microsoft.com/en-GB/library/windows/apps/dn166865.aspx
Shader "Custom/Bubbles" {
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
struct v2f{
float4 position : SV_POSITION;
};
v2f vert(float4 v:POSITION) : SV_POSITION {
v2f o;
o.position = mul (UNITY_MATRIX_MVP, v);
return o;
}
fixed4 frag(v2f i) : SV_Target {
float2 uv = -1.0 + 2.0*i.position.xy/ _ScreenParams.xy;
uv.x *= _ScreenParams.x/ _ScreenParams.y ;
// Background
fixed4 outColour = fixed4(0.8+0.2*uv.y,0.8+0.2*uv.y,0.8+0.2*uv.y,1);
// Bubbles
for (int i = 0; i < 40; i++) {
// Bubble seeds
float pha = sin(float(i)*546.13+1.0)*0.5 + 0.5;
float siz = pow( sin(float(i)*651.74+5.0)*0.5 + 0.5, 4.0 );
float pox = sin(float(i)*321.55+4.1);
// Bubble size, position and color
float rad = 0.1 + 0.5*siz;
float2 pos = float2( pox, -1.0-rad + (2.0+2.0*rad)*fmod(pha+0.1*_Time.y*(0.2+0.8*siz),1.0));
float dis = length(uv-pos);
float3 col = lerp( float3(0.94,0.3,0.0), float3(0.1,0.4,0.8), 0.5+0.5*sin(float(i)*1.2+1.9));
// Add a black outline around each bubble
col+= 8.0*smoothstep( rad*0.95, rad, dis );
// Render
float f = length(uv-pos)/rad;
f = sqrt(clamp(1.0-f*f,0.0,1.0));
outColour.rgb -= col.zyx *(1.0-smoothstep( rad*0.95, rad, dis )) * f;
}
// Vignetting
outColour *= sqrt(1.5-0.5*length(uv));
return outColour;
}
ENDCG
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
三、 最终效果
将CS代码拖到摄像机上,然后参考下图修改设置就可以看到效果啦,注意脚本组件中的分辨率要和当前屏幕保持一致才不会变形。
参考设置如下:
最终效果如图:
Unity中的ShaderToys——将大神们写的shader搬到unity中来吧的更多相关文章
- 厉害了,Google大神每天写多少行代码?
文章转自开源中国社区,编译自:Quora Quora上有个有趣的问题:Google工程师们每天写多少行代码? Google 的 AdMob 全栈工程师 Raymond Farias 在 Quora 发 ...
- 通过开发工具发布web应用到tomcat服务器中--对于小白,大神可以忽略不看,勿喷,谢谢
需要的工具 MyEclipse和TomCat 本人用的是MyEclipse2014和TomCat7 TomCat结构图 第一步:在MyEclipse中配置TomCat 如图所示: 第二步:创建Web项 ...
- 今天看了shell大神的写的一个统计脚本
通过nginx日志统计接口耗时排行 grep '/bigbox?' access_log | awk '{print $7"&process="$NF}'| sed -r ...
- SQL 分组排序分页(大神帮写的膜拜一下)
查询全部: SELECT P3.ID, P3.Name, P3.AddTimeFROM (SELECT Name, MAX(AddTime) AS MaxAddTime FROM Product AS ...
- 大神Java8写了一段逻辑,我直呼看不懂
业务背景 首先,业务需求是这样的,从第三方电商平台拉取所有订单,然后保存到公司自己的数据库,需要判断是否有物流信息,如果有物流信息,还需要再进行上传. 而第三方接口返回的数据是 JSON 格式的,其中 ...
- 学习大神笔记之“MyBatis学习总结(二)”
MyBatis对表的增删改查操作 主要有两种方式:基于XML实现和基于注解实现. 完整项目结构: 工具类:MyBatisUtil-------用于获取 sqlsession pack ...
- 实战经验|大神战队都在i春秋教你打CTF
全国大学生信息安全竞赛创新实践能力赛旨在培养.选拔.推荐优秀信息安全专业人才创造条件,促进高等学校信息安全专业课程体系.教学内容和方法的改革,培养学生的创新意识与团队合作精神,普及信息安全知识,增强学 ...
- [ACM训练] ACM中巧用文件的输入输出来改写acm程序的输入输出 + ACM中八大输入输出格式
ACM中巧用文件的输入输出来改写acm程序的输入输出 经常有见大神们使用文件来代替ACM程序中的IO,尤其是当程序IO比较复杂时,可以使自己能够更专注于代码的测试,而不是怎样敲输入. C/C++代码中 ...
- android中“下次不再提示”的对话框(修改自某大神)
如图,我们要做得就是这个: 先上代码: 1,逻辑代码 package com.example.hello; import android.app.Activity; import android.ap ...
随机推荐
- 【BZOJ3743】[Coci2015]Kamp 树形DP
[BZOJ3743][Coci2015]Kamp Description 一颗树n个点,n-1条边,经过每条边都要花费一定的时间,任意两个点都是联通的. 有K个人(分布在K个不同的点)要集中到一个点举 ...
- E - What Is Your Grade?
E - What Is Your Grade? Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & % ...
- AFN errorCode对应的状态码
转 http://blog.csdn.NET/wangyanchang21/article/details/50932191 在很多时候都会遇到错误, 还会带有一些 Error Code , 比如在各 ...
- 【python】-- GIL锁、线程锁(互斥锁)、递归锁(RLock)
GIL锁 计算机有4核,代表着同一时间,可以干4个任务.如果单核cpu的话,我启动10个线程,我看上去也是并发的,因为是执行了上下文的切换,让看上去是并发的.但是单核永远肯定时串行的,它肯定是串行的, ...
- Android系统移植与调试之------->如何修改Android默认字体大小和设置里面字体大小比例
因为我修改 ro.sf.lcd_density的值,将它从160修改 为120,所以导致整个系统的字体都变得很小.因此需要将整个字体变大,并且在设置-->显示-->字体大小的4个选项的值都 ...
- struts2 获取表单数据封装到list和map集合
一.获取封装表单数据到list集合 示例 获取用户输入的用户名和密码并输出用户名. jsp页面 list[0]表示list中的第一个user对象 Java代码 二.封装表单数据到map集合 示例 获取 ...
- 使用asn1tools进行asn1编解码
最近在做3GPP的编解码,发现有两个第三方库比较好用.一个是ASN1C(c语言编译环境),一个是python第三方库asn1tools.这里介绍下asn1tools的使用方法: 1 第一步:生成asn ...
- Hadoop初体验(续)--YARN
1.Hadoop已经安装完成并启动成功 复制mapred-site.xml.template重命名为mapred-site.xml /etc/hadoop/mapred-site.xml.templa ...
- scala语法解析(解码指环)
看惯了JAVA的语法,再看scala的语法,有的晦涩难懂.正好遇到一个介绍scala语法的文章,就直接截图留念.省的再临时抱佛脚了.
- 利用CocoaPods管理本地工程和发布开源框架
发布自己三方框架 发布云端库 1.创建spec pod spec create xxx 2.编辑spec s.name:名称,pod search 搜索的关键词,注意这里一定要和.podspec的名称 ...