您的位置:首页 > 编程语言 > VB

OpenGL VAO+VBO+EBO+GLSL练习

2019-03-14 17:24 477 查看
版权声明:, https://blog.csdn.net/u011760195/article/details/88556961

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: