1#include "NormalUpdater.h"
2#include "ClipmapUpdate.h"
4#include "RenderContext.h"
5#include "Raster/RasterLevel.h"
7#include "Rendering/IGraphicsDevice.h"
8#include "Rendering/IEffects.h"
9#include "Rendering/IContext.h"
10#include "Rendering/IBuffers.h"
12#include "Foundation/Logging/Logger.h"
25 Matrix projectionMatrix;
26 Vector2 oneOverHeightMapSize;
28 float heightExaggeration;
39void Cogs::NormalUpdater::initialize(IGraphicsDevice * device)
42 VertexFormatHandle positionFormat = device->getBuffers()->createVertexFormat(&positionElement, 1);
43 vertexBufferHandle = device->getBuffers()->loadVertexBuffer(quadVertices, 6, positionFormat);
45 IEffects * effects = device->getEffects();
47 LOG_DEBUG(logger,
"Loading climpap normal update effect.");
49 computeNormalsEffectHandle = Terrain::EffectLoader::loadEffect(effects,
"ClipmapComputeNormalsVS",
"ClipmapComputeNormalsPS");
52 LOG_ERROR(logger,
"Error loading normal computation effect.");
58 auto buffers = device->getBuffers();
60 computeNormalsLayoutHandle = device->getBuffers()->loadInputLayout(&positionFormat, 1, computeNormalsEffectHandle);
63 normalLevelBinding = effects->getConstantBufferBinding(computeNormalsEffectHandle,
"NormalLevelParameters");
66 normalUpdateBinding = effects->getConstantBufferBinding(computeNormalsEffectHandle,
"NormalUpdateParameters");
68 SamplerState nearestRepeatState = {
73 SamplerState::ComparisonFunction::Never,
75 { 0.0f, 0.0f, 0.0f, 0.0f }
78 nearestRepeatStateHandle = device->getTextures()->loadSamplerState(nearestRepeatState);
79 samplerStateBinding = effects->getSamplerStateBinding(computeNormalsEffectHandle, std::string(), 0);
81 levelTextureBinding = effects->getTextureBinding(computeNormalsEffectHandle,
"heightTexture", 0);
84void Cogs::NormalUpdater::updateNormalLevel(RenderContext & context,
const WorldOptions & worldOptions,
const ClipmapUpdate & clipmapUpdate, ClipmapLevel & normalLevel)
88 ClipmapUpdate updateWithBuffer = clipmapUpdate.addBufferWithinLevelNextExtent();
90 static std::vector<ClipmapUpdate> normalUpdates;
92 normalUpdates.clear();
94 ClipmapUpdate::splitUpdateToAvoidWrapping(updateWithBuffer, normalUpdates);
96 renderNormals(context, worldOptions, normalUpdates, normalLevel);
99void Cogs::NormalUpdater::renderNormals(RenderContext & renderContext,
const WorldOptions & worldOptions,
const std::vector<ClipmapUpdate> & normalUpdates, ClipmapLevel & normalLevel)
101 if (!normalUpdates.size() || !
HandleIsValid(computeNormalsEffectHandle))
return;
103 IContext * context = renderContext.context;
105 const ClipmapLevel * terrainLevel = normalUpdates[0].getLevel();
106 auto & nextExtent = terrainLevel->nextExtent;
108 const float width =
static_cast<float>(normalLevel.renderTexture.width);
109 const float height =
static_cast<float>(normalLevel.renderTexture.height);
112 context->setViewport(0, 0, width, height);
114 context->setEffect(computeNormalsEffectHandle);
116 context->setTexture(levelTextureBinding, terrainLevel->renderTexture.handle);
117 context->setSamplerState(samplerStateBinding, nearestRepeatStateHandle);
119 const uint32_t strides[] = { 2 *
sizeof(float) };
120 context->setVertexBuffers(&vertexBufferHandle, 1, strides,
nullptr);
121 context->setInputLayout(computeNormalsLayoutHandle);
123 context->setConstantBuffer(normalLevelBinding, normalLevelBuffer);
124 context->setConstantBuffer(normalUpdateBinding, normalUpdateBuffer);
127 MappedBuffer<NormalLevelParameters> levelParameters(context, normalLevelBuffer,
MapMode::WriteDiscard);
129 if (levelParameters) {
130 levelParameters->heightExaggeration = worldOptions.heightExaggeration;
132 levelParameters->projectionMatrix = glm::ortho<float>(0,
static_cast<float>(nextExtent.east - nextExtent.west), 0,
static_cast<float>(nextExtent.north - nextExtent.south), -1.0f, 1.0f);
134 levelParameters->oneOverHeightMapSize = Vector2(
135 1.0f / (
float) (terrainLevel->nextExtent.east - terrainLevel->nextExtent.west + 1),
136 1.0f / (
float) (terrainLevel->nextExtent.north - terrainLevel->nextExtent.south + 1));
138 levelParameters->postDelta =
static_cast<float>(terrainLevel->rasterLevel->getPostDeltaLongitude() * worldOptions.worldScale.x);
142 const int clipmapSize = terrainLevel->nextExtent.east - terrainLevel->nextExtent.west + 1;
144 for (
size_t i = 0; i < normalUpdates.size(); ++i) {
145 const ClipmapUpdate & normalUpdate = normalUpdates[i];
147 const int west = (terrainLevel->origin.x + (normalUpdate.getWest() - terrainLevel->nextExtent.west)) % clipmapSize;
148 const int south = (terrainLevel->origin.y + (normalUpdate.getSouth() - terrainLevel->nextExtent.south)) % clipmapSize;
151 MappedBuffer<NormalUpdateParameters> updateParameters(context, normalUpdateBuffer,
MapMode::WriteDiscard);
153 if (updateParameters) {
154 updateParameters->origin = Vector2(
static_cast<float>(west),
static_cast<float>(south));
155 updateParameters->updateSize = Vector2(
static_cast<float>(normalUpdate.getWidth()),
static_cast<float>(normalUpdate.getHeight()));
Log implementation class.
bool HandleIsValid(const ResourceHandle_t< T > &handle)
Check if the given resource is valid, that is not equal to NoHandle or InvalidHandle.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Contains all Cogs related functionality.
@ Ready
The resource has loaded successfully and is ready for use.
@ 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.
static const Handle_t InvalidHandle
Represents an invalid handle.
@ WriteDiscard
Write access. When unmapping the graphics system will discard the old contents of the resource.
@ Wrap
Texture coordinates automatically wrap around to [0, 1] range.
@ MinMagMipPoint
Point sampling for both minification and magnification.
@ Dynamic
Buffer will be loaded and modified with some frequency.