Cogs.Core
OceanRenderer.cpp
1#include "OceanRenderer.h"
2
3#include "ClipmapLevel.h"
4#include "ClipmapGeometry.h"
5
6#include "RenderBlock.h"
7#include "RenderBlockCulling.h"
8
9#include "Rendering/IRenderTargets.h"
10#include "Rendering/IContext.h"
11#include "Rendering/ITextures.h"
12#include "Rendering/IEffects.h"
13#include "Rendering/CommandGroupAnnotation.h"
14
15void Cogs::OceanRenderer::initialize(ClipmapRenderer * renderer, IGraphicsDevice * device)
16{
17 this->renderer = renderer;
18 this->device = device;
19
20 Cogs::BlendState blendState = { true, BlendState::Blend::SourceAlpha, BlendState::Blend::InverseSourceAlpha, BlendState::BlendOperation::Add };
21 blendStateHandle = device->getRenderTargets()->loadBlendState(blendState);
22
23 baseSpectrum.initialize(device);
24 timer.start();
25}
26
27void Cogs::OceanRenderer::initializeTextures(ITextures * /*textures*/, IRenderTargets * /*renderTargets*/)
28{
29}
30
31void Cogs::OceanRenderer::initializeEffects(IBuffers * buffers, IEffects * effects, const size_t numImagery, size_t permutation)
32{
33 auto & permutationOceanData = getPermutationDependentOceanRendererData(permutation);
34 if (!permutationOceanData.initialized) {
35 // First time, create and initialize constant buffers.
36 initializeConstantBuffers(buffers, permutationOceanData.oceanEffect, permutationOceanData.effectVariables, permutationOceanData.oceanEffectVariables, false);
37 }
38
39 initializeEffectVariables(effects, permutationOceanData.oceanEffect, permutationOceanData.effectVariables, permutationOceanData.oceanEffectVariables, numImagery, false);
40 initializeEffectBindings(effects, permutationOceanData.oceanEffect, permutationOceanData.oceanEffectBindings, numImagery, false);
41
42 VertexElement element = { 0, DataFormat::X32Y32_FLOAT, ElementSemantic::Position, 0, InputType::VertexData, 0 };
43 VertexFormatHandle meshFormat = device->getBuffers()->createVertexFormat(&element, 1);
44 inputLayout = buffers->loadInputLayout(&meshFormat, 1, permutationOceanData.oceanEffect);
45
46 permutationOceanData.initialized = true;
47}
48
49void Cogs::OceanRenderer::initializeConstantBuffers(IBuffers * buffers, EffectHandle /*effect*/, ClipmapEffectVariables & variables, OceanEffectVariables & oceanEffectVariables, bool /*isDepth*/)
50{
51 variables.globalBuffer = buffers->loadBuffer(nullptr, sizeof(GlobalParameters), Usage::Dynamic, AccessMode::Write, BindFlags::ConstantBuffer);
52 variables.levelBuffer = buffers->loadBuffer(nullptr, sizeof(LevelParameters), Usage::Dynamic, AccessMode::Write, BindFlags::ConstantBuffer);
53 variables.imageryBuffer = buffers->loadBuffer(nullptr, sizeof(ImageryParameters), Usage::Dynamic, AccessMode::Write, BindFlags::ConstantBuffer);
54
55 variables.patchBuffer = buffers->loadBuffer(nullptr, sizeof(PatchParameters), Usage::Dynamic, AccessMode::Write, BindFlags::ConstantBuffer);
56
57 variables.renderBuffer = buffers->loadBuffer(nullptr, sizeof(RenderParameters), Usage::Dynamic, AccessMode::Write, BindFlags::ConstantBuffer);
58 variables.levelRenderBuffer = buffers->loadBuffer(nullptr, sizeof(LevelRenderParameters), Usage::Dynamic, AccessMode::Write, BindFlags::ConstantBuffer);
59
60 oceanEffectVariables.oceanBuffer = buffers->loadBuffer(nullptr, sizeof(OceanParameters), Usage::Dynamic, AccessMode::Write, BindFlags::ConstantBuffer);
61}
62
63void Cogs::OceanRenderer::initializeEffectVariables(IEffects * effects, EffectHandle effectHandle, ClipmapEffectVariables & variables, OceanEffectVariables & oceanEffectVariables, const size_t /*numImagery*/, bool isDepth)
64{
65 variables.globalBufferBinding= effects->getConstantBufferBinding(effectHandle, "GlobalParameters");
66 variables.levelBufferBinding = effects->getConstantBufferBinding(effectHandle, "LevelParameters");
67
68 variables.patchBufferBinding = effects->getConstantBufferBinding(effectHandle, "PatchParameters");
69
70 if (!isDepth) {
71 variables.imageryBufferBinding = effects->getConstantBufferBinding(effectHandle, "ImageryParameters");
72
73 variables.renderBufferBinding = effects->getConstantBufferBinding(effectHandle, "RenderParameters");
74 variables.levelRenderBufferBinding = effects->getConstantBufferBinding(effectHandle, "LevelRenderParameters");
75 }
76
77 variables.customParametersBufferBinding = effects->getConstantBufferBinding(effectHandle, "CustomParameters");
78
79 oceanEffectVariables.oceanBufferBinding = effects->getConstantBufferBinding(effectHandle, "OceanParameters");
80}
81
82namespace
83{
84 const char * imagerySemantics[] = {
85 "imageryTexture[0]",
86 "imageryTexture[1]",
87 "imageryTexture[2]",
88 "imageryTexture[3]",
89 };
90
91 const char * coarseImagerySemantics[] = {
92 "coarseImageryTexture[0]",
93 "coarseImageryTexture[1]",
94 "coarseImageryTexture[2]",
95 "coarseImageryTexture[3]",
96 };
97}
98
99void Cogs::OceanRenderer::initializeEffectBindings(IEffects * effects, EffectHandle effect, ClipmapTextureBindings & bindings, const size_t numImagery, bool isDepth)
100{
101 int unit = 5;
102
103 bindings.heightMapBinding = effects->getTextureBinding(effect, "heightTexture", unit);
104 bindings.heightMapSamplerBinding = effects->getSamplerStateBinding(effect, "heightSampler", unit++);
105
106 bindings.coarseHeightMapBinding = effects->getTextureBinding(effect, "coarseHeightTexture", unit);
107 bindings.coarseHeightMapSamplerBinding = effects->getSamplerStateBinding(effect, "coarseHeightSampler", unit++);
108
109 if (!isDepth) {
110 bindings.normalMapBinding = effects->getTextureBinding(effect, "normalTexture", unit);
111 bindings.normalMapSamplerBinding = effects->getSamplerStateBinding(effect, "normalSampler", unit++);
112
113 bindings.coarseNormalMapBinding = effects->getTextureBinding(effect, "coarseNormalTexture", unit);
114 bindings.coarseNormalMapSamplerBinding = effects->getSamplerStateBinding(effect, "normalSampler", unit++);
115
116 if (oceanOptions.enableImagery) {
117 if (numImagery > 1) {
118 for (size_t i = 0; i < numImagery; ++i) {
119 auto & perImageBindings = bindings.getImageryBindingHandles(i);
120 perImageBindings.imageryBinding = effects->getTextureBinding(effect, imagerySemantics[i], unit);
121 perImageBindings.imagerySamplerBinding = effects->getSamplerStateBinding(effect, "imagerySampler", unit++);
122
123 perImageBindings.coarseImageryBinding = effects->getTextureBinding(effect, coarseImagerySemantics[i], unit);
124 perImageBindings.coarseImagerySamplerBinding = effects->getSamplerStateBinding(effect, "imagerySampler", unit++);
125 }
126 } else {
127 auto & perImageBindings = bindings.getImageryBindingHandles(0);
128 perImageBindings.imageryBinding = effects->getTextureBinding(effect, "imageryTexture[0]", unit);
129 perImageBindings.imagerySamplerBinding = effects->getSamplerStateBinding(effect, "imagerySampler", unit++);
130
131 perImageBindings.coarseImageryBinding = effects->getTextureBinding(effect, "coarseImageryTexture[0]", unit);
132 perImageBindings.coarseImagerySamplerBinding = perImageBindings.imagerySamplerBinding;
133 }
134 }
135 }
136}
137
138namespace Cogs
139{
140 template<typename Parameters>
141 void applyParameters(IContext * context, const Parameters & parameters, BufferHandle bufferHandle)
142 {
143 Parameters * out = static_cast<Parameters *>(context->map(bufferHandle, MapMode::WriteDiscard));
144
145 ::memcpy(out, &parameters, sizeof(Parameters));
146
147 context->unmap(bufferHandle);
148 }
149}
150
151void Cogs::OceanRenderer::updateGlobalParameters(const RenderContext & renderContext, const RenderOptions & renderOptions, const ClipmapState & /*clipmapState*/, const GlobalParameters & globalParameters)
152{
153 IContext * context = renderContext.context;
154 auto & permutationOceanData = getPermutationDependentOceanRendererData(renderContext.permutation);
155
156 const auto & variables = permutationOceanData.effectVariables;
157
158 RenderParameters renderParameters;
159 renderParameters.blendRegionColor = renderOptions.blendRegionColor;
160 renderParameters.showBlendRegions = renderOptions.showBlendRegions;
161 renderParameters.showImagery = renderOptions.showImagery;
162 renderParameters.showLevelColors = renderOptions.showLevelColors;
163
164 applyParameters(context, renderParameters, variables.renderBuffer);
165
166 applyParameters(context, globalParameters, variables.globalBuffer);
167
168 double baseTileCoordsFromWorld = 1.0 / static_cast<double>(oceanOptions.worldSpaceMeter*baseSpectrum.getTileExtent());
169 double baseTileX = baseTileCoordsFromWorld*renderContext.origin[0];
170 double baseTileY = baseTileCoordsFromWorld*renderContext.origin[1];
171
172 double detailTileCoordsFromWorld = 17.0 / static_cast<double>(oceanOptions.worldSpaceMeter*baseSpectrum.getTileExtent());
173 double detailTileX = detailTileCoordsFromWorld*renderContext.origin[0];
174 double detailTileY = detailTileCoordsFromWorld*renderContext.origin[1];
175
176 oceanParameters.viewportScale.x = 2.f*renderContext.width;
177 oceanParameters.viewportScale.y = 2.f*renderContext.height;
178
179 oceanParameters.tileCoordsFromWorld.x = static_cast<float>(baseTileCoordsFromWorld);
180 oceanParameters.tileCoordsFromWorld.y = static_cast<float>(detailTileCoordsFromWorld);
181
182 oceanParameters.tileOffset.x = static_cast<int>(std::floor(baseTileX));
183 oceanParameters.tileOffset.y = static_cast<int>(std::floor(baseTileY));
184 oceanParameters.tileOffset.z = static_cast<int>(std::floor(detailTileX));
185 oceanParameters.tileOffset.w = static_cast<int>(std::floor(detailTileY));
186
187 oceanParameters.tileRemainder.x = static_cast<float>(baseTileX - std::floor(baseTileX));
188 oceanParameters.tileRemainder.y = static_cast<float>(baseTileY - std::floor(baseTileY));
189 oceanParameters.tileRemainder.z = static_cast<float>(detailTileX - std::floor(detailTileX));
190 oceanParameters.tileRemainder.w = static_cast<float>(detailTileY - std::floor(detailTileY));
191
192 oceanParameters.oneOverTileExtentAdjust = 1.f / baseSpectrum.getTileExtentAdjust();
193
194// oceanParameters.baseTileCoordsFromWorld = 1.f / (oceanOptions.worldSpaceMeter*oceanOptions.baseTileLength);
195// oceanParameters.significantWaveHeightWorld = oceanOptions.worldSpaceMeter * oceanOptions.significantWaveHeight;
196// oceanParameters.oceanOrigin = vec4(std::fmod(renderContext.origin[0], 1000.0f), std::fmod(renderContext.origin[1], 1000.0f), 0, 0);
197
198 applyParameters(context, oceanParameters, permutationOceanData.oceanEffectVariables.oceanBuffer);
199}
200
201void Cogs::OceanRenderer::updateLevelParameters(IContext * context, const RenderOptions & options, const LevelParameters & parameters, const ImageryParameters & imageryParameters, size_t permutation)
202{
203 auto & permutationOceanData = getPermutationDependentOceanRendererData(permutation);
204 const auto & variables = permutationOceanData.effectVariables;
205
206 applyParameters(context, parameters, variables.levelBuffer);
207 applyParameters(context, imageryParameters, variables.imageryBuffer);
208
209 applyParameters(context, options.diffuseColor, variables.levelRenderBuffer);
210}
211
212void Cogs::OceanRenderer::updateLevelTextures(IContext * context, const RenderLevel * renderLevel, size_t permutation)
213{
214 auto & permutationOceanData = getPermutationDependentOceanRendererData(permutation);
215 auto & bindings = permutationOceanData.oceanEffectBindings;
216
217 context->setTexture(bindings.heightMapBinding, renderLevel->terrainLevel->renderTexture.handle);
218 context->setSamplerState(bindings.heightMapSamplerBinding, renderer->pointSamplerState);
219
220 context->setTexture(bindings.coarseHeightMapBinding, renderLevel->coarserTerrainLevel->renderTexture.handle);
221 context->setSamplerState(bindings.coarseHeightMapSamplerBinding, renderer->linearSamplerState);
222
223 if (renderLevel->normalLevel) {
224 context->setTexture(bindings.normalMapBinding, renderLevel->normalLevel->renderTexture.handle);
225 context->setSamplerState(bindings.normalMapSamplerBinding, renderer->linearSamplerState);
226
227 context->setTexture(bindings.coarseNormalMapBinding, renderLevel->coarserNormalLevel->renderTexture.handle);
228 context->setSamplerState(bindings.coarseNormalMapSamplerBinding, renderer->linearSamplerState);
229 }
230
231 const size_t levelIndex = renderLevel->terrainLevel->index;
232
233 if (oceanOptions.enableImagery) {
234 for (size_t i = 0; i < renderLevel->imagery->size(); ++i) {
235 const ClipmapLevel & imageryLevel = (*renderLevel->imagery)[i][levelIndex];
236 const auto & perImageBindings = bindings.getImageryBindingHandles(i);
237
238 context->setTexture(perImageBindings.imageryBinding, imageryLevel.renderTexture.handle);
239 context->setSamplerState(perImageBindings.imagerySamplerBinding, renderer->linearSamplerState);
240
241 context->setTexture(perImageBindings.coarseImageryBinding, imageryLevel.coarserLevel->renderTexture.handle);
242 context->setSamplerState(perImageBindings.coarseImagerySamplerBinding, renderer->linearSamplerState);
243 }
244 }
245}
246
247void Cogs::OceanRenderer::preRender(RenderContext & renderContext)
248{
249 CommandGroupAnnotation preGroup(renderContext.context, "Ocean::preRender");
250
251
252 if ((baseTileSizeLog2 != oceanOptions.baseTileSizeLog2) ||
253 (baseTileLength != oceanOptions.baseTileLength) ||
254 (significantWavePeriod != oceanOptions.significantWavePeriod))
255 {
256
257 if (baseTileSizeLog2 != oceanOptions.baseTileSizeLog2) {
258 baseTileSizeLog2 = oceanOptions.baseTileSizeLog2;
259 baseSpectrum.setSize(baseTileSizeLog2);
260 }
261
262 baseTileLength = oceanOptions.baseTileLength;
263 significantWavePeriod = oceanOptions.significantWavePeriod;
264
265 baseSpectrum.setConditions(baseTileLength,
266 0.f, 0.f,
267 significantWavePeriod,
268 10.f, 0.f,
269 0.f, 42);
270 }
271
272 float dt = static_cast<float>(timer.elapsedSeconds());
273 timer.start();
274
275 baseSpectrum.update(renderContext, dt);
276}
277
278void Cogs::OceanRenderer::setupOceanPass(RenderContext & renderContext)
279{
280 auto context = renderContext.context;
281 auto & permutationOceanData = getPermutationDependentOceanRendererData(renderContext.permutation);
282 auto & variables = permutationOceanData.effectVariables;
283
284 context->setEffect(permutationOceanData.oceanEffect);
285 context->setInputLayout(inputLayout);
286
287 renderContext.oceanCallback(permutationOceanData.oceanEffect);
288
289 context->setTexture("wavePosition", 0, baseSpectrum.positionTex());
290 context->setSamplerState("wavePositionSampler", 0, renderer->linearSamplerState);
291
292 context->setTexture("waveDerivatives", 1, baseSpectrum.derivativesTex());
293 context->setSamplerState("waveDerivativesSampler", 1, renderer->linearSamplerState);
294
295 if (renderContext.wireframe) {
296 context->setRasterizerState(renderer->wireframeRasterizerState);
297 } else {
298 context->setRasterizerState(renderContext.offsetEnabled ? renderer->solidOffsetRasterizerState : renderer->solidRasterizerState);
299 }
300
301 if (!renderContext.isOIT) {
302 context->setBlendState(blendStateHandle);
303
304 context->setDepthStencilState(renderContext.wireframe ? renderer->transparentWireframeDepthState : renderer->transparentDepthState);
305 }
306
307 context->setConstantBuffer(variables.globalBufferBinding, variables.globalBuffer);
308 context->setConstantBuffer(variables.levelBufferBinding, variables.levelBuffer);
309
310 if (HandleIsValid(variables.imageryBufferBinding)) {
311 context->setConstantBuffer(variables.imageryBufferBinding, variables.imageryBuffer);
312 }
313
314 context->setConstantBuffer(variables.patchBufferBinding, variables.patchBuffer);
315
316 if (HandleIsValid(variables.renderBufferBinding)) {
317 context->setConstantBuffer(variables.renderBufferBinding, variables.renderBuffer);
318 }
319
320 if (HandleIsValid(variables.levelRenderBufferBinding)) {
321 context->setConstantBuffer(variables.levelRenderBufferBinding, variables.levelRenderBuffer);
322 }
323
324 if (HandleIsValid(permutationOceanData.oceanEffectVariables.oceanBufferBinding)) {
325 context->setConstantBuffer(permutationOceanData.oceanEffectVariables.oceanBufferBinding, permutationOceanData.oceanEffectVariables.oceanBuffer);
326 }
327
328 if (HandleIsValid(renderer->customParametersBuffer) && HandleIsValid(variables.customParametersBufferBinding)) {
329 context->setConstantBuffer(variables.customParametersBufferBinding, renderer->customParametersBuffer);
330 }
331}
332
333void Cogs::OceanRenderer::render(RenderContext & renderContext, const RenderOptions & renderOptions, const WorldOptions & worldOptions, bool usePreviousCullingResults)
334{
335 if (!usePreviousCullingResults) {
336 for (size_t i = 0; i < renderer->levelIndex; ++i) {
337 const RenderLevel & renderLevel = renderer->levels[i];
338
339 updateLevelTextures(renderContext.context, &renderLevel, renderContext.permutation);
340
341 updateLevelParameters(renderContext.context, renderOptions, *renderLevel.levelParameters, *renderLevel.imageryParameters, renderContext.permutation);
342
343 cullRenderBlocks(renderLevel.renderBlocks,
344 renderer->visibleBlocks + i * kMaxNumBlocks,
345 renderLevel.blockCount,
346 renderLevel,
347 renderContext.cullVolume,
348 renderContext.center - renderContext.cullOrigin,
349 0.0f,
350 static_cast<float>(worldOptions.worldScale.x),
351 static_cast<float>(worldOptions.worldScale.y));
352
353 for (size_t j = 0; j < renderLevel.blockCount; ++j) {
354 if (renderer->visibleBlocks[j + i * kMaxNumBlocks] || !renderOptions.enableCulling) {
355 drawBlock(renderLevel.renderBlocks[j], renderContext);
356 }
357 }
358 }
359 } else {
360 for (size_t i = 0; i < renderer->levelIndex; ++i) {
361 const RenderLevel & renderLevel = renderer->levels[i];
362
363 updateLevelTextures(renderContext.context, &renderLevel, renderContext.permutation);
364
365 updateLevelParameters(renderContext.context, renderOptions, *renderLevel.levelParameters, *renderLevel.imageryParameters, renderContext.permutation);
366
367 for (size_t j = 0; j < renderLevel.blockCount; ++j) {
368 if (renderer->visibleBlocks[j + i * kMaxNumBlocks] || !renderOptions.enableCulling) {
369 drawBlock(renderLevel.renderBlocks[j], renderContext);
370 }
371 }
372 }
373 }
374}
375
376void Cogs::OceanRenderer::drawBlock(const RenderBlock & renderBlock, RenderContext & renderContext)
377{
378 IContext * context = renderContext.context;
379
380 auto & permutationOceanData = getPermutationDependentOceanRendererData(renderContext.permutation);
381 applyParameters(context, renderBlock.patchOriginInClippedLevel, permutationOceanData.effectVariables.patchBuffer);
382
383 context->setVertexBuffers(&renderBlock.mesh->vertexBuffer, 1, &renderBlock.mesh->stride, nullptr);
384 context->setIndexBuffer(renderBlock.mesh->indexBuffer, 2, 0);
385
386 context->drawIndexed(PrimitiveType::TriangleList, 0, 0);
387}
388
389void Cogs::OceanRenderer::setOptions(const OceanOptions * options)
390{
391 oceanOptions = *options;
392}
393
394void Cogs::OceanRenderer::update()
395{
396 float significantWaveLength = (9.81f*oceanOptions.significantWavePeriod*oceanOptions.significantWavePeriod) / (2.f*glm::pi<float>());
397
398 oceanParameters.deepColor = oceanOptions.deepColor;
399 oceanParameters.shallowColor = oceanOptions.shallowColor;
400 oceanParameters.roughColor = oceanOptions.roughColor;
401
402 oceanParameters.foamDetectionScale = -oceanOptions.foamDetectionScale*significantWaveLength;
403 oceanParameters.significantWaveHeightWorld = oceanOptions.worldSpaceMeter * oceanOptions.significantWaveHeight;
404 oceanParameters.worldSpaceMeter = oceanOptions.worldSpaceMeter;
405 oceanParameters.shoale = oceanOptions.shoale;
406 oceanParameters.swellDirection = oceanOptions.swellDirection;
407 oceanParameters.roughness = oceanOptions.roughness;
408
409 oceanParameters.foamErosionValue = oceanOptions.foamErosionValue;
410 oceanParameters.shoalingEffectFactor = oceanOptions.shoalingEffectFactor;
411
412 oceanParameters.lodDisplace.x = oceanOptions.lodDisplaceStart;
413 oceanParameters.lodDisplace.y = oceanOptions.lodDisplaceTransition;
414 oceanParameters.lodNormal.x = oceanOptions.lodNormalStart;
415 oceanParameters.lodNormal.y = oceanOptions.lodNormalTransition;
416 oceanParameters.lodDetail.x = oceanOptions.lodDetailStart;
417 oceanParameters.lodDetail.y = oceanOptions.lodDetailTransition;
418 oceanParameters.lodFoam.x = oceanOptions.lodFoamStart;
419 oceanParameters.lodFoam.y = oceanOptions.lodFoamTransition;
420}
bool HandleIsValid(const ResourceHandle_t< T > &handle)
Check if the given resource is valid, that is not equal to NoHandle or InvalidHandle.
Contains all Cogs related functionality.
Definition: FieldSetter.h:23
@ VertexData
Per vertex data.
@ TriangleList
List of triangles.
@ Position
Position semantic.
@ Write
The buffer can be mapped and written to by the CPU after creation.
Definition: Flags.h:50
@ ConstantBuffer
The buffer can be bound as input to effects as a constant buffer.
Definition: Flags.h:72
Encapsulates blend state for the graphics pipeline in a state object.
Definition: BlendState.h:9
@ WriteDiscard
Write access. When unmapping the graphics system will discard the old contents of the resource.
Definition: Flags.h:103
@ Dynamic
Buffer will be loaded and modified with some frequency.
Definition: Flags.h:30