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_LIGHT_MAP_EXT);
|
||||||
gfx_constant(G_LIGHTING_ENGINE_EXT);
|
gfx_constant(G_LIGHTING_ENGINE_EXT);
|
||||||
gfx_constant(G_PACKED_NORMALS_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_PRIM);
|
||||||
gfx_constant(G_COL_ENV);
|
gfx_constant(G_COL_ENV);
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@
|
||||||
#define G_LIGHT_MAP_EXT 0x00000800
|
#define G_LIGHT_MAP_EXT 0x00000800
|
||||||
#define G_LIGHTING_ENGINE_EXT 0x00004000
|
#define G_LIGHTING_ENGINE_EXT 0x00004000
|
||||||
#define G_PACKED_NORMALS_EXT 0x00000080
|
#define G_PACKED_NORMALS_EXT 0x00000080
|
||||||
|
#define G_FRESNEL_COLOR_EXT 0x00000040
|
||||||
|
#define G_FRESNEL_ALPHA_EXT 0x00400000
|
||||||
|
|
||||||
//////////
|
//////////
|
||||||
// DJUI //
|
// DJUI //
|
||||||
|
|
@ -118,3 +120,50 @@
|
||||||
(_SHIFTL(G_PPARTTOCOLOR, 24, 8)) | (_SHIFTL(color, 16, 8)), \
|
(_SHIFTL(G_PPARTTOCOLOR, 24, 8)) | (_SHIFTL(color, 16, 8)), \
|
||||||
((2 * ((part) + 1)) + 1 + offset) \
|
((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(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(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(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(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);
|
define_gfx_symbol_manual(gsSPSetGeometryMode, 1, false, GFX_PARAM_TYPE_INT);
|
||||||
|
|
|
||||||
|
|
@ -718,15 +718,13 @@ static void geo_process_camera(struct GraphNodeCamera *node) {
|
||||||
mtxf_copy(gCamera->mtx, gMatStack[gMatStackIndex]);
|
mtxf_copy(gCamera->mtx, gMatStack[gMatStackIndex]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// compute inverse matrix for lighting engine
|
// compute inverse matrix for lighting engine and fresnel
|
||||||
if (le_is_enabled()) {
|
|
||||||
Mat4 invCameraMatrix;
|
Mat4 invCameraMatrix;
|
||||||
if (mtxf_inverse_non_affine(invCameraMatrix, gCamera->mtx)) {
|
if (mtxf_inverse_non_affine(invCameraMatrix, gCamera->mtx)) {
|
||||||
Mtx *invMtx = alloc_display_list(sizeof(Mtx));
|
Mtx *invMtx = alloc_display_list(sizeof(Mtx));
|
||||||
mtxf_to_mtx(invMtx, invCameraMatrix);
|
mtxf_to_mtx(invMtx, invCameraMatrix);
|
||||||
gSPMatrix(gDisplayListHead++, invMtx, G_MTX_INVERSE_CAMERA_EXT);
|
gSPMatrix(gDisplayListHead++, invMtx, G_MTX_INVERSE_CAMERA_EXT);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (node->fnNode.node.children != 0) {
|
if (node->fnNode.node.children != 0) {
|
||||||
gCurGraphNodeCamera = node;
|
gCurGraphNodeCamera = node;
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,7 @@ static struct RSP {
|
||||||
|
|
||||||
uint32_t geometry_mode;
|
uint32_t geometry_mode;
|
||||||
int16_t fog_mul, fog_offset;
|
int16_t fog_mul, fog_offset;
|
||||||
|
int16_t fresnel_scale, fresnel_offset;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
// U0.16
|
// 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;
|
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) {
|
if (rsp.geometry_mode & G_TEXTURE_GEN) {
|
||||||
float dotx = 0, doty = 0;
|
float dotx = 0, doty = 0;
|
||||||
dotx += nx * rsp.current_lookat_coeffs[0][0];
|
dotx += nx * rsp.current_lookat_coeffs[0][0];
|
||||||
|
|
@ -970,9 +998,10 @@ static void OPTIMIZE_O3 gfx_sp_vertex(size_t n_vertices, size_t dest_index, cons
|
||||||
if (fog_z > 255) fog_z = 255;
|
if (fog_z > 255) fog_z = 255;
|
||||||
d->fog_z = fog_z;
|
d->fog_z = fog_z;
|
||||||
}
|
}
|
||||||
|
if (!(rsp.geometry_mode & G_FRESNEL_ALPHA_EXT)) {
|
||||||
d->color.a = v->cn[3];
|
d->color.a = v->cn[3];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OPTIMIZE_O3 gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t vtx3_idx) {
|
static void OPTIMIZE_O3 gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t vtx3_idx) {
|
||||||
|
|
@ -1297,7 +1326,7 @@ static void gfx_sp_copymem(uint8_t idx, uint16_t dstofs, uint16_t srcofs, UNUSED
|
||||||
}
|
}
|
||||||
#endif
|
#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) {
|
switch (index) {
|
||||||
case G_MW_NUMLIGHT:
|
case G_MW_NUMLIGHT:
|
||||||
#ifdef F3DEX_GBI_2
|
#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);
|
sDepthZMult = (gProjectionVanillaFarValue - gProjectionMaxNearValue) / (gProjectionVanillaFarValue - gProjectionVanillaNearValue);
|
||||||
sDepthZSub = 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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue