C++学习(四七八)GL_MAX_TEXTURE_SIZE

本文介绍了一种使用OpenGL API来获取当前系统支持的最大纹理尺寸的方法。通过调用glGetIntegerv函数并传入GL_MAX_TEXTURE_SIZE参数,可以得到系统能够处理的最大纹理尺寸。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

GLint maxTextureSize;
glGetIntegerv(GL_MAX_TEXTURE_SIZE,&maxTextureSize);

获取最大纹理大小。

<think>好的,用户现在希望得到一个完整的代码示例,结合C++、OpenGL、stb_image、glm、glfw和curl来实现高德影像瓦片地图的显示。之前我已经介绍了相关的概念和模块,现在用户需要具体的实现代码。我需要考虑几个方面: 首先,用户可能已经具备一定的C++和OpenGL基础,但可能对如何整合这些库不太熟悉。需要确保代码结构清晰,并且包含必要的库初始化和配置步骤。 其次,用户提到的库包括GLFW(窗口管理)、GLM(数学库)、stb_image(图像加载)和libcurl(网络请求)。这些库的集成是关键,尤其是正确处理异步网络请求和纹理加载,避免阻塞主线程。 然后,四叉树的管理和动态瓦片加载是核心部分。需要确保四叉树能根据视口动态加载和卸载瓦片,同时处理网络请求的异步性,比如使用线程池来管理下载任务。 另外,代码的可编译性和依赖管理也是需要考虑的。用户可能需要帮助如何设置项目,比如包含正确的头文件和链接库。例如,使用CMake来管理项目,或者提供编译命令。 此外,高德地图的瓦片URL可能需要处理访问限制或密钥,但用户提供的示例URL似乎不需要,但需要注意遵守高德地图的使用条款,避免法律问题。 还要考虑OpenGL的版本兼容性,确保使用的特性在大多数显卡上支持,比如使用OpenGL 3.3及以上,并正确设置顶点缓冲对象(VBO)和顶点数组对象(VAO)以提高渲染效率。 最后,用户可能希望代码有良好的错误处理和资源管理,比如纹理加载失败后的处理,网络请求的重试机制,以及内存泄漏的预防,比如使用智能指针管理四叉树节点。 总结下来,我需要提供一个完整的示例,涵盖窗口初始化、四叉树管理、异步瓦片下载、纹理加载和渲染循环,同时确保代码结构清晰,注释详细,便于用户理解和调整。</think>以下是一个整合了 **C++、OpenGLGLFW、GLM、stb_image 和 libcurl** 的完整示例代码,实现高德影像瓦片地图的动态加载与渲染。代码需要结合 CMake 或手动配置依赖库编译。 --- ### **1. 环境准备** - **依赖库**: - **GLFW**:窗口管理 - **GLM**:数学计算(坐标转换) - **stb_image**:图像加载 - **libcurl**:网络请求 - **开发环境**: - Linux:`sudo apt-get install libglfw3-dev libcurl4-openssl-dev` - Windows:通过 vcpkg 或手动配置库路径 --- ### **2. 完整代码** ```cpp #include <GLFW/glfw3.h> #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> #include <curl/curl.h> #include <stb_image.h> #include <vector> #include <string> #include <thread> #include <mutex> #include <queue> #include <map> #include <cmath> // 全局定义 const int TILE_SIZE = 256; const int MAX_ZOOM = 18; const std::string TILE_URL = "https://webst01.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1&style=6"; // 瓦片结构体 struct Tile { int x, y, z; GLuint textureID; bool textureLoaded = false; }; // 四叉树节点 struct QuadtreeNode { int x, y, z; QuadtreeNode* children[4] = {nullptr}; Tile tile; bool isActive = false; }; // 全局变量 std::mutex tileMutex; std::queue<Tile> tileLoadQueue; std::map<std::string, Tile> tileCache; QuadtreeNode* root = nullptr; glm::mat4 viewMatrix; glm::vec2 cameraPos(0.0f, 0.0f); float zoomLevel = 2.0f; // libcurl 回调函数(下载瓦片数据) size_t writeCallback(char* ptr, size_t size, size_t nmemb, std::vector<unsigned char>* data) { data->insert(data->end(), ptr, ptr + size * nmemb); return size * nmemb; } // 下载瓦片图像 void downloadTile(Tile& tile) { CURL* curl = curl_easy_init(); if (curl) { std::string url = TILE_URL; replace(url, "{x}", std::to_string(tile.x)); replace(url, "{y}", std::to_string(tile.y)); replace(url, "{z}", std::to_string(tile.z)); std::vector<unsigned char> imageData; curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeCallback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &imageData); CURLcode res = curl_easy_perform(curl); curl_easy_cleanup(curl); if (res == CURLE_OK) { // 使用 stb_image 加载图像 int width, height, channels; unsigned char* data = stbi_load_from_memory(imageData.data(), imageData.size(), &width, &height, &channels, 0); if (data) { glGenTextures(1, &tile.textureID); glBindTexture(GL_TEXTURE_2D, tile.textureID); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); stbi_image_free(data); tile.textureLoaded = true; } } } } // 四叉树更新逻辑 void updateQuadtree(QuadtreeNode* node, const glm::vec2& cameraPos, float zoom) { if (!node) return; // 计算瓦片在屏幕中的范围 glm::vec2 tileMin(node->x * TILE_SIZE / pow(2, node->z), node->y * TILE_SIZE / pow(2, node->z)); glm::vec2 tileMax((node->x + 1) * TILE_SIZE / pow(2, node->z), (node->y + 1) * TILE_SIZE / pow(2, node->z)); // 判断是否在视口内 bool inView = (tileMax.x > cameraPos.x - 1.0f / zoom) && (tileMin.x < cameraPos.x + 1.0f / zoom) && (tileMax.y > cameraPos.y - 1.0f / zoom) && (tileMin.y < cameraPos.y + 1.0f / zoom); if (inView) { // 如果未加载,加入下载队列 if (!node->tile.textureLoaded) { std::lock_guard<std::mutex> lock(tileMutex); tileLoadQueue.push(node->tile); } // 分裂条件:当前层级小于最大层级且缩放足够大 if (node->z < MAX_ZOOM && zoom > 0.5f * pow(2, node->z)) { if (!node->children[0]) { // 创建子节点 for (int i = 0; i < 4; i++) { node->children[i] = new QuadtreeNode(); node->children[i]->z = node->z + 1; node->children[i]->x = node->x * 2 + (i % 2); node->children[i]->y = node->y * 2 + (i / 2); } } // 递归更新子节点 for (int i = 0; i < 4; i++) { updateQuadtree(node->children[i], cameraPos, zoom); } } } else { // 卸载不可见节点 delete node; node = nullptr; } } // 渲染瓦片 void renderTile(const Tile& tile) { if (!tile.textureLoaded) return; glm::vec2 tileMin(tile.x * TILE_SIZE / pow(2, tile.z), tile.y * TILE_SIZE / pow(2, tile.z)); glm::vec2 tileMax((tile.x + 1) * TILE_SIZE / pow(2, tile.z), (tile.y + 1) * TILE_SIZE / pow(2, tile.z)); glBindTexture(GL_TEXTURE_2D, tile.textureID); glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex2f(tileMin.x, tileMin.y); glTexCoord2f(1, 0); glVertex2f(tileMax.x, tileMin.y); glTexCoord2f(1, 1); glVertex2f(tileMax.x, tileMax.y); glTexCoord2f(0, 1); glVertex2f(tileMin.x, tileMax.y); glEnd(); } // 主函数 int main() { // 初始化 GLFW if (!glfwInit()) return -1; GLFWwindow* window = glfwCreateWindow(800, 600, "AMap Tile Viewer", NULL, NULL); if (!window) { glfwTerminate(); return -1; } glfwMakeContextCurrent(window); glEnable(GL_TEXTURE_2D); // 初始化四叉树根节点 root = new QuadtreeNode(); root->x = 0; root->y = 0; root->z = 0; // 启动异步下载线程 std::thread downloadThread([]() { while (true) { if (!tileLoadQueue.empty()) { std::lock_guard<std::mutex> lock(tileMutex); Tile tile = tileLoadQueue.front(); tileLoadQueue.pop(); downloadTile(tile); } std::this_thread::sleep_for(std::chrono::milliseconds(100)); } }); // 主循环 while (!glfwWindowShouldClose(window)) { // 处理输入 if (glfwGetKey(window, GLFW_KEY_UP)) cameraPos.y += 0.01f / zoomLevel; if (glfwGetKey(window, GLFW_KEY_DOWN)) cameraPos.y -= 0.01f / zoomLevel; if (glfwGetKey(window, GLFW_KEY_LEFT)) cameraPos.x -= 0.01f / zoomLevel; if (glfwGetKey(window, GLFW_KEY_RIGHT)) cameraPos.x += 0.01f / zoomLevel; // 更新四叉树 updateQuadtree(root, cameraPos, zoomLevel); // 渲染 glClear(GL_COLOR_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(cameraPos.x - 1.0 / zoomLevel, cameraPos.x + 1.0 / zoomLevel, cameraPos.y - 1.0 / zoomLevel, cameraPos.y + 1.0 / zoomLevel, -1, 1); // 递归渲染四叉树 std::function<void(QuadtreeNode*)> renderNode = [&](QuadtreeNode* node) { if (!node) return; renderTile(node->tile); for (int i = 0; i < 4; i++) { renderNode(node->children[i]); } }; renderNode(root); glfwSwapBuffers(window); glfwPollEvents(); } // 清理资源 downloadThread.detach(); glfwTerminate(); return 0; } ``` --- ### **3. 关键代码说明** 1. **四叉树动态更新**: - 根据相机位置和缩放层级,递归判断瓦片是否在视口内。 - 异步下载瓦片避免阻塞主线程。 2. **OpenGL 渲染**: - 使用 `glOrtho` 设置投影矩阵,根据相机位置动态调整视口。 - 通过 `glTexImage2D` 将下载的瓦片图像绑定为纹理。 3. **输入控制**: - 方向键控制相机移动(`cameraPos`)。 - 缩放通过 `zoomLevel` 调整(需扩展代码支持滚轮事件)。 --- ### **4. 编译与运行** #### **Linux 编译命令**: ```bash g++ main.cpp -o map_viewer -lglfw -lGL -lcurl -lm -I./include -L./lib ``` #### **Windows (MSVC)**: 配置项目属性,包含以下库: - `glfw3.lib` - `opengl32.lib` - `libcurl.lib` - `stb_image.h` 需放在包含路径。 --- ### **5. 注意事项** 1. **异步线程安全**: - 使用 `std::mutex` 保护共享队列 `tileLoadQueue`。 2. **纹理内存管理**: - 需要实现 LRU 缓存,避免内存溢出。 3. **高德 API 限制**: - 遵守高德地图的[使用条款](https://lbs.amap.com/),避免高频请求。 如果需要更详细的实现(如坐标转换优化、视锥剔除),可以进一步补充代码!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值