【OpenGL】Shader技巧集合
2015-09-18 07:01
393 查看
这篇文章将收集unity中使用shader的相关技巧和特效,会不断地更新内容。关于在Unity中使用shader的介绍,请参考《【OpenGL】使用Unity来学习OpenGL》
常用的内置uniform
iResolution =》_ScreenParams
iGlobalTime => _Time.y
glFragCoord => float4 sp:WPOS // 需要 #pragma target 3.0, 另外的方式请见下面
vec2 => float2
mix => lerp
mod => fmod
texture2D => tex2D
textureCube => texCUBE
mat2=>float2x2
fract=>frac
========
关于glFragCoord, 可以使用另外一种方式计算(支持3.0之前的)参考官方例子
o.scrPos = ComputeScreenPos(o.pos);
float2 wcoord = (i.scrPos.xy/i.scrPos.w);
-------
float2 wcoord = sp.xy/_ScreenParams.xy;
关于数学的Shader:https://www.shadertoy.com/view/ldlSD2 https://www.shadertoy.com/view/ldlSWj
很好的一个教程:http://ogldev.atspace.co.uk/index.html
Deferred Shading 原理: http://ogldev.atspace.co.uk/www/tutorial35/tutorial35.html
关于Stencil Buffer 的理解:http://www.cnblogs.com/mikewolf2002/archive/2012/05/15/2500867.html
更多文章:1)http://docs.unity3d.com/Manual/SL-Stencil.html
2) http://answers.unity3d.com/questions/590800/how-to-cullrender-to-through-a-window.html
Stencil Shadow Volume : http://ogldev.atspace.co.uk/www/tutorial40/tutorial40.html
http://en.wikipedia.org/wiki/Shadow_volume
镜面反射的实现原理:
ftp://ftp.sgi.com/sgi/opengl/contrib/blythe/advanced99/notes/node158.html
其它镜面反射:
http://en.wikibooks.org/wiki/Cg_Programming/Unity/Mirrors
在unity cg中可以使用[HideInInspector]来隐藏uniform属性,这样就可以用作自定义常量。
Physically Based Rendering: Tutorial: Physically Based Rendering, And you can too!
边缘检测:1) http://www.codeproject.com/Articles/94817/Pixel-Shader-for-Edge-Detection-and-Cartoon-Effect
2) http://coding-experiments.blogspot.hk/2010/06/edge-detection.html
3) http://en.wikipedia.org/wiki/Edge_detection
Cg函数表:http://http.developer.nvidia.com/CgTutorial/cg_tutorial_appendix_e.html
heat effect : http://forum.unity3d.com/threads/50132-Heat-Distortion, http://www.cnblogs.com/geoffyange/archive/2013/06/06/3122570.html
skin shading in unity: http://www.altdevblogaday.com/2011/12/31/skin-shading-in-unity3d/
http://http.developer.nvidia.com/GPUGems3/gpugems3_ch14.html
http://gamedev.stackexchange.com/questions/31308/algorithm-for-creating-spheres
RenderMan University: http://renderman.pixar.com/view/renderman-university
一些shader的例子:
[cpp] view
plaincopy
Shader "shaderToy/LolCrap" {
Properties {
_MainTex ("image", 2D) = "white" {}
_NoiseTex("noise", 2D) = "bump" {}
_percent("percent", Range(-0.3, 1)) = 0
_DefColor ("defalutColor", COLOR) = ( 0, .8, .4, 1)
}
CGINCLUDE
#include "UnityCG.cginc"
#pragma target 3.0
#pragma glsl
float mod289(float x) {
return x - floor(x * (1.0 / 289.0)) * 289.0;
}
float4 mod289(float4 x) {
return x - floor(x * (1.0 / 289.0)) * 289.0;
}
float4 perm(float4 x) {
return mod289(((x * 34.0) + 1.0) * x);
}
float noise3d(float3 p) {
float3 a = floor(p);
float3 d = p - a;
d = d * d * (3.0 - 2.0 * d);
float4 b = a.xxyy + float4(0.0, 1.0, 0.0, 1.0);
float4 k1 = perm(b.xyxy);
float4 k2 = perm(k1.xyxy + b.zzww);
float4 c = k2 + a.zzzz;
float4 k3 = perm(c);
float4 k4 = perm(c + 1.0);
float4 o1 = frac(k3 * (1.0 / 41.0));
float4 o2 = frac(k4 * (1.0 / 41.0));
float4 o3 = o2 * d.z + o1 * (1.0 - d.z);
float2 o4 = o3.yw * d.x + o3.xz * (1.0 - d.x);
return o4.y * d.y + o4.x * (1.0 - d.y);
}
struct v2f {
half4 pos:SV_POSITION;
half4 uv : TEXCOORD0;
};
v2f vert(appdata_base v) {
v2f o;
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
return o;
}
fixed4 frag(float4 sp:WPOS) : COLOR0 {
float2 uv = 2.0 * sp.xy / _ScreenParams.xy - 1.0;
float3 water[4];
float3 fire[4];
float3x3 r = float3x3(0.36, 0.48, -0.8, -0.8, 0.60, 0.0, 0.48, 0.64, 0.60);
float3 p_pos = mul(float3(uv * float2(16.0, 9.0), 0.0), r);
float3 p_time = mul(float3(0.0, 0.0, _Time.y * 2.0), r);
// /* Noise sampling points for water */
water[0] = p_pos / 2.0 + p_time;
water[1] = p_pos / 4.0 + p_time;
water[2] = p_pos / 8.0 + p_time;
water[3] = p_pos / 16.0 + p_time;
// /* Noise sampling points for fire */
p_pos = 16.0 * p_pos - mul( float3(0.0, mod289(_Time.y) * 128.0, 0.0), r);
fire[0] = p_pos / 2.0 + p_time * 2.0;
fire[1] = p_pos / 4.0 + p_time * 1.5;
fire[2] = p_pos / 8.0 + p_time;
fire[3] = p_pos / 16.0 + p_time;
float2x2 rot = float2x2(cos(_Time.y), sin(_Time.y), -sin(_Time.y), cos(_Time.y));
float2 poszw = mul(uv, rot);
// /* Dither the transition between water and fire */
float test = poszw.x * poszw.y + 1.5 * sin(_Time.y);
float2 d = float2(16.0, 9.0) * uv;
test += 0.5 * (length(frac(d) - 0.5) - length(frac(d + 0.5) - 0.5));
// /* Compute 4 octaves of noise */
float3 points[4];
points[0] = (test > 0.0) ? fire[0] : water[0];
points[1] = (test > 0.0) ? fire[1] : water[1];
points[2] = (test > 0.0) ? fire[2] : water[2];
points[3] = (test > 0.0) ? fire[3] : water[3];
float4 n = float4(noise3d(points[0]),
noise3d(points[1]),
noise3d(points[2]),
noise3d(points[3]));
float4 color;
if (test > 0.0)
{
// /* Use noise results for fire */
float p = dot(n, float4(0.125, 0.125, 0.25, 0.5));
// /* Fade to black on top of screen */
p -= uv.y * 0.8 + 0.25;
p = max(p, 0.0);
p = min(p, 1.0);
float q = p * p * (3.0 - 2.0 * p);
float r = q * q * (3.0 - 2.0 * q);
color = float4(min(q * 2.0, 1.0),
max(r * 1.5 - 0.5, 0.0),
max(q * 8.0 - 7.3, 0.0),
1.0);
}
else
{
// /* Use noise results for water */
float p = dot(abs(2.0 * n - 1.0),
float4(0.5, 0.25, 0.125, 0.125));
float q = sqrt(p);
color = float4(1.0 - q,
1.0 - 0.5 * q,
1.0,
1.0);
}
return color;
}
ENDCG
SubShader {
Tags {"Queue" = "Transparent"}
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
ENDCG
}
}
FallBack Off
}
[cpp] view
plaincopy
// Modified by stalendp
// Created by inigo quilez - iq/2013
// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
// A list of usefull distance function to simple primitives, and an example on how to
// do some interesting boolean operations, repetition and displacement.
//
// More info here: http://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm
Shader "shaderToy/raymarchingPrimitives" {
Properties {
_NoiseTex("noise", 2D) = "bump" {}
}
CGINCLUDE
#include "UnityCG.cginc"
#pragma target 3.0
#pragma glsl
float sdPlane( float3 p )
{
return p.y;
}
float sdSphere( float3 p, float s )
{
return length(p)-s;
}
float sdBox( float3 p, float3 b )
{
float3 d = abs(p) - b;
return min(max(d.x,max(d.y,d.z)),0.0) +
length(max(d,0.0));
}
float udRoundBox( float3 p, float3 b, float r )
{
return length(max(abs(p)-b,0.0))-r;
}
float sdTorus( float3 p, float3 t )
{
float2 q = float2(length(p.xz)-t.x,p.y);
return length(q)-t.y;
}
float sdHexPrism( float3 p, float2 h )
{
float3 q = abs(p);
return max(q.z-h.y,max(q.x+q.y*0.57735,q.y*1.1547)-h.x);
}
float sdCapsule( float3 p, float3 a, float3 b, float r )
{
float3 pa = p - a;
float3 ba = b - a;
float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );
return length( pa - ba*h ) - r;
}
float sdTriPrism( float3 p, float2 h )
{
float3 q = abs(p);
return max(q.z-h.y,max(q.x*0.866025+p.y*0.5,-p.y)-h.x*0.5);
}
float sdCylinder( float3 p, float2 h )
{
float2 d = abs(float2(length(p.xz),p.y)) - h;
return min(max(d.x,d.y),0.0) + length(max(d,0.0));
}
float sdCone( in float3 p, in float3 c )
{
float2 q = float2( length(p.xz), p.y );
return max( max( dot(q,c.xy), p.y), -p.y-c.z );
}
float length2( float2 p )
{
return sqrt( p.x*p.x + p.y*p.y );
}
float length6( float2 p )
{
p = p*p*p; p = p*p;
return pow( p.x + p.y, 1.0/6.0 );
}
float length8( float2 p )
{
p = p*p; p = p*p; p = p*p;
return pow( p.x + p.y, 1.0/8.0 );
}
float sdTorus82( float3 p, float2 t )
{
float2 q = float2(length2(p.xz)-t.x,p.y);
return length8(q)-t.y;
}
float sdTorus88( float3 p, float2 t )
{
float2 q = float2(length8(p.xz)-t.x,p.y);
return length8(q)-t.y;
}
float sdCylinder6( float3 p, float2 h )
{
return max( length6(p.xz)-h.x, abs(p.y)-h.y );
}
//----------------------------------------------------------------------
float opS( float d1, float d2 )
{
return max(-d2,d1);
}
float2 opU( float2 d1, float2 d2 )
{
return (d1.x<d2.x) ? d1 : d2;
}
float3 opRep( float3 p, float3 c )
{
return fmod(p,c)-0.5*c;
}
//float3 opTwist( float3 p )
//{
// float c = cos(10.0*p.y+10.0);
// float s = sin(10.0*p.y+10.0);
// float2x2 m = float2x2(c,-s,s,c);
// return float3(m*p.xz,p.y);
//}
//----------------------------------------------------------------------
//
float2 map( in float3 pos )
{
float2 res = opU( float2( sdPlane( pos), 1.0 ),
float2( sdSphere( pos-float3( 0.0,0.25, 0.0), 0.25 ), 46.9 ) );
// res = opU( res, float2( sdBox( pos-float3( 1.0,0.25, 0.0), float3(0.25) ), 3.0 ) );
// res = opU( res, float2( udRoundBox( pos-float3( 1.0,0.25, 1.0), float3(0.15), 0.1 ), 41.0 ) );
// res = opU( res, float2( sdTorus( pos-float3( 0.0,0.25, 1.0), float2(0.20,0.05) ), 25.0 ) );
// res = opU( res, float2( sdCapsule( pos,float3(-1.3,0.20,-0.1), float3(-1.0,0.20,0.2), 0.1 ), 31.9 ) );
// res = opU( res, float2( sdTriPrism( pos-float3(-1.0,0.25,-1.0), float2(0.25,0.05) ),43.5 ) );
// res = opU( res, float2( sdCylinder( pos-float3( 1.0,0.30,-1.0), float2(0.1,0.2) ), 8.0 ) );
// res = opU( res, float2( sdCone( pos-float3( 0.0,0.50,-1.0), float3(0.8,0.6,0.3) ), 55.0 ) );
// res = opU( res, float2( sdTorus82( pos-float3( 0.0,0.25, 2.0), float2(0.20,0.05) ),50.0 ) );
// res = opU( res, float2( sdTorus88( pos-float3(-1.0,0.25, 2.0), float2(0.20,0.05) ),43.0 ) );
// res = opU( res, float2( sdCylinder6( pos-float3( 1.0,0.30, 2.0), float2(0.1,0.2) ), 12.0 ) );
// res = opU( res, float2( sdHexPrism( pos-float3(-1.0,0.20, 1.0), float2(0.25,0.05) ),17.0 ) );
//#if 1
// res = opU( res, float2( opS(
// udRoundBox( pos-float3(-2.0,0.2, 1.0), float3(0.15),0.05),
// sdSphere( pos-float3(-2.0,0.2, 1.0), 0.25)), 13.0 ) );
// res = opU( res, float2( opS(
// sdTorus82( pos-float3(-2.0,0.2, 0.0), float2(0.20,0.1)),
// sdCylinder( opRep( float3(atan(pos.x+2.0,pos.z)/6.2831 + 0.1*iGlobalTime,
// pos.y,
// 0.02+0.5*length(pos-float3(-2.0,0.2, 0.0))),
// float3(0.05,1.0,0.05)), float2(0.02,0.6))), 51.0 ) );
// res = opU( res, float2( sdSphere( pos-float3(-2.0,0.25,-1.0), 0.2 ) +
// 0.03*sin(50.0*pos.x)*sin(50.0*pos.y+8.0*iGlobalTime)*sin(50.0*pos.z),
// 65.0 ) );
//
// res = opU( res, float2( 0.5*sdTorus( opTwist(pos-float3(-2.0,0.25, 2.0)),float2(0.20,0.05)), 46.7 ) );
//#endif
return res;
}
float2 castRay( in float3 ro, in float3 rd, in float maxd )
{
float precis = 0.001;
float h=precis*2.0;
float t = 0.0;
float m = -1.0;
for( int i=0; i<60; i++ )
{
if( abs(h)<precis||t>maxd ) continue;//break;
t += h;
float2 res = map( ro+rd*t );
h = res.x;
m = res.y;
}
if( t>maxd ) m=-1.0;
return float2( t, m );
}
float softshadow( in float3 ro, in float3 rd, in float mint, in float maxt, in float k )
{
float res = 1.0;
float t = mint;
for( int i=0; i<30; i++ )
{
if( t<maxt )
{
float h = map( ro + rd*t ).x;
res = min( res, k*h/t );
t += 0.02;
}
}
return clamp( res, 0.0, 1.0 );
}
float3 calcNormal( in float3 pos )
{
float3 eps = float3( 0.001, 0.0, 0.0 );
float3 nor = float3(
map(pos+eps.xyy).x - map(pos-eps.xyy).x,
map(pos+eps.yxy).x - map(pos-eps.yxy).x,
map(pos+eps.yyx).x - map(pos-eps.yyx).x );
return normalize(nor);
}
float calcAO( in float3 pos, in float3 nor )
{
float totao = 0.0;
float sca = 1.0;
for( int aoi=0; aoi<5; aoi++ )
{
float hr = 0.01 + 0.05*float(aoi);
float3 aopos = nor * hr + pos;
float dd = map( aopos ).x;
totao += -(dd-hr)*sca;
sca *= 0.75;
}
return clamp( 1.0 - 4.0*totao, 0.0, 1.0 );
}
float3 render( in float3 ro, in float3 rd )
{
float3 col = float3(0.0);
float2 res = castRay(ro,rd,20.0);
float t = res.x;
float m = res.y;
if( m>-0.5 )
{
float3 pos = ro + t*rd;
float3 nor = calcNormal( pos );
//col = float3(0.6) + 0.4*sin( float3(0.05,0.08,0.10)*(m-1.0) );
col = float3(0.6) + 0.4*sin( float3(0.05,0.08,0.10)*(m-1.0) );
float ao = calcAO( pos, nor );
float3 lig = normalize( float3(-0.6, 0.7, -0.5) );
float amb = clamp( 0.5+0.5*nor.y, 0.0, 1.0 );
float dif = clamp( dot( nor, lig ), 0.0, 1.0 );
float bac = clamp( dot( nor, normalize(float3(-lig.x,0.0,-lig.z))), 0.0, 1.0 )*clamp( 1.0-pos.y,0.0,1.0);
float sh = 1.0;
if( dif>0.02 ) { sh = softshadow( pos, lig, 0.02, 10.0, 7.0 ); dif *= sh; }
float3 brdf = float3(0.0);
brdf += 0.20*amb*float3(0.10,0.11,0.13)*ao;
brdf += 0.20*bac*float3(0.15,0.15,0.15)*ao;
brdf += 1.20*dif*float3(1.00,0.90,0.70);
float pp = clamp( dot( reflect(rd,nor), lig ), 0.0, 1.0 );
float spe = sh*pow(pp,16.0);
float fre = ao*pow( clamp(1.0+dot(nor,rd),0.0,1.0), 2.0 );
col = col*brdf + float3(1.0)*col*spe + 0.2*fre*(0.5+0.5*col);
}
col *= exp( -0.01*t*t );
return float3( clamp(col,0.0,1.0) );
}
struct v2f {
half4 pos:SV_POSITION;
half4 uv : TEXCOORD0;
};
v2f vert(appdata_full v) {
v2f o;
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
return o;
}
float4 frag(float4 sp:WPOS) : COLOR0 {
float2 q = sp.xy/_ScreenParams.xy;
float2 p = -1.0+2.0*q;
p.x *= _ScreenParams.x/_ScreenParams.y;
float2 mo = float2(1)/_ScreenParams.xy;
//
float time = 15.0 + _Time.y;
// camera
float3 ro = float3( -0.5+3.2*cos(0.1*time + 6.0*mo.x), 1.0 + 2.0*mo.y, 0.5 + 3.2*sin(0.1*time + 6.0*mo.x) );
float3 ta = float3( -0.5, -0.4, 0.5 );
// camera tx
float3 cw = normalize( ta-ro );
float3 cp = float3( 0.0, 1.0, 0.0 );
float3 cu = normalize( cross(cw,cp) );
float3 cv = normalize( cross(cu,cw) );
float3 rd = normalize( p.x*cu + p.y*cv + 2.5*cw );
float3 col = render( ro, rd );
col = sqrt( col );
return float4( col, 1.0 );
}
ENDCG
SubShader {
Tags {"Queue" = "Transparent"}
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
ENDCG
}
}
}
[cpp] view
plaincopy
Shader "shaderToy/Interstellar" {
Properties {
_NoiseTex("noise", 2D) = "bump" {}
}
CGINCLUDE
#include "UnityCG.cginc"
#pragma target 3.0
#pragma glsl
sampler2D _NoiseTex;
float3 ToLinear( in float3 col )
{
// simulate a monitor, converting colour values into light values
return pow( col, float3(2.2) );
}
float3 ToGamma( in float3 col )
{
// convert back into colour values, so the correct light will come out of the monitor
return pow( col, float3(1.0/2.2) );
}
float4 Noise( in float2 x )
{
return tex2D( _NoiseTex, (float2(x)+0.5)/256.0 );
}
float4 Rand( in int x )
{
float2 uv;
uv.x = (float(x)+0.5)/256.0;
uv.y = (floor(uv.x)+0.5)/256.0;
return tex2D( _NoiseTex, uv );
}
struct v2f {
half4 pos:SV_POSITION;
half4 uv : TEXCOORD0;
};
v2f vert(appdata_full v) {
v2f o;
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
return o;
}
float4 frag(float4 sp:WPOS) : COLOR0 {
float3 ray;
ray.xy = 2.0*(sp.xy-_ScreenParams.xy*.5)/_ScreenParams.x;
ray.z = 1.0;
float offset = _Time.y*.5;
float speed2 = (cos(offset)+1.0)*8.0;
float speed = speed2+.1;
offset += sin(offset)*.96;
offset *= 2.0;
float3 col = float3(0);
float3 stp = ray/max(abs(ray.x),abs(ray.y));
float3 pos = 2.0*stp+.5;
float3 c = float3(0);
for ( int i=0; i < 20; i++ ) {
float z = Noise(float2(pos.xy)).x;
z = frac(z-offset);
float d = 50.0*z-pos.z;
float w = pow(max(0.0,1.0-10.0*length(frac(pos.xy)-.5)),2.0);
float3 c = max(float3(0),float3(1.0-abs(d+speed2*.5)/speed,1.0-abs(d)/speed,1.0-abs(d-speed2*.5)/speed));
col += 1.5*(1.0-z)*c*w;
pos += stp;
}
return float4(ToGamma(col),1.0);
}
ENDCG
SubShader {
Tags {"Queue" = "Transparent"}
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
ENDCG
}
}
}
[cpp] view
plaincopy
Shader "stalendp/shaderTest02" { //see https://www.shadertoy.com/view/4sj3zy
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
}
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 3.0
#include "UnityCG.cginc"
sampler2D _MainTex;
//Variable declarations
struct myvars {
float3 bgColor;
float sphereScale;
float sphereShine;
float3 sphereDiff;
float3 sphereSpec;
float2 specPoint;
};
float4 vert(appdata_base v) : POSITION {
return mul(UNITY_MATRIX_MVP, v.vertex);
}
float4 frag(float4 sp:WPOS): COLOR {
myvars mv;
mv.bgColor = float3(0.6, 0.5, 0.6);
mv.sphereScale = 0.7;
mv.sphereShine = 0.5;
mv.sphereDiff = float3(0.5, 0.0, 0.5);
mv.sphereSpec = float3(1.0, 1.0, 1.0);
mv.specPoint = float2(0.2, -0.1);
// creates shader pixel coordinates
float2 uv = sp.xy/_ScreenParams.xy;
// sets the position of the camera
float2 p = uv * 2.5 - float2(1.0, 1.0);
p.x *= _ScreenParams.x / _ScreenParams.y;
// Rotates the sphere in a circle
p.x += cos(-_Time.y) *0.35;
p.y += sin(-_Time.y) * 0.35;
// Rotates the specular point with the sphere
mv.specPoint.x += cos(-_Time.y) * 0.35;
mv.specPoint.y += sin(-_Time.y) * 0.35;
//Sets the radius of the sphere to the middle of the screen
float radius = length(p);//sqrt(dot(p, p));
float3 col = mv.bgColor;
//Sets the initial dark shadow around the edge of the sphere
float f = smoothstep(mv.sphereScale * 0.7, mv.sphereScale, length(p + mv.specPoint));
col -= lerp(col, float3(0.0,0.0,0.0), f) * 0.2;
//Only carries out the logic if the radius of the sphere is less than the scale
if(radius < mv.sphereScale) {
float3 bg = col;
//Sets the diffuse colour of the sphere (solid colour)
col = mv.sphereDiff;
//Adds smooth dark borders to help achieve 3D look
f = smoothstep(mv.sphereScale * 0.7, mv.sphereScale, radius);
col = lerp(col, mv.sphereDiff * 0.45, f);
//Adds specular glow to help achive 3D look
f = 1.0 - smoothstep(-0.2, 0.6, length(p - mv.specPoint));
col += f * mv.sphereShine * mv.sphereSpec;
//Smoothes the edge of the sphere
f = smoothstep(mv.sphereScale - 0.01, mv.sphereScale, radius);
col = lerp(col, bg, f);
}
//The final output of the shader logic above
//gl_FragColor is a vector with 4 paramaters(red, green, blue, alpha)
//Only 2 need to be used here, as "col" is a vector that already carries r, g, and b values
return float4(col, 1);
}
ENDCG
}
}
FallBack "Diffuse"
}
[cpp] view
plaincopy
Shader "Custom/shaderTest03" { // https://www.shadertoy.com/view/Xdf3DS
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
}
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 3.0
#include "UnityCG.cginc"
sampler2D _MainTex;
struct myvars {
float k;
float f;
float threshold;
float3 colour;
float3 normal;
float3 lightPos;
float3 lightColour;
float3 ambient;
float shinyness;
float diffuseFactor;
float4 fragCoord;
};
float2 center ( float2 border , float2 _offset , float2 vel, myvars mv) {
float2 c = _offset + vel * _Time * 0.5;
c = fmod ( c , 2. - 4. * border );
if ( c.x > 1. - border.x ) c.x = 2. - c.x - 2. * border.x;
if ( c.x < border.x ) c.x = 2. * border.x - c.x;
if ( c.y > 1. - border.y ) c.y = 2. - c.y - 2. * border.y;
if ( c.y < border.y ) c.y = 2. * border.y - c.y;
return c;
}
float field ( float b, float r , myvars mv) {
if ( r > b )
return 0.0;
if ( r >= b/3.0 ) {
float rb = 1.0 - r/b;
return (3.0*mv.k)/2.0 * rb * rb;
}
if ( r >= 0.0 && r <= b/3.0 ) {
return mv.k * ( 1.0 - ( (3.0*r*r)/(b*b) ) );
}
return 0.0;
}
void circle ( float r , float2 col , float2 _offset , float2 vel, myvars mv ) {
float2 pos = mv.fragCoord.xy / _ScreenParams.y;
float aspect = _ScreenParams.x / _ScreenParams.y;
float2 c = center ( float2 ( r / aspect , r ) , _offset , vel, mv);
c.x *= aspect;
float d = distance ( pos , c );
float thisField = field (r, d, mv);
mv.f += thisField;
mv.colour += float3(col, 0) * thisField;
mv.normal += normalize(float3(pos.x-c.x, pos.y-c.y,r))*thisField;
}
float4 vert(appdata_base v) : POSITION {
return mul(UNITY_MATRIX_MVP, v.vertex);
}
float4 frag(float4 sp:WPOS): COLOR {
myvars mv;
mv.fragCoord = sp;
mv.k = 100.0;
mv.f = 0.0;
mv.threshold = 10.0;
mv.colour = float3(0.0,0.0,0.0);
mv.normal = float3(0.0,0.0,0.0);
mv.lightPos = float3(_ScreenParams.xy,2000.0);
mv.lightColour = float3(0.9,0.9,1.0);
mv.ambient = float3(0.1,0.0,0.0);
mv.shinyness = 20.0;
mv.diffuseFactor = 0.0006;
circle ( .10 , float3 ( 0.7 , 0.2 , 0.8 ) , float2 ( .6 ) , float2 ( .30 , .70 ), mv );
circle ( .09 , float3 ( 0.7 , 0.9 , 0.6 ) , float2 ( .1 ) , float2 ( .02 , .20 ), mv );
circle ( .12 , float3 ( 0.3 , 0.4 , 0.1 ) , float2 ( .1 ) , float2 ( .10 , .04 ), mv );
circle ( .15 , float3 ( 0.2 , 0.5 , 0.1 ) , float2 ( .3 ) , float2 ( .10 , .20 ), mv );
circle ( .20 , float3 ( 0.1 , 0.3 , 0.7 ) , float2 ( .2 ) , float2 ( .40 , .25 ), mv );
circle ( .30 , float3 ( 0.9 , 0.4 , 0.2 ) , float2 ( .0 ) , float2 ( .15 , .20 ), mv );
float3 c;
if (mv.f < mv.threshold)
c = float3(0.0,0.0,0.0);
else {
mv.colour /= mv.f;
mv.normal = mv.normal/mv.f;
c = mv.ambient;
float3 lightDir = mv.lightPos - float3(sp.xy,0.0);
c += mv.colour * mv.diffuseFactor * max(dot(mv.normal,lightDir), 0.0);
float3 r = normalize ( reflect ( lightDir, mv.normal ) );
c += mv.lightColour * pow(max(dot(r,float3(0.0,0.0,-1.0)), 0.0), mv.shinyness);
}
return float4(c, 1);
}
ENDCG
}
}
}
[cpp] view
plaincopy
Shader "stalendp/shaderTest04" { //see https://www.shadertoy.com/view/Xsf3R8
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
}
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 3.0
#include "UnityCG.cginc"
sampler2D _MainTex;
struct Ray {
float3 org;
float3 dir;
};
float rayPlaneIntersect( Ray ray, float4 plane ) {
float f = dot( ray.dir, plane.xyz );
float t = -( dot( ray.org, plane.xyz ) + plane.w );
t /= f;
return t;
}
float3 shade( float3 pos, float3 nrm, float4 light ) {
float3 toLight = light.xyz - pos;
float toLightLen = length( toLight );
toLight = normalize( toLight );
float diff = dot( nrm, toLight );
float attn = 1.0 - pow( min( 1.0, toLightLen / light.w ), 2.0 );
float comb = 2.0 * diff * attn;
return float3( comb, comb, comb );
}
float4 vert(appdata_base v) : POSITION {
return mul(UNITY_MATRIX_MVP, v.vertex);
}
float4 frag(float4 sp:WPOS): COLOR {
// gl_FragCoord: location (0.5, 0.5) is returned
// for the lower-left-most pixel in a window
// XY of the normalized device coordinate
// ranged from [-1, 1]
float2 ndcXY = -1.0 + 2.0 * sp.xy / _ScreenParams.xy;
// aspect ratio
float aspectRatio = _ScreenParams.x / _ScreenParams.y;
// scaled XY which fits the aspect ratio
float2 scaledXY = ndcXY * float2( aspectRatio, 1.0 );
// camera XYZ in world space
float3 camWsXYZ = float3( 0.0, 1.0, 0.0 );
camWsXYZ.z += 10.0 * cos( _Time.y );
// construct the ray in world space
Ray ray;
ray.org = camWsXYZ;
ray.dir = float3( scaledXY, -2.0 ); // OpenGL is right handed
// define the plane in world space
float4 plane = float4( 0.0, 1.0, 0.0, 0.0 );
float t = rayPlaneIntersect( ray, plane );
// define the point light in world space (XYZ, range)
float4 lightWs = float4( 0.0, 5.0, -5.0, 10.0 );
if ( t >= 0.0 )
{
float3 sceneWsPos = ray.org + t * ray.dir;
float3 sceneWsNrm = plane.xyz;
float2 sceneUV = sceneWsPos.xz / 4.0;
float4 sceneBase = tex2D( _MainTex, sceneUV );
float3 sceneShade = shade( sceneWsPos, sceneWsNrm, lightWs );
return float4( sceneShade * sceneBase.xyz, 1.0 );
}
return float4( 0.0, 0.0, 0.0, 1.0 );
}
ENDCG
}
}
FallBack "Diffuse"
}
[cpp] view
plaincopy
Shader "stalendp/shaderTest04" { //see https://www.shadertoy.com/view/MdB3Dw
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
}
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 3.0
#include "UnityCG.cginc"
#define USE_ANALYTICAL_MBLUR
sampler2D _MainTex;
// intersect a MOVING sphere
float2 iSphere( in float3 ro, in float3 rd, in float4 sp, in float3 ve, out float3 nor )
{
float t = -1.0;
float s = 0.0;
nor = float3(0.0);
float3 rc = ro - sp.xyz;
float A = dot(rc,rd);
float B = dot(rc,rc) - sp.w*sp.w;
float C = dot(ve,ve);
float D = dot(rc,ve);
float E = dot(rd,ve);
float aab = A*A - B;
float eec = E*E - C;
float aed = A*E - D;
float k = aed*aed - eec*aab;
if( k>0.0 )
{
k = sqrt(k);
float hb = (aed - k)/eec;
float ha = (aed + k)/eec;
float ta = max( 0.0, ha );
float tb = min( 1.0, hb );
if( ta < tb )
{
ta = 0.5*(ta+tb);
t = -(A-E*ta) - sqrt( (A-E*ta)*(A-E*ta) - (B+C*ta*ta-2.0*D*ta) );
nor = normalize( (ro+rd*t) - (sp.xyz+ta*ve ) );
s = 2.0*(tb - ta);
}
}
return float2(t,s);
}
// intersect a STATIC sphere
float iSphere( in float3 ro, in float3 rd, in float4 sp, out float3 nor )
{
float t = -1.0;
nor = float3(0.0);
float3 rc = ro - sp.xyz;
float b = dot(rc,rd);
float c = dot(rc,rc) - sp.w*sp.w;
float k = b*b - c;
if( k>0.0 )
{
t = -b - sqrt(k);
nor = normalize( (ro+rd*t) - sp.xyz );
}
return t;
}
float3 getPosition( float time ) { return float3( 2.5*sin(8.0*time), 0.0, 1.0*cos(8.0*time) ); }
float3 getVelocity( float time ) { return float3( 8.0*2.5*cos(8.0*time), 0.0, -8.0*1.0*sin(8.0*time) ); }
float4 vert(appdata_base v) : POSITION {
return mul(UNITY_MATRIX_MVP, v.vertex);
}
float4 frag(float4 sp:WPOS): COLOR {
float2 q = sp.xy / _ScreenParams.xy;
float2 p = -1.0 + 2.0*q;
p.x *= _ScreenParams.x/_ScreenParams.y;
// camera
float3 ro = float3(0.0,0.0,4.0);
float3 rd = normalize( float3(p.xy,-2.0) );
// sphere
// render
float3 col = float3(0.0);
#ifdef USE_ANALYTICAL_MBLUR
//---------------------------------------------------
// render with analytical motion blur
//---------------------------------------------------
float3 ce = getPosition( _Time.y );
float3 ve = getVelocity( _Time.y );
col = float3(0.25) + 0.3*rd.y;
float3 nor = float3(0.0);
float3 tot = float3(0.25) + 0.3*rd.y;
float2 res = iSphere( ro, rd, float4(ce,1.0), ve/24.0, nor );
float t = res.x;
if( t>0.0 )
{
float dif = clamp( dot(nor,float3(0.5703)), 0.0, 1.0 );
float amb = 0.5 + 0.5*nor.y;
float3 lcol = dif*float3(1.0,0.9,0.3) + amb*float3(0.1,0.2,0.3);
col = lerp( tot, lcol, res.y );
}
#else
//---------------------------------------------------
// render with brute force sampled motion blur
//---------------------------------------------------
#define NUMSAMPLES 32
float3 tot = float3(0.0);
for( int i=0; i<NUMSAMPLES; i++ )
{
float fi = float(i)/float(NUMSAMPLES);
float3 ce = getPosition( _Time.y + fi/24.0 );
float3 nor = float3(0.0);
float3 tmp = float3(0.25) + 0.3*rd.y;
float t = iSphere( ro, rd, float4(ce,1.0), nor );
if( t>0.0 )
{
float dif = clamp( dot(nor,float3(0.5703)), 0.0, 1.0 );
float amb = 0.5 + 0.5*nor.y;
tmp = dif*float3(1.0,0.9,0.3) + amb*float3(0.1,0.2,0.3);
}
col += tmp;
}
col /= float(NUMSAMPLES);
#endif
col = pow( clamp(col,0.0,1.0), float3(0.45) );
return float4( col, 1.0 );
}
ENDCG
}
}
FallBack "Diffuse"
}
[cpp] view
plaincopy
Shader "stalendp/shaderTest05" { //see https://www.shadertoy.com/view/XsB3DW
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
_CubeDiffuse ("Cubemap Diffuse Map", CUBE) = "" {}
vv1("vv1", float) = -1.0
vv2("vv2", float) = 2.0
}
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 3.0
//下面防止编译错误:instruction limit of 1024 exceed;
#pragma glsl
#include "UnityCG.cginc"
#define MAX_STEPS 64
#define MAX_REFLECTIONS 4
#define PI 3.1415926536
sampler2D _MainTex;
samplerCUBE _CubeDiffuse;
float vv1, vv2;
struct Ray {
float3 o;
float3 d;
};
struct Sphere {
float3 o;
float r;
};
struct Box {
float3 o;
float3 s;
};
struct Torus {
float3 o;
float2 s;
};
float2 rotate2d(in float2 v, in float a) {
float sinA = sin(a);
float cosA = cos(a);
return float2(v.x * cosA - v.y * sinA, v.y * cosA + v.x * sinA);
}
float sdSphere(in float3 p, in Sphere s) {
return length(p-s.o)-s.r;
}
float sdBox(in float3 p, in Box b) {
float3 d = abs(p-b.o) - b.s;
return min(max(d.x,max(d.y,d.z)),0.0) +
length(max(d,0.0));
}
float sdTorus(in float3 p, in Torus t) {
p -= t.o;
float2 q = float2(length(p.xz)-t.s.x,p.y);
return length(q)-t.s.y;
}
float world(in float3 p) {
float ti = fmod(_Time.y,10.);
if(ti > 2.) {
Sphere s0 = Sphere(float3(0),1.);
Box b0 = Box(float3(0),float3(.8));
if(ti < 4.) {
return max(-sdSphere(p,s0),sdBox(p,b0));
} else if(ti < 6.) {
return min(sdSphere(p,s0),sdBox(p,b0));
} else if(ti < 8.) {
return max(sdSphere(p,s0),sdBox(p,b0));
} else {
return max(sdSphere(p,s0),-sdBox(p,b0));
}
} else {
float3 pr = p.xzy;
return sdTorus(pr, Torus(float3(0),float2(1.,.5)));
}
}
float3 getNormal(in float3 p) {
float3 d = float3(.005,0,0);
float3 n;
n.x = world(p+d.xyy);
n.y = world(p+d.yxy);
n.z = world(p+d.yyx);
return normalize(n);
}
bool march(in Ray r, out float3 p) {
p = r.o;
float d;
for(int i = 0; i < MAX_STEPS; i++) {
d = world(p);
p += r.d*d;
}
return d<=0.01;
}
float3 colorMarch(in Ray r) {
float3 p;
float3 col = float3(0);
for(int i = 0; i < MAX_REFLECTIONS; i++) {
if(march(r,p)) {
float3 ldir = normalize(float3(1,-1,.5));
float3 n = getNormal(p);
col += float3(dot(n,-ldir))*.25;
r = Ray(p,reflect(r.d,n));
r.o += r.d*0.2;
} else {
break;
}
}
col += texCUBE(_CubeDiffuse, r.d).rgb;
return col;
}
float4 vert(appdata_base v) : POSITION {
return mul(UNITY_MATRIX_MVP, v.vertex);
}
float4 frag(float4 sp:WPOS): COLOR {
float2 uv = 2.*sp.xy/_ScreenParams.xy-1.;
uv.x *= _ScreenParams.x/_ScreenParams.y;
Ray r = Ray(float3(0,0,-2),normalize(float3(uv,1)));
r.o.xz = rotate2d(r.o.xz,_Time.y*.5);
r.d.xz = rotate2d(r.d.xz,_Time.y*.5);
float3 cc =colorMarch(r);
return float4( cc, 1.0 );
}
ENDCG
}
}
FallBack "Diffuse"
}
[cpp] view
plaincopy
Shader "stalendp/myShaderWang" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
wangTex("wang texture", 2D) = "white" {}
disHeight ("texture height", float) = 0.0
}
SubShader {
Tags {"Queue" = "Transparent"}
Pass{
Cull Off
Cull Back // now render the front faces ZWrite Off // don't write to depth buffer
// in order not to occlude other objects
Blend SrcAlpha OneMinusSrcAlpha
// blend based on the fragment's alpha value
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
uniform sampler2D _MainTex;
uniform sampler2D wangTex;
uniform float disHeight;
struct vertexInput {
float4 vertex : POSITION;
float4 texcoord : TEXCOORD0;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 position_in_world_space : TEXCOORD1;
float4 tex : TEXCOORD0;
float4 sp:WPOS;
};
vertexOutput vert(vertexInput input) {
vertexOutput output;
output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
output.position_in_world_space = mul(_Object2World, input.vertex);
output.tex = input.texcoord;
return output;
}
float4 frag(vertexOutput input) : COLOR {
//https://www.shadertoy.com/view/4dsGzH
float3 COLOR1 = float3(0.0, 0.0, 0.3);
float3 COLOR2 = float3(0.5, 0.0, 0.0);
float BLOCK_WIDTH = 0.01;
float2 uv = float2(input.tex);
// To create the BG pattern
float3 final_color = float3(1.0);
float3 bg_color = float3(0.0);
float3 wave_color = float3(0.0);
float c1 = fmod(uv.x, 2.0 * BLOCK_WIDTH);
c1 = step(BLOCK_WIDTH, c1);
float c2 = fmod(uv.y, 2.0 * BLOCK_WIDTH);
c2 = step(BLOCK_WIDTH, c2);
bg_color = lerp(uv.x * COLOR1, uv.y * COLOR2, c1 * c2);
// To create the waves
float wave_width = 0.01;
uv = -1.0 + 2.0 * uv;
uv.y += 0.1;
for(float i = 0.0; i < 1.0; i++) {
uv.y += (0.07 * sin(uv.x + i/7.0 + _Time.y ));
wave_width = abs(1.0 / (150.0 * uv.y));
wave_color += float3(wave_width * 1.9, wave_width, wave_width * 1.5);
}
final_color = bg_color + wave_color;
float pos = input.position_in_world_space.y;
float p1 = saturate((pos - disHeight)*3);
float p2 = saturate((pos - disHeight - 0.5)*3);
float4 non = float4(0.0);
float4 skin = tex2D(_MainTex, float2(input.tex));
float4 wang = tex2D(wangTex, float2(input.tex));
float4 final = lerp(lerp(skin, wang, p1), non, p2);
return final + float4(final_color, 1.0);
}
ENDCG
}
}
FallBack "Diffuse"
}
CGINCLUDE的使用
[cpp] view
plaincopy
Shader "Self-Illumin/AngryBots/InterlacePatternAdditive" {
Properties {
_MainTex ("Base", 2D) = "white" {}
_TintColor ("TintColor", Color) = (1,1,1,1) // needed simply for shader replacement
_InterlacePattern ("InterlacePattern", 2D) = "white" {}
_Illum ("_Illum", 2D) = "white" {}
_EmissionLM ("Emission (Lightmapper)", Float) = 1.0
}
CGINCLUDE
#include "UnityCG.cginc"
sampler2D _MainTex;
sampler2D _InterlacePattern;
half4 _InterlacePattern_ST;
fixed4 _TintColor;
struct v2f {
half4 pos : SV_POSITION;
half2 uv : TEXCOORD0;
half2 uv2 : TEXCOORD1;
};
v2f vert(appdata_full v)
{
v2f o;
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
o.uv.xy = v.texcoord.xy;
o.uv2.xy = TRANSFORM_TEX(v.texcoord.xy, _InterlacePattern) + _Time.xx * _InterlacePattern_ST.zw;
return o;
}
fixed4 frag( v2f i ) : COLOR
{
fixed4 colorTex = tex2D (_MainTex, i.uv);
fixed4 interlace = tex2D (_InterlacePattern, i.uv2);
colorTex *= interlace;
return colorTex;
}
ENDCG
SubShader {
Tags {"RenderType" = "Transparent" "Queue" = "Transparent" "Reflection" = "RenderReflectionTransparentAdd" }
Cull Off
ZWrite Off
Blend One One
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
ENDCG
}
}
FallBack Off
}
常用的内置uniform
iResolution =》_ScreenParams
iGlobalTime => _Time.y
glFragCoord => float4 sp:WPOS // 需要 #pragma target 3.0, 另外的方式请见下面
vec2 => float2
mix => lerp
mod => fmod
texture2D => tex2D
textureCube => texCUBE
mat2=>float2x2
fract=>frac
========
关于glFragCoord, 可以使用另外一种方式计算(支持3.0之前的)参考官方例子
o.scrPos = ComputeScreenPos(o.pos);
float2 wcoord = (i.scrPos.xy/i.scrPos.w);
-------
float2 wcoord = sp.xy/_ScreenParams.xy;
关于数学的Shader:https://www.shadertoy.com/view/ldlSD2 https://www.shadertoy.com/view/ldlSWj
很好的一个教程:http://ogldev.atspace.co.uk/index.html
Deferred Shading 原理: http://ogldev.atspace.co.uk/www/tutorial35/tutorial35.html
关于Stencil Buffer 的理解:http://www.cnblogs.com/mikewolf2002/archive/2012/05/15/2500867.html
更多文章:1)http://docs.unity3d.com/Manual/SL-Stencil.html
2) http://answers.unity3d.com/questions/590800/how-to-cullrender-to-through-a-window.html
Stencil Shadow Volume : http://ogldev.atspace.co.uk/www/tutorial40/tutorial40.html
http://en.wikipedia.org/wiki/Shadow_volume
镜面反射的实现原理:
ftp://ftp.sgi.com/sgi/opengl/contrib/blythe/advanced99/notes/node158.html
其它镜面反射:
http://en.wikibooks.org/wiki/Cg_Programming/Unity/Mirrors
在unity cg中可以使用[HideInInspector]来隐藏uniform属性,这样就可以用作自定义常量。
Physically Based Rendering: Tutorial: Physically Based Rendering, And you can too!
边缘检测:1) http://www.codeproject.com/Articles/94817/Pixel-Shader-for-Edge-Detection-and-Cartoon-Effect
2) http://coding-experiments.blogspot.hk/2010/06/edge-detection.html
3) http://en.wikipedia.org/wiki/Edge_detection
Cg函数表:http://http.developer.nvidia.com/CgTutorial/cg_tutorial_appendix_e.html
heat effect : http://forum.unity3d.com/threads/50132-Heat-Distortion, http://www.cnblogs.com/geoffyange/archive/2013/06/06/3122570.html
skin shading in unity: http://www.altdevblogaday.com/2011/12/31/skin-shading-in-unity3d/
http://http.developer.nvidia.com/GPUGems3/gpugems3_ch14.html
http://gamedev.stackexchange.com/questions/31308/algorithm-for-creating-spheres
RenderMan University: http://renderman.pixar.com/view/renderman-university
一些shader的例子:
[cpp] view
plaincopy
Shader "shaderToy/LolCrap" {
Properties {
_MainTex ("image", 2D) = "white" {}
_NoiseTex("noise", 2D) = "bump" {}
_percent("percent", Range(-0.3, 1)) = 0
_DefColor ("defalutColor", COLOR) = ( 0, .8, .4, 1)
}
CGINCLUDE
#include "UnityCG.cginc"
#pragma target 3.0
#pragma glsl
float mod289(float x) {
return x - floor(x * (1.0 / 289.0)) * 289.0;
}
float4 mod289(float4 x) {
return x - floor(x * (1.0 / 289.0)) * 289.0;
}
float4 perm(float4 x) {
return mod289(((x * 34.0) + 1.0) * x);
}
float noise3d(float3 p) {
float3 a = floor(p);
float3 d = p - a;
d = d * d * (3.0 - 2.0 * d);
float4 b = a.xxyy + float4(0.0, 1.0, 0.0, 1.0);
float4 k1 = perm(b.xyxy);
float4 k2 = perm(k1.xyxy + b.zzww);
float4 c = k2 + a.zzzz;
float4 k3 = perm(c);
float4 k4 = perm(c + 1.0);
float4 o1 = frac(k3 * (1.0 / 41.0));
float4 o2 = frac(k4 * (1.0 / 41.0));
float4 o3 = o2 * d.z + o1 * (1.0 - d.z);
float2 o4 = o3.yw * d.x + o3.xz * (1.0 - d.x);
return o4.y * d.y + o4.x * (1.0 - d.y);
}
struct v2f {
half4 pos:SV_POSITION;
half4 uv : TEXCOORD0;
};
v2f vert(appdata_base v) {
v2f o;
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
return o;
}
fixed4 frag(float4 sp:WPOS) : COLOR0 {
float2 uv = 2.0 * sp.xy / _ScreenParams.xy - 1.0;
float3 water[4];
float3 fire[4];
float3x3 r = float3x3(0.36, 0.48, -0.8, -0.8, 0.60, 0.0, 0.48, 0.64, 0.60);
float3 p_pos = mul(float3(uv * float2(16.0, 9.0), 0.0), r);
float3 p_time = mul(float3(0.0, 0.0, _Time.y * 2.0), r);
// /* Noise sampling points for water */
water[0] = p_pos / 2.0 + p_time;
water[1] = p_pos / 4.0 + p_time;
water[2] = p_pos / 8.0 + p_time;
water[3] = p_pos / 16.0 + p_time;
// /* Noise sampling points for fire */
p_pos = 16.0 * p_pos - mul( float3(0.0, mod289(_Time.y) * 128.0, 0.0), r);
fire[0] = p_pos / 2.0 + p_time * 2.0;
fire[1] = p_pos / 4.0 + p_time * 1.5;
fire[2] = p_pos / 8.0 + p_time;
fire[3] = p_pos / 16.0 + p_time;
float2x2 rot = float2x2(cos(_Time.y), sin(_Time.y), -sin(_Time.y), cos(_Time.y));
float2 poszw = mul(uv, rot);
// /* Dither the transition between water and fire */
float test = poszw.x * poszw.y + 1.5 * sin(_Time.y);
float2 d = float2(16.0, 9.0) * uv;
test += 0.5 * (length(frac(d) - 0.5) - length(frac(d + 0.5) - 0.5));
// /* Compute 4 octaves of noise */
float3 points[4];
points[0] = (test > 0.0) ? fire[0] : water[0];
points[1] = (test > 0.0) ? fire[1] : water[1];
points[2] = (test > 0.0) ? fire[2] : water[2];
points[3] = (test > 0.0) ? fire[3] : water[3];
float4 n = float4(noise3d(points[0]),
noise3d(points[1]),
noise3d(points[2]),
noise3d(points[3]));
float4 color;
if (test > 0.0)
{
// /* Use noise results for fire */
float p = dot(n, float4(0.125, 0.125, 0.25, 0.5));
// /* Fade to black on top of screen */
p -= uv.y * 0.8 + 0.25;
p = max(p, 0.0);
p = min(p, 1.0);
float q = p * p * (3.0 - 2.0 * p);
float r = q * q * (3.0 - 2.0 * q);
color = float4(min(q * 2.0, 1.0),
max(r * 1.5 - 0.5, 0.0),
max(q * 8.0 - 7.3, 0.0),
1.0);
}
else
{
// /* Use noise results for water */
float p = dot(abs(2.0 * n - 1.0),
float4(0.5, 0.25, 0.125, 0.125));
float q = sqrt(p);
color = float4(1.0 - q,
1.0 - 0.5 * q,
1.0,
1.0);
}
return color;
}
ENDCG
SubShader {
Tags {"Queue" = "Transparent"}
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
ENDCG
}
}
FallBack Off
}
[cpp] view
plaincopy
// Modified by stalendp
// Created by inigo quilez - iq/2013
// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
// A list of usefull distance function to simple primitives, and an example on how to
// do some interesting boolean operations, repetition and displacement.
//
// More info here: http://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm
Shader "shaderToy/raymarchingPrimitives" {
Properties {
_NoiseTex("noise", 2D) = "bump" {}
}
CGINCLUDE
#include "UnityCG.cginc"
#pragma target 3.0
#pragma glsl
float sdPlane( float3 p )
{
return p.y;
}
float sdSphere( float3 p, float s )
{
return length(p)-s;
}
float sdBox( float3 p, float3 b )
{
float3 d = abs(p) - b;
return min(max(d.x,max(d.y,d.z)),0.0) +
length(max(d,0.0));
}
float udRoundBox( float3 p, float3 b, float r )
{
return length(max(abs(p)-b,0.0))-r;
}
float sdTorus( float3 p, float3 t )
{
float2 q = float2(length(p.xz)-t.x,p.y);
return length(q)-t.y;
}
float sdHexPrism( float3 p, float2 h )
{
float3 q = abs(p);
return max(q.z-h.y,max(q.x+q.y*0.57735,q.y*1.1547)-h.x);
}
float sdCapsule( float3 p, float3 a, float3 b, float r )
{
float3 pa = p - a;
float3 ba = b - a;
float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );
return length( pa - ba*h ) - r;
}
float sdTriPrism( float3 p, float2 h )
{
float3 q = abs(p);
return max(q.z-h.y,max(q.x*0.866025+p.y*0.5,-p.y)-h.x*0.5);
}
float sdCylinder( float3 p, float2 h )
{
float2 d = abs(float2(length(p.xz),p.y)) - h;
return min(max(d.x,d.y),0.0) + length(max(d,0.0));
}
float sdCone( in float3 p, in float3 c )
{
float2 q = float2( length(p.xz), p.y );
return max( max( dot(q,c.xy), p.y), -p.y-c.z );
}
float length2( float2 p )
{
return sqrt( p.x*p.x + p.y*p.y );
}
float length6( float2 p )
{
p = p*p*p; p = p*p;
return pow( p.x + p.y, 1.0/6.0 );
}
float length8( float2 p )
{
p = p*p; p = p*p; p = p*p;
return pow( p.x + p.y, 1.0/8.0 );
}
float sdTorus82( float3 p, float2 t )
{
float2 q = float2(length2(p.xz)-t.x,p.y);
return length8(q)-t.y;
}
float sdTorus88( float3 p, float2 t )
{
float2 q = float2(length8(p.xz)-t.x,p.y);
return length8(q)-t.y;
}
float sdCylinder6( float3 p, float2 h )
{
return max( length6(p.xz)-h.x, abs(p.y)-h.y );
}
//----------------------------------------------------------------------
float opS( float d1, float d2 )
{
return max(-d2,d1);
}
float2 opU( float2 d1, float2 d2 )
{
return (d1.x<d2.x) ? d1 : d2;
}
float3 opRep( float3 p, float3 c )
{
return fmod(p,c)-0.5*c;
}
//float3 opTwist( float3 p )
//{
// float c = cos(10.0*p.y+10.0);
// float s = sin(10.0*p.y+10.0);
// float2x2 m = float2x2(c,-s,s,c);
// return float3(m*p.xz,p.y);
//}
//----------------------------------------------------------------------
//
float2 map( in float3 pos )
{
float2 res = opU( float2( sdPlane( pos), 1.0 ),
float2( sdSphere( pos-float3( 0.0,0.25, 0.0), 0.25 ), 46.9 ) );
// res = opU( res, float2( sdBox( pos-float3( 1.0,0.25, 0.0), float3(0.25) ), 3.0 ) );
// res = opU( res, float2( udRoundBox( pos-float3( 1.0,0.25, 1.0), float3(0.15), 0.1 ), 41.0 ) );
// res = opU( res, float2( sdTorus( pos-float3( 0.0,0.25, 1.0), float2(0.20,0.05) ), 25.0 ) );
// res = opU( res, float2( sdCapsule( pos,float3(-1.3,0.20,-0.1), float3(-1.0,0.20,0.2), 0.1 ), 31.9 ) );
// res = opU( res, float2( sdTriPrism( pos-float3(-1.0,0.25,-1.0), float2(0.25,0.05) ),43.5 ) );
// res = opU( res, float2( sdCylinder( pos-float3( 1.0,0.30,-1.0), float2(0.1,0.2) ), 8.0 ) );
// res = opU( res, float2( sdCone( pos-float3( 0.0,0.50,-1.0), float3(0.8,0.6,0.3) ), 55.0 ) );
// res = opU( res, float2( sdTorus82( pos-float3( 0.0,0.25, 2.0), float2(0.20,0.05) ),50.0 ) );
// res = opU( res, float2( sdTorus88( pos-float3(-1.0,0.25, 2.0), float2(0.20,0.05) ),43.0 ) );
// res = opU( res, float2( sdCylinder6( pos-float3( 1.0,0.30, 2.0), float2(0.1,0.2) ), 12.0 ) );
// res = opU( res, float2( sdHexPrism( pos-float3(-1.0,0.20, 1.0), float2(0.25,0.05) ),17.0 ) );
//#if 1
// res = opU( res, float2( opS(
// udRoundBox( pos-float3(-2.0,0.2, 1.0), float3(0.15),0.05),
// sdSphere( pos-float3(-2.0,0.2, 1.0), 0.25)), 13.0 ) );
// res = opU( res, float2( opS(
// sdTorus82( pos-float3(-2.0,0.2, 0.0), float2(0.20,0.1)),
// sdCylinder( opRep( float3(atan(pos.x+2.0,pos.z)/6.2831 + 0.1*iGlobalTime,
// pos.y,
// 0.02+0.5*length(pos-float3(-2.0,0.2, 0.0))),
// float3(0.05,1.0,0.05)), float2(0.02,0.6))), 51.0 ) );
// res = opU( res, float2( sdSphere( pos-float3(-2.0,0.25,-1.0), 0.2 ) +
// 0.03*sin(50.0*pos.x)*sin(50.0*pos.y+8.0*iGlobalTime)*sin(50.0*pos.z),
// 65.0 ) );
//
// res = opU( res, float2( 0.5*sdTorus( opTwist(pos-float3(-2.0,0.25, 2.0)),float2(0.20,0.05)), 46.7 ) );
//#endif
return res;
}
float2 castRay( in float3 ro, in float3 rd, in float maxd )
{
float precis = 0.001;
float h=precis*2.0;
float t = 0.0;
float m = -1.0;
for( int i=0; i<60; i++ )
{
if( abs(h)<precis||t>maxd ) continue;//break;
t += h;
float2 res = map( ro+rd*t );
h = res.x;
m = res.y;
}
if( t>maxd ) m=-1.0;
return float2( t, m );
}
float softshadow( in float3 ro, in float3 rd, in float mint, in float maxt, in float k )
{
float res = 1.0;
float t = mint;
for( int i=0; i<30; i++ )
{
if( t<maxt )
{
float h = map( ro + rd*t ).x;
res = min( res, k*h/t );
t += 0.02;
}
}
return clamp( res, 0.0, 1.0 );
}
float3 calcNormal( in float3 pos )
{
float3 eps = float3( 0.001, 0.0, 0.0 );
float3 nor = float3(
map(pos+eps.xyy).x - map(pos-eps.xyy).x,
map(pos+eps.yxy).x - map(pos-eps.yxy).x,
map(pos+eps.yyx).x - map(pos-eps.yyx).x );
return normalize(nor);
}
float calcAO( in float3 pos, in float3 nor )
{
float totao = 0.0;
float sca = 1.0;
for( int aoi=0; aoi<5; aoi++ )
{
float hr = 0.01 + 0.05*float(aoi);
float3 aopos = nor * hr + pos;
float dd = map( aopos ).x;
totao += -(dd-hr)*sca;
sca *= 0.75;
}
return clamp( 1.0 - 4.0*totao, 0.0, 1.0 );
}
float3 render( in float3 ro, in float3 rd )
{
float3 col = float3(0.0);
float2 res = castRay(ro,rd,20.0);
float t = res.x;
float m = res.y;
if( m>-0.5 )
{
float3 pos = ro + t*rd;
float3 nor = calcNormal( pos );
//col = float3(0.6) + 0.4*sin( float3(0.05,0.08,0.10)*(m-1.0) );
col = float3(0.6) + 0.4*sin( float3(0.05,0.08,0.10)*(m-1.0) );
float ao = calcAO( pos, nor );
float3 lig = normalize( float3(-0.6, 0.7, -0.5) );
float amb = clamp( 0.5+0.5*nor.y, 0.0, 1.0 );
float dif = clamp( dot( nor, lig ), 0.0, 1.0 );
float bac = clamp( dot( nor, normalize(float3(-lig.x,0.0,-lig.z))), 0.0, 1.0 )*clamp( 1.0-pos.y,0.0,1.0);
float sh = 1.0;
if( dif>0.02 ) { sh = softshadow( pos, lig, 0.02, 10.0, 7.0 ); dif *= sh; }
float3 brdf = float3(0.0);
brdf += 0.20*amb*float3(0.10,0.11,0.13)*ao;
brdf += 0.20*bac*float3(0.15,0.15,0.15)*ao;
brdf += 1.20*dif*float3(1.00,0.90,0.70);
float pp = clamp( dot( reflect(rd,nor), lig ), 0.0, 1.0 );
float spe = sh*pow(pp,16.0);
float fre = ao*pow( clamp(1.0+dot(nor,rd),0.0,1.0), 2.0 );
col = col*brdf + float3(1.0)*col*spe + 0.2*fre*(0.5+0.5*col);
}
col *= exp( -0.01*t*t );
return float3( clamp(col,0.0,1.0) );
}
struct v2f {
half4 pos:SV_POSITION;
half4 uv : TEXCOORD0;
};
v2f vert(appdata_full v) {
v2f o;
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
return o;
}
float4 frag(float4 sp:WPOS) : COLOR0 {
float2 q = sp.xy/_ScreenParams.xy;
float2 p = -1.0+2.0*q;
p.x *= _ScreenParams.x/_ScreenParams.y;
float2 mo = float2(1)/_ScreenParams.xy;
//
float time = 15.0 + _Time.y;
// camera
float3 ro = float3( -0.5+3.2*cos(0.1*time + 6.0*mo.x), 1.0 + 2.0*mo.y, 0.5 + 3.2*sin(0.1*time + 6.0*mo.x) );
float3 ta = float3( -0.5, -0.4, 0.5 );
// camera tx
float3 cw = normalize( ta-ro );
float3 cp = float3( 0.0, 1.0, 0.0 );
float3 cu = normalize( cross(cw,cp) );
float3 cv = normalize( cross(cu,cw) );
float3 rd = normalize( p.x*cu + p.y*cv + 2.5*cw );
float3 col = render( ro, rd );
col = sqrt( col );
return float4( col, 1.0 );
}
ENDCG
SubShader {
Tags {"Queue" = "Transparent"}
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
ENDCG
}
}
}
[cpp] view
plaincopy
Shader "shaderToy/Interstellar" {
Properties {
_NoiseTex("noise", 2D) = "bump" {}
}
CGINCLUDE
#include "UnityCG.cginc"
#pragma target 3.0
#pragma glsl
sampler2D _NoiseTex;
float3 ToLinear( in float3 col )
{
// simulate a monitor, converting colour values into light values
return pow( col, float3(2.2) );
}
float3 ToGamma( in float3 col )
{
// convert back into colour values, so the correct light will come out of the monitor
return pow( col, float3(1.0/2.2) );
}
float4 Noise( in float2 x )
{
return tex2D( _NoiseTex, (float2(x)+0.5)/256.0 );
}
float4 Rand( in int x )
{
float2 uv;
uv.x = (float(x)+0.5)/256.0;
uv.y = (floor(uv.x)+0.5)/256.0;
return tex2D( _NoiseTex, uv );
}
struct v2f {
half4 pos:SV_POSITION;
half4 uv : TEXCOORD0;
};
v2f vert(appdata_full v) {
v2f o;
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
return o;
}
float4 frag(float4 sp:WPOS) : COLOR0 {
float3 ray;
ray.xy = 2.0*(sp.xy-_ScreenParams.xy*.5)/_ScreenParams.x;
ray.z = 1.0;
float offset = _Time.y*.5;
float speed2 = (cos(offset)+1.0)*8.0;
float speed = speed2+.1;
offset += sin(offset)*.96;
offset *= 2.0;
float3 col = float3(0);
float3 stp = ray/max(abs(ray.x),abs(ray.y));
float3 pos = 2.0*stp+.5;
float3 c = float3(0);
for ( int i=0; i < 20; i++ ) {
float z = Noise(float2(pos.xy)).x;
z = frac(z-offset);
float d = 50.0*z-pos.z;
float w = pow(max(0.0,1.0-10.0*length(frac(pos.xy)-.5)),2.0);
float3 c = max(float3(0),float3(1.0-abs(d+speed2*.5)/speed,1.0-abs(d)/speed,1.0-abs(d-speed2*.5)/speed));
col += 1.5*(1.0-z)*c*w;
pos += stp;
}
return float4(ToGamma(col),1.0);
}
ENDCG
SubShader {
Tags {"Queue" = "Transparent"}
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
ENDCG
}
}
}
[cpp] view
plaincopy
Shader "stalendp/shaderTest02" { //see https://www.shadertoy.com/view/4sj3zy
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
}
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 3.0
#include "UnityCG.cginc"
sampler2D _MainTex;
//Variable declarations
struct myvars {
float3 bgColor;
float sphereScale;
float sphereShine;
float3 sphereDiff;
float3 sphereSpec;
float2 specPoint;
};
float4 vert(appdata_base v) : POSITION {
return mul(UNITY_MATRIX_MVP, v.vertex);
}
float4 frag(float4 sp:WPOS): COLOR {
myvars mv;
mv.bgColor = float3(0.6, 0.5, 0.6);
mv.sphereScale = 0.7;
mv.sphereShine = 0.5;
mv.sphereDiff = float3(0.5, 0.0, 0.5);
mv.sphereSpec = float3(1.0, 1.0, 1.0);
mv.specPoint = float2(0.2, -0.1);
// creates shader pixel coordinates
float2 uv = sp.xy/_ScreenParams.xy;
// sets the position of the camera
float2 p = uv * 2.5 - float2(1.0, 1.0);
p.x *= _ScreenParams.x / _ScreenParams.y;
// Rotates the sphere in a circle
p.x += cos(-_Time.y) *0.35;
p.y += sin(-_Time.y) * 0.35;
// Rotates the specular point with the sphere
mv.specPoint.x += cos(-_Time.y) * 0.35;
mv.specPoint.y += sin(-_Time.y) * 0.35;
//Sets the radius of the sphere to the middle of the screen
float radius = length(p);//sqrt(dot(p, p));
float3 col = mv.bgColor;
//Sets the initial dark shadow around the edge of the sphere
float f = smoothstep(mv.sphereScale * 0.7, mv.sphereScale, length(p + mv.specPoint));
col -= lerp(col, float3(0.0,0.0,0.0), f) * 0.2;
//Only carries out the logic if the radius of the sphere is less than the scale
if(radius < mv.sphereScale) {
float3 bg = col;
//Sets the diffuse colour of the sphere (solid colour)
col = mv.sphereDiff;
//Adds smooth dark borders to help achieve 3D look
f = smoothstep(mv.sphereScale * 0.7, mv.sphereScale, radius);
col = lerp(col, mv.sphereDiff * 0.45, f);
//Adds specular glow to help achive 3D look
f = 1.0 - smoothstep(-0.2, 0.6, length(p - mv.specPoint));
col += f * mv.sphereShine * mv.sphereSpec;
//Smoothes the edge of the sphere
f = smoothstep(mv.sphereScale - 0.01, mv.sphereScale, radius);
col = lerp(col, bg, f);
}
//The final output of the shader logic above
//gl_FragColor is a vector with 4 paramaters(red, green, blue, alpha)
//Only 2 need to be used here, as "col" is a vector that already carries r, g, and b values
return float4(col, 1);
}
ENDCG
}
}
FallBack "Diffuse"
}
[cpp] view
plaincopy
Shader "Custom/shaderTest03" { // https://www.shadertoy.com/view/Xdf3DS
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
}
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 3.0
#include "UnityCG.cginc"
sampler2D _MainTex;
struct myvars {
float k;
float f;
float threshold;
float3 colour;
float3 normal;
float3 lightPos;
float3 lightColour;
float3 ambient;
float shinyness;
float diffuseFactor;
float4 fragCoord;
};
float2 center ( float2 border , float2 _offset , float2 vel, myvars mv) {
float2 c = _offset + vel * _Time * 0.5;
c = fmod ( c , 2. - 4. * border );
if ( c.x > 1. - border.x ) c.x = 2. - c.x - 2. * border.x;
if ( c.x < border.x ) c.x = 2. * border.x - c.x;
if ( c.y > 1. - border.y ) c.y = 2. - c.y - 2. * border.y;
if ( c.y < border.y ) c.y = 2. * border.y - c.y;
return c;
}
float field ( float b, float r , myvars mv) {
if ( r > b )
return 0.0;
if ( r >= b/3.0 ) {
float rb = 1.0 - r/b;
return (3.0*mv.k)/2.0 * rb * rb;
}
if ( r >= 0.0 && r <= b/3.0 ) {
return mv.k * ( 1.0 - ( (3.0*r*r)/(b*b) ) );
}
return 0.0;
}
void circle ( float r , float2 col , float2 _offset , float2 vel, myvars mv ) {
float2 pos = mv.fragCoord.xy / _ScreenParams.y;
float aspect = _ScreenParams.x / _ScreenParams.y;
float2 c = center ( float2 ( r / aspect , r ) , _offset , vel, mv);
c.x *= aspect;
float d = distance ( pos , c );
float thisField = field (r, d, mv);
mv.f += thisField;
mv.colour += float3(col, 0) * thisField;
mv.normal += normalize(float3(pos.x-c.x, pos.y-c.y,r))*thisField;
}
float4 vert(appdata_base v) : POSITION {
return mul(UNITY_MATRIX_MVP, v.vertex);
}
float4 frag(float4 sp:WPOS): COLOR {
myvars mv;
mv.fragCoord = sp;
mv.k = 100.0;
mv.f = 0.0;
mv.threshold = 10.0;
mv.colour = float3(0.0,0.0,0.0);
mv.normal = float3(0.0,0.0,0.0);
mv.lightPos = float3(_ScreenParams.xy,2000.0);
mv.lightColour = float3(0.9,0.9,1.0);
mv.ambient = float3(0.1,0.0,0.0);
mv.shinyness = 20.0;
mv.diffuseFactor = 0.0006;
circle ( .10 , float3 ( 0.7 , 0.2 , 0.8 ) , float2 ( .6 ) , float2 ( .30 , .70 ), mv );
circle ( .09 , float3 ( 0.7 , 0.9 , 0.6 ) , float2 ( .1 ) , float2 ( .02 , .20 ), mv );
circle ( .12 , float3 ( 0.3 , 0.4 , 0.1 ) , float2 ( .1 ) , float2 ( .10 , .04 ), mv );
circle ( .15 , float3 ( 0.2 , 0.5 , 0.1 ) , float2 ( .3 ) , float2 ( .10 , .20 ), mv );
circle ( .20 , float3 ( 0.1 , 0.3 , 0.7 ) , float2 ( .2 ) , float2 ( .40 , .25 ), mv );
circle ( .30 , float3 ( 0.9 , 0.4 , 0.2 ) , float2 ( .0 ) , float2 ( .15 , .20 ), mv );
float3 c;
if (mv.f < mv.threshold)
c = float3(0.0,0.0,0.0);
else {
mv.colour /= mv.f;
mv.normal = mv.normal/mv.f;
c = mv.ambient;
float3 lightDir = mv.lightPos - float3(sp.xy,0.0);
c += mv.colour * mv.diffuseFactor * max(dot(mv.normal,lightDir), 0.0);
float3 r = normalize ( reflect ( lightDir, mv.normal ) );
c += mv.lightColour * pow(max(dot(r,float3(0.0,0.0,-1.0)), 0.0), mv.shinyness);
}
return float4(c, 1);
}
ENDCG
}
}
}
[cpp] view
plaincopy
Shader "stalendp/shaderTest04" { //see https://www.shadertoy.com/view/Xsf3R8
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
}
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 3.0
#include "UnityCG.cginc"
sampler2D _MainTex;
struct Ray {
float3 org;
float3 dir;
};
float rayPlaneIntersect( Ray ray, float4 plane ) {
float f = dot( ray.dir, plane.xyz );
float t = -( dot( ray.org, plane.xyz ) + plane.w );
t /= f;
return t;
}
float3 shade( float3 pos, float3 nrm, float4 light ) {
float3 toLight = light.xyz - pos;
float toLightLen = length( toLight );
toLight = normalize( toLight );
float diff = dot( nrm, toLight );
float attn = 1.0 - pow( min( 1.0, toLightLen / light.w ), 2.0 );
float comb = 2.0 * diff * attn;
return float3( comb, comb, comb );
}
float4 vert(appdata_base v) : POSITION {
return mul(UNITY_MATRIX_MVP, v.vertex);
}
float4 frag(float4 sp:WPOS): COLOR {
// gl_FragCoord: location (0.5, 0.5) is returned
// for the lower-left-most pixel in a window
// XY of the normalized device coordinate
// ranged from [-1, 1]
float2 ndcXY = -1.0 + 2.0 * sp.xy / _ScreenParams.xy;
// aspect ratio
float aspectRatio = _ScreenParams.x / _ScreenParams.y;
// scaled XY which fits the aspect ratio
float2 scaledXY = ndcXY * float2( aspectRatio, 1.0 );
// camera XYZ in world space
float3 camWsXYZ = float3( 0.0, 1.0, 0.0 );
camWsXYZ.z += 10.0 * cos( _Time.y );
// construct the ray in world space
Ray ray;
ray.org = camWsXYZ;
ray.dir = float3( scaledXY, -2.0 ); // OpenGL is right handed
// define the plane in world space
float4 plane = float4( 0.0, 1.0, 0.0, 0.0 );
float t = rayPlaneIntersect( ray, plane );
// define the point light in world space (XYZ, range)
float4 lightWs = float4( 0.0, 5.0, -5.0, 10.0 );
if ( t >= 0.0 )
{
float3 sceneWsPos = ray.org + t * ray.dir;
float3 sceneWsNrm = plane.xyz;
float2 sceneUV = sceneWsPos.xz / 4.0;
float4 sceneBase = tex2D( _MainTex, sceneUV );
float3 sceneShade = shade( sceneWsPos, sceneWsNrm, lightWs );
return float4( sceneShade * sceneBase.xyz, 1.0 );
}
return float4( 0.0, 0.0, 0.0, 1.0 );
}
ENDCG
}
}
FallBack "Diffuse"
}
[cpp] view
plaincopy
Shader "stalendp/shaderTest04" { //see https://www.shadertoy.com/view/MdB3Dw
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
}
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 3.0
#include "UnityCG.cginc"
#define USE_ANALYTICAL_MBLUR
sampler2D _MainTex;
// intersect a MOVING sphere
float2 iSphere( in float3 ro, in float3 rd, in float4 sp, in float3 ve, out float3 nor )
{
float t = -1.0;
float s = 0.0;
nor = float3(0.0);
float3 rc = ro - sp.xyz;
float A = dot(rc,rd);
float B = dot(rc,rc) - sp.w*sp.w;
float C = dot(ve,ve);
float D = dot(rc,ve);
float E = dot(rd,ve);
float aab = A*A - B;
float eec = E*E - C;
float aed = A*E - D;
float k = aed*aed - eec*aab;
if( k>0.0 )
{
k = sqrt(k);
float hb = (aed - k)/eec;
float ha = (aed + k)/eec;
float ta = max( 0.0, ha );
float tb = min( 1.0, hb );
if( ta < tb )
{
ta = 0.5*(ta+tb);
t = -(A-E*ta) - sqrt( (A-E*ta)*(A-E*ta) - (B+C*ta*ta-2.0*D*ta) );
nor = normalize( (ro+rd*t) - (sp.xyz+ta*ve ) );
s = 2.0*(tb - ta);
}
}
return float2(t,s);
}
// intersect a STATIC sphere
float iSphere( in float3 ro, in float3 rd, in float4 sp, out float3 nor )
{
float t = -1.0;
nor = float3(0.0);
float3 rc = ro - sp.xyz;
float b = dot(rc,rd);
float c = dot(rc,rc) - sp.w*sp.w;
float k = b*b - c;
if( k>0.0 )
{
t = -b - sqrt(k);
nor = normalize( (ro+rd*t) - sp.xyz );
}
return t;
}
float3 getPosition( float time ) { return float3( 2.5*sin(8.0*time), 0.0, 1.0*cos(8.0*time) ); }
float3 getVelocity( float time ) { return float3( 8.0*2.5*cos(8.0*time), 0.0, -8.0*1.0*sin(8.0*time) ); }
float4 vert(appdata_base v) : POSITION {
return mul(UNITY_MATRIX_MVP, v.vertex);
}
float4 frag(float4 sp:WPOS): COLOR {
float2 q = sp.xy / _ScreenParams.xy;
float2 p = -1.0 + 2.0*q;
p.x *= _ScreenParams.x/_ScreenParams.y;
// camera
float3 ro = float3(0.0,0.0,4.0);
float3 rd = normalize( float3(p.xy,-2.0) );
// sphere
// render
float3 col = float3(0.0);
#ifdef USE_ANALYTICAL_MBLUR
//---------------------------------------------------
// render with analytical motion blur
//---------------------------------------------------
float3 ce = getPosition( _Time.y );
float3 ve = getVelocity( _Time.y );
col = float3(0.25) + 0.3*rd.y;
float3 nor = float3(0.0);
float3 tot = float3(0.25) + 0.3*rd.y;
float2 res = iSphere( ro, rd, float4(ce,1.0), ve/24.0, nor );
float t = res.x;
if( t>0.0 )
{
float dif = clamp( dot(nor,float3(0.5703)), 0.0, 1.0 );
float amb = 0.5 + 0.5*nor.y;
float3 lcol = dif*float3(1.0,0.9,0.3) + amb*float3(0.1,0.2,0.3);
col = lerp( tot, lcol, res.y );
}
#else
//---------------------------------------------------
// render with brute force sampled motion blur
//---------------------------------------------------
#define NUMSAMPLES 32
float3 tot = float3(0.0);
for( int i=0; i<NUMSAMPLES; i++ )
{
float fi = float(i)/float(NUMSAMPLES);
float3 ce = getPosition( _Time.y + fi/24.0 );
float3 nor = float3(0.0);
float3 tmp = float3(0.25) + 0.3*rd.y;
float t = iSphere( ro, rd, float4(ce,1.0), nor );
if( t>0.0 )
{
float dif = clamp( dot(nor,float3(0.5703)), 0.0, 1.0 );
float amb = 0.5 + 0.5*nor.y;
tmp = dif*float3(1.0,0.9,0.3) + amb*float3(0.1,0.2,0.3);
}
col += tmp;
}
col /= float(NUMSAMPLES);
#endif
col = pow( clamp(col,0.0,1.0), float3(0.45) );
return float4( col, 1.0 );
}
ENDCG
}
}
FallBack "Diffuse"
}
[cpp] view
plaincopy
Shader "stalendp/shaderTest05" { //see https://www.shadertoy.com/view/XsB3DW
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
_CubeDiffuse ("Cubemap Diffuse Map", CUBE) = "" {}
vv1("vv1", float) = -1.0
vv2("vv2", float) = 2.0
}
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 3.0
//下面防止编译错误:instruction limit of 1024 exceed;
#pragma glsl
#include "UnityCG.cginc"
#define MAX_STEPS 64
#define MAX_REFLECTIONS 4
#define PI 3.1415926536
sampler2D _MainTex;
samplerCUBE _CubeDiffuse;
float vv1, vv2;
struct Ray {
float3 o;
float3 d;
};
struct Sphere {
float3 o;
float r;
};
struct Box {
float3 o;
float3 s;
};
struct Torus {
float3 o;
float2 s;
};
float2 rotate2d(in float2 v, in float a) {
float sinA = sin(a);
float cosA = cos(a);
return float2(v.x * cosA - v.y * sinA, v.y * cosA + v.x * sinA);
}
float sdSphere(in float3 p, in Sphere s) {
return length(p-s.o)-s.r;
}
float sdBox(in float3 p, in Box b) {
float3 d = abs(p-b.o) - b.s;
return min(max(d.x,max(d.y,d.z)),0.0) +
length(max(d,0.0));
}
float sdTorus(in float3 p, in Torus t) {
p -= t.o;
float2 q = float2(length(p.xz)-t.s.x,p.y);
return length(q)-t.s.y;
}
float world(in float3 p) {
float ti = fmod(_Time.y,10.);
if(ti > 2.) {
Sphere s0 = Sphere(float3(0),1.);
Box b0 = Box(float3(0),float3(.8));
if(ti < 4.) {
return max(-sdSphere(p,s0),sdBox(p,b0));
} else if(ti < 6.) {
return min(sdSphere(p,s0),sdBox(p,b0));
} else if(ti < 8.) {
return max(sdSphere(p,s0),sdBox(p,b0));
} else {
return max(sdSphere(p,s0),-sdBox(p,b0));
}
} else {
float3 pr = p.xzy;
return sdTorus(pr, Torus(float3(0),float2(1.,.5)));
}
}
float3 getNormal(in float3 p) {
float3 d = float3(.005,0,0);
float3 n;
n.x = world(p+d.xyy);
n.y = world(p+d.yxy);
n.z = world(p+d.yyx);
return normalize(n);
}
bool march(in Ray r, out float3 p) {
p = r.o;
float d;
for(int i = 0; i < MAX_STEPS; i++) {
d = world(p);
p += r.d*d;
}
return d<=0.01;
}
float3 colorMarch(in Ray r) {
float3 p;
float3 col = float3(0);
for(int i = 0; i < MAX_REFLECTIONS; i++) {
if(march(r,p)) {
float3 ldir = normalize(float3(1,-1,.5));
float3 n = getNormal(p);
col += float3(dot(n,-ldir))*.25;
r = Ray(p,reflect(r.d,n));
r.o += r.d*0.2;
} else {
break;
}
}
col += texCUBE(_CubeDiffuse, r.d).rgb;
return col;
}
float4 vert(appdata_base v) : POSITION {
return mul(UNITY_MATRIX_MVP, v.vertex);
}
float4 frag(float4 sp:WPOS): COLOR {
float2 uv = 2.*sp.xy/_ScreenParams.xy-1.;
uv.x *= _ScreenParams.x/_ScreenParams.y;
Ray r = Ray(float3(0,0,-2),normalize(float3(uv,1)));
r.o.xz = rotate2d(r.o.xz,_Time.y*.5);
r.d.xz = rotate2d(r.d.xz,_Time.y*.5);
float3 cc =colorMarch(r);
return float4( cc, 1.0 );
}
ENDCG
}
}
FallBack "Diffuse"
}
[cpp] view
plaincopy
Shader "stalendp/myShaderWang" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
wangTex("wang texture", 2D) = "white" {}
disHeight ("texture height", float) = 0.0
}
SubShader {
Tags {"Queue" = "Transparent"}
Pass{
Cull Off
Cull Back // now render the front faces ZWrite Off // don't write to depth buffer
// in order not to occlude other objects
Blend SrcAlpha OneMinusSrcAlpha
// blend based on the fragment's alpha value
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
uniform sampler2D _MainTex;
uniform sampler2D wangTex;
uniform float disHeight;
struct vertexInput {
float4 vertex : POSITION;
float4 texcoord : TEXCOORD0;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 position_in_world_space : TEXCOORD1;
float4 tex : TEXCOORD0;
float4 sp:WPOS;
};
vertexOutput vert(vertexInput input) {
vertexOutput output;
output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
output.position_in_world_space = mul(_Object2World, input.vertex);
output.tex = input.texcoord;
return output;
}
float4 frag(vertexOutput input) : COLOR {
//https://www.shadertoy.com/view/4dsGzH
float3 COLOR1 = float3(0.0, 0.0, 0.3);
float3 COLOR2 = float3(0.5, 0.0, 0.0);
float BLOCK_WIDTH = 0.01;
float2 uv = float2(input.tex);
// To create the BG pattern
float3 final_color = float3(1.0);
float3 bg_color = float3(0.0);
float3 wave_color = float3(0.0);
float c1 = fmod(uv.x, 2.0 * BLOCK_WIDTH);
c1 = step(BLOCK_WIDTH, c1);
float c2 = fmod(uv.y, 2.0 * BLOCK_WIDTH);
c2 = step(BLOCK_WIDTH, c2);
bg_color = lerp(uv.x * COLOR1, uv.y * COLOR2, c1 * c2);
// To create the waves
float wave_width = 0.01;
uv = -1.0 + 2.0 * uv;
uv.y += 0.1;
for(float i = 0.0; i < 1.0; i++) {
uv.y += (0.07 * sin(uv.x + i/7.0 + _Time.y ));
wave_width = abs(1.0 / (150.0 * uv.y));
wave_color += float3(wave_width * 1.9, wave_width, wave_width * 1.5);
}
final_color = bg_color + wave_color;
float pos = input.position_in_world_space.y;
float p1 = saturate((pos - disHeight)*3);
float p2 = saturate((pos - disHeight - 0.5)*3);
float4 non = float4(0.0);
float4 skin = tex2D(_MainTex, float2(input.tex));
float4 wang = tex2D(wangTex, float2(input.tex));
float4 final = lerp(lerp(skin, wang, p1), non, p2);
return final + float4(final_color, 1.0);
}
ENDCG
}
}
FallBack "Diffuse"
}
CGINCLUDE的使用
[cpp] view
plaincopy
Shader "Self-Illumin/AngryBots/InterlacePatternAdditive" {
Properties {
_MainTex ("Base", 2D) = "white" {}
_TintColor ("TintColor", Color) = (1,1,1,1) // needed simply for shader replacement
_InterlacePattern ("InterlacePattern", 2D) = "white" {}
_Illum ("_Illum", 2D) = "white" {}
_EmissionLM ("Emission (Lightmapper)", Float) = 1.0
}
CGINCLUDE
#include "UnityCG.cginc"
sampler2D _MainTex;
sampler2D _InterlacePattern;
half4 _InterlacePattern_ST;
fixed4 _TintColor;
struct v2f {
half4 pos : SV_POSITION;
half2 uv : TEXCOORD0;
half2 uv2 : TEXCOORD1;
};
v2f vert(appdata_full v)
{
v2f o;
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
o.uv.xy = v.texcoord.xy;
o.uv2.xy = TRANSFORM_TEX(v.texcoord.xy, _InterlacePattern) + _Time.xx * _InterlacePattern_ST.zw;
return o;
}
fixed4 frag( v2f i ) : COLOR
{
fixed4 colorTex = tex2D (_MainTex, i.uv);
fixed4 interlace = tex2D (_InterlacePattern, i.uv2);
colorTex *= interlace;
return colorTex;
}
ENDCG
SubShader {
Tags {"RenderType" = "Transparent" "Queue" = "Transparent" "Reflection" = "RenderReflectionTransparentAdd" }
Cull Off
ZWrite Off
Blend One One
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
ENDCG
}
}
FallBack Off
}
相关文章推荐
- 【Linux探索之旅】第三部分第四课:后台运行及合并多个终端
- 为何中国GNU/Linux的话语权掌控在外籍人士手中?
- centos 7安装mysql5.5的方法
- CentOS 7中安装mysql server的步骤分享
- 【Linux探索之旅】第三部分第四课:后台运行及合并多个终端
- 揭秘知名网站如何收集个人数据及应对措施
- JS实现带有抽屉效果的产品类网站多级导航菜单代码
- apache软件包下载地址
- DDNS client on a Linux machine
- How to use USB 3G dongle/stick Huawei E169/E620/E800 ( Chip used Qualcomm e1750) in Linux (China and world)
- 浅谈Linux中的信号处理机制(二)
- GUN,Linux,Linux发行版
- 架构之路(三) 单元测试
- CentOS 7中安装mysql server的步骤分享
- centos 7安装mysql5.5的方法
- 网站内部优化--图6片优化的几个技巧
- 谈谈模板建站那点事
- apache的工作模式
- 对运维工程师的理解
- linux系统调优包括哪些