UnityShader官方案例之表面着色器光照示例

UnityShader——基础篇之UnityShader基础 Unity Shader 是 Unity 为研发者提供的高层记得渲染抽象层,Unity 希望以这种方式来让开发者更加轻松的控制渲染,见下图:在 Unity 中,所有的 Unity Shader 都是使用 ShaderLab 来编写的ShaderLab 是 Unity 编写 Unity Shader 的一种说明性语言,它使用了一些嵌套在花括号内部的**语义&&(syntax。 阅读详情

“Without purpose, the days would have ended, as such days always end, in disintegration.”

这个系列是表面着色器的光照模型,以及对自定义光照模型的深入
编写表面着色器时,您是在描述一个表面的属性(反射率颜色、法线等等),并由光照模型完成光照交互的计算。内置光照模型为 Lambert(漫反射光照)和 BlinnPhong(高光光照)。

有时您可能想使用自定义光照模型,在表面着色器 (Surface Shader) 中这是可以实现的。光照模型不过是与一些惯例匹配的几个 Cg/HLSL 函数。
内置
Lambert
和
BlinnPhong模型
在 Unity 的
Lighting.cginc里都可以找到

其在正向渲染路径中用于非与视线方向相关的光照模型(例如,漫反射)。

half4 LightingName (SurfaceOutput s, half3 lightDir, half atten);

其在正向渲染路径中用于与视线方向相关的光照模型。

half4 LightingName (SurfaceOutput s, half3 lightDir, half3 viewDir, half atten);

其用于延时光照路径中。

half4 LightingName_PrePass (SurfaceOutput s, half4 light);

_PrePass 这个函数,所有使用它的着色器都将仅编译成正向渲染。

现在来解释光照模型的定义:必须是Lighting + Name格式
光照模型函数参数:lightDir是光照模型的方向,atten是光照模型的衰减系数,viewDir是摄像机的视线方向

  Shader "Example/Diffuse Texture" {
    Properties {
      _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader {
      Tags { "RenderType" = "Opaque" }
      CGPROGRAM
      #pragma surface surf Lambert
      struct Input {
          float2 uv_MainTex;
      };
      sampler2D _MainTex;
      void surf (Input IN, inout SurfaceOutput o) {
          o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
      }
      ENDCG
    }
    Fallback "Diffuse"
  }

step1
这是Unity3D内置的Lambert(漫反射)光照模型

Lambert光照模型就在Lighting.cginc中,现在用unity Editor打开就可以看到内置的漫反射光照函数是怎么写的了
这里写图片描述

现在,让我们进行一次完全相同的操作,但要编写出我们自己的光照模型,而不是使用内置的 Lambert 模型。

//
// {
//    Properties 
//    {
//      _MainTex ("Texture", 2D) = "white" {}
//    }
//
//    SubShader
//    {
//      Tags { "RenderType" = "Opaque" }
//      CGPROGRAM
//
      //光照模式声明:使用自定义的光照模式  
      #pragma surface surf SimpleLambert

      //光照函数名必须是Lighting + 自定义名字
      //它通过在表面法线(s.Normal)和光线方向(LightDir)之间执行一次数量积来计算光照
      //然后应用光衰减和颜色。
      half4 LightingSimpleLambert (SurfaceOutput s, half3 lightDir, half atten) 
      {
          //SurfaceOutput s这个就是经过表面计算函数surf处理后的输出,我们讲对其上的点根据光线进行处理
          //点积的结果在-1至1之间,这个值越大表示法线与光线间夹角越小,这个点也就应该越亮。余弦值计算不多说了
          half NdotL = dot (s.Normal, lightDir);
          half4 c;

          //接下来我们将surf输出的颜色(s.Albedo)与光线的颜色_LightColor0.rgb的乘积,
          //然后再与刚才计算的光强系数(Ndotl)和输入的衰减系数相乘,
          //为什么后面还要乘以2? 大家可以试试把乘以2去掉,其实就是为了进行光强补偿
          c.rgb = s.Albedo * _LightColor0.rgb * (NdotL * atten * 2);
          c.a = s.Alpha;
          return c;
      }

//      struct Input 
//      {
//          float2 uv_MainTex;
//      };
//
//      sampler2D _MainTex;
//      void surf (Input IN, inout SurfaceOutput o) 
//      {
//          o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
//      }
//      ENDCG
//    }
//    Fallback "Diffuse"
//  }

step2
下面进行改进,漫反射遮蔽

 #pragma surface surf WrapLambert

        half4 LightingWrapLambert (SurfaceOutput s, half3 lightDir, half atten) 
        {
          half NdotL = dot (s.Normal, lightDir);


          //在光照的基础上加上这句,增加光强
          //其实官方的说法更准确:其中照明“环绕”在对象边缘。它对模拟子面散射效果有用。
          half diff = NdotL * 0.5 + 0.5;
          half4 c;
          c.rgb = s.Albedo * _LightColor0.rgb * (diff * atten * 2);
          c.a = s.Alpha;
          return c;
        }

step3
卡通渐变

通过一个不同的渐变纹理 实现不同的效果,
这是一个“渐变”(Ramp) 光照模型,它使用纹理渐变来定义表面如何对光线与法线之间的夹角作出反应。

Shader"Example / AutisticPatient SurfaceShader001"
 {
    Properties 
    {
      _MainTex ("Texture", 2D) = "white" {}
      //渐变纹理,初始值为gray
      _Ramp("Ramp",2D) = "gray"{}
    }

    SubShader
    {
      //子着色器标签
      Tags { "RenderType" = "Opaque" }
      CGPROGRAM

      //光照模式声明:使用自定义的光照模式  
      #pragma surface surf Ramp

      //变量声明
      sampler2D _Ramp;

      //实现光照函数
      half4 LightingRamp (SurfaceOutput s, half3 lightDir, half atten) 
      {
          //点乘反射光线法线和光线方向
          half NdotL = dot (s.Normal, lightDir);

          //增强光强
          half diff = NdotL * 0.5 + 0.5;

          //从纹理中定义渐变效果,官方的例子中是float2(diff)这样写的,很明显报错了
          half3 ramp = tex2D (_Ramp, float2(diff,diff)).rgb;
          half4 c;
          c.rgb = s.Albedo * _LightColor0.rgb * ramp * (atten * 2);
          c.a = s.Alpha;
          return c;
       }

      struct Input 
      {
          float2 uv_MainTex;
      };

      sampler2D _MainTex;
      void surf (Input IN, inout SurfaceOutput o) 
      {
          //从主纹理获取颜色值
          o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
      }
      ENDCG
    }
    Fallback "Diffuse"
  }

没有效果图,如果大家想找模型看看效果的话,asset store是个好地方,有很多免费的模型可以用,但一定要找有对应贴图的

step4
**简单高光**specular lighting model

Shader"Example / AutisticPatient SurfaceShader001"
 {
    Properties 
    {
      _MainTex ("Texture", 2D) = "white" {}
      //渐变纹理,初始值为gray
      _Ramp("Ramp",2D) = "gray"{}
    }

    SubShader
    {
      //子着色器标签
      Tags { "RenderType" = "Opaque" }
      CGPROGRAM

      //定义光照模型
      #pragma surface surf SimpleSpecular

      //实现自定义光照模型
      half4 LightingSimpleSpecular (SurfaceOutput s, half3 lightDir, half3 viewDir, half atten) 
      { 
          //normalize是来自CG语言中的函数,作用是归一化向量。
          half3 h = normalize (lightDir + viewDir);

          //点积后取最大值,当法线方向和灯光方向一致时,它们的点积结果达到最大值1,最亮
          //当两者方向垂直时,达到0,大于90度将为负值,max函数的作用便是保证光强不为负
          half diff = max (0, dot (s.Normal, lightDir));

          float nh = max (0, dot (s.Normal, h));

          //nh的 48次方
          float spec = pow (nh, 48.0);

          half4 c;
          c.rgb = (s.Albedo * _LightColor0.rgb * diff + _LightColor0.rgb * spec) * (atten * 2);
          c.a = s.Alpha;
          return c;
       }

      struct Input 
      {
          float2 uv_MainTex;
      };

      sampler2D _MainTex;
      void surf (Input IN, inout SurfaceOutput o) 
      {
          //从主纹理获取颜色值
          o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
      }
      ENDCG
    }
    Fallback "Diffuse"
  }

这里面有些数学计算我没注释,大家可以改动其中的一些值,在unity 中进行编译查看效果,就会明白数学计算的作用

好了,这节就到这吧

Unityshader 常用函数,常量,API手册 2、Uniform 参数:Uniform是用来限制一个变量的初始值的来源,当声明一个变量为Uniform类型的时候,表示这个变量的初始值来自于外部的其他环境。除了获取初始值的这点之外,Uniform关键字声明的变量和其他变量是完全一样的。1、varying 参数:在Cg程序中通过语义进行绑定变量, Cg语言提供了一组语义词,用以表示参数是由顶点的那些数据初始化的,一旦这个变量使用了语义词进行绑定,那么这个变量值被初始化的同时也意味着它有了特殊的含义,如表示位置、法线等含义。就得到了运动模糊效果。 阅读详情

相关推荐

【实现100个unity特效之4】Unity ShaderGraph使用教程与各种特效案例(2023/12/1更新)

ShaderGraph是Unity中的一个可视化工具,用于创建和编辑图形着色器。其意义在于简化编写复杂着色器的过程,减少对具体编程语言的依赖,使艺术家和设计师可以更方便地创建各种美术效果。使用ShaderGraph可以通过图形界面设置着色器属性,包括颜色、纹理、光照等,并在视窗预览中即时显示结果,从而快速迭代和调整着色器。使用ShaderGraph需要先安装Unity 2018.1或以上版本,并添加ShaderGraph插件。打开ShaderGraph面板后,可以通过拖放节点并连接它们来创建着色器。

向宇的博客,专注php/web全栈 unity游戏开发,欢迎大家评论纠错 4万+

Unity shader 官网文档全方位学习(二)Lighting model及自定义Lighting model

原文地址  http://www.kankanews.com/ICkengine/archives/85875.shtml 上文咱们学了surface shader。这玩意在开始的时候啊,在定义哪个函数处理surface时用一定要指定Lighting model(即光照模型)的。自带的是Lambert和BlinnPhong.本文首先对这两个进行说明,后面讲解如何自定义光照模型

啊哈的专栏 851

ShaderGraph案例工程

这个项目是一个使用Unity 2018.1的SG特性创建的不同自定义着色器库。所有的着色器都兼容轻量级脚本渲染管道。

UnityShader官方案例讲解——SurfaceShader(3)

“Focus on where you’re going and you’ll know what steps to take. Focus on the steps you’re taking and you won’t know where you’re going.”– Simon Sinek, Inspirational Speaker step1 接下来实现的是将细节纹理显示在游戏对象上

AutisticPatient的博客 918

本地部署 Anything LLM+Ollama+DeepSeek R1 大模型并实现外部访问

DeepSeek 一经发布就引起社会的广泛的关注,因为 DeepSeek 的价格低廉,性能卓越,提供了多种使用方式,满足不同用户的需求和场景。本文将详细的介绍如何在本地 Windows 上安装部署 Anything LLM + Ollama 来实现用户和 DeepSeek-r1 对话的功能以及利用路由侠内网穿透实现外网访问。

lyxnwct的博客 1897

保姆级教程:用SSH手动重建黑群晖RAID1阵列,修复‘存储空间损毁’

本文提供了一份详细的SSH手动重建黑群晖RAID1阵列的教程,帮助用户修复‘存储空间损毁’问题。通过深入解析mdadm软RAID的底层逻辑,从诊断到重建的全过程,确保用户能够掌握黑群晖存储池的修复技术。适用于技术爱好者和系统管理员。

weixin_30319153的博客 293

UnityShader官方案例讲解——SurfaceShader(1)

Living without an aim is like sailing without a compass.(John Ruskin)接下来要做的就是对uniy官方的着色器案例进行讲解,本着学习的态度,我会尽量解释每一行代码,因为还没有毕业,剩下的时间比较多,我会写的比较详细(慢&懒)因为我也是新手,所以我很理解新手的痛处吗,在一开始我不会一下子列出好多好多的语法,或者是好多 好多的关键字,咱们一起从例

AutisticPatient的博客 925

模型剪枝实战 | Torch-Pruning 库在YOLOv8上的应用指南

本文详细介绍了如何使用Torch-Pruning库对YOLOv8模型进行结构化剪枝,以实现模型“瘦身”。通过DepGraph(依赖图)技术自动处理层间依赖,确保剪枝安全。文章提供了从环境搭建、核心原理理解到完整剪枝流程的实战指南,并强调了剪枝后的微调与性能评估,帮助开发者在保持精度的同时显著提升模型推理速度。

weixin_29046035的博客 503

Shader 光照入门

shader光照入门

Theolulu的博客 1681

2、稳定性问题全景图——死机、重启、ANR、Crash、黑屏五大类

当 Crash 发生在 system_server、surfaceflinger、mediaserver 等关键系统进程中时,其后果等同于系统级故障,可能触发 Zygote 重启甚至 kernel panic。这类问题在稳定性治理中的优先级应等同于 P0。

woailuojp的博客 49

GEE聚类分析:基于sentinel-2 影像进行 K-Means 聚类分析

这篇博客介绍了如何使用 Google Earth Engine (GEE) 进行 K-Means 聚类分析,以识别感兴趣区域(ROI)内的不同地表覆盖类型。文章详细说明了从定义用户参数、准备参考区域、加载和预处理 Sentinel-2 图像,到训练 K-Means 聚类器并对图像进行聚类的完整流程。代码示例展示了如何设置参数、采样像素数据、训练聚类器,并将结果可视化。最后,还提供了将聚类结果导出到 Google Drive 的选项。通过该教程,用户可以掌握在 GEE 平台上进行地理数据聚类分析的基本方法。

此星光明博客 263

UnityShader学习笔记 Unity的表面着色器

将渲染流程划分为表面着色器、光照模型和光照着色器这样的层面。 其中,表面着色器定义了模型表面的反射率、法线和高光等,光照模型选择是使用兰伯特还是Blinn-Phong等模型。而光照着色器负责计算光照衰减、阴影等。 表面着色器实际上就是在顶点/片元着色器之上又添加了一层抽象。 表面着色器的一个例子 使用表面着色器来实现一个使用了法线纹理的漫反射效果。 Shader "Unity Shaders Book/Chapter 17/Bumped Diffuse" { Properties {

漫漫无期的博客 1624

【maven】idea左侧External Libraries里,没有Maven的依赖包 代码飘红

文章目录1.概述M.参考 1.概述 因为内网开发,然后这几天我被隔离了,然后公司搞了一个外网的vpn能连接的云桌面,云桌面也是网络隔离的,因此只能自己拷贝相关的文件到里面。 然后我就拷贝了代码和maven仓库中的一部分,因为本地的20G一次拷贝不完,需要多次拷贝,但是我拷贝了kafka,仍然飘红。具体如下 idea左侧External Libraries里,没有Maven的依赖包 然后整了很久都没搞定,后来我自己新建了一个项目,然后引入发现是不可以的,而且框框里面的飘红。 然后我就想是不是因为缺少依赖

九师兄 4411

【UnityShader入门精要学习笔记】第十七章 表面着色器

表面着色器实际上就是对顶点片元着色器上的一层抽象,使用表面着色器可以用一种更容易理解的方式编写shader,不需要考虑前向渲染路径还是延迟渲染路径,场景中的光源等等等等要素。

milu_ELK的博客 1945

Whisper 模型在嘈杂环境中的表现:降噪与增强技术

本报告系统分析了OpenAI Whisper模型在嘈杂环境中的表现机制,重点揭示其内在降噪能力的技术边界,并结合语音增强(SE)、时频分析等前沿技术提出优化方案。内容覆盖从基础概念(如噪声类型对ASR的影响)到理论框架(模型架构与数学形式化),再到实际应用(端到端部署策略)的全链路分析,同时通过案例研究与可视化工具(如梅尔频谱对比图)降低复杂概念的认知门槛。核心结论指出:Whisper的多语言预训练虽提升了泛化性,但在低信噪比(SNR<5dB)场景下需结合前端降噪或联合训练技术以突破性能瓶颈。

AI 原生应用开发的博客 488

YOLOv8改进:全网原创首发 | 新颖的多尺度卷积注意力(MSCA),即插即用,助力小目标检测 | NeurIPS2022

多尺度卷积注意力(MSCA),有效地提取上下文信息;1)作为注意力MSCA使用;

①答疑群聊服务;②YOLO大模型知识问答系统;③计算机视觉论文生成智能体; 3844

UnityShader入门精要——表面着色器

表面着色器的CG代码是直接而且也必须写在SubShader块中,Unity 会在背后为我们生成多个Pass。当然,可以在SubShader一开始处使用Tags来设置该表面着色器使用的标签。我们也可以使用LOD命令设置该表面着色器的LOD值。然后,我们使用CGPROGRAM和ENDCG定义了表面着色器的具体代码。 1 编译指令编译指令最重要的作用是指明该表面着色器使用的表面函数和光照函数,并设置一些可选参数。表面着色器的CG块中的第一句代码往往就是它的编译指令。编译指令的一般格式如下: 其中,#pra

weixin_51327051的博客 1698

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

UnityShader学习之旅 -- 表面着色器

表面着色器 与顶点/片元区别 CG代码是直接而且必须写在subshader块中,unity会在背后生成多个Pass, CG中定义表面着色器的具体代码 结构 两个结构体、编译指令 工作原理 1.surfaceFunc它将您需要的所有 UV 或数据作为输入,并填充输出结构 SurfaceOutput 2.表面着色器编译器随后计算出需要的输入、填充的输出等等,并生成实际的顶点和像素着色器以及渲染通道来处理前向和延迟渲染 特点 生成的表面着色器代码会尝试处理所有可能的光照/阴影/光照

laz0807的博客 495

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

UnityShader17:光照属性与阴影

前置:UnityShader16:点光源和聚光灯 一、一些重要的光照、阴影属性 一个一个来(绿色的部分暂时可以不用了解): Type:光照类型,除了常用的3个,还有一个面光源 Color:光照颜色 Mode:光照模式:实时光照/混合/烘培光照 Intensity:光照强度 Indirect Multiplier:在计算该灯光所产生的间接光照时的强度倍乘 Shadow Type:阴影类型:无阴影/硬阴影/软阴影 Cookie:用于光照投影的纹理 Cookie Size:Cooki...

加载中... 2345

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

UnityShader之五 表面着色器基础

UnityShader系列文章转载于 @浅墨_毛星云,为本人的学习笔记,转载请注明出处。 文章链接:https://blog.youkuaiyun.com/poem_qianmo/article/details/42215079 表面着色器的标准输出结构     定义一个“表面函数(surface function)”,需要输入相关的UV信息或数据信息,并在输出结构中填充SurfaceOutput。S...

m0_37884055的博客 2033

UnityShader4:UnityShader的形式

前置:UnityShader2:Shader与材质 一、Standard Surface Shader 代码解析 在前置中已经了解了什么是表面着色器,下面这是Standard Surface Shader,也是创建 Shader 时的默认代码之一 Shader "Custom/NewSurfaceShader" { Properties { _Color("Color", Color) = (1,1,1,1) _MainTex("Albedo ...

加载中... 731

UnityShader(一)基础光照shader

最近系统学习了UnityShader,想把自己的理解放在这里。 首先是基础光照Shader,包含了法线纹理,多光源,阴影,光照衰减的处理等,使用的是Phong光照模型。我基本标注了所有注释,如有不对还请提出。 Shader "Custom/BaseLight" { Properties { _Color ("Color", Color) = (1,1,1,1)//物体本身颜色 _MainTex ("Main Tex", 2D) = "white" {}//2D

qq_41982646的博客 506

[UnityShader2]表面着色器基础

原文链接:http://blog.youkuaiyun.com/poem_qianmo/article/details/42215079 1.输入结构 Input 这个输入结构通常拥有着色器需要的所有纹理坐标(texture coordinates)。纹理坐标(Texturecoordinates)必须被命名为“uv”后接纹理(texture)名字。(或者uv2开始,使用第二纹理坐标集)。

宏哥的博客 1188

【UnityShader入门精要学习笔记】第三章(3)章节总结

上一节我们学习了Unity Shader的定义、使用方法和基本结构。让我们回忆一下。我们在学习渲染流水线的时候了解到,Shader是用于着色器编程的。我们首先要区分,Unity中的Shader和我们在渲染流水线中的Shader不是同一个东西,Unity中的Shader统称为Unity Shader。如果开发者需要配置渲染流水线,就需要进行诸多配置以及着色器代码编写,其中涉及的配置和文件实在太多。Unity为这些工作集成了一个方便的抽象层,也就是。

milu_ELK的博客 1285

【UnityShader入门精要学习笔记】第三章(2)Unity Shader的形式,章节答疑

上一节我们学习了Unity Shader的定义、使用方法和基本结构。让我们回忆一下。我们在学习渲染流水线的时候了解到,Shader是用于着色器编程的。我们首先要区分,Unity中的Shader和我们在渲染流水线中的Shader不是同一个东西,Unity中的Shader统称为Unity Shader。如果开发者需要配置渲染流水线,就需要进行诸多配置以及着色器代码编写,其中涉及的配置和文件实在太多。Unity为这些工作集成了一个方便的抽象层,也就是。

milu_ELK的博客 1428

UnityShader(九)Unity中的基础光照(下)

标准光照模型仅仅是一个经验模型,它不完全符合现实世界的光照现象,但是它具有易用性、计算速度和得到的效果都比较好,也被广泛使用。因为广泛使用,它有许多称呼,一些资料会称它为Phong光照模型,在Blinn的方法简化下它也被称为Blinn-Phong光照模型。但这种模型有很多局限性。首先有很多重要的物理现象无法表现,如菲涅尔反射。其次,Blinn-Phong模型时各项同性的,当我们固定视角和光源方向旋转这个表面时反射不会发生任何变化。而有些表面是具有各项异性的。

米芝鱼的博客 1276
上一篇: UnityShader官方案例讲解——SurfaceShader(4)
下一篇: UnityShader官方案例之编写顶点和片段着色器
测试账号0001
博客等级 码龄10年 13粉丝 10原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值