Shader学习笔记(一):Surface Shader

卜若的代码笔记-unityshader系列-第三章:void surf()函数 第三章:void surf()函数 在本章中,我们主要介绍上一章遗留下的问题,void surf()扮演一个什么样的角色,我们应该怎么使用它? 1.1 函数的基本介绍 要想了解这个函数,我们或许得先了解一下片元着色器的着色流程 fragment shader 其中表面函数就是指void surf()函数。 请注意,这个流程是一个渲染流水线,在有些材料里面你可以看到渲染管线,其实都是... 阅读详情

Surface Shader是Unity为了方便shader编写提供的特殊功能,它对底层的vertex/fragment shader做了封装,省去了一些重复代码编写的工作量。我的理解是它同时具有vertex/fragment shader的功能,只是写法上更加简洁,更容易上手。

Unity的官方manual上就提供了几个最好的学习例子,我在学习的过程中加上了注释。

简单的漫反射(Simple)

这里写图片描述

  Shader "Example/Diffuse Simple" {
    SubShader {
      Tags { "RenderType" = "Opaque" } // 标签,决定什么时候渲染(对不透明物体渲染)
      CGPROGRAM // //CG语言标记开始
      #pragma surface surf Lambert // 编译指令 surface shader 自定义函数 光照模型[1] 
      struct Input {               // 输入的结构体
          float4 color : COLOR;    // 颜色值
      };
      void surf (Input IN, inout SurfaceOutput o) { // surface shader处理函数
          o.Albedo = 1;  // 将基础颜色设为白色[2]
      }
      ENDCG
    }
    Fallback "Diffuse" // 发生异常时回滚成Unity内置的Diffuse shader
  }

带纹理的漫反射(Texture)

这里写图片描述

  Shader "Example/Diffuse Texture" {
    Properties {
      _MainTex ("Texture", 2D) = "white" {} // 纹理,若没有赋值则默认为全白
    }
    SubShader {
      Tags { "RenderType" = "Opaque" }
      CGPROGRAM
      #pragma surface surf Lambert
      struct Input {
          float2 uv_MainTex; // 纹理uv坐标
      };
      sampler2D _MainTex;
      void surf (Input IN, inout SurfaceOutput o) {
          o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb; // 按uv坐标查找纹理上的像素,并获取rgb值
      }
      ENDCG
    } 
    Fallback "Diffuse"
  }

带法向贴图的漫反射(Normal mapping)

这里写图片描述

Shader "Example/Diffuse Bump" {
    Properties {
      _MainTex ("Texture", 2D) = "white" {}
      _BumpMap ("Bumpmap", 2D) = "bump" {} // 法向贴图[3]
    }
    SubShader {
      Tags { "RenderType" = "Opaque" } 
      CGPROGRAM
      #pragma surface surf Lambert
      struct Input {
        float2 uv_MainTex;
        float2 uv_BumpMap;
      };
      sampler2D _MainTex;
      sampler2D _BumpMap;
      void surf (Input IN, inout SurfaceOutput o) {
        o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
        o.Normal = UnpackNormal (tex2D (_BumpMap, IN.uv_BumpMap)); // 将从法向贴图中取得的法向量赋给output
      }
      ENDCG
    } 
    Fallback "Diffuse"
  }

边缘光(Rim Lighting)

这里写图片描述

 Shader "Example/Rim" {
    Properties {
      _MainTex ("Texture", 2D) = "white" {}
      _BumpMap ("Bumpmap", 2D) = "bump" {}
      _RimColor ("Rim Color", Color) = (0.26,0.19,0.16,0.0) // 边缘光的颜色
      _RimPower ("Rim Power", Range(0.5,8.0)) = 3.0 // 边缘光的强度
    }
    SubShader {
      Tags { "RenderType" = "Opaque" }
      CGPROGRAM
      #pragma surface surf Lambert
      struct Input {
          float2 uv_MainTex;
          float2 uv_BumpMap;
          float3 viewDir; // 观察向量
      };
      sampler2D _MainTex;
      sampler2D _BumpMap;
      float4 _RimColor;
      float _RimPower;
      void surf (Input IN, inout SurfaceOutput o) {
          o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
          o.Normal = UnpackNormal (tex2D (_BumpMap, IN.uv_BumpMap));
          // 对观察向量和法向量求点积,这个值越小,代表这两个方向夹角越接近90度,即为轮廓边缘
          half rim = 1.0 - saturate(dot (normalize(IN.viewDir), o.Normal)); 
          // 越接近边缘,发出的光越亮
          o.Emission = _RimColor.rgb * pow (rim, _RimPower);
      }
      ENDCG
    } 
    Fallback "Diffuse"
  }

细节纹理(Detail Texture)

这里写图片描述

  Shader "Example/Detail" {
    Properties {
      _MainTex ("Texture", 2D) = "white" {}
      _BumpMap ("Bumpmap", 2D) = "bump" {}
      _Detail ("Detail", 2D) = "gray" {} // 细节纹理[4]
    }
    SubShader {
      Tags { "RenderType" = "Opaque" }
      CGPROGRAM
      #pragma surface surf Lambert
      struct Input {
          float2 uv_MainTex;
          float2 uv_BumpMap;
          float2 uv_Detail;
      };
      sampler2D _MainTex;
      sampler2D _BumpMap;
      sampler2D _Detail;
      void surf (Input IN, inout SurfaceOutput o) {
          o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
          // 将纹理和细节纹理叠加
          o.Albedo *= tex2D (_Detail, IN.uv_Detail).rgb * 2;
          o.Normal = UnpackNormal (tex2D (_BumpMap, IN.uv_BumpMap));
      }
      ENDCG
    } 
    Fallback "Diffuse"
  }

屏幕空间下的细节纹理(Detail Texture in Screen Space)

这里写图片描述

 Shader "Example/ScreenPos" {
    Properties {
      _MainTex ("Texture", 2D) = "white" {}
      _Detail ("Detail", 2D) = "gray" {}
    }
    SubShader {
      Tags { "RenderType" = "Opaque" }
      CGPROGRAM
      #pragma surface surf Lambert
      struct Input {
          float2 uv_MainTex;
          float4 screenPos; // 屏幕坐标
      };
      sampler2D _MainTex;
      sampler2D _Detail;
      void surf (Input IN, inout SurfaceOutput o) {
          o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
          float2 screenUV = IN.screenPos.xy / IN.screenPos.w;
          screenUV *= float2(8,6);
          // 根据屏幕的uv坐标来叠加细节纹理[5]
          o.Albedo *= tex2D (_Detail, screenUV).rgb * 2;
      }
      ENDCG
    } 
    Fallback "Diffuse"
  }

立方体贴图反射(Cubemap Reflection)

这里写图片描述

  Shader "Example/WorldRefl" {
    Properties {
      _MainTex ("Texture", 2D) = "white" {}
      _Cube ("Cubemap", CUBE) = "" {} // 立方体贴图[6]
    }
    SubShader {
      Tags { "RenderType" = "Opaque" }
      CGPROGRAM
      #pragma surface surf Lambert
      struct Input {
          float2 uv_MainTex; 
          float3 worldRefl; // 世界反射向量
      };
      sampler2D _MainTex;
      samplerCUBE _Cube;
      void surf (Input IN, inout SurfaceOutput o) {
          o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb * 0.5;
          // 根据世界反射向量和立方体贴图,反射相应的rgb
          o.Emission = texCUBE (_Cube, IN.worldRefl).rgb;
      }
      ENDCG
    } 
    Fallback "Diffuse"
  }

世界坐标下的切片(Slices via World Space Position)

这里写图片描述

  Shader "Example/Slices" {
    Properties {
      _MainTex ("Texture", 2D) = "white" {}
      _BumpMap ("Bumpmap", 2D) = "bump" {}
    }
    SubShader {
      Tags { "RenderType" = "Opaque" }
      Cull Off
      CGPROGRAM
      #pragma surface surf Lambert
      struct Input {
          float2 uv_MainTex;
          float2 uv_BumpMap;
          float3 worldPos;
      };
      sampler2D _MainTex;
      sampler2D _BumpMap;
      void surf (Input IN, inout SurfaceOutput o) {
      // 自定义的切片函数(将y和z作为参数,意味沿x轴做切片)
          clip (frac((IN.worldPos.y+IN.worldPos.z*0.1) * 5) - 0.5);
          o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
          o.Normal = UnpackNormal (tex2D (_BumpMap, IN.uv_BumpMap));
      }
      ENDCG
    } 
    Fallback "Diffuse"
  }

使用顶点修改器的法线挤压(Normal Extrusion with Vertex Modifier)

这里写图片描述

  Shader "Example/Normal Extrusion" {
    Properties {
      _MainTex ("Texture", 2D) = "white" {}
      _Amount ("Extrusion Amount", Range(-1,1)) = 0.5 // 挤压参数
    }
    SubShader {
      Tags { "RenderType" = "Opaque" }
      CGPROGRAM
      #pragma surface surf Lambert vertex:vert // 声明会使用顶点修改器
      struct Input {
          float2 uv_MainTex;
      };
      float _Amount;
      void vert (inout appdata_full v) { // 顶点修改器实现
          v.vertex.xyz += v.normal * _Amount; // 沿法线移动顶点的坐标
      }
      sampler2D _MainTex;
      void surf (Input IN, inout SurfaceOutput o) {
          o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
      }
      ENDCG
    } 
    Fallback "Diffuse"
  }

逐顶点计算自定义数据(Custom data computed per-vertex)

这里写图片描述

  Shader "Example/Custom Vertex Data" {
    Properties {
      _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader {
      Tags { "RenderType" = "Opaque" }
      CGPROGRAM
      #pragma surface surf Lambert vertex:vert
      struct Input {
          float2 uv_MainTex;
          float3 customColor; // 自定义数据
      };
      void vert (inout appdata_full v, out Input o) {
          UNITY_INITIALIZE_OUTPUT(Input,o);
          // 在顶点修改器中,将法向量的绝对值赋值给参数customColor
          o.customColor = abs(v.normal); 
      }
      sampler2D _MainTex;
      void surf (Input IN, inout SurfaceOutput o) {
          o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
          // 使用传递过来的参数,对颜色做叠加
          o.Albedo *= IN.customColor;
      }
      ENDCG
    } 
    Fallback "Diffuse"
  }

注释:
[1]:Unity中最常用的是两种内置的光照模型:Lambert 和 BlinnPhong。
[2]:Albedo是物体的基础颜色,与之不同的Emission是自发光颜色,详细的input和output变量表参见官网。
[3]:法向贴图是为了实现凹凸不平的效果,可参见文章。
[4]:细节纹理是为了让纹理产生更细腻的感觉,可参见文章。
[5]:注意rgb相乘和相加的应用场合不同,这里给出了解释。
[6]:立方体贴图可用来做环境反射和天空盒,可参见文章。

【Unity Shaders】初探Surface Shader背后的机制 转载请注明出处!写在前面一直以来,Unity Surface Shader背后的机制一直是初学者为之困惑的地方。Unity Surface Shader在Unity 3.0的时候被开放给公众使用,其宣传手段也是号称让所有人都可以轻松地写shader。但由于资料缺乏,很多人知其然不知其所以然,无法理解Unity Surface Shader在背后为我们做了哪些事情。前几天一直被问到一个问题,为什么我 阅读详情

相关推荐

【Unity Shaders】Diffuse Shading——创建一个基本的Surface Shader

这一次的工作非常简单,我们主要是为了了解Unity Shaders的基本工作原理。 准备工作 创建一个新的Unity Project在Assets目录下新建一个文件夹:Shaders在Assets目录下新建一个文件夹:Materials 实现 在Shaders文件夹下,点击右键新建一个Shader,命名为BasicDiffuse,并打开它

candycat 1万+

Unity SurfaceShader基础知识入门

本文主要讲解了Unity中SurfaceShader的具体写法,以及几个常用的CG函数的用法。 在这里先说明一下,表面着色器将分为两次讲解,本文介绍表面着色器的基本概念和一些写法,用内置的兰伯特光照模式来进行Surface Shader的书写,而下次将介绍Surface Shader+自定义的光照模式的写法。

weixin_42565127的博客 1526

【Unity Shaders】Diffuse Shading——向Surface Shader添加properties

这次是在上一篇的基础上,进一步学习Unity Shaders的Properties。 准备工作 我们假设你已经进行了上一篇里的工作:创建了一个BasicDiffuse.shader,并且看到了Unity自动为你创建的代码: Shader "Custom/BasicDiffuse" { Properties { _MainTex ("Base (RGB)", 2D) =

candycat 1万+

SHADER学习笔记(一):Surface Shader

Surface Shader是Unity为了方便shader编写提供的特殊功能,它对底层的vertex/fragment shader做了封装,省去了一些重复代码编写的工作量。我的理解是它同时具有vertex/fragment shader的功能,只是写法上更加简洁,更容易上手。 Unity的官方manual上就提供了几个最好的学习例子,我在学习的过程中加上了注释。 简单的漫反射(SIMPLE) Shader "Example/Diffuse Simple" { SubShad.

真像大白阿的博客 1622

【Unity Shaders】Diffuse Shading——在Surface Shader中使用properties

在上一篇中,我们已经向Surface Shader中添加了一些properties。在这篇教程里,我们将学习如何在Shader中访问和使用它们,以便通过调整Inspector中的变量来改变渲染效果。 准备工作 在上一篇结束后,我们的shader代码如下:Shader "Custom/BasicDiffuse" { Properties { _EmissiveCol

candycat 1万+

Unity笔记 Surface Shader

学习《unity shaders and effects book》的tips。

fjl2007的博客 2922

Unity Shader表面着色器Surface Shader介绍

表面着色器是一种对艺术家友好的着色器,它不同于传统的顶点着色器和片元着色器等流程,而是添加了一层抽象,整个渲染流程的着色器被分为三个:表面着色器、光照模型和光照着色器。其中,表面着色器定义了模型表面的反射率、法线和高光等,光照模型则选择兰伯特、Phong和Bliin-Phong等模型。光照着色器负责计算光照衰减和阴影等。绝大部分时候只需要关注表面着色器,例如纹理和颜色等,光照模型是提前定义的,光照着色其由系统定义,不会轻易更改。...

weixin_42565127的博客 1102

Shader 笔记一 表面着色器 Surface Shader

参考 猫都能学会的Unity3D Shader入门指南(一) 猫都能学会的Unity3D Shader入门指南(二) https://docs.unity3d.com/Manual/SL-SurfaceShaders.html 概念 Shader和Material: Shader(着色器)实际上就是一小段程序,它负责将输入的Mesh(网格)以指定的方式和输入的贴图或者颜色等组合作...

王王王渣渣的博客 2271

UnityShader---SurfaceShader(模板和各种效果实现:边缘自发光、火焰流动、燃烧、法线扭曲、简单模糊、消融、区域过度、雪效果等)---17

//自定义表面着色器:自定义四个函数 Shader "Custom/39" { Properties { _Color ("Color", Color) = (1,1,1,1) _MainTex ("Albedo (RGB)", 2D) = "white" {} _BumpMap("BumpMap",2D)="bump"{} _Amount("Amount",Range(-0.1,0.1))=0 } SubSh

weixin_41155760的博客 1289

Unity Shader 学习笔记(一)——Shader基础

一、什么是Shader? 简单来说shader就是一个告诉计算机以某种方式描绘物体的程序。 二、编写语言 使用Nvidia CG语言、微软HLSL语言编写,但都包含在Unity的 ShaderLab 语言中。 三、常用的Shader类型 Vertex&Fragment Shader(顶点片元着色器):是最基本的,也是非常强大的一种类型。一般用于2D的物体以及场景或者做一些特效。 Surface Shader:在系统编译后是一个复杂的Vertex&Fragment ..

L人青的博客 769

【Unity5.x Shaders】最基本的Surface Shader-Diffuse shader以及Surface中的三种输出结构

某些物体可能具有均匀的颜色和光滑的表面,但光滑程度不足以照射反射光。 这些哑光材料最好用Diffuse Shader。 在现实世界中,不存在纯diffuse materials Diffuse shader经常出现在游戏中,下面就是一个简单的Diffuse shader代码Shader "Custom/DiffuseShader" { Properties {

森系少女的游戏梦 3052

Unity Shader 表面着色器(Surface Shader)

Unity Shader分为表面着色器(Surface Shader),顶点着色器(Vertex Shader),片段着色器(Fragment Shader) 我们先来看个简单的Surface Shader,看看它都能做什么。 首先我们通过"Create->3D Object ->Plane"创建一个面板 然后通过"Create->Shader->Standard Surface S

jk823394954的专栏 1万+

从EXIF到测绘:解码大疆影像元数据的实战应用指南

本文深入解析了大疆无人机影像元数据的实战价值,重点阐述了如何利用EXIF和XMP中的GPS、RTK、姿态角及相机内参等关键信息,提升测绘、三维重建及精准农业等项目的成果精度与效率。通过自动化质检脚本与行业应用场景剖析,指导从业者将元数据从信息转化为生产力,实现从拍照到专业测绘的跨越。

dell8的博客 527

Unity Shader开发指南:Surface、V&F与Shader Graph核心解析

在计算机图形学中,着色器(Shader)是控制渲染管线中顶点和像素处理的核心程序,其原理在于通过GPU并行计算,将3D模型的几何与材质信息转换为屏幕上的2D图像。这项技术是实现游戏画面、影视特效和实时可视化等数字内容的关键。对于Unity开发者而言,掌握不同的Shader编写方式能极大提升渲染效果开发效率与灵活性。表面着色器(Surface Shader)作为Unity封装的高级抽象层,通过声明式编程快速实现基于物理的光照模型,适合标准材质开发;顶点片元着色器(Vertex & Fragment Shade

weixin_30385925的博客 416

LightTools宏 vs Python API:光学仿真自动化方案选型指南

本文深入对比了LightTools光学仿真自动化中VBA宏与Python API两种方案。VBA宏内嵌易用,适合固定流程批处理;Python API生态强大,尤其在参数优化算法集成方面优势显著,便于构建复杂工作流。文章结合案例,为不同场景下的技术选型提供清晰指南。

garlic的博客 940

高德地图可视化入门:零基础用Python+高德API打造你的第一个热力图

本文详细介绍了如何使用Python和高德地图API从零构建商业级热力图。通过环境配置、地理编码、数据清洗到最终可视化展示的全流程指南,帮助开发者快速掌握地图可视化技术,特别适合展示商圈人流、疫情热点等地理分布数据。

weixin_29053067的博客 306

Unity3D Shader :surface Shader

Propertie                _Color("Color", Color) = (1,1,1,1)//主颜色 _MainTex("Albedo (RGB)", 2D) = "white" {}//主纹理 _Cutoff("Alpha Cutoff",Range(0.0,1.0)) = 0.5//Alpha剔除度 _Glossiness("Smoothness", Rang...

weixin_42452001的博客 612

231003-四步MacOS-iPadOS设置无线竖屏随航SideCar

新建虚拟屏幕参考文献。

专注机器学习之路 7487

Shader编程学习笔记(八)—— Surface Shader 2

目录1、引言2、surface函数3、SurfaceOutput”和“SurfaceOutputStandard”两种结构体的对比 1、引言   上一篇我们主要了解了Surface Shader使用了“#pragma surface surf Standard fullforwardshadows”指令的意义,这里我们主要了解“surf”surface函数。 void surf (Input I...

对酒当歌﹏✍ 513

第3.1.3章 机器人第三方库实战总结:ROS 2 入门实战及和ROS1的对比,打通机器人开发的任督二脉

本文针对机器人SLAM开发中第三方库的学习痛点,重点介绍ROS 2在SLAM中的应用。文章首先对比ROS 1与ROS 2的核心差异,梳理ROS 2知识图谱,包括节点、话题、服务等核心概念。通过实战项目演示如何构建激光SLAM节点,结合代码详解运行流程。最后给出学习建议,强调动手实践的重要性,帮助开发者快速掌握ROS 2在SLAM开发中的关键应用。

行知SLAM 180

Modbus测试工具ModbusPoll与Modbus Slave使用方法 小白实操记录

Modbus 下面介绍modbus标准协议从站、主站仿真工具;可用于指令下发,数据采集等;是学习、现场运维的好工具。 1 介绍 Modbus Poll :Modbus主机仿真器,用于测试和调试Modbus从设备。该软件支持ModbusRTU、ASCII、TCP/IP。用来帮助开发人员测试Modbus从设备,或者其它Modbus协议的测试和仿真。它支持多文档接口,即,可以同时监视多个从设备/数据域。每个窗口简单地设定从设备ID,功能,地址,大小和轮询间隔。你可以从任意一个窗口读写寄存器和线圈。如果你想改

码灵的博客 1万+

Shader 基础使用(二) --- surface Shader

基本数据类型 float 单个浮点数 (32位浮点数) float2 两个浮点数 相当于 Vector2 (32位浮点数) float3 三个浮点数 相当于 Vector3 (32位浮点数) float4 四个浮点数 相当于 Vector4 (32位浮点数) half half2 half

BattleTiger的博客 1705

1分钟了解LangChain是什么?

是一个基于大型语言模型(LLM)开发应用程序的框架, 它旨在简化语言模型应用的开发流程,特别是在构建对话系统和其他基于语言的AI解决方案时.目标是将复杂的语言模型技术转化为可通过简单API调用实现的功能,从而使开发者能够更加专注于创造性的解决方案设计。高效地解决了开发大语言模型应用的痛点问题。Langchain 最主要的特色是可以将 LLM 应用研发过程中的交互 Prompt、LLM 模型调用、语言模型与环境互动的自适应等方式融为一体。

gorgor在码农 2630

【Unity3D Shader编程】之六 暗黑城堡篇 表面着色器 Surface Shader 的写法 一

分享一下我老师大神的人工智能教程。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.youkuaiyun.com/jiangjunshow                 &

yttyffggh的博客 501

AI Agent 架构的底层原理与核心机制

AI Agent五层架构实现智能闭环运转:1)感知层负责多模态信息输入与预处理;2)记忆层分类存储短期/长期记忆及知识库;3)认知层通过ReAct推理和反思机制进行决策规划;4)工具层调用外部API扩展能力边界;5)执行层完成任务输出并形成反馈闭环。五层架构通过"输入-处理-输出-优化"的联动机制,使Agent具备自主决策、持续学习和任务执行能力,突破传统LLM的局限,实现从信息处理到实际落地的完整智能体系。

女王の专属领地 495

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Unity Surface Shader 示例分析

对于Unity中的表面着色器(Surface Shader),它的代码整体结构如下所示:      Shader "name" {          Properties {               // 第一部分          }          SubShader {               // 第二部分          }

清道夫的专栏(3D程序员,炼心,终生编程) 3390

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

上一篇: NavMesh生成研究(四):凸多边形生成
下一篇: NavMesh生成研究(五):细节网格生成
长三月
博客等级 码龄9年 228粉丝 80原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值