计算机图形学与可视化计算OPENGL 个人作业一

计算机图形学与可视化计算OPENGL 个人作业一


  关键词:OpenGL绘制线、点、球,世界的旋转


背景信息


  这是2022年春季学期,北京理工大学,计算机学院,软件工程,开设的一门选修课程,为期八周,共32课时,难度很高,自学与听讲的收获参半。

  课程的成绩结算方式为考查,分为三次个人作业与一次团队作业,难度层层递进,每次作业都是以上一次为基础。

  本篇内容为作业一,整体难度较为容易,耗时1~2天。

注意:编译环境与函数库详见(www.wo deng hui zai xie.net)


2022计算机图形学与可视化计算

目录

 (点击跳转)

1 程序使用说明

  1.1 向量的运算

    1.1.1 功能介绍
    1.1.2 执行截图

  1.2 图像的绘制

    1.2.1 功能介绍
    1.2.2 执行截图

2 程序设计说明

  2.1 向量的运算

    2.1.1 头文件Cvector167.h
    2.1.2 文件读取与向量计算、结果输出

  2.2 图像的绘制

    2.2.1 旋转的实现,空格控制旋转
    2.2.2 1000个彩色光滑圆点的绘制
    2.2.3 彩色坐标轴与白色线球的绘制
    2.2.4 彩色圆圈的绘制

源码



1程序使用说明

 1.1 向量的运算

  1.1.1 功能介绍

  将所需要计算的文档放于run目录下,以test.txt命名。
  test.txt中文件必须满足以下格式:

    a) 奇数行的内容必须为

      向量相加
      向量点乘
      向量叉乘
      向量标准化
      向量求模
      向量投影

     六种向量计算之一。

    b) 偶数行的数据必须对应上一行的内容

  向量之间以 ’\t’(单引号之间的内容为键盘上的Tab键)间隔,向量内分量以半角逗号分隔,分量可正可负,小数点后的位数不限,但是必须是float可以容纳的大小。程序会将test.txt中的内容按要求计算,按照原来的格式,输出内容到out.txt中,但偶数行内容有所变动,具体变动:将所给的向量按照原来的间隔方式输出,并在行末增加计算结果:一个向量或者浮点数,向量分量、浮点数均只保留两位小数。


  1.1.2 执行截图
    如下图放置文件

在这里插入图片描述

    test.txt内容

在这里插入图片描述

    out.txt内容

在这里插入图片描述



 1.2 图像的绘制

  1.2.1 功能介绍

  在上文out.txt文件生成后,该程序会完全自动执行图形的绘制,具体绘制内容如下:

  A. 绘制坐标轴X,Y,Z。使用红绿蓝三色的线段表示3个坐标轴。
  B. 使用线框模式绘制一个白色球,线粗1。
  C. 球内绘制1000个彩色圆点,原点随机改变位置,即视觉效果为躁动状态。
  D. 球内的点越靠近球顶部则越红,越靠近球底部则越蓝。
  E. 绘制彩色曲线圆圈套住球。
  F. 整个世界自动旋转,按空格键可切换旋转和暂停。

  1.2.2 执行截图

在这里插入图片描述

2 程序设计说明

2.1 向量的运算


2.1.1 头文件Cvector167.h
 向量类结构图

在这里插入图片描述
向量类程序说明:
建立CVector167类,其中包括float x,y,z,首先是重载操作符,实现[]便捷访问向量的分量,如向量v就可以通过v[]来访问v.x,并且此处的v[]可以作为左值使用。接着是加法、减法、赋值、数乘、判断相等、判断不相等的重载,其中要注意数乘操作需要满足向量在前,标量在后,如(向量v * 标量k)。为了方便生成向量,还编写了构造器CVector(x,y,z)。方法实现了如向量取模、向量点乘、向量标准化、向量赋值、向量投影、向量叉乘。

2.1.2 文件读取与向量计算、结果输出
 向量计算总体框架

在这里插入图片描述

如图所示实现了若干方法完成out.txt文件的创建,test.txt文件的读取,向量计算方法的判断,字符串转化成为向量类,将结果添加在out.txt文件末尾。

 Read函数流程图

在这里插入图片描述

Read()函数说明
第一步,打开文件输入流fin,文件输出流fout,并直接关闭fout,实现了空白文本文件out.txt的创建,假若out.txt已经存在,这一步也会清空文件内容
第二步,读取test.txt文件的一行内容,如果此行为空则结束读取循环,关闭文件fin。如果非空,那么根据规则一行向量的运算方式和一行向量数据,必然存在第二行,继续读取下一行,将这两行存入String[2]中,传递给compute函数进行计算以及输出。
由于给出的测试文件向量数量不确定,借此读取一个,计算一个,输出一个即可实现所需的要求。

 Compute函数程序流程图

在这里插入图片描述

函数的计算是程序的核心。
将传递过来的String[]的String[0] “向量XX”进行识别。
如“向量相加”会给出两个向量的信息,这时将String[1]调用getVector两次,第一次order = 0,第二次order = 1, 分别获取String[1]中的第一个向量和第二个向量。
但是诸如“向量标准化”只需要获取一个向量,此时我们传递String[1]和order = 0,即可。
获取向量后进行相应的运算,并将运算方法,运算结果输出到out.txt文件中,并且都保留两位小数,分量间以半角逗号间隔,向量间以tab间隔,行末为回车符。

 getVector函数程序流程图

在这里插入图片描述

获取向量函数是该程序的基础。
先判断order == 1与否,如果等于1则遍历String[1]得到第一个空格的位置,将空格下一个字符作为向量的起点开始遍历。
进入一个for循环,先给v[0]赋值,判断第一个字符是否为“-”,如果是我们做一个标记nagetive = -1,否则nagetive就保持初值1;为了叙述的普遍性,我们此处以“-12.63,xxx,xxx”为例:
首先第一个字符为符号,记录nagetive = -1;下一步字符为‘1’,我们将v[0]=10(初值是0),再v[0]+=‘1’-‘0’,此时第一个分量等于1;接下来下一个数字是2,1 → 110 = 10 → 10+2 = 12;如此循环直到读取到第一个非数字,即空格、回车、逗号、小数点,如果是前三者直接进行下一个分量的读取或者读取完毕,如果是小数点则给point赋值1,读取下一个字符,下一个字符为‘6’,我们进行这样的运算 12+=6/point,实现小数位的控制,计算完毕后point*=10控制下一位小数,直到此分量结束,此时将分量乘以nagetive实现正负的控制。给出的题目只有一位小数,但是为了普遍性,上述程序实现了多位的读取功能。

2.2 第二部分——图像的绘制


2.2.1 旋转的实现,空格控制旋转

在这里插入图片描述

如图所示,参考了例程,借鉴其旋转方法,键盘输入获取方法,具体实现:

首先创建三个全局变量

float seta = 0;
float seta_add = 0.1;
int space_count = 0;
分别用来控制旋转、每两次变换的差值,记录空格按下的次数。

先来说空格实现控制暂停与旋转,main函数调用glutKeyboardFunc(&myKeyboardFunc);进而调用函数
void myKeyboardFunc(unsigned char key, int x, int y);在此函数中实现空格的计数,当空格计数次为奇数时,将seta_add赋值0,即停止了旋转;当空格计数次为偶数时,seta_add赋值0.1,恢复正常旋转。

接下来是旋转的实现,main函数调用
glutTimerFunc(3, myTimerFunc, 0);进而调用函数
void myTimerFunc(int val);在此函数中实现seta值的增加,每次调用此函数增加值为seta_add,并调用
myDisplay(); 和 他自己本身glutTimerFunc(3, myTimerFunc, 0);
调用myDisplay()函数时候执行函数glRotatef(seta, 0, 1, 0);实现旋转。


2.2.2 1000个彩色光滑圆点的绘制

在这里插入图片描述

首先我们先随机产生三个处于-70,70之间的浮点数,并判断是否处于半径为70,圆心在圆点的球内,如果在球内,调用相应的函数生成该点,最终生成共计1000个点。
在生成点的同时,根据点的z值不同,赋予不同的颜色,如果z大于零,接近70的点将越红,如果z小于零,越接近-70的点将越蓝。
生成点之后,在主函数中会调用SetRc()函数,该函数会调用使点光滑的函数。

2.2.3 彩色坐标轴与白色线球的绘制

在这里插入图片描述

画坐标轴线首先指定线宽glLineWidth(2),然后开始绘制直线glBegin(GL_LINES),继续指定该轴的颜色glColor3f,以及起点glVertex3f,终点glVertex3f,最后结束绘制glEnd()。
绘制线圈球更加简单,指定颜色glColor3f(1.0f, 1.0f, 1.0f),线宽glLineWidth(1)后直接调用绘制线球函数glutWireSphere(70, 15, 15),其中数据的含义是线球的半径、经纬线条数。

2.2.4 彩色圆圈的绘制

在这里插入图片描述

首先指定线宽glLineWidth(3),接下来开始绘制直线线圈glBegin(GL_LINE_LOOP),并且指定半径为GLfloat R = 80.0f。
开始循环直线线圈节点,指定节点数为int n = 100。
写一个循环for (int i = 0; i < n; ++i),每一次循环中使用三角函数给定节点的坐标,并赋予不同但是逐渐变化的色彩。
float y = R * cos(2.0 * Pi / n * i);
float z = R * sin(2.0 * Pi / n * i);
glColor3f((i % 30) / 30.0 + 0.1, (i % 70) / 70.0 + 0.1, (i % 10) / 10.0 + 0.1);
glVertex3f(0, y, z);
最后结束直线线圈的绘制glEnd()。


CVector67.h

#pragma once



class CVector167
{
public:
	float x,y,z;
	float forth = -31415926;//第四维,赋一个几乎不用的初始值

	void Print();
	CVector167();
	CVector167(float x, float y, float z);
	void Set(float x, float y, float z);
	CVector167 operator +(const CVector167& v);
	CVector167 operator -(const CVector167& v);
	CVector167 operator =(const CVector167& v);
	bool operator ==(const CVector167& v);
	bool operator !=(const CVector167& v);
	CVector167 operator *(float k);
	float dotMul(CVector167& v);
	CVector167 crossMul(CVector167& v);
	float len();
	CVector167 Normalize();
	CVector167 project(CVector167& v);
	operator float* () { return &x; }
};





CVector67.cpp

#include "CVector167.h"
#include <math.h>
#include <iostream>

using namespace std;
void CVector167::Print() {
	if (forth == -31415926)cout << "x = " << this->x << ", y = " << this->y << ", z = " << this->z << "\n";
	else cout << "x = " << this->x << ", y = " << this->y << ", z = " << this->z << ", forth = " << this->forth << "\n";
}
CVector167::CVector167()
{
	this->x = 0;
	this->y = 0;
	this->z = 0;
};
CVector167::CVector167(float x, float y, float z)
{//构造器初始化
	this->Set(x, y, z);
}
void CVector167::Set(float x, float y, float z)
{//设初值
	this->x = x;
	this->y = y;
	this->z = z;
}


CVector167 CVector167::operator +(const CVector167& v)
{//加法重载
	CVector167 ve;
	ve.x = this->x + v.x;
	ve.y = this->y + v.y;
	ve.z = this->z + v.z;
	return ve;
}//无误2022 04 25

CVector167 CVector167::operator -(const CVector167& v)
{//减法
	CVector167 ve;
	ve.x = this->x - v.x;
	ve.y = this->y - v.y;
	ve.z = this->z - v.z;
	return ve;
}

CVector167 CVector167::operator =(const CVector167& v)
{//赋值
	this->x = v.x;
	this->y = v.y;
	this->z = v.z;
	return CVector167(v.x, v.y, v.z);
}
/*
注意!!!!!!!
此处const必须加入,否则可能会出现 向量a,b,
a = b * 2;  按照标量计算习惯应该是 a = (b * 2);
const的缺失会导致报错
*/
bool CVector167::operator ==(const CVector167& v)
{//判别相等
	if (this->x == v.x && this->y == v.y && this->z == v.z)return true;
	else return false;
}//无误,但是返回值打印的时候会变成 0 1,程序运行的时候确实是布尔值

bool CVector167::operator !=(const CVector167& v)
{//判别不等
	if (this->x != v.x || this->y != v.y || this->z != v.z)return true;
	else return false;
}

CVector167 CVector167::operator *(float k)
{//数乘 v * k 
	return CVector167(this->x * k, this->y * k, this->z * k);
}//无误,但是这个只能实现标量在后的情况

//以下函数没有const是因为老师给的参数列表的确如此
float CVector167::dotMul(CVector167& v)
{//点乘   返回float
	return (this->x * v.x + this->y * v.y + this->z * v.z);
}//无误

CVector167 CVector167::crossMul(CVector167& v)
{//向量叉乘
	return CVector167(this->y * v.z - this->z * v.y,
		this->z * v.x - this->x * v.z,
		this->x * v.y - this->y * v.x);
}//没问题

float CVector167::len()
{
	return (float)sqrt(((double)this->x * this->x) +
		((double)this->y * this->y) +
		((double)this->z * this->z));
}//此处的double是为了避免出现警告

CVector167 CVector167::Normalize()
{
	return CVector167(this->x / this->len(),
		this->y / this->len(),
		this->z / this->len());
}//无误

CVector167 CVector167::project(CVector167& v)
{//投影
	float project_length = this->dotMul(v) / v.len();

	return CVector167(v.x * (project_length / v.len()),
		v.y * (project_length / v.len()),
		v.z * (project_length / v.len()));
}//没问题

Work_01.cpp

#include "stdafx.h"
#include "glut.h"
#include "math.h"
#include "CVector167.h"

#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <fstream>//文件输入输出
#include <string>//字符串类
#include <iomanip>//保留两位小数

using namespace std;

CVector167 getVector(string s, int order);//声明
const GLfloat Pi = 3.1415926536;
float seta = 0.0;
float seta_add = 0.1;
int space_count = 0;
void myDisplay(void);

void Compute(string law_data[]) {
	ofstream fout;
	fout.open("out.txt", ios::app);//在文件末尾增加内容
	if (law_data[0] == "向量相加")
	{
		fout << setiosflags(ios::fixed) << setprecision(2) << "向量相加\n";
		CVector167 v1 = getVector(law_data[1], 0);
		CVector167 v2 = getVector(law_data[1], 1);
		CVector167 v0 = v1 + v2;

		fout << v1[0] << "," << v1[1] << "," << v1[2] << "	"/*Tab*/;
		fout << v2[0] << "," << v2[1] << "," << v2[2] << "	"/*Tab*/;
		fout << v0[0] << "," << v0[1] << "," << v0[2] << "\n";

	}
	else if (law_data[0] == "向量投影")
	{
		fout << setiosflags(ios::fixed) << setprecision(2) << "向量投影\n";
		CVector167 v1 = getVector(law_data[1], 0);
		CVector167 v2 = getVector(law_data[1], 1);
		CVector167 v0 = v1.project(v2);

		fout << v1[0] << "," << v1[1] << "," << v1[2] << "	"/*Tab*/;
		fout << v2[0] << "," << v2[1] << "," << v2[2] << "	"/*Tab*/;
		fout << v0[0] << "," << v0[1] << "," << v0[2] << "\n";
	}
	else if (law_data[0] == "向量叉乘")
	{
		fout << setiosflags(ios::fixed) << setprecision(2) << "向量叉乘\n";
		CVector167 v1 = getVector(law_data[1], 0);
		CVector167 v2 = getVector(law_data[1], 1);
		CVector167 v0 = v1.crossMul(v2);

		fout << v1[0] << "," << v1[1] << "," << v1[2] << "	"/*Tab*/;
		fout << v2[0] << "," << v2[1] << "," << v2[2] << "	"/*Tab*/;
		fout << v0[0] << "," << v0[1] << "," << v0[2] << "\n";
	}
	else if (law_data[0] == "向量点乘")
	{
		fout << setiosflags(ios::fixed) << setprecision(2) << "向量点乘\n";
		CVector167 v1 = getVector(law_data[1], 0);
		CVector167 v2 = getVector(law_data[1], 1);
		float dot = v1.dotMul(v2);

		fout << v1[0] << "," << v1[1] << "," << v1[2] << "	"/*Tab*/;
		fout << v2[0] << "," << v2[1] << "," << v2[2] << "	"/*Tab*/;
		fout << dot << "\n";
	}
	else if (law_data[0] == "向量求模")
	{
		fout << setiosflags(ios::fixed) << setprecision(2) << "向量求模\n";
		CVector167 v1 = getVector(law_data[1], 0);
		float len = v1.len();

		fout << v1[0] << "," << v1[1] << "," << v1[2] << "	"/*Tab*/;
		fout << len << "\n";
	}
	else if (law_data[0] == "向量标准化")
	{
		fout << setiosflags(ios::fixed) << setprecision(2) << "向量标准化\n";
		CVector167 v1 = getVector(law_data[1], 0);
		CVector167 v0 = v1.Normalize();

		fout << v1[0] << "," << v1[1] << "," << v1[2] << "	"/*Tab*/;
		fout << v0[0] << "," << v0[1] << "," << v0[2] << "\n";

	}
	else {
		cout << "不存在操作“" << law_data[0] << "”\n";
	}
	fout.close();
}

void Read()
{
	ifstream fin;
	fin.open("test.txt");//在run目录里面
	ofstream fout;
	fout.open("out.txt");//在run目录里面
	fout.close();//生成文件or删除文件内容

	if (!fin.is_open())
	{
		cout << "无法找到此文件!\n请将test.txt文件置于run目录中。\n";
		return;
	}

	string buff[2];
	int i = 0;
	while (getline(fin, buff[0]))
	{
		getline(fin, buff[1]);
		Compute(buff);
	}
	fin.close();
}

CVector167 getVector(string s, int order)
{//文本转化为向量
	CVector167 v(0, 0, 0);
	int begin = 0;
	if (order == 1)
	{//获取的是第二个向量的起点
		int i;
		for (i = 0; i < s.length(); i++)
			if (s[i] == ' ' || s[i] == '	'/*Tab*/)break;
		begin = i + 1;
	}
	int j = 0;//x,y,z
	int point = 0;
	int nagetive = 1;//等于1为正,等于-1为负
	for (int k = begin; k < s.length(); k++)
	{
		if (s[k] == '-')
			nagetive = -1;

		if ('0' <= s[k] && s[k] <= '9' && point == 0)
			v[j] *= 10, v[j] += s[k] - '0';//获取小数点前的数

		if (point == 0 && s[k] == '.')
			point = 10;

		if ('0' <= s[k] && s[k] <= '9' && point != 0) {
			v[j] += ((float)s[k] - '0') / point;//获取小数点后的数
			point *= 10;
		}
		if (s[k] == ',')
		{
			v[j] *= nagetive;
			point = 0;
			j++;
			continue;//下一个分量
		}

		if (s[k] == ' ' || s[k] == '	'/*Tab*/)
			break;//完毕
	}
	return v;
}

void myKeyboardFunc(unsigned char key, int x, int y) {
	if (key == ' ') 
		space_count++;
	if (space_count % 2 == 0)seta_add = 0.1;
	else seta_add = 0;
}

void myTimerFunc(int val)
{
	seta += seta_add;
	myDisplay();
	glutTimerFunc(3, myTimerFunc, 0);
}

void SetRC()//变光滑
{
	//glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
	glEnable(GL_POINT_SMOOTH);//光滑
	//glEnable(GL_BLEND);
	//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}

void myDisplay(void)
{
	glClear(GL_COLOR_BUFFER_BIT);
	glPushMatrix();
	glTranslatef(0, 0, -200);
	//glRotatef(90, 0, 1, 0);
	glRotatef(seta, 0, 1, 0);//旋转
	
	for (int count = 0; count < 1000; )
	{
		double x = -70 + 140.0 * rand() / double(RAND_MAX),
			y = -70 + 140.0 * rand() / double(RAND_MAX),
			z = -70 + 140.0 * rand() / double(RAND_MAX);
		if (x * x + y * y + z * z > 70.0 * 70)continue;
		else count++;
		
		double red, blue;
		if (z > 0) {
			red = z / 70+0.25;
			blue = 0;
		}
		else {
			red = 0;
			blue = -z / 70+0.25;
		}
		glPointSize(3.5);
		glBegin(GL_POINTS);
		glColor3f(0.05 + red, 0.30, 0.05 + blue);//
		glVertex3f(x, y, z);
		glEnd();

	}

	glLineWidth(2);//写在绘制的前面,也可以指定球线宽
	glBegin(GL_LINES);

	glColor3f(1.0f, 0.0f, 0.0f);//x轴
	glVertex3f(0, 0, 0);
	glVertex3f(100, 0, 0);

	glColor3f(0.0f, 1.0f, 0.0f);//y轴
	glVertex3f(0, 0, 0);
	glVertex3f(0, 100, 0);

	glColor3f(0.0f, 0.0f, 1.0f);;//z轴
	glVertex3f(0, 0, 0);
	glVertex3f(0, 0, 100);
	glEnd();

	glColor3f(1.0f, 1.0f, 1.0f);
	glLineWidth(1);//线宽为1
	glutWireSphere(70, 15, 15);


	glLineWidth(3);
	glBegin(GL_LINE_LOOP);
	GLfloat R = 75.0f;
	int n = 100;//圆的直线段数
	for (int i = 0; i < n; ++i)
	{
		float y = R * cos(2.0 * Pi / n * i);
		float z = R * sin(2.0 * Pi / n * i);
		glColor3f((i % 30) / 30.0 + 0.1, (i % 70) / 70.0 + 0.1, (i % 10) / 10.0 + 0.1);
		glVertex3f(0, y, z);
	}
	glEnd();

	glPopMatrix();
	glFlush();
}

void myReshape(int w, int h)
{
	GLfloat nRange = 100.0f;
	glViewport(0, 0, w, h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(60, GLfloat(w) / h, 1, 1000);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

int main(int argc, char* argv[])
{
	Read();

	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
	glutInitWindowPosition(100, 100);
	glutInitWindowSize(600, 600);
	glutCreateWindow("Work_1 刘成坤 1120200167");
	glutDisplayFunc(&myDisplay);
	
	glutTimerFunc(3, myTimerFunc, 0);//旋转
	
	glutReshapeFunc(&myReshape);

	glutKeyboardFunc(&myKeyboardFunc);//获取键盘数据
	SetRC();
	glutMainLoop();
	return 0;
}
  附件(百度云)

//有空再补
提取码:LINK

  • 1
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
实验一 OpenGL+GLUT开发平台搭建 5 小实验1: 开发环境设置 5 小实验2: 控制窗口位置和大小 6 小实验3:默认的可视化范围 6 小实验4:自定义可视化范围 7 小实验5: 几何对象变形的原因 8 小实验6: 视口坐标系及视口定义 8 小实验7:动态调整长宽比例,保证几何对象不变形 9 实验二 动画和交互 10 小实验1: 单缓冲动画技术 10 小实验2: 双缓冲动画技术 11 小实验3:键盘控制 13 小实验4:鼠标控制【试着单击鼠标左键或者右键,试着按下鼠标左键后再移动】 14 实验三 几何变换、观察变换、三维对象 16 小实验1:二维几何变换 16 小实验2:建模观察(MODELVIEW)矩阵堆栈 17 小实验3:正平行投影1 19 小实验4:正平行投影2 19 小实验5:正平行投影3 20 小实验6:透射投影1 21 小实验6:透射投影2 22 小实验7:三维对象 24 实验四 光照模型和纹理映射 26 小实验1:光照模型1----OpenGL简单光照效果的关键步骤。 26 小实验2:光照模型2----光源位置的问题 28 小实验3:光照模型3----光源位置的问题 31 小实验4:光照模型4----光源位置的问题 33 小实验5:光照模型5----光源位置的问题 35 小实验6:光照模型6----光源位置的问题 38 小实验7:光照模型7----光源位置的动态变化 40 小实验8:光照模型8----光源位置的动态变化 43 小实验9:光照模型9---光源位置的动态变化 45 小实验10:光照模型10---聚光灯效果模拟 48 小实验11:光照模型11---多光源效果模拟 50 小实验12:光照效果和雾效果的结合 53 小实验13:纹理映射初步—掌握OpenGL纹理映射的一般步骤 56 小实验13:纹理映射—纹理坐标的自动生成(基于参数的曲面映射) 59 小实验14:纹理映射—纹理坐标的自动生成(基于参考面距离) 61
计算机图形学是研究如何使用计机生成、处理和显示图像的学科。而OpenGL(Open Graphics Library)是一种跨平台的图形编程接口,它提供了一系列函数和工具,用于进行2D和3D图形的渲染和处理。 OpenGL具有以下特点: 1. 跨平台性:OpenGL可以在多个操作系统上运行,包括Windows、MacOS、Linux等。 2. 高性能:OpenGL使用硬件加速来进行图形渲染,能够实现高效的图形处理。 3. 开放性:OpenGL是一个开放标准,可以由各个厂商进行实现和扩展。 4. 简单易用:OpenGL提供了一套简单的函数接口,使得开发者可以方便地进行图形编程。 在学习OpenGL之前,你需要了解一些基础的计算机图形学概念,例如坐标系统、颜色模型、光照模型等。同时,你还需要了解一些基本的编程知识,例如C++语言。 学习OpenGL可以按照以下步骤进行: 1. 安装OpenGL开发环境:根据你所使用的操作系统,选择合适的OpenGL开发环境进行安装。 2. 学习OpenGL基础知识:学习OpenGL的基本概念、函数和工具的使用方法,了解如何创建窗口、绘制基本图形等。 3. 实践编程:通过编写简单的OpenGL程序来巩固所学知识,例如绘制简单的图形、添加光照效果等。 4. 深入学习:学习更高级的OpenGL技术,例如纹理映射、着色器编程、投影变换等。 5. 应用实践:将所学的OpenGL知识应用到实际项目中,例如游戏开发、可视化等。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值