1#include "OceanRenderer.h"
3#include "ClipmapLevel.h"
4#include "ClipmapGeometry.h"
6#include "RenderBlock.h"
7#include "RenderBlockCulling.h"
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"
15void Cogs::OceanRenderer::initialize(ClipmapRenderer * renderer, IGraphicsDevice * device)
17 this->renderer = renderer;
18 this->device = device;
20 Cogs::BlendState blendState = {
true, BlendState::Blend::SourceAlpha, BlendState::Blend::InverseSourceAlpha, BlendState::BlendOperation::Add };
21 blendStateHandle = device->getRenderTargets()->loadBlendState(blendState);
23 baseSpectrum.initialize(device);
27void Cogs::OceanRenderer::initializeTextures(ITextures * , IRenderTargets * )
31void Cogs::OceanRenderer::initializeEffects(IBuffers * buffers, IEffects * effects,
const size_t numImagery,
size_t permutation)
33 auto & permutationOceanData = getPermutationDependentOceanRendererData(permutation);
34 if (!permutationOceanData.initialized) {
36 initializeConstantBuffers(buffers, permutationOceanData.oceanEffect, permutationOceanData.effectVariables, permutationOceanData.oceanEffectVariables,
false);
39 initializeEffectVariables(effects, permutationOceanData.oceanEffect, permutationOceanData.effectVariables, permutationOceanData.oceanEffectVariables, numImagery,
false);
40 initializeEffectBindings(effects, permutationOceanData.oceanEffect, permutationOceanData.oceanEffectBindings, numImagery,
false);
43 VertexFormatHandle meshFormat = device->getBuffers()->createVertexFormat(&element, 1);
44 inputLayout = buffers->loadInputLayout(&meshFormat, 1, permutationOceanData.oceanEffect);
46 permutationOceanData.initialized =
true;
49void Cogs::OceanRenderer::initializeConstantBuffers(IBuffers * buffers, EffectHandle , ClipmapEffectVariables & variables, OceanEffectVariables & oceanEffectVariables,
bool )
63void Cogs::OceanRenderer::initializeEffectVariables(IEffects * effects, EffectHandle effectHandle, ClipmapEffectVariables & variables, OceanEffectVariables & oceanEffectVariables,
const size_t ,
bool isDepth)
65 variables.globalBufferBinding= effects->getConstantBufferBinding(effectHandle,
"GlobalParameters");
66 variables.levelBufferBinding = effects->getConstantBufferBinding(effectHandle,
"LevelParameters");
68 variables.patchBufferBinding = effects->getConstantBufferBinding(effectHandle,
"PatchParameters");
71 variables.imageryBufferBinding = effects->getConstantBufferBinding(effectHandle,
"ImageryParameters");
73 variables.renderBufferBinding = effects->getConstantBufferBinding(effectHandle,
"RenderParameters");
74 variables.levelRenderBufferBinding = effects->getConstantBufferBinding(effectHandle,
"LevelRenderParameters");
77 variables.customParametersBufferBinding = effects->getConstantBufferBinding(effectHandle,
"CustomParameters");
79 oceanEffectVariables.oceanBufferBinding = effects->getConstantBufferBinding(effectHandle,
"OceanParameters");
84 const char * imagerySemantics[] = {
91 const char * coarseImagerySemantics[] = {
92 "coarseImageryTexture[0]",
93 "coarseImageryTexture[1]",
94 "coarseImageryTexture[2]",
95 "coarseImageryTexture[3]",
99void Cogs::OceanRenderer::initializeEffectBindings(IEffects * effects, EffectHandle effect, ClipmapTextureBindings & bindings,
const size_t numImagery,
bool isDepth)
103 bindings.heightMapBinding = effects->getTextureBinding(effect,
"heightTexture", unit);
104 bindings.heightMapSamplerBinding = effects->getSamplerStateBinding(effect,
"heightSampler", unit++);
106 bindings.coarseHeightMapBinding = effects->getTextureBinding(effect,
"coarseHeightTexture", unit);
107 bindings.coarseHeightMapSamplerBinding = effects->getSamplerStateBinding(effect,
"coarseHeightSampler", unit++);
110 bindings.normalMapBinding = effects->getTextureBinding(effect,
"normalTexture", unit);
111 bindings.normalMapSamplerBinding = effects->getSamplerStateBinding(effect,
"normalSampler", unit++);
113 bindings.coarseNormalMapBinding = effects->getTextureBinding(effect,
"coarseNormalTexture", unit);
114 bindings.coarseNormalMapSamplerBinding = effects->getSamplerStateBinding(effect,
"normalSampler", unit++);
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++);
123 perImageBindings.coarseImageryBinding = effects->getTextureBinding(effect, coarseImagerySemantics[i], unit);
124 perImageBindings.coarseImagerySamplerBinding = effects->getSamplerStateBinding(effect,
"imagerySampler", unit++);
127 auto & perImageBindings = bindings.getImageryBindingHandles(0);
128 perImageBindings.imageryBinding = effects->getTextureBinding(effect,
"imageryTexture[0]", unit);
129 perImageBindings.imagerySamplerBinding = effects->getSamplerStateBinding(effect,
"imagerySampler", unit++);
131 perImageBindings.coarseImageryBinding = effects->getTextureBinding(effect,
"coarseImageryTexture[0]", unit);
132 perImageBindings.coarseImagerySamplerBinding = perImageBindings.imagerySamplerBinding;
140 template<
typename Parameters>
141 void applyParameters(IContext * context,
const Parameters & parameters, BufferHandle bufferHandle)
145 ::memcpy(out, ¶meters,
sizeof(Parameters));
147 context->unmap(bufferHandle);
151void Cogs::OceanRenderer::updateGlobalParameters(
const RenderContext & renderContext,
const RenderOptions & renderOptions,
const ClipmapState & ,
const GlobalParameters & globalParameters)
153 IContext * context = renderContext.context;
154 auto & permutationOceanData = getPermutationDependentOceanRendererData(renderContext.permutation);
156 const auto & variables = permutationOceanData.effectVariables;
158 RenderParameters renderParameters;
159 renderParameters.blendRegionColor = renderOptions.blendRegionColor;
160 renderParameters.showBlendRegions = renderOptions.showBlendRegions;
161 renderParameters.showImagery = renderOptions.showImagery;
162 renderParameters.showLevelColors = renderOptions.showLevelColors;
164 applyParameters(context, renderParameters, variables.renderBuffer);
166 applyParameters(context, globalParameters, variables.globalBuffer);
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];
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];
176 oceanParameters.viewportScale.x = 2.f*renderContext.width;
177 oceanParameters.viewportScale.y = 2.f*renderContext.height;
179 oceanParameters.tileCoordsFromWorld.x =
static_cast<float>(baseTileCoordsFromWorld);
180 oceanParameters.tileCoordsFromWorld.y =
static_cast<float>(detailTileCoordsFromWorld);
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));
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));
192 oceanParameters.oneOverTileExtentAdjust = 1.f / baseSpectrum.getTileExtentAdjust();
198 applyParameters(context, oceanParameters, permutationOceanData.oceanEffectVariables.oceanBuffer);
201void Cogs::OceanRenderer::updateLevelParameters(IContext * context,
const RenderOptions & options,
const LevelParameters & parameters,
const ImageryParameters & imageryParameters,
size_t permutation)
203 auto & permutationOceanData = getPermutationDependentOceanRendererData(permutation);
204 const auto & variables = permutationOceanData.effectVariables;
206 applyParameters(context, parameters, variables.levelBuffer);
207 applyParameters(context, imageryParameters, variables.imageryBuffer);
209 applyParameters(context, options.diffuseColor, variables.levelRenderBuffer);
212void Cogs::OceanRenderer::updateLevelTextures(IContext * context,
const RenderLevel * renderLevel,
size_t permutation)
214 auto & permutationOceanData = getPermutationDependentOceanRendererData(permutation);
215 auto & bindings = permutationOceanData.oceanEffectBindings;
217 context->setTexture(bindings.heightMapBinding, renderLevel->terrainLevel->renderTexture.handle);
218 context->setSamplerState(bindings.heightMapSamplerBinding, renderer->pointSamplerState);
220 context->setTexture(bindings.coarseHeightMapBinding, renderLevel->coarserTerrainLevel->renderTexture.handle);
221 context->setSamplerState(bindings.coarseHeightMapSamplerBinding, renderer->linearSamplerState);
223 if (renderLevel->normalLevel) {
224 context->setTexture(bindings.normalMapBinding, renderLevel->normalLevel->renderTexture.handle);
225 context->setSamplerState(bindings.normalMapSamplerBinding, renderer->linearSamplerState);
227 context->setTexture(bindings.coarseNormalMapBinding, renderLevel->coarserNormalLevel->renderTexture.handle);
228 context->setSamplerState(bindings.coarseNormalMapSamplerBinding, renderer->linearSamplerState);
231 const size_t levelIndex = renderLevel->terrainLevel->index;
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);
238 context->setTexture(perImageBindings.imageryBinding, imageryLevel.renderTexture.handle);
239 context->setSamplerState(perImageBindings.imagerySamplerBinding, renderer->linearSamplerState);
241 context->setTexture(perImageBindings.coarseImageryBinding, imageryLevel.coarserLevel->renderTexture.handle);
242 context->setSamplerState(perImageBindings.coarseImagerySamplerBinding, renderer->linearSamplerState);
247void Cogs::OceanRenderer::preRender(RenderContext & renderContext)
249 CommandGroupAnnotation preGroup(renderContext.context,
"Ocean::preRender");
252 if ((baseTileSizeLog2 != oceanOptions.baseTileSizeLog2) ||
253 (baseTileLength != oceanOptions.baseTileLength) ||
254 (significantWavePeriod != oceanOptions.significantWavePeriod))
257 if (baseTileSizeLog2 != oceanOptions.baseTileSizeLog2) {
258 baseTileSizeLog2 = oceanOptions.baseTileSizeLog2;
259 baseSpectrum.setSize(baseTileSizeLog2);
262 baseTileLength = oceanOptions.baseTileLength;
263 significantWavePeriod = oceanOptions.significantWavePeriod;
265 baseSpectrum.setConditions(baseTileLength,
267 significantWavePeriod,
272 float dt =
static_cast<float>(timer.elapsedSeconds());
275 baseSpectrum.update(renderContext, dt);
278void Cogs::OceanRenderer::setupOceanPass(RenderContext & renderContext)
280 auto context = renderContext.context;
281 auto & permutationOceanData = getPermutationDependentOceanRendererData(renderContext.permutation);
282 auto & variables = permutationOceanData.effectVariables;
284 context->setEffect(permutationOceanData.oceanEffect);
285 context->setInputLayout(inputLayout);
287 renderContext.oceanCallback(permutationOceanData.oceanEffect);
289 context->setTexture(
"wavePosition", 0, baseSpectrum.positionTex());
290 context->setSamplerState(
"wavePositionSampler", 0, renderer->linearSamplerState);
292 context->setTexture(
"waveDerivatives", 1, baseSpectrum.derivativesTex());
293 context->setSamplerState(
"waveDerivativesSampler", 1, renderer->linearSamplerState);
295 if (renderContext.wireframe) {
296 context->setRasterizerState(renderer->wireframeRasterizerState);
298 context->setRasterizerState(renderContext.offsetEnabled ? renderer->solidOffsetRasterizerState : renderer->solidRasterizerState);
301 if (!renderContext.isOIT) {
302 context->setBlendState(blendStateHandle);
304 context->setDepthStencilState(renderContext.wireframe ? renderer->transparentWireframeDepthState : renderer->transparentDepthState);
307 context->setConstantBuffer(variables.globalBufferBinding, variables.globalBuffer);
308 context->setConstantBuffer(variables.levelBufferBinding, variables.levelBuffer);
311 context->setConstantBuffer(variables.imageryBufferBinding, variables.imageryBuffer);
314 context->setConstantBuffer(variables.patchBufferBinding, variables.patchBuffer);
317 context->setConstantBuffer(variables.renderBufferBinding, variables.renderBuffer);
321 context->setConstantBuffer(variables.levelRenderBufferBinding, variables.levelRenderBuffer);
324 if (
HandleIsValid(permutationOceanData.oceanEffectVariables.oceanBufferBinding)) {
325 context->setConstantBuffer(permutationOceanData.oceanEffectVariables.oceanBufferBinding, permutationOceanData.oceanEffectVariables.oceanBuffer);
329 context->setConstantBuffer(variables.customParametersBufferBinding, renderer->customParametersBuffer);
333void Cogs::OceanRenderer::render(RenderContext & renderContext,
const RenderOptions & renderOptions,
const WorldOptions & worldOptions,
bool usePreviousCullingResults)
335 if (!usePreviousCullingResults) {
336 for (
size_t i = 0; i < renderer->levelIndex; ++i) {
337 const RenderLevel & renderLevel = renderer->levels[i];
339 updateLevelTextures(renderContext.context, &renderLevel, renderContext.permutation);
341 updateLevelParameters(renderContext.context, renderOptions, *renderLevel.levelParameters, *renderLevel.imageryParameters, renderContext.permutation);
343 cullRenderBlocks(renderLevel.renderBlocks,
344 renderer->visibleBlocks + i * kMaxNumBlocks,
345 renderLevel.blockCount,
347 renderContext.cullVolume,
348 renderContext.center - renderContext.cullOrigin,
350 static_cast<float>(worldOptions.worldScale.x),
351 static_cast<float>(worldOptions.worldScale.y));
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);
360 for (
size_t i = 0; i < renderer->levelIndex; ++i) {
361 const RenderLevel & renderLevel = renderer->levels[i];
363 updateLevelTextures(renderContext.context, &renderLevel, renderContext.permutation);
365 updateLevelParameters(renderContext.context, renderOptions, *renderLevel.levelParameters, *renderLevel.imageryParameters, renderContext.permutation);
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);
376void Cogs::OceanRenderer::drawBlock(
const RenderBlock & renderBlock, RenderContext & renderContext)
378 IContext * context = renderContext.context;
380 auto & permutationOceanData = getPermutationDependentOceanRendererData(renderContext.permutation);
381 applyParameters(context, renderBlock.patchOriginInClippedLevel, permutationOceanData.effectVariables.patchBuffer);
383 context->setVertexBuffers(&renderBlock.mesh->vertexBuffer, 1, &renderBlock.mesh->stride,
nullptr);
384 context->setIndexBuffer(renderBlock.mesh->indexBuffer, 2, 0);
389void Cogs::OceanRenderer::setOptions(
const OceanOptions * options)
391 oceanOptions = *options;
394void Cogs::OceanRenderer::update()
396 float significantWaveLength = (9.81f*oceanOptions.significantWavePeriod*oceanOptions.significantWavePeriod) / (2.f*glm::pi<float>());
398 oceanParameters.deepColor = oceanOptions.deepColor;
399 oceanParameters.shallowColor = oceanOptions.shallowColor;
400 oceanParameters.roughColor = oceanOptions.roughColor;
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;
409 oceanParameters.foamErosionValue = oceanOptions.foamErosionValue;
410 oceanParameters.shoalingEffectFactor = oceanOptions.shoalingEffectFactor;
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;
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.
@ 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.
@ ConstantBuffer
The buffer can be bound as input to effects as a constant buffer.
Encapsulates blend state for the graphics pipeline in a state object.
@ WriteDiscard
Write access. When unmapping the graphics system will discard the old contents of the resource.
@ Dynamic
Buffer will be loaded and modified with some frequency.