Unity'de “ıslak yüzey” / “sığ su birikintisi” gölgelendiriciyi nasıl yapabilirim?


71

Oyunumda dinamik su birikintileri oluşturmam gerekiyor ama nasıl bir etki yaratabileceğimi gösteren bir öğretici bulamıyorum (bunun bir örneği aşağıda gösterilmiştir). Nasıl yapabilirim?

Kuantum kırılması


4
Bu kadar yüksek oylu soruyu ve yüksek oylu cevabı kapatılmadığını görmek can sıkıcı. Kendi cevabınızı seçmek en iyisidir, kendinize ödül almak için biraz saçma olsa :)
Tim Holt

@TimHolt Ancak buna benzer bir soruyu hangi temelde kapatırız? Konuyla mükemmel görünüyor.
Josh

Bunu isteyen kişinin kendi cevabını kabul etmesi gerektiğini söylüyorum. Afedersin, İngilizce'yi kötüye kullandım.
Tim Holt

Yanıtlar:


121

yansıma

Islak bir gölgelendirici oluşturmak için önce bir yansıması olması gerekir.

SimpleRoad

Bir Reflection Probe veya MirrorReflection3 kullanabilirsiniz, ancak gölgelendirici daha sonra mobil cihazda kullanılabildiği için burada sahte bir yansıma (Cube Map) kullanıyorum.

yansıma

Shader "Smkgames/TransparentCubeMap" {
Properties {
_Color("Color",Color) = (1,1,1,1)
_Cube ("Cubemap", CUBE) = "" {}
_Metallic("Metallic",Range(0,1)) = 1
_Smoothness("Smoothness",Range(0,1)) = 1
_Alpha("Alpha",Range(0,1)) = 1
}
SubShader {
Tags {"RenderType"="Transparent" "Queue"="Transparent"}
LOD 200
Pass {
ColorMask 0
}
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
ColorMask RGB

CGPROGRAM
#pragma surface surf Standard fullforwardshadows alpha:fade

struct Input {
float2 uv_MainTex;
float3 worldRefl;
};
sampler2D _MainTex;
samplerCUBE _Cube;
float4 _Color;
float _Metallic;
float _Smoothness;
float4 _EmissionColor;
float _Alpha;
void surf (Input IN, inout SurfaceOutputStandard o) {
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;

o.Albedo = c.rgb * 0.5 * _Color;
o.Emission = texCUBE (_Cube, IN.worldRefl).rgb*_Color;
o.Metallic = _Metallic;
o.Smoothness = _Smoothness;
o.Alpha = _Alpha;

}
ENDCG
} 
Fallback "Diffuse"
}

Çarpıtma

Yansımasına bozulma eklemek için normal haritayı ve şunu çarpabilirsiniz worldRefl:

float3 distortion = tex2D(_Distortion, IN.uv_Distortion);
o.Emission = texCUBE(_Cube, IN.worldRefl*distortion).rgb

çarpıtma

Prosedür şekli

Prosedürel bir şekil oluşturmak için gürültüyü kullanabilirsiniz :

ele geçirmek

İşte bir Fractal Brownian Motion (FBM) dersi .

Shader "Smkgames/FbmNoise"
{
Properties
{
_TileAndOffset("Tile and Offset",Vector) = (1,1,0,0)
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100

Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// make fog work
#pragma multi_compile_fog

#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 _TileAndOffset;
float _Step,_Min,_Ma;

v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv*_TileAndOffset.xy+_TileAndOffset.zw;
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}

// Author @patriciogv - 2015
// http://patriciogonzalezvivo.com

float random (in float2 st) {
return frac(sin(dot(st.xy,
                    float2(12.9898,78.233)))*
    43758.5453123);
}

// Based on Morgan McGuire @morgan3d
// https://www.shadertoy.com/view/4dS3Wd
float noise (in float2 st) {
float2 i = floor(st);
float2 f = frac(st);

// Four corners in 2D of a tile
float a = random(i);
float b = random(i + float2(1.0, 0.0));
float c = random(i + float2(0.0, 1.0));
float d = random(i + float2(1.0, 1.0));

float2 u = f * f * (3.0 - 2.0 * f);

return lerp(a, b, u.x) +
        (c - a)* u.y * (1.0 - u.x) +
        (d - b) * u.x * u.y;
}

#define OCTAVES 6
float fbm (in float2 st) {
// Initial values
float value = 0.0;
float amplitude = .5;
float frequency = 0.;
//
// Loop of octaves
for (int i = 0; i < OCTAVES; i++) {
    value += amplitude * noise(st);
    st *= 2.;
    amplitude *= .5;
}
return value;
}

        fixed4 frag (v2f i) : SV_Target
        {


float2 st =i.uv;

float3 color = float3(0,0,0);
color += fbm(st*3.0);
return float4(color,1.0);

        }
ENDCG
}
}
}

Yukarıdaki FBM doğrudan gölgelendiricinizde kullanılmamalıdır, çünkü birçok GPU hesaplaması vardır ve performansı düşürür. Doğrudan kullanmak yerine, sonucu RenderTexture ile bir dokuya dönüştürebilirsiniz .

Shadertoy "tampon" başına bir tane olmak üzere birden çok geçiş kullanır . Adından da anlaşılacağı gibi, bu geçiş sonuçları yalnızca bir doku olan bir arabellekte saklar. Birlik size de dokuları oluşturmanıza izin verecektir.

2018-01-26_10-18-20

Maske Oluşturmak

Bu işlevlerle kalın ve pürüzsüz bir maske yapabilirsiniz:

Adım

adım

Eğer Çıkışlar 1 [A]den daha az veya eşit olan [B], aksi takdirde, 0 verir.

Smoothstep

smoothstep

Üçüncü bir değerin bu aralıkta olduğu yere göre 0 ile 1 arasında değerler vererek, iki değer arasında sorunsuzca karışır. Bunu, düzeltilmiş bir çıktı değerine sahip kelepçeli bir ters lp olarak düşünün.

Sonuç

/* Warning: don't use this shader because this is for preview only.
It has many GPU calculations so if you want use this in your game you should 
remove the FBM noise functions or render it to texture, or you can use an FBM texture
*/
//Created By Seyed Morteza Kamaly
Shader "Smkgames/WetShader" {
Properties{
_MainTex("MainTex",2D) = "white"{}
_Distortion("Distortion",2D) = "bump"{}
_Cube("Cubemap", CUBE) = "" {}
_BumpMap("Bumpmap", 2D) = "bump" {}
_Metallic("Metallic",Range(0,1)) = 0
_Smoothness("Smoothness",Range(0,1)) = 1
_ReflectAlpha("ReflectAlpha",Range(0,1)) = 1
scaleX("UV.X scale",Float) = 10.0
scaleY("UV.Y scale",Float) = 10.0
_Smooth("Smooth",Float) = 0.4
_Intensity("Intensity",Float) = 1
}
SubShader{
Tags{ "RenderType" = "Transparent" "Queue" = "Transparent" }
LOD 200
Pass{
ColorMask 0
}
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
ColorMask RGB

CGPROGRAM
#pragma surface surf Standard fullforwardshadows alpha:fade

struct Input {
float2 uv_MainTex;
float2 uv_Distortion;
float3 worldRefl;
float2 uv_BumpMap;
INTERNAL_DATA
};
sampler2D _MainTex, _Distortion;
samplerCUBE _Cube;
float _Metallic,_Smoothness;
float4 _EmissionColor;
sampler2D _NormalMap;
uniform fixed scaleX, scaleY, _Smooth, _Intensity,_Alpha,_ReflectAlpha;

static const float2x2 m = float2x2(-0.5, 0.8, 1.7, 0.2);

float hash(float2 n)
{
return frac(sin(dot(n, float2(95.43583, 93.323197))) * 65536.32);
}

float noise(float2 p)
{
float2 i = floor(p);
float2 u = frac(p);
u = u*u*(3.0 - 2.0*u);
float2 d = float2 (1.0, 0.0);
float r = lerp(lerp(hash(i), hash(i + d.xy), u.x), lerp(hash(i + d.yx), hash(i + d.xx), u.x), u.y);
return r*r;
}

float fbm(float2 p)
{
float f = 0.0;
f += 0.500000*(0.5 + 0.5*noise(p));
return f;
}

float fbm2(float2 p)
{
float f = 0.0;
f += 0.500000*(0.6 + 0.45*noise(p)); p = p*2.02; p = mul(p, m);
f += 0.250000*(0.6 + 0.36*noise(p));
return f;
}


void surf(Input IN, inout SurfaceOutputStandard o) {
fixed4 c = tex2D(_MainTex, IN.uv_MainTex);

o.Metallic = _Metallic;
o.Smoothness = _Smoothness;
o.Alpha = 1;

float t = fbm2(float2(IN.uv_MainTex.x*scaleX, IN.uv_MainTex.y*scaleY));

float fbmMask = step(t, _Smooth)*_Intensity;
float3 distortion = tex2D(_Distortion, IN.uv_Distortion);
o.Emission = texCUBE(_Cube, IN.worldRefl*distortion).rgb*_ReflectAlpha*fbmMask;

o.Albedo = float4(1.0, 1.0, 1.0, 1.0)*tex2Dlod(_MainTex, float4(IN.uv_MainTex, 0.0, 0.0));


}
ENDCG
}
Fallback "Diffuse"
}

görüntü

Haritalar'ı kullanma

shaderToy Fiziksel Bazlı Gölgelendirme

İşte yararlı bir tanım:

Pürüzlülük Nesnenin mikro yüzeyini açıklar. Beyaz 1.0 pürüzlü ve siyah 0.0 pürüzsüzdür. Pürüzlü ise mikro yüzey ışık ışınlarının dağılmasına ve vurgunun daha koyu ve daha geniş görünmesine neden olabilir. Aynı miktarda ışık enerjisi, yüzeye çıkarken ortaya çıkıyor. Bu harita en sanatsal özgürlüğe sahip. Burada yanlış cevap yok. Bu harita, çizime, parmak izlerine, lekelere, kir vb.

Parlaklık Bu harita pürüzlülük haritasının tersidir. Beyaz 1.0 pürüzsüz ve 0.0 siyah pürüzlüdür. Nesnenin mikro yüzeyini açıklar. Pürüzlü ise mikro yüzey ışık ışınlarının dağılmasına ve vurgunun daha koyu ve daha geniş görünmesine neden olabilir. Aynı miktarda ışık enerjisi, yüzeye çıkarken ortaya çıkıyor. Bu harita en sanatsal özgürlüğe sahip. Burada yanlış cevap yok. Bu harita, çizime, parmak izlerine, lekelere, kir vb.

Speküler Bu harita hem metal hem de dielektrik (metal olmayan) yüzeylerin yansıma bilgilerini içerir. Bu metal / kaba ve spec / gloss iş akışlarında önemli bir farktır. Aynı kurallar geçerlidir. Metaller için ölçülen değerleri kullanmanız gerekir ve çoğu dielektrik çoğu% 0.04 - 4 aralığında olacaktır. Metal üzerinde kir varsa, yansıtma değerinin de düşürülmesi gerekir. Ancak, dielektrik materyaller için speküler haritada farklı değerler ekleyebilirsiniz, çünkü haritayı kontrol etme yetkiniz vardır.

https://forum.allegorithmic.com/index.php?topic=3243.0

pürüzlülük

görüntü

Nedenini bilmiyorum ama Unity standart gölgelendiricinin düzgünlük haritası yok, bu yüzden temel bir gölgelendirici yazdım ve bu haritayı ekledim.

Shader "Smkgames/SimpleSurface" {
    Properties {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _GlossMap("GlossMap",2D) = "white"{}
        _Glossiness ("Smoothness", Float) = 1.5
        _Metallic ("Metallic", Float) = 0.5
        _MetallicMap("MetallicMap",2D) = "white"{}
    }
    SubShader {
        Tags { "RenderType"="Opaque" }
        LOD 200

        CGPROGRAM
        #pragma surface surf Standard fullforwardshadows

        #pragma target 3.0

        sampler2D _MainTex;

        struct Input {
            float2 uv_MainTex;
        };

        half _Glossiness,_Metallic;
        fixed4 _Color;
        sampler2D _GlossMap,_MetallicMap;

        UNITY_INSTANCING_CBUFFER_START(Props)
        UNITY_INSTANCING_CBUFFER_END

        void surf (Input IN, inout SurfaceOutputStandard o) {
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
            o.Albedo = c.rgb;
            o.Metallic = _Metallic*tex2D(_MetallicMap,IN.uv_MainTex);
            o.Smoothness = _Glossiness*tex2D(_GlossMap,IN.uv_MainTex);
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

Birliğin pürüzlülük olmadığını, sadece metalik olduğunu düşünüyorum, ancak alfa kanalı pürüzlülük için ve kırmızı kanal metalik için. Yoğunluğu pürüzsüzlükle değiştirebilirsiniz.

GitHub'daki kaynak .

Kullanışlı bağlantılar

çamur küre 1024x576

https://80.lv/articles/how-to-create-wet-mud-in-substance-designer/

https://www.fxguide.com/featured/game-environments-partc/


39
Vay canına, soru-cevap sitesinde tüm bir gölgelendirici eğitimi serisi yaptınız.
Ocelot

6
@Ocelot Seyed'in bunlara gittikçe daha fazla eklemeye devam etmesini seviyorum. Gölgelendiricilerle bağlantı kurmayı seviyorum ve bunlar daha fazla fikir ve öğreticiler için gerçekten yararlı. Bunları sonsuza dek ilan etmeye devam edebilir.
John Hamilton

7
Şaşırtıcı cevap. Gölgelendiricilerle çalışmak çok zordur ve istediğim etkiyi elde etmek için saatler süren titizlik, araştırma, deneme ve yanılma ile diğer gölgelendiricilerin incelenmesi gerekir. Ve burada bunu başkası için bedava yapıyorsun.
Draco18,

1
Standart Malzemeler için pürüzlülüğü metalik veya normal haritaya yerleştirmek en iyisidir (eski varsayılandır). Pürüzlülük sağlayan uygun bir metal oluşturmak için Fotoğraf Mağazası, Boya Mağazası veya Gimp'i kullanmanızı tavsiye ederim. Alternatif olarak, Madde Boyacısı veya benzerleri varsa, pürüzlülüğünüzü tam olarak Unity'nin istediği şekilde dışa aktarabilir ve materyallerinizi Unity'ye koymadan önce görselleştirme avantajından yararlanabilirsiniz.
David Peterson,

bir bilgin ve bir beyefendi
Bas Smit
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.