【DirectX】32-水

参考教程

Tutorial 29: Water

学习记录

  这一篇文章中,主要介绍水的实现,本篇更新后使用的框架如下:

1

  水面的渲染比较麻烦,首先纹理是靠着反射与折射实现,我们使用 LightShaderClass 来处理光照,RefractionShaderClass 处理折射相关的着色,WaterShaderClass 则负责综合各种效果实现水的渲染。

  首先看 LightClassLightShaderClassLightClass 只是用来做一个简单的数据封装,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
////////////////////////////////////////////////////////////////////////////////
// Class name: LightClass
////////////////////////////////////////////////////////////////////////////////
class LightClass
{
public:
LightClass();
LightClass(const LightClass&);
~LightClass();

void SetAmbientColor(float, float, float, float);
void SetDiffuseColor(float, float, float, float);
void SetSpecularColor(float, float, float, float);
void SetSpecularPower(float);
void SetDirection(float, float, float);

DirectX::XMFLOAT4 GetAmbientColor();
DirectX::XMFLOAT4 GetDiffuseColor();
DirectX::XMFLOAT4 GetSpecularColor();
float GetSpecularPower();
DirectX::XMFLOAT3 GetDirection();

private:
DirectX::XMFLOAT4 m_ambientColor;
DirectX::XMFLOAT4 m_diffuseColor;
DirectX::XMFLOAT4 m_specularColor;
float m_specularPower;
DirectX::XMFLOAT3 m_direction;
};

  LightShaderClassShaderClass 为基础封装了 LightShader 的处理,声明如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
////////////////////////////////////////////////////////////////////////////////
// Class name: LightShaderClass
////////////////////////////////////////////////////////////////////////////////
class LightShaderClass
{
private:
struct MatrixBufferType
{
DirectX::XMMATRIX world;
DirectX::XMMATRIX view;
DirectX::XMMATRIX projection;
};

struct LightBufferType
{
DirectX::XMFLOAT4 ambientColor;
DirectX::XMFLOAT4 diffuseColor;
DirectX::XMFLOAT3 lightDirection;
float padding;
};

public:
LightShaderClass();
LightShaderClass(const LightShaderClass&);
~LightShaderClass();

bool Initialize(ID3D11Device*, HWND);
void Shutdown();
bool Render(ID3D11DeviceContext*, int, DirectX::XMMATRIX, DirectX::XMMATRIX, DirectX::XMMATRIX, ID3D11ShaderResourceView*, DirectX::XMFLOAT3, DirectX::XMFLOAT4,
DirectX::XMFLOAT4);

private:
bool InitializeShader(ID3D11Device*, HWND, CHAR*, CHAR*);
void ShutdownShader();
void OutputShaderErrorMessage(ID3D10Blob*, HWND, CHAR*);

bool SetShaderParameters(ID3D11DeviceContext*, DirectX::XMMATRIX, DirectX::XMMATRIX, DirectX::XMMATRIX, ID3D11ShaderResourceView*,
DirectX::XMFLOAT3, DirectX::XMFLOAT4, DirectX::XMFLOAT4);
void RenderShader(ID3D11DeviceContext*, int);

private:
ID3D11VertexShader* m_vertexShader;
ID3D11PixelShader* m_pixelShader;
ID3D11InputLayout* m_layout;
ID3D11SamplerState* m_sampleState;
ID3D11Buffer* m_matrixBuffer;
ID3D11Buffer* m_lightBuffer;
};

  DX 代码里只是多了一个 LightBufferType ,而光照的计算代码之前我们写过,这里暂时不贴出来了。需要的话可以去文末的源代码地址下载。

  RefractionShaderClass 则是封装了折射效果的实现,其声明如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
////////////////////////////////////////////////////////////////////////////////
// Class name: RefractionShaderClass
////////////////////////////////////////////////////////////////////////////////
class RefractionShaderClass
{
private:
struct MatrixBufferType
{
DirectX::XMMATRIX world;
DirectX::XMMATRIX view;
DirectX::XMMATRIX projection;
};

struct LightBufferType
{
DirectX::XMFLOAT4 ambientColor;
DirectX::XMFLOAT4 diffuseColor;
DirectX::XMFLOAT3 lightDirection;
float padding;
};

struct ClipPlaneBufferType
{
DirectX::XMFLOAT4 clipPlane;
};

public:
RefractionShaderClass();
RefractionShaderClass(const RefractionShaderClass&);
~RefractionShaderClass();

bool Initialize(ID3D11Device*, HWND);
void Shutdown();
bool Render(ID3D11DeviceContext*, int, DirectX::XMMATRIX, DirectX::XMMATRIX, DirectX::XMMATRIX, ID3D11ShaderResourceView*,
DirectX::XMFLOAT3, DirectX::XMFLOAT4, DirectX::XMFLOAT4, DirectX::XMFLOAT4);

private:
bool InitializeShader(ID3D11Device*, HWND, CHAR*, CHAR*);
void ShutdownShader();
void OutputShaderErrorMessage(ID3D10Blob*, HWND, CHAR*);

bool SetShaderParameters(ID3D11DeviceContext*, DirectX::XMMATRIX, DirectX::XMMATRIX, DirectX::XMMATRIX, ID3D11ShaderResourceView*,
DirectX::XMFLOAT3, DirectX::XMFLOAT4, DirectX::XMFLOAT4, DirectX::XMFLOAT4);
void RenderShader(ID3D11DeviceContext*, int);

private:
ID3D11VertexShader* m_vertexShader;
ID3D11PixelShader* m_pixelShader;
ID3D11InputLayout* m_layout;
ID3D11SamplerState* m_sampleState;
ID3D11Buffer* m_matrixBuffer;
ID3D11Buffer* m_lightBuffer;
ID3D11Buffer* m_clipPlaneBuffer;
};

  而 WaterShaderClass 则是实现使用多张纹理来渲染水的动作,同时为了模拟出动态的效果以及水面的波纹,我们首先需要一张水面的法线贴图。如下:

3

 除了法线贴图以外,反射和折射的效果也将作为纹理来使用,WaterShaderClass 所对应的着色器 WaterVertexShader 中,我们有一个反射矩阵和三个纹理坐标,分别为他们计算变换后的值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
/////////////
// GLOBALS //
/////////////
cbuffer MatrixBuffer
{
matrix worldMatrix;
matrix viewMatrix;
matrix projectionMatrix;
};

cbuffer ReflectionBuffer
{
matrix reflectionMatrix;
};


//////////////
// TYPEDEFS //
//////////////
struct VertexInputType
{
float4 position : POSITION;
float2 tex : TEXCOORD0;
};

struct PixelInputType
{
float4 position : SV_POSITION;
float2 tex : TEXCOORD0;
float4 reflectionPosition : TEXCOORD1;
float4 refractionPosition : TEXCOORD2;
};


////////////////////////////////////////////////////////////////////////////////
// Vertex Shader
////////////////////////////////////////////////////////////////////////////////
PixelInputType WaterVertexShader(VertexInputType input)
{
PixelInputType output;
matrix reflectProjectWorld;
matrix viewProjectWorld;

// Calculate the position of the vertex against the world, view, and projection matrices.
output.position = mul(input.position, worldMatrix);
output.position = mul(output.position, viewMatrix);
output.position = mul(output.position, projectionMatrix);

// Store the texture coordinates for the pixel shader.
output.tex = input.tex;

// Create the reflection projection world matrix.
reflectProjectWorld = mul(reflectionMatrix, projectionMatrix);
reflectProjectWorld = mul(worldMatrix, reflectProjectWorld);

// Calculate the input position against the reflectProjectWorld matrix.
output.reflectionPosition = mul(input.position, reflectProjectWorld);

// Create the view projection world matrix for refraction.
viewProjectWorld = mul(viewMatrix, projectionMatrix);
viewProjectWorld = mul(worldMatrix, viewProjectWorld);

// Calculate the input position against the viewProjectWorld matrix.
output.refractionPosition = mul(input.position, viewProjectWorld);

return output;
}

  WaterPixelShader 中,我们使用反射纹理和折射纹理混合,最终可以渲染出这样的效果:

4

  着色器代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
Texture2D reflectionTexture;
Texture2D refractionTexture;
Texture2D normalTexture;

cbuffer WaterBuffer
{
float waterTranslation;
float reflectRefractScale;
float2 padding;
};


//////////////
// TYPEDEFS //
//////////////
struct PixelInputType
{
float4 position : SV_POSITION;
float2 tex : TEXCOORD0;
float4 reflectionPosition : TEXCOORD1;
float4 refractionPosition : TEXCOORD2;
};


////////////////////////////////////////////////////////////////////////////////
// Pixel Shader
////////////////////////////////////////////////////////////////////////////////
float4 WaterPixelShader(PixelInputType input) : SV_TARGET
{
float2 reflectTexCoord;
float2 refractTexCoord;
float4 normalMap;
float3 normal;
float4 reflectionColor;
float4 refractionColor;
float4 color;

// Calculate the projected reflection texture coordinates.
reflectTexCoord.x = input.reflectionPosition.x / input.reflectionPosition.w / 2.0f + 0.5f;
reflectTexCoord.y = -input.reflectionPosition.y / input.reflectionPosition.w / 2.0f + 0.5f;

// Calculate the projected refraction texture coordinates.
refractTexCoord.x = input.refractionPosition.x / input.refractionPosition.w / 2.0f + 0.5f;
refractTexCoord.y = -input.refractionPosition.y / input.refractionPosition.w / 2.0f + 0.5f;

// Sample the texture pixels from the textures using the updated texture coordinates.
reflectionColor = reflectionTexture.Sample(SampleType, reflectTexCoord);
refractionColor = refractionTexture.Sample(SampleType, refractTexCoord);

// Combine the reflection and refraction results for the final color.
color = lerp(reflectionColor, refractionColor, 0.6f);

return color;
}

  但是水面并非为平面,所以我们需要一个变量来模仿波纹效果。我们使用法线向量来对纹理进行偏移,如下:

1
2
3
4
5
6
7
8
9
// Sample the normal from the normal map texture.
normalMap = normalTexture.Sample(SampleType, input.tex);

// Expand the range of the normal from (0,1) to (-1,+1).
normal = (normalMap.xyz * 2.0f) - 1.0f;

// Re-position the texture coordinate sampling position by the normal map value to simulate the rippling wave effect.
reflectTexCoord = reflectTexCoord + (normal.xy * reflectRefractScale);
refractTexCoord = refractTexCoord + (normal.xy * reflectRefractScale);

  我们使用法线贴图读取法线,然后对折射和反射做一定程度上的偏移计算,使得水面出现一定的波纹效果。效果如下:

5

  和上图相比,由于折射和反射纹理的局部移位,我们的水面已经看起来很真实了,不过依旧可以改进,我们使用一个外部传进来的值来对法线贴图的纹理坐标进行计算以模拟水面的动态效果。

1
input.tex.y += waterTranslation;

  这里就不截图了,反正截图也看不出来动态的效果。

  最后,当我们修改完毕之后,我们的最终的 WaterPixelShader 如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
/////////////
// GLOBALS //
/////////////
SamplerState SampleType;
Texture2D reflectionTexture;
Texture2D refractionTexture;
Texture2D normalTexture;

cbuffer WaterBuffer
{
float waterTranslation;
float reflectRefractScale;
float2 padding;
};


//////////////
// TYPEDEFS //
//////////////
struct PixelInputType
{
float4 position : SV_POSITION;
float2 tex : TEXCOORD0;
float4 reflectionPosition : TEXCOORD1;
float4 refractionPosition : TEXCOORD2;
};


////////////////////////////////////////////////////////////////////////////////
// Pixel Shader
////////////////////////////////////////////////////////////////////////////////
float4 WaterPixelShader(PixelInputType input) : SV_TARGET
{
float2 reflectTexCoord;
float2 refractTexCoord;
float4 normalMap;
float3 normal;
float4 reflectionColor;
float4 refractionColor;
float4 color;


// Move the position the water normal is sampled from to simulate moving water.
input.tex.xy += waterTranslation;

// Calculate the projected reflection texture coordinates.
reflectTexCoord.x = input.reflectionPosition.x / input.reflectionPosition.w / 2.0f + 0.5f;
reflectTexCoord.y = -input.reflectionPosition.y / input.reflectionPosition.w / 2.0f + 0.5f;

// Calculate the projected refraction texture coordinates.
refractTexCoord.x = input.refractionPosition.x / input.refractionPosition.w / 2.0f + 0.5f;
refractTexCoord.y = -input.refractionPosition.y / input.refractionPosition.w / 2.0f + 0.5f;

// Sample the normal from the normal map texture.
normalMap = normalTexture.Sample(SampleType, input.tex);

// Expand the range of the normal from (0,1) to (-1,+1).
normal = (normalMap.xyz * 2.0f) - 1.0f;

// Re-position the texture coordinate sampling position by the normal map value to simulate the rippling wave effect.
reflectTexCoord = reflectTexCoord + (normal.xy * reflectRefractScale);
refractTexCoord = refractTexCoord + (normal.xy * reflectRefractScale);

// Sample the texture pixels from the textures using the updated texture coordinates.
reflectionColor = reflectionTexture.Sample(SampleType, reflectTexCoord);
refractionColor = refractionTexture.Sample(SampleType, refractTexCoord);

// Combine the reflection and refraction results for the final color.
color = lerp(reflectionColor, refractionColor, 0.6f);

return color;
}

  我们有 waterTranslationreflectRefractScale 两个变量来对纹理坐标计算使得水面更加真实。在 WaterShaderClass 中我们对这两个着色器服务,声明如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
////////////////////////////////////////////////////////////////////////////////
// Class name: WaterShaderClass
////////////////////////////////////////////////////////////////////////////////
class WaterShaderClass
{
private:
struct MatrixBufferType
{
DirectX::XMMATRIX world;
DirectX::XMMATRIX view;
DirectX::XMMATRIX projection;
};

struct ReflectionBufferType
{
DirectX::XMMATRIX reflection;
};

struct WaterBufferType
{
float waterTranslation;
float reflectRefractScale;
DirectX::XMFLOAT2 padding;
};

public:
WaterShaderClass();
WaterShaderClass(const WaterShaderClass&);
~WaterShaderClass();

bool Initialize(ID3D11Device*, HWND);
void Shutdown();
bool Render(ID3D11DeviceContext*, int, DirectX::XMMATRIX, DirectX::XMMATRIX, DirectX::XMMATRIX, DirectX::XMMATRIX, ID3D11ShaderResourceView*,
ID3D11ShaderResourceView*, ID3D11ShaderResourceView*, float, float);

private:
bool InitializeShader(ID3D11Device*, HWND, CHAR*, CHAR*);
void ShutdownShader();
void OutputShaderErrorMessage(ID3D10Blob*, HWND, CHAR*);

bool SetShaderParameters(ID3D11DeviceContext*, DirectX::XMMATRIX, DirectX::XMMATRIX, DirectX::XMMATRIX, DirectX::XMMATRIX, ID3D11ShaderResourceView*,
ID3D11ShaderResourceView*, ID3D11ShaderResourceView*, float, float);
void RenderShader(ID3D11DeviceContext*, int);

private:
ID3D11VertexShader* m_vertexShader;
ID3D11PixelShader* m_pixelShader;
ID3D11InputLayout* m_layout;
ID3D11SamplerState* m_sampleState;
ID3D11Buffer* m_matrixBuffer;
ID3D11Buffer* m_reflectionBuffer;
ID3D11Buffer* m_waterBuffer;
};

  在 GraphicsClass 中,我们实现将折射和反射渲染至纹理的方法,然后再用两张纹理和法线纹理来渲染水面,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
bool GraphicsClass::RenderRefractionToTexture()
{
DirectX::XMFLOAT4 clipPlane;
DirectX::XMMATRIX worldMatrix, viewMatrix, projectionMatrix;
bool result;


// Setup a clipping plane based on the height of the water to clip everything above it.
clipPlane = DirectX::XMFLOAT4(0.0f, -1.0f, 0.0f, m_waterHeight + 0.1f);

// Set the render target to be the refraction render to texture.
m_RefractionTexture->SetRenderTarget(m_D3D->GetDeviceContext(), m_D3D->GetDepthStencilView());

// Clear the refraction render to texture.
m_RefractionTexture->ClearRenderTarget(m_D3D->GetDeviceContext(), m_D3D->GetDepthStencilView(), 0.0f, 0.0f, 0.0f, 1.0f);

// Generate the view matrix based on the camera's position.
m_Camera->Render();

// Get the world, view, and projection matrices from the camera and d3d objects.
m_D3D->GetWorldMatrix(worldMatrix);
m_Camera->GetViewMatrix(viewMatrix);
m_D3D->GetProjectionMatrix(projectionMatrix);

// Translate to where the bath model will be rendered.
worldMatrix *= XMMatrixTranslation(0.0f, 2.0f, 0.0f);

// Put the bath model vertex and index buffers on the graphics pipeline to prepare them for drawing.
m_BathModel->Render(m_D3D->GetDeviceContext());

// Render the bath model using the light shader.
result = m_RefractionShader->Render(m_D3D->GetDeviceContext(), m_BathModel->GetIndexCount(), worldMatrix, viewMatrix,
projectionMatrix, m_BathModel->GetTexture(), m_Light->GetDirection(),
m_Light->GetAmbientColor(), m_Light->GetDiffuseColor(), clipPlane);
if(!result)
{
return false;
}

// Reset the render target back to the original back buffer and not the render to texture anymore.
m_D3D->SetBackBufferRenderTarget();

return true;
}


bool GraphicsClass::RenderReflectionToTexture()
{
DirectX::XMMATRIX reflectionViewMatrix, worldMatrix, projectionMatrix;
bool result;


// Set the render target to be the reflection render to texture.
m_ReflectionTexture->SetRenderTarget(m_D3D->GetDeviceContext(), m_D3D->GetDepthStencilView());

// Clear the reflection render to texture.
m_ReflectionTexture->ClearRenderTarget(m_D3D->GetDeviceContext(), m_D3D->GetDepthStencilView(), 0.0f, 0.0f, 0.0f, 1.0f);

// Use the camera to render the reflection and create a reflection view matrix.
m_Camera->RenderReflection(m_waterHeight);

// Get the camera reflection view matrix instead of the normal view matrix.
reflectionViewMatrix = m_Camera->GetReflectionViewMatrix();

// Get the world and projection matrices from the d3d object.
m_D3D->GetWorldMatrix(worldMatrix);
m_D3D->GetProjectionMatrix(projectionMatrix);

// Translate to where the wall model will be rendered.
worldMatrix *= XMMatrixTranslation(0.0f, 6.0f, 8.0f);

// Put the wall model vertex and index buffers on the graphics pipeline to prepare them for drawing.
m_WallModel->Render(m_D3D->GetDeviceContext());

// Render the wall model using the light shader and the reflection view matrix.
result = m_LightShader->Render(m_D3D->GetDeviceContext(), m_WallModel->GetIndexCount(), worldMatrix, reflectionViewMatrix,
projectionMatrix, m_WallModel->GetTexture(), m_Light->GetDirection(),
m_Light->GetAmbientColor(), m_Light->GetDiffuseColor());
if(!result)
{
return false;
}

// Reset the render target back to the original back buffer and not the render to texture anymore.
m_D3D->SetBackBufferRenderTarget();

return true;
}

bool GraphicsClass::RenderScene()
{
DirectX::XMMATRIX worldMatrix, viewMatrix, projectionMatrix, reflectionMatrix;
bool result;


// Clear the buffers to begin the scene.
m_D3D->BeginScene(0.0f, 0.0f, 0.0f, 1.0f);

// Generate the view matrix based on the camera's position.
m_Camera->Render();

// Get the world, view, and projection matrices from the camera and d3d objects.
m_D3D->GetWorldMatrix(worldMatrix);
m_Camera->GetViewMatrix(viewMatrix);
m_D3D->GetProjectionMatrix(projectionMatrix);

// Translate to where the ground model will be rendered.
worldMatrix *= XMMatrixTranslation(0.0f, 1.0f, 0.0f);

// Put the ground model vertex and index buffers on the graphics pipeline to prepare them for drawing.
m_GroundModel->Render(m_D3D->GetDeviceContext());

// Render the ground model using the light shader.
result = m_LightShader->Render(m_D3D->GetDeviceContext(), m_GroundModel->GetIndexCount(), worldMatrix, viewMatrix,
projectionMatrix, m_GroundModel->GetTexture(), m_Light->GetDirection(),
m_Light->GetAmbientColor(), m_Light->GetDiffuseColor());
if(!result)
{
return false;
}

// Reset the world matrix.
m_D3D->GetWorldMatrix(worldMatrix);

// Translate to where the wall model will be rendered.
worldMatrix *= XMMatrixTranslation(0.0f, 6.0f, 8.0f);

// Put the wall model vertex and index buffers on the graphics pipeline to prepare them for drawing.
m_WallModel->Render(m_D3D->GetDeviceContext());

// Render the wall model using the light shader.
result = m_LightShader->Render(m_D3D->GetDeviceContext(), m_WallModel->GetIndexCount(), worldMatrix, viewMatrix,
projectionMatrix, m_WallModel->GetTexture(), m_Light->GetDirection(),
m_Light->GetAmbientColor(), m_Light->GetDiffuseColor());
if(!result)
{
return false;
}

// Reset the world matrix.
m_D3D->GetWorldMatrix(worldMatrix);

// Translate to where the bath model will be rendered.
worldMatrix *= XMMatrixTranslation(0.0f, 2.0f, 0.0f);

// Put the bath model vertex and index buffers on the graphics pipeline to prepare them for drawing.
m_BathModel->Render(m_D3D->GetDeviceContext());

// Render the bath model using the light shader.
result = m_LightShader->Render(m_D3D->GetDeviceContext(), m_BathModel->GetIndexCount(), worldMatrix, viewMatrix,
projectionMatrix, m_BathModel->GetTexture(), m_Light->GetDirection(),
m_Light->GetAmbientColor(), m_Light->GetDiffuseColor());
if(!result)
{
return false;
}

// Reset the world matrix.
m_D3D->GetWorldMatrix(worldMatrix);

// Get the camera reflection view matrix.
reflectionMatrix = m_Camera->GetReflectionViewMatrix();

// Translate to where the water model will be rendered.
worldMatrix *= XMMatrixTranslation(0.0f, m_waterHeight, 0.0f);

// Put the water model vertex and index buffers on the graphics pipeline to prepare them for drawing.
m_WaterModel->Render(m_D3D->GetDeviceContext());

// Render the water model using the water shader.
result = m_WaterShader->Render(m_D3D->GetDeviceContext(), m_WaterModel->GetIndexCount(), worldMatrix, viewMatrix,
projectionMatrix, reflectionMatrix, m_ReflectionTexture->GetShaderResourceView(),
m_RefractionTexture->GetShaderResourceView(), m_WaterModel->GetTexture(),
m_waterTranslation, 0.01f);
if(!result)
{
return false;
}

// Present the rendered scene to the screen.
m_D3D->EndScene();

return true;
}

  在 Render 里调用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
bool GraphicsClass::Render()
{
bool result;


// Render the refraction of the scene to a texture.
result = RenderRefractionToTexture();
if(!result)
{
return false;
}

// Render the reflection of the scene to a texture.
result = RenderReflectionToTexture();
if(!result)
{
return false;
}

// Render the scene as normal to the back buffer.
result = RenderScene();
if(!result)
{
return false;
}

return true;
}

  源代码:DX11Tutorial-Water

0%