着色器: triangles.vert
#version 430 corelayout(location = 0) in vec4 vPosition;void main(){ gl_Position = vPosition;}其中 1.在程序起始的位置使用#version来声明所使用的版本,这里430表示使用OpenGL4.3对应的GLSL语言,core表示使用OpenGL核心模式。 2.vec4是GLSL的四维浮点数向量,vec4的默认值为(0,0,0,1) 3.in字段指定了数据进入着色器的流向 4.layout(location = 0)是布局限定符,目的是为变量提供元数据。
triangles.frag
#version 430 coreout vec4 fColorvoid main(){ fColor = vec4(0.0,0.0,1.0,1.0);}其中 1.指定out限定符,进fColor对应的数值输出。
实现程序:
#include "stdafx.h"#include<iostream>using namespace std;#include "vgl.h"#include "LoadShaders.h"enum VAO_IDs{ Triangles, NumVAOs };enum Buffer_IDs{ ArrayBuffer, NumBuffers };enum Attrib_IDs{ vPosition = 0 };GLuint VAOs[NumVAOs];GLuint Buffers[NumBuffers];const GLuint NumVertices = 6;void init(void){ //void glGenVertexArrays(GLsizei n,GLuint *arrays); //返回n个未使用的对象名到数组arrays中,用作顶点数组对象。返回的名字可以用来分配更多的缓存对象, //并且他们已经使用未初始化的顶点数组集合的默认状态进行了数值的初始化。 glGenVertexArrays(NumVAOs, VAOs); //void glBindVertexArray(GLuint array) //如果输入的变量array非0,并且是glGenVertexArrays()所返回的,那么它将创建一个新的顶点数组对象并且与其名称 //关联起来。如果绑定到一个已经创建的顶点数组对象中,那么会激活这个顶点数组对象,并且直接影响对象中所保存 //的顶点数组状态。如果输入的变量array为0,那么OpenGL将不再使用程序所分配的任何顶点数组对象,并且将渲染状 //态重设为顶点数组的默认状态。如果array不是glGenVertexArrays()所返回的数值,或者它已经被glDeleteVertexArrays() //函数释放了,那么这里将产生一个GL_INVALID_OperaTION错误。 glBindVertexArray(VAOs[Triangles]); GLfloat vertices[NumVertices][2] = { { -0.90, -0.90 }, { 0.85, -0.90 }, { -0.90, 0.85 }, { 0.90, -0.85 }, { 0.90, 0.90 }, { -0.85, 0.90 } }; //void glGenBuffers(GLsizei n,GLuint *buffers) //返回n个当前未使用的缓存对象名称,并保存到buffers数组中。返回到buffers中的名称不一定 //是连续的整形数据。这里返回的名称只用于分配其他缓存对象,他们在绑定之后只会记录一个可用 //的状态。0是一个保留的缓存对象名称,glGenBuffers()永远都不会返回这个值的缓存对象。 glGenBuffers(NumBuffers, Buffers); //void glBindBuffer(GLenum target,GLuint buffer) //指定当前激活的缓存对象。target必须设置为以下类型中的一个:GL_ARRAY_BUFFER,GL_ELEMENT_ARRAY_BUFFER //GL_PIXEL_PACK_BUFFER,GL_PIXEL_UNPACK_BUFFER,GL_COPY_READ_BUFFER,GL_COPY_WRITE_BUFFER,GL_TRANSFORM_FEEDBACK_BUFFER //和GL_UNIFORM_BUFFER.buffer设置的是要绑定的缓存对象名称。 //如果是第一次绑定buffer,且它是一个非零的无符号整形,那么将创建一个与该名称相对应的新缓存对象。如果绑定到一个已经创建的缓存对象 //那么它将成为当前被激活的缓存对象。如果绑定的buffer值为0,那么OpenGL将不再对当前target应用任何缓存对象。 glBindBuffer(GL_ARRAY_BUFFER, Buffers[ArrayBuffer]); //void glBufferData(GLenum target,GLsizeiptr size,const GLvoid *data,GLenum usage) //在OpenGL服务端内存中分配size个存储单位(通常为byte),用于存储数据或者索引。如果当前绑定的对象已经存在了关联的数据,那么会首先删除这些数据。 //对于顶点属性数据,target设置为GL_ARRAY_BUFFER,索引数据为GL_ELEMENT_ARRAY_BUFFER;OpenGL的像素数据为GL_PIXEL_UNPACK_BUFFER;对于从OpenGL中获取 //的像素数据为GL_PIXEL_PACK_BUFFER,对于缓存之间的复制数据为GL_COPY_READ_BUFFER和GL_COPY_WRITE_BUFFER;对于纹理缓存中存储的纹理数据为GL_TEXTURE_BUFFER //对于通过transform feedback着色器获得的结果设置为GL_TRANSFORM_FEEDBACK_BUFFER;而一致变量要设置为GL_UNIFORM_BUFFER.size表示存储数据的总数量。这个数值 //等于data中存储的元素的总数乘以单位元素存储空间的结果。data要么是一个客户端内存的指针,以便初始化缓存对象,要么是NULL.如果传入的指针合法,那么将会有 //size大小的数据从客户端拷贝到服务端。如果传入NULL,那么将保留size大小的初始化数据,以备后用。usage用于设置分配数据之后的读取和写入方式。可用的方式包括 //GL_STREAM_DRAW,GL_STREAM_READ,GL_STREAM_COPY,GL_STATIC_DRAW,GL_STATIC_READ,GL_STATIC_COPY,GL_DYNAMIC_DRAW,GL_DYNAMIC_READ和GL_DYNAMIC_COPY.如果所需 //的size大小超过了服务端能够分配的额度,那么glBufferData()将产生一个GL_OUT_OF_MEMORY错误。如果usage设置的不是可用的模式值,那么将产生GL_INVALID_VALUE错误。 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); ShaderInfo shaders[] = { { GL_VERTEX_SHADER, "triangles.vert" }, { GL_FRAGMENT_SHADER, "triangles.frag" }, { GL_NONE, NULL } }; GLuint PRogram = LoadShaders(shaders); //void glUseProgram(GLuint program) //使用链接过的着色器程序program.如果program为0,那么所有当前使用的着色器都会被清除。如果没有绑定任何着色器,那么OpenGL的操作结果是未定义的,但是不会产生错误。 //如果已经启用了一个程序,而它需要关联新的着色器对象,或者解除之前关联的对象,那么我们需要重新对它进行链接。如果链接过程成功,那么新的程序会直接替代之前启用 //的程序。如果链接失败,那么当前绑定的着色器程序依然是可用的,不会被替代,知道我们成功地重新链接或者使用glUseProgram()指定了新的程序为止。 glUseProgram(program); //void glVertexAttribPointer(GLuint index,GLint size,GLenum type,GLboolean normalized,GLsizei stride,const GLvoid*pinter) //设置index(着色器中的属性位置,即layout(location = 0) in vec4 vPosition;中的0)位置对应的数据值。pointer表示缓存对象中,从其实位置开始计算的数组数据的偏移值 //(假设起始地址为0),使用基本的系统单位(byte).size表示每个顶点需要更新的分量数目,可以是1,2,3,4或者GL_BGRA。type指定了数组中每个元素的数据类型(GL_BYTE, //GL_UNSIGNED_BYTE,GL_SHORT,GL_UNSIGNED_SHORT,GL_INT,GL_UNSIGNED_INT,GL_FIXED,GL_HALF_FLOAT,GL_FLOAT或GL_DOUBLE)。normalized设置顶点数据在存储前是否需要归一化 //(或者使用glVertexAttribFourN*()函数)。stride是数组中每2个元素之间的大小偏移值(byte).如果stride为0,那么数据应该紧密地封装在一起。 glVertexAttribPointer(vPosition, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0)); //void glEnableVertexAttribArray(GLuint index) //设置是否启用与index索引相关联的顶点数组。index必须是一个介于0到GL_MAX_VERTEX_ATTRIBS-1之间的值。 glEnableVertexAttribArray(vPosition);}void display(void){ //void glClear(GLbitfield mask) //清除指定的缓存数据并重设为当前的清除值。mask是一个可以通过逻辑“或”操作来指定多个数值的参数。可用的数值:颜色缓存:GL_COLOR_BUFFER_BIT //深度缓存GL_DEPTH_BUFFER_BIT,模板缓存:GL_STENCIL_BUFFER_BIT. glClear(GL_COLOR_BUFFER_BIT); glBindVertexArray(VAOs[Triangles]); //void glDrawArrays(GLenum mode,GLint first, GLsizei count) //使用数组元素建立连续的几何图元序列,每个启用的数组中起始位置为first,结束位置为first+count-1.mode表示构建图元的类型,它必须是GL_TRIANGLES, //GL_LINE_LOOP,GL_LINES,GL_POINTS等类型标识符之一。 glDrawArrays(GL_TRIANGLES, 0, NumVertices); //glFlush() //强制之前的OpenGL命令立即执行,这样可以保证他们在一定时间内全部完成。 glFlush();}int main(int argc, char** argv){ //负责初始化GLUT库. //它会处理向程序输入的命令行参数,并且移除其中与控制GLUT如何操作相关的部分(例如设置窗口的大小) //glutInit必须是应用程序调用的第一个GLUT函数,它会负责设置其他GLUT例程所必须的数据结构。 glutInit(&argc, argv); //设置程序所使用的窗口类型。其中GLUT_RGBA表示RGBA颜色空间。 glutInitDisplayMode(GLUT_RGBA); //设置所需的窗口大小。 glutInitWindowSize(512, 512); //设置使用OpenGL4.3版本 glutInitContextVersion(4, 3); //设置使用OpenGL核心模式。 glutInitContextProfile(GLUT_CORE_PROFILE); //创建窗口 glutCreateWindow(argv[0]); //不加这句glGenVertexArrays奔溃 glewExperimental = GL_TRUE; if (glewInit()) { cerr << "Unable to initialize GLEW .. exiting" << endl; exit(EXIT_FAILURE); } init(); //设置显示回调,即GLUT在每次更新窗口内容的时候会自动调用的例程。 glutDisplayFunc(display); //这是一个无限执行的循环,它会负责一直处理窗口和操作系统的用户输入等操作。 //例如它会判断窗口是否需要重绘,然后它就会自动调用glutDisplayFunc()中注册的函数。 //glutMainLoop是一个无限循环,因此不会执行在它之后的所有命令。 glutMainLoop();}新闻热点
疑难解答