Merge pull request #121 from h4570/tyrav2-static-dynamic-pipelines

[Tyra2] Static/Dynamic pipeline/mesh
This commit is contained in:
Sandro Sobczyński
2022-07-25 21:11:05 +02:00
committed by GitHub
166 changed files with 4874 additions and 2018 deletions
+3 -3
View File
@@ -1,10 +1,9 @@
------------ Tyra's v2.0 roadmap to publish on GitHub ------------
--- H4570
- [Renderer] Static and dynamic pipeline
- [Renderer] Add possibility to on/off frustum check in all pipelines (renderOptions?)
- [Loaders] Think about ".tyrobj" format - implement it (add multicolor support)
- [Loaders] DFF loader as static Mesh loader
- [Game] Update intellisense from docker
- [Texture] Test cache hits with large amount of textures (dolphin sample?)
- [Demo] Create cool demo which will show all features of Tyra (I will take this one)
@@ -24,7 +23,7 @@
- [General] Check all TYRA_ASSERT() if there are no asserts like (TYRA_ASSERT(!audsrv_load_adpcm(result, data, adpcmFileSize)))
because this lines will be removed on make-release. Only debug stuff should be checked in assert
- [General] All Copyrights to 2020-2022
- [General] All Copyrights to 2022
- [General] CI in Github via docker image
@@ -54,3 +53,4 @@ because Mesh rendering uses only core.render()
------------ Github issues for Tyra v2 ------------
- [3D] Add drawLine(x, y , color, size)
- [3D] Add drawBBox(x, y , color, size)
- [File] Async file loading
+1
View File
@@ -12,6 +12,7 @@
#include "math/vec4.hpp"
#include "math/math.hpp"
#include <string>
namespace Tyra {
+2
View File
@@ -10,6 +10,8 @@
#pragma once
#include "./vec4.hpp"
#include <string>
namespace Tyra {
-1
View File
@@ -15,7 +15,6 @@ extern "C" {
#include <tamtypes.h>
}
#include <iomanip>
#include <string>
#include "math/math.hpp"
-3
View File
@@ -16,9 +16,6 @@ extern "C" {
}
#include <math3d.h>
#include <iomanip>
#include <cmath>
#include <sstream>
#include <string>
#include "math/math.hpp"
@@ -0,0 +1,82 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#pragma once
#include "loaders/3d/builder/mesh_builder_data.hpp"
#include "../mesh_frame.hpp"
#include "../mesh_material_frame.hpp"
#include "./dynamic_mesh_anim_state.hpp"
#include "../mesh.hpp"
namespace Tyra {
class DynamicMesh : public Mesh {
public:
explicit DynamicMesh(const MeshBuilderData& data);
explicit DynamicMesh(const DynamicMesh& mesh);
~DynamicMesh();
const DynamicMeshAnimState& getAnimState() const { return animState; }
/** Returns single frame. */
MeshFrame* getFrame(const u32& i) { return frames[i]; }
MeshFrame** getFrames() { return frames; }
/** Count of frames. Static object (not animated) will have only 1 frame. */
const u32& getFramesCount() const { return framesCount; }
const u32& getCurrentAnimationFrame() const { return animState.currentFrame; }
const u32& getNextAnimationFrame() const { return animState.nextFrame; }
const u32& getStartAnimationFrame() const { return animState.startFrame; }
const u32& getEndAnimationFrame() const { return animState.endFrame; }
const u32& getStayAnimationFrame() const { return animState.stayFrame; }
void setCurrentAnimationFrame(const u32& v) { animState.currentFrame = v; }
void setNextAnimationFrame(const u32& v) { animState.nextFrame = v; }
void setStartAnimationFrame(const u32& v) { animState.startFrame = v; }
void setEndAnimationFrame(const u32& v) { animState.endFrame = v; }
void setStayAnimationFrame(const u32& v) { animState.stayFrame = v; }
/** @returns bounding box object of current frame. */
const BBox& getCurrentBoundingBox() const {
return frames[animState.currentFrame]->getBBox();
}
/** Loop in one frame */
void playAnimation(const u32& t_frame) { playAnimation(t_frame, t_frame); }
/** Play animation in loop from startFrame to endFrame */
void playAnimation(const u32& t_startFrame, const u32& t_endFrame);
/** Play animation from startFrame to endFrame and after loop in stayFrame
*/
void playAnimation(const u32& t_startFrame, const u32& t_endFrame,
const u32& t_stayFrame);
void setAnimSpeed(const float& t_value) { animState.speed = t_value; }
void animate();
/**
* Check if this class loaded mesh data first.
* Meshes which use loadFrom() method have false there.
*/
const u8& isStayAnimationSet() const { return animState.isStayFrameSet; }
private:
void initAnimation();
DynamicMeshAnimState animState;
u32 framesCount;
MeshFrame** frames;
};
} // namespace Tyra
@@ -25,6 +25,6 @@ typedef struct {
u32 animType;
u32 currentFrame;
u32 nextFrame;
} MeshAnimState;
} DynamicMeshAnimState;
} // namespace Tyra
+14 -75
View File
@@ -10,10 +10,10 @@
#pragma once
#include "loaders/3d/builder/mesh_builder_data.hpp"
#include "./mesh_frame.hpp"
#include "./mesh_material_frame.hpp"
#include "./mesh_anim_state.hpp"
#include "math/m4x4.hpp"
#include "./mesh_material.hpp"
#include <tamtypes.h>
#include "debug/debug.hpp"
namespace Tyra {
@@ -32,89 +32,28 @@ class Mesh {
/** Scale matrix */
M4x4 scale;
const u32& getId() const { return id; }
const u8& isMother() const { return _isMother; }
inline const u32& getId() const { return id; }
inline const u8& isMother() const { return _isMother; }
M4x4 getModelMatrix() const;
/** Get position from translation matrix */
Vec4* getPosition() {
inline Vec4* getPosition() {
return reinterpret_cast<Vec4*>(&translation.data[3 * 4]);
}
void setPosition(const Vec4& v) {
TYRA_ASSERT(v.w == 1.0F, "Vec4 must be homogeneous");
reinterpret_cast<Vec4*>(&translation.data[3 * 4])->set(v);
}
void setPosition(const Vec4& v);
/** Returns material, which is a mesh "subgroup". */
MeshMaterial* getMaterial(const u32& i) const { return materials[i]; }
MeshMaterial** getMaterials() { return materials; }
const u32& getMaterialsCount() const { return materialsCount; }
const MeshAnimState& getAnimState() const { return animState; }
/** Count of all vertices. */
u32 getVertexCount() { return frames[0]->getVertexCount(); }
/** Returns single frame. */
MeshFrame* getFrame(const u32& i) const { return frames[i]; }
/** Count of frames. Static object (not animated) will have only 1 frame. */
const u32& getFramesCount() const { return framesCount; }
const u32& getCurrentAnimationFrame() const { return animState.currentFrame; }
const u32& getNextAnimationFrame() const { return animState.nextFrame; }
const u32& getStartAnimationFrame() const { return animState.startFrame; }
const u32& getEndAnimationFrame() const { return animState.endFrame; }
const u32& getStayAnimationFrame() const { return animState.stayFrame; }
M4x4 getModelMatrix() const;
// /**
// * Returns material, which is a mesh "subgroup".
// * NULL if not found.
// */
// MeshMaterial* getMaterialById(const u32& t_id) const;
/** @returns bounding box object of current frame. */
const BBox& getCurrentBoundingBox() const {
return frames[animState.currentFrame]->getBBox();
}
/** Check if are there any frames */
u8 isDataLoaded() const { return framesCount > 0; }
/** Loop in one frame */
void playAnimation(const u32& t_frame) { playAnimation(t_frame, t_frame); }
/** Play animation in loop from startFrame to endFrame */
void playAnimation(const u32& t_startFrame, const u32& t_endFrame);
/** Play animation from startFrame to endFrame and after loop in stayFrame
*/
void playAnimation(const u32& t_startFrame, const u32& t_endFrame,
const u32& t_stayFrame);
void setAnimSpeed(const float& t_value) { animState.speed = t_value; }
void animate();
/**
* Check if this class loaded mesh data first.
* Meshes which use loadFrom() method have false there.
*/
const u8& isStayAnimationSet() const { return animState.isStayFrameSet; }
private:
void initMesh();
MeshAnimState animState;
protected:
void init();
u8 _isMother;
u32 id, framesCount, materialsCount;
MeshFrame** frames;
u32 id, materialsCount;
MeshMaterial** materials;
};
+2 -13
View File
@@ -10,7 +10,7 @@
#pragma once
#include "renderer/3d/mesh/mesh_material.hpp"
#include "./mesh_material.hpp"
#include "loaders/3d/builder/mesh_builder_data.hpp"
#include "renderer/3d/bbox/bbox.hpp"
@@ -23,18 +23,9 @@ class MeshFrame {
~MeshFrame();
const u32& getId() const { return id; }
const u32& getVertexCount() const { return vertexCount; }
const u32& getTextureCoordsCount() const { return textureCoordsCount; }
const u32& getNormalsCount() const { return normalsCount; }
const u32& getColorsCount() const { return colorsCount; }
const u8& isMother() const { return _isMother; }
const BBox& getBBox() const { return *bbox; }
Vec4* getVertices() const { return vertices; }
Vec4* getNormals() const { return normals; }
Vec4* getTextureCoords() const { return textureCoords; }
Color* getColors() const { return colors; }
void print() const;
void print(const char* name) const;
void print(const std::string& name) const { print(name.c_str()); }
@@ -43,9 +34,7 @@ class MeshFrame {
private:
u8 _isMother;
BBox* bbox;
u32 id, vertexCount, textureCoordsCount, normalsCount, colorsCount;
Vec4 *vertices, *textureCoords, *normals;
Color* colors;
u32 id;
};
} // namespace Tyra
+9 -12
View File
@@ -12,7 +12,7 @@
#include "debug/debug.hpp"
#include "loaders/3d/builder/mesh_builder_data.hpp"
#include "renderer/3d/mesh/mesh_material_frame.hpp"
#include "./mesh_material_frame.hpp"
namespace Tyra {
@@ -22,22 +22,20 @@ class MeshMaterial {
explicit MeshMaterial(const MeshMaterial& material);
~MeshMaterial();
Color singleColor;
Color color;
const u32& getId() const { return id; }
const std::string& getName() const { return _name; }
const u32& getFacesCount() const { return facesCount; }
const u8& isMother() const { return _isMother; }
const u8& isSingleColorActivated() const { return singleColorFlag; }
const u32& getFramesCount() const { return framesCount; }
const u8& isSingleColorActivated() const {
return singleColorFlag;
} // TODO: colormode -> color / lightmap
u32* getVertexFaces() const { return vertexFaces; }
u32* getTextureCoordFaces() const { return textureCoordFaces; }
u32* getNormalFaces() const { return normalFaces; }
u32* getColorFaces() const { return normalFaces; }
MeshMaterialFrame* getFrames() const { return *frames; }
MeshMaterialFrame** getFrames() const { return frames; }
MeshMaterialFrame* getFrame(const u32& i) const { return frames[i]; }
const BBox& getBBox(const u32& frame) const;
void setSingleColorFlag(const u8& flag);
void print() const;
@@ -50,8 +48,7 @@ class MeshMaterial {
std::string _name;
u8 _isMother, singleColorFlag;
u32 id, facesCount, framesCount;
u32 *vertexFaces, *textureCoordFaces, *normalFaces, *colorFaces;
u32 id, framesCount;
};
} // namespace Tyra
@@ -10,6 +10,7 @@
#pragma once
#include "loaders/3d/builder/mesh_builder_data.hpp"
#include "./renderer/3d/bbox/bbox.hpp"
namespace Tyra {
@@ -25,11 +26,33 @@ class MeshMaterialFrame {
const u8& isMother() const { return _isMother; }
const BBox& getBBox() const { return *bbox; }
const u32& getVertexCount() const { return vertexCount; }
Vec4* getVertices() const { return vertices; }
Vec4* getNormals() const { return normals; }
Vec4* getTextureCoords() const { return textureCoords; }
Color* getColors() const { return colors; }
void print() const;
void print(const char* name) const;
void print(const std::string& name) const { print(name.c_str()); }
std::string getPrint(const char* name = nullptr) const;
private:
void allocateVertices(const MeshBuilderData& data, const u32& frameIndex,
const u32& materialIndex);
void allocateTextureCoords(const MeshBuilderData& data, const u32& frameIndex,
const u32& materialIndex);
void allocateNormals(const MeshBuilderData& data, const u32& frameIndex,
const u32& materialIndex);
void allocateColors(const MeshBuilderData& data, const u32& frameIndex,
const u32& materialIndex);
BBox* bbox;
u8 _isMother;
u32 id;
u32 id, vertexCount;
Vec4 *vertices, *textureCoords, *normals;
Color* colors;
};
} // namespace Tyra
@@ -0,0 +1,34 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#pragma once
#include "../mesh.hpp"
#include "../mesh_frame.hpp"
#include "../mesh_material.hpp"
namespace Tyra {
class StaticMesh : public Mesh {
public:
StaticMesh(const MeshBuilderData& data);
StaticMesh(const StaticMesh& mesh);
~StaticMesh();
MeshFrame* getFrame() { return frame; }
/** @returns bounding box object of current frame. */
const BBox& getBoundingBox() const { return frame->getBBox(); }
private:
MeshFrame* frame;
};
} // namespace Tyra
@@ -0,0 +1,67 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#pragma once
#include "math/vec4.hpp"
#include "renderer/3d/pipeline/shared/bag/pipeline_info_bag.hpp"
#include "./dynpip_color_bag.hpp"
#include "./dynpip_lighting_bag.hpp"
#include "./dynpip_texture_bag.hpp"
#include "renderer/core/texture/models/texture.hpp"
namespace Tyra {
/**
* @brief 3D Animated render data bag.
* Supports frustum culling, simple clipping (culling), lighting,
* texture and single color / many colors.
*/
class DynPipBag {
public:
DynPipBag();
~DynPipBag();
/** Mandatory. Object info. */
PipelineInfoBag* info;
/** Mandatory. Object color(s). */
DynPipColorBag* color;
/** Mandatory. Vertex count per frame. */
u32 count;
/** Mandatory. From (frame) vertices */
Vec4* verticesFrom;
/** Mandatory. To (frame) vertices */
Vec4* verticesTo;
/**
* Mandatory.
* State of animation interpolation
* (between from and to)
*/
float interpolation;
/** Optional. Texture coordinates and image. */
DynPipTextureBag* texture;
/** Optional. Object lighting. */
DynPipLightingBag* lighting;
void print() const;
void print(const char* name) const;
void print(const std::string& name) const { print(name.c_str()); }
std::string getPrint(const char* name = nullptr) const;
};
} // namespace Tyra
@@ -0,0 +1,29 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#pragma once
#include "renderer/models/color.hpp"
namespace Tyra {
/**
* @brief Color data. At least one color data is required (single/many).
*/
class DynPipColorBag {
public:
DynPipColorBag();
~DynPipColorBag();
/** Mandatory */
Color* single;
};
} // namespace Tyra
@@ -0,0 +1,36 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#pragma once
#include "math/vec4.hpp"
#include "renderer/3d/pipeline/shared/bag/pipeline_dir_lights_bag.hpp"
namespace Tyra {
class DynPipLightingBag {
public:
DynPipLightingBag();
~DynPipLightingBag();
/** Mandatory. Model matrix for lights. */
M4x4* lightMatrix;
/** Mandatory. Lighting normals per vertex. */
Vec4* normalsFrom;
Vec4* normalsTo;
/** Mandatory. Directional lights */
PipelineDirLightsBag* dirLights;
void freeNormals();
};
} // namespace Tyra
@@ -10,25 +10,24 @@
#pragma once
#include <draw.h>
#include "math/m4x4.hpp"
#include "math/vec4.hpp"
#include "../../stdpip_shading_type.hpp"
#include "renderer/core/texture/models/texture.hpp"
namespace Tyra {
class StdpipInfoBag {
class DynPipTextureBag {
public:
StdpipInfoBag();
~StdpipInfoBag();
DynPipTextureBag();
~DynPipTextureBag();
/** Mandatory. Model matrix */
M4x4* model;
/** Mandatory. Texture coordinates per vertex. */
Vec4* coordinatesFrom;
Vec4* coordinatesTo;
StdpipShadingType shadingType;
bool blendingEnabled;
bool antiAliasingEnabled;
bool noClipChecks;
/** Mandatory. Texture image. */
Texture* texture;
void freeCoords();
};
} // namespace Tyra
@@ -0,0 +1,66 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#pragma once
#include <tamtypes.h>
#include "./bag/dynpip_bag.hpp"
#include "renderer/core/renderer_core.hpp"
#include "./dynpip_programs_repository.hpp"
#include "./dynpip_renderer.hpp"
namespace Tyra {
class DynPipCore {
public:
DynPipCore();
~DynPipCore();
DynPipProgramsRepository repository;
void init(RendererCore* t_core);
/** Force starting VU1 program instead of continueing */
void clear() { qbufferRenderer.clearLastProgramName(); }
/**
* Send model matrix, lighting data and other
* repetitve stuff to VU1
*/
void initParts(DynPipBag* data);
/** Render 3D via "bags" */
void renderPart(DynPipBag** bags, const u32& count,
const bool& frustumCull = true);
/** Get max vert count of VU1 qbuffer (for optimizations) */
u32 getMaxVertCountByParams(const bool& isLightingEnabled,
const bool& isTextureEnabled);
/**
* - Uploads standard VU1 programs.
* - Sends static "Tyra Renderer3D" VU1 data.
* - Sets double buffers exactly for "Tyra Renderer3D"
* Should be called if VU1 was used by your non standard programs.
*/
void reinitVU1Programs();
void allocateOnUse(const u32& t_packetSize) {
qbufferRenderer.allocateOnUse(t_packetSize);
}
void deallocateOnUse() { qbufferRenderer.deallocateOnUse(); }
private:
M4x4 mvp;
RendererCore* rendererCore;
DynPipRenderer qbufferRenderer;
};
} // namespace Tyra
@@ -0,0 +1,24 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#pragma once
namespace Tyra {
enum DynPipProgramName {
DynPipUndefinedProgram,
DynPipColor,
DynPipDirLights,
DynPipTextureDirLights,
DynPipTextureColor,
};
} // namespace Tyra
@@ -0,0 +1,41 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#pragma once
#include "debug/debug.hpp"
#include "renderer/core/paths/path1/vu1_program.hpp"
#include "./bag/dynpip_bag.hpp"
#include "./programs/dynpip_c_vu1_program.hpp"
#include "./programs/dynpip_d_vu1_program.hpp"
#include "./programs/dynpip_td_vu1_program.hpp"
#include "./programs/dynpip_tc_vu1_program.hpp"
namespace Tyra {
class DynPipProgramsRepository {
public:
DynPipProgramsRepository();
~DynPipProgramsRepository();
DynPipVU1Program* getProgram(const DynPipProgramName& name);
DynPipVU1Program* getProgramByParams(const bool& isLightingEnabled,
const bool& isTextureEnabled);
DynPipVU1Program* getProgramByBag(const DynPipBag* bag);
private:
DynPipCVU1Program color;
DynPipDVU1Program dirLights;
DynPipTDVU1Program textureDirLights;
DynPipTCVU1Program textureColor;
};
} // namespace Tyra
@@ -0,0 +1,66 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#pragma once
#include <tamtypes.h>
#include "renderer/core/renderer_core.hpp"
#include "./dynpip_programs_repository.hpp"
namespace Tyra {
class DynPipRenderer {
public:
DynPipRenderer();
~DynPipRenderer();
void init(RendererCore* t_core, DynPipProgramsRepository* t_programRepo);
void reinitVU1();
void sendObjectData(DynPipBag* bag, M4x4* mvp,
RendererCoreTextureBuffers* texBuffers) const;
void render(DynPipBag** bags, const u32& count);
void clearLastProgramName();
const u16& getBufferSize() { return bufferSize; }
void allocateOnUse(const u32& t_packetSize);
void deallocateOnUse();
private:
void sendStaticData() const;
void setProgramsCache();
void uploadPrograms();
void setDoubleBuffer();
void addBufferDataToPacket(DynPipVU1Program* program, DynPipBag** bags,
const u32& count);
void sendPacket();
packet2_t* packets[2];
packet2_t* programsPacket;
packet2_t* currentPacket;
packet2_t* staticDataPacket;
packet2_t* objectDataPacket;
DynPipProgramsRepository* programsRepo;
RendererCore* rendererCore;
Path1* path1;
DynPipProgramName lastProgramName;
u16 bufferSize;
u8 context;
};
} // namespace Tyra
@@ -0,0 +1,48 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#pragma once
#include "./dynpip_program_name.hpp"
#include "renderer/core/paths/path1/vu1_program.hpp"
#include "./programs/dynpip_vu1_shared_defines.h"
#include "./bag/dynpip_bag.hpp"
namespace Tyra {
class DynPipVU1Program : public VU1Program {
public:
DynPipVU1Program(const DynPipProgramName& name, u32* start, u32* end,
const u32& t_reglist, const u8& t_reglistCount,
const u8& t_elementsPerVertex);
~DynPipVU1Program();
u32& getReglist();
const DynPipProgramName& getName() const;
u16 getMaxVertCount(const u16& vu1DBufferSize) const;
void addBufferDataToPacket(packet2_t* packet, DynPipBag* bag, prim_t* prim);
protected:
DynPipProgramName name;
u8 reglistCount, elementsPerVertex;
u32 destinationAddress, reglist;
virtual void addProgramQBufferDataToPacket(packet2_t* packet,
DynPipBag* bag) const = 0;
private:
void addStandardBufferDataToPacket(packet2_t* packet, DynPipBag* bag,
prim_t* prim);
};
} // namespace Tyra
@@ -12,17 +12,17 @@
#include <packet2_utils.h>
#include <string>
#include "../../vu1_program.hpp"
#include "../dynpip_vu1_program.hpp"
namespace Tyra {
class VU1DrawFinish : public VU1Program {
class DynPipCVU1Program : public DynPipVU1Program {
public:
VU1DrawFinish();
~VU1DrawFinish();
DynPipCVU1Program();
~DynPipCVU1Program();
std::string getStringName() const;
void addTag(packet2_t* packet, prim_t* prim) const;
void addProgramQBufferDataToPacket(packet2_t* packet, DynPipBag* bag) const;
};
} // namespace Tyra
@@ -0,0 +1,28 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#pragma once
#include <packet2_utils.h>
#include <string>
#include "../dynpip_vu1_program.hpp"
namespace Tyra {
class DynPipDVU1Program : public DynPipVU1Program {
public:
DynPipDVU1Program();
~DynPipDVU1Program();
std::string getStringName() const;
void addProgramQBufferDataToPacket(packet2_t* packet, DynPipBag* bag) const;
};
} // namespace Tyra
@@ -0,0 +1,28 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#pragma once
#include <packet2_utils.h>
#include <string>
#include "../dynpip_vu1_program.hpp"
namespace Tyra {
class DynPipTCVU1Program : public DynPipVU1Program {
public:
DynPipTCVU1Program();
~DynPipTCVU1Program();
std::string getStringName() const;
void addProgramQBufferDataToPacket(packet2_t* packet, DynPipBag* bag) const;
};
} // namespace Tyra
@@ -0,0 +1,28 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#pragma once
#include <packet2_utils.h>
#include <string>
#include "../dynpip_vu1_program.hpp"
namespace Tyra {
class DynPipTDVU1Program : public DynPipVU1Program {
public:
DynPipTDVU1Program();
~DynPipTDVU1Program();
std::string getStringName() const;
void addProgramQBufferDataToPacket(packet2_t* packet, DynPipBag* bag) const;
};
} // namespace Tyra
@@ -0,0 +1,89 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#pragma once
#include <tamtypes.h>
#include "../renderer_3d_pipeline.hpp"
#include "./dynpip_options.hpp"
#include "./core/dynpip_core.hpp"
#include "renderer/core/renderer_core.hpp"
#include "renderer/3d/mesh/dynamic/dynamic_mesh.hpp"
namespace Tyra {
/**
* Pipeline for animated models (DynamicMesh).
* Supports:
* - Simple PS2 clipping (culling)
* - Frustum culling
* - Modes: color, texture+color, dir lights, texture + dir lights
*/
class DynamicPipeline : public Renderer3DPipeline {
public:
DynamicPipeline();
~DynamicPipeline();
static const u32 buffersCount;
DynPipCore core;
void setRenderer(RendererCore* core);
void onUse();
void onUseEnd();
/**
* Render dynamic model.
* This render() method is a bridge to core.render() method.
*/
void render(DynamicMesh* mesh, const DynPipOptions* options = nullptr);
private:
RendererCore* rendererCore;
Vec4* colorsCache;
DynPipBag* buffers;
static const u32 halfBuffersCount;
void setBuffer(DynPipBag* buffers, DynPipBag* buffer, u16* bufferIndex,
const PipelineFrustumCulling& frustumCulling);
void sendRestOfBuffers(DynPipBag* buffers, u16* bufferIndex,
const PipelineFrustumCulling& frustumCulling);
void addVertices(MeshMaterialFrame* materialFrameFrom,
MeshMaterialFrame* materialFrameTo, DynPipBag* bag,
const u32& startIndex) const;
PipelineInfoBag* getInfoBag(DynamicMesh* mesh, const DynPipOptions* options,
M4x4* model) const;
DynPipColorBag* getColorBag(MeshMaterial* material) const;
DynPipTextureBag* getTextureBag(MeshMaterial* material,
MeshMaterialFrame* materialFrameFrom,
MeshMaterialFrame* materialFrameTo,
const u32& startIndex);
DynPipLightingBag* getLightingBag(MeshMaterialFrame* materialFrameFrom,
MeshMaterialFrame* materialFrameTo,
M4x4* model, const DynPipOptions* options,
PipelineDirLightsBag* dirLightsBag,
const u32& startIndex) const;
void setLightingColorsCache(PipelineLightingOptions* lightingOptions);
void freeBuffer(DynPipBag* bag);
void setBuffersDefaultVars(DynPipBag* buffers, DynamicMesh* mesh,
PipelineInfoBag* infoBag);
void setBuffersColorBag(DynPipBag* buffers, DynPipColorBag* colorBag);
};
} // namespace Tyra
@@ -0,0 +1,23 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#pragma once
#include "renderer/3d/pipeline/shared/pipeline_options.hpp"
namespace Tyra {
class DynPipOptions : public PipelineOptions {
public:
DynPipOptions() {}
~DynPipOptions() {}
};
} // namespace Tyra
@@ -18,17 +18,34 @@
namespace Tyra {
/**
* Pipeline specialized in fast rendering of voxels
* Supports:
* - Full "against each plane" clipping
* - Frustum culling (on fullClipChecks = true)
*/
class MinecraftPipeline : public Renderer3DPipeline {
public:
MinecraftPipeline();
~MinecraftPipeline();
void init(RendererCore* core);
void setRenderer(RendererCore* core);
void onUse();
void onUseEnd();
/**
* @brief Render voxels
*
* @param blocks blocks to render
* @param count number of blocks to render
* @param t_tex texture to use
* @param isMulti is this a 6 texture voxel?
* @param fullClipChecks false = faster, simple PS2 clipping. True = slower
* "against each plane" clipping.
*/
void render(McpipBlock* blocks, const u32& count, Texture* t_tex,
const bool& isMulti = false, const bool& noClipChecks = true);
const bool& isMulti = false, const bool& fullClipChecks = false);
inline const float& getTextureOffset() const {
return manager.getTextureOffset();
@@ -42,12 +59,17 @@ class MinecraftPipeline : public Renderer3DPipeline {
RenderBBox* bbox;
McpipProgramName latestMode;
McpipBlock*** spamBuffers;
u32* spamCounts;
u32 spamBuffersCount;
u32 spammerIndex;
void initBBox();
void changeMode(const McpipProgramName& requestedMode, const u8& force);
void cull(McpipBlock* blocks, const std::vector<u32>& indexes,
RendererCoreTextureBuffers* texBuffers,
RendererCoreTextureBuffers* texBuffers, const bool& isCullOnly,
const bool& isMulti = false);
void clip(McpipBlock* blocks, const std::vector<u32>& indexes,
@@ -55,6 +77,12 @@ class MinecraftPipeline : public Renderer3DPipeline {
const bool& isMulti = false);
Tyra::CoreBBoxFrustum isInFrustum(const McpipBlock& block) const;
void addToSpammer(McpipBlock** blockPointerArray, const u32& count,
RendererCoreTextureBuffers* texBuffers,
const bool& isMulti);
void flushSpammer(RendererCoreTextureBuffers* texBuffers,
const bool& isMulti);
};
} // namespace Tyra
@@ -18,7 +18,7 @@
#include "../../mcpip_block.hpp"
#include "../../data/mcpip_block_data.hpp"
#include "./mcpip_vu1_as_is_shared_defines.h"
#include "renderer/core/paths/path1/clipper/path1_ee_clip_algorithm.hpp"
#include "renderer/core/3d/clipper/ee_clip_algorithm.hpp"
namespace Tyra {
@@ -27,8 +27,8 @@ class McpipClip {
McpipClip();
~McpipClip();
Path1EEClipAlgorithm algorithm;
Path1EEClipAlgorithmSettings algoSettings;
EEClipAlgorithm algorithm;
EEClipAlgorithmSettings algoSettings;
void init(RendererCore* core, McpipBlockData* t_singleBlockData,
McpipBlockData* t_multiBlockData);
@@ -48,16 +48,14 @@ class McpipClip {
packet2_t* staticPacket;
u16 vu1DBufferSize;
std::vector<Path1ClipVertex> clippedTriangle;
std::vector<Path1ClipVertex> inputTriangle;
std::vector<EEClipVertex> clippedTriangle;
std::vector<EEClipVertex> inputTriangle;
Vec4 vertexBuffers[2][108];
Vec4 texCoordBuffers[2][108];
void addCorrections(std::vector<Path1ClipVertex>* vertices,
McpipBlock* block);
void moveDataToBuffer(std::vector<Path1ClipVertex>* vertices,
const u8& context);
void addCorrections(std::vector<EEClipVertex>* vertices, McpipBlock* block);
void moveDataToBuffer(std::vector<EEClipVertex>* vertices, const u8& context);
void addDataToPacket(packet2_t* packet, const u8& context, McpipBlock* block,
const int& count,
RendererCoreTextureBuffers* texBuffers);
@@ -42,6 +42,10 @@ class BlockizerProgramsManager {
void clearLastProgram() { lastProgramName = UndefinedMcpipProgram; }
void cullSpam(McpipBlock*** blockPointerArrays, u32* blockPointerArrayCounts,
u32 blockPointerArraysCount,
RendererCoreTextureBuffers* texBuffers, const bool& isMulti);
void cull(McpipBlock** blockPointerArray, u32 blockPointerArrayCount,
RendererCoreTextureBuffers* texBuffers, const bool& isMulti);
@@ -54,6 +58,9 @@ class BlockizerProgramsManager {
const McpipBlockData& getBlockData() const { return singleTexBlockData; }
void allocateOnUse();
void deallocateOnUse();
private:
McpipProgramsRepository repo;
Renderer* renderer;
@@ -69,6 +76,7 @@ class BlockizerProgramsManager {
void setProgramsCache();
void uploadBlock(bool isMulti);
void addProgram(McpipProgram* program);
void sendPacket(McpipProgram* program);
};
@@ -19,8 +19,9 @@ class Renderer3DPipeline {
Renderer3DPipeline() {}
~Renderer3DPipeline() {}
virtual void init(RendererCore* core) = 0;
virtual void setRenderer(RendererCore* core) = 0;
virtual void onUse() = 0;
virtual void onUseEnd() = 0;
};
} // namespace Tyra
@@ -16,15 +16,12 @@
namespace Tyra {
enum StdpipLightingBagMode { Auto, Manual };
enum PipelineDirLightsBagMode { Auto, Manual };
class StdpipLightingBag {
class PipelineDirLightsBag {
public:
explicit StdpipLightingBag(const bool& manual = false);
~StdpipLightingBag();
Vec4* normals;
M4x4* lightMatrix;
explicit PipelineDirLightsBag(const bool& manual = false);
~PipelineDirLightsBag();
void setAmbientColor(const Color& color);
void setDirectionalLightColors(Color* colors, const u8& count);
@@ -47,7 +44,7 @@ class StdpipLightingBag {
void deallocate();
void forceDeallocate();
u8 isAllocated;
StdpipLightingBagMode mode;
PipelineDirLightsBagMode mode;
Vec4* lightColors;
Vec4* lightDirections;
@@ -0,0 +1,44 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#pragma once
#include <draw.h>
#include "math/m4x4.hpp"
#include "math/vec4.hpp"
#include "../pipeline_shading_type.hpp"
namespace Tyra {
class PipelineInfoBag {
public:
PipelineInfoBag();
~PipelineInfoBag();
/** Mandatory. Model matrix */
M4x4* model;
PipelineShadingType shadingType;
bool blendingEnabled;
bool antiAliasingEnabled;
/**
* @brief False -> disables "clip against each plane" algorithm.
* Default: True.
*
* Full clip checks are slow, but they are
* preventing visual artifacts, which can happen
* for big 3D objects (or objects near camera eyes)
* Force enabled in dynamic pipe, because of efficiency.
*/
bool fullClipChecks;
};
} // namespace Tyra
@@ -0,0 +1,24 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#pragma once
namespace Tyra {
enum PipelineFrustumCulling {
/** No frustum culling */
PipelineFrustumCulling_None = 0,
/** Frustum culling of whole object */
PipelineFrustumCulling_Simple = 1,
/** Frustum culling of parts of an object */
PipelineFrustumCulling_Precise = 2,
};
}
@@ -15,10 +15,10 @@
namespace Tyra {
class StdpipLightingOptions {
class PipelineLightingOptions {
public:
StdpipLightingOptions() {}
~StdpipLightingOptions() {}
PipelineLightingOptions() {}
~PipelineLightingOptions() {}
/**
* Mandatory.
@@ -10,23 +10,24 @@
#pragma once
#include "./stdpip_shading_type.hpp"
#include "./stdpip_lighting_options.hpp"
#include "renderer/3d/pipeline/shared/pipeline_shading_type.hpp"
#include "../shared/pipeline_lighting_options.hpp"
#include "./pipeline_frustum_culling.hpp"
namespace Tyra {
class StdpipOptions {
class PipelineOptions {
public:
StdpipOptions() {}
~StdpipOptions() {}
PipelineOptions() { lighting = nullptr; }
~PipelineOptions() {}
StdpipShadingType shadingType;
PipelineFrustumCulling frustumCulling;
PipelineShadingType shadingType;
bool blendingEnabled;
bool antiAliasingEnabled;
bool noClipChecks;
/** Optional */
StdpipLightingOptions* lighting;
PipelineLightingOptions* lighting;
};
} // namespace Tyra
@@ -12,9 +12,9 @@
namespace Tyra {
enum StdpipShadingType {
StdpipShadingFlat,
StdpipShadingGouraud,
enum PipelineShadingType {
TyraShadingFlat,
TyraShadingGouraud,
};
} // namespace Tyra
@@ -10,17 +10,17 @@
#pragma once
#include "../stdpip_bag.hpp"
#include "../stapip_bag.hpp"
#include "renderer/core/3d/bbox/core_bbox_frustum.hpp"
namespace Tyra {
class StdpipBagPackage {
class StaPipBagPackage {
public:
StdpipBagPackage();
~StdpipBagPackage();
StaPipBagPackage();
~StaPipBagPackage();
StdpipBag* bag;
StaPipBag* bag;
Vec4* vertices;
Vec4* sts;
@@ -32,12 +32,12 @@ class StdpipBagPackage {
CoreBBoxFrustum isInFrustum;
/**
* We are creating StdpipBagPackagesBBox which checks CoreBBoxBBox for every
* We are creating StaPipBagPackagesBBox which checks CoreBBoxBBox for every
* maxVertCount / 3. So this variable is index of starting
* StdpipBagPackagesBBox's CoreBBoxBBox. If package have <= maxVertCount / 3
* StaPipBagPackagesBBox's CoreBBoxBBox. If package have <= maxVertCount / 3
* verts, we will need only single (starting) bbox. if package have
* maxVertCount verts, we will calculate CoreBBoxBBox from 3
* StdpipBagPackagesBBox's bboxes.
* StaPipBagPackagesBBox's bboxes.
*/
u32 indexOf1By3BBox;
@@ -12,20 +12,20 @@
#include "renderer/core/3d/bbox/core_bbox.hpp"
#include "renderer/core/3d/renderer_3d_frustum_planes.hpp"
#include "renderer/core/paths/path1/clipper/path1_ee_clip_algorithm.hpp"
#include "./stdpip_bag_packages_bbox.hpp"
#include "./stdpip_bag_package.hpp"
#include "../stdpip_bag.hpp"
#include "renderer/core/3d/clipper/ee_clip_algorithm.hpp"
#include "./stapip_bag_packages_bbox.hpp"
#include "./stapip_bag_package.hpp"
#include "../stapip_bag.hpp"
namespace Tyra {
class StdpipBagPackager {
class StaPipBagPackager {
public:
StdpipBagPackager();
~StdpipBagPackager();
StaPipBagPackager();
~StaPipBagPackager();
void init(Renderer3DFrustumPlanes* frustumPlanes);
void setRenderBBox(StdpipBagPackagesBBox* bbox) { renderBBox = bbox; }
void setRenderBBox(StaPipBagPackagesBBox* bbox) { renderBBox = bbox; }
void setMaxVertCount(const u32& count);
/**
@@ -33,20 +33,20 @@ class StdpipBagPackager {
*
* @param size Max maxVertCount verts (VU1 buffer size)
*/
StdpipBagPackage* create(u16* o_size, StdpipBag* data, u16 size);
StaPipBagPackage* create(u16* o_size, StaPipBag* data, u16 size);
/**
* @brief Split render package to smaller packages
*
* @param size Max maxVertCount verts (VU1 buffer size)
*/
StdpipBagPackage* create(u16* o_size, const StdpipBagPackage& pkg, u16 size);
StaPipBagPackage* create(u16* o_size, const StaPipBagPackage& pkg, u16 size);
CoreBBoxFrustum checkFrustum(const StdpipBagPackage& pkg);
CoreBBoxFrustum checkFrustum(const StaPipBagPackage& pkg);
private:
u32 maxVertCount;
Renderer3DFrustumPlanes* frustumPlanes;
StdpipBagPackagesBBox* renderBBox;
StaPipBagPackagesBBox* renderBBox;
};
} // namespace Tyra
@@ -18,13 +18,13 @@ namespace Tyra {
* Splits all 3D input vertices into 16vert parts and creates child bboxes for
* it
*/
class StdpipBagPackagesBBox {
class StaPipBagPackagesBBox {
public:
StdpipBagPackagesBBox(Vec4* t_vertices, u32* t_faces, const u32& t_facesCount,
StaPipBagPackagesBBox(Vec4* t_vertices, u32* t_faces, const u32& t_facesCount,
const u32& t_maxVertCount);
StdpipBagPackagesBBox(Vec4* t_vertices, const u32& t_counts,
StaPipBagPackagesBBox(Vec4* t_vertices, const u32& t_counts,
const u32& t_maxVertCount);
~StdpipBagPackagesBBox();
~StaPipBagPackagesBBox();
void setMaxVertCount(const u32& count);
@@ -11,30 +11,30 @@
#pragma once
#include "math/vec4.hpp"
#include "./stdpip_lighting_bag.hpp"
#include "./stdpip_info_bag.hpp"
#include "./stdpip_color_bag.hpp"
#include "./stdpip_texture_bag.hpp"
#include "renderer/3d/pipeline/shared/bag/pipeline_info_bag.hpp"
#include "./stapip_color_bag.hpp"
#include "./stapip_lighting_bag.hpp"
#include "./stapip_texture_bag.hpp"
#include "renderer/core/texture/models/texture.hpp"
#include "./packaging/stdpip_bag_packages_bbox.hpp"
#include "./packaging/stapip_bag_packages_bbox.hpp"
namespace Tyra {
/**
* @brief 3D Render data bag.
* Supports frustum culling, clipping, lighting,
* Supports frustum culling, full plane clipping, lighting,
* texture and single color / many colors.
*/
class StdpipBag {
class StaPipBag {
public:
StdpipBag();
~StdpipBag();
StaPipBag();
~StaPipBag();
/** Mandatory. Object info. */
StdpipInfoBag* info;
PipelineInfoBag* info;
/** Mandatory. Object color(s). */
StdpipColorBag* color;
StaPipColorBag* color;
/** Mandatory. Vertex count. */
u32 count;
@@ -43,15 +43,15 @@ class StdpipBag {
Vec4* vertices;
/** Optional. Texture coordinates and image. */
StdpipTextureBag* texture;
StaPipTextureBag* texture;
/** Optional. Object lighting. */
StdpipLightingBag* lighting;
StaPipLightingBag* lighting;
/**
* @param maxVertCount This parameter is available in renderer API.
*/
StdpipBagPackagesBBox calculateBbox(const u32& maxVertCount);
StaPipBagPackagesBBox calculateBbox(const u32& maxVertCount);
void print() const;
void print(const char* name) const;
@@ -17,10 +17,10 @@ namespace Tyra {
/**
* @brief Color data. At least one color data is required (single/many).
*/
class StdpipColorBag {
class StaPipColorBag {
public:
StdpipColorBag();
~StdpipColorBag();
StaPipColorBag();
~StaPipColorBag();
/** Optional. Single color for all vertices. */
Color* single;
@@ -0,0 +1,33 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#pragma once
#include "math/vec4.hpp"
#include "renderer/3d/pipeline/shared/bag/pipeline_dir_lights_bag.hpp"
namespace Tyra {
class StaPipLightingBag {
public:
StaPipLightingBag();
~StaPipLightingBag();
/** Mandatory. Model matrix for lights. */
M4x4* lightMatrix;
/** Mandatory. Lighting normals per vertex. */
Vec4* normals;
/** Mandatory. Directional lights */
PipelineDirLightsBag* dirLights;
};
} // namespace Tyra
@@ -15,10 +15,10 @@
namespace Tyra {
class StdpipTextureBag {
class StaPipTextureBag {
public:
StdpipTextureBag();
~StdpipTextureBag();
StaPipTextureBag();
~StaPipTextureBag();
/** Mandatory. Texture coordinates per vertex. */
Vec4* coordinates;
@@ -12,19 +12,19 @@
#include <packet2_utils.h>
#include <string>
#include "../../stdpip_vu1_program.hpp"
#include "../../stapip_vu1_program.hpp"
namespace Tyra {
class StdpipAsIsCVU1Program : public StdpipVU1Program {
class StaPipAsIsCVU1Program : public StaPipVU1Program {
public:
StdpipAsIsCVU1Program();
~StdpipAsIsCVU1Program();
StaPipAsIsCVU1Program();
~StaPipAsIsCVU1Program();
std::string getStringName() const;
void addProgramQBufferDataToPacket(packet2_t* packet,
StdpipQBuffer* qbuffer) const;
StaPipQBuffer* qbuffer) const;
};
} // namespace Tyra
@@ -12,18 +12,18 @@
#include <packet2_utils.h>
#include <string>
#include "../../stdpip_vu1_program.hpp"
#include "../../stapip_vu1_program.hpp"
namespace Tyra {
class StdpipAsIsDVU1Program : public StdpipVU1Program {
class StaPipAsIsDVU1Program : public StaPipVU1Program {
public:
StdpipAsIsDVU1Program();
~StdpipAsIsDVU1Program();
StaPipAsIsDVU1Program();
~StaPipAsIsDVU1Program();
std::string getStringName() const;
void addProgramQBufferDataToPacket(packet2_t* packet,
StdpipQBuffer* qbuffer) const;
StaPipQBuffer* qbuffer) const;
};
} // namespace Tyra
@@ -12,18 +12,18 @@
#include <packet2_utils.h>
#include <string>
#include "../../stdpip_vu1_program.hpp"
#include "../../stapip_vu1_program.hpp"
namespace Tyra {
class StdpipAsIsTCVU1Program : public StdpipVU1Program {
class StaPipAsIsTCVU1Program : public StaPipVU1Program {
public:
StdpipAsIsTCVU1Program();
~StdpipAsIsTCVU1Program();
StaPipAsIsTCVU1Program();
~StaPipAsIsTCVU1Program();
std::string getStringName() const;
void addProgramQBufferDataToPacket(packet2_t* packet,
StdpipQBuffer* qbuffer) const;
StaPipQBuffer* qbuffer) const;
};
} // namespace Tyra
@@ -12,18 +12,18 @@
#include <packet2_utils.h>
#include <string>
#include "../../stdpip_vu1_program.hpp"
#include "../../stapip_vu1_program.hpp"
namespace Tyra {
class StdpipCullCVU1Program : public StdpipVU1Program {
class StaPipAsIsTDVU1Program : public StaPipVU1Program {
public:
StdpipCullCVU1Program();
~StdpipCullCVU1Program();
StaPipAsIsTDVU1Program();
~StaPipAsIsTDVU1Program();
std::string getStringName() const;
void addProgramQBufferDataToPacket(packet2_t* packet,
StdpipQBuffer* qbuffer) const;
StaPipQBuffer* qbuffer) const;
};
} // namespace Tyra
@@ -12,18 +12,18 @@
#include <packet2_utils.h>
#include <string>
#include "../../stdpip_vu1_program.hpp"
#include "../../stapip_vu1_program.hpp"
namespace Tyra {
class StdpipCullDVU1Program : public StdpipVU1Program {
class StaPipCullCVU1Program : public StaPipVU1Program {
public:
StdpipCullDVU1Program();
~StdpipCullDVU1Program();
StaPipCullCVU1Program();
~StaPipCullCVU1Program();
std::string getStringName() const;
void addProgramQBufferDataToPacket(packet2_t* packet,
StdpipQBuffer* qbuffer) const;
StaPipQBuffer* qbuffer) const;
};
} // namespace Tyra
@@ -0,0 +1,29 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#pragma once
#include <packet2_utils.h>
#include <string>
#include "../../stapip_vu1_program.hpp"
namespace Tyra {
class StaPipCullDVU1Program : public StaPipVU1Program {
public:
StaPipCullDVU1Program();
~StaPipCullDVU1Program();
std::string getStringName() const;
void addProgramQBufferDataToPacket(packet2_t* packet,
StaPipQBuffer* qbuffer) const;
};
} // namespace Tyra
@@ -12,18 +12,18 @@
#include <packet2_utils.h>
#include <string>
#include "../../stdpip_vu1_program.hpp"
#include "../../stapip_vu1_program.hpp"
namespace Tyra {
class StdpipAsIsTDVU1Program : public StdpipVU1Program {
class StaPipCullTCVU1Program : public StaPipVU1Program {
public:
StdpipAsIsTDVU1Program();
~StdpipAsIsTDVU1Program();
StaPipCullTCVU1Program();
~StaPipCullTCVU1Program();
std::string getStringName() const;
void addProgramQBufferDataToPacket(packet2_t* packet,
StdpipQBuffer* qbuffer) const;
StaPipQBuffer* qbuffer) const;
};
} // namespace Tyra
@@ -0,0 +1,29 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#pragma once
#include <packet2_utils.h>
#include <string>
#include "../../stapip_vu1_program.hpp"
namespace Tyra {
class StaPipCullTDVU1Program : public StaPipVU1Program {
public:
StaPipCullTDVU1Program();
~StaPipCullTDVU1Program();
std::string getStringName() const;
void addProgramQBufferDataToPacket(packet2_t* packet,
StaPipQBuffer* qbuffer) const;
};
} // namespace Tyra
@@ -0,0 +1,24 @@
//
// ______ ____ ___
// | \/ ____| |___|
// | | | \ | |
//-----------------------------------------------------------------------
// Copyright 2022, tyra - https://github.com/h4570/tyra
// Licenced under Apache License 2.0
// Sandro Sobczyński <sandro.sobczynski@gmail.com>
//
// Updated once per mesh
#define VU1_MVP_MATRIX_ADDR 0
#define VU1_LIGHTS_MATRIX_ADDR 4
#define VU1_SINGLE_COLOR_ADDR 7
#define VU1_OPTIONS_ADDR 8
#define VU1_LOD_ADDR 9
#define VU1_CLUT_ADDR 10
#define VU1_LIGHTS_DIRS_ADDR 11
#define VU1_LIGHTS_COLORS_ADDR 14
#define VU1_SET_GIFTAG_ADDR 18
#define VU1_LAST_ITEM_ADDR 18
// Buffer data (xtop)
#define VU1_VERT_DATA_ADDR 2
@@ -12,9 +12,9 @@
#include <vector>
#include "debug/debug.hpp"
#include "./stdpip_qbuffer.hpp"
#include "./stapip_qbuffer.hpp"
#include "renderer/renderer_settings.hpp"
#include "renderer/core/paths/path1/clipper/path1_ee_clip_algorithm.hpp"
#include "renderer/core/3d/clipper/ee_clip_algorithm.hpp"
namespace Tyra {
@@ -25,23 +25,23 @@ namespace Tyra {
* To be honest clipping algorithm should be moved to VU1 and "AsIs" VU1 program
* should be renamed to "Clip" - I don't want to do it now, too much time.
*/
class StdpipClipper {
class StaPipClipper {
public:
StdpipClipper();
~StdpipClipper();
void clip(StdpipQBuffer* buffer);
StaPipClipper();
~StaPipClipper();
void clip(StaPipQBuffer* buffer);
void init(const RendererSettings& settings);
void setMaxVertCount(const u32& count);
void setMVP(M4x4* mvp);
private:
u32 maxVertCount;
Path1EEClipAlgorithm algorithm;
EEClipAlgorithm algorithm;
M4x4* mvp;
void perspectiveDivide(std::vector<Path1ClipVertex>* vertices);
void moveDataToBuffer(const std::vector<Path1ClipVertex>& vertices,
StdpipQBuffer* buffer);
void perspectiveDivide(std::vector<EEClipVertex>* vertices);
void moveDataToBuffer(const std::vector<EEClipVertex>& vertices,
StaPipQBuffer* buffer);
};
} // namespace Tyra
@@ -11,23 +11,25 @@
#pragma once
#include <tamtypes.h>
#include "./bag/stdpip_bag.hpp"
#include "./bag/packaging/stdpip_bag_packages_bbox.hpp"
#include "./bag/packaging/stdpip_bag_package.hpp"
#include "./bag/packaging/stdpip_bag_packager.hpp"
#include "./path1/stdpip_qbuffer_renderer.hpp"
#include "./bag/stapip_bag.hpp"
#include "./bag/packaging/stapip_bag_packages_bbox.hpp"
#include "./bag/packaging/stapip_bag_package.hpp"
#include "./bag/packaging/stapip_bag_packager.hpp"
#include "./stapip_qbuffer_renderer.hpp"
#include "renderer/3d/pipeline/shared/pipeline_frustum_culling.hpp"
namespace Tyra {
class StdPipelineCore {
class StaPipCore {
public:
StdPipelineCore();
~StdPipelineCore();
StaPipCore();
~StaPipCore();
void init(RendererCore* t_core);
/** Render 3D data via "bags" */
void render(StdpipBag* data, StdpipBagPackagesBBox* bbox = nullptr);
/** Render 3D via "bags" */
void render(StaPipBag* bag, const bool& frustumCull,
StaPipBagPackagesBBox* bbox = nullptr);
/** Get max vert count of VU1 qbuffer (for optimizations) */
u32 getMaxVertCountByParams(const bool& isSingleColor,
@@ -35,7 +37,7 @@ class StdPipelineCore {
const bool& isTextureEnabled);
/** Get max vert count of VU1 qbuffer (for optimizations) */
u32 getMaxVertCountByBag(const StdpipBag* bag);
u32 getMaxVertCountByBag(const StaPipBag* bag);
/**
* - Uploads standard VU1 programs.
@@ -43,17 +45,20 @@ class StdPipelineCore {
* - Sets double buffers exactly for "Tyra Renderer3D"
* Should be called if VU1 was used by your non standard programs.
*/
void reinitStandardVU1Programs();
void reinitVU1Programs();
void allocateOnUse() { qbufferRenderer.allocateOnUse(); }
void deallocateOnUse() { qbufferRenderer.deallocateOnUse(); }
private:
u32 maxVertCount;
RendererCore* rendererCore;
void setMaxVertCount(const u32& count);
StdpipBagPackager packager;
StdpipQBufferRenderer qbufferRenderer;
void renderPkgs(StdpipBagPackage* packages, u16 count);
void renderSubpkgs(StdpipBagPackage* packages, u16 count);
StaPipBagPackager packager;
StaPipQBufferRenderer qbufferRenderer;
void renderPkgs(StaPipBagPackage* packages, const bool& doClip, u16 count);
void renderSubpkgs(StaPipBagPackage* packages, u16 count);
};
} // namespace Tyra
@@ -12,20 +12,20 @@
namespace Tyra {
enum StdpipProgramName {
StdipUndefinedProgram,
enum StaPipProgramName {
StaPipUndefinedProgram,
StdpipCullColor,
StdpipAsIsColor,
StaPipCullColor,
StaPipAsIsColor,
StdpipCullDirLights,
StdpipAsIsDirLights,
StaPipCullDirLights,
StaPipAsIsDirLights,
StdpipCullTextureDirLights,
StdpipAsIsTextureDirLights,
StaPipCullTextureDirLights,
StaPipAsIsTextureDirLights,
StdpipCullTextureColor,
StdpipAsIsTextureColor,
StaPipCullTextureColor,
StaPipAsIsTextureColor,
};
} // namespace Tyra
@@ -12,11 +12,11 @@
namespace Tyra {
enum StdpipProgramType {
StdpipVU1Color,
StdpipVU1DirLights,
StdpipVU1TextureDirLights,
StdpipVU1TextureColor,
enum StaPipProgramType {
StaPipVU1Color,
StaPipVU1DirLights,
StaPipVU1TextureDirLights,
StaPipVU1TextureColor,
};
} // namespace Tyra
@@ -0,0 +1,46 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#pragma once
#include "debug/debug.hpp"
#include "renderer/core/paths/path1/vu1_program.hpp"
#include "./programs/as_is/stapip_as_is_c_vu1_program.hpp"
#include "./programs/as_is/stapip_as_is_d_vu1_program.hpp"
#include "./programs/as_is/stapip_as_is_td_vu1_program.hpp"
#include "./programs/as_is/stapip_as_is_tc_vu1_program.hpp"
#include "./programs/cull/stapip_cull_c_vu1_program.hpp"
#include "./programs/cull/stapip_cull_d_vu1_program.hpp"
#include "./programs/cull/stapip_cull_td_vu1_program.hpp"
#include "./programs/cull/stapip_cull_tc_vu1_program.hpp"
namespace Tyra {
class StaPipProgramsRepository {
public:
StaPipProgramsRepository();
~StaPipProgramsRepository();
StaPipVU1Program* getProgram(const StaPipProgramName& name);
private:
StaPipAsIsCVU1Program asIsColor;
StaPipCullCVU1Program cullColor;
StaPipAsIsDVU1Program asIsDirLights;
StaPipCullDVU1Program cullDirLights;
StaPipAsIsTDVU1Program asIsTextureDirLights;
StaPipCullTDVU1Program cullTextureDirLights;
StaPipAsIsTCVU1Program asIsTextureColor;
StaPipCullTCVU1Program cullTextureColor;
};
} // namespace Tyra
@@ -12,17 +12,16 @@
#include <math3d.h>
#include <string>
#include <sstream>
#include "debug/debug.hpp"
#include "../bag/packaging/stdpip_bag_package.hpp"
#include "../bag/stdpip_bag.hpp"
#include "./bag/packaging/stapip_bag_package.hpp"
#include "./bag/stapip_bag.hpp"
namespace Tyra {
class StdpipQBuffer {
class StaPipQBuffer {
public:
StdpipQBuffer();
~StdpipQBuffer();
StaPipQBuffer();
~StaPipQBuffer();
void setMaxVertCount(const u32& count);
@@ -30,27 +29,27 @@ class StdpipQBuffer {
* @brief Dont allocate any dynamic data in buffer.
* Just copy pointers to input data.
*/
void fillByPointer(const StdpipBagPackage& pkg);
void fillByPointer(const StaPipBagPackage& pkg);
/**
* @brief Allocate dynamic data in buffer
* And copy input data to it.
*/
void fillByCopyMax(const StdpipBagPackage& pkg1, const StdpipBagPackage& pkg2,
const StdpipBagPackage& pkg3);
void fillByCopyMax(const StaPipBagPackage& pkg1, const StaPipBagPackage& pkg2,
const StaPipBagPackage& pkg3);
/**
* @brief Allocate dynamic data in buffer
* And copy input data to it.
*/
void fillByCopy1By2(const StdpipBagPackage& pkg1,
const StdpipBagPackage& pkg2);
void fillByCopy1By2(const StaPipBagPackage& pkg1,
const StaPipBagPackage& pkg2);
/**
* @brief Allocate dynamic data in buffer
* And copy input data to it.
*/
void fillByCopy1By3(const StdpipBagPackage& pkg);
void fillByCopy1By3(const StaPipBagPackage& pkg);
/**
* @brief Deallocate dynamic data if it was allocated and allocate new data
@@ -61,7 +60,7 @@ class StdpipQBuffer {
bool any() const;
StdpipBag* bag;
StaPipBag* bag;
Vec4* vertices;
Vec4* sts;
@@ -77,7 +76,7 @@ class StdpipQBuffer {
private:
u32 maxVertCount;
void deallocateDynamicData();
void allocateDynamicData(u16 size, StdpipBag* bag);
void allocateDynamicData(u16 size, StaPipBag* bag);
u8 _isDynamicallyAllocated, _stAllocated, _colorAllocated, _normalAllocated;
};
@@ -17,21 +17,21 @@
#include "math/m4x4.hpp"
#include "renderer/renderer_settings.hpp"
#include "renderer/models/color.hpp"
#include "./stdpip_qbuffer.hpp"
#include "./stdpip_program_type.hpp"
#include "./stdpip_program_name.hpp"
#include "./stdpip_programs_repository.hpp"
#include "./stdpip_clipper.hpp"
#include "./stapip_qbuffer.hpp"
#include "./stapip_program_type.hpp"
#include "./stapip_program_name.hpp"
#include "./stapip_programs_repository.hpp"
#include "./stapip_clipper.hpp"
#include "renderer/core/paths/path1/path1.hpp"
#include "renderer/core/renderer_core.hpp"
#include "renderer/core/texture/renderer_core_texture_buffers.hpp"
namespace Tyra {
class StdpipQBufferRenderer {
class StaPipQBufferRenderer {
public:
StdpipQBufferRenderer();
~StdpipQBufferRenderer();
StaPipQBufferRenderer();
~StaPipQBufferRenderer();
void init(RendererCore* t_core);
@@ -39,59 +39,73 @@ class StdpipQBufferRenderer {
void setClipperMVP(M4x4* mvp) { clipper.setMVP(mvp); }
StdpipQBuffer* getBuffer();
StaPipQBuffer* getBuffer();
void sendObjectData(StdpipBag* bag, M4x4* mvp,
void sendObjectData(StaPipBag* bag, M4x4* mvp,
RendererCoreTextureBuffers* texBuffers) const;
void setMaxVertCount(const u32& count);
void setInfo(StdpipInfoBag* bag);
void setInfo(PipelineInfoBag* bag);
/** Fast render with culling */
void cull(StdpipQBuffer* buffer);
void cull(StaPipQBuffer* buffer);
/** Slower render with clipping */
void clip(StdpipQBuffer* buffer);
void clip(StaPipQBuffer* buffer);
void flushBuffers();
void clearLastProgramName();
StdpipVU1Program* getCullProgramByBag(const StdpipBag* bag);
StaPipVU1Program* getCullProgramByBag(const StaPipBag* bag);
StdpipVU1Program* getCullProgramByParams(const bool& isLightingEnabled,
StaPipVU1Program* getCullProgramByParams(const bool& isLightingEnabled,
const bool& isTextureEnabled);
const u16& getBufferSize() { return bufferSize; }
void allocateOnUse();
void deallocateOnUse();
private:
bool is1stDBufferFlushTime();
bool is2ndDBufferFlushTime();
void sendStaticData() const;
void setProgramsCache();
void uploadPrograms();
void setDoubleBuffer();
u16 getQBufferIndex(StaPipQBuffer* buffer);
u16 qbuffersPacketSize;
StdpipVU1Program* getProgramByName(const StdpipProgramName& name);
void addBufferDataToPacket(StdpipVU1Program* program, StdpipQBuffer* buffer);
static const u16 buffersCount;
StaPipVU1Program* getProgramByName(const StaPipProgramName& name);
void addBufferDataToPacket(StaPipQBuffer** buffers, const u32& count);
void sendPacket();
StdpipVU1Program* getAsIsProgramByBag(const StdpipBag* bag);
StdpipVU1Program* getCullProgramByType(const StdpipProgramType& programType);
StdpipProgramType getDrawProgramTypeByBag(const StdpipBag* bag) const;
StdpipProgramType getDrawProgramTypeByParams(
StaPipVU1Program* getAsIsProgramByBag(const StaPipBag* bag);
StaPipVU1Program* getCullProgramByType(const StaPipProgramType& programType);
StaPipProgramType getDrawProgramTypeByBag(const StaPipBag* bag) const;
StaPipProgramType getDrawProgramTypeByParams(
const bool& isLightingEnabled, const bool& isTextureEnabled) const;
packet2_t* packets[2];
packet2_t* programsPacket;
StdpipQBuffer buffers[2];
packet2_t** packets;
StaPipVU1Program** dBufferPrograms;
StaPipQBuffer** buffers;
packet2_t* currentPacket;
packet2_t* staticDataPacket;
packet2_t* objectDataPacket;
RendererCore* rendererCore;
StdpipProgramName lastProgramName;
StaPipProgramName lastProgramName;
Path1* path1;
StdpipClipper clipper;
StdpipProgramsRepository repository;
StaPipClipper clipper;
StaPipProgramsRepository repository;
u16 bufferSize;
u16 bufferSize, nextBufferIndex, currentBufferIndex;
u8 context;
};
@@ -10,40 +10,40 @@
#pragma once
#include "./stdpip_program_name.hpp"
#include "./stapip_program_name.hpp"
#include "renderer/core/paths/path1/vu1_program.hpp"
#include "./stdpip_qbuffer.hpp"
#include "./programs/stdpip_vu1_shared_defines.h"
#include "./stapip_qbuffer.hpp"
#include "./programs/stapip_vu1_shared_defines.h"
namespace Tyra {
class StdpipVU1Program : public VU1Program {
class StaPipVU1Program : public VU1Program {
public:
StdpipVU1Program(const StdpipProgramName& name, u32* start, u32* end,
StaPipVU1Program(const StaPipProgramName& name, u32* start, u32* end,
const u32& t_reglist, const u8& t_reglistCount,
const u8& t_elementsPerVertex);
~StdpipVU1Program();
~StaPipVU1Program();
u32& getReglist();
const StdpipProgramName& getName() const;
const StaPipProgramName& getName() const;
u16 getMaxVertCount(const bool& singleColorEnabled,
const u16& vu1DBufferSize) const;
void addBufferDataToPacket(packet2_t* packet, StdpipQBuffer* buffer,
void addBufferDataToPacket(packet2_t* packet, StaPipQBuffer* buffer,
prim_t* prim);
protected:
StdpipProgramName name;
StaPipProgramName name;
u8 reglistCount, elementsPerVertex;
u32 destinationAddress, reglist;
virtual void addProgramQBufferDataToPacket(packet2_t* packet,
StdpipQBuffer* qbuffer) const = 0;
StaPipQBuffer* qbuffer) const = 0;
private:
void addStandardBufferDataToPacket(packet2_t* packet, StdpipQBuffer* buffer,
void addStandardBufferDataToPacket(packet2_t* packet, StaPipQBuffer* buffer,
prim_t* prim);
};
@@ -0,0 +1,33 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#pragma once
#include "renderer/3d/pipeline/shared/pipeline_options.hpp"
namespace Tyra {
class StaPipOptions : public PipelineOptions {
public:
StaPipOptions() { fullClipChecks = false; }
~StaPipOptions() {}
/**
* @brief False -> disables "clip against each plane" algorithm.
* Mandatory, default: True.
*
* Full clip checks are slow, but they are
* preventing visual artifacts, which can happen
* for big 3D objects (or objects near camera eyes)
*/
bool fullClipChecks;
};
} // namespace Tyra
@@ -0,0 +1,74 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#pragma once
#include <tamtypes.h>
#include "../renderer_3d_pipeline.hpp"
#include "../shared/pipeline_lighting_options.hpp"
#include "renderer/core/renderer_core.hpp"
#include "renderer/3d/mesh/static/static_mesh.hpp"
#include "./core/stapip_core.hpp"
#include "./stapip_options.hpp"
namespace Tyra {
/**
* Pipeline for static models (StaticMesh).
* Supports:
* - Full "against each plane" clipping and simple PS2 clipping
* (fullClipChecks),
* - Force enabled precise frustum culling (checks parts of given mesh)
* - Modes: color(s), texture+color(s), dir lights, texture + dir lights
*/
class StaticPipeline : public Renderer3DPipeline {
public:
StaticPipeline();
~StaticPipeline();
StaPipCore core;
void setRenderer(RendererCore* core);
void onUse();
void onUseEnd();
/**
* Render static model
* This render() method is a bridge to core.render() method.
*/
void render(StaticMesh* mesh, const StaPipOptions* options = nullptr);
private:
RendererCore* rendererCore;
Vec4* colorsCache;
void addVertices(MeshMaterialFrame* materialFrame, StaPipBag* bag) const;
PipelineInfoBag* getInfoBag(StaticMesh* mesh, const StaPipOptions* options,
M4x4* model) const;
StaPipColorBag* getColorBag(MeshMaterial* material,
MeshMaterialFrame* materialFrame) const;
StaPipTextureBag* getTextureBag(MeshMaterial* material,
MeshMaterialFrame* materialFrame);
StaPipLightingBag* getLightingBag(MeshMaterialFrame* materialFrame,
M4x4* model,
const StaPipOptions* options) const;
void deallocDrawBags(StaPipBag* bag, MeshMaterial* material) const;
void setLightingColorsCache(PipelineLightingOptions* lightingOptions);
};
} // namespace Tyra
@@ -1,29 +0,0 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#pragma once
#include <packet2_utils.h>
#include <string>
#include "../../stdpip_vu1_program.hpp"
namespace Tyra {
class StdpipCullTCVU1Program : public StdpipVU1Program {
public:
StdpipCullTCVU1Program();
~StdpipCullTCVU1Program();
std::string getStringName() const;
void addProgramQBufferDataToPacket(packet2_t* packet,
StdpipQBuffer* qbuffer) const;
};
} // namespace Tyra
@@ -1,29 +0,0 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#pragma once
#include <packet2_utils.h>
#include <string>
#include "../../stdpip_vu1_program.hpp"
namespace Tyra {
class StdpipCullTDVU1Program : public StdpipVU1Program {
public:
StdpipCullTDVU1Program();
~StdpipCullTDVU1Program();
std::string getStringName() const;
void addProgramQBufferDataToPacket(packet2_t* packet,
StdpipQBuffer* qbuffer) const;
};
} // namespace Tyra
@@ -1,49 +0,0 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#pragma once
#include "debug/debug.hpp"
#include "renderer/core/paths/path1/vu1_program.hpp"
#include "./programs/as_is/stdpip_as_is_c_vu1_program.hpp"
#include "./programs/as_is/stdpip_as_is_d_vu1_program.hpp"
#include "./programs/as_is/stdpip_as_is_td_vu1_program.hpp"
#include "./programs/as_is/stdpip_as_is_tc_vu1_program.hpp"
#include "./programs/cull/stdpip_cull_c_vu1_program.hpp"
#include "./programs/cull/stdpip_cull_d_vu1_program.hpp"
#include "./programs/cull/stdpip_cull_td_vu1_program.hpp"
#include "./programs/cull/stdpip_cull_tc_vu1_program.hpp"
#include "renderer/core/paths/path1/programs/draw_finish/vu1_draw_finish.hpp"
namespace Tyra {
class StdpipProgramsRepository {
public:
StdpipProgramsRepository();
~StdpipProgramsRepository();
StdpipVU1Program* getProgram(const StdpipProgramName& name);
private:
StdpipAsIsCVU1Program asIsColor;
StdpipCullCVU1Program cullColor;
StdpipAsIsDVU1Program asIsLightingColor;
StdpipCullDVU1Program cullLightingColor;
StdpipAsIsTDVU1Program asIsLightingTextureColor;
StdpipCullTDVU1Program cullLightingTextureColor;
StdpipAsIsTCVU1Program asIsTextureColor;
StdpipCullTCVU1Program cullTextureColor;
VU1DrawFinish drawFinish;
};
} // namespace Tyra
@@ -1,59 +0,0 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#pragma once
#include <tamtypes.h>
#include "../renderer_3d_pipeline.hpp"
#include "./stdpip_options.hpp"
#include "renderer/core/renderer_core.hpp"
#include "renderer/3d/mesh/mesh.hpp"
#include "./core/std_pipeline_core.hpp"
namespace Tyra {
class StdPipeline : public Renderer3DPipeline {
public:
StdPipeline();
~StdPipeline();
void init(RendererCore* core);
void onUse();
/**
* Render 3D data via "meshes".
* This render() method is a bridge to core.renderer3D.render() method.
*/
void render(Mesh* mesh, const StdpipOptions* options = nullptr);
private:
StdPipelineCore core;
RendererCore* rendererCore;
Vec4* colorsCache;
void addVertices(Mesh* mesh, MeshMaterial* material, StdpipBag* bag,
MeshFrame* frameFrom, MeshFrame* frameTo) const;
StdpipInfoBag* getInfoBag(Mesh* mesh, const StdpipOptions* options,
M4x4* model) const;
StdpipColorBag* getColorBag(Mesh* mesh, MeshMaterial* material,
MeshFrame* frameFrom, MeshFrame* frameTo) const;
StdpipTextureBag* getTextureBag(Mesh* mesh, MeshMaterial* material,
MeshFrame* frameFrom, MeshFrame* frameTo);
StdpipLightingBag* getLightingBag(Mesh* mesh, MeshMaterial* material,
M4x4* model, MeshFrame* frameFrom,
MeshFrame* frameTo,
const StdpipOptions* options) const;
void deallocDrawBags(StdpipBag* bag, MeshMaterial* material) const;
void setLightingColorsCache(StdpipLightingOptions* lightingOptions);
};
} // namespace Tyra
@@ -11,6 +11,7 @@
#pragma once
#include <vector>
#include <string>
#include "./core_bbox_frustum.hpp"
#include "math/m4x4.hpp"
#include "math/plane.hpp"
@@ -11,42 +11,42 @@
#pragma once
#include <vector>
#include "./path1_clip_vertex.hpp"
#include "./ee_clip_vertex.hpp"
#include "debug/debug.hpp"
#include "renderer/renderer_settings.hpp"
namespace Tyra {
struct Path1EEClipAlgorithmSettings {
struct EEClipAlgorithmSettings {
bool lerpNormals, lerpTexCoords, lerpColors;
};
class Path1EEClipAlgorithm {
class EEClipAlgorithm {
public:
Path1EEClipAlgorithm();
~Path1EEClipAlgorithm();
EEClipAlgorithm();
~EEClipAlgorithm();
void init(const RendererSettings& settings);
void clip(std::vector<Path1ClipVertex>* o_vertices,
const std::vector<Path1ClipVertex>& vertices,
const Path1EEClipAlgorithmSettings& settings);
void clip(std::vector<EEClipVertex>* o_vertices,
const std::vector<EEClipVertex>& vertices,
const EEClipAlgorithmSettings& settings);
static float clipMargin;
private:
float halfWidth, halfHeight, near, far;
std::vector<Path1ClipVertex> tempVertices;
std::vector<EEClipVertex> tempVertices;
float getValueByPlane(const Path1ClipVertex& v, const int& plane);
float getValueByPlane(const EEClipVertex& v, const int& plane);
bool isInside(const int& plane, const float& v, const float& w,
const float& planeLimitValue);
void clipAgainstPlane(const std::vector<Path1ClipVertex>& original,
std::vector<Path1ClipVertex>* clipped, const int& plane,
void clipAgainstPlane(const std::vector<EEClipVertex>& original,
std::vector<EEClipVertex>* clipped, const int& plane,
const float& planeLimitValue,
const Path1EEClipAlgorithmSettings& settings);
const EEClipAlgorithmSettings& settings);
};
} // namespace Tyra
@@ -14,7 +14,7 @@
namespace Tyra {
struct Path1ClipVertex {
struct EEClipVertex {
Vec4 position, normal, st, color;
};
@@ -10,7 +10,7 @@
#pragma once
#include <sstream>
#include <string>
#include "renderer/renderer_settings.hpp"
#include "./camera_info_3d.hpp"
#include "math/plane.hpp"
@@ -14,29 +14,29 @@ namespace Tyra {
enum TextureBpp {
// Tyra has 1.3MB~ free VRAM for textures.
// Tyra has 2.27MB~ free VRAM for textures.
/**
* @brief 32-bit RGBA - Slowest
* Tyra can cache about 4~ of these textures (256x256)
* Tyra can cache about 8~ of these textures (256x256)
*/
bpp32 = 32,
/**
* @brief 24-bit RGB - Slow
* Tyra can cache about 6~ of these textures (256x256)
* Tyra can cache about 11~ of these textures (256x256)
*/
bpp24 = 24,
/**
* @brief 8-bit palletized (indexed) - Super fast
* Tyra can cache about 19~ of these textures (256x256)
* Tyra can cache about 34~ of these textures (256x256)
*/
bpp8 = 8,
/**
* @brief 4-bit palletized (indexed) - Super, super fast
* Tyra can cache about 39~ of these textures (256x256)
* Tyra can cache about 69~ of these textures (256x256)
*/
bpp4 = 4,
};
@@ -36,31 +36,19 @@ class TextureRepository {
* For 3D: MeshMaterial id.
* For 2D: Sprite id.
*/
Texture* getBySpriteOrMesh(const u32& t_id) {
for (u32 i = 0; i < textures.size(); i++)
if (textures[i]->isLinkedWith(t_id)) return textures[i];
return nullptr;
}
Texture* getBySpriteOrMesh(const u32& t_id) const;
/**
* Returns single texture.
* nullptr if not found.
*/
Texture* getByTextureId(const u32& t_id) const {
for (u32 i = 0; i < textures.size(); i++)
if (t_id == textures[i]->getId()) return textures[i];
return nullptr;
}
Texture* getByTextureId(const u32& t_id) const;
/**
* Returns index of link.
* -1 if not found.
*/
const s32 getIndexOf(const u32& t_texId) const {
for (u32 i = 0; i < textures.size(); i++)
if (textures[i]->getId() == t_texId) return i;
return -1;
}
const s32 getIndexOf(const u32& t_texId) const;
// ----
// Setters
@@ -107,19 +95,19 @@ class TextureRepository {
* Remove texture from repository.
* Texture is NOT destructed.
*/
void removeByIndex(const u32& t_index) {
textures.erase(textures.begin() + t_index);
}
void removeByIndex(const u32& t_index);
/**
* Remove texture from repository.
* Texture is NOT destructed.
*/
const void removeById(const u32& t_texId) {
s32 index = getIndexOf(t_texId);
TYRA_ASSERT(index != -1, "Cant remove texture, because it was not found!");
removeByIndex(index);
}
void removeById(const u32& t_texId);
/**
* Remove texture from repository.
* Texture IS destructed.
*/
void free(const u32& t_texId);
private:
std::vector<Texture*> textures;
@@ -33,6 +33,11 @@ class RendererSettings {
const float& getProjectionScale() const { return projectionScale; }
const float& getAspectRatio() const { return aspectRatio; }
float getInterlacedHeightF() const { return getHeight() / 2; }
unsigned int getInterlacedHeightUI() const {
return static_cast<unsigned int>(getInterlacedHeightF());
}
static void copy(RendererSettings* out, const RendererSettings* in);
void set(const RendererSettings& v);
@@ -24,7 +24,20 @@ MeshBuilderFrameData::MeshBuilderFrameData() {
colorsCount = 0;
}
MeshBuilderFrameData::~MeshBuilderFrameData() {}
MeshBuilderFrameData::~MeshBuilderFrameData() {
if (vertices) {
delete[] vertices;
}
if (normals) {
delete[] normals;
}
if (textureCoords) {
delete[] textureCoords;
}
if (colors) {
delete[] colors;
}
}
void MeshBuilderFrameData::allocateTextureCoords(const u32& count) {
textureCoordsCount = count;
@@ -22,7 +22,20 @@ MeshBuilderMaterialData::MeshBuilderMaterialData() {
count = 0;
}
MeshBuilderMaterialData::~MeshBuilderMaterialData() {}
MeshBuilderMaterialData::~MeshBuilderMaterialData() {
if (vertexFaces) {
delete[] vertexFaces;
}
if (textureCoordFaces) {
delete[] textureCoordFaces;
}
if (normalFaces) {
delete[] normalFaces;
}
if (colorFaces) {
delete[] colorFaces;
}
}
void MeshBuilderMaterialData::allocateFaces(const u32& t_count) {
vertexFaces = new u32[t_count];
+1 -1
View File
@@ -9,7 +9,7 @@
*/
#include <stdio.h>
#include <string>
#include <iomanip>
#include <sstream>
#include "math/m4x4.hpp"
+2 -1
View File
@@ -8,8 +8,9 @@
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#include <string>
#include "math/vec4.hpp"
#include <iomanip>
#include <sstream>
#include "math/plane.hpp"
namespace Tyra {
+1
View File
@@ -9,6 +9,7 @@
*/
#include "math/vec2.hpp"
#include <iomanip>
namespace Tyra {
+3
View File
@@ -9,6 +9,9 @@
*/
#include "math/vec4.hpp"
#include <iomanip>
#include <cmath>
#include <sstream>
namespace Tyra {
@@ -0,0 +1,112 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#include <tamtypes.h>
#include "math/m4x4.hpp"
#include "renderer/3d/mesh/dynamic/dynamic_mesh.hpp"
namespace Tyra {
DynamicMesh::DynamicMesh(const MeshBuilderData& data) : Mesh(data) {
TYRA_ASSERT(framesCount > 1, "Frames count must be greater than 1");
framesCount = data.framesCount;
frames = new MeshFrame*[framesCount];
for (u32 i = 0; i < framesCount; i++) {
frames[i] = new MeshFrame(data, i);
}
initAnimation();
}
DynamicMesh::DynamicMesh(const DynamicMesh& mesh) : Mesh(mesh) {
framesCount = mesh.framesCount;
frames = new MeshFrame*[framesCount];
for (u32 i = 0; i < framesCount; i++) {
frames[i] = new MeshFrame(*mesh.frames[i]);
}
initAnimation();
}
DynamicMesh::~DynamicMesh() {
for (u32 i = 0; i < framesCount; i++) {
delete frames[i];
}
delete[] frames;
}
void DynamicMesh::initAnimation() {
animState.startFrame = 0;
animState.endFrame = 0;
animState.interpolation = 0.0F;
animState.animType = 0;
animState.currentFrame = 0;
animState.stayFrame = 0;
animState.isStayFrameSet = false;
animState.nextFrame = 0;
animState.speed = 0.1F;
}
void DynamicMesh::playAnimation(const u32& t_startFrame,
const u32& t_endFrame) {
TYRA_ASSERT(framesCount > 0,
"Cant play animation, because no mesh data was loaded!");
TYRA_ASSERT(framesCount != 1,
"Cant play animation, because this mesh have only one frame.");
TYRA_ASSERT(
t_endFrame < framesCount,
"End frame value is too high. Valid range: (0, getFramesCount()-1)");
animState.startFrame = t_startFrame;
animState.endFrame = t_endFrame;
if (animState.currentFrame == t_startFrame)
animState.nextFrame = t_endFrame;
else
animState.nextFrame = t_startFrame;
}
void DynamicMesh::playAnimation(const u32& t_startFrame, const u32& t_endFrame,
const u32& t_stayFrame) {
TYRA_ASSERT(framesCount > 0,
"Cant play animation, because no mesh data was loaded!");
TYRA_ASSERT(framesCount != 1,
"Cant play animation, because this mesh have only one frame.");
TYRA_ASSERT(
t_endFrame < framesCount,
"End frame value is too high. Valid range: (0, getFramesCount()-1)");
animState.startFrame = t_startFrame;
animState.endFrame = t_endFrame;
animState.isStayFrameSet = true;
animState.stayFrame = t_stayFrame;
animState.nextFrame = t_startFrame;
}
void DynamicMesh::animate() {
animState.interpolation += animState.speed;
if (animState.interpolation >= 1.0F) {
animState.interpolation = 0.0F;
animState.currentFrame = animState.nextFrame;
if (++animState.nextFrame > animState.endFrame) {
if (animState.isStayFrameSet) {
animState.isStayFrameSet = false;
animState.nextFrame = animState.stayFrame;
animState.startFrame = animState.stayFrame;
animState.endFrame = animState.stayFrame;
} else {
animState.nextFrame = animState.startFrame;
}
}
}
}
} // namespace Tyra
+21 -100
View File
@@ -9,136 +9,57 @@
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#include <tamtypes.h>
#include "math/m4x4.hpp"
#include "renderer/3d/mesh/mesh.hpp"
namespace Tyra {
Mesh::Mesh(const MeshBuilderData& data) {
id = rand() % 1000000;
init();
framesCount = data.framesCount;
TYRA_ASSERT(framesCount > 0, "Frames count must be greater than 0");
TYRA_ASSERT(data.materialsCount > 0,
"Materials count must be greater than 0");
materialsCount = data.materialsCount;
TYRA_ASSERT(materialsCount > 0, "Materials count must be greater than 0");
frames = new MeshFrame*[framesCount];
for (u32 i = 0; i < framesCount; i++) {
frames[i] = new MeshFrame(data, i);
}
materials = new MeshMaterial*[materialsCount];
for (u32 i = 0; i < materialsCount; i++) {
materials[i] = new MeshMaterial(data, i);
}
translation.translate(Vec4(0.0F, 0.0F, 0.0F, 1.0F));
initMesh();
_isMother = true;
}
Mesh::Mesh(const Mesh& mesh) {
id = rand() % 1000000;
init();
framesCount = mesh.framesCount;
materialsCount = mesh.materialsCount;
frames = new MeshFrame*[framesCount];
for (u32 i = 0; i < framesCount; i++) {
frames[i] = new MeshFrame(*mesh.frames[i]);
}
materials = new MeshMaterial*[materialsCount];
for (u32 i = 0; i < materialsCount; i++) {
materials[i] = new MeshMaterial(*mesh.materials[i]);
}
translation.translate(Vec4(0.0F, 0.0F, 0.0F, 1.0F));
initMesh();
_isMother = false;
}
Mesh::~Mesh() {
for (u32 i = 0; i < framesCount; i++) {
delete frames[i];
}
delete[] frames;
for (u32 i = 0; i < materialsCount; i++) {
delete materials[i];
delete[] materials;
}
}
M4x4 Mesh::getModelMatrix() const { return translation * rotation * scale; }
void Mesh::initMesh() {
animState.startFrame = 0;
animState.endFrame = 0;
animState.interpolation = 0.0F;
animState.animType = 0;
animState.currentFrame = 0;
animState.stayFrame = 0;
animState.isStayFrameSet = false;
animState.nextFrame = 0;
animState.speed = 0.1F;
}
void Mesh::playAnimation(const u32& t_startFrame, const u32& t_endFrame) {
TYRA_ASSERT(framesCount > 0,
"Cant play animation, because no mesh data was loaded!");
TYRA_ASSERT(framesCount != 1,
"Cant play animation, because this mesh have only one frame.");
TYRA_ASSERT(
t_endFrame < framesCount,
"End frame value is too high. Valid range: (0, getFramesCount()-1)");
animState.startFrame = t_startFrame;
animState.endFrame = t_endFrame;
if (animState.currentFrame == t_startFrame)
animState.nextFrame = t_endFrame;
else
animState.nextFrame = t_startFrame;
}
void Mesh::playAnimation(const u32& t_startFrame, const u32& t_endFrame,
const u32& t_stayFrame) {
TYRA_ASSERT(framesCount > 0,
"Cant play animation, because no mesh data was loaded!");
TYRA_ASSERT(framesCount != 1,
"Cant play animation, because this mesh have only one frame.");
TYRA_ASSERT(
t_endFrame < framesCount,
"End frame value is too high. Valid range: (0, getFramesCount()-1)");
animState.startFrame = t_startFrame;
animState.endFrame = t_endFrame;
animState.isStayFrameSet = true;
animState.stayFrame = t_stayFrame;
animState.nextFrame = t_startFrame;
}
void Mesh::animate() {
animState.interpolation += animState.speed;
if (animState.interpolation >= 1.0F) {
animState.interpolation = 0.0F;
animState.currentFrame = animState.nextFrame;
if (++animState.nextFrame > animState.endFrame) {
if (animState.isStayFrameSet) {
animState.isStayFrameSet = false;
animState.nextFrame = animState.stayFrame;
animState.startFrame = animState.stayFrame;
animState.endFrame = animState.stayFrame;
} else {
animState.nextFrame = animState.startFrame;
}
}
Mesh::~Mesh() {
for (u32 i = 0; i < materialsCount; i++) {
delete materials[i];
}
delete[] materials;
}
void Mesh::init() {
id = rand() % 1000000;
materialsCount = 0;
translation.translate(Vec4(0.0F, 0.0F, 0.0F, 1.0F));
}
void Mesh::setPosition(const Vec4& v) {
TYRA_ASSERT(v.w == 1.0F, "Vec4 must be homogeneous");
reinterpret_cast<Vec4*>(&translation.data[3 * 4])->set(v);
}
} // namespace Tyra
+1 -77
View File
@@ -11,6 +11,7 @@
#include "debug/debug.hpp"
#include <tamtypes.h>
#include <iomanip>
#include <string>
#include "math/vec4.hpp"
#include "renderer/models/color.hpp"
@@ -24,38 +25,6 @@ MeshFrame::MeshFrame(const MeshBuilderData& data, const u32& index) {
id = rand() % 1000000;
vertices = data.frames[index]->vertices;
TYRA_ASSERT(vertices != nullptr, "Vertices are required");
vertexCount = data.frames[index]->verticesCount;
TYRA_ASSERT(vertexCount > 0, "Vertices count must be greater than 0");
if (data.normalsEnabled) {
normals = data.frames[index]->normals;
normalsCount = data.frames[index]->normalsCount;
TYRA_ASSERT(normals != nullptr, "Normals are required");
} else {
normalsCount = 0;
normals = nullptr;
}
if (data.textureCoordsEnabled) {
textureCoords = data.frames[index]->textureCoords;
textureCoordsCount = data.frames[index]->textureCoordsCount;
TYRA_ASSERT(textureCoords != nullptr, "Texture coordinates are required");
} else {
textureCoordsCount = 0;
textureCoords = nullptr;
}
if (data.manyColorsEnabled) {
colors = data.frames[index]->colors;
colorsCount = data.frames[index]->colorsCount;
TYRA_ASSERT(colors != nullptr, "Colors are required");
} else {
colorsCount = 0;
colors = nullptr;
}
bbox =
new BBox(data.frames[index]->vertices, data.frames[index]->verticesCount);
@@ -65,16 +34,6 @@ MeshFrame::MeshFrame(const MeshBuilderData& data, const u32& index) {
MeshFrame::MeshFrame(const MeshFrame& frame) {
id = rand() % 1000000;
vertices = frame.vertices;
normals = frame.normals;
textureCoords = frame.textureCoords;
colors = frame.colors;
vertexCount = frame.vertexCount;
normalsCount = frame.normalsCount;
textureCoordsCount = frame.textureCoordsCount;
colorsCount = frame.colorsCount;
bbox = frame.bbox;
_isMother = false;
@@ -82,10 +41,6 @@ MeshFrame::MeshFrame(const MeshFrame& frame) {
MeshFrame::~MeshFrame() {
if (_isMother) {
delete[] vertices;
if (normals) delete[] normals;
if (textureCoords) delete[] textureCoords;
if (colors) delete[] colors;
delete bbox;
}
}
@@ -110,38 +65,7 @@ std::string MeshFrame::getPrint(const char* name) const {
res << std::fixed << std::setprecision(2);
res << "Id: " << id << ", " << std::endl;
res << "VertexCount: " << vertexCount << ", " << std::endl;
res << "NormalsCount: " << normalsCount << ", " << std::endl;
res << "TextureCoordsCount: " << textureCoordsCount << ", " << std::endl;
res << "ColorsCount: " << colorsCount << ", " << std::endl;
res << "BBox: " << bbox->getPrint() << ", " << std::endl;
res << "Vertices: ";
for (u32 i = 0; i < vertexCount; i++) {
res << vertices[i].getPrint() << ", " << std::endl;
}
if (normals) {
res << "Normals: ";
for (u32 i = 0; i < normalsCount; i++) {
res << normals[i].getPrint() << ", " << std::endl;
}
}
if (textureCoords) {
res << "TextureCoords: ";
for (u32 i = 0; i < textureCoordsCount; i++) {
res << textureCoords[i].getPrint() << ", " << std::endl;
}
}
if (colors) {
res << "Colors: ";
for (u32 i = 0; i < colorsCount; i++) {
res << colors[i].getPrint() << ", " << std::endl;
}
}
res << ")";
return res.str();
+9 -74
View File
@@ -12,49 +12,27 @@
#include <tamtypes.h>
#include <string>
#include <cstdlib>
#include <iomanip>
#include "renderer/3d/mesh/mesh_material.hpp"
namespace Tyra {
MeshMaterial::MeshMaterial(const MeshBuilderData& data,
const u32& materialIndex)
: singleColor(false) {
: color(false) {
TYRA_ASSERT(materialIndex < data.materialsCount && materialIndex >= 0,
"Provided index \"", materialIndex, "\" is out of range");
id = rand() % 1000000;
vertexFaces = data.materials[materialIndex]->vertexFaces;
TYRA_ASSERT(vertexFaces != nullptr, "Vertex faces are required");
if (data.textureCoordsEnabled) {
textureCoordFaces = data.materials[materialIndex]->textureCoordFaces;
TYRA_ASSERT(textureCoordFaces != nullptr,
"Texture coord faces are required");
} else {
textureCoordFaces = nullptr;
}
if (data.normalsEnabled) {
normalFaces = data.materials[materialIndex]->normalFaces;
TYRA_ASSERT(normalFaces != nullptr, "Normal faces are required");
} else {
normalFaces = nullptr;
}
if (data.manyColorsEnabled) {
colorFaces = data.materials[materialIndex]->colorFaces;
singleColorFlag = false;
TYRA_ASSERT(colorFaces != nullptr, "Colors faces are required");
TYRA_ASSERT(data.frames[0]->colors != nullptr, "Colors faces are required");
} else {
colorFaces = nullptr;
singleColorFlag = true;
}
singleColor.set(128.0F, 128.0F, 128.0F, 128.0F);
facesCount = data.materials[materialIndex]->count;
TYRA_ASSERT(facesCount > 0, "Faces count must be greater than 0");
color.set(128.0F, 128.0F, 128.0F, 128.0F);
_name = data.materials[materialIndex]->name;
TYRA_ASSERT(_name.length() > 0, "MeshMaterial name cannot be empty");
@@ -71,16 +49,11 @@ MeshMaterial::MeshMaterial(const MeshBuilderData& data,
MeshMaterial::MeshMaterial(const MeshMaterial& mesh) {
id = rand() % 1000000;
vertexFaces = mesh.vertexFaces;
textureCoordFaces = mesh.textureCoordFaces;
normalFaces = mesh.normalFaces;
colorFaces = mesh.colorFaces;
facesCount = mesh.facesCount;
singleColorFlag = mesh.singleColorFlag;
framesCount = mesh.framesCount;
_name = mesh._name;
singleColor.set(128.0F, 128.0F, 128.0F, 128.0F);
color.set(128.0F, 128.0F, 128.0F, 128.0F);
frames = new MeshMaterialFrame*[framesCount];
for (u32 i = 0; i < framesCount; i++) {
@@ -91,13 +64,6 @@ MeshMaterial::MeshMaterial(const MeshMaterial& mesh) {
}
MeshMaterial::~MeshMaterial() {
if (_isMother) {
delete[] vertexFaces;
if (textureCoordFaces) delete[] textureCoordFaces;
if (normalFaces) delete[] normalFaces;
if (colorFaces) delete[] colorFaces;
}
for (u32 i = 0; i < framesCount; i++) {
delete frames[i];
}
@@ -110,7 +76,7 @@ const BBox& MeshMaterial::getBBox(const u32& frame) const {
void MeshMaterial::setSingleColorFlag(const u8& flag) {
TYRA_ASSERT(
colorFaces != nullptr,
frames[0]->getColors() != nullptr,
"Colors and color faces are required to use color-per-vertex mode");
singleColorFlag = flag;
@@ -138,39 +104,8 @@ std::string MeshMaterial::getPrint(const char* name) const {
res << std::fixed << std::setprecision(2);
res << "Id: " << id << ", " << std::endl;
res << "Name: " << _name << ", " << std::endl;
res << "FacesCount: " << facesCount << ", " << std::endl;
res << "FramesCount: " << framesCount << ", " << std::endl;
res << "vertexFaces: " << std::endl;
for (u32 i = 0; i < facesCount; i++) {
res << vertexFaces[i] << ", ";
if (i % 3 == 2) res << std::endl;
}
if (textureCoordFaces) {
res << "TextureCoordFaces: " << std::endl;
for (u32 i = 0; i < facesCount; i++) {
res << textureCoordFaces[i] << ", ";
if (i % 3 == 2) res << std::endl;
}
}
if (normalFaces) {
res << "NormalFaces: " << std::endl;
for (u32 i = 0; i < facesCount; i++) {
res << normalFaces[i] << ", ";
if (i % 3 == 2) res << std::endl;
}
}
if (colorFaces) {
res << "ColorFaces: " << std::endl;
for (u32 i = 0; i < facesCount; i++) {
res << colorFaces[i] << ", ";
if (i % 3 == 2) res << std::endl;
}
}
res << "Frames count: " << framesCount << ", " << std::endl;
res << "Single color?: " << static_cast<u32>(singleColorFlag) << std::endl;
res << ")";
return res.str();
@@ -11,6 +11,8 @@
#include "debug/debug.hpp"
#include <tamtypes.h>
#include <iomanip>
#include <string>
#include "renderer/models/color.hpp"
#include "loaders/3d/builder/mesh_builder_data.hpp"
#include "renderer/3d/mesh/mesh_material_frame.hpp"
@@ -31,12 +33,24 @@ MeshMaterialFrame::MeshMaterialFrame(const MeshBuilderData& data,
data.materials[materialIndex]->vertexFaces,
data.materials[materialIndex]->count);
allocateVertices(data, frameIndex, materialIndex);
allocateNormals(data, frameIndex, materialIndex);
allocateTextureCoords(data, frameIndex, materialIndex);
allocateColors(data, frameIndex, materialIndex);
_isMother = true;
}
MeshMaterialFrame::MeshMaterialFrame(const MeshMaterialFrame& frame) {
id = rand() % 1000000;
vertexCount = frame.vertexCount;
vertices = frame.vertices;
normals = frame.normals;
textureCoords = frame.textureCoords;
colors = frame.colors;
bbox = frame.bbox;
_isMother = false;
@@ -44,8 +58,124 @@ MeshMaterialFrame::MeshMaterialFrame(const MeshMaterialFrame& frame) {
MeshMaterialFrame::~MeshMaterialFrame() {
if (_isMother) {
delete[] vertices;
if (normals) delete[] normals;
if (textureCoords) delete[] textureCoords;
if (colors) delete[] colors;
delete bbox;
}
}
std::string MeshMaterialFrame::getPrint(const char* name) const {
std::stringstream res;
if (name) {
res << name << "(";
} else {
res << "MeshMaterialFrame(";
}
res << std::fixed << std::setprecision(2);
res << "Id: " << id << ", " << std::endl;
res << "Vertex count: " << vertexCount << ", " << std::endl;
res << "BBox: " << bbox->getPrint() << ", " << std::endl;
res << "Vertices: ";
for (u32 i = 0; i < vertexCount; i++) {
res << vertices[i].getPrint() << ", " << std::endl;
}
if (normals) {
res << "Normals: ";
for (u32 i = 0; i < vertexCount; i++) {
res << normals[i].getPrint() << ", " << std::endl;
}
}
if (textureCoords) {
res << "TextureCoords: ";
for (u32 i = 0; i < vertexCount; i++) {
res << textureCoords[i].getPrint() << ", " << std::endl;
}
}
if (colors) {
res << "Colors: ";
for (u32 i = 0; i < vertexCount; i++) {
res << colors[i].getPrint() << ", " << std::endl;
}
}
res << ")";
return res.str();
}
void MeshMaterialFrame::allocateVertices(const MeshBuilderData& data,
const u32& frameIndex,
const u32& materialIndex) {
vertexCount = data.materials[materialIndex]->count; // faces count
vertices = new Vec4[vertexCount];
TYRA_ASSERT(vertexCount > 0, "Vertex count must be greater than 0");
auto* rolled = data.frames[frameIndex]->vertices;
auto* faces = data.materials[materialIndex]->vertexFaces;
TYRA_ASSERT(rolled != nullptr, "Vertices are required");
TYRA_ASSERT(faces != nullptr, "Vertex faces are required");
for (u32 i = 0; i < vertexCount; i++) vertices[i] = rolled[faces[i]];
}
void MeshMaterialFrame::allocateTextureCoords(const MeshBuilderData& data,
const u32& frameIndex,
const u32& materialIndex) {
textureCoords = nullptr;
if (!data.textureCoordsEnabled) return;
textureCoords = new Vec4[vertexCount];
auto* rolled = data.frames[frameIndex]->textureCoords;
auto* faces = data.materials[materialIndex]->textureCoordFaces;
TYRA_ASSERT(rolled != nullptr, "Texture coordinates are required");
TYRA_ASSERT(faces != nullptr, "Texture coordinate faces are required");
for (u32 i = 0; i < vertexCount; i++) textureCoords[i] = rolled[faces[i]];
}
void MeshMaterialFrame::allocateNormals(const MeshBuilderData& data,
const u32& frameIndex,
const u32& materialIndex) {
normals = nullptr;
if (!data.normalsEnabled) return;
normals = new Vec4[vertexCount];
auto* rolled = data.frames[frameIndex]->normals;
auto* faces = data.materials[materialIndex]->normalFaces;
TYRA_ASSERT(rolled != nullptr, "Normals are required");
TYRA_ASSERT(faces != nullptr, "Normal faces are required");
for (u32 i = 0; i < vertexCount; i++) normals[i] = rolled[faces[i]];
}
void MeshMaterialFrame::allocateColors(const MeshBuilderData& data,
const u32& frameIndex,
const u32& materialIndex) {
colors = nullptr;
if (!data.manyColorsEnabled) return;
colors = new Color[vertexCount];
auto* rolled = data.frames[frameIndex]->colors;
auto* faces = data.materials[materialIndex]->colorFaces;
TYRA_ASSERT(rolled != nullptr, "Colors are required");
TYRA_ASSERT(faces != nullptr, "Color faces are required");
for (u32 i = 0; i < vertexCount; i++) colors[i] = rolled[faces[i]];
}
} // namespace Tyra
@@ -0,0 +1,32 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#include "renderer/3d/mesh/static/static_mesh.hpp"
namespace Tyra {
StaticMesh::StaticMesh(const MeshBuilderData& data) : Mesh(data) {
TYRA_ASSERT(data.framesCount > 0, "Frames count must be greater than 0");
if (data.framesCount > 1)
TYRA_WARN("Static meshes should have only one frame, but ",
data.framesCount, " frames were found");
frame = new MeshFrame(data, 0);
}
StaticMesh::StaticMesh(const StaticMesh& mesh) : Mesh(mesh) {
frame = new MeshFrame(*mesh.frame);
}
StaticMesh::~StaticMesh() { delete frame; }
} // namespace Tyra
@@ -0,0 +1,87 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#include "renderer/3d/pipeline/dynamic/core/bag/dynpip_bag.hpp"
#include <sstream>
#include <iomanip>
namespace Tyra {
DynPipBag::DynPipBag() {
info = nullptr;
color = nullptr;
texture = nullptr;
lighting = nullptr;
verticesFrom = nullptr;
verticesTo = nullptr;
}
DynPipBag::~DynPipBag() {}
void DynPipBag::print() const {
auto text = getPrint(nullptr);
printf("%s\n", text.c_str());
}
void DynPipBag::print(const char* name) const {
auto text = getPrint(name);
printf("%s\n", text.c_str());
}
std::string DynPipBag::getPrint(const char* name) const {
std::stringstream res;
if (name) {
res << name << "(";
} else {
res << "DynPipBag(";
}
res << std::fixed << std::setprecision(4);
res << std::endl;
res << "Count: " << count << ", " << std::endl;
res << "Vertices from present: " << (verticesFrom != nullptr ? "Yes" : "No")
<< ", " << std::endl;
res << "Vertices to present: " << (verticesTo != nullptr ? "Yes" : "No")
<< ", " << std::endl;
res << "Info present: " << (info != nullptr ? "Yes" : "No") << ", "
<< std::endl;
res << "Color present: " << (color != nullptr ? "Yes" : "No") << ", "
<< std::endl;
res << "Texture present: " << (texture != nullptr ? "Yes" : "No") << ", "
<< std::endl;
res << "Lighting present: " << (lighting != nullptr ? "Yes" : "No") << ", "
<< std::endl;
res << "Model matrix: " << info->model->getPrint() << ", " << std::endl;
if (color->single) {
res << "Color single: " << color->single->getPrint() << ", " << std::endl;
}
if (texture) {
res << "Texture coords from present: "
<< (texture->coordinatesFrom != nullptr ? "Yes" : "No") << ", "
<< std::endl;
res << "Texture coords to present: "
<< (texture->coordinatesTo != nullptr ? "Yes" : "No") << ", "
<< std::endl;
res << "Texture: " << texture->texture->getPrint() << ", " << std::endl;
}
if (lighting) {
res << "Lighting normals from present: "
<< (lighting->normalsFrom ? "Yes" : "No") << ", " << std::endl;
res << "Lighting normals to present: "
<< (lighting->normalsTo ? "Yes" : "No") << ", " << std::endl;
res << "Lighting matrix: " << lighting->lightMatrix->getPrint() << ", "
<< std::endl;
}
res << ")";
return res.str();
}
} // namespace Tyra
@@ -0,0 +1,19 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#include "renderer/3d/pipeline/dynamic/core/bag/dynpip_color_bag.hpp"
namespace Tyra {
DynPipColorBag::DynPipColorBag() { single = nullptr; }
DynPipColorBag::~DynPipColorBag() {}
} // namespace Tyra
@@ -0,0 +1,29 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#include "renderer/3d/pipeline/dynamic/core/bag/dynpip_lighting_bag.hpp"
namespace Tyra {
DynPipLightingBag::DynPipLightingBag() {
lightMatrix = nullptr;
normalsFrom = nullptr;
normalsTo = nullptr;
dirLights = nullptr;
}
DynPipLightingBag::~DynPipLightingBag() {}
void DynPipLightingBag::freeNormals() {
if (normalsFrom) delete[] normalsFrom;
if (normalsTo) delete[] normalsTo;
}
} // namespace Tyra
@@ -0,0 +1,28 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#include "renderer/3d/pipeline/dynamic/core/bag/dynpip_texture_bag.hpp"
namespace Tyra {
DynPipTextureBag::DynPipTextureBag() {
coordinatesFrom = nullptr;
coordinatesTo = nullptr;
texture = nullptr;
}
DynPipTextureBag::~DynPipTextureBag() {}
void DynPipTextureBag::freeCoords() {
if (coordinatesFrom) delete[] coordinatesFrom;
if (coordinatesTo) delete[] coordinatesTo;
}
} // namespace Tyra
@@ -0,0 +1,99 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#include "renderer/3d/pipeline/dynamic/core/dynpip_core.hpp"
#include <sstream>
#include <iomanip>
#include "thread/threading.hpp"
namespace Tyra {
DynPipCore::DynPipCore() {}
DynPipCore::~DynPipCore() {}
void DynPipCore::init(RendererCore* t_core) {
rendererCore = t_core;
qbufferRenderer.init(t_core, &repository);
}
void DynPipCore::reinitVU1Programs() { qbufferRenderer.reinitVU1(); }
u32 DynPipCore::getMaxVertCountByParams(const bool& isLightingEnabled,
const bool& isTextureEnabled) {
return repository.getProgramByParams(isLightingEnabled, isTextureEnabled)
->getMaxVertCount(qbufferRenderer.getBufferSize());
}
void DynPipCore::initParts(DynPipBag* bag) {
RendererCoreTextureBuffers* texBuffers = nullptr;
if (bag->texture) {
auto temp = rendererCore->texture.useTexture(bag->texture->texture);
texBuffers = new RendererCoreTextureBuffers{temp.id, temp.core, temp.clut};
}
mvp = rendererCore->renderer3D.getViewProj() * *bag->info->model;
qbufferRenderer.sendObjectData(bag, &mvp, texBuffers);
delete texBuffers;
}
void DynPipCore::renderPart(DynPipBag** bags, const u32& count,
const bool& frustumCull) {
if (count <= 0) return;
TYRA_ASSERT(
bags[0]->verticesFrom != nullptr && bags[0]->verticesTo != nullptr,
"Vertices are required in 3D render bag!");
TYRA_ASSERT(bags[0]->info != nullptr,
"Info bag is required in 3D render bag!");
TYRA_ASSERT(bags[0]->info->model != nullptr,
"Info bag's model pointer is empty!");
TYRA_ASSERT(bags[0]->color != nullptr,
"Color bag is required in 3D render bag!");
TYRA_ASSERT(bags[0]->color->single, "Color is required in 3D render bag!");
TYRA_ASSERT(
!bags[0]->lighting ||
(bags[0]->lighting->lightMatrix && bags[0]->lighting->normalsFrom &&
bags[0]->lighting->normalsTo && bags[0]->lighting->dirLights),
"If you want lighting, please provide light matrix normals and dir "
"lights!");
TYRA_ASSERT(!bags[0]->texture || (bags[0]->texture->texture &&
bags[0]->texture->coordinatesFrom &&
bags[0]->texture->coordinatesTo),
"If you want texture, please provide texture and coordinates!");
if (!frustumCull) {
qbufferRenderer.render(bags, count);
return;
}
DynPipBag** bagsToRender = new DynPipBag*[count];
u32 inserted = 0;
for (u32 i = 0; i < count; i++) {
auto* bag = bags[i];
CoreBBox bbox(bag->verticesTo, bag->count);
if (bbox.isInFrustum(rendererCore->renderer3D.frustumPlanes.getAll(),
*bag->info->model) ==
CoreBBoxFrustum::OUTSIDE_FRUSTUM) {
continue;
}
bagsToRender[inserted++] = bag;
}
qbufferRenderer.render(bagsToRender, inserted);
delete[] bagsToRender;
}
} // namespace Tyra
@@ -0,0 +1,54 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#include "renderer/3d/pipeline/dynamic/core/dynpip_programs_repository.hpp"
namespace Tyra {
DynPipProgramsRepository::DynPipProgramsRepository() {}
DynPipProgramsRepository::~DynPipProgramsRepository() {}
DynPipVU1Program* DynPipProgramsRepository::getProgramByBag(
const DynPipBag* bag) {
return getProgramByParams(bag->lighting, bag->texture);
}
DynPipVU1Program* DynPipProgramsRepository::getProgramByParams(
const bool& isLightingEnabled, const bool& isTextureEnabled) {
if (isLightingEnabled && isTextureEnabled)
return &textureDirLights;
else if (isLightingEnabled)
return &dirLights;
else if (isTextureEnabled)
return &textureColor;
else
return &color;
}
DynPipVU1Program* DynPipProgramsRepository::getProgram(
const DynPipProgramName& name) {
switch (name) {
case DynPipProgramName::DynPipColor:
return &color;
case DynPipProgramName::DynPipDirLights:
return &dirLights;
case DynPipProgramName::DynPipTextureDirLights:
return &textureDirLights;
case DynPipProgramName::DynPipTextureColor:
return &textureColor;
default:
TYRA_TRAP("Unknown VU1 program name");
return &color;
}
}
} // namespace Tyra
@@ -0,0 +1,200 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#include "renderer/3d/pipeline/dynamic/core/dynpip_renderer.hpp"
#include "renderer/3d/pipeline/dynamic/core/programs/dynpip_vu1_shared_defines.h"
#include <dma.h>
namespace Tyra {
DynPipRenderer::DynPipRenderer() {
context = 0;
bufferSize = 0;
lastProgramName = DynPipProgramName::DynPipUndefinedProgram;
programsPacket = nullptr;
}
DynPipRenderer::~DynPipRenderer() {
if (programsPacket) packet2_free(programsPacket);
}
void DynPipRenderer::allocateOnUse(const u32& t_packetSize) {
staticDataPacket = packet2_create(3, P2_TYPE_NORMAL, P2_MODE_CHAIN, true);
objectDataPacket = packet2_create(16, P2_TYPE_NORMAL, P2_MODE_CHAIN, true);
for (u16 i = 0; i < 2; i++)
packets[i] =
packet2_create(t_packetSize, P2_TYPE_NORMAL, P2_MODE_CHAIN, true);
sendStaticData();
}
void DynPipRenderer::deallocateOnUse() {
packet2_free(staticDataPacket);
packet2_free(objectDataPacket);
for (u16 i = 0; i < 2; i++) packet2_free(packets[i]);
}
void DynPipRenderer::init(RendererCore* t_core,
DynPipProgramsRepository* t_programRepo) {
path1 = t_core->getPath1();
rendererCore = t_core;
programsRepo = t_programRepo;
dma_channel_initialize(DMA_CHANNEL_VIF1, NULL, 0);
dma_channel_fast_waits(DMA_CHANNEL_VIF1);
setProgramsCache();
reinitVU1();
TYRA_LOG("DynPipRenderer initialized");
}
void DynPipRenderer::reinitVU1() {
uploadPrograms();
setDoubleBuffer();
}
void DynPipRenderer::setProgramsCache() {
VU1Program** programs = new VU1Program*[4];
programs[0] = programsRepo->getProgram(DynPipProgramName::DynPipColor);
programs[1] = programsRepo->getProgram(DynPipProgramName::DynPipDirLights);
programs[2] = programsRepo->getProgram(DynPipProgramName::DynPipTextureColor);
programs[3] =
programsRepo->getProgram(DynPipProgramName::DynPipTextureDirLights);
programsPacket = path1->createProgramsCache(programs, 4, 0);
delete[] programs;
}
void DynPipRenderer::sendStaticData() const {
packet2_reset(staticDataPacket, false);
packet2_utils_vu_open_unpack(staticDataPacket, VU1_SET_GIFTAG_ADDR, false);
{ packet2_utils_gif_add_set(staticDataPacket, 1); }
packet2_utils_vu_close_unpack(staticDataPacket);
packet2_utils_vu_add_end_tag(staticDataPacket);
dma_channel_wait(DMA_CHANNEL_VIF1, 0);
dma_channel_send_packet2(staticDataPacket, DMA_CHANNEL_VIF1, true);
}
void DynPipRenderer::sendObjectData(
DynPipBag* bag, M4x4* mvp, RendererCoreTextureBuffers* texBuffers) const {
packet2_reset(objectDataPacket, false);
packet2_utils_vu_add_unpack_data(objectDataPacket, VU1_MVP_MATRIX_ADDR,
mvp->data, 4, false);
if (bag->lighting) {
packet2_utils_vu_add_unpack_data(objectDataPacket, VU1_LIGHTS_MATRIX_ADDR,
bag->lighting->lightMatrix, 3, false);
packet2_utils_vu_add_unpack_data(
objectDataPacket, VU1_LIGHTS_DIRS_ADDR,
bag->lighting->dirLights->getLightDirections(), 3, false);
packet2_utils_vu_add_unpack_data(objectDataPacket, VU1_LIGHTS_COLORS_ADDR,
bag->lighting->dirLights->getLightColors(),
4, false);
}
u8 singleColorEnabled = bag->color->single != nullptr;
if (singleColorEnabled) // Color is placed in 4th slot of
// VU1_LIGHTS_MATRIX_ADDR
packet2_utils_vu_add_unpack_data(objectDataPacket, VU1_SINGLE_COLOR_ADDR,
bag->color->single->rgba, 1, false);
packet2_utils_vu_open_unpack(objectDataPacket, VU1_OPTIONS_ADDR, false);
{
packet2_add_u32(objectDataPacket,
singleColorEnabled); // Single color enabled.
packet2_add_float(objectDataPacket,
bag->interpolation); // Interpolation value
packet2_add_u32(objectDataPacket, 0); // not used, padding
packet2_add_u32(objectDataPacket, 0); // not used, padding
packet2_utils_gs_add_lod(objectDataPacket, &rendererCore->gs.lod);
if (texBuffers != nullptr) {
packet2_utils_gs_add_texbuff_clut(objectDataPacket, texBuffers->core,
&rendererCore->texture.clut);
rendererCore->texture.updateClutBuffer(texBuffers->clut);
}
}
packet2_utils_vu_close_unpack(objectDataPacket);
packet2_utils_vu_add_end_tag(objectDataPacket);
dma_channel_wait(DMA_CHANNEL_VIF1, 0);
dma_channel_send_packet2(objectDataPacket, DMA_CHANNEL_VIF1, true);
}
void DynPipRenderer::render(DynPipBag** bags, const u32& count) {
if (count <= 0) return;
auto* program = programsRepo->getProgramByBag(bags[0]);
addBufferDataToPacket(program, bags, count);
sendPacket();
}
void DynPipRenderer::addBufferDataToPacket(DynPipVU1Program* program,
DynPipBag** bags, const u32& count) {
currentPacket = packets[context];
packet2_reset(currentPacket, false);
for (u32 i = 0; i < count; i++) {
if (bags[i]->count <= 0) continue;
program->addBufferDataToPacket(currentPacket, bags[i],
&rendererCore->gs.prim);
if (lastProgramName != program->getName()) {
packet2_utils_vu_add_start_program(currentPacket,
program->getDestinationAddress());
lastProgramName = program->getName();
} else {
packet2_utils_vu_add_continue_program(currentPacket);
}
}
packet2_utils_vu_add_end_tag(currentPacket);
}
void DynPipRenderer::sendPacket() {
dma_channel_wait(DMA_CHANNEL_VIF1, 0);
dma_channel_send_packet2(currentPacket, DMA_CHANNEL_VIF1, true);
// Switch packet, so we can proceed during DMA transfer
context = !context;
}
void DynPipRenderer::clearLastProgramName() {
lastProgramName = DynPipUndefinedProgram;
}
void DynPipRenderer::uploadPrograms() {
dma_channel_wait(DMA_CHANNEL_VIF1, 0);
dma_channel_send_packet2(programsPacket, DMA_CHANNEL_VIF1, true);
dma_channel_wait(DMA_CHANNEL_VIF1, 0);
}
void DynPipRenderer::setDoubleBuffer() {
u16 startingAddr = VU1_LAST_ITEM_ADDR + 1;
const u16 bufferMaxSize = 1000;
bufferSize = (bufferMaxSize - startingAddr) / 2;
path1->setDoubleBuffer(startingAddr, bufferSize);
bufferSize -= 1; // Because we don't want to upload anything from first
// buffer, to first addr of second buffer
}
} // namespace Tyra
@@ -0,0 +1,79 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#include "renderer/3d/pipeline/dynamic/core/dynpip_vu1_program.hpp"
namespace Tyra {
DynPipVU1Program::DynPipVU1Program(const DynPipProgramName& t_name,
u32* t_start, u32* t_end,
const u32& t_reglist,
const u8& t_reglistCount,
const u8& t_elementsPerVertex)
: VU1Program(t_start, t_end),
name(t_name),
reglistCount(t_reglistCount),
elementsPerVertex(t_elementsPerVertex),
reglist(t_reglist) {
packetSize = packet2_utils_get_packet_size_for_program(start, end);
programSize = calculateProgramSize();
}
DynPipVU1Program::~DynPipVU1Program() {}
const DynPipProgramName& DynPipVU1Program::getName() const { return name; }
u32& DynPipVU1Program::getReglist() { return reglist; }
void DynPipVU1Program::addBufferDataToPacket(packet2_t* packet, DynPipBag* bag,
prim_t* prim) {
addStandardBufferDataToPacket(packet, bag, prim);
addProgramQBufferDataToPacket(packet, bag);
}
void DynPipVU1Program::addStandardBufferDataToPacket(packet2_t* packet,
DynPipBag* bag,
prim_t* prim) {
if (bag->texture)
prim->mapping = 1;
else
prim->mapping = 0;
packet2_utils_vu_open_unpack(packet, 0, true);
{
packet2_add_float(packet, 2048.0F); // scale
packet2_add_float(packet, 2048.0F); // scale
packet2_add_float(packet,
static_cast<float>(0xFFFFFF) / 32.0F); // scale
packet2_add_u32(packet, bag->count); // vertex count
packet2_utils_gs_add_prim_giftag(packet, prim, bag->count, reglist,
reglistCount, 0);
}
packet2_utils_vu_close_unpack(packet);
}
u16 DynPipVU1Program::getMaxVertCount(const u16& bufferSize) const {
u16 res = bufferSize - 4;
res /= (elementsPerVertex + reglistCount);
// Buffer size = VU1 double buffer size (xtop)
// QBufferSize = res (it is placed inside VU1)
// Animation = 2 verts for final vert
res = res / 2;
// Triangle = 3 verts
res = res / 3;
res = res * 3;
return res;
}
} // namespace Tyra
@@ -0,0 +1,130 @@
; ______ ____ ___
; | \/ ____| |___|
; | | | \ | |
;---------------------------------------------------------------
; Copyright 2022, tyra - https://github.com/h4570/tyra
; Licenced under Apache License 2.0
; Sandro Sobczyński <sandro.sobczynski@gmail.com>
;
;---------------------------------------------------------------
; Triangle list
; Cull = Standard PS2 way. clipw polys are culled.
; Animation
; Color
;---------------------------------------------------------------
.syntax new
.name DynPipVU1_C
.vu
.init_vf_all
.init_vi_all
#include "src/renderer/3d/pipeline/shared/vcl_sml.i"
#include "src/renderer/3d/pipeline/shared/tyra_macros.i"
#include "inc/renderer/3d/pipeline/dynamic/core/programs/dynpip_vu1_shared_defines.h"
#define RGBA_STORE_OFFSET 0
#define XYZ2_STORE_OFFSET 1
--enter
--endenter
#vuprog DynPipVU1C
ResetClipFlags{ }
LoadTyraStaticData{ gifSetTag }
MatrixLoad{ mvp, VU1_MVP_MATRIX_ADDR, vi00 }
LoadTyraSingleColor{ singleColor, singleColorEnabled, VU1_SINGLE_COLOR_ADDR, VU1_OPTIONS_ADDR }
LoadTyraTags{ lodGifTag, texBufferClutGifTag, VU1_LOD_ADDR, VU1_CLUT_ADDR }
FixColor{ singleColor }
begin:
xtop buffer
LoadTyraPrimTag{ primTag, buffer }
ilw.w vertexCount, 0(buffer)
iaddiu vertexDataFrom, buffer, VU1_VERT_DATA_ADDR
iadd kickAddress, vertexDataFrom, vertexCount
iadd destAddress, kickAddress, vertexCount
iadd kickAddress, kickAddress, vertexCount
StoreTyraGifTags{ gifSetTag, lodGifTag, texBufferClutGifTag, primTag, destAddress }
LoadTyraLerpValue{ interp, VU1_OPTIONS_ADDR }
LoadTyraScaleValue{ scale, buffer }
;--- Loop
iadd vertexCounter, buffer, vertexCount
vertexLoop:
iadd vertexDataTo, vertexDataFrom, vertexCount
;--- Vertex 1 - from-to -> lerp
lq vertex1From, (vertexDataFrom)
lq vertex1To, (vertexDataTo)
Lerp{ vertex1, vertex1From, vertex1To, interp }
;--- Vertex 1 - Calculate
MatrixMultiplyVertex{ vertex1, mvp, vertex1 }
PerformClipCheck{ vertex1, destAddress, XYZ2_STORE_OFFSET }
VertexPersCorr{ vertex1, vertex1 }
ScaleVertexToGSFormat{ scale, vertex1 }
;--- Vertex 1 - Store
sq singleColor, RGBA_STORE_OFFSET(destAddress)
sq.xyz vertex1, XYZ2_STORE_OFFSET(destAddress)
; ---------------------------------------
;--- Vertex 2 - from-to -> lerp
lq vertex2From, 1(vertexDataFrom)
lq vertex2To, 1(vertexDataTo)
Lerp{ vertex2, vertex2From, vertex2To, interp }
;--- Vertex 2 - Calculate
MatrixMultiplyVertex{ vertex2, mvp, vertex2 }
PerformClipCheck{ vertex2, destAddress, XYZ2_STORE_OFFSET+2 }
VertexPersCorr{ vertex2, vertex2 }
ScaleVertexToGSFormat{ scale, vertex2 }
;--- Vertex 2 - Store
sq singleColor, RGBA_STORE_OFFSET+2(destAddress)
sq.xyz vertex2, XYZ2_STORE_OFFSET+2(destAddress)
; ---------------------------------------
;--- Vertex 3 - from-to -> lerp
lq vertex3From, 2(vertexDataFrom)
lq vertex3To, 2(vertexDataTo)
Lerp{ vertex3, vertex3From, vertex3To, interp }
;--- Vertex 3 - Calculate
MatrixMultiplyVertex{ vertex3, mvp, vertex3 }
PerformClipCheck{ vertex3, destAddress, XYZ2_STORE_OFFSET+4 }
VertexPersCorr{ vertex3, vertex3 }
ScaleVertexToGSFormat{ scale, vertex3 }
;--- Vertex 3 - Store
sq singleColor, RGBA_STORE_OFFSET+4(destAddress)
sq.xyz vertex3, XYZ2_STORE_OFFSET+4(destAddress)
;-------------------------------
iaddiu vertexDataFrom, vertexDataFrom, 3
iaddiu destAddress, destAddress, 6
;--- Fix loop
iaddi vertexCounter, vertexCounter, -3 ; decrement the loop counter
ibne vertexCounter, buffer, vertexLoop ; and repeat if needed
xgkick kickAddress ; dispatch to the GS rasterizer.
--barrier ; Why the hell I must add barrier AFTER XGKICK? VCL does not adds E bit without it...
--cont
b begin
#endvuprog
--exit
--endexit
@@ -0,0 +1,42 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#include "debug/debug.hpp"
#include "renderer/3d/pipeline/dynamic/core/programs/dynpip_c_vu1_program.hpp"
extern u32 DynPipVU1_C_CodeStart __attribute__((section(".vudata")));
extern u32 DynPipVU1_C_CodeEnd __attribute__((section(".vudata")));
namespace Tyra {
DynPipCVU1Program::DynPipCVU1Program()
: DynPipVU1Program(
DynPipColor, &DynPipVU1_C_CodeStart, &DynPipVU1_C_CodeEnd,
((u64)GIF_REG_RGBAQ) << 0 | ((u64)GIF_REG_XYZ2) << 4, 2, 1) {}
DynPipCVU1Program::~DynPipCVU1Program() {}
std::string DynPipCVU1Program::getStringName() const {
return std::string("DynPip - C");
}
void DynPipCVU1Program::addProgramQBufferDataToPacket(packet2_t* packet,
DynPipBag* bag) const {
u32 addr = VU1_VERT_DATA_ADDR;
// Add vertices
packet2_utils_vu_add_unpack_data(packet, addr, bag->verticesFrom, bag->count,
true);
addr += bag->count;
packet2_utils_vu_add_unpack_data(packet, addr, bag->verticesTo, bag->count,
true);
}
} // namespace Tyra
@@ -0,0 +1,154 @@
; ______ ____ ___
; | \/ ____| |___|
; | | | \ | |
;---------------------------------------------------------------
; Copyright 2022, tyra - https://github.com/h4570/tyra
; Licenced under Apache License 2.0
; Sandro Sobczyński <sandro.sobczynski@gmail.com>
;
;---------------------------------------------------------------
; Triangle list
; Cull = Standard PS2 way. clipw polys are culled.
; Animation
; Directional lights
;---------------------------------------------------------------
.syntax new
.name DynPipVU1_D
.vu
.init_vf_all
.init_vi_all
#include "src/renderer/3d/pipeline/shared/vcl_sml.i"
#include "src/renderer/3d/pipeline/shared/tyra_macros.i"
#include "inc/renderer/3d/pipeline/dynamic/core/programs/dynpip_vu1_shared_defines.h"
#define RGBA_STORE_OFFSET 0
#define XYZ2_STORE_OFFSET 1
--enter
--endenter
#vuprog DynPipVU1D
ResetClipFlags{ }
LoadTyraStaticData{ gifSetTag }
MatrixLoad{ mvp, VU1_MVP_MATRIX_ADDR, vi00 }
LoadTyraTags{ lodGifTag, texBufferClutGifTag, VU1_LOD_ADDR, VU1_CLUT_ADDR }
begin:
xtop buffer
LoadTyraPrimTag{ primTag, buffer }
ilw.w vertexCount, 0(buffer)
iaddiu vertexDataFrom, buffer, VU1_VERT_DATA_ADDR
iadd normalDataFrom, vertexDataFrom, vertexCount
iadd normalDataFrom, normalDataFrom, vertexCount
iadd kickAddress, normalDataFrom, vertexCount
iadd destAddress, kickAddress, vertexCount
iadd kickAddress, kickAddress, vertexCount
StoreTyraGifTags{ gifSetTag, lodGifTag, texBufferClutGifTag, primTag, destAddress }
LoadTyraLerpValue{ interp, VU1_OPTIONS_ADDR }
LoadTyraScaleValue{ scale, buffer }
;--- Loop
iadd vertexCounter, buffer, vertexCount
vertexLoop:
iadd vertexDataTo, vertexDataFrom, vertexCount
iadd normalDataTo, normalDataFrom, vertexCount
;--- Vertex 1 - from-to -> lerp
lq vertex1From, (vertexDataFrom)
lq vertex1To, (vertexDataTo)
Lerp{ vertex1, vertex1From, vertex1To, interp }
lq.xyz normal1From, (normalDataFrom)
lq.xyz normal1To, (normalDataTo)
LerpXYZ{ normal1, normal1From, normal1To, interp }
;--- Vertex 1 - Calculate
MatrixMultiplyVertex{ vertex1, mvp, vertex1 }
PerformClipCheck{ vertex1, destAddress, XYZ2_STORE_OFFSET }
VertexPersCorr{ vertex1, vertex1 }
ScaleVertexToGSFormat{ scale, vertex1 }
LoadTyraDirectionalLights{ lightMatrix, lightDirections, lightColors, ambientColor, VU1_LIGHTS_DIRS_ADDR, VU1_LIGHTS_COLORS_ADDR, VU1_LIGHTS_MATRIX_ADDR }
CalculateTyraDirectionalLights{ outputColor1, normal1, lightDirections, lightColors, lightMatrix, ambientColor }
FixColor{ outputColor1 }
;--- Vertex 1 - Store
sq outputColor1, RGBA_STORE_OFFSET(destAddress)
sq.xyz vertex1, XYZ2_STORE_OFFSET(destAddress)
; ---------------------------------------
;--- Vertex 2 - from-to -> lerp
lq vertex2From, 1(vertexDataFrom)
lq vertex2To, 1(vertexDataTo)
Lerp{ vertex2, vertex2From, vertex2To, interp }
lq.xyz normal2From, 1(normalDataFrom)
lq.xyz normal2To, 1(normalDataTo)
LerpXYZ{ normal2, normal2From, normal2To, interp }
;--- Vertex 2 - Calculate
MatrixMultiplyVertex{ vertex2, mvp, vertex2 }
PerformClipCheck{ vertex2, destAddress, XYZ2_STORE_OFFSET }
VertexPersCorr{ vertex2, vertex2 }
ScaleVertexToGSFormat{ scale, vertex2 }
LoadTyraDirectionalLights{ lightMatrix, lightDirections, lightColors, ambientColor, VU1_LIGHTS_DIRS_ADDR, VU1_LIGHTS_COLORS_ADDR, VU1_LIGHTS_MATRIX_ADDR }
CalculateTyraDirectionalLights{ outputColor2, normal2, lightDirections, lightColors, lightMatrix, ambientColor }
FixColor{ outputColor2 }
;--- Vertex 2 - Store
sq outputColor2, RGBA_STORE_OFFSET+2(destAddress)
sq.xyz vertex2, XYZ2_STORE_OFFSET+2(destAddress)
; ---------------------------------------
;--- Vertex 3 - from-to -> lerp
lq vertex3From, 2(vertexDataFrom)
lq vertex3To, 2(vertexDataTo)
Lerp{ vertex3, vertex3From, vertex3To, interp }
lq.xyz normal3From, 2(normalDataFrom)
lq.xyz normal3To, 2(normalDataTo)
LerpXYZ{ normal3, normal3From, normal3To, interp }
;--- Vertex 3 - Calculate
MatrixMultiplyVertex{ vertex3, mvp, vertex3 }
PerformClipCheck{ vertex3, destAddress, XYZ2_STORE_OFFSET }
VertexPersCorr{ vertex3, vertex3 }
ScaleVertexToGSFormat{ scale, vertex3 }
LoadTyraDirectionalLights{ lightMatrix, lightDirections, lightColors, ambientColor, VU1_LIGHTS_DIRS_ADDR, VU1_LIGHTS_COLORS_ADDR, VU1_LIGHTS_MATRIX_ADDR }
CalculateTyraDirectionalLights{ outputColor3, normal3, lightDirections, lightColors, lightMatrix, ambientColor }
FixColor{ outputColor3 }
;--- Vertex 3 - Store
sq outputColor3, RGBA_STORE_OFFSET+4(destAddress)
sq.xyz vertex3, XYZ2_STORE_OFFSET+4(destAddress)
;-------------------------------
iaddiu vertexDataFrom, vertexDataFrom, 3
iaddiu normalDataFrom, normalDataFrom, 3
iaddiu destAddress, destAddress, 6
;--- Fix loop
iaddi vertexCounter, vertexCounter, -3 ; decrement the loop counter
ibne vertexCounter, buffer, vertexLoop ; and repeat if needed
xgkick kickAddress ; dispatch to the GS rasterizer.
--barrier ; Why the hell I must add barrier AFTER XGKICK? VCL does not adds E bit without it...
--cont
b begin
#endvuprog
--exit
--endexit
@@ -0,0 +1,53 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#include "debug/debug.hpp"
#include "renderer/3d/pipeline/dynamic/core/programs/dynpip_d_vu1_program.hpp"
extern u32 DynPipVU1_D_CodeStart __attribute__((section(".vudata")));
extern u32 DynPipVU1_D_CodeEnd __attribute__((section(".vudata")));
namespace Tyra {
DynPipDVU1Program::DynPipDVU1Program()
: DynPipVU1Program(
DynPipDirLights, &DynPipVU1_D_CodeStart, &DynPipVU1_D_CodeEnd,
((u64)GIF_REG_RGBAQ) << 0 | ((u64)GIF_REG_XYZ2) << 4, 2, 2) {}
DynPipDVU1Program::~DynPipDVU1Program() {}
std::string DynPipDVU1Program::getStringName() const {
return std::string("DynPip - D");
}
void DynPipDVU1Program::addProgramQBufferDataToPacket(packet2_t* packet,
DynPipBag* bag) const {
u32 addr = VU1_VERT_DATA_ADDR;
// Add vertices
packet2_utils_vu_add_unpack_data(packet, addr, bag->verticesFrom, bag->count,
true);
addr += bag->count;
packet2_utils_vu_add_unpack_data(packet, addr, bag->verticesTo, bag->count,
true);
addr += bag->count;
if (bag->lighting) {
// Add normal
packet2_utils_vu_add_unpack_data(packet, addr, bag->lighting->normalsFrom,
bag->count, true);
addr += bag->count;
packet2_utils_vu_add_unpack_data(packet, addr, bag->lighting->normalsTo,
bag->count, true);
addr += bag->count;
}
}
} // namespace Tyra
@@ -0,0 +1,154 @@
; ______ ____ ___
; | \/ ____| |___|
; | | | \ | |
;---------------------------------------------------------------
; Copyright 2022, tyra - https://github.com/h4570/tyra
; Licenced under Apache License 2.0
; Sandro Sobczyński <sandro.sobczynski@gmail.com>
;
;---------------------------------------------------------------
; Triangle list
; Cull = Standard PS2 way. clipw polys are culled.
; Animation
; Lighting, texture, color
;---------------------------------------------------------------
.syntax new
.name DynPipVU1_TC
.vu
.init_vf_all
.init_vi_all
#include "src/renderer/3d/pipeline/shared/vcl_sml.i"
#include "src/renderer/3d/pipeline/shared/tyra_macros.i"
#include "inc/renderer/3d/pipeline/dynamic/core/programs/dynpip_vu1_shared_defines.h"
#define STQ_STORE_OFFSET 0
#define RGBA_STORE_OFFSET 1
#define XYZ2_STORE_OFFSET 2
--enter
--endenter
#vuprog DynPipVU1TC
ResetClipFlags{ }
LoadTyraStaticData{ gifSetTag }
MatrixLoad{ mvp, VU1_MVP_MATRIX_ADDR, vi00 }
LoadTyraSingleColor{ singleColor, singleColorEnabled, VU1_SINGLE_COLOR_ADDR, VU1_OPTIONS_ADDR }
LoadTyraTags{ lodGifTag, texBufferClutGifTag, VU1_LOD_ADDR, VU1_CLUT_ADDR }
FixColor{ singleColor }
begin:
xtop buffer
LoadTyraPrimTag{ primTag, buffer }
ilw.w vertexCount, 0(buffer)
iaddiu vertexDataFrom, buffer, VU1_VERT_DATA_ADDR
iadd stqDataFrom, vertexDataFrom, vertexCount
iadd stqDataFrom, stqDataFrom, vertexCount
iadd kickAddress, stqDataFrom, vertexCount
iadd destAddress, kickAddress, vertexCount
iadd kickAddress, kickAddress, vertexCount
StoreTyraGifTags{ gifSetTag, lodGifTag, texBufferClutGifTag, primTag, destAddress }
LoadTyraLerpValue{ interp, VU1_OPTIONS_ADDR }
LoadTyraScaleValue{ scale, buffer }
;--- Loop
iadd vertexCounter, buffer, vertexCount
vertexLoop:
iadd vertexDataTo, vertexDataFrom, vertexCount
iadd stqDataTo, stqDataFrom, vertexCount
;--- Vertex 1 - from-to -> lerp
lq vertex1From, (vertexDataFrom)
lq vertex1To, (vertexDataTo)
Lerp{ vertex1, vertex1From, vertex1To, interp }
lq stq1From, (stqDataFrom)
lq stq1To, (stqDataTo)
Lerp{ stq1, stq1From, stq1To, interp }
;--- Vertex 1 - Calculate
MatrixMultiplyVertex{ vertex1, mvp, vertex1 }
PerformClipCheck{ vertex1, destAddress, XYZ2_STORE_OFFSET }
VertexPersCorr{ vertex1, vertex1 }
ScaleVertexToGSFormat{ scale, vertex1 }
PerformTexturePerspectiveCorrection{ outputStq1, stq1 }
;--- Vertex 1 - Store
sq outputStq1, STQ_STORE_OFFSET(destAddress)
sq singleColor, RGBA_STORE_OFFSET(destAddress)
sq.xyz vertex1, XYZ2_STORE_OFFSET(destAddress)
; ---------------------------------------
;--- Vertex 2 - from-to -> lerp
lq vertex2From, 1(vertexDataFrom)
lq vertex2To, 1(vertexDataTo)
Lerp{ vertex2, vertex2From, vertex2To, interp }
lq stq2From, 1(stqDataFrom)
lq stq2To, 1(stqDataTo)
Lerp{ stq2, stq2From, stq2To, interp }
;--- Vertex 2 - Calculate
MatrixMultiplyVertex{ vertex2, mvp, vertex2 }
PerformClipCheck{ vertex2, destAddress, XYZ2_STORE_OFFSET+3 }
VertexPersCorr{ vertex2, vertex2 }
ScaleVertexToGSFormat{ scale, vertex2 }
PerformTexturePerspectiveCorrection{ outputStq2, stq2 }
;--- Vertex 2 - Store
sq outputStq2, STQ_STORE_OFFSET+3(destAddress)
sq singleColor, RGBA_STORE_OFFSET+3(destAddress)
sq.xyz vertex2, XYZ2_STORE_OFFSET+3(destAddress)
; ---------------------------------------
;--- Vertex 3 - from-to -> lerp
lq vertex3From, 2(vertexDataFrom)
lq vertex3To, 2(vertexDataTo)
Lerp{ vertex3, vertex3From, vertex3To, interp }
lq stq3From, 2(stqDataFrom)
lq stq3To, 2(stqDataTo)
Lerp{ stq3, stq3From, stq3To, interp }
;--- Vertex 3 - Calculate
MatrixMultiplyVertex{ vertex3, mvp, vertex3 }
PerformClipCheck{ vertex3, destAddress, XYZ2_STORE_OFFSET+6 }
VertexPersCorr{ vertex3, vertex3 }
ScaleVertexToGSFormat{ scale, vertex3 }
PerformTexturePerspectiveCorrection{ outputStq3, stq3 }
;--- Vertex 3 - Store
sq outputStq3, STQ_STORE_OFFSET+6(destAddress)
sq singleColor, RGBA_STORE_OFFSET+6(destAddress)
sq.xyz vertex3, XYZ2_STORE_OFFSET+6(destAddress)
;-------------------------------
iaddiu vertexDataFrom, vertexDataFrom, 3
iaddiu stqDataFrom, stqDataFrom, 3
iaddiu destAddress, destAddress, 9
;--- Fix loop
iaddi vertexCounter, vertexCounter, -3 ; decrement the loop counter
ibne vertexCounter, buffer, vertexLoop ; and repeat if needed
xgkick kickAddress ; dispatch to the GS rasterizer.
--barrier ; Why the hell I must add barrier AFTER XGKICK? VCL does not adds E bit without it...
--cont
b begin
#endvuprog
--exit
--endexit

Some files were not shown because too many files have changed in this diff Show More