Làm thế nào tôi có thể tạo ra một bề mặt ướt của người Viking / người đánh bóng nông cạn trong trò chơi Unity?


71

Trong trò chơi của tôi, tôi cần tạo ra những vũng nước động nhưng tôi không thể tìm thấy một hướng dẫn cho thấy cách tôi có thể tạo ra hiệu ứng như vậy (một ví dụ được trình bày bên dưới). Tôi làm nó như thế nào?

Phá vỡ lượng tử


4
Bực mình khi thấy một câu hỏi được bình chọn cao như vậy và câu trả lời được bình chọn cao hơn không bị đóng cửa. Sẽ tốt hơn nếu bạn chọn câu trả lời của riêng mình là tốt nhất, mặc dù hơi ngớ ngẩn khi yêu cầu tiền thưởng cho chính mình :)
Tim Holt

@TimHolt Trên cơ sở nào chúng ta sẽ đóng một câu hỏi như thế này? Có vẻ như hoàn hảo về chủ đề.
Josh

Tôi đang nói rằng người hỏi nó nên chấp nhận câu trả lời của chính mình. Xin lỗi vì tôi lạm dụng tiếng Anh.
Tim Holt

Câu trả lời:


121

Suy tư

Để tạo một shader ướt, trước tiên bạn cần phải có một sự phản chiếu.

Tải đơn giản

Bạn có thể sử dụng Đầu dò phản xạ hoặc MirrorReflection3 nhưng, tôi sử dụng phản xạ giả (Bản đồ khối) ở đây vì trình tạo bóng sau đó có thể được sử dụng trên thiết bị di động.

Suy tư

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

Méo mó

Để thêm méo vào hình phản chiếu của bạn, bạn có thể nhân bản đồ bình thường và worldRefl:

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

méo mó

Hình dạng thủ tục

Bạn có thể sử dụng tiếng ồn để tạo hình dạng thủ tục :

chụp

Dưới đây là hướng dẫn Fractal 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 ở trên không nên được sử dụng trực tiếp vào trình đổ bóng của bạn vì nó có nhiều tính toán GPU và giảm hiệu suất. Thay vì sử dụng trực tiếp, bạn có thể hiển thị kết quả thành một kết cấu với RenderTexture .

Shadertoy sử dụng nhiều đường chuyền , mỗi lần "đệm". Như tên cho thấy, pass này lưu trữ các kết quả trong một bộ đệm, đây chỉ là một kết cấu. Unity sẽ cho phép bạn kết xuất với kết cấu quá.

2018-01-26_10-18-20

Tạo mặt nạ

Bạn có thể làm một mặt nạ dày và mịn với các chức năng sau:

Bươc

bươc

Đầu ra 1 nếu [A]nhỏ hơn hoặc bằng [B], nếu không thì xuất 0.

Bước chân

bước chân

Pha trộn trơn tru giữa hai giá trị, dựa trên vị trí của giá trị thứ ba trong phạm vi đó, xuất ra các giá trị trong khoảng từ 0 đến 1. Hãy nghĩ về nó như một lerp nghịch đảo kẹp với giá trị đầu ra được làm mịn.

Kết quả

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

Hình ảnh, tưởng tượng

Sử dụng bản đồ

shaderToy Vật lý dựa trên bóng

Đây là một định nghĩa hữu ích:

Roughness Mô tả microsurface của đối tượng. Trắng 1.0 thô và đen 0,0 mịn. Mặt kính hiển vi nếu thô có thể làm cho các tia sáng tán xạ và làm cho phần nổi bật trông mờ hơn và rộng hơn. Cùng một lượng năng lượng ánh sáng được phản xạ đi ra ngoài bề mặt. Bản đồ này có sự tự do nghệ thuật nhất. Không có câu trả lời sai ở đây. Bản đồ này mang lại cho tài sản nhiều đặc tính nhất vì nó thực sự mô tả bề mặt, ví dụ như vết trầy xước, dấu vân tay, vết bẩn, bụi bẩn, v.v.

Độ bóng Bản đồ này là nghịch đảo của bản đồ độ nhám. Trắng 1.0 mịn và 0,0 đen là thô. Mô tả microsurface của đối tượng. Mặt kính hiển vi nếu thô có thể làm cho các tia sáng tán xạ và làm cho phần nổi bật trông mờ hơn và rộng hơn. Cùng một lượng năng lượng ánh sáng được phản xạ đi ra ngoài bề mặt. Bản đồ này có sự tự do nghệ thuật nhất. Không có câu trả lời sai ở đây. Bản đồ này mang lại cho tài sản nhiều đặc tính nhất vì nó thực sự mô tả bề mặt, ví dụ như vết trầy xước, dấu vân tay, vết bẩn, bụi bẩn, v.v.

Specular Bản đồ này chứa thông tin phản xạ cho cả bề mặt kim loại và điện môi (phi kim loại). Đây là một sự khác biệt chính trong quy trình công việc kim loại / thô và spec / độ bóng. Các quy tắc tương tự áp dụng. Bạn cần sử dụng các giá trị đo cho kim loại và hầu hết tất cả các chất điện môi sẽ nằm trong phạm vi 0,04 - 4%. Nếu có bụi bẩn trên kim loại, giá trị phản xạ cũng cần phải được hạ xuống. Tuy nhiên, bạn có thể thêm các giá trị khác nhau trong bản đồ đặc trưng cho vật liệu điện môi vì bạn có quyền kiểm soát tác giả bản đồ.

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

Độ nhám

Hình ảnh, tưởng tượng

Tôi không biết tại sao, nhưng trình tạo bóng tiêu chuẩn Unity không có bản đồ độ mịn, vì vậy tôi đã viết một trình tạo bóng cơ bản và thêm bản đồ này.

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

Tôi nghĩ Unity không có độ nhám, nó chỉ có kim loại, nhưng kênh alpha dành cho độ nhám và kênh màu đỏ là dành cho kim loại. Bạn có thể thay đổi cường độ với độ mịn.

Nguồn trên GitHub .

Liên kết hữu ích

bùn-hình cầu-1024x576

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

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


39
Ồ, bạn đã thực hiện một loạt hướng dẫn shader trên trang web Hỏi & Đáp.
Ocelot

6
@Ocelot Tôi thích cách Seyed tiếp tục bổ sung ngày càng nhiều trong số này ở đây. Tôi thích mày mò với shader và những thứ này thực sự hữu ích cho nhiều ý tưởng cũng như hướng dẫn. Anh ấy có thể tiếp tục đăng những điều này mãi mãi theo ý kiến ​​của tôi.
John Hamilton

7
Câu trả lời tuyệt vời. Shader rất khó để làm việc và tôi phải mất hàng giờ để nghiên cứu, nghiên cứu, thử nghiệm và sửa lỗi, và kiểm tra các shader khác để có được hiệu ứng tôi muốn. Và ở đây bạn đang làm điều đó, cho người khác, miễn phí.
Draco18

1
Đối với Vật liệu tiêu chuẩn, tốt nhất là nhúng độ nhám trong bản đồ kim loại hoặc bình thường (trước đây dường như là mặc định). Tôi sẽ khuyên bạn nên sử dụng Photo Shop, Paint Shop hoặc Gimp để tạo ra một kim loại phù hợp có độ nhám. Ngoài ra, nếu bạn có Họa sĩ Chất hoặc tương tự, bạn có thể xuất độ nhám của mình chính xác như Unity mong muốn và có lợi ích hình dung tài liệu của bạn trước khi bạn đặt chúng vào Unity.
David Peterson

một học giả và một quý ông
Bas Smit
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.