OpenGL学习——绘制第一个三角形
终于把三角形绘制出来了,首先一些关键概念、操作。
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学习——绘制第一个三角形的更多相关文章
- OpenGL学习-------绘制简单的几何图形
本次课程所要讲的是绘制简单的几何图形,在实际绘制之前,让我们先熟悉一些概念. 一.点.直线和多边形我们知道数学(具体的说,是几何学)中有点.直线和多边形的概念,但这些概念在计算机中会有所不同.数学上的 ...
- OpenGL教程(3)——第一个三角形
我们已经学会了创建窗口,这一讲,我们将学习如何使用现代OpenGL画一个三角形.在开始写代码之前,我们需要先了解一些OpenGL概念.本文会很长,请大家做好心理准备~ 注:以下OpenGL概念翻译自h ...
- OpenGL学习——绘制矩形
接下来稍微扩展一步,绘制矩形,即两个拼在一起的三角形. 引入一个概念, EBO Element Buffer Object 元素缓冲对象, EBO用于存放描述“顶点绘制顺序”的对象. 外注:创建VS ...
- OpenGL学习进程(3)第一课:初始化窗体
本节是OpenGL学习的第一个课时,下面介绍如何初始化一个窗体: (1)显示一个有蓝色背景的窗体: #include <GL/glut.h> #include <st ...
- OpenGL学习(2)——绘制三角形(补)
对上一篇的补充,通过绘制三角形来完成矩形的绘制.此外,完成章节后练习. 绘制矩形 一个矩形由两个三角形组成,因此绘制矩形需要绘制两个三角形,一共6个顶点,其中2个顶点重复画了两次. 为了减小开销,仅储 ...
- OpenGL学习进程(10)第七课:四边形绘制与动画基础
本节是OpenGL学习的第七个课时,下面以四边形为例介绍绘制OpenGL动画的相关知识: (1)绘制几种不同的四边形: 1)四边形(GL_QUADS) OpenGL的GL_QUADS图 ...
- OpenGL学习进程(4)第二课:绘制图形
本节是OpenGL学习的第二个课时,下面介绍如何用点和线来绘制图形: (1)用点的坐标来绘制矩形: #include <GL/glut.h> void display(void) ...
- OpenGL学习进程(11)第八课:颜色绘制的详解
本节是OpenGL学习的第八个课时,下面将详细介绍OpenGL的颜色模式,颜色混合以及抗锯齿. (1)颜色模式: OpenGL支持两种颜色模式:一种是RGBA,一种是颜色索引模式. R ...
- OpenGL学习进程(8)第六课:点、边和图形(三)绘制图形
本节是OpenGL学习的第六个课时,下面介绍OpenGL图形的相关知识: (1)多边形的概念: 多边形是由多条线段首尾相连而形成的闭合区域.OpenGL规定,一个多边形必须是一个“凸多边形”. ...
随机推荐
- android SharedPreferences 存储文件
- js不加alert后面的代码不工作
问题:用Ajax从后台拿到了json,append到select的option里面,然后想用for循环来设置某个作为默认值,发现在for循环外面加了个alert()的话,就能实现成功,没有加这个ale ...
- shell函数的定义和调用
- 十二、结构模式之门面(Facade)模式
什么是门面模式 门面模式(也有翻译为外观模式)是对象的结构模式,外部与一个子系统的通信必须通过一个统一的门面进行.其为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子 ...
- Spring IOC 的理解,初始化过程
在创建ApplicationContext实例对象过程中会创建一个spring容器,该容器会读取配置文件"cn/wuliaokankan/beans.xml",并统一管理由该文件中 ...
- JQuery-跑马灯(文字无缝向上翻动-封装)
转载自他人:https://blog.csdn.net/z69183787/article/details/12857587 (function($){ $.fn.extend({ &qu ...
- vue学习笔记(五)— 组件通信
关于vue父子组件通信 作者:狐狸家的鱼 本文链接:vue组件通信 GitHub:sueRimn 如果组件是一个单页面,组件之间存在父子关系,数据传递就需要根据父子不同的地位使用不同的办法. 借助新建 ...
- STM点滴一
就就是你用BSRR和BRR去改变管脚状态的时候,没有被中断打断的风险.也就不需要关闭中断. This way, there is no risk that an IRQ occurs between ...
- 【leetcode】1004. Max Consecutive Ones III
题目如下: Given an array A of 0s and 1s, we may change up to K values from 0 to 1. Return the length of ...
- rabbitMQ初始化配置
用户管理添加用户# rabbitmqctl add_user username password删除用户# rabbitmqctl delete_user username修改密码# rabbitmq ...