opengl开发环境搭建
声明:文章核心内容摘自opengl中文网 https://learnopengl-cn.github.io/,也会补充一部分网站上没有的内容。
目录
一 安装cmake
二 安装GLFW
三 下载glad
四 创建测试工程
一 安装cmake
cmake是一个跨平台的c/c++项目管理工具,下面我们编译安装相关依赖库的时候需要用到。下载页,下载后安装即可。
二 安装GLFW
在我们画出出色的效果之前,首先要做的就是创建一个OpenGL上下文(Context)和一个用于显示的窗口。然而,这些操作在每个系统上都是不一样的,OpenGL有目的地将这些操作抽象(Abstract)出去。这意味着我们不得不自己处理创建窗口,定义OpenGL上下文以及处理用户输入。幸运的是,有一些库已经提供了我们所需的功能,其中一部分是特别针对OpenGL的。这些库节省了我们书写操作系统相关代码的时间,提供给我们一个窗口和上下文用来渲染。最流行的几个库有GLUT,SDL,SFML和GLFW。在教程里我们将使用GLFW。首先下载GLFW:下载页
点击Source package下载源码编译安装(建议下载源码进行编译一个自己的lib库文件,否则可能会有兼容问题),下载解压后,在glfw文件夹内创建build目录,然后双击第一步安装的cmake,开始编译lib库,打开后配置如下
最上面选择glfw的源码位置和build生成的目录位置(根据自己的实际目录配置),然后先点击Configure按钮,点击后选择相应的vs版本,然后点击Generate按钮生成vs工程,最后点击Open Project打开工程,打开后选中vs右侧解决方案右键,点击生成解决方案,生成lib库。生成成功后,在build/src中找到(我的目录F:\workspace\opengl\glfw-3.3.2\build\src\Debug)glfw3.lib文件拷贝到任意制定位置(建议放到项目工程目录下,后面会说放到哪里)。
三 下载glad
因为OpenGL只是一个标准/规范,具体的实现是由驱动开发商针对特定显卡实现的。由于OpenGL驱动版本众多,它大多数函数的位置都无法在编译时确定下来,需要在运行时查询。所以任务就落在了开发者身上,开发者需要在运行时获取函数地址并将其保存在一个函数指针中供以后使用。取得地址的方法因平台而异,在Windows上会是类似这样:
// 定义函数原型
typedef void (*GL_GENBUFFERS) (GLsizei, GLuint*);
// 找到正确的函数并赋值给函数指针
GL_GENBUFFERS glGenBuffers = (GL_GENBUFFERS)wglGetProcAddress("glGenBuffers");
// 现在函数可以被正常调用了
GLuint buffer;
glGenBuffers(1, &buffer);
你可以看到代码非常复杂,而且很繁琐,我们需要对每个可能使用的函数都要重复这个过程。幸运的是,有些库能简化此过程,其中GLAD是目前最新,也是最流行的库。
GLAD是一个开源的库,它能解决我们上面提到的那个繁琐的问题。GLAD的配置与大多数的开源库有些许的不同,GLAD使用了一个在线服务。在这里我们能够告诉GLAD需要定义的OpenGL版本,并且根据这个版本加载所有相关的OpenGL函数。打开GLAD的在线服务,将语言(Language)设置为C/C++,在API选项中,选择3.3以上的OpenGL(gl)版本(我们的教程中将使用3.3版本,但更新的版本也能正常工作)。之后将模式(Profile)设置为Core,并且保证生成加载器(Generate a loader)的选项是选中的。现在可以先(暂时)忽略拓展(Extensions)中的内容。
都选择完之后, 把网页拉到底,点击生成(Generate)按钮来生成库文件,GLAD现在应该提供给你了一个zip压缩文件,包含两个头文件目录,和一个glad.c文件然后下载生成的文件,后面会说怎么用。
四 创建测试工程
1 打开vs创建一个空项目opengltest
生成项目后我的工程目录如下
glad是上面下载的glad的源码(glad下载下来解压后是2个目录include和src,建议把这两个目录放到一个文件夹下如glad等),这个不需要编译直接用就行后面会说怎么用,glfw-3.3.2放glfw的源码文件(后面需要引用里面的头文件include目录),lib目录下放的是我们编译的glfw的库文件,opengltest是我们创建的空工程目录。
2 接着打开创建的空工程目录,右键解决方案选择属性,配置包含目录,把我们的glad,glfw的头文件引用进去,如图
3 接着配置lib库引用目录,把我们的lib目录包含进去,如图
4 添加glfw,和opengl库文件(opengl库一般在安装vs的时候会自动带进去),如图
5 选中解决方案中的源文件,右键添加,选择现有项,把glad目录下的glad.c文件添加到工程中,然后继续右键添加新建项main.cpp,成功后工程目录结构如下
6 然后在maim.cpp中添加如下代码(这里暂不解释代码):
#include <glad/glad.h>
#include <GLFW/glfw3.h>#include <iostream>void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow *window);// settings
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;const char *vertexShaderSource = "#version 330 core\n""layout (location = 0) in vec3 aPos;\n""void main()\n""{\n"" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n""}\0";
const char *fragmentShaderSource = "#version 330 core\n""out vec4 FragColor;\n""void main()\n""{\n"" FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n""}\n\0";int main()
{// glfw: initialize and configure// ------------------------------glfwInit();glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);#ifdef __APPLE__glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif// glfw window creation// --------------------GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);if (window == NULL){std::cout << "Failed to create GLFW window" << std::endl;glfwTerminate();return -1;}glfwMakeContextCurrent(window);glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);// glad: load all OpenGL function pointers// ---------------------------------------if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)){std::cout << "Failed to initialize GLAD" << std::endl;return -1;}// build and compile our shader program// ------------------------------------// vertex shaderint vertexShader = glCreateShader(GL_VERTEX_SHADER);glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);glCompileShader(vertexShader);// check for shader compile errorsint success;char infoLog[512];glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);if (!success){glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;}// fragment shaderint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);glCompileShader(fragmentShader);// check for shader compile errorsglGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);if (!success){glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;}// link shadersint shaderProgram = glCreateProgram();glAttachShader(shaderProgram, vertexShader);glAttachShader(shaderProgram, fragmentShader);glLinkProgram(shaderProgram);// check for linking errorsglGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);if (!success) {glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;}glDeleteShader(vertexShader);glDeleteShader(fragmentShader);// set up vertex data (and buffer(s)) and configure vertex attributes// ------------------------------------------------------------------float vertices[] = {-0.5f, -0.5f, 0.0f, // left 0.5f, -0.5f, 0.0f, // right 0.0f, 0.5f, 0.0f // top }; unsigned int VBO, VAO;glGenVertexArrays(1, &VAO);glGenBuffers(1, &VBO);// bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).glBindVertexArray(VAO);glBindBuffer(GL_ARRAY_BUFFER, VBO);glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);glEnableVertexAttribArray(0);// note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbindglBindBuffer(GL_ARRAY_BUFFER, 0); // You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other// VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary.glBindVertexArray(0); // uncomment this call to draw in wireframe polygons.//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);// render loop// -----------while (!glfwWindowShouldClose(window)){// input// -----processInput(window);// render// ------glClearColor(0.2f, 0.3f, 0.3f, 1.0f);glClear(GL_COLOR_BUFFER_BIT);// draw our first triangleglUseProgram(shaderProgram);glBindVertexArray(VAO); // seeing as we only have a single VAO there's no need to bind it every time, but we'll do so to keep things a bit more organizedglDrawArrays(GL_TRIANGLES, 0, 3);// glBindVertexArray(0); // no need to unbind it every time // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)// -------------------------------------------------------------------------------glfwSwapBuffers(window);glfwPollEvents();}// optional: de-allocate all resources once they've outlived their purpose:// ------------------------------------------------------------------------glDeleteVertexArrays(1, &VAO);glDeleteBuffers(1, &VBO);glDeleteProgram(shaderProgram);// glfw: terminate, clearing all previously allocated GLFW resources.// ------------------------------------------------------------------glfwTerminate();return 0;
}// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
// ---------------------------------------------------------------------------------------------------------
void processInput(GLFWwindow *window)
{if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)glfwSetWindowShouldClose(window, true);
}// glfw: whenever the window size changed (by OS or user resize) this callback function executes
// ---------------------------------------------------------------------------------------------
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{// make sure the viewport matches the new window dimensions; note that width and // height will be significantly larger than specified on retina displays.glViewport(0, 0, width, height);
}
7 运最后行后项目可以看到我们我们通过opengl渲染出来的三角形:
opengl开发环境搭建相关推荐
- 【游戏开发】基于VS2017的OpenGL开发环境搭建
一.简介 最近,马三买了两本有关于"计算机图形学"的书籍,准备在工作之余鼓捣鼓捣图形学和OpenGL编程,提升自己的价值(奔着学完能涨一波工资去的).俗话说得好,"工欲善 ...
- OpenGL+VS2012环境搭建
近段时间在做图像处理,第一步当然是学习OpenGL.千里之行,始于足下.开发环境总是要浪费程序员太多时间.昨天捣鼓一天OpenGL的开发环境,看了网上N多的环境搭建教程和问题解决方案,始终没有达到自己 ...
- Slick2D游戏引擎基础知识和开发环境搭建
目录 介绍 开发环境搭建 文件准备 添加库文件 设置 VM Options HelloWorld示例 示例程序说明 介绍 Slick 2D 是一个轻量级.跨平台的 Java 2D 游戏引擎. 我一直打 ...
- STM32MP157开发笔记 | 02 - 开发环境搭建(A7核、M4核)
一.STM32MP157 1. 系列介绍 STM32MP157微处理器基于灵活的双Arm® Cortex®-A7内核(工作频率800 MHz)和Cortex®-M4内核(工作频率209 MHz)架构, ...
- VCF的开发环境搭建
VCF的开发环境搭建 一.VCF是什么? 已经有几篇文章详细介绍了,这里我就不重复了,详细内容请了解linkman网友的 关于VCF(Visual Component Framework),关于VCF ...
- 【Android基础笔记01】Android开发环境搭建和HelloWorld
最近手头项目3.0版本要上线了, 没有那么多工作压力了, 抽空看了看之前在云笔记上做的笔记 都是一些基础知识 给大家分享出来吧 一.什么是Android?[了解 ] Android(中文俗称安卓)是一 ...
- Android环境搭建和Android HelloWorld—Android开发环境搭建
Android_Android开发环境搭建-搭建Android的开发环境 1.我考虑先下载JDK7.0,在JDK的安装中,考虑一般SDK都是向上兼容的,于是选择了最高的版本7.0 这里是我总结的详细的 ...
- qt工程在linux系统里颜色显示错误_【飞凌嵌入式RK3399开发板试用体验】+QT开发环境搭建测试(二)...
作者:飞扬的青春 在拿到开发板之后,已经体验了Android操作系统,接下来就是体验Linux下的开发,本次以QT的一个小案例来测试下. 首先是自己先搭建了一个Ubuntu18.04的虚拟机,使用真机 ...
- Go:分布式学习利器(1) -- 开发环境搭建 + 运行第一个go程序
文章目录 为什么要学习 go 开发环境搭建 -- MAC 运行第一个go程序 go 函数的返回值设置 go 函数的命令行参数 为什么要学习 go 在如下几个应用场景的需求下产生了go: 超大规模分布式 ...
最新文章
- 使用阿里云服务器安装docker,并用nginx示例
- 在 Java Web 项目中,Service 层和 Dao 层真的有必要每个类都加上接口吗
- android canves rotate 详解
- Python学习笔记4—Python字典元组
- 看完本文若不能让你学通“Python”,我将永远退出IT界
- Bailian2933 停车场收费【水题】
- Characterizing stochastic time series with ordinal networks
- 美国算法交易的影响和启示
- HIVE存储(四)ORCFile
- SPSS详细图文教程:手把手教你配对样本t检验,
- MAC使用Safari浏览器仿真IE
- Windows程序设计之WinAPI详解程序
- 社交媒体与社会网络分析,深度分析社交网络问题
- 高中计算机绘画教,高中美术电脑绘画教案.doc
- 自学英语最有效的方法
- Ubuntu 如何安装 微信?实测
- 西瓜书课后习题5.5源码
- 电话簿管理系统(超详细)
- vue3 预览docx文件
- jupyter输出为html隐藏代码,在jupyter noteb中隐藏代码
热门文章
- C# 字符串操作--减少垃圾回收压力
- [ARM嵌入式系统开发]第一章之嵌入式系统的软硬件
- 基于有源钳位三电平的有源电力滤波器(ANPC-APF)MATLAB仿真,包括自建的DSOGI锁相模块和PQ谐波检测模块。 可简单解释。
- 项目中报错:Warning: count():Parameter must be an array or an object that implements Countable的解决方案
- java+springboot的大学生心理健康测试测评系统vue
- 压缩感知的尽头: 原子范数最小化
- arduino nano 蓝牙_基于Arduino的摩尔斯电码练习及无线收发报训练器
- 计算机应用能力考试裸考,五分钟拯救裸考生,计算机二级这样就能过
- 与docker-spoon配对
- uniapp的checkbox标签属性