mirror of
https://github.com/4jcraft/4jcraft.git
synced 2026-05-21 12:22:56 +00:00
find my renderers - slenderman or some shit
This commit is contained in:
parent
ad50bf21d4
commit
6b6fa9a6b0
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -29,3 +29,4 @@ Common
|
|||
*.a
|
||||
*.so
|
||||
*.out
|
||||
oldimpl
|
||||
|
|
@ -237,13 +237,6 @@ static GLenum mapPrimType(int pt)
|
|||
}
|
||||
|
||||
// clientside awawawa
|
||||
static bool isCompilingDisplayList()
|
||||
{
|
||||
GLint listMode = 0;
|
||||
::glGetIntegerv(GL_LIST_MODE, &listMode);
|
||||
return (listMode == GL_COMPILE || listMode == GL_COMPILE_AND_EXECUTE);
|
||||
}
|
||||
|
||||
void C4JRender::DrawVertices(ePrimitiveType PrimitiveType, int count,
|
||||
void *dataIn, eVertexType vType,
|
||||
C4JRender::ePixelShaderType psType)
|
||||
|
|
@ -251,60 +244,67 @@ void C4JRender::DrawVertices(ePrimitiveType PrimitiveType, int count,
|
|||
if (count <= 0 || !dataIn) return;
|
||||
|
||||
GLenum mode = mapPrimType((int)PrimitiveType);
|
||||
unsigned char *data = (unsigned char *)dataIn;
|
||||
|
||||
// Vertex layout: 3 floats pos, 2 floats tex, 4 bytes color, 4 bytes normal, 4 bytes padding = 32 bytes
|
||||
const int stride = 32;
|
||||
|
||||
// Color byte-order fix for little-endian (x86/x64):
|
||||
// Console code (Xbox 360 / PS3, big-endian) stores color as int col = (r<<24)|(g<<16)|(b<<8)|a
|
||||
// Big-endian memory: [r, g, b, a] — correct for glColor4ub(col[0], col[1], col[2], col[3])
|
||||
// Little-endian memory: [a, b, g, r] — bytes are reversed!
|
||||
// Fix: read bytes in reverse order col[3]=r, col[2]=g, col[1]=b, col[0]=a
|
||||
|
||||
if (isCompilingDisplayList()) {
|
||||
if (vType == VERTEX_TYPE_COMPRESSED) {
|
||||
// Compact terrain vertex: 8 × int16_t = 16 bytes per vertex
|
||||
// Layout: [x*1024, y*1024, z*1024, RGB565-32768, u*8192, v*8192, tex2u, tex2v]
|
||||
// Always use glBegin/glEnd — works correctly both inside and outside display lists.
|
||||
int16_t *sdata = (int16_t *)dataIn;
|
||||
::glBegin(mode);
|
||||
for (int i = 0; i < count; i++) {
|
||||
unsigned char *v = data + i * stride;
|
||||
float *pos = (float *)(v);
|
||||
float *tex = (float *)(v + 12);
|
||||
unsigned char *col = v + 20;
|
||||
signed char *nrm = (signed char *)(v + 24);
|
||||
int16_t *vert = sdata + i * 8;
|
||||
|
||||
::glNormal3f(nrm[0] / 127.0f, nrm[1] / 127.0f, nrm[2] / 127.0f);
|
||||
::glColor4ub(col[3], col[2], col[1], col[0]); // LE fix: r,g,b,a from reversed bytes
|
||||
::glTexCoord2f(tex[0], tex[1]);
|
||||
::glVertex3f(pos[0], pos[1], pos[2]);
|
||||
float x = vert[0] / 1024.0f;
|
||||
float y = vert[1] / 1024.0f;
|
||||
float z = vert[2] / 1024.0f;
|
||||
|
||||
// Unpack RGB565 colour (Tesselator stores as packedcol - 32768 to fit in int16)
|
||||
unsigned short packedColor = (unsigned short)((int)vert[3] + 32768);
|
||||
float r = ((packedColor >> 11) & 0x1f) / 31.0f;
|
||||
float g = ((packedColor >> 5) & 0x3f) / 63.0f;
|
||||
float b = ( packedColor & 0x1f) / 31.0f;
|
||||
|
||||
float fu = vert[4] / 8192.0f;
|
||||
float fv = vert[5] / 8192.0f;
|
||||
// Strip mipmap-disable flag: Tesselator adds +1.0 (= +8192) to u when mipmaps off
|
||||
if (fu >= 1.0f) fu -= 1.0f;
|
||||
|
||||
::glColor3f(r, g, b);
|
||||
::glTexCoord2f(fu, fv);
|
||||
::glVertex3f(x, y, z);
|
||||
}
|
||||
::glEnd();
|
||||
} else {
|
||||
// For vertex array path, swap color bytes in-place to RGBA order
|
||||
// Standard (non-compact) vertex: 8 × int32 = 32 bytes per vertex
|
||||
// Layout: [x(f), y(f), z(f), u(f), v(f), color(RGBA packed), normal, tex2]
|
||||
// Color byte-order fix for little-endian (x86/x64):
|
||||
// Console code stores color as int col = (r<<24)|(g<<16)|(b<<8)|a
|
||||
// In little-endian memory the bytes are: [a, b, g, r] at increasing addresses.
|
||||
// Read as: col[3]=r, col[2]=g, col[1]=b, col[0]=a.
|
||||
// Always use glBegin/glEnd — safe for both display-list compilation and immediate mode.
|
||||
// (glVertexPointer/glDrawArrays inside glNewList record a stale pointer, not the data.)
|
||||
unsigned int *idata = (unsigned int *)dataIn;
|
||||
::glBegin(mode);
|
||||
for (int i = 0; i < count; i++) {
|
||||
unsigned char *col = data + i * stride + 20;
|
||||
unsigned char tmp;
|
||||
tmp = col[0]; col[0] = col[3]; col[3] = tmp; // swap a<->r
|
||||
tmp = col[1]; col[1] = col[2]; col[2] = tmp; // swap b<->g
|
||||
}
|
||||
|
||||
::glEnableClientState(GL_VERTEX_ARRAY);
|
||||
::glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
::glEnableClientState(GL_COLOR_ARRAY);
|
||||
::glEnableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
::glVertexPointer(3, GL_FLOAT, stride, data);
|
||||
::glTexCoordPointer(2, GL_FLOAT, stride, data + 12);
|
||||
::glColorPointer(4, GL_UNSIGNED_BYTE, stride, data + 20);
|
||||
::glNormalPointer(GL_BYTE, stride, data + 24);
|
||||
|
||||
::glDrawArrays(mode, 0, count);
|
||||
|
||||
// Swap back to preserve original data
|
||||
for (int i = 0; i < count; i++) {
|
||||
unsigned char *col = data + i * stride + 20;
|
||||
unsigned char tmp;
|
||||
tmp = col[0]; col[0] = col[3]; col[3] = tmp;
|
||||
tmp = col[1]; col[1] = col[2]; col[2] = tmp;
|
||||
float *fdata = (float *)(idata + i * 8);
|
||||
|
||||
unsigned int colorInt = idata[i * 8 + 5];
|
||||
unsigned char cr = (colorInt >> 24) & 0xFF;
|
||||
unsigned char cg = (colorInt >> 16) & 0xFF;
|
||||
unsigned char cb = (colorInt >> 8) & 0xFF;
|
||||
unsigned char ca = colorInt & 0xFF;
|
||||
|
||||
unsigned int normalInt = idata[i * 8 + 6];
|
||||
int8_t nx = (int8_t)( normalInt & 0xFF);
|
||||
int8_t ny = (int8_t)((normalInt >> 8) & 0xFF);
|
||||
int8_t nz = (int8_t)((normalInt >> 16) & 0xFF);
|
||||
|
||||
::glNormal3f(nx / 127.0f, ny / 127.0f, nz / 127.0f);
|
||||
::glColor4ub(cr, cg, cb, ca);
|
||||
::glTexCoord2f(fdata[3], fdata[4]);
|
||||
::glVertex3f(fdata[0], fdata[1], fdata[2]);
|
||||
}
|
||||
::glEnd();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -374,37 +374,44 @@ void C4JRender::TextureBind(int idx)
|
|||
|
||||
void C4JRender::TextureBindVertex(int idx)
|
||||
{
|
||||
::glActiveTexture(GL_TEXTURE1);
|
||||
if (idx < 0) {
|
||||
::glBindTexture(GL_TEXTURE_2D, 0);
|
||||
} else {
|
||||
::glBindTexture(GL_TEXTURE_2D, (GLuint)idx);
|
||||
}
|
||||
::glActiveTexture(GL_TEXTURE0);
|
||||
// No-op on desktop OpenGL. On consoles this binds a lightmap to the vertex shader
|
||||
// sampler. On desktop GL 2.1 fixed-function there is no vertex texture concept;
|
||||
// lighting is handled via vertex colors. Binding anything here OVERRIDES GL_TEXTURE0
|
||||
// after the call (because the game calls glTexParameteri on whatever is active),
|
||||
// causing the terrain atlas filter params to be corrupted or the lightmap to appear
|
||||
// on terrain instead of the atlas. Leave it as a no-op.
|
||||
(void)idx;
|
||||
}
|
||||
|
||||
void C4JRender::TextureSetTextureLevels(int levels) { s_textureLevels = levels; }
|
||||
void C4JRender::TextureSetTextureLevels(int levels)
|
||||
{
|
||||
// Set GL_TEXTURE_MAX_LEVEL so OpenGL knows how many mip levels this texture has.
|
||||
// Without this, the default is 1000, and any texture that doesn't upload all 1000
|
||||
// levels is considered "incomplete" and renders as white.
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, levels > 0 ? levels - 1 : 0);
|
||||
s_textureLevels = levels;
|
||||
}
|
||||
int C4JRender::TextureGetTextureLevels() { return s_textureLevels; }
|
||||
|
||||
void C4JRender::TextureData(int width, int height, void *data, int level,
|
||||
eTextureFormat /*format*/)
|
||||
{
|
||||
::glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA8,
|
||||
// Game produces [r,g,b,a] bytes via the non-Xbox transferFromImage/loadTexture paths.
|
||||
// Use GL_RGBA so OpenGL interprets them correctly. GL_BGRA would swap R and B channels.
|
||||
::glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA,
|
||||
width, height, 0,
|
||||
GL_BGRA, GL_UNSIGNED_BYTE, data);
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||
|
||||
// Do NOT set filter params here — the game calls glTexParameteri with the correct
|
||||
// filter settings (GL_NEAREST_MIPMAP_LINEAR etc.) BEFORE calling TextureData.
|
||||
// Setting params here would override those mipmap settings.
|
||||
// Only guarantee the texture is always complete by generating mipmaps as a safety net.
|
||||
if (level == 0) {
|
||||
if (s_textureLevels > 1) {
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
|
||||
GL_NEAREST_MIPMAP_LINEAR);
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL,
|
||||
s_textureLevels - 1);
|
||||
} else {
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
GLint maxLevel = 0;
|
||||
::glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, &maxLevel);
|
||||
if (maxLevel > 0) {
|
||||
::glGenerateMipmap(GL_TEXTURE_2D);
|
||||
}
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -413,7 +420,7 @@ void C4JRender::TextureDataUpdate(int xoffset, int yoffset,
|
|||
void *data, int level)
|
||||
{
|
||||
::glTexSubImage2D(GL_TEXTURE_2D, level, xoffset, yoffset,
|
||||
width, height, GL_BGRA, GL_UNSIGNED_BYTE, data);
|
||||
width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||
}
|
||||
|
||||
void C4JRender::TextureSetParam(int param, int value)
|
||||
|
|
@ -645,7 +652,15 @@ void C4JRender::StateSetFogColour(float red, float green, float blue)
|
|||
|
||||
void C4JRender::StateSetLightingEnable(bool enable)
|
||||
{
|
||||
if (enable) ::glEnable(GL_LIGHTING); else ::glDisable(GL_LIGHTING);
|
||||
if (enable) {
|
||||
::glEnable(GL_LIGHTING);
|
||||
// Enable color material so glColor calls set material ambient+diffuse
|
||||
::glEnable(GL_COLOR_MATERIAL);
|
||||
::glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
|
||||
} else {
|
||||
::glDisable(GL_LIGHTING);
|
||||
::glDisable(GL_COLOR_MATERIAL);
|
||||
}
|
||||
}
|
||||
|
||||
void C4JRender::StateSetVertexTextureUV(float u, float v)
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@
|
|||
#include <signal.h>
|
||||
#include <execinfo.h>
|
||||
#include <unistd.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
static void sigsegv_handler(int sig) {
|
||||
const char msg[] = "\n=== SIGNAL CAUGHT: ";
|
||||
write(STDERR_FILENO, msg, sizeof(msg)-1);
|
||||
|
|
@ -870,70 +869,6 @@ pDevice->SetSamplerState(0,SamplerStateModes[i],SamplerStateA[i]);
|
|||
RenderManager.Set_matrixDirty();
|
||||
#endif
|
||||
|
||||
// DEBUG: Dump framebuffer to file once after game has been running a while
|
||||
{
|
||||
static int _fbDumpFrame = 0;
|
||||
_fbDumpFrame++;
|
||||
if (_fbDumpFrame == 2000 || _fbDumpFrame == 4000) {
|
||||
// Test: is GL context current? Force red clear before read.
|
||||
void* curCtx = glfwGetCurrentContext();
|
||||
fprintf(stderr, "[FBDUMP] frame=%d glfwGetCurrentContext()=%p\n", _fbDumpFrame, curCtx);
|
||||
fflush(stderr);
|
||||
// Read the ACTUAL rendered framebuffer first
|
||||
int fbW, fbH;
|
||||
RenderManager.GetFramebufferSize(fbW, fbH);
|
||||
int sz = fbW * fbH * 3;
|
||||
unsigned char *pixels = (unsigned char*)malloc(sz);
|
||||
if (pixels) {
|
||||
::glReadPixels(0, 0, fbW, fbH, GL_RGB, GL_UNSIGNED_BYTE, pixels);
|
||||
GLenum err = glGetError();
|
||||
fprintf(stderr, "[FBDUMP] glReadPixels err=0x%x size=%dx%d\n", err, fbW, fbH);
|
||||
// Check bound framebuffer
|
||||
GLint boundFBO = -1;
|
||||
#ifndef GL_FRAMEBUFFER_BINDING
|
||||
#define GL_FRAMEBUFFER_BINDING 0x8CA6
|
||||
#endif
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &boundFBO);
|
||||
GLint drawBuf = 0;
|
||||
glGetIntegerv(GL_DRAW_BUFFER, &drawBuf);
|
||||
GLint readBuf = 0;
|
||||
glGetIntegerv(GL_READ_BUFFER, &readBuf);
|
||||
fprintf(stderr, "[FBDUMP] FBO=%d drawBuf=0x%x readBuf=0x%x\n", boundFBO, drawBuf, readBuf);
|
||||
fflush(stderr);
|
||||
char fname[128];
|
||||
snprintf(fname, sizeof(fname), "/tmp/fb_dump_%d.ppm", _fbDumpFrame);
|
||||
FILE *fp = fopen(fname, "wb");
|
||||
if (fp) {
|
||||
fprintf(fp, "P6\n%d %d\n255\n", fbW, fbH);
|
||||
for (int y = fbH - 1; y >= 0; y--) {
|
||||
fwrite(pixels + y * fbW * 3, 1, fbW * 3, fp);
|
||||
}
|
||||
fclose(fp);
|
||||
fprintf(stderr, "[RENDER] Dumped framebuffer %dx%d to %s\n", fbW, fbH, fname);
|
||||
fflush(stderr);
|
||||
}
|
||||
// Now force a red clear and dump again to verify GL context works
|
||||
::glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
|
||||
::glClear(GL_COLOR_BUFFER_BIT);
|
||||
::glFinish();
|
||||
::glReadPixels(0, 0, fbW, fbH, GL_RGB, GL_UNSIGNED_BYTE, pixels);
|
||||
char fname2[128];
|
||||
snprintf(fname2, sizeof(fname2), "/tmp/fb_dump_%d_RED.ppm", _fbDumpFrame);
|
||||
FILE *fp2 = fopen(fname2, "wb");
|
||||
if (fp2) {
|
||||
fprintf(fp2, "P6\n%d %d\n255\n", fbW, fbH);
|
||||
for (int y = fbH - 1; y >= 0; y--) {
|
||||
fwrite(pixels + y * fbW * 3, 1, fbW * 3, fp2);
|
||||
}
|
||||
fclose(fp2);
|
||||
fprintf(stderr, "[RENDER] Dumped RED test %dx%d to %s\n", fbW, fbH, fname2);
|
||||
fflush(stderr);
|
||||
}
|
||||
free(pixels);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Present the frame.
|
||||
RenderManager.Present();
|
||||
|
||||
|
|
|
|||
|
|
@ -1294,23 +1294,6 @@ void GameRenderer::renderLevel(float a, __int64 until)
|
|||
|
||||
setupCamera(a, i);
|
||||
Camera::prepare(mc->player, mc->player->ThirdPersonView() == 2);
|
||||
// DEBUG: Log camera-relevant state
|
||||
static int _dbgCam = 0;
|
||||
_dbgCam++;
|
||||
if (_dbgCam <= 5 || (_dbgCam % 300 == 0)) {
|
||||
float mv[16]; ::glGetFloatv(GL_MODELVIEW_MATRIX, mv);
|
||||
float pj[16]; ::glGetFloatv(GL_PROJECTION_MATRIX, pj);
|
||||
float cc[4]; ::glGetFloatv(GL_COLOR_CLEAR_VALUE, cc);
|
||||
int vp[4]; ::glGetIntegerv(GL_VIEWPORT, vp);
|
||||
fprintf(stderr, "[RENDER] CAM frame=%d viewport=(%d,%d,%d,%d) clearColor=(%.2f,%.2f,%.2f) renderDist=%.0f\n",
|
||||
_dbgCam, vp[0], vp[1], vp[2], vp[3], cc[0], cc[1], cc[2], renderDistance);
|
||||
fprintf(stderr, "[RENDER] MV[12..14]=(%f,%f,%f) PJ[0,5,10]=(%f,%f,%f)\n",
|
||||
mv[12], mv[13], mv[14], pj[0], pj[5], pj[10]);
|
||||
fprintf(stderr, "[RENDER] cameraEntity pos=(%.2f,%.2f,%.2f) heightOff=%.2f\n",
|
||||
mc->cameraTargetPlayer->x, mc->cameraTargetPlayer->y, mc->cameraTargetPlayer->z,
|
||||
mc->cameraTargetPlayer->heightOffset);
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
Frustum::getFrustum();
|
||||
if (mc->options->viewDistance < 2)
|
||||
|
|
|
|||
|
|
@ -801,9 +801,9 @@ int LevelRenderer::renderChunks(int from, int to, int layer, double alpha)
|
|||
}
|
||||
static int _dbgRC = 0;
|
||||
_dbgRC++;
|
||||
if (_dbgRC <= 5 || (_dbgRC % 600 == 0)) {
|
||||
fprintf(stderr, "[RENDER] renderChunks frame=%d layer=%d total=%d notVis=%d noIdx=%d empty=%d called=%d callOk=%d xOff=%.1f yOff=%.1f zOff=%.1f chunkLists=%d\n",
|
||||
_dbgRC, layer, chunks[playerIndex].length, dbgNotVisible, dbgNoIdx, dbgEmpty, dbgCalled, dbgCallOk, xOff, yOff, zOff, chunkLists);
|
||||
if (_dbgRC <= 2 || (_dbgRC % 3000 == 0)) {
|
||||
fprintf(stderr, "[RENDER] renderChunks frame=%d layer=%d total=%d notVis=%d noIdx=%d empty=%d called=%d callOk=%d chunkLists=%d\n",
|
||||
_dbgRC, layer, chunks[playerIndex].length, dbgNotVisible, dbgNoIdx, dbgEmpty, dbgCalled, dbgCallOk, chunkLists);
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ void Tesselator::CreateNewThreadStorage(int bytes)
|
|||
TlsSetValue(tlsIdx, instance);
|
||||
}
|
||||
|
||||
// she tessalate my vertices till i render
|
||||
Tesselator::Tesselator(int size)
|
||||
{
|
||||
// 4J - this block of things moved to constructor from general initialisations round Java class
|
||||
|
|
|
|||
|
|
@ -104,9 +104,8 @@ LevelType *LevelType::getLevelType(wstring name)
|
|||
{
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
wstring genname=levelTypes[i]->m_generatorName;
|
||||
|
||||
if (levelTypes[i] != NULL && (genname.compare(name)==0))
|
||||
// Fix: check NULL before accessing member to avoid null dereference
|
||||
if (levelTypes[i] != NULL && (levelTypes[i]->m_generatorName.compare(name)==0))
|
||||
{
|
||||
return levelTypes[i];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -382,6 +382,8 @@ shared_ptr<Packet> Packet::readPacket(DataInputStream *dis, bool isServer) // th
|
|||
}
|
||||
__debugbreak();
|
||||
//assert(false);
|
||||
// Close the stream to prevent further reads on a desynced stream
|
||||
dis->close();
|
||||
return nullptr;
|
||||
// throw new IOException(wstring(L"Bad packet id ") + _toString<int>(id));
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue