3D游戏引擎系列七.docx

上传人:b****6 文档编号:7069508 上传时间:2023-01-16 格式:DOCX 页数:17 大小:320.12KB
下载 相关 举报
3D游戏引擎系列七.docx_第1页
第1页 / 共17页
3D游戏引擎系列七.docx_第2页
第2页 / 共17页
3D游戏引擎系列七.docx_第3页
第3页 / 共17页
3D游戏引擎系列七.docx_第4页
第4页 / 共17页
3D游戏引擎系列七.docx_第5页
第5页 / 共17页
点击查看更多>>
下载资源
资源描述

3D游戏引擎系列七.docx

《3D游戏引擎系列七.docx》由会员分享,可在线阅读,更多相关《3D游戏引擎系列七.docx(17页珍藏版)》请在冰豆网上搜索。

3D游戏引擎系列七.docx

3D游戏引擎系列七

3D游戏引擎系列七

JimBlinn在1978发表了一篇名为:

“SimulationofWrinkledSurfaces”,提出了BumpMapping这个东东。

BumpMapping通过一张HeightMap记录各象素点的高度信息,有了高度信息,就可以计算HeightMap中当前象素与周围象素的高度差,这个高度差就代表了各象素的坡度,用这个坡度信息去绕动法向量,得到最终法向量,用于光照计算。

在前面的博客中也有介绍过高光法线时介绍过TBN,在这里利用TBN渲染Bumpmapping实现原理。

GPU渲染属于可编程流水线,在使用Shader编程时首先要明白其实现原理,我们可以通过可编程流水线了解一下其原理:

上图中显示了TBNMatrix,T表示的是切向量,B表示次法线向量,N表示的是法线向量,这个也是求BumpMapping必须要计算得到的,TBNMatrix可以将其放到GPU中计算得到的。

下面我们就一步步给读者介绍其实现,只用文字很难描述清楚,还是通过图看的比较明白。

为了帮助读者理解Tangent空间向量,先给读者看一下场景中的四边形,纹理图片是要贴到四边形上的,如下图所示的效果:

图中显示的是纹理坐标的关系,左下角是(0,0),右上角是(1,1)。

现在,我们需要找到两个顶点的切线。

“S切线”点的方向的纹理坐标,“T切线”点的方向的纹理坐标。

这两个切线和法线是一个顶点的“基础”。

它们定义了一个坐标空间-“切向量空间”。

s切线,t切线和法线分别是用x,y,z轴表示的,TBN矩阵是从物体空间转换到切线空间,矩阵的表示如下所示:

(SxSySz)

(TxTyTz)

(NxNyNz)

S也是切线空间中的一种,我们也可以将其表示为Binormal,现在的主要问题是求解S,T,N向量。

先抛开GPU编程,先用C++代码实现一遍,首先定义一个类用于存储TBN,类的存储代码如下所示:

[cpp]viewplaincopy

classTORUS_VERTEX

{

public:

VECTOR3Dposition;

floats,t;

VECTOR3DsTangent,tTangent;

VECTOR3Dnormal;

VECTOR3DtangentSpaceLight;

};

结构体定义好了后,接下来,我们假设在场景中放置一个圆环,这个圆环有48个点组成,用于存储顶点和索引链表,代码类完整定义如下所示:

[cpp]viewplaincopy

#ifndefTORUS_H

#defineTORUS_H

classTORUS_VERTEX

{

public:

VECTOR3Dposition;

floats,t;

VECTOR3DsTangent,tTangent;

VECTOR3Dnormal;

VECTOR3DtangentSpaceLight;

};

classTORUS

{

public:

TORUS();

~TORUS();

boolInitTorus();

intnumVertices;

intnumIndices;

unsignedint*indices;

TORUS_VERTEX*vertices;

};

constinttorusPrecision=48;

#endif

现在开始计算圆环的顶点位置,法线,切向量空间,首先我们把圆环在XY平面上的示例图展示如下:

接下来在圆环上的材质实现法线和切向量空间的代码如下所示:

[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片

for(inti=0;i

{

vertices[i].position=VECTOR3D(1.5f,0.0f,0.0f).GetRotatedZ(i*360.0f/torusPrecision)+VECTOR3D(4.0f,0.0f,0.0f);

vertices[i].s=0.0f;

vertices[i].t=(float)i/torusPrecision;

vertices[i].sTangent.Set(0.0f,0.0f,-1.0f);

vertices[i].tTangent=VECTOR3D(0.0f,-1.0f,0.0f).GetRotatedZ(i*360.0f/torusPrecision);

vertices[i].normal=vertices[i].tTangent.CrossProduct(vertices[i].sTangent);

}

图中实现的是静止不动的圆环,利用for循环实现了TBN向量,转动后的效果计算也是类似的,下面把完整的代码给读者展现一下:

[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片

#include

#include

#include

#include"Maths/Maths.h"

#include"TORUS.h"

TORUS:

:

TORUS()

{

InitTorus();

}

TORUS:

:

~TORUS()

{

if(indices)

delete[]indices;

indices=NULL;

if(vertices)

delete[]vertices;

vertices=NULL;

}

boolTORUS:

:

InitTorus()

{

numVertices=(torusPrecision+1)*(torusPrecision+1);

numIndices=2*torusPrecision*torusPrecision*3;

vertices=newTORUS_VERTEX[numVertices];

if(!

vertices)

{

printf("Unabletoallocatememoryfortorusvertices\n");

returnfalse;

}

indices=newunsignedint[numIndices];

if(!

indices)

{

printf("Unabletoallocatememoryfortorusindices\n");

returnfalse;

}

//calculatethefirstring-innerradius4,outerradius1.5

for(inti=0;i

{

vertices[i].position=VECTOR3D(1.5f,0.0f,0.0f).GetRotatedZ(i*360.0f/torusPrecision)+

VECTOR3D(4.0f,0.0f,0.0f);

vertices[i].s=0.0f;

vertices[i].t=(float)i/torusPrecision;

vertices[i].sTangent.Set(0.0f,0.0f,-1.0f);

vertices[i].tTangent=VECTOR3D(0.0f,-1.0f,0.0f).GetRotatedZ(i*360.0f/torusPrecision);

vertices[i].normal=vertices[i].tTangent.

CrossProduct(vertices[i].sTangent);

}

//rotatethistogetotherrings

for(intring=1;ring

{

for(inti=0;i

{

vertices[ring*(torusPrecision+1)+i].position=vertices[i].position.GetRotatedY(ring*360.0f/torusPrecision);

vertices[ring*(torusPrecision+1)+i].s=2.0f*ring/torusPrecision;

vertices[ring*(torusPrecision+1)+i].t=vertices[i].t;

vertices[ring*(torusPrecision+1)+i].sTangent=vertices[i].sTangent.GetRotatedY(ring*360.0f/torusPrecision);

vertices[ring*(torusPrecision+1)+i].tTangent=vertices[i].tTangent.GetRotatedY(ring*360.0f/torusPrecision);

vertices[ring*(torusPrecision+1)+i].normal=vertices[i].normal.GetRotatedY(ring*360.0f/torusPrecision);

}

}

//calculatetheindices

for(intring=0;ring

{

for(inti=0;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*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;

}

}

returntrue;

}

以上代码实现的圆环效果是在CPU中运行得到的,它渲染的凹凸效果如下所示:

CPU上的效率没有GPU运行效率高,还是建议读者在GPU中实现出来,最后把在GPU中实现的Shader代码给读者展示一下:

[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片

//矩阵

float4x4g_matWorld:

World;

float4x4g_matWorldView:

WorldView;

float4x4g_matWorldViewProj:

WorldViewProj;

float4x4g_matInverWorldView:

InverseWorldView;

//灯光

float4g_LightPositionViewSpace;

floatg_OneOverSqrLightRadius;

float4g_EyePosition;

//材质

floatg_MaterialAmbient;

floatg_MaterialDiffuse;

floatg_MaterialSpecular;

floatg_MaterialEmissive;

floatg_MaterialShininess;

//纹理图片

textureg_texEnvMap;

textureg_texNormalMap;

textureg_texHeightMap;

floatg_fReflectivity=0.5f;

floatg_fScale=0.04f;//[0,0.05]

staticfloatg_fBias=g_fScale*0.5f;

//---------------------------------------------------------------

//Sampler

//---------------------------------------------------------------

samplerg_EnvMapSampler=sampler_state

{

Texture=;

MinFilter=Linear;

MagFilter=Linear;

MipFilter=Linear;

};

samplerg_NormalMapSampler=sampler_state

{

Texture=(g_texNormalMap);

MinFilter=Linear;

MagFilter=Linear;

MipFilter=Linear;

};

samplerg_HeightMapSampler=sampler_state

{

Texture=(g_texHeightMap);

MinFilter=Linear;

MagFilter=Linear;

MipFilter=Linear;

};

//---------------------------------------------------------------

//Utilities

//---------------------------------------------------------------

halfCalAttenuation(half3lightVec)

{

returnsaturate(1-dot(lightVec,lightVec)*g_OneOverSqrLightRadius);

}

float3x3CalInvertMatrix3X3(float3x3M)

{

floatdet=dot(cross(M[0],M[1]),M[2]);

float3x3T=transpose(M);

returnfloat3x3(

cross(T[1],T[2]),

cross(T[2],T[0]),

cross(T[0],T[1]))/det;

}

//计算TBN矩阵

float3x3CalTangentFrame(float3N)

{

float3binormal;

float3tangent;

float3c1=cross(N,float3(0.0,0.0,1.0));

float3c2=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);

returnfloat3x3(tangent,binormal,N);

}

float3CalReflect(float4position,float3normal)

{

float3Normal=mul(normalize(normal),g_matWorld);

float3PosWorld=mul(ition,g_matWorld);

float3ViewDir=normalize(PosWorld-g_EyePosition.xyz);

//returnrefract(ViewDir,Normal,.99);

returnreflect(ViewDir,Normal);

}

//---------------------------------------------------------------

//vertex&pixelshader

//---------------------------------------------------------------

structVS_OUTPUT_ENV

{

float4position:

POSITION;

float3texRefCoord:

TEXCOORD0;

};

VS_OUTPUT_ENVVS_EnvMapping(float4position:

POSITION,float3normal:

NORMAL)

{

VS_OUTPUT_ENVOUT=(VS_OUTPUT_ENV)0;

OUT.position=mul(position,g_matWorldViewProj);

OUT.texRefCoord=CalReflect(position,normal);

returnOUT;

}

float4PS_EnvMapping(float3tex:

TEXCOORD0):

COLOR0

{

returng_fReflectivity*texCUBE(g_EnvMapSampler,tex);

}

//---------------------------------------------------------------

structVS_OUTPUT

{

float4position:

POSITION;

float3normal:

TEXCOORD0;

float2texCoord:

TEXCOORD1;

float3worldViewPos:

TEXCOORD2;

float3texRefCoord:

TEXCOORD3;

};

VS_OUTPUTVS_NormalMapping(float4pos:

POSITION,float3normal:

NORMAL,float2texCoord:

TEXCOORD0)

{

VS_OUTPUToutData=(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=CalReflect(pos,normal);

returnoutData;

}

float4PS_Phong(VS_OUTPUTinData):

COLOR0

{

half3lightVec=g_LightPositionViewSpace-inData.worldViewPos;

half3eyeVec=-inData.worldViewPos;

half3normal=normalize(inData.normal);

half3lightDir=normalize(lightVec);

half3eyeDir=normalize(eyeVec);

half3halfDir=normalize(eyeDir+lightDir);

half3light=lit(dot(lightDir,normal),dot(halfDir,normal),g_MaterialShininess);

halfatten=CalAttenuation(lightVec);

float4Id=light.y*g_MaterialDiffuse;

float4Is=light.z*g_MaterialSpecular;

float4envColor=g_fReflectivity*texCUBE(g_EnvMapSampler,inData.texRefCoord);

float4Ia=envColor*g_MaterialAmbient;

return(Ia+Id+Is)*atten*envColor;

}

float4PS_NormalMapping(VS_OUTPUTinData):

COLOR0

{

half3lightVec=g_LightPositionViewSpace-inData.worldViewPos;

half3eyeVec=-inData.worldViewPos;

//getthenormalmnormalmap

half3normal=normalize(tex2D(g_NormalMapSampler,inData.texCoord).xyz*2.0-1.0);

//transformthevectorfromworldspacetotangentspace

float

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 表格模板 > 合同协议

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

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