Render Entity Shadows
This commit is contained in:
parent
d4ab0099f0
commit
5668dcc852
@ -47,6 +47,7 @@
|
||||
* `Fix Crash When Generating Certain Seeds` (Enabled By Default)
|
||||
* `Click Buttons On Mouse Down` (Enabled By Default)
|
||||
* `3D Dropped Items` (Enabled By Default)
|
||||
* `Render Entity Shadows` (Enabled By Default)
|
||||
* Existing Functionality (All Enabled By Default)
|
||||
* `Fix Screen Rendering When Hiding HUD`
|
||||
* `Sanitize Usernames`
|
||||
|
@ -19,6 +19,12 @@ install(
|
||||
DESTINATION "${MCPI_INSTALL_DIR}/data/images/item"
|
||||
)
|
||||
|
||||
# Entity Shadow
|
||||
install(
|
||||
FILES "shadow.png"
|
||||
DESTINATION "${MCPI_INSTALL_DIR}/data/images/misc"
|
||||
)
|
||||
|
||||
# Icon
|
||||
set(ICON_DIR "${MCPI_SHARE_DIR}/icons/hicolor/512x512/apps")
|
||||
install(
|
||||
|
BIN
images/shadow.png
Normal file
BIN
images/shadow.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 868 B |
@ -109,4 +109,5 @@ TRUE Use Updated Title
|
||||
TRUE Hide Block Outline When GUI Is Hidden
|
||||
TRUE Fix Crash When Generating Certain Seeds
|
||||
TRUE Click Buttons On Mouse Down
|
||||
TRUE 3D Dropped Items
|
||||
TRUE 3D Dropped Items
|
||||
TRUE Render Entity Shadows
|
@ -135,6 +135,7 @@ static std::vector<std::string> get_debug_info_right(const Minecraft *minecraft)
|
||||
}
|
||||
xyz_precision = debug_precision;
|
||||
}
|
||||
minecraft->command_server->pos_translator.to(x, y, z);
|
||||
info.push_back("");
|
||||
info.push_back("Target X: " + to_string_with_precision(x, xyz_precision));
|
||||
info.push_back("Target Y: " + to_string_with_precision(y, xyz_precision));
|
||||
|
@ -90,69 +90,193 @@ static void sort_chunks(Chunk **chunks_begin, Chunk **chunks_end, const Distance
|
||||
}
|
||||
|
||||
// Fire Rendering
|
||||
static void render_fire(EntityRenderer *self, Entity *entity, const float x, float y, const float z) {
|
||||
// Check If Entity Is On Fire
|
||||
if (!entity->isOnFire()) {
|
||||
return;
|
||||
}
|
||||
// Here Be Decompiled Code
|
||||
y -= entity->height_offset;
|
||||
const int texture = Tile::fire->texture;
|
||||
const int xt = (texture & 0xf) << 4;
|
||||
const int yt = texture & 0xf0;
|
||||
glPushMatrix();
|
||||
glTranslatef(x, y, z);
|
||||
const float s = entity->hitbox_width * 1.4f;
|
||||
glScalef(s, s, s);
|
||||
self->bindTexture("terrain.png");
|
||||
Tesselator &t = Tesselator::instance;
|
||||
float r = 0.5f;
|
||||
float h = entity->hitbox_height / s;
|
||||
float yo = entity->y - entity->height_offset - entity->hitbox.y1;
|
||||
float player_rot_y = EntityRenderer::entityRenderDispatcher->player_rot_y;
|
||||
if (EntityRenderer::entityRenderDispatcher->minecraft->options.third_person == 2) {
|
||||
// Handle Front-Facing
|
||||
player_rot_y -= 180.f;
|
||||
}
|
||||
glRotatef(-player_rot_y, 0, 1, 0);
|
||||
glTranslatef(0, 0, -0.3f + float(int(h)) * 0.02f);
|
||||
glColor4f(1, 1, 1, 1);
|
||||
float zo = 0;
|
||||
int ss = 0;
|
||||
t.begin(7);
|
||||
while (h > 0) {
|
||||
constexpr float xo = 0.0f;
|
||||
float u0;
|
||||
float u1;
|
||||
float v0;
|
||||
float v1;
|
||||
if (ss % 2 == 0) {
|
||||
u0 = float(xt) / 256.0f;
|
||||
u1 = (float(xt) + 15.99f) / 256.0f;
|
||||
v0 = float(yt) / 256.0f;
|
||||
v1 = (float(yt) + 15.99f) / 256.0f;
|
||||
} else {
|
||||
u0 = float(xt) / 256.0f;
|
||||
u1 = (float(xt) + 15.99f) / 256.0f;
|
||||
v0 = (float(yt) + 16) / 256.0f;
|
||||
v1 = (float(yt) + 16 + 15.99f) / 256.0f;
|
||||
}
|
||||
if (ss / 2 % 2 == 0) {
|
||||
std::swap(u1, u0);
|
||||
}
|
||||
t.vertexUV(r - xo, 0 - yo, zo, u1, v1);
|
||||
t.vertexUV(-r - xo, 0 - yo, zo, u0, v1);
|
||||
t.vertexUV(-r - xo, 1.4f - yo, zo, u0, v0);
|
||||
t.vertexUV(r - xo, 1.4f - yo, zo, u1, v0);
|
||||
h -= 0.45f;
|
||||
yo -= 0.45f;
|
||||
r *= 0.9f;
|
||||
zo += 0.03f;
|
||||
ss++;
|
||||
}
|
||||
t.draw();
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
// Entity Shadows
|
||||
static void render_shadow_tile(Tile *tile, const float x, const float y, const float z, int xt, int yt, int zt, const float pow, const float r, const float xo, const float yo, const float zo) {
|
||||
Tesselator &t = Tesselator::instance;
|
||||
if (!tile->isCubeShaped()) {
|
||||
return;
|
||||
}
|
||||
float a = ((pow - (y - (float(yt) + yo)) / 2) * 0.5f) * EntityRenderer::entityRenderDispatcher->level->getBrightness(xt, yt, zt);
|
||||
if (a < 0) {
|
||||
return;
|
||||
} else if (a > 1) {
|
||||
a = 1;
|
||||
}
|
||||
t.color(255, 255, 255, int(a * 255));
|
||||
float x0 = float(xt) + tile->x1 + xo;
|
||||
float x1 = float(xt) + tile->x2 + xo;
|
||||
float y0 = float(yt) + tile->y1 + yo + 1.0f / 64.0f;
|
||||
float z0 = float(zt) + tile->z1 + zo;
|
||||
float z1 = float(zt) + tile->z2 + zo;
|
||||
float u0 = (x - x0) / 2 / r + 0.5f;
|
||||
float u1 = (x - x1) / 2 / r + 0.5f;
|
||||
float v0 = (z - z0) / 2 / r + 0.5f;
|
||||
float v1 = (z - z1) / 2 / r + 0.5f;
|
||||
t.vertexUV(x0, y0, z0, u0, v0);
|
||||
t.vertexUV(x0, y0, z1, u0, v1);
|
||||
t.vertexUV(x1, y0, z1, u1, v1);
|
||||
t.vertexUV(x1, y0, z0, u1, v0);
|
||||
}
|
||||
static void render_shadow(const EntityRenderer *self, Entity *entity, float x, float y, float z, const float a) {
|
||||
// Calculate Power
|
||||
float pow = 0;
|
||||
if (self->shadow_radius > 0) {
|
||||
const float dist = EntityRenderer::entityRenderDispatcher->distanceToSqr(entity->x, entity->y, entity->z);
|
||||
pow = (1 - dist / (16.0f * 16.0f)) * self->shadow_strength;
|
||||
}
|
||||
if (pow <= 0) {
|
||||
return;
|
||||
}
|
||||
// Render
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
Textures *textures = EntityRenderer::entityRenderDispatcher->textures;
|
||||
textures->loadAndBindTexture("misc/shadow.png");
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
Level *level = EntityRenderer::entityRenderDispatcher->level;
|
||||
glDepthMask(false);
|
||||
const float r = self->shadow_radius;
|
||||
const float ex = entity->old_x + (entity->x - entity->old_x) * a;
|
||||
float ey = entity->old_y + (entity->y - entity->old_y) * a + entity->getShadowHeightOffs() - entity->height_offset;
|
||||
const float ez = entity->old_z + (entity->z - entity->old_z) * a;
|
||||
const int x0 = Mth::floor(ex - r);
|
||||
const int x1 = Mth::floor(ex + r);
|
||||
const int y0 = Mth::floor(ey - r);
|
||||
const int y1 = Mth::floor(ey);
|
||||
const int z0 = Mth::floor(ez - r);
|
||||
const int z1 = Mth::floor(ez + r);
|
||||
const float xo = x - ex;
|
||||
const float yo = y - ey;
|
||||
const float zo = z - ez;
|
||||
Tesselator &tt = Tesselator::instance;
|
||||
tt.begin(7);
|
||||
for (int xt = x0; xt <= x1; xt++) {
|
||||
for (int yt = y0; yt <= y1; yt++) {
|
||||
for (int zt = z0; zt <= z1; zt++) {
|
||||
const int t = level->getTile(xt, yt - 1, zt);
|
||||
if (t > 0 && level->getRawBrightness(xt, yt, zt) > 3) {
|
||||
render_shadow_tile(
|
||||
Tile::tiles[t],
|
||||
x, y + entity->getShadowHeightOffs() - entity->height_offset, z,
|
||||
xt, yt, zt,
|
||||
pow, r,
|
||||
xo, yo + entity->getShadowHeightOffs() - entity->height_offset, zo
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
tt.draw();
|
||||
glColor4f(1, 1, 1, 1);
|
||||
glDisable(GL_BLEND);
|
||||
glDepthMask(true);
|
||||
}
|
||||
static void EntityRenderDispatcher_assign_injection(EntityRenderDispatcher_assign_t original, EntityRenderDispatcher *self, const uchar entity_id, EntityRenderer *renderer) {
|
||||
// Modify Shadow Size
|
||||
float new_radius;
|
||||
switch (entity_id) {
|
||||
case 16:
|
||||
case 3: {
|
||||
new_radius = 0.5f;
|
||||
break;
|
||||
}
|
||||
case 9:
|
||||
case 7:
|
||||
case 8: {
|
||||
new_radius = 0.7f;
|
||||
break;
|
||||
}
|
||||
case 6: {
|
||||
new_radius = 0.3f;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
new_radius = renderer->shadow_radius;
|
||||
}
|
||||
}
|
||||
renderer->shadow_radius = new_radius;
|
||||
// Call Original Method
|
||||
original(self, entity_id, renderer);
|
||||
}
|
||||
|
||||
// Modify Entity Rendering
|
||||
static bool should_render_fire;
|
||||
static bool should_render_shadows;
|
||||
static void EntityRenderDispatcher_render_EntityRenderer_render_injection(EntityRenderer *self, Entity *entity, float x, float y, float z, float rot, float unknown) {
|
||||
// Call Original Method
|
||||
self->render(entity, x, y, z, rot, unknown);
|
||||
|
||||
// Render Shadow
|
||||
if (should_render_shadows) {
|
||||
render_shadow(self, entity, x, y, z, unknown);
|
||||
}
|
||||
// Render Fire
|
||||
if (entity->isOnFire()) {
|
||||
// Here Be Decompiled Code
|
||||
y -= entity->height_offset;
|
||||
const int texture = Tile::fire->texture;
|
||||
const int xt = (texture & 0xf) << 4;
|
||||
const int yt = texture & 0xf0;
|
||||
glPushMatrix();
|
||||
glTranslatef(x, y, z);
|
||||
const float s = entity->hitbox_width * 1.4f;
|
||||
glScalef(s, s, s);
|
||||
self->bindTexture("terrain.png");
|
||||
Tesselator &t = Tesselator::instance;
|
||||
float r = 0.5f;
|
||||
float h = entity->hitbox_height / s;
|
||||
float yo = entity->y - entity->height_offset - entity->hitbox.y1;
|
||||
float player_rot_y = EntityRenderer::entityRenderDispatcher->player_rot_y;
|
||||
if (EntityRenderer::entityRenderDispatcher->minecraft->options.third_person == 2) {
|
||||
// Handle Front-Facing
|
||||
player_rot_y -= 180.f;
|
||||
}
|
||||
glRotatef(-player_rot_y, 0, 1, 0);
|
||||
glTranslatef(0, 0, -0.3f + float(int(h)) * 0.02f);
|
||||
glColor4f(1, 1, 1, 1);
|
||||
float zo = 0;
|
||||
int ss = 0;
|
||||
t.begin(7);
|
||||
while (h > 0) {
|
||||
constexpr float xo = 0.0f;
|
||||
float u0;
|
||||
float u1;
|
||||
float v0;
|
||||
float v1;
|
||||
if (ss % 2 == 0) {
|
||||
u0 = float(xt) / 256.0f;
|
||||
u1 = (float(xt) + 15.99f) / 256.0f;
|
||||
v0 = float(yt) / 256.0f;
|
||||
v1 = (float(yt) + 15.99f) / 256.0f;
|
||||
} else {
|
||||
u0 = float(xt) / 256.0f;
|
||||
u1 = (float(xt) + 15.99f) / 256.0f;
|
||||
v0 = (float(yt) + 16) / 256.0f;
|
||||
v1 = (float(yt) + 16 + 15.99f) / 256.0f;
|
||||
}
|
||||
if (ss / 2 % 2 == 0) {
|
||||
std::swap(u1, u0);
|
||||
}
|
||||
t.vertexUV(r - xo, 0 - yo, zo, u1, v1);
|
||||
t.vertexUV(-r - xo, 0 - yo, zo, u0, v1);
|
||||
t.vertexUV(-r - xo, 1.4f - yo, zo, u0, v0);
|
||||
t.vertexUV(r - xo, 1.4f - yo, zo, u1, v0);
|
||||
h -= 0.45f;
|
||||
yo -= 0.45f;
|
||||
r *= 0.9f;
|
||||
zo += 0.03f;
|
||||
ss++;
|
||||
}
|
||||
t.draw();
|
||||
glPopMatrix();
|
||||
if (should_render_fire) {
|
||||
render_fire(self, entity, x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
@ -377,9 +501,12 @@ void _init_misc_graphics() {
|
||||
overwrite_calls_manual((void *) 0x51fac, (void *) sort_chunks);
|
||||
}
|
||||
|
||||
// Render Fire In Third-Person
|
||||
if (feature_has("Render Fire In Third-Person", server_disabled)) {
|
||||
overwrite_call((void *) 0x606c0, (void *) EntityRenderDispatcher_render_EntityRenderer_render_injection);
|
||||
// Modify Entity Rendering
|
||||
overwrite_call((void *) 0x606c0, (void *) EntityRenderDispatcher_render_EntityRenderer_render_injection);
|
||||
should_render_fire = feature_has("Render Fire In Third-Person", server_disabled);
|
||||
should_render_shadows = feature_has("Render Entity Shadows", server_disabled);
|
||||
if (should_render_shadows) {
|
||||
overwrite_calls(EntityRenderDispatcher_assign, EntityRenderDispatcher_assign_injection);
|
||||
}
|
||||
|
||||
// Slightly Nicer Water Rendering
|
||||
|
@ -22,15 +22,16 @@ virtual-method int getAuxData() = 0xf4;
|
||||
virtual-method bool isOnFire() = 0x90;
|
||||
virtual-method void baseTick() = 0x38;
|
||||
virtual-method bool isSneaking() = 0x88;
|
||||
virtual-method float getShadowHeightOffs() = 0x60;
|
||||
|
||||
property float x = 0x4;
|
||||
property float y = 0x8;
|
||||
property float z = 0xc;
|
||||
property int id = 0x1c;
|
||||
property Level *level = 0x24;
|
||||
property float old_x = 0x28;
|
||||
property float old_y = 0x2c;
|
||||
property float old_z = 0x30;
|
||||
property float old_x = 0x7c;
|
||||
property float old_y = 0x80;
|
||||
property float old_z = 0x84;
|
||||
property float vel_x = 0x34;
|
||||
property float vel_y = 0x38;
|
||||
property float vel_z = 0x3c;
|
||||
|
@ -2,8 +2,11 @@ constructor () = 0x6096c;
|
||||
|
||||
method void assign(uchar entity_id, EntityRenderer *renderer) = 0x6094c;
|
||||
method void render(Entity *entity, float x, float y, float z, float rot, float unknown) = 0x60674;
|
||||
method float distanceToSqr(float x, float y, float z) = 0x60790;
|
||||
static-method EntityRenderDispatcher *getInstance() = 0x60e90;
|
||||
|
||||
property ItemInHandRenderer *item_renderer = 0x0;
|
||||
property float player_rot_y = 0x14;
|
||||
property Minecraft *minecraft = 0xc;
|
||||
property Minecraft *minecraft = 0xc;
|
||||
property Level *level = 0x8;
|
||||
property Textures *textures = 0x4;
|
@ -5,5 +5,8 @@ virtual-method void render(Entity *entity, float param_2, float param_3, float p
|
||||
// Can be called without an EntityRenderer, just do EntityRenderer_bindTexture->get(false)(NULL, &file);
|
||||
method void bindTexture(const std::string &file) = 0x62540;
|
||||
|
||||
property float shadow_radius = 0x4;
|
||||
property float shadow_strength = 0x8;
|
||||
|
||||
// Globals
|
||||
static-property EntityRenderDispatcher *entityRenderDispatcher = 0x137bc0;
|
||||
|
@ -1,6 +1,6 @@
|
||||
virtual-method int getTile(int x, int y, int z) = 0x8;
|
||||
virtual-method int isEmptyTile(int x, int y, int z) = 0xc;
|
||||
virtual-method int getBrightness(int x, int y, int z) = 0x10;
|
||||
virtual-method float getBrightness(int x, int y, int z) = 0x10;
|
||||
virtual-method int getData(int x, int y, int z) = 0x14;
|
||||
virtual-method Material *getMaterial(int x, int y, int z) = 0x18;
|
||||
virtual-method bool isSolidRenderTile(int x, int y, int z) = 0x1c;
|
||||
|
Loading…
Reference in New Issue
Block a user