话说程序员有三大浪漫,操作系统、编译原理和计算机图形学。这里称作计算机图形学,而不是图形学,是为了避免歧义。

opengl是干什么的,可以自行google。这里仅作为一个学习里程中的记录。不作为权威指南。

入门教程参见,https://learnopengl-cn.readthedocs.io/zh/latest/01%20Getting%20started/02%20Creating%20a%20window/

opengl的环境配置可以见,https://zhuanlan.zhihu.com/p/23226676?utm_medium=social&utm_source=qq,谢谢大神分享。

本是在windows10, visual studio2015的环境下运行。顺便提一句,windows10自带opengl库,即包含了opengl32.lib。下面上代码。

shader.vs    顶点着色器代码

  1. #version core
  2. layout (location = ) in vec3 position;//in 代表输入向量, location,与下面的顶点属性描述有关。
  3. layout (location = ) in vec3 color;
  4.  
  5. out vec3 ourColor;//out 代表输出3维向量,作为片段着色器的输入,见下文
  6.  
  7. void main()
  8. {
  9. gl_Position = vec4(position, 1.0f);
  10. ourColor = color;
  11. }

shader.frag  片段着色器代码

  1. #version core
  2. in vec3 ourColor;
  3. out vec4 color;
  4.  
  5. void main()
  6. {
  7. color = vec4(ourColor, 1.0f);
  8. }

main.cpp

  1. #include <iostream>
  2. // GLEW
  3. #define GLEW_STATIC
  4. #include <GL/glew.h>
  5. // GLFW
  6. #include <GLFW/glfw3.h>
  7. // Other includes
  8. #include "Shader.h"
  9.  
  10. // Function prototypes
  11. void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
  12.  
  13. // Window dimensions
  14. const GLuint WIDTH = , HEIGHT = ;
  15. // The MAIN function, from here we start the application and run the game loop
  16. int main()
  17. {
  18. // Init GLFW
  19. glfwInit();
  20. // Set all the required options for GLFW
  21. glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, );
  22. glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, );
  23. glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
  24. glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
  25.  
  26. // Create a GLFWwindow object that we can use for GLFW's functions
  27. GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr);
  28. glfwMakeContextCurrent(window);
  29.  
  30. // Set the required callback functions
  31. glfwSetKeyCallback(window, key_callback);
  32.  
  33. // Set this to true so GLEW knows to use a modern approach to retrieving function pointers and extensions
  34. glewExperimental = GL_TRUE;
  35. // Initialize GLEW to setup the OpenGL Function pointers
  36. glewInit();
  37.  
  38. // Define the viewport dimensions
  39. glViewport(, , WIDTH, HEIGHT);
  40.  
  41. //读取shader文件,并编译,见shader.h代码
  42. Shader ourShader("C:\\Users\\leng\\Desktop\\shader.vs", "C:\\Users\\leng\\Desktop\\shader.frag");
  43.  
  44. // 一维数组,每六个代表一个顶点属性,前三个代表位置属性,后三个代表颜色属性
  45. GLfloat vertices[] = {
  46. // Positions // Colors
  47. 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, // Bottom Right
  48. -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, // Bottom Left
  49. 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f // Top
  50. };
  51. GLuint VBO, VAO;//声明顶点缓冲,声明顶点数组用于管理顶点数据
  52. glGenVertexArrays(, &VAO);//创建顶点数组,返回一个独一无二的整数,标识数组
  53. glGenBuffers(, &VBO);//创建顶点缓冲,返回一个独一无二的整数,标识缓冲区
  54.  
  55. glBindVertexArray(VAO);//绑定顶点数组
  56. glBindBuffer(GL_ARRAY_BUFFER, VBO);//绑定顶点缓冲
      //指定顶点数组的数据源为vertices,第四个参数代表显卡如何管理给定的数据,GL_STATIC_DRWA代表几乎不会改变
  57. glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
  58.  
  59. // 指定顶点属性的解析方式。即,如何从顶点缓冲获取相应的顶点属性和相应的颜色属性。或者说,顶点着色器中如何知道去哪个顶点属性分量重着色呢
      //对每一个顶点而言,属性有2种,一是位置属性,而是颜色属性,因此每六个浮点数决定了一个顶点的位置和颜色
  60.  
  61.   //顶点着色器中使用layout(location = 0)定义了position顶点属性的位置值(Location),因此第一个参数,代表属性分量的索引
      //参数二:顶点位置属性的维度,参数三:属性向量的数据类型,参数四:是否标准化;参数五,顶点位置属性的总字节长度,参数六:在缓冲数组中的偏移量,即起始位置
  62. glVertexAttribPointer(, , GL_FLOAT, GL_FALSE, * sizeof(GLfloat), (GLvoid*));
  63. glEnableVertexAttribArray();//启用属性0,因为默认是禁用的
  64. // 参数一,对应顶点着色器中的layout (location = 1) in vec3 color;参数六:说明颜色属性的偏移量在三个浮点数后,与上文vertices一致
  65. glVertexAttribPointer(, , GL_FLOAT, GL_FALSE, * sizeof(GLfloat), (GLvoid*)( * sizeof(GLfloat)));
  66. glEnableVertexAttribArray();//启用属性1.
  67.   //顶点数组对象(Vertex Array Object, VAO)的好处就是,当配置顶点属性指针时,你只需要将上面的代码调用执行一次,之后再绘制物体的时候只需要绑定相应的VAO就行了。如下文循环中的绑定再解绑
  68. glBindVertexArray(); // 解绑 VAO
  69. // Game loop
  70. while (!glfwWindowShouldClose(window))
  71. {
  72. // 检查事件,调用相应的回调函数,如下文的key_callback函数
  73. glfwPollEvents();
  74.  
  75. // Render
  76. // Clear the colorbuffer
  77. glClearColor(0.2f, 0.3f, 0.3f, 1.0f);//渲染颜色到后台缓冲
  78. glClear(GL_COLOR_BUFFER_BIT);//清除前台缓冲
  79.  
  80. // Draw the triangle
  81. ourShader.Use();//启用着色器程序
  82. glBindVertexArray(VAO);//每次循环都调用,绑定函数绑定VAO
  83. glDrawArrays(GL_TRIANGLES, , );
  84. glBindVertexArray();//解绑
  85.  
  86. // Swap the screen buffers
  87. glfwSwapBuffers(window);
  88. }
  89. // Properly de-allocate all resources once they've outlived their purpose
  90. glDeleteVertexArrays(, &VAO);
  91. glDeleteBuffers(, &VBO);
  92. // Terminate GLFW, clearing any resources allocated by GLFW.
  93. glfwTerminate();
  94. return ;
  95. }
  96.  
  97. // Is called whenever a key is pressed/released via GLFW
  98. void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
  99. {
  100. if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
  101. glfwSetWindowShouldClose(window, GL_TRUE);
  102. }

Shader.h    从文件中读取着色器代码,并编译。

  1. #ifndef SHADER_H
  2. #define SHADER_H
  3.  
  4. #include <string>
  5. #include <fstream>
  6. #include <sstream>
  7. #include <iostream>
  8.  
  9. #include <GL/glew.h>
  10.  
  11. class Shader
  12. {
  13. public:
  14. GLuint Program;
  15. // Constructor generates the shader on the fly
  16. Shader(const GLchar* vertexPath, const GLchar* fragmentPath)
  17. {
  18. // 1. Retrieve the vertex/fragment source code from filePath
  19. std::string vertexCode;
  20. std::string fragmentCode;
  21. std::ifstream vShaderFile;
  22. std::ifstream fShaderFile;
  23. // ensures ifstream objects can throw exceptions:
  24. vShaderFile.exceptions(std::ifstream::badbit);
  25. fShaderFile.exceptions(std::ifstream::badbit);
  26. try
  27. {
  28. // Open files
  29. vShaderFile.open(vertexPath);
  30. fShaderFile.open(fragmentPath);
  31. std::stringstream vShaderStream, fShaderStream;
  32. // Read file's buffer contents into streams
  33. vShaderStream << vShaderFile.rdbuf();
  34. fShaderStream << fShaderFile.rdbuf();
  35. // close file handlers
  36. vShaderFile.close();
  37. fShaderFile.close();
  38. // Convert stream into string
  39. vertexCode = vShaderStream.str();
  40. fragmentCode = fShaderStream.str();
  41. }
  42. catch (std::ifstream::failure e)
  43. {
  44. std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl;
  45. }
  46. const GLchar* vShaderCode = vertexCode.c_str();
  47. const GLchar * fShaderCode = fragmentCode.c_str();
  48. // 2. Compile shaders
  49. GLuint vertex, fragment;
  50. GLint success;
  51. GLchar infoLog[];
  52. // Vertex Shader
  53. vertex = glCreateShader(GL_VERTEX_SHADER);//创建顶点着色器
  54. glShaderSource(vertex, , &vShaderCode, NULL);//指定源代码
  55. glCompileShader(vertex);//编译着色器
  56. // Print compile errors if any
  57. glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);//查看是否编译成功
  58. if (!success)
  59. {
  60. glGetShaderInfoLog(vertex, , NULL, infoLog);
  61. std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
  62. }
  63. // Fragment Shader
  64. fragment = glCreateShader(GL_FRAGMENT_SHADER);//创建片段着色器
  65. glShaderSource(fragment, , &fShaderCode, NULL);
  66. glCompileShader(fragment);
  67. // Print compile errors if any
  68. glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);
  69. if (!success)
  70. {
  71. glGetShaderInfoLog(fragment, , NULL, infoLog);
  72. std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
  73. }
  74. // Shader Program
  75. this->Program = glCreateProgram();//创建着色程序
  76. glAttachShader(this->Program, vertex);//关联顶点着色器
  77. glAttachShader(this->Program, fragment);//关联片段着色器
  78. glLinkProgram(this->Program);//链接编译器
  79. // Print linking errors if any
  80. glGetProgramiv(this->Program, GL_LINK_STATUS, &success);
  81. if (!success)
  82. {
  83. glGetProgramInfoLog(this->Program, , NULL, infoLog);
  84. std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
  85. }
  86. // Delete the shaders as they're linked into our program now and no longer necessery
  87. glDeleteShader(vertex);
  88. glDeleteShader(fragment);
  89.  
  90. }
  91. // Uses the current shader
  92. void Use()
  93. {
  94. glUseProgram(this->Program);
  95. }
  96. };
  97.  
  98. #endif

最后附上,运行图片

opengl入门篇一: 第一个三角形的更多相关文章

  1. opengl入门篇二: 索引缓冲对象EBO

    在绘制图形的过程中,顶点可能会重复.比如两个三角形组成了四边形,那么,必然有两个点是重复的.因此采用索引的方式,四个点即可描述四边形. // 四个顶点 GLfloat vertices[] = { / ...

  2. Google C++测试框架系列入门篇:第一章 介绍:为什么使用GTest?

    原始链接:Introduction: Why Google C++ Testing Framework? 词汇表 版本号:v_0.1 介绍:为什么使用GTest? GTest帮助你写更好的C++测试代 ...

  3. Sping Boot入门到实战之入门篇(一):Spring Boot简介

    该篇为Spring Boot入门到实战系列入门篇的第一篇.对Spring Boot做一个大致的介绍. 传统的基于Spring的Java Web应用,需要配置web.xml, applicationCo ...

  4. Google C++测试框架系列入门篇:第二章 开始一个新项目

    上一篇:Google C++测试框架系列入门篇:第一章 介绍:为什么使用GTest? 原始链接:Setting up a New Test Project 词汇表 版本号:v_0.1 开始一个新项目 ...

  5. 【OpenCV入门指南】第一篇 安装OpenCV

    http://blog.csdn.net/morewindows/article/details/8225783/ win10下vs2015配置Opencv3.1.0过程详解(转) http://ww ...

  6. 新注册第一帖----------------------乱码新手自学.net 之Linq 入门篇

    作为一个业余开发,断断续续学.net/c#也有不少日子了, 学习过程中,不断忘了学,学了忘,这让我很苦恼. 以前学习过程中,我总是在笔记本中记录下来知识要点,这么久下来,笔记本都写了四五本了. 然而, ...

  7. .NET Core实战项目之CMS 第一章 入门篇-开篇及总体规划

    作者:依乐祝 原文地址:https://www.cnblogs.com/yilezhu/p/9977862.html 写在前面 千呼万唤始出来,首先,请允许我长吸一口气!真没想到一份来自28岁老程序员 ...

  8. net core体系-web应用程序-4asp.net core2.0 项目实战(CMS)-第一章 入门篇-开篇及总体规划

    .NET Core实战项目之CMS 第一章 入门篇-开篇及总体规划   原文地址:https://www.cnblogs.com/yilezhu/p/9977862.html 写在前面 千呼万唤始出来 ...

  9. SaltStack入门到精通第一篇:安装SaltStack

    SaltStack入门到精通第一篇:安装SaltStack 作者:纳米龙  发布日期:2014-06-09 17:50:36   实际环境的设定: 系统环境: centos6 或centos5 实验机 ...

随机推荐

  1. 为何 linux 要用 tar.gz,而不用 7z 或 zip?

    因为 7z 和 zip 压缩格式都不能保留 unix 风格的文件权限,比如解压出个可执行文件要重新 chmod chown 才能恢复正常.而 tar 格式可以.而 tar 本身不提供压缩,无非就是把包 ...

  2. 《Maven 实战》笔记之setting.xml介绍

    maven是什么?有什么用? Maven是一个跨平台的项目管理工具,主要服务于Java平台的项目构建,依赖管理和项目信息管理.项目构建包括创建项目框架.清理.编译.测试.到生成报告,再到打包和部署,项 ...

  3. iptables 设置特定IP访问指定端口

    一.添加规则:设置禁止所有IP访问指定端口8075 [root@zabbix_server ~]# iptables -I INPUT -p tcp --dport -j DROP 二.测试telne ...

  4. springboot中使用servlet时返回结果乱码问题

    在总的配置文件:application.properties中做一个配置,把我的问题解决了. #编码格式 spring.http.encoding.force=true spring.http.enc ...

  5. SpringBoot 在IDEA中实现热部署(实用版)(引入)

    SpringBoot 在IDEA中实现热部署(实用版) 引用:https://www.jianshu.com/p/f658fed35786 好的热部署让开发调试事半功倍,这样的“神技能”怎么能错过呢, ...

  6. mysql innodb存储引擎 锁 事务

    以下内容翻译自mysql5.6官方手册. InnoDB是一种通用存储引擎,可平衡高可靠性和高性能.在MySQL 5.6中,InnoDB是默认的MySQL存储引擎.除非已经配置了不同的默认存​​储引擎, ...

  7. 软件测试课程--安装QTP后java环境变量冲突

    很多学习性能测试的朋友们都会有这样的问题,安装QuickTest Professional11之后,类似于eclipse.pycharm打开弹出报错窗口,命令行(CMD)也无法正常显示javac.ja ...

  8. spring data mongo API learn(转)

    显示操作mongo的语句,log4j里面加入: log4j.logger.org.springframework.data.mongodb.core=DEBUG, mongodb log4j.appe ...

  9. Codeforces Round #608 (Div. 2) E. Common Number

    链接: https://codeforces.com/contest/1271/problem/E 题意: At first, let's define function f(x) as follow ...

  10. eclipse导入tomcat时Unknown version of Tomcat was specified

    Unknown version of Tomcat was specified 的原因有2种可能: 1 路径不是真正的路径,可能是其子路径,要找到bin路径. 2 安装目录没有访问权限. 我的就是第2 ...