OpenGL三维镂垫
2015-10-15 01:00
736 查看
2015-12-12帮舍友尝试这个代码的时候发现舍友的会出现No GLSL support 后来发现舍友的版本2.0、2.1才能用
舍友的是glutInitContextVersion(3, 1);改为glutInitContextVersion(2,
1);.所以用的话,如果闪退,可以尝试修改一下版本号
【关于版本的更多知识http://blog.csdn.net/ym19860303/article/details/44115135】
整个代码资源:http://download.csdn.net/detail/u014646950/9350045
代码有书上的+网上的+我自己码的
用vs2013社区英语版可以得结果,但是有一点小故障,如下。
代码批注部分贡献者http://www.mamicode.com/info-detail-504374.html
首先要会创建consoleApplication,会3个新建文本并重命名,下载配置头文件
相关经验http://jingyan.baidu.com/article/3c48dd34873509e10be35880.html
或者
http://xujiayu317.blog.163.com/blog/static/25475209201591393731494/?newFollowBlog
在文件名字为 fshader3.glsl里面填上如下(图代码)
在文件名字为 vshader3.glsl里面填上如下(图代码)
在文件名字为 ogl3.cpp里面填上如下(图代码)
上面是这里代码的效果图
更改点坐标和颜色可获得其他效果图
舍友的是glutInitContextVersion(3, 1);改为glutInitContextVersion(2,
1);.所以用的话,如果闪退,可以尝试修改一下版本号
【关于版本的更多知识http://blog.csdn.net/ym19860303/article/details/44115135】
整个代码资源:http://download.csdn.net/detail/u014646950/9350045
GLSL Versions
OpenGL Version | GLSL Version |
2.0 | 110 |
2.1 | 120 |
3.0 | 130 |
3.1 | 140 |
3.2 | 150 |
3.3 | 330 |
4.0 | 400 |
4.1 | 410 |
4.2 | 420 |
4.3 | 430 |
用vs2013社区英语版可以得结果,但是有一点小故障,如下。
代码批注部分贡献者http://www.mamicode.com/info-detail-504374.html
首先要会创建consoleApplication,会3个新建文本并重命名,下载配置头文件
相关经验http://jingyan.baidu.com/article/3c48dd34873509e10be35880.html
或者
http://xujiayu317.blog.163.com/blog/static/25475209201591393731494/?newFollowBlog
在文件名字为 fshader3.glsl里面填上如下(图代码)
in vec4 color; out vec4 YanColor; void main() { YanColor =color; } /*@注释上下代码功能等价 in vec4 color; void main() { gl_FragColor =color; }*/
在文件名字为 vshader3.glsl里面填上如下(图代码)
in vec4 vPosition; in vec4 vColor; out vec4 color; void main() { gl_Position = vPosition; color=vColor; }
在文件名字为 ogl3.cpp里面填上如下(图代码)
#include <iostream> #include<glew.h> #include<freeglut.h> #include<gl.h> #pragma comment(lib,"glew32.lib") #pragma comment(lib,"freeglut.lib") #pragma comment(lib,"glut32.lib") //#pragma comment(lib,"opengl.lib") /*/#define BUFFER_OFFSET(offset)((GLint *)NULL+offset)用这一个会变成奇怪的颜色*/ #define BUFFER_OFFSET(bytes)((GLvoid *)(bytes))/*/这个是在书上的,这种竟然没有在附录的代码里面*/ const int NumTimesToSubdivide = 5;/*/这里是递归的次数*/ const int NumTetrahedrons = 1024; /*4^5 tetrahedrons;根据上面递归五次,所以就是4的五次方个四面体*/ const int NumTriangles = 4 * NumTetrahedrons; /*/ 4 triangles / tetrahedron每个四面体有4各面*/ const int NumVertices = 3 * NumTriangles; /*/ 3 vertices / triangle 每个面有3个顶点*/ /*@注释 *这个看书上说是在vec.h的头文件里面,可是我电脑上没有, *我只知道,书上是说vec是甚么向量, *vec2是连续两个float, *vec3是连续三个float, *vec4是连续四个float, *我尝试自己弄这个结构体,并有构造函数初始化。 */ struct vec3 { GLfloat x, y, z; vec3(){} vec3(GLfloat hong, GLfloat lv, GLfloat lan) :x(hong), y(lv), z(lan) {} vec3 operator +(vec3 other)const { vec3 temp(x + other.x,y + other.y,z + other.z); return temp; } vec3 operator/(GLint t) { vec3 temp(x/t, y/t, z/t); return temp; } }; typedef ::vec3 point3; typedef ::vec3 color3;/*书上说甚么opengl习惯性这样,对于我来说,觉得这样很啰嗦,明明都是同一个类型*/ point3 points[NumVertices]; color3 YanSe[NumVertices]; color3 vertex_Yase[4] = { color3(0.6f, 0.7f, 0.0f), color3(0.0f, 1.0f, 0.0f), color3(0.0f, 0.5f, 0.2f), color3(0.4f, 0.0f, 0.0f) /*四面体有四个三角面,所以就设置了四种颜色*/ }; int Index = 0; //---------------------------------------------------------------------------- int colorIndex; /*@注释*对于由a、b、c确定的一个三角面,三个点设置同一个颜色才会是纯色的,否则是渐变的代码 */ void triangle(const vec3& a, const vec3& b, const vec3& c) { YanSe[Index] = vertex_Yase[colorIndex]; points[Index++] = a; YanSe[Index] = vertex_Yase[colorIndex]; points[Index++] = b; YanSe[Index] = vertex_Yase[colorIndex]; points[Index++] = c; /*@注释*下面是渐变代码 YanSe[Index] = vertex_Yase[0]; points[Index++] = a; YanSe[Index] = vertex_Yase[1]; points[Index++] = b; YanSe[Index] = vertex_Yase[2]; points[Index++] = c; */ } //---------------------------------------------------------------------------- /*@说明*下面的colorIndex用于给 *最终的每一个四面体的 *四个三角面triangle涂上不同的纯色, *如果要用渐变,可以去掉colorIndex */ void tetra(const vec3& a, const vec3& b, const vec3& c, const vec3& d) { colorIndex = 0; triangle(a, b, c); colorIndex = 1; triangle(a, c, d); colorIndex = 2; triangle(a, d, b); colorIndex = 3; triangle(b, d, c); } //---------------------------------------------------------------------------- /*@注释*递归划分*/ void divide_tetra(const vec3& a, const vec3& b, const vec3& c, const vec3& d, int count) { if (count > 0) { vec3 v0 =(a + b) / 2; vec3 v1 = (a + c) / 2; vec3 v2 = (a + d) / 2; vec3 v3 = (b + c) / 2; vec3 v4 = (c + d) / 2; vec3 v5 = (b + d) / 2; divide_tetra(a, v0, v1, v2, count - 1); divide_tetra(v0, b, v3, v5, count - 1); divide_tetra(v1, v3, c, v4, count - 1); divide_tetra(v2, v5, v4,d , count - 1); } else { tetra(a, b, c, d); // draw tetrahedron at end of recursion } } //---------------------------------------------------------------------------- /*@注释*读取文件,以字符串的形式返回*/ static char* readShaderSource(const char *file) { FILE *fp; if (file == NULL) return NULL; fopen_s(&fp,file, "rb"); /*@注释,我这里是用的vs2013,vs2013不让用fp=fopen(file, "rb");*/ if (fp == NULL)return NULL; fseek(fp, 0, SEEK_END);/*@注释:将fp所指向的文件位置指针移到以SEEK_END的基准位置,以0为位移量位置*/ GLsizei length = ftell(fp); rewind(fp);/*@注释:将fp指示文件中位置的的指针置于文件的开头位置,并清楚文件爱你结束标志和错误标志*/ GLchar * shaderChan =new GLchar[length + 1]; fread(shaderChan, sizeof(char), length, fp); shaderChan[length] = '\0'; if (shaderChan == NULL) { delete[]shaderChan;//删除着色器字符串 std::cerr << file << "error" << std::endl; exit(EXIT_FAILURE); } fclose(fp); return shaderChan; } /*@注释*创建并编译着色器*/ GLuint buildShader(const char* FileName, GLenum shaderType) { GLchar*shaderChan = readShaderSource(FileName);//以字符串的形式读取文件 GLuint shaderHandle = glCreateShader(shaderType); glShaderSource(shaderHandle, 1,&shaderChan, NULL); //(const GLchar**)把着色器对象与相应的着色器字符相关联 delete[]shaderChan;//删除着色器字符串 glCompileShader(shaderHandle); //编译着色器 GLint compileSuccess; glGetShaderiv(shaderHandle, GL_COMPILE_STATUS, &compileSuccess); if (compileSuccess == GL_FALSE) { // 若失败... std::cerr << FileName << "failed to compile:" << std::endl; GLint logsize; glGetShaderiv(shaderHandle, GL_INFO_LOG_LENGTH, &logsize); char*logMsg = new char[logsize+1]; glGetShaderInfoLog(shaderHandle, logsize, NULL, logMsg); std::cerr << logMsg << std::endl; delete[] logMsg; exit(EXIT_FAILURE); } return shaderHandle; } /*@注释*初始化着色器*/ GLuint InitShader(const char *vertexShaderFilename, const char *fragmentShaderFilename) { /*创建顶点着色器对象和片元着色器对象*/ GLuint vertexShaderHandle = buildShader(vertexShaderFilename, GL_VERTEX_SHADER); GLuint fragmentShaderHandle = buildShader(fragmentShaderFilename, GL_FRAGMENT_SHADER); GLuint programHandle = glCreateProgram(); glAttachShader(programHandle, vertexShaderHandle); glAttachShader(programHandle, fragmentShaderHandle); glLinkProgram(programHandle); GLint linkSuccess; glGetProgramiv(programHandle, GL_LINK_STATUS, &linkSuccess); if (linkSuccess == GL_FALSE) { // 判断连接是否成功... std::cerr << "shader program failed to link:" << std::endl; GLint logsize; glGetProgramiv(programHandle, GL_INFO_LOG_LENGTH, &logsize); char*logMsg = new char[logsize]; glGetProgramInfoLog(programHandle, logsize, NULL, logMsg); std::cerr << logMsg << std::endl; delete[]logMsg; exit(EXIT_FAILURE); } glUseProgram(programHandle); return programHandle; } /*@注释*初始化GLSL*/ void init(void) { /*@注释:初始化四个顶点*/ vec3 vertices[4] = { vec3(1.0, -1.0,0.0), vec3(-1.0,-1.0, 0.0), vec3(0.0,1.0, 0.0), vec3(0.0, 0.0, 0.6) }; /*@注释:调用递归划分Subdivide the original tetrahedron*/ divide_tetra(vertices[0], vertices[1], vertices[2], vertices[3], NumTimesToSubdivide); /*@注释: 创建一个顶点数组对象*/ GLuint vao; glGenVertexArrays(1, &vao);/*注释:顶点数组对象标识申请,管理着顶点属性的集合*/ glBindVertexArray(vao);/*@注释:在这里将做3个事情:1、如果参数是非0,并且是glGenvertexArrays()返回的新值,未经glBindVertexArray的 *那么他将创建一个新的顶点数组对象(这里才真正创建),并且与其名称关联起来。 *2、如果绑定包已经创建过的顶点数组对象,那么该顶点数组对象将被激活。这便于帧间切换绘制数据 *3、如果输入参数是0那么OpenGL将不再使用程序所分配的任何顶点数组对象,并且将渲染状态重设为默认值。*/ /*@注释 创建并初始化一个缓冲区对象*/ GLuint buffer; glGenBuffers(1, &buffer);/*注释:申请顶点缓存对象标识。*/ glBindBuffer(GL_ARRAY_BUFFER, buffer); /*注释:申请顶点缓存对象标识。 *指定顶点缓存对象的用途,GL_ARRAY_BUFFER表示顶点数据。之力glBindBuffer同样完成了3项工作: *1、如果是第一次绑定对象(第二个参数),他是一个非0的无符号整型,那么将创建一个与名称对应的(第一个参数)新的缓存对象 *2、如果绑定到一个已经创建的缓存对象,那么她将被激活为当前使用对象。 *3、如果第二个参数是0,那么OpenGL不再为当前名称(第一个参数)应用任何缓存对象。*/ glBufferData(GL_ARRAY_BUFFER, sizeof(points) + sizeof(YanSe), NULL, GL_STATIC_DRAW); /*注释:glBufferData( GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage ) *向缓存对象输入数据的环节:, glBufferData是真正为缓存对象分配存储空间。 *1、target目标:顶点数据(GL_ARRAY_BUFFER)、索引数据(GL_ELEMENT_ARRAY_BUFFER)、OpenGL的像素数据(GL_PIXEL_UNPACK_BUFFER)、 *从OpenGL中获取的像素数据(GL_PIXEL_PACK_BUFFER)、缓存之间复制数据(GL_COPY_READ_BUFFER/GL_COPY_WRITE_BUFFER)、 *纹理缓存中存储的纹理数据(GL_TEXTURE_BUFFER)、一致性变量(GL_UNIFORM_BUFFER) *2、size:表示缓存数据的总量,字节数。 *3、data:是客户端应用程序的内存指针,数据的来源。要么是NULL,否则如果合法则将会有size大小的数据从客户端拷贝到服务端(显卡内存),如果data数据未初始化 *将保留size大小的内存备用。 *4、usage:用于设置分配数据之后的读取和写入方式,这关系都OpenGL对于缓存对象存储数据中的最优分配方案的管理。说白了,这个参数试图向OpenGL提供 *这堆数据的用途,是否只读,是否静态,用于绘制?拷贝?通过内置标识符的方式告诉OpenGL,OpenGL根据信息来优化内存分配,管理。*/ glBufferSubData(GL_ARRAY_BUFFER, 0,sizeof(points) ,points); /*@注释*glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertex_positions), vertex_positions ); *用数据部分替换目标缓存的内容,注意在glBufferData中我们的data为NULL,所以在这里才真正初始化。 *这个接口使得我们的操作更为灵活,对数据的组织更为紧凑,因为我们只为顶点坐标数据和颜色数据分配了一块连续的空间。 *第二个参数是偏移地址,第三个参数是替换数据的大小,第四个参数是客户端内存指针,也就是数据源。 *需要注意的是不可超越glBufferData保留的内存。 *到这里关于缓存对象的操作只是最简单的部分,还有很多OpenGL接口供我们去灵活控制,优化。*/ glBufferSubData(GL_ARRAY_BUFFER, sizeof(points),sizeof(YanSe) ,YanSe); /*@注释*glBufferSubData(GL_ARRAY_BUFFER, sizeof(vertex_positions), sizeof(vertex_colors), vertex_colors);*/ /*@注释*载入着色器并使用所得到的着色器程序*/ GLuint program = InitShader("vshader3.glsl", "fshader3.glsl"); glUseProgram(program); /*@注释* 初始化顶点着色器中的顶点位置属性*/ GLuint loc = glGetAttribLocation(program, "vPosition"); glEnableVertexAttribArray(loc); /*@注释*参数对应于glVertexAttribPointer的index.也就是location值,与这个值相关联的定点数组将被启用*/ glVertexAttribPointer(loc, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0)); /*@注释* / glVertexAttribPointer(GLuint index, Glint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* pointer) //index:着色器中属性的位置,还记得layout(location = 0)的定义么,就是这个location. //size:表示每个顶点该属性需要更新的分量数目,这里顶点坐标为4个float,所以就是4.值的范围可以是1,2,3,4或GL_BGRA //type:数据类型 //normalized:使用顶点数据之前是否要进行归一化。 //stride:每组数据之间是否要进行偏移,如果是0则,数据是紧密的。 //pointer:表示缓存对象中,从开始位置开始计算数组数据的偏移值*/ GLuint se = glGetAttribLocation(program, "vColor"); glEnableVertexAttribArray(se);/*@注释*启用颜色属性数组 */ glVertexAttribPointer(se, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(sizeof(points))); glClearColor(1.0f, 1.0f, 1.0f, 1.0f);/*@注释*背景色 */ /*@注释*建立视图*/ glLoadIdentity(); glMatrixMode(GL_PROJECTION); glEnable(GL_DEPTH_TEST);/*@注释*开启深度缓存测试*/ glEnable(GL_CULL_FACE);///*@注释*启动多边形剔除功能*/ //*@注释*这里glortho也可以为gluOrtho2D( 1.0, 1.0,1.0, 0.0);*/ glOrtho(1.0,0.0,0.0,1.0,0.0,1.0); } //---------------------------------------------------------------------------- void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glDrawArrays(GL_TRIANGLES, 0, NumVertices); glFlush(); } //---------------------------------------------------------------------------- void keyboard(unsigned char key, int x, int y) { switch (key) { case 033: exit(EXIT_SUCCESS); break; } } void changeSize(int w, int h) { /*@注释:重新定义视口*/ glViewport(0, 0, w, h); /*@注释:重新设置投影变换*/ if (h == 0) h = 1;/*@注释:防止高为0产生除0错误*/ float ratio = 1.0 * w / h;/*@注释:宽高比*/ glMatrixMode(GL_PROJECTION);/*@注释:当前矩阵设为投影矩阵*/ glLoadIdentity();/*@注释:清空投影矩阵*/ gluPerspective(45, ratio, 1, 1000);/*@注释:重设投影矩阵*/ /*@注释:模型视点变换*/ glMatrixMode(GL_MODELVIEW);/*@注释:当前矩阵设为模型视点矩阵*/ } //---------------------------------------------------------------------------- int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE| GLUT_RGBA | GLUT_DEPTH);/*@注释:这里要GLUT_SINGLE*/ glutInitWindowPosition(100, 100); glutInitWindowSize(540, 540); glutInitContextVersion(3, 1); glutInitContextFlags(GLUT_FORWARD_COMPATIBLE); glutInitContextProfile(GLUT_CORE_PROFILE); glutCreateWindow("Simple GLSL example"); /*@注释:窗口大小变化时的处理函数 */ glewExperimental = GL_TRUE; glewInit(); /*@注释:检测是否支持基本的顶点着色器和片元着色器*/ if (GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader) { printf("Ready for GLSL\n"); } else { printf("No GLSL support\n"); exit(1); } init(); glutDisplayFunc(display); glutIdleFunc(display); glutReshapeFunc(changeSize);/*@注释:注册窗口大小改变时的回调函数 changeSize*/ glutKeyboardFunc(keyboard); glutMainLoop(); return 0; }
上面是这里代码的效果图
更改点坐标和颜色可获得其他效果图
相关文章推荐
- 解决Vista系统OpenGL驱动问题的方法整理
- Delphi下OpenGL2d绘图之画四边形的方法
- Delphi下OpenGL2d绘图之画点的方法
- Delphi下OpenGL2d绘图之初始化流程详解
- Delphi使用OpenGL2d绘图之画图片Bmp的方法
- 通过OpenGL ES混合模式缩放视频缓冲区来适应显示尺寸
- VC运用OPENGL加载BMP纹理图的实现方法汇总
- java实现OpenGL ES纹理映射的方法
- java基于OpenGL ES实现渲染实例
- OpenGL坐标系介绍
- linux下opengl的安装(with qt)
- OpenGL超级宝典笔记——显示列表
- OpenGL超级宝典笔记——顶点数组
- OpenGL生成轮廓
- OpenGL超级宝典笔记——性能比较
- OpenGL超级宝典笔记——顶点缓冲区对象
- OpenGL超级宝典笔记——选择
- OpenGL超级宝典笔记——反馈
- OpenGL超级宝典笔记——遮挡查询
- OpenGL超级宝典笔记——深度纹理和阴影