- Home /
Porting from ShaderToy(GLSL) to shaderlab(HLSL/CG) unity not giving me the desired result.
I came across this beautiful shader from shadertoy which I am trying to implement in Unity. I managed to get the blur box background and also the random dots get generated. But I am not able to get the curl effect as shown in the original shader. Here is my code, where _MainText
takes the default colour black and _MainTexBg
has this texture attached,
Shader "Unlit/MyFirstShader"
{
Properties
{
_MainTex ("Texture", 2D) = "black" {}
_MainTexBg ("Curl Pattern 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 _MainTex;
float4 _MainTex_ST;
sampler2D _MainTexBg;
float4 _MainTexBg_ST;
float2 hash2( float n )
{
return frac(sin(float2(n,n+1.0))*float2(43758.5453123,22578.1459123));
}
// smoothstep interpolation of texture
float4 ssamp( float2 uv, float oct )
{
uv = uv.xy / oct;
//return texture( iChannel0, uv, -10.0 );
float texSize = 8.;
float2 x = uv * texSize - .5;
float2 f = frac(x);
// remove fractional part
x = x - f;
// apply smoothstep to fractional part
f = f*f*(3.0-2.0*f);
// reapply fractional part
x = x + f;
uv = (x+.5) / texSize;
return tex2D( _MainTexBg, uv );
}
float2 e = float2(1./256., 0.);
float4 dx( float2 uv, float oct )
{
return (ssamp(uv+e.xy,oct) - ssamp(uv-e.xy,oct)) / (2.*e.x);
}
float4 dy( float2 uv, float oct )
{
return (ssamp(uv+e.yx,oct) - ssamp(uv-e.yx,oct)) / (2.*e.x);
}
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
i.uv=1-i.uv;
fixed4 col = tex2D(_MainTex, i.uv);
col=mul(col,2.0);
col = smoothstep(0.,1.,col);
col.xyz = 1.-col.xyz;
col.xyz = mul(col.xyz,pow(1. - 1.9*dot(i.uv-.5,i.uv-.5),.07));
float4 res = float4(0.,0.,0.,0.);
float scl = _ScreenParams.x/640.;
// random paint drops
//float fr = float(_Time.y);
float period = _Time.y < 2.9 ? 30. : _Time.y < 47. ? 8. : 3.;
float2 sparkPos = hash2(_Time.y+1.11) * _ScreenParams.xy;
if( length(sparkPos-i.vertex)<5.*scl && i.vertex.x > 1. && i.vertex.y > 1. )
{
// everyones favourite colour gradient
res = res + 2.5*float4(i.uv,0.5+0.5*sin(_Time.y),1.0);
}
float2 off = 0.* (float2(128.,128.)/_ScreenParams.xy) * unity_DeltaTime;
float oct = .25;
float2 curl1 = .001*float2( dy(i.uv,oct).x, -dx(i.uv,oct).x )*oct;
oct = 5.; float sp = 0.1;
curl1 = curl1 + .0002*float2( dy(i.uv+sp*_Time.y,oct).x, -dx(i.uv+sp*_Time.y,oct).x )*oct;
off = off + curl1;
off = mul(off,.4);
res = res + .999*tex2D( _MainTexBg, i.uv - off);
return col*res;
}
ENDCG
}
}
}
I am very new to shader programming. Thanks for your help.
Answer by villevli · Jan 12, 2018 at 01:01 PM
I managed to import this shader to Unity. I attached a zip that you can export to your Assets folder.
Relevant parts of the rendering code:
Create a RenderTexture and assign it to bufferA_RT
.
In OnPostRender() - (script attached to a Camera):
var screenTarget = RenderTexture.active;
// pass input channels
bufferA_Material.SetTexture(iChannel0_Id, bufferA_RT);
bufferA_Material.SetTexture(iChannel1_Id, bufferA_Channel1InputTexture);
// we need to render to a temporary buffer because rendering to a buffer that is used as shader input causes problems
var tempBuf = RenderTexture.GetTemporary(bufferA_RT.width, bufferA_RT.height, bufferA_RT.depth, bufferA_RT.format, RenderTextureReadWrite.Linear, bufferA_RT.antiAliasing);
Graphics.Blit(null, tempBuf, bufferA_Material);
Graphics.Blit(tempBuf, bufferA_RT);
RenderTexture.ReleaseTemporary(tempBuf);
// render to screen and use Image shader
image_Material.SetTexture(iChannel0_Id, bufferA_RT);
Graphics.Blit(null, screenTarget, image_Material);
Shader for Buf A - ( bufferA_Material
uses this):
Shader "ShaderToy/KindergartenArtClass3-BufA"
{
Properties
{
_Channel0 ("iChannel0", 2D) = "black" {}
_Channel1 ("iChannel1", 2D) = "black" {}
}
SubShader
{
// No culling or depth
Cull Off ZWrite Off ZTest Always
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;
};
/*
Common variables/functions for ShaderToy fragment programs
*/
#define iChannel0 _Channel0
sampler2D iChannel0;
#define iChannel1 _Channel1
sampler2D iChannel1;
#define iResolution _ScreenParams
// float3;
#define iTime _Time.y
// float;
#define iTimeDelta unity_DeltaTime.x
// float;
#define iFrame ((int)(_Time.y / iTimeDelta))
// int;
#define iMouse _MousePos
float4 iMouse;
float mod(float x, float y) { return x - y * floor(x / y); }
/*
Common shader mains for ShaderToy fragment programs
*/
void mainImage(out float4 fragColor, float2 fragCoord);
v2f vert(appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv * iResolution.xy;
return o;
}
fixed4 frag(v2f i) : SV_Target
{
float4 fragColor;
mainImage(fragColor, i.uv);
return fragColor;
}
/*
Kindergarten Art Class III - Buf A
https://www.shadertoy.com/view/4ltXR4
*/
float2 hash2(float n) { return frac(sin(float2(n, n + 1.0))*float2(43758.5453123, 22578.1459123)); }
// smoothstep interpolation of texture
float4 ssamp(float2 uv, float oct)
{
uv /= oct;
//return tex2D( iChannel0, uv, -10.0 );
float texSize = 8.;
float2 x = uv * texSize - .5;
float2 f = frac(x);
// remove fractional part
x -= f;
// apply smoothstep to fractional part
f = f * f*(3.0 - 2.0*f);
// reapply fractional part
x += f;
uv = (x + .5) / texSize;
//uv.y = 1 - uv.y;
//return tex2D(iChannel1, uv);
return tex2Dbias(iChannel1, float4(uv, 0., -10.0));
}
// it's important to mark this static as otherwise it will not contain the assigned value
static float2 e = float2(1. / 256., 0.);
float4 dx(float2 uv, float oct) { return (ssamp(uv + e.xy, oct) - ssamp(uv - e.xy, oct)) / (2.*e.x); }
float4 dy(float2 uv, float oct) { return (ssamp(uv + e.yx, oct) - ssamp(uv - e.yx, oct)) / (2.*e.x); }
void mainImage(out float4 fragColor, float2 fragCoord)
{
float2 uv = fragCoord / iResolution.xy;
float4 res = (float4)0.;
float scl = iResolution.x / 640.;
// random paint drops
float fr = float(iFrame);
float period = iTime < 2.9 ? 30. : iTime < 47. ? 8. : 3.;
if (mod(fr, period) == 0.)
{
float2 sparkPos = hash2(iTime + 1.11) * iResolution.xy;
if (length(sparkPos - fragCoord)<5.*scl && fragCoord.x > 1. && fragCoord.y > 1.)
{
// everyones favourite colour gradient
res += 2.5*float4(uv, 0.5 + 0.5*sin(iTime), 1.0);
}
}
// mouse paint
if (length(fragCoord - iMouse.xy) < 5.*scl && iMouse.z > 0.)
{
// added sin gives pulsing feel
res += .7*float4(uv, 0.5 + 0.5*sin(iTime), 1.0)*(.6 + .5*-sin(iTime*10.5));
}
// lookup offset
float2 off = 0.* ((float2)128. / iResolution.xy) * iTimeDelta;
float oct = .25;
float2 curl1 = .001*float2(dy(uv, oct).x, -dx(uv, oct).x)*oct;
oct = 5.; float sp = 0.1;
curl1 += .0002*float2(dy(uv + sp * iTime, oct).x, -dx(uv + sp * iTime, oct).x)*oct;
off += curl1;
off *= .4;
res += .999*tex2D(iChannel0, uv - off);
fragColor = res;
}
ENDCG
}
}
}
As you can see I used some macros to ease the conversion.
Neatly documented. Well explained. Works perfect. You are awesome! Thank you. #myshaderprogram$$anonymous$$gskill++
Answer by Buckslice · Jan 10, 2018 at 06:24 PM
I believe you need two separate shaders. The main large shader you have here ("Buf A" code in shadertoy) would be rendered into a RenderTexture and then another shader (the "Image" code in shadertoy) would render that RenderTexture to the screen or a quad or something.
I came across this article and tried to combine both the textures from 'Buf A' and 'Image' together. Can you help me by pointing to some refference where multiple shaders are implemented in unity?
Read up about CustomRenderTextures I think they will work for what you are trying to do. Basically modifying a texture over time with a shader is what they are for. Here is a nice project demonstrating their usage, maybe this code will help you.
Your answer
Follow this Question
Related Questions
Flat Shading / No Vertex Interpolation 2 Answers
regarding Shader Optimization 0 Answers
Obtaining relative speed of vertex in a shader 1 Answer
Can this shader run in unity? 1 Answer
ShaderLab builtin lighting properties are not correct? 0 Answers