opengl入门篇一: 第一个三角形
话说程序员有三大浪漫,操作系统、编译原理和计算机图形学。这里称作计算机图形学,而不是图形学,是为了避免歧义。
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 顶点着色器代码
- #version core
- layout (location = ) in vec3 position;//in 代表输入向量, location,与下面的顶点属性描述有关。
- layout (location = ) in vec3 color;
- out vec3 ourColor;//out 代表输出3维向量,作为片段着色器的输入,见下文
- void main()
- {
- gl_Position = vec4(position, 1.0f);
- ourColor = color;
- }
shader.frag 片段着色器代码
- #version core
- in vec3 ourColor;
- out vec4 color;
- void main()
- {
- color = vec4(ourColor, 1.0f);
- }
main.cpp
- #include <iostream>
- // GLEW
- #define GLEW_STATIC
- #include <GL/glew.h>
- // GLFW
- #include <GLFW/glfw3.h>
- // Other includes
- #include "Shader.h"
- // Function prototypes
- void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
- // Window dimensions
- const GLuint WIDTH = , HEIGHT = ;
- // The MAIN function, from here we start the application and run the game loop
- int main()
- {
- // Init GLFW
- glfwInit();
- // Set all the required options for GLFW
- glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, );
- glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, );
- glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
- glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
- // Create a GLFWwindow object that we can use for GLFW's functions
- GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr);
- glfwMakeContextCurrent(window);
- // Set the required callback functions
- glfwSetKeyCallback(window, key_callback);
- // Set this to true so GLEW knows to use a modern approach to retrieving function pointers and extensions
- glewExperimental = GL_TRUE;
- // Initialize GLEW to setup the OpenGL Function pointers
- glewInit();
- // Define the viewport dimensions
- glViewport(, , WIDTH, HEIGHT);
- //读取shader文件,并编译,见shader.h代码
- Shader ourShader("C:\\Users\\leng\\Desktop\\shader.vs", "C:\\Users\\leng\\Desktop\\shader.frag");
- // 一维数组,每六个代表一个顶点属性,前三个代表位置属性,后三个代表颜色属性
- GLfloat vertices[] = {
- // Positions // Colors
- 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, // Bottom Right
- -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, // Bottom Left
- 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f // Top
- };
- GLuint VBO, VAO;//声明顶点缓冲,声明顶点数组用于管理顶点数据
- glGenVertexArrays(, &VAO);//创建顶点数组,返回一个独一无二的整数,标识数组
- glGenBuffers(, &VBO);//创建顶点缓冲,返回一个独一无二的整数,标识缓冲区
- glBindVertexArray(VAO);//绑定顶点数组
- glBindBuffer(GL_ARRAY_BUFFER, VBO);//绑定顶点缓冲
//指定顶点数组的数据源为vertices,第四个参数代表显卡如何管理给定的数据,GL_STATIC_DRWA代表几乎不会改变- glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
- // 指定顶点属性的解析方式。即,如何从顶点缓冲获取相应的顶点属性和相应的颜色属性。或者说,顶点着色器中如何知道去哪个顶点属性分量重着色呢
//对每一个顶点而言,属性有2种,一是位置属性,而是颜色属性,因此每六个浮点数决定了一个顶点的位置和颜色- //顶点着色器中使用layout(location = 0)定义了position顶点属性的位置值(Location),因此第一个参数,代表属性分量的索引
//参数二:顶点位置属性的维度,参数三:属性向量的数据类型,参数四:是否标准化;参数五,顶点位置属性的总字节长度,参数六:在缓冲数组中的偏移量,即起始位置- glVertexAttribPointer(, , GL_FLOAT, GL_FALSE, * sizeof(GLfloat), (GLvoid*));
- glEnableVertexAttribArray();//启用属性0,因为默认是禁用的
- // 参数一,对应顶点着色器中的layout (location = 1) in vec3 color;参数六:说明颜色属性的偏移量在三个浮点数后,与上文vertices一致
- glVertexAttribPointer(, , GL_FLOAT, GL_FALSE, * sizeof(GLfloat), (GLvoid*)( * sizeof(GLfloat)));
- glEnableVertexAttribArray();//启用属性1.
- //顶点数组对象(Vertex Array Object, VAO)的好处就是,当配置顶点属性指针时,你只需要将上面的代码调用执行一次,之后再绘制物体的时候只需要绑定相应的VAO就行了。如下文循环中的绑定再解绑
- glBindVertexArray(); // 解绑 VAO
- // Game loop
- while (!glfwWindowShouldClose(window))
- {
- // 检查事件,调用相应的回调函数,如下文的key_callback函数
- glfwPollEvents();
- // Render
- // Clear the colorbuffer
- glClearColor(0.2f, 0.3f, 0.3f, 1.0f);//渲染颜色到后台缓冲
- glClear(GL_COLOR_BUFFER_BIT);//清除前台缓冲
- // Draw the triangle
- ourShader.Use();//启用着色器程序
- glBindVertexArray(VAO);//每次循环都调用,绑定函数绑定VAO
- glDrawArrays(GL_TRIANGLES, , );
- glBindVertexArray();//解绑
- // Swap the screen buffers
- glfwSwapBuffers(window);
- }
- // Properly de-allocate all resources once they've outlived their purpose
- glDeleteVertexArrays(, &VAO);
- glDeleteBuffers(, &VBO);
- // Terminate GLFW, clearing any resources allocated by GLFW.
- glfwTerminate();
- return ;
- }
- // Is called whenever a key is pressed/released via GLFW
- void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
- {
- if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
- glfwSetWindowShouldClose(window, GL_TRUE);
- }
Shader.h 从文件中读取着色器代码,并编译。
- #ifndef SHADER_H
- #define SHADER_H
- #include <string>
- #include <fstream>
- #include <sstream>
- #include <iostream>
- #include <GL/glew.h>
- class Shader
- {
- public:
- GLuint Program;
- // Constructor generates the shader on the fly
- Shader(const GLchar* vertexPath, const GLchar* fragmentPath)
- {
- // 1. Retrieve the vertex/fragment source code from filePath
- std::string vertexCode;
- std::string fragmentCode;
- std::ifstream vShaderFile;
- std::ifstream fShaderFile;
- // ensures ifstream objects can throw exceptions:
- vShaderFile.exceptions(std::ifstream::badbit);
- fShaderFile.exceptions(std::ifstream::badbit);
- try
- {
- // Open files
- vShaderFile.open(vertexPath);
- fShaderFile.open(fragmentPath);
- std::stringstream vShaderStream, fShaderStream;
- // Read file's buffer contents into streams
- vShaderStream << vShaderFile.rdbuf();
- fShaderStream << fShaderFile.rdbuf();
- // close file handlers
- vShaderFile.close();
- fShaderFile.close();
- // Convert stream into string
- vertexCode = vShaderStream.str();
- fragmentCode = fShaderStream.str();
- }
- catch (std::ifstream::failure e)
- {
- std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl;
- }
- const GLchar* vShaderCode = vertexCode.c_str();
- const GLchar * fShaderCode = fragmentCode.c_str();
- // 2. Compile shaders
- GLuint vertex, fragment;
- GLint success;
- GLchar infoLog[];
- // Vertex Shader
- vertex = glCreateShader(GL_VERTEX_SHADER);//创建顶点着色器
- glShaderSource(vertex, , &vShaderCode, NULL);//指定源代码
- glCompileShader(vertex);//编译着色器
- // Print compile errors if any
- glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);//查看是否编译成功
- if (!success)
- {
- glGetShaderInfoLog(vertex, , NULL, infoLog);
- std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
- }
- // Fragment Shader
- fragment = glCreateShader(GL_FRAGMENT_SHADER);//创建片段着色器
- glShaderSource(fragment, , &fShaderCode, NULL);
- glCompileShader(fragment);
- // Print compile errors if any
- glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);
- if (!success)
- {
- glGetShaderInfoLog(fragment, , NULL, infoLog);
- std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
- }
- // Shader Program
- this->Program = glCreateProgram();//创建着色程序
- glAttachShader(this->Program, vertex);//关联顶点着色器
- glAttachShader(this->Program, fragment);//关联片段着色器
- glLinkProgram(this->Program);//链接编译器
- // Print linking errors if any
- glGetProgramiv(this->Program, GL_LINK_STATUS, &success);
- if (!success)
- {
- glGetProgramInfoLog(this->Program, , NULL, infoLog);
- std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
- }
- // Delete the shaders as they're linked into our program now and no longer necessery
- glDeleteShader(vertex);
- glDeleteShader(fragment);
- }
- // Uses the current shader
- void Use()
- {
- glUseProgram(this->Program);
- }
- };
- #endif
最后附上,运行图片
opengl入门篇一: 第一个三角形的更多相关文章
- opengl入门篇二: 索引缓冲对象EBO
在绘制图形的过程中,顶点可能会重复.比如两个三角形组成了四边形,那么,必然有两个点是重复的.因此采用索引的方式,四个点即可描述四边形. // 四个顶点 GLfloat vertices[] = { / ...
- Google C++测试框架系列入门篇:第一章 介绍:为什么使用GTest?
原始链接:Introduction: Why Google C++ Testing Framework? 词汇表 版本号:v_0.1 介绍:为什么使用GTest? GTest帮助你写更好的C++测试代 ...
- Sping Boot入门到实战之入门篇(一):Spring Boot简介
该篇为Spring Boot入门到实战系列入门篇的第一篇.对Spring Boot做一个大致的介绍. 传统的基于Spring的Java Web应用,需要配置web.xml, applicationCo ...
- Google C++测试框架系列入门篇:第二章 开始一个新项目
上一篇:Google C++测试框架系列入门篇:第一章 介绍:为什么使用GTest? 原始链接:Setting up a New Test Project 词汇表 版本号:v_0.1 开始一个新项目 ...
- 【OpenCV入门指南】第一篇 安装OpenCV
http://blog.csdn.net/morewindows/article/details/8225783/ win10下vs2015配置Opencv3.1.0过程详解(转) http://ww ...
- 新注册第一帖----------------------乱码新手自学.net 之Linq 入门篇
作为一个业余开发,断断续续学.net/c#也有不少日子了, 学习过程中,不断忘了学,学了忘,这让我很苦恼. 以前学习过程中,我总是在笔记本中记录下来知识要点,这么久下来,笔记本都写了四五本了. 然而, ...
- .NET Core实战项目之CMS 第一章 入门篇-开篇及总体规划
作者:依乐祝 原文地址:https://www.cnblogs.com/yilezhu/p/9977862.html 写在前面 千呼万唤始出来,首先,请允许我长吸一口气!真没想到一份来自28岁老程序员 ...
- net core体系-web应用程序-4asp.net core2.0 项目实战(CMS)-第一章 入门篇-开篇及总体规划
.NET Core实战项目之CMS 第一章 入门篇-开篇及总体规划 原文地址:https://www.cnblogs.com/yilezhu/p/9977862.html 写在前面 千呼万唤始出来 ...
- SaltStack入门到精通第一篇:安装SaltStack
SaltStack入门到精通第一篇:安装SaltStack 作者:纳米龙 发布日期:2014-06-09 17:50:36 实际环境的设定: 系统环境: centos6 或centos5 实验机 ...
随机推荐
- 为何 linux 要用 tar.gz,而不用 7z 或 zip?
因为 7z 和 zip 压缩格式都不能保留 unix 风格的文件权限,比如解压出个可执行文件要重新 chmod chown 才能恢复正常.而 tar 格式可以.而 tar 本身不提供压缩,无非就是把包 ...
- 《Maven 实战》笔记之setting.xml介绍
maven是什么?有什么用? Maven是一个跨平台的项目管理工具,主要服务于Java平台的项目构建,依赖管理和项目信息管理.项目构建包括创建项目框架.清理.编译.测试.到生成报告,再到打包和部署,项 ...
- iptables 设置特定IP访问指定端口
一.添加规则:设置禁止所有IP访问指定端口8075 [root@zabbix_server ~]# iptables -I INPUT -p tcp --dport -j DROP 二.测试telne ...
- springboot中使用servlet时返回结果乱码问题
在总的配置文件:application.properties中做一个配置,把我的问题解决了. #编码格式 spring.http.encoding.force=true spring.http.enc ...
- SpringBoot 在IDEA中实现热部署(实用版)(引入)
SpringBoot 在IDEA中实现热部署(实用版) 引用:https://www.jianshu.com/p/f658fed35786 好的热部署让开发调试事半功倍,这样的“神技能”怎么能错过呢, ...
- mysql innodb存储引擎 锁 事务
以下内容翻译自mysql5.6官方手册. InnoDB是一种通用存储引擎,可平衡高可靠性和高性能.在MySQL 5.6中,InnoDB是默认的MySQL存储引擎.除非已经配置了不同的默认存储引擎, ...
- 软件测试课程--安装QTP后java环境变量冲突
很多学习性能测试的朋友们都会有这样的问题,安装QuickTest Professional11之后,类似于eclipse.pycharm打开弹出报错窗口,命令行(CMD)也无法正常显示javac.ja ...
- spring data mongo API learn(转)
显示操作mongo的语句,log4j里面加入: log4j.logger.org.springframework.data.mongodb.core=DEBUG, mongodb log4j.appe ...
- 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 ...
- eclipse导入tomcat时Unknown version of Tomcat was specified
Unknown version of Tomcat was specified 的原因有2种可能: 1 路径不是真正的路径,可能是其子路径,要找到bin路径. 2 安装目录没有访问权限. 我的就是第2 ...