OpenGL(二十四) VAO、VBO和着色器使用示例


1. 新建一个工程,新建一个头文件Shader.h,内容如下:

#ifndef _SHADER_H_  
#define _SHADER_H_

#include <vector>
#include <string>
#include <cstring>
#include <GL/glew.h>

class Shader
{
public:
	static GLuint createShader(GLenum eShaderType, const std::string &strShaderFile);
	static GLuint createShader(GLenum eShaderType, const char* fileName);
	static GLuint createProgram(const std::vector<GLuint> &shaderList);
};

#endif


2. 相应的新建一个源文件Shader.h,内容如下:

#include <fstream>  
#include <sstream>
#include "shader.h"

//从字符串流构造着色器对象  
GLuint Shader::createShader(GLenum eShaderType, const std::string &strShaderFile)
{
	GLuint shader = glCreateShader(eShaderType);//根据类型创建shader  
	const char * strFileData = strShaderFile.c_str();
	glShaderSource(shader, 1, &strFileData, NULL);//绑定shader字符串  
	glCompileShader(shader);//编译shader  
	//检查shader状态  
	GLint status;
	glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
	if (status == GL_FALSE)
	{
		GLint infoLogLength;
		glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
		GLchar *strInfoLog = new GLchar[infoLogLength + 1];
		glGetShaderInfoLog(shader, infoLogLength, NULL, strInfoLog);
		const char * strShaderType = NULL;
		switch (eShaderType)
		{
		case GL_VERTEX_SHADER: strShaderType = "vertex"; break;
		case GL_GEOMETRY_SHADER: strShaderType = "geometry"; break;
		case GL_FRAGMENT_SHADER: strShaderType = "fragment"; break;
		}
		fprintf(stderr, "Compile failure in %s shader:
%s
", strShaderType, strInfoLog);
		delete[] strInfoLog;
	}
	return shader;
}

//从文件构造着色器对象  
GLuint Shader::createShader(GLenum eShaderType, const char* fileName)
{
	std::ifstream infile(fileName);
	if (!infile)
	{
		fprintf(stderr, "Could not open file : %s for reading.", fileName);
		return 0;
	}
	std::stringstream  buffer;
	buffer << infile.rdbuf();
	infile.close();
	return Shader::createShader(eShaderType, buffer.str());
}

//构造着色器程序对象  
GLuint Shader::createProgram(const std::vector<GLuint> &shaderList)
{
	GLuint programId = glCreateProgram();//创建program  
	for (std::vector<GLuint>::size_type iLoop = 0; iLoop < shaderList.size(); iLoop++)
		glAttachShader(programId, shaderList[iLoop]);//绑定shader  

	glLinkProgram(programId);//链接shader  
 //检查program状态  
	GLint status;
	glGetProgramiv(programId, GL_LINK_STATUS, &status);
	if (status == GL_FALSE)
	{
		GLint infoLogLength;
		glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &infoLogLength);

		GLchar *strInfoLog = new GLchar[infoLogLength + 1];
		glGetProgramInfoLog(programId, infoLogLength, NULL, strInfoLog);
		fprintf(stderr, "Linker failure: %s
", strInfoLog);
		delete[] strInfoLog;
	}
	for (size_t iLoop = 0; iLoop < shaderList.size(); iLoop++)
		glDetachShader(programId, shaderList[iLoop]);
	return programId;
}



3. Shader.h和Shader.cpp文件主要作用是构建了一个着色器,以下是主要的工程实现代码,新建一个源文件VaoVboTest.cpp,内容如下:

//使用VAO VBO和着色器绘制三角形(现代OpenGL方式)  
#include <string>
#include <vector>
#include <GL/glew.h>
#include <GL/freeglut.h>
#include "Shader.h"

using namespace std;

void userInit();
void reshape(int w, int h);
void display(void);
void keyboardAction(unsigned char key, int x, int y);

GLuint vboId;//vertex buffer object句柄  
GLuint vaoId;//vertext array object句柄  
GLuint programId;//shader program 句柄  

int main(int argc, char **argv)
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
	glutInitWindowPosition(100, 100);
	glutInitWindowSize(512, 512);
	glutCreateWindow("Triangle demo");

	glewInit();
	userInit();
	glutReshapeFunc(reshape);
	glutDisplayFunc(display);
	glutKeyboardFunc(keyboardAction);
	glutMainLoop();
	return 0;
}

//自定义初始化函数  
void userInit()
{
	glClearColor(0.0, 0.0, 0.0, 0.0);
	//创建顶点数据  
	const GLfloat vertices[] = {
-0.5f,-0.5f,0.0f,1.0f,
	   0.5f,0.0f,0.0f,1.0f,
	   0.0f,0.5f,0.0f,1.0f,
	};

	//创建vertex array object对象  
	glGenVertexArrays(1, &vaoId);
	glBindVertexArray(vaoId);

	//创建vertex buffer object对象  
	glGenBuffers(1, &vboId);
	glBindBuffer(GL_ARRAY_BUFFER, vboId);
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
	glBindBuffer(GL_ARRAY_BUFFER, 0);

	//创建着色器  
	const std::string vertexStr(
		"#version 450
"
		"layout(location=0) in vec4 position;
"
		"void main()
"
		"{gl_Position = position;}
"
	);

	const std::string fragmentStr(
		"#version 450
"
		"out vec4 outputColor;
"
		"void main()
"
		"{outputColor = vec4(1.0f,1.0f,0.0f,1.0f);}
"
	);

	std::vector<GLuint> idVector;
	idVector.push_back(Shader::createShader(GL_VERTEX_SHADER, vertexStr));
	idVector.push_back(Shader::createShader(GL_FRAGMENT_SHADER, fragmentStr));
	programId = Shader::createProgram(idVector);
}

//调整窗口大小回调函数  
void reshape(int w, int h)
{
	glViewport(0, 0, (GLsizei)w, (GLsizei)h);
}

//绘制回调函数  
void display(void)
{
	glClear(GL_COLOR_BUFFER_BIT);
	glUseProgram(programId);
	glBindBuffer(GL_ARRAY_BUFFER, vboId);
	glEnableVertexAttribArray(0);
	glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
	glDrawArrays(GL_TRIANGLES, 0, 3);
	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glUseProgram(0);
	glDisableVertexAttribArray(0);
	glutSwapBuffers();
}

//键盘按键回调函数  
void keyboardAction(unsigned char key, int x, int y)
{
	switch (key)
	{
	case 033:  // Escape key  
		exit(EXIT_SUCCESS);
		break;
	}
}


不要忘了在链接器->输入->附加依赖项里添加 “glew32.lib”。完成之后编译生成效果:



原文地址:https://www.cnblogs.com/mtcnn/p/9411900.html