镜面反射和运动模糊效果图:
镜面反射渲染过程:
1. 正常渲染镜子。
2. 打开模板测试(测试方式为始终通过)。重复渲染一次镜子,使模板缓存中的镜子区域的缓存值为&H1(其余区域为&H0)。
3. 修改模板测试方式(模板缓存中像素模板值为&H1时,才通过测试),渲染球体镜像。这时球体镜像在镜子外面的部分将不会通过模板测试而不会被渲染
4. 关闭模板测试,正常渲染球体。
程序中添加了Motion Blur(运动模糊)效果。实现方式为:
1. 计算出球体的当前位置和当前速度(当前速度为根据实际当前速度进行缩放得到)。
2. 根据即时速度修改球体的位置,在新的位置重画一次球体,每次重画时增加球体的透明度
渲染过程代码如下:
Private Sub Render()
CurrentPosition.x = 5 * Sin(Timer * 2) //计算当前位置
CurrentPosition.y = 0
CurrentPosition.z = 0
CurrentSpeed.x = Cos(Timer * 2) / 4 //计算当前速度
CurrentSpeed.y = 0
CurrentSpeed.z = 0
Dim v As CUSTOMVERTEX
Dim sizeOfVertex As Long
Dim Mtrl As D3DMATERIAL8
Dim Col As D3DCOLORVALUE
sizeOfVertex = Len(v)
g_D3DDevice.Clear 0, ByVal 0, D3DCLEAR_TARGET Or D3DCLEAR_ZBUFFER Or D3DCLEAR_STENCIL, &HB5B5FF, 1#, 0
g_D3DDevice.BeginScene
//设置矩阵
Dim matWorld As D3DMATRIX
Dim matView As D3DMATRIX
Dim matProj As D3DMATRIX
Dim TempMat As D3DMATRIX
D3DXMatrixLookAtLH matView, vec3(15#, 2#, 10#), vec3(0#, 0#, 0#), vec3(0#, 1#, 0#)
D3DXMatrixPerspectiveFovLH matProj, g_pi / 4#, 1#, 1, 150
D3DXMatrixIdentity TempMat
g_D3DDevice.SetTransform D3DTS_WORLD, TempMat
g_D3DDevice.SetTransform D3DTS_VIEW, matView
g_D3DDevice.SetTransform D3DTS_PROJECTION, matProj
//正常渲染镜子
g_D3DDevice.SetStreamSource 0, g_MirrorVB, sizeOfVertex
g_D3DDevice.SetVertexShader D3DFVF_CUSTOMVERTEX
g_D3DDevice.DrawPrimitive D3DPT_TRIANGLESTRIP, 0, 2
//开启模板缓存,再次渲染镜子,使模板缓存中的镜子区域缓存值为&H1
g_D3DDevice.SetRenderState D3DRS_STENCILENABLE, True
g_D3DDevice.SetRenderState D3DRS_STENCILFUNC, D3DCMP_ALWAYS
g_D3DDevice.SetRenderState D3DRS_STENCILREF, &H1
g_D3DDevice.SetRenderState D3DRS_STENCILMASK, &HFFFFFFFF
g_D3DDevice.SetRenderState D3DRS_STENCILWRITEMASK, &HFFFFFFFF
g_D3DDevice.SetRenderState D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP
g_D3DDevice.SetRenderState D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP
g_D3DDevice.SetRenderState D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE
//关闭Z缓存写入,但Z比较照常进行
g_D3DDevice.SetRenderState D3DRS_ZWRITEENABLE, False
g_D3DDevice.SetRenderState D3DRS_ALPHABLENDENABLE, True
g_D3DDevice.SetRenderState D3DRS_SRCBLEND, D3DBLEND_ZERO
g_D3DDevice.SetRenderState D3DRS_DESTBLEND, D3DBLEND_ONE
g_D3DDevice.SetStreamSource 0, g_MirrorVB, sizeOfVertex
g_D3DDevice.SetVertexShader D3DFVF_CUSTOMVERTEX
g_D3DDevice.DrawPrimitive D3DPT_TRIANGLESTRIP, 0, 2
//打开Z写入,修改模板测试方式,渲染球体镜像
g_D3DDevice.SetRenderState D3DRS_ZWRITEENABLE, True
g_D3DDevice.Clear 0, ByVal 0, D3DCLEAR_ZBUFFER, 0, 1#, 0
g_D3DDevice.SetRenderState D3DRS_STENCILFUNC, D3DCMP_EQUAL
g_D3DDevice.SetRenderState D3DRS_STENCILPASS, D3DSTENCILOP_KEEP
g_D3DDevice.SetRenderState D3DRS_SRCBLEND, D3DBLEND_SRCALPHA
g_D3DDevice.SetRenderState D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA
Dim ReflectM As D3DMATRIX
Dim Plane As D3DPLANE
Plane.a = 0
Plane.b = 0
Plane.c = 1
Plane.d = 2
D3DXMatrixReflect ReflectM, Plane
g_D3DDevice.SetTransform D3DTS_WORLD, matWorld
D3DXMatrixMultiply ReflectM, ReflectM, matView
g_D3DDevice.SetTransform D3DTS_VIEW, ReflectM
g_D3DDevice.SetRenderState D3DRS_CULLMODE, D3DCULL_CW
g_D3DDevice.SetStreamSource 0, g_VB, sizeOfVertex
g_D3DDevice.SetVertexShader D3DFVF_CUSTOMVERTEX
//实现镜像运动模糊效果
For i = 1 To 10
Col.a = 1 / (i * i): Col.b = 1: Col.g = 1: Col.r = 1
Mtrl.diffuse = Col
Mtrl.specular = Col
Mtrl.power = 200
g_D3DDevice.SetMaterial Mtrl
D3DXMatrixTranslation TempMat, CurrentPosition.x - CurrentSpeed.x * i, CurrentPosition.y - CurrentSpeed.y * i, CurrentPosition.z - CurrentSpeed.z * i
g_D3DDevice.SetTransform D3DTS_WORLD, TempMat
For j = 0 To 39
g_D3DDevice.DrawPrimitive D3DPT_TRIANGLESTRIP, j * 80, 78
Next j
Next i
//关闭模板测试,渲染球体
g_D3DDevice.SetRenderState D3DRS_STENCILENABLE, False
g_D3DDevice.SetRenderState D3DRS_CULLMODE, D3DCULL_CCW
g_D3DDevice.SetTransform D3DTS_VIEW, matView
g_D3DDevice.SetRenderState D3DRS_SRCBLEND, D3DBLEND_SRCALPHA
g_D3DDevice.SetRenderState D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA
g_D3DDevice.SetStreamSource 0, g_VB, sizeOfVertex
g_D3DDevice.SetVertexShader D3DFVF_CUSTOMVERTEX
//实现球体运动模糊效果
For i = 1 To 10
Col.a = 1 / (i * i): Col.b = 1: Col.g = 1: Col.r = 1
Mtrl.diffuse = Col
Mtrl.specular = Col
Mtrl.power = 200
g_D3DDevice.SetMaterial Mtrl
D3DXMatrixTranslation TempMat, CurrentPosition.x - CurrentSpeed.x * i, CurrentPosition.y - CurrentSpeed.y * i, CurrentPosition.z - CurrentSpeed.z * i
g_D3DDevice.SetTransform D3DTS_WORLD, TempMat
For j = 0 To 39
g_D3DDevice.DrawPrimitive D3DPT_TRIANGLESTRIP, j * 80, 78
Next j
Next i
g_D3DDevice.SetRenderState D3DRS_ALPHABLENDENABLE, False
g_D3DDevice.EndScene
g_D3DDevice.Present ByVal 0, ByVal 0, 0, ByVal 0
End Sub