From 18f7d644059a9703cd847f9185077c6b69fa8dae Mon Sep 17 00:00:00 2001 From: TheBrokenRail Date: Fri, 18 Oct 2024 15:14:18 -0400 Subject: [PATCH] Entities Have Shading! --- media-layer/gles/src/passthrough.cpp | 12 ++++ media-layer/include/GLES/gl.h | 14 ++++ media-layer/trampoline/src/GLESv1_CM.cpp | 64 ++++++++++++++++--- mods/CMakeLists.txt | 2 + mods/src/misc/graphics.cpp | 7 +- mods/src/shading/init.cpp | 2 + mods/src/shading/lighting.cpp | 55 ++++++++++++++++ mods/src/shading/normals.cpp | 26 ++++++++ mods/src/shading/shading-internal.h | 4 +- mods/src/shading/tesselator.cpp | 43 +++++++------ symbols/CMakeLists.txt | 6 +- .../src/entity/{ => model}/HumanoidModel.def | 0 symbols/src/entity/{ => model}/ModelPart.def | 0 symbols/src/entity/model/PolygonQuad.def | 3 + symbols/src/entity/model/VertexPT.def | 7 ++ symbols/src/level/renderer/LevelRenderer.def | 1 + symbols/src/misc/Vec3.def | 2 + 17 files changed, 211 insertions(+), 37 deletions(-) create mode 100644 mods/src/shading/lighting.cpp create mode 100644 mods/src/shading/normals.cpp rename symbols/src/entity/{ => model}/HumanoidModel.def (100%) rename symbols/src/entity/{ => model}/ModelPart.def (100%) create mode 100644 symbols/src/entity/model/PolygonQuad.def create mode 100644 symbols/src/entity/model/VertexPT.def diff --git a/media-layer/gles/src/passthrough.cpp b/media-layer/gles/src/passthrough.cpp index 36778c5f2d..5cb9b2cfae 100644 --- a/media-layer/gles/src/passthrough.cpp +++ b/media-layer/gles/src/passthrough.cpp @@ -231,4 +231,16 @@ void glGenBuffers(const GLsizei n, GLuint *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); +} +GL_FUNC(glLightfv, void, (GLenum light, GLenum pname, const GLfloat *params)) +void glLightfv(const GLenum light, const GLenum pname, const GLfloat *params) { + real_glLightfv()(light, pname, params); +} +GL_FUNC(glColorMaterial, void, (GLenum face, GLenum mode)) +void glColorMaterial(const GLenum face, const GLenum mode) { + real_glColorMaterial()(face, mode); +} +GL_FUNC(glLightModelfv, void, (GLenum pname, const GLfloat *params)) +void glLightModelfv(const GLenum pname, const GLfloat *params) { + real_glLightModelfv()(pname, params); } \ No newline at end of file diff --git a/media-layer/include/GLES/gl.h b/media-layer/include/GLES/gl.h index 86ca5a5a27..7228e4a010 100644 --- a/media-layer/include/GLES/gl.h +++ b/media-layer/include/GLES/gl.h @@ -88,6 +88,17 @@ extern "C" { #define GL_ALPHA 0x1906 #define GL_NONE 0 #define GL_ALIASED_LINE_WIDTH_RANGE 0x846e +#define GL_LIGHTING 0xb50 +#define GL_LIGHT0 0x4000 +#define GL_LIGHT1 0x4001 +#define GL_RESCALE_NORMAL 0x803a +#define GL_POSITION 0x1203 +#define GL_DIFFUSE 0x1201 +#define GL_AMBIENT 0x1200 +#define GL_SPECULAR 0x1202 +#define GL_FRONT_AND_BACK 0x408 +#define GL_AMBIENT_AND_DIFFUSE 0x1602 +#define GL_LIGHT_MODEL_AMBIENT 0xb53 typedef float GLfloat; typedef float GLclampf; @@ -161,6 +172,9 @@ void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const void 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); +void glLightfv(GLenum light, GLenum pname, const GLfloat *params); +void glColorMaterial(GLenum face, GLenum mode); +void glLightModelfv(GLenum pname, const GLfloat *params); #ifdef __cplusplus } diff --git a/media-layer/trampoline/src/GLESv1_CM.cpp b/media-layer/trampoline/src/GLESv1_CM.cpp index 56460b50a6..5722e51a40 100644 --- a/media-layer/trampoline/src/GLESv1_CM.cpp +++ b/media-layer/trampoline/src/GLESv1_CM.cpp @@ -353,6 +353,10 @@ void glDisableClientState(const GLenum array) { gl_array_details.glTexCoordPointer.size = -1; break; } + case GL_NORMAL_ARRAY: { + gl_array_details.glNormalPointer.size = -1; + break; + } } } #endif @@ -387,6 +391,7 @@ void glBindBuffer(const GLenum target, const GLuint buffer) { gl_array_details.glVertexPointer.size = -1; gl_array_details.glColorPointer.size = -1; gl_array_details.glTexCoordPointer.size = -1; + gl_array_details.glNormalPointer.size = -1; } #endif @@ -674,11 +679,17 @@ CALL(56, glViewport, void, (GLint x, GLint y, GLsizei width, GLsizei height)) #endif } +CALL(57, glNormal3f, void, (GLfloat nx, GLfloat ny, GLfloat nz)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST -void glNormal3f(__attribute__((unused)) GLfloat nx, __attribute__((unused)) GLfloat ny, __attribute__((unused)) GLfloat nz) { - // Do Nothing -} + trampoline(true, nx, ny, nz); +#else + GLfloat nx = args.next(); + GLfloat ny = args.next(); + GLfloat nz = args.next(); + func(nx, ny, nz); + return 0; #endif +} CALL(58, glIsEnabled, GLboolean, (GLenum cap)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST @@ -771,12 +782,13 @@ CALL(69, glBufferSubData, void, (GLenum target, GLintptr offset, GLsizeiptr size 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); \ + gl_array_details_t &state = gl_array_details.glNormalPointer; + if (state.size == -1 || state.type != type || state.stride != stride || state.pointer != uint32_t(pointer)) { + state.size = 0; + 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()); @@ -784,4 +796,38 @@ CALL(72, glNormalPointer, void, (GLenum type, GLsizei stride, const void *pointe func(state.type, state.stride, (const void *) uintptr_t(state.pointer)); return 0; #endif +} + +CALL(73, glLightfv, void, (GLenum light, GLenum pname, const GLfloat *params)) +#ifdef MEDIA_LAYER_TRAMPOLINE_GUEST + trampoline(true, light, pname, copy_array(4, params)); +#else + GLenum light = args.next(); + GLenum pname = args.next(); + const GLfloat *params = args.next_arr(); + func(light, pname, params); + return 0; +#endif +} + +CALL(74, glColorMaterial, void, (GLenum face, GLenum mode)) +#ifdef MEDIA_LAYER_TRAMPOLINE_GUEST + trampoline(true, face, mode); +#else + GLenum face = args.next(); + GLenum mode = args.next(); + func(face, mode); + return 0; +#endif +} + +CALL(75, glLightModelfv, void, (GLenum pname, const GLfloat *params)) +#ifdef MEDIA_LAYER_TRAMPOLINE_GUEST + trampoline(true, pname, copy_array(4, params)); +#else + GLenum pname = args.next(); + const GLfloat *params = args.next_arr(); + func(pname, params); + return 0; +#endif } \ No newline at end of file diff --git a/mods/CMakeLists.txt b/mods/CMakeLists.txt index 7a16f04b59..9198636584 100644 --- a/mods/CMakeLists.txt +++ b/mods/CMakeLists.txt @@ -102,6 +102,8 @@ set(SRC # shading src/shading/init.cpp src/shading/tesselator.cpp + src/shading/lighting.cpp + src/shading/normals.cpp ) # Install Splashes install( diff --git a/mods/src/misc/graphics.cpp b/mods/src/misc/graphics.cpp index c067f1e8d8..a61b20a6e0 100644 --- a/mods/src/misc/graphics.cpp +++ b/mods/src/misc/graphics.cpp @@ -346,14 +346,13 @@ static void ModelPart_render_injection(ModelPart *model_part, float scale) { // Stop is_rendering_chest = false; } -static void Tesselator_vertexUV_injection(Tesselator_vertexUV_t original, Tesselator *tesselator, const float x, const float y, const float z, const float u, float v) { +static void Tesselator_vertexUV_injection(Tesselator *self, const float x, const float y, const float z, const float u, float v) { // Fix Chest Texture if (is_rendering_chest) { v /= 2; } - // Call Original Method - original(tesselator, x, y, z, u, v); + self->vertexUV(x, y, z, u, v); } static bool ChestTileEntity_shouldSave_injection(__attribute__((unused)) ChestTileEntity_shouldSave_t original, __attribute__((unused)) ChestTileEntity *tile_entity) { return true; @@ -555,7 +554,7 @@ void _init_misc_graphics() { overwrite_call((void *) 0x6655c, (void *) ModelPart_render_injection); overwrite_call((void *) 0x66568, (void *) ModelPart_render_injection); overwrite_call((void *) 0x66574, (void *) ModelPart_render_injection); - overwrite_calls(Tesselator_vertexUV, Tesselator_vertexUV_injection); + overwrite_call((void *) 0x4278c, (void *) Tesselator_vertexUV_injection); unsigned char chest_model_patch[4] = {0x13, 0x20, 0xa0, 0xe3}; // "mov r2, #0x13" patch((void *) 0x66fc8, chest_model_patch); unsigned char chest_color_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop" diff --git a/mods/src/shading/init.cpp b/mods/src/shading/init.cpp index c225cce973..5f586127d9 100644 --- a/mods/src/shading/init.cpp +++ b/mods/src/shading/init.cpp @@ -7,5 +7,7 @@ void init_shading() { if (feature_has("Proper Entity Shading", server_disabled)) { _init_custom_tesselator(); + _init_normals(); + _init_lighting(); } } \ No newline at end of file diff --git a/mods/src/shading/lighting.cpp b/mods/src/shading/lighting.cpp new file mode 100644 index 0000000000..b8da6aa8a2 --- /dev/null +++ b/mods/src/shading/lighting.cpp @@ -0,0 +1,55 @@ +#include +#include +#include + +#include "shading-internal.h" + +// OpenGL Lighting +static float *get_buffer(const float a, const float b, const float c, const float d) { + static float buffer[4]; + buffer[0] = a; + buffer[1] = b; + buffer[2] = c; + buffer[3] = d; + return buffer; +} +static void lighting_turn_on() { + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_LIGHT1); + glEnable(GL_COLOR_MATERIAL); + glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); + constexpr float a = 0.4f; + constexpr float d = 0.6f; + constexpr float s = 0.0f; + Vec3 l = Vec3(0.2f, 1.0f, -0.7f).normalized(); + glLightfv(GL_LIGHT0, GL_POSITION, get_buffer(l.x, l.y, l.z, 0)); + glLightfv(GL_LIGHT0, GL_DIFFUSE, get_buffer(d, d, d, 1)); + glLightfv(GL_LIGHT0, GL_AMBIENT, get_buffer(0, 0, 0, 1)); + glLightfv(GL_LIGHT0, GL_SPECULAR, get_buffer(s, s, s, 1.0f)); + l = Vec3(-0.2f, 1.0f, 0.7f).normalized(); + glLightfv(GL_LIGHT1, GL_POSITION, get_buffer(l.x, l.y, l.z, 0)); + glLightfv(GL_LIGHT1, GL_DIFFUSE, get_buffer(d, d, d, 1)); + glLightfv(GL_LIGHT1, GL_AMBIENT, get_buffer(0, 0, 0, 1)); + glLightfv(GL_LIGHT1, GL_SPECULAR, get_buffer(s, s, s, 1.0f)); + glShadeModel(GL_FLAT); + glLightModelfv(GL_LIGHT_MODEL_AMBIENT, get_buffer(a, a, a, 1)); +} +static void lighting_turn_off() { + glDisable(GL_LIGHTING); + glDisable(GL_LIGHT0); + glDisable(GL_LIGHT1); + glDisable(GL_COLOR_MATERIAL); +} + +// Entity Rendering +static void LevelRenderer_renderEntities_injection(LevelRenderer_renderEntities_t original, LevelRenderer *self, Vec3 pos, void *unknown, float a) { + lighting_turn_on(); + original(self, pos, unknown, a); + lighting_turn_off(); +} + +// Init +void _init_lighting() { + overwrite_calls(LevelRenderer_renderEntities, LevelRenderer_renderEntities_injection); +} \ No newline at end of file diff --git a/mods/src/shading/normals.cpp b/mods/src/shading/normals.cpp new file mode 100644 index 0000000000..168fd99b74 --- /dev/null +++ b/mods/src/shading/normals.cpp @@ -0,0 +1,26 @@ +#include +#include + +#include "shading-internal.h" + +// PolygonQuad +Vec3 vector_to(const Vec3 &a, const Vec3 &b) { + return Vec3(a.x - b.x, a.y - b.y, a.z - b.z); +} +Vec3 vector_cross(const Vec3 &a, const Vec3 &b) { + return Vec3(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x); +} +static void PolygonQuad_render_injection(PolygonQuad_render_t original, PolygonQuad *self, Tesselator &t, float scale, int buffer) { + // Set Normal + const Vec3 v0 = vector_to(self->vertices[1].pos, self->vertices[0].pos); + const Vec3 v1 = vector_to(self->vertices[1].pos, self->vertices[2].pos); + const Vec3 n = vector_cross(v1, v0).normalized(); + t.normal(n.x, n.y, n.z); + // Call Original Method + original(self, t, scale, buffer); +} + +// Init +void _init_normals() { + overwrite_calls(PolygonQuad_render, PolygonQuad_render_injection); +} \ No newline at end of file diff --git a/mods/src/shading/shading-internal.h b/mods/src/shading/shading-internal.h index e7134851b1..aad370bad4 100644 --- a/mods/src/shading/shading-internal.h +++ b/mods/src/shading/shading-internal.h @@ -1,3 +1,5 @@ #pragma once -__attribute__((visibility("internal"))) void _init_custom_tesselator(); \ No newline at end of file +__attribute__((visibility("internal"))) void _init_custom_tesselator(); +__attribute__((visibility("internal"))) void _init_normals(); +__attribute__((visibility("internal"))) void _init_lighting(); \ No newline at end of file diff --git a/mods/src/shading/tesselator.cpp b/mods/src/shading/tesselator.cpp index 9a0851e486..632193de6b 100644 --- a/mods/src/shading/tesselator.cpp +++ b/mods/src/shading/tesselator.cpp @@ -31,6 +31,7 @@ struct CustomTesselator { }; CustomTesselator CustomTesselator::instance; +// Setup Vertex Array static void Tesselator_clear_injection(Tesselator_clear_t original, Tesselator *self) { if (original) { original(self); @@ -39,7 +40,6 @@ static void Tesselator_clear_injection(Tesselator_clear_t original, Tesselator * 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); @@ -47,6 +47,7 @@ static void Tesselator_init_injection(Tesselator_init_t original, Tesselator *se Tesselator_clear_injection(nullptr, nullptr); } +// Handle Tesselation Start static void Tesselator_begin_injection(Tesselator_begin_t original, Tesselator *self, const int mode) { original(self, mode); if (!self->void_begin_end) { @@ -54,13 +55,13 @@ static void Tesselator_begin_injection(Tesselator_begin_t original, Tesselator * } } +// Drawing 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) { @@ -83,7 +84,6 @@ static RenderChunk Tesselator_end_injection(Tesselator *self, const bool use_giv self->active = false; return out; } - static void Tesselator_draw_injection(Tesselator *self) { // Check if (!self->active) { @@ -132,7 +132,22 @@ static void Tesselator_draw_injection(Tesselator *self) { self->clear(); self->active = false; } +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); +} +// Add Vertex 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 = { @@ -166,28 +181,14 @@ static void Tesselator_vertex_injection(const Tesselator *self, const float x, c } } +// Specify Normal 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); + const signed char xx = (signed char) (nx * 127); + const signed char yy = (signed char) (ny * 127); + const signed char zz = (signed 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); diff --git a/symbols/CMakeLists.txt b/symbols/CMakeLists.txt index 1114e3f945..ceae189e3f 100644 --- a/symbols/CMakeLists.txt +++ b/symbols/CMakeLists.txt @@ -35,7 +35,7 @@ set(SRC src/entity/EntityRenderer.def src/entity/ItemSpriteRenderer.def src/entity/PathfinderMob.def - src/entity/HumanoidModel.def + src/entity/model/HumanoidModel.def src/entity/TripodCameraRenderer.def src/entity/TripodCamera.def src/entity/MobFactory.def @@ -161,7 +161,9 @@ set(SRC src/misc/Strings.def src/misc/I18n.def src/misc/SimpleFoodData.def - src/entity/ModelPart.def + src/entity/model/ModelPart.def + src/entity/model/PolygonQuad.def + src/entity/model/VertexPT.def src/misc/Tesselator.def src/misc/AABB.def src/misc/Vec3.def diff --git a/symbols/src/entity/HumanoidModel.def b/symbols/src/entity/model/HumanoidModel.def similarity index 100% rename from symbols/src/entity/HumanoidModel.def rename to symbols/src/entity/model/HumanoidModel.def diff --git a/symbols/src/entity/ModelPart.def b/symbols/src/entity/model/ModelPart.def similarity index 100% rename from symbols/src/entity/ModelPart.def rename to symbols/src/entity/model/ModelPart.def diff --git a/symbols/src/entity/model/PolygonQuad.def b/symbols/src/entity/model/PolygonQuad.def new file mode 100644 index 0000000000..63e07f5b00 --- /dev/null +++ b/symbols/src/entity/model/PolygonQuad.def @@ -0,0 +1,3 @@ +method void render(Tesselator &t, float scale, int buffer) = 0x42744; + +property VertexPT vertices[4] = 0x0; \ No newline at end of file diff --git a/symbols/src/entity/model/VertexPT.def b/symbols/src/entity/model/VertexPT.def new file mode 100644 index 0000000000..122fa20473 --- /dev/null +++ b/symbols/src/entity/model/VertexPT.def @@ -0,0 +1,7 @@ +size 0x14; + +property Vec3 pos = 0x0; +property float u = 0xc; +property float v = 0x10; + +mark-as-simple; \ No newline at end of file diff --git a/symbols/src/level/renderer/LevelRenderer.def b/symbols/src/level/renderer/LevelRenderer.def index f66e4f9f7f..b4a9be0add 100644 --- a/symbols/src/level/renderer/LevelRenderer.def +++ b/symbols/src/level/renderer/LevelRenderer.def @@ -6,6 +6,7 @@ method void generateSky() = 0x4d0d4; method void renderHitSelect(Player *player, const HitResult &hit_result, int i, void *vp, float f) = 0x4e318; method void renderHitOutline(Player *player, const HitResult &hit_result, int i, void *vp, float f) = 0x4dc14; method int renderChunks(int start, int end, int a, float b) = 0x4f35c; +method void renderEntities(Vec3 pos, void *unknown, float a) = 0x500ec; property Minecraft *minecraft = 0xb4; property RenderList render_list = 0x34; diff --git a/symbols/src/misc/Vec3.def b/symbols/src/misc/Vec3.def index 5ed176cd1d..078b7808f2 100644 --- a/symbols/src/misc/Vec3.def +++ b/symbols/src/misc/Vec3.def @@ -1,5 +1,7 @@ size 0xc; +method Vec3 normalized() = 0x5eae4; + property float x = 0x0; property float y = 0x4; property float z = 0x8;