我想一些代码ShaderToy转换成统一。这是我试图转换的着色器:https://www.shadertoy.com/view/Ws23WD。
我已经成功地编译我的代码,但是,当我看着自己在团结球体着色器,这似乎是一个静态的黄色圆圈。我只改变了语法从ShaderToy到统一当量;什么可以去错了吗?
Shader "Unlit/Lava"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
iChannel0 ("iChannel0", 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;
UNITY_FOG_COORDS(1)
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
sampler2D iChannel0;
float4 _MainTex_ST;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}
#define pi (3.14159265358979323846)
#define EPSILON (0.0001)
float2 rotate(float2 v, float a)
{
float c = cos(a);
float s = sin(a);
return float2(
v.x*c-v.y*s,
v.x*s+v.y*c
);
}
float sphere(float3 p, float r)
{
return length(p)-r;
}
float scene(float3 p)
{
float b = sphere(p, 1.6);
if(b > 0.001) return b; // optimisation
float3 disp = 0;
float f = 0.5;
disp.x = tex2D(iChannel0, p.zy * 0.05 + _Time.y * 0.02).x * f;
disp.z = tex2D(iChannel0, p.xy * 0.05 + _Time.y * 0.03).z * f;
disp.y = tex2D(iChannel0, p.xz * 0.05 + _Time.y * 0.04).y * f;
return sphere(p + disp, 1.0 + sin(_Time.y*2.4) * 0.15);
}
fixed4 frag (v2f i) : SV_Target
{
//float2 uv = float2(fragCoord.x / iResolution.x, fragCoord.y / iResolution.y);
float2 uv = float2(i.uv);
uv -= 0.5;
//uv /= float2(iResolution.y / iResolution.x, 1);
float3 cam = float3(0, -0.15, -3.5);
float3 dir = normalize(float3(uv,1));
float cam_a2 = sin(_Time.y) * pi * 0.1;
cam.yz = rotate(cam.yz, cam_a2);
dir.yz = rotate(dir.yz, cam_a2);
float cam_a = _Time.y * pi * 0.1;
cam.xz = rotate(cam.xz, cam_a);
dir.xz = rotate(dir.xz, cam_a);
float4 color = float4(0.16, 0.12, 0.10, 1.0);
float t = 0.00001;
const int maxSteps = 128;
for(int i = 0; i < maxSteps; ++i) {
float3 p = cam + dir * t;
float d = scene(p);
if(d < 0.0001 * t) {
color = float4(1.0, length(p) * (0.6 + (sin(_Time.y*3.0)+1.0) * 0.5 * 0.4), 0, 0);
break;
}
t += d;
}
//fragColor.rgb = color;
return color;
//fragColor.a = 1.0;
}
ENDCG
}
}
}
我做了一些更改您的着色器。主要用于将UV计算和alpha混合设置。
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "Unlit/Lava"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
iChannel0 ("iChannel0", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="TransparentCutout" }
LOD 100
Blend OneMinusSrcAlpha SrcAlpha // Specify blend mode. This is inverted from usual usage.
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag lambert alpha:blend // Enable alpha blend
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
UNITY_FOG_COORDS(1)
float4 vertex : SV_POSITION;
float4 screenPos : TEXCOORD1;
};
sampler2D _MainTex;
sampler2D iChannel0;
float4 _MainTex_ST;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.screenPos = ComputeScreenPos(o.vertex);
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}
#define pi (3.14159265358979323846)
#define EPSILON (0.0001)
float2 rotate(float2 v, float a)
{
float c = cos(a);
float s = sin(a);
return float2(
v.x*c-v.y*s,
v.x*s+v.y*c
);
}
float sphere(float3 p, float r)
{
return length(p)-r;
}
float scene(float3 p)
{
float b = sphere(p, 1.6);
if(b > 0.001) return b; // optimisation
float3 disp = 0;
float f = 0.5;
disp.x = tex2D(iChannel0, p.zy * 0.05 + _Time.y * 0.02).x * f;
disp.z = tex2D(iChannel0, p.xy * 0.05 + _Time.y * 0.03).z * f;
disp.y = tex2D(iChannel0, p.xz * 0.05 + _Time.y * 0.04).y * f;
return sphere(p + disp, 1.0 + sin(_Time.y*2.4) * 0.15);
}
fixed4 frag (v2f i) : SV_Target
{
//float2 uv = float2(fragCoord.x / iResolution.x, fragCoord.y / iResolution.y);
float2 uv = float2(i.screenPos.x , i.screenPos.y); // Unity equivalent of the above
uv -= 0.5;
uv /= float2((_ScreenParams.y / _ScreenParams.x)*0.5, (_ScreenParams.y / _ScreenParams.x)*0.5); // Shrink the globule
float3 cam = float3(0, -0.15, -3.5);
float3 dir = normalize(float3(uv,1));
float cam_a2 = sin(_Time.y) * pi * 0.1;
cam.yz = rotate(cam.yz, cam_a2);
dir.yz = rotate(dir.yz, cam_a2);
float cam_a = _Time.y * pi * 0.1;
cam.xz = rotate(cam.xz, cam_a);
dir.xz = rotate(dir.xz, cam_a);
float4 color = float4(0.16, 0.12, 0.10, 1.0);
float t = 0.00001;
const int maxSteps = 128;
for(int i = 0; i < maxSteps; ++i) {
float3 p = cam + dir * t;
float d = scene(p);
if(d < 0.0001 * t) {
color = float4(1.0, length(p) * (0.6 + (sin(_Time.y*3.0)+1.0) * 0.5 * 0.4), 0, 0);
break;
}
t += d;
}
return color;
}
ENDCG
}
}
}
其结果是不完美的,但更接近:
我觉得跟ShaderToy着色器的问题是,它是为屏幕空间。你会看到,当你移动相机,熔岩怪胎。我想这是因为屏幕空间紫外计算。你需要找到一个不同的方法。
祝好运