3D游戏引擎系列八

标签: 3d引擎3d渲染GPUShader
1178人阅读 评论(3) 收藏 举报
分类:

笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,国家专利发明人;已出版书籍:《手把手教你架构3D游戏引擎》电子工业出版社和《Unity3D实战核心技术详解》电子工业出版社等。

CSDN课程视频网址:http://edu.csdn.net/lecturer/144

环境映射在材质的渲染上同样应用广泛,现实生活中我们也经常遇到环境映射,比如一个光滑的铁球上可以映射出周围环境。它的实现方式就是把周围的环境通过反射,折射映射到3D物体表面的材质上,给人非常炫酷的感觉。实现方式有两种:一种是通过美工做一张环境映射贴图实现环境映射;第二种方式是美工做六张贴图实现环境映射。Unity实现方式采用的是后者,本节实现的是第一种方式,第二种方式可以借鉴Unity的立方体纹理,Unity实现效果如下图:


通过六张贴图就可以把环境映射的效果展现出来,这种方式同样适用于天空盒的实现。本节是通过一张贴图实现环境映射效果,接下来还是新建一个文本文件,将其扩展名改成.fx。完整代码如下所示:

float4x4 matWorldViewPrj;
float4x4 matWorld;
float4x4 matView;
float3 eyePos;

texture cubeMapTexture;
texture sphereMapTexture;

//--
struct VS_INPUT
{
	float3 pos		: POSITION;
	float3 normal : NORMAL;
};

struct VS_OUTPUT
{
	float4 pos : POSITION;
	float3 cubeTex	: TEXCOORD0;
};

VS_OUTPUT my_vs(VS_INPUT vert)
{
	VS_OUTPUT vsout;
	vsout.pos = mul(float4(vert.pos,1),matWorldViewPrj);
	
	float3 worldPos = mul(float4(vert.pos,1),matWorld);
	float3 worldNormal = normalize(mul(vert.normal,matWorld));
		
	float3 viewDir = normalize(worldPos - eyePos);
	
	vsout.cubeTex = reflect(viewDir, worldNormal);
	
	return vsout;
}

//--
samplerCUBE cubeMap = sampler_state
{
	Texture = <cubeMapTexture>;
	MipFilter = LINEAR;
    MinFilter = LINEAR;
    MagFilter = LINEAR;
};

float4 my_ps(float3 cubeTex	: TEXCOORD0) : COLOR
{
	return texCUBE(cubeMap,cubeTex);
}

//--
technique myCubeEnvMap
{
	pass p0
	{
		VertexShader = compile vs_1_1 my_vs();
		PixelShader = compile ps_2_0 my_ps();
	}
}

//--
struct VS_OUTPUT_Sphere
{
	float4 pos : POSITION;
	float2 sphereTex	: TEXCOORD0;
};

VS_OUTPUT_Sphere my_sphere_vs(VS_INPUT vert)
{
	VS_OUTPUT_Sphere vsout;
	
	vsout.pos = mul(float4(vert.pos,1),matWorldViewPrj);
	
	float3 viewNormal = mul(vert.normal,matWorld);
	viewNormal = mul(viewNormal,matView);
	viewNormal = normalize(viewNormal);
		
	vsout.sphereTex = float2(viewNormal.x/2+0.5,viewNormal.y/2+0.5);
	
	return vsout;
}

sampler sphereMap = sampler_state
{
	Texture = <sphereMapTexture>;
	MipFilter = LINEAR;
    MinFilter = LINEAR;
    MagFilter = LINEAR;
};

float4 my_sphere_ps(float2 sphereTex	: TEXCOORD0
			) : COLOR
{
	return tex2D(sphereMap,sphereTex);
}

technique mySphereEnvMap
{
	pass p0
	{
		VertexShader = compile vs_1_1 my_sphere_vs();
		PixelShader = compile ps_2_0 my_sphere_ps();
	}
}

相比上一个CelShading卡通渲染Shader,在函数:

VS_OUTPUT my_vs(VS_INPUT vert)

增加了反射函数reflect语句如下:

float3 viewDir = normalize(worldPos - eyePos);vsout.cubeTex = reflect(viewDir, worldNormal)

计算中的反射和折射不需要程序手工计算,直接调用Shader的库函数就可以实现,但是原理还是要搞清楚。在该Shader中实现了两种效果:分别是立方体和球体,Shader实现方面也分了两个Technique,每个Technique有一个pass通道分别是关于立方体映射和球体映射。这里面涉及到两张贴图的渲染,一个是环境平面材质的渲染,另一个是球体的环境材质渲染。C++要实现此效果,需要两张贴图,第一张贴图是环境贴图,第二张是球贴图如下所示:




立方体环境映射渲染效果如图:


其在引擎内部的调用与前面CelShading的编写代码类似,这里就不介绍了。C++主要是调用不同的Technique以达到不同的渲染处理方式,代码语句如下:

m_pEffect->SetTechnique("myCubeEnvMap");

这条语句是默认的通道,可以通过if else条件语句去切换立方体和球体映射,换句话说就是调用不同的Technique技术,因为GPU一次只能执行一个Technique。



0
1

猜你在找
【视频】C语言及程序设计(讲师:贺利坚)
【视频】Python爬虫工程师培养课程全套(讲师:韦玮)
【视频】Python全栈开发入门与实战(讲师:李杰)
【视频】2017软考网络规划设计师套餐(讲师:任铄)
【视频】2017软考软件设计师套餐(讲师:任铄)
【视频】2017软考信息系统项目管理师套餐(讲师:任铄)
【视频】软考(高级)项目经理实战营(讲师:张传波)
【视频】微信公众平台开发套餐(讲师:刘运强)
深度学习原理+实战+算法+主流框架套餐(讲师:唐宇迪)
2017系统集成项目管理工程师通关套餐(讲师:徐朋)
查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:191323次
    • 积分:3790
    • 等级:
    • 排名:第8283名
    • 原创:176篇
    • 转载:1篇
    • 译文:0篇
    • 评论:124条
    著作书籍
    《Unity3D实战核心技术详解》电子工业出版社 《手把手教你架构3D游戏引擎》电子工业出版社
    博客专栏
    最新评论