ImageVerifierCode 换一换
格式:DOCX , 页数:17 ,大小:320.12KB ,
资源ID:7069508      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/7069508.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(3D游戏引擎系列七.docx)为本站会员(b****6)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

3D游戏引擎系列七.docx

1、3D游戏引擎系列七3D游戏引擎系列七Jim Blinn在1978发表了一篇名为:“Simulationof Wrinkled Surfaces”,提出了Bump Mapping这个东东。BumpMapping通过一张Height Map记录各象素点的高度信息,有了高度信息,就可以计算HeightMap中当前象素与周围象素的高度差,这个高度差就代表了各象素的坡度,用这个坡度信息去绕动法向量,得到最终法向量,用于光照计算。在前面的博客中也有介绍过高光法线时介绍过TBN,在这里利用TBN渲染Bumpmapping实现原理。 GPU渲染属于可编程流水线,在使用Shader编程时首先要明白其实现原理,我

2、们可以通过可编程流水线了解一下其原理:上图中显示了TBNMatrix,T表示的是切向量,B表示次法线向量,N表示的是法线向量,这个也是求Bump Mapping必须要计算得到的,TBN Matrix可以将其放到GPU中计算得到的。下面我们就一步步给读者介绍其实现,只用文字很难描述清楚,还是通过图看的比较明白。为了帮助读者理解Tangent 空间向量,先给读者看一下场景中的四边形,纹理图片是要贴到四边形上的,如下图所示的效果:图中显示的是纹理坐标的关系,左下角是(0,0),右上角是(1,1)。现在,我们需要找到两个顶点的切线。“S切线”点的方向的纹理坐标,“T切线”点的方向的纹理坐标。这两个切线

3、和法线是一个顶点的“基础”。它们定义了一个坐标空间-“切向量空间”。s 切线,t切线和法线分别是用x,y,z轴表示的,TBN矩阵是从物体空间转换到切线空间,矩阵的表示如下所示:( Sx Sy Sz )( Tx Ty Tz )( Nx Ny Nz )S也是切线空间中的一种,我们也可以将其表示为Binormal,现在的主要问题是求解S,T,N向量。先抛开GPU编程,先用C+代码实现一遍,首先定义一个类用于存储TBN,类的存储代码如下所示:cpp view plain copyclass TORUS_VERTEX public: VECTOR3D position; float s, t; VECT

4、OR3D sTangent, tTangent; VECTOR3D normal; VECTOR3D tangentSpaceLight; ; 结构体定义好了后,接下来,我们假设在场景中放置一个圆环,这个圆环有48个点组成,用于存储顶点和索引链表, 代码类完整定义如下所示:cpp view plain copy#ifndef TORUS_H #define TORUS_H class TORUS_VERTEX public: VECTOR3D position; float s, t; VECTOR3D sTangent, tTangent; VECTOR3D normal; VECTOR3D

5、 tangentSpaceLight; ; class TORUS public: TORUS(); TORUS(); bool InitTorus(); int numVertices; int numIndices; unsigned int * indices; TORUS_VERTEX * vertices; ; const int torusPrecision=48; #endif 现在开始计算圆环的顶点位置,法线,切向量空间,首先我们把圆环在XY平面上的示例图展示如下:接下来在圆环上的材质实现法线和切向量空间的代码如下所示:cpp view plain copy 在CODE上查看代

6、码片派生到我的代码片for(int i=0; itorusPrecision+1; i+) verticesi.position=VECTOR3D(1.5f, 0.0f, 0.0f).GetRotatedZ(i*360.0f/torusPrecision)+VECTOR3D(4.0f, 0.0f, 0.0f); verticesi.s=0.0f; verticesi.t=(float)i/torusPrecision; verticesi.sTangent.Set(0.0f, 0.0f, -1.0f); verticesi.tTangent=VECTOR3D(0.0f, -1.0f, 0.0f

7、).GetRotatedZ(i*360.0f/torusPrecision); verticesi.normal=verticesi.tTangent.CrossProduct(verticesi.sTangent); 图中实现的是静止不动的圆环,利用for循环实现了TBN向量,转动后的效果计算也是类似的,下面把完整的代码给读者展现一下:cpp view plain copy 在CODE上查看代码片派生到我的代码片#include #include #include #include Maths/Maths.h #include TORUS.h TORUS:TORUS() InitTorus(

8、); TORUS:TORUS() if(indices) delete indices; indices=NULL; if(vertices) delete vertices; vertices=NULL; bool TORUS:InitTorus() numVertices=(torusPrecision+1)*(torusPrecision+1); numIndices=2*torusPrecision*torusPrecision*3; vertices=new TORUS_VERTEXnumVertices; if(!vertices) printf(Unable to allocat

9、e memory for torus verticesn); return false; indices=new unsigned intnumIndices; if(!indices) printf(Unable to allocate memory for torus indicesn); return false; /calculate the first ring - inner radius 4, outer radius 1.5 for(int i=0; iusPrecision+1; i+) verticesi.position=VECTOR3D(1.5f, 0.0f, 0.0f

10、).GetRotatedZ(i*360.0f/torusPrecision)+ VECTOR3D(4.0f, 0.0f, 0.0f); verticesi.s=0.0f; verticesi.t=(float)i/torusPrecision; verticesi.sTangent.Set(0.0f, 0.0f, -1.0f); verticesi.tTangent=VECTOR3D(0.0f, -1.0f, 0.0f).GetRotatedZ(i*360.0f/torusPrecision); verticesi.normal=verticesi.tTangent. CrossProduct

11、(verticesi.sTangent); /rotate this to get other rings for(int ring=1; ringtorusPrecision+1; ring+) for(int i=0; itorusPrecision+1; i+) verticesring*(torusPrecision+1)+i.position=verticesi.position.GetRotatedY(ring*360.0f/torusPrecision); verticesring*(torusPrecision+1)+i.s=2.0f*ring/torusPrecision;

12、verticesring*(torusPrecision+1)+i.t=verticesi.t; verticesring*(torusPrecision+1)+i.sTangent=verticesi.sTangent.GetRotatedY(ring*360.0f/torusPrecision); verticesring*(torusPrecision+1)+i.tTangent=verticesi.tTangent.GetRotatedY(ring*360.0f/torusPrecision); verticesring*(torusPrecision+1)+i.normal=vert

13、icesi.normal.GetRotatedY(ring*360.0f/torusPrecision); /calculate the indices for(int ring=0; ringtorusPrecision; ring+) for(int i=0; itorusPrecision; i+) indices(ring*torusPrecision+i)*2)*3+0=ring*(torusPrecision+1)+i; indices(ring*torusPrecision+i)*2)*3+1=(ring+1)*(torusPrecision+1)+i; indices(ring

14、*torusPrecision+i)*2)*3+2=ring*(torusPrecision+1)+i+1; indices(ring*torusPrecision+i)*2+1)*3+0=ring*(torusPrecision+1)+i+1; indices(ring*torusPrecision+i)*2+1)*3+1=(ring+1)*(torusPrecision+1)+i; indices(ring*torusPrecision+i)*2+1)*3+2=(ring+1)*(torusPrecision+1)+i+1; return true; 以上代码实现的圆环效果是在CPU中运行

15、得到的,它渲染的凹凸效果如下所示:CPU上的效率没有GPU运行效率高,还是建议读者在GPU中实现出来,最后把在GPU中实现的Shader代码给读者展示一下:cpp view plain copy 在CODE上查看代码片派生到我的代码片/ 矩阵 float4x4 g_matWorld : World; float4x4 g_matWorldView : WorldView; float4x4 g_matWorldViewProj : WorldViewProj; float4x4 g_matInverWorldView : InverseWorldView; / 灯光 float4 g_Ligh

16、tPositionViewSpace; float g_OneOverSqrLightRadius; float4 g_EyePosition; / 材质 float g_MaterialAmbient; float g_MaterialDiffuse; float g_MaterialSpecular; float g_MaterialEmissive; float g_MaterialShininess; / 纹理图片 texture g_texEnvMap; texture g_texNormalMap; texture g_texHeightMap; float g_fReflecti

17、vity = 0.5f; float g_fScale = 0.04f; / 0, 0.05 static float g_fBias = g_fScale * 0.5f; / - / Sampler / - sampler g_EnvMapSampler = sampler_state Texture = ; MinFilter = Linear; MagFilter = Linear; MipFilter = Linear; ; sampler g_NormalMapSampler = sampler_state Texture = (g_texNormalMap); MinFilter

18、= Linear; MagFilter = Linear; MipFilter = Linear; ; sampler g_HeightMapSampler = sampler_state Texture = (g_texHeightMap); MinFilter = Linear; MagFilter = Linear; MipFilter = Linear; ; / - / Utilities / - half CalAttenuation(half3 lightVec) return saturate(1 - dot(lightVec, lightVec) * g_OneOverSqrL

19、ightRadius); float3x3 CalInvertMatrix3X3(float3x3 M) float det = dot(cross(M0, M1), M2); float3x3 T = transpose(M); return float3x3( cross(T1, T2), cross(T2, T0), cross(T0, T1) / det; /计算TBN矩阵 float3x3 CalTangentFrame(float3 N) float3 binormal; float3 tangent; float3 c1 = cross(N, float3(0.0, 0.0, 1

20、.0); float3 c2 = cross(N, float3(0.0, 1.0, 0.0); if(length(c1)length(c2) tangent = c1; else tangent = c2; tangent = normalize(tangent); binormal = cross(N, tangent); binormal = normalize(binormal); return float3x3(tangent, binormal, N); float3 CalReflect(float4 position, float3 normal) float3 Normal

21、 = mul(normalize(normal), g_matWorld); float3 PosWorld = mul(ition, g_matWorld); float3 ViewDir = normalize(PosWorld - g_EyePosition.xyz); /return refract(ViewDir, Normal, .99); return reflect(ViewDir, Normal); / - / vertex & pixel shader / - struct VS_OUTPUT_ENV float4 position : POSITION; float3 t

22、exRefCoord : TEXCOORD0; ; VS_OUTPUT_ENV VS_EnvMapping(float4 position : POSITION, float3 normal : NORMAL) VS_OUTPUT_ENV OUT = (VS_OUTPUT_ENV)0; OUT.position = mul(position, g_matWorldViewProj); OUT.texRefCoord = CalReflect(position, normal); return OUT; float4 PS_EnvMapping(float3 tex : TEXCOORD0) :

23、 COLOR0 return g_fReflectivity * texCUBE(g_EnvMapSampler, tex); / - struct VS_OUTPUT float4 position : POSITION; float3 normal : TEXCOORD0; float2 texCoord : TEXCOORD1; float3 worldViewPos : TEXCOORD2; float3 texRefCoord : TEXCOORD3; ; VS_OUTPUT VS_NormalMapping(float4 pos : POSITION, float3 normal

24、: NORMAL, float2 texCoord : TEXCOORD0) VS_OUTPUT outData = (VS_OUTPUT)0; outData.position = mul(pos, g_matWorldViewProj); outData.normal = normalize(mul(normal, (float3x3)g_matWorldView); outData.texCoord = texCoord; outData.worldViewPos = mul(pos, g_matWorldView).xyz; outData.texRefCoord = CalRefle

25、ct(pos, normal); return outData; float4 PS_Phong(VS_OUTPUT inData) : COLOR0 half3 lightVec = g_LightPositionViewSpace - inData.worldViewPos; half3 eyeVec = -inData.worldViewPos; half3 normal = normalize(inData.normal); half3 lightDir = normalize(lightVec); half3 eyeDir = normalize(eyeVec); half3 hal

26、fDir = normalize(eyeDir + lightDir); half3 light = lit(dot(lightDir, normal), dot(halfDir, normal), g_MaterialShininess); half atten = CalAttenuation(lightVec); float4 Id = light.y * g_MaterialDiffuse; float4 Is = light.z * g_MaterialSpecular; float4 envColor = g_fReflectivity * texCUBE(g_EnvMapSamp

27、ler, inData.texRefCoord); float4 Ia = envColor * g_MaterialAmbient; return (Ia + Id + Is) * atten * envColor; float4 PS_NormalMapping(VS_OUTPUT inData) : COLOR0 half3 lightVec = g_LightPositionViewSpace - inData.worldViewPos; half3 eyeVec = -inData.worldViewPos; / get the normal m normal map half3 normal = normalize(tex2D(g_NormalMapSampler, inData.texCoord).xyz * 2.0 - 1.0); / transform the vector from world space to tangent space float

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1