naomi2: fix regressions. 2-volume and bump mapping support WIP
optimize open gl uniforms
This commit is contained in:
parent
8947100701
commit
e1038ea632
|
@ -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()
|
||||
|
||||
|
|
|
@ -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<typename T>
|
||||
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 <typename T>
|
||||
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
#pragma once
|
||||
#include "rend/gles/gles.h"
|
||||
#include "hw/pvr/elan_struct.h"
|
||||
#include <unordered_map>
|
||||
|
||||
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;
|
||||
|
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#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);
|
||||
}
|
|
@ -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
|
||||
{
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#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);
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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<typename ShaderType>
|
||||
void resetN2UniformCache(ShaderType *shader)
|
||||
{
|
||||
shader->lastMvMat = nullptr;
|
||||
shader->lastProjMat = nullptr;
|
||||
shader->lastLightModel = nullptr;
|
||||
}
|
||||
|
||||
template<typename ShaderType>
|
||||
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<typename ShaderType>
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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<SortTrigDrawParam>& 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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue