mirror of
https://github.com/izzy2lost/Super3.git
synced 2026-07-05 15:18:38 -07:00
3D graphics now working
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 186 KiB |
@@ -1,7 +1,11 @@
|
||||
#ifndef _GLSLSHADER_H_
|
||||
#define _GLSLSHADER_H_
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include <GLES3/gl3.h>
|
||||
#else
|
||||
#include <GL/glew.h>
|
||||
#endif
|
||||
#include <map>
|
||||
#include <cstring>
|
||||
|
||||
@@ -58,4 +62,4 @@ private:
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -18,7 +18,9 @@ namespace New3D {
|
||||
|
||||
CNew3D::CNew3D(const Util::Config::Node &config, const std::string& gameName)
|
||||
: m_r3dShader(config),
|
||||
#ifndef __ANDROID__
|
||||
m_r3dScrollFog(config),
|
||||
#endif
|
||||
m_gameName(gameName)
|
||||
{
|
||||
m_cullingRAMLo = nullptr;
|
||||
@@ -31,10 +33,12 @@ CNew3D::CNew3D(const Util::Config::Node &config, const std::string& gameName)
|
||||
m_numPolyVerts = 3;
|
||||
m_primType = GL_TRIANGLES;
|
||||
|
||||
#ifndef __ANDROID__
|
||||
if (config["QuadRendering"].ValueAs<bool>()) {
|
||||
m_numPolyVerts = 4;
|
||||
m_primType = GL_LINES_ADJACENCY;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
CNew3D::~CNew3D()
|
||||
@@ -84,8 +88,9 @@ bool CNew3D::Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned yR
|
||||
m_totalYRes = totalYResParam;
|
||||
|
||||
m_r3dShader.LoadShader();
|
||||
|
||||
#ifndef __ANDROID__
|
||||
m_r3dFrameBuffers.CreateFBO(totalXResParam, totalYResParam);
|
||||
#endif
|
||||
|
||||
glUseProgram(0);
|
||||
|
||||
@@ -117,6 +122,7 @@ void CNew3D::UploadTextures(unsigned level, unsigned x, unsigned y, unsigned wid
|
||||
|
||||
void CNew3D::DrawScrollFog()
|
||||
{
|
||||
#ifndef __ANDROID__
|
||||
// this is my best guess at the logic based upon what games are doing
|
||||
//
|
||||
// ocean hunter - every viewport has scroll fog values set. Must start with lowest priority layers as the higher ones sometimes are garbage
|
||||
@@ -166,6 +172,7 @@ CheckScroll:
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool CNew3D::RenderScene(int priority, bool renderOverlay, Layer layer)
|
||||
@@ -306,6 +313,78 @@ void CNew3D::DisableRenderStates()
|
||||
|
||||
void CNew3D::RenderFrame(void)
|
||||
{
|
||||
#ifdef __ANDROID__
|
||||
// Android/GLES: basic mesh path (no multi-pass transparency compositing yet).
|
||||
for (int i = 0; i < 4; i++) {
|
||||
m_nfPairs[i].zNear = -std::numeric_limits<float>::max();
|
||||
m_nfPairs[i].zFar = std::numeric_limits<float>::max();
|
||||
}
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(m_losMutex);
|
||||
std::swap(m_losBack, m_losFront);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
m_losBack->value[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
m_polyBufferRam.clear();
|
||||
m_nodes.clear();
|
||||
m_modelMat.Release();
|
||||
m_nodeAttribs.Reset();
|
||||
|
||||
RenderViewport(0x800000);
|
||||
|
||||
m_vbo.Bind(true);
|
||||
m_vbo.BufferSubData(MAX_ROM_VERTS*sizeof(FVertex), m_polyBufferRam.size()*sizeof(FVertex), m_polyBufferRam.data());
|
||||
|
||||
if (!m_polyBufferRom.empty()) {
|
||||
int romBytes = (int)m_polyBufferRom.size() * sizeof(FVertex);
|
||||
int vboBytes = m_vbo.GetSize();
|
||||
int size = romBytes - vboBytes;
|
||||
|
||||
if (size) {
|
||||
if (m_polyBufferRom.size() >= MAX_ROM_VERTS) {
|
||||
m_polyBufferRom.clear();
|
||||
m_romMap.clear();
|
||||
m_vbo.Reset();
|
||||
}
|
||||
else {
|
||||
m_vbo.AppendData(size, &m_polyBufferRom[vboBytes / sizeof(FVertex)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Draw to default framebuffer.
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
for (int pri = 0; pri <= 3; pri++) {
|
||||
if (SkipLayer(pri)) continue;
|
||||
|
||||
// Opaque pass.
|
||||
SetRenderStates();
|
||||
m_r3dShader.DiscardAlpha(true);
|
||||
glDisable(GL_BLEND);
|
||||
RenderScene(pri, false, Layer::colour);
|
||||
RenderScene(pri, true, Layer::colour);
|
||||
DisableRenderStates();
|
||||
|
||||
// Translucent pass (rough): draw both layers with blending.
|
||||
SetRenderStates();
|
||||
m_r3dShader.DiscardAlpha(false);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glDepthMask(GL_FALSE);
|
||||
RenderScene(pri, false, Layer::trans1);
|
||||
RenderScene(pri, false, Layer::trans2);
|
||||
RenderScene(pri, true, Layer::trans1);
|
||||
RenderScene(pri, true, Layer::trans2);
|
||||
glDepthMask(GL_TRUE);
|
||||
DisableRenderStates();
|
||||
}
|
||||
return;
|
||||
#else
|
||||
for (int i = 0; i < 4; i++) {
|
||||
m_nfPairs[i].zNear = -std::numeric_limits<float>::max();
|
||||
m_nfPairs[i].zFar = std::numeric_limits<float>::max();
|
||||
@@ -400,6 +479,7 @@ void CNew3D::RenderFrame(void)
|
||||
}
|
||||
|
||||
m_r3dFrameBuffers.CompositeAlphaLayer();
|
||||
#endif
|
||||
}
|
||||
|
||||
void CNew3D::BeginFrame(void)
|
||||
@@ -1636,7 +1716,12 @@ void CNew3D::CalcViewport(Viewport* vp, float near, float far)
|
||||
// and only their scissor box differs)
|
||||
float correction = windowAR / viewableAreaAR;
|
||||
|
||||
// Android: use x offset for letterboxed "viewable area" within the physical window.
|
||||
#ifdef __ANDROID__
|
||||
vp->x = m_xOffs;
|
||||
#else
|
||||
vp->x = 0;
|
||||
#endif
|
||||
vp->y = m_yOffs + (int)((float)(384 - (vp->vpY + vp->vpHeight))*m_yRatio);
|
||||
vp->width = m_totalXRes;
|
||||
vp->height = (int)((float)vp->vpHeight*m_yRatio);
|
||||
|
||||
@@ -29,7 +29,11 @@
|
||||
#ifndef INCLUDED_NEW3D_H
|
||||
#define INCLUDED_NEW3D_H
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include <GLES3/gl3.h>
|
||||
#else
|
||||
#include <GL/glew.h>
|
||||
#endif
|
||||
#include "Types.h"
|
||||
#include "TextureSheet.h"
|
||||
#include "Graphics/IRender3D.h"
|
||||
@@ -40,9 +44,13 @@
|
||||
#include "R3DData.h"
|
||||
#include "Plane.h"
|
||||
#include "Vec.h"
|
||||
#ifndef __ANDROID__
|
||||
#include "R3DScrollFog.h"
|
||||
#endif
|
||||
#include "PolyHeader.h"
|
||||
#ifndef __ANDROID__
|
||||
#include "R3DFrameBuffers.h"
|
||||
#endif
|
||||
#include <mutex>
|
||||
|
||||
namespace New3D {
|
||||
@@ -282,8 +290,10 @@ private:
|
||||
|
||||
VBO m_vbo; // large VBO to hold our poly data, start of VBO is ROM data, ram polys follow
|
||||
R3DShader m_r3dShader;
|
||||
#ifndef __ANDROID__
|
||||
R3DScrollFog m_r3dScrollFog;
|
||||
R3DFrameBuffers m_r3dFrameBuffers;
|
||||
#endif
|
||||
|
||||
Plane m_planes[5];
|
||||
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
#ifndef FBO_H
|
||||
#define FBO_H
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include <GLES3/gl3.h>
|
||||
#else
|
||||
#include <GL/glew.h>
|
||||
#endif
|
||||
#include "VBO.h"
|
||||
#include "GLSLShader.h"
|
||||
#include "Model.h"
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "R3DShader.h"
|
||||
#ifndef __ANDROID__
|
||||
#include "R3DShaderQuads.h"
|
||||
#endif
|
||||
#include "R3DShaderTriangles.h"
|
||||
|
||||
// having 2 sets of shaders to maintain is really less than ideal
|
||||
@@ -48,16 +50,22 @@ void R3DShader::Start()
|
||||
bool R3DShader::LoadShader(const char* vertexShader, const char* fragmentShader)
|
||||
{
|
||||
bool quads = m_config["QuadRendering"].ValueAs<bool>();
|
||||
#ifdef __ANDROID__
|
||||
// GLES 3.0: no geometry shaders / adjacency in the baseline path.
|
||||
quads = false;
|
||||
#endif
|
||||
|
||||
const char* vShader = vertexShaderR3D;
|
||||
const char* gShader = "";
|
||||
const char* fShader = fragmentShaderR3D;
|
||||
|
||||
#ifndef __ANDROID__
|
||||
if (quads) {
|
||||
vShader = vertexShaderR3DQuads;
|
||||
gShader = geometryShaderR3DQuads;
|
||||
fShader = fragmentShaderR3DQuads;
|
||||
}
|
||||
#endif
|
||||
|
||||
m_shaderProgram = glCreateProgram();
|
||||
m_vertexShader = glCreateShader(GL_VERTEX_SHADER);
|
||||
@@ -69,6 +77,7 @@ bool R3DShader::LoadShader(const char* vertexShader, const char* fragmentShader)
|
||||
glCompileShader(m_vertexShader);
|
||||
glCompileShader(m_fragmentShader);
|
||||
|
||||
#ifndef __ANDROID__
|
||||
if (quads) {
|
||||
m_geoShader = glCreateShader(GL_GEOMETRY_SHADER);
|
||||
glShaderSource(m_geoShader, 1, (const GLchar **)&gShader, NULL);
|
||||
@@ -76,6 +85,7 @@ bool R3DShader::LoadShader(const char* vertexShader, const char* fragmentShader)
|
||||
glAttachShader(m_shaderProgram, m_geoShader);
|
||||
PrintShaderResult(m_geoShader);
|
||||
}
|
||||
#endif
|
||||
|
||||
PrintShaderResult(m_vertexShader);
|
||||
PrintShaderResult(m_fragmentShader);
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
#ifndef _R3DSHADER_H_
|
||||
#define _R3DSHADER_H_
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include <GLES3/gl3.h>
|
||||
#else
|
||||
#include <GL/glew.h>
|
||||
#endif
|
||||
#include "Util/NewConfig.h"
|
||||
#include "Model.h"
|
||||
#include <unordered_map>
|
||||
|
||||
@@ -1,6 +1,86 @@
|
||||
#ifndef _R3DSHADERTRIANGLES_H_
|
||||
#define _R3DSHADERTRIANGLES_H_
|
||||
|
||||
#ifdef __ANDROID__
|
||||
// GLES 3.0 shaders (minimal path: textured vertex-colour with optional alpha discard).
|
||||
static const char *vertexShaderR3D = R"glsl(
|
||||
|
||||
#version 300 es
|
||||
precision highp float;
|
||||
|
||||
// uniforms
|
||||
uniform float modelScale;
|
||||
uniform mat4 modelMat;
|
||||
uniform mat4 projMat;
|
||||
uniform bool translatorMap;
|
||||
|
||||
// attributes
|
||||
layout(location=0) in vec4 inVertex;
|
||||
layout(location=1) in vec3 inNormal;
|
||||
layout(location=2) in vec2 inTexCoord;
|
||||
layout(location=3) in vec4 inColour; // normalized UBYTE -> float
|
||||
layout(location=4) in vec3 inFaceNormal;
|
||||
layout(location=5) in float inFixedShade;
|
||||
|
||||
out vec2 vTexCoord;
|
||||
out vec4 vColor;
|
||||
out float vAlpha;
|
||||
out vec3 vDummy; // keeps attributes alive
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 c = inColour;
|
||||
if (translatorMap) c.rgb *= 16.0;
|
||||
vColor = c;
|
||||
vTexCoord = inTexCoord;
|
||||
vAlpha = c.a;
|
||||
vDummy = inNormal + inFaceNormal + vec3(inFixedShade);
|
||||
gl_Position = projMat * modelMat * inVertex;
|
||||
}
|
||||
)glsl";
|
||||
|
||||
static const char *fragmentShaderR3D = R"glsl(
|
||||
|
||||
#version 300 es
|
||||
precision mediump float;
|
||||
|
||||
in vec2 vTexCoord;
|
||||
in vec4 vColor;
|
||||
in float vAlpha;
|
||||
in vec3 vDummy;
|
||||
|
||||
uniform sampler2D tex1;
|
||||
uniform bool textureEnabled;
|
||||
uniform bool textureAlpha;
|
||||
uniform bool alphaTest;
|
||||
uniform bool discardAlpha;
|
||||
|
||||
out vec4 oColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 col = vColor;
|
||||
|
||||
if (textureEnabled) {
|
||||
vec4 t = texture(tex1, vTexCoord);
|
||||
if (textureAlpha) {
|
||||
col *= t;
|
||||
} else {
|
||||
col.rgb *= t.rgb;
|
||||
}
|
||||
}
|
||||
|
||||
// keep vDummy "used"
|
||||
col.rgb += vDummy * 0.0;
|
||||
|
||||
if (alphaTest && col.a < 0.5) discard;
|
||||
if (discardAlpha && col.a < 0.99) discard;
|
||||
|
||||
oColor = col;
|
||||
}
|
||||
)glsl";
|
||||
|
||||
#else
|
||||
static const char *vertexShaderR3D = R"glsl(
|
||||
|
||||
#version 120
|
||||
@@ -35,7 +115,7 @@ vec4 GetColour(vec4 colour)
|
||||
c.rgb *= 16.0;
|
||||
}
|
||||
|
||||
return c;
|
||||
return c;
|
||||
}
|
||||
|
||||
float CalcBackFace(in vec3 viewVertex)
|
||||
@@ -424,5 +504,6 @@ void main()
|
||||
gl_FragColor = finalData;
|
||||
}
|
||||
)glsl";
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -2,7 +2,11 @@
|
||||
#define _TEXTURE_H_
|
||||
|
||||
#include "Types.h"
|
||||
#ifdef __ANDROID__
|
||||
#include <GLES3/gl3.h>
|
||||
#else
|
||||
#include <GL/glew.h>
|
||||
#endif
|
||||
|
||||
namespace New3D {
|
||||
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
#ifndef _VBO_H_
|
||||
#define _VBO_H_
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include <GLES3/gl3.h>
|
||||
#else
|
||||
#include <GL/glew.h>
|
||||
#endif
|
||||
|
||||
namespace New3D {
|
||||
|
||||
|
||||
@@ -54,9 +54,11 @@ public:
|
||||
bool Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned yRes, unsigned totalXRes, unsigned totalYRes);
|
||||
|
||||
const uint32_t* GetFrameBufferRGBA() const { return m_frame.data(); }
|
||||
const uint32_t* GetTopSurfaceARGB() const { return m_topSurface.data(); }
|
||||
unsigned GetFrameWidth() const { return m_xPixels; }
|
||||
unsigned GetFrameHeight() const { return m_yPixels; }
|
||||
bool HasFrame() const { return !m_frame.empty(); }
|
||||
bool HasTopSurface() const { return m_surfacesPresent.first; }
|
||||
|
||||
private:
|
||||
std::pair<bool, bool> DrawTilemaps(uint32_t *pixelsBottom, uint32_t *pixelsTop);
|
||||
|
||||
@@ -115,6 +115,16 @@ add_library(super3 SHARED
|
||||
gles_presenter.cpp
|
||||
gles_stub_render3d.cpp
|
||||
render2d_android.cpp
|
||||
"${REPO_ROOT}/Src/Graphics/New3D/Mat4.cpp"
|
||||
"${REPO_ROOT}/Src/Graphics/New3D/Model.cpp"
|
||||
"${REPO_ROOT}/Src/Graphics/New3D/New3D.cpp"
|
||||
"${REPO_ROOT}/Src/Graphics/New3D/PolyHeader.cpp"
|
||||
"${REPO_ROOT}/Src/Graphics/New3D/R3DFloat.cpp"
|
||||
"${REPO_ROOT}/Src/Graphics/New3D/R3DShader.cpp"
|
||||
"${REPO_ROOT}/Src/Graphics/New3D/Texture.cpp"
|
||||
"${REPO_ROOT}/Src/Graphics/New3D/TextureSheet.cpp"
|
||||
"${REPO_ROOT}/Src/Graphics/New3D/VBO.cpp"
|
||||
"${REPO_ROOT}/Src/Graphics/New3D/Vec.cpp"
|
||||
${SUPER3_SOURCES}
|
||||
${M68K_GENERATED_SOURCES}
|
||||
)
|
||||
|
||||
@@ -206,7 +206,7 @@ void GlesPresenter::UpdateQuadVerts()
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
void GlesPresenter::Render()
|
||||
void GlesPresenter::Render(bool alphaBlend)
|
||||
{
|
||||
if (!m_program || !m_vao || !m_tex || m_outputW <= 0 || m_outputH <= 0)
|
||||
return;
|
||||
@@ -214,6 +214,15 @@ void GlesPresenter::Render()
|
||||
glViewport(0, 0, m_outputW, m_outputH);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_CULL_FACE);
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
|
||||
if (alphaBlend) {
|
||||
glEnable(GL_BLEND);
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
} else {
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
glUseProgram(m_program);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
@@ -227,4 +236,3 @@ void GlesPresenter::Render()
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glUseProgram(0);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ public:
|
||||
|
||||
// pixelsARGB: 0xAARRGGBB packed.
|
||||
void UpdateFrameARGB(const uint32_t* pixelsARGB, int width, int height);
|
||||
void Render();
|
||||
void Render(bool alphaBlend);
|
||||
|
||||
private:
|
||||
bool CreateProgram();
|
||||
@@ -40,4 +40,3 @@ private:
|
||||
// Converted upload buffer in RGBA8.
|
||||
std::vector<uint8_t> m_uploadRGBA;
|
||||
};
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "android_input_system.h"
|
||||
#include "gles_presenter.h"
|
||||
#include "gles_stub_render3d.h"
|
||||
#include "Graphics/New3D/New3D.h"
|
||||
|
||||
// Minimal OSD glue -----------------------------------------------------------
|
||||
|
||||
@@ -62,7 +63,9 @@ struct Super3Host {
|
||||
AndroidInputSystem inputSystem;
|
||||
CInputs inputs{&inputSystem};
|
||||
StubOutputs outputs;
|
||||
GlesStubRender3D render3d;
|
||||
GlesStubRender3D stub3d;
|
||||
std::unique_ptr<New3D::CNew3D> new3d;
|
||||
IRender3D* render3d = &stub3d;
|
||||
CRender2D render2d{config};
|
||||
|
||||
std::unique_ptr<GameLoader> loader;
|
||||
@@ -240,7 +243,7 @@ struct Super3Host {
|
||||
// TileGen allocates and wires VRAM/palette/register pointers during Init();
|
||||
// attach renderers after Init()/LoadGame() so Render2D sees valid pointers.
|
||||
SDL_Log("Attaching renderers...");
|
||||
model3->AttachRenderers(&render2d, &render3d);
|
||||
model3->AttachRenderers(&render2d, render3d);
|
||||
|
||||
// Establish initial CPU/device state (ppc_reset(), etc).
|
||||
SDL_Log("Model3 Reset...");
|
||||
@@ -270,6 +273,42 @@ struct Super3Host {
|
||||
model3->RunFrame();
|
||||
}
|
||||
}
|
||||
|
||||
bool InstallNew3D(unsigned totalXRes, unsigned totalYRes)
|
||||
{
|
||||
if (!model3 || new3d)
|
||||
return !!new3d;
|
||||
|
||||
// Letterbox the Model 3 496x384 output into the physical drawable area.
|
||||
// We pass the "viewable area" size to New3D so it doesn't wide-screen expand the frustum.
|
||||
const float targetAR = 496.0f / 384.0f;
|
||||
unsigned viewW = totalXRes;
|
||||
unsigned viewH = totalYRes;
|
||||
const float windowAR = (float)totalXRes / (float)totalYRes;
|
||||
if (windowAR > targetAR) {
|
||||
viewH = totalYRes;
|
||||
viewW = (unsigned)std::lround((double)totalYRes * targetAR);
|
||||
} else {
|
||||
viewW = totalXRes;
|
||||
viewH = (unsigned)std::lround((double)totalXRes / targetAR);
|
||||
}
|
||||
const unsigned xOff = (totalXRes - viewW) / 2;
|
||||
const unsigned yOff = (totalYRes - viewH) / 2;
|
||||
|
||||
SDL_Log("Initializing New3D (GLES) ...");
|
||||
new3d = std::make_unique<New3D::CNew3D>(config, game.name);
|
||||
if (new3d->Init(xOff, yOff, viewW, viewH, viewW, viewH) != 0)
|
||||
{
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "New3D Init failed");
|
||||
new3d.reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
render3d = new3d.get();
|
||||
model3->AttachRenderers(&render2d, render3d);
|
||||
SDL_Log("New3D attached");
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
static std::string JoinPath(const std::string& a, const std::string& b)
|
||||
@@ -352,7 +391,6 @@ extern "C" int SDL_main(int argc, char* argv[]) {
|
||||
// Initialize renderer backends up-front. The core will attach VRAM/palette/register
|
||||
// pointers later (after it has initialized the tile generator).
|
||||
host.render2d.Init(0, 0, 496, 384, 496, 384);
|
||||
host.render3d.Init(0, 0, 496, 384, 496, 384);
|
||||
|
||||
// Locate resources. Prefer app-specific external storage (no runtime perms),
|
||||
// but also probe common legacy locations for dev convenience.
|
||||
@@ -412,6 +450,7 @@ extern "C" int SDL_main(int argc, char* argv[]) {
|
||||
bool backgrounded = false;
|
||||
bool loggedControls = false;
|
||||
bool audioOpened = false;
|
||||
bool new3dAttached = false;
|
||||
while (running) {
|
||||
SDL_Event ev;
|
||||
while (SDL_PollEvent(&ev)) {
|
||||
@@ -457,6 +496,11 @@ extern "C" int SDL_main(int argc, char* argv[]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int winW = 0, winH = 0;
|
||||
SDL_GL_GetDrawableSize(window, &winW, &winH);
|
||||
if (winW <= 0) winW = 1;
|
||||
if (winH <= 0) winH = 1;
|
||||
|
||||
const int state = loadState.load(std::memory_order_acquire);
|
||||
if (state == 1) {
|
||||
if (!audioOpened) {
|
||||
@@ -470,27 +514,37 @@ extern "C" int SDL_main(int argc, char* argv[]) {
|
||||
loggedControls = true;
|
||||
SDL_Log("Controls (touch): bottom-left=COIN, bottom-right=START, top-left=SERVICE, top-right=TEST, left-middle=DPAD/STEER, right-middle=THROTTLE/BRAKE");
|
||||
}
|
||||
host.RunFrame();
|
||||
}
|
||||
|
||||
int winW = 0, winH = 0;
|
||||
SDL_GL_GetDrawableSize(window, &winW, &winH);
|
||||
presenter.Resize(winW, winH);
|
||||
if (!new3dAttached) {
|
||||
new3dAttached = host.InstallNew3D((unsigned)winW, (unsigned)winH);
|
||||
}
|
||||
|
||||
glClearColor(0.f, 0.f, 0.f, 1.f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
if (new3dAttached) {
|
||||
// 3D path: let New3D draw into the default framebuffer from inside the core.
|
||||
glViewport(0, 0, winW, winH);
|
||||
glClearColor(0.f, 0.f, 0.f, 1.f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
host.RunFrame();
|
||||
|
||||
if (state == 1 && host.render2d.HasFrame()) {
|
||||
const uint32_t* pixels = host.render2d.GetFrameBufferRGBA();
|
||||
presenter.UpdateFrameARGB(pixels, (int)host.render2d.GetFrameWidth(), (int)host.render2d.GetFrameHeight());
|
||||
presenter.Render();
|
||||
|
||||
// Debug: draw a small triangle on top so we can verify GLES is working
|
||||
// and we have a valid 3D hook. The real integration will happen inside
|
||||
// the GPU/TileGen render path once New3D is ported.
|
||||
host.render3d.BeginFrame();
|
||||
host.render3d.RenderFrame();
|
||||
host.render3d.EndFrame();
|
||||
// Overlay TileGen top layers (HUD/menus) on top of 3D.
|
||||
presenter.Resize(winW, winH);
|
||||
if (host.render2d.HasTopSurface()) {
|
||||
const uint32_t* pixels = host.render2d.GetTopSurfaceARGB();
|
||||
presenter.UpdateFrameARGB(pixels, (int)host.render2d.GetFrameWidth(), (int)host.render2d.GetFrameHeight());
|
||||
presenter.Render(true);
|
||||
}
|
||||
} else {
|
||||
// 2D-only path: keep showing TileGen software output.
|
||||
host.RunFrame();
|
||||
presenter.Resize(winW, winH);
|
||||
glClearColor(0.f, 0.f, 0.f, 1.f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
if (host.render2d.HasFrame()) {
|
||||
const uint32_t* pixels = host.render2d.GetFrameBufferRGBA();
|
||||
presenter.UpdateFrameARGB(pixels, (int)host.render2d.GetFrameWidth(), (int)host.render2d.GetFrameHeight());
|
||||
presenter.Render(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SDL_GL_SwapWindow(window);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user