From e1038ea6326749060e9839ea1d23fc2cd4284848 Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Wed, 26 Jan 2022 22:15:10 +0100 Subject: [PATCH] naomi2: fix regressions. 2-volume and bump mapping support WIP optimize open gl uniforms --- CMakeLists.txt | 4 +- core/hw/pvr/elan.cpp | 300 +++++++++--------------- core/hw/pvr/elan_struct.h | 6 +- core/hw/pvr/ta_vtx.cpp | 12 + core/rend/TexCache.cpp | 2 + core/rend/gl4/gl4.h | 21 ++ core/rend/gl4/gl4naomi2.cpp | 54 +++++ core/rend/gl4/{naomi2.h => gl4naomi2.h} | 3 +- core/rend/gl4/gldraw.cpp | 2 +- core/rend/gl4/gles.cpp | 17 +- core/rend/gl4/naomi2.cpp | 127 ---------- core/rend/gles/gles.cpp | 18 +- core/rend/gles/gles.h | 21 ++ core/rend/gles/naomi2.cpp | 173 ++++++-------- core/rend/gles/naomi2.h | 125 +++++++++- core/rend/sorter.cpp | 6 +- 16 files changed, 440 insertions(+), 451 deletions(-) create mode 100644 core/rend/gl4/gl4naomi2.cpp rename core/rend/gl4/{naomi2.h => gl4naomi2.h} (92%) delete mode 100644 core/rend/gl4/naomi2.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index a5dfefdc4..39038bbb7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -937,8 +937,8 @@ if(USE_OPENGL) core/rend/gl4/gl4.h core/rend/gl4/gldraw.cpp core/rend/gl4/gles.cpp - core/rend/gl4/naomi2.cpp - core/rend/gl4/naomi2.h) + core/rend/gl4/gl4naomi2.cpp + core/rend/gl4/gl4naomi2.h) endif() endif() diff --git a/core/hw/pvr/elan.cpp b/core/hw/pvr/elan.cpp index e6f23167c..eddf0676a 100644 --- a/core/hw/pvr/elan.cpp +++ b/core/hw/pvr/elan.cpp @@ -508,142 +508,6 @@ static u32 packColor(const glm::vec4& color) | (int)(std::max(0.f, std::min(1.f, color.b)) * 255.f); } -static void computeColors(glm::vec4& baseCol, glm::vec4& offsetCol, const glm::vec4& pos, const glm::vec4& normal) -{ - if (curLightModel == nullptr) - return; - glm::vec4 ambient{}; - glm::vec4 diffuse{}; - glm::vec4 specular{}; - float diffuseAlphaDiff = 0; - float specularAlphaDiff = 0; - - for (u32 lightId = 0; lightId < MAX_LIGHTS; lightId++) - { - const ElanBase *base = curLights[lightId]; - if (base == nullptr) - continue; - if (!curLightModel->isDiffuse(lightId) && !curLightModel->isSpecular(lightId)) - continue; - - glm::vec4 lightDir; // direction to the light - int routing; - int dmode; - int smode = N2_LMETHOD_SINGLE_SIDED; - glm::vec4 lightColor; - if (base->pcw.parallelLight) - { - ParallelLight *light = (ParallelLight *)base; - lightDir = glm::normalize(glm::vec4((int8_t)light->dirX, -(int8_t)light->dirY, -(int8_t)light->dirZ, 0)); - lightColor = unpackColor(light->red, light->green, light->blue); - routing = light->routing; - dmode = light->dmode; - } - else - { - PointLight *light = (PointLight *)base; - glm::vec4 lightPos(light->posX, light->posY, light->posZ, 1); - lightDir = glm::normalize(lightPos - pos); // FIXME normalizing 4D vec - - lightColor = unpackColor(light->red, light->green, light->blue); - routing = light->routing; - - if (light->isAttnDist()) - { - float distance = glm::length(lightPos - pos); - lightColor *= light->attnDist(distance); - } - if (light->isAttnAngle()) - { - glm::vec4 spotDir = glm::normalize(glm::vec4((int8_t)light->dirX, (int8_t)light->dirY, (int8_t)light->dirZ, 0)); - float cosAngle = glm::max(0.f, glm::dot(-lightDir, spotDir)); - lightColor *= light->attnAngle(cosAngle); - } - dmode = light->dmode; - smode = light->smode; - } - verify(dmode == N2_LMETHOD_SINGLE_SIDED || dmode == N2_LMETHOD_SPECIAL_EFFECT || dmode == N2_LMETHOD_DOUBLE_SIDED); - verify(smode == N2_LMETHOD_SINGLE_SIDED || smode == N2_LMETHOD_SPECIAL_EFFECT || smode == N2_LMETHOD_DOUBLE_SIDED); - if (!(routing == N2_LFUNC_BASEDIFF_BASESPEC_ADD || routing == N2_LFUNC_BASEDIFF_OFFSSPEC_ADD - || routing == N2_LFUNC_OFFSDIFF_BASESPEC_ADD || routing == N2_LFUNC_OFFSDIFF_OFFSSPEC_ADD - || routing == N2_LFUNC_ALPHADIFF_SUB)) - WARN_LOG(PVR, "routing = %d dmode %d smode %d lightCol %f %f %f %f", routing ,dmode, smode, lightColor.r, lightColor.g, lightColor.b, lightColor.a); - if (curLightModel->isDiffuse(lightId) && curGmp->paramSelect.d0) - { - float factor; - switch (dmode) - { - case N2_LMETHOD_SINGLE_SIDED: - factor = glm::max(glm::dot(normal, lightDir), 0.f); - break; - case N2_LMETHOD_DOUBLE_SIDED: - factor = glm::abs(glm::dot(normal, lightDir)); - break; - case N2_LMETHOD_SPECIAL_EFFECT: - default: - factor = 1; - break; - } - if (routing == N2_LFUNC_ALPHADIFF_SUB) - // FIXME probably need to substract from baseCol.a/OffsetCol.a instead? still not working... - //diffuse.a = std::max(0.f, diffuse.a - lightColor.r * factor); - diffuseAlphaDiff -= lightColor.r * factor; - else if (routing == N2_LFUNC_BASEDIFF_BASESPEC_ADD || routing == N2_LFUNC_BASEDIFF_OFFSSPEC_ADD) - diffuse += lightColor * factor; - if (routing == N2_LFUNC_OFFSDIFF_BASESPEC_ADD || routing == N2_LFUNC_OFFSDIFF_OFFSSPEC_ADD) - specular += lightColor * factor; - } - if (curLightModel->isSpecular(lightId) && curGmp->paramSelect.s0) - { - glm::vec4 reflectDir = glm::reflect(-lightDir, normal); - float factor; - switch (smode) - { - case N2_LMETHOD_SINGLE_SIDED: - factor = glm::pow(glm::max(glm::dot(glm::normalize(-pos), reflectDir), 0.f), curGmp->gloss.getCoef0()); - break; - case N2_LMETHOD_DOUBLE_SIDED: - factor = glm::pow(glm::abs(glm::dot(glm::normalize(-pos), reflectDir)), curGmp->gloss.getCoef0()); - break; - case N2_LMETHOD_SPECIAL_EFFECT: - default: - factor = 1; - break; - } - if (routing == N2_LFUNC_ALPHADIFF_SUB) - //specular.a = std::max(0.f, specular.a - lightColor.r * factor); - specularAlphaDiff -= lightColor.r * factor; - else if (routing == N2_LFUNC_OFFSDIFF_OFFSSPEC_ADD || routing == N2_LFUNC_BASEDIFF_OFFSSPEC_ADD) - specular += lightColor * factor; - if (routing == N2_LFUNC_BASEDIFF_BASESPEC_ADD || routing == N2_LFUNC_OFFSDIFF_BASESPEC_ADD) - diffuse += lightColor * factor; - } - } - if (curGmp->paramSelect.a0) // ambient0 TODO check - { - if (curLightModel->useAmbientBase0) - diffuse += unpackColor(curLightModel->ambientBase0); - if (curLightModel->useAmbientOffset0) - specular += unpackColor(curLightModel->ambientOffset0); - } - baseCol *= diffuse; - offsetCol *= specular; - if (curGmp->paramSelect.a0) - { - if (!curLightModel->useAmbientBase0) - baseCol += unpackColor(curLightModel->ambientBase0); - if (!curLightModel->useAmbientOffset0) - offsetCol += unpackColor(curLightModel->ambientOffset0); - } - baseCol.a = std::max(0.f, baseCol.a + diffuseAlphaDiff); - offsetCol.a = std::max(0.f, offsetCol.a + specularAlphaDiff); - if (curLightModel->useBaseOver) - { - glm::vec4 overflow = glm::max(glm::vec4(0), baseCol - glm::vec4(1)); - offsetCol += overflow; - } -} - template glm::vec4 getNormal(const T& vtx) { @@ -674,26 +538,35 @@ void convertVertex(const N2_VERTEX& vs, Vertex& vd) setCoords(vd, vs.x, vs.y, vs.z); setNormal(vd, vs); SetEnvMapUV(vd); - glm::vec4 baseCol; - glm::vec4 offsetCol; + glm::vec4 baseCol0; + glm::vec4 offsetCol0; + glm::vec4 baseCol1; + glm::vec4 offsetCol1; if (curGmp != nullptr) { - baseCol = unpackColor(curGmp->diffuse0); - offsetCol = unpackColor(curGmp->specular0); + baseCol0 = unpackColor(curGmp->diffuse0); + offsetCol0 = unpackColor(curGmp->specular0); + baseCol1 = unpackColor(curGmp->diffuse1); + offsetCol1 = unpackColor(curGmp->specular1); if (state.listType == 2) { // FIXME - baseCol.a = 0; - offsetCol.a = 1; + baseCol0.a = 0; + offsetCol0.a = 1; + baseCol1.a = 0; + offsetCol1.a = 1; } - computeColors(baseCol, offsetCol, curMatrix * glm::vec4(vs.x, vs.y, vs.z, 1), getNormal(vs)); } else { - baseCol = glm::vec4(0); - offsetCol = glm::vec4(0); + baseCol0 = glm::vec4(0); + offsetCol0 = glm::vec4(0); + baseCol1 = glm::vec4(0); + offsetCol1 = glm::vec4(0); } - *(u32 *)vd.col = packColor(baseCol + offsetCol); + // non-textured vertices have no offset color + *(u32 *)vd.col = packColor(baseCol0 + offsetCol0); + *(u32 *)vd.col1 = packColor(baseCol1 + offsetCol1); } template<> @@ -702,16 +575,21 @@ void convertVertex(const N2_VERTEX_VR& vs, Vertex& vd) setCoords(vd, vs.x, vs.y, vs.z); setNormal(vd, vs); SetEnvMapUV(vd); - glm::vec4 baseCol = unpackColor(vs.rgb.argb0); - glm::vec4 offsetCol = baseCol; + glm::vec4 baseCol0 = unpackColor(vs.rgb.argb0); + glm::vec4 offsetCol0 = baseCol0; + glm::vec4 baseCol1 = unpackColor(vs.rgb.argb1); + glm::vec4 offsetCol1 = baseCol1; if (curGmp != nullptr) { // Not sure about offset but vf4 needs base addition - baseCol += unpackColor(curGmp->diffuse0); - offsetCol += unpackColor(curGmp->specular0); - computeColors(baseCol, offsetCol, curMatrix * glm::vec4(vs.x, vs.y, vs.z, 1), getNormal(vs)); + baseCol0 += unpackColor(curGmp->diffuse0); + offsetCol0 += unpackColor(curGmp->specular0); + baseCol1 += unpackColor(curGmp->diffuse1); + offsetCol1 += unpackColor(curGmp->specular1); } - *(u32 *)vd.col = packColor(baseCol + offsetCol); + // non-textured vertices have no offset color + *(u32 *)vd.col = packColor(baseCol0 + offsetCol0); + *(u32 *)vd.col1 = packColor(baseCol1 + offsetCol1); } template<> @@ -720,21 +598,28 @@ void convertVertex(const N2_VERTEX_VU& vs, Vertex& vd) setCoords(vd, vs.x, vs.y, vs.z); setNormal(vd, vs); setUV(vs, vd); - glm::vec4 baseCol; - glm::vec4 offsetCol; + glm::vec4 baseCol0; + glm::vec4 offsetCol0; + glm::vec4 baseCol1; + glm::vec4 offsetCol1; if (curGmp != nullptr) { - baseCol = unpackColor(curGmp->diffuse0); - offsetCol = unpackColor(curGmp->specular0); - computeColors(baseCol, offsetCol, curMatrix * glm::vec4(vs.x, vs.y, vs.z, 1), getNormal(vs)); + baseCol0 = unpackColor(curGmp->diffuse0); + offsetCol0 = unpackColor(curGmp->specular0); + baseCol1 = unpackColor(curGmp->diffuse1); + offsetCol1 = unpackColor(curGmp->specular1); } else { - baseCol = glm::vec4(0); - offsetCol = glm::vec4(0); + baseCol0 = glm::vec4(0); + offsetCol0 = glm::vec4(0); + baseCol1 = glm::vec4(0); + offsetCol1 = glm::vec4(0); } - *(u32 *)vd.col = packColor(baseCol); - *(u32 *)vd.spc = packColor(offsetCol); + *(u32 *)vd.col = packColor(baseCol0); + *(u32 *)vd.spc = packColor(offsetCol0); + *(u32 *)vd.col1 = packColor(baseCol1); + *(u32 *)vd.spc1 = packColor(offsetCol1); } template<> @@ -743,41 +628,63 @@ void convertVertex(const N2_VERTEX_VUR& vs, Vertex& vd) setCoords(vd, vs.x, vs.y, vs.z); setNormal(vd, vs); setUV(vs, vd); - glm::vec4 baseCol = unpackColor(vs.rgb.argb0); - glm::vec4 offsetCol = baseCol; + glm::vec4 baseCol0 = unpackColor(vs.rgb.argb0); + glm::vec4 offsetCol0 = baseCol0; + glm::vec4 baseCol1 = unpackColor(vs.rgb.argb1); + glm::vec4 offsetCol1 = baseCol1; if (curGmp != nullptr) { // Not sure about offset but vf4 needs base addition - baseCol += unpackColor(curGmp->diffuse0); - offsetCol += unpackColor(curGmp->specular0); - computeColors(baseCol, offsetCol, curMatrix * glm::vec4(vs.x, vs.y, vs.z, 1), getNormal(vs)); + baseCol0 += unpackColor(curGmp->diffuse0); + offsetCol0 += unpackColor(curGmp->specular0); + baseCol1 += unpackColor(curGmp->diffuse1); + offsetCol1 += unpackColor(curGmp->specular1); } - *(u32 *)vd.col = packColor(baseCol); - *(u32 *)vd.spc = packColor(offsetCol); + *(u32 *)vd.col = packColor(baseCol0); + *(u32 *)vd.spc = packColor(offsetCol0); + *(u32 *)vd.col1 = packColor(baseCol1); + *(u32 *)vd.spc1 = packColor(offsetCol1); } template<> void convertVertex(const N2_VERTEX_VUB& vs, Vertex& vd) { - // TODO setCoords(vd, vs.x, vs.y, vs.z); setNormal(vd, vs); setUV(vs, vd); - glm::vec4 baseCol; - glm::vec4 offsetCol; + glm::vec4 baseCol0; + glm::vec4 baseCol1; if (curGmp != nullptr) { - baseCol = unpackColor(curGmp->diffuse0); - offsetCol = unpackColor(curGmp->specular0); - computeColors(baseCol, offsetCol, curMatrix * glm::vec4(vs.x, vs.y, vs.z, 1), getNormal(vs)); + baseCol0 = unpackColor(curGmp->diffuse0); + baseCol1 = unpackColor(curGmp->diffuse1); } else { - baseCol = glm::vec4(0); - offsetCol = glm::vec4(0); + baseCol0 = glm::vec4(0); + baseCol1 = glm::vec4(0); } - *(u32 *)vd.col = packColor(baseCol); - *(u32 *)vd.spc = packColor(offsetCol); + *(u32 *)vd.col = packColor(baseCol0); + *(u32 *)vd.col1 = packColor(baseCol1); + // Stuff the bump map normals and parameters in the specular colors + vd.spc[0] = vs.bump.tangent.x; + vd.spc[1] = vs.bump.tangent.y; + vd.spc[2] = vs.bump.tangent.z; + vd.spc1[0] = vs.bump.bitangent.x; + vd.spc1[1] = vs.bump.bitangent.y; + vd.spc1[2] = vs.bump.bitangent.z; + vd.spc[3] = vs.bump.scaleFactor.bumpDegree; // always 255? + vd.spc1[3] = vs.bump.scaleFactor.fixedOffset; // always 0? +// int nx = (int8_t)vs.header.nx; +// int ny = (int8_t)vs.header.ny; +// int nz = (int8_t)vs.header.nz; +// printf("BumpMap vtx deg %d off %d normal %d %d %d tangent %d %d %d bitangent %d %d %d dot %d %d %d\n", vs.bump.scaleFactor.bumpDegree, vs.bump.scaleFactor.fixedOffset, +// nx, ny, nz, +// vs.bump.tangent.x, vs.bump.tangent.y, vs.bump.tangent.z, vs.bump.bitangent.x, vs.bump.bitangent.y, vs.bump.bitangent.z, +// nx * vs.bump.tangent.x + ny * vs.bump.tangent.y + nz * vs.bump.tangent.z, +// nx * vs.bump.bitangent.x + ny * vs.bump.bitangent.y + nz * vs.bump.bitangent.z, +// vs.bump.tangent.x * vs.bump.bitangent.x + vs.bump.tangent.y * vs.bump.bitangent.y + vs.bump.tangent.z * vs.bump.bitangent.z +// ); } template @@ -1052,8 +959,13 @@ static void setStateParams(PolyParam& pp) pp.tsp.DstInstr = 5; } // projFlip is for left-handed projection matrices (initd rear view mirror) - bool projFlip = std::signbit(taProjMatrix[0]) == std::signbit(taProjMatrix[5]); + bool projFlip = taProjMatrix != nullptr && std::signbit(taProjMatrix[0]) == std::signbit(taProjMatrix[5]); pp.isp.CullMode ^= (u32)cullingReversed ^ (u32)projFlip; + if (pp.pcw.Volume == 0) + { + pp.tsp1.full = -1; + pp.tcw1.full = -1; + } } static void sendPolygon(ICHList *list) @@ -1087,8 +999,10 @@ static void sendPolygon(ICHList *list) PolyParam pp{}; pp.pcw.Shadow = list->pcw.shadow; pp.pcw.Gouraud = list->pcw.gouraud; + pp.pcw.Volume = list->pcw.volume; pp.isp = list->isp; pp.tsp = list->tsp0; + pp.tsp1 = list->tsp1; setStateParams(pp); if (curGmp != nullptr && curGmp->paramSelect.e0) { @@ -1133,19 +1047,31 @@ static void sendPolygon(ICHList *list) } else { - verify(curGmp == nullptr || curGmp->paramSelect.e0 == 0); PolyParam pp{}; pp.pcw.Shadow = list->pcw.shadow; pp.pcw.Texture = 1; pp.pcw.Offset = list->pcw.offset; pp.pcw.Gouraud = list->pcw.gouraud; + pp.pcw.Volume = list->pcw.volume; pp.isp = list->isp; pp.tsp = list->tsp0; pp.tcw = list->tcw0; + pp.tsp1 = list->tsp1; + pp.tcw1 = list->tcw1; setStateParams(pp); + if (curGmp != nullptr && curGmp->paramSelect.e0) + { + // Environment mapping + pp.pcw.Offset = 0; + pp.tsp.UseAlpha = 1; + pp.tsp.IgnoreTexA = 0; + pp.envMapping = true; + envMapping = true; + } ta_add_poly(state.listType, pp); sendVertices(list, vtx); + envMapping = false; } } break; @@ -1161,9 +1087,12 @@ static void sendPolygon(ICHList *list) pp.pcw.Texture = 1; pp.pcw.Offset = list->pcw.offset; pp.pcw.Gouraud = list->pcw.gouraud; + pp.pcw.Volume = list->pcw.volume; pp.isp = list->isp; pp.tsp = list->tsp0; pp.tcw = list->tcw0; + pp.tsp1 = list->tsp1; + pp.tcw1 = list->tcw1; setStateParams(pp); ta_add_poly(state.listType, pp); @@ -1179,8 +1108,10 @@ static void sendPolygon(ICHList *list) PolyParam pp{}; pp.pcw.Shadow = list->pcw.shadow; pp.pcw.Gouraud = list->pcw.gouraud; + pp.pcw.Volume = list->pcw.volume; pp.isp = list->isp; pp.tsp = list->tsp0; + pp.tsp1 = list->tsp1; setStateParams(pp); if (curGmp != nullptr && curGmp->paramSelect.e0) { @@ -1204,6 +1135,7 @@ static void sendPolygon(ICHList *list) case ICHList::VTX_TYPE_VUB: { // TODO + //printf("BUMP MAP fmt %d filter %d src select %d dst %d\n", list->tcw0.PixelFmt, list->tsp0.FilterMode, list->tsp0.SrcSelect, list->tsp0.DstSelect); N2_VERTEX_VUB *vtx = (N2_VERTEX_VUB *)((u8 *)list + sizeof(ICHList)); if (!isInFrustum(vtx, list->vtxCount)) break; @@ -1212,14 +1144,16 @@ static void sendPolygon(ICHList *list) pp.pcw.Texture = 1; pp.pcw.Offset = 1; pp.pcw.Gouraud = list->pcw.gouraud; + pp.pcw.Volume = list->pcw.volume; pp.isp = list->isp; pp.tsp = list->tsp0; pp.tcw = list->tcw0; + pp.tsp1 = list->tsp1; + pp.tcw1 = list->tcw1; setStateParams(pp); - //ta_add_poly(state.listType, pp); + ta_add_poly(state.listType, pp); - //sendVertices(list, vtx); - INFO_LOG(PVR, "Unhandled poly format VTX_TYPE_VUB"); + sendVertices(list, vtx); } break; diff --git a/core/hw/pvr/elan_struct.h b/core/hw/pvr/elan_struct.h index 7d7af0758..20972dfba 100644 --- a/core/hw/pvr/elan_struct.h +++ b/core/hw/pvr/elan_struct.h @@ -275,13 +275,13 @@ struct BumpMap int8_t y; int8_t z; u8 _res; - } v0; + } tangent; struct { int8_t x; int8_t y; int8_t z; u8 _res; - } v1; + } bitangent; u32 _res; }; @@ -344,7 +344,7 @@ struct ICHList : public ElanBase TSP tsp0; TCW tcw0; TSP tsp1; - TSP tcw1; + TCW tcw1; u32 flags; u32 vtxCount; diff --git a/core/hw/pvr/ta_vtx.cpp b/core/hw/pvr/ta_vtx.cpp index 0a88214d7..8e686c6b1 100644 --- a/core/hw/pvr/ta_vtx.cpp +++ b/core/hw/pvr/ta_vtx.cpp @@ -1658,14 +1658,26 @@ bool ta_parse_naomi2(TA_context* ctx) // TODO BGRA colors bgpp.envMapping = false; for (PolyParam& pp : ctx->rend.global_param_op) + { if (pp.pcw.Texture) pp.texture = renderer->GetTexture(pp.tsp, pp.tcw); + if (pp.tsp1.full != (u32)-1) + pp.texture1 = renderer->GetTexture(pp.tsp1, pp.tcw1); + } for (PolyParam& pp : ctx->rend.global_param_pt) + { if (pp.pcw.Texture) pp.texture = renderer->GetTexture(pp.tsp, pp.tcw); + if (pp.tsp1.full != (u32)-1) + pp.texture1 = renderer->GetTexture(pp.tsp1, pp.tcw1); + } for (PolyParam& pp : ctx->rend.global_param_tr) + { if (pp.pcw.Texture) pp.texture = renderer->GetTexture(pp.tsp, pp.tcw); + if (pp.tsp1.full != (u32)-1) + pp.texture1 = renderer->GetTexture(pp.tsp1, pp.tcw1); + } bool overrun = ctx->rend.Overrun; if (overrun) diff --git a/core/rend/TexCache.cpp b/core/rend/TexCache.cpp index 3ca209343..9192832ae 100644 --- a/core/rend/TexCache.cpp +++ b/core/rend/TexCache.cpp @@ -408,6 +408,7 @@ static const TextureType PAL_TYPE[4] = { void BaseTextureCacheData::PrintTextureName() { +#if !defined(NDEBUG) || defined(DEBUGFAST) char str[512]; sprintf(str, "Texture: %s", GetPixelFormatName()); @@ -427,6 +428,7 @@ void BaseTextureCacheData::PrintTextureName() std::string id = GetId(); sprintf(str + strlen(str), " id=%s", id.c_str()); DEBUG_LOG(RENDERER, "%s", str); +#endif } //true if : dirty or paletted texture and hashes don't match diff --git a/core/rend/gl4/gl4.h b/core/rend/gl4/gl4.h index 524d27045..5c2af12a3 100755 --- a/core/rend/gl4/gl4.h +++ b/core/rend/gl4/gl4.h @@ -18,6 +18,7 @@ */ #pragma once #include "rend/gles/gles.h" +#include "hw/pvr/elan_struct.h" #include void gl4DrawStrips(GLuint output_fbo, int width, int height); @@ -54,6 +55,26 @@ struct gl4PipelineShader GLint ambientMaterial; GLint useBaseOver; GLint envMapping; + GLint bumpMapping; + struct { + GLint color; + GLint direction; + GLint position; + GLint parallel; + GLint diffuse; + GLint specular; + GLint routing; + GLint dmode; + GLint smode; + GLint distAttnMode; + GLint attnDistA; + GLint attnDistB; + GLint attnAngleA; + GLint attnAngleB; + } lights[elan::MAX_LIGHTS]; + float *lastMvMat; + float *lastProjMat; + N2LightModel *lastLightModel; bool cp_AlphaTest; bool pp_InsideClipping; diff --git a/core/rend/gl4/gl4naomi2.cpp b/core/rend/gl4/gl4naomi2.cpp new file mode 100644 index 000000000..ef248bb40 --- /dev/null +++ b/core/rend/gl4/gl4naomi2.cpp @@ -0,0 +1,54 @@ +/* + Copyright 2022 flyinghead + + This file is part of Flycast. + + Flycast is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + Flycast is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Flycast. If not, see . + */ +#include "gl4naomi2.h" + +extern const char *N2VertexShader; +extern const char *N2ColorShader; +extern const char *GeometryClippingShader; + +static const char *gouraudSource = R"( +#if pp_Gouraud == 0 +#define INTERPOLATION flat +#else +#define INTERPOLATION noperspective +#endif +#define NOPERSPECTIVE noperspective +)"; + +N2Vertex4Source::N2Vertex4Source(bool gouraud, bool geometryOnly) : OpenGl4Source() +{ + addConstant("pp_Gouraud", gouraud); + addConstant("GEOM_ONLY", geometryOnly); + addConstant("TWO_VOLUMES", 1); + + addSource(gouraudSource); + if (!geometryOnly) + addSource(N2ColorShader); + addSource(N2VertexShader); +} + +N2Geometry4Shader::N2Geometry4Shader(bool gouraud, bool geometryOnly) : OpenGl4Source() +{ + addConstant("pp_Gouraud", gouraud); + addConstant("GEOM_ONLY", geometryOnly); + addConstant("TWO_VOLUMES", 1); + + addSource(gouraudSource); + addSource(GeometryClippingShader); +} diff --git a/core/rend/gl4/naomi2.h b/core/rend/gl4/gl4naomi2.h similarity index 92% rename from core/rend/gl4/naomi2.h rename to core/rend/gl4/gl4naomi2.h index c8fd7a513..5775a4c9d 100644 --- a/core/rend/gl4/naomi2.h +++ b/core/rend/gl4/gl4naomi2.h @@ -18,8 +18,7 @@ */ #pragma once #include "gl4.h" - -void setN2Uniforms(const PolyParam *pp, const gl4PipelineShader *shader); +#include "rend/gles/naomi2.h" class N2Vertex4Source : public OpenGl4Source { diff --git a/core/rend/gl4/gldraw.cpp b/core/rend/gl4/gldraw.cpp index 6433b5cb4..6a1bd232b 100644 --- a/core/rend/gl4/gldraw.cpp +++ b/core/rend/gl4/gldraw.cpp @@ -20,7 +20,7 @@ #include "rend/gles/glcache.h" #include "rend/tileclip.h" #include "rend/osd.h" -#include "naomi2.h" +#include "gl4naomi2.h" static gl4PipelineShader* CurrentShader; extern u32 gcflip; diff --git a/core/rend/gl4/gles.cpp b/core/rend/gl4/gles.cpp index 211673e99..2e6fc241b 100644 --- a/core/rend/gl4/gles.cpp +++ b/core/rend/gl4/gles.cpp @@ -21,7 +21,7 @@ #include "rend/transform_matrix.h" #include "rend/osd.h" #include "glsl.h" -#include "naomi2.h" +#include "gl4naomi2.h" //Fragment and vertex shaders code @@ -548,17 +548,8 @@ bool gl4CompilePipelineShader(gl4PipelineShader* s, const char *fragment_source glUniform1i(gu, 6); // GL_TEXTURE6 s->palette_index = glGetUniformLocation(s->program, "palette_index"); - // Naomi2 - s->mvMat = glGetUniformLocation(s->program, "mvMat"); - s->projMat = glGetUniformLocation(s->program, "projMat"); - s->glossCoef0 = glGetUniformLocation(s->program, "glossCoef0"); - s->envMapping = glGetUniformLocation(s->program, "envMapping"); - // Lights - s->lightCount = glGetUniformLocation(s->program, "lightCount"); - s->ambientBase = glGetUniformLocation(s->program, "ambientBase"); - s->ambientOffset = glGetUniformLocation(s->program, "ambientOffset"); - s->ambientMaterial = glGetUniformLocation(s->program, "ambientMaterial"); - s->useBaseOver = glGetUniformLocation(s->program, "useBaseOver"); + if (s->naomi2) + initN2Uniforms(s); return glIsProgram(s->program)==GL_TRUE; } @@ -775,6 +766,8 @@ static bool RenderFrame(int width, int height) glcache.UseProgram(gl4.n2ModVolShader.program); glUniformMatrix4fv(gl4.n2ModVolShader.normal_matrix, 1, GL_FALSE, &gl4ShaderUniforms.normal_mat[0][0]); } + for (auto& it : gl4.shaders) + resetN2UniformCache(&it.second); gl4ShaderUniforms.PT_ALPHA=(PT_ALPHA_REF&0xFF)/255.0f; diff --git a/core/rend/gl4/naomi2.cpp b/core/rend/gl4/naomi2.cpp deleted file mode 100644 index a3969fc76..000000000 --- a/core/rend/gl4/naomi2.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/* - Copyright 2022 flyinghead - - This file is part of Flycast. - - Flycast is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - Flycast is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Flycast. If not, see . - */ -#include "naomi2.h" - -extern const char *N2VertexShader; -extern const char *N2ColorShader; -extern const char *GeometryClippingShader; - -static const char *gouraudSource = R"( -#if pp_Gouraud == 0 -#define INTERPOLATION flat -#else -#define INTERPOLATION noperspective -#endif -#define NOPERSPECTIVE noperspective -)"; - -N2Vertex4Source::N2Vertex4Source(bool gouraud, bool geometryOnly) : OpenGl4Source() -{ - addConstant("pp_Gouraud", gouraud); - addConstant("GEOM_ONLY", geometryOnly); - addConstant("TWO_VOLUMES", 1); - - addSource(gouraudSource); - if (!geometryOnly) - addSource(N2ColorShader); - addSource(N2VertexShader); -} - -N2Geometry4Shader::N2Geometry4Shader(bool gouraud, bool geometryOnly) : OpenGl4Source() -{ - addConstant("pp_Gouraud", gouraud); - addConstant("GEOM_ONLY", geometryOnly); - addConstant("TWO_VOLUMES", 1); - - addSource(gouraudSource); - addSource(GeometryClippingShader); -} - -static void setLightUniform(const gl4PipelineShader *shader, int lightId, const char *name, int v) -{ - char s[128]; - sprintf(s, "lights[%d].%s", lightId, name); - GLint loc = glGetUniformLocation(shader->program, s); - glUniform1i(loc, v); -} - -static void setLightUniform(const gl4PipelineShader *shader, int lightId, const char *name, float v) -{ - char s[128]; - sprintf(s, "lights[%d].%s", lightId, name); - GLint loc = glGetUniformLocation(shader->program, s); - glUniform1f(loc, v); -} - -static void setLightUniform4f(const gl4PipelineShader *shader, int lightId, const char *name, const float *v) -{ - char s[128]; - sprintf(s, "lights[%d].%s", lightId, name); - GLint loc = glGetUniformLocation(shader->program, s); - glUniform4fv(loc, 1, v); -} - -void setN2Uniforms(const PolyParam *pp, const gl4PipelineShader *shader) -{ - glUniformMatrix4fv(shader->mvMat, 1, GL_FALSE, &pp->mvMatrix[0]); - glUniformMatrix4fv(shader->projMat, 1, GL_FALSE, &pp->projMatrix[0]); - glUniform1f(shader->glossCoef0, pp->glossCoef0); - N2LightModel *const lightModel = pp->lightModel; - if (lightModel != nullptr) - { - glUniform1i(shader->ambientMaterial, lightModel->ambientMaterial); - glUniform4fv(shader->ambientBase, 1, lightModel->ambientBase); - glUniform4fv(shader->ambientOffset, 1, lightModel->ambientOffset); - glUniform1i(shader->useBaseOver, lightModel->useBaseOver); - glUniform1i(shader->lightCount, lightModel->lightCount); - for (int i = 0; i < lightModel->lightCount; i++) - { - const N2Light& light = lightModel->lights[i]; - setLightUniform(shader, i, "parallel", light.parallel); - - setLightUniform4f(shader, i, "color", light.color); - setLightUniform4f(shader, i, "direction", light.direction); - setLightUniform4f(shader, i, "position", light.position); - - setLightUniform(shader, i, "diffuse", light.diffuse); - setLightUniform(shader, i, "specular", light.specular); - setLightUniform(shader, i, "routing", light.routing); - setLightUniform(shader, i, "dmode", light.dmode); - setLightUniform(shader, i, "smode", light.smode); - setLightUniform(shader, i, "distAttnMode", light.distAttnMode); - - setLightUniform(shader, i, "attnDistA", light.attnDistA); - setLightUniform(shader, i, "attnDistB", light.attnDistB); - setLightUniform(shader, i, "attnAngleA", light.attnAngleA); - setLightUniform(shader, i, "attnAngleB", light.attnAngleB); - } - } - else - { - float white[] { 1.f, 1.f, 1.f, 1.f }; - float black[4]{}; - glUniform1i(shader->ambientMaterial, 0); - glUniform4fv(shader->ambientBase, 1, white); - glUniform4fv(shader->ambientOffset, 1, black); - glUniform1i(shader->useBaseOver, 0); - glUniform1i(shader->lightCount, 0); - } - glUniform1i(shader->envMapping, pp->envMapping); - glEnable(GL_CLIP_DISTANCE0); -} diff --git a/core/rend/gles/gles.cpp b/core/rend/gles/gles.cpp index 9acc6e962..7277479c8 100644 --- a/core/rend/gles/gles.cpp +++ b/core/rend/gles/gles.cpp @@ -574,8 +574,10 @@ GLuint gl_CompileAndLink(const char *vertexShader, const char *fragmentShader, c GLuint vs = gl_CompileShader(vertexShader, GL_VERTEX_SHADER); GLuint ps = gl_CompileShader(fragmentShader, GL_FRAGMENT_SHADER); GLuint gs = 0; +#ifdef GL_GEOMETRY_SHADER // TODO Need GL 3.2 or GLES 3.2. Not defined on iOS if (geometryShader != nullptr) gs = gl_CompileShader(geometryShader, GL_GEOMETRY_SHADER); +#endif GLuint program = glCreateProgram(); glAttachShader(program, vs); @@ -787,17 +789,8 @@ bool CompilePipelineShader(PipelineShader* s) } s->normal_matrix = glGetUniformLocation(s->program, "normal_matrix"); - // Naomi2 - s->mvMat = glGetUniformLocation(s->program, "mvMat"); - s->projMat = glGetUniformLocation(s->program, "projMat"); - s->glossCoef0 = glGetUniformLocation(s->program, "glossCoef0"); - s->envMapping = glGetUniformLocation(s->program, "envMapping"); - // Lights - s->lightCount = glGetUniformLocation(s->program, "lightCount"); - s->ambientBase = glGetUniformLocation(s->program, "ambientBase"); - s->ambientOffset = glGetUniformLocation(s->program, "ambientOffset"); - s->ambientMaterial = glGetUniformLocation(s->program, "ambientMaterial"); - s->useBaseOver = glGetUniformLocation(s->program, "useBaseOver"); + if (s->naomi2) + initN2Uniforms(s); ShaderUniforms.Set(s); @@ -1253,10 +1246,11 @@ bool RenderFrame(int width, int height) ShaderUniforms.PT_ALPHA=(PT_ALPHA_REF&0xFF)/255.0f; - for (const auto& it : gl.shaders) + for (auto& it : gl.shaders) { glcache.UseProgram(it.second.program); ShaderUniforms.Set(&it.second); + resetN2UniformCache(&it.second); } //setup render target first diff --git a/core/rend/gles/gles.h b/core/rend/gles/gles.h index 84a59852d..9e20210a7 100755 --- a/core/rend/gles/gles.h +++ b/core/rend/gles/gles.h @@ -1,6 +1,7 @@ #pragma once #include "hw/pvr/ta_structs.h" #include "hw/pvr/ta_ctx.h" +#include "hw/pvr/elan_struct.h" #include "rend/TexCache.h" #include "wsi/gl_context.h" #include "glcache.h" @@ -61,6 +62,26 @@ struct PipelineShader GLint ambientMaterial; GLint useBaseOver; GLint envMapping; + GLint bumpMapping; + struct { + GLint color; + GLint direction; + GLint position; + GLint parallel; + GLint diffuse; + GLint specular; + GLint routing; + GLint dmode; + GLint smode; + GLint distAttnMode; + GLint attnDistA; + GLint attnDistB; + GLint attnAngleA; + GLint attnAngleB; + } lights[elan::MAX_LIGHTS]; + float *lastMvMat; + float *lastProjMat; + N2LightModel *lastLightModel; // bool cp_AlphaTest; diff --git a/core/rend/gles/naomi2.cpp b/core/rend/gles/naomi2.cpp index 6c7a8f06b..6f89ad855 100644 --- a/core/rend/gles/naomi2.cpp +++ b/core/rend/gles/naomi2.cpp @@ -21,6 +21,7 @@ // FIXME GLES #ifndef GL_CLIP_DISTANCE0 #define GL_CLIP_DISTANCE0 0x3000 +#define GL_CLIP_DISTANCE1 0x3001 #endif const char* N2VertexShader = R"( @@ -31,6 +32,7 @@ uniform float sp_FOG_DENSITY; uniform mat4 mvMat; uniform mat4 projMat; uniform int envMapping; +uniform int bumpMapping; // Vertex input in vec3 in_pos; @@ -54,7 +56,7 @@ INTERPOLATION out vec4 vs_offs1; noperspective out vec2 vs_uv1; #endif #endif -out float gl_ClipDistance[1]; +out float gl_ClipDistance[6]; void main() { @@ -66,9 +68,13 @@ void main() vs_base1 = in_base1; vs_offs1 = in_offs1; vs_uv1 = in_uv1; + // FIXME need offset0 and offset1 for bump maps + if (bumpMapping == 1) + computeBumpMap(vs_offs, vs_offs1, normalize(in_normal)); #endif vec4 vnorm = normalize(mvMat * vec4(in_normal, 0.0)); - computeColors(vs_base, vs_offs, vpos.xyz, vnorm.xyz); + if (bumpMapping == 0) + computeColors(vs_base, vs_offs, vpos.xyz, vnorm.xyz); vs_uv.xy = in_uv; if (envMapping == 1) computeEnvMap(vs_uv.xy, vpos.xyz, vnorm.xyz); @@ -77,6 +83,7 @@ void main() vpos = projMat * vpos; gl_ClipDistance[0] = vpos.w - 0.001; // near FIXME + gl_ClipDistance[1] = 100000.0 - vpos.w; // far FIXME gl_Position = vpos; } @@ -84,6 +91,8 @@ void main() )"; const char* N2ColorShader = R"( +#define PI 3.1415926 + #define LMODE_SINGLE_SIDED 0 #define LMODE_DOUBLE_SIDED 1 #define LMODE_DOUBLE_SIDED_WITH_TOLERANCE 2 @@ -250,11 +259,50 @@ void computeEnvMap(inout vec2 uv, in vec3 position, in vec3 normal) uv = clamp(uv, 0.0, 1.0); } +void computeBumpMap(inout vec4 color0, in vec4 color1, in vec3 normal) +{ + vec3 tangent = color0.xyz; + if (tangent.x > 0.5) + tangent.x -= 1.0; + if (tangent.y > 0.5) + tangent.y -= 1.0; + if (tangent.z > 0.5) + tangent.z -= 1.0; + tangent = normalize(tangent); + vec3 bitangent = color1.xyz; + if (bitangent.x > 0.5) + bitangent.x -= 1.0; + if (bitangent.y > 0.5) + bitangent.y -= 1.0; + if (bitangent.z > 0.5) + bitangent.z -= 1.0; + bitangent = normalize(bitangent); + + float scaleDegree = color0.w; + float scaleOffset = color1.w; + + // FIXME not right + float sinT = normal.x; + float cosQ = tangent.y; + float sinQ = bitangent.z; + + float k1 = 1.0 - scaleDegree; + float k2 = scaleDegree * sinT; + float k3 = scaleDegree * sqrt(1.0 - sinT * sinT); + float q = acos(cosQ); + if (sinQ < 0) + q = 2.0 * PI - q; + color0.x = q / PI / 2.0; + color0.y = k3; + color0.z = k2; + color0.w = k1; +} + )"; const char *GeometryClippingShader = R"( layout (triangles) in; -layout (triangle_strip, max_vertices = 6) out; +layout (triangle_strip, max_vertices = 12) out; uniform mat4 normal_matrix; @@ -289,7 +337,7 @@ struct Vertex vec4 offs1; vec2 uv1; #endif - float clipDist; + float clipDist[2]; }; Vertex interpolate(in Vertex v0, in Vertex v1, in float d0, in float d1) @@ -307,7 +355,8 @@ Vertex interpolate(in Vertex v0, in Vertex v1, in float d0, in float d1) v.uv1 = mix(v0.uv1, v1.uv1, f); #endif #endif - v.clipDist = mix(v0.clipDist, v1.clipDist, f); + v.clipDist[0] = mix(v0.clipDist[0], v1.clipDist[0], f); + v.clipDist[1] = mix(v0.clipDist[1], v1.clipDist[1], f); return v; } @@ -418,39 +467,27 @@ void emitVertex(in Vertex v) void main() { - Vertex vtx[6]; - vtx[0].pos = gl_in[0].gl_Position; - vtx[1].pos = gl_in[1].gl_Position; - vtx[2].pos = gl_in[2].gl_Position; + Vertex vtx[12]; + for (int i = 0; i < 3; i++) + { + vtx[i].pos = gl_in[i].gl_Position; #if GEOM_ONLY == 0 - vtx[0].base = vs_base[0]; - vtx[0].offs = vs_offs[0]; - vtx[0].uv = vs_uv[0]; - vtx[1].base = vs_base[1]; - vtx[1].offs = vs_offs[1]; - vtx[1].uv = vs_uv[1]; - vtx[2].base = vs_base[2]; - vtx[2].offs = vs_offs[2]; - vtx[2].uv = vs_uv[2]; + vtx[i].base = vs_base[i]; + vtx[i].offs = vs_offs[i]; + vtx[i].uv = vs_uv[i]; #if TWO_VOLUMES == 1 - vtx[0].base1 = vs_base1[0]; - vtx[0].offs1 = vs_offs1[0]; - vtx[0].uv1 = vs_uv1[0]; - vtx[1].base1 = vs_base1[1]; - vtx[1].offs1 = vs_offs1[1]; - vtx[1].uv1 = vs_uv1[1]; - vtx[2].base1 = vs_base1[2]; - vtx[2].offs1 = vs_offs1[2]; - vtx[2].uv1 = vs_uv1[2]; + vtx[i].base1 = vs_base1[i]; + vtx[i].offs1 = vs_offs1[i]; + vtx[i].uv1 = vs_uv1[i]; #endif #endif + vtx[i].clipDist[0] = gl_in[i].gl_ClipDistance[0]; + vtx[i].clipDist[1] = gl_in[i].gl_ClipDistance[1]; + } int vtxCount = 3; - vtx[0].clipDist = gl_in[0].gl_ClipDistance[0]; - vtx[1].clipDist = gl_in[1].gl_ClipDistance[0]; - vtx[2].clipDist = gl_in[2].gl_ClipDistance[0]; // near-plane only - vec3 dist = vec3(vtx[0].clipDist, vtx[1].clipDist, vtx[2].clipDist); + vec3 dist = vec3(vtx[0].clipDist[0], vtx[1].clipDist[0], vtx[2].clipDist[0]); Vertex v3; int size = clip3(dist, vtx[0], vtx[1], vtx[2], v3); if (size == 0) @@ -495,77 +532,3 @@ N2GeometryShader::N2GeometryShader(bool gouraud, bool geometryOnly) : OpenGlSour addSource(GouraudSource); addSource(GeometryClippingShader); } - -static void setLightUniform(const PipelineShader *shader, int lightId, const char *name, int v) -{ - char s[128]; - sprintf(s, "lights[%d].%s", lightId, name); - GLint loc = glGetUniformLocation(shader->program, s); - glUniform1i(loc, v); -} - -static void setLightUniform(const PipelineShader *shader, int lightId, const char *name, float v) -{ - char s[128]; - sprintf(s, "lights[%d].%s", lightId, name); - GLint loc = glGetUniformLocation(shader->program, s); - glUniform1f(loc, v); -} - -static void setLightUniform4f(const PipelineShader *shader, int lightId, const char *name, const float *v) -{ - char s[128]; - sprintf(s, "lights[%d].%s", lightId, name); - GLint loc = glGetUniformLocation(shader->program, s); - glUniform4fv(loc, 1, v); -} - -void setN2Uniforms(const PolyParam *pp, const PipelineShader *shader) -{ - glUniformMatrix4fv(shader->mvMat, 1, GL_FALSE, &pp->mvMatrix[0]); - glUniformMatrix4fv(shader->projMat, 1, GL_FALSE, &pp->projMatrix[0]); - glUniform1f(shader->glossCoef0, pp->glossCoef0); - N2LightModel *const lightModel = pp->lightModel; - if (lightModel != nullptr) - { - glUniform1i(shader->ambientMaterial, lightModel->ambientMaterial); - glUniform4fv(shader->ambientBase, 1, lightModel->ambientBase); - glUniform4fv(shader->ambientOffset, 1, lightModel->ambientOffset); - glUniform1i(shader->useBaseOver, lightModel->useBaseOver); - glUniform1i(shader->lightCount, lightModel->lightCount); - for (int i = 0; i < lightModel->lightCount; i++) - { - const N2Light& light = lightModel->lights[i]; - setLightUniform(shader, i, "parallel", light.parallel); - - setLightUniform4f(shader, i, "color", light.color); - setLightUniform4f(shader, i, "direction", light.direction); - setLightUniform4f(shader, i, "position", light.position); - - setLightUniform(shader, i, "diffuse", light.diffuse); - setLightUniform(shader, i, "specular", light.specular); - setLightUniform(shader, i, "routing", light.routing); - setLightUniform(shader, i, "dmode", light.dmode); - setLightUniform(shader, i, "smode", light.smode); - setLightUniform(shader, i, "distAttnMode", light.distAttnMode); - - setLightUniform(shader, i, "attnDistA", light.attnDistA); - setLightUniform(shader, i, "attnDistB", light.attnDistB); - setLightUniform(shader, i, "attnAngleA", light.attnAngleA); - setLightUniform(shader, i, "attnAngleB", light.attnAngleB); - } - } - else - { - float white[] { 1.f, 1.f, 1.f, 1.f }; - float black[4]{}; - glUniform1i(shader->ambientMaterial, 0); - glUniform4fv(shader->ambientBase, 1, white); - glUniform4fv(shader->ambientOffset, 1, black); - glUniform1i(shader->useBaseOver, 0); - glUniform1i(shader->lightCount, 0); - } - glUniform1i(shader->envMapping, pp->envMapping); - - glEnable(GL_CLIP_DISTANCE0); -} diff --git a/core/rend/gles/naomi2.h b/core/rend/gles/naomi2.h index 0a49cbec2..5af95e53f 100644 --- a/core/rend/gles/naomi2.h +++ b/core/rend/gles/naomi2.h @@ -19,8 +19,6 @@ #pragma once #include "gles.h" -void setN2Uniforms(const PolyParam *pp, const PipelineShader *shader); - class N2VertexSource : public OpenGlSource { public: @@ -32,3 +30,126 @@ class N2GeometryShader : public OpenGlSource public: N2GeometryShader(bool gouraud, bool geometryOnly = false); }; + +template +void resetN2UniformCache(ShaderType *shader) +{ + shader->lastMvMat = nullptr; + shader->lastProjMat = nullptr; + shader->lastLightModel = nullptr; +} + +template +void initN2Uniforms(ShaderType *shader) +{ + shader->mvMat = glGetUniformLocation(shader->program, "mvMat"); + shader->projMat = glGetUniformLocation(shader->program, "projMat"); + shader->glossCoef0 = glGetUniformLocation(shader->program, "glossCoef0"); + shader->envMapping = glGetUniformLocation(shader->program, "envMapping"); + shader->bumpMapping = glGetUniformLocation(shader->program, "bumpMapping"); + // Lights + shader->lightCount = glGetUniformLocation(shader->program, "lightCount"); + shader->ambientBase = glGetUniformLocation(shader->program, "ambientBase"); + shader->ambientOffset = glGetUniformLocation(shader->program, "ambientOffset"); + shader->ambientMaterial = glGetUniformLocation(shader->program, "ambientMaterial"); + shader->useBaseOver = glGetUniformLocation(shader->program, "useBaseOver"); + for (u32 i = 0; i < ARRAY_SIZE(shader->lights); i++) + { + char str[128]; + sprintf(str, "lights[%d].color", i); + shader->lights[i].color = glGetUniformLocation(shader->program, str); + sprintf(str, "lights[%d].direction", i); + shader->lights[i].direction = glGetUniformLocation(shader->program, str); + sprintf(str, "lights[%d].position", i); + shader->lights[i].position = glGetUniformLocation(shader->program, str); + sprintf(str, "lights[%d].parallel", i); + shader->lights[i].parallel = glGetUniformLocation(shader->program, str); + sprintf(str, "lights[%d].diffuse", i); + shader->lights[i].diffuse = glGetUniformLocation(shader->program, str); + sprintf(str, "lights[%d].specular", i); + shader->lights[i].specular = glGetUniformLocation(shader->program, str); + sprintf(str, "lights[%d].routing", i); + shader->lights[i].routing = glGetUniformLocation(shader->program, str); + sprintf(str, "lights[%d].dmode", i); + shader->lights[i].dmode = glGetUniformLocation(shader->program, str); + sprintf(str, "lights[%d].smode", i); + shader->lights[i].smode = glGetUniformLocation(shader->program, str); + sprintf(str, "lights[%d].distAttnMode", i); + shader->lights[i].distAttnMode = glGetUniformLocation(shader->program, str); + sprintf(str, "lights[%d].attnDistA", i); + shader->lights[i].attnDistA = glGetUniformLocation(shader->program, str); + sprintf(str, "lights[%d].attnDistB", i); + shader->lights[i].attnDistB = glGetUniformLocation(shader->program, str); + sprintf(str, "lights[%d].attnAngleA", i); + shader->lights[i].attnAngleA = glGetUniformLocation(shader->program, str); + sprintf(str, "lights[%d].attnAngleB", i); + shader->lights[i].attnAngleB = glGetUniformLocation(shader->program, str); + } + resetN2UniformCache(shader); +} + +template +void setN2Uniforms(const PolyParam *pp, ShaderType *shader) +{ + if (pp->mvMatrix != shader->lastMvMat) + { + shader->lastMvMat = pp->mvMatrix; + glUniformMatrix4fv(shader->mvMat, 1, GL_FALSE, &pp->mvMatrix[0]); + } + if (pp->projMatrix != shader->lastProjMat) + { + shader->lastProjMat = pp->projMatrix; + glUniformMatrix4fv(shader->projMat, 1, GL_FALSE, &pp->projMatrix[0]); + } + glUniform1f(shader->glossCoef0, pp->glossCoef0); + + N2LightModel *const lightModel = pp->lightModel; + if (lightModel != shader->lastLightModel) + { + shader->lastLightModel = lightModel; + if (lightModel != nullptr) + { + glUniform1i(shader->ambientMaterial, lightModel->ambientMaterial); + glUniform4fv(shader->ambientBase, 1, lightModel->ambientBase); + glUniform4fv(shader->ambientOffset, 1, lightModel->ambientOffset); + glUniform1i(shader->useBaseOver, lightModel->useBaseOver); + glUniform1i(shader->lightCount, lightModel->lightCount); + for (int i = 0; i < lightModel->lightCount; i++) + { + const N2Light& light = lightModel->lights[i]; + glUniform1i(shader->lights[i].parallel, light.parallel); + + glUniform4fv(shader->lights[i].color, 1, light.color); + glUniform4fv(shader->lights[i].direction, 1, light.direction); + glUniform4fv(shader->lights[i].position, 1, light.position); + + glUniform1i(shader->lights[i].diffuse, light.diffuse); + glUniform1i(shader->lights[i].specular, light.specular); + glUniform1i(shader->lights[i].routing, light.routing); + glUniform1i(shader->lights[i].dmode, light.dmode); + glUniform1i(shader->lights[i].smode, light.smode); + glUniform1i(shader->lights[i].distAttnMode, light.distAttnMode); + + glUniform1f(shader->lights[i].attnDistA, light.attnDistA); + glUniform1f(shader->lights[i].attnDistB, light.attnDistB); + glUniform1f(shader->lights[i].attnAngleA, light.attnAngleA); + glUniform1f(shader->lights[i].attnAngleB, light.attnAngleB); + } + } + else + { + float white[] { 1.f, 1.f, 1.f, 1.f }; + float black[4]{}; + glUniform1i(shader->ambientMaterial, 0); + glUniform4fv(shader->ambientBase, 1, white); + glUniform4fv(shader->ambientOffset, 1, black); + glUniform1i(shader->useBaseOver, 0); + glUniform1i(shader->lightCount, 0); + } + } + glUniform1i(shader->envMapping, pp->envMapping); + glUniform1i(shader->bumpMapping, pp->pcw.Texture == 1 && pp->tcw.PixelFmt == PixelBumpMap); + + glEnable(GL_CLIP_DISTANCE0); + glEnable(GL_CLIP_DISTANCE1); +} diff --git a/core/rend/sorter.cpp b/core/rend/sorter.cpp index 16d1428de..1197ac4a0 100644 --- a/core/rend/sorter.cpp +++ b/core/rend/sorter.cpp @@ -76,7 +76,7 @@ void SortPParams(int first, int count) if (pp->projMatrix != nullptr) { - glm::mat4 mvMat = glm::make_mat4(pp->mvMatrix); + glm::mat4 mvMat = pp->mvMatrix != nullptr ? glm::make_mat4(pp->mvMatrix) : glm::mat4(1); glm::mat4 projMat = glm::make_mat4(pp->projMatrix); glm::vec4 min{ 1e38f, 1e38f, 1e38f, 0.f }; glm::vec4 max{ -1e38f, -1e38f, -1e38f, 0.f }; @@ -301,7 +301,9 @@ void GenSorted(int first, int count, std::vector& pidx_sort, if (pp->projMatrix != nullptr) { - mat = glm::make_mat4(pp->projMatrix) * glm::make_mat4(pp->mvMatrix); + mat = glm::make_mat4(pp->projMatrix); + if (pp->mvMatrix != nullptr) + mat *= glm::make_mat4(pp->mvMatrix); z0 = getProjectedZ(vtx_base + idx[0], mat); z1 = getProjectedZ(vtx_base + idx[1], mat); }