Rest Of The Tesselator

This commit is contained in:
TheBrokenRail 2024-10-18 01:41:59 -04:00
parent b2db67b4bf
commit 1001427309
16 changed files with 310 additions and 12 deletions

View File

@ -113,3 +113,4 @@ TRUE 3D Dropped Items
TRUE Render Entity Shadows
TRUE Render Vignette
TRUE Increase Render Chunk Size
TRUE Proper Entity Shading

View File

@ -10,7 +10,7 @@
void reborn_init_patch();
// Replace Call Located At start With A Call To target
void overwrite_call(void *start, void *target);
void overwrite_call(void *start, void *target, bool force_b_instruction = false);
// Replace All Calls To Method start With target
void *overwrite_calls_manual(void *start, void *target, bool allow_no_callsites = false);

View File

@ -21,8 +21,8 @@ static void _overwrite_call_internal(void *start, void *target, const bool use_b
// Increment Code Block Position
increment_code_block();
}
void overwrite_call(void *start, void *target) {
const bool use_b_instruction = ((unsigned char *) start)[3] == B_INSTRUCTION;
void overwrite_call(void *start, void *target, const bool force_b_instruction) {
const bool use_b_instruction = force_b_instruction || ((unsigned char *) start)[3] == B_INSTRUCTION;
_overwrite_call_internal(start, target, use_b_instruction);
}

View File

@ -228,3 +228,7 @@ GL_FUNC(glGenBuffers, void, (GLsizei n, GLuint *buffers))
void glGenBuffers(const GLsizei n, GLuint *buffers) {
real_glGenBuffers()(n, buffers);
}
GL_FUNC(glNormalPointer, void, (GLenum type, GLsizei stride, const void *pointer))
void glNormalPointer(const GLenum type, const GLsizei stride, const void *pointer) {
real_glNormalPointer()(type, stride, pointer);
}

View File

@ -30,6 +30,7 @@ extern "C" {
#define GL_VERTEX_ARRAY 0x8074
#define GL_COLOR_ARRAY 0x8076
#define GL_TEXTURE_COORD_ARRAY 0x8078
#define GL_NORMAL_ARRAY 0x8075
#define GL_GREATER 0x204
#define GL_ALPHA_TEST 0xbc0
#define GL_TEXTURE_2D 0xde1
@ -47,6 +48,7 @@ extern "C" {
#define GL_TRIANGLES 0x4
#define GL_TRIANGLE_STRIP 0x5
#define GL_TRIANGLE_FAN 0x6
#define GL_QUADS 0x7
#define GL_FASTEST 0x1101
#define GL_BACK 0x405
#define GL_CULL_FACE 0xb44
@ -158,6 +160,7 @@ GLenum glGetError();
void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
void glPixelStorei(GLenum pname, GLint param);
void glMultiDrawArrays(GLenum mode, const GLint *first, const GLsizei *count, GLsizei drawcount);
void glNormalPointer(GLenum type, GLsizei stride, const void *pointer);
#ifdef __cplusplus
}

View File

@ -33,6 +33,7 @@ struct {
gl_array_details_t glVertexPointer;
gl_array_details_t glColorPointer;
gl_array_details_t glTexCoordPointer;
gl_array_details_t glNormalPointer;
} gl_array_details;
#endif
struct gl_state_t {
@ -41,6 +42,7 @@ struct gl_state_t {
bool vertex_array_enabled = false;
bool color_array_enabled = false;
bool tex_coord_array_enabled = false;
bool normal_array_enabled = false;
// Update State
bool &get_array_enabled(const GLenum array) {
switch (array) {
@ -53,6 +55,9 @@ struct gl_state_t {
case GL_TEXTURE_COORD_ARRAY: {
return tex_coord_array_enabled;
}
case GL_NORMAL_ARRAY: {
return normal_array_enabled;
}
default: {
ERR("Unsupported Array Type: %i", array);
}
@ -71,6 +76,7 @@ struct gl_state_t {
send_array_to_driver(GL_VERTEX_ARRAY);
send_array_to_driver(GL_COLOR_ARRAY);
send_array_to_driver(GL_TEXTURE_COORD_ARRAY);
send_array_to_driver(GL_NORMAL_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, bound_array_buffer);
glBindTexture(GL_TEXTURE_2D, bound_texture);
}
@ -762,3 +768,20 @@ CALL(69, glBufferSubData, void, (GLenum target, GLintptr offset, GLsizeiptr size
return 0;
#endif
}
CALL(72, glNormalPointer, void, (GLenum type, GLsizei stride, const void *pointer))
#ifdef MEDIA_LAYER_TRAMPOLINE_GUEST
gl_array_details_t &state = gl_array_details.glNormalPointer; \
if (state.type != type || state.stride != stride || state.pointer != uint32_t(pointer)) { \
state.type = type; \
state.stride = stride; \
state.pointer = uint32_t(pointer); \
trampoline(true, gl_state.bound_array_buffer, state); \
}
#else
glBindBuffer(GL_ARRAY_BUFFER, args.next<GLuint>());
gl_array_details_t state = args.next<gl_array_details_t>();
func(state.type, state.stride, (const void *) uintptr_t(state.pointer));
return 0;
#endif
}

View File

@ -99,6 +99,9 @@ set(SRC
src/multidraw/storage.cpp
# classic-ui
src/classic-ui/classic-ui.cpp
# shading
src/shading/init.cpp
src/shading/tesselator.cpp
)
# Install Splashes
install(

View File

@ -31,4 +31,5 @@ void init_screenshot();
void init_f3();
void init_multidraw();
void init_classic_ui();
void init_shading();
}

View File

@ -2,6 +2,7 @@
#include <symbols/minecraft.h>
extern int multidraw_vertex_size;
extern "C" {
void LevelRenderer_renderSameAsLast(LevelRenderer *self, float delta);
}

View File

@ -16,6 +16,7 @@ __attribute__((constructor)) static void init() {
init_multiplayer();
if (!reborn_is_headless()) {
init_sound();
init_shading();
}
init_input();
init_sign();

View File

@ -50,7 +50,7 @@ HOOK(glBufferData, void, (GLenum target, GLsizeiptr size, const void *data, GLen
}
// Render
#define VERTEX_SIZE 24
int multidraw_vertex_size = 24;
#define MAX_RENDER_CHUNKS 4096
static bool supports_multidraw() {
static int ret = -1;
@ -76,9 +76,9 @@ static void multidraw_renderSameAsLast(const LevelRenderer *self, const float b)
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, storage->buffer->server_side_data);
glVertexPointer(3, GL_FLOAT, VERTEX_SIZE, (void *) 0);
glTexCoordPointer(2, GL_FLOAT, VERTEX_SIZE, (void *) 0xc);
glColorPointer(4, GL_UNSIGNED_BYTE, VERTEX_SIZE, (void *) 0x14);
glVertexPointer(3, GL_FLOAT, multidraw_vertex_size, (void *) 0);
glTexCoordPointer(2, GL_FLOAT, multidraw_vertex_size, (void *) 0xc);
glColorPointer(4, GL_UNSIGNED_BYTE, multidraw_vertex_size, (void *) 0x14);
// Draw
if (supports_multidraw()) {
@ -110,7 +110,7 @@ static int LevelRenderer_renderChunks_injection(__attribute__((unused)) LevelRen
}
// Queue
const int j = multidraw_total++;
multidraw_firsts[j] = block->offset / VERTEX_SIZE;
multidraw_firsts[j] = block->offset / multidraw_vertex_size;
multidraw_counts[j] = render_chunk->vertices;
}
}

View File

@ -0,0 +1,11 @@
#include <mods/init/init.h>
#include <mods/feature/feature.h>
#include "shading-internal.h"
// Init
void init_shading() {
if (feature_has("Proper Entity Shading", server_disabled)) {
_init_custom_tesselator();
}
}

View File

@ -0,0 +1,202 @@
#include <optional>
#include <cstddef>
#include <algorithm>
#include <GLES/gl.h>
#include <libreborn/libreborn.h>
#include <symbols/minecraft.h>
#include <mods/multidraw/multidraw.h>
#include "shading-internal.h"
// Structures
struct UV {
float u;
float v;
};
struct CustomVertex {
Vec3 pos;
UV uv;
GLuint color;
GLuint normal;
};
struct CustomTesselator {
int vertex_count;
CustomVertex *vertices;
std::optional<uint32_t> normal;
int quad_to_triangle_tracker;
static CustomTesselator instance;
};
CustomTesselator CustomTesselator::instance;
static void Tesselator_clear_injection(Tesselator_clear_t original, Tesselator *self) {
if (original) {
original(self);
}
CustomTesselator::instance.vertex_count = 0;
CustomTesselator::instance.quad_to_triangle_tracker = 0;
CustomTesselator::instance.normal.reset();
}
#define MAX_VERTICES 524288
static void Tesselator_init_injection(Tesselator_init_t original, Tesselator *self) {
original(self);
CustomTesselator::instance.vertices = new CustomVertex[MAX_VERTICES];
Tesselator_clear_injection(nullptr, nullptr);
}
static void Tesselator_begin_injection(Tesselator_begin_t original, Tesselator *self, const int mode) {
original(self, mode);
if (!self->void_begin_end) {
Tesselator_clear_injection(nullptr, nullptr);
}
}
static GLuint get_next_buffer() {
Tesselator::instance.next_buffer_id++;
Tesselator::instance.next_buffer_id %= Tesselator::instance.buffer_count;
const GLuint out = Tesselator::instance.buffers[Tesselator::instance.next_buffer_id];
return out;
}
static RenderChunk Tesselator_end_injection(Tesselator *self, const bool use_given_buffer, const int buffer) {
// Check
if (!self->active) {
IMPOSSIBLE();
}
RenderChunk out;
out.constructor();
if (self->void_begin_end) {
return out;
}
// Render
out.vertices = CustomTesselator::instance.vertex_count;
if (out.vertices > 0) {
out.buffer = use_given_buffer ? buffer : get_next_buffer();
glBindBuffer(GL_ARRAY_BUFFER, out.buffer);
glBufferData(GL_ARRAY_BUFFER, out.vertices * sizeof(CustomVertex), CustomTesselator::instance.vertices, GL_STATIC_DRAW);
}
// Finish
self->clear();
self->active = false;
return out;
}
static void Tesselator_draw_injection(Tesselator *self) {
// Check
if (!self->active) {
IMPOSSIBLE();
}
if (self->void_begin_end) {
return;
}
// Render
const int vertices = CustomTesselator::instance.vertex_count;
if (vertices > 0) {
const GLuint buffer = get_next_buffer();
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, vertices * sizeof(CustomVertex), CustomTesselator::instance.vertices, GL_STATIC_DRAW);
if (self->has_texture) {
glTexCoordPointer(2, GL_FLOAT, sizeof(CustomVertex), (void *) offsetof(CustomVertex, uv));
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}
if (self->has_color) {
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(CustomVertex), (void *) offsetof(CustomVertex, color));
glEnableClientState(GL_COLOR_ARRAY);
}
if (CustomTesselator::instance.normal) {
glNormalPointer(GL_BYTE, sizeof(CustomVertex), (void *) offsetof(CustomVertex, normal));
glEnableClientState(GL_NORMAL_ARRAY);
}
glVertexPointer(3, GL_FLOAT, sizeof(CustomVertex), (void *) offsetof(CustomVertex, pos));
glEnableClientState(GL_VERTEX_ARRAY);
int mode = self->mode;
if (mode == GL_QUADS) {
mode = GL_TRIANGLES;
}
glDrawArrays(mode, 0, vertices);
glDisableClientState(GL_VERTEX_ARRAY);
if (self->has_texture) {
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
if (self->has_color) {
glDisableClientState(GL_COLOR_ARRAY);
}
if (CustomTesselator::instance.normal) {
glDisableClientState(GL_NORMAL_ARRAY);
}
}
// Finish
self->clear();
self->active = false;
}
static void Tesselator_vertex_injection(const Tesselator *self, const float x, const float y, const float z) {
CustomVertex &vertex = CustomTesselator::instance.vertices[CustomTesselator::instance.vertex_count++];
vertex.pos = {
(self->offset_x + x) * self->sx,
(self->offset_y + y) * self->sy,
self->offset_z + z
};
if (self->has_texture) {
vertex.uv = {self->u, self->v};
}
if (self->has_color) {
vertex.color = self->_color;
}
if (CustomTesselator::instance.normal) {
vertex.normal = *CustomTesselator::instance.normal;
}
// Convert To Triangles
if (self->mode == GL_QUADS) {
int &tracker = CustomTesselator::instance.quad_to_triangle_tracker;
if (tracker == 3) {
tracker = 0;
} else {
if (tracker == 2) {
const int last_vertex = CustomTesselator::instance.vertex_count - 1;
for (const int i : {-2, 0}) {
CustomTesselator::instance.vertices[CustomTesselator::instance.vertex_count++] = CustomTesselator::instance.vertices[last_vertex + i];
}
}
tracker++;
}
}
}
static void Tesselator_normal_injection(__attribute__((unused)) Tesselator *self, const float nx, const float ny, const float nz) {
const char xx = (char) (nx * 128);
const char yy = (char) (ny * 127);
const char zz = (char) (nz * 127);
CustomTesselator::instance.normal = xx | (yy << 8) | (zz << 16);
}
static void drawArrayVT_injection(const int buffer, const int vertices, int vertex_size, const uint mode) {
vertex_size = sizeof(CustomVertex);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glTexCoordPointer(2, GL_FLOAT, vertex_size, (void *) offsetof(CustomVertex, uv));
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(3, GL_FLOAT, vertex_size, (void *) offsetof(CustomVertex, pos));
glEnableClientState(GL_VERTEX_ARRAY);
glNormalPointer(GL_BYTE, sizeof(CustomVertex), (void *) offsetof(CustomVertex, normal));
glEnableClientState(GL_NORMAL_ARRAY);
glDrawArrays(mode, 0, vertices);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
}
// Init
void _init_custom_tesselator() {
multidraw_vertex_size = sizeof(CustomVertex);
overwrite_calls(Tesselator_init, Tesselator_init_injection);
overwrite_calls(Tesselator_clear, Tesselator_clear_injection);
overwrite_calls(Tesselator_begin, Tesselator_begin_injection);
overwrite_call((void *) Tesselator_end->backup, (void *) Tesselator_end_injection, true);
overwrite_call((void *) Tesselator_draw->backup, (void *) Tesselator_draw_injection, true);
overwrite_call((void *) Tesselator_vertex->backup, (void *) Tesselator_vertex_injection, true);
overwrite_call((void *) Tesselator_normal->backup, (void *) Tesselator_normal_injection, true);
overwrite_call((void *) Common_drawArrayVT->backup, (void *) drawArrayVT_injection, true);
}

View File

@ -1,7 +1,10 @@
size 0x18;
constructor () = 0x525ac;
property uint buffer = 0x0;
property int vertices = 0x4;
property float x = 0xc;
property float y = 0x10;
property float z = 0x14;
property int id = 0x8;
property Vec3 pos = 0xc;
mark-as-simple;

View File

@ -7,3 +7,4 @@ static-method int sdl_key_to_minecraft_key(int sdl_key) = 0x1243c;
static-method void anGenBuffers(int count, uint *buffers) = 0x5f28c;
static-method int getTimeMs() = 0x13cd4;
static-method int getEpochTimeS() = 0x13d00;
static-method void drawArrayVT(int buffer, int vertices, int vertex_size, uint mode) = 0x5f2cc;

View File

@ -1,9 +1,53 @@
method void init() = 0x5289c;
method void clear() = 0x528ac;
method void begin(int mode) = 0x529d4;
method void begin_quads() = 0x52a24;
method RenderChunk end(bool use_given_buffer, int buffer) = 0x528d4;
method void draw() = 0x52e08;
method void voidBeginAndEndCalls(bool x) = 0x52f74;
method void colorABGR(int color) = 0x52b54;
method void color(int r, int g, int b, int a) = 0x52a48;
method void noColor() = 0x52d54;
method void enableColor() = 0x52f7c;
method void vertex(float x, float y, float z) = 0x52bc0;
method void tex(float u, float v) = 0x52a2c;
method void vertexUV(float x, float y, float z, float u, float v) = 0x52d40;
method void scale2d(float sx, float sy) = 0x52b94;
method void resetScale() = 0x52bb0;
method void normal(float nx, float ny, float nz) = 0x52d68;
method void offset(float x, float y, float z) = 0x52d80;
method void addOffset(float x, float y, float z) = 0x52d90;
method void offset_vec3(const Vec3 &x) = 0x52db8;
method void addOffset_vec3(const Vec3 &x) = 0x52dd4;
property bool active = 0x3c;
property int mode = 0x58;
property int next_buffer_id = 0x44;
property uint *buffers = 0x48;
property int buffer_count = 0x40;
property float offset_x = 0x8;
property float offset_y = 0xc;
property float offset_z = 0x10;
property bool has_texture = 0x2d;
property float u = 0x14;
property float v = 0x18;
property bool has_color = 0x2c;
property uint _color = 0x1c;
property float sx = 0x24;
property float sy = 0x28;
property bool void_begin_end = 0x30;
static-property Tesselator instance = 0x137538;