mirror of
https://github.com/4jcraft/4jcraft.git
synced 2026-08-20 09:57:10 +00:00
shit renderer
This commit is contained in:
parent
60ad8c291e
commit
ad50bf21d4
|
|
@ -8,6 +8,7 @@
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
C4JRender RenderManager;
|
C4JRender RenderManager;
|
||||||
|
|
||||||
|
|
@ -16,6 +17,24 @@ static int s_textureLevels = 1;
|
||||||
static int s_windowWidth = 1920;
|
static int s_windowWidth = 1920;
|
||||||
static int s_windowHeight = 1080;
|
static int s_windowHeight = 1080;
|
||||||
|
|
||||||
|
// Thread-local storage for per-thread shared GL contexts.
|
||||||
|
// The main thread uses s_window directly; worker threads get invisible
|
||||||
|
// windows that share objects (textures, display lists) with s_window.
|
||||||
|
static pthread_key_t s_glCtxKey;
|
||||||
|
static pthread_once_t s_glCtxKeyOnce = PTHREAD_ONCE_INIT;
|
||||||
|
static void makeGLCtxKey() { pthread_key_create(&s_glCtxKey, nullptr); }
|
||||||
|
|
||||||
|
// Pre-created pool of shared contexts for worker threads
|
||||||
|
static const int MAX_SHARED_CONTEXTS = 8;
|
||||||
|
static GLFWwindow *s_sharedContexts[MAX_SHARED_CONTEXTS] = {};
|
||||||
|
static int s_sharedContextCount = 0;
|
||||||
|
static int s_nextSharedContext = 0;
|
||||||
|
static pthread_mutex_t s_sharedCtxMutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
|
// Track which thread is the main (rendering) thread
|
||||||
|
static pthread_t s_mainThread;
|
||||||
|
static bool s_mainThreadSet = false;
|
||||||
|
|
||||||
void C4JRender::Initialise()
|
void C4JRender::Initialise()
|
||||||
{
|
{
|
||||||
if (!glfwInit()) {
|
if (!glfwInit()) {
|
||||||
|
|
@ -60,11 +79,67 @@ void C4JRender::Initialise()
|
||||||
(const char*)::glGetString(GL_VERSION),
|
(const char*)::glGetString(GL_VERSION),
|
||||||
(const char*)::glGetString(GL_RENDERER));
|
(const char*)::glGetString(GL_RENDERER));
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
|
||||||
|
// Tag this as the main rendering thread
|
||||||
|
pthread_once(&s_glCtxKeyOnce, makeGLCtxKey);
|
||||||
|
s_mainThread = pthread_self();
|
||||||
|
s_mainThreadSet = true;
|
||||||
|
pthread_setspecific(s_glCtxKey, s_window);
|
||||||
|
|
||||||
|
// Pre-create shared GL contexts for worker threads (chunk builders etc.)
|
||||||
|
// Must be done on the main thread because GLFW requires it.
|
||||||
|
for (int i = 0; i < MAX_SHARED_CONTEXTS; i++) {
|
||||||
|
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
|
||||||
|
s_sharedContexts[i] = glfwCreateWindow(1, 1, "", nullptr, s_window);
|
||||||
|
glfwWindowHint(GLFW_VISIBLE, GLFW_TRUE);
|
||||||
|
if (s_sharedContexts[i]) {
|
||||||
|
s_sharedContextCount++;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "[4J_Render] WARN: only created %d/%d shared contexts\n", i, MAX_SHARED_CONTEXTS);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Ensure main thread still has the context
|
||||||
|
glfwMakeContextCurrent(s_window);
|
||||||
|
fprintf(stderr, "[4J_Render] Created %d shared GL contexts for worker threads\n", s_sharedContextCount);
|
||||||
|
fflush(stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void C4JRender::InitialiseContext()
|
void C4JRender::InitialiseContext()
|
||||||
{
|
{
|
||||||
if (s_window) glfwMakeContextCurrent(s_window);
|
if (!s_window) return;
|
||||||
|
pthread_once(&s_glCtxKeyOnce, makeGLCtxKey);
|
||||||
|
|
||||||
|
// Main thread reclaiming context (e.g. after startup thread finishes)
|
||||||
|
if (s_mainThreadSet && pthread_equal(pthread_self(), s_mainThread)) {
|
||||||
|
glfwMakeContextCurrent(s_window);
|
||||||
|
pthread_setspecific(s_glCtxKey, s_window);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Worker thread: check if it already has a shared context
|
||||||
|
GLFWwindow *ctx = (GLFWwindow*)pthread_getspecific(s_glCtxKey);
|
||||||
|
if (ctx) {
|
||||||
|
glfwMakeContextCurrent(ctx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Grab a pre-created shared context from the pool
|
||||||
|
pthread_mutex_lock(&s_sharedCtxMutex);
|
||||||
|
GLFWwindow *shared = nullptr;
|
||||||
|
if (s_nextSharedContext < s_sharedContextCount) {
|
||||||
|
shared = s_sharedContexts[s_nextSharedContext++];
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&s_sharedCtxMutex);
|
||||||
|
|
||||||
|
if (!shared) {
|
||||||
|
fprintf(stderr, "[4J_Render] ERROR: no shared GL contexts left for worker thread!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
glfwMakeContextCurrent(shared);
|
||||||
|
pthread_setspecific(s_glCtxKey, shared);
|
||||||
|
fprintf(stderr, "[4J_Render] Assigned shared GL context %p to worker thread\n", (void*)shared);
|
||||||
|
fflush(stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void C4JRender::StartFrame()
|
void C4JRender::StartFrame()
|
||||||
|
|
@ -103,6 +178,7 @@ void C4JRender::SetClearColour(const float colourRGBA[4])
|
||||||
|
|
||||||
bool C4JRender::IsWidescreen() { return true; }
|
bool C4JRender::IsWidescreen() { return true; }
|
||||||
bool C4JRender::IsHiDef() { return true; }
|
bool C4JRender::IsHiDef() { return true; }
|
||||||
|
void C4JRender::GetFramebufferSize(int &width, int &height) { width = s_windowWidth; height = s_windowHeight; }
|
||||||
void C4JRender::CaptureThumbnail(ImageFileBuffer *) {}
|
void C4JRender::CaptureThumbnail(ImageFileBuffer *) {}
|
||||||
void C4JRender::CaptureScreen(ImageFileBuffer *, XSOCIAL_PREVIEWIMAGE *) {}
|
void C4JRender::CaptureScreen(ImageFileBuffer *, XSOCIAL_PREVIEWIMAGE *) {}
|
||||||
void C4JRender::BeginConditionalSurvey(int) {}
|
void C4JRender::BeginConditionalSurvey(int) {}
|
||||||
|
|
@ -174,23 +250,19 @@ void C4JRender::DrawVertices(ePrimitiveType PrimitiveType, int count,
|
||||||
{
|
{
|
||||||
if (count <= 0 || !dataIn) return;
|
if (count <= 0 || !dataIn) return;
|
||||||
|
|
||||||
static int _dbgDVCount = 0;
|
|
||||||
_dbgDVCount++;
|
|
||||||
if (_dbgDVCount <= 10 || (_dbgDVCount % 5000 == 0)) {
|
|
||||||
GLenum err = ::glGetError();
|
|
||||||
fprintf(stderr, "[RENDER] DrawVertices call=%d count=%d prim=%d vType=%d displayList=%d glErr=%d\n",
|
|
||||||
_dbgDVCount, count, (int)PrimitiveType, (int)vType, isCompilingDisplayList(), err);
|
|
||||||
fflush(stderr);
|
|
||||||
}
|
|
||||||
|
|
||||||
GLenum mode = mapPrimType((int)PrimitiveType);
|
GLenum mode = mapPrimType((int)PrimitiveType);
|
||||||
unsigned char *data = (unsigned char *)dataIn;
|
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
|
// Vertex layout: 3 floats pos, 2 floats tex, 4 bytes color, 4 bytes normal, 4 bytes padding = 32 bytes
|
||||||
const int stride = 32;
|
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 (isCompilingDisplayList()) {
|
||||||
// run.
|
|
||||||
::glBegin(mode);
|
::glBegin(mode);
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
unsigned char *v = data + i * stride;
|
unsigned char *v = data + i * stride;
|
||||||
|
|
@ -200,13 +272,20 @@ void C4JRender::DrawVertices(ePrimitiveType PrimitiveType, int count,
|
||||||
signed char *nrm = (signed char *)(v + 24);
|
signed char *nrm = (signed char *)(v + 24);
|
||||||
|
|
||||||
::glNormal3f(nrm[0] / 127.0f, nrm[1] / 127.0f, nrm[2] / 127.0f);
|
::glNormal3f(nrm[0] / 127.0f, nrm[1] / 127.0f, nrm[2] / 127.0f);
|
||||||
::glColor4ub(col[0], col[1], col[2], col[3]);
|
::glColor4ub(col[3], col[2], col[1], col[0]); // LE fix: r,g,b,a from reversed bytes
|
||||||
::glTexCoord2f(tex[0], tex[1]);
|
::glTexCoord2f(tex[0], tex[1]);
|
||||||
::glVertex3f(pos[0], pos[1], pos[2]);
|
::glVertex3f(pos[0], pos[1], pos[2]);
|
||||||
}
|
}
|
||||||
::glEnd();
|
::glEnd();
|
||||||
} else {
|
} else {
|
||||||
// waiter ! fast vertex pls !
|
// For vertex array path, swap color bytes in-place to RGBA order
|
||||||
|
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_VERTEX_ARRAY);
|
||||||
::glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
::glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
::glEnableClientState(GL_COLOR_ARRAY);
|
::glEnableClientState(GL_COLOR_ARRAY);
|
||||||
|
|
@ -218,6 +297,14 @@ void C4JRender::DrawVertices(ePrimitiveType PrimitiveType, int count,
|
||||||
::glNormalPointer(GL_BYTE, stride, data + 24);
|
::glNormalPointer(GL_BYTE, stride, data + 24);
|
||||||
|
|
||||||
::glDrawArrays(mode, 0, count);
|
::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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -254,13 +341,6 @@ void C4JRender::CBuffEnd()
|
||||||
bool C4JRender::CBuffCall(int index, bool /*full*/)
|
bool C4JRender::CBuffCall(int index, bool /*full*/)
|
||||||
{
|
{
|
||||||
if (index <= 0) return false;
|
if (index <= 0) return false;
|
||||||
static int _dbgCBCount = 0;
|
|
||||||
_dbgCBCount++;
|
|
||||||
if (_dbgCBCount <= 5 || (_dbgCBCount % 5000 == 0)) {
|
|
||||||
fprintf(stderr, "[RENDER] CBuffCall call=%d index=%d isList=%d\n",
|
|
||||||
_dbgCBCount, index, ::glIsList(index));
|
|
||||||
fflush(stderr);
|
|
||||||
}
|
|
||||||
if (::glIsList(index)) { ::glCallList(index); return true; }
|
if (::glIsList(index)) { ::glCallList(index); return true; }
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,7 @@ public:
|
||||||
void SetClearColour(const float colourRGBA[4]);
|
void SetClearColour(const float colourRGBA[4]);
|
||||||
bool IsWidescreen();
|
bool IsWidescreen();
|
||||||
bool IsHiDef();
|
bool IsHiDef();
|
||||||
|
void GetFramebufferSize(int &width, int &height);
|
||||||
void CaptureThumbnail(ImageFileBuffer *pngOut);
|
void CaptureThumbnail(ImageFileBuffer *pngOut);
|
||||||
void CaptureScreen(ImageFileBuffer *jpgOut, XSOCIAL_PREVIEWIMAGE *previewOut);
|
void CaptureScreen(ImageFileBuffer *jpgOut, XSOCIAL_PREVIEWIMAGE *previewOut);
|
||||||
void BeginConditionalSurvey(int identifier);
|
void BeginConditionalSurvey(int identifier);
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <execinfo.h>
|
#include <execinfo.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
static void sigsegv_handler(int sig) {
|
static void sigsegv_handler(int sig) {
|
||||||
const char msg[] = "\n=== SIGNAL CAUGHT: ";
|
const char msg[] = "\n=== SIGNAL CAUGHT: ";
|
||||||
write(STDERR_FILENO, msg, sizeof(msg)-1);
|
write(STDERR_FILENO, msg, sizeof(msg)-1);
|
||||||
|
|
@ -868,6 +869,71 @@ pDevice->SetSamplerState(0,SamplerStateModes[i],SamplerStateA[i]);
|
||||||
|
|
||||||
RenderManager.Set_matrixDirty();
|
RenderManager.Set_matrixDirty();
|
||||||
#endif
|
#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.
|
// Present the frame.
|
||||||
RenderManager.Present();
|
RenderManager.Present();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -995,13 +995,6 @@ int GameRenderer::getLightTexture(int iPad, Level *level)
|
||||||
|
|
||||||
void GameRenderer::render(float a, bool bFirst)
|
void GameRenderer::render(float a, bool bFirst)
|
||||||
{
|
{
|
||||||
static int _dbgRenderCount = 0;
|
|
||||||
_dbgRenderCount++;
|
|
||||||
if (_dbgRenderCount <= 5 || (_dbgRenderCount % 300 == 0)) {
|
|
||||||
fprintf(stderr, "[RENDER] GameRenderer::render frame=%d level=%p screen=%p width=%d height=%d\n",
|
|
||||||
_dbgRenderCount, (void*)mc->level, (void*)mc->screen, mc->width, mc->height);
|
|
||||||
fflush(stderr);
|
|
||||||
}
|
|
||||||
if( _updateLightTexture && bFirst) updateLightTexture(a);
|
if( _updateLightTexture && bFirst) updateLightTexture(a);
|
||||||
if (Display::isActive())
|
if (Display::isActive())
|
||||||
{
|
{
|
||||||
|
|
@ -1087,6 +1080,7 @@ void GameRenderer::render(float a, bool bFirst)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
glViewport(0, 0, mc->width, mc->height);
|
glViewport(0, 0, mc->width, mc->height);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
glMatrixMode(GL_PROJECTION);
|
glMatrixMode(GL_PROJECTION);
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
glMatrixMode(GL_MODELVIEW);
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
|
@ -1261,17 +1255,6 @@ void GameRenderer::DisableUpdateThread()
|
||||||
|
|
||||||
void GameRenderer::renderLevel(float a, __int64 until)
|
void GameRenderer::renderLevel(float a, __int64 until)
|
||||||
{
|
{
|
||||||
static int _dbgRLCount = 0;
|
|
||||||
_dbgRLCount++;
|
|
||||||
if (_dbgRLCount <= 3 || (_dbgRLCount % 300 == 0)) {
|
|
||||||
fprintf(stderr, "[RENDER] renderLevel frame=%d player=%p levelRenderer=%p\n",
|
|
||||||
_dbgRLCount, (void*)mc->player.get(), (void*)mc->levelRenderer);
|
|
||||||
if (mc->player) {
|
|
||||||
fprintf(stderr, "[RENDER] playerPos=(%.1f, %.1f, %.1f)\n",
|
|
||||||
mc->player->x, mc->player->y, mc->player->z);
|
|
||||||
}
|
|
||||||
fflush(stderr);
|
|
||||||
}
|
|
||||||
// if (updateLightTexture) updateLightTexture(); // 4J - TODO - Java 1.0.1 has this line enabled, should check why - don't want to put it in now in case it breaks split-screen
|
// if (updateLightTexture) updateLightTexture(); // 4J - TODO - Java 1.0.1 has this line enabled, should check why - don't want to put it in now in case it breaks split-screen
|
||||||
|
|
||||||
glEnable(GL_CULL_FACE);
|
glEnable(GL_CULL_FACE);
|
||||||
|
|
@ -1311,6 +1294,23 @@ void GameRenderer::renderLevel(float a, __int64 until)
|
||||||
|
|
||||||
setupCamera(a, i);
|
setupCamera(a, i);
|
||||||
Camera::prepare(mc->player, mc->player->ThirdPersonView() == 2);
|
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();
|
Frustum::getFrustum();
|
||||||
if (mc->options->viewDistance < 2)
|
if (mc->options->viewDistance < 2)
|
||||||
|
|
|
||||||
|
|
@ -778,24 +778,34 @@ int LevelRenderer::renderChunks(int from, int to, int layer, double alpha)
|
||||||
|
|
||||||
bool first = true;
|
bool first = true;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
int dbgNotVisible = 0, dbgNoIdx = 0, dbgEmpty = 0, dbgCalled = 0, dbgCallOk = 0;
|
||||||
ClipChunk *pClipChunk = chunks[playerIndex].data;
|
ClipChunk *pClipChunk = chunks[playerIndex].data;
|
||||||
unsigned char emptyFlag = LevelRenderer::CHUNK_FLAG_EMPTY0 << layer;
|
unsigned char emptyFlag = LevelRenderer::CHUNK_FLAG_EMPTY0 << layer;
|
||||||
for( int i = 0; i < chunks[playerIndex].length; i++, pClipChunk++ )
|
for( int i = 0; i < chunks[playerIndex].length; i++, pClipChunk++ )
|
||||||
{
|
{
|
||||||
if( !pClipChunk->visible ) continue; // This will be set if the chunk isn't visible, or isn't compiled, or has both empty flags set
|
if( !pClipChunk->visible ) { dbgNotVisible++; continue; }
|
||||||
if( pClipChunk->globalIdx == -1 ) continue; // Not sure if we should ever encounter this... TODO check
|
if( pClipChunk->globalIdx == -1 ) { dbgNoIdx++; continue; }
|
||||||
if( ( globalChunkFlags[pClipChunk->globalIdx] & emptyFlag ) == emptyFlag ) continue; // Check that this particular layer isn't empty
|
if( ( globalChunkFlags[pClipChunk->globalIdx] & emptyFlag ) == emptyFlag ) { dbgEmpty++; continue; }
|
||||||
|
|
||||||
// List can be calculated directly from the chunk's global idex
|
// List can be calculated directly from the chunk's global idex
|
||||||
int list = pClipChunk->globalIdx * 2 + layer;
|
int list = pClipChunk->globalIdx * 2 + layer;
|
||||||
list += chunkLists;
|
list += chunkLists;
|
||||||
|
|
||||||
|
dbgCalled++;
|
||||||
if(RenderManager.CBuffCall(list, first))
|
if(RenderManager.CBuffCall(list, first))
|
||||||
{
|
{
|
||||||
first = false;
|
first = false;
|
||||||
|
dbgCallOk++;
|
||||||
}
|
}
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
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);
|
||||||
|
fflush(stderr);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __PSVITA__
|
#ifdef __PSVITA__
|
||||||
// AP - alpha cut out is expensive on vita. Now we render all the alpha cut outs
|
// AP - alpha cut out is expensive on vita. Now we render all the alpha cut outs
|
||||||
|
|
|
||||||
1
Minecraft.World/Build/st3iWWKx
Normal file
1
Minecraft.World/Build/st3iWWKx
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
!<arch>
|
||||||
Loading…
Reference in a new issue