Occlusion Checking

This commit is contained in:
TheBrokenRail 2024-11-09 00:17:25 -05:00
parent a63125f335
commit a8d0962491
7 changed files with 87 additions and 4 deletions

View File

@ -52,6 +52,7 @@
* `Increase Render Chunk Size` (Enabled By Default)
* `Proper Entity Shading` (Enabled By Default)
* `Fix Sugar Position In Hand` (Enabled By Default)
* `Chunk OpenGL Occlusion Checking` (Disabled By Default)
* Existing Functionality (All Enabled By Default)
* `Fix Screen Rendering When Hiding HUD`
* `Sanitize Usernames`

View File

@ -112,4 +112,5 @@ TRUE Render Entity Shadows
TRUE Render Vignette
TRUE Increase Render Chunk Size
TRUE Proper Entity Shading
TRUE Fix Sugar Position In Hand
TRUE Fix Sugar Position In Hand
FALSE Chunk OpenGL Occlusion Checking

View File

@ -501,6 +501,63 @@ static int safe_log2(const int x) {
return z;
}
// Occlusion Checking
static int num_occlusion_ids;
static GLuint *occlusion_ids;
static LevelRenderer *LevelRenderer_injection(LevelRenderer_constructor_t original, LevelRenderer *self, Minecraft *minecraft) {
// Call Original Method
original(self, minecraft);
// Setup
self->occlusion_check = true;
num_occlusion_ids = self->num_buffers / 3;
occlusion_ids = new GLuint[num_occlusion_ids];
media_glGenQueries(num_occlusion_ids, occlusion_ids);
return self;
}
static void LevelRenderer_allChanged_Chunk_setDirty_injection(Chunk *self) {
self->occlusion_id = int(occlusion_ids[self->id]);
// Call Original Method
self->setDirty();
}
static void check_query_result(Chunk *chunk) {
if (chunk->occlusion_querying) {
GLuint val;
media_glGetQueryObjectuiv(chunk->occlusion_id, GL_QUERY_RESULT_AVAILABLE, &val);
if (val != 0) {
chunk->occlusion_querying = false;
media_glGetQueryObjectuiv(chunk->occlusion_id, GL_QUERY_RESULT, &val);
chunk->occlusion_visible = val != 0;
}
}
}
static int LevelRenderer_render_LevelRenderer_renderChunks_injection(LevelRenderer *self, const int start, const int end, const int a, const float b) {
for (int i = start; i < end; i++) {
Chunk *chunk = self->chunks[i];
check_query_result(chunk);
chunk->occlusion_visible = true;
}
// Call Original Method
return self->renderChunks(start, end, a, b);
}
static bool LevelRenderer_render_Chunk_isEmpty_injection(Chunk *self) {
check_query_result(self);
// Call Original Method
return self->isEmpty();
}
static void Chunk_renderBB_injection(__attribute__((unused)) Chunk_renderBB_t original, Chunk *self) {
media_glBeginQuery(GL_SAMPLES_PASSED, self->occlusion_id);
AABB aabb = {
.x1 = self->aabb.x1 - float(self->x),
.y1 = self->aabb.y1 - float(self->y),
.z1 = self->aabb.z1 - float(self->z),
.x2 = self->aabb.x2 - float(self->x),
.y2 = self->aabb.y2 - float(self->y),
.z2 = self->aabb.z2 - float(self->z)
};
EntityRenderer::renderFlat(aabb);
media_glEndQuery(GL_SAMPLES_PASSED);
}
// Init
void _init_misc_graphics() {
// Disable V-Sync
@ -651,6 +708,15 @@ void _init_misc_graphics() {
patch((void *) 0x4f20c, render_chunk_patch_seven);
}
// Occlusion Checking
if(feature_has("Chunk OpenGL Occlusion Checking", server_disabled)) {
overwrite_calls(LevelRenderer_constructor, LevelRenderer_injection);
overwrite_call((void *) 0x4fce4, (void *) LevelRenderer_allChanged_Chunk_setDirty_injection);
overwrite_call((void *) 0x4f8d4, (void *) LevelRenderer_render_LevelRenderer_renderChunks_injection);
overwrite_call((void *) 0x4f960, (void *) LevelRenderer_render_Chunk_isEmpty_injection);
overwrite_calls(Chunk_renderBB, Chunk_renderBB_injection);
}
// Don't Render Game In Headless Mode
if (reborn_is_headless()) {
overwrite_calls(GameRenderer_render, nop<GameRenderer_render_t, GameRenderer *, float>);

View File

@ -94,13 +94,13 @@ static void multidraw_renderSameAsLast(const LevelRenderer *self, const float b)
media_glDisableClientState(GL_TEXTURE_COORD_ARRAY);
media_glPopMatrix();
}
static int LevelRenderer_renderChunks_injection(__attribute__((unused)) LevelRenderer_renderChunks_t original, LevelRenderer *self, const int start, const int end, const int a, const float b) {
static int LevelRenderer_renderChunks_injection(__attribute__((unused)) LevelRenderer_renderChunks_t original, const LevelRenderer *self, const int start, const int end, const int a, const float b) {
// Batch
multidraw_total = 0;
for (int i = start; i < end; i++) {
Chunk *chunk = self->chunks[i];
// Check If Chunk Is Visible
if (!chunk->field_1c[a] && chunk->visible) {
if (!chunk->field_1c[a] && chunk->visible && (!self->occlusion_check || chunk->occlusion_visible)) {
const RenderChunk *render_chunk = chunk->getRenderChunk(a);
// Get Data Block
const int chunk_id = int(render_chunk->buffer - MULTIDRAW_BASE);

View File

@ -10,3 +10,4 @@ property float shadow_strength = 0x8;
// Globals
static-property EntityRenderDispatcher *entityRenderDispatcher = 0x137bc0;
static-method void renderFlat(const AABB &aabb) = 0x627c8;

View File

@ -3,7 +3,15 @@ property int y = 0x8;
property int z = 0xc;
property bool field_1c[3] = 0x1c;
property bool visible = 0x4c;
property bool occlusion_visible = 0x4d;
property bool occlusion_querying = 0x4e;
property int occlusion_id = 0x50;
property AABB aabb = 0x30;
property int id = 0x48;
method float distanceToSqr(const Entity *entity) = 0x47ba0;
method int getList(int a) = 0x47e48;
method RenderChunk *getRenderChunk(int a) = 0x47e74;
method void renderBB() = 0x47ed8;
method void setDirty() = 0x47ef0;
method bool isEmpty() = 0x47edc;

View File

@ -1,3 +1,7 @@
vtable 0x107438;
constructor (Minecraft *minecraft) = 0x4e5f8;
method void tick() = 0x4da1c;
method int render(Mob *mob, int param_1, float delta) = 0x4f710;
method void render_AABB(const AABB &box) = 0x4d740;
@ -10,4 +14,6 @@ method void renderEntities(Vec3 pos, void *unknown, float a) = 0x500ec;
property Minecraft *minecraft = 0xb4;
property RenderList render_list = 0x34;
property Chunk **chunks = 0x98;
property Chunk **chunks = 0x98;
property bool occlusion_check = 0xb8;
property int num_buffers = 0xd0;