为什么我的着色器的代码ShaderToy转换为统一后出现静电?

问题描述 投票:0回答:2

我想一些代码ShaderToy转换成统一。这是我试图转换的着色器:https://www.shadertoy.com/view/Ws23WD

我已经成功地编译我的代码,但是,当我看着自己在团结球体着色器,这似乎是一个静态的黄色圆圈。我只改变了语法从ShaderToy到统一当量;什么可以去错了吗?

enter image description here

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
        }
    }
}
unity3d shader
2个回答
0
投票

你需要按下PLAY按钮来查看着色器的动画。

着色器的工作原理。

Shader works well


0
投票

我做了一些更改您的着色器。主要用于将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
        }
    }
}

其结果是不完美的,但更接近:

Lava

我觉得跟ShaderToy着色器的问题是,它是为屏幕空间。你会看到,当你移动相机,熔岩怪胎。我想这是因为屏幕空间紫外计算。你需要找到一个不同的方法。

祝好运

© www.soinside.com 2019 - 2024. All rights reserved.