Fix render to texture

This commit is contained in:
Magnus Norddahl 2019-12-08 01:39:17 +01:00
parent cef3fd53ab
commit fdb93309fe
7 changed files with 43 additions and 23 deletions

View file

@ -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);
}

View file

@ -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<PolyHardwareTexture*>(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)

View file

@ -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

View file

@ -44,7 +44,7 @@ PolyCommandBuffer::PolyCommandBuffer(RenderMemory* frameMemory)
mQueue = std::make_shared<DrawerCommandQueue>(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<PolySetViewportCommand>(x, y, width, height, dest, dest_width, dest_height, dest_pitch, dest_bgra, depthstencil);
mQueue->Push<PolySetViewportCommand>(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)

View file

@ -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

View file

@ -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:

View file

@ -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<const uint32_t*>(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