1、Opengl是一个有限状态机
输入:各种三维模型、外部事件
输出:屏幕的像素值
状态:颜色、观察位置、材质、透视方法
2、回调函数
交互程序能够随时响应事件,依靠无限的事件处理循环
回调函数定义程序对具体事件的响应方式。
事件放入事件队列,并由系统窗口系统用相应的回调函数处理。
a、显示回调函数
void glutDisplayFunc(void (*func)(void))
顶点变换依靠矩阵运算完成,包含平移旋转投影
不同操作使用使用不同的矩阵,投影矩阵(projection matrix)、模型视图矩阵(model-view-matrix)
模型视图矩阵负责定义摄像机的位姿即摄像机的位置和观察方向。
b、变形回调函数
void glutReshapeFunc(void(*func)(GLint width, GLint height))
c 、空闲回调函数
void glutIdlefunc(void (*f)(void))
当没有窗口事件到达时,GLUT程序功能可以执行后台处理任务或连续动画。
3、图形流水线
a、应用程序
应用程序生成由一些列顶点座标描述的三维模型,将其送至图形流水线的入口
如glutWireTeapot
b、顶点着色器
负责逐顶点计算,位移、旋转、投影变换
例子中旋转矩阵、透视投影矩阵交给顶点着色器对整个模型进行逐顶点操作
将三维顶点变为二维投影平面的一个点
c、光栅化器
将投影在二维平面上的点转化为离散的像素点,决定帧缓冲里每个像素取值
d、片段着色器
负责逐像素计算,在绘制二维图形时给每个帧缓冲像素赋值,如设置目标和背景的颜色
e、帧缓存
最终图像绘制完成并输出到显示的地方
glutSwapBuffers交换后台帧缓存和前台帧缓存,刷新到屏幕
#define GLEW_STATIC
#include <GL/glew.h>
#include <stdio.h>
#include <stdlib.h>
#include <GL/glut.h>
GLuint v, f, p;
float lpos[4] = { 1,0.5,1,0 };
#pragma comment( lib, "glew32s.lib" )
void changeSize(int w, int h)
{
printf("changesize w = %d, h = %d\n", w, h);
if (h == 0) h = 1;
float ratio = 1.0*w / h;
//在更改之前重设座标系
glMatrixMode(GL_PROJECTION);//设置为投影矩阵
glLoadIdentity();//设置为单位矩阵
//设置视口为整个窗口
glViewport(0, 0, w, h);
//设置正确的透视投影方法
gluPerspective(45, ratio, 1, 1000);
/*
void gluPerspective(
GLdouble fovy, //角度
GLdouble aspect,//视景体的宽高比
GLdouble zNear,//沿z轴方向的两裁面之间的距离的近处
GLdouble zFar //沿z轴方向的两裁面之间的距离的远处
)
*/
glMatrixMode(GL_MODELVIEW);
}
float a = 0;
void renderScene(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//组合不同的缓冲标志位,表明需要清除的缓冲
//GL_COLOR_BUFFER_BIT颜色缓冲 GL_DEPTH_BUFFER_BIT深度缓冲
glLoadIdentity();// 当前矩阵初始化为单位矩阵,为默认的模型视图矩阵
gluLookAt(0.0, 0.0, 5.0,// 摄影机的位置
0.0, 0.0, -1.0,//摄影机指向的点
0.0f, 1.0f, 0.0f);//定义的正上方
//此时初始化的当前矩阵被gluLookAt确定的模型视图修改
glLightfv(GL_LIGHT0, GL_POSITION, lpos);//光源函数
glRotatef(a, 0, 1, 1);// 旋转变换,a角度,以[0,1,1]为转轴
//glutSolidTeapot(2);//太大看不到茶壶
glutWireTeapot(1); //网格茶壶,上一个为连续表面茶壶
a += 0.1;
glutSwapBuffers();//双缓冲,交换缓冲
//glutPostRedisplay();//glutIdleFunc如果不调用,需要加这个,不然没法旋转,标记当前窗口需要重新绘制
}
int main(int argc, char**argv)
{
glutInit(&argc, argv);
//设置初始显示模式。深度缓冲、双缓冲、颜色缓冲
//GLUT_STENCIL.模板缓冲区。
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100, 100);
glutInitWindowSize(320, 320);
glutCreateWindow("GPGPU GLSL");
glutDisplayFunc(renderScene); //注册显示回调函数
glutIdleFunc(renderScene);
glutReshapeFunc(changeSize);//注册变形回调函数
glEnable(GL_DEPTH_TEST);
glClearColor(1.0, 0.0, 0.0, 0.5);
glColor3f(0.0, 0.0, 1.0);//定义绘制目标的颜色
glewInit();
glutMainLoop();
return 0;
}