了解基元:三角形、线段、点
myglwidget.cpp
#include "myglwidget.h"
#include <QPainter>
#include <QPen>
#include <QDebug>
#include <QThread>
/*
* 最后摘录《编程指南》
* *********************************************
* 创建和编译着色器
* 第 1 步 创建着色器
* 第 2 步 提供着色器源码
* 第 3 步 编译
* 创建和链接项目
* 准备渲染
* *********************************************
* 着色器是 OpenGL ES 2.0 API 核心的基础。
* 每个 OpenGL ES 2.0程序要求一个顶点着色器和一个片段着色器去渲染一个图形
*/
MyGLWidget::MyGLWidget(QWidget *parent)
: QOpenGLWidget(parent)
{
setWindowTitle("My OpenGL Widget");
resize(600, 400);
}
MyGLWidget::~MyGLWidget()
{
program->release();
}
/* 1.1 着色器代码 */
/* *********************************************
* 摘录自 《编程指南》
* varying:
* 顶点着色器的输出叫做 varying 变量
* 在最初的光栅化阶段,这些变量被计算,作为片段着色器的输入,
* 从顶点着色器的矩阵使用插补的方法产生片段着色器的变量
*
* attribute:
* 在顶点着色器中,一个变量被使用限定词 attribute 声明为顶点属性
* 这个限定词仅仅在顶点着色器中使用
* 如果被用于片段着色器,片段着色器编译时将会产生错误
*
* uniform:
* 顶点着色器使用的常量数据
* ******************************************** */
/* ********************* 顶点着色器 ********************** */
/* ************ openGL ES 2.0 vertex shader ************ */
/*
* uniforms samplers (optional)
* | |
* attribute 0 V V varying 0
* attribute 1 _______________ varying 1
* attribute 2 | | varying 2
* attribute 3 ----\ | | ----\ varying 3
* attribute 4 ----/ | vertex shader | ----/ varying 4
* attribute 5 | | varying 5
* attribute 6 |_______________| varying 6
* attribute 7 varying 7
* /\
* /||\
* ||
* \||/
* \/
* temporary
* variables
*
* ****************************************************** */
/* 顶点着色器被使用在传统的基于顶点的操作,
* 例如位移矩阵、计算光照方程、产生贴图坐标。
* 顶点着色器被应用指定,应用于客户的顶点转化。
* ===================================================== */
/* 顶点数据,也称为顶点属性:指每一个顶点数据。 */
/* 指定顶点属性数据:每个顶点的属性数据能够被指定使用顶点矩阵或者为基元的每个顶点使用一个常量值 */
/* 顶点属性常量:指基元的所有顶点属性是相同的, 因此仅仅对基元的所有顶点仅仅需要指定一个值。 */
static const char *vertexShaderSourceCore =
"#version 150\n"
"in vec4 vPosition;\n"
"attribute lowp vec4 a_color;\n"
"varying lowp vec4 v_color;\n"
"void main() {\n"
" v_color = a_color;\n"
" gl_Position = vPosition;\n"
"}\n";
/* 光栅化是转化图元为二维片段的过程,被片段着色器执行,
* 二维的片段像素能够被绘制在屏幕上。 */
/* 片段着色器 */
static const char *fragmentShaderSourceCore =
"#version 150\n"
"varying lowp vec4 v_color;\n"
"out highp vec4 fragColor;\n"
"void main() {\n"
" fragColor = v_color;\n"
"}\n";
void MyGLWidget::initializeGL()
{
qDebug("+++ initializeGL +++");
/* 0. 初始化函数,使得函数可以使用 */
initializeOpenGLFunctions();
/* 创建项目对象链接着色器 */
/* 1. 初始化最大的任务是装载顶点和片段着色器 */
program = new QOpenGLShaderProgram;
/* 1.2 加载 */
program->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSourceCore);
program->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSourceCore);
/* 1.3 传值 (这样说明,不知道合不合适) */ /* 错误说明 */
/* 1.3 设置属性位置,将vPosition属性设置为位置0 */
program->bindAttributeLocation("vPosition", 0);
/* 1.4 链接项目检查错误 */
program->link();
}
/* 2. 回调绘画 */
void MyGLWidget::paintGL()
{
/* 1.5 为使用项目对象去渲染,需要绑定 */
program->bind();
/* 2.1 viewport 设定窗口的原点 origin (x, y)、宽度和高度 */
glViewport(0, 0, width(), height());
/* 2.2 缓冲区将被用 glClearColor 函数的颜色参数值清除 */
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
/* 2.3 三角形顶点的坐标 */
GLfloat vVertices[] = {0.0f, 0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f};
/* 2.4 Load the vertex data */
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vVertices);
glEnableVertexAttribArray(0);
/* 获取属性a_color的位置 */
GLuint a_color = program->attributeLocation("a_color");
GLfloat colors[] = {1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f};
/* 装载到a_color */
glVertexAttribPointer(a_color, 3, GL_FLOAT, GL_FALSE, 0, colors);
/* 使能 */
glEnableVertexAttribArray(a_color);
/* 基元:是使用 glDrawArrays 和 glDrawElements 能够绘制的图形。
* 基元是一系列用顶点位置、颜色、贴图坐标等信息描述的顶点。
* OpenGL ES 2.0 能绘制的基元有:三角形、直线、点 */
/* 三角形:GL_TRIANGLES, GL_TRIANGLE_STRIP 和 GL_TRIANGLE_FAN
* GL_TRIANGLES 描述一系列独立的三角形,
* 一共有 n/3 的三角形会被绘制,
* n 是 glDrawArrays or glDrawElements 的参数 count 的索引数目
* GL_TRIANGLE_STRIP 绘制一系列相连的三角形
* 一共有 n-2 个三角形被绘制 (V0, V1, V2)、(V2, V1, V3) 和 (V2, V3, V4)
* GL_TRIANGLE_FAN 也绘制了一系列相连的三角形
* 一共有 n-2 个三角形被绘制 (V0, V1, V2)、(V0, V2, V3) 和 (V0, V3, V4)
***/
/* 直线: GL_LINES, GL_LINE_STRIP 和 GL_LINE_LOOP
* GL_LINES 绘制一系列不相连的直线
* 总数 n/2 的线段被绘制 (V0, V1)、(V2, V3)、(V4, V5)
* GL_LINE_STRIP 绘制一系列相连的直线,最后非闭合
* 总数 n-1 的线段被绘制 (V0, V1)、(V1, V2)、(V2, V3)
* GL_LINE_LOOP 绘制一系列相连的直线,最后闭合
* 总数 n 的线段被绘制 (V0, V1)、(V1, V2)、(V2, V3)、(V3, V0)
*
* 直线宽使用 glLineWidth 指定
***/
/* 点纹理:GL_POINTS
* 点是特殊的,当绘制他们为点而不是正方形,使用的渲染效率被影响。
* 点是被指定位置和半径的对齐屏幕的矩形。
* 位置是方形的中心,半径被使用计算四个正方形的坐标。
**/
/* 绘制基元:glDrawArrays glDrawElements
* glDrawArrays(GLenum mode, GLint first, GLsizei count)
* 使用元素索引表中的 first 到 first + count-1 作顶点,使用 mode 作类型绘制基元
* glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices)
*
* 虽然可以使用 glDrawElements 和 glDrawArrays 都可以绘制三角形,
* 但在 GPU 上,因为很多原因 glDrawElements 比 glDrawArrays 更快。
* 例如当顶点重复时使用 glDrawElements 顶点属性数据的量更少。
**/
/* 最后一步是调用 OpenGL ES 去绘制基元 */
/* 三角形 */
//glDrawArrays(GL_TRIANGLES, 0, 3);
/* 线段 */
glDrawArrays(GL_LINE_LOOP, 0, 3);
glFlush();
}
void MyGLWidget::resizeGL(int w ,int h)
{
p.setToIdentity();
p.perspective(35.0f, float(w)/float(h), 1.0f, 30.0f);
}线段的效果: