有两个水着色器。两者都有一个字段_ReflectionTex ("Internal Reflection", 2D) = "" {}
当你将这些着色器挂在一个对象上并在这个字段中放置一个纹理时,画面就完全不同了——
第一个着色器 Oney 用此图像填充对象,并在其上拉伸。
第二个着色器 FX/Water 用图像填充屏幕空间——这个功能正是我们第一个着色器所需要的!
两个着色器的图像处理代码大致相同 - 它们在这里和那里都采用TEXTCOORD0,对其执行操作
half4 refl = tex2Dproj( _ReflectionTex, UNITY_PROJ_COORD(uv1) );
,然后在原始纹理具有透明度的地方分配此纹理的值。一般来说,水中的倒影。但同样,效果完全不同。
我想让 Oney 着色器在保持其所有功能的同时,能够将纹理应用到屏幕空间(而不是一个对象),就像 FX / Water 着色器成功完成的那样
代码如下,为了节省一些空间,它被剪掉了一点。因此,如果缺少几个变量——正因为如此,源代码大约会大一倍半。
Shader "Oney" { //Всем хорош, но не может в наложение текстур на экран.
Properties {
_Color ("Color", Color) = (0.7016652,0.8427501,0.9264706,1)
_Color_Waves ("Color_Waves", Color) = (0.1096453,0.3823529,0.2920773,1)
_Normal_1 ("Normal_1", 2D) = "bump" {}
_Normal_2 ("Normal_2", 2D) = "bump" {}
_Waves ("Waves", 2D) = "white" {}
_CubMap ("CubMap", Cube) = "_Skybox" {}
_Intensity_Waves ("Intensity_Waves", Range(0, 50)) = 10
_Speed ("Speed", Range(0, 1)) = 0.1
_Intensity_Color ("Intensity_Color", Range(0, 10)) = 5
_Spec ("Spec", Range(0, 2)) = 1
_Gloss ("Gloss", Range(0, 2)) = 1
_Reflection ("Reflection", Range(0, 2)) = 0
_ReflectionTex ("Internal Reflection", 2D) = "" {}
}
SubShader {
Tags {
"RenderType"="Opaque"
}
Pass {
Name "FORWARD"
Tags {
"LightMode"="ForwardBase"
}
CGPROGRAM
uniform sampler2D _Normal_2; uniform float4 _Normal_2_ST;
uniform float _Intensity_Color;
uniform float4 _Color_Waves;
uniform float _Speed;
uniform samplerCUBE _CubMap;
uniform float _Reflection;
struct VertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 tangent : TANGENT;
float4 texcoord0 : TEXCOORD0;
};
struct VertexOutput {
float4 pos : SV_POSITION;
float4 uv0 : TEXCOORD0;
float4 posWorld : TEXCOORD1;
float3 normalDir : TEXCOORD2;
float3 tangentDir : TEXCOORD3;
float3 bitangentDir : TEXCOORD4;
LIGHTING_COORDS(5,6)
UNITY_FOG_COORDS(7)
};
VertexOutput vert (VertexInput v) {
VertexOutput o = (VertexOutput)0;
o.uv0 = v.texcoord0;
o.normalDir = UnityObjectToWorldNormal(v.normal);
o.tangentDir = normalize( mul( unity_ObjectToWorld, float4( v.tangent.xyz, 0.0 ) ).xyz );
o.bitangentDir = normalize(cross(o.normalDir, o.tangentDir) * v.tangent.w);
float4 node_9273 = _Time + _TimeEditor;
float2 node_9735 = (o.uv0+(node_9273.r*_Speed)*float2(0,1));
float4 _Waves_var = tex2Dlod(_Waves,float4(TRANSFORM_TEX(node_9735, _Waves),0.0,0));
v.vertex.xyz += (_Waves_var.r*v.normal*_Intensity_Waves);
o.posWorld = mul(unity_ObjectToWorld, v.vertex);
float3 lightColor = _LightColor0.rgb;
o.pos = UnityObjectToClipPos(v.vertex );
UNITY_TRANSFER_FOG(o,o.pos);
TRANSFER_VERTEX_TO_FRAGMENT(o)
return o;
}
sampler2D _ReflectionTex;
float4 frag(VertexOutput i) : COLOR {
i.normalDir = normalize(i.normalDir);
float3x3 tangentTransform = float3x3( i.tangentDir, i.bitangentDir, i.normalDir);
float3 viewDirection = normalize(_WorldSpaceCameraPos.xyz - i.posWorld.xyz);
float4 node_1446 = _Time + _TimeEditor;
float2 node_4184 = (i.uv0+node_1446.g*float2(0.0002,0.0001));
float3 _Normal_1_var = UnpackNormal(tex2D(_Normal_1,TRANSFORM_TEX(node_4184, _Normal_1)));
float2 node_5576 = (i.uv0+node_1446.g*float2(0.0002,-0.0001));
float3 _Normal_2_var = UnpackNormal(tex2D(_Normal_2,TRANSFORM_TEX(node_5576, _Normal_2)));
float3 normalLocal = (_Normal_1_var.rgb+_Normal_2_var.rgb);
//Expiremental
float4 uv1 = i.uv0;
half4 refl = tex2Dproj( _ReflectionTex, UNITY_PROJ_COORD(uv1) );
float3 normalDirection = normalize(mul( normalLocal, tangentTransform )); // Perturbed normals
float3 viewReflectDirection = reflect( -viewDirection, normalDirection );
float3 lightDirection = normalize(_WorldSpaceLightPos0.xyz);
float3 lightColor = _LightColor0.rgb;
float3 halfDirection = normalize(viewDirection+lightDirection);
/// Final Color:
float3 finalColor = diffuse + specular + emissive;
fixed4 finalRGBA = fixed4(finalColor,1);
finalRGBA.rgb = lerp( finalColor.rgb, refl.rgb, 1); finalRGBA.a = refl.a;
UNITY_APPLY_FOG(i.fogCoord, finalRGBA);
return finalRGBA;
}
ENDCG
第二个着色器,FX/水
Shader "FX/Water" { // Умеет класть текстуру прямо на экран!
Properties {
_WaveScale ("Wave scale", Range (0.002,0.15)) = 0.063
_ReflDistort ("Reflection distort", Range (0,15)) = 0.44
[NoScaleOffset] _Fresnel ("Fresnel (A) ", 2D) = "gray" {}
[NoScaleOffset] _BumpMap ("Normalmap ", 2D) = "bump" {}
WaveSpeed ("Wave speed (map1 x,y; map2 x,y)", Vector) = (19,9,-16,-7)
[NoScaleOffset] _ReflectiveColor ("Reflective color (RGB) fresnel (A) ", 2D) = "" {}
_HorizonColor ("Simple water horizon color", COLOR) = ( .172, .463, .435, 1)
_ReflectionTex ("Internal Reflection", 2D) = "" {}
}
// -----------------------------------------------------------
// Fragment program cards
Subshader {
Tags { "WaterMode"="Refractive" "RenderType"="Opaque" }
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fog
#include "UnityCG.cginc"
struct appdata {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f {
float4 pos : SV_POSITION;
#if defined(HAS_REFLECTION) || defined(HAS_REFRACTION)
float4 ref : TEXCOORD0;
float2 bumpuv0 : TEXCOORD1;
float2 bumpuv1 : TEXCOORD2;
float3 viewDir : TEXCOORD3;
#else
float2 bumpuv0 : TEXCOORD0;
float2 bumpuv1 : TEXCOORD1;
float3 viewDir : TEXCOORD2;
#endif
UNITY_FOG_COORDS(4)
};
v2f vert(appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
// scroll bump waves
float4 temp;
float4 wpos = mul (unity_ObjectToWorld, v.vertex);
temp.xyzw = wpos.xzxz * _WaveScale4 + _WaveOffset;
o.bumpuv0 = temp.xy;
o.bumpuv1 = temp.wz;
// object space view direction (will normalize per pixel)
o.viewDir.xzy = WorldSpaceViewDir(v.vertex);
#if defined(HAS_REFLECTION) || defined(HAS_REFRACTION)
o.ref = ComputeNonStereoScreenPos(o.pos);
#endif
UNITY_TRANSFER_FOG(o,o.pos);
return o;
}
sampler2D _ReflectionTex;
half4 frag( v2f i ) : SV_Target
{
i.viewDir = normalize(i.viewDir);
// combine two scrolling bumpmaps into one
half3 bump1 = UnpackNormal(tex2D( _BumpMap, i.bumpuv0 )).rgb;
half3 bump2 = UnpackNormal(tex2D( _BumpMap, i.bumpuv1 )).rgb;
half3 bump = (bump1 + bump2) * 0.5;
// fresnel factor
half fresnelFac = dot( i.viewDir, bump );
// perturb reflection/refraction UVs by bumpmap, and lookup colors
float4 uv1 = i.ref; uv1.xy += bump * _ReflDistort;
half4 refl = tex2Dproj( _ReflectionTex, UNITY_PROJ_COORD(uv1) );
// final color is between refracted and reflected based on fresnel
half4 color;
half4 water = tex2D( _ReflectiveColor, float2(fresnelFac,fresnelFac) );
color.rgb = lerp( water.rgb, refl.rgb, water.a );
color.a = refl.a * water.a;
UNITY_APPLY_FOG(i.fogCoord, color);
return color;
}
ENDCG
}
}
}
案例结果是在一个命令中,它将所有内容都转换为屏幕坐标
将它应用到第一个着色器的顶点部分,我们得到了我们需要的结果。只需要
ref取一个类似的变量TEXTCOORD0因此,所需着色器的最终代码