【Unity Shader入门精要 第6章】基础光照(二)

1. 获取环境光

unity shader中可以通过 UNITY_LIGHTMODEL_AMBIENT获取当前环境光颜色信息。

fixed4 frag(v2f i) : SV_Target
{
     return UNITY_LIGHTMODEL_AMBIENT;
}

在这里插入图片描述

2. 漫反射

2.1 兰伯特模型

  • 创建Chapter_6_Diffuse_Lambert作为测试材质
  • 创建Chapter_6_Diffuse_Lambert作为测试shader,并赋给Chapter_6_Diffuse_Lambert材质
  • Pass中增加Tags{“LightMode” = “ForwardBase”},并添加引用 #include “Lighting.cginc”
  • 场景中创建胶囊体,将Chapter_6_Diffuse_Lambert材质赋给胶囊体
  • 场景中添加一盏平行光,并调整平行光角度

shader如下:

Shader "MyShader/Chapter_6/Chapter_6_Diffuse_Lambert"
{
    Properties
    {
        _Diffuse("Diffuse", Color) = (1,1,1,1)
    }

    SubShader
    {
        Pass
        {
            Tags{"LightMode" = "ForwardBase"}
            
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            #include "Lighting.cginc"
            
            struct a2v
            {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
            };
            
            struct v2f
            {
                float4 vertex : SV_POSITION;
                fixed4 color : COLOR0;
            };
            
            fixed4 _Diffuse;
            
            v2f vert(a2v i)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(i.vertex);
                fixed3 _ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
                
                float3 _lightDir = normalize(ObjSpaceLightDir(i.vertex));
                float3 _normal = normalize(i.normal);
                fixed3 _diffuse = _LightColor0.rgb * _Diffuse.xyz * saturate(dot(_normal, _lightDir));
                o.color = fixed4(_diffuse + _ambient, 1);

                return o;
            }
            
            fixed4 frag(v2f i) : SV_Target
            {
                return i.color;
            }
            
            ENDCG
        }
    }
}

shader效果如下:
在这里插入图片描述

2.2 半兰伯特模型

  • 将顶点着色器中的 fixed3 _diffuse = _LightColor0.rgb * _Diffuse.xyz * saturate(dot(_normal, _lightDir)); 修改为
    fixed3 _diffuse = _LightColor0.rgb * _Diffuse.xyz * (0.5 * dot(_normal, _lightDir) + 0.5);

效果如下:
在这里插入图片描述

2.3 逐像素的漫反射

  • 以兰伯特模型为基础,将光照计算改为在片元着色器中逐像素处理
  • 需要在顶点着色器中先将顶点的法线转换到世界空间
  • 然后在片元着色器中用插值得到的当前像素的法线方向与世界空间下的光源方向进行光照计算
  • 由于平行光不关心位置信息,因此对于平行光源,_WorldSpaceLightPos0.xyz存储的是光源的方向而不是位置

shader如下:

Shader "MyShader/Chapter_6/Chapter_6_Diffuse_LambertInFragment"
{
    Properties
    {
        _Diffuse("Diffuse", Color) = (1,1,1,1)
    }

    SubShader
    {
        Pass
        {
            Tags{"LightMode" = "ForwardBase"}
            
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            #include "Lighting.cginc"
            
            struct a2v
            {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
            };
            
            struct v2f
            {
                float4 vertex : SV_POSITION;
                float3 worldNormal : COLOR0;
            };
            
            fixed4 _Diffuse;
            
            v2f vert(a2v i)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(i.vertex);
                o.worldNormal = mul(i.normal, (float3x3)unity_WorldToObject);
                return o;
            }
            
            fixed4 frag(v2f i) : SV_Target
            {
                fixed3 _ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;
                
                float3 _worldNormal = normalize(i.worldNormal);
                float3 _worldLight = normalize(_WorldSpaceLightPos0.xyz);
                fixed3 _diffuse = _LightColor0.rgb * _Diffuse.xyz * saturate(dot(_worldNormal, _worldLight));
                
                return fixed4(_diffuse + _ambient, 1);
            }
            
            ENDCG
        }
    }
}

效果如下:
在这里插入图片描述
可见与逐顶点光照相比,阴影边缘明显更加平滑

3. 高光反射

3.1 逐顶点光照的Phong模型

shader如下:

Shader "MyShader/Chapter_6/Chapter_6_Specular_PhongInVertex"
{
    Properties
    {
        _Diffuse("Diffuse", Color) = (1,1,1,1)
        _Specular("Specular", Color) = (1,1,1,1)
        _Gloss("Gloss", Range(1.0, 256.0)) = 20
    }

    SubShader
    {
        Pass
        {
            Tags{"LightMode" = "ForwardBase"}
            
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            #include "Lighting.cginc"
            
            struct a2v
            {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
            };
            
            struct v2f
            {
                float4 vertex : SV_POSITION;
                fixed4 color : COLOR0;
            };
            
            fixed4 _Diffuse;
            fixed4 _Specular;
            half _Gloss;
            
            v2f vert(a2v i)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(i.vertex);
                
                fixed3 _ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;
                
                float3 _lightDir = normalize(ObjSpaceLightDir(i.vertex));
                float3 _normalDir = normalize(i.normal);
                fixed3 _diffuse = _LightColor0.rgb * _Diffuse.xyz * saturate(dot(_lightDir, _normalDir));
                
                float3 _viewDir = normalize(ObjSpaceViewDir(i.vertex));
                float3 _reflDir = normalize(2 * dot(_lightDir, _normalDir) * _normalDir - _lightDir);
                fixed3 _specular = _LightColor0.rgb * _Specular.xyz * pow(saturate(dot(_viewDir, _reflDir)), _Gloss);
                o.color = fixed4(_diffuse + _specular + _ambient, 1);
                
                return o;
            }
            
            fixed4 frag(v2f i) : SV_Target
            {   
                return i.color;
            }
            
            ENDCG
        }
    }
}

效果如下:
在这里插入图片描述

3.2 逐像素光照的Phong模型

  • 这里用 reflect(-_worldLight, _worldNormal) 方法代替了原来手动计算反射光线的过程,二者结果是一样的
  • reflect方法要求传入的入射光方向是从光源指向照射点,因此需要将原来计算得到的光源方向先取反再传入

shader如下:

Shader "MyShader/Chapter_6/Chapter_6_Specular_PhongInFragment"
{
    Properties
    {
        _Diffuse("Diffuse", Color) = (1,1,1,1)
        _Specular("Specular", Color) = (1,1,1,1)
        _Gloss("Gloss", Range(1.0, 256.0)) = 20
    }

    SubShader
    {
        Pass
        {
            Tags{"LightMode" = "ForwardBase"}
            
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            #include "Lighting.cginc"
            
            struct a2v
            {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
            };
            
            struct v2f
            {
                float4 vertex : SV_POSITION;
                float3 worldNormal : COLOR0;
                float3 worldPos : COLOR1;
            };
            
            fixed4 _Diffuse;
            fixed4 _Specular;
            half _Gloss;
            
            v2f vert(a2v i)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(i.vertex);
                o.worldNormal = mul(i.normal, (float3x3)unity_WorldToObject);
                o.worldPos = mul(unity_ObjectToWorld, i.vertex).xyz;
                return o;
            }
            
            fixed4 frag(v2f i) : SV_Target
            {
                fixed3 _ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;
                
                float3 _worldNormal = normalize(i.worldNormal);
                float3 _worldLight = normalize(_WorldSpaceLightPos0.xyz);
                fixed3 _diffuse = _LightColor0.rgb * _Diffuse.xyz * saturate(dot(_worldNormal, _worldLight));
                
                float3 _viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos);
//                float3 _reflDir = normalize(2 * dot(_worldNormal, _worldLight) * _worldNormal - _worldLight);
                float3 _reflDir = normalize(reflect(-_worldLight, _worldNormal));
                fixed3 _specular = _LightColor0.rgb * _Specular.xyz * pow(saturate(dot(_viewDir, _reflDir)), _Gloss);
                
                return fixed4(_diffuse + _specular + _ambient, 1);
            }
            
            ENDCG
        }
    }
}

效果如下:
在这里插入图片描述

3.3 逐像素光照的Blinn-Phong模型

shader如下:

Shader "MyShader/Chapter_6/Chapter_6_Specular_BlinnPhongInFragment"
{
    Properties
    {
        _Diffuse("Diffuse", Color) = (1,1,1,1)
        _Specular("Specular", Color) = (1,1,1,1)
        _Gloss("Gloss", Range(1.0, 256.0)) = 20
    }

    SubShader
    {
        Pass
        {
            Tags{"LightMode" = "ForwardBase"}
            
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            #include "Lighting.cginc"
            
            struct a2v
            {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
            };
            
            struct v2f
            {
                float4 vertex : SV_POSITION;
                float3 worldNormal : COLOR0;
                float3 worldPos : COLOR1;
            };
            
            fixed4 _Diffuse;
            fixed4 _Specular;
            half _Gloss;
            
            v2f vert(a2v i)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(i.vertex);
                o.worldNormal = mul(i.normal, (float3x3)unity_WorldToObject);
                o.worldPos = mul(unity_ObjectToWorld, i.vertex).xyz;
                return o;
            }
            
            fixed4 frag(v2f i) : SV_Target
            {
                fixed3 _ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;
                
                float3 _worldNormal = normalize(i.worldNormal);
                float3 _worldLight = normalize(_WorldSpaceLightPos0.xyz);
                fixed3 _diffuse = _LightColor0.rgb * _Diffuse.xyz * saturate(dot(_worldNormal, _worldLight));
                
                float3 _worldView = normalize(_WorldSpaceCameraPos.xyz - i.worldPos);
                float3 _h = normalize(_worldLight + _worldView);
                fixed3 _specular = _LightColor0.rgb * _Specular.xyz * pow(saturate(dot(_h, _worldNormal)), _Gloss);
                
                return fixed4(_diffuse + _specular + _ambient, 1);
            }
            
            ENDCG
        }
    }
}

效果如下:
在这里插入图片描述
相同Gloss下感觉Blinn-Phong好像要更发散一些,逐顶点的Blinn-Phong就不做了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/616084.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

i春秋-GetFlag

题目 考点 sql注入,md5加密,代码审计,利用eval函数 解题 参考wp https://www.cnblogs.com/qiaowukong/p/13630130.html找md5值 看见验证码中的提示,就是去找一个md5值前六位是指定值的数(严格来说不一定是数&…

408算法题专项-2019年

题目: 分析:要求空间复杂度为O(1),我们可以逆向假设可以开空间,得出一种思路,然后对这种思路优化空间即可得到O(1) 思路一:假设开空间 思考:再开…

【C语言题解】用函数来模拟实现strlen()、strcpy()、strcmp()、strcat()

🥰欢迎关注 轻松拿捏C语言系列,来和 小哇 一起进步!✊ 学习了函数后,老师让我们用函数来实现上面这四个字符串函数。 我们首先来了解一下这四个字符串函数: 1.strlen函数 用于获取字符串长度(不包括末尾…

读天才与算法:人脑与AI的数学思维笔记25_涌现理论

1. 人工智能新闻 1.1. 人工智能新闻报道算法的核心是如何将未经处理的原始数据转换成新闻报道 1.2. 很少有记者为美联社决定使用机器来帮助报道这些新闻持反对意见 1.2.1. 像“Wordsmith”这样的算法,具有自动化的洞察力、科学的叙事能力,现在正被应用…

2024年建筑施工特种作业人员安全生产知识试题

100分题库提供安全员考试试题、建筑安全员考试预测题、建筑安全员ABC考试真题、安全员证考试题库等,提供在线做题刷题,在线模拟考试,助你考试轻松过关。 单选题(1-10) 1.因生产安全事故受损害的从业人员,除…

打开远程连接的命令是什么?

远程连接是一种能够在不同设备之间建立连接并共享信息的技术。在许多情况下,我们需要通过远程连接来访问其他设备或处理一些远程任务。本文将介绍一些常用的打开远程连接的命令。 使用SSH连接远程设备 SSH(Secure Shell)是一种安全的网络协议…

大数据Scala教程从入门到精通第六篇:Scala编译结果反编译分析

一:Scala编译结果反编译分析 问题:为什么Scalac之后的生成的class文件有两个,一个带$的,一个不带$的? 不能直接java 执行scala编译的字节码文件。 直接运行的话就会报错,会报一个类没有被找到。 引入类库就…

免费思维13招之六:功能型思维

免费思维13招之六:功能型思维 这节来学习一下免费思维的另一大思维——功能型思维。 这个思维通俗易懂。功能型思维是指将其他产品的功能在我们的产品上进行体现,让客户获得免费的使用。 也就是说,客户买了你的产品,却可以免费得…

Android Studio在android Emulator中运行的项目黑屏

前言: 最近在做一个Android相关的小项目,因为之前这方面的项目做的比较的少。今天在使用虚拟机调试的时候经常出现一些莫名其妙的问题,经过自己多次的尝试和搜索终于解决了这些问题。 问题: 每次run(运行&#xff09…

报表-集成

1、部署报表服务器 以centos为例 1.1 将服务拷贝到服务器 其中JDK-17是对应平台的jdk 1.2 修改lite-report下的source.config 1.3 把设计好的报表文件拷贝到lite-report/report 1.4 启动服务:sh run.sh restart 2、使用Nginx location /litereport/ { …

【全面介绍下Spring】

🌈个人主页: 程序员不想敲代码啊 🏆CSDN优质创作者,CSDN实力新星,CSDN博客专家 👍点赞⭐评论⭐收藏 🤝希望本文对您有所裨益,如有不足之处,欢迎在评论区提出指正,让我们共…

Golang | Leetcode Golang题解之第77题组合

题目&#xff1a; 题解&#xff1a; func combine(n int, k int) (ans [][]int) {// 初始化// 将 temp 中 [0, k - 1] 每个位置 i 设置为 i 1&#xff0c;即 [0, k - 1] 存 [1, k]// 末尾加一位 n 1 作为哨兵temp : []int{}for i : 1; i < k; i {temp append(temp, i)}t…

转载:ubuntu18.04 安装wine以及添加mono和gecko打开简单.net应用的方法

https://www.cnblogs.com/jinanxiaolaohu/p/12191576.html 1. 今天突然想试试能不能用ubuntu跑一下公司的.net的智能客户端(SmartClient). 想到的办法就是 安装wine 但是过程略坑..这里简单说一下总结之后的过程. 2. 第一步安装wine相关内容 查了下有winehq和wine两种. …

[数据集][目标检测]管道焊缝质量检测数据集VOC+YOLO格式1134张2类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;1134 标注数量(xml文件个数)&#xff1a;1134 标注数量(txt文件个数)&#xff1a;1134 标注…

java项目之相亲网站的设计与实现源码(springboot+mysql+vue)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的相亲网站的设计与实现。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; 相亲网站的设计与实…

leetcode——反转链表

206. 反转链表 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a;创建三个指针n1,n2,n3&#xff0c;遍历原链表&#xff0c;通过三者之间的关系将链表反转。下面给出图示&#xff1a; 下面给出题解代码&#xff1a; typedef struct ListNode ListNode; struct List…

华为昇腾310B1平台 [ERROR] Send frame to vdec failed, errorno:507018

目录 1 [ERROR] Send frame to vdec failed, errorno:507018 2 bug解决尝试1 3 bug解决尝试2 4 bug解决尝试3 附录&#xff1a;华为视频解码基本原理 1调用aclvdecCreateChannel接口创建视频码流数据处理的通道 2 调用aclvdecSendFrame接口将视频码流解码成YUV420SP格式…

【SpringBoot】解锁后端测试新境界:学习Mockito与MockMvc的单元测试魔法

文章目录 前言&#xff1a;Java常见的单元测试框架一.Junit5基础二.SpringBoot项目单元测试1.添加依赖2.SpringBoot单元测试标准结构3.SpringBoot单元测试常用注解 三.单元测试中如何注入依赖对象1.真实注入&#xff08;AutoWired、 Resource&#xff09;2.Mock注入2.1.前言2.2…

技术爱好者必看:如何用AI问答API彻底改变用户体验!

AI 问答 API 对接说明 我们知道&#xff0c;市面上一些问答 API 的对接还是相对没那么容易的&#xff0c;比如说 OpenAI 的 Chat Completions API&#xff0c;它有一个 messages 字段&#xff0c;如果要完成连续对话&#xff0c;需要我们把所有的上下文历史全部传递&#xff0…

RustGUI学习(iced)之小部件(十二):如何使用rule分割线部件来分割UI?

前言 本专栏是学习Rust的GUI库iced的合集,将介绍iced涉及的各个小部件分别介绍,最后会汇总为一个总的程序。 iced是RustGUI中比较强大的一个,目前处于发展中(即版本可能会改变),本专栏基于版本0.12.1. 概述 这是本专栏的第十二篇,主要讲述rule分割线部件的使用,会结合…