mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2024-11-22 13:55:38 +00:00
Harry made some important discoveries with regards to fixed shading on the model 3 (per vertex poly brightness values). Firstly values are allowed to be negative, and they are used as a drop in replacement in the standard lighting equation for the normal dot light vector. This quite radically changes the brightness in LA Machine guns, but now correctly matches the arcade.
This commit is contained in:
parent
94e6f9a156
commit
cd5978773a
|
@ -12,7 +12,7 @@ namespace New3D {
|
|||
|
||||
struct ClipVertex
|
||||
{
|
||||
float pos[3];
|
||||
float pos[4];
|
||||
};
|
||||
|
||||
struct ClipPoly
|
||||
|
@ -23,12 +23,11 @@ struct ClipPoly
|
|||
|
||||
struct Vertex
|
||||
{
|
||||
float pos[3];
|
||||
float pos[4];
|
||||
float normal[3];
|
||||
float texcoords[2];
|
||||
UINT8 color[4];
|
||||
UINT8 fixedShade;
|
||||
UINT8 padding[3];
|
||||
float fixedShade;
|
||||
};
|
||||
|
||||
struct Poly // our polys are always 3 triangles, unlike the real h/w
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
#define MAX_RAM_POLYS 100000
|
||||
#define MAX_ROM_POLYS 500000
|
||||
|
||||
#define BYTE_TO_FLOAT(B) ((2.0f * (B) + 1.0f) * (1.0F/255.0f))
|
||||
|
||||
namespace New3D {
|
||||
|
||||
CNew3D::CNew3D(const Util::Config::Node &config, std::string gameName)
|
||||
|
@ -286,11 +288,11 @@ void CNew3D::RenderFrame(void)
|
|||
glEnableVertexAttribArray(4);
|
||||
|
||||
// before draw, specify vertex and index arrays with their offsets, offsetof is maybe evil ..
|
||||
glVertexAttribPointer(m_r3dShader.GetVertexAttribPos("inVertex"), 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
|
||||
glVertexAttribPointer(m_r3dShader.GetVertexAttribPos("inVertex"), 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
|
||||
glVertexAttribPointer(m_r3dShader.GetVertexAttribPos("inNormal"), 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, normal));
|
||||
glVertexAttribPointer(m_r3dShader.GetVertexAttribPos("inTexCoord"), 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, texcoords));
|
||||
glVertexAttribPointer(m_r3dShader.GetVertexAttribPos("inColour"), 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), (void*)offsetof(Vertex, color));
|
||||
glVertexAttribPointer(m_r3dShader.GetVertexAttribPos("inFixedShade"), 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), (void*)offsetof(Vertex, fixedShade));
|
||||
glVertexAttribPointer(m_r3dShader.GetVertexAttribPos("inFixedShade"), 1, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, fixedShade));
|
||||
|
||||
m_r3dShader.SetShader(true);
|
||||
|
||||
|
@ -784,8 +786,11 @@ void CNew3D::RenderViewport(UINT32 addr)
|
|||
vp->lightingParams[5] = 0.0; // reserved
|
||||
|
||||
// this is a hack because we haven't yet found in memory where these are set
|
||||
// these two games use a slightly different light model to the test of the games
|
||||
if (m_gameName == "lamachin" || m_gameName == "dayto2pe") {
|
||||
if (m_gameName == "dayto2pe"||
|
||||
m_gameName == "lamachin"||
|
||||
m_gameName == "von2" ||
|
||||
m_gameName == "von254g" ||
|
||||
m_gameName == "von2a") {
|
||||
vp->sunClamp = false;
|
||||
}
|
||||
else {
|
||||
|
@ -1178,33 +1183,29 @@ void CNew3D::CacheModel(Model *m, const UINT32 *data)
|
|||
p.v[j].pos[0] = (((INT32)ix) >> 8) * m_vertexFactor;
|
||||
p.v[j].pos[1] = (((INT32)iy) >> 8) * m_vertexFactor;
|
||||
p.v[j].pos[2] = (((INT32)iz) >> 8) * m_vertexFactor;
|
||||
p.v[j].pos[3] = 1.0f;
|
||||
|
||||
// Per vertex normals
|
||||
if (ph.SmoothShading()) {
|
||||
p.v[j].normal[0] = (INT8)(ix & 0xFF) / 128.f;
|
||||
p.v[j].normal[1] = (INT8)(iy & 0xFF) / 128.f;
|
||||
p.v[j].normal[2] = (INT8)(iz & 0xFF) / 128.f;
|
||||
p.v[j].normal[0] = BYTE_TO_FLOAT((INT8)(ix & 0xFF));
|
||||
p.v[j].normal[1] = BYTE_TO_FLOAT((INT8)(iy & 0xFF));
|
||||
p.v[j].normal[2] = BYTE_TO_FLOAT((INT8)(iz & 0xFF));
|
||||
}
|
||||
|
||||
if (ph.FixedShading() && ph.TexEnabled() && !ph.SmoothShading()) { // fixed shading seems to be disabled if actual normals are set
|
||||
|
||||
//==========
|
||||
UINT8 shade;
|
||||
float shade;
|
||||
//==========
|
||||
|
||||
if (m_step <= 0x15) {
|
||||
shade = ((ix & 0x7F) * 255) / 127; // this matches the sdk (values are from 0-127 only) and the intensity is clamped to to 0-1
|
||||
if (ph.SpecularEnabled()) {
|
||||
shade = (ix & 0xFF) / 255.f; // Star wars is the only game to use unsigned fixed shaded values. It's also the only game to set the specular flag on these polys
|
||||
}
|
||||
else {
|
||||
if (ph.SpecularEnabled()) {
|
||||
shade = ix & 0xFF; // Star wars is the only game to use unsigned fixed shaded values. It's also the only game to set the specular flag on these polys
|
||||
}
|
||||
else {
|
||||
shade = (ix + 128) & 0xFF; // Step 2+ uses signed or unsigned values for lighting 0-255. Todo finish this logic
|
||||
}
|
||||
shade = BYTE_TO_FLOAT((INT8)(ix & 0xFF));
|
||||
}
|
||||
|
||||
p.v[j].fixedShade = shade; // hardware doesn't really have per vertex colours, only per poly
|
||||
|
||||
p.v[j].fixedShade = shade;
|
||||
}
|
||||
|
||||
float texU, texV = 0;
|
||||
|
@ -1606,23 +1607,11 @@ void CNew3D::ClipModel(const Model *m)
|
|||
|
||||
//==================================
|
||||
Poly& poly = (*polys)[start + i];
|
||||
float in[4], out[4];
|
||||
//==================================
|
||||
|
||||
memcpy(in, poly.p1.pos, sizeof(float) * 3);
|
||||
in[3] = 1;
|
||||
MultVec(m->modelMat, in, out);
|
||||
memcpy(clipPoly.list[0].pos, out, sizeof(float) * 3);
|
||||
|
||||
memcpy(in, poly.p2.pos, sizeof(float) * 3);
|
||||
in[3] = 1;
|
||||
MultVec(m->modelMat, in, out);
|
||||
memcpy(clipPoly.list[1].pos, out, sizeof(float) * 3);
|
||||
|
||||
memcpy(in, poly.p3.pos, sizeof(float) * 3);
|
||||
in[3] = 1;
|
||||
MultVec(m->modelMat, in, out);
|
||||
memcpy(clipPoly.list[2].pos, out, sizeof(float) * 3);
|
||||
MultVec(m->modelMat, poly.p1.pos, clipPoly.list[0].pos);
|
||||
MultVec(m->modelMat, poly.p2.pos, clipPoly.list[1].pos);
|
||||
MultVec(m->modelMat, poly.p3.pos, clipPoly.list[2].pos);
|
||||
|
||||
clipPoly.count = 3;
|
||||
|
||||
|
|
|
@ -12,14 +12,9 @@ uniform float fogIntensity;
|
|||
uniform float fogDensity;
|
||||
uniform float fogStart;
|
||||
uniform float modelScale;
|
||||
uniform int hardwareStep;
|
||||
uniform vec3 lighting[2]; // also used in fragment shader
|
||||
uniform bool lightEnabled; // also used in fragment shader
|
||||
uniform bool fixedShading; // also used in fragment shader
|
||||
uniform bool sunClamp; // also used in fragment shader
|
||||
|
||||
// attributes
|
||||
attribute vec3 inVertex;
|
||||
attribute vec4 inVertex;
|
||||
attribute vec3 inNormal;
|
||||
attribute vec2 inTexCoord;
|
||||
attribute vec4 inColour;
|
||||
|
@ -31,39 +26,19 @@ varying vec3 fsViewVertex;
|
|||
varying vec3 fsViewNormal; // per vertex normal vector
|
||||
varying vec2 fsTexCoord;
|
||||
varying vec4 fsColor;
|
||||
|
||||
vec4 GetVertexColour()
|
||||
{
|
||||
vec4 polyColour = inColour;
|
||||
|
||||
if(fixedShading) {
|
||||
|
||||
float lightAmbient = lighting[1].y;
|
||||
if(!sunClamp) {
|
||||
lightAmbient = 0; // guess work here. La machine guns is the only game to use this light model. Black is black in this game, it's not effected by ambient
|
||||
}
|
||||
|
||||
if(lightEnabled) {
|
||||
polyColour.rgb *= (inFixedShade + lightAmbient); // per vertex brightness + ambient
|
||||
}
|
||||
else {
|
||||
polyColour.rgb += lightAmbient; // this is similar to above but basically a flat shaded version. So poly colour + ambient
|
||||
}
|
||||
}
|
||||
|
||||
return polyColour;
|
||||
}
|
||||
varying float fsFixedShade;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
fsViewVertex = vec3(gl_ModelViewMatrix * vec4(inVertex,1.0));
|
||||
fsViewVertex = vec3(gl_ModelViewMatrix * inVertex);
|
||||
fsViewNormal = (mat3(gl_ModelViewMatrix) * inNormal) / modelScale;
|
||||
float z = length(fsViewVertex);
|
||||
fsFogFactor = fogIntensity * clamp(fogStart + z * fogDensity, 0.0, 1.0);
|
||||
|
||||
fsColor = GetVertexColour();
|
||||
fsColor = inColour;
|
||||
fsTexCoord = inTexCoord;
|
||||
gl_Position = gl_ModelViewProjectionMatrix * vec4(inVertex,1.0);
|
||||
fsFixedShade = inFixedShade;
|
||||
gl_Position = gl_ModelViewProjectionMatrix * inVertex;
|
||||
}
|
||||
)glsl";
|
||||
|
||||
|
@ -99,6 +74,7 @@ uniform float shininess; // specular shininess
|
|||
uniform float fogAttenuation;
|
||||
uniform float fogAmbient;
|
||||
uniform bool fixedShading;
|
||||
uniform int hardwareStep;
|
||||
|
||||
//interpolated inputs from vertex shader
|
||||
varying float fsFogFactor;
|
||||
|
@ -106,6 +82,7 @@ varying vec3 fsViewVertex;
|
|||
varying vec3 fsViewNormal; // per vertex normal vector
|
||||
varying vec4 fsColor;
|
||||
varying vec2 fsTexCoord;
|
||||
varying float fsFixedShade;
|
||||
|
||||
vec4 GetTextureValue()
|
||||
{
|
||||
|
@ -134,6 +111,17 @@ vec4 GetTextureValue()
|
|||
return tex1Data;
|
||||
}
|
||||
|
||||
void Step15Lighting(inout vec4 colour)
|
||||
{
|
||||
// on step 1.5 these polys seem to be effected by vpAmbient
|
||||
// logic is not completely understood
|
||||
if(hardwareStep==0x15) {
|
||||
if(!lightEnabled && fixedShading) {
|
||||
colour.rgb += lighting[1].y; // + vpAmbient
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 tex1Data;
|
||||
|
@ -149,9 +137,10 @@ void main()
|
|||
}
|
||||
|
||||
colData = fsColor;
|
||||
Step15Lighting(colData); // no-op for step 2.0
|
||||
finalData = tex1Data * colData;
|
||||
|
||||
if (finalData.a < (1.0/16.0)) { // basically chuck out any totally transparent pixels value = 1/16 the smallest transparency level h/w supports
|
||||
if (finalData.a < (1.0/16.0)) { // basically chuck out any totally transparent pixels value = 1/16 the smallest transparency level h/w supports
|
||||
discard;
|
||||
}
|
||||
|
||||
|
@ -161,7 +150,7 @@ void main()
|
|||
ellipse = 1.0 - ellipse; // invert
|
||||
ellipse = max(0.0, ellipse); // clamp
|
||||
|
||||
if (lightEnabled && !fixedShading) {
|
||||
if (lightEnabled) {
|
||||
vec3 lightIntensity;
|
||||
vec3 sunVector; // sun lighting vector (as reflecting away from vertex)
|
||||
float sunFactor; // sun light projection along vertex normal (0.0 to 1.0)
|
||||
|
@ -170,7 +159,12 @@ void main()
|
|||
sunVector = lighting[0];
|
||||
|
||||
// Compute diffuse factor for sunlight
|
||||
sunFactor = dot(sunVector, fsViewNormal);
|
||||
if(fixedShading) {
|
||||
sunFactor = fsFixedShade;
|
||||
}
|
||||
else {
|
||||
sunFactor = dot(sunVector, fsViewNormal);
|
||||
}
|
||||
|
||||
// Clamp ceil, fix for upscaled models without "modelScale" defined
|
||||
sunFactor = clamp(sunFactor,-1.0,1.0);
|
||||
|
@ -208,7 +202,8 @@ void main()
|
|||
|
||||
finalData.rgb *= lightIntensity;
|
||||
|
||||
if (specularEnabled) {
|
||||
// for now assume fixed shading doesn't work with specular
|
||||
if (specularEnabled && !fixedShading) {
|
||||
|
||||
float exponent, NdotL, specularFactor;
|
||||
vec4 biasIndex, expIndex, multIndex;
|
||||
|
|
Loading…
Reference in a new issue