ฉันจะสร้าง "พื้นผิวเปียก" / "แอ่งน้ำตื้น" ใน Unity ได้อย่างไร


71

ในเกมของฉันฉันต้องสร้างแอ่งน้ำแบบไดนามิก แต่ฉันไม่สามารถหาบทช่วยสอนที่แสดงให้เห็นว่าฉันสามารถสร้างเอฟเฟกต์ได้อย่างไร (ตัวอย่างที่แสดงด้านล่าง) ฉันจะทำมันได้อย่างไร

ควอนตัมเบรค


4
น่ารำคาญที่เห็นคำถามที่โหวตแล้วและไม่ได้ปิด มันเป็นเรื่องปกติที่จะเลือกคำตอบของคุณเองเป็นดีที่สุดแม้เพียงเล็กน้อยโง่ที่จะเรียกร้องเงินรางวัลสำหรับตัวคุณเอง :)
ทิมโฮลท์

@ TimHolt เราจะปิดคำถามพื้นฐานเช่นนี้ได้อย่างไร ดูเหมือนว่าสมบูรณ์ในหัวข้อ
Josh

ฉันกำลังบอกว่าคนที่ถามควรยอมรับคำตอบของเขาเอง ให้อภัยการใช้ภาษาอังกฤษในทางที่ผิดของฉัน
Tim Holt

คำตอบ:


121

การสะท้อน

ในการสร้าง shader เปียกก่อนอื่นคุณต้องมีการสะท้อน

SimpleRoad

คุณสามารถใช้Reflection ProbeหรือMirrorReflection3แต่ฉันใช้การสะท้อนกลับปลอม (Cube Map) ที่นี่เพราะ shader สามารถใช้บนมือถือได้

การสะท้อน

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"
}

การบิดเบือน

ในการเพิ่มความผิดเพี้ยนให้กับภาพสะท้อนของคุณคุณสามารถคูณแผนที่ปกติและworldRefl:

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

การบิดเบือน

รูปร่างวิธีการ

คุณสามารถใช้เสียงเพื่อสร้างรูปร่างของขั้นตอน :

การจับกุม

นี่เป็นเศษส่วน Brownian Motion (FBM) กวดวิชา

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
}
}
}

FBM ด้านบนไม่ควรใช้กับ shader ของคุณโดยตรงเนื่องจากมีการคำนวณ GPU มากมายและประสิทธิภาพลดลง แทนการใช้โดยตรงคุณสามารถแสดงผลให้พื้นผิวที่มีRenderTexture

Shadertoyใช้หลายรอบหนึ่งต่อ "บัฟเฟอร์" ตามที่ชื่อบ่งบอกรหัสผ่านนี้จะเก็บผลลัพธ์ไว้ในบัฟเฟอร์ซึ่งเป็นเพียงพื้นผิว ความสามัคคีจะช่วยให้คุณแสดงถึงพื้นผิวเช่นกัน

2018-01-26_10-18-20

การสร้างหน้ากาก

คุณสามารถสร้างหน้ากากหนาและเรียบเนียนด้วยฟังก์ชั่นเหล่านี้:

ขั้นตอน

ขั้นตอน

เอาท์พุท 1 ถ้า[A]น้อยกว่าหรือเท่ากับ[B]มิฉะนั้นเอาท์พุท 0

smoothstep

smoothstep

ผสมผสานอย่างราบรื่นระหว่างค่าสองค่าโดยขึ้นอยู่กับว่าค่าที่สามอยู่ในช่วงนั้นส่งออกค่าระหว่าง 0 และ 1 คิดว่าเป็นค่าผกผัน lerp ที่ถูกยึดกับค่าเอาต์พุตเรียบ

ผลลัพธ์

/* 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"
}

ภาพ

การใช้ Maps

shaderToy การแรเงาจากร่างกาย

นี่คือคำจำกัดความที่มีประโยชน์:

ความหยาบ อธิบายพื้นผิวไมโครสโคปของวัตถุ สีขาว 1.0 หยาบและสีดำ 0.0 เรียบ microsurface ถ้าหยาบสามารถทำให้รังสีแสงกระจัดกระจายและทำให้ไฮไลท์ปรากฏหรี่และกว้างขึ้น พลังงานแสงปริมาณเท่ากันนั้นจะสะท้อนออกมาเมื่อเข้าสู่พื้นผิว แผนที่นี้มีอิสระทางศิลปะมากที่สุด ไม่มีคำตอบที่ผิดที่นี่ แผนที่นี้ช่วยให้ทรัพย์สินมีตัวละครมากที่สุดเนื่องจากมันอธิบายพื้นผิวอย่างแท้จริงเช่นรอยขีดข่วนรอยนิ้วมือรอยเปื้อนรอยเปื้อน ฯลฯ

ความมันวาว แผนที่นี้เป็นส่วนกลับของแผนที่ความหยาบ สีขาว 1.0 เรียบและ 0.0 ดำหยาบ อธิบายถึงไมโครไซต์ของวัตถุ microsurface ถ้าหยาบสามารถทำให้รังสีแสงกระจัดกระจายและทำให้ไฮไลท์ปรากฏหรี่และกว้างขึ้น พลังงานแสงปริมาณเท่ากันนั้นจะสะท้อนออกมาเมื่อเข้าสู่พื้นผิว แผนที่นี้มีอิสระทางศิลปะมากที่สุด ไม่มีคำตอบที่ผิดที่นี่ แผนที่นี้ช่วยให้ทรัพย์สินมีตัวละครมากที่สุดเนื่องจากมันอธิบายพื้นผิวอย่างแท้จริงเช่นรอยขีดข่วนรอยนิ้วมือรอยเปื้อนรอยเปื้อน ฯลฯ

Specular แผนที่นี้มีข้อมูลการสะท้อนแสงสำหรับพื้นผิวโลหะและไดอิเล็กทริก (ไม่ใช่โลหะ) นี่คือความแตกต่างที่สำคัญในเวิร์กโฟลว์โลหะ / หยาบและข้อมูลจำเพาะ / เงา ใช้กฎเดียวกัน คุณต้องใช้ค่าที่วัดได้สำหรับโลหะและส่วนใหญ่ dielectrics จะอยู่ในช่วง 0.04 - 4% หากมีสิ่งสกปรกบนโลหะค่าการสะท้อนแสงจะต้องลดลงเช่นกัน อย่างไรก็ตามคุณสามารถเพิ่มค่าที่แตกต่างในแผนที่ specular สำหรับวัสดุอิเล็กทริกเนื่องจากคุณสามารถควบคุมในการเขียนแผนที่

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

ความหยาบ

ภาพ

ฉันไม่รู้ว่าทำไม แต่ส่วนมาตรฐานของ Unity ไม่มีแผนที่ที่ราบรื่นดังนั้นฉันจึงเขียน shader พื้นฐานและเพิ่มแผนที่นี้

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"
}

ฉันคิดว่าความสามัคคีไม่ได้มีความหยาบ แต่มีแค่โลหะ แต่ช่องอัลฟาสำหรับความหยาบและช่องสีแดงนั้นสำหรับโลหะ คุณสามารถเปลี่ยนความเข้มด้วยความนุ่มนวล

แหล่งที่มาบน GitHub

ลิงค์ที่มีประโยชน์

โคลนกลม 1024x576

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

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


39
ว้าวคุณได้ทำแบบฝึกหัดเกี่ยวกับ Shader ทั้งหมดบนเว็บไซต์ถาม - ตอบ
Ocelot

6
@Ocelot ฉันชอบวิธีที่ Seyed ทำการเพิ่มมากขึ้นเรื่อย ๆ ที่นี่ ฉันชอบการตกแต่งด้วยเฉดสีและสิ่งเหล่านี้มีประโยชน์มากสำหรับแนวคิดเพิ่มเติมและแบบฝึกหัดเช่นกัน เขาสามารถโพสต์สิ่งเหล่านี้ตลอดไปในความคิดของฉัน
จอห์นแฮมิลตัน

7
คำตอบที่น่าอัศจรรย์ Shaders ทำงานได้ยากมากและใช้เวลาหลายชั่วโมงในการเล่นการวิจัยการลองผิดลองถูก และที่นี่คุณกำลังทำเพื่อคนอื่นฟรี
Draco18s

1
สำหรับวัสดุมาตรฐานมักจะเป็นการดีที่สุดที่จะฝังความขรุขระในแผนที่โลหะหรือปกติ (ก่อนหน้านี้ดูเหมือนจะเป็นค่าเริ่มต้น) ฉันอยากจะแนะนำให้ใช้ Photo Shop, Paint Shop หรือ Gimp เพื่อสร้างโลหะที่เหมาะสมซึ่งฝังความหยาบกร้าน อีกทางเลือกหนึ่งถ้าคุณมี Subter Painter หรือสิ่งที่คล้ายกันคุณสามารถส่งออกความหยาบได้ตามที่ Unity ต้องการและจะได้รับประโยชน์จากการแสดงภาพวัสดุของคุณก่อนที่จะใส่ Unity
David Peterson

นักวิชาการและสุภาพบุรุษ
Bas Smit
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.