Unity Shader - 兰伯特漫反射

这篇具有很好参考价值的文章主要介绍了Unity Shader - 兰伯特漫反射。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

兰伯特漫反射公式:

漫反射(Diffuse)= 光源颜色 * max(0,cos(光方向和法线的夹角))

公式原理:

Unity Shader - 兰伯特漫反射

 从上面图片可以看出光照方向 L 与物体法相 N形成的 余弦值越大,反射光越大,角度为0度的时候最强 Cos(0) = 1,大于等于90度的时候为0 Cos(90) = 0;

所以我们首先需要计算出法向量N入射光方向L的角度的余弦值。

我们可以通过他们的点乘来计算,公式如下:

Unity Shader - 兰伯特漫反射

把向量归一化处理后,|L| 和 |N| 都是1,可以简化为:

Unity Shader - 兰伯特漫反射

让我们来实现以下:

逐顶点漫反射:

Shader "Unlit/001"
{
    Properties
    {
        // 漫反射颜色
        _Diffuse ("_Diffuse",Color) = (1,1,1,1)
    }
    SubShader
    {
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            
            #include "UnityCG.cginc"
            #include "Lighting.cginc"
            
            float4 _Diffuse;
            struct v2v
            {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
            };

            struct v2f
            {
                float4 vertex : POSITION;
                float3 color : Color;
            };

            v2f vert (v2v v)
            {
                v2f o;
                // 将对象空间中的点变换到齐次坐标中的摄像机裁剪空间
                o.vertex = UnityObjectToClipPos(v.vertex);
                // 光源方向
                float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
                // 将法向量转到世界坐标法向量
                float3 normal = UnityObjectToWorldNormal(v.normal);
                // 环境光颜色
                float3 ambinet = UNITY_LIGHTMODEL_AMBIENT.xyz;
                // 光源颜色 0 表示第一套光源 ,场景里可以有多个光源
                float3 lightColor = _LightColor0.xyz;
                // 漫反射公式 计算
                float3 diffuse = _Diffuse * lightColor * max(0,dot(lightDir,normal));
                o.color = diffuse + ambinet;
                return o;   
            }

            fixed4 frag (v2f i) : SV_Target
            {
                float4 color = float4(i.color,1);
                return color;
            }
            ENDCG
        }
    }
}

逐片源漫反射:

Shader "Unlit/002"
{
    Properties
    {
        // 漫反射颜色
        _Diffuse ("_Diffuse",Color) = (1,1,1,1)
    }
    SubShader
    {
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            
            #include "UnityCG.cginc"
            #include "Lighting.cginc"
            
            float4 _Diffuse;
            struct v2v
            {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
            };

            struct v2f
            {
                float4 vertex : POSITION;
                float3 normal : NORMAL;                
            };

            v2f vert (v2v v)
            {
                v2f o;
                // 将对象空间中的点变换到齐次坐标中的摄像机裁剪空间
                o.vertex = UnityObjectToClipPos(v.vertex);
                // 将法向量转到世界坐标法向量
                o.normal = UnityObjectToWorldNormal(v.normal);
                return o;   
            }

            fixed4 frag (v2f i) : SV_Target
            {
                // 光源方向
                float3 lightDir = _WorldSpaceLightPos0.xyz;
                // 光源颜色
                float lightColor = _LightColor0.rgb;
                // 漫反射公式 计算
                float3 diffuse = lightColor * lightDir * max(0,dot(lightDir,i.normal));
                float3 ambinet = UNITY_LIGHTMODEL_AMBIENT.rgb;
                float3 color = diffuse + ambinet;
                return float4(color,1);
            }
            ENDCG
        }
    }
}

让我们看以下效果:左边是逐顶点漫反射,右边是逐片元漫反射逐顶点的漫反射与逐片元的漫反射的区别在于顶点漫反射在阴影切换处会有明显的锯齿反应(不过在我这电脑上看并不明显),可以看的到明显的顶点。而片元漫反射则相对切换平滑。相对的,逐片元就比逐顶点好性能。

Unity Shader - 兰伯特漫反射

背光效果:

Unity Shader - 兰伯特漫反射 我们看到背光的地方非常暗,完全就看不见模型纹理了,这样的话效果在游戏里太影响体验了,于是就有了 半兰伯特光照模型 ,该技术是Valve公式在开发游戏《半条命》时提出的,由于该技术是在原兰伯特光照模型的基础上修改的,所以被称为半兰伯特光照模型 

漫反射(Diffuse)= 光源颜色 * (cos(光方向和法线的夹角)* 0.5 + 0.5)

其实就是把结果范围从 [-1,1] 映射到 [0,1]的范围内。这样的话在背光面也会有明暗变化,不会完全黑掉。

整体代码我就不贴出来了,把公式部分贴出来

// 漫反射公式 计算
//float3 diffuse = _Diffuse * lightColor * max(0,dot(lightDir,normal));
float3 diffuse = _Diffuse * lightColor * (dot(lightDir,normal) * 0.5 + 0.5);

正面:

Unity Shader - 兰伯特漫反射

背面:

Unity Shader - 兰伯特漫反射文章来源地址https://www.toymoban.com/news/detail-494008.html

到了这里,关于Unity Shader - 兰伯特漫反射的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Unity | Shader基础知识(第一集:unity中最简单的shader)

    目录 一、unity的shader 二、创建一个shader(在创建时,选前三种都可以) 三、内容解读 1.shader一直都在 2.我们写shader在写什么 四、没有被干预的shader(最简单的shader) 相关阅读 编写着色器概述 - Unity 手册 一、unity的shader unity写的shader并不是真正意义上的shader。 官方解释:

    2024年02月04日
    浏览(42)
  • 【Unity Shader】Unity阴影

    记录下在unity中如果想实现阴影,有哪些路子可以选择,目前看有两种 1.经典的shadowmap 2.planar projection 如果开启renderer组件的cast shadows为on,开启平行光的light组件的shadow type,那么就会在物体shader中寻找LightMode=ShadowCaster的Pass进行渲染 场景有两个物体,平面和球体,使用unity内

    2024年02月09日
    浏览(42)
  • Unity | Shader基础知识(什么是shader)

    Shader的中文名叫着色器。 着色器的作用: 这个世界是3D的,包括在Unity的场景中,我们建的球球,方块块之类的,都是3D的,但是,屏幕是2D的,把3D的东西,通过颜色的汇总,显示在2D的屏幕上。 想知道颜色是怎么合到一起的,我们就找个图片,把它拆开看。 因为世界上所有

    2024年02月15日
    浏览(50)
  • Unity Shader - UI/Default shader 优化示例

    Unity : 2020.3.37f1 Pipeline : BRP 做性能优化都是慢慢都扣出来的 当然,优先处理 top 热点的 但是一些就算不是 top,但是像素面积有多,overdraw 也多不可小觑 当然,如果你能找到性能热点,那还是优先分析一下哪些 shader 占的 cycles 最高,和 A, L/S, T, 最高 还有 register 的数量尽可能

    2024年02月07日
    浏览(31)
  • Unity中Shader观察空间推导(在Shader中实现)

    在上篇文章中,我们是实现了Shader中的观察空间推导。 Unity中Shader观察空间推导 我们在这篇文章中,根据上篇文章的推导,在Shader中实现观察空间矩阵的推导。 P view = [W view ] * P world P view = [V world ] -1 * P world P view = [V world ] T * P world 在属性面板定义测试使用到的 摄像机坐标

    2024年01月24日
    浏览(31)
  • Unity中Shader裁剪空间推导(在Shader中实现)

    我们在上一篇文章中,进行了正交相机视图空间下转化到裁剪空间下的矩阵推导。 Unity中Shader裁剪空间推导(正交相机到裁剪空间的转化矩阵) 我们在这篇文章中,在Unity的Shader中实现一下。 OpenGL下: [ 2 w 0 0 0 0 2 h 0 0 0 0 2 n − f n + f n − f 0 0 0 1 ] begin{bmatrix} frac{2}{w} 0 0 0

    2024年02月03日
    浏览(31)
  • 【Unity Shader】Unity前向渲染

    ForwardBase Pass(优先渲染),渲染一个逐像素平行光和所有的顶点/球面调和光,阴影只和平行光有关系,那阴影应该是这个Pass中实现的 ForwardAdd Pass(需要和Base配合使用,否则不生效),渲染剩余全部逐像素灯光 Unity会根据场景中各个光源的设置以及这些光源对物体的影响程

    2024年02月08日
    浏览(47)
  • Unity Shader:常用的C#与shader交互的方法

      俗话说久病成医,虽然不是专业技术美术,但代码写久了自然会积累一些常用的shader交互方法。零零散散的,总结如下:   有时候我们需要改变ui的一些属性,从而实现想要的效果。通常UGUI上有如下属性,而我们想要改变,就需要获取到Material这个属性:   这里拿Image来举

    2024年02月14日
    浏览(21)
  • Shader学习第七篇:几种Unity的Shader的例子

    下面是几种Shader的例子,从简单到复杂,一步一步了解 Shader 的编写机制。 顶点/片元着色器 Vertex/Fragment Shader,下面我们介绍的示例就是这个。 表面着色器 Surface Shader ,而这个底层Unity也是转成了顶点/片元着色器 固定函数着色器 Fixed Function Shader (已弃用) 在一些低端设备使

    2024年02月09日
    浏览(41)
  • 2023-08-22 Unity Shader 开发入门2 —— Shader 开发介绍

    ​ 计算机图形程序接口(Graphics API)是一套可编程的开放标准,不论 2D 还是 3D 游戏都需要这部分的底层 API 支持。 ​ 它本质上是软件,并不是硬件,是前人提前写好的调用系统硬件(GPU)绘制图形的代码。可以简单理解成是显卡厂商定义的一系列的底层的进行图形操作的加

    2024年02月11日
    浏览(26)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包