mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2025-10-30 08:01:01 +00:00
Fresnel Lighting from F3DEX3 (#941)
Some checks are pending
Build coop / build-linux (push) Waiting to run
Build coop / build-steamos (push) Waiting to run
Build coop / build-windows-opengl (push) Waiting to run
Build coop / build-windows-directx (push) Waiting to run
Build coop / build-macos-arm (push) Waiting to run
Build coop / build-macos-intel (push) Waiting to run
Some checks are pending
Build coop / build-linux (push) Waiting to run
Build coop / build-steamos (push) Waiting to run
Build coop / build-windows-opengl (push) Waiting to run
Build coop / build-windows-directx (push) Waiting to run
Build coop / build-macos-arm (push) Waiting to run
Build coop / build-macos-intel (push) Waiting to run
* Fresnel part1 * Fresnel part2 * vmacu
This commit is contained in:
parent
2c332d4db6
commit
6524e709a3
5 changed files with 96 additions and 11 deletions
|
|
@ -405,6 +405,8 @@ s64 DynOS_Gfx_ParseGfxConstants(const String& _Arg, bool* found) {
|
|||
gfx_constant(G_LIGHT_MAP_EXT);
|
||||
gfx_constant(G_LIGHTING_ENGINE_EXT);
|
||||
gfx_constant(G_PACKED_NORMALS_EXT);
|
||||
gfx_constant(G_FRESNEL_COLOR_EXT);
|
||||
gfx_constant(G_FRESNEL_ALPHA_EXT);
|
||||
|
||||
gfx_constant(G_COL_PRIM);
|
||||
gfx_constant(G_COL_ENV);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@
|
|||
#define G_LIGHT_MAP_EXT 0x00000800
|
||||
#define G_LIGHTING_ENGINE_EXT 0x00004000
|
||||
#define G_PACKED_NORMALS_EXT 0x00000080
|
||||
#define G_FRESNEL_COLOR_EXT 0x00000040
|
||||
#define G_FRESNEL_ALPHA_EXT 0x00400000
|
||||
|
||||
//////////
|
||||
// DJUI //
|
||||
|
|
@ -118,3 +120,50 @@
|
|||
(_SHIFTL(G_PPARTTOCOLOR, 24, 8)) | (_SHIFTL(color, 16, 8)), \
|
||||
((2 * ((part) + 1)) + 1 + offset) \
|
||||
}}
|
||||
|
||||
////////////////////
|
||||
//// G_MOVEWORD ////
|
||||
////////////////////
|
||||
|
||||
#define G_MW_FX 0x00 /* replaces G_MW_MATRIX which is no longer supported */
|
||||
#define G_MWO_FRESNEL 0x0C
|
||||
|
||||
/**
|
||||
* Fresnel - Feature suggested by thecozies
|
||||
* Enabled with the G_FRESNEL bit in geometry mode.
|
||||
* The dot product between a vertex normal and the vector from the vertex to the
|
||||
* camera is computed. The offset and scale here convert this to a shade alpha
|
||||
* value. This is useful for making surfaces fade between transparent when
|
||||
* viewed straight-on and opaque when viewed at a large angle, or for applying a
|
||||
* fake "outline" around the border of meshes.
|
||||
*
|
||||
* If using Fresnel, you need to set the camera world position whenever you set
|
||||
* the VP matrix, viewport, etc. See SPCameraWorld.
|
||||
*
|
||||
* The RSP does:
|
||||
* s16 dotProduct = dot(vertex normal, camera pos - vertex pos);
|
||||
* dotProduct = abs(dotProduct); // 0 = points to side, 7FFF = points at or away
|
||||
* s32 factor = ((scale * dotProduct) >> 15) + offset;
|
||||
* s16 result = clamp(factor << 8, 0, 7FFF);
|
||||
* color_or_alpha = result >> 7;
|
||||
*
|
||||
* At dotMax, color_or_alpha = FF, result = 7F80, factor = 7F
|
||||
* At dotMin, color_or_alpha = 00, result = 0, factor = 0
|
||||
* 7F = ((scale * dotMax) >> 15) + offset
|
||||
* 00 = ((scale * dotMin) >> 15) + offset
|
||||
* Subtract: 7F = (scale * (dotMax - dotMin)) >> 15
|
||||
* 3F8000 = scale * (dotMax - dotMin)
|
||||
* scale = 3F8000 / (dotMax - dotMin) <--
|
||||
* offset = -(((3F8000 / (dotMax - dotMin)) * dotMin) >> 15)
|
||||
* offset = -((7F * dotMin) / (dotMax - dotMin)) <--
|
||||
*
|
||||
* To convert in the opposite direction:
|
||||
* ((7F - offset) << 15) / scale = dotMax
|
||||
* ((00 - offset) << 15) / scale = dotMin
|
||||
*/
|
||||
#define gSPFresnel(pkt, scale, offset) \
|
||||
gMoveWd(pkt, G_MW_FX, G_MWO_FRESNEL, \
|
||||
(_SHIFTL((scale), 16, 16) | _SHIFTL((offset), 0, 16)))
|
||||
#define gsSPFresnel(scale, offset) \
|
||||
gsMoveWd(G_MW_FX, G_MWO_FRESNEL, \
|
||||
(_SHIFTL((scale), 16, 16) | _SHIFTL((offset), 0, 16)))
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ define_gfx_symbol(gsMoveWd, 3, false, GFX_PARAM_TYPE_INT, GFX_PARAM_TYPE_INT, GF
|
|||
define_gfx_symbol(gsSPLoadGeometryMode, 1, false, GFX_PARAM_TYPE_INT);
|
||||
define_gfx_symbol(gsSPVertexNonGlobal, 3, true, GFX_PARAM_TYPE_VTX, GFX_PARAM_TYPE_INT, GFX_PARAM_TYPE_INT);
|
||||
define_gfx_symbol(gsSPCopyPlayerPartToColor, 3, false, GFX_PARAM_TYPE_INT, GFX_PARAM_TYPE_INT, GFX_PARAM_TYPE_INT);
|
||||
define_gfx_symbol(gsSPFresnel, 2, false, GFX_PARAM_TYPE_INT, GFX_PARAM_TYPE_INT);
|
||||
|
||||
define_gfx_symbol_manual(gsSPTexture, 5, false, GFX_PARAM_TYPE_INT, GFX_PARAM_TYPE_INT, GFX_PARAM_TYPE_INT, GFX_PARAM_TYPE_INT, GFX_PARAM_TYPE_INT);
|
||||
define_gfx_symbol_manual(gsSPSetGeometryMode, 1, false, GFX_PARAM_TYPE_INT);
|
||||
|
|
|
|||
|
|
@ -718,14 +718,12 @@ static void geo_process_camera(struct GraphNodeCamera *node) {
|
|||
mtxf_copy(gCamera->mtx, gMatStack[gMatStackIndex]);
|
||||
}
|
||||
|
||||
// compute inverse matrix for lighting engine
|
||||
if (le_is_enabled()) {
|
||||
Mat4 invCameraMatrix;
|
||||
if (mtxf_inverse_non_affine(invCameraMatrix, gCamera->mtx)) {
|
||||
Mtx *invMtx = alloc_display_list(sizeof(Mtx));
|
||||
mtxf_to_mtx(invMtx, invCameraMatrix);
|
||||
gSPMatrix(gDisplayListHead++, invMtx, G_MTX_INVERSE_CAMERA_EXT);
|
||||
}
|
||||
// compute inverse matrix for lighting engine and fresnel
|
||||
Mat4 invCameraMatrix;
|
||||
if (mtxf_inverse_non_affine(invCameraMatrix, gCamera->mtx)) {
|
||||
Mtx *invMtx = alloc_display_list(sizeof(Mtx));
|
||||
mtxf_to_mtx(invMtx, invCameraMatrix);
|
||||
gSPMatrix(gDisplayListHead++, invMtx, G_MTX_INVERSE_CAMERA_EXT);
|
||||
}
|
||||
|
||||
if (node->fnNode.node.children != 0) {
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ static struct RSP {
|
|||
|
||||
uint32_t geometry_mode;
|
||||
int16_t fog_mul, fog_offset;
|
||||
int16_t fresnel_scale, fresnel_offset;
|
||||
|
||||
struct {
|
||||
// U0.16
|
||||
|
|
@ -850,6 +851,33 @@ static void OPTIMIZE_O3 gfx_sp_vertex(size_t n_vertices, size_t dest_index, cons
|
|||
d->color.b *= vtxB;
|
||||
}
|
||||
|
||||
if (rsp.geometry_mode & (G_FRESNEL_COLOR_EXT | G_FRESNEL_ALPHA_EXT)) {
|
||||
Vec3f vpos = { v->ob[0], v->ob[1], v->ob[2] };
|
||||
Vec3f vnormal = { nx / 255.0f, ny / 255.0f, nz / 255.0f };
|
||||
// transform vpos and vnormal to world space
|
||||
gfx_local_to_world_space(vpos, vnormal);
|
||||
|
||||
Vec3f viewDir = {
|
||||
sInverseCameraMatrix[3][0] - vpos[0],
|
||||
sInverseCameraMatrix[3][1] - vpos[1],
|
||||
sInverseCameraMatrix[3][2] - vpos[2]
|
||||
};
|
||||
vec3f_normalize(viewDir);
|
||||
vec3f_normalize(vnormal);
|
||||
|
||||
int32_t dot = (int32_t) (fabsf(vec3f_dot(vnormal, viewDir)) * 32767.0f);
|
||||
int32_t factor = ((rsp.fresnel_scale * dot) >> 15) + rsp.fresnel_offset;
|
||||
int32_t fresnel = clamp(factor << 8, 0, 0x7FFF);
|
||||
uint8_t result = (uint8_t) (fresnel >> 7);
|
||||
|
||||
if (rsp.geometry_mode & G_FRESNEL_COLOR_EXT) {
|
||||
d->color.r = d->color.g = d->color.b = result;
|
||||
}
|
||||
if (rsp.geometry_mode & G_FRESNEL_ALPHA_EXT) {
|
||||
d->color.a = result;
|
||||
}
|
||||
}
|
||||
|
||||
if (rsp.geometry_mode & G_TEXTURE_GEN) {
|
||||
float dotx = 0, doty = 0;
|
||||
dotx += nx * rsp.current_lookat_coeffs[0][0];
|
||||
|
|
@ -970,8 +998,9 @@ static void OPTIMIZE_O3 gfx_sp_vertex(size_t n_vertices, size_t dest_index, cons
|
|||
if (fog_z > 255) fog_z = 255;
|
||||
d->fog_z = fog_z;
|
||||
}
|
||||
|
||||
d->color.a = v->cn[3];
|
||||
if (!(rsp.geometry_mode & G_FRESNEL_ALPHA_EXT)) {
|
||||
d->color.a = v->cn[3];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1297,7 +1326,7 @@ static void gfx_sp_copymem(uint8_t idx, uint16_t dstofs, uint16_t srcofs, UNUSED
|
|||
}
|
||||
#endif
|
||||
|
||||
static void gfx_sp_moveword(uint8_t index, UNUSED uint16_t offset, uint32_t data) {
|
||||
static void gfx_sp_moveword(uint8_t index, uint16_t offset, uint32_t data) {
|
||||
switch (index) {
|
||||
case G_MW_NUMLIGHT:
|
||||
#ifdef F3DEX_GBI_2
|
||||
|
|
@ -1318,6 +1347,12 @@ static void gfx_sp_moveword(uint8_t index, UNUSED uint16_t offset, uint32_t data
|
|||
sDepthZMult = (gProjectionVanillaFarValue - gProjectionMaxNearValue) / (gProjectionVanillaFarValue - gProjectionVanillaNearValue);
|
||||
sDepthZSub = gProjectionVanillaNearValue;
|
||||
|
||||
break;
|
||||
case G_MW_FX:
|
||||
if (offset == G_MWO_FRESNEL) {
|
||||
rsp.fresnel_scale = (int16_t)(data >> 16);
|
||||
rsp.fresnel_offset = (int16_t)data;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue