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; }
相关文章推荐
- OpenGL——VAO,VBO,EBO等对象的使用
- OpenGL4.0】GLSL渲染语言入门与VBO、VAO使用:绘制一个三角形
- 【OpenGL4.0】GLSL渲染语言入门与VBO、VAO使用:绘制一个三角形
- 在macOS上学习OpenGL | VBO、VAO 和 EBO
- 【OpenGL4.0】GLSL渲染语言入门与VBO、VAO使用:绘制一个三角形
- 【OpenGL4.0】GLSL渲染语言入门与VBO、VAO使用:绘制一个三角形
- 【OpenGL4.0】GLSL渲染语言入门与VBO、VAO使用:绘制一个三角形 【转】
- OpenGL进阶(九) - GLSL中VAO和VBO的使用
- OpenGL进阶(九) - GLSL中VAO和VBO的使用
- opengl3.x之glsl数据传递VAO,VBO
- 【OpenGL4.0】GLSL渲染语言入门与VBO、VAO使用:绘制一个三角形
- 【OpenGL4.0】GLSL渲染语言入门与VBO、VAO使用:绘制一个三角形
- OpenGL 4.0 GLSL 基础教程概览——VAO和VBO常用操作接口
- OpenGL进阶(九) - GLSL中VAO和VBO的使用
- GLSL渲染语言入门与VBO、VAO使用:绘制一个三角形
- 【OpenGL】VAO与VBO
- OpenGL中glVertex、显示列表(glCallList)、顶点数组(Vertex array)、VBO及VAO区别
- 《GLSL渲染语言入门与VBO、VAO使用:绘制一个三角形》的正确版本及源代码
- OpenGL图形渲染管线、VBO、VAO、EBO概念及用例
- opengl中VAO,VBO,IBO用法小结(zz)