计算机图形学基础(OpenGL版) 实验五 视图变换

计算机图形学基础 实验五 视图变换


1.实验目的:
理解掌握OpenGL程序的模型视图变换。

2.实验内容:
(1)阅读实验原理,运行示范实验代码,理解掌握OpenGL程序的模型视图变换;

(2)根据示范代码,尝试完成实验作业;

3.实验原理:
我们生活在一个三维的世界——如果要观察一个物体,我们可以:

1、从不同的位置去观察它(人运动,选定某个位置去看)。(视图变换)

2、移动或者旋转它,当然了,如果它只是计算机里面的物体,我们还可以放大或缩小它(物体运动,让人看它的不同部分)。(模型变换)

3、如果把物体画下来,我们可以选择:是否需要一种“近大远小”的透视效果。另外,我们可能只希望看到物体的一部分,而不是全部(指定看的范围)。(投影变换)

4、我们可能希望把整个看到的图形画下来,但它只占据纸张的一部分,而不是全部(指定在显示器窗口的那个位置显示)。(视口变换)

这些,都可以在OpenGL中实现。

从“相对移动”的观点来看,改变观察点的位置与方向和改变物体本身的位置与方向具有等效性。在OpenGL中,实现这两种功能甚至使用的是同样的函数。

由于模型和视图的变换都通过矩阵运算来实现,在进行变换前,应先设置当前操作的矩阵为“模型视图矩阵”。设置的方法是以GL_MODELVIEW为参数调用glMatrixMode函数,像这样:

glMatrixMode(GL_MODELVIEW);

该语句指定一个4×4的建模矩阵作为当前矩阵。

通常,我们需要在进行变换前把当前矩阵设置为单位矩阵。把当前矩阵设置为单位矩阵的函数为:

glLoadIdentity();

我们在进行矩阵操作时,有可能需要先保存某个矩阵,过一段时间再恢复它。当我们需要保存时,调用glPushMatrix()函数,它相当于把当前矩阵压入堆栈。当需要恢复最近一次的保存时,调用glPopMatrix()函数,它相当于从堆栈栈顶弹出一个矩阵为当前矩阵。OpenGL规定堆栈的容量至少可以容纳32个矩阵,某些OpenGL实现中,堆栈的容量实际上超过了32个。因此不必过于担心矩阵的容量问题。

通常,用这种先保存后恢复的措施,比先变换再逆变换要更方便,更快速。

注意:模型视图矩阵和投影矩阵都有相应的堆栈。使用glMatrixMode来指定当前操作的究竟是模型视图矩阵还是投影矩阵。

在代码中,视图变换必须出现在模型变换之前,但可以在绘图之前的任何时候执行投影变换和视口变换。

1.display()程序中绘图函数潜在的重复性强调了:在指定的视图变换之前,应该使用glLoadIdentity()函数把当前矩阵设置为单位矩阵。

2.在载入单位矩阵之后,使用gluLookAt()函数指定视图变换。如果程序没有调用gluLookAt(),那么照相机会设定为一个默认的位置和方向。在默认的情况下,照相机位于原点,指向Z轴负方向,朝上向量为(0,1,0)。

3.一般而言,display()函数包括:视图变换 + 模型变换 + 绘制图形的函数(如glutWireCube())。display()会在窗口被移动或者原来先遮住这个窗口的东西被一开时,被重复调用,并经过适当变换,保证绘制的图形是按照希望的方式进行绘制。

4.在调用glFrustum()设置投影变换之前,在reshape()函数中有一些准备工作:视口变换 + 投影变换 + 模型视图变换。由于投影变换,视口变换共同决定了场景是如何映射到计算机的屏幕上的,而且它们都与屏幕的宽度,高度密切相关,因此应该放在reshape()中。reshape()会在窗口初次创建,移动或改变时被调用。

OpenGL中矩阵坐标之间的关系

物理坐标模型视图矩阵投影矩阵透视除法规范化设备坐标——〉窗口坐标

(1)视图变换函数gluLookAt(0.0,0.0,5.0,0.0,0.0,0.0,0.0,1.0,0.0,)设置照相机的位置

把照相机放在(0,0,5),镜头瞄准(0,0,0),朝上向量定为(0,1,0)朝上向量为照相机指定了一个唯一的方向。如果没有调用gluLookAt,照相机就设定一个默认的位置和方向,在默认情况下,照相机位于原点,指向Z轴的负方向,朝上向量为(0,1,0)

glLoadIdentity()函数把当前矩阵设置为单位矩阵。

(2)使用模型变换的目的是设置模型的位置和方向

(3)投影变换,指定投影变换类似于为照相机选择镜头,可以认为这种变换的目的是确定视野,并因此确定哪些物体位于视野之内以及他们能够被看到的程度。

除了考虑视野之外,投影变换确定物体如何投影到屏幕上,OpenGL提供了两种基本类型的投影,1、透视投影:远大近小;2、正投影:不影响相对大小,一般用于建筑和CAD应用程序中

(4)视口变换

视口变换指定一个图象在屏幕上所占的区域

(5)绘制场景

4.示范代码: 太阳系

#include "Dependencies\glew\glew.h"
#include "Dependencies\freeglut\freeglut.h"
#include <amp_graphics.h>

static int year = 0, day = 0;

void init(void)
{
	glClearColor(0.0, 0.0, 0.0, 0.0);
	glShadeModel(GL_FLAT);
}

void display(void)
{
	glClear(GL_COLOR_BUFFER_BIT);
	glColor3f(1.0, 1.0, 1.0);
	glPushMatrix();
	glutWireSphere(1.0, 20, 16); /* draw sun */
	glRotatef((GLfloat)year, 0.0, 1.0, 0.0);
	glTranslatef(2.0, 0.0, 0.0);
	glRotatef((GLfloat)day, 0.0, 1.0, 0.0);
	glutWireSphere(0.2, 10, 8); /* draw smaller planet */
	
	glPopMatrix();
	glutSwapBuffers();
}

void reshape(int w, int h)
{
	glViewport(0, 0, (GLsizei)w, (GLsizei)h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(60.0, (GLfloat)w / (GLfloat)h, 1.0, 20.0);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
}

void keyboard(unsigned char key, int x, int y)
{
	switch (key) {
	case 'd':
		day = (day + 10) % 360;
		glutPostRedisplay();
		break;
	case 'D':
		day = (day - 10) % 360;
		glutPostRedisplay();
		break;
	case 'y':
		year = (year + 5) % 360;
		glutPostRedisplay();
		break;
	case 'Y':
		year = (year - 5) % 360;
		glutPostRedisplay();
		break;
	case 27:
		exit(0);
		break;
	default:
		break;
	}
}

int main(int argc, char** argv)
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
	glutInitWindowSize(500, 500);
	glutInitWindowPosition(100, 100);
	glutCreateWindow(argv[0]);
	
	init();
	glutDisplayFunc(display);
	glutReshapeFunc(reshape);
	glutKeyboardFunc(keyboard);
	glutMainLoop();
	return 0;
}

代码说明:
上面所描述的这个程序绘制一个简单的太阳系,其中有一颗行星和一颗太阳,它们是用同一个球体绘制函数绘制的。为了编写这个程序,需要使用glRtate*()函数让这颗行星绕太阳旋转,并且绕自身的轴旋转。还需要使用glTranslate*()函数让这颗行星远离太阳系原点,移动到它自己的轨道上。记住,可以在glutWireSphere()函数中使用适当的参数,在绘制两个球体时指定球体的大小。

为了绘制这个太阳系,首先需要设置一个投影变换和一个视图变换。在这个例子中,可以使用glutPerspective()和gluLookat().

绘制太阳比较简单,因为它应该位于全局固定坐标系统的原点,也就是球体函数进行绘图的位置。因此,绘制太阳时并不需要移动,可以使用glRotate*()函数绕一个任意的轴旋转。绘制一颗绕太阳旋转的行星要求进行几次模型变换。这颗行星需要每天绕自己的轴旋转一周,每年沿着自己的轨道绕太阳旋转一周。

为了确定模型变换的顺序,可以从局部坐标系统的角度考虑。首先,调用初始的glRotate*()函数对局部坐标系统进行旋转,这个局部坐标系统最初与全局固定坐标系统是一致的。接着,可以调用glTranslate*()把局部坐标系统移动到行星轨道上的一个位置。移动的距离应该等于轨道的半径。因此,第一个glRotate*()函数实际上确定了这颗行星从什么地方开始绕太阳旋转(或者说,从一年的什么时候开始)。

第二次调用glRotate*()使局部坐标轴进行旋转,因此确定了这颗行星在一天中的时间。当调用了这些函数变换之后,就可以绘制这颗行星了。

  1. 实验作业:
    (1)尝试在太阳系中增加一颗卫星,一颗行星。提示:使用glPushMatrix()和glPopMatrix()在适当的时候保存和恢复坐标系统的位置。如果打算绘制几颗卫星绕同一颗行星旋转,需要在移动每颗卫星的位置之前保存坐标系统,并在绘制每颗卫星之后恢复坐标系统。

(2)尝试把行星的轴倾斜。

实验内容原文链接

实验提高代码

#include "Dependencies\glew\glew.h"
#include "Dependencies\freeglut\freeglut.h"
#include <amp_graphics.h>

static int year = 0, day = 0,day01=0,sday=0;

void init(void)
{
	glClearColor(0.0, 0.0, 0.0, 0.0);
	glShadeModel(GL_FLAT);
}

void display(void)
{
	glClear(GL_COLOR_BUFFER_BIT);
	glColor3f(1.0, 1.0, 1.0);

	glPushMatrix();
	glutWireSphere(1.0, 30, 16); /* draw sun */

	glRotatef((GLfloat)year, 0.0, 1.0, 0.5);
	glTranslatef(2.0, 0.0, 0.0);

	glRotatef((GLfloat)day, 0.0, 1.0, 0.0);
	glutWireSphere(0.2, 10, 8); /* draw smaller planet */

	glRotatef((GLfloat)sday, 0.0, 1.0, 0.0);
	glTranslatef(0.5, 0.0, 0.0);
	
	glutWireSphere(0.1, 10, 8); /* draw 卫星 */
	//glRotatef((GLfloat)day, 0.0, 0.5, 0.0);
	
	
	glPopMatrix();

	glPushMatrix();
	glRotatef((GLfloat)year, 0.0, 1.0, 0.0);
	glTranslatef(3.0, 0.0, 0.0);
	glRotatef((GLfloat)day01, 0.0, 1.0, 0.0);
	glutWireSphere(0.3, 10, 8); /* draw 第二个行星 */
	glPopMatrix();

	glutSwapBuffers();
}

void reshape(int w, int h)
{
	glViewport(0, 0, (GLsizei)w, (GLsizei)h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(60.0, (GLfloat)w / (GLfloat)h, 1.0, 20.0);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
	//Y是0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0
	//原来是0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0
}

void keyboard(unsigned char key, int x, int y)
{
	switch (key) {
	case 'd':
		day = (day + 10) % 360;
		day01 = (day01 + 10) % 360;
		sday = (sday + 10) % 360;
		glutPostRedisplay();
		break;
	case 'D':
		day = (day - 10) % 360;
		day01 = (day01 - 10) % 360;
		glutPostRedisplay();
		break;
	case 'y':
		year = (year + 5) % 360;
		glutPostRedisplay();
		break;
	case 'Y':
		year = (year - 5) % 360;
		glutPostRedisplay();
		break;
	case 'a':
		year = (year + 5) % 360;
		day = (day + 10) % 360;
		day01 = (day01 + 10) % 360;
		glutPostRedisplay();
		break;
	case 'A':
		year = (year - 5) % 360;
		day = (day - 10) % 360;
		day01 = (day01 - 10) % 360;
		glutPostRedisplay();
		break;
	case 27:
		exit(0);
		break;
	default:
		break;
	}
}

int main(int argc, char** argv)
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
	glutInitWindowSize(500, 500);
	glutInitWindowPosition(100, 100);
	glutCreateWindow(argv[0]);
	
	init();
	glutDisplayFunc(display);
	glutReshapeFunc(reshape);
	glutKeyboardFunc(keyboard);
	glutMainLoop();
	return 0;
}
  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第1章绪论 1.1计算机图形学及其相关概念 1.2计算机图形学的发展 1.2.1计算机图形学学科的发展 1.2.2图形硬件设备的发展 1.2.3图形软件的发展 1.3计算机图形学的应用 1.3.1计算机辅助设计与制造 1.3.2计算机辅助绘图 1.3.3计算机辅助教学 1.3.4办公自动化和电子出技术 1.3.5计算机艺术 1.3.6在工业控制及交通方面的应用 1.3.7在医疗卫生方面的应用 1.3.8图形用户界面 1.4计算机图形学研究动态 1.4.1计算机动画 1.4.2地理信息系统 1.4.3人机交互 1.4.4真实感图形显示 1.4.5虚拟现实 1.4.6科学计算可视化 1.4.7并行图形处理 第2章计算机图形系统及图形硬件 2.1计算机图形系统概述 2.1.1计算机图形系统的功能 2.1.2计算机图形系统的结构 2.2图形输入设备 2.2.1键盘 2.2.2鼠标器 2.2.3光笔 2.2.4触摸屏 2.2.5操纵杆 2.2.6跟踪球和空间球 2.2.7数据手套 2.2.8数字化仪 2.2.9图像扫描仪 2.2.10声频输入系统 2.2.11视频输入系统 2.3图形显示设备 2.3.1阴极射线管 2.3.2CRT图形显示器 2.3.3平板显示器 2.3.4三维观察设备 2.4图形显示子系统 2.4.1光栅扫描图形显示子系统的结构 2.4.2绘制流水线 2.4.3相关概念 2.5图形硬拷贝设备 2.5.1打印机 2.5.2绘图仪 2.6OpenGL图形软件包 2.6.1OpenGL的主要功能 2.6.2OpenGL的绘制流程 2.6.3OpenGL的基本语法 2.6.4一个完整的OpenGL程序 第3章用户接口与交互式技术 3.1用户接口设计 3.1.1用户模型 3.1.2显示屏幕的有效利用 3.1.3反馈 3.1.4一致性原则 3.1.5减少记忆量 3.1.6回退和出错处理 3.1.7联机帮助 3.1.8视觉效果设计 3.1.9适应不同的用户 3.2逻辑输入设备与输入处理 3.2.1逻辑输入设备 3.2.2输入模式 3.3交互式绘图技术 3.3.1基本交互式绘图技术 3.3.2三维交互技术 3.4OpenGL中橡皮筋技术的实现 3.4.1基于鼠标的实现 3.4.2基于键盘的实现 3.5OpenGL中拾取操作的实现 3.6OpenGL的菜单功能 第4章图形的表示与数据结构 4.1基本概念 4.1.1基本图形元素 4.1.2几何信息与拓扑信息 4.1.3坐标系 4.1.4实体的定义 4.1.5正则集合运算 4.1.6平面多面体与欧拉公式 4.2三维形体的表示 4.2.1多边形表面模型 4.2.2扫描表示 4.2.3构造实体几何法 4.2.4空间位置枚举表示 4.2.5八叉树 4.2.6BSP树 4.2.7OpenGL中的实体模型函数 4.3非规则对象的表示 4.3.1分形几何 4.3.2形状语法 4.3.3粒子系统 4.3.4基于物理的建模 4.3.5数据场的可视化 4.4层次建模 4.4.1段与层次建模 4.4.2层次模型的实现 4.4.3OpenGL中层次模型的实现 第5章基本图形生成算法 5.1直线的扫描转换 5.1.1数值微分法 5.1.2中点Bresenham算法 5.1.3Bresenham算法 5.2圆的扫描转换 5.2.1八分法画圆 5.2.2中点Bresenham画圆算法 5.3椭圆的扫描转换 5.3.1椭圆的特征 5.3.2椭圆的中点Bresenham算法 5.4多边形的扫描转换与区域填充 5.4.1多边形的扫描转换 5.4.2边缘填充算法 5.4.3区域填充 5.4.4其他相关概念 5.5字符处理 5.5.1点阵字符 5.5.2矢量字符 5.6属性处理 5.6.1线型和线宽 5.6.2字符的属性 5.6.3区域填充的属性 5.7反走样 5.7.1过取样 5.7.2简单的区域取样 5.7.3加权区域取样 5.8在OpenGL中绘制图形 5.8.1点的绘制 5.8.2直线的绘制 5.8.3多边形面的绘制 5.8.4OpenGL中的字符函数 5.8.5OpenGL中的反走样 第6章二维变换及二维观察 6.1基本概念 6.2基本几何变换 6.2.1平移变换 6.2.2比例变换 6.2.3旋转变换 6.2.4对称变换 6.2.5错切变换 6.2.6二维图形几何变换的计算 6.3复合变换 6.3.1二维复合平移变换和比例变换 6.3.2二维复合旋转变换 6.3.4其他二维复合变换 6.3.5相对任一参考点的二维几何变换 6.3.6相对于任意方向的二维几何变换 6.3.7坐标系之间的变换 6.3.8光栅变换 6.3.9变换的性质 6.4二维观察 6.4.1基本概念 6.4.2?用户坐标系到观察坐标系的变换 6.4.3?窗口到视区的变换 6.5?裁剪 6.5.1?点的裁剪 6.5.2直线段的裁剪 6.5.3多边形的裁剪 6.5.4其他裁剪 6.6OpenGL中的二维观察变换 第7章三维变换及三维观察 7.1三维变换的基本概念 7.1.1几何变换 7.1.2三维齐次坐标变换矩阵 7.1.3平面几何投影 7.2三维几何变换 7.2.1三维基本几何变换 7.2.2三维复合变换 7.3三维投影变换 7.3.1正投影 7.3.2斜投影 7.4透视投影 7.4.1一点透视 7.4.2二点透视 7.4.3三点透视 7.5观察坐标系及观察空间 7.5.1观察坐标系 7.5.2观察空间 7.6三维观察流程 7.6.1用户坐标系到观察坐标系的变换 7.6.2平行投影的规范化投影变换 7.6.3透视投影的规范化投影变换 7.7三维裁剪 7.7.1关于规范化观察空间的裁剪 7.7.2齐次坐标空间的裁剪 7.8OpenGL中的变换 7.8.1矩阵堆栈 7.8.2模型视图变换 7.8.3投影变换 7.8.4实例 第8章曲线与曲面 8.1基本概念 8.1.1曲线/曲面数学描述的发展 8.1.2曲线/曲面的表示要求 8.1.3曲线/曲面的表示 8.1.4插值与逼近 8.1.5连续性条件 8.1.6样条描述 8.2三次样条 8.2.1自然三次样条 8.2.2Hermite插值样条 8.3Bezier曲线/曲面 8.3.1Bezier曲线的定义 8.3.2Bezier曲线的性质 8.3.3Bezier曲线的生成 8.3.4Bezier曲面 8.4B样条曲线/曲面 8.4.1B样条曲线 8.4.2B样条曲线的性质 8.4.3B样条曲面 8.5有理样条曲线/曲面 8.5.1NURBS曲线/曲面的定义 8.5.2有理基函数的性质 8.5.3NURBS曲线/曲面的特点 8.6曲线/曲面的转换和计算 8.6.1样条曲线/曲面的转换 8.6.2样条曲线/曲面的离散生成 8.7OpenGL生成曲线/曲面 8.7.1Bezier曲线/曲面函数 8.7.2GLU中的B样条曲线/曲面函数 第9章消隐 9.1深度缓存器算法 9.2区间扫描线算法 9.3深度排序算法 9.4区域细分算法 9.5光线投射算法 9.6BSP树 9.7多边形区域排序算法 9.8OpenGL中的消隐处理 第10章真实感图形绘制 10.1简单光照模型 10.1.1环境光 10.1.2漫反射光 10.1.3镜面反射光 10.1.4光强衰减 10.1.5颜色 10.2基于简单光照模型的多边形绘制 10.2.1恒定光强的多边形绘制 10.2.2Gouraud明暗处理 10.2.3Phong明暗处理 10.3透明处理 10.4产生阴影 10.5模拟景物表面细节 10.5.1用多边形模拟表面细节 10.5.2纹理的定义和映射 10.5.3凹凸映射 10.6整体光照模型与光线追踪 10.6.1整体光照模型 10.6.2Whitted光照模型 10.6.3光线跟踪算法 10.6.4光线跟踪反走样 10.7 OpenGL中的光照与表面绘制函数 10.7.1 OpenGL点光源 10.7.2 OpenGL全局光照 10.7.3 OpenGL表面材质 10.7.4 OpenGL透明处理 10.7.5 OpenGL表面绘制 10.7.6 实例 10.8 OpenGL中的纹理映射
### 回答1: 计算机图形学基础OpenGL)是一本介绍计算机图形学基础知识的书籍,主要使用OpenGL作为实现工具。该书内容涵盖了计算机图形学的基本概念、图形学编程基础、3D图形学、光照和材质、纹理映射、几何变换视图变换、投影变换等方面的内容。该书适合计算机图形学初学者学习,也适合OpenGL编程初学者学习。 ### 回答2: 计算机图形学基础(opengl) pdf 是一本讲解计算机图形学基础知识的书籍,其重点关注如何使用OpenGL来实现图形学应用。该书籍从基础入手,详细阐述了OpenGL基础知识和编程技巧,涵盖了OpenGL的绘图操作、光照、材质、纹理映射等方面的内容。 作为计算机科学领域重要的一支,计算机图形学的应用已经广泛地渗透到生活各个领域。例如游戏、动画、虚拟现实、建筑、医学等多个领域,都离不开计算机图形学的支持。因此,掌握计算机图形学基础知识,对于计算机科学学习者来说十分重要。 在该书的学习过程中,读者需要了解OpenGL的绘制模式,包括点、线、三角形和四边形等基本图形。同时,书中也讲解了如何通过OpenGL的API实现图形的旋转、缩放、平移等变换。此外,读者还需要了解OpenGL的光照模型和材质模型,从而实现多彩多样的图形。 此外,该书籍也重点介绍了OpenGL实现纹理映射技术。纹理映射技术可以帮助设计师将贴图与模型结合,以实现更加真实的效果。同时,该书籍还涵盖了OpenGL的卡通渲染和OpenGL的深度检测以及多重采样技术等方面的内容。 总之,计算机图形学基础(opengl) pdf 是一本内容详尽、学习难度适中的图形学基础知识的书籍。它既覆盖了丰富的理论知识,也体现了实践方面的应用。对于学习计算机图形学的初学者来说,这是一本非常好的入门教材。 ### 回答3: 计算机图形学基础(opengl) pdf是一本非常优秀的图形学教材,它涵盖了图形学基础的各个方面,从三角形到光照再到着色和阴影,从基本的渲染方程到高级的像素运算,本书讲解了图形学的主要概念,算法和技术,同时采用opengl作为实现工具,给予读者一些实战经验。 首先,在理论方面,计算机图形学基础(opengl) pdf通过简单而易懂的语言,对图形学的基本概念进行了详细的讲解。它在三维坐标系的基础上,介绍了各种图形学的基本概念,如顶点,向量,矩阵,坐标变换等。然后,通过顶点组成三角形来进行渲染,并进一步介绍切线空间和相机模型的概念。作者还详细阐述了光照、阴影算法和纹理映射等重要技术,这些都是图形学的重点中的重点。 其次,在实践方面,计算机图形学基础 (opengl) pdf提供了丰富的实验和示例代码,帮助读者更好地理解和运用图形学知识。例如,第三章介绍了OpenGL渲染流程和基本操作,第四章则介绍了绘制基本图形形状,第章介绍了纹理映射实现。几乎每个章节的结束都配有实例源代码供读者练习使用。此外,也有课堂实验和作业,更进一步提高了实践操作的难度与复杂度。 最后,值得一提的是,计算机图形学基础 (opengl) pdf的编写风格简洁又精准,图文并茂。它不仅能够让初学者一步步了解图形学的基本概念,但也满足了几乎所有图形学的应用需求,尤其是那些想要使用opengl来实现复杂图形学项目的人们。总的来说,它是一本非常优秀的图形学教材,值得每个学习图形学的人士阅读掌握。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值