用球体模拟天空

之前说到可以用球体作为Sky Dome模拟天空,那么就来说一说其中的细节.

Sky Dome就是天空穹顶,是一种在三维场景中模拟天空的方法,用Sky Dome模拟的天空较Sky Box更为逼真,对应用Sky Box的场景采用雾效果很容易穿帮,而Sky Dome不会,因为Sky Box是方形从视点到各个顶点的距离不相等,Sky Dome则是球体,把视点设置为球体中心则到各个顶点的距离相等,雾效果的可见程度与视点到顶点的距离有直接关系.

那么来看看这么用之前的球体模型模拟Sky Dome吧.

之前已经给球体建了个模,现在的问题是怎么把天空贴图贴到球体上去,这将会用到一种新的贴图方法Cubemap以及着色器. 先看一下效果如何:

嗯,效果就是这样.现在看下具体是怎么实现的:

首先要了解Cubemap的原理,具体的教程网上有很多,可以搜索一些来看,这边讨论一下天空穹顶的实现细节.

先准备6张图,Cubemap需要6张贴图分别是:

  • GL_TEXTURE_CUBE_MAP_POSITIVE_X?
  • GL_TEXTURE_CUBE_MAP_NEGATIVE_X?
  • GL_TEXTURE_CUBE_MAP_POSITIVE_Y?
  • GL_TEXTURE_CUBE_MAP_NEGATIVE_Y?
  • GL_TEXTURE_CUBE_MAP_POSITIVE_Z?
  • GL_TEXTURE_CUBE_MAP_NEGATIVE_Z?

这6张图各自在四个方向上必须与相邻的四张贴图是连续的,这样才不会导致穿帮. 使用以下方法创建Cubemap:

bool loadCubemapTexture(const char* xpos,const char* xneg,
		const char* ypos,const char* yneg,
		const char* zpos,const char* zneg,
		GLuint& id) {
	BmpLoader bmpXpos,bmpXneg,bmpYpos,bmpYneg,bmpZpos,bmpZneg;

	if(!bmpXpos.loadBitmap((char*)xpos)||
			!bmpXneg.loadBitmap((char*)xneg)||
			!bmpYpos.loadBitmap((char*)ypos)||
			!bmpYneg.loadBitmap((char*)yneg)||
			!bmpZpos.loadBitmap((char*)zpos)||
			!bmpZneg.loadBitmap((char*)zneg)) {
		printf("loadBitmap error\n");
		return false;
	}

	glGenTextures(1,&id);
	glBindTexture(GL_TEXTURE_CUBE_MAP,id);

	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);

	glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X,0,GL_RGB,
			bmpXpos.bitInfo->biWidth,bmpXpos.bitInfo->biHeight
			,0,GL_RGB,GL_UNSIGNED_BYTE,bmpXpos.image);
	glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X,0,GL_RGB,
			bmpXneg.bitInfo->biWidth,bmpXneg.bitInfo->biHeight
			,0,GL_RGB,GL_UNSIGNED_BYTE,bmpXneg.image);
	glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y,0,GL_RGB,
			bmpYpos.bitInfo->biWidth,bmpYpos.bitInfo->biHeight
			,0,GL_RGB,GL_UNSIGNED_BYTE,bmpYpos.image);
	glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,0,GL_RGB,
			bmpYneg.bitInfo->biWidth,bmpYneg.bitInfo->biHeight
			,0,GL_RGB,GL_UNSIGNED_BYTE,bmpYneg.image);
	glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z,0,GL_RGB,
			bmpZpos.bitInfo->biWidth,bmpZpos.bitInfo->biHeight
			,0,GL_RGB,GL_UNSIGNED_BYTE,bmpZpos.image);
	glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,0,GL_RGB,
			bmpZneg.bitInfo->biWidth,bmpZneg.bitInfo->biHeight
			,0,GL_RGB,GL_UNSIGNED_BYTE,bmpZneg.image);

	return true;
}

注意从此开始这6张贴图属于同一个Cubemap对象,它们是一个整体.

	initCubemapTexture(YZ_PATH,YZ_PATH,XZ_PATH,XZ_PATH,
			XY_PATH,XY_PATH,CUBE_MAP_TEXTURE);

现在这个Cubemap对象的名字叫做CUBE_MAP_TEXTURE.

使用glBindTexture(GL_TEXTURE_CUBE_MAP,CUBE_MAP_TEXTURE)我们就可以使用这个纹理对象了.等一下,纹理有了但是还没有纹理坐标.

让我们看一下OpenGL官方网站是怎么说的:

The texture coordinates for cubemaps are 3D vector directions. These are conceptually directions from within the cube defined by the cubemap, pointing in a particular direction.

嗯,Cubemap的纹理坐标是一个3d向量,并非是传统纹理坐标的2d向量, 应该是从球体中心到球体表面上的向量,如图所示:

看明白了吧,那么来看一下Shader又是怎么写的:

Vertex Shader:

varying vec3 texCoord;

void main() {
	texCoord = vec3(gl_Vertex.x, gl_Vertex.y, gl_Vertex.z);
	texCoord = normalize(texCoord);
	gl_Position = ftransform();
}

Fragment Shader:

uniform samplerCube texCube;

varying vec3 texCoord;

void main() {
    gl_FragColor = textureCube(texCube, texCoord);
}

接着编写渲染代码:

	useShader(shaderTex);
	glBindTexture(GL_TEXTURE_CUBE_MAP,CUBE_MAP_TEXTURE);

	glPushMatrix();
	glTranslatef(0,-10,-200);
	glScalef(100,100,100);
	sphere->render();
	glPopMatrix();

先使用坐标轴贴图,让我们看看效果对不对:

呦,效果不对,xy轴反了,怎么办?修改Vertex Shader!

varying vec3 texCoord;

void main() {
	texCoord = vec3(gl_Vertex.x, -gl_Vertex.y, -gl_Vertex.z);
	texCoord = normalize(texCoord);
	gl_Position = ftransform();
}

嗯,这样就对了,然后换上天空贴图就行了. 还在等什么,赶紧试一试呗!

时间: 2024-11-03 00:54:41

用球体模拟天空的相关文章

建一座安全的“天空城” ——揭秘腾讯WeTest如何与祖龙共同挖掘手游安全漏洞

作者:腾讯WeTest手游安全测试团队商业转载请联系腾讯WeTest获得授权,非商业转载请注明出处. WeTest导读 <九州天空城3D>上线至今,长期稳定在APP Store畅销排行的前五,本文将介绍腾讯WeTest手游安全团队在游戏上线前为<九州天空城3D>挖掘安全漏洞的全过程. <九州天空城3D>(下文简称<九州>)是祖龙娱乐的一款正版授权次世代3D飞行手游,在8月,正式向全平台开放.作为一个前身是端游研发工作室的研发商,祖龙娱乐在<九州>

天空因尘埃而蔚蓝

一束阳关照进教室,老师指着那束阳光问我们:"阳光中有什么?" 阳光是透明的,阳光中会有什么呢?我们说:"什么也没有.""真的什么也没有吗?你们再仔细看看." 于是我们班全体同学一个个瞪大眼睛盯着那束阳光,我们终于发现,阳光中有许许多多细小的尘埃在飞舞. "有尘埃!"我们齐声回答. "这些尘埃会导致什么结果呢?" "污染空气." "你们只说对了其一."老师说,"

【更新】【封装必备】封装辅助 - 清理&amp;优化工具 For Win7(IT天空会员专版)

https://www.itsk.com/thread-353560-1-4.html nqawen 发表于 2015-7-9 17:26:37   本帖最后由 Amz 于 2015-11-25 10:07 编辑 [运行界面预览]<ignore_js_op> <ignore_js_op> <ignore_js_op> [介绍]曾经看到有些兄弟封装win7系统,清理优化类工具多达十来种,本人也玩封装,常用的工具就是Dism++ ,然后就是本人之前发过的 封装辅助 - 减肥

游戏架构其九:光线投射和天空 { Raycast and Sky }

光线和天空能够大大增强游戏的画面效果,以下是实现: 1. 光线效果 Raycast #pragma once //======================================================================== // Raycast.h - implements a raycast into the rendered scene //==========================================================

一个民族需要关注天空的人

作者:姚国华(华中科技大学哲学系教授)原编者按:真正的大学精神何在?大学是人格养成之所,是人文精神的摇篮,是理性和良知的支撑.蔡元培说,大学者,研究高深学问者也.为囊括大典,网罗众学之学府.按此标准,今天,大学需要反思.庸俗.功利.虚无侵蚀了大学学生及教员的思想.官僚本位.僵化学术机制以及对商业和技术的迷恋,让大学创造之源干涸.有人说,中国的大学已失去了脊梁,泯灭了精神,只余下赤裸裸的追名逐利.更有人说,中国20多年来根本没有大学,有的只是一个“打工仔岗前培训机构”.本报特别策划“追寻缺失的大学

【COGS1049】天空中的繁星

[题目背景] 第二届『Citric』杯NOIP提高组模拟赛 第二题 [题目描述] Lemon最近买了一台数码相机.某天Lemon很无聊,于是对着夜空拍了一张照片,然后把照片导入了电脑.Lemon想依靠电脑的力量,完成他小时候经常做却从来没有成功过的事情:数天空中有多少颗星星.Lemon已经把相片处理成了黑白的,也就是说,每个像素只可能是两个颜色之一,白或黑.Lemon定义像素(x,y)处是一颗星星,当且仅当,像素(x,y),(x-1,y),(x+1,y),(x,y-1),(x,y+1)都是白色的

描写天空的比喻句和拟人句

描写天空的比喻句和拟人句 天空红得像一片快要烧成灰烬的炭火. 今天,天气放晴,万里无云,整个天空像洗过一样. 红日西沉,天色逐渐暗了下来.西边的天空,燃起了一片火红的晚霞-- 天空的色彩真是美妙呀!近似一处橙色,西边一片红色,把深蓝天空映照得格外艳丽. 暗蓝色的夜空上,斜挂着一叶月牙儿,周围有几丝白云在飘移,月牙儿发出淡淡的白光,就像一只白色的小帆船在深蓝色的大海中飘流,飘呀!飘呀!小船将会飘到西天去. 我和爸爸来到桥头,仰望星空,那密密麻麻的星星使我眼花缭乱. (造句 www.zaojuzi.

天空象棋——网站与用户

上一篇文章<天空象棋——冲上云霄>介绍了如何把天空象棋的算法服务发布到Azure上,以及提供了一个使用该云服务的象棋客户端.这次的任务是为天空象棋在Azure上创建一个网站,并且提供用户注册.登陆的功能.涉及以下知识点: 在Azure上创建网站 使用Visual Studio发布自定义网站 使用SQL Server Management Studio连接Azure数据库服务器 为网站提供Membership服务 创建天空象棋网站 登陆Azure管理网站,依次点击“+NEW”,“COMPUTE”

《逐梦旅程 WINDOWS游戏编程之从零开始》笔记10——三维天空的构建&amp;三维粒子的实现&amp;多游戏模型的载入

第23章 三维天空的构建 目前描述三维天空的技术主要包括三种类型,直接来介绍使用最广泛的模拟技术,详细的描述可以见作者的博文. 天空盒(Sky Box),即放到场景的是一个立方体.它是目前使用最广泛的三维天空模拟技术,网络上素材丰富,所以这次就用教大家用天空盒来模拟三维天空.天空盒经常是由24个顶点.六个面组成的立方体(或者直接从做好的X模型文件载入天空盒),并经常会随着视点的移动而移动,来刻画极远处玩家无法达到位置的天空 天空盒的设计 1.准备天空盒纹理素材 天空盒的纹理自然就是我们这个天空盒