Entities Have Shading!
This commit is contained in:
parent
1001427309
commit
18f7d64405
@ -232,3 +232,15 @@ 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);
|
||||
}
|
@ -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
|
||||
}
|
||||
|
@ -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>();
|
||||
GLfloat ny = args.next<GLfloat>();
|
||||
GLfloat nz = args.next<GLfloat>();
|
||||
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<GLuint>());
|
||||
@ -785,3 +797,37 @@ CALL(72, glNormalPointer, void, (GLenum type, GLsizei stride, const void *pointe
|
||||
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>();
|
||||
GLenum pname = args.next<GLenum>();
|
||||
const GLfloat *params = args.next_arr<GLfloat>();
|
||||
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>();
|
||||
GLenum mode = args.next<GLenum>();
|
||||
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<GLenum>();
|
||||
const GLfloat *params = args.next_arr<GLfloat>();
|
||||
func(pname, params);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
@ -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(
|
||||
|
@ -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"
|
||||
|
@ -7,5 +7,7 @@
|
||||
void init_shading() {
|
||||
if (feature_has("Proper Entity Shading", server_disabled)) {
|
||||
_init_custom_tesselator();
|
||||
_init_normals();
|
||||
_init_lighting();
|
||||
}
|
||||
}
|
55
mods/src/shading/lighting.cpp
Normal file
55
mods/src/shading/lighting.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
#include <GLES/gl.h>
|
||||
#include <symbols/minecraft.h>
|
||||
#include <libreborn/libreborn.h>
|
||||
|
||||
#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);
|
||||
}
|
26
mods/src/shading/normals.cpp
Normal file
26
mods/src/shading/normals.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
#include <symbols/minecraft.h>
|
||||
#include <libreborn/libreborn.h>
|
||||
|
||||
#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);
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
__attribute__((visibility("internal"))) void _init_custom_tesselator();
|
||||
__attribute__((visibility("internal"))) void _init_normals();
|
||||
__attribute__((visibility("internal"))) void _init_lighting();
|
@ -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);
|
||||
|
@ -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
|
||||
|
3
symbols/src/entity/model/PolygonQuad.def
Normal file
3
symbols/src/entity/model/PolygonQuad.def
Normal file
@ -0,0 +1,3 @@
|
||||
method void render(Tesselator &t, float scale, int buffer) = 0x42744;
|
||||
|
||||
property VertexPT vertices[4] = 0x0;
|
7
symbols/src/entity/model/VertexPT.def
Normal file
7
symbols/src/entity/model/VertexPT.def
Normal file
@ -0,0 +1,7 @@
|
||||
size 0x14;
|
||||
|
||||
property Vec3 pos = 0x0;
|
||||
property float u = 0xc;
|
||||
property float v = 0x10;
|
||||
|
||||
mark-as-simple;
|
@ -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;
|
||||
|
@ -1,5 +1,7 @@
|
||||
size 0xc;
|
||||
|
||||
method Vec3 normalized() = 0x5eae4;
|
||||
|
||||
property float x = 0x0;
|
||||
property float y = 0x4;
|
||||
property float z = 0x8;
|
||||
|
Loading…
Reference in New Issue
Block a user