openGL可编程笔记三——将Shader,VertexBuffer封装

本文介绍了一个OpenGL地形绘制的封装方案,包括Shader初始化、图形位置指定、MVP矩阵设置及VertexBuffer操作等内容,通过实例展示了如何使用这些封装来简化复杂的地形绘制过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

如果每次都绘制不同的图形,我们就需要每次都写重复的代码。所以这里封装了一下


对于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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值