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

@ -112,4 +112,5 @@ TRUE Click Buttons On Mouse Down
TRUE 3D Dropped Items
TRUE Render Entity Shadows
TRUE Render Vignette
TRUE Increase Render Chunk Size
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);
}
@ -761,4 +767,21 @@ CALL(69, glBufferSubData, void, (GLenum target, GLintptr offset, GLsizeiptr size
func(target, offset, size, data);
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;