GLdc/GL/lighting.c

645 lines
20 KiB
C
Raw Normal View History

#include <stdio.h>
#include <string.h>
2020-02-17 10:12:15 +00:00
#include <math.h>
2020-02-17 20:49:40 +00:00
#include <limits.h>
2021-04-09 15:24:47 +00:00
2018-05-12 13:05:54 +00:00
#include "private.h"
2021-04-09 15:24:47 +00:00
#include "platform.h"
2018-05-12 13:05:54 +00:00
2020-02-19 09:30:26 +00:00
#define _MIN(x, y) (x < y) ? x : y
/* Lighting will not be calculated if the attenuation
* multiplier ends up less than this value */
2020-05-22 06:32:02 +00:00
#define ATTENUATION_THRESHOLD 100.0f
2023-03-07 10:19:09 +00:00
void _glPrecalcLightingValues(GLuint mask) {
/* Pre-calculate lighting values */
GLshort i;
2018-05-12 13:05:54 +00:00
2023-03-07 10:19:09 +00:00
Material* material = _glActiveMaterial();
2020-05-07 19:58:24 +00:00
2023-03-07 10:19:09 +00:00
if(mask & AMBIENT_MASK) {
for(i = 0; i < MAX_GLDC_LIGHTS; ++i) {
LightSource* light = _glLightAt(i);
2020-05-07 19:58:24 +00:00
2023-03-07 10:19:09 +00:00
light->ambientMaterial[0] = light->ambient[0] * material->ambient[0];
light->ambientMaterial[1] = light->ambient[1] * material->ambient[1];
light->ambientMaterial[2] = light->ambient[2] * material->ambient[2];
light->ambientMaterial[3] = light->ambient[3] * material->ambient[3];
2018-05-12 13:05:54 +00:00
2023-03-07 10:19:09 +00:00
}
}
2020-05-07 19:58:24 +00:00
2023-03-07 10:19:09 +00:00
if(mask & DIFFUSE_MASK) {
for(i = 0; i < MAX_GLDC_LIGHTS; ++i) {
LightSource* light = _glLightAt(i);
2023-03-07 10:19:09 +00:00
light->diffuseMaterial[0] = light->diffuse[0] * material->diffuse[0];
light->diffuseMaterial[1] = light->diffuse[1] * material->diffuse[1];
light->diffuseMaterial[2] = light->diffuse[2] * material->diffuse[2];
light->diffuseMaterial[3] = light->diffuse[3] * material->diffuse[3];
}
}
if(mask & SPECULAR_MASK) {
for(i = 0; i < MAX_GLDC_LIGHTS; ++i) {
LightSource* light = _glLightAt(i);
light->specularMaterial[0] = light->specular[0] * material->specular[0];
light->specularMaterial[1] = light->specular[1] * material->specular[1];
light->specularMaterial[2] = light->specular[2] * material->specular[2];
light->specularMaterial[3] = light->specular[3] * material->specular[3];
}
}
2023-03-07 10:19:09 +00:00
/* If ambient or emission are updated, we need to update
* the base colour. */
if((mask & AMBIENT_MASK) || (mask & EMISSION_MASK) || (mask & SCENE_AMBIENT_MASK)) {
GLfloat* scene_ambient = _glLightModelSceneAmbient();
material->baseColour[0] = MATH_fmac(scene_ambient[0], material->ambient[0], material->emissive[0]);
material->baseColour[1] = MATH_fmac(scene_ambient[1], material->ambient[1], material->emissive[1]);
material->baseColour[2] = MATH_fmac(scene_ambient[2], material->ambient[2], material->emissive[2]);
material->baseColour[3] = MATH_fmac(scene_ambient[3], material->ambient[3], material->emissive[3]);
}
}
2018-09-15 10:45:38 +00:00
void _glInitLights() {
2023-03-07 10:19:09 +00:00
Material* material = _glActiveMaterial();
2018-05-12 13:05:54 +00:00
static GLfloat ONE [] = {1.0f, 1.0f, 1.0f, 1.0f};
static GLfloat ZERO [] = {0.0f, 0.0f, 0.0f, 1.0f};
static GLfloat PARTIAL [] = {0.2f, 0.2f, 0.2f, 1.0f};
static GLfloat MOSTLY [] = {0.8f, 0.8f, 0.8f, 1.0f};
2023-03-07 10:19:09 +00:00
memcpy(material->ambient, PARTIAL, sizeof(GLfloat) * 4);
memcpy(material->diffuse, MOSTLY, sizeof(GLfloat) * 4);
memcpy(material->specular, ZERO, sizeof(GLfloat) * 4);
memcpy(material->emissive, ZERO, sizeof(GLfloat) * 4);
material->exponent = 0.0f;
2018-05-12 13:05:54 +00:00
2018-05-14 16:10:53 +00:00
GLubyte i;
for(i = 0; i < MAX_GLDC_LIGHTS; ++i) {
2023-03-07 10:19:09 +00:00
LightSource* light = _glLightAt(i);
memcpy(light->ambient, ZERO, sizeof(GLfloat) * 4);
memcpy(light->diffuse, ONE, sizeof(GLfloat) * 4);
memcpy(light->specular, ONE, sizeof(GLfloat) * 4);
2018-05-12 13:05:54 +00:00
if(i > 0) {
2023-03-07 10:19:09 +00:00
memcpy(light->diffuse, ZERO, sizeof(GLfloat) * 4);
memcpy(light->specular, ZERO, sizeof(GLfloat) * 4);
2018-05-12 13:05:54 +00:00
}
2023-03-07 10:19:09 +00:00
light->position[0] = light->position[1] = light->position[3] = 0.0f;
light->position[2] = 1.0f;
light->isDirectional = GL_TRUE;
light->isEnabled = GL_FALSE;
2018-05-12 13:05:54 +00:00
2023-03-07 10:19:09 +00:00
light->spot_direction[0] = light->spot_direction[1] = 0.0f;
light->spot_direction[2] = -1.0f;
2018-05-12 13:05:54 +00:00
2023-03-07 10:19:09 +00:00
light->spot_exponent = 0.0f;
light->spot_cutoff = 180.0f;
2018-05-12 13:05:54 +00:00
2023-03-07 10:19:09 +00:00
light->constant_attenuation = 1.0f;
light->linear_attenuation = 0.0f;
light->quadratic_attenuation = 0.0f;
2018-05-12 13:05:54 +00:00
}
2020-05-07 19:58:24 +00:00
_glPrecalcLightingValues(~0);
2023-03-07 10:19:09 +00:00
_glRecalcEnabledLights();
}
2018-05-12 13:05:54 +00:00
void APIENTRY glLightModelf(GLenum pname, const GLfloat param) {
glLightModelfv(pname, &param);
}
void APIENTRY glLightModeli(GLenum pname, const GLint param) {
glLightModeliv(pname, &param);
}
void APIENTRY glLightModelfv(GLenum pname, const GLfloat *params) {
switch(pname) {
2020-05-07 19:58:24 +00:00
case GL_LIGHT_MODEL_AMBIENT: {
2023-03-23 20:01:41 +00:00
if(memcmp(_glGetLightModelSceneAmbient(), params, sizeof(float) * 4) != 0) {
_glSetLightModelSceneAmbient(params);
_glPrecalcLightingValues(SCENE_AMBIENT_MASK);
}
2020-05-07 19:58:24 +00:00
} break;
2018-05-12 13:05:54 +00:00
case GL_LIGHT_MODEL_LOCAL_VIEWER:
2023-03-07 10:19:09 +00:00
_glSetLightModelViewerInEyeCoordinates((*params) ? GL_TRUE : GL_FALSE);
2018-05-12 13:05:54 +00:00
break;
case GL_LIGHT_MODEL_TWO_SIDE:
/* Not implemented */
default:
_glKosThrowError(GL_INVALID_ENUM, __func__);
}
}
void APIENTRY glLightModeliv(GLenum pname, const GLint* params) {
switch(pname) {
case GL_LIGHT_MODEL_COLOR_CONTROL:
2023-03-07 10:19:09 +00:00
_glSetLightModelColorControl(*params);
2018-05-12 13:05:54 +00:00
break;
case GL_LIGHT_MODEL_LOCAL_VIEWER:
2023-03-07 10:19:09 +00:00
_glSetLightModelViewerInEyeCoordinates((*params) ? GL_TRUE : GL_FALSE);
2018-05-12 13:05:54 +00:00
break;
default:
_glKosThrowError(GL_INVALID_ENUM, __func__);
}
}
void APIENTRY glLightfv(GLenum light, GLenum pname, const GLfloat *params) {
GLubyte idx = light & 0xF;
if(idx >= MAX_GLDC_LIGHTS) {
2023-03-07 10:19:09 +00:00
_glKosThrowError(GL_INVALID_VALUE, __func__);
2018-05-12 13:05:54 +00:00
return;
}
2020-05-07 19:58:24 +00:00
GLuint mask = (pname == GL_AMBIENT) ? AMBIENT_MASK :
(pname == GL_DIFFUSE) ? DIFFUSE_MASK :
(pname == GL_SPECULAR) ? SPECULAR_MASK : 0;
2023-03-07 10:19:09 +00:00
LightSource* l = _glLightAt(idx);
2023-03-23 20:01:41 +00:00
GLboolean rebuild = GL_FALSE;
2018-05-12 13:05:54 +00:00
switch(pname) {
case GL_AMBIENT:
2023-03-23 20:01:41 +00:00
rebuild = memcmp(l->ambient, params, sizeof(GLfloat) * 4) != 0;
if(rebuild) {
memcpy(l->ambient, params, sizeof(GLfloat) * 4);
}
2018-05-12 13:05:54 +00:00
break;
case GL_DIFFUSE:
2023-03-23 20:01:41 +00:00
rebuild = memcmp(l->diffuse, params, sizeof(GLfloat) * 4) != 0;
if(rebuild) {
memcpy(l->diffuse, params, sizeof(GLfloat) * 4);
}
2018-05-12 13:05:54 +00:00
break;
case GL_SPECULAR:
2023-03-23 20:01:41 +00:00
rebuild = memcmp(l->specular, params, sizeof(GLfloat) * 4) != 0;
if(rebuild) {
memcpy(l->specular, params, sizeof(GLfloat) * 4);
}
2018-05-12 13:05:54 +00:00
break;
2018-08-03 13:08:01 +00:00
case GL_POSITION: {
2023-03-07 10:19:09 +00:00
memcpy(l->position, params, sizeof(GLfloat) * 4);
2018-08-03 13:08:01 +00:00
2023-03-07 10:19:09 +00:00
l->isDirectional = params[3] == 0.0f;
2020-05-07 19:58:24 +00:00
2023-03-07 10:19:09 +00:00
if(l->isDirectional) {
2018-08-28 08:24:51 +00:00
//FIXME: Do we need to rotate directional lights?
} else {
2023-03-23 20:01:41 +00:00
_glMatrixLoadModelView();
2023-03-07 10:19:09 +00:00
TransformVec3(l->position);
2018-08-28 08:24:51 +00:00
}
2018-08-03 13:08:01 +00:00
}
2018-05-12 13:05:54 +00:00
break;
2018-08-28 14:55:50 +00:00
case GL_SPOT_DIRECTION: {
2023-03-07 10:19:09 +00:00
l->spot_direction[0] = params[0];
l->spot_direction[1] = params[1];
l->spot_direction[2] = params[2];
2018-08-28 14:55:50 +00:00
} break;
case GL_CONSTANT_ATTENUATION:
2018-05-13 08:34:44 +00:00
case GL_LINEAR_ATTENUATION:
case GL_QUADRATIC_ATTENUATION:
2018-05-12 13:05:54 +00:00
case GL_SPOT_CUTOFF:
case GL_SPOT_EXPONENT:
2018-05-13 08:34:44 +00:00
glLightf(light, pname, *params);
2018-08-28 14:55:50 +00:00
break;
2018-05-12 13:05:54 +00:00
default:
_glKosThrowError(GL_INVALID_ENUM, __func__);
return;
2018-05-12 13:05:54 +00:00
}
2020-05-07 19:58:24 +00:00
2023-03-23 20:01:41 +00:00
if(rebuild) {
_glPrecalcLightingValues(mask);
}
2018-05-12 13:05:54 +00:00
}
void APIENTRY glLightf(GLenum light, GLenum pname, GLfloat param) {
2018-05-13 08:34:44 +00:00
GLubyte idx = light & 0xF;
2018-05-12 13:05:54 +00:00
if(idx >= MAX_GLDC_LIGHTS) {
2023-03-07 10:19:09 +00:00
_glKosThrowError(GL_INVALID_VALUE, __func__);
2018-05-13 08:34:44 +00:00
return;
}
2023-03-07 10:19:09 +00:00
LightSource* l = _glLightAt(idx);
2018-05-13 08:34:44 +00:00
switch(pname) {
case GL_CONSTANT_ATTENUATION:
2023-03-07 10:19:09 +00:00
l->constant_attenuation = param;
2018-05-13 08:34:44 +00:00
break;
case GL_LINEAR_ATTENUATION:
2023-03-07 10:19:09 +00:00
l->linear_attenuation = param;
2018-05-13 08:34:44 +00:00
break;
case GL_QUADRATIC_ATTENUATION:
2023-03-07 10:19:09 +00:00
l->quadratic_attenuation = param;
2018-05-13 08:34:44 +00:00
break;
case GL_SPOT_EXPONENT:
2023-03-07 10:19:09 +00:00
l->spot_exponent = param;
2018-08-28 14:55:50 +00:00
break;
2018-05-13 08:34:44 +00:00
case GL_SPOT_CUTOFF:
2023-03-07 10:19:09 +00:00
l->spot_cutoff = param;
2018-08-28 14:55:50 +00:00
break;
2018-05-13 08:34:44 +00:00
default:
_glKosThrowError(GL_INVALID_ENUM, __func__);
}
2018-05-12 13:05:54 +00:00
}
2018-05-13 18:48:55 +00:00
void APIENTRY glMaterialf(GLenum face, GLenum pname, const GLfloat param) {
if(face == GL_BACK || pname != GL_SHININESS) {
_glKosThrowError(GL_INVALID_ENUM, __func__);
return;
}
2018-05-12 13:05:54 +00:00
2023-03-07 10:19:09 +00:00
_glActiveMaterial()->exponent = _MIN(param, 128); /* 128 is the max according to the GL spec */
2018-05-12 13:05:54 +00:00
}
2018-05-13 18:48:55 +00:00
void APIENTRY glMateriali(GLenum face, GLenum pname, const GLint param) {
glMaterialf(face, pname, param);
2018-05-12 13:05:54 +00:00
}
void APIENTRY glMaterialfv(GLenum face, GLenum pname, const GLfloat *params) {
2018-05-13 18:48:55 +00:00
if(face == GL_BACK) {
_glKosThrowError(GL_INVALID_ENUM, __func__);
return;
}
2018-05-12 13:05:54 +00:00
2023-03-07 10:19:09 +00:00
Material* material = _glActiveMaterial();
2023-03-23 20:01:41 +00:00
GLboolean rebuild = GL_FALSE;
2018-05-13 18:48:55 +00:00
switch(pname) {
2020-05-07 19:58:24 +00:00
case GL_SHININESS:
glMaterialf(face, pname, *params);
2023-03-23 20:01:41 +00:00
rebuild = GL_TRUE;
2020-05-07 19:58:24 +00:00
break;
2023-03-23 20:01:41 +00:00
case GL_AMBIENT: {
if(memcmp(material->ambient, params, sizeof(float) * 4) != 0) {
vec4cpy(material->ambient, params);
rebuild = GL_TRUE;
}
} break;
2018-05-13 18:48:55 +00:00
case GL_DIFFUSE:
2023-03-23 20:01:41 +00:00
if(memcmp(material->diffuse, params, sizeof(float) * 4) != 0) {
vec4cpy(material->diffuse, params);
rebuild = GL_TRUE;
}
2018-05-13 18:48:55 +00:00
break;
case GL_SPECULAR:
2023-03-23 20:01:41 +00:00
if(memcmp(material->specular, params, sizeof(float) * 4) != 0) {
vec4cpy(material->specular, params);
rebuild = GL_TRUE;
}
2018-05-13 18:48:55 +00:00
break;
case GL_EMISSION:
2023-03-23 20:01:41 +00:00
if(memcmp(material->emissive, params, sizeof(float) * 4) != 0) {
vec4cpy(material->emissive, params);
rebuild = GL_TRUE;
}
2018-05-13 18:48:55 +00:00
break;
case GL_AMBIENT_AND_DIFFUSE: {
2023-03-23 20:01:41 +00:00
rebuild = (
memcmp(material->ambient, params, sizeof(float) * 4) != 0 ||
memcmp(material->diffuse, params, sizeof(float) * 4) != 0
);
if(rebuild) {
vec4cpy(material->ambient, params);
vec4cpy(material->diffuse, params);
}
2018-05-13 18:48:55 +00:00
} break;
case GL_COLOR_INDEXES:
default: {
_glKosThrowError(GL_INVALID_ENUM, __func__);
return;
2018-05-13 18:48:55 +00:00
}
}
2020-05-07 19:58:24 +00:00
2023-03-23 20:01:41 +00:00
if(rebuild) {
GLuint updateMask = (pname == GL_AMBIENT) ? AMBIENT_MASK:
(pname == GL_DIFFUSE) ? DIFFUSE_MASK:
(pname == GL_SPECULAR) ? SPECULAR_MASK:
(pname == GL_EMISSION) ? EMISSION_MASK:
(pname == GL_AMBIENT_AND_DIFFUSE) ? AMBIENT_MASK | DIFFUSE_MASK : 0;
2020-05-07 19:58:24 +00:00
2023-03-23 20:01:41 +00:00
_glPrecalcLightingValues(updateMask);
}
2018-05-12 13:05:54 +00:00
}
2018-09-15 10:42:42 +00:00
void APIENTRY glColorMaterial(GLenum face, GLenum mode) {
2018-08-22 08:24:49 +00:00
if(face != GL_FRONT_AND_BACK) {
_glKosThrowError(GL_INVALID_ENUM, __func__);
return;
}
2019-03-13 15:14:09 +00:00
GLint validModes[] = {GL_AMBIENT, GL_DIFFUSE, GL_AMBIENT_AND_DIFFUSE, GL_EMISSION, GL_SPECULAR, 0};
2018-08-22 08:24:49 +00:00
if(_glCheckValidEnum(mode, validModes, __func__) != 0) {
return;
}
2023-03-07 10:19:09 +00:00
GLenum mask = (mode == GL_AMBIENT) ? AMBIENT_MASK:
2020-05-07 19:58:24 +00:00
(mode == GL_DIFFUSE) ? DIFFUSE_MASK:
(mode == GL_AMBIENT_AND_DIFFUSE) ? AMBIENT_MASK | DIFFUSE_MASK:
(mode == GL_EMISSION) ? EMISSION_MASK : SPECULAR_MASK;
2023-03-07 10:19:09 +00:00
_glSetColorMaterialMask(mask);
_glSetColorMaterialMode(mode);
2018-08-22 08:24:49 +00:00
}
2020-05-11 19:34:09 +00:00
GL_FORCE_INLINE void bgra_to_float(const uint8_t* input, GLfloat* output) {
static const float scale = 1.0f / 255.0f;
output[0] = ((float) input[R8IDX]) * scale;
output[1] = ((float) input[G8IDX]) * scale;
output[2] = ((float) input[B8IDX]) * scale;
output[3] = ((float) input[A8IDX]) * scale;
}
2020-05-21 19:14:43 +00:00
void _glUpdateColourMaterialA(const GLubyte* argb) {
2023-03-07 10:19:09 +00:00
Material* material = _glActiveMaterial();
2020-05-21 19:14:43 +00:00
float colour[4];
bgra_to_float(argb, colour);
2023-03-07 10:19:09 +00:00
vec4cpy(material->ambient, colour);
GLenum mask = _glColorMaterialMode();
_glPrecalcLightingValues(mask);
2020-05-21 19:14:43 +00:00
}
2020-05-07 19:58:24 +00:00
2020-05-21 19:14:43 +00:00
void _glUpdateColourMaterialD(const GLubyte* argb) {
2023-03-07 10:19:09 +00:00
Material* material = _glActiveMaterial();
2020-05-11 19:34:09 +00:00
float colour[4];
bgra_to_float(argb, colour);
2023-03-07 10:19:09 +00:00
vec4cpy(material->diffuse, colour);
GLenum mask = _glColorMaterialMode();
_glPrecalcLightingValues(mask);
2020-05-21 19:14:43 +00:00
}
2020-05-11 19:34:09 +00:00
2020-05-21 19:14:43 +00:00
void _glUpdateColourMaterialE(const GLubyte* argb) {
2023-03-07 10:19:09 +00:00
Material* material = _glActiveMaterial();
2020-05-21 19:14:43 +00:00
float colour[4];
bgra_to_float(argb, colour);
2023-03-07 10:19:09 +00:00
vec4cpy(material->emissive, colour);
GLenum mask = _glColorMaterialMode();
_glPrecalcLightingValues(mask);
2020-05-21 19:14:43 +00:00
}
2020-05-07 19:58:24 +00:00
2020-05-21 19:14:43 +00:00
void _glUpdateColourMaterialAD(const GLubyte* argb) {
2023-03-07 10:19:09 +00:00
Material* material = _glActiveMaterial();
2020-05-21 19:14:43 +00:00
float colour[4];
bgra_to_float(argb, colour);
2023-03-07 10:19:09 +00:00
vec4cpy(material->ambient, colour);
vec4cpy(material->diffuse, colour);
GLenum mask = _glColorMaterialMode();
_glPrecalcLightingValues(mask);
2020-05-07 19:58:24 +00:00
}
GL_FORCE_INLINE GLboolean isDiffuseColorMaterial() {
2023-03-07 10:19:09 +00:00
GLenum mode = _glColorMaterialMode();
return (
mode == GL_DIFFUSE ||
mode == GL_AMBIENT_AND_DIFFUSE
);
2018-08-22 08:24:49 +00:00
}
GL_FORCE_INLINE GLboolean isAmbientColorMaterial() {
2023-03-07 10:19:09 +00:00
GLenum mode = _glColorMaterialMode();
return (
mode == GL_AMBIENT ||
mode == GL_AMBIENT_AND_DIFFUSE
);
2018-08-22 08:24:49 +00:00
}
GL_FORCE_INLINE GLboolean isSpecularColorMaterial() {
2023-03-07 10:19:09 +00:00
GLenum mode = _glColorMaterialMode();
return (mode == GL_SPECULAR);
2018-08-22 08:24:49 +00:00
}
2020-02-20 09:44:45 +00:00
/*
* Implementation from here (MIT):
* https://github.com/appleseedhq/appleseed/blob/master/src/appleseed/foundation/math/fastmath.h
*/
GL_FORCE_INLINE float faster_pow2(const float p) {
// Underflow of exponential is common practice in numerical routines, so handle it here.
const float clipp = p < -126.0f ? -126.0f : p;
const union { uint32_t i; float f; } v =
{
(uint32_t) ((1 << 23) * (clipp + 126.94269504f))
};
return v.f;
}
2020-02-20 09:44:45 +00:00
GL_FORCE_INLINE float faster_log2(const float x) {
2022-08-25 20:24:08 +00:00
gl_assert(x >= 0.0f);
2020-02-17 10:12:15 +00:00
2020-02-20 09:44:45 +00:00
const union { float f; uint32_t i; } vx = { x };
const float y = (float) (vx.i) * 1.1920928955078125e-7f;
2020-02-17 20:49:40 +00:00
2020-02-20 09:44:45 +00:00
return y - 126.94269504f;
2020-02-17 19:02:45 +00:00
}
2020-02-20 09:44:45 +00:00
GL_FORCE_INLINE float faster_pow(const float x, const float p) {
return faster_pow2(p * faster_log2(x));
}
2020-02-19 10:45:31 +00:00
GL_FORCE_INLINE void _glLightVertexDirectional(
2020-05-11 19:34:09 +00:00
float* final, uint8_t lid,
2020-05-07 19:58:24 +00:00
float LdotN, float NdotH) {
2020-02-19 10:45:31 +00:00
2023-03-07 10:19:09 +00:00
Material* material = _glActiveMaterial();
LightSource* light = _glLightAt(lid);
float FI = (material->exponent) ?
faster_pow((LdotN != 0.0f) * NdotH, material->exponent) : 1.0f;
2018-08-03 13:08:01 +00:00
2020-05-11 19:34:09 +00:00
#define _PROCESS_COMPONENT(X) \
2023-03-07 10:19:09 +00:00
final[X] += (LdotN * light->diffuseMaterial[X] + light->ambientMaterial[X]) \
+ (FI * light->specularMaterial[X]); \
2020-05-11 19:34:09 +00:00
_PROCESS_COMPONENT(0);
_PROCESS_COMPONENT(1);
_PROCESS_COMPONENT(2);
#undef _PROCESS_COMPONENT
}
2020-02-19 10:45:31 +00:00
GL_FORCE_INLINE void _glLightVertexPoint(
2020-05-11 19:34:09 +00:00
float* final, uint8_t lid,
2020-05-07 19:58:24 +00:00
float LdotN, float NdotH, float att) {
2020-02-19 10:45:31 +00:00
2023-03-07 10:19:09 +00:00
Material* material = _glActiveMaterial();
LightSource* light = _glLightAt(lid);
float FI = (material->exponent) ?
faster_pow((LdotN != 0.0f) * NdotH, material->exponent) : 1.0f;
2020-05-11 19:34:09 +00:00
#define _PROCESS_COMPONENT(X) \
2023-03-07 10:19:09 +00:00
final[X] += ((LdotN * light->diffuseMaterial[X] + light->ambientMaterial[X]) \
+ (FI * light->specularMaterial[X])) * att; \
2020-05-11 19:34:09 +00:00
_PROCESS_COMPONENT(0);
_PROCESS_COMPONENT(1);
_PROCESS_COMPONENT(2);
#undef _PROCESS_COMPONENT
}
2021-04-09 15:24:47 +00:00
void _glPerformLighting(Vertex* vertices, EyeSpaceData* es, const uint32_t count) {
GLubyte i;
GLuint j;
2018-08-22 08:24:49 +00:00
2023-03-07 10:19:09 +00:00
Material* material = _glActiveMaterial();
2019-12-27 10:36:30 +00:00
Vertex* vertex = vertices;
EyeSpaceData* data = es;
2020-02-19 10:45:31 +00:00
2020-05-21 19:14:43 +00:00
/* Calculate the colour material function once */
void (*updateColourMaterial)(const GLubyte*) = NULL;
if(_glIsColorMaterialEnabled()) {
2023-03-07 10:19:09 +00:00
GLenum mode = _glColorMaterialMode();
switch(mode) {
2020-05-21 19:14:43 +00:00
case GL_AMBIENT:
updateColourMaterial = _glUpdateColourMaterialA;
break;
case GL_DIFFUSE:
updateColourMaterial = _glUpdateColourMaterialD;
break;
case GL_EMISSION:
updateColourMaterial = _glUpdateColourMaterialE;
break;
case GL_AMBIENT_AND_DIFFUSE:
updateColourMaterial = _glUpdateColourMaterialAD;
break;
}
}
/* Calculate the ambient lighting and set up colour material */
for(j = 0; j < count; ++j, ++vertex, ++data) {
2020-05-21 19:14:43 +00:00
if(updateColourMaterial) {
updateColourMaterial(vertex->bgra);
}
2019-12-27 10:36:30 +00:00
2020-05-07 19:58:24 +00:00
/* Copy the base colour across */
2023-03-07 10:19:09 +00:00
vec4cpy(data->finalColour, material->baseColour);
}
2023-03-07 10:19:09 +00:00
if(!_glEnabledLightCount()) {
return;
2020-05-21 19:14:43 +00:00
}
2020-05-21 19:14:43 +00:00
vertex = vertices;
data = es;
2020-05-21 19:14:43 +00:00
for(j = 0; j < count; ++j, ++vertex, ++data) {
2020-02-21 14:51:05 +00:00
/* Direction to vertex in eye space */
float Vx = -vertex->xyz[0];
float Vy = -vertex->xyz[1];
float Vz = -vertex->xyz[2];
2021-04-09 15:24:47 +00:00
VEC3_NORMALIZE(Vx, Vy, Vz);
2019-12-27 10:36:30 +00:00
const float Nx = data->n[0];
const float Ny = data->n[1];
const float Nz = data->n[2];
for(i = 0; i < MAX_GLDC_LIGHTS; ++i) {
2023-03-07 10:19:09 +00:00
LightSource* light = _glLightAt(i);
if(!light->isEnabled) {
continue;
}
2019-12-27 10:36:30 +00:00
2023-03-07 10:19:09 +00:00
float Lx = light->position[0] - vertex->xyz[0];
float Ly = light->position[1] - vertex->xyz[1];
float Lz = light->position[2] - vertex->xyz[2];
2020-02-21 14:51:05 +00:00
2023-03-07 10:19:09 +00:00
if(light->isDirectional) {
2020-02-21 14:51:05 +00:00
float Hx = (Lx + 0);
float Hy = (Ly + 0);
float Hz = (Lz + 1);
2018-05-19 08:17:24 +00:00
2021-04-09 15:24:47 +00:00
VEC3_NORMALIZE(Lx, Ly, Lz);
VEC3_NORMALIZE(Hx, Hy, Hz);
2018-08-04 18:34:07 +00:00
2020-05-09 05:33:28 +00:00
float LdotN, NdotH;
2021-04-09 15:24:47 +00:00
VEC3_DOT(
2020-05-09 05:33:28 +00:00
Nx, Ny, Nz, Lx, Ly, Lz, LdotN
);
2019-12-27 10:36:30 +00:00
2021-04-09 15:24:47 +00:00
VEC3_DOT(
2020-05-09 05:33:28 +00:00
Nx, Ny, Nz, Hx, Hy, Hz, NdotH
);
2019-12-27 10:36:30 +00:00
2020-05-07 19:58:24 +00:00
if(LdotN < 0.0f) LdotN = 0.0f;
if(NdotH < 0.0f) NdotH = 0.0f;
_glLightVertexDirectional(
data->finalColour,
2020-05-07 19:58:24 +00:00
i, LdotN, NdotH
);
} else {
float D;
2021-04-09 15:24:47 +00:00
VEC3_LENGTH(Lx, Ly, Lz, D);
2018-08-04 18:34:07 +00:00
float att = (
2023-03-07 10:19:09 +00:00
light->constant_attenuation + (
light->linear_attenuation * D
) + (light->quadratic_attenuation * D * D)
);
2020-05-22 06:32:02 +00:00
/* Anything over the attenuation threshold will
* be a tiny value after inversion (< 0.01f) so
* let's just skip the lighting at that point */
if(att < ATTENUATION_THRESHOLD) {
att = MATH_Fast_Invert(att);
float Hx = (Lx + Vx);
float Hy = (Ly + Vy);
float Hz = (Lz + Vz);
2019-12-27 10:36:30 +00:00
2021-04-09 15:24:47 +00:00
VEC3_NORMALIZE(Lx, Ly, Lz);
VEC3_NORMALIZE(Hx, Hy, Hz);
2020-05-09 05:33:28 +00:00
float LdotN, NdotH;
2021-04-09 15:24:47 +00:00
VEC3_DOT(
2020-05-09 05:33:28 +00:00
Nx, Ny, Nz, Lx, Ly, Lz, LdotN
);
2021-04-09 15:24:47 +00:00
VEC3_DOT(
2020-05-09 05:33:28 +00:00
Nx, Ny, Nz, Hx, Hy, Hz, NdotH
);
2020-05-07 19:58:24 +00:00
if(LdotN < 0.0f) LdotN = 0.0f;
if(NdotH < 0.0f) NdotH = 0.0f;
_glLightVertexPoint(
data->finalColour,
2020-05-07 19:58:24 +00:00
i, LdotN, NdotH, att
);
}
}
}
2020-05-11 19:34:09 +00:00
vertex->bgra[R8IDX] = clamp(data->finalColour[0] * 255.0f, 0, 255);
vertex->bgra[G8IDX] = clamp(data->finalColour[1] * 255.0f, 0, 255);
vertex->bgra[B8IDX] = clamp(data->finalColour[2] * 255.0f, 0, 255);
vertex->bgra[A8IDX] = clamp(data->finalColour[3] * 255.0f, 0, 255);
2019-12-27 10:36:30 +00:00
}
2018-05-12 13:05:54 +00:00
}
2019-12-27 10:36:30 +00:00
#undef LIGHT_COMPONENT