1#include "ClipmapDepthQuery.h"
2#include "ClipmapRenderer.h"
4#include "Foundation/Logging/Logger.h"
6#include "Rendering/IBuffers.h"
7#include "Rendering/IContext.h"
14Cogs::ClipmapDepthQuery::ClipmapDepthQuery()
16 clipmapRenderer(nullptr)
21void Cogs::ClipmapDepthQuery::initialize(IGraphicsDevice * device, ClipmapRenderer * clipmapRenderer)
23 this->device = device;
24 this->clipmapRenderer = clipmapRenderer;
26 const size_t queryBufferSize = clipmapRenderer->depthQuerySize * clipmapRenderer->depthQuerySize *
sizeof(float) * 4;
31Cogs::ClipmapDepthQuery::~ClipmapDepthQuery()
35 auto buffers = device->getBuffers();
38 buffers->releaseBuffer(queryReadBackBuffer);
42void Cogs::ClipmapDepthQuery::readBack()
44 IContext * context = this->device->getImmediateContext();
45 for (
auto & data : clipmapRenderer->raypickDepthData) {
46 context->setRenderTarget(data.depthRenderHandle, data.depthTargetHandle);
47 context->readColorBuffer(data.readbackBufferHandle, 0, 0, data.width, data.height,
Framebuffer::Front);
50 context->setRenderTarget(clipmapRenderer->depthQueryRenderHandle, clipmapRenderer->depthQueryTargetHandle);
51 context->readColorBuffer(queryReadBackBuffer, 0, 0, clipmapRenderer->depthQuerySize, clipmapRenderer->depthQuerySize,
Framebuffer::Front);
53 hasReadBack = clipmapRenderer->raypickDepthData[0].depthRenderInitialized && clipmapRenderer->depthQueryRenderInitialized;
56bool Cogs::ClipmapDepthQuery::getPositions(
const Vector2 * mousePositions,
const Matrix & inverseViewProjection,
const size_t numPositions, Vector4 * worldPos,
bool * positionValid,
int rayPickId)
58 if (rayPickId < 0 || rayPickId >=
static_cast<int>(clipmapRenderer->raypickDepthData.size())) {
59 LOG_ERROR(logger,
"Invalid ray pick id: %d", rayPickId);
63 auto & depthData = clipmapRenderer->raypickDepthData[rayPickId];
64 if (!device || !
HandleIsValid(depthData.readbackBufferHandle) || !hasReadBack)
return false;
66 IContext * context = this->device->getImmediateContext();
68 MappedBuffer<float> data(context, depthData.readbackBufferHandle,
MapMode::Read);
70 if (!data)
return false;
72 bool anyValid =
false;
73 const int width = depthData.width;
74 const int height = depthData.height;
78 const int rowPitch = data.getStride() ? data.getStride() /
sizeof(float) : width;
80 for (
size_t i = 0; i < numPositions; ++i) {
81 const float screenX = mousePositions[i][0] * width;
82 const float screenY = (flip ? (1.0f - mousePositions[i][1]) : mousePositions[i][1]) * height;
84 const int screenIndexX =
static_cast<int>(screenX);
85 const int screenIndexY =
static_cast<int>(screenY);
87 if ((screenIndexX < 0 || screenIndexX >= width) || (screenIndexY < 0 || screenIndexY >= height)) {
88 LOG_WARNING(logger,
"Readback positions outside of buffer dimensions.");
93 const float depth = data[screenIndexY * rowPitch + screenIndexX];
94 float clearDepth = 1.0;
95 if(clipmapRenderer->reverseDepth)
98 if (depth != clearDepth) {
101 const float x = (mousePositions[i][0] - 0.5f) * 2.0f;
102 const float y = (mousePositions[i][1] - 0.5f) * 2.0f;
104 const Vector4 screenPos(x, y, depth, 1);
106 worldPos[i] = inverseViewProjection * screenPos;
108 if (worldPos[i][3] != 0) {
110 worldPos[i] /= worldPos[i][3];
111 positionValid[i] =
true;
114 positionValid[i] =
false;
117 positionValid[i] =
false;
126 if (!device || !HandleIsValid(queryReadBackBuffer))
return 0.0f;
128 IContext * context = this->device->getImmediateContext();
132 if (!data)
return 0.0f;
134 float min = std::numeric_limits<float>::max();
138 auto size = clipmapRenderer->depthQuerySize;
139 const int sampleSize = 4;
140 const int rowPitch = data.getStride() ? data.getStride() / (
sizeof(float) * sampleSize) : size;
142 for (
int y = 0; y < size; ++y) {
143 for (
int x = 0; x < size; ++x) {
144 int sampleIndex = (y * rowPitch + x) * sampleSize;
146 const float depth = data[sampleIndex];
147 float clearDepth = 1.0;
148 if(clipmapRenderer->reverseDepth)
151 if (depth != clearDepth) {
152 const float xPos = data[sampleIndex + 1];
153 const float yPos = data[sampleIndex + 2];
155 if(clipmapRenderer->reverseDepth){
173 const Vector4 screenPos(minX, minY, min, 1);
176 viewPos = inverseProjection * screenPos;
178 if (viewPos[3] != 0) {
179 viewPos /= viewPos[3];
189 if (!device || !HandleIsValid(queryReadBackBuffer))
return 0.0f;
191 IContext * context = this->device->getImmediateContext();
195 if (!data)
return 0.0f;
197 float min = std::numeric_limits<float>::max();
201 auto size = clipmapRenderer->depthQuerySize;
202 const int sampleSize = 4;
203 const int rowPitch = data.getStride() ? data.getStride() / (
sizeof(float) * sampleSize) : size;
205 for (
int y = 0; y < size; ++y) {
206 for (
int x = 0; x < size; ++x) {
207 int sampleIndex = (y * rowPitch + x) * sampleSize;
209 float depth = data[sampleIndex];
210 float clearDepth = 1.0;
211 if(clipmapRenderer->reverseDepth)
214 if (depth != clearDepth) {
215 const float xPos = data[sampleIndex + 1];
216 const float yPos = data[sampleIndex + 2];
218 if(clipmapRenderer->reverseDepth){
236 const Vector4 screenPos(minX, minY, min, 1);
239 viewPos = inverseProjection * screenPos;
244 viewPos /= viewPos[3];
248 if (prevViewPos[3]) {
249 prevViewPos = viewMatrix * glm::inverse(prevViewMatrix) * prevViewPos;
250 ret = std::min(ret, -prevViewPos[2]);
253 prevViewPos = viewPos;
254 prevViewMatrix = viewMatrix;
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
@ Direct3D11
Graphics device using the Direct3D 11 API.
@ Read
The buffer can be mapped and read from by the CPU after creation.
float getNearestTerrainSample(const Matrix &inverseProjection)
Returns the nearest sample in the query readback buffer.
float getNearestTerrainSample2(const Matrix &inverseProjection, const Matrix &viewMatrix)
Returns the nearest sample in the query readback buffer for two frames.
static const Handle_t NoHandle
Represents a handle to nothing.
Represents a graphics device context which can receive rendering commands.
Provides RAII style mapping of a buffer resource.