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 ...
随机推荐
- 【BZOJ3791】作业 DP
[BZOJ3791]作业 Description 众所周知,白神是具有神奇的能力的.比如说,他对数学作业说一声“数”,数学作业就会出于畏惧而自己完成:对语文作业说一声“语”,语文作业就会出于畏惧而自己 ...
- Gaby Ivanushka(快排)
Gaby Ivanushka Once upon a time there lived a tsar that has a daughter — Beautiful Vasilisa. There w ...
- Robbery(记忆化搜索)
Robbery Inspector Robstop is very angry. Last night, a bank has been robbed and the robber has not b ...
- office2013安装/激活
ed2k://|file|cn_office_professional_plus_2013_x64_dvd_1134006.iso|914106368|E5FBAE9EE9CB35D5E777EA78 ...
- mac上傻瓜式java安装环境配置
适用于mac新手用户或者黑苹果用户 首先,打开终端 输入 java -version 检查是否已安装好Java运行环境 显示我现在电脑没有安装 如果返回版本号,说明运行环境成功 对于windows用过 ...
- 七招从办公室政治中取胜 发表于 09 May 2008 ? 领导力培养
办公室政治,对有些人来说是一个禁忌词汇,但在工作场合它却不可回避.简单说来,它就是职场上人与人的不同:观念的差异.利益的冲突 都可以看成是办公室政治的表现.它等于人与人之间的交流和关系.没必要害怕办公 ...
- Python基础(4)_字典、集合、bool值
三.字典 定义:{key1:value1,key2:value2},key-value结构,key必须是不可变类型,或者可hash 基本形式:key:value特性: 1.可存放多个值 2.可修改指定 ...
- LeetCode:算法特辑——二分搜索
LeetCode:算法特辑——二分搜索 算法模板——基础 int L =0; int R =arr.length; while(L<R) { int M = (R-L)/2+L; if(arr[ ...
- php匹配字符串中大写字母的位置
变量名用的是驼峰,数据库中字段中的是下划线,现在想把userId等变量批量转换成user_id,怎么样获取大写字母在字符串中的位置?echo strtolower(preg_replace('/((? ...
- 收缩VC数据库
注意: 在收缩日志前必须截断事务日志. 一. SQL Server 2008 收缩日志 (1) 使用SQL管理器收缩日志 第一步执行如下命令 ALTER DATABASE dbname SET REC ...