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

@ -113,3 +113,4 @@ TRUE Render Vignette
TRUE Increase Render Chunk Size
TRUE Proper Entity Shading
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;
@ -11,3 +15,5 @@ method void renderEntities(Vec3 pos, void *unknown, float a) = 0x500ec;
property Minecraft *minecraft = 0xb4;
property RenderList render_list = 0x34;
property Chunk **chunks = 0x98;
property bool occlusion_check = 0xb8;
property int num_buffers = 0xd0;