GLSL教程 第十三章:综合项目:创建一个完整的渲染场景(一更)
目录
13.1 项目规划和设计
13.1.1 项目目标
13.1.2 设计要求
13.2 实现场景中的光照、材质和纹理
13.2.1 创建基础场景
13.2.2 应用材质和纹理
13.3 集成高级渲染效果和后期处理
13.3.1 阴影映射(Shadow Mapping)
13.3.2 环境光遮蔽(AO)
13.3.3 简单的景深效果(Depth of Field)
13.3.4 阴影技术
13.4 性能优化
13.4.1 批处理渲染
13.4.2 LOD(细节层次)
13.4.3 减少状态切换
13.4.4 延迟渲染
在本章中,我们将创建一个完整的渲染场景,涵盖从基础的场景设置到高级的渲染效果和后期处理。我们将使用OpenGL和GLSL来实现场景的渲染,并逐步引入光照、材质、纹理、阴影映射、环境光遮蔽(AO)以及景深效果等技术。
13.1 项目规划和设计
13.1.1 项目目标
本项目的目标是创建一个包含地面、墙壁和一个简单3D模型(如立方体)的基本渲染场景。除此之外,我们还将实现以下高级渲染效果:
- 阴影映射(Shadow Mapping)
- 环境光遮蔽(Ambient Occlusion,AO)
- 简单的景深效果(Depth of Field)
13.1.2 设计要求
- 场景内容:
- 地面
- 墙壁
- 3D模型(立方体)
- 光照效果:
- 点光源
- 环境光
- 材质效果:
- 漫反射和高光
- 高级渲染效果:
- 阴影映射
- 环境光遮蔽(AO)
- 简单的景深效果
13.2 实现场景中的光照、材质和纹理
13.2.1 创建基础场景
首先,我们将设置基础场景,包括地面、墙壁和一个简单的3D模型(立方体)。我们使用OpenGL创建这些基本几何体,并为每个对象定义适当的顶点和片段着色器。
顶点着色器 (shader.vert):
#version 330 corelayout(location = 0) in vec3 aPos;
layout(location = 1) in vec3 aNormal;
layout(location = 2) in vec2 aTexCoord;out vec3 FragPos;
out vec3 Normal;
out vec2 TexCoord;uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;void main() {vec4 worldPosition = model * vec4(aPos, 1.0);FragPos = worldPosition.xyz;Normal = mat3(transpose(inverse(model))) * aNormal;TexCoord = aTexCoord;gl_Position = projection * view * worldPosition;
}
片段着色器 (shader.frag):
#version 330 corein vec3 FragPos;
in vec3 Normal;
in vec2 TexCoord;out vec4 FragColor;struct Material {vec3 ambient;vec3 diffuse;vec3 specular;float shininess;
};struct Light {vec3 position;vec3 ambient;vec3 diffuse;vec3 specular;
};uniform Material material;
uniform Light light;
uniform vec3 viewPos;
uniform sampler2D diffuseTexture;void main() {// Ambientvec3 ambient = material.ambient * light.ambient;// Diffusevec3 norm = normalize(Normal);vec3 lightDir = normalize(light.position - FragPos);float diff = max(dot(norm, lightDir), 0.0);vec3 diffuse = material.diffuse * diff * light.diffuse;// Specularvec3 viewDir = normalize(viewPos - FragPos);vec3 reflectDir = reflect(-lightDir, norm);float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);vec3 specular = material.specular * spec * light.specular;vec3 result = ambient + diffuse + specular;FragColor = vec4(result, 1.0) * texture(diffuseTexture, TexCoord);
}
13.2.2 应用材质和纹理
接下来,我们为场景中的物体应用基础的材质和纹理。材质的主要属性包括漫反射、镜面反射和环境光成分。纹理则用于为物体添加更多的细节和颜色。
纹理加载和绑定 (texture.cpp):
#include "texture.hpp"
#include <iostream>Texture::Texture(const char* imagePath) {glGenTextures(1, &ID);glBindTexture(GL_TEXTURE_2D, ID);// 设置纹理参数glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);// 加载并生成纹理int width, height, nrChannels;unsigned char* data = stbi_load(imagePath, &width, &height, &nrChannels, 0);if (data) {GLenum format;if (nrChannels == 1)format = GL_RED;else if (nrChannels == 3)format = GL_RGB;else if (nrChannels == 4)format = GL_RGBA;glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);glGenerateMipmap(GL_TEXTURE_2D);} else {std::cerr << "Failed to load texture: " << imagePath << std::endl;}stbi_image_free(data);
}void Texture::bind() const {glBindTexture(GL_TEXTURE_2D, ID);
}
场景对象加载 (scene_object.cpp):
#include "scene_object.hpp"
#include <glm/gtc/matrix_transform.hpp>SceneObject::SceneObject(const std::vector<Vertex>& vertices, const std::vector<unsigned int>& indices, const char* texturePath): vertices(vertices), indices(indices), texture(texturePath) {setupMesh();
}void SceneObject::setupMesh() {glGenVertexArrays(1, &VAO);glGenBuffers(1, &VBO);glGenBuffers(1, &EBO);glBindVertexArray(VAO);glBindBuffer(GL_ARRAY_BUFFER, VBO);glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), &vertices[0], GL_STATIC_DRAW);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);// 顶点位置glEnableVertexAttribArray(0);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);// 法线glEnableVertexAttribArray(1);glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Normal));// 纹理坐标glEnableVertexAttribArray(2);glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, TexCoords));glBindVertexArray(0);
}void SceneObject::draw(const Shader& shader) {shader.use();glBindVertexArray(VAO);glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);glBindVertexArray(0);
}
13.3 集成高级渲染效果和后期处理
13.3.1 阴影映射(Shadow Mapping)
阴影映射用于在场景中生成逼真的阴影效果。我们将使用深度贴图来计算阴影,并在片段着色器中进行深度比较。
阴影映射Shader (shadow_mapping_shader.vert and shadow_mapping_shader.frag):
顶点着色器 (shadow_mapping_shader.vert):
#version 330 corelayout(location = 0) in vec3 aPos;uniform mat4 lightSpaceMatrix;
uniform mat4 model;void main() {gl_Position = lightSpaceMatrix * model * vec4(aPos, 1.0);
}
片段着色器 (shadow_mapping_shader.frag):
#version 330 corevoid main() {// 这里不需要输出颜色,深度缓冲会自动存储深度值
}
<相关文章:
GLSL教程 第十三章:综合项目:创建一个完整的渲染场景(一更)
目录 13.1 项目规划和设计 13.1.1 项目目标 13.1.2 设计要求 13.2 实现场景中的光照、材质和纹理 13.2.1 创建基础场景 13.2.2 应用材质和纹理 13.3 集成高级渲染效果和后期处理 13.3.1 阴影映射(Shadow Mapping) 13.3.2 环境光遮蔽(AO) 13.3.3 简单的景深效果(…...
pgvector: 30 倍构建向量嵌入索引
使用 pgvector 为 HNSW 并行构建索引 Postgres 最受欢迎的向量搜索扩展 pgvector 最近实现了并行索引构建功能,这将分层可导航小世界 (HNSW) 索引构建时间显著提高了 30 倍。 祝贺 Andrew Kane 和 pgvector 的贡献者发布此版本,这巩固了 Postgres 作为最…...
GNSS形变监测系统
TH-WY1 GNSS形变监测系统采用扼流圈设计有以下几个优势: 高精度测量:扼流圈是一种高精度的传感器,可以提供非常精确的测量结果。这使得GNSS形变监测系统能够准确地测量结构物的形变变化。 高稳定性:扼流圈设计使得传感器具有良好…...
每天一个数据分析题(四百五十三)- 随机抽样
在进行随机抽样时由于某些原因会产生抽样误差,以下关于抽样误差的说法,正确的是 A. 抽样误差是随机抽样调查中偶然发生的代表性误差 B. 抽样误差的大小同样本单位数成正比关系 C. 简单随机抽样比分层抽样误差大 D. 重复抽样比不重复抽样误差小 数据…...
Python爬虫知识体系-----Selenium
数据科学、数据分析、人工智能必备知识汇总-----Python爬虫-----持续更新:https://blog.csdn.net/grd_java/article/details/140574349 文章目录 一、安装和基本使用二、元素定位三、访问元素信息四、自动化交互五、PhantomJS六、Chrome headless 一、安装和基本使用…...
springboot+webSocket对接chatgpt
webSocket对接参考 话不多说直接上代码 WebSocket package com.student.config;import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; import lombok.extern.slf4j.Slf4j; import org.springframework.http.MediaType; import org.springfram…...
【ROS2】 默认的DDS通信中间件替换为Eclipse Cyclone_DDS (DDS配置方法)
ROS2替换中间件为Cyclone_DDS 1.一些介绍:)2.不同DDS的RMW实现3.默认的FastDDS替换为Cyclone DDSi.安装依赖ii.编译 cyclone-dds 4.配置网络 1.一些介绍:) 上一篇我们探讨了ros1和ros2编写launch的区别 【ROS2】launch启动文件编…...
迈向数智金融:机器学习金融科技新纪元的新风采
个人名片: 🐼作者简介:一名大三在校生,喜欢AI编程🎋 🐻❄️个人主页🥇:落798. 🐼个人WeChat:hmmwx53 🕊️系列专栏:🖼️…...
Nginx+PHP+CI框架实现,访问静态文件带权限验证
1、访问来源验证配置nginx #文件访问来源校验 如路径:https://ys.test.com/test/api/uploads/test.png #不是该允许域名的将返回403页面 location /test/api/uploads/ {valid_referers ys.test.com ys.test2.com;if ($invalid_referer) {return 403;} }2、拦截访问…...
javascript 第二天
正则表达式 a/正则表达式内容/ a.test(“需要检测的内容”) 焦点事件 onfocus 获得焦点 onblur 失去焦点 他们都是事件,和onclick一样 onchange 内容改变 失去焦点时生效,多了内容检测,如果内容不变不触发,内容改变才触发 onk…...
unity2D游戏开发17战斗精灵
导入 将PlayerFight32x32.png拖Player文件夹进去 设置属性 创建动画剪辑 选中前四帧,右键Create|Animation,将动画命名为player-ire-east 其他几个动画也创建好后,将其拖到Animations|Animations文件夹 选中PlayerController,再点击Animator 创建新的Blend Tree Graph,并重…...
kafka架构+原理+源码
1.安装jdk17 sudo yum -y update sudo wget https://download.oracle.com/java/17/latest/jdk-17_linux-x64_bin.rpm sudo yum -y install ./jdk-17_linux-x64_bin.rpm sudo java -version 2.安装kafka How to easily install kafka without zookeeper | Aditya’s Blog 1.…...
实力共鉴!微风企斩获2024年浙江省专精特新中小企业
日前,微风企斩获2024年浙江省专精特新中小企业荣誉,这是继获得“国家高新技术企业”“浙江省科技中小企业”“杭州市雏鹰计划企业”等权威性认证后,微风企荣获的又一重磅殊荣。 “专精特新中小企业”是国家对具有“专业化、精细化、特色化、新…...
C#:枚举及位标志周边知识详解(小白入门)
文章目录 枚举为什么要有枚举?枚举的性质设置默认类型和显式设置成员的值 位标志(重要)位标记是什么及作用位标志周边知识HasFlag判断是否有该功能枚举前面加Flags的好处 关于枚举的更多知识using static简化代码获取枚举成员的字面量 枚举 为什么要有枚举? 为了增加代码的…...
这本vue3编译原理开源电子书,初中级前端竟然都能看懂
前言 众所周知vue提供了很多黑魔法,比如单文件组件(SFC)、指令、宏函数、css scoped等。这些都是vue提供的开箱即用的功能,大家平时用这些黑魔法的时候有没有疑惑过一些疑问呢。 我们每天写的vue代码一般都是写在*.vue文件中,但是浏览器却只…...
小白如何安装WNO(小波神经算子),需要安装python3.8,torch,ptwt,pywt等
下载项目 WNO在github上面的项目地址如下: https://github.com/csccm-iitd/WNO/tree/main 下载下来后,里面的数据集需要用matlab代码生成,也可以到里面提到的google云盘里面下载数据集 安装环境 然后需要安装环境 注意python版本一定要…...
Java HashMap 源码解读笔记(一)--xunznux
文章目录 HashMap介绍实现说明:源码解读静态常量和内部节点类 Node静态工具方法属性字段 Fields未完待续。。。 HashMap 本文主要是用于记录我在阅读Java1.8的 HashMap 源码所做的笔记。对于源码中的注释会进行翻译下来,并且会对其中部分源码进行注释。 这一篇文章…...
“等保测评下的数据加密与隐私保护“
在当今数字化时代,数据已成为企业最宝贵的资产之一。然而,数据泄露、隐私侵犯等事件频发,不仅给企业带来经济损失,更严重损害了公众信任。等保测评,作为国家信息安全等级保护制度的重要组成部分,对数据加密…...
Oat++ 后端实现跨域
这里记录在官方的例子中,加入跨域。Oat Example-CRUD 在官方的例子中,加入跨域。 Oat Example-CRUD 修改AppComponent.hpp文件中的代码,如下: #include "AppComponent.hpp"#include "controller/UserController…...
Three basic starting points to do AI
Computers have been based on memory/storage for so many years. Don’t try to come up with something else. For so many years, AI has been based on fixed precise rules or fuzzy matching rules. Don’t think about coming up with the third one by yourself. Vi…...
装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
7.4.分块查找
一.分块查找的算法思想: 1.实例: 以上述图片的顺序表为例, 该顺序表的数据元素从整体来看是乱序的,但如果把这些数据元素分成一块一块的小区间, 第一个区间[0,1]索引上的数据元素都是小于等于10的, 第二…...
AI Agent与Agentic AI:原理、应用、挑战与未来展望
文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例:使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例:使用OpenAI GPT-3进…...
鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/
使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题:docker pull 失败 网络不同,需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...
Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?
在大数据处理领域,Hive 作为 Hadoop 生态中重要的数据仓库工具,其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式,很多开发者常常陷入选择困境。本文将从底…...
Python ROS2【机器人中间件框架】 简介
销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...
MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...
android RelativeLayout布局
<?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_parent"android:gravity&…...
MyBatis中关于缓存的理解
MyBatis缓存 MyBatis系统当中默认定义两级缓存:一级缓存、二级缓存 默认情况下,只有一级缓存开启(sqlSession级别的缓存)二级缓存需要手动开启配置,需要局域namespace级别的缓存 一级缓存(本地缓存&#…...
企业大模型服务合规指南:深度解析备案与登记制度
伴随AI技术的爆炸式发展,尤其是大模型(LLM)在各行各业的深度应用和整合,企业利用AI技术提升效率、创新服务的步伐不断加快。无论是像DeepSeek这样的前沿技术提供者,还是积极拥抱AI转型的传统企业,在面向公众…...
