Add highlights to software rendering (#218)

This commit is contained in:
Anders Jenbo 2025-06-02 04:14:40 +02:00 committed by GitHub
parent 5375336b5a
commit f08aec7438
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -164,51 +164,70 @@ void Direct3DRMSoftwareRenderer::BlendPixel(Uint8* pixelAddr, Uint8 r, Uint8 g,
SDL_Color Direct3DRMSoftwareRenderer::ApplyLighting(const PositionColorVertex& vertex) SDL_Color Direct3DRMSoftwareRenderer::ApplyLighting(const PositionColorVertex& vertex)
{ {
float r = 0, g = 0, b = 0; FColor specular = {0, 0, 0, 0};
for (const SceneLight& light : m_lights) { FColor diffuse = {0, 0, 0, 0};
if (light.positional == 0.f && light.directional == 0.f) {
// Position and normal
D3DVECTOR position = {vertex.x, vertex.y, vertex.z};
D3DVECTOR normal = {vertex.nx, vertex.ny, vertex.nz};
float normLen = std::sqrt(normal.x * normal.x + normal.y * normal.y + normal.z * normal.z);
if (normLen == 0.0f) {
return {vertex.r, vertex.g, vertex.b, vertex.a};
}
normal.x /= normLen;
normal.y /= normLen;
normal.z /= normLen;
for (const auto& light : m_lights) {
FColor lightColor = light.color;
if (light.positional == 0.0f && light.directional == 0.0f) {
// Ambient light // Ambient light
r += light.color.r; diffuse.r += lightColor.r;
g += light.color.g; diffuse.g += lightColor.g;
b += light.color.b; diffuse.b += lightColor.b;
continue;
} }
else if (light.directional == 1.f) {
// Directional // TODO lightVec only has to be calculated once per frame for directional lights
D3DVECTOR L = light.direction; D3DVECTOR lightVec;
float Llen = std::sqrt(L.x * L.x + L.y * L.y + L.z * L.z); if (light.directional == 1.0f) {
if (Llen > 0.f) { lightVec = {-light.direction.x, -light.direction.y, -light.direction.z};
L.x /= Llen;
L.y /= Llen;
L.z /= Llen;
float ndotl = std::max(0.0f, -(vertex.nx * L.x + vertex.ny * L.y + vertex.nz * L.z));
r += light.color.r * ndotl;
g += light.color.g * ndotl;
b += light.color.b * ndotl;
}
} }
else if (light.positional == 1.f) { else if (light.positional == 1.0f) {
// Point lightVec = {light.position.x - position.x, light.position.y - position.y, light.position.z - position.z};
D3DVECTOR L = {light.position.x - vertex.x, light.position.y - vertex.y, light.position.z - vertex.z}; }
float Llen = std::sqrt(L.x * L.x + L.y * L.y + L.z * L.z);
if (Llen > 0.f) { float len = std::sqrt(lightVec.x * lightVec.x + lightVec.y * lightVec.y + lightVec.z * lightVec.z);
L.x /= Llen; if (len == 0.0f) {
L.y /= Llen; continue;
L.z /= Llen; }
float ndotl = std::max(0.0f, vertex.nx * L.x + vertex.ny * L.y + vertex.nz * L.z); lightVec.x /= len;
r += light.color.r * ndotl; lightVec.y /= len;
g += light.color.g * ndotl; lightVec.z /= len;
b += light.color.b * ndotl;
float dotNL = normal.x * lightVec.x + normal.y * lightVec.y + normal.z * lightVec.z;
if (dotNL > 0.0f) {
// Diffuse contribution
diffuse.r += dotNL * lightColor.r;
diffuse.g += dotNL * lightColor.g;
diffuse.b += dotNL * lightColor.b;
if (vertex.shininess != 0.0f) {
// Using dotNL ignores view angle, but this matches DirectX 5 behavior.
float spec = std::pow(dotNL, vertex.shininess);
specular.r += spec * lightColor.r;
specular.g += spec * lightColor.g;
specular.b += spec * lightColor.b;
} }
} }
} }
r = std::min(1.0f, r);
g = std::min(1.0f, g);
b = std::min(1.0f, b);
return { return SDL_Color{
static_cast<Uint8>(vertex.r * r), static_cast<Uint8>(std::min(255.0f, diffuse.r * vertex.r + specular.r * 255.0f)),
static_cast<Uint8>(vertex.g * g), static_cast<Uint8>(std::min(255.0f, diffuse.g * vertex.g + specular.g * 255.0f)),
static_cast<Uint8>(vertex.b * b), static_cast<Uint8>(std::min(255.0f, diffuse.b * vertex.b + specular.b * 255.0f)),
vertex.a vertex.a
}; };
} }