unity shader reflect

改编自《cg教程--可编程实时图形学权威指南》上的demo。

本文的目的不在于教你如何实现反射效果,而是在于让你学会迁移cg、hlsl、glsl到unity中 [unity shader 资料很少,但是前面哪几种还是相对较多的 ]

反射向量计算公式 R=I-2N(N*I) 备注N*I是点乘   I入射光线,N法向量

函数实现:
float3 reflect(float3 I,float3 N)
{
  return I-2.0*N*dot(N,I);
}

Shader "CG shader Reflect"{
     Properties {      
                  environmentMap("Environment Map", Cube) = "" {}
                  reflectivity("reflectivity1", float) =1 //反射系数  决定反射强度
                  decalMap("decalMap", 2D) = "white" {}
                }
                SubShader{
                      Pass{
                           CGPROGRAM
                           #pragma vertex vert //顶点编程入口
                           #pragma fragment frag //片段编程入口
                           #include "UnityCG.cginc" //注意引入
                           struct VertInput{  //在UnityCG中有定义 可以参考appdata_base、appdata_tan、appdata_full
                               float4 position:POSITION;
                               float2 texCoordw:TEXCOORD0;
                               float3 normal1:NORMAL;
                           };
                           struct VertOutput{
                               float4 oPosition:SV_POSITION;
                               float2 oTexCoord:TEXCOORD0;
                               float3 R:TEXCOORD1;
                           };
                           // uniform 类型的参数 需要在Properties里面定义
                           uniform samplerCUBE environmentMap;
                           uniform float reflectivity;
                           uniform sampler2D decalMap;
                           VertOutput vert(VertInput input)
                           {
                               VertOutput o;
                               o.oPosition=mul(UNITY_MATRIX_MVP,input.position);//UNITY_MATRIX_MVP变量, 就是对应图形中的模型视图投影矩阵(ModelViewProj),unity中规定 必须这么写
                               o.oTexCoord=input.texCoordw;
                               float3 positionW=mul(_Object2World,input.position).xyz;//_Object2World 模型矩阵,把本地坐标转到世界坐标
                               float3 N=mul((float3x3)_Object2World,input.normal1);
                               N=normalize(N);
                               float3 I=positionW-_WorldSpaceCameraPos;//计算入射光线,需要在世界坐标系中计算。_WorldSpaceCameraPos视点在世界坐标的位置
                               o.R=reflect(I,N);//计算反射光线 reflect系统自带函数
                               return o;
                           }
                           
                           float4 frag(VertOutput output):COLOR
                           {
                               float4 reflectionColor=texCUBE(environmentMap,output.R);
                               float4 decalColor=tex2D(decalMap,output.oTexCoord);
                               float4 color1=lerp(decalColor,reflectionColor,reflectivity);
                               return color1;
                           }
                           ENDCG
                    }
            }
}

上例代码出现的_Object2World,_WorldSpaceCameraPos 莫名奇妙的参数,来自UnityCG.cginc文件,在对cg、hlsl、glsl进行移植的时候,特殊参数需要参考UnityCG.cginc文件的定义。

附unity shader 学习资料: http://en.wikibooks.org/wiki/Cg_Programming/Unity
### Unity URP 实现玻璃效果的 Shader 教程 #### 使用 HLSL 和透明度混合模式创建基础玻璃材质 为了在 Unity Universal Render Pipeline (URP) 中实现逼真的玻璃效果,通常会使用 `Transparent` 渲染队列并启用折射和反射特性。以下是构建此类着色器的关键要素: - **渲染类型设置**:将渲染类型设为 Transparent 并开启 ZWrite 关闭以允许其他物体透过玻璃显示[^1]。 ```csharp Tags { "RenderType"="Transparent" } ZWrite Off Blend SrcAlpha OneMinusSrcAlpha ``` - **表面输入定义**:通过自定义 HLSL 函数处理法线、颜色以及环境映射等属性来模拟光线穿过介质的行为[^2]。 ```hlsl struct Attributes { float4 positionOS : POSITION; float3 normalOS : NORMAL; }; half4 Frag(Varyings input) : SV_Target{ // 计算世界空间中的位置与法向量 float3 worldPos = mul(unity_ObjectToWorld, input.position).xyz; float3 viewDir = normalize(_WorldSpaceCameraPos - worldPos); // 获取当前像素的世界坐标系下的法线方向 float3 worldNormal = TransformObjectToWorldNormal(input.normal); // 折射率参数设定 const float etaRatio = 0.7f; // 利用 Snell 定律计算入射角对应的偏折角度 float cosThetaI = dot(-viewDir, worldNormal); float sinThetaT2 = pow((etaRatio * sqrt(max(0., 1.-cosThetaI*cosThetaI))), 2.); bool totalInternalReflection = false; if(sinThetaT2 >= 1.) { totalInternalReflection = true; } // 如果发生全内反射,则只返回反射光;否则按一定比例混合透射光和反射光 half3 reflColor = Reflect(viewDir, worldNormal); half3 refrColor = Refract(viewDir, worldNormal, etaRatio); half3 finalColor = lerp(refrColor, reflColor, step(cosThetaI, 0)); return half4(finalColor, 0.8); } ``` 此代码片段展示了如何利用 HLSL 编写一个简单的透明材质着色器,在其中实现了基本的折射逻辑,并考虑到了可能发生的全内反射现象[^3]。 对于更高级的效果,可以引入更多物理性质如菲涅尔效应、各向异性散射等,还可以借助于屏幕空间技术(Screen Space Reflection/Refraction)进一步增强视觉质量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值