找回密码
 立即注册
查看: 210|回复: 0

UnityShader 基础(61)玻璃折射计算

[复制链接]
发表于 2023-2-12 20:49 | 显示全部楼层 |阅读模式
上一节使用CubeMap(环境球贴图)来实现反射效果
核心是使用了:
//表面反射方向(视角反方向,物体表面法线)
fixed3 reflectDir = reflect(-viewDir, worldNormal);
//使用反射方向读取环境球图像。
float3 _CubeMapColor = texCUBElod(_CubeMap, fixed4(reflectDir, _CubeMapMipLevel));

如果使用:
//表面折射方向(视角反方向,物体表面法线,折射比率)
fixed3 refractDir = refract(normalize(viewDir), normalize(i.worldNormal),_RefractRatio);



Shader效果


Shader代码
Shader "CRLuo/CRLuo_CubemapNormalTex_Refract"{
        Properties{


                //反射贴图获取
                [NoScaleOffset]
                _CubeMap("环境球贴图",cube) = "Skybox"{}
                _CubeMapMipLevel("环境球模糊",range(0,10)) = 0
                _RefractRatio("折射率",range(-1,1)) = 1

        }
                subshader{
                        Tags{"RenderType" = "Opaque"}
                        pass {
                                Tags{"LightMode" = "ForWardBase"}

                                CGPROGRAM

                                #pragma vertex vert
                                #pragma fragment  frag

                                #include"UnityCG.cginc"


                                        //输入结构
                                        struct appdata
                                        {
                                                float4 vertex : POSITION;
                                                float2 uv : TEXCOORD0;

                                                //获取表面法线
                                                float3 normal:NORMAL;

                                        };

                                        struct v2f
                                        {
                                                float2 uv : TEXCOORD0;
                                                float4 pos : SV_POSITION;


                                                //世界顶点坐标
                                                float3 worldPos:TEXCOORD1;
                                                //世界法线
                                                float3 worldNormal:TEXCOORD2;


                                        };


                                        //获取环境球贴图
                                        samplerCUBE _CubeMap;
                                        float _CubeMapMipLevel;
                                        float _RefractRatio;

                                        //顶点函数
                                        v2f vert(appdata v)
                                        {
                                                v2f o;
                                                UNITY_INITIALIZE_OUTPUT(v2f, o);
                                                o.pos = UnityObjectToClipPos(v.vertex);
                                                //物体空间坐标 顶点 转 世界空间坐标
                                                o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
                                                //物体空间 法线转 世界空间法线
                                                o.worldNormal = UnityObjectToWorldNormal(v.normal);
                                                return o;
                                        }

                                        fixed4 frag(v2f i) : SV_Target
                                        {
                                                //摄像机方向
                                                fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos);
                                                //表面折射率变化
                                                float faceRatio = dot(i.worldNormal, viewDir);
                                                //表面折射发现
                                                fixed3 refractDir = refract(normalize(-viewDir), normalize(i.worldNormal), faceRatio*_RefractRatio);
                                                //获取折射图像
                                                 float3 _CubeMapColor = texCUBElod(_CubeMap, float4(refractDir, _CubeMapMipLevel));
                                                //输出仿色贴图
                                                return fixed4(_CubeMapColor,1);
                                 }
                                 ENDCG
                         }
        }
}
不过只有上面的代码是不会有效果的。
需要
1、创建反射探针


2、设置场景静态物体(反射与折射物体)。


3、烘焙环境图


4、把贴图赋予材质球



<hr/>继续吧玻璃做完


Shader代码
Shader "CRLuo/CRLuo_CubemapNormalTex_Glass"{
        Properties{
                [HDR]_GlassColor("玻璃颜色", Color) = (0.325, 0.807, 0.971, 0.725)
                [HDR]_HighlightColor("高光颜色", Color) = (1, 1, 1, 1)
                _HighlightPow("高光范围",  Range(0.001,50)) = 0.1
                //反射贴图获取
                [NoScaleOffset]
                _CubeMap("环境球贴图",cube) = "Skybox"{}
                _CubeMapMipLevelA("环境球反射模糊",range(0,1)) = 0
                _CubeMapMipLevelB("环境球折射模糊",range(0,1)) = 0
                _RefractRatio("折射率",range(-1,1)) = 1

        }
                subshader{
                        Tags{"RenderType" = "Opaque"}


                        //===================创建阴影pass===================
        pass
        {
                        //---------------阴影模式
                        Tags{ "LightMode" = "ShadowCaster" }

                        CGPROGRAM
                        #pragma vertex vert
                        #pragma fragment frag

                                //---------------创建阴影
                        #pragma multi_compile_shadowcaster

                        #include "UnityCG.cginc"

                                struct appdata
                        {
                                float4 vertex : POSITION;
                                half3 normal:NORMAL;
                        };

                        struct v2f
                        {
                                //---------------申请阴影数据结构
                                V2F_SHADOW_CASTER;
                        };


                        v2f vert(appdata v)
                        {
                                v2f o;
                                //---------------放入阴影生成模块
                                TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
                                return o;
                        }

                        fixed4 frag(v2f i) : SV_TARGET
                        {
                                //---------------渲染阴影
                                SHADOW_CASTER_FRAGMENT(i)
                        }
                                ENDCG
                }













                        pass {
                                //---------------向前渲染基础灯光
                                                         Tags { "LightMode" = "ForwardBase" }
                                                        CGPROGRAM

                                                                 //---------------向前渲染基础
                                                                 #pragma multi_compile_fwdbase

                                #pragma vertex vert
                                #pragma fragment  frag

                                #include"UnityCG.cginc"
                        //---------------阴影程序集
                        #include "AutoLight.cginc"
                        //---------------光照程序集
                        #include "Lighting.cginc"

                                        //输入结构
                                        struct appdata
                                        {
                                                float4 vertex : POSITION;
                                                float2 uv : TEXCOORD0;
                                                float3 normal : NORMAL;

                                        };

                                        struct v2f
                                        {
                                                float2 uv : TEXCOORD0;
                                                float4 pos : SV_POSITION;
                                                //世界顶点坐标
                                                float3 worldPos:TEXCOORD1;
                                                //世界法线
                                                float3 worldNormal:TEXCOORD2;
                                                //---------------阴影数据结构
                                                SHADOW_COORDS(3)
                                        };

                                        float4 _GlassColor;
                                        float _HighlightPow;
                                        //获取环境球贴图
                                        samplerCUBE _CubeMap;
                                        float _CubeMapMipLevelA;
                                        float _CubeMapMipLevelB;
                                        float _RefractRatio;
                                        float4 _HighlightColor;

                                        //顶点函数
                                        v2f vert(appdata v)
                                        {
                                                v2f o;
                                                UNITY_INITIALIZE_OUTPUT(v2f, o);
                                                o.pos = UnityObjectToClipPos(v.vertex);
                                                //物体空间坐标 顶点 转 世界空间坐标
                                                o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
                                                //物体空间 法线转 世界空间法线
                                                o.worldNormal = UnityObjectToWorldNormal(v.normal);
                                                //---------------传递且处理阴影数据
                                                TRANSFER_SHADOW(o);
                                                //---------------更改输入顶点变量
                                                UNITY_TRANSFER_FOG(o, o.pos);
                                                return o;
                                        }

                                        fixed4 frag(v2f i) : SV_Target
                                        {
                                                //---------------获取阴影
                                fixed shadow = SHADOW_ATTENUATION(i);
                                        //---------------获取环境色
                                        fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;
                                                //摄像机方向
                                                fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos);
                                                //面比率
                                                float faceRatio =abs( dot(i.worldNormal, viewDir));

                                                //世界坐标灯光方向
                                                fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
                                                //灯光反射
                                                fixed3 reflectLightDir = normalize(reflect(-lightDir, i.worldNormal));
                                                //反射光线与视角点乘,获得高光渐变。
                                                fixed         Ramp_Specular = saturate(dot(reflectLightDir, viewDir));





                                                //表面反射方向
                                                fixed3 reflectDir = reflect(normalize(-viewDir), normalize(i.worldNormal));
                                                //获取反射贴图
                                                float3 _reflectColor = texCUBElod(_CubeMap, float4(reflectDir, _CubeMapMipLevelA*8));


                                                //表面折射射方向
                                                fixed3 refractDir = refract(normalize(-viewDir), normalize(i.worldNormal), faceRatio*_RefractRatio);
                                                //获取折射贴图
                                                 float3 _refractColor = texCUBElod(_CubeMap, float4(refractDir, (_CubeMapMipLevelB+ _CubeMapMipLevelA)*8));

                                                 float3 outColor = lerp(_reflectColor * _HighlightColor.rgb, _refractColor * _GlassColor.rgb * _HighlightColor.rgb, faceRatio)+ pow(Ramp_Specular, _HighlightPow)* _HighlightColor.rgb* shadow;


                                                //输出仿色贴图
                                                return fixed4(outColor+ ambient,1);
                                 }
                                 ENDCG
                         }
        }
}
支持法线贴图


Shader "CRLuo/CRLuo_CubemapNormalTex_Glass"{
        Properties{
                [HDR]_GlassColor("玻璃颜色", Color) = (0.325, 0.807, 0.971, 0.725)
                _BumpMap("法线贴图",2D) = "bump"{}
                _BumpScale("法线贴图强度",Range(-2.0,2.0)) = -1.0
                [HDR]_HighlightColor("高光颜色", Color) = (1, 1, 1, 1)
                _HighlightPow("高光范围",  Range(0.001,50)) = 0.1
                //反射贴图获取
                [NoScaleOffset]
                _CubeMap("环境球贴图",cube) = "Skybox"{}
                _CubeMapMipLevelA("环境球反射模糊",range(0,1)) = 0
                _CubeMapMipLevelB("环境球折射模糊",range(0,1)) = 0
                _RefractRatio("折射率",range(-1,1)) = 1

        }
                subshader{
                        Tags{"RenderType" = "Opaque"}


                        //===================创建阴影pass===================
        pass
        {
                        //---------------阴影模式
                        Tags{ "LightMode" = "ShadowCaster" }

                        CGPROGRAM
                        #pragma vertex vert
                        #pragma fragment frag

                                //---------------创建阴影
                        #pragma multi_compile_shadowcaster

                        #include "UnityCG.cginc"

                                struct appdata
                        {
                                float4 vertex : POSITION;
                                half3 normal:NORMAL;
                        };

                        struct v2f
                        {
                                //---------------申请阴影数据结构
                                V2F_SHADOW_CASTER;
                        };


                        v2f vert(appdata v)
                        {
                                v2f o;
                                //---------------放入阴影生成模块
                                TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
                                return o;
                        }

                        fixed4 frag(v2f i) : SV_TARGET
                        {
                                //---------------渲染阴影
                                SHADOW_CASTER_FRAGMENT(i)
                        }
                                ENDCG
                }













                        pass {
                                //---------------向前渲染基础灯光
                                                         Tags { "LightMode" = "ForwardBase" }
                                                        CGPROGRAM

                                                                 //---------------向前渲染基础
                                                                 #pragma multi_compile_fwdbase

                                #pragma vertex vert
                                #pragma fragment  frag

                                #include"UnityCG.cginc"
                        //---------------阴影程序集
                        #include "AutoLight.cginc"
                        //---------------光照程序集
                        #include "Lighting.cginc"

                                        //输入结构
                                        struct appdata
                                        {
                                                float4 vertex : POSITION;
                                                float2 uv : TEXCOORD0;
                                                //获取表面法线
                                                float3 normal:NORMAL;
                                                //获取表面切线
                                                float4 tangent:TANGENT;

                                        };

                                        struct v2f
                                        {
                                                float2 uv : TEXCOORD0;
                                                float4 pos : SV_POSITION;
                                                //切线空间转世界空间数据3代4
                                                float4 T2W0:TEXCOORD1;
                                                float4 T2W1:TEXCOORD2;
                                                float4 T2W2:TEXCOORD3;
                                                //---------------阴影数据结构
                                                SHADOW_COORDS(4)
                                        };

                                        float4 _GlassColor;
                                        //定义法线贴图变量
                                        sampler2D _BumpMap;
                                        float4 _BumpMap_ST;
                                        //定义法线强度变量
                                        float _BumpScale;
                                        float _HighlightPow;
                                        //获取环境球贴图
                                        samplerCUBE _CubeMap;
                                        float _CubeMapMipLevelA;
                                        float _CubeMapMipLevelB;
                                        float _RefractRatio;
                                        float4 _HighlightColor;

                                        //顶点函数
                                        v2f vert(appdata v)
                                        {
                                                v2f o;
                                                UNITY_INITIALIZE_OUTPUT(v2f, o);
                                                o.uv = TRANSFORM_TEX(v.uv, _BumpMap);
                                                o.pos = UnityObjectToClipPos(v.vertex);
                                                //世界法线
                                                float3 worldNormal = UnityObjectToWorldNormal(v.normal);
                                                //世界切线
                                                float3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
                                                //世界副切线
                                                float3 worldBinormal = cross(worldNormal, worldTangent) * v.tangent.w;
                                                //世界坐标
                                                float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;

                                                //构建变换矩阵
                                                //z轴是法线方向(n),x轴是切线方向(t),y轴可由法线和切线叉积得到,也称为副切线(bitangent, b)
                                                o.T2W0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);
                                                o.T2W1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);
                                                o.T2W2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);
                                                //---------------传递且处理阴影数据
                                                TRANSFER_SHADOW(o);
                                                //---------------更改输入顶点变量
                                                UNITY_TRANSFER_FOG(o, o.pos);
                                                return o;
                                        }

                                        fixed4 frag(v2f i) : SV_Target
                                        {
                                                //获取法线贴图
                                                float4 Normaltex = tex2D(_BumpMap, i.uv);
                                                //法线贴图0~1转-1~1
                                                float3 tangentNormal = UnpackNormal(Normaltex);
                                                //乘以凹凸系数
                                                tangentNormal.xy *= _BumpScale;
                                                //向量点乘自身算出x2+y2,再求出z的值
                                                tangentNormal.z = sqrt(1.0 - saturate(dot(tangentNormal.xy, tangentNormal.xy)));
                                                //向量变换只需要3*3
                                                float3x3 T2WMatrix = float3x3(i.T2W0.xyz,i.T2W1.xyz,i.T2W2.xyz);
                                                //法线从切线空间到世界空间
                                                float3 worldNormal = mul(T2WMatrix,tangentNormal);

                                                //获取顶点世界坐标
                                                float3 WordPos = float3(i.T2W0.w, i.T2W1.w, i.T2W2.w);



                                                //---------------获取阴影
                                fixed shadow = SHADOW_ATTENUATION(i);
                                        //---------------获取环境色
                                        fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;


                                                //摄像机方向
                                                fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - WordPos);
                                                //面比率
                                                float faceRatio =abs( dot(worldNormal, viewDir));

                                                //世界坐标灯光方向
                                                fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
                                                //灯光反射
                                                fixed3 reflectLightDir = normalize(reflect(-lightDir, worldNormal));
                                                //反射光线与视角点乘,获得高光渐变。
                                                fixed         Ramp_Specular = saturate(dot(reflectLightDir, viewDir));





                                                //表面反射方向
                                                fixed3 reflectDir = reflect(normalize(-viewDir), normalize(worldNormal));
                                                //获取反射贴图
                                                float3 _reflectColor = texCUBElod(_CubeMap, float4(reflectDir, _CubeMapMipLevelA*8));


                                                //表面折射射方向
                                                fixed3 refractDir = refract(normalize(-viewDir), normalize(worldNormal), faceRatio*_RefractRatio);
                                                //获取折射贴图
                                                 float3 _refractColor = texCUBElod(_CubeMap, float4(refractDir, (_CubeMapMipLevelB+ _CubeMapMipLevelA)*8));

                                                 float3 outColor = lerp(_reflectColor * _HighlightColor.rgb, _refractColor * _GlassColor.rgb * _HighlightColor.rgb, faceRatio)+ pow(Ramp_Specular, _HighlightPow)* _HighlightColor.rgb* shadow;


                                                //输出仿色贴图
                                                return fixed4(outColor+ ambient,1);
                                 }
                                 ENDCG
                         }
        }
}

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-11-16 08:27 , Processed in 0.092869 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表