OpenGL VAO+VBO+EBO+GLSL练习

OpenGL VAO+VBO+EBO+GLSL练习

一、VAO,VBO,EBO之间的关系

废话不多说,直接上图
在这里插入图片描述
也就是说:

  • 每个个VAO管理着数个VBO,同时可以拥有一个EBO(EBO,索引数据,可以没有,此时直接用顶点数据绘制)

  • 每个VBO用来存放数组数据,这个数据可以由你自己定义顺序

在绑定了VAO之后,后面绑定的VBO和EBO归属到这个VAO中

	// 创建VAO对象
	glGenVertexArrays(1, &_array);
	glBindVertexArray(_array);

	// 绑定顶点缓冲对象
	glGenBuffers(1, &_vertex);
	glBindBuffer(GL_ARRAY_BUFFER, _vertex);
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertex), vertex, GL_STATIC_DRAW);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(0);

	// 绑定颜色缓冲对象
	glGenBuffers(1, &_color);
	glBindBuffer(GL_ARRAY_BUFFER, _color);
	glBufferData(GL_ARRAY_BUFFER, sizeof(color), color, GL_STATIC_DRAW);
	glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(1);

	// 绑定法线缓冲对象
	glGenBuffers(1, &_normal);
	glBindBuffer(GL_ARRAY_BUFFER, _normal);
	glBufferData(GL_ARRAY_BUFFER, sizeof(normal), normal, GL_STATIC_DRAW);
	glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(2);

	// 绑定索引缓冲对象
	glGenBuffers(1, &_index);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _index);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(index), index, GL_STATIC_DRAW);

	// 解除绑定
	glBindVertexArray(0);
	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

你可以用
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0);
来指定VBO中数据的安排方式
同时用glEnableVertexAttribArray(2);
来告诉glsl传入数据的位置

例如对上面的VAO,顶点着色器这样写:

#version 440

uniform mat4 _model_view;
uniform mat4 _projection;

uniform vec4 _light0_position;

layout (location = 0) in vec3 v;
layout (location = 1) in vec4 c;
layout (location = 2) in vec3 n;

struct v2f{
	vec4 c;

};

out v2f vert_out;

void main(){
	vert_out.c = c;
	gl_Position = _projection * _model_view * vec4(v,1);
}

通过 layout (location = 1) in vec4 c; 来取得VAO中的glEnableVertexAttribArray(1);的数据

二、代码

先放效果图:
在这里插入图片描述
geomtery

class geomtery {
public:
	geomtery();
	~geomtery();
	geomtery(vec3 center, GLfloat w, GLfloat h,vec4 c);
	void draw(void);
private:
	GLuint _array;
	GLuint _vertex;
	GLuint _color;
	GLuint _normal;
	GLuint _index;
};

geomtery::geomtery(vec3 c, GLfloat w, GLfloat h,vec4 cl) {

	GLfloat half_w = w / 2.0f, half_h = h / 2.0;
	GLfloat vertex[12];
	vertex[0] = c.x - half_w;	vertex[1] = c.y + half_h; vertex[2] = c.z;
	vertex[3] = c.x - half_w;	vertex[4] = c.y - half_h; vertex[5] = c.z;
	vertex[6] = c.x + half_w;	vertex[7] = c.y - half_h; vertex[8] = c.z;
	vertex[9] = c.x + half_w;	vertex[10] = c.y + half_h; vertex[11] = c.z;

	GLfloat color[4];
	color[0] = cl.x; color[1] = cl.y; color[2] = cl.z; color[3] = cl.w;

	vec3 v1, v2, n;
	v1 = vec3(vertex[6], vertex[7], vertex[8]) - vec3(vertex[0], vertex[1], vertex[2]);
	v2 = vec3(vertex[9], vertex[10], vertex[11]) - vec3(vertex[3], vertex[4], vertex[5]);
	n =  cross(v1, v2);
	n = normalize(n);
	GLfloat normal[3];
	normal[0] = n.x; normal[1] = n.y; normal[2] = n.z;

	GLuint index[6];
	index[0] = 0; index[1] = 1; index[2] = 2; index[3] = 0; index[4] = 2; index[5] = 3;

	// 创建VAO对象
	glGenVertexArrays(1, &_array);
	glBindVertexArray(_array);

	// 绑定顶点缓冲对象
	glGenBuffers(1, &_vertex);
	glBindBuffer(GL_ARRAY_BUFFER, _vertex);
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertex), vertex, GL_STATIC_DRAW);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(0);

	// 绑定颜色缓冲对象
	glGenBuffers(1, &_color);
	glBindBuffer(GL_ARRAY_BUFFER, _color);
	glBufferData(GL_ARRAY_BUFFER, sizeof(color), color, GL_STATIC_DRAW);
	glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(1);

	// 绑定法线缓冲对象
	glGenBuffers(1, &_normal);
	glBindBuffer(GL_ARRAY_BUFFER, _normal);
	glBufferData(GL_ARRAY_BUFFER, sizeof(normal), normal, GL_STATIC_DRAW);
	glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(2);

	// 绑定索引缓冲对象
	glGenBuffers(1, &_index);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _index);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(index), index, GL_STATIC_DRAW);

	// 解除绑定
	glBindVertexArray(0);
	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

}

void geomtery::draw(void) {

	glBindVertexArray(_array);
	glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, NULL);
	glBindVertexArray(0);
}

main


#include <iostream>
#include <fstream>

#include <GL/glew.h>

#ifdef _WIN32
#define FREEGLUT_STATIC
#include <GL/glut.h>
#endif

#include <sstream>
#include <cmath>
#include "common.h"
#include "geomtery.h"

using namespace std;

#include <vector>

GLuint shader_vert;
GLuint shader_geom;
GLuint shader_frag;

GLuint shader_program;

geomtery * g = nullptr;

GLfloat proj[16];
GLfloat mv[16];

GLuint g_WorldMatrixUniformIndex;
GLuint g_ProjMatrixUniformIndex;

GLfloat light_0_position[4];
GLfloat light_0_ambient[4];
GLfloat light_0_diffuse[4];
GLfloat light_0_specular[4];
GLuint g_LightSource_0_position_Index;
GLuint g_LightSource_0_ambient_Index;
GLuint g_LightSource_0_diffuse_Index;
GLuint g_LightSource_0_specular_Index;



long load_shader(void) {

	GLuint *vert = &shader_vert;
	GLuint *frag = &shader_frag;
	GLuint *program = &shader_program;

	*vert = glCreateShader(GL_VERTEX_SHADER);
	*frag = glCreateShader(GL_FRAGMENT_SHADER);


	fstream in("_vertex.vert");
	if (!in.is_open()) {
		return -1;
	}

	ostringstream buff;
	buff << in.rdbuf();
	string t = std::move(buff.str());
	const GLchar * pbuff =t.c_str();

	glShaderSource(*vert, 1,&pbuff,NULL);

	in.close();
	in.open("_fragment.frag");
	if (!in.is_open()) {
		return -1;
	}

	ostringstream buff2;
	buff2 << in.rdbuf();
	string t2 = std::move(buff2.str());
	pbuff = t2.c_str();

	glShaderSource(*frag, 1, &pbuff, NULL);

	in.close();


	glCompileShader(*vert);
	glCompileShader(*frag);

	int l;
	int cw;

	char* log;
	glGetShaderiv(*vert, GL_INFO_LOG_LENGTH, &l);
	if (l > 0) {

		log = new char[l];
		glGetShaderInfoLog(*vert, l, &cw, log);

		cout << log << endl;
		delete log;

	}

	glGetShaderiv(*frag, GL_INFO_LOG_LENGTH, &l);
	if (l > 0) {

		log = new char[l];
		glGetShaderInfoLog(*frag, l, &cw, log);

		cout << log << endl;
		delete log;

	}


	*program = glCreateProgram();

	glAttachShader(*program, *vert);
	glAttachShader(*program, *frag);

	glLinkProgram(*program);
	glGetProgramiv(*program, GL_INFO_LOG_LENGTH, &l);
	if (l > 0) {

		log = new char[l];
		glGetProgramInfoLog(*program, l, &cw, log);

		cout << log << endl;
		delete log;

	}
	glUseProgram(*program);


	g_WorldMatrixUniformIndex = glGetUniformLocation(*program, "_model_view");
	g_ProjMatrixUniformIndex = glGetUniformLocation(*program, "_projection");

	glGetFloatv(GL_PROJECTION_MATRIX, proj);
	glGetFloatv(GL_MODELVIEW_MATRIX, mv);

	glUniformMatrix4fv(g_WorldMatrixUniformIndex, 1, GL_FALSE, mv);
	glUniformMatrix4fv(g_ProjMatrixUniformIndex, 1, GL_FALSE, proj);

	g_LightSource_0_position_Index = glGetUniformLocation(*program, "_light0_position");
	glUniform4fv(g_LightSource_0_position_Index, 1, light_0_position);

	g_LightSource_0_ambient_Index = glGetUniformLocation(*program, "_light0_ambient");
	glUniform4fv(g_LightSource_0_ambient_Index, 1, light_0_ambient);

	g_LightSource_0_diffuse_Index = glGetUniformLocation(*program, "_light0_diffuse");
	glUniform4fv(g_LightSource_0_diffuse_Index, 1, light_0_diffuse);

	g_LightSource_0_specular_Index = glGetUniformLocation(*program, "_light0_specular");
	glUniform4fv(g_LightSource_0_specular_Index, 1, light_0_specular);


}

void changed_size(int w, int h) {
	// 修改视窗size
	glViewport(0, 0, w, h);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	gluPerspective(45.0f, double(w) / double(h), 1.0f, 1000.0f);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	
	gluLookAt(0.0f, 0.0f, 3.0f,
		0.0f, 0.0f, 0.0f,
		0.0f, 1.0f, 0.0f);


	glGetFloatv(GL_PROJECTION_MATRIX, proj);
	glGetFloatv(GL_MODELVIEW_MATRIX, mv);

	glUniformMatrix4fv(g_WorldMatrixUniformIndex, 1, GL_FALSE, mv);
	glUniformMatrix4fv(g_ProjMatrixUniformIndex, 1, GL_FALSE, proj);

	return;
}

// 初始化渲染环境
void init_render_context() {

	// 蓝色背景
	glClearColor(0.f, 0.f, .3f, 1.f);
	
	//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

	glEnable(GL_CULL_FACE);

	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);

	make_vec4(light_0_ambient , .3f,.3f,.3f,1.f );
	make_vec4(light_0_diffuse, .7f, .7f, .7f, 1.f);
	make_vec4(light_0_specular, .5f, .5f, .5f, 1.f);

	glLightfv(GL_LIGHT0, GL_AMBIENT, light_0_ambient);
	glLightfv(GL_LIGHT0, GL_DIFFUSE, light_0_diffuse);
	glLightfv(GL_LIGHT0, GL_SPECULAR, light_0_specular);

	make_vec4(light_0_position, 2.0f, 2.0f, 2.f, 1.f);
	glLightfv(GL_LIGHT0, GL_POSITION, light_0_position);

	//glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 1);
	//glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0);
	//glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0);

}

// 渲染
void render(void) {

	// 清除颜色缓冲、深度缓冲、模板缓冲
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);


	if (g != nullptr) {

		g->draw();

	}
	// 交换缓冲区
	glutSwapBuffers();
}

int main(int argc, char**argv) {

	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
	glutInitWindowSize(800, 600);
	glutCreateWindow("OpenGL");
	glutReshapeFunc(changed_size);
	glutDisplayFunc(render);
	glutIdleFunc(render);

	GLenum err = glewInit();
	if (GLEW_OK != err) {
		std::cerr << "GLEW Error : " << glewGetErrorString(err) << std::endl;
		return 1;
	}

	init_render_context();


	/* ========================== */
	/*
	*			shader	
	*/

	load_shader();

	g= new geomtery(vec3(0.0, 0.0, 0.0), 1.0, 1.0, vec4(1.0, 1.0, 1.0, 1.0));

	glutMainLoop();

	return 0;
}

_vertex.vert

#version 440

uniform mat4 _model_view;
uniform mat4 _projection;

uniform vec4 _light0_position;

layout (location = 0) in vec3 v;
layout (location = 1) in vec4 c;
layout (location = 2) in vec3 n;

struct v2f{
	vec4 c;

};

out v2f vert_out;

void main(){
	vert_out.c = c;
	gl_Position = _projection * _model_view * vec4(v,1);
}

_fragment.frag

#version 440

uniform vec4 _light0_position;
uniform vec4 _light0_ambient;
uniform vec4 _light0_diffuse;

out vec4 o;

struct v2f{
	vec4 c;

};

in v2f vert_out;

void main() {
	o = vert_out.c;
}

glmath


class vec3 {
public:
	vec3();
	~vec3();
	vec3(GLfloat _x,GLfloat _y,GLfloat _z);
	GLfloat x,y,z;
};

class vec4:public vec3 {
public:
	vec4();
	~vec4();
	vec4(GLfloat _x, GLfloat _y, GLfloat _z,GLfloat _w );
	GLfloat w;
};

vec3 cross(vec3 &v1, vec3 &v2) {
	vec3 r;
	r.x = (v1.y * v2.z) - (v1.z * v2.y);
	r.y = (v1.z * v2.x) - (v1.x * v2.z);
	r.z = (v1.x * v2.y) - (v1.y * v2.x);

	return r;
}

vec3 normalize(vec3 &v) {
	vec3 r;
	GLfloat a = 1.0 / sqrt(v.x*v.x + v.y*v.y + v.z*v.z);
	r.x = static_cast<GLfloat>(a*v.x);
	r.y = static_cast<GLfloat>(a*v.y);
	r.z = static_cast<GLfloat>(a*v.z);

	return r;
}


vec3 operator+(const vec3& l, const vec3& r) {
	vec3 ret;
	ret.x = l.x + r.x;
	ret.y = l.y + r.y;
	ret.z = l.z + r.z;

	return ret;
}

vec4 operator+(const vec4& l, const vec4& r) {
	vec4 ret;
	ret.x = l.x + r.x;
	ret.y = l.y + r.y;
	ret.z = l.z + r.z;
	ret.w = l.w + r.w;
	return ret;
}

vec3 operator-(const vec3& l, const vec3& r) {
	vec3 ret;
	ret.x = l.x - r.x;
	ret.y = l.y - r.y;
	ret.z = l.z - r.z;

	return ret;
}

vec4 operator-(const vec4& l, const vec4& r) {
	vec4 ret;
	ret.x = l.x - r.x;
	ret.y = l.y - r.y;
	ret.z = l.z - r.z;
	ret.w = l.w - r.w;
	return ret;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值