Files
EVEngine/src/modules/graphics/Graphics.h
T
sunxfancyandCursor 8e0221c552 feat: enhance build system and documentation for SDK installation and shader support
- Updated .gitignore to include new build and output directories for SDK packaging.
- Modified CMakeLists.txt to include installation script for SDK.
- Enhanced Makefile to support new SDK targets for various platforms.
- Improved documentation to reflect new shader capabilities and 3D model support.
- Added new shader functions and updated rendering systems to utilize custom shaders.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-06 21:08:47 +08:00

337 lines
13 KiB
C++

#pragma once
#include "common/Module.h"
#include "graphics/Shader.h"
#include "graphics/Drawable.h"
#include "graphics/Canvas.h"
#include "graphics/Texture.h"
#include "graphics/Mesh.h"
#include <vector>
#include <optional>
#include <cstdint>
#include <string>
#include <glm/glm.hpp>
struct aiMesh;
namespace eve::graphics {
class Graphics : public Module, public Canvas {
public:
Module_REG(Graphics);
virtual ~Graphics() {}
/**
* Resets the current color, background color, line style, and so forth.
**/
void reset();
/** Script-friendly wrappers (r,g,b[,a] floats — no Color type in Squirrel). */
void clearScreen();
void setBackgroundColorRGBA(float r, float g, float b, float a = 1.f);
void drawSolidRectRGBA(float x, float y, float w, float h, float r, float g, float b,
float a = 1.f);
virtual void present() = 0;
/**
* Bind to an existing native window (SDL_Window*) and create Vulkan device/swapchain.
* Must be called after the window exists (SDL_WINDOW_VULKAN).
**/
virtual void initWithWindow(void *nativeWindow) = 0;
/**
* Sets the current graphics display viewport dimensions.
**/
virtual void setViewportSize(int width, int height, int pixelwidth, int pixelheight) = 0;
int getWidth() const { return width; }
int getHeight() const { return height; }
int getPixelWidth() const { return pixelWidth; }
int getPixelHeight() const { return pixelHeight; }
double getCurrentDPIScale() const {
return (width > 0) ? double(pixelWidth) / double(width) : 1.0;
}
double getScreenDPIScale() const { return getCurrentDPIScale(); }
/** Internal immediate-mode helper used by RenderSystem / Batcher. */
virtual void drawSolidRect(float x, float y, float w, float h, const Color &color) = 0;
/** Create RGBA8 texture from CPU pixels (size = width*height*4). Caller owns Texture*. */
virtual Texture *newTexture(int width, int height, const uint8_t *rgba, bool repeatU = false,
bool repeatV = false) = 0;
/** Create texture from ImageData (RGBA8 required for now). */
virtual Texture *newTexture(image::ImageData *data) = 0;
/** Load file via Filesystem + Image decode, then upload (RGBA8). Throws on failure. */
virtual Texture *newTextureFromFile(const std::string &filename) = 0;
/** Draw a textured quad (full UV 0..1). texture may be null → solid.
* Uses currentShader when set (or per-call override via drawTexturedRectShader). */
virtual void drawTexturedRect(Texture *texture, float x, float y, float w, float h,
const Color &color) = 0;
/** Draw with an explicit Shader (nullptr = default textured pipeline). */
virtual void drawTexturedRectShader(Texture *texture, Shader *shader, float x, float y, float w,
float h, const Color &color) = 0;
/** Upload triangulated mesh from Assimp (pos/normal/uv + indices). Owned by Graphics. */
virtual Mesh *newMeshFromAssimp(const ::aiMesh &mesh) = 0;
/**
* Procedural UV sphere (radius 1, Y-up). Owned by Graphics.
* slices = longitude divisions, stacks = latitude divisions.
*/
virtual Mesh *newMeshSphere(int slices = 32, int stacks = 16) = 0;
/** Run RenderSystem3D (begin3DFrame + draw visible Renderable3D). */
void render3D();
void setDirectionalLight(float dx, float dy, float dz, float r = 1.f, float g = 1.f,
float b = 1.f);
/**
* Begin a swapchain pass cleared for 3D (color+depth). Leaves the pass open for drawMesh
* and a following RenderSystem::render (2D). Does not present.
* Soft-fails (no throw) when the swapchain cannot be acquired yet — check had3DThisFrame().
*/
virtual void begin3DFrame() = 0;
/** viewProj used by subsequent drawMesh (mvp = viewProj * model). RH + ZO clip. */
virtual void setMesh3DViewProj(const glm::mat4 &viewProj) = 0;
/** Draw one mesh with model matrix. Requires begin3DFrame() (or an open swapchain pass). */
virtual void drawMesh(Mesh *mesh, const glm::mat4 &model, Texture *texture, const Color &tint) = 0;
/** Draw mesh with an explicit Mesh3D Shader (nullptr = default lit pipeline). */
virtual void drawMeshShader(Mesh *mesh, const glm::mat4 &model, Texture *texture, const Color &tint,
Shader *shader) = 0;
/** Directional light for subsequent drawMesh calls (world-space direction toward surface). */
virtual void setMesh3DLight(const glm::vec3 &dir, const glm::vec3 &color) = 0;
/** Camera eye used by mesh shaders that need view/rim (stored in Mesh3DUBO). */
virtual void setMesh3DCameraPos(const glm::vec3 &eye) = 0;
/** True after begin3DFrame until present completes. */
bool consumeFrameHad3D() {
bool v = frameHad3D;
return v;
}
bool had3DThisFrame() const { return frameHad3D; }
Color getBackgroundColor() const { return backgroundColor; }
void setBackgroundColor(const Color &c) { backgroundColor = c; }
/**
* When true, each present copies the swapchain to a CPU buffer for getPixel/newImageData.
* Default false — full-frame readback is expensive; enable only for tests / tools.
*/
void setScreenReadbackEnabled(bool enabled) { screenReadbackEnabled = enabled; }
bool isScreenReadbackEnabled() const { return screenReadbackEnabled; }
/** Pause/resume presenting (Android background / foreground). */
void setActive(bool active) {
graphicsActive = active;
if (active)
markSwapchainDirty();
}
bool isActive() const { return graphicsActive; }
/** Request swapchain recreation on next present/begin3DFrame. */
virtual void markSwapchainDirty() {}
/**
* Request recreation of the platform render surface on the next frame
* (Android background/foreground destroys the native window). Safe to call
* from a non-render thread; the actual work happens on the render thread.
*/
virtual void requestSurfaceRecreate() {}
/**
* Optional overlay drawn inside the swapchain render pass (before end).
* Used by declarative UI (ImGui). `commandBuffer` is a VkCommandBuffer as void*.
*/
using PresentOverlayFn = void (*)(void *userdata, void *commandBuffer);
void setPresentOverlay(PresentOverlayFn fn, void *userdata) {
presentOverlayFn_ = fn;
presentOverlayUser_ = userdata;
}
PresentOverlayFn getPresentOverlay() const { return presentOverlayFn_; }
void *getPresentOverlayUser() const { return presentOverlayUser_; }
// void setFont(Font *font);
// Font *getFont();
void setShader(Shader *shader);
void setShader();
Shader *getShader() const { return currentShader; }
/**
* Create a custom 2D shader from SPIR-V words (vert + frag).
* Owned by Graphics. Vertex stage may be empty → uses the default textured vertex shader.
*/
virtual Shader *newShaderFromSpv(const std::vector<uint32_t> &vertSpv,
const std::vector<uint32_t> &fragSpv) = 0;
/** Load SPIR-V from files via Filesystem (empty vertPath → default textured vert). */
virtual Shader *newShaderFromSpvFile(const std::string &vertPath, const std::string &fragPath) = 0;
Shader *newShaderFromSpvFile(const std::string &fragPath) {
return newShaderFromSpvFile(std::string(), fragPath);
}
/**
* Compile GLSL source with glslc (must be on PATH). Empty vertGlsl → default textured vert.
* Throws if compilation fails.
*/
virtual Shader *newShader(const std::string &vertGlsl, const std::string &fragGlsl) = 0;
Shader *newShader(const std::string &fragGlsl) { return newShader(std::string(), fragGlsl); }
/**
* Create a Mesh3D custom shader (MeshVertex + Frame UBO + albedo).
* Empty vert → default mesh3d.vert. Owned by Graphics.
*/
virtual Shader *newMeshShaderFromSpv(const std::vector<uint32_t> &vertSpv,
const std::vector<uint32_t> &fragSpv) = 0;
virtual Shader *newMeshShader(const std::string &vertGlsl, const std::string &fragGlsl) = 0;
Shader *newMeshShader(const std::string &fragGlsl) {
return newMeshShader(std::string(), fragGlsl);
}
/** Create an offscreen render target (sampleable). Owned by Graphics. */
virtual Canvas *newCanvas(int width, int height) = 0;
/** nullptr or this → screen. Switching flushes pending draws to the previous target. */
virtual void setCanvas(Canvas *canvas) = 0;
void setCanvas() { setCanvas(nullptr); }
virtual bool isCanvasActive() const = 0;
virtual Canvas *getCanvas() const = 0;
void draw(Drawable *drawable, const glm::mat4 &m);
// void draw(Texture *texture, Quad *quad, const glm::mat4 &m);
// void drawLayer(Texture *texture, int layer, const glm::mat4 &m);
// void drawLayer(Texture *texture, int layer, Quad *quad, const glm::mat4 &m);
// void drawInstanced(Mesh *mesh, const glm::mat4 &m, int instancecount);
/**
* Draws a series of points at the specified positions.
**/
void points(const std::vector<glm::vec2>& positions, const std::vector<Color>& colors);
/**
* Draws a series of lines connecting the given vertices.
* @param coords Vertex positions (v1, ..., vn). If v1 == vn the line will be drawn closed.
* @param count Number of vertices.
**/
void polyline(const glm::mat4 *vertices, size_t count);
/**
* Draws a rectangle.
* @param x Position along x-axis for top-left corner.
* @param y Position along y-axis for top-left corner.
* @param w The width of the rectangle.
* @param h The height of the rectangle.
**/
void rectangle(std::string mode, float x, float y, float w, float h);
/**
* Variant of rectangle that draws a rounded rectangle.
* @param mode The mode of drawing (line/filled).
* @param x X-coordinate of top-left corner
* @param y Y-coordinate of top-left corner
* @param w The width of the rectangle.
* @param h The height of the rectangle.
* @param rx The radius of the corners on the x axis
* @param ry The radius of the corners on the y axis
* @param points The number of points to use per corner
**/
void rectangle(std::string mode, float x, float y, float w, float h, float rx, float ry, int points);
void rectangle(std::string mode, float x, float y, float w, float h, float rx, float ry);
/**
* Draws a circle using the specified arguments.
* @param mode The mode of drawing (line/filled).
* @param x X-coordinate.
* @param y Y-coordinate.
* @param radius Radius of the circle.
* @param points Number of points to use to draw the circle.
**/
void circle(std::string mode, float x, float y, float radius, int points);
void circle(std::string mode, float x, float y, float radius);
/**
* Draws an ellipse using the specified arguments.
* @param mode The mode of drawing (line/filled).
* @param x X-coordinate of center
* @param y Y-coordinate of center
* @param a Radius in x-direction
* @param b Radius in y-direction
* @param points Number of points to use to draw the circle.
**/
void ellipse(std::string mode, float x, float y, float a, float b, int points);
void ellipse(std::string mode, float x, float y, float a, float b);
/**
* Draws an arc using the specified arguments.
* @param drawmode The mode of drawing (line/filled).
* @param arcmode The type of arc.
* @param x X-coordinate.
* @param y Y-coordinate.
* @param radius Radius of the arc.
* @param angle1 The angle at which the arc begins.
* @param angle2 The angle at which the arc terminates.
* @param points Number of points to use to draw the arc.
**/
void arc(std::string mode, std::string arcmode, float x, float y, float radius, float angle1, float angle2, int points);
void arc(std::string mode, std::string arcmode, float x, float y, float radius, float angle1, float angle2);
/**
* Draws a polygon with an arbitrary number of vertices.
* @param mode The type of drawing (line/filled).
* @param coords Vertex positions.
* @param count Vertex array size.
**/
void polygon(std::string mode, const std::vector<glm::vec2>& vertices, bool skipLastFilledVertex = true);
void push(bool all);
void pop();
const glm::mat4 &getTransform() const;
const glm::mat4 &getProjection() const;
void rotate(float r);
void scale(float x, float y = 1.0f);
void translate(float x, float y);
void origin();
// void applyTransform(love::math::Transform *transform);
// void replaceTransform(love::math::Transform *transform);
glm::vec2 transformPoint(glm::vec2 point);
glm::vec2 inverseTransformPoint(glm::vec2 point);
// virtual void draw(const DrawCommand &cmd) = 0;
// virtual void draw(const DrawIndexedCommand &cmd) = 0;
// virtual void drawQuads(int start, int count, const vertex::Attributes &attributes, const vertex::BufferBindings &buffers, Texture *texture) = 0;
protected:
int width = 0;
int height = 0;
int pixelWidth = 0;
int pixelHeight = 0;
Color backgroundColor{0.1f, 0.1f, 0.12f, 1.0f};
bool frameHad3D = false;
bool screenReadbackEnabled = false;
bool graphicsActive = true;
PresentOverlayFn presentOverlayFn_ = nullptr;
void *presentOverlayUser_ = nullptr;
Shader *currentShader = nullptr;
};
} // namespace eve::graphics