10.高光反射Blinn

2023-11-08

 高光反射的公式:

 Specular = 直射光 * pow(cosθ,高光的参数) θ是反射光方向和视野方向的夹角

 

 

 

由图像看出高光参数可控制光的可视范围

  1. 逐顶点的高光反射
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "Custom/MySpecularShader-Vert"
{
    Properties
    {
        _Diffuse("Diffuse color",Color) = (1,1,1,1)
        _Gloss("Gloss",Range(8,200)) = 10
        _Specular("Specular",Color) = (1,1,1,1)
    }
    SubShader
    {
        pass
        {
            Tags { "LightMode"="ForwardBase" }
            CGPROGRAM
            #include "Lighting.cginc"
            #pragma vertex vert
            #pragma fragment frag
            fixed4 _Diffuse;
            half _Gloss;
            fixed3 _Specular;
            struct a2v
            {
                float4 vertex:POSITION;
                float3 normal:NORMAL;
            };
            struct v2f
            {
                float4 pos:SV_POSITION;
                fixed3 color:color;
            };
            v2f vert(a2v i)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(i.vertex);//UnityObjectToClipPos(i.vertex);
                fixed3 worldNormalDir = mul(i.normal,(float3x3)unity_WorldToObject);
                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;//获取环境光
                fixed3 normalDir = normalize(worldNormalDir);  //这个矩阵把一个方向从世界空间转换到模型空间  这样放在后面就是模型到世界了
                fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz);//对于每个顶点来说光的位置就是光的方向,因为光是平行的。
                fixed3 halfLambert = max(dot(normalDir,lightDir),0);//dot(normalDir,lightDir) * 0.5 + 0.5;  //半兰伯特光照公式 max(dot(normalDir,lightDir),0);
                fixed3 diffuse = _LightColor0.rgb * halfLambert * _Diffuse;//取得漫反射的颜色
                
                fixed3 reflectDir = normalize(reflect(-lightDir,normalDir));//反射光方向 
                fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - o.pos.xyz);//视野方向
                fixed3 specular = _LightColor0.rgb * _Specular * pow(max(dot(reflectDir, viewDir) , 0) , _Gloss);
                fixed3 tempColor = diffuse + ambient + specular;
                o.color = tempColor;
                return o;
            }
            float4 frag(v2f i):SV_TARGET
            {
                return fixed4(i.color,1);
            }  
            ENDCG
        }
    }
    FallBack "Diffuse"
}

 

 

  1. 逐像素的高光反射
Shader "Custom/MySpecularShader-Frag"
{
    Properties
    {
        _Diffuse("Diffuse color",Color) = (1,1,1,1)
        _Gloss("Gloss",Range(8,200)) = 10
        _Specular("Specular",Color) = (1,1,1,1)
    }
    SubShader
    {
        pass
        {
            Tags { "LightMode"="ForwardBase" }
            CGPROGRAM
            #include "Lighting.cginc"
            #pragma vertex vert
            #pragma fragment frag
            fixed4 _Diffuse;
            half _Gloss;
            fixed3 _Specular;
            struct a2v
            {
                float4 vertex:POSITION;
                float3 normal:NORMAL;
            };
            struct v2f
            {
                float4 pos:SV_POSITION;
                fixed3 worldNormalDir:color;
            };
            v2f vert(a2v i)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(i.vertex);//UnityObjectToClipPos(i.vertex);
                o.worldNormalDir = mul(i.normal,(float3x3)unity_WorldToObject);
                // o.color = tempColor;
                return o;
            }
            float4 frag(v2f i):SV_TARGET
            {
                //fixed3 worldNormalDir = mul(i.normal,(float3x3)unity_WorldToObject);
                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;//获取环境光
                fixed3 normalDir = normalize(i.worldNormalDir);  //这个矩阵把一个方向从世界空间转换到模型空间  这样放在后面就是模型到世界了
                fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz);//对于每个顶点来说光的位置就是光的方向,因为光是平行的。
                fixed3 halfLambert = max(dot(normalDir,lightDir),0);//dot(normalDir,lightDir) * 0.5 + 0.5;  //半兰伯特光照公式 max(dot(normalDir,lightDir),0);
                fixed3 diffuse = _LightColor0.rgb * halfLambert * _Diffuse;//取得漫反射的颜色
                
                fixed3 reflectDir = normalize(reflect(-lightDir,normalDir));//反射光方向 
                fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.pos.xyz);//视野方向
                fixed3 specular = _LightColor0.rgb * _Specular * pow(max(dot(reflectDir, viewDir) , 0) , _Gloss);
                fixed3 tempColor = diffuse + ambient + specular;
                return fixed4(tempColor,1);
            }  
            ENDCG
        }
    }
    FallBack "Diffuse"
}

效果如下

 

在后续发现高光位置和现实中不符合发现一个bug原因如下:

 

我在计算相机位置的时候把 点在剪裁空间下的坐标代入计算了,

实际上应该把点从模型空间下转成世界空间下再代入计算。

 

最终代码:

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "Custom/MySpecularShader-Vert"
{
    Properties
    {
        _Diffuse("Diffuse color",Color) = (1,1,1,1)
        _Gloss("Gloss",Range(8,200)) = 10
        _Specular("Specular",Color) = (1,1,1,1)
    }
    SubShader
    {
        pass
        {
            Tags { "LightMode"="ForwardBase" }
            CGPROGRAM
            #include "Lighting.cginc"
            #pragma vertex vert
            #pragma fragment frag
            fixed4 _Diffuse;
            half _Gloss;
            fixed3 _Specular;
            struct a2v
            {
                float4 vertex:POSITION;
                float3 normal:NORMAL;
            };
            struct v2f
            {
                float4 pos:SV_POSITION;
                fixed3 color:color;
            };
            v2f vert(a2v i)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(i.vertex);//UnityObjectToClipPos(i.vertex);
                fixed3 worldNormalDir = mul(i.normal,(float3x3)unity_WorldToObject);
                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;//获取环境光
                fixed3 normalDir = normalize(worldNormalDir);  //这个矩阵把一个方向从世界空间转换到模型空间  这样放在后面就是模型到世界了
                fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz);//对于每个顶点来说光的位置就是光的方向,因为光是平行的。
                fixed3 halfLambert = max(dot(normalDir,lightDir),0);//dot(normalDir,lightDir) * 0.5 + 0.5;  //半兰伯特光照公式 max(dot(normalDir,lightDir),0);
                fixed3 diffuse = _LightColor0.rgb * halfLambert * _Diffuse;//取得漫反射的颜色
                
                fixed3 reflectDir = normalize(reflect(-lightDir,normalDir));//反射光方向 
                float4 worldVert = mul(unity_ObjectToWorld, i.vertex);
                fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - worldVert.xyz);//视野方向
                fixed3 specular = _LightColor0.rgb * _Specular * pow(max(dot(reflectDir, viewDir) , 0) , _Gloss);
                fixed3 tempColor = diffuse + ambient + specular;
                o.color = tempColor;
                return o;
            }
            float4 frag(v2f i):SV_TARGET
            {
                return fixed4(i.color,1);
            }  
            ENDCG
        }
    }
    FallBack "Diffuse"
}
Shader "Custom/MySpecularShader-Frag"
{
    Properties
    {
        _Diffuse("Diffuse color",Color) = (1,1,1,1)
        _Gloss("Gloss",Range(8,200)) = 10
        _Specular("Specular",Color) = (1,1,1,1)
    }
    SubShader
    {
        pass
        {
            Tags { "LightMode"="ForwardBase" }
            CGPROGRAM
            #include "Lighting.cginc"
            #pragma vertex vert
            #pragma fragment frag
            fixed4 _Diffuse;
            half _Gloss;
            fixed3 _Specular;
            struct a2v
            {
                float4 vertex:POSITION;
                float3 normal:NORMAL;
            };
            struct v2f
            {
                float4 pos:SV_POSITION;
                fixed3 worldNormalDir:color;
                float4 worldVert:TEXCOORD1;
            };
            v2f vert(a2v i)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(i.vertex);//UnityObjectToClipPos(i.vertex);
                o.worldNormalDir = mul(i.normal,(float3x3)unity_WorldToObject);
                o.worldVert = mul(unity_ObjectToWorld, i.vertex);
                // o.color = tempColor;
                return o;
            }
            float4 frag(v2f i):SV_TARGET
            {
                //fixed3 worldNormalDir = mul(i.normal,(float3x3)unity_WorldToObject);
                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;//获取环境光
                fixed3 normalDir = normalize(i.worldNormalDir);  //这个矩阵把一个方向从世界空间转换到模型空间  这样放在后面就是模型到世界了
                fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz);//对于每个顶点来说光的位置就是光的方向,因为光是平行的。
                fixed3 halfLambert = max(dot(normalDir,lightDir),0);//dot(normalDir,lightDir) * 0.5 + 0.5;  //半兰伯特光照公式 max(dot(normalDir,lightDir),0);
                fixed3 diffuse = _LightColor0.rgb * halfLambert * _Diffuse;//取得漫反射的颜色
                
                fixed3 reflectDir = normalize(reflect(-lightDir,normalDir));//反射光方向 
                fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldVert.xyz);//视野方向
                fixed3 specular = _LightColor0.rgb * _Specular * pow(max(dot(reflectDir, viewDir) , 0) , _Gloss);
                fixed3 tempColor = diffuse + ambient + specular;
                return fixed4(tempColor,1);
            }  
            ENDCG
        }
    }
    FallBack "Diffuse"
}

 

这才是正确效果:

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

10.高光反射Blinn 的相关文章

  • 在 Threejs 平面上渲染 TMX 地图

    使用新代码更新了问题 我正在尝试编写一个 WebGL 着色器来绘制TMX层 https github com bjorn tiled wiki TMX Map Format 从 Tiled 编辑器导出 我正在使用 THREE js 创建一个
  • 如何使用 WebGL 和 GLSL 在 J/s 文件中运行 Shadertoy 中的着色器?

    我是着色器编程新手 我想使用 WebGL 和 GLSL 创建一个着色器 为了了解它的实际工作原理 我想测试 Shadertoy 的着色器 但是如何从 Shadertoy 获取代码并实际在 J S 文件中运行它呢 您是否只需将 Shadert
  • OpenGL ES - 在片段着色器中旋转纹理而不失真

    我正在使用 Android 的 GPUImage 库对位图应用一些效果 本质上 GPUImage接受位图并使用OpenGL ES 将1 x 1立方体渲染到位图大小的帧缓冲区中 用户可以编写自定义片段着色器来控制输出 我正在尝试编写一个片段着
  • 用于几何入口点的 SceneKit 着色器修改器适用于 iOS,但不适用于 OS X

    我正处于制作 SceneKit 着色器修改器 用于几何入口点 的早期阶段 该修改器根据高度图纹理置换平面的几何形状 计划是用它来创建地形 在 iOS 编辑 iOS 模拟器 中 着色器按其应有的方式工作 但会将此警告打印到控制台 SceneK
  • 着色器使立方体的边缘倾斜?

    这个问题涉及使用着色器 可能在 Unity3D 环境中 但 Metal 或 OpenGL 都可以 以在网格最小立方体上实现圆角边缘 我希望只使用 12 个三角形的简约网格立方体 然后通过着色器 使每个块的边缘 角 稍微倾斜 其实这样可以吗带
  • 如何在 Unity 中创建一个可以显示由许多小图像组成的纹理的着色器

    所以我想做的是从 SQL 表加载卫星图像并将它们包裹在一个球体周围以创建一个地球仪 我知道我已经加载了所涵盖的图像 我只是不确定如何使我的着色器以正确的方向显示图像 我去了 Unity 论坛并查看了这段代码 https docs unity
  • Unity3D - 用于精灵裁剪的着色器

    我正在尝试创建一个可用于在游戏中剪辑 2D 精灵的着色器 我在中找到了该着色器另一个问题 https stackoverflow com questions 16397023 unity3d a shader that will clip
  • OpenGL 实现多通道

    我在移植一些已成功实现的代码时遇到问题着色玩具 https www shadertoy com view XdyfWK对于桌面 OpenGL 问题是我需要创建一个 FrameBufferObject FBO 以便我可以进行离屏计算 稍后将其
  • glUseProgram(0) 的作用是什么?

    OpenGL 文档为glUseProgram https www khronos org registry OpenGL Refpages gl4 html glUseProgram xhtml声称用参数调用它zero将导致着色器执行的结果
  • OpenGL - 固定管线着色器默认值(使用着色器模仿固定管线)

    谁能给我提供类似于固定功能管道的着色器 我最需要默认的片段着色器 因为我在网上找到了类似的顶点着色器 但如果你有一双应该没问题 我想使用固定管道 但具有着色器的灵活性 因此我需要类似的着色器 以便我能够模仿固定管道的功能 非常感谢 我是新来
  • OpenGL ES 2.0 多个程序或多着色器还是什么?它是如何工作的?

    问题 TL DR 我的问题从根本上来说是我不知道 OpenGL ES 2 0 期望我如何编写和使用多个着色器 或者如果甚至建议 期望一个人会这样做 这里的基本问题是 如果我有一个苹果 一块发光的岩石和一个模糊网格 它们都在同一个 3D 世界
  • 如何使用鼠标改变OpenGL相机

    我正在尝试在 OpenGL 中设置一个相机来查看 3 维中的一些点 为了实现这一点 我不想使用旧的 固定的功能样式 glMatrixMode glTranslate 等 而是自己设置模型视图投影矩阵并在我的顶点着色器中使用它 正交投影就足够
  • 对数/线性 Z 缓冲区阴影贴图

    问题在于 伪影出现在距离很远的阴影中 我想尝试制作一个对数深度缓冲区 但我不明白应该在哪里完成以及如何完成 我对全向阴影贴图使用点光源方法 顶点着色器 version 460 core layout location 0 in vec3 a
  • Phong 着色问题

    我正在根据以下内容编写着色器冯模型 http en wikipedia org wiki Phong reflection model 我正在尝试实现这个方程 其中 n 是法线 l 是光线方向 v 是相机方向 r 是光反射 维基百科文章中更
  • Unity3D:在 AA 解析后绘制粒子以提高性能

    我正在尝试评估 MSAA 对 Unity 中含有大量粒子的场景的影响 为此 我需要 使用 8x MSAA 绘制场景中的所有非粒子对象 使用上一个通道中解析的深度缓冲区来渲染所有 将非遮挡粒子系统转移到较小的渲染目标上 将 2 的颜色缓冲区与
  • 更改 Qt OpenGL 窗口示例以使用 OpenGL 3.3

    我正在尝试更改 Qt OpenGL 示例以使用更现代的 opengl 版本 330 似乎合适 所以我做了 在 main cpp 上设置版本和配置文件 设置着色器版本 更改着色器以使用统一 它现在构建没有任何错误 但我只看到一个空白窗口 我错
  • 将自己的结构传递到 opengl es 2.0 着色器中

    我想尝试 OpenGL ES 2 0 编程指南 一书中的照明示例 在着色器中他们制作了两种结构 struct directional light vec3 direction normalized light direction in ey
  • 如何在使用 Cmake 构建期间编译 HLSL 着色器?

    我正在开发 d3d 应用程序 我想在使用 cmake 构建期间编译我的 hlsl 着色器 我不知道从哪里开始 这是我当前的 CMakeLists txt cmake minimum required VERSION 3 20 project
  • 如何计算正切和副法线?

    谈谈OpenGL着色语言 GLSL 中的凹凸贴图 镜面高光之类的东西 I have 顶点数组 例如 0 2 0 5 0 1 0 2 0 4 0 5 法线数组 例如 0 0 0 0 1 0 0 0 1 0 0 0 世界空间中点光源的位置 例如
  • 金属中的 SCN 着色器修改器 - 将统一传递给着色器

    我正在尝试将着色器修改器与 Metal 一起使用 我无法弄清楚如何声明制服 到目前为止我的片段修饰符是 color changes pragma arguments float4x4 u color transformation pragm

随机推荐

  • linux设备模型之bus,device,driver分析一

    本文系本站原创 欢迎转载 转载请注明出处 http www cnblogs com gdt a20 内核的开发者将总线 设备 驱动这三者用软件思想抽象了出来 巧妙的建立了其间的关系 使之更形象化 结合前面所学的知识 总的来说其三者间的关系为
  • vscode删除缩进多行tab

    shift tab 转载于 https www cnblogs com v5captain p 9160398 html
  • chrome扩展开发(2)- manifest.json文件简述

    一 本文目标 结合具体应用场景 让读者对manifest json文件的写法和主要属性拥有初步认识 二 目标读者 chrome扩展开发的初学者 想要先从宏观上了解一下chrome扩展能干哪些事情 而不是急于写出一个能运行的demo的人 三
  • 密码学 ~ 数字签名

    概念 数字签名 又称公钥数字签名 是只有信息的发送者才能产生的别人无法伪造的一段数字串 这段数字串同时也是对信息的发送者发送信息真实性的一个有效证明 它是一种类似写在纸上的普通的物理签名 但是使用了公钥加密领域的技术来实现的 用于鉴别数字信
  • PyCharm调试代码的时候出现pydev debugger: process xxxx is connecting

    最近在初学python的时候 在使用PyCharm调试代码的时候出现 pydev debugger process xxxx is connecting 和 Process finished with exit code 0 从从其返回的状
  • matlab神经网络训练图解释,matlab实现神经网络算法

    matlab 神经网络 net newff pr 3 2 logsig logsig 创建一个bp神经网络 10 显示训练迭代过程 0 05 学习速率0 05 1e 10 训练精度net trainParam epochs 50000 最大
  • 自定义单选框和多选框

    说明 作为一个Java后端程序员 有时候也需要自己去写些前端代码 所以将工作中用到的一些小知识做记录分享 1 自定义单选框 有图片 先看效果图 再献上完整代码
  • STM32F103ZET6【HAL函开发】STM32CUBEMX------3.USART串口进行数据的接收的发送

    目的 1 开机后 向串口1发送 hello world 2 串口1收到字节指令 0xA1 打开LED1 发送 LED1 Open 3 串口1收到字节指令 0xA2 关闭LED1 发送 LED1 Closed 4 在串口发送过程中 打开LED
  • python3 pip ipython 安装

    1 安装Python3 6 安装准备 mkdir usr local python3 wget no check certificate https www python org ftp python 3 6 0 Python 3 6 0
  • readis windows servrer 搭建与Java客户端的连接

    1 首先下载redis redis 2 0 2 zip 32 bit 解压 从下面地址下 http code google com p servicestack wiki RedisWindowsDownload 看到下面有redis 2
  • 《SegFormer:Simple and Efficient Design for Semantic Segmentation with Transformers》论文笔记

    参考代码 SegFormer 1 概述 介绍 这篇文章提出的分割方法是基于transformer结构构建的 不过这里使用到的transformer是针对分割任务在patch merge self attention和FFN进行了改进 使其更
  • 计算机内存取证之BitLocker恢复密钥提取还原

    BitLocker是微软Windows自带的用于加密磁盘分卷的技术 通常 解开后的加密卷通过Windows自带的命令工具 manage bde 可以查看其恢复密钥串 如下图所示 如图 这里的数字密码下面的一长串字符串即是下面要提取恢复密钥
  • 华为服务器如何设置网站dns,设置为正确的DNS 服务器地址

    设置为正确的DNS 服务器地址 内容精选 换一换 域名的DNS服务器定义了域名用于解析的权威DNS服务器 通过华为云注册成功的域名默认使用华为云DNS进行解析 详细内容 请参见华为云DNS对用户提供域名服务的DNS是什么 若您选择非华为云D
  • UE4缓存路径修改

    最简单的办法就是通过Evenyting搜索 Engine Config BaseEngine ini 找到你要修改的引擎对应文件 将 ENGINEVERSIONAGNOSTICUSERDIR DerivedDataCache修改为 GAME
  • ORA-00257:archiver error解决办法*

    ORA 00257 archiver error解决办法 出现ORA 00257错误 空间不足错误 通过查找资料 绝大部分说这是由于归档日志太多 占用了全部的硬盘剩余空间导致的 通过简单删除日志或加大存储空间就能够解决 一 更改归档模式 目
  • 为什么C++有多种整型?

    C 中有多种整型是为了满足不同的需求 提供更灵活和高效的整数表示方式 不同的整型具有不同的字节大小 范围和精度 可以根据应用的需求选择合适的整型类型 以下是一些原因解释为什么C 有多种整型 内存和性能优化 不同的整型在内存中占用的空间不同
  • 【读点论文】YOLOv7: Trainable bag-of-freebies sets new state-of-the-art for real-time object detectors新集合体

    YOLOv7 Trainable bag of freebies sets new state of the art for real time object detectors Abstract YOLOv7在5 FPS到160 FPS的
  • 实时监控MySQL慢查询

    背景 为了优化SQL 我们首先需要发现有问题的SQL语句 网上诸多教程都在教你使用诸如mysqldumpslow pt query digest这类工具分析MySQL慢查询日志 然而这一系列的工具都存在一个致命的缺陷 无法实时监控 而说起实
  • 如何使用HuggingFace训练Transformer

    文章目录 HuggingFace Transformers Tokenizer Model 下游任务 HuggingFace Transformers 使用BERT和其他各类Transformer模型 绕不开HuggingFace提供的Tr
  • 10.高光反射Blinn

    高光反射的公式 Specular 直射光 pow cos 高光的参数 是反射光方向和视野方向的夹角 由图像看出高光参数可控制光的可视范围 逐顶点的高光反射 Upgrade NOTE replaced mul UNITY MATRIX MVP