We were force normalising the result of matrix * normal, which looked correct in most cases. But this didn't preserve the scaling of the matrix, or the scaling of the model normals which resulted in many over bright areas. On it's own this generally worked, but games like Star Wars looked quite broken. Harry correctly figured out if you scale these normals by the scaling value that is sometimes present in the culling nodes the lighting looks correct. Still more work to do to correctly figure out the model3's lighting model.

This commit is contained in:
Ian Curtis 2017-07-29 16:30:30 +00:00
parent a9b49c1676
commit 9aa3f13777
5 changed files with 38 additions and 10 deletions

View file

@ -8,6 +8,7 @@ NodeAttributes::NodeAttributes()
currentTexOffsetY = 0;
currentPage = 0;
currentClipStatus = Clip::INTERCEPT;
currentModelScale = 1.0f;
}
bool NodeAttributes::Push()
@ -25,8 +26,9 @@ bool NodeAttributes::Push()
na.texOffsetX = currentTexOffsetX;
na.texOffsetY = currentTexOffsetY;
na.clip = currentClipStatus;
na.modelScale = currentModelScale;
m_vecAttribs.push_back(na);
m_vecAttribs.emplace_back(na);
return true;
}
@ -37,12 +39,13 @@ bool NodeAttributes::Pop()
return false; // check for underflow
}
auto last = &m_vecAttribs.back();
auto &last = m_vecAttribs.back();
currentPage = last->page;
currentTexOffsetX = last->texOffsetX;
currentTexOffsetY = last->texOffsetY;
currentClipStatus = last->clip;
currentPage = last.page;
currentTexOffsetX = last.texOffsetX;
currentTexOffsetY = last.texOffsetY;
currentClipStatus = last.clip;
currentModelScale = last.modelScale;
m_vecAttribs.pop_back();
@ -60,6 +63,7 @@ void NodeAttributes::Reset()
currentTexOffsetX = 0;
currentTexOffsetY = 0;
currentClipStatus = Clip::INTERCEPT;
currentModelScale = 1.0f;
m_vecAttribs.clear();
}

View file

@ -118,6 +118,9 @@ struct Model
//matrices
float modelMat[16];
float determinant; // we check if the determinant of the matrix is negative, if it is, the matrix will swap the axis order
//model scale step 1.5+
float scale = 1.0f;
};
struct Viewport
@ -166,6 +169,7 @@ public:
int currentTexOffsetY;
int currentPage;
Clip currentClipStatus;
float currentModelScale;
private:
@ -175,6 +179,7 @@ private:
int texOffsetY;
int page;
Clip clip;
float modelScale;
};
std::vector<NodeAttribs> m_vecAttribs;
};

View file

@ -409,6 +409,7 @@ bool CNew3D::DrawModel(UINT32 modelAddr)
m->textureOffsetX = m_nodeAttribs.currentTexOffsetX;
m->textureOffsetY = m_nodeAttribs.currentTexOffsetY;
m->page = m_nodeAttribs.currentPage;
m->scale = m_nodeAttribs.currentModelScale;
if (!cached) {
CacheModel(m, modelAddress);
@ -463,6 +464,12 @@ void CNew3D::DescendCullingNode(UINT32 addr)
m_nodeAttribs.Push(); // save current attribs
if (!m_offset) { // Step 1.5+
float modelScale = *(float *)&node[1];
if (modelScale) {
m_nodeAttribs.currentModelScale = modelScale;
}
// apply texture offsets, else retain current ones
if ((node[0x02] & 0x8000)) {
int tx = 32 * ((node[0x02] >> 7) & 0x3F);
@ -477,7 +484,7 @@ void CNew3D::DescendCullingNode(UINT32 addr)
m_modelMat.PushMatrix();
// apply translation vector
if ((node[0x00] & 0x10)) {
if (node[0x00] & 0x10) {
float x = *(float *)&node[0x04 - m_offset];
float y = *(float *)&node[0x05 - m_offset];
float z = *(float *)&node[0x06 - m_offset];

View file

@ -9,6 +9,7 @@ static const char *vertexShaderR3D = R"glsl(
uniform float fogIntensity;
uniform float fogDensity;
uniform float fogStart;
uniform float modelScale;
//outputs to fragment shader
varying float fsFogFactor;
@ -19,7 +20,7 @@ varying vec4 fsColor;
void main(void)
{
fsViewVertex = vec3(gl_ModelViewMatrix * gl_Vertex);
fsViewNormal = normalize(gl_NormalMatrix * gl_Normal);
fsViewNormal = (mat3(gl_ModelViewMatrix) * gl_Normal) / modelScale;
float z = length(fsViewVertex);
fsFogFactor = fogIntensity * clamp(fogStart + z * fogDensity, 0.0, 1.0);
@ -193,6 +194,7 @@ void R3DShader::Start()
m_lightEnabled = false;
m_layered = false;
m_textureInverted = false;
m_modelScale = 1.0f;
m_baseTexSize[0] = 0;
m_baseTexSize[1] = 0;
@ -255,6 +257,7 @@ bool R3DShader::LoadShader(const char* vertexShader, const char* fragmentShader)
m_locSpotRange = glGetUniformLocation(m_shaderProgram, "spotRange");
m_locSpotColor = glGetUniformLocation(m_shaderProgram, "spotColor");
m_locSpotFogColor = glGetUniformLocation(m_shaderProgram, "spotFogColor");
m_locModelScale = glGetUniformLocation(m_shaderProgram, "modelScale");
return success;
}
@ -414,6 +417,11 @@ void R3DShader::SetModelStates(const Model* model)
}
}
if (m_dirtyModel || model->scale != m_modelScale) {
glUniform1f(m_locModelScale, model->scale);
m_modelScale = model->scale;
}
m_matDet = test;
m_dirtyModel = false;
}

View file

@ -53,7 +53,8 @@ private:
// cached model values
enum class MatDet { notset, negative, positive, zero };
MatDet m_matDet;
MatDet m_matDet;
float m_modelScale;
// are our cache values dirty
bool m_dirtyMesh;
@ -67,7 +68,7 @@ private:
GLint m_locFogAttenuation;
GLint m_locFogAmbient;
// lighting
// lighting / other
GLint m_locLighting;
GLint m_locLightEnable;
GLint m_locLightClamp;
@ -77,6 +78,9 @@ private:
GLint m_locSpotRange;
GLint m_locSpotColor;
GLint m_locSpotFogColor;
// model uniforms
GLint m_locModelScale;
};
} // New3D