【Unity Shader入门精要 第7章】基础纹理(三)

news2025/1/19 17:06:09

1. 渐变纹理

另外一种对于纹理的使用方式是通过渐变纹理为物体提供漫反射光照效果。

在这里插入图片描述
顾名思义,渐变纹理本身就是一张颜色渐变(可以是连续渐变,也可能是突变)的图片,这个渐变的过程模拟的就是光源从不同的角度照射物体的过程,因此对渐变纹理的采样通关不关心目标像素的位置信息,只关心光照角度。

通常来讲,渐变纹理都是左右不可以互相拼接的(像上图这样)。假设我们期望的采样点在纹理的最右侧(白色),但考虑到采样坐标的精度问题,实际的采样坐标可能为1.001,如果渐变纹理的 Wrap Mode 选择的是 Repeat,就会按照 0.001 进行采样,于是就会从渐变纹理的最左边进行采样(深红),从而导致一片白色中突然出现一点深红。因此,为了避免这种问题,渐变纹理的 Wrap Mode 需要选择为 Clamp。

在这里插入图片描述
如上图所示,我们在Shader中为物体设置了一张 MainTex 用于提供物体的基本颜色,然后设置了一张RampTex,用于根据光照角度提供漫反射颜色。

Shader如下:

Shader "MyShader/Chapter_7/Chapter_7_RampTexture"
{
    Properties
    {
        _MainTex("MainTex", 2D) = "white"{}
        _RampTex("RampTex", 2D) = ""{}
        _Specular("Specular", Color) = (1,1,1,1)
        _Gloss("Gloss", Range(1.0, 256.0)) = 16
    }
    
    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;
                float2 uv : TEXCOORD0;
            };
            
            struct v2f
            {
                float4 vertex : SV_POSITION;
                float2 uv : TEXCOORD0;
                float3 worldNormal : TEXCOORD1;
                float3 worldPos : TEXCOORD2;
            };
            
            sampler2D _MainTex;
            float4 _MainTex_ST;
            sampler2D _RampTex;
            fixed4 _Specular;
            half _Gloss;
            
            v2f vert(a2v v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                o.worldNormal = mul(v.normal, unity_WorldToObject);
                o.worldPos = mul(unity_ObjectToWorld, v.vertex);
                return o;
            }
            
            fixed4 frag(v2f i) : SV_Target
            {
                
                fixed3 _ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;
                
                float3 _worldNormal = normalize(i.worldNormal);
                float3 _worldLight = normalize(_WorldSpaceLightPos0.xyz);
                fixed4 _albode = tex2D(_MainTex, i.uv);
                float _halfLambert = 0.5 * dot(_worldNormal, _worldLight) + 0.5;
                fixed4 _ramp = tex2D(_RampTex, _halfLambert.rr);
                fixed3 _diffuse = _LightColor0.rgb * _albode.xyz * _ramp.rgb;
                
                float3 _worldView = normalize(_WorldSpaceCameraPos.xyz - i.worldPos);
                float3 _h = normalize(_worldView + _worldLight);
                fixed3 _specular = _LightColor0.rgb * _Specular.xyz * pow(saturate(dot(_worldNormal, _h)) , _Gloss);
                
                return fixed4(_ambient + _diffuse + _specular, 1);
            }
            
            ENDCG
        }
    
    }

}

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

2.遮罩纹理

所谓遮罩纹理,其实就是向Shader提供额外参数控制的一种手段。由于通过纹理采样可以覆盖到物体表面的每一个像素,因此我们可以通过将参数存储到纹理中为物体表面每一个像素提供更精细的控制。

比如在进行高光反射计算时,如果我们希望物体表面某些地方的高光强度更高,某些地方的高光强度更低,就可以将这个调整高光强度的系数存到一张纹理当中,在计算高光反射的最后乘以从纹理中采样得到的控制系数。

再比如我们在Shader 的 Properties 中设置了某些属性可以供使用者调整,但这个属性的值是对整个Shader生效的,或者说是对物体表面每一个像素生效的,就像之前Shader中常用的 _Gloss 属性,用于控制高光亮斑的大小,如果我们希望物体不同部分在计算高光反射时,分别按照不同的 _Gloss 值进行计算,就可以将需要的 _Gloss 值存到纹理中,在着色器中采样获得。

在这里插入图片描述

这个例子中,通过一张遮罩纹理的R通道为漫反射提供了一个额外的强度系数。

Shader如下:

Shader "MyShader/Chapter_7/Chapter_7_MaskTexture"
{
    Properties
    {
        _MainTex("MainTex", 2D) = "white"{}
        _BumpTex("BumpTex", 2D) = "bump"{}
        _MaskTex("MaskTex", 2D) = ""{}
        _MaskScale("MaskScale", float) = 5
        _Specular("Specular", Color) = (1,1,1,1)
        _Gloss("Gloss", Range(1.0, 256.0)) = 16
    }
    
    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;
                float4 tangent : TANGENT;
                float2 uv : TEXCOORD0;
            };
            
            struct v2f
            {
                float4 vertex : SV_POSITION;
                float2 uv : TEXCOORD0;
                float3 tangentView : TEXCOORD1;
                float3 tangentLight : TEXCOORD2;
            };
            
            sampler2D _MainTex;
            float4 _MainTex_ST;
            sampler2D _BumpTex;
            sampler2D _MaskTex;
            half _MaskScale;
            fixed4 _Specular;
            half _Gloss;
            
            v2f vert(a2v v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                
                TANGENT_SPACE_ROTATION;
                o.tangentView = mul(rotation, ObjSpaceViewDir(v.vertex));
                o.tangentLight = mul(rotation, ObjSpaceLightDir(v.vertex));
                return o;
            }
            
            fixed4 frag(v2f i) : SV_Target
            {
                
                fixed3 _ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;
                
                float3 _tangentLight = normalize(i.tangentLight);
                fixed4 _packedNormal = tex2D(_BumpTex, i.uv);
                float3 _tangentNormal = UnpackNormal(_packedNormal) ;
                _tangentNormal.z = sqrt(1.0 - dot(_tangentNormal.xy, _tangentNormal.xy));
                fixed4 _albode = tex2D(_MainTex, i.uv);
                float _diffuseFix = tex2D(_MaskTex, i.uv).r * _MaskScale;
                fixed3 _diffuse = _LightColor0.rgb * _albode.xyz * saturate(dot(_tangentNormal, _tangentLight)) * _diffuseFix;
                
                float3 _tangentView = normalize(i.tangentView);
                float3 _h = normalize(_tangentView + _tangentLight);
                fixed3 _specular = _LightColor0.rgb * _Specular.xyz * pow(saturate(dot(_tangentNormal, _h)) , _Gloss);
                
                return fixed4(_ambient + _diffuse + _specular, 1);
            }
            
            ENDCG
        }
    
    }

}

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Git—常用命令

官方 Git - Book (git-scm.com) 常用命令 命令作用git config --global user.name 用户名设置用户作者git config --global user.email 邮箱设置用户邮箱 git init初始化本地仓库git status查看本地仓库状态 git add 文件名 添加到暂存区git commit -m "提交日志…

【K8s】专题四:Kubernetes 安装方法之 Sealos

以下内容均来自个人笔记并重新梳理,如有错误欢迎指正!如果对您有帮助,烦请点赞、关注、转发!欢迎扫码关注个人公众号! 目录 一、Sealos 简介 二、Sealos 下载、安装 三、Sealos 部署 Kubernetes 集群 四、Sealos 常…

vue2人力资源项目9权限管理

页面搭建 <template><div class"container"><div class"app-container"><el-button size"mini" type"primary">添加权限</el-button><el-table-column label"名称" /><el-table-co…

反序列化漏洞【1】

1.不安全的反序列化漏洞介绍 序列化&#xff1a;将对象转换成字符串&#xff0c;目的是方便传输&#xff0c;关键词serialize a代表数组&#xff0c;数组里有三个元素&#xff0c;第一个元素下标为0&#xff0c;长度为7&#xff0c;内容为porsche&#xff1b;第二个元素下标为1…

rk3399 shell 测试串口 sttf

问题&#xff1a; 使用 ubunut shell 来对串口进行测试。 板卡上使用的是 USB 转串口&#xff0c; 使用了一片ch340 原理图如下&#xff1a; 再 ubuntu shell 的测试命令。 这里首先要 insmod 一下 ch340 的驱动&#xff0c;默认会有 /usr/sbin/ch34x.ko&#xff0c; 如果没…

创新指南 | 企业AI战略实施方案探讨(下):如何基于AI重构业务流程并落地实施

人工智能&#xff08;AI&#xff09;的浪潮已经席卷全球&#xff0c;成为推动现代企业发展的强大动力。AI技术不仅提升了企业的运营效率&#xff0c;还催生了新的商业模式和市场机会。本文将深入探讨AI的革新性应用案例&#xff0c;并提供一套企业落地AI的具体实施方案&#xf…

springboot3.0+继续使用springboot2.0配置会显示 `无法自动装配,找不到对应的Bean`解决方法

在 Spring Boot 3.0 中&#xff0c;Spring 团队对自动配置机制进行了重大变更&#xff0c;特别是 spring.factories 文件。spring.factories 文件已被 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件所取代。在springboot3.0继续使用…

SQL使用Groupby分组后,选择每个分组某个值最大的那一行

思路是&#xff1a; 先定位分组后某个值最大的值是多少根据值去全表匹配&#xff0c;得到对应的行 比如有个表&#xff1a; SELECT * FROM my_table按照sku_id分组后&#xff0c;选择record_date最大的那一行的全部值&#xff0c;先分组&#xff1a; SELECT sku_id,max(rec…

四川易点慧电商抖音小店运营秘籍引领电商新潮流

在当今数字化浪潮中&#xff0c;抖音小店作为电商领域的一匹黑马&#xff0c;以其独特的社交属性和庞大的用户基础&#xff0c;正迅速崛起为新的销售增长点。四川易点慧电子商务有限公司&#xff0c;作为电商行业的佼佼者&#xff0c;深谙抖音小店运营的精髓&#xff0c;专业助…

Pytest测试实战

Pytest测试框架是动态语言Python专用的测试框架&#xff0c;使用起来非常的简单&#xff0c;这主要得易于它的设计&#xff0c;Pytest测试框架具备强大的功能&#xff0c;丰富的第三方插件&#xff0c;以及可扩展性好&#xff0c;可以很好的和unittest测试框架能够结合起来在项…

手机如何下载短视频到本地:成都鼎茂宏升文化传媒公

手机如何下载短视频到本地 ​随着移动互联网的迅猛发展&#xff0c;短视频已经成为人们生活中不可或缺的一部分。从娱乐、学习到社交&#xff0c;短视频以其短小精悍、内容丰富的特点&#xff0c;吸引了大量用户的关注。然而&#xff0c;有时我们可能希望将喜欢的短视频保存到…

计算机网络-DHCPv6基础

前面我们学习了IPv6地址可以通过手动配置、无状态自动配置、DHCPv6配置&#xff0c;这里简单学习下DHCPv6的知识点。 一、DHCPv6概述 DHCPv6 (Dynamic Host Configuration Protocol for IPv6) 是一种网络协议&#xff0c;设计用于IPv6网络环境中自动为网络设备分配必要的配置信…

LiveGBS流媒体平台GB/T28181用户手册-服务器概览:通道信息、负载信息、CPU使用、存储使用、带宽使用(Mbps)、内存使用

LiveGBS用户手册-服务器概览&#xff1a;通道信息、负载信息、CPU使用、存储使用、带宽使用&#xff08;Mbps&#xff09;、内存使用 1、服务器概览1.1、通道信息1.2、负载信息1.2.1、信息说明1.2.2、会话列表 1.3、CPU使用1.4、存储使用1.5、带宽使用&#xff08;Mbps&#xf…

理解 Python 中的 `super()` 与 `__init__()` 方法

在 Python 的面向对象编程中&#xff0c;super() 函数和 __init__() 方法是两个非常重要的概念。它们在类的继承和初始化过程中扮演着关键的角色。本文将深入探讨这两个概念的工作原理&#xff0c;并通过示例代码来展示它们的使用。 基本原理 __init__() 方法 __init__() 是…

数据结构-栈(带图)

目录 栈的概念 画图理解栈 栈的实现 fun.h fun.c main.c 栈的概念 栈&#xff08;Stack&#xff09;是一种基本的数据结构&#xff0c;其特点是只允许在同一端进行插入和删除操作&#xff0c;这一端被称为栈顶。遵循后进先出&#xff08;Last In, First Out, LIFO&#…

通俗易懂的策略模式讲解

什么是策略模式&#xff1f; 策略模式是一种设计模式&#xff0c;它允许你定义一系列的算法&#xff08;策略&#xff09;&#xff0c;并将每个算法封装成一个对象。这样&#xff0c;你可以轻松地切换不同的算法&#xff0c;而不需要改变原始代码。 一个简单的例子 假设你是…

OpenHarmony标准设备应用开发(二)——布局、动画与音乐

本章是 OpenHarmony 标准设备应用开发的第二篇文章。我们通过知识体系新开发的几个基于 OpenHarmony3.1 Beta 标准系统的样例&#xff1a;分布式音乐播放、传炸弹、购物车等样例&#xff0c;分别介绍下音乐播放、显示动画、动画转场&#xff08;页面间转场&#xff09;三个进阶…

Qwen学习笔记2:Qwen模型基于ReAct原理实现function calling

前言 这也是一篇笔记&#xff0c;再探索一下Qwen模型的function calling功能。 Qwen1.8B模型能够进行function calling功能吗&#xff1f; 我们使用之前的reason_prompt模板进行测试&#xff1a; PROMPT_REACT """ Use the following format:Question: the…

AWS RDS ElasticCache 监控可观测最佳实践

在当今的电子商务时代&#xff0c;一个高效、稳定的电商平台对于保持竞争力至关重要。数据库作为电商平台的核心支撑&#xff0c;其性能直接影响到用户体验和业务流畅度。本文将深入探讨如何在电商场景下通过观测云对亚马逊云科技 RDS&#xff08;MySQL&#xff09; 和 Elastic…

python怎么安装matplotlib

1、登陆官方网址“https://pypi.org/project/matplotlib/#description”&#xff0c;下载安装包。 2、选择合适的安装包&#xff0c;下载下来。 3、将安装包放置到python交互命令窗口的当前目录下。 4、打开windows的命令行窗口&#xff0c;通过"pip install"这个命令…