OpenGL基础(一)建立第一个shader

本片文章适合刚入门OpenGL没有实战经验的新手。文章最后提供源码获取方式

OpenGL的背景 有什么作用就先不讲了,直接进入正题,创建第一个shader。

首先,先创建OpenGL的环境。

需要以下几个工具 Qt5.9级以上版本, vs2015以上 本人用的是Qt5.9 以及vs2019社区版

首先,先借助vs建立一个Qt桌面应用

OpenGL基础(一)建立第一个shader

并按照下图方式勾选, 红线

OpenGL基础(一)建立第一个shader

基类选择继承QWidget , 按照上面设置

这里顺便说一下,不要纠结你选择的界面显示框架,不要纠结于用 Qt的 或者windows的 又或者是OpenGL扩展库创建的,我会在后面为大家详细解答的

到这里我们完成了第一步,下面开始真的创建OpenGL环境

首先我们先修改头文件里继承的类,按照上述方法,我们继承的应该是QWidget 这个是Qt界面类,Qt本身自带OpenGL,我们修改为继承 public QOpenGLWidget, 和 protected QOpenGLFunctions ,如下面代码块所示

<code>#include <qopenglwidget>
#include <qopenglfunctions>
class OpenGLTest : public QOpenGLWidget, protected QOpenGLFunctions/<qopenglfunctions>/<qopenglwidget>/<code>

QOpenGLWidget类是用于渲染OpenGL图形。 提供一个OpenGL窗口

接下来我们需要实现三个函数

<code>protected:
\tvoid initializeGL();
\tvoid paintGL();
\tvoid resizeGL(int w, int h);/<code>

initializeGL()函数 负责初始化, 会在另外两个函数之前调用

resizeGL()函数用来 设置OpenGL视口,投影等。每当调整Widget的大小时(第一次显示窗口Widget时会调用它,因为所有新创建Widget都会自动获得调整大小的事件)

paintGL()函数用来渲染OpenGL场景。

分别在对饮的cpp文件中实现这三个函数

<code>void OpenGLTest::initializeGL()
{
//调用内容初始化函数
initializeOpenGLFunctions();
}
void OpenGLTest::resizeGL(int w, int h)
{
}
void OpenGLTest::paintGL()
{
}/<code>

到这里为止 我们的环境就算是搭建好了

接下来让我们来写shader 首先写顶点shader 。shader的代码类似于C语言 如下面代码块所示

<code>\tconst char* vs = "void main()\\
{\\
gl_Position = ftransform();\\
}";/<code>

这个是顶点shader

gl_Position 这个是顶点shader 里面内置的成员变量

ftransform() 这个也是内置的成员函数

这里是对输入的顶点做处理 怎么处理的后面会详细介绍

下面是片元shader

<code>\tconst char* ps = "void main()\\
{\\
gl_FragColor = vec4(1,0,0,1);\\
}";/<code>

片元着色器 这里设置要画的图形的颜色

gl_FragColor 这个是OpenGL 内置的成员变量

vec4 拥有四个float变量


创建完shader代码之后 我们需要对shader进行编译 如下面代码所示

<code>\t\t//调用OpenGL函数  来创建shader
\t\tmVShader = glCreateShader(GL_VERTEX_SHADER);//创建顶点着色器shader
\t\tmPShader = glCreateShader(GL_FRAGMENT_SHADER); //创建片元着色器shader

\t\t//指定shader的源代码 mVShader是顶点着色器 对应着顶点着色器代码
\t\tglShaderSource(mVShader, 1, (const GLchar**)&vs, 0);
\t\tglShaderSource(mPShader, 1, (const GLchar**)&ps, 0);

\t\t//! 编译shader
\t\t//顶点shader
\t\tglCompileShader(mVShader);
\t\tGLint status = 0;
\t\tchar compileLog[1024] = { 0 };
\t\t//得到编译结果 成功还是失败
\t\tglGetShaderiv(mVShader, GL_COMPILE_STATUS, &status);
\t\tif (status == GL_FALSE)
\t\t{
\t\t\t//打印错误消息
\t\t\tglGetShaderInfoLog(mVShader, sizeof(compileLog), 0, compileLog);
\t\t}

\t\t//片元着色器shader

\t\tglCompileShader(mPShader);

\t\tglGetShaderiv(mPShader, GL_COMPILE_STATUS, &status);
\t\tif (status == GL_FALSE)
\t\t{
\t\t\tglGetShaderInfoLog(mPShader, sizeof(compileLog), 0, compileLog);
\t\t}

\t\t//! 4创建程序
\t\tmProgram = glCreateProgram();
\t\t//将编译好的 shader放入程序中
\t\tglAttachShader(mProgram, mVShader);
\t\tglAttachShader(mProgram, mPShader);

\t\t//! 5链接程序
\t\tglLinkProgram(mProgram);
\t\t//得到程序的状态 成功还是失败
\t\tglGetProgramiv(mProgram, GL_LINK_STATUS, &status);
\t\tif (status == GL_FALSE)
\t\t{
\t\t\tglGetProgramInfoLog(mProgram, sizeof(compileLog), 0, compileLog);
\t\t\tbreak;
\t\t}
/<code>

以上的操作需要在函数进行初始化时候调用 也就是在initializeGL函数中调用

接下来 我们需要在resizeGL函数中设置视口(即在窗口中可以见到或可以用来绘图的部分)

<code>void OpenGLTest::resizeGL(int w, int h)
{
//当窗口大小改变时,调整界面坐标显示高度和宽度
glViewport(0, 0, w, h);
}/<code>

接下来使我们的渲染函数paintGL() 这个函数主要负责渲染图形

<code>//定义顶点
struct Point
{
\tfloat x, y, z; //图形点坐标
\tfloat r, g, b; //图形颜色
};

//清除之前图形并将背景设置为黑色
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

\t//! 指定以下的操作针对投影矩阵
\tglMatrixMode(GL_PROJECTION);
\t//! 将投影举证清空成单位矩阵
\tglLoadIdentity();

\t//创建一个正交平行的视景体
\tglOrtho(0, width, heigth, 0, -100, 100);

\tPoint rect[] =
\t{
\t\t{10, 10, 0, 1, 0, 0},
\t\t{110, 10, 0, 0, 1, 0},
\t\t{10, 110, 0, 0, 0, 1},
\t\t{110, 110, 0, 1, 0, 1},
\t};

\t//启用顶点数组
\tglEnableClientState(GL_VERTEX_ARRAY);
\t//启用着色数组
\tglEnableClientState(GL_COLOR_ARRAY);
\tglVertexPointer(3, GL_FLOAT, sizeof(Point), rect);
\tglColorPointer(3, GL_FLOAT, sizeof(Point), &rect[0].r);

\tbeginProgram();
\tglDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
\tendProgram();/<code>

这个样子就是创建成功了一个简单的OpenGL程序 最终显示结果 如下图所示


OpenGL基础(一)建立第一个shader

第一个程序显示的是简答的矩形。

下一章我会讲如何绘制自己想要的图形 以及设置颜色,纹理

如果有人需要源程序 可以私信我。

大家还有什么建议在下方留言,我会仔细查看大家的意见。


分享到:


相關文章: