tyrav2 init
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "renderer/3d/bbox/bbox.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
BBox::BBox(CoreBBox** t_bboxes, const u32& count) : CoreBBox(t_bboxes, count) {
|
||||
setData();
|
||||
}
|
||||
|
||||
BBox::BBox(Vec4* t_vertices, u32 count) : CoreBBox(t_vertices, count) {
|
||||
setData();
|
||||
}
|
||||
|
||||
BBox::BBox(Vec4* t_vertices, u32* faces, u32 count)
|
||||
: CoreBBox(t_vertices, faces, count) {
|
||||
setData();
|
||||
}
|
||||
|
||||
BBox::BBox(Vec4* t_vertices) : CoreBBox(t_vertices) { setData(); }
|
||||
|
||||
void BBox::setData() {
|
||||
// This might be shortened with Vec4 operator overloading, but current
|
||||
// implementation is more human readable.
|
||||
_height = _vertices[0].y - _vertices[2].y;
|
||||
_width = _vertices[0].x - _vertices[4].x;
|
||||
_depth = _vertices[0].z - _vertices[1].z;
|
||||
|
||||
_centerVector = _vertices[0];
|
||||
_centerVector.x += (_width / 2);
|
||||
_centerVector.y += (_height / 2);
|
||||
_centerVector.z += (_depth / 2);
|
||||
|
||||
// Z-Axis faces
|
||||
_frontFace = BBoxFace(_vertices[1], _vertices[7], _vertices[1].z);
|
||||
_backFace = BBoxFace(_vertices[0], _vertices[6], _vertices[0].z);
|
||||
// X-Axis faces
|
||||
_leftFace = BBoxFace(_vertices[0], _vertices[3], _vertices[0].x);
|
||||
_rightFace = BBoxFace(_vertices[4], _vertices[7], _vertices[4].x);
|
||||
// Y-Axis faces
|
||||
_topFace = BBoxFace(_vertices[2], _vertices[7], _vertices[2].y);
|
||||
_bottomFace = BBoxFace(_vertices[0], _vertices[5], _vertices[0].y);
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,144 @@
|
||||
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# 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/mesh.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
Mesh::Mesh(const MeshBuilderData& data) {
|
||||
id = rand() % 1000000;
|
||||
|
||||
framesCount = data.framesCount;
|
||||
TYRA_ASSERT(framesCount > 0, "Frames 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;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,150 @@
|
||||
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "debug/debug.hpp"
|
||||
#include <tamtypes.h>
|
||||
#include <string>
|
||||
#include "math/vec4.hpp"
|
||||
#include "renderer/models/color.hpp"
|
||||
#include "renderer/3d/mesh/mesh_frame.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
MeshFrame::MeshFrame(const MeshBuilderData& data, const u32& index) {
|
||||
TYRA_ASSERT(index < data.framesCount && index >= 0, "Provided index \"",
|
||||
index, "\" is out of range");
|
||||
|
||||
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);
|
||||
|
||||
_isMother = true;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
MeshFrame::~MeshFrame() {
|
||||
if (_isMother) {
|
||||
delete[] vertices;
|
||||
if (normals) delete[] normals;
|
||||
if (textureCoords) delete[] textureCoords;
|
||||
if (colors) delete[] colors;
|
||||
delete bbox;
|
||||
}
|
||||
}
|
||||
|
||||
void MeshFrame::print() const {
|
||||
auto text = getPrint(nullptr);
|
||||
printf("%s\n", text.c_str());
|
||||
}
|
||||
|
||||
void MeshFrame::print(const char* name) const {
|
||||
auto text = getPrint(name);
|
||||
printf("%s\n", text.c_str());
|
||||
}
|
||||
|
||||
std::string MeshFrame::getPrint(const char* name) const {
|
||||
std::stringstream res;
|
||||
if (name) {
|
||||
res << name << "(";
|
||||
} else {
|
||||
res << "MeshFrame(";
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,179 @@
|
||||
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# 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 <string>
|
||||
#include <cstdlib>
|
||||
#include "renderer/3d/mesh/mesh_material.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
MeshMaterial::MeshMaterial(const MeshBuilderData& data,
|
||||
const u32& materialIndex)
|
||||
: singleColor(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");
|
||||
} 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");
|
||||
|
||||
_name = data.materials[materialIndex]->name;
|
||||
TYRA_ASSERT(_name.length() > 0, "MeshMaterial name cannot be empty");
|
||||
|
||||
framesCount = data.framesCount;
|
||||
frames = new MeshMaterialFrame*[framesCount];
|
||||
for (u32 i = 0; i < framesCount; i++) {
|
||||
frames[i] = new MeshMaterialFrame(data, i, materialIndex);
|
||||
}
|
||||
|
||||
_isMother = true;
|
||||
}
|
||||
|
||||
MeshMaterial::MeshMaterial(const MeshMaterial& mesh) {
|
||||
id = rand() % 1000000;
|
||||
|
||||
vertexFaces = mesh.vertexFaces;
|
||||
textureCoordFaces = mesh.textureCoordFaces;
|
||||
normalFaces = mesh.normalFaces;
|
||||
colorFaces = mesh.colorFaces;
|
||||
|
||||
facesCount = mesh.facesCount;
|
||||
framesCount = mesh.framesCount;
|
||||
_name = mesh._name;
|
||||
|
||||
singleColor.set(128.0F, 128.0F, 128.0F, 128.0F);
|
||||
|
||||
frames = new MeshMaterialFrame*[framesCount];
|
||||
for (u32 i = 0; i < framesCount; i++) {
|
||||
frames[i] = new MeshMaterialFrame(*mesh.frames[i]);
|
||||
}
|
||||
|
||||
_isMother = false;
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
delete[] frames;
|
||||
}
|
||||
|
||||
const BBox& MeshMaterial::getBBox(const u32& frame) const {
|
||||
return frames[frame]->getBBox();
|
||||
}
|
||||
|
||||
void MeshMaterial::setSingleColorFlag(const u8& flag) {
|
||||
TYRA_ASSERT(
|
||||
colorFaces != nullptr,
|
||||
"Colors and color faces are required to use color-per-vertex mode");
|
||||
|
||||
singleColorFlag = flag;
|
||||
}
|
||||
|
||||
void MeshMaterial::print() const {
|
||||
auto text = getPrint(nullptr);
|
||||
printf("%s\n", text.c_str());
|
||||
}
|
||||
|
||||
void MeshMaterial::print(const char* name) const {
|
||||
auto text = getPrint(name);
|
||||
printf("%s\n", text.c_str());
|
||||
}
|
||||
|
||||
std::string MeshMaterial::getPrint(const char* name) const {
|
||||
std::stringstream res;
|
||||
if (name) {
|
||||
res << name << "(";
|
||||
} else {
|
||||
res << "MeshMaterial(";
|
||||
}
|
||||
|
||||
res << std::endl;
|
||||
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 << ")";
|
||||
|
||||
return res.str();
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,51 @@
|
||||
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "debug/debug.hpp"
|
||||
#include <tamtypes.h>
|
||||
#include "renderer/models/color.hpp"
|
||||
#include "loaders/3d/builder/mesh_builder_data.hpp"
|
||||
#include "renderer/3d/mesh/mesh_material_frame.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
MeshMaterialFrame::MeshMaterialFrame(const MeshBuilderData& data,
|
||||
const u32& frameIndex,
|
||||
const u32& materialIndex) {
|
||||
TYRA_ASSERT(frameIndex < data.framesCount && frameIndex >= 0,
|
||||
"Provided index \"", frameIndex, "\" is out of range");
|
||||
TYRA_ASSERT(materialIndex < data.materialsCount && materialIndex >= 0,
|
||||
"Provided index \"", materialIndex, "\" is out of range");
|
||||
|
||||
id = rand() % 1000000;
|
||||
|
||||
bbox = new BBox(data.frames[frameIndex]->vertices,
|
||||
data.materials[materialIndex]->vertexFaces,
|
||||
data.materials[materialIndex]->count);
|
||||
|
||||
_isMother = true;
|
||||
}
|
||||
|
||||
MeshMaterialFrame::MeshMaterialFrame(const MeshMaterialFrame& frame) {
|
||||
id = rand() % 1000000;
|
||||
|
||||
bbox = frame.bbox;
|
||||
|
||||
_isMother = false;
|
||||
}
|
||||
|
||||
MeshMaterialFrame::~MeshMaterialFrame() {
|
||||
if (_isMother) {
|
||||
delete bbox;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# 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/minecraft/data/mcpip_block_data.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
McpipBlockData::McpipBlockData() {
|
||||
vertices = nullptr;
|
||||
textureCoords = nullptr;
|
||||
comboData = nullptr;
|
||||
offset = 0.0F;
|
||||
count = 0;
|
||||
}
|
||||
|
||||
McpipBlockData::~McpipBlockData() {}
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0F
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "renderer/3d/pipeline/minecraft/data/mcpip_multi_tex_block_data.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
McpipMultiTexBlockData::McpipMultiTexBlockData() {
|
||||
allocateTempData();
|
||||
unroll();
|
||||
dellocateTempData();
|
||||
}
|
||||
|
||||
McpipMultiTexBlockData::~McpipMultiTexBlockData() {
|
||||
if (comboData != nullptr) {
|
||||
delete[] comboData;
|
||||
}
|
||||
}
|
||||
|
||||
void McpipMultiTexBlockData::allocateTempData() {
|
||||
u32 tempVertsStsCount = 24;
|
||||
|
||||
tempVerts = new Tyra::Vec4[tempVertsStsCount];
|
||||
tempVerts[0].set(-1.0F, -1.0F, -1.0F);
|
||||
tempVerts[1].set(1.0F, -1.0F, -1.0F);
|
||||
tempVerts[2].set(1.0F, -1.0F, 1.0F);
|
||||
tempVerts[3].set(-1.0F, -1.0F, 1.0F);
|
||||
tempVerts[4].set(1.0F, -1.0F, 1.0F);
|
||||
tempVerts[5].set(1.0F, 1.0F, 1.0F);
|
||||
tempVerts[6].set(-1.0F, 1.0F, 1.0F);
|
||||
tempVerts[7].set(-1.0F, -1.0F, 1.0F);
|
||||
tempVerts[8].set(-1.0F, -1.0F, 1.0F);
|
||||
tempVerts[9].set(-1.0F, 1.0F, 1.0F);
|
||||
tempVerts[10].set(-1.0F, 1.0F, -1.0F);
|
||||
tempVerts[11].set(-1.0F, -1.0F, -1.0F);
|
||||
tempVerts[12].set(1.0F, -1.0F, -1.0F);
|
||||
tempVerts[13].set(1.0F, 1.0F, -1.0F);
|
||||
tempVerts[14].set(1.0F, 1.0F, 1.0F);
|
||||
tempVerts[15].set(1.0F, -1.0F, 1.0F);
|
||||
tempVerts[16].set(-1.0F, -1.0F, -1.0F);
|
||||
tempVerts[17].set(-1.0F, 1.0F, -1.0F);
|
||||
tempVerts[18].set(1.0F, 1.0F, -1.0F);
|
||||
tempVerts[19].set(1.0F, -1.0F, -1.0F);
|
||||
tempVerts[20].set(1.0F, 1.0F, -1.0F);
|
||||
tempVerts[21].set(-1.0F, 1.0F, -1.0F);
|
||||
tempVerts[22].set(-1.0F, 1.0F, 1.0F);
|
||||
tempVerts[23].set(1.0F, 1.0F, 1.0F);
|
||||
|
||||
tempTexCoords = new Tyra::Vec4[tempVertsStsCount];
|
||||
tempTexCoords[0].set(0.062721F, 0.813282F, 1.0F, 0.0F);
|
||||
tempTexCoords[1].set(0.062721F, 0.875327F, 1.0F, 0.0F);
|
||||
tempTexCoords[2].set(0.000676F, 0.875327F, 1.0F, 0.0F);
|
||||
tempTexCoords[3].set(0.000676F, 0.813282F, 1.0F, 0.0F);
|
||||
tempTexCoords[4].set(0.062095F, 0.750461F, 1.0F, 0.0F);
|
||||
tempTexCoords[5].set(0.062095F, 0.812244F, 1.0F, 0.0F);
|
||||
tempTexCoords[6].set(0.000311F, 0.812244F, 1.0F, 0.0F);
|
||||
tempTexCoords[7].set(0.000311F, 0.750461F, 1.0F, 0.0F);
|
||||
tempTexCoords[8].set(0.062629F, 0.687779F, 1.0F, 0.0F);
|
||||
tempTexCoords[9].set(0.000000F, 0.687779F, 1.0F, 0.0F);
|
||||
tempTexCoords[10].set(0.000000F, 0.624816F, 1.0F, 0.0F);
|
||||
tempTexCoords[11].set(0.062629F, 0.624816F, 1.0F, 0.0F);
|
||||
tempTexCoords[12].set(0.062667F, 0.626382F, 1.0F, 0.0F);
|
||||
tempTexCoords[13].set(0.000000F, 0.626382F, 1.0F, 0.0F);
|
||||
tempTexCoords[14].set(0.000000F, 0.561642F, 1.0F, 0.0F);
|
||||
tempTexCoords[15].set(0.062667F, 0.561642F, 1.0F, 0.0F);
|
||||
tempTexCoords[16].set(0.000000F, 0.937621F, 1.0F, 0.0F);
|
||||
tempTexCoords[17].set(0.000000F, 0.875134F, 1.0F, 0.0F);
|
||||
tempTexCoords[18].set(0.062128F, 0.875134F, 1.0F, 0.0F);
|
||||
tempTexCoords[19].set(0.062128F, 0.937621F, 1.0F, 0.0F);
|
||||
tempTexCoords[20].set(0.000000F, 0.937223F, 1.0F, 0.0F);
|
||||
tempTexCoords[21].set(0.062223F, 0.937223F, 1.0F, 0.0F);
|
||||
tempTexCoords[22].set(0.062223F, 0.999641F, 1.0F, 0.0F);
|
||||
tempTexCoords[23].set(0.000000F, 0.999641F, 1.0F, 0.0F);
|
||||
|
||||
// Because 16 blocks can fit in single column of 256x256 tex atlas
|
||||
offset = 1.0F / 16.0F;
|
||||
|
||||
for (u32 i = 0; i < tempVertsStsCount; i++)
|
||||
tempTexCoords[i].y = 1.0F - tempTexCoords[i].y;
|
||||
|
||||
tempVertFaces = new u32[36];
|
||||
tempTexCoordsFaces = new u32[36];
|
||||
|
||||
std::string vertexFaces =
|
||||
"1,2,3,1,3,4,5,6,7,5,7,8,9,10,11,9,11,12,13,14,15,13,15,16,17,18,19,17,"
|
||||
"19,20,21,22,23,21,23,24";
|
||||
std::stringstream ssVertexFaces(vertexFaces);
|
||||
|
||||
std::string texCoordFaces =
|
||||
"1,2,3,1,3,4,5,6,7,5,7,8,9,10,11,9,11,12,13,14,15,13,15,16,17,18,19,17,"
|
||||
"19,20,21,22,23,21,23,24";
|
||||
std::stringstream ssTexCoordFaces(texCoordFaces);
|
||||
|
||||
int i = 0;
|
||||
std::string item;
|
||||
|
||||
while (std::getline(ssVertexFaces, item, ','))
|
||||
tempVertFaces[i++] = std::stoi(item) - 1;
|
||||
|
||||
i = 0;
|
||||
|
||||
while (std::getline(ssTexCoordFaces, item, ','))
|
||||
tempTexCoordsFaces[i++] = std::stoi(item) - 1;
|
||||
}
|
||||
|
||||
void McpipMultiTexBlockData::unroll() {
|
||||
count = 36;
|
||||
comboData = new Tyra::Vec4[36 * 2];
|
||||
vertices = &comboData[0];
|
||||
textureCoords = &comboData[36];
|
||||
|
||||
for (u32 i = 0; i < count; i++) {
|
||||
vertices[i] = tempVerts[tempVertFaces[i]];
|
||||
textureCoords[i] = tempTexCoords[tempTexCoordsFaces[i]];
|
||||
}
|
||||
}
|
||||
|
||||
void McpipMultiTexBlockData::dellocateTempData() {
|
||||
delete[] tempVerts;
|
||||
delete[] tempTexCoords;
|
||||
delete[] tempVertFaces;
|
||||
delete[] tempTexCoordsFaces;
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0F
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "renderer/3d/pipeline/minecraft/data/mcpip_single_tex_block_data.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
McpipSingleTexBlockData::McpipSingleTexBlockData() {
|
||||
allocateTempData();
|
||||
unroll();
|
||||
dellocateTempData();
|
||||
}
|
||||
|
||||
McpipSingleTexBlockData::~McpipSingleTexBlockData() {
|
||||
if (comboData != nullptr) {
|
||||
delete[] comboData;
|
||||
}
|
||||
}
|
||||
|
||||
void McpipSingleTexBlockData::allocateTempData() {
|
||||
u32 tempVertsStsCount = 24;
|
||||
|
||||
tempVerts = new Tyra::Vec4[tempVertsStsCount];
|
||||
tempVerts[0].set(-1.0F, -1.0F, -1.0F);
|
||||
tempVerts[1].set(1.0F, -1.0F, -1.0F);
|
||||
tempVerts[2].set(1.0F, -1.0F, 1.0F);
|
||||
tempVerts[3].set(-1.0F, -1.0F, 1.0F);
|
||||
tempVerts[4].set(1.0F, -1.0F, 1.0F);
|
||||
tempVerts[5].set(1.0F, 1.0F, 1.0F);
|
||||
tempVerts[6].set(-1.0F, 1.0F, 1.0F);
|
||||
tempVerts[7].set(-1.0F, -1.0F, 1.0F);
|
||||
tempVerts[8].set(-1.0F, -1.0F, 1.0F);
|
||||
tempVerts[9].set(-1.0F, 1.0F, 1.0F);
|
||||
tempVerts[10].set(-1.0F, 1.0F, -1.0F);
|
||||
tempVerts[11].set(-1.0F, -1.0F, -1.0F);
|
||||
tempVerts[12].set(1.0F, -1.0F, -1.0F);
|
||||
tempVerts[13].set(1.0F, 1.0F, -1.0F);
|
||||
tempVerts[14].set(1.0F, 1.0F, 1.0F);
|
||||
tempVerts[15].set(1.0F, -1.0F, 1.0F);
|
||||
tempVerts[16].set(-1.0F, -1.0F, -1.0F);
|
||||
tempVerts[17].set(-1.0F, 1.0F, -1.0F);
|
||||
tempVerts[18].set(1.0F, 1.0F, -1.0F);
|
||||
tempVerts[19].set(1.0F, -1.0F, -1.0F);
|
||||
tempVerts[20].set(1.0F, 1.0F, -1.0F);
|
||||
tempVerts[21].set(-1.0F, 1.0F, -1.0F);
|
||||
tempVerts[22].set(-1.0F, 1.0F, 1.0F);
|
||||
tempVerts[23].set(1.0F, 1.0F, 1.0F);
|
||||
|
||||
tempTexCoords = new Tyra::Vec4[tempVertsStsCount];
|
||||
tempTexCoords[0].set(0.000618F, 0.937685F, 1.0F, 0.0F);
|
||||
tempTexCoords[1].set(0.062592F, 0.937685F, 1.0F, 0.0F);
|
||||
tempTexCoords[2].set(0.062592F, 0.999658F, 1.0F, 0.0F);
|
||||
tempTexCoords[3].set(0.000618F, 0.999658F, 1.0F, 0.0F);
|
||||
tempTexCoords[4].set(0.062608F, 0.937379F, 1.0F, 0.0F);
|
||||
tempTexCoords[5].set(0.062576F, 0.999352F, 1.0F, 0.0F);
|
||||
tempTexCoords[6].set(0.000602F, 0.999320F, 1.0F, 0.0F);
|
||||
tempTexCoords[7].set(0.000634F, 0.937346F, 1.0F, 0.0F);
|
||||
tempTexCoords[8].set(0.062592F, 0.937381F, 1.0F, 0.0F);
|
||||
tempTexCoords[9].set(0.062592F, 0.999354F, 1.0F, 0.0F);
|
||||
tempTexCoords[10].set(0.000618F, 0.999354F, 1.0F, 0.0F);
|
||||
tempTexCoords[11].set(0.000618F, 0.937381F, 1.0F, 0.0F);
|
||||
tempTexCoords[12].set(0.062618F, 0.937600F, 1.0F, 0.0F);
|
||||
tempTexCoords[13].set(0.062618F, 0.999542F, 1.0F, 0.0F);
|
||||
tempTexCoords[14].set(0.000603F, 0.999576F, 1.0F, 0.0F);
|
||||
tempTexCoords[15].set(0.000616F, 0.937585F, 1.0F, 0.0F);
|
||||
tempTexCoords[16].set(0.062561F, 0.937533F, 1.0F, 0.0F);
|
||||
tempTexCoords[17].set(0.062561F, 0.999446F, 1.0F, 0.0F);
|
||||
tempTexCoords[18].set(0.000649F, 0.999446F, 1.0F, 0.0F);
|
||||
tempTexCoords[19].set(0.000649F, 0.937533F, 1.0F, 0.0F);
|
||||
tempTexCoords[20].set(0.000556F, 0.937533F, 1.0F, 0.0F);
|
||||
tempTexCoords[21].set(0.062530F, 0.937533F, 1.0F, 0.0F);
|
||||
tempTexCoords[22].set(0.062530F, 0.999506F, 1.0F, 0.0F);
|
||||
tempTexCoords[23].set(0.000556F, 0.999506F, 1.0F, 0.0F);
|
||||
|
||||
// Because 16 blocks can fit in single column of 256x256 tex atlas
|
||||
offset = 1.0F / 16.0F;
|
||||
|
||||
for (u32 i = 0; i < tempVertsStsCount; i++)
|
||||
tempTexCoords[i].y = 1.0F - tempTexCoords[i].y;
|
||||
|
||||
tempVertFaces = new u32[36];
|
||||
tempTexCoordsFaces = new u32[36];
|
||||
|
||||
std::string vertexFaces =
|
||||
"1,2,3,1,3,4,5,6,7,5,7,8,9,10,11,9,11,12,13,14,15,13,15,16,17,18,19,17,"
|
||||
"19,20,21,22,23,21,23,24";
|
||||
std::stringstream ssVertexFaces(vertexFaces);
|
||||
|
||||
std::string texCoordFaces =
|
||||
"1,2,3,1,3,4,5,6,7,5,7,8,9,10,11,9,11,12,13,14,15,13,15,16,17,18,19,17,"
|
||||
"19,20,21,22,23,21,23,24";
|
||||
std::stringstream ssTexCoordFaces(texCoordFaces);
|
||||
|
||||
int i = 0;
|
||||
std::string item;
|
||||
|
||||
while (std::getline(ssVertexFaces, item, ','))
|
||||
tempVertFaces[i++] = std::stoi(item) - 1;
|
||||
|
||||
i = 0;
|
||||
|
||||
while (std::getline(ssTexCoordFaces, item, ','))
|
||||
tempTexCoordsFaces[i++] = std::stoi(item) - 1;
|
||||
}
|
||||
|
||||
void McpipSingleTexBlockData::unroll() {
|
||||
count = 36;
|
||||
comboData = new Tyra::Vec4[36 * 2];
|
||||
vertices = &comboData[0];
|
||||
textureCoords = &comboData[36];
|
||||
|
||||
for (u32 i = 0; i < count; i++) {
|
||||
vertices[i] = tempVerts[tempVertFaces[i]];
|
||||
textureCoords[i] = tempTexCoords[tempTexCoordsFaces[i]];
|
||||
}
|
||||
}
|
||||
|
||||
void McpipSingleTexBlockData::dellocateTempData() {
|
||||
delete[] tempVerts;
|
||||
delete[] tempTexCoords;
|
||||
delete[] tempVertFaces;
|
||||
delete[] tempTexCoordsFaces;
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include <tamtypes.h>
|
||||
#include "renderer/3d/pipeline/minecraft/minecraft_pipeline.hpp"
|
||||
#include "thread/threading.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
MinecraftPipeline::MinecraftPipeline() { latestMode = UndefinedMcpipProgram; }
|
||||
|
||||
MinecraftPipeline::~MinecraftPipeline() {
|
||||
if (bbox) {
|
||||
delete bbox;
|
||||
}
|
||||
}
|
||||
|
||||
void MinecraftPipeline::init(RendererCore* core) {
|
||||
rendererCore = core;
|
||||
manager.init(core);
|
||||
|
||||
initBBox();
|
||||
}
|
||||
|
||||
void MinecraftPipeline::onUse() {
|
||||
manager.uploadVU1Programs();
|
||||
|
||||
changeMode(McPipCull, true);
|
||||
}
|
||||
|
||||
void MinecraftPipeline::initBBox() {
|
||||
const auto& block = manager.getBlockData();
|
||||
bbox = new RenderBBox(block.vertices, block.count);
|
||||
}
|
||||
|
||||
void MinecraftPipeline::render(McpipBlock* blocks, const u32& count,
|
||||
Texture* t_tex, const bool& isMulti,
|
||||
const bool& noClipChecks) {
|
||||
auto texBuffers = rendererCore->texture.useTexture(t_tex);
|
||||
rendererCore->gs.prim.mapping = 1;
|
||||
|
||||
manager.clearLastProgram();
|
||||
std::vector<u32> cullIndexes;
|
||||
|
||||
if (noClipChecks) {
|
||||
for (u32 i = 0; i < count; i++) cullIndexes.push_back(i);
|
||||
cull(blocks, cullIndexes, &texBuffers, isMulti);
|
||||
} else {
|
||||
u32 culled = 0, clipped = 0;
|
||||
std::vector<u32> clipIndexes;
|
||||
|
||||
for (u32 i = 0; i < count; i++) {
|
||||
auto frustum = isInFrustum(blocks[i]);
|
||||
if (frustum == CoreBBoxFrustum::IN_FRUSTUM) {
|
||||
cullIndexes.push_back(i);
|
||||
culled++;
|
||||
} else if (frustum == CoreBBoxFrustum::PARTIALLY_IN_FRUSTUM) {
|
||||
clipIndexes.push_back(i);
|
||||
clipped++;
|
||||
}
|
||||
}
|
||||
|
||||
if (culled > 0) cull(blocks, cullIndexes, &texBuffers, isMulti);
|
||||
if (clipped > 0) clip(blocks, clipIndexes, &texBuffers, isMulti);
|
||||
}
|
||||
|
||||
Threading::switchThread();
|
||||
}
|
||||
|
||||
CoreBBoxFrustum MinecraftPipeline::isInFrustum(const McpipBlock& block) const {
|
||||
const auto* frustumPlanes = rendererCore->renderer3D.frustumPlanes.getAll();
|
||||
return bbox->clipIsInFrustum(frustumPlanes, block.model);
|
||||
}
|
||||
|
||||
void MinecraftPipeline::cull(McpipBlock* blocks,
|
||||
const std::vector<u32>& indexes,
|
||||
RendererCoreTextureBuffers* texBuffers,
|
||||
const bool& isMulti) {
|
||||
changeMode(McPipCull, false);
|
||||
|
||||
auto maxBlocksPerQBuffer = manager.culler.getMaxBlocksCountPerQBuffer();
|
||||
auto partsCount = static_cast<u32>(
|
||||
ceil(indexes.size() / static_cast<float>(maxBlocksPerQBuffer)));
|
||||
|
||||
for (u32 i = 0; i < partsCount; i++) {
|
||||
u32 subArraySize = i != partsCount - 1
|
||||
? maxBlocksPerQBuffer
|
||||
: indexes.size() - i * maxBlocksPerQBuffer;
|
||||
|
||||
McpipBlock** blockPointerArray = new McpipBlock*[subArraySize];
|
||||
u32 blockPointerArrayCount = 0;
|
||||
for (u32 j = 0; j < subArraySize; j++) {
|
||||
blockPointerArray[blockPointerArrayCount++] =
|
||||
&blocks[indexes[i * maxBlocksPerQBuffer + j]];
|
||||
}
|
||||
|
||||
manager.cull(blockPointerArray, blockPointerArrayCount, texBuffers,
|
||||
isMulti);
|
||||
|
||||
delete[] blockPointerArray;
|
||||
}
|
||||
}
|
||||
|
||||
// -- 2nd qbuff = 36 * 3 (ST,RGBA,STQ)
|
||||
// * 2 (We will have at least 2x more verts after clip)
|
||||
// + Set, lod, set, clut, prim = 221
|
||||
// -- 1st qbuff: 500 - 221 = 279
|
||||
// Tags: 279 - for example 20 = 259
|
||||
// Vert + ST from EE = 259 / 2 = 129 verts | OK!
|
||||
void MinecraftPipeline::clip(McpipBlock* blocks,
|
||||
const std::vector<u32>& indexes,
|
||||
RendererCoreTextureBuffers* texBuffers,
|
||||
const bool& isMulti) {
|
||||
changeMode(McPipAsIs, false);
|
||||
|
||||
for (u32 i = 0; i < indexes.size(); i++) {
|
||||
manager.clip(&blocks[indexes[i]], texBuffers, isMulti);
|
||||
}
|
||||
}
|
||||
|
||||
void MinecraftPipeline::changeMode(const McpipProgramName& requestedMode,
|
||||
const u8& force) {
|
||||
if (!force) {
|
||||
if (latestMode == requestedMode) return;
|
||||
}
|
||||
|
||||
if (requestedMode == McPipCull) {
|
||||
manager.culler.configureVU1AndSendStaticData();
|
||||
latestMode = McPipCull;
|
||||
} else {
|
||||
manager.clipper.configureVU1AndSendStaticData();
|
||||
latestMode = McPipAsIs;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,34 @@
|
||||
;//--------------------------------------------------------------------------------
|
||||
;// MinecraftPipeline cull macros library
|
||||
;//--------------------------------------------------------------------------------
|
||||
|
||||
;//---------------------------------------------------------
|
||||
;// LoadStaticData - Load lod, set and viewproj matrix
|
||||
;//---------------------------------------------------------
|
||||
#macro LoadStaticData: t_lod, t_set
|
||||
lq t_lod, VU1_MCPIP_AS_IS_STATIC_LOD(vi00)
|
||||
lq t_set, VU1_MCPIP_AS_IS_STATIC_SET_TAG(vi00)
|
||||
#endmacro
|
||||
|
||||
;//---------------------------------------------------------
|
||||
;// LoadDynamicData - Load scale, prim and clut
|
||||
;//---------------------------------------------------------
|
||||
#macro LoadDynamicData: t_scale, t_prim, t_clut, t_color, t_vertexCount, t_buffer
|
||||
lq t_scale, VU1_MCPIP_AS_IS_DYNAMIC_SCALE(t_buffer)
|
||||
lq t_prim, VU1_MCPIP_AS_IS_DYNAMIC_PRIM(t_buffer)
|
||||
lq t_clut, VU1_MCPIP_AS_IS_DYNAMIC_CLUT(t_buffer)
|
||||
lq t_color, VU1_MCPIP_AS_IS_DYNAMIC_COLOR(t_buffer)
|
||||
ilw.w t_vertexCount, VU1_MCPIP_AS_IS_DYNAMIC_SCALE(t_buffer)
|
||||
#endmacro
|
||||
|
||||
;//---------------------------------------------------------
|
||||
;// StoreTags - Store lod, prim, clut
|
||||
;//---------------------------------------------------------
|
||||
#macro StoreTags: t_lodTag, t_setTag, t_primTag, t_clut, t_destAddress
|
||||
sq t_setTag, 0(t_destAddress)
|
||||
sq t_lodTag, 1(t_destAddress)
|
||||
sq t_setTag, 2(t_destAddress)
|
||||
sq t_clut, 3(t_destAddress)
|
||||
sq t_primTag, 4(t_destAddress)
|
||||
iaddiu t_destAddress, t_destAddress, 5
|
||||
#endmacro
|
||||
@@ -0,0 +1,118 @@
|
||||
; ______ ____ ___
|
||||
; | \/ ____| |___|
|
||||
; | | | \ | |
|
||||
;---------------------------------------------------------------
|
||||
; Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
; Licenced under Apache License 2.0
|
||||
; Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
;
|
||||
;---------------------------------------------------------------
|
||||
; Super fast renderer of minecraft blocks.
|
||||
; Block data is statically allocated in vi00
|
||||
;
|
||||
; - Triangle list
|
||||
; - AsIs = NO TRANSFORM
|
||||
; - Colors
|
||||
;---------------------------------------------------------------
|
||||
|
||||
.syntax new
|
||||
.name VU1BlocksAsIs
|
||||
.vu
|
||||
.init_vf_all
|
||||
.init_vi_all
|
||||
|
||||
#include "src/renderer/core/paths/path1/programs/vcl_sml.i"
|
||||
#include "inc/renderer/3d/pipeline/minecraft/programs/as_is/mcpip_vu1_as_is_shared_defines.h"
|
||||
#include "src/renderer/3d/pipeline/minecraft/programs/as_is/macros.i"
|
||||
|
||||
#define STQ_STORE_OFFSET 0
|
||||
#define RGBA_STORE_OFFSET 1
|
||||
#define XYZ2_STORE_OFFSET 2
|
||||
|
||||
--enter
|
||||
--endenter
|
||||
|
||||
#vuprog VU1BlocksAsIs
|
||||
|
||||
LoadStaticData{ lodTag, setTag }
|
||||
|
||||
begin:
|
||||
|
||||
xtop buffer
|
||||
LoadDynamicData{ scale, primTag, clut, color, vertexCount, buffer }
|
||||
|
||||
iaddiu vertexData, buffer, VU1_MCPIP_AS_IS_DYNAMIC_VERTEX_DATA_ADDR
|
||||
iadd stqData, vertexData, vertexCount
|
||||
iadd destAddress, stqData, vertexCount
|
||||
iadd kickAddress, stqData, vertexCount
|
||||
|
||||
StoreTags{ lodTag, setTag, primTag, clut, destAddress }
|
||||
FixColor{ color }
|
||||
|
||||
;--- Loop
|
||||
iadd vertexCounter, buffer, vertexCount
|
||||
vertexLoop:
|
||||
|
||||
;--- Load vertex1
|
||||
lq vertex1, (vertexData)
|
||||
lq stq1, (stqData)
|
||||
|
||||
;--- Load vertex2
|
||||
lq vertex2, 1(vertexData)
|
||||
lq stq2, 1(stqData)
|
||||
|
||||
;--- Load vertex3
|
||||
lq vertex3, 2(vertexData)
|
||||
lq stq3, 2(stqData)
|
||||
|
||||
;--- Calculate vertex1
|
||||
ScaleVertexToGSFormat{ scale, vertex1 }
|
||||
div q, vf00[w], vertex1[w]
|
||||
PerformTexturePerspectiveCorrection{ outputStq1, stq1 }
|
||||
|
||||
;--- Calculate vertex2
|
||||
ScaleVertexToGSFormat{ scale, vertex2 }
|
||||
div q, vf00[w], vertex2[w]
|
||||
PerformTexturePerspectiveCorrection{ outputStq2, stq2 }
|
||||
|
||||
;--- Calculate vertex3
|
||||
ScaleVertexToGSFormat{ scale, vertex3 }
|
||||
div q, vf00[w], vertex3[w]
|
||||
PerformTexturePerspectiveCorrection{ outputStq3, stq3 }
|
||||
|
||||
;--- Store vertex1
|
||||
sq outputStq1, STQ_STORE_OFFSET(destAddress)
|
||||
sq color, RGBA_STORE_OFFSET(destAddress)
|
||||
sq.xyz vertex1, XYZ2_STORE_OFFSET(destAddress)
|
||||
|
||||
;--- Store vertex2
|
||||
sq outputStq2, STQ_STORE_OFFSET+3(destAddress)
|
||||
sq color, RGBA_STORE_OFFSET+3(destAddress)
|
||||
sq.xyz vertex2, XYZ2_STORE_OFFSET+3(destAddress)
|
||||
|
||||
;--- Store vertex3
|
||||
sq outputStq3, STQ_STORE_OFFSET+6(destAddress)
|
||||
sq color, RGBA_STORE_OFFSET+6(destAddress)
|
||||
sq.xyz vertex3, XYZ2_STORE_OFFSET+6(destAddress)
|
||||
|
||||
;-------------------------------
|
||||
|
||||
iaddiu vertexData, vertexData, 3
|
||||
iaddiu stqData, stqData, 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
|
||||
@@ -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/minecraft/programs/as_is/mcpip_as_is_vu1_program.hpp"
|
||||
|
||||
extern u32 VU1BlocksAsIs_CodeStart __attribute__((section(".vudata")));
|
||||
extern u32 VU1BlocksAsIs_CodeEnd __attribute__((section(".vudata")));
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
McpipAsIsVU1Program::McpipAsIsVU1Program()
|
||||
: McpipProgram(McpipProgramName::McPipAsIs, &VU1BlocksAsIs_CodeStart,
|
||||
&VU1BlocksAsIs_CodeEnd) {}
|
||||
|
||||
McpipAsIsVU1Program::~McpipAsIsVU1Program() {}
|
||||
|
||||
std::string McpipAsIsVU1Program::getStringName() const {
|
||||
return std::string("As is");
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# 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/minecraft/programs/as_is/mcpip_clip.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
McpipClip::McpipClip() {
|
||||
staticPacket = packet2_create(8, P2_TYPE_NORMAL, P2_MODE_CHAIN, true);
|
||||
algoSettings.lerpColors = false;
|
||||
algoSettings.lerpTexCoords = true;
|
||||
algoSettings.lerpNormals = false;
|
||||
}
|
||||
|
||||
McpipClip::~McpipClip() { packet2_free(staticPacket); }
|
||||
|
||||
void McpipClip::init(RendererCore* core, McpipBlockData* t_singleBlockData,
|
||||
McpipBlockData* t_multiBlockData) {
|
||||
singleBlockData = t_singleBlockData;
|
||||
multiBlockData = t_multiBlockData;
|
||||
rendererCore = core;
|
||||
algorithm.init(rendererCore->getSettings());
|
||||
setDBufferSize();
|
||||
initStaticPacket();
|
||||
}
|
||||
|
||||
u32 McpipClip::uploadVU1Program(McpipProgramsRepository* repo,
|
||||
const u32& addr) {
|
||||
auto* program = repo->getProgram(McpipProgramName::McPipAsIs);
|
||||
return rendererCore->renderer3D.uploadVU1Program(program, addr);
|
||||
}
|
||||
|
||||
void McpipClip::configureVU1AndSendStaticData() {
|
||||
u16 start = VU1_MCPIP_AS_IS_STATIC_LAST_DATA_ADDR + 1;
|
||||
rendererCore->renderer3D.setVU1DoubleBuffers(start, vu1DBufferSize);
|
||||
sendVU1StaticData();
|
||||
}
|
||||
|
||||
void McpipClip::initStaticPacket() {
|
||||
packet2_utils_vu_open_unpack(staticPacket, VU1_MCPIP_AS_IS_STATIC_LOD, false);
|
||||
{
|
||||
packet2_utils_gs_add_lod(staticPacket, &rendererCore->gs.lod);
|
||||
packet2_utils_gif_add_set(staticPacket, 1);
|
||||
}
|
||||
packet2_utils_vu_close_unpack(staticPacket);
|
||||
|
||||
packet2_utils_vu_add_end_tag(staticPacket);
|
||||
}
|
||||
|
||||
void McpipClip::addData(McpipBlock* block, const bool& isMulti,
|
||||
RendererCoreTextureBuffers* texBuffers,
|
||||
packet2_t* packet, const u8& context) {
|
||||
std::vector<Path1ClipVertex> clippedVertices;
|
||||
auto mvp = rendererCore->renderer3D.getViewProj() * block->model;
|
||||
|
||||
const auto* blockData = isMulti ? multiBlockData : singleBlockData;
|
||||
|
||||
for (u32 i = 0; i < blockData->count / 3; i++) {
|
||||
for (u8 j = 0; j < 3; j++) {
|
||||
Path1ClipVertex vert = {mvp * blockData->vertices[i * 3 + j], Vec4(),
|
||||
blockData->textureCoords[i * 3 + j], Vec4()};
|
||||
|
||||
inputTriangle.push_back(vert);
|
||||
}
|
||||
|
||||
clippedTriangle.clear();
|
||||
|
||||
algorithm.clip(&clippedTriangle, inputTriangle, algoSettings);
|
||||
|
||||
inputTriangle.clear();
|
||||
|
||||
if (clippedTriangle.size() == 0) continue;
|
||||
|
||||
auto va = clippedTriangle.at(0);
|
||||
for (u32 j = 1; j <= clippedTriangle.size() - 2; j++) {
|
||||
auto vb = clippedTriangle.at(j);
|
||||
auto vc = clippedTriangle.at((j + 1) % clippedTriangle.size());
|
||||
clippedVertices.push_back(va);
|
||||
clippedVertices.push_back(vb);
|
||||
clippedVertices.push_back(vc);
|
||||
}
|
||||
}
|
||||
|
||||
addCorrections(&clippedVertices, block);
|
||||
moveDataToBuffer(&clippedVertices, context);
|
||||
addDataToPacket(packet, context, block, clippedVertices.size(), texBuffers);
|
||||
}
|
||||
|
||||
void McpipClip::addCorrections(std::vector<Path1ClipVertex>* vertices,
|
||||
McpipBlock* block) {
|
||||
for (u32 i = 0; i < vertices->size(); i++) {
|
||||
(*vertices)[i].position /= (*vertices)[i].position.w; // Perspective divide
|
||||
(*vertices)[i].st += block->textureOffset; // Texture offset
|
||||
}
|
||||
}
|
||||
|
||||
void McpipClip::moveDataToBuffer(std::vector<Path1ClipVertex>* vertices,
|
||||
const u8& context) {
|
||||
for (u32 i = 0; i < vertices->size(); i++) {
|
||||
vertexBuffers[context][i].set(vertices->at(i).position);
|
||||
texCoordBuffers[context][i].set(vertices->at(i).st);
|
||||
}
|
||||
}
|
||||
|
||||
void McpipClip::addDataToPacket(packet2_t* packet, const u8& context,
|
||||
McpipBlock* block, const int& count,
|
||||
RendererCoreTextureBuffers* texBuffers) {
|
||||
packet2_reset(packet, false);
|
||||
|
||||
rendererCore->texture.updateClutBuffer(texBuffers->clut);
|
||||
|
||||
packet2_utils_vu_open_unpack(packet, VU1_MCPIP_AS_IS_DYNAMIC_SCALE, 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_s32(packet, count); // vertex count
|
||||
|
||||
packet2_utils_gs_add_prim_giftag(packet, &rendererCore->gs.prim, count,
|
||||
((u64)GIF_REG_ST) << 0 |
|
||||
((u64)GIF_REG_RGBAQ) << 4 |
|
||||
((u64)GIF_REG_XYZ2) << 8,
|
||||
3, 0);
|
||||
|
||||
packet2_utils_gs_add_texbuff_clut(packet, texBuffers->core,
|
||||
&rendererCore->texture.clut);
|
||||
|
||||
Packet2TyraUtils::addColor(packet, block->color);
|
||||
}
|
||||
packet2_utils_vu_close_unpack(packet);
|
||||
|
||||
u32 addr = VU1_MCPIP_AS_IS_DYNAMIC_VERTEX_DATA_ADDR;
|
||||
|
||||
packet2_utils_vu_add_unpack_data(packet, addr, vertexBuffers[context], count,
|
||||
true);
|
||||
addr += count;
|
||||
|
||||
packet2_utils_vu_add_unpack_data(packet, addr, texCoordBuffers[context],
|
||||
count, true);
|
||||
}
|
||||
|
||||
void McpipClip::setDBufferSize() {
|
||||
vu1DBufferSize = 1000; // VU1 mem size
|
||||
vu1DBufferSize -= VU1_MCPIP_AS_IS_STATIC_LAST_DATA_ADDR; // static data
|
||||
vu1DBufferSize -= 1;
|
||||
vu1DBufferSize /= 2; // xtop double buffer
|
||||
}
|
||||
|
||||
void McpipClip::sendVU1StaticData() {
|
||||
dma_channel_wait(DMA_CHANNEL_VIF1, 0);
|
||||
dma_channel_send_packet2(staticPacket, DMA_CHANNEL_VIF1, true);
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,93 @@
|
||||
;//--------------------------------------------------------------------------------
|
||||
;// MinecraftPipeline cull macros library
|
||||
;//--------------------------------------------------------------------------------
|
||||
|
||||
;//---------------------------------------------------------
|
||||
;// StoreBlockizerStaticData - Load and store lod, clut and prim.
|
||||
;// Push dest address by 5 qwords
|
||||
;//---------------------------------------------------------
|
||||
#macro StoreBlockizerLodClutTexPrim: t_destAddr, t_clutTex
|
||||
lq setTag, VU1_MCPIP_CULL_STATIC_SET_TAG(vi00)
|
||||
lq lodTag, VU1_MCPIP_CULL_STATIC_LOD(vi00)
|
||||
sq setTag, 0(t_destAddr)
|
||||
sq lodTag, 1(t_destAddr)
|
||||
sq setTag, 2(t_destAddr)
|
||||
sq t_clutTex, 3(t_destAddr)
|
||||
lq primTag, VU1_MCPIP_CULL_STATIC_PRIM(vi00)
|
||||
sq primTag, 4(t_destAddr)
|
||||
iaddiu t_destAddr, t_destAddr, 5
|
||||
#endmacro
|
||||
|
||||
;//---------------------------------------------------------
|
||||
;// GetDestinationAddress - Load VU1 options and check
|
||||
;// in which double buffer we are. If 0, return first double buff
|
||||
;// if 1, return second double buffer.
|
||||
;// Also toggle VU1 dbuff option, so next call of this macro will result
|
||||
;// opposite buffer.
|
||||
;//---------------------------------------------------------
|
||||
#macro GetDestinationAddress: t_destAddr, t_kickAddr
|
||||
ilw.w static1, VU1_MCPIP_CULL_STATIC_VU1_OPTIONS(vi00)
|
||||
ilw.x currDBufferOffset, VU1_MCPIP_CULL_STATIC_VU1_OPTIONS(vi00)
|
||||
ibgtz currDBufferOffset, get_dest_addr_second
|
||||
|
||||
get_dest_addr_first:
|
||||
iaddiu t_destAddr, vi00, VU1_MCPIP_CULL_DYNAMIC_OUTPUT_DOUBLE_BUFF1_ADDR
|
||||
isw.x static1, VU1_MCPIP_CULL_STATIC_VU1_OPTIONS(vi00)
|
||||
b get_dest_addr_finish
|
||||
|
||||
get_dest_addr_second:
|
||||
iaddiu t_destAddr, vi00, VU1_MCPIP_CULL_DYNAMIC_OUTPUT_DOUBLE_BUFF2_ADDR
|
||||
isw.x vi00, VU1_MCPIP_CULL_STATIC_VU1_OPTIONS(vi00)
|
||||
|
||||
get_dest_addr_finish:
|
||||
iaddiu t_kickAddr, t_destAddr, 0
|
||||
#endmacro
|
||||
|
||||
;//---------------------------------------------------------
|
||||
;// LoadScaleAndBlocksCount - Load scale vec3 and blocks count
|
||||
;// from w component
|
||||
;//---------------------------------------------------------
|
||||
#macro LoadBufferDynamicData: t_buffer, t_scale, t_clutTex, t_blocksCount, t_viewProj
|
||||
lq.xyz t_scale, VU1_MCPIP_CULL_DYNAMIC_SCALE_AND_BLOCKS_COUNT_ADDR(t_buffer)
|
||||
ilw.w t_blocksCount, VU1_MCPIP_CULL_DYNAMIC_SCALE_AND_BLOCKS_COUNT_ADDR(t_buffer)
|
||||
lq t_clutTex, VU1_MCPIP_CULL_DYNAMIC_CLUT_TEX(t_buffer)
|
||||
lq t_viewProj[0], 0+VU1_MCPIP_CULL_DYNAMIC_VIEW_PROJ_MATRIX_ADDR(t_buffer)
|
||||
lq t_viewProj[1], 1+VU1_MCPIP_CULL_DYNAMIC_VIEW_PROJ_MATRIX_ADDR(t_buffer)
|
||||
lq t_viewProj[2], 2+VU1_MCPIP_CULL_DYNAMIC_VIEW_PROJ_MATRIX_ADDR(t_buffer)
|
||||
lq t_viewProj[3], 3+VU1_MCPIP_CULL_DYNAMIC_VIEW_PROJ_MATRIX_ADDR(t_buffer)
|
||||
#endmacro
|
||||
|
||||
;//---------------------------------------------------------
|
||||
;// GetVertAndStData - Get static vertex data and tex coords
|
||||
;//---------------------------------------------------------
|
||||
#macro GetVertAndStData: t_vertData, t_stData
|
||||
iaddiu t_vertData, vi00, VU1_MCPIP_CULL_STATIC_VERTEX_DATA
|
||||
iaddiu t_stData, vi00, VU1_MCPIP_CULL_STATIC_TEX_COORD_DATA
|
||||
#endmacro
|
||||
|
||||
;//---------------------------------------------------------
|
||||
;// GetBlockData - Get mvp matrix, color, st offset for single block
|
||||
;//---------------------------------------------------------
|
||||
#macro GetBlockData: t_blockData, t_model, t_color, t_stOffset
|
||||
lq t_model[0], 0(t_blockData)
|
||||
lq t_model[1], 1(t_blockData)
|
||||
lq t_model[2], 2(t_blockData)
|
||||
lq t_model[3], 3(t_blockData)
|
||||
lq t_color, 4(t_blockData)
|
||||
lq t_stOffset, 5(t_blockData)
|
||||
#endmacro
|
||||
|
||||
;//---------------------------------------------------------
|
||||
;// GetVertexData - Get vertex and tex coord
|
||||
;//---------------------------------------------------------
|
||||
#macro GetVertexData: t_vertData, t_stqData, t_vertex, t_stq, t_offset
|
||||
lq t_vertex, t_offset(t_vertData)
|
||||
lq t_stq, t_offset(t_stqData)
|
||||
#endmacro
|
||||
|
||||
;//---------------------------------------------------------
|
||||
;// GetVertexData - Get vertex and tex coord
|
||||
;//---------------------------------------------------------
|
||||
#macro AddSTOffset: t_stq, t_stqOffset
|
||||
add t_stq, t_stq, t_stqOffset
|
||||
#endmacro
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# 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/minecraft/programs/cull/mcpip_cull.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
McpipCull::McpipCull() {
|
||||
staticPacket = packet2_create(8, P2_TYPE_NORMAL, P2_MODE_CHAIN, true);
|
||||
}
|
||||
|
||||
McpipCull::~McpipCull() { packet2_free(staticPacket); }
|
||||
|
||||
void McpipCull::init(RendererCore* core, McpipBlockData* t_blockData) {
|
||||
blockData = t_blockData;
|
||||
rendererCore = core;
|
||||
initStaticPacket();
|
||||
setDBufferSize();
|
||||
}
|
||||
|
||||
void McpipCull::setDBufferSize() {
|
||||
vu1DBufferSize = 1000; // VU1 mem size
|
||||
vu1DBufferSize -= VU1_MCPIP_CULL_STATIC_LAST_DATA_ADDR; // static data
|
||||
|
||||
// Our additional, mini output double buffer at the bottom of VU1 mem
|
||||
u16 miniOutputDoubleBufferSize =
|
||||
blockData->count * 3 +
|
||||
5; // 36 * (ST, XYZ2, RGBAQ) + Set, lod, set, clut, prim
|
||||
|
||||
vu1DBufferSize -= miniOutputDoubleBufferSize; // First
|
||||
vu1DBufferSize -= miniOutputDoubleBufferSize; // Second
|
||||
|
||||
TYRA_ASSERT(1000 - (miniOutputDoubleBufferSize * 2) ==
|
||||
VU1_MCPIP_CULL_DYNAMIC_OUTPUT_DOUBLE_BUFF1_ADDR,
|
||||
"There is mismatch in output dbuffer1 size. Should be: ",
|
||||
1000 - (miniOutputDoubleBufferSize * 2),
|
||||
"but is: ", VU1_MCPIP_CULL_DYNAMIC_OUTPUT_DOUBLE_BUFF1_ADDR);
|
||||
|
||||
TYRA_ASSERT(1000 - miniOutputDoubleBufferSize ==
|
||||
VU1_MCPIP_CULL_DYNAMIC_OUTPUT_DOUBLE_BUFF2_ADDR,
|
||||
"There is mismatch in output dbuffer2 size. Should be: ",
|
||||
1000 - miniOutputDoubleBufferSize,
|
||||
"but is: ", VU1_MCPIP_CULL_DYNAMIC_OUTPUT_DOUBLE_BUFF2_ADDR);
|
||||
|
||||
vu1DBufferSize /= 2; // xtop double buffer
|
||||
}
|
||||
|
||||
u32 McpipCull::uploadVU1Program(McpipProgramsRepository* repo,
|
||||
const u32& addr) {
|
||||
auto* program = repo->getProgram(McpipProgramName::McPipCull);
|
||||
return rendererCore->renderer3D.uploadVU1Program(program, addr);
|
||||
}
|
||||
|
||||
void McpipCull::configureVU1AndSendStaticData() {
|
||||
rendererCore->renderer3D.setVU1DoubleBuffers(
|
||||
VU1_MCPIP_CULL_STATIC_LAST_DATA_ADDR, vu1DBufferSize);
|
||||
|
||||
sendVU1StaticData();
|
||||
}
|
||||
|
||||
u32 McpipCull::getMaxBlocksCountPerQBuffer() const {
|
||||
u32 result = vu1DBufferSize;
|
||||
result -= 1; // VU1_MCPIP_CULL_DYNAMIC_SCALE_AND_BLOCKS_COUNT;
|
||||
result -= 1; // Lod tag
|
||||
result -= 4; // View proj
|
||||
|
||||
result /= VU1_MCPIP_CULL_QWORDS_PER_BLOCK;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void McpipCull::initStaticPacket() {
|
||||
packet2_utils_vu_open_unpack(staticPacket, VU1_MCPIP_CULL_STATIC_LOD, false);
|
||||
{
|
||||
packet2_utils_gs_add_lod(staticPacket, &rendererCore->gs.lod);
|
||||
|
||||
packet2_utils_gs_add_prim_giftag(staticPacket, &rendererCore->gs.prim, 36,
|
||||
((u64)GIF_REG_ST) << 0 |
|
||||
((u64)GIF_REG_RGBAQ) << 4 |
|
||||
((u64)GIF_REG_XYZ2) << 8,
|
||||
3, 0);
|
||||
packet2_utils_gif_add_set(staticPacket, 1);
|
||||
|
||||
packet2_add_u32(staticPacket, 0); // Param1 - Mini double buffer switcher
|
||||
packet2_add_u32(staticPacket, 0);
|
||||
packet2_add_u32(staticPacket, 0);
|
||||
packet2_add_u32(staticPacket,
|
||||
1); // static 1 - used in VU1's GetDestinationAddress{}
|
||||
}
|
||||
packet2_utils_vu_close_unpack(staticPacket);
|
||||
|
||||
packet2_utils_vu_add_end_tag(staticPacket);
|
||||
}
|
||||
|
||||
void McpipCull::sendVU1StaticData() {
|
||||
dma_channel_wait(DMA_CHANNEL_VIF1, 0);
|
||||
dma_channel_send_packet2(staticPacket, DMA_CHANNEL_VIF1, true);
|
||||
}
|
||||
|
||||
void McpipCull::addData(packet2_t* packet, McpipBlock** blockPointerArray,
|
||||
u32 blockPointerArrayCount,
|
||||
RendererCoreTextureBuffers* texBuffers, bool isMulti) {
|
||||
packet2_reset(packet, false);
|
||||
|
||||
rendererCore->texture.updateClutBuffer(texBuffers->clut);
|
||||
|
||||
packet2_utils_vu_open_unpack(
|
||||
packet, VU1_MCPIP_CULL_DYNAMIC_SCALE_AND_BLOCKS_COUNT_ADDR, 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, blockPointerArrayCount); // blocks count
|
||||
|
||||
packet2_utils_gs_add_texbuff_clut(packet, texBuffers->core,
|
||||
&rendererCore->texture.clut);
|
||||
|
||||
Packet2TyraUtils::addM4x4(packet, rendererCore->renderer3D.getViewProj());
|
||||
}
|
||||
packet2_utils_vu_close_unpack(packet);
|
||||
|
||||
u32 addr = VU1_MCPIP_CULL_DYNAMIC_BLOCKS_DATA;
|
||||
|
||||
for (u32 i = 0; i < blockPointerArrayCount; i++) {
|
||||
packet2_utils_vu_add_unpack_data(packet, addr, blockPointerArray[i],
|
||||
VU1_MCPIP_CULL_QWORDS_PER_BLOCK, true);
|
||||
addr += VU1_MCPIP_CULL_QWORDS_PER_BLOCK;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,129 @@
|
||||
; ______ ____ ___
|
||||
; | \/ ____| |___|
|
||||
; | | | \ | |
|
||||
;---------------------------------------------------------------
|
||||
; Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
; Licenced under Apache License 2.0
|
||||
; Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
;
|
||||
;---------------------------------------------------------------
|
||||
; Super fast renderer of minecraft blocks.
|
||||
; Block data is statically allocated in vi00
|
||||
;
|
||||
; - Triangle list
|
||||
; - Cull = transform
|
||||
; - Colors
|
||||
;---------------------------------------------------------------
|
||||
|
||||
.syntax new
|
||||
.name VU1BlocksCull
|
||||
.vu
|
||||
.init_vf_all
|
||||
.init_vi_all
|
||||
|
||||
#include "src/renderer/core/paths/path1/programs/vcl_sml.i"
|
||||
#include "inc/renderer/3d/pipeline/minecraft/programs/cull/mcpip_vu1_cull_shared_defines.h"
|
||||
#include "src/renderer/3d/pipeline/minecraft/programs/cull/macros.i"
|
||||
|
||||
#define STQ_STORE_OFFSET 0
|
||||
#define RGBA_STORE_OFFSET 1
|
||||
#define XYZ2_STORE_OFFSET 2
|
||||
|
||||
--enter
|
||||
--endenter
|
||||
|
||||
#vuprog VU1BlocksCull
|
||||
|
||||
GetVertAndStData{ staticVertexData, staticStqData }
|
||||
ResetClipFlags{ }
|
||||
|
||||
begin:
|
||||
|
||||
xtop buffer
|
||||
iaddiu blockData, buffer, VU1_MCPIP_CULL_DYNAMIC_BLOCKS_DATA
|
||||
LoadBufferDynamicData{ buffer, scale, clutTex, blocksCount, viewProj }
|
||||
|
||||
;--- Loop
|
||||
iadd blockCounter, buffer, blocksCount
|
||||
|
||||
blocksLoop:
|
||||
|
||||
GetBlockData{ blockData, model, color, stOffset }
|
||||
MatrixMultiply{ mvp, model, viewProj }
|
||||
FixColor{ color }
|
||||
GetDestinationAddress{ destAddress, kickAddress }
|
||||
StoreBlockizerLodClutTexPrim{ destAddress, clutTex }
|
||||
iaddiu vertexData, staticVertexData, 0
|
||||
iaddiu stqData, staticStqData, 0
|
||||
|
||||
iaddiu vertexCounter, buffer, VU1_MCPIP_CULL_VERTEX_COUNT
|
||||
vertexLoop:
|
||||
|
||||
GetVertexData{ vertexData, stqData, vertex1, stq1, 0 }
|
||||
GetVertexData{ vertexData, stqData, vertex2, stq2, 1 }
|
||||
GetVertexData{ vertexData, stqData, vertex3, stq3, 2 }
|
||||
|
||||
;--- Calculate vertex1
|
||||
MatrixMultiplyVertex{ vertex1, mvp, vertex1 }
|
||||
PerformClipCheck{ vertex1, destAddress, XYZ2_STORE_OFFSET }
|
||||
VertexPersCorr{ vertex1, vertex1 }
|
||||
ScaleVertexToGSFormat{ scale, vertex1 }
|
||||
AddSTOffset{ stq1, stOffset }
|
||||
PerformTexturePerspectiveCorrection{ outputStq1, stq1 }
|
||||
|
||||
;--- Calculate vertex2
|
||||
MatrixMultiplyVertex{ vertex2, mvp, vertex2 }
|
||||
PerformClipCheck{ vertex2, destAddress, XYZ2_STORE_OFFSET+3 }
|
||||
VertexPersCorr{ vertex2, vertex2 }
|
||||
ScaleVertexToGSFormat{ scale, vertex2 }
|
||||
AddSTOffset{ stq2, stOffset }
|
||||
PerformTexturePerspectiveCorrection{ outputStq2, stq2 }
|
||||
|
||||
;--- Calculate vertex3
|
||||
MatrixMultiplyVertex{ vertex3, mvp, vertex3 }
|
||||
PerformClipCheck{ vertex3, destAddress, XYZ2_STORE_OFFSET+6 }
|
||||
VertexPersCorr{ vertex3, vertex3 }
|
||||
ScaleVertexToGSFormat{ scale, vertex3 }
|
||||
AddSTOffset{ stq3, stOffset }
|
||||
PerformTexturePerspectiveCorrection{ outputStq3, stq3 }
|
||||
|
||||
;--- Store vertex1
|
||||
sq outputStq1, STQ_STORE_OFFSET(destAddress)
|
||||
sq color, RGBA_STORE_OFFSET(destAddress)
|
||||
sq.xyz vertex1, XYZ2_STORE_OFFSET(destAddress)
|
||||
|
||||
;--- Store vertex2
|
||||
sq outputStq2, STQ_STORE_OFFSET+3(destAddress)
|
||||
sq color, RGBA_STORE_OFFSET+3(destAddress)
|
||||
sq.xyz vertex2, XYZ2_STORE_OFFSET+3(destAddress)
|
||||
|
||||
;--- Store vertex3
|
||||
sq outputStq3, STQ_STORE_OFFSET+6(destAddress)
|
||||
sq color, RGBA_STORE_OFFSET+6(destAddress)
|
||||
sq.xyz vertex3, XYZ2_STORE_OFFSET+6(destAddress)
|
||||
|
||||
iaddiu vertexData, vertexData, 3
|
||||
iaddiu stqData, stqData, 3
|
||||
iaddiu destAddress, destAddress, 9
|
||||
|
||||
iaddi vertexCounter, vertexCounter, -3
|
||||
ibne vertexCounter, buffer, vertexLoop
|
||||
; End of vertex loop
|
||||
|
||||
--barrier
|
||||
|
||||
xgkick kickAddress
|
||||
|
||||
iaddiu blockData, blockData, VU1_MCPIP_CULL_QWORDS_PER_BLOCK
|
||||
iaddi blockCounter, blockCounter, -1
|
||||
ibne blockCounter, buffer, blocksLoop
|
||||
; End of block loop
|
||||
|
||||
--cont
|
||||
|
||||
b begin
|
||||
|
||||
#endvuprog
|
||||
|
||||
--exit
|
||||
--endexit
|
||||
@@ -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/minecraft/programs/cull/mcpip_cull_vu1_program.hpp"
|
||||
|
||||
extern u32 VU1BlocksCull_CodeStart __attribute__((section(".vudata")));
|
||||
extern u32 VU1BlocksCull_CodeEnd __attribute__((section(".vudata")));
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
McpipCullVU1Program::McpipCullVU1Program()
|
||||
: McpipProgram(McpipProgramName::McPipCull, &VU1BlocksCull_CodeStart,
|
||||
&VU1BlocksCull_CodeEnd) {}
|
||||
|
||||
McpipCullVU1Program::~McpipCullVU1Program() {}
|
||||
|
||||
std::string McpipCullVU1Program::getStringName() const {
|
||||
return std::string("Cull");
|
||||
}
|
||||
|
||||
} // 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>
|
||||
*/
|
||||
|
||||
#include "renderer/3d/pipeline/minecraft/programs/mcpip_program.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
McpipProgram::McpipProgram(const McpipProgramName& t_name, u32* t_start,
|
||||
u32* t_end)
|
||||
: VU1Program(t_start, t_end), name(t_name) {}
|
||||
|
||||
McpipProgram::~McpipProgram() {}
|
||||
|
||||
const McpipProgramName& McpipProgram::getName() const { return name; }
|
||||
|
||||
} // 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>
|
||||
*/
|
||||
|
||||
#include "renderer/3d/pipeline/minecraft/programs/mcpip_programs_manager.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
BlockizerProgramsManager::BlockizerProgramsManager() {
|
||||
lastProgramName = UndefinedMcpipProgram;
|
||||
context = 0;
|
||||
vu1BlockData = BlockNotUploaded;
|
||||
dynamicPackets[0] = packet2_create(100, P2_TYPE_NORMAL, P2_MODE_CHAIN, true);
|
||||
dynamicPackets[1] = packet2_create(100, P2_TYPE_NORMAL, P2_MODE_CHAIN, true);
|
||||
staticPacket = packet2_create(2, P2_TYPE_NORMAL, P2_MODE_CHAIN, true);
|
||||
setProgramsCache();
|
||||
}
|
||||
|
||||
BlockizerProgramsManager::~BlockizerProgramsManager() {
|
||||
packet2_free(dynamicPackets[0]);
|
||||
packet2_free(dynamicPackets[1]);
|
||||
packet2_free(staticPacket);
|
||||
packet2_free(programsPacket);
|
||||
}
|
||||
|
||||
void BlockizerProgramsManager::init(RendererCore* core) {
|
||||
culler.init(core, &singleTexBlockData);
|
||||
clipper.init(core, &singleTexBlockData, &multiTexBlockData);
|
||||
}
|
||||
|
||||
void BlockizerProgramsManager::setProgramsCache() {
|
||||
VU1Program** programs = new VU1Program*[2];
|
||||
programs[0] = repo.getProgram(McpipProgramName::McPipCull);
|
||||
programs[1] = repo.getProgram(McpipProgramName::McPipAsIs);
|
||||
programsPacket =
|
||||
renderer->core.getPath1()->createProgramsCache(programs, 2, 0);
|
||||
delete[] programs;
|
||||
}
|
||||
|
||||
void BlockizerProgramsManager::uploadVU1Programs() {
|
||||
dma_channel_wait(DMA_CHANNEL_VIF1, 0);
|
||||
dma_channel_send_packet2(programsPacket, DMA_CHANNEL_VIF1, true);
|
||||
dma_channel_wait(DMA_CHANNEL_VIF1, 0);
|
||||
lastProgramName = UndefinedMcpipProgram;
|
||||
vu1BlockData = BlockNotUploaded;
|
||||
}
|
||||
|
||||
void BlockizerProgramsManager::uploadBlock(bool isMulti) {
|
||||
if (vu1BlockData != BlockNotUploaded) {
|
||||
if (isMulti && vu1BlockData == BlockMultiUploaded) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (!isMulti && vu1BlockData == BlockSingleUploaded) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
packet2_reset(staticPacket, false);
|
||||
|
||||
const McpipBlockData& blockData =
|
||||
isMulti ? static_cast<McpipBlockData>(multiTexBlockData)
|
||||
: static_cast<McpipBlockData>(singleTexBlockData);
|
||||
|
||||
packet2_utils_vu_add_unpack_data(
|
||||
staticPacket, VU1_MCPIP_CULL_STATIC_VERTEX_DATA, blockData.comboData,
|
||||
blockData.getComboCount(), false);
|
||||
|
||||
packet2_utils_vu_add_end_tag(staticPacket);
|
||||
|
||||
vu1BlockData = isMulti ? BlockMultiUploaded : BlockSingleUploaded;
|
||||
dma_channel_wait(DMA_CHANNEL_VIF1, 0);
|
||||
dma_channel_send_packet2(staticPacket, DMA_CHANNEL_VIF1, true);
|
||||
}
|
||||
|
||||
void BlockizerProgramsManager::cull(McpipBlock** blockPointerArray,
|
||||
u32 blockPointerArrayCount,
|
||||
RendererCoreTextureBuffers* texBuffers,
|
||||
const bool& isMulti) {
|
||||
uploadBlock(isMulti);
|
||||
|
||||
auto* currentPacket = dynamicPackets[context];
|
||||
|
||||
auto* program = repo.getProgram(McpipProgramName::McPipCull);
|
||||
|
||||
culler.addData(currentPacket, blockPointerArray, blockPointerArrayCount,
|
||||
texBuffers, isMulti);
|
||||
|
||||
sendPacket(program);
|
||||
}
|
||||
|
||||
void BlockizerProgramsManager::clip(McpipBlock* block,
|
||||
RendererCoreTextureBuffers* texBuffers,
|
||||
const bool& isMulti) {
|
||||
vu1BlockData = BlockNotUploaded;
|
||||
|
||||
auto* currentPacket = dynamicPackets[context];
|
||||
|
||||
auto* program = repo.getProgram(McpipProgramName::McPipAsIs);
|
||||
|
||||
clipper.addData(block, isMulti, texBuffers, currentPacket, context);
|
||||
|
||||
sendPacket(program);
|
||||
}
|
||||
|
||||
void BlockizerProgramsManager::sendPacket(McpipProgram* program) {
|
||||
auto* currentPacket = dynamicPackets[context];
|
||||
|
||||
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);
|
||||
|
||||
dma_channel_wait(DMA_CHANNEL_VIF1, 0);
|
||||
dma_channel_send_packet2(currentPacket, DMA_CHANNEL_VIF1, true);
|
||||
context = !context;
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -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>
|
||||
*/
|
||||
|
||||
#include "renderer/3d/pipeline/minecraft/programs/mcpip_programs_repository.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
McpipProgramsRepository::McpipProgramsRepository() {}
|
||||
|
||||
McpipProgramsRepository::~McpipProgramsRepository() {}
|
||||
|
||||
McpipProgram* McpipProgramsRepository::getProgram(
|
||||
const McpipProgramName& name) {
|
||||
switch (name) {
|
||||
case McpipProgramName::McPipCull:
|
||||
return &cull;
|
||||
case McpipProgramName::McPipAsIs:
|
||||
return &asIs;
|
||||
|
||||
default:
|
||||
TYRA_TRAP("Unknown VU1 program name");
|
||||
return &cull;
|
||||
}
|
||||
}
|
||||
|
||||
} // 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>
|
||||
*/
|
||||
|
||||
#include <tamtypes.h>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include "renderer/3d/pipeline/std/core/bag/packaging/stdpip_bag_package.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
StdpipBagPackage::StdpipBagPackage() {
|
||||
size = 0;
|
||||
bag = nullptr;
|
||||
vertices = nullptr;
|
||||
sts = nullptr;
|
||||
normals = nullptr;
|
||||
colors = nullptr;
|
||||
}
|
||||
StdpipBagPackage::~StdpipBagPackage() {}
|
||||
|
||||
void StdpipBagPackage::print() const {
|
||||
auto text = getPrint(nullptr);
|
||||
printf("%s\n", text.c_str());
|
||||
}
|
||||
|
||||
void StdpipBagPackage::print(const char* name) const {
|
||||
auto text = getPrint(name);
|
||||
printf("%s\n", text.c_str());
|
||||
}
|
||||
|
||||
std::string StdpipBagPackage::getPrint(const char* name) const {
|
||||
std::stringstream res;
|
||||
if (name) {
|
||||
res << name << "(";
|
||||
} else {
|
||||
res << "StdpipBagPackage(";
|
||||
}
|
||||
res << std::fixed << std::setprecision(2);
|
||||
res << std::endl;
|
||||
res << "Size: " << static_cast<int>(size) << std::endl;
|
||||
|
||||
res << "Vectors: " << std::endl;
|
||||
for (u32 i = 0; i < size; i++) {
|
||||
res << i << ": " << vertices[i].getPrint() << std::endl;
|
||||
}
|
||||
|
||||
if (sts != nullptr) {
|
||||
res << "STs: " << std::endl;
|
||||
for (u32 i = 0; i < size; i++)
|
||||
res << i << ": " << sts[i].getPrint() << std::endl;
|
||||
}
|
||||
|
||||
if (colors != nullptr) {
|
||||
res << "Colors: " << std::endl;
|
||||
for (u32 i = 0; i < size; i++)
|
||||
res << i << ": " << colors[i].getPrint() << std::endl;
|
||||
}
|
||||
|
||||
if (normals != nullptr) {
|
||||
res << "Normals: " << std::endl;
|
||||
for (u32 i = 0; i < size; i++)
|
||||
res << i << ": " << normals[i].getPrint() << std::endl;
|
||||
}
|
||||
|
||||
res << "Is in frustum: ";
|
||||
switch (isInFrustum) {
|
||||
case CoreBBoxFrustum::IN_FRUSTUM:
|
||||
res << "Yes";
|
||||
break;
|
||||
case CoreBBoxFrustum::OUTSIDE_FRUSTUM:
|
||||
res << "No";
|
||||
break;
|
||||
case CoreBBoxFrustum::PARTIALLY_IN_FRUSTUM:
|
||||
res << "Partially";
|
||||
break;
|
||||
}
|
||||
|
||||
res << ")";
|
||||
return res.str();
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include <tamtypes.h>
|
||||
#include <math.h>
|
||||
#include "debug/debug.hpp"
|
||||
#include "renderer/3d/pipeline/std/core/bag/packaging/stdpip_bag_packager.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
StdpipBagPackager::StdpipBagPackager() {}
|
||||
StdpipBagPackager::~StdpipBagPackager() {}
|
||||
|
||||
void StdpipBagPackager::init(Renderer3DFrustumPlanes* t_frustumPlanes) {
|
||||
frustumPlanes = t_frustumPlanes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create render packages from provided render data
|
||||
*
|
||||
* @param size Max maxVertCount verts (VU1 buffer size)
|
||||
*/
|
||||
StdpipBagPackage* StdpipBagPackager::create(u16* o_size, StdpipBag* data,
|
||||
u16 size) {
|
||||
TYRA_ASSERT(size <= maxVertCount, "StdpipBagPackage can have max ",
|
||||
maxVertCount, " verts. Provided \"", size, "\"");
|
||||
|
||||
*o_size = ceil(data->count / static_cast<float>(size));
|
||||
StdpipBagPackage* result = new StdpipBagPackage[*o_size];
|
||||
|
||||
for (u16 i = 0; i < *o_size; i++) {
|
||||
result[i].bag = data;
|
||||
result[i].vertices = &data->vertices[i * size];
|
||||
|
||||
if (data->texture) result[i].sts = &data->texture->coordinates[i * size];
|
||||
|
||||
if (data->color->many)
|
||||
result[i].colors = reinterpret_cast<Vec4*>(&data->color->many[i * size]);
|
||||
|
||||
if (data->lighting) result[i].normals = &data->lighting->normals[i * size];
|
||||
|
||||
result[i].indexOf1By3BBox = (i * size) / (maxVertCount / 3);
|
||||
|
||||
if (i == *o_size - 1) {
|
||||
result[i].size = data->count - i * size;
|
||||
} else {
|
||||
result[i].size = size;
|
||||
}
|
||||
|
||||
result[i].isInFrustum = checkFrustum(result[i]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Split render package to smaller packages
|
||||
*
|
||||
* @param size Max maxVertCount verts (VU1 buffer size)
|
||||
*/
|
||||
StdpipBagPackage* StdpipBagPackager::create(u16* o_count,
|
||||
const StdpipBagPackage& pkg,
|
||||
u16 size) {
|
||||
TYRA_ASSERT(size <= maxVertCount, "StdpipBagPackage can have max ",
|
||||
maxVertCount, " verts. Provided \"", size, "\"");
|
||||
|
||||
*o_count = ceil(pkg.size / static_cast<float>(size));
|
||||
auto* result = new StdpipBagPackage[*o_count];
|
||||
|
||||
for (u16 i = 0; i < *o_count; i++) {
|
||||
result[i].bag = pkg.bag;
|
||||
result[i].vertices = &pkg.vertices[i * size];
|
||||
|
||||
if (pkg.bag->texture) result[i].sts = &pkg.sts[i * size];
|
||||
|
||||
if (pkg.bag->color->many) result[i].colors = &pkg.colors[i * size];
|
||||
|
||||
if (pkg.bag->lighting) result[i].normals = &pkg.normals[i * size];
|
||||
|
||||
result[i].indexOf1By3BBox =
|
||||
pkg.indexOf1By3BBox + ((i * size) / (maxVertCount / 3));
|
||||
|
||||
if (i == *o_count - 1) {
|
||||
result[i].size = pkg.size - i * size;
|
||||
} else {
|
||||
result[i].size = size;
|
||||
}
|
||||
|
||||
result[i].isInFrustum = checkFrustum(result[i]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
CoreBBoxFrustum StdpipBagPackager::checkFrustum(const StdpipBagPackage& pkg) {
|
||||
if (pkg.size <= (maxVertCount / 3)) { // Is subpackage
|
||||
auto& bbox = renderBBox->getChildBBox1By3(pkg.indexOf1By3BBox);
|
||||
return bbox.clipIsInFrustum(frustumPlanes->getAll(), *pkg.bag->info->model);
|
||||
} else { // Is package
|
||||
auto bbox = renderBBox->createChildBBox(
|
||||
pkg.indexOf1By3BBox,
|
||||
ceil(pkg.size / static_cast<float>(maxVertCount / 3)));
|
||||
|
||||
return bbox.clipIsInFrustum(frustumPlanes->getAll(), *pkg.bag->info->model);
|
||||
}
|
||||
}
|
||||
|
||||
void StdpipBagPackager::setMaxVertCount(const u32& count) {
|
||||
maxVertCount = count;
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include <tamtypes.h>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include "debug/debug.hpp"
|
||||
#include "renderer/3d/pipeline/std/core/bag/packaging/stdpip_bag_packages_bbox.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
StdpipBagPackagesBBox::StdpipBagPackagesBBox(Vec4* t_vertices, u32* t_faces,
|
||||
const u32& t_facesCount,
|
||||
const u32& t_maxVertCount) {
|
||||
u32 splitPartSize = t_maxVertCount / 3;
|
||||
vertexCount = t_facesCount;
|
||||
partsCount = ceil(vertexCount / static_cast<float>(splitPartSize));
|
||||
|
||||
bboxParts = new std::vector<CoreBBox>;
|
||||
for (u32 i = 0; i < partsCount; i++) {
|
||||
u32 partSize =
|
||||
i == partsCount - 1 ? t_facesCount - i * splitPartSize : splitPartSize;
|
||||
bboxParts->push_back(
|
||||
CoreBBox(t_vertices, t_faces + i * splitPartSize, partSize));
|
||||
}
|
||||
mainBBox = new RenderBBox(*bboxParts, 0, partsCount);
|
||||
}
|
||||
|
||||
StdpipBagPackagesBBox::StdpipBagPackagesBBox(Vec4* t_vertices,
|
||||
const u32& t_count,
|
||||
const u32& t_maxVertCount) {
|
||||
u32 splitPartSize = t_maxVertCount / 3;
|
||||
vertexCount = t_count;
|
||||
partsCount = ceil(vertexCount / static_cast<float>(splitPartSize));
|
||||
|
||||
bboxParts = new std::vector<CoreBBox>;
|
||||
for (u32 i = 0; i < partsCount; i++) {
|
||||
u32 partSize =
|
||||
i == partsCount - 1 ? t_count - i * splitPartSize : splitPartSize;
|
||||
bboxParts->push_back(RenderBBox(t_vertices + i * splitPartSize, partSize));
|
||||
}
|
||||
|
||||
mainBBox = new RenderBBox(*bboxParts, 0, partsCount);
|
||||
}
|
||||
|
||||
const RenderBBox& StdpipBagPackagesBBox::getChildBBox1By3(
|
||||
const u32& index) const {
|
||||
TYRA_ASSERT(index < partsCount,
|
||||
"Index out of range. Provided index: ", index);
|
||||
return static_cast<RenderBBox&>(bboxParts->at(index));
|
||||
}
|
||||
|
||||
RenderBBox* StdpipBagPackagesBBox::getMainBBox() { return mainBBox; }
|
||||
|
||||
const u32& StdpipBagPackagesBBox::getPartsCount() const { return partsCount; }
|
||||
|
||||
const u32& StdpipBagPackagesBBox::getVertexCount() const { return vertexCount; }
|
||||
|
||||
RenderBBox StdpipBagPackagesBBox::createChildBBox(const u32& index,
|
||||
const u16& partsSize) const {
|
||||
return RenderBBox(*bboxParts, index, partsSize);
|
||||
}
|
||||
|
||||
void StdpipBagPackagesBBox::print() const {
|
||||
auto text = getPrint(nullptr);
|
||||
printf("%s\n", text.c_str());
|
||||
}
|
||||
|
||||
void StdpipBagPackagesBBox::print(const char* name) const {
|
||||
auto text = getPrint(name);
|
||||
printf("%s\n", text.c_str());
|
||||
}
|
||||
|
||||
std::string StdpipBagPackagesBBox::getPrint(const char* name) const {
|
||||
std::stringstream res;
|
||||
if (name) {
|
||||
res << name << "(";
|
||||
} else {
|
||||
res << "StdpipBagPackagesBBox(";
|
||||
}
|
||||
res << std::fixed << std::setprecision(2);
|
||||
res << std::endl;
|
||||
res << "Vertices count: " << static_cast<int>(vertexCount) << std::endl;
|
||||
|
||||
res << "Main CoreBBox: " << std::endl;
|
||||
res << mainBBox->getPrint() << std::endl;
|
||||
|
||||
res << "Child BBoxes: " << std::endl;
|
||||
for (u32 i = 0; i < partsCount; i++) {
|
||||
res << i << ": " << bboxParts->at(i).getPrint();
|
||||
if (i != partsCount - 1) {
|
||||
res << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
res << ")";
|
||||
return res.str();
|
||||
}
|
||||
|
||||
StdpipBagPackagesBBox::~StdpipBagPackagesBBox() {
|
||||
delete bboxParts;
|
||||
delete mainBBox;
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include "renderer/3d/pipeline/std/core/bag/stdpip_bag.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
StdpipBag::StdpipBag() {
|
||||
info = nullptr;
|
||||
color = nullptr;
|
||||
texture = nullptr;
|
||||
lighting = nullptr;
|
||||
}
|
||||
|
||||
StdpipBag::~StdpipBag() {}
|
||||
|
||||
StdpipBagPackagesBBox StdpipBag::calculateBbox(const u32& maxVertCount) {
|
||||
TYRA_ASSERT(vertices != nullptr, "Vertices are required to calculate bbox");
|
||||
TYRA_ASSERT(count > 0, "Count must be greater than 0 to calculate bbox");
|
||||
return StdpipBagPackagesBBox(vertices, count, maxVertCount);
|
||||
}
|
||||
|
||||
void StdpipBag::print() const {
|
||||
auto text = getPrint(nullptr);
|
||||
printf("%s\n", text.c_str());
|
||||
}
|
||||
|
||||
void StdpipBag::print(const char* name) const {
|
||||
auto text = getPrint(name);
|
||||
printf("%s\n", text.c_str());
|
||||
}
|
||||
|
||||
std::string StdpipBag::getPrint(const char* name) const {
|
||||
std::stringstream res;
|
||||
if (name) {
|
||||
res << name << "(";
|
||||
} else {
|
||||
res << "StdpipBag(";
|
||||
}
|
||||
res << std::fixed << std::setprecision(4);
|
||||
res << std::endl;
|
||||
res << "Count: " << count << ", " << std::endl;
|
||||
res << "Vertices present: " << (vertices != 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;
|
||||
} else {
|
||||
res << "Color many: " << color->many->getPrint() << ", " << std::endl;
|
||||
}
|
||||
if (texture) {
|
||||
res << "Texture coords present: "
|
||||
<< (texture->coordinates != nullptr ? "Yes" : "No") << ", "
|
||||
<< std::endl;
|
||||
res << "Texture: " << texture->texture->getPrint() << ", " << std::endl;
|
||||
}
|
||||
if (lighting) {
|
||||
res << "Lighting normals present: " << (lighting->normals ? "Yes" : "No")
|
||||
<< ", " << std::endl;
|
||||
res << "Lighting matrix: " << lighting->lightMatrix->getPrint() << ", "
|
||||
<< std::endl;
|
||||
}
|
||||
res << ")";
|
||||
|
||||
return res.str();
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# 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/std/core/bag/stdpip_color_bag.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
StdpipColorBag::StdpipColorBag() {
|
||||
single = nullptr;
|
||||
many = nullptr;
|
||||
}
|
||||
|
||||
StdpipColorBag::~StdpipColorBag() {}
|
||||
|
||||
} // 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>
|
||||
*/
|
||||
|
||||
#include "renderer/3d/pipeline/std/core/bag/stdpip_info_bag.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
StdpipInfoBag::StdpipInfoBag() {
|
||||
shadingType = StdpipShadingFlat;
|
||||
blendingEnabled = true;
|
||||
antiAliasingEnabled = false;
|
||||
model = nullptr;
|
||||
}
|
||||
|
||||
StdpipInfoBag::~StdpipInfoBag() {}
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# 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/std/core/bag/stdpip_lighting_bag.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
StdpipLightingBag::StdpipLightingBag(const bool& manual) {
|
||||
isAllocated = false;
|
||||
mode = Auto;
|
||||
normals = nullptr;
|
||||
lightMatrix = nullptr;
|
||||
lightColors = nullptr;
|
||||
lightDirections = nullptr;
|
||||
if (manual) {
|
||||
mode = Manual;
|
||||
} else {
|
||||
allocate();
|
||||
}
|
||||
}
|
||||
|
||||
StdpipLightingBag::~StdpipLightingBag() { deallocate(); }
|
||||
|
||||
void StdpipLightingBag::setAmbientColor(const Color& color) {
|
||||
TYRA_ASSERT(mode != Manual, "Ambient color cannot be set in manual mode");
|
||||
lightColors[3].set(reinterpret_cast<const Vec4&>(color));
|
||||
}
|
||||
|
||||
void StdpipLightingBag::setDirectionalLightColors(Color* colors,
|
||||
const u8& count) {
|
||||
for (u8 i = 0; i < count; i++) setDirectionalLightColor(colors[i], i);
|
||||
}
|
||||
|
||||
void StdpipLightingBag::setDirectionalLightDirections(Vec4* directions,
|
||||
const u8& count) {
|
||||
for (u8 i = 0; i < count; i++) setDirectionalLightDirection(directions[i], i);
|
||||
}
|
||||
|
||||
void StdpipLightingBag::setDirectionalLightColor(const Color& color,
|
||||
const u8& index) {
|
||||
TYRA_ASSERT(mode != Manual,
|
||||
"Directional lights cannot be set in manual mode");
|
||||
TYRA_ASSERT(index < 3, "There are max 3 directional lights");
|
||||
lightColors[index].set(reinterpret_cast<const Vec4&>(color));
|
||||
}
|
||||
|
||||
void StdpipLightingBag::setDirectionalLightDirection(const Vec4& direction,
|
||||
const u8& index) {
|
||||
TYRA_ASSERT(mode != Manual,
|
||||
"Directional lights cannot be set in manual mode");
|
||||
TYRA_ASSERT(index < 3, "There are max 3 directional lights");
|
||||
|
||||
lightDirections[index].set(direction);
|
||||
}
|
||||
|
||||
void StdpipLightingBag::setLightsManually(Vec4* colors, Vec4* directions) {
|
||||
deallocate();
|
||||
lightColors = colors;
|
||||
lightDirections = directions;
|
||||
mode = Manual;
|
||||
}
|
||||
|
||||
void StdpipLightingBag::disableManualMode() {
|
||||
allocate();
|
||||
mode = Auto;
|
||||
}
|
||||
|
||||
void StdpipLightingBag::allocate() {
|
||||
if (isAllocated) return;
|
||||
|
||||
lightColors = new Vec4[4];
|
||||
lightDirections = new Vec4[3];
|
||||
|
||||
for (u8 i = 0; i < 3; i++) {
|
||||
lightColors[i].set(0.0F, 0.0F, 0.0F, 1.0F);
|
||||
}
|
||||
|
||||
lightColors[3].set(.5F, .5F, .5F, 1.0F); // Ambient
|
||||
|
||||
for (u8 i = 0; i < 3; i++) {
|
||||
lightDirections[i].set(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
}
|
||||
|
||||
isAllocated = true;
|
||||
}
|
||||
|
||||
void StdpipLightingBag::deallocate() {
|
||||
if (!isAllocated) return;
|
||||
|
||||
forceDeallocate();
|
||||
}
|
||||
|
||||
void StdpipLightingBag::forceDeallocate() {
|
||||
forceDeallocateColors();
|
||||
forceDeallocateDirections();
|
||||
|
||||
isAllocated = false;
|
||||
}
|
||||
|
||||
void StdpipLightingBag::forceDeallocateColors() {
|
||||
if (lightColors != nullptr) {
|
||||
delete[] lightColors;
|
||||
lightColors = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void StdpipLightingBag::forceDeallocateDirections() {
|
||||
if (lightDirections != nullptr) {
|
||||
delete[] lightDirections;
|
||||
lightDirections = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# 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/std/core/bag/stdpip_texture_bag.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
StdpipTextureBag::StdpipTextureBag() {
|
||||
coordinates = nullptr;
|
||||
texture = nullptr;
|
||||
}
|
||||
|
||||
StdpipTextureBag::~StdpipTextureBag() {}
|
||||
|
||||
} // namespace Tyra
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
; ______ ____ ___
|
||||
; | \/ ____| |___|
|
||||
; | | | \ | |
|
||||
;---------------------------------------------------------------
|
||||
; Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
; Licenced under Apache License 2.0
|
||||
; Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
;
|
||||
;---------------------------------------------------------------
|
||||
; Triangle list
|
||||
; AsIs = NO TRANSFORM
|
||||
; Colors
|
||||
;---------------------------------------------------------------
|
||||
|
||||
.syntax new
|
||||
.name StdpipVU1As_Is_C
|
||||
.vu
|
||||
.init_vf_all
|
||||
.init_vi_all
|
||||
|
||||
#include "src/renderer/core/paths/path1/programs/vcl_sml.i"
|
||||
#include "src/renderer/core/paths/path1/programs/tyra_macros.i"
|
||||
#include "inc/renderer/3d/pipeline/std/core/path1/programs/stdpip_vu1_shared_defines.h"
|
||||
|
||||
#define RGBA_STORE_OFFSET 0
|
||||
#define XYZ2_STORE_OFFSET 1
|
||||
|
||||
--enter
|
||||
--endenter
|
||||
|
||||
#vuprog StdpipVU1AsIsC
|
||||
|
||||
LoadTyraStaticData{ gifSetTag }
|
||||
LoadTyraSingleColor{ singleColor, singleColorEnabled, VU1_SINGLE_COLOR_ADDR, VU1_OPTIONS_ADDR }
|
||||
LoadTyraTags{ lodGifTag, texBufferClutGifTag, VU1_LOD_ADDR, VU1_CLUT_ADDR }
|
||||
|
||||
begin:
|
||||
xtop buffer
|
||||
LoadTyraBufferTags{ scale, primTag, buffer }
|
||||
|
||||
iaddiu vertexData, buffer, VU1_VERT_DATA_ADDR
|
||||
ilw.w vertexCount, 0(buffer)
|
||||
iadd colorData, vertexData, vertexCount
|
||||
iblez singleColorEnabled, setDestAddrMultiColor
|
||||
iadd kickAddress, vertexData, vertexCount
|
||||
b setDestAddr
|
||||
setDestAddrMultiColor:
|
||||
iadd kickAddress, colorData, vertexCount
|
||||
setDestAddr:
|
||||
iaddiu destAddress, kickAddress, 0
|
||||
|
||||
StoreTyraGifTags{ gifSetTag, lodGifTag, texBufferClutGifTag, primTag, destAddress }
|
||||
|
||||
;--- Loop
|
||||
iadd vertexCounter, buffer, vertexCount
|
||||
vertexLoop:
|
||||
|
||||
iblez singleColorEnabled, multiColor
|
||||
;--- Load vertices single color
|
||||
add color1, vf00, singleColor
|
||||
add color2, vf00, singleColor
|
||||
add color3, vf00, singleColor
|
||||
b processing
|
||||
|
||||
multiColor:
|
||||
;--- Load vertices colors
|
||||
lq color1, (colorData)
|
||||
lq color2, 1(colorData)
|
||||
lq color3, 2(colorData)
|
||||
|
||||
processing:
|
||||
;--- Load vertex1
|
||||
lq.xyz vertex1, (vertexData)
|
||||
|
||||
;--- Load vertex2
|
||||
lq.xyz vertex2, 1(vertexData)
|
||||
|
||||
;--- Load vertex3
|
||||
lq.xyz vertex3, 2(vertexData)
|
||||
|
||||
;--- Calculate vertex1
|
||||
ScaleVertexToGSFormat{ scale, vertex1 }
|
||||
FixColor{ color1 }
|
||||
|
||||
;--- Calculate vertex2
|
||||
ScaleVertexToGSFormat{ scale, vertex2 }
|
||||
FixColor{ color2 }
|
||||
|
||||
;--- Calculate vertex3
|
||||
ScaleVertexToGSFormat{ scale, vertex3 }
|
||||
FixColor{ color3 }
|
||||
|
||||
;--- Store vertex1
|
||||
sq color1, RGBA_STORE_OFFSET(destAddress)
|
||||
sq.xyz vertex1, XYZ2_STORE_OFFSET(destAddress)
|
||||
|
||||
;--- Store vertex2
|
||||
sq color2, RGBA_STORE_OFFSET+2(destAddress)
|
||||
sq.xyz vertex2, XYZ2_STORE_OFFSET+2(destAddress)
|
||||
|
||||
;--- Store vertex3
|
||||
sq color3, RGBA_STORE_OFFSET+4(destAddress)
|
||||
sq.xyz vertex3, XYZ2_STORE_OFFSET+4(destAddress)
|
||||
|
||||
;-------------------------------
|
||||
|
||||
iaddiu vertexData, vertexData, 3
|
||||
iaddiu colorData, colorData, 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
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# 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/std/core/path1/programs/as_is/stdpip_as_is_c_vu1_program.hpp"
|
||||
|
||||
extern u32 StdpipVU1As_Is_C_CodeStart __attribute__((section(".vudata")));
|
||||
extern u32 StdpipVU1As_Is_C_CodeEnd __attribute__((section(".vudata")));
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
StdpipAsIsCVU1Program::StdpipAsIsCVU1Program()
|
||||
: StdpipVU1Program(StdpipAsIsColor, &StdpipVU1As_Is_C_CodeStart,
|
||||
&StdpipVU1As_Is_C_CodeEnd,
|
||||
((u64)GIF_REG_RGBAQ) << 0 | ((u64)GIF_REG_XYZ2) << 4, 2,
|
||||
2) {}
|
||||
|
||||
StdpipAsIsCVU1Program::~StdpipAsIsCVU1Program() {}
|
||||
|
||||
std::string StdpipAsIsCVU1Program::getStringName() const {
|
||||
return std::string("As is - C");
|
||||
}
|
||||
|
||||
void StdpipAsIsCVU1Program::addProgramQBufferDataToPacket(
|
||||
packet2_t* packet, StdpipQBuffer* qbuffer) const {
|
||||
u32 addr = VU1_VERT_DATA_ADDR;
|
||||
|
||||
// Add vertices
|
||||
packet2_utils_vu_add_unpack_data(packet, addr, qbuffer->vertices,
|
||||
qbuffer->size, true);
|
||||
|
||||
// Add colors
|
||||
if (qbuffer->bag->color->single == nullptr) {
|
||||
addr += qbuffer->size;
|
||||
packet2_utils_vu_add_unpack_data(packet, addr, qbuffer->colors,
|
||||
qbuffer->size, true);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
; ______ ____ ___
|
||||
; | \/ ____| |___|
|
||||
; | | | \ | |
|
||||
;---------------------------------------------------------------
|
||||
; Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
; Licenced under Apache License 2.0
|
||||
; Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
;
|
||||
;---------------------------------------------------------------
|
||||
; Triangle list
|
||||
; AsIs = NO TRANSFORM
|
||||
; Directional lights
|
||||
;---------------------------------------------------------------
|
||||
|
||||
.syntax new
|
||||
.name StdpipVU1As_Is_D
|
||||
.vu
|
||||
.init_vf_all
|
||||
.init_vi_all
|
||||
|
||||
#include "src/renderer/core/paths/path1/programs/vcl_sml.i"
|
||||
#include "src/renderer/core/paths/path1/programs/tyra_macros.i"
|
||||
#include "inc/renderer/3d/pipeline/std/core/path1/programs/stdpip_vu1_shared_defines.h"
|
||||
|
||||
#define RGBA_STORE_OFFSET 0
|
||||
#define XYZ2_STORE_OFFSET 1
|
||||
|
||||
--enter
|
||||
--endenter
|
||||
|
||||
#vuprog StdpipVU1AsIsD
|
||||
|
||||
LoadTyraStaticData{ gifSetTag }
|
||||
LoadTyraDirectionalLights{ lightMatrix, lightDirections, lightColors, ambientColor, VU1_LIGHTS_DIRS_ADDR, VU1_LIGHTS_COLORS_ADDR, VU1_LIGHTS_MATRIX_ADDR }
|
||||
LoadTyraTags{ lodGifTag, texBufferClutGifTag, VU1_LOD_ADDR, VU1_CLUT_ADDR }
|
||||
|
||||
begin:
|
||||
xtop buffer
|
||||
LoadTyraBufferTags{ scale, primTag, buffer }
|
||||
|
||||
iaddiu vertexData, buffer, VU1_VERT_DATA_ADDR
|
||||
ilw.w vertexCount, 0(buffer)
|
||||
iadd normalData, vertexData, vertexCount
|
||||
iadd kickAddress, normalData, vertexCount
|
||||
iadd destAddress, normalData, vertexCount
|
||||
|
||||
StoreTyraGifTags{ gifSetTag, lodGifTag, texBufferClutGifTag, primTag, destAddress }
|
||||
|
||||
;--- Loop
|
||||
iadd vertexCounter, buffer, vertexCount
|
||||
vertexLoop:
|
||||
;--- Load vertex1
|
||||
lq.xyz vertex1, (vertexData)
|
||||
lq.xyz normal1, (normalData)
|
||||
|
||||
;--- Load vertex2
|
||||
lq.xyz vertex2, 1(vertexData)
|
||||
lq.xyz normal2, 1(normalData)
|
||||
|
||||
;--- Load vertex3
|
||||
lq.xyz vertex3, 2(vertexData)
|
||||
lq.xyz normal3, 2(normalData)
|
||||
|
||||
;--- Calculate vertex1
|
||||
ScaleVertexToGSFormat{ scale, vertex1 }
|
||||
CalculateTyraDirectionalLights{ outputColor1, normal1, lightDirections, lightColors, lightMatrix, ambientColor }
|
||||
FixColor{ outputColor1 }
|
||||
|
||||
;--- Calculate vertex2
|
||||
ScaleVertexToGSFormat{ scale, vertex2 }
|
||||
CalculateTyraDirectionalLights{ outputColor2, normal2, lightDirections, lightColors, lightMatrix, ambientColor }
|
||||
FixColor{ outputColor2 }
|
||||
|
||||
;--- Calculate vertex3
|
||||
ScaleVertexToGSFormat{ scale, vertex3 }
|
||||
CalculateTyraDirectionalLights{ outputColor3, normal3, lightDirections, lightColors, lightMatrix, ambientColor }
|
||||
FixColor{ outputColor3 }
|
||||
|
||||
;--- Store vertex1
|
||||
sq outputColor1, RGBA_STORE_OFFSET(destAddress)
|
||||
sq.xyz vertex1, XYZ2_STORE_OFFSET(destAddress)
|
||||
|
||||
;--- Store vertex2
|
||||
sq outputColor2, RGBA_STORE_OFFSET+2(destAddress)
|
||||
sq.xyz vertex2, XYZ2_STORE_OFFSET+2(destAddress)
|
||||
|
||||
;--- Store vertex3
|
||||
sq outputColor3, RGBA_STORE_OFFSET+4(destAddress)
|
||||
sq.xyz vertex3, XYZ2_STORE_OFFSET+4(destAddress)
|
||||
|
||||
;-------------------------------
|
||||
|
||||
iaddiu vertexData, vertexData, 3
|
||||
iaddiu normalData, normalData, 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
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# 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/std/core/path1/programs/as_is/stdpip_as_is_d_vu1_program.hpp"
|
||||
|
||||
extern u32 StdpipVU1As_Is_D_CodeStart __attribute__((section(".vudata")));
|
||||
extern u32 StdpipVU1As_Is_D_CodeEnd __attribute__((section(".vudata")));
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
StdpipAsIsDVU1Program::StdpipAsIsDVU1Program()
|
||||
: StdpipVU1Program(StdpipAsIsDirLights, &StdpipVU1As_Is_D_CodeStart,
|
||||
&StdpipVU1As_Is_D_CodeEnd,
|
||||
((u64)GIF_REG_RGBAQ) << 0 | ((u64)GIF_REG_XYZ2) << 4, 2,
|
||||
3) {}
|
||||
|
||||
StdpipAsIsDVU1Program::~StdpipAsIsDVU1Program() {}
|
||||
|
||||
std::string StdpipAsIsDVU1Program::getStringName() const {
|
||||
return std::string("As is - LC");
|
||||
}
|
||||
|
||||
void StdpipAsIsDVU1Program::addProgramQBufferDataToPacket(
|
||||
packet2_t* packet, StdpipQBuffer* qbuffer) const {
|
||||
u32 addr = VU1_VERT_DATA_ADDR;
|
||||
|
||||
// Add vertices
|
||||
packet2_utils_vu_add_unpack_data(packet, addr, qbuffer->vertices,
|
||||
qbuffer->size, true);
|
||||
addr += qbuffer->size;
|
||||
|
||||
// Add normal
|
||||
packet2_utils_vu_add_unpack_data(packet, addr, qbuffer->normals,
|
||||
qbuffer->size, true);
|
||||
|
||||
// Add colors
|
||||
if (qbuffer->bag->color->single == nullptr) {
|
||||
addr += qbuffer->size;
|
||||
packet2_utils_vu_add_unpack_data(packet, addr, qbuffer->colors,
|
||||
qbuffer->size, true);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
+140
@@ -0,0 +1,140 @@
|
||||
; ______ ____ ___
|
||||
; | \/ ____| |___|
|
||||
; | | | \ | |
|
||||
;---------------------------------------------------------------
|
||||
; Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
; Licenced under Apache License 2.0
|
||||
; Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
;
|
||||
;---------------------------------------------------------------
|
||||
; Triangle list
|
||||
; AsIs = NO TRANSFORM
|
||||
; Texture, colors
|
||||
;---------------------------------------------------------------
|
||||
|
||||
.syntax new
|
||||
.name StdpipVU1As_Is_TC
|
||||
.vu
|
||||
.init_vf_all
|
||||
.init_vi_all
|
||||
|
||||
#include "src/renderer/core/paths/path1/programs/vcl_sml.i"
|
||||
#include "src/renderer/core/paths/path1/programs/tyra_macros.i"
|
||||
#include "inc/renderer/3d/pipeline/std/core/path1/programs/stdpip_vu1_shared_defines.h"
|
||||
|
||||
#define STQ_STORE_OFFSET 0
|
||||
#define RGBA_STORE_OFFSET 1
|
||||
#define XYZ2_STORE_OFFSET 2
|
||||
|
||||
--enter
|
||||
--endenter
|
||||
|
||||
#vuprog StdpipVU1AsIsTC
|
||||
|
||||
LoadTyraStaticData{ gifSetTag }
|
||||
LoadTyraSingleColor{ singleColor, singleColorEnabled, VU1_SINGLE_COLOR_ADDR, VU1_OPTIONS_ADDR }
|
||||
LoadTyraTags{ lodGifTag, texBufferClutGifTag, VU1_LOD_ADDR, VU1_CLUT_ADDR }
|
||||
|
||||
begin:
|
||||
xtop buffer
|
||||
LoadTyraBufferTags{ scale, primTag, buffer }
|
||||
|
||||
iaddiu vertexData, buffer, VU1_VERT_DATA_ADDR
|
||||
ilw.w vertexCount, 0(buffer)
|
||||
iadd stqData, vertexData, vertexCount
|
||||
iadd colorData, stqData, vertexCount
|
||||
iblez singleColorEnabled, setDestAddrMultiColor
|
||||
iadd kickAddress, stqData, vertexCount
|
||||
b setDestAddr
|
||||
setDestAddrMultiColor:
|
||||
iadd kickAddress, colorData, vertexCount
|
||||
setDestAddr:
|
||||
iaddiu destAddress, kickAddress, 0
|
||||
|
||||
StoreTyraGifTags{ gifSetTag, lodGifTag, texBufferClutGifTag, primTag, destAddress }
|
||||
|
||||
;--- Loop
|
||||
iadd vertexCounter, buffer, vertexCount
|
||||
vertexLoop:
|
||||
|
||||
iblez singleColorEnabled, multiColor
|
||||
;--- Load vertices single color
|
||||
add color1, vf00, singleColor
|
||||
add color2, vf00, singleColor
|
||||
add color3, vf00, singleColor
|
||||
b processing
|
||||
|
||||
multiColor:
|
||||
;--- Load vertices colors
|
||||
lq color1, (colorData)
|
||||
lq color2, 1(colorData)
|
||||
lq color3, 2(colorData)
|
||||
|
||||
processing:
|
||||
;--- Load vertex1
|
||||
lq vertex1, (vertexData)
|
||||
lq stq1, (stqData)
|
||||
|
||||
;--- Load vertex2
|
||||
lq vertex2, 1(vertexData)
|
||||
lq stq2, 1(stqData)
|
||||
|
||||
;--- Load vertex3
|
||||
lq vertex3, 2(vertexData)
|
||||
lq stq3, 2(stqData)
|
||||
|
||||
;--- Calculate vertex1
|
||||
ScaleVertexToGSFormat{ scale, vertex1 }
|
||||
div q, vf00[w], vertex1[w]
|
||||
PerformTexturePerspectiveCorrection{ outputStq1, stq1 }
|
||||
FixColor{ color1 }
|
||||
|
||||
;--- Calculate vertex2
|
||||
ScaleVertexToGSFormat{ scale, vertex2 }
|
||||
div q, vf00[w], vertex2[w]
|
||||
PerformTexturePerspectiveCorrection{ outputStq2, stq2 }
|
||||
FixColor{ color2 }
|
||||
|
||||
;--- Calculate vertex3
|
||||
ScaleVertexToGSFormat{ scale, vertex3 }
|
||||
div q, vf00[w], vertex3[w]
|
||||
PerformTexturePerspectiveCorrection{ outputStq3, stq3 }
|
||||
FixColor{ color3 }
|
||||
|
||||
;--- Store vertex1
|
||||
sq outputStq1, STQ_STORE_OFFSET(destAddress)
|
||||
sq color1, RGBA_STORE_OFFSET(destAddress)
|
||||
sq.xyz vertex1, XYZ2_STORE_OFFSET(destAddress)
|
||||
|
||||
;--- Store vertex2
|
||||
sq outputStq2, STQ_STORE_OFFSET+3(destAddress)
|
||||
sq color2, RGBA_STORE_OFFSET+3(destAddress)
|
||||
sq.xyz vertex2, XYZ2_STORE_OFFSET+3(destAddress)
|
||||
|
||||
;--- Store vertex3
|
||||
sq outputStq3, STQ_STORE_OFFSET+6(destAddress)
|
||||
sq color3, RGBA_STORE_OFFSET+6(destAddress)
|
||||
sq.xyz vertex3, XYZ2_STORE_OFFSET+6(destAddress)
|
||||
|
||||
;-------------------------------
|
||||
|
||||
iaddiu vertexData, vertexData, 3
|
||||
iaddiu stqData, stqData, 3
|
||||
iaddiu colorData, colorData, 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
|
||||
+53
@@ -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/std/core/path1/programs/as_is/stdpip_as_is_tc_vu1_program.hpp"
|
||||
|
||||
extern u32 StdpipVU1As_Is_TC_CodeStart __attribute__((section(".vudata")));
|
||||
extern u32 StdpipVU1As_Is_TC_CodeEnd __attribute__((section(".vudata")));
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
StdpipAsIsTCVU1Program::StdpipAsIsTCVU1Program()
|
||||
: StdpipVU1Program(StdpipAsIsTextureColor, &StdpipVU1As_Is_TC_CodeStart,
|
||||
&StdpipVU1As_Is_TC_CodeEnd,
|
||||
((u64)GIF_REG_ST) << 0 | ((u64)GIF_REG_RGBAQ) << 4 |
|
||||
((u64)GIF_REG_XYZ2) << 8,
|
||||
3, 3) {}
|
||||
|
||||
StdpipAsIsTCVU1Program::~StdpipAsIsTCVU1Program() {}
|
||||
|
||||
std::string StdpipAsIsTCVU1Program::getStringName() const {
|
||||
return std::string("As is - TC");
|
||||
}
|
||||
|
||||
void StdpipAsIsTCVU1Program::addProgramQBufferDataToPacket(
|
||||
packet2_t* packet, StdpipQBuffer* qbuffer) const {
|
||||
u32 addr = VU1_VERT_DATA_ADDR;
|
||||
|
||||
// Add vertices
|
||||
packet2_utils_vu_add_unpack_data(packet, addr, qbuffer->vertices,
|
||||
qbuffer->size, true);
|
||||
addr += qbuffer->size;
|
||||
|
||||
// Add sts
|
||||
packet2_utils_vu_add_unpack_data(packet, addr, qbuffer->sts, qbuffer->size,
|
||||
true);
|
||||
|
||||
// Add colors
|
||||
if (qbuffer->bag->color->single == nullptr) {
|
||||
addr += qbuffer->size;
|
||||
packet2_utils_vu_add_unpack_data(packet, addr, qbuffer->colors,
|
||||
qbuffer->size, true);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
; ______ ____ ___
|
||||
; | \/ ____| |___|
|
||||
; | | | \ | |
|
||||
;---------------------------------------------------------------
|
||||
; Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
; Licenced under Apache License 2.0
|
||||
; Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
;
|
||||
;---------------------------------------------------------------
|
||||
; Triangle list
|
||||
; AsIs = NO TRANSFORM
|
||||
; Texture, directional lights
|
||||
;---------------------------------------------------------------
|
||||
|
||||
.syntax new
|
||||
.name StdpipVU1As_Is_TD
|
||||
.vu
|
||||
.init_vf_all
|
||||
.init_vi_all
|
||||
|
||||
#include "src/renderer/core/paths/path1/programs/vcl_sml.i"
|
||||
#include "src/renderer/core/paths/path1/programs/tyra_macros.i"
|
||||
#include "inc/renderer/3d/pipeline/std/core/path1/programs/stdpip_vu1_shared_defines.h"
|
||||
|
||||
#define STQ_STORE_OFFSET 0
|
||||
#define RGBA_STORE_OFFSET 1
|
||||
#define XYZ2_STORE_OFFSET 2
|
||||
|
||||
--enter
|
||||
--endenter
|
||||
|
||||
#vuprog StdpipVU1AsIsTD
|
||||
|
||||
LoadTyraStaticData{ gifSetTag }
|
||||
LoadTyraDirectionalLights{ lightMatrix, lightDirections, lightColors, ambientColor, VU1_LIGHTS_DIRS_ADDR, VU1_LIGHTS_COLORS_ADDR, VU1_LIGHTS_MATRIX_ADDR }
|
||||
LoadTyraTags{ lodGifTag, texBufferClutGifTag, VU1_LOD_ADDR, VU1_CLUT_ADDR }
|
||||
|
||||
begin:
|
||||
xtop buffer
|
||||
LoadTyraBufferTags{ scale, primTag, buffer }
|
||||
|
||||
iaddiu vertexData, buffer, VU1_VERT_DATA_ADDR
|
||||
ilw.w vertexCount, 0(buffer)
|
||||
iadd stqData, vertexData, vertexCount
|
||||
iadd normalData, stqData, vertexCount
|
||||
iadd kickAddress, normalData, vertexCount
|
||||
iadd destAddress, normalData, vertexCount
|
||||
|
||||
StoreTyraGifTags{ gifSetTag, lodGifTag, texBufferClutGifTag, primTag, destAddress }
|
||||
|
||||
;--- Loop
|
||||
iadd vertexCounter, buffer, vertexCount
|
||||
vertexLoop:
|
||||
;--- Load vertex1
|
||||
lq vertex1, (vertexData)
|
||||
lq stq1, (stqData)
|
||||
lq.xyz normal1, (normalData)
|
||||
|
||||
;--- Load vertex2
|
||||
lq vertex2, 1(vertexData)
|
||||
lq stq2, 1(stqData)
|
||||
lq.xyz normal2, 1(normalData)
|
||||
|
||||
;--- Load vertex3
|
||||
lq vertex3, 2(vertexData)
|
||||
lq stq3, 2(stqData)
|
||||
lq.xyz normal3, 2(normalData)
|
||||
|
||||
;--- Calculate vertex1
|
||||
ScaleVertexToGSFormat{ scale, vertex1 }
|
||||
div q, vf00[w], vertex1[w]
|
||||
PerformTexturePerspectiveCorrection{ outputStq1, stq1 }
|
||||
CalculateTyraDirectionalLights{ outputColor1, normal1, lightDirections, lightColors, lightMatrix, ambientColor }
|
||||
FixColor{ outputColor1 }
|
||||
|
||||
;--- Calculate vertex2
|
||||
ScaleVertexToGSFormat{ scale, vertex2 }
|
||||
div q, vf00[w], vertex2[w]
|
||||
PerformTexturePerspectiveCorrection{ outputStq2, stq2 }
|
||||
CalculateTyraDirectionalLights{ outputColor2, normal2, lightDirections, lightColors, lightMatrix, ambientColor }
|
||||
FixColor{ outputColor2 }
|
||||
|
||||
;--- Calculate vertex3
|
||||
ScaleVertexToGSFormat{ scale, vertex3 }
|
||||
div q, vf00[w], vertex3[w]
|
||||
PerformTexturePerspectiveCorrection{ outputStq3, stq3 }
|
||||
CalculateTyraDirectionalLights{ outputColor3, normal3, lightDirections, lightColors, lightMatrix, ambientColor }
|
||||
FixColor{ outputColor3 }
|
||||
|
||||
;--- Store vertex1
|
||||
sq outputStq1, STQ_STORE_OFFSET(destAddress)
|
||||
sq outputColor1, RGBA_STORE_OFFSET(destAddress)
|
||||
sq.xyz vertex1, XYZ2_STORE_OFFSET(destAddress)
|
||||
|
||||
;--- Store vertex2
|
||||
sq outputStq2, STQ_STORE_OFFSET+3(destAddress)
|
||||
sq outputColor2, RGBA_STORE_OFFSET+3(destAddress)
|
||||
sq.xyz vertex2, XYZ2_STORE_OFFSET+3(destAddress)
|
||||
|
||||
;--- Store vertex3
|
||||
sq outputStq3, STQ_STORE_OFFSET+6(destAddress)
|
||||
sq outputColor3, RGBA_STORE_OFFSET+6(destAddress)
|
||||
sq.xyz vertex3, XYZ2_STORE_OFFSET+6(destAddress)
|
||||
|
||||
;-------------------------------
|
||||
|
||||
iaddiu vertexData, vertexData, 3
|
||||
iaddiu stqData, stqData, 3
|
||||
iaddiu normalData, normalData, 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
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# 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/std/core/path1/programs/as_is/stdpip_as_is_td_vu1_program.hpp"
|
||||
|
||||
extern u32 StdpipVU1As_Is_TD_CodeStart __attribute__((section(".vudata")));
|
||||
extern u32 StdpipVU1As_Is_TD_CodeEnd __attribute__((section(".vudata")));
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
StdpipAsIsTDVU1Program::StdpipAsIsTDVU1Program()
|
||||
: StdpipVU1Program(StdpipAsIsTextureDirLights, &StdpipVU1As_Is_TD_CodeStart,
|
||||
&StdpipVU1As_Is_TD_CodeEnd,
|
||||
((u64)GIF_REG_ST) << 0 | ((u64)GIF_REG_RGBAQ) << 4 |
|
||||
((u64)GIF_REG_XYZ2) << 8,
|
||||
3, 4) {}
|
||||
|
||||
StdpipAsIsTDVU1Program::~StdpipAsIsTDVU1Program() {}
|
||||
|
||||
std::string StdpipAsIsTDVU1Program::getStringName() const {
|
||||
return std::string("As is - LTC");
|
||||
}
|
||||
|
||||
void StdpipAsIsTDVU1Program::addProgramQBufferDataToPacket(
|
||||
packet2_t* packet, StdpipQBuffer* qbuffer) const {
|
||||
u32 addr = VU1_VERT_DATA_ADDR;
|
||||
|
||||
// Add vertices
|
||||
packet2_utils_vu_add_unpack_data(packet, addr, qbuffer->vertices,
|
||||
qbuffer->size, true);
|
||||
addr += qbuffer->size;
|
||||
|
||||
// Add sts
|
||||
packet2_utils_vu_add_unpack_data(packet, addr, qbuffer->sts, qbuffer->size,
|
||||
true);
|
||||
addr += qbuffer->size;
|
||||
|
||||
// Add normal
|
||||
packet2_utils_vu_add_unpack_data(packet, addr, qbuffer->normals,
|
||||
qbuffer->size, true);
|
||||
|
||||
// Add colors
|
||||
if (qbuffer->bag->color->single == nullptr) {
|
||||
addr += qbuffer->size;
|
||||
packet2_utils_vu_add_unpack_data(packet, addr, qbuffer->colors,
|
||||
qbuffer->size, true);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,136 @@
|
||||
; ______ ____ ___
|
||||
; | \/ ____| |___|
|
||||
; | | | \ | |
|
||||
;---------------------------------------------------------------
|
||||
; 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.
|
||||
; Volors
|
||||
;---------------------------------------------------------------
|
||||
|
||||
.syntax new
|
||||
.name StdpipVU1Cull_C
|
||||
.vu
|
||||
.init_vf_all
|
||||
.init_vi_all
|
||||
|
||||
#include "src/renderer/core/paths/path1/programs/vcl_sml.i"
|
||||
#include "src/renderer/core/paths/path1/programs/tyra_macros.i"
|
||||
#include "inc/renderer/3d/pipeline/std/core/path1/programs/stdpip_vu1_shared_defines.h"
|
||||
|
||||
#define RGBA_STORE_OFFSET 0
|
||||
#define XYZ2_STORE_OFFSET 1
|
||||
|
||||
--enter
|
||||
--endenter
|
||||
|
||||
#vuprog StdpipVU1CullC
|
||||
|
||||
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 }
|
||||
|
||||
begin:
|
||||
xtop buffer
|
||||
LoadTyraBufferTags{ scale, primTag, buffer }
|
||||
|
||||
iaddiu vertexData, buffer, VU1_VERT_DATA_ADDR
|
||||
ilw.w vertexCount, 0(buffer)
|
||||
iadd colorData, vertexData, vertexCount
|
||||
iblez singleColorEnabled, setDestAddrMultiColor
|
||||
iadd kickAddress, vertexData, vertexCount
|
||||
b setDestAddr
|
||||
setDestAddrMultiColor:
|
||||
iadd kickAddress, colorData, vertexCount
|
||||
setDestAddr:
|
||||
iaddiu destAddress, kickAddress, 0
|
||||
|
||||
StoreTyraGifTags{ gifSetTag, lodGifTag, texBufferClutGifTag, primTag, destAddress }
|
||||
|
||||
;--- Loop
|
||||
iadd vertexCounter, buffer, vertexCount
|
||||
vertexLoop:
|
||||
|
||||
iblez singleColorEnabled, multiColor
|
||||
;--- Load vertices single color
|
||||
add color1, vf00, singleColor
|
||||
add color2, vf00, singleColor
|
||||
add color3, vf00, singleColor
|
||||
b processing
|
||||
|
||||
multiColor:
|
||||
;--- Load vertices colors
|
||||
lq color1, (colorData)
|
||||
lq color2, 1(colorData)
|
||||
lq color3, 2(colorData)
|
||||
|
||||
processing:
|
||||
;--- Load vertex1
|
||||
lq vertex1, (vertexData)
|
||||
|
||||
;--- Load vertex2
|
||||
lq vertex2, 1(vertexData)
|
||||
|
||||
;--- Load vertex3
|
||||
lq vertex3, 2(vertexData)
|
||||
|
||||
;--- Calculate vertex1
|
||||
MatrixMultiplyVertex{ vertex1, mvp, vertex1 }
|
||||
PerformClipCheck{ vertex1, destAddress, XYZ2_STORE_OFFSET }
|
||||
VertexPersCorr{ vertex1, vertex1 }
|
||||
ScaleVertexToGSFormat{ scale, vertex1 }
|
||||
FixColor{ color1 }
|
||||
|
||||
;--- Calculate vertex2
|
||||
MatrixMultiplyVertex{ vertex2, mvp, vertex2 }
|
||||
PerformClipCheck{ vertex2, destAddress, XYZ2_STORE_OFFSET+2 }
|
||||
VertexPersCorr{ vertex2, vertex2 }
|
||||
ScaleVertexToGSFormat{ scale, vertex2 }
|
||||
FixColor{ color2 }
|
||||
|
||||
;--- Calculate vertex3
|
||||
MatrixMultiplyVertex{ vertex3, mvp, vertex3 }
|
||||
PerformClipCheck{ vertex3, destAddress, XYZ2_STORE_OFFSET+4 }
|
||||
VertexPersCorr{ vertex3, vertex3 }
|
||||
ScaleVertexToGSFormat{ scale, vertex3 }
|
||||
FixColor{ color3 }
|
||||
|
||||
;--- Store vertex1
|
||||
sq color1, RGBA_STORE_OFFSET(destAddress)
|
||||
sq.xyz vertex1, XYZ2_STORE_OFFSET(destAddress)
|
||||
|
||||
;--- Store vertex2
|
||||
sq color2, RGBA_STORE_OFFSET+2(destAddress)
|
||||
sq.xyz vertex2, XYZ2_STORE_OFFSET+2(destAddress)
|
||||
|
||||
;--- Store vertex3
|
||||
sq color3, RGBA_STORE_OFFSET+4(destAddress)
|
||||
sq.xyz vertex3, XYZ2_STORE_OFFSET+4(destAddress)
|
||||
|
||||
;-------------------------------
|
||||
|
||||
iaddiu vertexData, vertexData, 3
|
||||
iaddiu colorData, colorData, 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
|
||||
+46
@@ -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>
|
||||
*/
|
||||
|
||||
#include "debug/debug.hpp"
|
||||
#include "renderer/3d/pipeline/std/core/path1/programs/cull/stdpip_cull_c_vu1_program.hpp"
|
||||
|
||||
extern u32 StdpipVU1Cull_C_CodeStart __attribute__((section(".vudata")));
|
||||
extern u32 StdpipVU1Cull_C_CodeEnd __attribute__((section(".vudata")));
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
StdpipCullCVU1Program::StdpipCullCVU1Program()
|
||||
: StdpipVU1Program(
|
||||
StdpipCullColor, &StdpipVU1Cull_C_CodeStart, &StdpipVU1Cull_C_CodeEnd,
|
||||
((u64)GIF_REG_RGBAQ) << 0 | ((u64)GIF_REG_XYZ2) << 4, 2, 2) {}
|
||||
|
||||
StdpipCullCVU1Program::~StdpipCullCVU1Program() {}
|
||||
|
||||
std::string StdpipCullCVU1Program::getStringName() const {
|
||||
return std::string("Cull - C");
|
||||
}
|
||||
|
||||
void StdpipCullCVU1Program::addProgramQBufferDataToPacket(
|
||||
packet2_t* packet, StdpipQBuffer* qbuffer) const {
|
||||
u32 addr = VU1_VERT_DATA_ADDR;
|
||||
|
||||
// Add vertices
|
||||
packet2_utils_vu_add_unpack_data(packet, addr, qbuffer->vertices,
|
||||
qbuffer->size, true);
|
||||
|
||||
// Add colors
|
||||
if (qbuffer->bag->color->single == nullptr) {
|
||||
addr += qbuffer->size;
|
||||
packet2_utils_vu_add_unpack_data(packet, addr, qbuffer->colors,
|
||||
qbuffer->size, true);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,122 @@
|
||||
; ______ ____ ___
|
||||
; | \/ ____| |___|
|
||||
; | | | \ | |
|
||||
;---------------------------------------------------------------
|
||||
; 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.
|
||||
; Directional lights
|
||||
;---------------------------------------------------------------
|
||||
|
||||
.syntax new
|
||||
.name StdpipVU1Cull_D
|
||||
.vu
|
||||
.init_vf_all
|
||||
.init_vi_all
|
||||
|
||||
#include "src/renderer/core/paths/path1/programs/vcl_sml.i"
|
||||
#include "src/renderer/core/paths/path1/programs/tyra_macros.i"
|
||||
#include "inc/renderer/3d/pipeline/std/core/path1/programs/stdpip_vu1_shared_defines.h"
|
||||
|
||||
#define RGBA_STORE_OFFSET 0
|
||||
#define XYZ2_STORE_OFFSET 1
|
||||
|
||||
--enter
|
||||
--endenter
|
||||
|
||||
#vuprog StdpipVU1CullD
|
||||
|
||||
ResetClipFlags{ }
|
||||
LoadTyraStaticData{ gifSetTag }
|
||||
MatrixLoad{ mvp, VU1_MVP_MATRIX_ADDR, vi00 }
|
||||
LoadTyraDirectionalLights{ lightMatrix, lightDirections, lightColors, ambientColor, VU1_LIGHTS_DIRS_ADDR, VU1_LIGHTS_COLORS_ADDR, VU1_LIGHTS_MATRIX_ADDR }
|
||||
LoadTyraTags{ lodGifTag, texBufferClutGifTag, VU1_LOD_ADDR, VU1_CLUT_ADDR }
|
||||
|
||||
begin:
|
||||
xtop buffer
|
||||
LoadTyraBufferTags{ scale, primTag, buffer }
|
||||
|
||||
iaddiu vertexData, buffer, VU1_VERT_DATA_ADDR
|
||||
ilw.w vertexCount, 0(buffer)
|
||||
iadd normalData, vertexData, vertexCount
|
||||
iadd kickAddress, normalData, vertexCount
|
||||
iadd destAddress, normalData, vertexCount
|
||||
|
||||
StoreTyraGifTags{ gifSetTag, lodGifTag, texBufferClutGifTag, primTag, destAddress }
|
||||
|
||||
;--- Loop
|
||||
iadd vertexCounter, buffer, vertexCount
|
||||
vertexLoop:
|
||||
;--- Load vertex1
|
||||
lq vertex1, (vertexData)
|
||||
lq.xyz normal1, (normalData)
|
||||
|
||||
;--- Load vertex2
|
||||
lq vertex2, 1(vertexData)
|
||||
lq.xyz normal2, 1(normalData)
|
||||
|
||||
;--- Load vertex3
|
||||
lq vertex3, 2(vertexData)
|
||||
lq.xyz normal3, 2(normalData)
|
||||
|
||||
;--- Calculate vertex1
|
||||
MatrixMultiplyVertex{ vertex1, mvp, vertex1 }
|
||||
PerformClipCheck{ vertex1, destAddress, XYZ2_STORE_OFFSET }
|
||||
VertexPersCorr{ vertex1, vertex1 }
|
||||
ScaleVertexToGSFormat{ scale, vertex1 }
|
||||
CalculateTyraDirectionalLights{ outputColor1, normal1, lightDirections, lightColors, lightMatrix, ambientColor }
|
||||
FixColor{ outputColor1 }
|
||||
|
||||
;--- Calculate vertex2
|
||||
MatrixMultiplyVertex{ vertex2, mvp, vertex2 }
|
||||
PerformClipCheck{ vertex2, destAddress, XYZ2_STORE_OFFSET+2 }
|
||||
VertexPersCorr{ vertex2, vertex2 }
|
||||
ScaleVertexToGSFormat{ scale, vertex2 }
|
||||
CalculateTyraDirectionalLights{ outputColor2, normal2, lightDirections, lightColors, lightMatrix, ambientColor }
|
||||
FixColor{ outputColor2 }
|
||||
|
||||
;--- Calculate vertex3
|
||||
MatrixMultiplyVertex{ vertex3, mvp, vertex3 }
|
||||
PerformClipCheck{ vertex3, destAddress, XYZ2_STORE_OFFSET+4 }
|
||||
VertexPersCorr{ vertex3, vertex3 }
|
||||
ScaleVertexToGSFormat{ scale, vertex3 }
|
||||
CalculateTyraDirectionalLights{ outputColor3, normal3, lightDirections, lightColors, lightMatrix, ambientColor }
|
||||
FixColor{ outputColor3 }
|
||||
|
||||
;--- Store vertex1
|
||||
sq outputColor1, RGBA_STORE_OFFSET(destAddress)
|
||||
sq.xyz vertex1, XYZ2_STORE_OFFSET(destAddress)
|
||||
|
||||
;--- Store vertex2
|
||||
sq outputColor2, RGBA_STORE_OFFSET+2(destAddress)
|
||||
sq.xyz vertex2, XYZ2_STORE_OFFSET+2(destAddress)
|
||||
|
||||
;--- Store vertex3
|
||||
sq outputColor3, RGBA_STORE_OFFSET+4(destAddress)
|
||||
sq.xyz vertex3, XYZ2_STORE_OFFSET+4(destAddress)
|
||||
|
||||
;-------------------------------
|
||||
|
||||
iaddiu vertexData, vertexData, 3
|
||||
iaddiu normalData, normalData, 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
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# 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/std/core/path1/programs/cull/stdpip_cull_d_vu1_program.hpp"
|
||||
|
||||
extern u32 StdpipVU1Cull_D_CodeStart __attribute__((section(".vudata")));
|
||||
extern u32 StdpipVU1Cull_D_CodeEnd __attribute__((section(".vudata")));
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
StdpipCullDVU1Program::StdpipCullDVU1Program()
|
||||
: StdpipVU1Program(StdpipCullDirLights, &StdpipVU1Cull_D_CodeStart,
|
||||
&StdpipVU1Cull_D_CodeEnd,
|
||||
((u64)GIF_REG_RGBAQ) << 0 | ((u64)GIF_REG_XYZ2) << 4, 2,
|
||||
3) {}
|
||||
|
||||
StdpipCullDVU1Program::~StdpipCullDVU1Program() {}
|
||||
|
||||
std::string StdpipCullDVU1Program::getStringName() const {
|
||||
return std::string("Cull - LC");
|
||||
}
|
||||
|
||||
void StdpipCullDVU1Program::addProgramQBufferDataToPacket(
|
||||
packet2_t* packet, StdpipQBuffer* qbuffer) const {
|
||||
u32 addr = VU1_VERT_DATA_ADDR;
|
||||
|
||||
// Add vertices
|
||||
packet2_utils_vu_add_unpack_data(packet, addr, qbuffer->vertices,
|
||||
qbuffer->size, true);
|
||||
addr += qbuffer->size;
|
||||
|
||||
// Add normal
|
||||
packet2_utils_vu_add_unpack_data(packet, addr, qbuffer->normals,
|
||||
qbuffer->size, true);
|
||||
|
||||
// Add colors
|
||||
if (qbuffer->bag->color->single == nullptr) {
|
||||
addr += qbuffer->size;
|
||||
packet2_utils_vu_add_unpack_data(packet, addr, qbuffer->colors,
|
||||
qbuffer->size, true);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
+148
@@ -0,0 +1,148 @@
|
||||
; ______ ____ ___
|
||||
; | \/ ____| |___|
|
||||
; | | | \ | |
|
||||
;---------------------------------------------------------------
|
||||
; 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.
|
||||
; Lighting, texture, colors
|
||||
;---------------------------------------------------------------
|
||||
|
||||
.syntax new
|
||||
.name StdpipVU1Cull_TC
|
||||
.vu
|
||||
.init_vf_all
|
||||
.init_vi_all
|
||||
|
||||
#include "src/renderer/core/paths/path1/programs/vcl_sml.i"
|
||||
#include "src/renderer/core/paths/path1/programs/tyra_macros.i"
|
||||
#include "inc/renderer/3d/pipeline/std/core/path1/programs/stdpip_vu1_shared_defines.h"
|
||||
|
||||
#define STQ_STORE_OFFSET 0
|
||||
#define RGBA_STORE_OFFSET 1
|
||||
#define XYZ2_STORE_OFFSET 2
|
||||
|
||||
--enter
|
||||
--endenter
|
||||
|
||||
#vuprog StdpipVU1CullTC
|
||||
|
||||
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 }
|
||||
|
||||
begin:
|
||||
xtop buffer
|
||||
LoadTyraBufferTags{ scale, primTag, buffer }
|
||||
|
||||
iaddiu vertexData, buffer, VU1_VERT_DATA_ADDR
|
||||
ilw.w vertexCount, 0(buffer)
|
||||
iadd stqData, vertexData, vertexCount
|
||||
iadd colorData, stqData, vertexCount
|
||||
iblez singleColorEnabled, setDestAddrMultiColor
|
||||
iadd kickAddress, stqData, vertexCount
|
||||
b setDestAddr
|
||||
setDestAddrMultiColor:
|
||||
iadd kickAddress, colorData, vertexCount
|
||||
setDestAddr:
|
||||
iaddiu destAddress, kickAddress, 0
|
||||
|
||||
StoreTyraGifTags{ gifSetTag, lodGifTag, texBufferClutGifTag, primTag, destAddress }
|
||||
|
||||
;--- Loop
|
||||
iadd vertexCounter, buffer, vertexCount
|
||||
vertexLoop:
|
||||
|
||||
iblez singleColorEnabled, multiColor
|
||||
;--- Load vertices single color
|
||||
add color1, vf00, singleColor
|
||||
add color2, vf00, singleColor
|
||||
add color3, vf00, singleColor
|
||||
b processing
|
||||
|
||||
multiColor:
|
||||
;--- Load vertices colors
|
||||
lq color1, (colorData)
|
||||
lq color2, 1(colorData)
|
||||
lq color3, 2(colorData)
|
||||
|
||||
processing:
|
||||
;--- Load vertex1
|
||||
lq vertex1, (vertexData)
|
||||
lq stq1, (stqData)
|
||||
|
||||
;--- Load vertex2
|
||||
lq vertex2, 1(vertexData)
|
||||
lq stq2, 1(stqData)
|
||||
|
||||
;--- Load vertex3
|
||||
lq vertex3, 2(vertexData)
|
||||
lq stq3, 2(stqData)
|
||||
|
||||
;--- Calculate vertex1
|
||||
MatrixMultiplyVertex{ vertex1, mvp, vertex1 }
|
||||
PerformClipCheck{ vertex1, destAddress, XYZ2_STORE_OFFSET }
|
||||
VertexPersCorr{ vertex1, vertex1 }
|
||||
ScaleVertexToGSFormat{ scale, vertex1 }
|
||||
PerformTexturePerspectiveCorrection{ outputStq1, stq1 }
|
||||
FixColor{ color1 }
|
||||
|
||||
;--- Calculate vertex2
|
||||
MatrixMultiplyVertex{ vertex2, mvp, vertex2 }
|
||||
PerformClipCheck{ vertex2, destAddress, XYZ2_STORE_OFFSET+3 }
|
||||
VertexPersCorr{ vertex2, vertex2 }
|
||||
ScaleVertexToGSFormat{ scale, vertex2 }
|
||||
PerformTexturePerspectiveCorrection{ outputStq2, stq2 }
|
||||
FixColor{ color2 }
|
||||
|
||||
;--- Calculate vertex3
|
||||
MatrixMultiplyVertex{ vertex3, mvp, vertex3 }
|
||||
PerformClipCheck{ vertex3, destAddress, XYZ2_STORE_OFFSET+6 }
|
||||
VertexPersCorr{ vertex3, vertex3 }
|
||||
ScaleVertexToGSFormat{ scale, vertex3 }
|
||||
PerformTexturePerspectiveCorrection{ outputStq3, stq3 }
|
||||
FixColor{ color3 }
|
||||
|
||||
;--- Store vertex1
|
||||
sq outputStq1, STQ_STORE_OFFSET(destAddress)
|
||||
sq color1, RGBA_STORE_OFFSET(destAddress)
|
||||
sq.xyz vertex1, XYZ2_STORE_OFFSET(destAddress)
|
||||
|
||||
;--- Store vertex2
|
||||
sq outputStq2, STQ_STORE_OFFSET+3(destAddress)
|
||||
sq color2, RGBA_STORE_OFFSET+3(destAddress)
|
||||
sq.xyz vertex2, XYZ2_STORE_OFFSET+3(destAddress)
|
||||
|
||||
;--- Store vertex3
|
||||
sq outputStq3, STQ_STORE_OFFSET+6(destAddress)
|
||||
sq color3, RGBA_STORE_OFFSET+6(destAddress)
|
||||
sq.xyz vertex3, XYZ2_STORE_OFFSET+6(destAddress)
|
||||
|
||||
;-------------------------------
|
||||
|
||||
iaddiu vertexData, vertexData, 3
|
||||
iaddiu stqData, stqData, 3
|
||||
iaddiu colorData, colorData, 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
|
||||
+53
@@ -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/std/core/path1/programs/cull/stdpip_cull_tc_vu1_program.hpp"
|
||||
|
||||
extern u32 StdpipVU1Cull_TC_CodeStart __attribute__((section(".vudata")));
|
||||
extern u32 StdpipVU1Cull_TC_CodeEnd __attribute__((section(".vudata")));
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
StdpipCullTCVU1Program::StdpipCullTCVU1Program()
|
||||
: StdpipVU1Program(StdpipCullTextureColor, &StdpipVU1Cull_TC_CodeStart,
|
||||
&StdpipVU1Cull_TC_CodeEnd,
|
||||
((u64)GIF_REG_ST) << 0 | ((u64)GIF_REG_RGBAQ) << 4 |
|
||||
((u64)GIF_REG_XYZ2) << 8,
|
||||
3, 3) {}
|
||||
|
||||
StdpipCullTCVU1Program::~StdpipCullTCVU1Program() {}
|
||||
|
||||
std::string StdpipCullTCVU1Program::getStringName() const {
|
||||
return std::string("Cull - TC");
|
||||
}
|
||||
|
||||
void StdpipCullTCVU1Program::addProgramQBufferDataToPacket(
|
||||
packet2_t* packet, StdpipQBuffer* qbuffer) const {
|
||||
u32 addr = VU1_VERT_DATA_ADDR;
|
||||
|
||||
// Add vertices
|
||||
packet2_utils_vu_add_unpack_data(packet, addr, qbuffer->vertices,
|
||||
qbuffer->size, true);
|
||||
addr += qbuffer->size;
|
||||
|
||||
// Add sts
|
||||
packet2_utils_vu_add_unpack_data(packet, addr, qbuffer->sts, qbuffer->size,
|
||||
true);
|
||||
|
||||
// Add colors
|
||||
if (qbuffer->bag->color->single == nullptr) {
|
||||
addr += qbuffer->size;
|
||||
packet2_utils_vu_add_unpack_data(packet, addr, qbuffer->colors,
|
||||
qbuffer->size, true);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
+134
@@ -0,0 +1,134 @@
|
||||
; ______ ____ ___
|
||||
; | \/ ____| |___|
|
||||
; | | | \ | |
|
||||
;---------------------------------------------------------------
|
||||
; 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.
|
||||
; Texture, directional lights
|
||||
;---------------------------------------------------------------
|
||||
|
||||
.syntax new
|
||||
.name StdpipVU1Cull_TD
|
||||
.vu
|
||||
.init_vf_all
|
||||
.init_vi_all
|
||||
|
||||
#include "src/renderer/core/paths/path1/programs/vcl_sml.i"
|
||||
#include "src/renderer/core/paths/path1/programs/tyra_macros.i"
|
||||
#include "inc/renderer/3d/pipeline/std/core/path1/programs/stdpip_vu1_shared_defines.h"
|
||||
|
||||
#define STQ_STORE_OFFSET 0
|
||||
#define RGBA_STORE_OFFSET 1
|
||||
#define XYZ2_STORE_OFFSET 2
|
||||
|
||||
--enter
|
||||
--endenter
|
||||
|
||||
#vuprog StdpipVU1CullTD
|
||||
|
||||
ResetClipFlags{ }
|
||||
LoadTyraStaticData{ gifSetTag }
|
||||
MatrixLoad{ mvp, VU1_MVP_MATRIX_ADDR, vi00 }
|
||||
LoadTyraDirectionalLights{ lightMatrix, lightDirections, lightColors, ambientColor, VU1_LIGHTS_DIRS_ADDR, VU1_LIGHTS_COLORS_ADDR, VU1_LIGHTS_MATRIX_ADDR }
|
||||
LoadTyraTags{ lodGifTag, texBufferClutGifTag, VU1_LOD_ADDR, VU1_CLUT_ADDR }
|
||||
|
||||
begin:
|
||||
xtop buffer
|
||||
LoadTyraBufferTags{ scale, primTag, buffer }
|
||||
|
||||
iaddiu vertexData, buffer, VU1_VERT_DATA_ADDR
|
||||
ilw.w vertexCount, 0(buffer)
|
||||
iadd stqData, vertexData, vertexCount
|
||||
iadd normalData, stqData, vertexCount
|
||||
iadd kickAddress, normalData, vertexCount
|
||||
iadd destAddress, normalData, vertexCount
|
||||
|
||||
StoreTyraGifTags{ gifSetTag, lodGifTag, texBufferClutGifTag, primTag, destAddress }
|
||||
|
||||
;--- Loop
|
||||
iadd vertexCounter, buffer, vertexCount
|
||||
vertexLoop:
|
||||
;--- Load vertex1
|
||||
lq vertex1, (vertexData)
|
||||
lq stq1, (stqData)
|
||||
lq.xyz normal1, (normalData)
|
||||
|
||||
;--- Load vertex2
|
||||
lq vertex2, 1(vertexData)
|
||||
lq stq2, 1(stqData)
|
||||
lq.xyz normal2, 1(normalData)
|
||||
|
||||
;--- Load vertex3
|
||||
lq vertex3, 2(vertexData)
|
||||
lq stq3, 2(stqData)
|
||||
lq.xyz normal3, 2(normalData)
|
||||
|
||||
;--- Calculate vertex1
|
||||
MatrixMultiplyVertex{ vertex1, mvp, vertex1 }
|
||||
PerformClipCheck{ vertex1, destAddress, XYZ2_STORE_OFFSET }
|
||||
VertexPersCorr{ vertex1, vertex1 }
|
||||
ScaleVertexToGSFormat{ scale, vertex1 }
|
||||
PerformTexturePerspectiveCorrection{ outputStq1, stq1 }
|
||||
CalculateTyraDirectionalLights{ outputColor1, normal1, lightDirections, lightColors, lightMatrix, ambientColor }
|
||||
FixColor{ outputColor1 }
|
||||
|
||||
;--- Calculate vertex2
|
||||
MatrixMultiplyVertex{ vertex2, mvp, vertex2 }
|
||||
PerformClipCheck{ vertex2, destAddress, XYZ2_STORE_OFFSET+3 }
|
||||
VertexPersCorr{ vertex2, vertex2 }
|
||||
ScaleVertexToGSFormat{ scale, vertex2 }
|
||||
PerformTexturePerspectiveCorrection{ outputStq2, stq2 }
|
||||
CalculateTyraDirectionalLights{ outputColor2, normal2, lightDirections, lightColors, lightMatrix, ambientColor }
|
||||
FixColor{ outputColor2 }
|
||||
|
||||
;--- Calculate vertex3
|
||||
MatrixMultiplyVertex{ vertex3, mvp, vertex3 }
|
||||
PerformClipCheck{ vertex3, destAddress, XYZ2_STORE_OFFSET+6 }
|
||||
VertexPersCorr{ vertex3, vertex3 }
|
||||
ScaleVertexToGSFormat{ scale, vertex3 }
|
||||
PerformTexturePerspectiveCorrection{ outputStq3, stq3 }
|
||||
CalculateTyraDirectionalLights{ outputColor3, normal3, lightDirections, lightColors, lightMatrix, ambientColor }
|
||||
FixColor{ outputColor3 }
|
||||
|
||||
;--- Store vertex1
|
||||
sq outputStq1, STQ_STORE_OFFSET(destAddress)
|
||||
sq outputColor1, RGBA_STORE_OFFSET(destAddress)
|
||||
sq.xyz vertex1, XYZ2_STORE_OFFSET(destAddress)
|
||||
|
||||
;--- Store vertex2
|
||||
sq outputStq2, STQ_STORE_OFFSET+3(destAddress)
|
||||
sq outputColor2, RGBA_STORE_OFFSET+3(destAddress)
|
||||
sq.xyz vertex2, XYZ2_STORE_OFFSET+3(destAddress)
|
||||
|
||||
;--- Store vertex3
|
||||
sq outputStq3, STQ_STORE_OFFSET+6(destAddress)
|
||||
sq outputColor3, RGBA_STORE_OFFSET+6(destAddress)
|
||||
sq.xyz vertex3, XYZ2_STORE_OFFSET+6(destAddress)
|
||||
|
||||
;-------------------------------
|
||||
|
||||
iaddiu vertexData, vertexData, 3
|
||||
iaddiu stqData, stqData, 3
|
||||
iaddiu normalData, normalData, 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
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# 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/std/core/path1/programs/cull/stdpip_cull_td_vu1_program.hpp"
|
||||
|
||||
extern u32 StdpipVU1Cull_TD_CodeStart __attribute__((section(".vudata")));
|
||||
extern u32 StdpipVU1Cull_TD_CodeEnd __attribute__((section(".vudata")));
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
StdpipCullTDVU1Program::StdpipCullTDVU1Program()
|
||||
: StdpipVU1Program(StdpipCullTextureDirLights, &StdpipVU1Cull_TD_CodeStart,
|
||||
&StdpipVU1Cull_TD_CodeEnd,
|
||||
((u64)GIF_REG_ST) << 0 | ((u64)GIF_REG_RGBAQ) << 4 |
|
||||
((u64)GIF_REG_XYZ2) << 8,
|
||||
3, 4) {}
|
||||
|
||||
StdpipCullTDVU1Program::~StdpipCullTDVU1Program() {}
|
||||
|
||||
std::string StdpipCullTDVU1Program::getStringName() const {
|
||||
return std::string("Cull - LTC");
|
||||
}
|
||||
|
||||
void StdpipCullTDVU1Program::addProgramQBufferDataToPacket(
|
||||
packet2_t* packet, StdpipQBuffer* qbuffer) const {
|
||||
u32 addr = VU1_VERT_DATA_ADDR;
|
||||
|
||||
// Add vertices
|
||||
packet2_utils_vu_add_unpack_data(packet, addr, qbuffer->vertices,
|
||||
qbuffer->size, true);
|
||||
addr += qbuffer->size;
|
||||
|
||||
// Add sts
|
||||
packet2_utils_vu_add_unpack_data(packet, addr, qbuffer->sts, qbuffer->size,
|
||||
true);
|
||||
addr += qbuffer->size;
|
||||
|
||||
// Add normal
|
||||
packet2_utils_vu_add_unpack_data(packet, addr, qbuffer->normals,
|
||||
qbuffer->size, true);
|
||||
|
||||
// Add colors
|
||||
if (qbuffer->bag->color->single == nullptr) {
|
||||
addr += qbuffer->size;
|
||||
packet2_utils_vu_add_unpack_data(packet, addr, qbuffer->colors,
|
||||
qbuffer->size, true);
|
||||
}
|
||||
}
|
||||
|
||||
} // 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/std/core/path1/stdpip_clipper.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
StdpipClipper::StdpipClipper() {}
|
||||
StdpipClipper::~StdpipClipper() {}
|
||||
|
||||
void StdpipClipper::setMVP(M4x4* t_mvp) { mvp = t_mvp; }
|
||||
|
||||
void StdpipClipper::init(const RendererSettings& settings) {
|
||||
algorithm.init(settings);
|
||||
}
|
||||
|
||||
void StdpipClipper::setMaxVertCount(const u32& count) { maxVertCount = count; }
|
||||
|
||||
void StdpipClipper::clip(StdpipQBuffer* buffer) {
|
||||
TYRA_ASSERT(buffer->size <= maxVertCount / 3, "Buffer should have max ",
|
||||
maxVertCount / 3, " verts if we want to clip it.");
|
||||
|
||||
Path1EEClipAlgorithmSettings algoSettings = {
|
||||
buffer->bag->lighting != nullptr, buffer->bag->texture != nullptr,
|
||||
buffer->bag->color->many != nullptr};
|
||||
|
||||
std::vector<Path1ClipVertex> clippedVertices;
|
||||
|
||||
for (u32 i = 0; i < buffer->size / 3; i++) {
|
||||
std::vector<Path1ClipVertex> inputTriangle;
|
||||
for (u8 j = 0; j < 3; j++) {
|
||||
Path1ClipVertex vert = {
|
||||
*mvp * buffer->vertices[i * 3 + j],
|
||||
buffer->bag->lighting ? buffer->normals[i * 3 + j] : Vec4(),
|
||||
buffer->bag->texture ? buffer->sts[i * 3 + j] : Vec4(),
|
||||
buffer->bag->color->many ? buffer->colors[i * 3 + j] : Vec4()};
|
||||
|
||||
inputTriangle.push_back(vert);
|
||||
}
|
||||
|
||||
std::vector<Path1ClipVertex> clippedTriangle;
|
||||
algorithm.clip(&clippedTriangle, inputTriangle, algoSettings);
|
||||
|
||||
if (clippedTriangle.size() == 0) continue;
|
||||
|
||||
auto va = clippedTriangle.at(0);
|
||||
for (u32 j = 1; j <= clippedTriangle.size() - 2; j++) {
|
||||
auto vb = clippedTriangle.at(j);
|
||||
auto vc = clippedTriangle.at((j + 1) % clippedTriangle.size());
|
||||
clippedVertices.push_back(va);
|
||||
clippedVertices.push_back(vb);
|
||||
clippedVertices.push_back(vc);
|
||||
}
|
||||
}
|
||||
|
||||
perspectiveDivide(&clippedVertices);
|
||||
moveDataToBuffer(clippedVertices, buffer);
|
||||
}
|
||||
|
||||
void StdpipClipper::perspectiveDivide(std::vector<Path1ClipVertex>* vertices) {
|
||||
for (u32 i = 0; i < vertices->size(); i++) {
|
||||
(*vertices)[i].position /= (*vertices)[i].position.w;
|
||||
}
|
||||
}
|
||||
|
||||
void StdpipClipper::moveDataToBuffer(
|
||||
const std::vector<Path1ClipVertex>& vertices, StdpipQBuffer* buffer) {
|
||||
buffer->reallocateManually(vertices.size());
|
||||
|
||||
for (u32 i = 0; i < vertices.size(); i++) {
|
||||
auto& vertex = vertices.at(i);
|
||||
buffer->vertices[i] = vertex.position;
|
||||
|
||||
if (buffer->bag->texture) buffer->sts[i] = vertex.st;
|
||||
if (buffer->bag->color->many) buffer->colors[i] = vertex.color;
|
||||
if (buffer->bag->lighting) buffer->normals[i] = vertex.normal;
|
||||
}
|
||||
}
|
||||
|
||||
} // 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>
|
||||
*/
|
||||
|
||||
#include "renderer/3d/pipeline/std/core/path1/stdpip_programs_repository.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
StdpipProgramsRepository::StdpipProgramsRepository() {}
|
||||
|
||||
StdpipProgramsRepository::~StdpipProgramsRepository() {}
|
||||
|
||||
StdpipVU1Program* StdpipProgramsRepository::getProgram(
|
||||
const StdpipProgramName& name) {
|
||||
switch (name) {
|
||||
case StdpipProgramName::StdpipAsIsColor:
|
||||
return &asIsColor;
|
||||
case StdpipProgramName::StdpipCullColor:
|
||||
return &cullColor;
|
||||
|
||||
case StdpipProgramName::StdpipAsIsDirLights:
|
||||
return &asIsLightingColor;
|
||||
case StdpipProgramName::StdpipCullDirLights:
|
||||
return &cullLightingColor;
|
||||
|
||||
case StdpipProgramName::StdpipAsIsTextureDirLights:
|
||||
return &asIsLightingTextureColor;
|
||||
case StdpipProgramName::StdpipCullTextureDirLights:
|
||||
return &cullLightingTextureColor;
|
||||
|
||||
case StdpipProgramName::StdpipAsIsTextureColor:
|
||||
return &asIsTextureColor;
|
||||
case StdpipProgramName::StdpipCullTextureColor:
|
||||
return &cullTextureColor;
|
||||
|
||||
default:
|
||||
TYRA_TRAP("Unknown VU1 program name");
|
||||
return &cullLightingTextureColor;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,265 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# 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/std/core/path1/stdpip_qbuffer.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
StdpipQBuffer::StdpipQBuffer() {
|
||||
size = 0;
|
||||
_isDynamicallyAllocated = false;
|
||||
_stAllocated = false;
|
||||
_colorAllocated = false;
|
||||
_normalAllocated = false;
|
||||
|
||||
vertices = nullptr;
|
||||
colors = nullptr;
|
||||
sts = nullptr;
|
||||
normals = nullptr;
|
||||
}
|
||||
|
||||
StdpipQBuffer::~StdpipQBuffer() { deallocateDynamicData(); }
|
||||
|
||||
void StdpipQBuffer::setMaxVertCount(const u32& count) { maxVertCount = count; }
|
||||
|
||||
void StdpipQBuffer::fillByPointer(const StdpipBagPackage& pkg) {
|
||||
TYRA_ASSERT(pkg.size <= maxVertCount, "VU1 buffer supports only ",
|
||||
maxVertCount, " verts. Provided: ", pkg.size);
|
||||
|
||||
deallocateDynamicData();
|
||||
|
||||
vertices = pkg.vertices;
|
||||
sts = pkg.sts;
|
||||
colors = pkg.colors;
|
||||
normals = pkg.normals;
|
||||
size = pkg.size;
|
||||
bag = pkg.bag;
|
||||
}
|
||||
|
||||
void StdpipQBuffer::fillByCopyMax(const StdpipBagPackage& pkg1,
|
||||
const StdpipBagPackage& pkg2,
|
||||
const StdpipBagPackage& pkg3) {
|
||||
TYRA_ASSERT(pkg1.size <= maxVertCount / 3,
|
||||
"Wrong package size (1). Provided: ", pkg1.size);
|
||||
TYRA_ASSERT(pkg2.size <= maxVertCount / 3,
|
||||
"Wrong package size (2). Provided: ", pkg2.size);
|
||||
TYRA_ASSERT(pkg3.size <= maxVertCount / 3,
|
||||
"Wrong package size (3). Provided: ", pkg3.size);
|
||||
|
||||
deallocateDynamicData();
|
||||
size = pkg1.size + pkg2.size + pkg3.size;
|
||||
allocateDynamicData(size, pkg1.bag);
|
||||
|
||||
for (u16 i = 0; i < pkg1.size; i++) {
|
||||
vertices[i].set(pkg1.vertices[i]);
|
||||
|
||||
if (pkg1.bag->texture) sts[i].set(pkg1.sts[i]);
|
||||
|
||||
if (pkg1.bag->color->many)
|
||||
colors[i].set(reinterpret_cast<const Vec4&>(pkg1.colors[i]));
|
||||
|
||||
if (pkg1.bag->lighting) normals[i].set(pkg1.normals[i]);
|
||||
}
|
||||
|
||||
for (u16 i = 0; i < pkg2.size; i++) {
|
||||
vertices[i + pkg1.size].set(pkg2.vertices[i]);
|
||||
|
||||
if (pkg1.bag->texture) sts[i + pkg1.size].set(pkg2.sts[i]);
|
||||
|
||||
if (pkg1.bag->color->many)
|
||||
colors[i + pkg1.size].set(reinterpret_cast<const Vec4&>(pkg2.colors[i]));
|
||||
|
||||
if (pkg1.bag->lighting) normals[i + pkg1.size].set(pkg2.normals[i]);
|
||||
}
|
||||
|
||||
for (u16 i = 0; i < pkg3.size; i++) {
|
||||
vertices[i + pkg1.size + pkg2.size].set(pkg3.vertices[i]);
|
||||
|
||||
if (pkg1.bag->texture) sts[i + pkg1.size + pkg2.size].set(pkg3.sts[i]);
|
||||
|
||||
if (pkg1.bag->color->many)
|
||||
colors[i + pkg1.size + pkg2.size].set(
|
||||
reinterpret_cast<const Vec4&>(pkg3.colors[i]));
|
||||
|
||||
if (pkg1.bag->lighting)
|
||||
normals[i + pkg1.size + pkg2.size].set(pkg3.normals[i]);
|
||||
}
|
||||
|
||||
bag = pkg1.bag;
|
||||
}
|
||||
|
||||
void StdpipQBuffer::fillByCopy1By2(const StdpipBagPackage& pkg1,
|
||||
const StdpipBagPackage& pkg2) {
|
||||
TYRA_ASSERT(pkg1.size <= maxVertCount / 3,
|
||||
"Wrong package size (1). Provided: ", pkg1.size);
|
||||
TYRA_ASSERT(pkg2.size <= maxVertCount / 3,
|
||||
"Wrong package size (2). Provided: ", pkg2.size);
|
||||
|
||||
deallocateDynamicData();
|
||||
size = pkg1.size + pkg2.size;
|
||||
allocateDynamicData(size, pkg1.bag);
|
||||
|
||||
for (u16 i = 0; i < pkg1.size; i++) {
|
||||
vertices[i].set(pkg1.vertices[i]);
|
||||
|
||||
if (pkg1.bag->texture) sts[i].set(pkg1.sts[i]);
|
||||
|
||||
if (pkg1.bag->color->many)
|
||||
colors[i].set(reinterpret_cast<const Vec4&>(pkg1.colors[i]));
|
||||
|
||||
if (pkg1.bag->lighting) normals[i].set(pkg1.normals[i]);
|
||||
}
|
||||
|
||||
for (u16 i = 0; i < pkg2.size; i++) {
|
||||
vertices[i + pkg1.size].set(pkg2.vertices[i]);
|
||||
|
||||
if (pkg1.bag->texture) sts[i + pkg1.size].set(pkg2.sts[i]);
|
||||
|
||||
if (pkg1.bag->color->many)
|
||||
colors[i + pkg1.size].set(reinterpret_cast<const Vec4&>(pkg2.colors[i]));
|
||||
|
||||
if (pkg1.bag->lighting) normals[i + pkg1.size].set(pkg2.normals[i]);
|
||||
}
|
||||
|
||||
bag = pkg1.bag;
|
||||
}
|
||||
|
||||
void StdpipQBuffer::fillByCopy1By3(const StdpipBagPackage& pkg) {
|
||||
TYRA_ASSERT(pkg.size <= maxVertCount / 3,
|
||||
"Wrong package size (1). Provided: ", pkg.size);
|
||||
|
||||
deallocateDynamicData();
|
||||
size = pkg.size;
|
||||
allocateDynamicData(size, pkg.bag);
|
||||
|
||||
for (u16 i = 0; i < pkg.size; i++) {
|
||||
vertices[i].set(pkg.vertices[i]);
|
||||
|
||||
if (pkg.bag->texture) sts[i].set(pkg.sts[i]);
|
||||
|
||||
if (pkg.bag->color->many)
|
||||
colors[i].set(reinterpret_cast<const Vec4&>(pkg.colors[i]));
|
||||
|
||||
if (pkg.bag->lighting) normals[i].set(pkg.normals[i]);
|
||||
}
|
||||
|
||||
bag = pkg.bag;
|
||||
}
|
||||
|
||||
void StdpipQBuffer::reallocateManually(const u16& t_size) {
|
||||
deallocateDynamicData();
|
||||
allocateDynamicData(t_size, bag);
|
||||
size = t_size;
|
||||
}
|
||||
|
||||
void StdpipQBuffer::deallocateDynamicData() {
|
||||
if (_isDynamicallyAllocated) {
|
||||
delete[] vertices;
|
||||
|
||||
if (_stAllocated) {
|
||||
delete[] sts;
|
||||
_stAllocated = false;
|
||||
}
|
||||
|
||||
if (_colorAllocated) {
|
||||
delete[] colors;
|
||||
_colorAllocated = false;
|
||||
}
|
||||
|
||||
if (_normalAllocated) {
|
||||
delete[] normals;
|
||||
_normalAllocated = false;
|
||||
}
|
||||
|
||||
_isDynamicallyAllocated = false;
|
||||
}
|
||||
}
|
||||
|
||||
/** When we not receive maxVertCount vertices, we must align it by ourself.
|
||||
* Too bad - not efficient. */
|
||||
void StdpipQBuffer::allocateDynamicData(u16 size, StdpipBag* bag) {
|
||||
TYRA_ASSERT(size <= maxVertCount, "Wrong size. Max buffer size in VU1 is ",
|
||||
maxVertCount, ". Provided: ", size);
|
||||
TYRA_ASSERT(!_isDynamicallyAllocated, "Buffer is already allocated");
|
||||
|
||||
vertices = new (std::align_val_t(sizeof(VECTOR))) Vec4[size];
|
||||
|
||||
if (bag->texture != nullptr) {
|
||||
sts = new (std::align_val_t(sizeof(VECTOR))) Vec4[size];
|
||||
_stAllocated = true;
|
||||
}
|
||||
|
||||
if (bag->color->many != nullptr) {
|
||||
colors = new (std::align_val_t(sizeof(VECTOR))) Vec4[size];
|
||||
_colorAllocated = true;
|
||||
}
|
||||
|
||||
if (bag->lighting != nullptr) {
|
||||
normals = new (std::align_val_t(sizeof(VECTOR))) Vec4[size];
|
||||
_normalAllocated = true;
|
||||
}
|
||||
|
||||
_isDynamicallyAllocated = true;
|
||||
}
|
||||
|
||||
bool StdpipQBuffer::any() const { return size > 0; }
|
||||
|
||||
void StdpipQBuffer::print() const {
|
||||
auto text = getPrint(nullptr);
|
||||
printf("%s\n", text.c_str());
|
||||
}
|
||||
|
||||
void StdpipQBuffer::print(const char* name) const {
|
||||
auto text = getPrint(name);
|
||||
printf("%s\n", text.c_str());
|
||||
}
|
||||
|
||||
std::string StdpipQBuffer::getPrint(const char* name) const {
|
||||
std::stringstream res;
|
||||
if (name) {
|
||||
res << name << "(";
|
||||
} else {
|
||||
res << "Path1Buffer(";
|
||||
}
|
||||
res << std::fixed << std::setprecision(2);
|
||||
res << std::endl;
|
||||
res << "Size: " << static_cast<int>(size) << std::endl;
|
||||
|
||||
res << "Vectors: " << std::endl;
|
||||
for (u32 i = 0; i < size; i++)
|
||||
res << i << ": " << vertices[i].getPrint() << std::endl;
|
||||
|
||||
if (bag->texture != nullptr) {
|
||||
res << "STs: " << std::endl;
|
||||
for (u32 i = 0; i < size; i++)
|
||||
res << i << ": " << sts[i].getPrint() << std::endl;
|
||||
}
|
||||
|
||||
if (bag->color->many != nullptr) {
|
||||
res << "Colors: " << std::endl;
|
||||
for (u32 i = 0; i < size; i++)
|
||||
res << i << ": " << colors[i].getPrint() << std::endl;
|
||||
}
|
||||
|
||||
if (bag->lighting != nullptr) {
|
||||
res << "Normals: " << std::endl;
|
||||
for (u32 i = 0; i < size; i++) {
|
||||
res << i << ": " << normals[i].getPrint();
|
||||
if (i < size - 1) {
|
||||
res << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
res << ")";
|
||||
return res.str();
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,320 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# 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/std/core/path1/stdpip_qbuffer_renderer.hpp"
|
||||
#include "renderer/3d/pipeline/std/core/path1/programs/stdpip_vu1_shared_defines.h"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
/**
|
||||
* VU1 = 1000 vert
|
||||
*
|
||||
* Quadbuffering:
|
||||
* 2 main buffers = 1000 / 2 = 500 vert
|
||||
* 2 kick buffers = 500 / 2 = 250 vert
|
||||
*
|
||||
* Vert data:
|
||||
* Pos + Normal + ST + Color = 4
|
||||
* = 4 * 48 = 192
|
||||
*
|
||||
* Other data:
|
||||
* mvp matrix, light matrix, tags = 14
|
||||
* 20 light vectors, light intesities = 25
|
||||
* = 14 + 25 = 39
|
||||
*
|
||||
* All data:
|
||||
* = 192 + 39 = 231
|
||||
*
|
||||
*/
|
||||
|
||||
StdpipQBufferRenderer::StdpipQBufferRenderer() {
|
||||
context = 0;
|
||||
lastProgramName = StdipUndefinedProgram;
|
||||
staticDataPacket = packet2_create(3, P2_TYPE_NORMAL, P2_MODE_CHAIN, true);
|
||||
objectDataPacket = packet2_create(16, P2_TYPE_NORMAL, P2_MODE_CHAIN, true);
|
||||
programsPacket = nullptr;
|
||||
}
|
||||
StdpipQBufferRenderer::~StdpipQBufferRenderer() {
|
||||
packet2_free(packets[0]);
|
||||
packet2_free(packets[1]);
|
||||
packet2_free(staticDataPacket);
|
||||
packet2_free(objectDataPacket);
|
||||
|
||||
if (programsPacket) packet2_free(programsPacket);
|
||||
}
|
||||
|
||||
void StdpipQBufferRenderer::init(RendererCore* t_core) {
|
||||
path1 = t_core->getPath1();
|
||||
clipper.init(t_core->getSettings());
|
||||
rendererCore = t_core;
|
||||
|
||||
dma_channel_initialize(DMA_CHANNEL_VIF1, NULL, 0);
|
||||
dma_channel_fast_waits(DMA_CHANNEL_VIF1);
|
||||
|
||||
const u32 VU1_PACKET_SIZE = 16;
|
||||
|
||||
packets[0] =
|
||||
packet2_create(VU1_PACKET_SIZE, P2_TYPE_NORMAL, P2_MODE_CHAIN, true);
|
||||
|
||||
packets[1] =
|
||||
packet2_create(VU1_PACKET_SIZE, P2_TYPE_NORMAL, P2_MODE_CHAIN, true);
|
||||
|
||||
setProgramsCache();
|
||||
|
||||
reinitVU1();
|
||||
|
||||
TYRA_LOG("Renderer3DQBufferRenderer initialized");
|
||||
}
|
||||
|
||||
void StdpipQBufferRenderer::reinitVU1() {
|
||||
sendStaticData();
|
||||
uploadPrograms();
|
||||
setDoubleBuffer();
|
||||
}
|
||||
|
||||
StdpipQBuffer* StdpipQBufferRenderer::getBuffer() { return &buffers[context]; }
|
||||
|
||||
void StdpipQBufferRenderer::sendObjectData(
|
||||
StdpipBag* 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->getLightDirections(), 3,
|
||||
false);
|
||||
|
||||
packet2_utils_vu_add_unpack_data(objectDataPacket, VU1_LIGHTS_COLORS_ADDR,
|
||||
bag->lighting->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_u32(objectDataPacket, 0); // not used, padding
|
||||
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 StdpipQBufferRenderer::setInfo(StdpipInfoBag* bag) {
|
||||
rendererCore->gs.prim.antialiasing = bag->antiAliasingEnabled;
|
||||
rendererCore->gs.prim.blending = bag->blendingEnabled;
|
||||
rendererCore->gs.prim.shading = bag->shadingType;
|
||||
}
|
||||
|
||||
void StdpipQBufferRenderer::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 StdpipQBufferRenderer::setProgramsCache() {
|
||||
VU1Program** programs = new VU1Program*[8];
|
||||
programs[0] = repository.getProgram(StdpipCullColor);
|
||||
programs[1] = repository.getProgram(StdpipAsIsColor);
|
||||
programs[2] = repository.getProgram(StdpipCullDirLights);
|
||||
programs[3] = repository.getProgram(StdpipAsIsDirLights);
|
||||
programs[4] = repository.getProgram(StdpipCullTextureDirLights);
|
||||
programs[5] = repository.getProgram(StdpipAsIsTextureDirLights);
|
||||
programs[6] = repository.getProgram(StdpipCullTextureColor);
|
||||
programs[7] = repository.getProgram(StdpipAsIsTextureColor);
|
||||
programsPacket = path1->createProgramsCache(programs, 8, 0);
|
||||
delete[] programs;
|
||||
}
|
||||
|
||||
void StdpipQBufferRenderer::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 StdpipQBufferRenderer::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
|
||||
}
|
||||
|
||||
void StdpipQBufferRenderer::cull(StdpipQBuffer* buffer) {
|
||||
if (buffer->size == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto program = getCullProgramByBag(buffer->bag);
|
||||
addBufferDataToPacket(program, buffer);
|
||||
sendPacket();
|
||||
}
|
||||
|
||||
// void StdpipQBufferRenderer::sendFinishTag() {
|
||||
// StdpipQBufferRenderer way proposition
|
||||
// auto program = path1->getProgramByName(Draw_Finish);
|
||||
// addBufferDataToPacket(program, nullptr);
|
||||
// sendPacket();
|
||||
|
||||
// packet2_t* packet2 = packet2_create(8, P2_TYPE_NORMAL, P2_MODE_CHAIN,
|
||||
// true); auto program =
|
||||
// static_cast<VU1DrawFinish*>(getProgramByName(Draw_Finish));
|
||||
|
||||
// program->addTag(packet2, prim);
|
||||
// packet2_utils_vu_add_start_program(packet2,
|
||||
// program->getDestinationAddress()); packet2_utils_vu_add_end_tag(packet2);
|
||||
// dma_channel_wait(DMA_CHANNEL_VIF1, 0);
|
||||
// dma_channel_send_packet2(packet2, DMA_CHANNEL_VIF1, true);
|
||||
// packet2_free(packet2);
|
||||
// }
|
||||
|
||||
void StdpipQBufferRenderer::clip(StdpipQBuffer* buffer) {
|
||||
if (buffer->size == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto program = getAsIsProgramByBag(buffer->bag);
|
||||
clipper.clip(buffer);
|
||||
|
||||
if (buffer->any()) {
|
||||
if (buffer) addBufferDataToPacket(program, buffer);
|
||||
sendPacket();
|
||||
}
|
||||
}
|
||||
|
||||
void StdpipQBufferRenderer::clearLastProgramName() {
|
||||
lastProgramName = StdipUndefinedProgram;
|
||||
}
|
||||
|
||||
void StdpipQBufferRenderer::addBufferDataToPacket(StdpipVU1Program* program,
|
||||
StdpipQBuffer* buffer) {
|
||||
currentPacket = packets[context];
|
||||
packet2_reset(currentPacket, false);
|
||||
|
||||
program->addBufferDataToPacket(currentPacket, buffer, &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 StdpipQBufferRenderer::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 StdpipQBufferRenderer::setMaxVertCount(const u32& count) {
|
||||
buffers[0].setMaxVertCount(count);
|
||||
buffers[1].setMaxVertCount(count);
|
||||
clipper.setMaxVertCount(count);
|
||||
}
|
||||
|
||||
StdpipVU1Program* StdpipQBufferRenderer::getAsIsProgramByBag(
|
||||
const StdpipBag* bag) {
|
||||
auto programType = getDrawProgramTypeByBag(bag);
|
||||
|
||||
if (programType == StdpipVU1TextureDirLights)
|
||||
return getProgramByName(StdpipAsIsTextureDirLights);
|
||||
else if (programType == StdpipVU1DirLights)
|
||||
return getProgramByName(StdpipAsIsDirLights);
|
||||
else if (programType == StdpipVU1TextureColor)
|
||||
return getProgramByName(StdpipAsIsTextureColor);
|
||||
else
|
||||
return getProgramByName(StdpipAsIsColor);
|
||||
}
|
||||
|
||||
StdpipVU1Program* StdpipQBufferRenderer::getCullProgramByBag(
|
||||
const StdpipBag* bag) {
|
||||
auto programType = getDrawProgramTypeByBag(bag);
|
||||
return getCullProgramByType(programType);
|
||||
}
|
||||
|
||||
StdpipVU1Program* StdpipQBufferRenderer::getProgramByName(
|
||||
const StdpipProgramName& name) {
|
||||
return repository.getProgram(name);
|
||||
}
|
||||
|
||||
StdpipVU1Program* StdpipQBufferRenderer::getCullProgramByParams(
|
||||
const bool& isLightingEnabled, const bool& isTextureEnabled) {
|
||||
auto type = getDrawProgramTypeByParams(isLightingEnabled, isTextureEnabled);
|
||||
return getCullProgramByType(type);
|
||||
}
|
||||
|
||||
StdpipVU1Program* StdpipQBufferRenderer::getCullProgramByType(
|
||||
const StdpipProgramType& programType) {
|
||||
if (programType == StdpipVU1TextureDirLights)
|
||||
return getProgramByName(StdpipCullTextureDirLights);
|
||||
else if (programType == StdpipVU1DirLights)
|
||||
return getProgramByName(StdpipCullDirLights);
|
||||
else if (programType == StdpipVU1TextureColor)
|
||||
return getProgramByName(StdpipCullTextureColor);
|
||||
else
|
||||
return getProgramByName(StdpipCullColor);
|
||||
}
|
||||
|
||||
StdpipProgramType StdpipQBufferRenderer::getDrawProgramTypeByBag(
|
||||
const StdpipBag* bag) const {
|
||||
auto isLightingEnabled = bag->lighting != nullptr;
|
||||
auto isTextureEnabled = bag->texture != nullptr;
|
||||
return getDrawProgramTypeByParams(isLightingEnabled, isTextureEnabled);
|
||||
}
|
||||
|
||||
StdpipProgramType StdpipQBufferRenderer::getDrawProgramTypeByParams(
|
||||
const bool& isLightingEnabled, const bool& isTextureEnabled) const {
|
||||
if (isLightingEnabled && isTextureEnabled)
|
||||
return StdpipVU1TextureDirLights;
|
||||
else if (isLightingEnabled)
|
||||
return StdpipVU1DirLights;
|
||||
else if (isTextureEnabled)
|
||||
return StdpipVU1TextureColor;
|
||||
else
|
||||
return StdpipVU1Color;
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# 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/std/core/path1/stdpip_vu1_program.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
StdpipVU1Program::StdpipVU1Program(const StdpipProgramName& 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();
|
||||
}
|
||||
|
||||
StdpipVU1Program::~StdpipVU1Program() {}
|
||||
|
||||
const StdpipProgramName& StdpipVU1Program::getName() const { return name; }
|
||||
|
||||
u32& StdpipVU1Program::getReglist() { return reglist; }
|
||||
|
||||
void StdpipVU1Program::addBufferDataToPacket(packet2_t* packet,
|
||||
StdpipQBuffer* buffer,
|
||||
prim_t* prim) {
|
||||
addStandardBufferDataToPacket(packet, buffer, prim);
|
||||
addProgramQBufferDataToPacket(packet, buffer);
|
||||
}
|
||||
|
||||
void StdpipVU1Program::addStandardBufferDataToPacket(packet2_t* packet,
|
||||
StdpipQBuffer* buffer,
|
||||
prim_t* prim) {
|
||||
if (buffer->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, buffer->size); // vertex count
|
||||
|
||||
packet2_utils_gs_add_prim_giftag(packet, prim, buffer->size, reglist,
|
||||
reglistCount, 0);
|
||||
}
|
||||
packet2_utils_vu_close_unpack(packet);
|
||||
}
|
||||
|
||||
u16 StdpipVU1Program::getMaxVertCount(const bool& singleColorEnabled,
|
||||
const u16& bufferSize) const {
|
||||
u16 res = bufferSize - 4;
|
||||
u8 colorElementsPerVertex =
|
||||
singleColorEnabled ? (elementsPerVertex - 1) : elementsPerVertex;
|
||||
res /= (colorElementsPerVertex + reglistCount);
|
||||
|
||||
// Buffer size = VU1 double buffer size (xtop)
|
||||
// res = qbuffer size (directly inside VU1)
|
||||
|
||||
// Must be dividable by 3 and the result also dividable by 3. Why?
|
||||
// 1st dividable reason - triangle, and packaging system in 3d rendering
|
||||
// 2nd dividable reason - subpackaging system. We are splitting packages into
|
||||
// 3 subpackages in 3d renderer.
|
||||
res = res / 3 / 3;
|
||||
res = res * 3 * 3;
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,227 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# 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/std/core/std_pipeline_core.hpp"
|
||||
#include "renderer/core/renderer_core.hpp"
|
||||
#include "thread/threading.hpp"
|
||||
|
||||
// #define TYRA_RENDERER_VERBOSE_LOG 1
|
||||
|
||||
#ifdef TYRA_RENDERER_VERBOSE_LOG
|
||||
#define Verbose(...) Debug::writeLines("VRB: ", ##__VA_ARGS__, "\n")
|
||||
#else
|
||||
#define Verbose(...) ((void)0)
|
||||
#endif
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
StdPipelineCore::StdPipelineCore() { maxVertCount = 0; }
|
||||
|
||||
StdPipelineCore::~StdPipelineCore() {}
|
||||
|
||||
void StdPipelineCore::init(RendererCore* t_core) {
|
||||
rendererCore = t_core;
|
||||
qbufferRenderer.init(t_core);
|
||||
packager.init(&rendererCore->renderer3D.frustumPlanes);
|
||||
}
|
||||
|
||||
void StdPipelineCore::reinitStandardVU1Programs() {
|
||||
qbufferRenderer.reinitVU1();
|
||||
}
|
||||
|
||||
u32 StdPipelineCore::getMaxVertCountByBag(const StdpipBag* bag) {
|
||||
return qbufferRenderer.getCullProgramByBag(bag)->getMaxVertCount(
|
||||
bag->color->many == nullptr, qbufferRenderer.getBufferSize());
|
||||
}
|
||||
|
||||
u32 StdPipelineCore::getMaxVertCountByParams(const bool& isSingleColor,
|
||||
const bool& isLightingEnabled,
|
||||
const bool& isTextureEnabled) {
|
||||
return qbufferRenderer
|
||||
.getCullProgramByParams(isLightingEnabled, isTextureEnabled)
|
||||
->getMaxVertCount(isSingleColor, qbufferRenderer.getBufferSize());
|
||||
}
|
||||
|
||||
void StdPipelineCore::render(StdpipBag* bag, StdpipBagPackagesBBox* bbox) {
|
||||
if (bag->count <= 0) return;
|
||||
|
||||
TYRA_ASSERT(bag->vertices != nullptr,
|
||||
"Vertices are required in 3D render bag!");
|
||||
TYRA_ASSERT(bag->info != nullptr, "Info bag is required in 3D render bag!");
|
||||
TYRA_ASSERT(bag->info->model != nullptr,
|
||||
"Info bag's model pointer is empty!");
|
||||
TYRA_ASSERT(bag->color != nullptr, "Color bag is required in 3D render bag!");
|
||||
TYRA_ASSERT(bag->color->single || bag->color->many,
|
||||
"At least one color is required in 3D render bag!");
|
||||
TYRA_ASSERT((!bag->color->many && !bag->lighting) ||
|
||||
(bag->color->many && !bag->lighting) ||
|
||||
(!bag->color->many && bag->lighting),
|
||||
"Multicolor is not supported with lighting, please choose one!");
|
||||
TYRA_ASSERT(
|
||||
!bag->lighting || (bag->lighting->lightMatrix && bag->lighting->normals),
|
||||
"If you want lighting, please provide light matrix and normals!");
|
||||
TYRA_ASSERT(
|
||||
!bag->texture || (bag->texture->texture && bag->texture->coordinates),
|
||||
"If you want texture, please provide texture and coordinates!");
|
||||
|
||||
StdpipBagPackagesBBox* renderBbox;
|
||||
|
||||
u32 maxVertCount = getMaxVertCountByBag(bag);
|
||||
|
||||
setMaxVertCount(maxVertCount);
|
||||
|
||||
if (!bbox)
|
||||
renderBbox =
|
||||
new StdpipBagPackagesBBox(bag->vertices, bag->count, maxVertCount);
|
||||
else
|
||||
renderBbox = bbox;
|
||||
|
||||
auto frustumCheck = renderBbox->getMainBBox()->clipIsInFrustum(
|
||||
rendererCore->renderer3D.frustumPlanes.getAll(), *bag->info->model);
|
||||
auto mvp = rendererCore->renderer3D.getViewProj() * *bag->info->model;
|
||||
|
||||
if (frustumCheck == OUTSIDE_FRUSTUM) return;
|
||||
|
||||
RendererCoreTextureBuffers* texBuffers = nullptr;
|
||||
if (bag->texture) {
|
||||
auto temp = rendererCore->texture.useTexture(bag->texture->texture);
|
||||
texBuffers = new RendererCoreTextureBuffers{temp.id, temp.core, temp.clut};
|
||||
}
|
||||
|
||||
qbufferRenderer.clearLastProgramName();
|
||||
|
||||
qbufferRenderer.sendObjectData(bag, &mvp, texBuffers);
|
||||
|
||||
packager.setRenderBBox(renderBbox);
|
||||
|
||||
qbufferRenderer.setClipperMVP(&mvp);
|
||||
|
||||
qbufferRenderer.setInfo(bag->info);
|
||||
|
||||
if (frustumCheck == IN_FRUSTUM ||
|
||||
(frustumCheck == PARTIALLY_IN_FRUSTUM && bag->info->noClipChecks)) {
|
||||
u16 packagesCount = 0;
|
||||
auto biggerPkgs = packager.create(&packagesCount, bag, maxVertCount);
|
||||
Verbose("Material - in frustum. Pkgs: ", packagesCount,
|
||||
" size: ", static_cast<int>(biggerPkgs[0].size));
|
||||
for (u16 i = 0; i < packagesCount; i++) {
|
||||
Verbose(i, " package - cull by data pointer");
|
||||
auto buffer = qbufferRenderer.getBuffer();
|
||||
buffer->fillByPointer(biggerPkgs[i]);
|
||||
qbufferRenderer.cull(buffer);
|
||||
}
|
||||
delete[] biggerPkgs;
|
||||
} else if (frustumCheck == PARTIALLY_IN_FRUSTUM) {
|
||||
u16 packagesCount = 0;
|
||||
if (bag->count >= maxVertCount * 2) {
|
||||
auto packages = packager.create(&packagesCount, bag, maxVertCount);
|
||||
Verbose("Material - partial. Packages: ", packagesCount);
|
||||
renderPkgs(packages, packagesCount);
|
||||
delete[] packages;
|
||||
} else {
|
||||
auto subpkgs = packager.create(&packagesCount, bag, maxVertCount / 3);
|
||||
Verbose("Material - partial. Subpackages: ", packagesCount);
|
||||
renderSubpkgs(subpkgs, packagesCount);
|
||||
delete[] subpkgs;
|
||||
}
|
||||
}
|
||||
|
||||
if (!bbox) delete renderBbox;
|
||||
if (texBuffers) delete texBuffers;
|
||||
|
||||
Threading::switchThread();
|
||||
|
||||
Verbose("Render finished");
|
||||
}
|
||||
|
||||
void StdPipelineCore::renderPkgs(StdpipBagPackage* packages, u16 count) {
|
||||
for (u16 i = 0; i < count; i++) {
|
||||
if (packages[i].isInFrustum == IN_FRUSTUM) {
|
||||
Verbose(i, " - package in frustum -> cull");
|
||||
auto buffer = qbufferRenderer.getBuffer();
|
||||
buffer->fillByPointer(packages[i]);
|
||||
qbufferRenderer.cull(buffer);
|
||||
} else if (packages[i].isInFrustum == PARTIALLY_IN_FRUSTUM) {
|
||||
u16 subpkgsSize = 0;
|
||||
auto packages1By3 =
|
||||
packager.create(&subpkgsSize, packages[i], maxVertCount / 3);
|
||||
Verbose(i, " - partial package. Created subpkgs: ", subpkgsSize);
|
||||
|
||||
renderSubpkgs(packages1By3, subpkgsSize);
|
||||
delete[] packages1By3;
|
||||
}
|
||||
Verbose(i, " - package skipped (outside)");
|
||||
}
|
||||
}
|
||||
|
||||
void StdPipelineCore::renderSubpkgs(StdpipBagPackage* subpkgs, u16 count) {
|
||||
std::vector<u16> doneIndexes;
|
||||
std::vector<u16> loadedIndexes;
|
||||
|
||||
// Check if some subpkgs are full in frustum
|
||||
for (u16 i = 0; i < count; i++) {
|
||||
if (subpkgs[i].isInFrustum == IN_FRUSTUM) {
|
||||
if (loadedIndexes.size() <= 1) {
|
||||
Verbose(i, " - subpackage in frustum -> load");
|
||||
loadedIndexes.push_back(i);
|
||||
} else { // Hmm, this will never happen?
|
||||
Verbose(i, " - subpackage in frustum, cull all 3 subpkgs");
|
||||
auto buffer = qbufferRenderer.getBuffer();
|
||||
buffer->fillByCopyMax(subpkgs[loadedIndexes[0]],
|
||||
subpkgs[loadedIndexes[1]], subpkgs[i]);
|
||||
qbufferRenderer.cull(buffer);
|
||||
doneIndexes.push_back(loadedIndexes[0]);
|
||||
doneIndexes.push_back(loadedIndexes[1]);
|
||||
doneIndexes.push_back(i);
|
||||
loadedIndexes.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (loadedIndexes.size() == 2) {
|
||||
Verbose("2 in frustum subpkgs left -> cull them");
|
||||
auto buffer = qbufferRenderer.getBuffer();
|
||||
buffer->fillByCopy1By2(subpkgs[loadedIndexes[0]],
|
||||
subpkgs[loadedIndexes[1]]);
|
||||
qbufferRenderer.cull(buffer);
|
||||
doneIndexes.push_back(loadedIndexes[0]);
|
||||
doneIndexes.push_back(loadedIndexes[1]);
|
||||
} else if (loadedIndexes.size() == 1) {
|
||||
Verbose("1 in frustum subpkg left -> cull it");
|
||||
auto buffer = qbufferRenderer.getBuffer();
|
||||
buffer->fillByPointer(subpkgs[loadedIndexes[0]]);
|
||||
qbufferRenderer.cull(buffer);
|
||||
doneIndexes.push_back(loadedIndexes[0]);
|
||||
}
|
||||
|
||||
for (u16 i = 0; i < count; i++) {
|
||||
bool isSkip = subpkgs[i].isInFrustum == OUTSIDE_FRUSTUM ||
|
||||
std::find(doneIndexes.begin(), doneIndexes.end(), i) !=
|
||||
doneIndexes.end();
|
||||
|
||||
if (isSkip) {
|
||||
Verbose(i, " - subpkg skipped, already rendered/outside");
|
||||
continue;
|
||||
}
|
||||
|
||||
auto buffer = qbufferRenderer.getBuffer();
|
||||
buffer->fillByCopy1By3(subpkgs[i]);
|
||||
Verbose(i, " - subpkg out/partial -> send to clipper");
|
||||
qbufferRenderer.clip(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void StdPipelineCore::setMaxVertCount(const u32& count) {
|
||||
maxVertCount = count;
|
||||
packager.setMaxVertCount(count);
|
||||
qbufferRenderer.setMaxVertCount(count);
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# 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/std/std_pipeline.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
StdPipeline::StdPipeline() { colorsCache = new Vec4[4]; }
|
||||
|
||||
StdPipeline::~StdPipeline() { delete[] colorsCache; }
|
||||
|
||||
void StdPipeline::init(RendererCore* t_core) {
|
||||
rendererCore = t_core;
|
||||
core.init(t_core);
|
||||
}
|
||||
|
||||
void StdPipeline::onUse() { core.reinitStandardVU1Programs(); }
|
||||
|
||||
void StdPipeline::render(Mesh* mesh, const StdpipOptions* options) {
|
||||
auto model = mesh->getModelMatrix();
|
||||
|
||||
MeshFrame* frameFrom = mesh->getFramesCount() > 0
|
||||
? mesh->getFrame(mesh->getCurrentAnimationFrame())
|
||||
: mesh->getFrame(0);
|
||||
|
||||
MeshFrame* frameTo = mesh->getFramesCount() > 0
|
||||
? mesh->getFrame(mesh->getNextAnimationFrame())
|
||||
: nullptr;
|
||||
|
||||
auto* infoBag = getInfoBag(mesh, options, &model);
|
||||
|
||||
if (options->lighting) setLightingColorsCache(options->lighting);
|
||||
|
||||
for (u32 i = 0; i < mesh->getMaterialsCount(); i++) {
|
||||
auto* material = mesh->getMaterial(i);
|
||||
|
||||
// 2x bufory[maxVertCount*2] -> pętla po mniejszych częściach i czestsze
|
||||
// rendery
|
||||
|
||||
// TODO: Double buffering in future
|
||||
// auto maxVertCount = core->renderer3D.getMaxVertCountByParams(
|
||||
// material->isSingleColorActivated(), material->getNormalFaces(),
|
||||
// material->getTextureCoordFaces());
|
||||
|
||||
StdpipBag bag;
|
||||
addVertices(mesh, material, &bag, frameFrom, frameTo);
|
||||
bag.info = infoBag;
|
||||
bag.color = getColorBag(mesh, material, frameFrom, frameTo);
|
||||
bag.texture = getTextureBag(mesh, material, frameFrom, frameTo);
|
||||
bag.lighting =
|
||||
getLightingBag(mesh, material, &model, frameFrom, frameTo, options);
|
||||
|
||||
core.render(&bag);
|
||||
|
||||
deallocDrawBags(&bag, material);
|
||||
}
|
||||
|
||||
delete infoBag;
|
||||
}
|
||||
|
||||
void StdPipeline::addVertices(Mesh* mesh, MeshMaterial* material,
|
||||
StdpipBag* bag, MeshFrame* frameFrom,
|
||||
MeshFrame* frameTo) const {
|
||||
bag->count = material->getFacesCount();
|
||||
bag->vertices = new Vec4[bag->count];
|
||||
|
||||
for (u32 i = 0; i < bag->count; i++) {
|
||||
auto& face = material->getVertexFaces()[i];
|
||||
if (frameTo == nullptr) {
|
||||
bag->vertices[i] = frameFrom->getVertices()[face];
|
||||
} else {
|
||||
Vec4::setLerp(&bag->vertices[i], frameFrom->getVertices()[face],
|
||||
frameTo->getVertices()[face],
|
||||
mesh->getAnimState().interpolation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StdpipInfoBag* StdPipeline::getInfoBag(Mesh* mesh, const StdpipOptions* options,
|
||||
M4x4* model) const {
|
||||
auto* result = new StdpipInfoBag();
|
||||
|
||||
if (options) {
|
||||
result->antiAliasingEnabled = options->antiAliasingEnabled;
|
||||
result->blendingEnabled = options->blendingEnabled;
|
||||
result->shadingType = options->shadingType;
|
||||
result->noClipChecks = options->noClipChecks;
|
||||
} else {
|
||||
result->antiAliasingEnabled = false;
|
||||
result->blendingEnabled = true;
|
||||
result->shadingType = StdpipShadingFlat;
|
||||
result->noClipChecks = true;
|
||||
}
|
||||
|
||||
result->model = model;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
StdpipColorBag* StdPipeline::getColorBag(Mesh* mesh, MeshMaterial* material,
|
||||
MeshFrame* frameFrom,
|
||||
MeshFrame* frameTo) const {
|
||||
auto* result = new StdpipColorBag();
|
||||
|
||||
if (material->isSingleColorActivated()) {
|
||||
result->single = &material->singleColor;
|
||||
} else {
|
||||
result->many = new Color[material->getFacesCount()];
|
||||
|
||||
for (u32 i = 0; i < material->getFacesCount(); i++) {
|
||||
auto& face = material->getColorFaces()[i];
|
||||
if (frameTo == nullptr) {
|
||||
result->many[i] = frameFrom->getColors()[face];
|
||||
} else {
|
||||
Vec4::setLerp(
|
||||
reinterpret_cast<Vec4*>(&result->many[i]),
|
||||
reinterpret_cast<const Vec4&>(frameFrom->getColors()[face]),
|
||||
reinterpret_cast<const Vec4&>(frameTo->getColors()[face]),
|
||||
mesh->getAnimState().interpolation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
StdpipTextureBag* StdPipeline::getTextureBag(Mesh* mesh, MeshMaterial* material,
|
||||
MeshFrame* frameFrom,
|
||||
MeshFrame* frameTo) {
|
||||
if (!material->getTextureCoordFaces()) return nullptr;
|
||||
|
||||
auto* result = new StdpipTextureBag();
|
||||
|
||||
result->texture =
|
||||
rendererCore->texture.repository.getBySpriteOrMesh(material->getId());
|
||||
TYRA_ASSERT(result->texture, "Texture for material id: ", material->getId(),
|
||||
" was not found in texture repository!");
|
||||
|
||||
result->coordinates = new Vec4[material->getFacesCount()];
|
||||
|
||||
for (u32 i = 0; i < material->getFacesCount(); i++) {
|
||||
auto& face = material->getTextureCoordFaces()[i];
|
||||
if (frameTo == nullptr) {
|
||||
result->coordinates[i] = frameFrom->getTextureCoords()[face];
|
||||
} else {
|
||||
Vec4::setLerp(&result->coordinates[i],
|
||||
frameFrom->getTextureCoords()[face],
|
||||
frameTo->getTextureCoords()[face],
|
||||
mesh->getAnimState().interpolation);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
StdpipLightingBag* StdPipeline::getLightingBag(
|
||||
Mesh* mesh, MeshMaterial* material, M4x4* model, MeshFrame* frameFrom,
|
||||
MeshFrame* frameTo, const StdpipOptions* options) const {
|
||||
if (!material->getNormalFaces() || options == nullptr ||
|
||||
options->lighting == nullptr)
|
||||
return nullptr;
|
||||
|
||||
auto* result = new StdpipLightingBag(true);
|
||||
result->lightMatrix = model;
|
||||
|
||||
result->setLightsManually(colorsCache,
|
||||
options->lighting->directionalDirections);
|
||||
|
||||
result->normals = new Vec4[material->getFacesCount()];
|
||||
|
||||
for (u32 i = 0; i < material->getFacesCount(); i++) {
|
||||
auto& face = material->getNormalFaces()[i];
|
||||
if (frameTo == nullptr) {
|
||||
result->normals[i] = frameFrom->getNormals()[face];
|
||||
} else {
|
||||
Vec4::setLerp(&result->normals[i], frameFrom->getNormals()[face],
|
||||
frameTo->getNormals()[face],
|
||||
mesh->getAnimState().interpolation);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void StdPipeline::setLightingColorsCache(
|
||||
StdpipLightingOptions* lightingOptions) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
colorsCache[i] =
|
||||
reinterpret_cast<Vec4&>(lightingOptions->directionalColors[i]);
|
||||
}
|
||||
colorsCache[3] = reinterpret_cast<Vec4&>(*lightingOptions->ambientColor);
|
||||
}
|
||||
|
||||
void StdPipeline::deallocDrawBags(StdpipBag* bag,
|
||||
MeshMaterial* material) const {
|
||||
if (bag->color->many) {
|
||||
delete[] bag->color->many;
|
||||
}
|
||||
|
||||
if (bag->texture) {
|
||||
delete[] bag->texture->coordinates;
|
||||
delete bag->texture;
|
||||
}
|
||||
|
||||
if (bag->lighting) {
|
||||
delete[] bag->lighting->normals;
|
||||
delete bag->lighting;
|
||||
}
|
||||
|
||||
delete[] bag->vertices;
|
||||
delete bag->color;
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,27 @@
|
||||
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "renderer/3d/renderer_3d.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
Renderer3D::Renderer3D() { currentPipeline = nullptr; }
|
||||
|
||||
Renderer3D::~Renderer3D() {}
|
||||
|
||||
void Renderer3D::usePipeline(Renderer3DPipeline* pipeline) {
|
||||
if (currentPipeline != pipeline) {
|
||||
currentPipeline = pipeline;
|
||||
currentPipeline->onUse();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
Reference in New Issue
Block a user