naomi2: fix regressions. 2-volume and bump mapping support WIP

optimize open gl uniforms
This commit is contained in:
Flyinghead 2022-01-26 22:15:10 +01:00
parent 8947100701
commit e1038ea632
16 changed files with 440 additions and 451 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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