Unity中Shader立方体纹理Cubemap

文章目录

  • 前言
  • 一、什么是立方体纹理
  • 二、立方体纹理的生成方式
    • 1、使用6个面的生成方式
    • 2、使用单张图片的生成方式
  • 三、Cubemap的采样方式
  • 四、在Unity中看一下Cubemap
  • 五、在Shader中,对立方体纹理进行采样使用
    • 1、我们在属性面板定义一个Cube类型的变量来存放立方体纹理
    • 2、使用前在Pass中,声明一下该变量
    • 3、在片元着色器中,对其纹理采样
    • 4、模拟真实的反射效果 (Cubemap的环境映射)
    • 5、计算视线的反射向量
  • 六、最终效果


前言

Unity中Shader立方体纹理Cubemap


一、什么是立方体纹理

立方体纹理,也被叫做Cubemap。通常用来做反射效果

在Unity中,如果全都使用实时反射,那么对于设备性能的消耗是比较大的,所以使用一种投机取巧的方式实现的反射效果

在这里插入图片描述


二、立方体纹理的生成方式

1、使用6个面的生成方式

在这里插入图片描述
在这里插入图片描述
一般选择Auto即可,会自动适配

2、使用单张图片的生成方式

在这里插入图片描述
在这里插入图片描述
一般选择Auto即可,会自动适配


三、Cubemap的采样方式

在这里插入图片描述
由模型顶点向Cubemap发射射线,射线经过的Cubemap哪个点,那个点就是采样点


四、在Unity中看一下Cubemap

在纹理的 Inspector,按如下设置,就可以把普通纹理类型修改为立方体纹理
在这里插入图片描述
请添加图片描述


五、在Shader中,对立方体纹理进行采样使用

我们使用上一篇文章的Shader继续测试:

  • Unity中Shader纹理的环绕方式

1、我们在属性面板定义一个Cube类型的变量来存放立方体纹理

_CubeMap(“CubeMap”,Cube) = “white” {}

2、使用前在Pass中,声明一下该变量

samplerCUBE _Cubemap;

3、在片元着色器中,对其纹理采样

这里进行纹理采样时,由其原理可知,需要使用顶点的本地坐标。

在这里插入图片描述

所以,这里使用 appdata 传入的顶点数据来采样即可。

  • 我们先在 v2f 中定义一个变量来存储应用程序阶段传入的数据

我们只需要顶点的 xyz 即可

float3 localPos : TEXCOORD1;

  • 然后,在顶点着色器阶段,把 appdata 的顶点 xyz 传给 v2f 中的 localPos

o.localPos = v.vertex.xyz;

  • 返回一下采样的结果看看(已经有了采样的结果)

fixed4 cubemap = texCUBE(_CubeMap,i.localPos);
return cubemap;

在这里插入图片描述

4、模拟真实的反射效果 (Cubemap的环境映射)

要模拟出真实的反射效果,不能向之前一样,采样眼睛处的Cubemap

而是需要采样视线的反射视线经过Cubemap的点

在这里插入图片描述

5、计算视线的反射向量

因为需要计算视线的反射向量,所以需要准备一些数据:

摄像机的世界坐标、模型顶点的世界坐标、法线的世界坐标

  • 准备摄像机的世界坐标

_WorldSpaceCameraPos

  • 准备模型顶点的世界坐标

1、在 v2f 中,定义一个变量存储顶点的世界信息
float3 worldPos : TEXCOORD2;
2、在顶点着色器中,进行顶点坐标转化
o.worldPos = mul(unity_ObjectToWorld,v.vertex);

  • 准备法线的世界坐标

1、在 appdata 中传入法线信息
half3 normal : NORMAL;
2、在 v2f 中,定义一个变量存储法线世界坐标
half3 worldNormal : NORMAL;
3、在顶点着色器中,进行法线坐标转化
o.worldNormal = UnityObjectToWorldNormal(v.normal);

  • 准备最后的计算

1、计算世界坐标下 视线单位向量 V
fixed3 V = normalize(i.worldPos - _WorldSpaceCameraPos);
2、计算世界坐标下 法线单位向量 N
fixed3 N = normalize(i.worldNormal);
3、计算世界坐标下 反射向量R
fixed3 R = reflect(V,N);
4、用 R 对Cubemap进行纹理采样
fixed4 cubemap = texCUBE(_CubeMap,R);


六、最终效果

请添加图片描述

最终代码:

//纹理的多级渐远 Mipmap
//纹理的环绕方式
Shader "MyShader/P2_1_5"
{Properties{_MainTex ("Texture", 2D) = "white" {}[KeywordEnum (Repeat,Clamp)]_WrapMode("WrapMode",int) = 0[IntRange]_Mipmap ("Mipmap",Range(0,10)) = 0//在属性面板定义立方体纹理_CubeMap("CubeMap",Cube) = "white" {}}SubShader{Tags { "RenderType"="Opaque" }LOD 100Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#pragma shader_feature _WRAPMODE_REPEAT _WRAPMODE_CLAMP#include "UnityCG.cginc"struct appdata{float4 vertex : POSITION;float2 uv : TEXCOORD0;half3 normal : NORMAL;};struct v2f{float2 uv : TEXCOORD0;float4 vertex : SV_POSITION;float3 localPos : TEXCOORD1;float3 worldPos : TEXCOORD2;half3 worldNormal : NORMAL;};sampler2D _MainTex;float4 _MainTex_ST;half _Mipmap;samplerCUBE _CubeMap;v2f vert (appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);o.uv = TRANSFORM_TEX(v.uv, _MainTex);o.localPos = v.vertex.xyz;o.worldPos = mul(unity_ObjectToWorld,v.vertex);o.worldNormal = UnityObjectToWorldNormal(v.normal);return o;}fixed4 frag (v2f i) : SV_Target{//WrapMode#if _WRAPMODE_REPEATi.uv = frac(i.uv);#elif _WRAPMODE_CLAMP//法一://i.uv = clamp(i.uv,0,1);//法二:i.uv = saturate(i.uv);#endiffloat4 uvMipmap = fixed4(i.uv,0,_Mipmap);fixed4 col = tex2Dlod(_MainTex, uvMipmap);//Cubefixed4 cubemap = texCUBE(_CubeMap,i.localPos);//V,N,Rfixed3 V = normalize(i.worldPos - _WorldSpaceCameraPos);fixed3 N = normalize(i.worldNormal);fixed3 R = reflect(V,N);cubemap = texCUBE(_CubeMap,R);return cubemap;return col;}ENDCG}}
}

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

多功能神器,强劲升级,太极2.x你值得拥有!

嗨,大家好,今天给大家分享一个好用好玩的软件。那就是太极2.x软件,最近在1.0版本上进行了全新升级,升级后的功能更强更稳定,轻度用户使用基本功能就已经足够了,我们一起来看看吧! 首页 首页左…

15项基本SCADA技术技能

1. 人机界面 人机界面是将操作员连接到设备、系统或机器的仪表板或用户界面。 以下是 hmi 在 scada 技术人员简历中的使用方式: 完成了查尔斯湖废水处理厂和提升站的完整 HMI 图形界面。对加油系统、加油车、PLC、HMI、触摸屏进行故障排除和维修。对 Horner HMI …

策略模式在数据接收和发送场景的应用(升级版)

1.背景 在数据接收和发送场景打算使用了 if else 进行判断: if("A".equals(system)){ASystem.sync("向A同步数据"); } if("B".equals(system)){BSystem.sync("向B同步数据"); } ... 非常麻烦,需求多了很臃肿&…

C/C++字符判断 2021年12月电子学会青少年软件编程(C/C++)等级考试一级真题答案解析

目录 C/C字符判断 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序编写 四、程序说明 五、运行结果 六、考点分析 C/C字符判断 2021年12月 C/C编程等级考试一级编程题 一、题目要求 1、编程实现 对于给定的字符,如果该字符是大小写字母或…

使用opera/火狐浏览器将网页固定到桌面和任务栏

1.单击Windows 图标,搜索Opera,右键单击它,然后选择Open file location 2.右键单击Opera,然后选择Show more options 3.将光标悬停在“发送到”选项上,然后选择“桌面(创建快捷方式)” 4.转到…

springboot项目中获取业务功能的导入数据模板文件

场景: 在实际业务场景中,经常会遇到某些管理功能需要数据导入共功能,但既然是导入数据,肯定会有规则限制,有规则就会有数据模板,但这个模板一般是让客户自己下载固定规则模板,而不是让客户自己随便上传模板。下面介绍直接下载模板 一、下载模板示例 1、在项目的…

剑指JUC原理-20.并发编程实践

👏作者简介:大家好,我是爱吃芝士的土豆倪,24届校招生Java选手,很高兴认识大家📕系列专栏:Spring源码、JUC源码🔥如果感觉博主的文章还不错的话,请👍三连支持&…

综述:目标检测二十年(机翻版)(未完

原文地址 20年来的目标检测:一项调查 摘要关键词一 介绍二 目标检测二十年A.一个目标检测的路线图1)里程碑:传统探测器Viola Jones探测器HOG检测器基于可变形零件的模型(DPM) 2)里程碑:基于CNN的两阶段探测器RCNNSPPN…

深入理解Linux网络笔记(七):异常TCP连接建立情况、如何查看是否有连接队列溢出发生

本文为《深入理解Linux网络》学习笔记,使用的Linux源码版本是3.10,网卡驱动默认采用的都是Intel的igb网卡驱动 Linux源码在线阅读:https://elixir.bootlin.com/linux/v3.10/source 5、深度理解TCP连接建立过程(二) 4&…

、如何在企业签名、超级签名、tf签名之间做选择

企业签名 (Enterprise Signing): 用途: 适用于企业内部发布应用,不需要经过App Store审核,可以通过企业内部渠道直接分发给员工或内部用户。限制: 仅限于企业内部使用,无法在App Store上发布或向外部用户分发。 超级签…

最短路问题

单源最短路 Dijkstra算法 力扣 743.网络延迟时间 const int N 7777; int INF 0x3f3f3f3f; class Solution {struct edge {int v, w;};vector<edge> e[N];int d[N], vis[N]; //d数组存储最短路径长度priority_queue <pair<int, int>, vector<pair<int…

AIGC 是通向 AGI 的那条路吗?

AIGC 是通向 AGI 的那条路吗&#xff1f; 目录 一、背景知识 1.1、AGI&#xff08;人工通用智能&#xff09; 1.1.1、概念定义 1.1.2、通用人工智能特质 1.1.3、通用人工智能需要掌握能力 1.2、AIGC 二、AIGC 是通向 AGI 的那条路吗&#xff1f; 三、当前实现真正的 A…