重新整理了一下,还好没把网课学的还给老师。。
个人理解大体分为这六部分
一: shader准备部分(读取,编译shader)
二:创建程序program并且绑定链接shader
三:shader已经绑定,链接好,则销毁shader在当前程序中的文件
四:告知GPU,哪一个插槽中,绑定的是什么变量
五:绘图: 在第四部的基础上,将数据传入GPU中对应的插槽位置
六:初始化,为下次做准备。
再具体些:
第一部分:
1.读取文件到vsShader,fsShader
//LoadFileContent需要自己实现
unsigned char *vsShaderCode = LoadFileContent("Res/test.vs", fileSize);
unsigned char *fsShaderCode = LoadFileContent("Res/test.fs",fileSize);
2.编译shader自身
这个部分也可以自己手动实现,详情看下面代码
GLuint vsShader = CompileShader(GL_VERTEX_SHADER, (char*)vsShaderCode);
GLuint fsShader = CompileShader(GL_FRAGMENT_SHADER, (char*)fsShaderCode);
第二部分:
1.将shader绑定到程序上
glAttachShader(program, vsShader);
glAttachShader(program, fsShader);
2.将shader链接Link
glLinkProgram(program);
第三部分:
1.删除读入的文本文件(char数组)
delete vsShaderCode;
delete fsShaderCode;
2.解绑定shader
glDetachShader(program, vsShader);
glDetachShader(program, fsShader);
3.删除shader
glDeleteShader(vsShader);
glDeleteShader(fsShader);
第四部分:
1.绑定到vbo,buffer数组中
glGenBuffers(1, &vbo);
2.因为openGL是状态机的概念,设置当前操作对象 ,即buffer数组vbo
glBindBuffer(GL_ARRAY_BUFFER, vbo);
//把vbo设置成当前操作对象
//原型:void glBindBuffer(GLenum target,GLuint buffer);
//指定当前激活的缓存对象,
完成三项工作:
//1. 指定第一次绑定的buffer, 创建一个与该名称对应的新缓存对象
//2.如果绑定到一个已经创建的缓存对象,那么它将成为当前激活的缓存对象
//3.若果绑定buffer==0,那么将不对target应用任何缓存对象
3.设置ebo状态,告知如何绘制三角形
//ebo状态设置
unsigned short indexes[] = { 0,1,2 };//表示绘制点的时候,从0,1,2顺序绘制
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned short) * 3, indexes, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
4.告知GPU,对应数据在插槽中的位置
positionLocation = glGetAttribLocation(program, "position");
colorLocation = glGetAttribLocation(program, "color");
第五部分: 绘图
1.绑定数据,并且启用插槽
modelMatrixLocation = glGetUniformLocation(program, "ModelMatrix");
viewMatrixLocation = glGetUniformLocation(program, "ViewMatrix");
projectionMatrixLocation = glGetUniformLocation(program, "ProjectionMatrix");
modelMatrix = glm::translate(0.0f, 0.0f, -0.6f);
glUseProgram(program);
//位置 ,个数,是否转置,
glUniformMatrix4fv(modelMatrixLocation,1, GL_FALSE, glm::value_ptr(modelMatrix));
glUniformMatrix4fv(viewMatrixLocation, 1, GL_FALSE, glm::value_ptr(viewMatrix));
glUniformMatrix4fv(projectionMatrixLocation, 1, GL_FALSE, glm::value_ptr(projectionMatrix));
//启用position插槽
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glEnableVertexAttribArray(positionLocation);
glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, sizeof(float)*8,0);
//插槽位置,数据分量个数,类型,是否归一化(颜色rgba会对应到0.0~1.0), 两个点的字节距离
//启用color插槽
glEnableVertexAttribArray(colorLocation);
glVertexAttribPointer(colorLocation, 4, GL_FLOAT, GL_FALSE, sizeof(float)*8, (void*)(sizeof (float)*4) );//第一个color与第二个colo数据间隔
2.绘制方式 ebo
//若无ebo可以依此绘制 glDrawArrays(GL_TRIANGLES, 0, 3);
//从第0个点开始 绘制三个点
//有了ebo可以指定绘制顺序
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glDrawElements( GL_TRIANGLES,3,GL_UNSIGNED_SHORT,0);
//第一个参数 三角形, 第二个参数 多少个索引数据绘图 第三个参数类型, 第四个参数,起始数据
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
第六部分: 初始化
//六.初始化为下次做准备
glBindBuffer(GL_ARRAY_BUFFER, 0);
glUseProgram(0);
// void glUseProgram(GLuint program);
// 如果参数为0,则表示所有当前使用的着色器都会被清除
这样一个简单的完整shader就实现了。
之前曾经将 第四部分中告知GPU , 某些插槽指定了那些数据,放在了每一次调用draw函数中,发现内存猛长,这个问题要注意。
下面附上所有代码
以及glew.h等封装好的库
https://github.com/ycb577114589/Shader_openGL/tree/master/Triangle