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里面填上如下(图代码)
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;
}  
 
 
上面是这里代码的效果图
  
 

 
 更改点坐标和颜色可获得其他效果图
 
 

OpenGL三维镂垫的更多相关文章

  1. 02->交互式图形学--用glut库实现Sierpinski镂垫

    Sierpinski图形是一类有趣的图形,本文结合交互式图形学教材,讲解Sierpinski镂垫图形生成,作为入门图形学编程的第一课.为了简便,本文就2D来进行讨论.实验环境见01 算法 主要是根据随 ...

  2. Qt OpenGL三维绘图

     简介 OpenGL是为三维绘图提供的标准应用编程接口. OpenGL处理的仅仅是三维绘图方面,而很少或是根本不提供图形用户界面编程方面的支持.OpenGL*应用程序的用户界面必须由其它工具包创建,比 ...

  3. 基于OpenGL三维软件开发

    实验原理: OpenGL在MFC下编程原理---- Windows操作系统对OpenGL的支持 在Windows下用GDI作图必须通过设备上下文(DeviceContext简写DC)调用相应的函数:用 ...

  4. [图形学] Chp10 OpenGL三维观察程序示例

    10.10节书中给出了一个程序示例,有一个填充正方形,从侧面的角度观察并画到屏幕上. 图0 这里进一步画出一个立方体,将相机放入立方体中心,旋转相机,达到在立方体中旋转看到不同画面的效果. 步骤: 1 ...

  5. OpenGL三维与光照

    #include<windows.h> #include<gl/glut.h> #include<gl/gl.h> #include<gl/glu.h> ...

  6. OpenGL——三维多面体实现

    #include<iostream> #include <math.h> #include<Windows.h> #include <GL/glut.h> ...

  7. OpenGL 获取当前屏幕坐标的三维坐标(gluUnProject使用例子 Qt)

    之前使用VS+glut实现了gluUnProject使用例子,用于渲染管道的逆过程,将屏幕坐标转换为opengl三维坐标,本文将尝试使用QT来实现. 代码如下:  main.cpp  12345678 ...

  8. 三维投影总结:数学原理、投影几何、OpenGL教程、我的方法

    如果要得到pose视图,除非有精密的测量方法,否则进行大量的样本采集时很耗时耗力的.可以采取一些取巧的方法,正如A Survey on Partial of 3d shapes,描述的,可以利用已得到 ...

  9. 基于OpenGL的三维曲面动态显示实现

    在使用Visual C++的MFC AppWizard建立应用程序框架后,生成了多个类,与OpenGL编程相关的类是视图类,主要的显示任务都在其中完成. 1.基于OpenGL绘图的基本设置 1.1 设 ...

随机推荐

  1. ASP.NET 实现简单的图片防盗链介绍

    在此,网站图片防盗链的方法是,通过获取Http请求头中的 Referer 标头与本网站域名比较,来判断用户是否来自本站跳转过来的 . 创建一个全局处理程序,用来处理images目录下的图片的直接请求: ...

  2. LESS语法备忘

    变量 很容易理解: @nice-blue: #5B83AD; @light-blue: @nice-blue + #111; #header { color: @light-blue; } 输出: # ...

  3. ECshop网点程序优化-后台添加类目自动选择上次父类目并计算Sort Order

    如果在ECshop后台批量添加过大量类目的人都能体会到是多么的不方便(这点还是要说一下ECshop的产品经理,细节上还是要多注意),每次添加都需要在几百个类目里面找到要添加的父类目也是一个麻烦事,比如 ...

  4. Challenge Checkio(python)—初尝python练习网站

    最近在找点python语言练习的网站,发现这个网站不错 http://www.checkio.org/ 页面设计的也比较漂亮,比较适合学习python的语法知识.不过注册这个网站 开始就得解决一个py ...

  5. 如何配置SSH Keys登录

    SSH Keys简介: 使用SSH Keys的登录远程虚拟云主机的方式比单独使用密码登录更加安全,简单的密码很可能被暴力破解.而目前来看采用长度大于1024位的RSA加密算法,几乎是不可能被破解的.S ...

  6. 【BZOJ】1088: [SCOI2005]扫雷Mine

    1088: [SCOI2005]扫雷Mine Description 相 信大家都玩过扫雷的游戏.那是在一个n*m的矩阵里面有一些雷,要你根据一些信息找出雷来.万圣节到了,“余”人国流行起了一种简单的 ...

  7. 导航栏 & 状态栏覆盖

    当 automaticallyAdjustsScrollViewInsets 为 YES 时,也是默认行为,表现就比较正常了,和 edgesForExtendedLayout = UIRectEdge ...

  8. UIViewCotroller 的生命周期函数

    Viewcontroller 的所有生命周期函数 重写时 一定要先写 父类 方法 就是(super  +生命周期函数) LoadView ViewDidLoad ViewDidUnload: 在iOS ...

  9. DB天气app冲刺第六天

    更改计划 以前是准备完全自己写一个天气App 而且加上自己已经成功的做了一个安卓开发的小例子了,就感觉可以做的出来了.结果这五天证明自己一开始的思路就错了.所以上次跟别的同学问了一下.看了一下他们的方 ...

  10. 自己画一个ActivityIndicatorView-b

    苹果的UI控件中有一个UIActivityIndicatorView,俗称菊花.→_→现在我们仿照它来制作一个其它样式的指示器,如下: ActivityView.png 自定义指示器 首先画一个白色的 ...