如何在Unity中制作径向渐变天空盒?
How to make radial gradient skybox in Unity?
好的,我是天空盒的新手,在尝试实现径向渐变天空盒时遇到了一些问题。我有一个径向渐变着色器,但是当我把它作为天空盒时,在两种颜色之间插值的部分放大得太大,这意味着你根本无法分辨出它是一个渐变。
我认为这是因为它不是用于天空盒的着色器。然后我找到了一个线性渐变天空盒的着色器,它作为线性渐变工作,但我需要它是径向的,比如从中心颜色向外。
我到处都找过了,但找不到径向渐变 SKYBOX 着色器。我的问题是 - 如何将线性渐变着色器转换为天空盒的径向着色器?或者如何让我现有的径向渐变适用于天空盒?
这不是我写的,但这是线性渐变天空盒的代码:
Shader "Custom/Horizontal Skybox"
{
Properties
{
_Color1 ("Top Color", Color) = (1, 1, 1, 0)
_Color2 ("Horizon Color", Color) = (1, 1, 1, 0)
_Color3 ("Bottom Color", Color) = (1, 1, 1, 0)
_Exponent1 ("Exponent Factor for Top Half", Float) = 1.0
_Exponent2 ("Exponent Factor for Bottom Half", Float) = 1.0
_Intensity ("Intensity Amplifier", Float) = 1.0
}
CGINCLUDE
#include "UnityCG.cginc"
struct appdata
{
float4 position : POSITION;
float3 texcoord : TEXCOORD0;
};
struct v2f
{
float4 position : SV_POSITION;
float3 texcoord : TEXCOORD0;
};
half4 _Color1;
half4 _Color2;
half4 _Color3;
half _Intensity;
half _Exponent1;
half _Exponent2;
v2f vert (appdata v)
{
v2f o;
o.position = mul (UNITY_MATRIX_MVP, v.position);
o.texcoord = v.texcoord;
return o;
}
half4 frag (v2f i) : COLOR
{
float p = normalize (i.texcoord).y;
float p1 = 1.0f - pow (min (1.0f, 1.0f - p), _Exponent1);
float p3 = 1.0f - pow (min (1.0f, 1.0f + p), _Exponent2);
float p2 = 1.0f - p1 - p3;
return (_Color1 * p1 + _Color2 * p2 + _Color3 * p3) * _Intensity;
}
ENDCG
SubShader
{
Tags { "RenderType"="Background" "Queue"="Background" }
Pass
{
ZWrite Off
Cull Off
Fog { Mode Off }
CGPROGRAM
#pragma fragmentoption ARB_precision_hint_fastest
#pragma vertex vert
#pragma fragment frag
ENDCG
}
}
}
像这样-
要创建示例图像,您根本不需要使用天空盒。
- 创建平面或四边形
- 为其添加径向渐变着色器或径向渐变纹理
- 确保您使用的着色器是 "unlit"
- 禁用网格组件上的阴影投射和阴影接收
- 移动平面并调整其大小,使其位于场景中您想要的位置
- 可以选择将它作为相机的父级,或者创建一个 "follow" 脚本,如果你总是希望它在视图中
- 将它设置在不同的绘制层上,使其像天空盒一样工作,并且不与游戏其余部分所在的绘制层交互
- 确保绘制图层在图层顺序中处于最低位置,以便它始终位于所有内容下方
您提供的着色器代码确实绘制了径向渐变,仅沿 y 轴。如果你通过改变线来翻转轴
float p = normalize (i.texcoord).y;
到
float p = normalize (i.texcoord).x;
编辑:
既然你真的要旋转渐变,那么你可以在vertex shader中做如下操作(1.57是pi/2)。
v2f vert (appdata v)
{
v2f o;
float sinX = sin ( 1.57 );
float cosX = cos ( 1.57 );
float sinY = sin ( 1.57 );
float2x2 rotationMatrix = float2x2( cosX, -sinX, sinY, cosX);
o.position = mul (UNITY_MATRIX_MVP, v.position);
o.texcoord.xz = mul(v.texcoord.xz, rotationMatrix);
o.texcoord.y = v.texcoord.y;
return o;
}
编辑 2:
完整代码:
Shader "Custom/Horizontal Skybox"
{
Properties
{
_Color1 ("Top Color", Color) = (1, 1, 1, 0)
_Color2 ("Horizon Color", Color) = (1, 1, 1, 0)
_Color3 ("Bottom Color", Color) = (1, 1, 1, 0)
_Exponent1 ("Exponent Factor for Top Half", Float) = 1.0
_Exponent2 ("Exponent Factor for Bottom Half", Float) = 1.0
_Intensity ("Intensity Amplifier", Float) = 1.0
_Angle ("Angle", Float) = 0.0
}
CGINCLUDE
#include "UnityCG.cginc"
struct appdata
{
float4 position : POSITION;
float3 texcoord : TEXCOORD0;
};
struct v2f
{
float4 position : SV_POSITION;
float3 texcoord : TEXCOORD0;
};
half4 _Color1;
half4 _Color2;
half4 _Color3;
half _Intensity;
half _Exponent1;
half _Exponent2;
half _Angle;
v2f vert (appdata v)
{
v2f o;
float sinX = sin ( _Angle );
float cosX = cos ( _Angle );
float sinY = sin ( _Angle );
float2x2 rotationMatrix = float2x2( cosX, -sinX, sinY, cosX);
o.position = mul (UNITY_MATRIX_MVP, v.position);
o.texcoord.xz = mul(v.texcoord.xz, rotationMatrix);
o.texcoord.y = v.texcoord.y;
return o;
}
half4 frag (v2f i) : COLOR
{
float p = normalize (i.texcoord).x;
float p1 = 1.0f - pow (min (1.0f, 1.0f - p), _Exponent1);
float p3 = 1.0f - pow (min (1.0f, 1.0f + p), _Exponent2);
float p2 = 1.0f - p1 - p3;
return (_Color1 * p1 + _Color2 * p2 + _Color3 * p3) * _Intensity;
}
ENDCG
SubShader
{
Tags { "RenderType"="Background" "Queue"="Background" }
Pass
{
ZWrite Off
Cull Off
Fog { Mode Off }
CGPROGRAM
#pragma fragmentoption ARB_precision_hint_fastest
#pragma vertex vert
#pragma fragment frag
ENDCG
}
}
}
好的,我是天空盒的新手,在尝试实现径向渐变天空盒时遇到了一些问题。我有一个径向渐变着色器,但是当我把它作为天空盒时,在两种颜色之间插值的部分放大得太大,这意味着你根本无法分辨出它是一个渐变。
我认为这是因为它不是用于天空盒的着色器。然后我找到了一个线性渐变天空盒的着色器,它作为线性渐变工作,但我需要它是径向的,比如从中心颜色向外。
我到处都找过了,但找不到径向渐变 SKYBOX 着色器。我的问题是 - 如何将线性渐变着色器转换为天空盒的径向着色器?或者如何让我现有的径向渐变适用于天空盒?
这不是我写的,但这是线性渐变天空盒的代码:
Shader "Custom/Horizontal Skybox"
{
Properties
{
_Color1 ("Top Color", Color) = (1, 1, 1, 0)
_Color2 ("Horizon Color", Color) = (1, 1, 1, 0)
_Color3 ("Bottom Color", Color) = (1, 1, 1, 0)
_Exponent1 ("Exponent Factor for Top Half", Float) = 1.0
_Exponent2 ("Exponent Factor for Bottom Half", Float) = 1.0
_Intensity ("Intensity Amplifier", Float) = 1.0
}
CGINCLUDE
#include "UnityCG.cginc"
struct appdata
{
float4 position : POSITION;
float3 texcoord : TEXCOORD0;
};
struct v2f
{
float4 position : SV_POSITION;
float3 texcoord : TEXCOORD0;
};
half4 _Color1;
half4 _Color2;
half4 _Color3;
half _Intensity;
half _Exponent1;
half _Exponent2;
v2f vert (appdata v)
{
v2f o;
o.position = mul (UNITY_MATRIX_MVP, v.position);
o.texcoord = v.texcoord;
return o;
}
half4 frag (v2f i) : COLOR
{
float p = normalize (i.texcoord).y;
float p1 = 1.0f - pow (min (1.0f, 1.0f - p), _Exponent1);
float p3 = 1.0f - pow (min (1.0f, 1.0f + p), _Exponent2);
float p2 = 1.0f - p1 - p3;
return (_Color1 * p1 + _Color2 * p2 + _Color3 * p3) * _Intensity;
}
ENDCG
SubShader
{
Tags { "RenderType"="Background" "Queue"="Background" }
Pass
{
ZWrite Off
Cull Off
Fog { Mode Off }
CGPROGRAM
#pragma fragmentoption ARB_precision_hint_fastest
#pragma vertex vert
#pragma fragment frag
ENDCG
}
}
}
像这样-
要创建示例图像,您根本不需要使用天空盒。
- 创建平面或四边形
- 为其添加径向渐变着色器或径向渐变纹理
- 确保您使用的着色器是 "unlit"
- 禁用网格组件上的阴影投射和阴影接收
- 移动平面并调整其大小,使其位于场景中您想要的位置
- 可以选择将它作为相机的父级,或者创建一个 "follow" 脚本,如果你总是希望它在视图中
- 将它设置在不同的绘制层上,使其像天空盒一样工作,并且不与游戏其余部分所在的绘制层交互
- 确保绘制图层在图层顺序中处于最低位置,以便它始终位于所有内容下方
您提供的着色器代码确实绘制了径向渐变,仅沿 y 轴。如果你通过改变线来翻转轴
float p = normalize (i.texcoord).y;
到
float p = normalize (i.texcoord).x;
编辑:
既然你真的要旋转渐变,那么你可以在vertex shader中做如下操作(1.57是pi/2)。
v2f vert (appdata v)
{
v2f o;
float sinX = sin ( 1.57 );
float cosX = cos ( 1.57 );
float sinY = sin ( 1.57 );
float2x2 rotationMatrix = float2x2( cosX, -sinX, sinY, cosX);
o.position = mul (UNITY_MATRIX_MVP, v.position);
o.texcoord.xz = mul(v.texcoord.xz, rotationMatrix);
o.texcoord.y = v.texcoord.y;
return o;
}
编辑 2:
完整代码:
Shader "Custom/Horizontal Skybox"
{
Properties
{
_Color1 ("Top Color", Color) = (1, 1, 1, 0)
_Color2 ("Horizon Color", Color) = (1, 1, 1, 0)
_Color3 ("Bottom Color", Color) = (1, 1, 1, 0)
_Exponent1 ("Exponent Factor for Top Half", Float) = 1.0
_Exponent2 ("Exponent Factor for Bottom Half", Float) = 1.0
_Intensity ("Intensity Amplifier", Float) = 1.0
_Angle ("Angle", Float) = 0.0
}
CGINCLUDE
#include "UnityCG.cginc"
struct appdata
{
float4 position : POSITION;
float3 texcoord : TEXCOORD0;
};
struct v2f
{
float4 position : SV_POSITION;
float3 texcoord : TEXCOORD0;
};
half4 _Color1;
half4 _Color2;
half4 _Color3;
half _Intensity;
half _Exponent1;
half _Exponent2;
half _Angle;
v2f vert (appdata v)
{
v2f o;
float sinX = sin ( _Angle );
float cosX = cos ( _Angle );
float sinY = sin ( _Angle );
float2x2 rotationMatrix = float2x2( cosX, -sinX, sinY, cosX);
o.position = mul (UNITY_MATRIX_MVP, v.position);
o.texcoord.xz = mul(v.texcoord.xz, rotationMatrix);
o.texcoord.y = v.texcoord.y;
return o;
}
half4 frag (v2f i) : COLOR
{
float p = normalize (i.texcoord).x;
float p1 = 1.0f - pow (min (1.0f, 1.0f - p), _Exponent1);
float p3 = 1.0f - pow (min (1.0f, 1.0f + p), _Exponent2);
float p2 = 1.0f - p1 - p3;
return (_Color1 * p1 + _Color2 * p2 + _Color3 * p3) * _Intensity;
}
ENDCG
SubShader
{
Tags { "RenderType"="Background" "Queue"="Background" }
Pass
{
ZWrite Off
Cull Off
Fog { Mode Off }
CGPROGRAM
#pragma fragmentoption ARB_precision_hint_fastest
#pragma vertex vert
#pragma fragment frag
ENDCG
}
}
}