Ventuz目前主要用于一些大型展会,三维实时交互,工业流程以及数据的可视化展示。
Shader在Ventuz中的使用可以使得效果变得更加炫酷。
1.搬运shadertoy中的效果
首先按照网上已有的词语替换规则修改代码
替换规则很容易查到
第二步 将渲染的效果固定到rect上
直接搬运的效果的uv坐标是通过:vec2 uv = fragCoord.xy / iResolution.xy;计算而来的(iResolution.xy/res.xy是固定值,按照工程的实际分辨率设定)
这个计算式是将rect中的每一点的uv值放入全屏幕空间,判断了该点在全屏幕空间的相对位置,这使得渲染的图案并不会跟从rect移动,形成一种shader在全屏渲染但是只能看到rect存在的部分的图案的错觉。
解决方法,更改与uv相关的计算公式,全部使用Input.uv进行计算
三、一个从shadertoy上面扒下来的火焰效果小例子
uniform float time;
#define MAX_ITER 22
float2 res;
float velocity=1.5 ;
#define detail_steps_ 26
#define mod3_ float3(.1031, .11369, .13787)
float offScale=0.5;
float3 hash3_3(float3 p3);
float perlin_noise3(float3 p);
float noise_sum_abs3(float3 p);
float2 domain(float2 uv, float s);
float4 Color
<
string SasUiControl = "ColorPicker";
string SasUiLabel = "Color";
> = { 1.0f, 1.0f, 1.0f, 1.0f };
float4x4 WorldViewProjection : WORLDVIEWPROJECTION;
struct VS_INPUT
{
float4 Position : POSITION;
float2 uv : TEXCOORD0;
};
//飘动的参数
float _Magnitude;
float _Frequency;
float _InvWaveLength;
float _Speed;
//火焰参数
float2 moveUV(float2 vertUV)
{
float textureNum = 12.0;
float timePerFrame = 100;
float index = frac(time%(textureNum * timePerFrame));
float2 uvScale = float2(1 / textureNum*10, 1);
if(index <= uvScale.x)
return vertUV * uvScale;
else if(index <= 2 * uvScale.x)
return vertUV * uvScale + float2(uvScale.x, 0.0);
else if(index <= 3 * uvScale.x)
return vertUV * uvScale + float2(2 * uvScale.x, 0.0);
else if(index <= 4 * uvScale.x)
return vertUV * uvScale + float2(3 * uvScale.x, 0.0);
else if(index <= 5 * uvScale.x)
return vertUV * uvScale + float2(4 * uvScale.x, 0.0);
else if(index <= 6 * uvScale.x)
return vertUV * uvScale + float2(5 * uvScale.x, 0.0);
else if(index <= 7 * uvScale.x)
return vertUV * uvScale + float2(6 * uvScale.x, 0.0);
else if(index <= 8 * uvScale.x)
return vertUV * uvScale + float2(7 * uvScale.x, 0.0);
else if(index <= 9 * uvScale.x)
return vertUV * uvScale + float2(8 * uvScale.x, 0.0);
else if(index <= 10 * uvScale.x)
return vertUV * uvScale + float2(9 * uvScale.x, 0.0);
else if(index <= 11 * uvScale.x)
return vertUV * uvScale + float2(10 * uvScale.x, 0.0);
else
return vertUV * uvScale + float2(11 * uvScale.x, 0.0);
}
struct VS_OUTPUT
{
float4 Position : POSITION;
float2 uv : TEXCOORD0;
};
VS_OUTPUT VS( VS_INPUT Input )
{
VS_OUTPUT Output;
float4 offset=float4(0,0,0,0);
Output.Position = mul(Input.Position, WorldViewProjection);
offset.x = sin(3.1416 * time *40* clamp(-Input.uv.y+1, 0, 1)) * offScale;//摆动
Output.Position.x+=offset.x;
Output.uv=Input.uv;
// Output.uv=moveUV(Input.uv);
return Output;
}
float noise(float3 p) //Thx to Las^Mercury
{
float3 i = floor(p);
float4 a = dot(i, float3(1., 57., 21.)) + float4(0., 57., 21., 78.);
float3 f = cos((p-i)*acos(-1.))*(-.5)+.5;
a = lerp(sin(cos(a)*a),sin(cos(1.+a)*(1.+a)), f.x);
a.xy = lerp(a.xz, a.yw, f.y);
return lerp(a.x, a.y, f.z);
}
float sphere(float3 p, float4 spr)
{
return length(spr.xyz-p) - spr.w;
}
float flame(float3 p)
{
float d = sphere(p*float3(1.,.5,1.), float4(.0,-1.,.0,1.));
return d + (noise(p+float3(.0,time*200.,.0)) + noise(p*3.)*.5)*.25*(p.y) ;
}
float scene(float3 p)
{
return min(100.-length(p) , abs(flame(p)) );
}
float4 raymarch(float3 org, float3 dir)
{
float d = 0.0, glow = 0.0, eps = 0.02;
float3 p = org;
bool glowed = false;
for(int i=0; i<64; i++)
{
d = scene(p) + eps;
p += d * dir;
if( d>eps )
{
if(flame(p) < .0)
glowed=true;
if(glowed)
glow = float(i)/64.0;
}
}
return float4(p,glow);
}
float4 PS(VS_OUTPUT i ) : COLOR
{
float2 v = 1.0 - 2.0 *i.uv;
v=v*2;
v.y+=1;
float3 org = float3(0.0, -2.0, 4.0);
float3 dir = normalize(float3(v.x*1.6, -v.y, -1.5));
float4 p = raymarch(org, dir);
float glow = p.w;
float4 col = lerp(float4(1.0,0.5,0.1,1.0), float4(0.1,0.5,1.0,1.0), p.y*0.02+.4);
float4 screenSpace = lerp(float4(0.0,0.0,0.0,0), col, pow(glow*2.0,4.0));
// screenSpace.a=0.8;
return screenSpace;
}
technique Tech1
{
pass pass0
{
vertexshader = compile vs_3_0 VS();
pixelshader = compile ps_3_0 PS();
}
}