From fdb93309feaa51289b25c1aa976cef373944f2fa Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sun, 8 Dec 2019 01:39:17 +0100 Subject: [PATCH] Fix render to texture --- .../polyrenderer/backend/poly_framebuffer.cpp | 8 +++--- .../polyrenderer/backend/poly_renderstate.cpp | 9 ++++--- .../polyrenderer/backend/poly_renderstate.h | 3 ++- .../polyrenderer/drawers/poly_triangle.cpp | 26 ++++++++++++++----- .../polyrenderer/drawers/poly_triangle.h | 12 +++++---- .../polyrenderer/drawers/poly_vertex_shader.h | 2 -- .../polyrenderer/drawers/screen_triangle.cpp | 6 ++++- 7 files changed, 43 insertions(+), 23 deletions(-) diff --git a/src/rendering/polyrenderer/backend/poly_framebuffer.cpp b/src/rendering/polyrenderer/backend/poly_framebuffer.cpp index 413b97ef6..365770968 100644 --- a/src/rendering/polyrenderer/backend/poly_framebuffer.cpp +++ b/src/rendering/polyrenderer/backend/poly_framebuffer.cpp @@ -97,6 +97,7 @@ void PolyFrameBuffer::CheckCanvas() { if (!mCanvas || mCanvas->GetWidth() != GetWidth() || mCanvas->GetHeight() != GetHeight()) { + FlushDrawCommands(); DrawerThreads::WaitForWorkers(); mCanvas.reset(new DCanvas(0, 0, true)); @@ -104,7 +105,7 @@ void PolyFrameBuffer::CheckCanvas() mDepthStencil.reset(); mDepthStencil.reset(new PolyDepthStencil(GetWidth(), GetHeight())); - mRenderState->SetRenderTarget(GetCanvas(), GetDepthStencil()); + mRenderState->SetRenderTarget(GetCanvas(), GetDepthStencil(), true); } } @@ -342,7 +343,7 @@ void PolyFrameBuffer::RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint, int height = mat->TextureHeight(); DCanvas *image = BaseLayer->GetImage(tex, 0, 0); PolyDepthStencil *depthStencil = BaseLayer->GetDepthStencil(tex); - mRenderState->SetRenderTarget(image, depthStencil); + mRenderState->SetRenderTarget(image, depthStencil, false); IntRect bounds; bounds.left = bounds.top = 0; @@ -352,8 +353,9 @@ void PolyFrameBuffer::RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint, FRenderViewpoint texvp; RenderViewpoint(texvp, Viewpoint, &bounds, FOV, (float)width / height, (float)width / height, false, false); + FlushDrawCommands(); DrawerThreads::WaitForWorkers(); - mRenderState->SetRenderTarget(GetCanvas(), GetDepthStencil()); + mRenderState->SetRenderTarget(GetCanvas(), GetDepthStencil(), true); tex->SetUpdated(true); } diff --git a/src/rendering/polyrenderer/backend/poly_renderstate.cpp b/src/rendering/polyrenderer/backend/poly_renderstate.cpp index 61dd19a99..bf6400763 100644 --- a/src/rendering/polyrenderer/backend/poly_renderstate.cpp +++ b/src/rendering/polyrenderer/backend/poly_renderstate.cpp @@ -201,7 +201,7 @@ void PolyRenderState::Apply() if (mNeedApply) { - mDrawCommands->SetViewport(mViewport.x, mViewport.y, mViewport.width, mViewport.height, mRenderTarget.Canvas, mRenderTarget.DepthStencil); + mDrawCommands->SetViewport(mViewport.x, mViewport.y, mViewport.width, mViewport.height, mRenderTarget.Canvas, mRenderTarget.DepthStencil, mRenderTarget.TopDown); mDrawCommands->SetScissor(mScissor.x, mScissor.y, mScissor.width, mScissor.height); mDrawCommands->SetViewpointUniforms(mViewpointUniforms); mDrawCommands->SetDepthClamp(mDepthClamp); @@ -282,7 +282,7 @@ void PolyRenderState::ApplyMaterial() if (base) { DCanvas *texcanvas = base->GetImage(mMaterial); - mDrawCommands->SetTexture(0, texcanvas->GetPixels(), texcanvas->GetHeight(), texcanvas->GetWidth(), texcanvas->IsBgra()); + mDrawCommands->SetTexture(0, texcanvas->GetPixels(), texcanvas->GetWidth(), texcanvas->GetHeight(), texcanvas->IsBgra()); int numLayers = mMaterial.mMaterial->GetLayers(); for (int i = 1; i < numLayers; i++) @@ -291,7 +291,7 @@ void PolyRenderState::ApplyMaterial() auto systex = static_cast(mMaterial.mMaterial->GetLayer(i, 0, &layer)); texcanvas = systex->GetImage(layer, 0, mMaterial.mMaterial->isExpanded() ? CTF_Expand : 0); - mDrawCommands->SetTexture(i, texcanvas->GetPixels(), texcanvas->GetHeight(), texcanvas->GetWidth(), texcanvas->IsBgra()); + mDrawCommands->SetTexture(i, texcanvas->GetPixels(), texcanvas->GetWidth(), texcanvas->GetHeight(), texcanvas->IsBgra()); } } @@ -347,10 +347,11 @@ void PolyRenderState::ApplyMatrices() } } -void PolyRenderState::SetRenderTarget(DCanvas *canvas, PolyDepthStencil *depthStencil) +void PolyRenderState::SetRenderTarget(DCanvas *canvas, PolyDepthStencil *depthStencil, bool topdown) { mRenderTarget.Canvas = canvas; mRenderTarget.DepthStencil = depthStencil; + mRenderTarget.TopDown = topdown; } void PolyRenderState::Bind(PolyDataBuffer *buffer, uint32_t offset, uint32_t length) diff --git a/src/rendering/polyrenderer/backend/poly_renderstate.h b/src/rendering/polyrenderer/backend/poly_renderstate.h index e677dd714..1370a15aa 100644 --- a/src/rendering/polyrenderer/backend/poly_renderstate.h +++ b/src/rendering/polyrenderer/backend/poly_renderstate.h @@ -40,7 +40,7 @@ public: void EnableLineSmooth(bool on) override; void EnableDrawBuffers(int count) override; - void SetRenderTarget(DCanvas *canvas, PolyDepthStencil *depthStencil); + void SetRenderTarget(DCanvas *canvas, PolyDepthStencil *depthStencil, bool topdown); void Bind(PolyDataBuffer *buffer, uint32_t offset, uint32_t length); PolyVertexInputAssembly *GetVertexFormat(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute *attrs); void EndRenderPass(); @@ -69,6 +69,7 @@ private: { DCanvas *Canvas = nullptr; PolyDepthStencil *DepthStencil = nullptr; + bool TopDown = true; } mRenderTarget; struct Rect diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.cpp b/src/rendering/polyrenderer/drawers/poly_triangle.cpp index 5c4dd4a72..1c33fa077 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/poly_triangle.cpp @@ -44,7 +44,7 @@ PolyCommandBuffer::PolyCommandBuffer(RenderMemory* frameMemory) mQueue = std::make_shared(frameMemory); } -void PolyCommandBuffer::SetViewport(int x, int y, int width, int height, DCanvas *canvas, PolyDepthStencil *depthstencil) +void PolyCommandBuffer::SetViewport(int x, int y, int width, int height, DCanvas *canvas, PolyDepthStencil *depthstencil, bool topdown) { uint8_t *dest = (uint8_t*)canvas->GetPixels(); int dest_width = canvas->GetWidth(); @@ -52,7 +52,7 @@ void PolyCommandBuffer::SetViewport(int x, int y, int width, int height, DCanvas int dest_pitch = canvas->GetPitch(); bool dest_bgra = canvas->IsBgra(); - mQueue->Push(x, y, width, height, dest, dest_width, dest_height, dest_pitch, dest_bgra, depthstencil); + mQueue->Push(x, y, width, height, dest, dest_width, dest_height, dest_pitch, dest_bgra, depthstencil, topdown); } void PolyCommandBuffer::SetInputAssembly(PolyInputAssembly *input) @@ -217,7 +217,7 @@ void PolyTriangleThreadData::ClearStencil(uint8_t value) } } -void PolyTriangleThreadData::SetViewport(int x, int y, int width, int height, uint8_t *new_dest, int new_dest_width, int new_dest_height, int new_dest_pitch, bool new_dest_bgra, PolyDepthStencil *new_depthstencil) +void PolyTriangleThreadData::SetViewport(int x, int y, int width, int height, uint8_t *new_dest, int new_dest_width, int new_dest_height, int new_dest_pitch, bool new_dest_bgra, PolyDepthStencil *new_depthstencil, bool new_topdown) { viewport_x = x; viewport_y = y; @@ -229,6 +229,7 @@ void PolyTriangleThreadData::SetViewport(int x, int y, int width, int height, ui dest_pitch = new_dest_pitch; dest_bgra = new_dest_bgra; depthstencil = new_depthstencil; + topdown = new_topdown; UpdateClip(); } @@ -620,7 +621,10 @@ void PolyTriangleThreadData::DrawShadedLine(const ShadedTriVertex *const* vert) // Apply viewport scale to get screen coordinates: v.x = viewport_x + viewport_width * (1.0f + v.x) * 0.5f; - v.y = viewport_y + viewport_height * (1.0f - v.y) * 0.5f; + if (topdown) + v.y = viewport_y + viewport_height * (1.0f - v.y) * 0.5f; + else + v.y = viewport_y + viewport_height * (1.0f + v.y) * 0.5f; } uint32_t vColorA = (int)(vert[0]->vColor.W * 255.0f + 0.5f); @@ -714,8 +718,11 @@ void PolyTriangleThreadData::DrawShadedTriangle(const ShadedTriVertex *const* ve // Apply viewport scale to get screen coordinates: v.x = viewport_x + viewport_width * (1.0f + v.x) * 0.5f; - v.y = viewport_y + viewport_height * (1.0f - v.y) * 0.5f; - } + if (topdown) + v.y = viewport_y + viewport_height * (1.0f - v.y) * 0.5f; + else + v.y = viewport_y + viewport_height * (1.0f + v.y) * 0.5f; + } #else // Map to 2D viewport: __m128 mviewport_x = _mm_set1_ps((float)viewport_x); @@ -740,7 +747,10 @@ void PolyTriangleThreadData::DrawShadedTriangle(const ShadedTriVertex *const* ve // Apply viewport scale to get screen coordinates: vx = _mm_add_ps(mviewport_x, _mm_mul_ps(mviewport_halfwidth, _mm_add_ps(mone, vx))); - vy = _mm_add_ps(mviewport_y, _mm_mul_ps(mviewport_halfheight, _mm_sub_ps(mone, vy))); + if (topdown) + vy = _mm_add_ps(mviewport_y, _mm_mul_ps(mviewport_halfheight, _mm_sub_ps(mone, vy))); + else + vy = _mm_add_ps(mviewport_y, _mm_mul_ps(mviewport_halfheight, _mm_add_ps(mone, vy))); _MM_TRANSPOSE4_PS(vx, vy, vz, vw); _mm_storeu_ps(&clippedvert[j].x, vx); @@ -750,6 +760,8 @@ void PolyTriangleThreadData::DrawShadedTriangle(const ShadedTriVertex *const* ve } #endif + if (!topdown) ccw = !ccw; + TriDrawTriangleArgs args; if (twosided && numclipvert > 2) diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.h b/src/rendering/polyrenderer/drawers/poly_triangle.h index 0ba1b0479..227dab664 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.h +++ b/src/rendering/polyrenderer/drawers/poly_triangle.h @@ -49,7 +49,7 @@ class PolyCommandBuffer public: PolyCommandBuffer(RenderMemory* frameMemory); - void SetViewport(int x, int y, int width, int height, DCanvas *canvas, PolyDepthStencil *depthStencil); + void SetViewport(int x, int y, int width, int height, DCanvas *canvas, PolyDepthStencil *depthStencil, bool topdown); void SetInputAssembly(PolyInputAssembly *input); void SetVertexBuffer(const void *vertices); void SetIndexBuffer(const void *elements); @@ -137,7 +137,7 @@ public: void ClearDepth(float value); void ClearStencil(uint8_t value); - void SetViewport(int x, int y, int width, int height, uint8_t *dest, int dest_width, int dest_height, int dest_pitch, bool dest_bgra, PolyDepthStencil *depthstencil); + void SetViewport(int x, int y, int width, int height, uint8_t *dest, int dest_width, int dest_height, int dest_pitch, bool dest_bgra, PolyDepthStencil *depthstencil, bool topdown); void SetCullCCW(bool value) { ccw = value; } void SetTwoSided(bool value) { twosided = value; } @@ -224,6 +224,7 @@ public: bool dest_bgra = false; uint8_t *dest = nullptr; PolyDepthStencil *depthstencil = nullptr; + bool topdown = true; float depthbias = 0.0f; @@ -504,9 +505,9 @@ private: class PolySetViewportCommand : public PolyDrawerCommand { public: - PolySetViewportCommand(int x, int y, int width, int height, uint8_t *dest, int dest_width, int dest_height, int dest_pitch, bool dest_bgra, PolyDepthStencil *depthstencil) - : x(x), y(y), width(width), height(height), dest(dest), dest_width(dest_width), dest_height(dest_height), dest_pitch(dest_pitch), dest_bgra(dest_bgra), depthstencil(depthstencil) { } - void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->SetViewport(x, y, width, height, dest, dest_width, dest_height, dest_pitch, dest_bgra, depthstencil); } + PolySetViewportCommand(int x, int y, int width, int height, uint8_t *dest, int dest_width, int dest_height, int dest_pitch, bool dest_bgra, PolyDepthStencil *depthstencil, bool topdown) + : x(x), y(y), width(width), height(height), dest(dest), dest_width(dest_width), dest_height(dest_height), dest_pitch(dest_pitch), dest_bgra(dest_bgra), depthstencil(depthstencil), topdown(topdown) { } + void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->SetViewport(x, y, width, height, dest, dest_width, dest_height, dest_pitch, dest_bgra, depthstencil, topdown); } private: int x; @@ -519,6 +520,7 @@ private: int dest_pitch; bool dest_bgra; PolyDepthStencil *depthstencil; + bool topdown; }; class PolySetViewpointUniformsCommand : public PolyDrawerCommand diff --git a/src/rendering/polyrenderer/drawers/poly_vertex_shader.h b/src/rendering/polyrenderer/drawers/poly_vertex_shader.h index 45af2e4e1..dd37c2ced 100644 --- a/src/rendering/polyrenderer/drawers/poly_vertex_shader.h +++ b/src/rendering/polyrenderer/drawers/poly_vertex_shader.h @@ -134,8 +134,6 @@ public: gl_ClipDistance[3] = 1.0f; gl_ClipDistance[4] = 1.0f; } - - std::swap(vTexCoord.X, vTexCoord.Y); // textures are transposed because the software renderer did them this way } private: diff --git a/src/rendering/polyrenderer/drawers/screen_triangle.cpp b/src/rendering/polyrenderer/drawers/screen_triangle.cpp index 38023ff23..2e3e1553f 100644 --- a/src/rendering/polyrenderer/drawers/screen_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/screen_triangle.cpp @@ -623,7 +623,7 @@ static uint32_t SampleTexture(uint32_t u, uint32_t v, const void* texPixels, int { int texelX = (u * texWidth) >> 16; int texelY = (v * texHeight) >> 16; - int texelOffset = texelX * texHeight + texelY; + int texelOffset = texelX + texelY * texWidth; if (texBgra) { return static_cast(texPixels)[texelOffset]; @@ -648,6 +648,10 @@ static void RunShader(int x0, int x1, PolyTriangleThreadData* thread) /*float fogdist = pixelpos.w; float fogfactor = exp2(uFogDensity * fogdist); FragColor = vec4(uFogColor.rgb, 1.0 - fogfactor);*/ + for (int x = x0; x < x1; x++) + { + fragcolor[x] = 0; + } return; } else if (thread->SpecialEffect == EFF_BURN) // burn.fp