Вертикальное затемнение и проблема с освещением

Шейдеры и все-все-все.

Вертикальное затемнение и проблема с освещением

Сообщение verden 07 апр 2018, 22:58

Всем привет.
Мне нужно добавить вертикальное затемнение на все объекты, которое работает поверх стандартного тумана, решил сделать это через шейдер. Но теперь при добавлении точечного источника света в сцену все объекты, освещаемые этим светом имеют какой то светлый квадрат, причем если выключить туман (в настройках сцены, а не вырезать в коде), то все работает нормально. Первоначально я думал, что просто пропишу умножение по высоте в функции finalcolor и будет чудо, но тогда пропадает стандартный туман, я думал, что эта функция работает уже после наложения всего освещения, тумана и прочего, но видимо чего то не знаю/понимаю. Именно поэтому пришлось вернуть туман в finalcolor. Куда копать?
Изображение
Синтаксис:
Используется javascript
Shader "Test/Diffuse_VerticalFade"
{
Properties {
        _Color ("Main Color", Color) = (1,1,1,1)
        _MainTex ("Main Texture", 2D) = "white" {}
        _Height ("Height edge sharpness", float) = 1.0
        _HOffset ("Height offset", float) = 0.0
}
SubShader {
        Tags { "RenderType"="Opaque" }
        Fog {Mode Off}
        LOD 200

CGPROGRAM
#pragma surface surf Lambert finalcolor:mycolor vertex:myvert

sampler2D _MainTex;
fixed4 _Color;
float _Height;
float _HOffset;

uniform half4 unity_FogStart;
uniform half4 unity_FogEnd;

struct Input {
        float2 uv_MainTex;
        float3 worldPos;
        half fog;
};

void myvert (inout appdata_full v, out Input data) {
        UNITY_INITIALIZE_OUTPUT (Input, data);
        float pos = length(UnityObjectToViewPos(v.vertex).xyz);
        float diff = unity_FogEnd.x - unity_FogStart.x;
        float invDiff = 1.0f/diff;
        data.fog = 1.0f - clamp((unity_FogEnd.x - pos) * invDiff, 0.0f, 1.0f);
}

void surf (Input IN, inout SurfaceOutput o) {
        fixed3 c = tex2D(_MainTex, IN.uv_MainTex).rgb * _Color.rgb;
        o.Albedo = c.rgb;
        o.Alpha = 1.0;
}

void mycolor (Input IN, SurfaceOutput o, inout fixed4 color) {
        color.rgb = lerp(color.rgb, unity_FogColor, IN.fog);
        color.rgb = color.rgb * saturate((IN.worldPos.y + _HOffset) * _Height);
}
ENDCG
}

Fallback "Legacy Shaders/VertexLit"
}
verden
UNец
 
Сообщения: 14
Зарегистрирован: 28 мар 2012, 00:23

Re: Вертикальное затемнение и проблема с освещением

Сообщение jetyb 10 апр 2018, 22:47

Синтаксис:
Используется csharp
void mycolor (Input IN, SurfaceOutput o, inout fixed4 color) {
        color.rgb = lerp(color.rgb, unity_FogColor, IN.fog);
        color.rgb = color.rgb * saturate((IN.worldPos.y + _HOffset) * _Height);
}
 

Формула тут не совсем корректная: даже если color = 0, то наличие тумана дает пикселю цвет. Проявляется это в режиме ForwarAdd, в котором цвет color пикселя смешивается с цветом пикселя с кадра (см там Blend One One). Но если color != 0, значит в активной зоне шейдера (квадратике) на экран всегда будет накладываться какое-то осветление. Что и наблюдается.

Решение: отключить или изменить работу этого смешивания в режие ForwardAdd.
Синтаксис:
Используется csharp
void mycolor (Input IN, SurfaceOutput o, inout fixed4 color) {
#ifdef UNITY_PASS_FORWARD_ADD
        color.rgb = lerp(color.rgb, unity_FogColor, IN.fog);
        color.rgb = color.rgb * saturate((IN.worldPos.y + _HOffset) * _Height);
#endif
}
 

Вроде надо написать как-то так (точность синтаксиса UNITY_PASS_FORWARD_ADD не помню)
jetyb
Адепт
 
Сообщения: 1486
Зарегистрирован: 31 окт 2011, 17:21

Re: Вертикальное затемнение и проблема с освещением

Сообщение verden 11 апр 2018, 01:54

Большое спасибо за наводку, помогло. А вообще можно создать функцию, которая будет работать после выполнения всех пасов, источников света и абсолютно всех вычислений или это из области фантастики? (popcorn)
Синтаксис:
Используется javascript
void mycolor (Input IN, SurfaceOutput o, inout fixed4 color) {
        fixed3 fc = unity_FogColor;
        #ifdef UNITY_PASS_FORWARDADD
        fc = 0;
        #endif
        color.rgb = lerp(color.rgb, fc, IN.fog);
        color.rgb = color.rgb * saturate((IN.worldPos.y + _HOffset) * _Height);
}
verden
UNец
 
Сообщения: 14
Зарегистрирован: 28 мар 2012, 00:23


Вернуться в Shader Lab

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 3