- Implement model rendering in softpoly

This commit is contained in:
Magnus Norddahl 2017-11-24 00:39:10 +01:00
commit 00d7dd0c64
13 changed files with 444 additions and 4 deletions

View file

@ -0,0 +1,255 @@
/*
** Polygon Doom software renderer
** Copyright (c) 2016 Magnus Norddahl
**
** This software is provided 'as-is', without any express or implied
** warranty. In no event will the authors be held liable for any damages
** arising from the use of this software.
**
** Permission is granted to anyone to use this software for any purpose,
** including commercial applications, and to alter it and redistribute it
** freely, subject to the following restrictions:
**
** 1. The origin of this software must not be misrepresented; you must not
** claim that you wrote the original software. If you use this software
** in a product, an acknowledgment in the product documentation would be
** appreciated but is not required.
** 2. Altered source versions must be plainly marked as such, and must not be
** misrepresented as being the original software.
** 3. This notice may not be removed or altered from any source distribution.
**
*/
#include <stdlib.h>
#include "templates.h"
#include "doomdef.h"
#include "sbar.h"
#include "r_data/r_translate.h"
#include "poly_model.h"
#include "polyrenderer/poly_renderer.h"
#include "polyrenderer/scene/poly_light.h"
#include "polyrenderer/poly_renderthread.h"
#include "r_data/r_vanillatrans.h"
#include "actorinlines.h"
void PolyRenderModel(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, uint32_t stencilValue, float x, float y, float z, FSpriteModelFrame *smf, AActor *actor)
{
PolyModelRenderer renderer(thread, worldToClip, clipPlane, stencilValue);
renderer.RenderModel(x, y, z, smf, actor);
}
void PolyRenderHUDModel(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, uint32_t stencilValue, DPSprite *psp, float ofsx, float ofsy)
{
PolyModelRenderer renderer(thread, worldToClip, clipPlane, stencilValue);
renderer.RenderHUDModel(psp, ofsx, ofsy);
}
/////////////////////////////////////////////////////////////////////////////
void PolyModelRenderer::BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix)
{
ModelActor = actor;
const_cast<VSMatrix &>(objectToWorldMatrix).copy(ObjectToWorld.matrix);
}
void PolyModelRenderer::EndDrawModel(AActor *actor, FSpriteModelFrame *smf)
{
ModelActor = nullptr;
}
IModelVertexBuffer *PolyModelRenderer::CreateVertexBuffer(bool needindex, bool singleframe)
{
return new PolyModelVertexBuffer(needindex, singleframe);
}
void PolyModelRenderer::SetVertexBuffer(IModelVertexBuffer *buffer)
{
}
void PolyModelRenderer::ResetVertexBuffer()
{
}
VSMatrix PolyModelRenderer::GetViewToWorldMatrix()
{
TriMatrix swapYZ = TriMatrix::null();
swapYZ.matrix[0 + 0 * 4] = 1.0f;
swapYZ.matrix[1 + 2 * 4] = 1.0f;
swapYZ.matrix[2 + 1 * 4] = 1.0f;
swapYZ.matrix[3 + 3 * 4] = 1.0f;
VSMatrix worldToView;
worldToView.loadMatrix((PolyRenderer::Instance()->WorldToView * swapYZ).matrix);
VSMatrix objectToWorld;
worldToView.inverseMatrix(objectToWorld);
return objectToWorld;
}
void PolyModelRenderer::BeginDrawHUDModel(AActor *actor, const VSMatrix &objectToWorldMatrix)
{
ModelActor = actor;
const_cast<VSMatrix &>(objectToWorldMatrix).copy(ObjectToWorld.matrix);
}
void PolyModelRenderer::EndDrawHUDModel(AActor *actor)
{
ModelActor = nullptr;
}
void PolyModelRenderer::SetInterpolation(double interpolation)
{
InterpolationFactor = (float)interpolation;
}
void PolyModelRenderer::SetMaterial(FTexture *skin, int clampmode, int translation)
{
SkinTexture = skin;
}
void PolyModelRenderer::DrawArrays(int primitiveType, int start, int count)
{
const auto &viewpoint = PolyRenderer::Instance()->Viewpoint;
bool foggy = false;
int actualextralight = foggy ? 0 : viewpoint.extralight << 4;
sector_t *sector = ModelActor->Sector;
bool fullbrightSprite = ((ModelActor->renderflags & RF_FULLBRIGHT) || (ModelActor->flags5 & MF5_BRIGHT));
int lightlevel = fullbrightSprite ? 255 : ModelActor->Sector->lightlevel + actualextralight;
TriMatrix swapYZ = TriMatrix::null();
swapYZ.matrix[0 + 0 * 4] = 1.0f;
swapYZ.matrix[1 + 2 * 4] = 1.0f;
swapYZ.matrix[2 + 1 * 4] = 1.0f;
swapYZ.matrix[3 + 3 * 4] = 1.0f;
TriMatrix *transform = Thread->FrameMemory->NewObject<TriMatrix>();
*transform = WorldToClip * swapYZ * ObjectToWorld;
PolyDrawArgs args;
args.SetLight(GetColorTable(sector->Colormap, sector->SpecialColors[sector_t::sprites], true), lightlevel, PolyRenderer::Instance()->Light.SpriteGlobVis(foggy), fullbrightSprite);
args.SetTransform(transform);
args.SetFaceCullCCW(true);
args.SetStencilTestValue(StencilValue);
args.SetClipPlane(0, PolyClipPlane());
args.SetStyle(TriBlendMode::TextureOpaque);
args.SetTexture(SkinTexture);
args.SetDepthTest(true);
args.SetWriteDepth(true);
args.SetWriteStencil(false);
args.DrawArray(Thread, VertexBuffer + start, count);
}
void PolyModelRenderer::DrawElements(int primitiveType, int numIndices, int elementType, size_t offset)
{
const auto &viewpoint = PolyRenderer::Instance()->Viewpoint;
bool foggy = false;
int actualextralight = foggy ? 0 : viewpoint.extralight << 4;
sector_t *sector = ModelActor->Sector;
bool fullbrightSprite = ((ModelActor->renderflags & RF_FULLBRIGHT) || (ModelActor->flags5 & MF5_BRIGHT));
int lightlevel = fullbrightSprite ? 255 : ModelActor->Sector->lightlevel + actualextralight;
TriMatrix swapYZ = TriMatrix::null();
swapYZ.matrix[0 + 0 * 4] = 1.0f;
swapYZ.matrix[1 + 2 * 4] = 1.0f;
swapYZ.matrix[2 + 1 * 4] = 1.0f;
swapYZ.matrix[3 + 3 * 4] = 1.0f;
TriMatrix *transform = Thread->FrameMemory->NewObject<TriMatrix>();
*transform = WorldToClip * swapYZ * ObjectToWorld;
PolyDrawArgs args;
args.SetLight(GetColorTable(sector->Colormap, sector->SpecialColors[sector_t::sprites], true), lightlevel, PolyRenderer::Instance()->Light.SpriteGlobVis(foggy), fullbrightSprite);
args.SetTransform(transform);
args.SetFaceCullCCW(true);
args.SetStencilTestValue(StencilValue);
args.SetClipPlane(0, PolyClipPlane());
args.SetStyle(TriBlendMode::TextureOpaque);
args.SetTexture(SkinTexture);
args.SetDepthTest(true);
args.SetWriteDepth(true);
args.SetWriteStencil(false);
args.DrawElements(Thread, VertexBuffer, IndexBuffer + offset / sizeof(unsigned int), numIndices);
}
float PolyModelRenderer::GetTimeFloat()
{
return 0.0f; // (float)gl_frameMS * (float)TICRATE / 1000.0f;
}
/////////////////////////////////////////////////////////////////////////////
PolyModelVertexBuffer::PolyModelVertexBuffer(bool needindex, bool singleframe)
{
}
PolyModelVertexBuffer::~PolyModelVertexBuffer()
{
}
FModelVertex *PolyModelVertexBuffer::LockVertexBuffer(unsigned int size)
{
mVertexBuffer.Resize(size);
return &mVertexBuffer[0];
}
void PolyModelVertexBuffer::UnlockVertexBuffer()
{
}
unsigned int *PolyModelVertexBuffer::LockIndexBuffer(unsigned int size)
{
mIndexBuffer.Resize(size);
return &mIndexBuffer[0];
}
void PolyModelVertexBuffer::UnlockIndexBuffer()
{
}
void PolyModelVertexBuffer::SetupFrame(FModelRenderer *renderer, unsigned int frame1, unsigned int frame2, unsigned int size)
{
PolyModelRenderer *polyrenderer = (PolyModelRenderer *)renderer;
if (true)//if (frame1 == frame2 || size == 0 || polyrenderer->InterpolationFactor == 0.f)
{
TriVertex *vertices = polyrenderer->Thread->FrameMemory->AllocMemory<TriVertex>(size);
for (unsigned int i = 0; i < size; i++)
{
vertices[i] =
{
mVertexBuffer[frame1 + i].x,
mVertexBuffer[frame1 + i].y,
mVertexBuffer[frame1 + i].z,
1.0f,
mVertexBuffer[frame1 + i].u,
mVertexBuffer[frame1 + i].v
};
}
polyrenderer->VertexBuffer = vertices;
polyrenderer->IndexBuffer = &mIndexBuffer[0];
}
else
{
TriVertex *vertices = polyrenderer->Thread->FrameMemory->AllocMemory<TriVertex>(size);
float frac = polyrenderer->InterpolationFactor;
for (unsigned int i = 0; i < size; i++)
{
vertices[i].x = mVertexBuffer[frame1 + i].x * (1.0f - frac) + mVertexBuffer[frame2 + i].x * frac;
vertices[i].y = mVertexBuffer[frame1 + i].y * (1.0f - frac) + mVertexBuffer[frame2 + i].y * frac;
vertices[i].z = mVertexBuffer[frame1 + i].z * (1.0f - frac) + mVertexBuffer[frame2 + i].z * frac;
vertices[i].w = 1.0f;
vertices[i].u = mVertexBuffer[frame1 + i].u;
vertices[i].v = mVertexBuffer[frame1 + i].v;
}
polyrenderer->VertexBuffer = vertices;
polyrenderer->IndexBuffer = &mIndexBuffer[0];
}
}

View file

@ -0,0 +1,82 @@
/*
** Polygon Doom software renderer
** Copyright (c) 2016 Magnus Norddahl
**
** This software is provided 'as-is', without any express or implied
** warranty. In no event will the authors be held liable for any damages
** arising from the use of this software.
**
** Permission is granted to anyone to use this software for any purpose,
** including commercial applications, and to alter it and redistribute it
** freely, subject to the following restrictions:
**
** 1. The origin of this software must not be misrepresented; you must not
** claim that you wrote the original software. If you use this software
** in a product, an acknowledgment in the product documentation would be
** appreciated but is not required.
** 2. Altered source versions must be plainly marked as such, and must not be
** misrepresented as being the original software.
** 3. This notice may not be removed or altered from any source distribution.
**
*/
#pragma once
#include "polyrenderer/drawers/poly_triangle.h"
#include "gl/data/gl_matrix.h"
#include "gl/models/gl_models.h"
void PolyRenderModel(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, uint32_t stencilValue, float x, float y, float z, FSpriteModelFrame *smf, AActor *actor);
void PolyRenderHUDModel(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, uint32_t stencilValue, DPSprite *psp, float ofsx, float ofsy);
class PolyModelRenderer : public FModelRenderer
{
public:
PolyModelRenderer(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, uint32_t stencilValue) : Thread(thread), WorldToClip(worldToClip), ClipPlane(clipPlane), StencilValue(stencilValue) { }
void BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix) override;
void EndDrawModel(AActor *actor, FSpriteModelFrame *smf) override;
IModelVertexBuffer *CreateVertexBuffer(bool needindex, bool singleframe) override;
void SetVertexBuffer(IModelVertexBuffer *buffer) override;
void ResetVertexBuffer() override;
VSMatrix GetViewToWorldMatrix() override;
void BeginDrawHUDModel(AActor *actor, const VSMatrix &objectToWorldMatrix) override;
void EndDrawHUDModel(AActor *actor) override;
void SetInterpolation(double interpolation) override;
void SetMaterial(FTexture *skin, int clampmode, int translation) override;
void DrawArrays(int primitiveType, int start, int count) override;
void DrawElements(int primitiveType, int numIndices, int elementType, size_t offset) override;
float GetTimeFloat() override;
PolyRenderThread *Thread = nullptr;
const TriMatrix &WorldToClip;
const PolyClipPlane &ClipPlane;
uint32_t StencilValue = 0;
AActor *ModelActor = nullptr;
TriMatrix ObjectToWorld;
FTexture *SkinTexture = nullptr;
unsigned int *IndexBuffer = nullptr;
TriVertex *VertexBuffer = nullptr;
float InterpolationFactor = 0.0;
};
class PolyModelVertexBuffer : public IModelVertexBuffer
{
public:
PolyModelVertexBuffer(bool needindex, bool singleframe);
~PolyModelVertexBuffer();
FModelVertex *LockVertexBuffer(unsigned int size) override;
void UnlockVertexBuffer() override;
unsigned int *LockIndexBuffer(unsigned int size) override;
void UnlockIndexBuffer() override;
void SetupFrame(FModelRenderer *renderer, unsigned int frame1, unsigned int frame2, unsigned int size) override;
private:
int mIndexFrame[2];
TArray<FModelVertex> mVertexBuffer;
TArray<unsigned int> mIndexBuffer;
};

View file

@ -29,6 +29,7 @@
#include "polyrenderer/poly_renderer.h"
#include "d_player.h"
#include "polyrenderer/scene/poly_light.h"
#include "polyrenderer/scene/poly_model.h"
EXTERN_CVAR(Bool, r_drawplayersprites)
EXTERN_CVAR(Bool, r_deathcamera)
@ -39,6 +40,10 @@ void RenderPolyPlayerSprites::Render(PolyRenderThread *thread)
{
// This code cannot be moved directly to RenderRemainingSprites because the engine
// draws the canvas textures between this call and the final call to RenderRemainingSprites..
//
// We also can't move it because the model render code relies on it
renderHUDModel = gl_IsHUDModelForPlayerAvailable(players[consoleplayer].camera->player);
const auto &viewpoint = PolyRenderer::Instance()->Viewpoint;
@ -244,6 +249,12 @@ void RenderPolyPlayerSprites::RenderSprite(PolyRenderThread *thread, DPSprite *p
sy += wy;
}
if (renderHUDModel)
{
PolyRenderHUDModel(thread, PolyRenderer::Instance()->WorldToClip, PolyClipPlane(), 1, pspr, (float)sx, (float)sy);
return;
}
double yaspectMul = 1.2 * ((double)SCREENHEIGHT / SCREENWIDTH) * r_viewwindow.WidescreenRatio;
double pspritexscale = viewwindow.centerxwide / 160.0;

View file

@ -102,4 +102,5 @@ private:
TArray<PolyHWAccelPlayerSprite> AcceleratedSprites;
sector_t tempsec;
bool renderHUDModel = false;
};

View file

@ -29,6 +29,7 @@
#include "polyrenderer/poly_renderer.h"
#include "polyrenderer/scene/poly_light.h"
#include "polyrenderer/poly_renderthread.h"
#include "polyrenderer/scene/poly_model.h"
#include "r_data/r_vanillatrans.h"
#include "actorinlines.h"
@ -73,6 +74,17 @@ bool RenderPolySprite::GetLine(AActor *thing, DVector2 &left, DVector2 &right)
void RenderPolySprite::Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, AActor *thing, subsector_t *sub, uint32_t stencilValue, float t1, float t2)
{
int spritenum = thing->sprite;
bool isPicnumOverride = thing->picnum.isValid();
FSpriteModelFrame *modelframe = isPicnumOverride ? nullptr : gl_FindModelFrame(thing->GetClass(), spritenum, thing->frame, !!(thing->flags & MF_DROPPED));
if (modelframe)
{
const auto &viewpoint = PolyRenderer::Instance()->Viewpoint;
DVector3 pos = thing->InterpolatedPosition(viewpoint.TicFrac);
PolyRenderModel(thread, worldToClip, clipPlane, stencilValue, (float)pos.X, (float)pos.Y, (float)pos.Z, modelframe, thing);
return;
}
DVector2 line[2];
if (!GetLine(thing, line[0], line[1]))
return;