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"
23 Matrix projectionMatrix;
24 Vector2 oneOverHeightMapSize;
26 float heightExaggeration;
37void Cogs::NormalUpdater::initialize(IGraphicsDevice * device)
40 VertexFormatHandle positionFormat = device->getBuffers()->createVertexFormat(&positionElement, 1);
41 vertexBufferHandle = device->getBuffers()->loadVertexBuffer(quadVertices, 6, positionFormat);
43 IEffects * effects = device->getEffects();
45 LOG_DEBUG(logger,
"Loading climpap normal update effect.");
47 computeNormalsEffectHandle = Terrain::EffectLoader::loadEffect(effects,
"ClipmapComputeNormalsVS",
"ClipmapComputeNormalsPS");
50 LOG_ERROR(logger,
"Error loading normal computation effect.");
55 auto buffers = device->getBuffers();
57 computeNormalsLayoutHandle = device->getBuffers()->loadInputLayout(&positionFormat, 1, computeNormalsEffectHandle);
60 normalLevelBinding = effects->getConstantBufferBinding(computeNormalsEffectHandle,
"NormalLevelParameters");
63 normalUpdateBinding = effects->getConstantBufferBinding(computeNormalsEffectHandle,
"NormalUpdateParameters");
65 SamplerState nearestRepeatState = {
70 SamplerState::ComparisonFunction::Never,
72 { 0.0f, 0.0f, 0.0f, 0.0f }
75 nearestRepeatStateHandle = device->getTextures()->loadSamplerState(nearestRepeatState);
76 samplerStateBinding = effects->getSamplerStateBinding(computeNormalsEffectHandle, std::string(), 0);
78 levelTextureBinding = effects->getTextureBinding(computeNormalsEffectHandle,
"heightTexture", 0);
81void Cogs::NormalUpdater::updateNormalLevel(RenderContext & context,
const WorldOptions & worldOptions,
const ClipmapUpdate & clipmapUpdate, ClipmapLevel & normalLevel)
85 ClipmapUpdate updateWithBuffer = clipmapUpdate.addBufferWithinLevelNextExtent();
87 static std::vector<ClipmapUpdate> normalUpdates;
89 normalUpdates.clear();
91 ClipmapUpdate::splitUpdateToAvoidWrapping(updateWithBuffer, normalUpdates);
93 renderNormals(context, worldOptions, normalUpdates, normalLevel);
96void Cogs::NormalUpdater::renderNormals(RenderContext & renderContext,
const WorldOptions & worldOptions,
const std::vector<ClipmapUpdate> & normalUpdates, ClipmapLevel & normalLevel)
98 if (!normalUpdates.size() || !
HandleIsValid(computeNormalsEffectHandle))
return;
100 IContext * context = renderContext.context;
102 const ClipmapLevel * terrainLevel = normalUpdates[0].getLevel();
103 auto & nextExtent = terrainLevel->nextExtent;
105 const float width =
static_cast<float>(normalLevel.renderTexture.width);
106 const float height =
static_cast<float>(normalLevel.renderTexture.height);
109 context->setViewport(0, 0, width, height);
111 context->setEffect(computeNormalsEffectHandle);
113 context->setTexture(levelTextureBinding, terrainLevel->renderTexture.handle);
114 context->setSamplerState(samplerStateBinding, nearestRepeatStateHandle);
116 const uint32_t strides[] = { 2 *
sizeof(float) };
117 context->setVertexBuffers(&vertexBufferHandle, 1, strides,
nullptr);
118 context->setInputLayout(computeNormalsLayoutHandle);
120 context->setConstantBuffer(normalLevelBinding, normalLevelBuffer);
121 context->setConstantBuffer(normalUpdateBinding, normalUpdateBuffer);
124 MappedBuffer<NormalLevelParameters> levelParameters(context, normalLevelBuffer,
MapMode::WriteDiscard);
126 if (levelParameters) {
127 levelParameters->heightExaggeration = worldOptions.heightExaggeration;
129 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);
131 levelParameters->oneOverHeightMapSize = Vector2(
132 1.0f / (
float) (terrainLevel->nextExtent.east - terrainLevel->nextExtent.west + 1),
133 1.0f / (
float) (terrainLevel->nextExtent.north - terrainLevel->nextExtent.south + 1));
135 levelParameters->postDelta =
static_cast<float>(terrainLevel->rasterLevel->getPostDeltaLongitude() * worldOptions.worldScale.x);
139 const int clipmapSize = terrainLevel->nextExtent.east - terrainLevel->nextExtent.west + 1;
141 for (
size_t i = 0; i < normalUpdates.size(); ++i) {
142 const ClipmapUpdate & normalUpdate = normalUpdates[i];
144 const int west = (terrainLevel->origin.x + (normalUpdate.getWest() - terrainLevel->nextExtent.west)) % clipmapSize;
145 const int south = (terrainLevel->origin.y + (normalUpdate.getSouth() - terrainLevel->nextExtent.south)) % clipmapSize;
148 MappedBuffer<NormalUpdateParameters> updateParameters(context, normalUpdateBuffer,
MapMode::WriteDiscard);
150 if (updateParameters) {
151 updateParameters->origin = Vector2(
static_cast<float>(west),
static_cast<float>(south));
152 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.
@ VertexData
Per vertex data.
@ 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.
@ TriangleList
List of triangles.
@ 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.