着色(Shading)

曲面细分只是地球渲染的第一步。接下来是着色——通过模拟光线与材质的相互作用,计算每个像素的最终颜色。本节先回顾基础的光照与纹理映射,再讲解虚拟地球特有的经纬网格夜景灯光效果。


6.1 光照(Lighting)

我们从最简“直通”着色器(Listing 1)开始,逐步加入漫反射与镜面反射。

/*----------------List 1----------------------*/
// Vertex shader
in vec4 position;
uniform mat4 ce_modelViewPerspectiveMatrix;void main()
{gl_Position = ce_modelViewPerspectiveMatrix * position ;
}// Fragment shader
out vec3 fragmentColor;
void main() {fragmentColor = vec3(0.0, 0.0, 0.0);
}
  • 顶点着色器
    使用自动变量 ce_modelViewPerspective 把顶点坐标变换到裁剪空间。
    此时球体全黑。
    在这里插入图片描述

  • 光源位置
    采用“眼旁点光源”:光源放在相机位置,仿佛用户提着一盏灯。
    为简化,光照计算在世界坐标系完成(示例仅有一个坐标系)。

  • 逐像素光照
    在片元着色器计算 Phong 光照,可消除因插值导致的高光锯齿,也便于后续纹理特效。

漫反射
粗糙表面散射光线,强度仅与入射角有关:
Idiffuse=max⁡(n^⋅l^,0) I_{\text{diffuse}} = \max(\hat{\mathbf n}\cdot \hat{\mathbf l},0) Idiffuse=max(n^l^,0)
其中 n^\hat{\mathbf n}n^ 为法线,l^\hat{\mathbf l}l^ 为光源方向。
球面法线可直接归一化世界坐标得到;椭球需用 GeodeticSurfaceNormal

镜面反射
光滑表面产生高光,强度与视线方向有关:
Ispec=(r^⋅v^)α,r^=2(n^⋅l^)n^−l^ I_{\text{spec}} = \left(\hat{\mathbf r}\cdot \hat{\mathbf v}\right)^\alpha,\quad \hat{\mathbf r}=2(\hat{\mathbf n}\cdot\hat{\mathbf l})\hat{\mathbf n}-\hat{\mathbf l} Ispec=(r^v^)α,r^=2(n^l^)n^l^
指数 α\alphaα 决定高光锐利度。
最终光照:
I=kdIdiffuse+ksIspec+ka I = k_dI_{\text{diffuse}} + k_sI_{\text{spec}} + k_a I=kdIdiffuse+ksIspec+ka

实现见 Listing 2(顶点)与 Listing 3(片元)。

/*-----------Listing 2--------------------*/
// Vertex shader for diffuse and specular lighting.
in vec4 position;
out vec3 worldPosition;
out vec3 positionToLight;
out vec3 positionToEye;uniform mat4 ce_modelViewPerspectiveMatrix;
uniform vec3 ce_cameraEye;
uniform vec3 ce_cameraLightPosition;void main()
{gl_Position = ce_modelViewPerspectiveMatrix * position;worldPosition = position.xyz;positioinToLight = ce_cameraLightPosition - worldPosition;positionToEye = ce_cameraEye - worldPosition;
}
/*-----------Listing 3--------------------*/
// Final Phong-lighting fragment shader.
in vec3 worldPosition;
in vec3 positionToLight;
in vec3 positionToEye;
out vec3 fragmentColor;uniform vec4 ce_diffuseSpecularAmbientShininess;float LightIntensity(vec3 normal, vec3 toLight, vec3 toEye, vec4 diffuseSpecularAmbientShininess)
{vec3 toReflectedLight = reflect(-toLight, normal);float diffuse = max(dot(toLight, normal), 0.0);float specular = max(dot(toReflectedLight, toEye), 0.0);specular = pow(specular, diffuseSpecularAmbientShininess.w);return (diffuseSpecularAmbientShininess.x * diffuse) + (diffuseSpecularAmbientShininess.y * specular) + diffuseSpecularAmbientShininess.z;
}void main()
{vec3 normal = normalize(worldPosition);float intensity = LightIntensity(normal, normalize(positionToLight), normalize(positionToEye), ce_diffuseSpecularAmbientShininess);fragmentColor = vec3(intensity, intensity, intensity);
}

6.2 纹理映射(Texturing)

光照体现曲率,但地球真正魅力来自高分辨率影像。本节讲解逐像素计算纹理坐标(假设纹理一次性装入显存,且 float 精度足够)。
在这里插入图片描述

  • 世界影像通常 2:1 宽高比,WGS84 坐标。

  • 给定片元法线 n=(nx,ny,nz)∈[−1,1]\mathbf n=(n_x,n_y,n_z)\in[-1,1]n=(nx,ny,nz)[1,1],计算 (s,t)∈[0,1](s,t)\in[0,1](s,t)[0,1]
    s=atan2(ny,nx)2π+0.5,t=arcsin⁡nzπ+0.5. \begin{aligned} s &= \frac{\text{atan2}(n_y,n_x)}{2\pi}+0.5,\\[2pt] t &= \frac{\arcsin n_z}{\pi}+0.5. \end{aligned} st=2πatan2(ny,nx)+0.5,=πarcsinnz+0.5.
    该公式把经纬度映射到纹理空间(Listing 4.11)。

  • 光照×颜色:
    finalColor=texture(uday,(s,t))×I \text{finalColor} = \text{texture}(u_{\text{day}},(s,t)) \times I finalColor=texture(uday,(s,t))×I
    (图 4.11(c))

极点问题
纹理极区像素密度过高,过滤反而加剧失真。
EVE Online 采用“平面+球面”混合投影;也可改用立方体贴图避免极点拉伸,但在每个立方体面的边界处会引入轻微的畸变。


6.3 CPU / GPU 权衡

方案优点缺点
逐片元 计算法线/纹理坐标节省显存;无插值误差;代码简洁;无 IDL 特殊处理GPU 反三角函数精度/速度低
逐顶点 计算并存储顶点着色器简单;一次计算多次使用顶点数据翻倍;顶点插值导致 IDL 纹理跳变(下图)

在这里插入图片描述


6.4 经纬网格(Latitude-Longitude Grid)

几乎所有虚拟地球都可叠加经纬网(图 4.13)。常见做法:

  • CPU 生成折线;
  • 缓存网格,视角移动时复用;
  • 根据缩放级别动态增减分辨率(LOD)。

片元着色器方案
优点:

  • 无 CPU 计算;
  • 无额外显存/带宽;
  • 无 Z-fighting;
  • 无需额外 Pass。

缺点:

  • 单 Pass 渲染耗时稍长;
  • 受 32-bit float 精度限制;
  • 文字标注需额外处理。

实现要点

  • 通过纹理坐标 (s,t) 判断是否在网格线附近;
  • dFdx/dFdy 获得屏幕空间梯度,实现像素恒定线宽(Listing 4);
  • 支持不同颜色、线宽、淡入淡出、抗锯齿及线型。
/*------------------------Listing 4-------------------------------*/
void main()
{vec3 normal = GeodeticSurfaceNormal(worldPosition, u_globeOneOverRadiiSquared);vec2 textureCoordinate = ComputeTextureCoordinates(normal);vec2 distanceToLine = mod(textureCoordinate, u_gridResolution);vec2 dx = abs(dFdx(textureCoordinate));vec2 dy = abs(dFdy(textureCoordinate));vec2 dF = vec2(max(dx.s, dy.s), max(dx.t, dy.t)) * u_gridLineWidth;if (any(lessThan(distanceToLine, dF))){fragmentColor = vec3(1.0, 0.0, 0.0);}else{float intensity = LightIntensity(normal,normalize(positionToLight),normalize(positionToEye),ce_diffuseSpecularAmbientShininess);fragmentColor = intensity * texture(ce_texture0, textureCoordinate).rgb;}
}

LOD 控制
根据相机高度分段设置 u_gridResolution

  • 定义高度区间 → 网格分辨率映射表;
  • 利用时间连续性,优先检查上一区间,查找几乎 O(1)。
    在这里插入图片描述

6.5 夜景灯光(Night Lights)

虚拟地球常在背阳面显示城市灯光——经典多重纹理应用:
白天纹理 + 夜间灯光纹理,按太阳照射角度混合。

片元着色器流程

  • 顶点着色器传入太阳位置 og_sunPosition
  • 新增 uniform:
    • u_dayTexture, u_nightTexture
    • u_blendDuration 过渡时长
    • u_blendDurationScale = 1/(2u_blendDuration)(预计算)
  • 片元着色器:
    1. 计算漫反射因子 d=max⁡(n^⋅l^,0)d = \max(\hat{\mathbf n}\cdot\hat{\mathbf l},0)d=max(n^l^,0)
    2. d>ublendDurationd > u_{\text{blendDuration}}d>ublendDuration:用白天纹理 + Phong 光照。
    3. d<−ublendDurationd < -u_{\text{blendDuration}}d<ublendDuration:用夜间纹理,无光照。
    4. 介于两者之间:线性混合昼夜颜色。
      在这里插入图片描述

性能实验

  • 仅看昼面 vs 仅看夜面:夜面帧率更高(夜间纹理分辨率低且无光照计算)。
  • 游戏常用技巧:用纹理图集 + 旋转/镜像,少量纹理即可产生丰富夜景变化(EVE Online)。

多重纹理其他应用

  • 云层纹理
  • 水面高光贴图(gloss map)
    早期硬件不支持多重纹理时,STK 采用多 Pass 实现夜景。

参考:

  • Cozi, Patrick; Ring, Kevin. 3D Engine Design for Virtual Globes. CRC Press, 2011.

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

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

相关文章

OpenCV Python——图像拼接(一)(图像拼接原理、基础知识、单应性矩阵 + 图像变换 + 拼接)

1 图像拼接基础知识1.1 特征匹配 原理及代码示例1.2 单应性矩阵 原理及代码示例2 图像拼接&#xff08;一&#xff09;&#xff08;直接拼接&#xff09;3 图像拼接&#xff08;二&#xff09;&#xff08;单应性矩阵 图像变换 拼接&#xff09;3.1 单应性矩阵函数3.2 拼接函…

Git 中切换到指定 tag

在 Git 中切换到指定 tag&#xff08;比如 v1.22.1&#xff09;的正确做法如下&#xff1a;1️⃣ 查看已有的 taggit tag会列出所有可用的版本&#xff0c;比如&#xff1a;v1.21.0 v1.22.0 v1.22.1 v1.23.02️⃣ 切换到指定 taggit checkout tags/v1.22.1 -b v1.22.1解释&…

rust 从入门到精通之变量和常量

变量和常量 随着软件系统安全的重要性与日俱增, rust这门集聚高并发, 安全, 适配云环境的编程语言在市场上得到了越来越高的认可和关注。但其复杂的机制使其难以学习。且其很多特性对于其他语言是全新的&#xff0c;这加剧了学习的困难程度。教程主要针对rust基础进行讲解, 虽然…

2508C++,支持rdma通信的高性能rpc库

原文 [重磅]支持rdma通信的高性能的rpc库–yalantinglibs.coro_rpc yalantinglibs的coro_rpc是基于C20的协程的高性能的rpc库,提供了简洁易用的接口,让用户几行代码就可实现rpc通信,现在coro_rpc除了支持tcp通信之外还支持了rdma通信(ibverbs). 通过简单示例来感受一下rdma通…

FastAPI + React:现代 Web 前后端分离开发的全栈实践指南

一、为什么选 FastAPI React&#xff1f; 性能&#xff1a;FastAPI 基于 Starlette Uvicorn&#xff0c;QPS 与 Node/Go 同级&#xff0c;实测 3 倍于 Flask&#xff1b;React 虚拟 DOM 代码分割&#xff0c;首屏 < 1.2 s。效率&#xff1a;FastAPI 内置 Swagger/OpenAPI…

嵌入式硬件篇---电平转换电路

电平转换电路是电子电路中用来实现不同电压信号之间转换的关键电路&#xff0c;比如把 3.3V 的信号转换成 5V&#xff0c;或者把 5V 转换成 1.8V&#xff0c;确保不同电压的芯片、模块能正常通信。下面用通俗易懂的方式介绍几种常见的电平转换电路&#xff1a;一、电阻分压电路…

SAP ABAP IS SUPPLIED

效果 此谓词表达式用于检查过程的某个形式参数“para”是否已赋值或被请求使用。如果在调用时实际参数被赋值给了该形式参数&#xff0c;则该表达式为真。 这种关系表达式仅能在函数模块和方法中使用。而对于“para”而言&#xff0c;所有可选的形参都可以进行指定。 加上“NOT…

视频内容提取与AI总结:提升学习效率的实用方法

文章目录1、前言2、方法介绍2.1 B站视频处理方案2.2 通用视频处理方案2.3 AI内容总结3、实际效果4、使用建议5、技术发展趋势6、总结&#x1f343; 作者介绍&#xff1a;25届双非本科网络工程专业&#xff0c;阿里云专家博主&#xff0c;专注于 AI 原理、AI 应用开发、AI 产品设…

JVM 面试精选 20 题

目录1. 什么是 JVM、JDK 和 JRE&#xff1f;它们之间的关系是什么&#xff1f;2. Java 内存区域&#xff08;运行时数据区&#xff09;有哪些&#xff1f;3. 说说你对 JVM 垃圾回收机制的理解。4. 常用的垃圾回收算法有哪些&#xff1f;5. 什么是 Minor GC、Major GC 和 Full G…

CMIP6 气候模式核心特性解析

在全球气候变化研究中&#xff0c;CMIP6&#xff08;第六次耦合模式比较计划&#xff09;的气候模式是关键工具。以下从研发背景与核心能力角度&#xff0c;解析五类主流模式的技术特点与适用场景。 一、主流模式技术特性 1. CanESM5/CanESM5-1&#xff08;加拿大环境与气候变…

【牛客刷题】BM63 跳台阶:三种解法深度解析(递归/DP动态规划/记忆化搜索)

文章目录 一、题目介绍 1.1 题目描述 1.2 示例 二、算法设计思路 2.1 核心问题分析 2.2 斐波那契数列关系 三、流程图 解法1:递归法(自顶向下) 解法2:动态规划(自底向上) 解法3:记忆化搜索(递归优化) 解法4: 优化DP流程(推荐) 四、解法实现 五、复杂度分析对比 六、…

《解构WebSocket断网重连:指数退避算法的前端工业级实践指南》

WebSocket作为客户端与服务器双向通信的核心载体,支撑着从在线协作、金融行情到即时通讯等各类高实时性场景。然而,网络环境的动态变化—从用户设备的Wi-Fi与蜂窝网络切换,到公共网络的临时拥塞,再到服务器的短暂重启—都可能导致WebSocket连接中断,进而引发数据传输停滞、…

医疗洁净间的“隐形助手”:富唯智能复合机器人如何重塑手术器械供应链

当手术刀片在无影灯下传递时&#xff0c;0.01mm的抓取偏差可能意味着感染风险——而富唯智能复合机器人以0.02mm的重复定位精度与99.999%无菌操作的硬实力&#xff0c;正成为高端医疗产线中替代人力的关键技术支点。一、医疗上下料的三大痛点&#xff1a;精度、洁净与连续性1.毫…

《设计模式》工厂方法模式

1.工厂方法模式&#xff08;Factory Method&#xff09;定义 定义一个用于创建对象的接口&#xff0c;让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。 1.1 UML图&#xff1a; 主要有4个对象&#xff1a; 抽象工厂&#xff08;Abstract Creator&#xf…

冒泡排序——简单理解和使用

阅前声明&#xff1a;如果想直接了解冒泡排序的简化思想&#xff0c;请跳至文章尾部在介绍之前&#xff0c;我们先看一个用到该功能的实战训练&#xff08;本人也是从中开始认识到冒泡排序这个函数定义&#xff09;对于小白来说&#xff0c;我的思路如下&#xff1a;1.题目中涉…

AI应用商业化加速落地 2025智能体爆发与端侧创新成增长引擎

今年以来&#xff0c;人工智能 (AI) 正在进入从算力投入到云服务消耗再到商业化收入&#xff0c;最终回到算力再投入的良性循环&#xff0c;而 AI 应用的起量正是推动这一飞轮效应的关键。7 月 31 日&#xff0c;国务院常务会议审议通过了《关于深入实施 “人工智能 ” 行动的意…

Pytest测试框架基础及进阶

Pytest测试框架基础# Pytest测试框架介绍# Pytest是Python一款三方测试框架&#xff0c;用于编写和运行单元测试、集成测试和功能测试。Pytest测试框架具有简单、灵活、易于扩展等特点&#xff0c;被广泛应用于Python项目的测试工作中。 Pytest主要特点&#xff1a; 简单易用…

航空装备先进加工工艺与制造技术论坛——2025成都航空装备展

300参展企业 11500㎡展区面积 7大专业展区 12000观众规模15同期会议 160发言嘉宾 5000参会嘉宾 100媒体报道航空工业飞速发展&#xff0c;先进加工工艺与制造技术成为了支撑航空装备性能提升、质量保障和产能优化的核心基石。为探索前沿技术路径、凝聚行业创新力量&#xff0c;…

为什么品牌更愿意为新品打广告?

品牌资源向新品广告倾斜&#xff0c;可以说是市场上的普遍现象。尤其对于没有明星产品的品牌而言&#xff0c;新品推广时企业的重要曝光节点。下面就让我们一同来了解下&#xff0c;为什么品牌更愿意为新品打广告。一、市场需求更充分新品广告往往承担着市场教育的功能&#xf…

电子电气架构 --- 关于整车信息安全的一些思考

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 做到欲望极简,了解自己的真实欲望,不受外在潮流的影响,不盲从,不跟风。把自己的精力全部用在自己。一是去掉多余,凡事找规律,基础是诚信;二是…