如果每次都绘制不同的图形,我们就需要每次都写重复的代码。所以这里封装了一下
对于Shader而言:
第一部分:
shader初始化: 解码vs, fs,并且链接为程序,并且指定shader代码部分中,GPU插槽位置
void Shader::Init(const char *vs, const char *fs) {
int nFileSize = 0;
const char* vsCode = (char*)LoadFileContent(vs, nFileSize);
const char* fsCode = (char*)LoadFileContent(fs, nFileSize);
GLuint vsShader = CompileShader(GL_VERTEX_SHADER, vsCode);
if (vsShader == 0) return;
GLuint fsShader = CompileShader(GL_FRAGMENT_SHADER, fsCode);
if (fsShader == 0) return;
mProgram = CreateProgram(vsShader, fsShader);
glDeleteShader(vsShader);
glDeleteShader(fsShader);
if (mProgram != 0) {
mModelMatrixLocation = glGetUniformLocation(mProgram, "ModelMatrix");
mViewMatrixLocation = glGetUniformLocation(mProgram, "ViewMatrix");
mProjectionMatrixLocation = glGetUniformLocation(mProgram, "ProjectionMatrix");
mColorLocation = glGetAttribLocation(mProgram, "color");
mPositionLocation = glGetAttribLocation(mProgram, "position");
mTexcoordLocation = glGetAttribLocation(mProgram, "texcoord");
mNormalLocation = glGetAttribLocation(mProgram, "normal");
}
}
第二部分:
在绘图之前需要指定图形绘制位置,MVP矩阵,以及绑定数据
void Shader::Bind(float *M, float *V, float *P) {
glUseProgram(mProgram);
glUniformMatrix4fv(mModelMatrixLocation, 1, GL_FALSE, M);
glUniformMatrix4fv(mViewMatrixLocation, 1, GL_FALSE, V);
glUniformMatrix4fv(mProjectionMatrixLocation, 1, GL_FALSE, P);
glEnableVertexAttribArray(mPositionLocation);
glVertexAttribPointer(mPositionLocation, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
glEnableVertexAttribArray(mColorLocation);
glVertexAttribPointer(mColorLocation, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(sizeof(float) * 4));
glEnableVertexAttribArray(mTexcoordLocation);
glVertexAttribPointer(mTexcoordLocation, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(sizeof(float) * 8));
glEnableVertexAttribArray(mNormalLocation);
glVertexAttribPointer(mNormalLocation, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(sizeof(float) * 12));
}
对于VertexBuffer部分:
无非只是:初始化+设置数据+ 绘图时期指定vbo对象绘图的过程
1.初始化:
void VertexBuffer::SetSize(int vertexCount) {
mVertexCount = vertexCount;
mVertexes = new Vertex[mVertexCount];
memset(mVertexes, 0, sizeof(mVertexes));
mVBO = CreateBufferObject(GL_ARRAY_BUFFER,sizeof(Vertex) *mVertexCount, GL_STATIC_DRAW, nullptr);
}
GLuint CreateBufferObject(GLenum bufferType, GLsizeiptr size, GLenum usage, void *data) {
GLuint object;
glGenBuffers(1, &object);
glBindBuffer(bufferType, object);
glBufferData(bufferType, size, data, usage);
glBindBuffer(bufferType, 0);
return object;
}
初始化数组,并且将vbo对象,绑定数据。
2.设置数据
void VertexBuffer::SetPosition(int index, float x, float y, float z,float w) {
mVertexes[index].Position[0] = x;
mVertexes[index].Position[1] = y;
mVertexes[index].Position[2] = z;
mVertexes[index].Position[3] = w;
}
void VertexBuffer::SetColor(int index, float r, float g, float b, float a ) {
mVertexes[index].Color[0] = r;
mVertexes[index].Color[1] = g;
mVertexes[index].Color[2] = b;
mVertexes[index].Color[3] = a;
}
void VertexBuffer::SetTexcoord(int index,float x, float y) {
mVertexes[index].Texcoord[0] = x;
mVertexes[index].Texcoord[1] = y;
}
void VertexBuffer::SetNormal(int index, float x, float y, float z) {
mVertexes[index].Normal[0] = x;
mVertexes[index].Normal[1] = y;
mVertexes[index].Normal[2] = z;
mVertexes[index].Normal[3] = 1.0;
}
注意这两部分不要在draw的函数部分,否则内存爆炸
3.绘图部分的绑定vbo以及解绑定初始化
void VertexBuffer::Bind() {
glBindBuffer(GL_ARRAY_BUFFER, mVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex)*mVertexCount, mVertexes,GL_STATIC_DRAW);
// glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vertex)*mVertexCount, mVertexes);
}
void VertexBuffer::Unbind() {
glBindBuffer(mVBO, 0);
}
Vertex& VertexBuffer::Get(int index) {
return mVertexes[index];
}
这里以绘制一个地形为例。
#include "Ground.h"
void Ground::init() {
mVertexBuffer = new VertexBuffer;
mVertexBuffer->SetSize(1600);
for (int z = 0; z < 20; ++z) {
float zStart = 100.0f - z*10.0f;
for (int x = 0; x < 20; ++x) {
int offset = (x + z * 20) * 4;
float xStart = x*10.0f - 100.0f;
mVertexBuffer->SetPosition(offset, xStart, -1.0f, zStart);
mVertexBuffer->SetPosition(offset + 1, xStart + 10.0f, -1.0f, zStart);
mVertexBuffer->SetPosition(offset + 2, xStart, -1.0f, zStart - 10.0f);
mVertexBuffer->SetPosition(offset + 3, xStart + 10.0f, -1.0f, zStart - 10.0f);
mVertexBuffer->SetNormal(offset, 0.0f, 1.0f, 0.0f);
mVertexBuffer->SetNormal(offset + 1, 0.0f, 1.0f, 0.0f);
mVertexBuffer->SetNormal(offset + 2, 0.0f, 1.0f, 0.0f);
if ((z & 1) ^ (x & 1)) {
mVertexBuffer->SetColor(offset, 0.1f, 0.1f, 0.1f);
mVertexBuffer->SetColor(offset+1, 0.1f, 0.1f, 0.1f);
mVertexBuffer->SetColor(offset+2, 0.1f, 0.1f, 0.1f);
mVertexBuffer->SetColor(offset+3, 0.1f, 0.1f, 0.1f);
}
else {
mVertexBuffer->SetColor(offset, 0.3f, 0.8f, 0.8f);
mVertexBuffer->SetColor(offset+1, 0.8f, 0.2f, 0.8f);
mVertexBuffer->SetColor(offset+2, 0.8f, 0.8f, 0.7f);
mVertexBuffer->SetColor(offset+3, 0.6f, 0.8f, 0.8f);
}
}
}
mShader = new Shader;
mShader->Init("Res/ground.vs", "Res/ground.fs");
}
void Ground::Draw(glm::mat4&viewMatrix, glm::mat4 &projectionMatirx) {
glEnable(GL_DEPTH_TEST);
mVertexBuffer->Bind();
mShader->Bind(glm::value_ptr(mModelMatrix), glm::value_ptr(viewMatrix), glm::value_ptr(projectionMatirx));
for(int i=0;i<400;i++){
glDrawArrays(GL_TRIANGLE_STRIP, i * 4, 4);
}
mVertexBuffer->Unbind();
}
全部代码:
https://github.com/ycb577114589/Shader_openGL/tree/master/Ground