终于把三角形绘制出来了,首先一些关键概念、操作。

Vertex Data                       顶点数据

VBO Vertex Buffer Objects  顶点缓冲对象

VAO Vertex Array Objects   顶点数组对象

Vertex Attribute Pointer      顶点属性指针

NDC Normalized Device Coordinates 标准化设备坐标

Vertex Shader Objects        顶点着色器对象

GLSL   OpenGL Shading Language 着色器语言

顶点数组位置声明

顶点着色器 in 关键字声明输入

预定义关键字 gl_Position 顶点着色器输出

Fragment Shader Objects    片段着色器对象

片段着色器 out 关键字声明输出

Shader Program                 着色器程序

着色器程序链接顶点着色器与片段着色器

在绘制循环里使用着色器程序、绑定顶点数组对象、告知绘制图元类型、解绑顶点数组对象。

Graphics Pipeline:

Vertex Data => Vertex Shader => Primitive Assembly => Geometry Shader

Alpha Test And Blending <= Fragment Shader   <= Rasterization

就这些吧,上图、上源码:

主函数 main.cpp

// GLEW
#define GLEW_STATIC
#include <GL/glew.h>
// GLFW
#include <GLFW/glfw3.h>
#include <iostream>
#include "Triangles.h" int main(){
// glfw init
glfwInit();
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 glfw window
GLFWwindow *window = glfwCreateWindow(, , "opengl-triangles", nullptr, nullptr);
if (window == nullptr){
std::cout << "create glfw window failed..." << std::endl;
glfwTerminate();
return -;
}
glfwMakeContextCurrent(window);//set current window // glew init
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK){
std::cout << "glew init failed..." << std::endl;
return -;
} //get width and height from glfw window
int width, height;
glfwGetFramebufferSize(window, &width, &height);
//define the glViewport
glViewport(, , width, height); Triangles triangles;
triangles.init();
//add the game loop
while (!glfwWindowShouldClose(window)){
//check event
glfwPollEvents(); //now clear window
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);//the gl color buffer bit //your OpenGL code logical
triangles.draw(); //swap buffer
glfwSwapBuffers(window);
} //the end, glfw window has been closed
glfwTerminate();
return ;
}

头文件Triangles.h:

// GLEW
#define GLEW_STATIC
#include <GL/glew.h>
// GLFW
#include <GLFW/glfw3.h>
#include <iostream>
#include <sstream> class Triangles{ public:
Triangles(); ~Triangles(); public:
void init(); void draw(); private:
//create vertex shader
void createVertexShader(); //create fragment shader
void createFragmentShader(); //create shader program
void createShaderProgram(); //get vertex shader source code
std::string getVertexShaderSrc(); //get fragment shader source code
std::string getFragmentShaderSrc(); private:
GLuint VAO; //define VAO, vertex array object
GLuint vertexShader;
GLuint fragmentShader;
GLuint shaderProgram;
};

实现类Triangles.cpp:

#include "Triangles.h"

Triangles::Triangles(){
} Triangles::~Triangles(){
} void Triangles::init(){
// x,y,z opengl coordinates, the vertex data, three 3d point in normalized device coordinates
GLfloat vertexs[] = {
-0.4f, -0.5f, 0.0f,
0.4f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f,
};
//define VAO, vertex array object
//GLuint VAO;
glGenVertexArrays(, &VAO);
glBindVertexArray(VAO); // bind vertex array object
//define VBO, vertex buffer object
GLuint VBO;
glGenBuffers(, &VBO); // gen buffer object
glBindBuffer(GL_ARRAY_BUFFER, VBO); // bind buffer to the target
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexs), vertexs, GL_STATIC_DRAW); // copy vertex data to VBO
//set vertex attribute point
glVertexAttribPointer(, , GL_FLOAT, GL_FALSE, * sizeof(GLfloat), (GLvoid*));
glEnableVertexAttribArray();
glBindVertexArray();//unbind vertex array object //create shader program
this->createShaderProgram();
} void Triangles::draw(){
//use shader programs
glUseProgram(shaderProgram); //draw the triangles
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, , );
glBindVertexArray();
} void Triangles::createVertexShader(){
//compile vertex shader source
std::string vertexShaderStr = this->getVertexShaderSrc();
const char *vertexShaderSrc = vertexShaderStr.c_str();
std::cout << "vertexShaderSrc:\n" << vertexShaderSrc;
//GLuint vertexShader; // shader object
vertexShader = glCreateShader(GL_VERTEX_SHADER); // create vertex shader object
glShaderSource(vertexShader, , &vertexShaderSrc, NULL); // shader source attach to shader object
glCompileShader(vertexShader); // compile shader
//compile result check
GLint success;
GLchar infoLog[];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success){
glGetShaderInfoLog(vertexShader, , NULL, infoLog);
std::cout << "vertex shader source compile failed...\n" << infoLog << std::endl;
std::cout << vertexShaderSrc;
}
} void Triangles::createFragmentShader(){
//compile fragment shader source
std::string fragmentShaderStr = this->getFragmentShaderSrc();
const char *fragmentShaderSrc = fragmentShaderStr.c_str();
std::cout << "\n\nfragmentShaderSrc:\n" << fragmentShaderSrc;
//GLuint fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, , &fragmentShaderSrc, NULL);
glCompileShader(fragmentShader);
} void Triangles::createShaderProgram(){
this->createVertexShader();
this->createFragmentShader();
if (vertexShader == NULL || fragmentShader == NULL){
return;
}
//shader program, link vertex shader object and fragment shader object
//GLuint shaderProgram;
shaderProgram = glCreateProgram(); // create shader program
glAttachShader(shaderProgram, vertexShader); // attach vertex shader
glAttachShader(shaderProgram, fragmentShader); // attach fragment shader
glLinkProgram(shaderProgram); // linking
//check link result
GLint success;
GLchar infoLog[];
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success){
glGetProgramInfoLog(shaderProgram, , NULL, infoLog);
std::cout << "shader program linking failed...\n"<< infoLog << std::endl;
return;
}
//delete vertex shader object and fragment shader object
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
//return shaderProgram;
} std::string Triangles::getVertexShaderSrc(){
std::stringstream ss;
ss << "#version 330 core \n";
ss << "layout (location = 0) in vec3 position;";
ss << "void main()";
ss << "{";
ss << " gl_Position = vec4(position.x, position.y, position.z, 1.0);";
ss << "}";
//return ss.str(); std::string vertexShaderStr =
"#version 330 core\n"
"layout (location = 0) in vec3 pos; "
"void main () {"
" gl_Position = vec4(pos, 1.0);"
"}";
return vertexShaderStr;
} std::string Triangles::getFragmentShaderSrc(){
std::stringstream ss;
ss << " #version 330 core \n";
ss << " out vec4 color; \n";
ss << " void main(){ \n";
ss << " color = vec4(1.0f, 0.1f, 0.1f, 1.0f); \n";
ss << " } \n";
//return ss.str(); std::string fragmentShaderStr =
"#version 330 core\n"
"out vec4 color; "
"void main () {"
" color = vec4(1.0f, 0.1f, 0.1f, 1.0f);"
"}";
return fragmentShaderStr;
}

运行结果:

参照:https://learnopengl-cn.readthedocs.io/zh/latest/01%20Getting%20started/04%20Hello%20Triangle/

 

OpenGL学习——绘制第一个三角形的更多相关文章

  1. OpenGL学习-------绘制简单的几何图形

    本次课程所要讲的是绘制简单的几何图形,在实际绘制之前,让我们先熟悉一些概念. 一.点.直线和多边形我们知道数学(具体的说,是几何学)中有点.直线和多边形的概念,但这些概念在计算机中会有所不同.数学上的 ...

  2. OpenGL教程(3)——第一个三角形

    我们已经学会了创建窗口,这一讲,我们将学习如何使用现代OpenGL画一个三角形.在开始写代码之前,我们需要先了解一些OpenGL概念.本文会很长,请大家做好心理准备~ 注:以下OpenGL概念翻译自h ...

  3. OpenGL学习——绘制矩形

    接下来稍微扩展一步,绘制矩形,即两个拼在一起的三角形. 引入一个概念, EBO Element Buffer Object  元素缓冲对象, EBO用于存放描述“顶点绘制顺序”的对象. 外注:创建VS ...

  4. OpenGL学习进程(3)第一课:初始化窗体

        本节是OpenGL学习的第一个课时,下面介绍如何初始化一个窗体:     (1)显示一个有蓝色背景的窗体: #include <GL/glut.h> #include <st ...

  5. OpenGL学习(2)——绘制三角形(补)

    对上一篇的补充,通过绘制三角形来完成矩形的绘制.此外,完成章节后练习. 绘制矩形 一个矩形由两个三角形组成,因此绘制矩形需要绘制两个三角形,一共6个顶点,其中2个顶点重复画了两次. 为了减小开销,仅储 ...

  6. OpenGL学习进程(10)第七课:四边形绘制与动画基础

        本节是OpenGL学习的第七个课时,下面以四边形为例介绍绘制OpenGL动画的相关知识:     (1)绘制几种不同的四边形: 1)四边形(GL_QUADS) OpenGL的GL_QUADS图 ...

  7. OpenGL学习进程(4)第二课:绘制图形

    本节是OpenGL学习的第二个课时,下面介绍如何用点和线来绘制图形:     (1)用点的坐标来绘制矩形: #include <GL/glut.h> void display(void) ...

  8. OpenGL学习进程(11)第八课:颜色绘制的详解

        本节是OpenGL学习的第八个课时,下面将详细介绍OpenGL的颜色模式,颜色混合以及抗锯齿.     (1)颜色模式: OpenGL支持两种颜色模式:一种是RGBA,一种是颜色索引模式. R ...

  9. OpenGL学习进程(8)第六课:点、边和图形(三)绘制图形

    本节是OpenGL学习的第六个课时,下面介绍OpenGL图形的相关知识:     (1)多边形的概念: 多边形是由多条线段首尾相连而形成的闭合区域.OpenGL规定,一个多边形必须是一个“凸多边形”. ...

随机推荐

  1. Python基础篇(初始函数)

    Python初始函数: 一.什么是函数 1.我们到目前为止, 已经可以完成一些软件的基础功能了. 那么我们来完成这样一个功 能: 约x: print("拿出手机") print(& ...

  2. 在线px转换rem工具

    今天推荐一个在线工具,在线px转换rem工具 只要输入1rem = 多少px即可在线转换 和cssrem插件差不多的功能   rem在线转换工具: http://www.ofmonkey.com/fr ...

  3. 【知识强化】第四章 网络层 4.3 IP

    这节课我们来学习一下IP数据报的格式.那之所以把路由算法这一小节跳过呢,就是因为我们之后会要讲到路由的选择协议.那在路由选择协议这一块讲路由算法,我觉得是比较合适的.那我们先来看一下这节课要讲的知识. ...

  4. WebAPI 生成验证码

    private HttpResponseMessage CreateCheckCodeImage(string checkCode) { HttpResponseMessage result = ne ...

  5. wpf 查找控件

    public List<T> GetChildObjects<T>(DependencyObject obj, Type typename) where T : Framewo ...

  6. 2019-8-31-C#-使用汇编

    title author date CreateTime categories C# 使用汇编 lindexi 2019-08-31 16:55:58 +0800 2019-2-16 8:56:5 + ...

  7. Apache+tomcat 动静分离

    环境准备: Centos7 需要软件 jdk-8u45-linux-x64.tar.gz apache-tomcat-.tar.gz apr-.tar.gz apr-util-.tar.gz pcre ...

  8. shell unique

    由于uniq命令只能对相邻行进行去重复操作,所以在进行去重前,先要对文本行进行排序,使重复行集中到一起 1.文本行去重 (1)排序由于uniq命令只能对相邻行进行去重复操作,所以在进行去重前,先要对文 ...

  9. 【转】java中JVM的原理

    转载自https://blog.csdn.net/witsmakemen/article/details/28600127/ 一.java虚拟机的生命周期: Java虚拟机的生命周期 一个运行中的Ja ...

  10. H5 移动调试全攻略

    H5 移动调试全攻略 随着移动设备的高速发展,H5 开发也成为了 F2E 不可或缺的能力.而移动开发的重中之重就是掌握调试技巧,定 Bug于无形. 一.概要 因为移动端操作系统分为 iOS 和 And ...