Support 8-bit textures

This commit is contained in:
Magnus Norddahl 2019-12-02 00:35:15 +01:00
parent 74c6b9fe6d
commit 4a2b763aaa
4 changed files with 38 additions and 25 deletions

View file

@ -233,7 +233,7 @@ void PolyRenderState::ApplyMaterial()
if (base)
{
DCanvas *texcanvas = base->GetImage(mMaterial);
PolyTriangleDrawer::SetTexture(GetPolyFrameBuffer()->GetDrawCommands(), 0, texcanvas->GetPixels(), texcanvas->GetHeight(), texcanvas->GetWidth());
PolyTriangleDrawer::SetTexture(GetPolyFrameBuffer()->GetDrawCommands(), 0, texcanvas->GetPixels(), texcanvas->GetHeight(), texcanvas->GetWidth(), texcanvas->IsBgra());
int numLayers = mMaterial.mMaterial->GetLayers();
for (int i = 1; i < numLayers; i++)
@ -242,7 +242,7 @@ void PolyRenderState::ApplyMaterial()
auto systex = static_cast<PolyHardwareTexture*>(mMaterial.mMaterial->GetLayer(i, 0, &layer));
texcanvas = systex->GetImage(mMaterial);
PolyTriangleDrawer::SetTexture(GetPolyFrameBuffer()->GetDrawCommands(), i, texcanvas->GetPixels(), texcanvas->GetHeight(), texcanvas->GetWidth());
PolyTriangleDrawer::SetTexture(GetPolyFrameBuffer()->GetDrawCommands(), i, texcanvas->GetPixels(), texcanvas->GetHeight(), texcanvas->GetWidth(), texcanvas->IsBgra());
}
}

View file

@ -153,9 +153,9 @@ void PolyTriangleDrawer::SetRenderStyle(const DrawerCommandQueuePtr &queue, FRen
queue->Push<PolySetRenderStyleCommand>(style);
}
void PolyTriangleDrawer::SetTexture(const DrawerCommandQueuePtr &queue, int unit, void *pixels, int width, int height)
void PolyTriangleDrawer::SetTexture(const DrawerCommandQueuePtr &queue, int unit, void *pixels, int width, int height, bool bgra)
{
queue->Push<PolySetTextureCommand>(unit, pixels, width, height);
queue->Push<PolySetTextureCommand>(unit, pixels, width, height, bgra);
}
void PolyTriangleDrawer::SetShader(const DrawerCommandQueuePtr &queue, int specialEffect, int effectState, bool alphaTest)
@ -408,9 +408,9 @@ void PolyTriangleThreadData::SetShader(int specialEffect, int effectState, bool
AlphaTest = alphaTest;
}
void PolyTriangleThreadData::SetTexture(int unit, void *pixels, int width, int height)
void PolyTriangleThreadData::SetTexture(int unit, const void *pixels, int width, int height, bool bgra)
{
textures[unit].pixels = (uint8_t*)pixels;
textures[unit].pixels = pixels;
textures[unit].width = width;
textures[unit].height = height;
textures[unit].bgra = true;

View file

@ -65,7 +65,7 @@ public:
static void SetScissor(const DrawerCommandQueuePtr &queue, int x, int y, int w, int h);
static void EnableDepthTest(const DrawerCommandQueuePtr &queue, bool on);
static void SetRenderStyle(const DrawerCommandQueuePtr &queue, FRenderStyle style);
static void SetTexture(const DrawerCommandQueuePtr &queue, int unit, void *pixels, int width, int height);
static void SetTexture(const DrawerCommandQueuePtr &queue, int unit, void *pixels, int width, int height, bool bgra);
static void SetShader(const DrawerCommandQueuePtr &queue, int specialEffect, int effectState, bool alphaTest);
static void PushStreamData(const DrawerCommandQueuePtr &queue, const StreamData &data, const PolyPushConstants &constants);
static void PushMatrices(const DrawerCommandQueuePtr &queue, const VSMatrix &modelMatrix, const VSMatrix &normalModelMatrix, const VSMatrix &textureMatrix);
@ -149,7 +149,7 @@ public:
void SetScissor(int x, int y, int w, int h);
void EnableDepthTest(bool on);
void SetRenderStyle(FRenderStyle style);
void SetTexture(int unit, void *pixels, int width, int height);
void SetTexture(int unit, const void *pixels, int width, int height, bool bgra);
void SetShader(int specialEffect, int effectState, bool alphaTest);
void UpdateClip();
@ -245,7 +245,7 @@ public:
struct TextureUnit
{
const uint8_t* pixels = nullptr;
const void* pixels = nullptr;
int width = 0;
int height = 0;
bool bgra = true;
@ -429,14 +429,15 @@ private:
class PolySetTextureCommand : public PolyDrawerCommand
{
public:
PolySetTextureCommand(int unit, void *pixels, int width, int height) : unit(unit), pixels(pixels), width(width), height(height) { }
void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->SetTexture(unit, pixels, width, height); }
PolySetTextureCommand(int unit, void *pixels, int width, int height, bool bgra) : unit(unit), pixels(pixels), width(width), height(height), bgra(bgra) { }
void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->SetTexture(unit, pixels, width, height, bgra); }
private:
int unit;
void *pixels;
int width;
int height;
bool bgra;
};
class PolySetShaderCommand : public PolyDrawerCommand

View file

@ -351,11 +351,20 @@ static float wrap(float value)
}
#endif
static uint32_t sampleTexture(float u, float v, const uint32_t* texPixels, int texWidth, int texHeight)
static uint32_t sampleTexture(float u, float v, const void* texPixels, int texWidth, int texHeight, bool texBgra)
{
int texelX = MIN(static_cast<int>(wrap(u) * texWidth), texWidth - 1);
int texelY = MIN(static_cast<int>(wrap(v) * texHeight), texHeight - 1);
return texPixels[texelX * texHeight + texelY];
int texelOffset = texelX * texHeight + texelY;
if (texBgra)
{
return static_cast<const uint32_t*>(texPixels)[texelOffset];
}
else
{
uint32_t c = static_cast<const uint8_t*>(texPixels)[texelOffset];
return c | 0xff000000;
}
}
static void RunShader(int x0, int x1, PolyTriangleThreadData* thread)
@ -377,11 +386,13 @@ static void RunShader(int x0, int x1, PolyTriangleThreadData* thread)
{
int texWidth = thread->textures[0].width;
int texHeight = thread->textures[0].height;
const uint32_t* texPixels = (const uint32_t*)thread->textures[0].pixels;
const void* texPixels = thread->textures[0].pixels;
bool texBgra = thread->textures[0].bgra;
int tex2Width = thread->textures[1].width;
int tex2Height = thread->textures[1].height;
const uint32_t* tex2Pixels = (const uint32_t*)thread->textures[1].pixels;
const void* tex2Pixels = thread->textures[1].pixels;
bool tex2Bgra = thread->textures[1].bgra;
uint32_t frag = thread->mainVertexShader.vColor;
uint32_t frag_r = RPART(frag);
@ -394,8 +405,8 @@ static void RunShader(int x0, int x1, PolyTriangleThreadData* thread)
frag_a += frag_a >> 7; // 255 -> 256
for (int x = x0; x < x1; x++)
{
uint32_t t1 = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight);
uint32_t t2 = sampleTexture(u[x], 1.0f - v[x], tex2Pixels, tex2Width, tex2Height);
uint32_t t1 = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight, texBgra);
uint32_t t2 = sampleTexture(u[x], 1.0f - v[x], tex2Pixels, tex2Width, tex2Height, tex2Bgra);
uint32_t r = (frag_r * RPART(t1)) >> 8;
uint32_t g = (frag_g * GPART(t1)) >> 8;
@ -443,7 +454,8 @@ static void RunShader(int x0, int x1, PolyTriangleThreadData* thread)
{
int texWidth = thread->textures[0].width;
int texHeight = thread->textures[0].height;
const uint32_t* texPixels = (const uint32_t*)thread->textures[0].pixels;
const void* texPixels = thread->textures[0].pixels;
bool texBgra = thread->textures[0].bgra;
switch (constants->uTextureMode)
{
@ -452,35 +464,35 @@ static void RunShader(int x0, int x1, PolyTriangleThreadData* thread)
case TM_FOGLAYER:
for (int x = x0; x < x1; x++)
{
uint32_t texel = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight);
uint32_t texel = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight, texBgra);
fragcolor[x] = texel;
}
break;
case TM_STENCIL: // TM_STENCIL
for (int x = x0; x < x1; x++)
{
uint32_t texel = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight);
uint32_t texel = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight, texBgra);
fragcolor[x] = texel | 0x00ffffff;
}
break;
case TM_OPAQUE:
for (int x = x0; x < x1; x++)
{
uint32_t texel = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight);
uint32_t texel = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight, texBgra);
fragcolor[x] = texel | 0xff000000;
}
break;
case TM_INVERSE:
for (int x = x0; x < x1; x++)
{
uint32_t texel = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight);
uint32_t texel = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight, texBgra);
fragcolor[x] = MAKEARGB(APART(texel), 0xff - RPART(texel), 0xff - BPART(texel), 0xff - GPART(texel));
}
break;
case TM_ALPHATEXTURE:
for (int x = x0; x < x1; x++)
{
uint32_t texel = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight);
uint32_t texel = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight, texBgra);
uint32_t gray = (RPART(texel) * 77 + GPART(texel) * 143 + BPART(texel) * 37) >> 8;
uint32_t alpha = APART(texel);
alpha += alpha >> 7;
@ -493,7 +505,7 @@ static void RunShader(int x0, int x1, PolyTriangleThreadData* thread)
for (int x = x0; x < x1; x++)
{
if (v[x] >= 0.0 && v[x] <= 1.0)
fragcolor[x] = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight);
fragcolor[x] = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight, texBgra);
else
fragcolor[x] = 0;
}
@ -501,7 +513,7 @@ static void RunShader(int x0, int x1, PolyTriangleThreadData* thread)
case TM_INVERTOPAQUE:
for (int x = x0; x < x1; x++)
{
uint32_t texel = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight);
uint32_t texel = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight, texBgra);
fragcolor[x] = MAKEARGB(0xff, 0xff - RPART(texel), 0xff - BPART(texel), 0xff - GPART(texel));
}
}