Страница 1 из 1

Surface shader: Fresnel Reflective bumped specular

СообщениеДобавлено: 10 окт 2010, 01:16
gnoblin
Хочется добавить к стандартному reflective bumped specular (в Unity 3.0, surface shader) коэффициент френеля для более прикольного отражения.
Нагуглил формулу, но что-то результаты меня не радуют. Может кто-нибудь подсказать где я ошибся? :D

Синтаксис:
Используется glsl
Shader "Reflective/Bumped Specular Fresnel" {
Properties {
        _Color ("Main Color", Color) = (1,1,1,1)
        _SpecColor ("Specular Color", Color) = (0.5,0.5,0.5,1)
        _Shininess ("Shininess", Range (0.01, 1)) = 0.078125
        _ReflectColor ("Reflection Color", Color) = (1,1,1,0.5)
        _MainTex ("Base (RGB) RefStrGloss (A)", 2D) = "white" {}
        _Cube ("Reflection Cubemap", Cube) = "" { TexGen CubeReflect }
        _BumpMap ("Normalmap", 2D) = "bump" {}
        _Fresnel("Fresnel Coef.", Range (0.01, 0.7)) = 0.35
}

SubShader {
        Tags { "RenderType"="Opaque" }
        LOD 400
CGPROGRAM
#pragma surface surf BlinnPhong
#pragma target 3.0

sampler2D _MainTex;
sampler2D _BumpMap;
samplerCUBE _Cube;

float4 _Color;
float4 _ReflectColor;
float _Shininess;
float _Fresnel;

struct Input {
        float2 uv_MainTex;
        float2 uv_BumpMap;
        //float3 normal;
        float3 viewDir;
        float3 worldRefl;
        INTERNAL_DATA
};

//подперто с gamedev.ru
float fresnel(float VdotN, float eta)
{
 float sqr_eta = eta * eta; // квадрат показателя преломления
 float etaCos = eta * VdotN; // η·cos(Θ)
 float sqr_etaCos = etaCos*etaCos; // в квадрате
 float one_minSqrEta = 1.0 - sqr_eta; // 1 – η2
 float value = etaCos - sqrt(one_minSqrEta + sqr_etaCos);
 value *= value / one_minSqrEta; // возводим в квадрат и делим на 1 – η2
 return min(1.0, value * value); // финальное возведение в квадрат
}
 
  //float fFresnel = fresnel(dot(vViewNormal, vNormalWS), indexOfRefraction);
 
void surf (Input IN, inout SurfaceOutput o) {
        half4 tex = tex2D(_MainTex, IN.uv_MainTex);
        half4 c = tex * _Color;
        o.Albedo = c.rgb;
       
        o.Gloss = tex.a;
        o.Specular = _Shininess;
       
        o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
       
        float3 worldRefl = WorldReflectionVector (IN, o.Normal);

        half4 reflcol = texCUBE (_Cube, worldRefl);
        reflcol *= tex.a;
       
        //reflcol = lerp(c, reflcol, fresnel(worldRefl, _Fresnel));
        reflcol = lerp(c, reflcol, fresnel(dot(IN.viewDir,o.Normal), _Fresnel));

        o.Emission = reflcol.rgb * _ReflectColor.rgb;
        o.Alpha = reflcol.a * _ReflectColor.a;
}
ENDCG
}

FallBack "Reflective/Bumped Diffuse"
}
 

Re: Surface shader: Fresnel Reflective bumped specular

СообщениеДобавлено: 11 окт 2010, 15:16
Battle Angel Alita
Юнити почему-то передает ненормализированый вьюДир. надо просто написать normalize(IN.viewDir)
+ вот мой код для фреснеля
_FPOW = 5.0, _R0 = 0.05
Код: Выделить всё
half fresnel = saturate(1.0 - dot(o.Normal, normalize(IN.viewDir)));
fresnel = pow(fresnel, _FPOW);
fresnel = _R0 + (1.0 - _R0) * fresnel;

Re: Surface shader: Fresnel Reflective bumped specular

СообщениеДобавлено: 11 окт 2010, 17:46
gnoblin
Спасибо :ymhug:

Re: Surface shader: Fresnel Reflective bumped specular

СообщениеДобавлено: 18 окт 2010, 01:29
gnoblin
Так получше? :)

Синтаксис:
Используется glsl
Shader "Reflective/Bumped Specular Fresnel 2" {
Properties {
        _Color ("Main Color", Color) = (1,1,1,1)
        _SpecColor ("Specular Color", Color) = (0.5,0.5,0.5,1)
        _Shininess ("Shininess", Range (0.01, 1)) = 0.078125
        _ReflectColor ("Reflection Color", Color) = (1,1,1,0.5)
        _MainTex ("Base (RGB) RefStrGloss (A)", 2D) = "white" {}
        _Cube ("Reflection Cubemap", Cube) = "" { TexGen CubeReflect }
        _BumpMap ("Normalmap", 2D) = "bump" {}
        _FPOW("FPOW", Float) = 5.0
        _R0("R0", Float) = 0.05
}

SubShader {
        Tags { "RenderType"="Opaque" }
        LOD 400
CGPROGRAM
#pragma surface surf BlinnPhong
#pragma target 3.0

sampler2D _MainTex;
sampler2D _BumpMap;
samplerCUBE _Cube;

float4 _Color;
float4 _ReflectColor;
float _Shininess;
float _FPOW;
float _R0;

struct Input {
        float2 uv_MainTex;
        float2 uv_BumpMap;
        //float3 normal;
        float3 viewDir;
        float3 worldRefl;
        INTERNAL_DATA
};
 
void surf (Input IN, inout SurfaceOutput o) {
        half4 tex = tex2D(_MainTex, IN.uv_MainTex);
        half4 c = tex * _Color;
        o.Albedo = c.rgb;
       
        o.Gloss = tex.a;
        o.Specular = _Shininess;
       
        o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
       
        float3 worldRefl = WorldReflectionVector (IN, o.Normal);

        half4 reflcol = texCUBE (_Cube, worldRefl);
        reflcol *= tex.a;    

        half fresnel = saturate(1.0 - dot(o.Normal, normalize(IN.viewDir)));
        fresnel = pow(fresnel, _FPOW);
        fresnel = _R0 + (1.0 - _R0) * fresnel;
        reflcol = lerp(c, reflcol, fresnel);

        o.Emission = reflcol.rgb * _ReflectColor.rgb;
        o.Alpha = reflcol.a * _ReflectColor.a;
}
ENDCG
}

FallBack "Reflective/Bumped Diffuse"
}

Re: Surface shader: Fresnel Reflective bumped specular

СообщениеДобавлено: 24 окт 2010, 09:55
gnoblin
Вопрос: а зачем для френеля 1D полоску с градиентом используют? :-\

Re: Surface shader: Fresnel Reflective bumped specular

СообщениеДобавлено: 24 окт 2010, 12:11
Battle Angel Alita
Это называется лук-ап текстура, в неё заносят какие-нибудь предпросчитанные данные. В данном случае кусок кода с pow и r0. Раньше(до гефорсов 6000-ой серии и до радеонов 9000-ной серии) прочитать из текстуры было быстрее чем делать "сложную" математику. Плюс лук-ап текстурой можно задать какую-нибудь даже очень сложную функцию.
По моему мнению - крутилки гораздо удобнее и нагляднее для художника чем лук-ап текстуры.

Re: Surface shader: Fresnel Reflective bumped specular

СообщениеДобавлено: 26 окт 2010, 03:15
gnoblin
А какие еще могут быть техники для улучшения рефлектив шейдера?

Спекуляр составляющая (напр. shininess) никак не привязывается к френелю?

Re: Surface shader: Fresnel Reflective bumped specular

СообщениеДобавлено: 26 окт 2010, 06:06
GrueGames
Вообще-то спекуляр - ни что иное, как имитация отражения источника света. В физически корректных рендерах, например в maxwell render, он полностью заменен отражением, а источники света имеют для этого размер в пространстве.
Так что на спекуляр по идее тоже должен распространяться эффект френеля.

Re: Surface shader: Fresnel Reflective bumped specular

СообщениеДобавлено: 30 окт 2010, 01:03
gnoblin
Я попробовал к френелю привязывать шайнинес - получилась какая-то фигня :)

Re: Surface shader: Fresnel Reflective bumped specular

СообщениеДобавлено: 03 ноя 2010, 11:52
Левша
Хороший шейдер, как раз такой нужен был.
А можно глупый вопрос, как реализавать изменение параметров Main Color? Т.е. привязать к интерфейсу (ползункам).
В квест 3d сделал, а в Unity даже не знаю с какой стороны подойти :(

Re: Surface shader: Fresnel Reflective bumped specular

СообщениеДобавлено: 03 ноя 2010, 19:20
666marat666
Както так:

Синтаксис:
Используется glsl
Shader "Freshnel"
{
        Properties
        {
_Color0("_Color0", Color) = (1,1,1,1)
_Diffuse("_Diffuse", 2D) = "white" {}
_NormalMap("_NormalMap", 2D) = "white" {}

        }
       
        SubShader
        {
                Tags
                {
"Queue"="Geometry+0"
"IgnoreProjector"="False"
"RenderType"="Opaque"

                }

               
Cull Back
ZWrite On
ZTest LEqual


                CGPROGRAM
#pragma surface surf BlinnPhongEditor  vertex:vert
#pragma target 2.0

                        struct EditorSurfaceOutput {
                                half3 Albedo;
                                half3 Normal;
                                half3 Emission;
                                half3 Gloss;
                                half Specular;
                                half Alpha;
                        };
                       
                        inline half4 LightingBlinnPhongEditor (EditorSurfaceOutput s, half3 lightDir, half3 viewDir, half atten)
                        {
                                #ifndef USING_DIRECTIONAL_LIGHT
                                lightDir = normalize(lightDir);
                                #endif
                                viewDir = normalize(viewDir);
                                half3 h = normalize (lightDir + viewDir);
                               
                                half diff = max (0, dot (s.Normal, lightDir));
                               
                                float nh = max (0, dot (s.Normal, h));
                                float3 spec = pow (nh, s.Specular*128.0) * s.Gloss;
                               
                                half4 c;
                                c.rgb = (s.Albedo * _LightColor0.rgb * diff + _LightColor0.rgb * spec) * (atten * 2);
                                c.a = s.Alpha + _LightColor0.a * Luminance(spec) * atten;
                                return c;
                        }
                       
                        inline half4 LightingBlinnPhongEditor_PrePass (EditorSurfaceOutput s, half4 light)
                        {
                                half3 spec = light.a * s.Gloss;
                               
                                half4 c;
                                c.rgb = (s.Albedo * light.rgb + light.rgb * spec);
                                c.a = s.Alpha + Luminance(spec);
                                return c;
                        }
                       
                        struct Input {
                                float2 uv_Diffuse;
float3 viewDir;
float2 uv_NormalMap;

                        };
                       
                        void vert (inout appdata_full v, out Input o) {

                        }
                       
float4 _Color0;
sampler2D _Diffuse;
sampler2D _NormalMap;



                        void surf (Input IN, inout EditorSurfaceOutput o) {
                                o.Albedo = 0.0;
                                o.Normal = float3(0.0,0.0,1.0);
                                o.Emission = 0.0;
                                o.Gloss = 0.0;
                                o.Specular = 0.0;
                                o.Alpha = 1.0;
float4 Tex2D1=tex2D(_Diffuse,(IN.uv_Diffuse.xyxy).xy);
float4 Multiply0=_Color0 * Tex2D1;
float4 Tex2DNormal0=UnpackNormal( tex2D(_NormalMap,(IN.uv_NormalMap.xyxy).xy) );
float4 Fresnel0=float4( 1.0 - dot( normalize( float4(IN.viewDir, 1.0).xyz), normalize( Tex2DNormal0.xyz ) ) );
float4 Master0_2_NoInput = float4(0,0,0,0);
float4 Master0_3_NoInput = float4(0,0,0,0);
float4 Master0_4_NoInput = float4(0,0,0,0);
float4 Master0_5_NoInput = float4(1,1,1,1);
float4 Master0_6_NoInput = float4(1,1,1,1);
o.Albedo = Multiply0;
o.Normal = Fresnel0;
o.Alpha = 1.0;

                        }
                ENDCG
        }
        Fallback "Diffuse"
}

Re: Surface shader: Fresnel Reflective bumped specular

СообщениеДобавлено: 03 ноя 2010, 20:12
gnoblin
Ползунками в гуи?
В инспекторе цвет меняется и так.

Re: Surface shader: Fresnel Reflective bumped specular

СообщениеДобавлено: 03 ноя 2010, 20:45
666marat666
Сори не заметил что ползунками , ну так это дело скрипта если не ошибаюсь O:-)

Re: Surface shader: Fresnel Reflective bumped specular

СообщениеДобавлено: 08 ноя 2010, 09:29
Левша
gnoblin писал(а):Ползунками в гуи?

Ну да.