阅读《计算机图形学编程(使用OpenGL和C++)》2 - 画点

OpenGL可以绘制点、线、三角形,这些简单的东西叫做图元,多数3D模型通常是由许多三角形的图元构成。图元由顶点组成。顶点可以从文件读取并由C++/OpenGL应用载入缓冲区或直接在C++文件中硬编码字符串或直接在GLSL代码中。在加载顶点之前,C++/OpenGL应用必须编译并链接合适的GLSL顶点着色器和片段着色器程序,之后将它们载入管线。

C++/OpenGL应用同时负责通知OpenGL构建三角形,通过调用函数glDrawArrays(),管线中的GLSL代码开始执行。所有的顶点都会被传入顶点着色器。着色器对每个顶点执行一次,这些执行过程通常是并行的。

glDrawArrays (GLenum mode, GLint first, GLsizei count);

mode参数是图元的类型——对于三角形用GL_TRIANGLES。First参数表示从哪个顶点开始绘制(通常是顶点0,即第一个顶点),count是要绘制的顶点总数。

将GLSL程序载入着色器
1、 使用C++获取GLSL着色器代码,从文件或字符串中读取
2、 创建OpenGL着色器对象并将GLSL着色器代码加载进着色器对象
3、 用OpenGL命令编译并连接着色器对象,并将其安装进GPU

OpenGL中点的默认大小为1像素。

窗口中央有一个蓝色的点的代码如下。

main.cpp

(#include列表与之前同)
#define numVAOs 1

GLuint renderingProgram;
GLuint vao[numVAOs];

GLuint createShaderProgram()
{
    const char* vshaderSource = 
        "#version 460 \n"
        "void main(void) \n"
        "{ gl_Position = vec4(0.0, 0.0, 0.0, 1.0); }";

    const char* fshaderSource =
        "#version 460 \n"
        "out vec4 color; \n"
        "void main(void) \n"
        "{ color = vec4(0.0, 0.0, 1.0, 1.0); }";

    GLuint vShader = glCreateShader(GL_VERTEX_SHADER); // 创建类型 GL_VERTEX_SHADER 的着色器,返回引用它的序号
    GLuint fShader = glCreateShader(GL_FRAGMENT_SHADER); // 创建类型 GL_FRAGMENT_SHADER 的着色器,返回引用它的序号

    glShaderSource(vShader, 1, &vshaderSource, NULL); // 将GLSL代码从字符串载入空着色器对象中 
    glShaderSource(fShader, 1, &fshaderSource, NULL);
    glCompileShader(vShader); // 编译各着色器
    glCompileShader(fShader);

    GLuint vfProgram = glCreateProgram(); // 创建程序对象,并储存指向它的整数ID
    glAttachShader(vfProgram, vShader); // 将着色器加入程序对象
    glAttachShader(vfProgram, fShader);
    glLinkProgram(vfProgram); // 让GLSL编译器确保它们的兼容性

    return vfProgram;
}

void init(GLFWwindow* window){
    renderingProgram = createShaderProgram();
    glGenVertexArrays(numVAOs, vao);
    glBindVertexArray(vao[0]);
}

void display(GLFWwindow* window, double currentTime)
{
    glUseProgram(renderingProgram); // 将含有两个已编译着色器的程序载入OpenGL管线阶段(在GPU上),没有运行着色器,只是将着色器加载进硬件
    glDrawArrays(GL_POINTS, 0, 1); // 启动管线处理过程
}
(main函数与之前同)

字符串 vshaderSource 是顶点着色器中硬编码了一个顶点。顶点着色器的主要目标是将顶点发送给管线。内置变量  gl_Position 用来设置顶点在3D空间的坐标位置,并发送至下一个管线阶段。GLSL数据类型 vec4 用来存储4元组。

顶点接下来将沿着管线移动到光栅着色器,它们在这里被转换成像素位置。最终这些像素到达片段着色器 fshaderSource 。片段着色器的目的是给将要展示的像素赋予RGB颜色。本例中是蓝色。"out" 标签表明 color 变量是输出变量。在顶点着色器中 gl_Position 是预定义的输出变量,所以并不是必须给它指定 "out" 标签。

当准备将数据集发送给管线时是以缓冲区形式发送的,这些缓冲区最后都会被存入顶点数组对象(Vertex Array Object, VAO)中,即使应用程序没有用到任何缓冲区,OpenGL仍然需要在使用着色器的时候至少有一个创建好的 VAO,所以 init() 后两行用来创建OpenGL要求的 VAO。

glShaderSource()有4个参数:

1、着色器对象;2、着色器源代码中的字符串数量;3、包含源代码的字符串指针;4、指定一个长度数组,其中包括给定着色器程序中每行代码的字符串的整数长度。如果设为NULL,OpenGL将会自动从以 NULL 结尾的字符串中构建这个数组。

glShaderSource(GLuint shader, GLsizei count, const GLchar *const* string, const GLint* length);

结果如下:

 在display()中加入下面代码,放在 glDrawArrays() 前面

glPointSize(30.0f);

当光栅化阶段从顶点着色器收到顶点时,它会为一个大小是30像素的点设置像素颜色值。

结果如下:

猜你喜欢

转载自blog.csdn.net/ttod/article/details/135343075