NeHe OpenGL第九课:移动图像

第九课:移动图像

 

 


 

3D空间中移动图像:

你想知道如何在3D空间中移动物体,你想知道如何在屏幕上绘制一个图像,而让图像的背景色变为透明,你希望有一个简单的动画。这一课将教会你所有的一切。前面的课程涵盖了基础的OpenGL,每一课都是在前一课的基础上创建的。这一课是前面几课知识的综合,当你学习这课时,请确保你已经掌握了前面几课的知识。

 

欢迎进入第九课。到现在为止,您应该很好的理解OpenGL了。您已经学会了设置一个OpenGL窗口的每个细节。学会在旋转的物体上贴图并打上光线以及混色(透明)处理。这一课应该算是第一课中级教程。您将学到如下的知识:在3D场景中移动位图,并去除位图上的黑色象素(使用混色)。接着为黑白纹理上色,最后您将学会创建丰富的色彩,并把上过不同色彩的纹理相互混合,得到简单的动画效果。
我们在第一课的代码基础上进行修改。先在程序源码的开始处增加几个变量。出于清晰起见,我重写了整段代码。

 

#include	<stdio.h>		// 标准输入输出库头文件
#include	<glaux.h>	// GLaux库的头文件

下列这几行新加的。twinkle和 tp是布尔变量, 表示它们只能设为 TRUE 或 FALSE。 twinkle用来跟踪 闪烁 效果是否启用。 tp用来检查 'T'键有没有被按下或松开. (按下时 tp=TRUE, 松开时 tp=FALSE).

 

BOOL	twinkle;	 // 闪烁的星星
BOOL	tp;	 // 'T' 按下了么? 

 num 跟踪屏幕上所绘制的星星数。这个数字被定义为一个常量。这意味着无法在以后的代码中对其进行修改。这么做的原因是因为您无法重新定义一个数组。因此,如果我们定义一个50颗星星的数组,然后又将num增加到51的话,就会出错。不过您还是可以(也只可以)在这一行上随意修改这个数字。但是以后请您别再改动 num 的值了,除非您想看见灾难发生。

 

const	num=50;	 // 绘制的星星数

现在我们来创建一个结构。 结构这词听起来有点可怕,但实际上并非如此。 一个结构使用一组简单类型的数据 (以及变量等)来表达较大的具有相似性的数据组合。 我们知道我们在保持对星星的跟踪。 您可以看到下面的第七行就是 stars;并且每个星星有三个整型的色彩值。第三行 int r,g,b设置了三个整数. 一个红色 (r), 一个绿色 (g), 以及一个蓝色 (b). 此外,每个星星离屏幕中心的距离不同, 而且可以是以屏幕中心为原点的任意360度中的一个角度。如果你看下面第四行的话, 会发现我们使用了一个叫做 dist的浮点数来保持对距离 的跟踪. 第五行则用一个叫做 angle的浮点数保持对星星角度值的跟踪。
因此我们使用了一组数据来描述屏幕上星星的色彩, 距离, 和角度。 不幸的是我们不止对一个星星进行跟踪。但是无需创建 50 个红色值、 50 个绿色值、 50 个蓝色值、 50 个距离值 以及 50 个角度值,而只需创建一个数组star。 star数组的每个元素都是stars类型的,里面存放 了描述星星的所有数据。star数组在下面的第八行创建。 第八行的样子是这样的: stars star[num]。数组类型是 stars结构. 所数组 能存放所有stars结构的信息。 数组名字是 star. 数组大小是 [num]。 数组中存放着 stars结构的元素. 跟踪结构元素会比跟踪各自分开的变量容易的多. 不过这样也很笨, 因为我们竟然不能改变常量 num来增减星星 数量。

typedef struct // 为星星创建一个结构
{
	int r, g, b;	 // 星星的颜色
	GLfloat dist; // 星星距离中心的距离
	GLfloat angle; // 当前星星所处的角度
}stars; // 结构命名为stars
stars star[num]; // 使用 'stars' 结构生成一个包含 'num'个元素的 'star'数组

接下来我们设置几个跟踪变量:星星离观察者的距离变量(zoom),我们所见到的星星所处的角度(tilt),以及使闪烁的星星绕Z轴自转的变量spin。
loop变量用来绘制50颗星星。texture[1]用来存放一个黑白纹理。如果您需要更多的纹理的话,您应该增加texture数组的大小至您决定采用的纹理个数。

GLfloat	zoom=-15.0f; // 星星离观察者的距离
GLfloat tilt=90.0f; // 星星的倾角
GLfloat	spin; // 闪烁星星的自转
GLuint	loop; // 全局 Loop 变量
GLuint	texture[1]; // 存放一个纹理

紧接着上面的代码就是我们用来载入纹理的代码。我不打算再详细的解释这段代码。这跟我们在第六、七、八课中所用的代码是一模一样的。这一次载入的位图叫做star.bmp。这里我们使用glGenTextures(1, &texture[0]),来生成一个纹理。纹理采用线性滤波方式。

AUX_RGBImageRec *LoadBMP(char *Filename) // 载入位图文件
{
	FILE *File=NULL; // 文件句柄
	if (!Filename) // 确认已给出文件名
	{
		return NULL; // 若无返回 NULL
	}

	File=fopen(Filename,"r"); // 检查文件是否存在

	if (File)				
	{
		fclose(File); // 关闭文件句柄
		return auxDIBImageLoad(Filename); // 载入位图并返回指针
	}
	return NULL; // 如果载入失败返回 NULL
}

下面的代码(调用上面的代码)载入位图,并转换成纹理。变量用来跟踪纹理是否已载入并创建好了。

int LoadGLTextures() // 载入位图并转换成纹理
{
	int Status=FALSE; // 状态指示器

	AUX_RGBImageRec *TextureImage[1]; // 为纹理分配存储空间

	memset(TextureImage,0,sizeof(void *)*1); // 将指针设为 NULL
	// 载入位图,查错,如果未找到位图文件则退出
	if (TextureImage[0]=LoadBMP("Data/Star.bmp"))
	{
		Status=TRUE; // 将 Status 设为TRUE

		glGenTextures(1, &texture[0]); // 创建一个纹理

		// 创建一个线性滤波纹理
		glBindTexture(GL_TEXTURE_2D, texture[0]);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
	}

	if (TextureImage[0])			
	{
		if (TextureImage[0]->data)		
		{
			free(TextureImage[0]->data);	// 释放纹理图像所占的内存
		}

		free(TextureImage[0]);// 释放图像结构
	}

	return Status;// 返回 Status的值
}

现在设置OpenGL的渲染方式。这里不打算使用深度测试,如果您使用第一课的代码的话,请确认是否已经去掉了 glDepthFunc(GL_LEQUAL); 和 glEnable(GL_DEPTH_TEST);两行。否则,您所见到的效果将会一团糟。这里我们使用了纹理映射,因此请您确认您已经加上了这些第一课中所没有的代码。您会注意到我们通过混色来启用了纹理映射。

int InitGL(GLvoid) // 此处开始对OpenGL进行所有设置
{
	if (!LoadGLTextures()) // 调用纹理载入子例程
	{
		return FALSE; // 如果未能载入,返回FALSE
	}

	glEnable(GL_TEXTURE_2D); // 启用纹理映射
	glShadeModel(GL_SMOOTH); // 启用阴影平滑
	glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // 黑色背景
	glClearDepth(1.0f); // 设置深度缓存
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);// 真正精细的透视修正
	glBlendFunc(GL_SRC_ALPHA,GL_ONE); // 设置混色函数取得半透明效果
	glEnable(GL_BLEND); // 启用混色

以下是新增的代码。设置了每颗星星的起始角度、距离、和颜色。您会注意到修改结构的属性有多容易。全部50颗星星都会被循环设置。要改变star[1]的角度我们所要做的只是star[1].angle={某个数值};就这么简单!

for (loop=0; loop<num; loop++)// 创建循环设置全部星星
{
	star[loop].angle=0.0f;// 所有星星都从零角度开始

第loop颗星星离中心的距离是将loop的值除以星星的总颗数,然后乘上5.0f。基本上这样使得后一颗星星比前一颗星星离中心更远一点。这样当loop为50时(最后一颗星星),loop 除以 num正好是1.0f。之所以要乘以5.0f是因为1.0f*5.0f 就是 5.0f。5.0f已经很接近屏幕边缘。我不想星星飞出屏幕,5.0f是最好的选择了。当然如果如果您将场景设置的更深入屏幕里面的话,也许可以使用大于5.0f的数值,但星星看起来就更小一些(都是透视的缘故)。
您还会注意到每颗星星的颜色都是从0~255之间的一个随机数。也许您会奇怪为何这里的颜色得取值范围不是OpenGL通常的0.0f~1.0f之间。这里我们使用的颜色设置函数是glColor4ub,而不是以前的glColor4f。ub意味着参数是Unsigned Byte型的。一个byte的取值范围是0~255。这里使用byte值取随机整数似乎要比取一个浮点的随机数更容易一些。        

	star[loop].dist=(float(loop)/num)*5.0f;// 计算星星离中心的距离
	star[loop].r=rand()%256;// 为star[loop]设置随机红色分量
	star[loop].g=rand()%256;// 为star[loop]设置随机红色分量
	star[loop].b=rand()%256;// 为star[loop]设置随机红色分量
}
return TRUE;// 初始化一切OK
}

Resize的代码也是一样的,现在我们转入绘图代码。如果您使用第一课的代码,删除旧的DrawGLScene代码,只需将下面的代码复制过去就行了。实际上,第一课的代码只有两行,所以没太多东西要删掉的。

int DrawGLScene(GLvoid) // 此过程中包括所有的绘制代码
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// 清除屏幕及深度缓存
	glBindTexture(GL_TEXTURE_2D, texture[0]);// 选择纹理

	for (loop=0; loop<num; loop++) // 循环设置所有的星星
	{
		glLoadIdentity(); // 绘制每颗星星之前,重置模型观察矩阵
		glTranslatef(0.0f,0.0f,zoom); // 深入屏幕里面
		glRotatef(tilt,1.0f,0.0f,0.0f); // 倾斜视角

现在我们来移动星星。星星开始时位于屏幕的中心。我们要做的第一件事是把场景沿Y轴旋转。如果我们旋转90度的话,X轴不再是自左至右的了,他将由里向外穿出屏幕。为了让大家更清楚些,举个例子。假想您站在房子中间。再设想您左侧的墙上写着-x,前面的墙上写着-z,右面墙上就是+x咯,您身后的墙上则是+z。加入整个房子向右转90度,但您没有动,那么前面的墙上将是-x而不再是-z了。所有其他的墙也都跟着移动。-z出现在右侧,+z出现在左侧,+x出现在您背后。神经错乱了吧?通过旋转场景,我们改变了x和z平面的方向。
第二行代码沿x轴移动一个正值。通常x轴上的正值代表移向了屏幕的右侧(也就是通常的x轴的正向),但这里由于我们绕y轴旋转了坐标系,x轴的正向可以是任意方向。如果我们转180度的话,屏幕的左右侧就镜像反向了。因此,当我们沿 x轴正向移动时,可能向左,向右,向前或向后。

glRotatef(star[loop].angle,0.0f,1.0f,0.0f);// 旋转至当前所画星星的角度
glTranslatef(star[loop].dist,0.0f,0.0f);// 沿X轴正向移动

接着的代码带点小技巧。星星实际上是一个平面的纹理。现在您在屏幕中心画了个平面的四边形然后贴上纹理,这看起来很不错。一切都如您所想的那样。但是当您当您沿着y轴转上个90度的话,纹理在屏幕上就只剩右侧和左侧的两条边朝着您。看起来就是一条细线。这不是我们所想要的。我们希望星星永远正面朝着我们,而不管屏幕如何旋转或倾斜。
我们通过在绘制星星之前,抵消对星星所作的任何旋转来实现这个愿望。您可以采用逆序来抵消旋转。当我们倾斜屏幕时,我们实际上以当前角度旋转了星星。通过逆序,我们又以当前角度"反旋转"星星。也就是以当前角度的负值来旋转星星。就是说,如果我们将星星旋转了10度的话,又将其旋转-10度来使星星在那个轴上重新面对屏幕。下面的第一行抵消了沿y轴的旋转。然后,我们还需要抵消掉沿x轴的屏幕倾斜。要做到这一点,我们只需要将屏幕再旋转-tilt倾角。在抵消掉x和y轴的旋转后,星星又完全面对着我们了。

glRotatef(-star[loop].angle,0.0f,1.0f,0.0f); // 取消当前星星的角度
glRotatef(-tilt,1.0f,0.0f,0.0f); // 取消屏幕倾斜

如果 twinkle 为 TRUE,我们在屏幕上先画一次不旋转的星星:将星星总数(num) 减去当前的星星数(loop)再减去1,来提取每颗星星的不同颜色(这么做是因为循环范围从0到num-1)。举例来说,结果为10的时候,我们就使用10号星星的颜色。这样相邻星星的颜色总是不同的。这不是个好法子,但很有效。最后一个值是alpha通道分量。这个值越小,这颗星星就越暗。
由于启用了twinkle,每颗星星最后会被绘制两遍。程序运行起来会慢一些,这要看您的机器性能如何了。但两遍绘制的星星颜色相互融合,会产生很棒的效果。同时由于第一遍的星星没有旋转,启用twinkle后的星星看起来有一种动画效果。

 值得注意的是给纹理上色是件很容易的事。尽管纹理本身是黑白的,纹理将变成我们在绘制它之前选定的任意颜色。此外,同样值得注意的是我们在这里使用的颜色值是byte型的,而不是通常的浮点数。甚至alpha通道分量也是如此。

if (twinkle)// 启用闪烁效果
{
	// 使用byte型数值指定一个颜色
	glColor4ub(star[(num-loop)-1].r,star[(num-loop)-1].g,star[(num-loop)-1].b,255);
	glBegin(GL_QUADS);// 开始绘制纹理映射过的四边形
	glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,-1.0f, 0.0f);
	glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,-1.0f, 0.0f);
	glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 0.0f);
	glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 0.0f);
	glEnd();// 四边形绘制结束
}

现在绘制第二遍的星星。唯一和前面的代码不同的是这一遍的星星肯定会被绘制,并且这次的星星绕着z轴旋转。

glRotatef(spin,0.0f,0.0f,1.0f);// 绕z轴旋转星星
// 使用byte型数值指定一个颜色
glColor4ub(star[loop].r,star[loop].g,star[loop].b,255);
glBegin(GL_QUADS);// 开始绘制纹理映射过的四边形
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,-1.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,-1.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 0.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 0.0f);
glEnd();// 四边形绘制结束

以下的代码代表星星的运动。我们增加spin的值来旋转所有的星星(公转)。然后,将每颗星星的自转角度增加loop/num。这使离中心更远的星星转的更快。最后减少每颗星星离屏幕中心的距离。这样看起来,星星们好像被不断地吸入屏幕的中心。

spin+=0.01f;// 星星的公转
star[loop].angle+=float(loop)/num;// 改变星星的自转角度
star[loop].dist-=0.01f;// 改变星星离中心的距离

接着几行检查星星是否已经碰到了屏幕中心。当星星碰到屏幕中心时,我们为它赋一个新颜色,然后往外移5个单位,这颗星星将踏上它回归屏幕中心的旅程。

	if (star[loop].dist<0.0f)// 星星到达中心了么
	{
		star[loop].dist+=5.0f;// 往外移5个单位
		star[loop].r=rand()%256;// 赋一个新红色分量
		star[loop].g=rand()%256;// 赋一个新绿色分量
		star[loop].b=rand()%256;// 赋一个新蓝色分量
	}
}
return TRUE;// 一切正常
}

现在我们添加监视键盘的代码。下移到WinMain()。找到SwapBuffers(hDC)一行。我们就在这一行后面增加键盘监视代码。
代码将检查T键是否已按下。如果T键按下过,并且又放开了,if块内的代码将被执行。如果twinkle为FALSE,他将变为TRUE。反之亦然。只要T键按下, tp就变为TRUE。这样处理可以防止如果您一直按着T键的话,块内的代码被反复执行。

SwapBuffers(hDC);	// 切换缓冲
if (keys['T'] && !tp)	// 是否T 键已按下并且 tp值为 FALSE
{
	tp=TRUE;	// 若是,将tp设为TRUE
	twinkle=!twinkle;// 翻转 twinkle的值
}

下面的代码检查是否松开了T键。若是,使 tp=FALSE。除非tp的值为FALSE,否则按着T键时什么也不会发生。所以这行代码很重要。

if (!keys['T'])// T 键已松开了么?
{
	tp=FALSE;// 若是 ,tp为 FALSE
}

剩下的代码检查上、下方向键,向上翻页键或向下翻页键是否按下。

if (keys[VK_UP])// 上方向键按下了么?
{
	tilt-=0.5f;	// 屏幕向上倾斜
}
if (keys[VK_DOWN])	// 下方向键按下了么?
{
	tilt+=0.5f;	// 屏幕向下倾斜
}
if (keys[VK_PRIOR])	// 向上翻页键按下了么
{
	zoom-=0.2f;// 缩小
}
if (keys[VK_NEXT])	// 向下翻页键按下了么?
{
	zoom+=0.2f;// 放大
}

像以前一样,确认窗口的标题是否正确。

	if (keys[VK_F1])// F1键按下了么?
	{
		keys[VK_F1]=FALSE;// 若是,使对应的Key数组中的值为 FALSE
		KillGLWindow();// 销毁当前的窗口
		fullscreen=!fullscreen;// 切换 全屏 / 窗口 模式
		// 重建 OpenGL 窗口
		if (!CreateGLWindow("NeHe's 透明纹理实例",640,480,16,fullscreen))
		{
			return 0;	// 如果窗口未能创建,程序退出
		}
	}
}
}

 

原文及其个版本源代码下载:

http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=09             

Qt5版NeHe OpenGL教程之八:3D空间中移动图像        欢迎进入第八课。到现在为止,您应该很好的理解OpenGL了。您已经学会了设置一个OpenGL窗口的每个细节。学会在旋转的物体上贴图并打上光线以及混色(透明)处理。       这一课应该算是第一课中级教程。您将学到如下的知识:在3D场景中移动位图,并去除位图上的黑色象素(使用混色)。接着为黑白纹理上色,最后您将学会创建丰富的色彩,并把上过不同色彩的纹理相互混合,得到简单的动画效果。l... 阅读详情

相关推荐

NeHe OpenGL教程:从入门到精通

本文还有配套的精品资源,点击获取 简介:OpenGL是一个广泛应用于多个领域的图形编程接口,NeHe OpenGL教程为初学者提供了一系列指导,帮助掌握OpenGL的基础知识和高级特性。教程包含在NeHe_OpenGL.chm帮助文件中,详细讲解了OpenGL环境设置、基本图形渲染、光照、纹理映射等内容。此外,还提供了一个文本文件***.txt,可能包含了额外资源和社区讨论...

weixin_30765637的博客 1674

OpenGL学习笔记(九)图片缩放、移动、旋转

程序效果: 源码如下 main.c #include &amp;lt;glad/glad.h&amp;gt; #include &amp;lt;GLFW/glfw3.h&amp;gt; #include &amp;lt;cmath&amp;gt; #include &amp;lt;iostream&amp;gt; #include &amp;lt;fstream&amp;gt; #include &amp;

czhzasui的博客 3423

Nehe的OpenGL教程电子书

创建一个OpenGL窗口: 在这个教程里,我将教你在Windows环境中创建OpenGL程序.它将显示一个空的OpenGL窗口,可以在窗口和全屏模式下切换,按ESC退出.它是我们以后应用程序的框架. 理解OpenGL如何工作非常重要,你可以在教程的末尾下载源程序,但我强烈建议你至少读一遍教程,然后再开始编程. 2.你的第一个多边形: 在第一个教程的基础上,我们添加了一个三角形和一个四边形。也许你认为这很简单,但你已经迈出了一大步,要知道任何在OpenGL中绘制的模型都会被分解为这两种简单的图形。 读完了这一课,你会学到如何在空间放置模型,并且会知道深度缓存的概念。 3.添加颜色: 作为第二课的扩展,我将叫你如何使用颜色。你将理解两种着色模式,在左图中,三角形用的是光滑着色,四边形用的是平面着色。 注意三角形上的颜色是如何混合的。 颜色为OpenGlL 工程增加很多。通过理解平面着色(flat coloring)和平滑着色(smooth coloring),你能显著的改善你的OpenGL Demo的样子。 4.旋转: 在这一课里,我将教会你如何旋转三角形和四边形。左图中的三角形沿Y轴旋转,四边形沿着X 轴旋转。 这一章将引入两个变量, rtri 被用来存储三角形的角度, rquad存储四边形的角度。 和容易创建一个多边形组成的场景。让这些物体动起来是整个场景变得生动起来。在后面的课程钟我将教给你如何绕屏幕上的一个点旋转物体,使得物体绕屏幕而不是它的轴转动。 5.3D形体: 既然我们已经领会到多边形,方形,色彩和旋转。现在该建立3D物体了。我将使用多边形和矩形c创建3D物体。这次我们将扩展上一章的教程,并且将三角形转换成一个彩色的棱锥,把正方形变为一个实心正方体。棱锥使用混合色,正方体每个面使用一种颜色。在3D空间创建物体可能很费时间,但是所获得的结果(收获)值得这样做。充分发挥你的想象力吧。 6.纹理映射: 你想要它,它现在就在这里了,那就是 ... 纹理映射!!!在这一章我将教会你如何将一幅位图(bitmap)映射到正方体的六个面上去。我们将使用第一章的OpenGL代码来创建工程。创建一个空的窗口比修改上一课的代码更容易。 你将会发现第一章的代码在对于快速创建工程来说是及其有价值的。第一章的代码为你设置好了一切,你所需要做的只是集中精力为效果编程。 7.纹理滤波, 光照和键盘控制: 好的,我希望到现在你已经理解了所有的东西,因为这是一个巨大的教程。我想教给你两个新的方法来过滤(filter)你的纹理,简单的光照,键盘控制并且还可能更多 :) .如果你对到这一课为止你所学的东西并不充满信心,那就回头复习一下。玩一下其它课程的代码,不要操之过急。最好专心把每一课学好,而不是蜻蜓点水,只知道如何把东西做出来。 8.混合 有理由等一下,一个来自很酷的Hypercosm的程序员伙伴问(我)他是否可以写一章关于混合的教程。第八课通常正是讲混合的,所以太巧了。这一章教程扩展了第七章。混合是一项很酷的技术 .. 我希望你们能好好享受这一章教程。这一章的作者是Tom Stanis他在这制作一章上花费了很多精力,所以让他知道你觉得怎么样。混合可不是一个好讲的话题。 9.在3D空间中移动位图: 这一章覆盖了一些你们要求的主题,你想知道如何移动你在3D屏幕空间上创造的物体。你想要知道如何在屏幕上绘制一幅位图,并且位图的黑色部分不会覆盖它后面的东西。你想要简单的动画,想要更多的混合的应用,这一章将教会你所有这些。You'll notice there's no spinning boxes(yaker:很惭愧这一句我不是很明白)。前面的课程覆盖了OpenGL的基础,每一章都基于前面的内容。前面的课程涵盖了基础的OpenGL,每一课都是在前一课的基础上创建的。这一课是前面几课知识的综合,当你学习这课时,请确保你已经掌握了前面几课的知识。 10.加载3D世界,并在其中漫游: 你一直期待的教程来了!这一章友一个叫Lionel Brites的伙伴制作。这一课里你讲学到如何导入一个3D世界。代码仍然使用第一章的,但是,课程页面只是解释了新的部分,包括导入3D场景,在3D世界中移动。下载VC++代码并且在你阅读教程的同时阅读代码。按[B]键控制混合,[F]键控制滤波,[L]键控制光照(但光并不随场景移动),还有[Page UP]和[Page Down]键。我希望你能喜欢Lionel对网站的贡献。我有空的时候我会让这个教程更容易学习。 11.旗帜效果

Andriod OpenGL 教程 09 - 移动图像

关键字: android OpenGL 移动开发 教程           这一课我们将利用以前学到的知识,做一个简单的动画,显示在空间运动的星星。 在这一课,您将学到如下的知识:在3D场景中移动位图,并去除位图上的黑色象素(使用混色)。接着为黑白纹理上色,最后您将学会创建丰富的色彩,并把上过不同色彩的纹理相互混合,得到简单的动画效果。         我们将绘制一些在空中旋转和闪烁的星星

seniorwizard的专栏 1076

OpenGL-Nehe完整中文教程.pdf

OpenGL-Nehe完整中文教程.pdf

如何加快香山处理器Chisel->Verilog编译速度

相比使用默认的scala firrtl complier,使用CIRCT能够将香山代码编译到Verilog的速度提高50%左右。在执行make命令时加上MFC=1,例如make verilog MFC=1或make emu MFC=1。在本地从源码编译CIRCT,在编译完成后将circt/bin路径加入PATH中。使用GraalVM免费版作为JVM编译香山比OpenJDK快10%-20%。我们推荐使用GraalVM代替OpenJDK。使用CIRCT编译香山。

专业技术人员的归宿 862

NeHe OpenGL教程 (九)

第09课      3D空间中移动图像:你想知道如何在3D空间中移动物体,你想知道如何在屏幕上绘制一个图像,而让图像的背景色变为透明,你希望有一个简单的动画。这一课将教会你所有的一切。前面的课程涵盖了基础的OpenGL,每一课都是在前一课的基础上创建的。这一课是前面几课知识的综合,当你学习这课时,请确保你已经掌握了前面几课的知识。    欢迎进入第九课。到现在为止,您应该很

Welcom to zougangx's blog 823

中国1986-2024年30米分辨率年最大NDVI数据集:条带修复技术与植被动态监测

本文介绍了中国1986-2024年30米分辨率年最大NDVI数据集的构建,重点阐述了针对Landsat 7 SLC-off故障等问题的条带修复技术。通过应用GapFill等核心算法,该数据集有效修复了数据缺失,为长时间序列的植被动态监测、生态变迁分析和极端气候事件评估提供了高质量、连续可靠的数据基础。

weixin_29200485的博客 167

opengles(四)让图像动起来

之前画的三角型是无法与用户交互的,为了使交互过程变得更好玩,我们需要监听触摸事件,让图像跟随我们的触摸一起动起来。首先,我们需要重写触摸事件 onTouchEvent ,并且我们想在触摸发生变化时才进行渲染,所以设置渲染模式为 RENDERMODE_WHEN_DIRTY ,在 onTouchEvent 调用 requestRender 来渲染。private final float TOUCH_SC

jackyqiziheng的专栏 787

【Ragflow】9.问答为什么比搜索响应慢?从源码角度深入分析

前几天看到有群友提到一个现象:Ragflow的搜索界面的问答速度很快,但聊天界面的问答速度很慢,究竟是什么原因?在深入挖掘源码之后,逐渐发现了问题的答案。

兴趣使然的创作者 2900

Windows11 下 Detectron2 的安装与配置全攻略

本文提供了在Windows11系统下安装和配置Detectron2的完整教程。详细介绍了从环境准备、创建虚拟环境、安装PyTorch与CUDA,到修改源码、编译安装以及运行验证Demo的全过程,帮助开发者克服Windows平台上的常见问题,成功部署这一强大的计算机视觉库。

weixin_29081703的博客 245

NeHe OpenGL教程 第九课:移动图像

转自【翻译】NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改。对NeHe的OpenGL管线教程的编写,以及yarn的翻译整理表示感谢。   NeHe OpenGL第九课:移动图像 3D空间中移动图像: 你想知道如何在3D空间中移动物体,你想知道如何在屏幕上绘制一个图像,...

weixin_33860528的博客 103

05 SAP CPI 访问第一个CPI接口

其中的clientid的值可作为Basic验证的用户名,clientsecret的值可作为Basic验证的密码。点击SEND按钮,可看见返回状态为200 OK。在04中,我们得到TOKEN令牌。POSTMAN向下滚动。点击按钮获取token。

SAP CPI 662

NeHe OpenGL教程 第九课:移动图像 代码

#include &lt;windows.h&gt; // Windows的头文件 #include &lt;glew.h&gt; // 包含最新的gl.h,glu.h库 #include &lt;glut.h&gt; // 包含OpenGL实用库 #include &lt;stdio.h&gt; // 标准输入/输出库的头文件 #include &lt;glaux.h&gt; ...

u011955875的博客 363

STM32入门教程:智能马桶盖控制

通过编写相应的代码,您可以根据需要实现其他功能,例如座圈温度调节和液晶显示屏显示等。初始化配置 首先,使用STM32CubeMX创建一个新的工程,并选择您所使用的STM32单片机型号。智能马桶盖是一种集成了多种功能的智能家居设备,通过控制芯片来实现自动冲水、座圈加热、座圈温度调节等功能。在本教程中,我们将使用STM32系列单片机来控制智能马桶盖的各个功能。以上代码演示了如何通过STM32的GPIO控制引脚来控制智能马桶盖的冲水和座圈加热功能。写代码 接下来,我们将通过编写代码来控制智能马桶盖的各个功能。

2401_85258012的博客 657

手把手教你从入门到精通C# Modbus通信

本文是《Modbus通信从入门到精通》的导读,本专栏将会详细介绍ModusRTU 、ModbusASCII、ModbusTCP这三种协议的C#实现,由一个高级工程师多年实战经验总结而成,绝对干货!

qq_34059233的博客 1万+

NeHe_OpenGL_第九课 3D空间中移动图像

http://52coding.com/nehe-3d-space-picture-moving 我将上下左右改成键盘上wsad的控制,好多天没学习OpenGL,忘记了specialKeyboard如何使用了。按下t键开启闪烁效果(我就感觉亮了一些) #include "stdafx.h" #define GLUT_DISABLE_ATEXIT_HACK #include "glaux

延陵小明 1846

cursor AI代码编辑器IDE对接deepseek模型api;字节ai编辑器trae

参考: https://www.cursor.com/ https://platform.deepseek.com/https://www.cursor.com/下载安装后,注册账号登录即可 再高级里选择设置 再模型这注册模型: 模型名称一定要填正确,url地址填好,最后填上秘钥验证

weixin_42357472的博客 1万+

ArchieOpenGL基础教程第九课:光照和键盘

参考Nehe教程第7课 在上节基础上继续。 ----------------------------------------------------- 这一课我会教您如何使用三种不同的纹理滤波方式。教您如何使用键盘来移动场景中的对象,还会教您在OpenGL场景中应用简单的光照。这一课包含了很多内容,如果您对前面的课程有疑问的话,先回头复习一下。进入后面的代码之前,很好的理解基础知识十分重要。

可乐鸡翅 1012

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

android toast的用法,Android第九课 Toast 用法注意事项

优点:l 与JDBC相比较减少了61%的代码量(不知道怎么算的这么准:>>)l&nbsp...PYTHON的线程一、线程例: import threading&nb...6.8 ln 。link快捷方式ln -s 源文件名称 目标文件名称 :软连接ln 源文件名称 目标文件名称 :硬连接(相当于复...

weixin_29826413的博客 221

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

OpenGL之路(十)绚丽的移动动画

效果绚丽的动画效果,可闪光,w键和s键旋转,r 键控制闪光开关 代码如下: #include <gl/glut.h> #include <gl/glaux.h> #include <stdio.h> #pragma comment(lib, "opengl32.lib") #pragma comment(lib, "glut32.lib") #pra...

weixin_30667649的博客 829

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

NeHe的OpenGL教程笔记

大一寒假的时候对OpenGL产生了兴趣,但那会根本看不懂这个教程。大三寒假之前看了20课的代码,但是交了计算机图形学的大作业后就又搁置了。这次重新拾起,希望可以全部看完,并整理一下每节教程的内容。 第1课,介绍了一个OpenGL在Win32下面的框架。和普通的Win32程序不一样的是在一个循环中使用PeekMessage(),而不是GetMessage(),然后在没有消息时,调用DrawGLSce...

RayoNicks的博客 1339
上一篇: Android/Ophone应用程序数字签名
下一篇: Android\OPhone自定义视图(View)
yarin
博客等级 码龄17年 35粉丝 68原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值