finished tutorial 03

This commit is contained in:
h4570
2022-08-21 16:40:26 +02:00
parent 4303cc2c97
commit 409ee294eb
27 changed files with 349 additions and 25 deletions
-2
View File
@@ -1,7 +1,5 @@
------------ Tyra's v2.0 roadmap to publish on GitHub ------------ ------------ Tyra's v2.0 roadmap to publish on GitHub ------------
- [Tutorials] 3. Minecraft cube - explain this pipeline, and explain that there are many 3D pipelines
- [Tutorials] 4. Mesh rendering - explain staticPipeline, render .obj file via Mesh class, explain that this is high-level - [Tutorials] 4. Mesh rendering - explain staticPipeline, render .obj file via Mesh class, explain that this is high-level
abstract 3D object class, and what it have (animation etc) abstract 3D object class, and what it have (animation etc)
@@ -43,7 +43,7 @@ class MinecraftPipeline : public Renderer3DPipeline {
* @param fullClipChecks false = faster, simple PS2 clipping. True = slower, * @param fullClipChecks false = faster, simple PS2 clipping. True = slower,
* experimental "against each plane" clipping. * experimental "against each plane" clipping.
*/ */
void render(std::vector<McpipBlock*> blocks, Texture* t_tex, void render(std::vector<McpipBlock*> blocks, const Texture* t_tex,
const bool& isMulti = false, const bool& fullClipChecks = false); const bool& isMulti = false, const bool& fullClipChecks = false);
inline const float& getTextureOffset() const { inline const float& getTextureOffset() const {
+1
View File
@@ -27,6 +27,7 @@ class Renderer3D {
/** Deinitialize previous pipeline and initialize new pipeline */ /** Deinitialize previous pipeline and initialize new pipeline */
void usePipeline(Renderer3DPipeline* pipeline); void usePipeline(Renderer3DPipeline* pipeline);
void usePipeline(Renderer3DPipeline& pipeline);
private: private:
Renderer3DPipeline* currentPipeline; Renderer3DPipeline* currentPipeline;
@@ -16,11 +16,11 @@ namespace Tyra {
class CameraInfo3D { class CameraInfo3D {
public: public:
CameraInfo3D(Vec4* cameraPosition, Vec4* cameraLooksAt, CameraInfo3D(const Vec4* cameraPosition, const Vec4* cameraLooksAt,
Vec4* cameraUp = nullptr); const Vec4* cameraUp = nullptr);
~CameraInfo3D(); ~CameraInfo3D();
Vec4 *position, *looksAt, *up; const Vec4 *position, *looksAt, *up;
private: private:
static Vec4 defaultCameraUp; static Vec4 defaultCameraUp;
@@ -29,7 +29,7 @@ class Path3 {
void sendDrawFinishTag(); void sendDrawFinishTag();
void clearScreen(zbuffer_t* z, const Color& color); void clearScreen(zbuffer_t* z, const Color& color);
void sendTexture(Texture* texture, void sendTexture(const Texture* texture,
const RendererCoreTextureBuffers& texBuffers); const RendererCoreTextureBuffers& texBuffers);
private: private:
@@ -45,7 +45,7 @@ class Texture {
float getSizeInMB() const; float getSizeInMB() const;
inline texwrap_t* getWrapSettings() { return &wrap; } inline const texwrap_t* getWrapSettings() const { return &wrap; }
inline const std::vector<TextureLink>& getTextureLinks() const { inline const std::vector<TextureLink>& getTextureLinks() const {
return links; return links;
@@ -27,7 +27,7 @@ class RendererCoreTexture {
clutbuffer_t clut; clutbuffer_t clut;
TextureRepository repository; TextureRepository repository;
RendererCoreTextureBuffers useTexture(Texture* t_tex); RendererCoreTextureBuffers useTexture(const Texture* t_tex);
/** Called by renderer during initialization */ /** Called by renderer during initialization */
void init(RendererCoreGS* gs, Path3* path3); void init(RendererCoreGS* gs, Path3* path3);
@@ -27,7 +27,7 @@ class RendererCoreTextureSender {
void init(Path3* path3, RendererCoreGS* gs); void init(Path3* path3, RendererCoreGS* gs);
RendererCoreTextureBuffers allocate(Texture* t_texture); RendererCoreTextureBuffers allocate(const Texture* t_texture);
void deallocate(const RendererCoreTextureBuffers& texBuffers); void deallocate(const RendererCoreTextureBuffers& texBuffers);
@@ -37,8 +37,8 @@ class RendererCoreTextureSender {
RendererCoreGS* gs; RendererCoreGS* gs;
Path3* path3; Path3* path3;
TextureBpp getBppByPsm(const u32& psm); TextureBpp getBppByPsm(const u32& psm);
texbuffer_t* allocateTextureCore(Texture* t_texture); texbuffer_t* allocateTextureCore(const Texture* t_texture);
texbuffer_t* allocateTextureClut(Texture* t_texture); texbuffer_t* allocateTextureClut(const Texture* t_texture);
}; };
} // namespace Tyra } // namespace Tyra
@@ -83,8 +83,8 @@ void MinecraftPipeline::initBBox() {
bbox = new RenderBBox(block.vertices, block.count); bbox = new RenderBBox(block.vertices, block.count);
} }
void MinecraftPipeline::render(std::vector<McpipBlock*> blocks, Texture* t_tex, void MinecraftPipeline::render(std::vector<McpipBlock*> blocks,
const bool& isMulti, const Texture* t_tex, const bool& isMulti,
const bool& fullClipChecks) { const bool& fullClipChecks) {
auto texBuffers = rendererCore->texture.useTexture(t_tex); auto texBuffers = rendererCore->texture.useTexture(t_tex);
+4
View File
@@ -19,6 +19,10 @@ Renderer3D::~Renderer3D() {}
void Renderer3D::init(RendererCore* core) { utility.init(core); } void Renderer3D::init(RendererCore* core) { utility.init(core); }
void Renderer3D::usePipeline(Renderer3DPipeline& pipeline) {
usePipeline(&pipeline);
}
void Renderer3D::usePipeline(Renderer3DPipeline* pipeline) { void Renderer3D::usePipeline(Renderer3DPipeline* pipeline) {
if (currentPipeline != pipeline) { if (currentPipeline != pipeline) {
if (currentPipeline) currentPipeline->onUseEnd(); if (currentPipeline) currentPipeline->onUseEnd();
@@ -14,8 +14,9 @@ namespace Tyra {
Vec4 CameraInfo3D::defaultCameraUp = Vec4(0.0F, 1.0F, 0.0F); Vec4 CameraInfo3D::defaultCameraUp = Vec4(0.0F, 1.0F, 0.0F);
CameraInfo3D::CameraInfo3D(Vec4* t_cameraPosition, Vec4* t_cameraLooksAt, CameraInfo3D::CameraInfo3D(const Vec4* t_cameraPosition,
Vec4* t_cameraUp) { const Vec4* t_cameraLooksAt,
const Vec4* t_cameraUp) {
position = t_cameraPosition; position = t_cameraPosition;
looksAt = t_cameraLooksAt; looksAt = t_cameraLooksAt;
@@ -25,6 +26,7 @@ CameraInfo3D::CameraInfo3D(Vec4* t_cameraPosition, Vec4* t_cameraLooksAt,
up = t_cameraUp; up = t_cameraUp;
} }
} }
CameraInfo3D::~CameraInfo3D() {} CameraInfo3D::~CameraInfo3D() {}
} // namespace Tyra } // namespace Tyra
@@ -61,7 +61,7 @@ void Path3::clearScreen(zbuffer_t* z, const Color& color) {
dma_channel_send_packet2(clearScreenPacket, DMA_CHANNEL_GIF, true); dma_channel_send_packet2(clearScreenPacket, DMA_CHANNEL_GIF, true);
} }
void Path3::sendTexture(Texture* texture, void Path3::sendTexture(const Texture* texture,
const RendererCoreTextureBuffers& texBuffers) { const RendererCoreTextureBuffers& texBuffers) {
packet2_reset(texturePacket, false); packet2_reset(texturePacket, false);
@@ -83,8 +83,9 @@ void Path3::sendTexture(Texture* texture,
packet2_chain_open_cnt(texturePacket, 0, 0, 0); packet2_chain_open_cnt(texturePacket, 0, 0, 0);
packet2_update(texturePacket, packet2_update(texturePacket,
draw_texture_wrapping(texturePacket->next, 0, draw_texture_wrapping(
texture->getWrapSettings())); texturePacket->next, 0,
const_cast<texwrap_t*>(texture->getWrapSettings())));
packet2_chain_close_tag(texturePacket); packet2_chain_close_tag(texturePacket);
packet2_update(texturePacket, draw_texture_flush(texturePacket->next)); packet2_update(texturePacket, draw_texture_flush(texturePacket->next));
@@ -35,7 +35,8 @@ void RendererCoreTexture::updateClutBuffer(texbuffer_t* clutBuffer) {
} }
} }
RendererCoreTextureBuffers RendererCoreTexture::useTexture(Texture* t_tex) { RendererCoreTextureBuffers RendererCoreTexture::useTexture(
const Texture* t_tex) {
TYRA_ASSERT(t_tex != nullptr, "Provided nullptr texture!"); TYRA_ASSERT(t_tex != nullptr, "Provided nullptr texture!");
auto allocated = getAllocatedBuffersByTextureId(t_tex->id); auto allocated = getAllocatedBuffersByTextureId(t_tex->id);
@@ -23,7 +23,7 @@ void RendererCoreTextureSender::init(Path3* t_path3, RendererCoreGS* t_gs) {
} }
RendererCoreTextureBuffers RendererCoreTextureSender::allocate( RendererCoreTextureBuffers RendererCoreTextureSender::allocate(
Texture* t_texture) { const Texture* t_texture) {
texbuffer_t* core = allocateTextureCore(t_texture); texbuffer_t* core = allocateTextureCore(t_texture);
texbuffer_t* clut = nullptr; texbuffer_t* clut = nullptr;
@@ -54,7 +54,7 @@ void RendererCoreTextureSender::deallocate(
} }
texbuffer_t* RendererCoreTextureSender::allocateTextureCore( texbuffer_t* RendererCoreTextureSender::allocateTextureCore(
Texture* t_texture) { const Texture* t_texture) {
auto* result = new texbuffer_t; auto* result = new texbuffer_t;
const auto* core = t_texture->core; const auto* core = t_texture->core;
@@ -73,7 +73,7 @@ texbuffer_t* RendererCoreTextureSender::allocateTextureCore(
} }
texbuffer_t* RendererCoreTextureSender::allocateTextureClut( texbuffer_t* RendererCoreTextureSender::allocateTextureClut(
Texture* t_texture) { const Texture* t_texture) {
auto* result = new texbuffer_t; auto* result = new texbuffer_t;
const auto* clut = t_texture->clut; const auto* clut = t_texture->clut;
+1 -1
View File
@@ -1,4 +1,4 @@
TARGET := tutorial_01.elf TARGET := tutorial_02.elf
ENGINEDIR := ../../engine ENGINEDIR := ../../engine
#The Directories, Source, Includes, Objects, Binary and Resources #The Directories, Source, Includes, Objects, Binary and Resources
-1
View File
@@ -11,7 +11,6 @@
#pragma once #pragma once
#include <tyra> #include <tyra>
#include <memory.h>
namespace Tyra { namespace Tyra {
+3
View File
@@ -32,7 +32,10 @@ Tutorial02::~Tutorial02() {
void Tutorial02::init() { void Tutorial02::init() {
engine->renderer.setClearScreenColor(Color(32.0F, 32.0F, 32.0F)); engine->renderer.setClearScreenColor(Color(32.0F, 32.0F, 32.0F));
/** Sprite contains rectangle information. */
loadSprite(); loadSprite();
/** Texture contains png image. */
loadTexture(); loadTexture();
} }
+24
View File
@@ -0,0 +1,24 @@
TARGET := tutorial_03.elf
ENGINEDIR := ../../engine
#The Directories, Source, Includes, Objects, Binary and Resources
SRCDIR := src
INCDIR := inc
BUILDDIR := obj
TARGETDIR := bin
RESDIR := res
SRCEXT := cpp
VSMEXT := vsm
VCLEXT := vcl
VCLPPEXT := vclpp
DEPEXT := d
OBJEXT := o
#Flags, Libraries and Includes
CFLAGS :=
LIB :=
LIBDIRS :=
INC := -I$(INCDIR)
INCDEP := -I$(INCDIR)
include ../Makefile.tutorials-base
+4
View File
@@ -0,0 +1,4 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore
@@ -0,0 +1,54 @@
/*
# _____ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licensed under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#pragma once
#include <tyra>
#include <vector>
#include "./tutorial_block.hpp"
namespace Tyra {
class Tutorial03 : public Game {
public:
Tutorial03(Engine* engine);
~Tutorial03();
void init();
void loop();
private:
void loadTexture();
TutorialBlock getBlock(const u8& atlasX, const u8& atlasY,
const float& translationX);
void rotateBlock(TutorialBlock& block);
Engine* engine;
std::vector<TutorialBlock> blocks;
Texture* textureAtlas;
/**
* This is a 3D pipeline (renderer) which we will be using.
*
* Tyra has 3 pipelines:
* - Minecraft (this one)
* - Static (for static 3D objects)
* - Dynamic (for dynamic 3D objects)
*/
MinecraftPipeline mcpip;
/** Our camera */
Vec4 cameraPosition, cameraLookAt;
};
} // namespace Tyra
@@ -0,0 +1,42 @@
/*
# _____ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licensed under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#pragma once
#include <tyra>
namespace Tyra {
class TutorialBlock {
public:
TutorialBlock();
TutorialBlock(const TutorialBlock& v);
~TutorialBlock();
void updateModelMatrix();
M4x4 translation, rotation, scale;
/** Result matrix with translation, rotation and scale */
M4x4 model;
/** Color */
Color color;
/** Texture atlas offset */
Vec4 atlasOffset;
McpipBlock renderData;
private:
void setRenderData();
};
} // namespace Tyra
+4
View File
@@ -0,0 +1,4 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore
+4
View File
@@ -0,0 +1,4 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore
+4
View File
@@ -0,0 +1,4 @@
$ConfigFile = Join-Path $PSScriptRoot '../../windows-pcsx2.ps1'
. $ConfigFile
RunPCSX2
+27
View File
@@ -0,0 +1,27 @@
/*
# _____ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licensed under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#include "engine.hpp"
#include "tutorial_03.hpp"
/**
* In this tutorial we will learn:
* - What are the VU1 pipelines
* - How to create a 3D camera
* - What is the translation, rotation scale and model matrix
* - How to render 3D minecraft cubes
*/
int main() {
Tyra::Engine engine;
Tyra::Tutorial03 game(&engine);
engine.run(&game);
return 0;
}
+102
View File
@@ -0,0 +1,102 @@
/*
# _____ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licensed under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#include <tyra>
#include "tutorial_03.hpp"
namespace Tyra {
Tutorial03::Tutorial03(Engine* t_engine) : engine(t_engine) {
textureAtlas = nullptr;
}
Tutorial03::~Tutorial03() {
if (textureAtlas != nullptr) {
engine->renderer.core.texture.repository.free(textureAtlas);
}
}
void Tutorial03::init() {
loadTexture();
engine->renderer.setClearScreenColor(Color(32.0F, 32.0F, 32.0F));
cameraPosition = Vec4(0.0F, 0.0F, -10.0F); // Move camera one step back
cameraLookAt.unit(); // Look at the origin - (0,0,0)
/** Every 3D pipeline, needs to set RendererCore to it */
mcpip.setRenderer(&engine->renderer.core);
blocks.push_back(getBlock(0, 1, 2.0F));
blocks.push_back(getBlock(4, 0, -2.0F));
}
void Tutorial03::loop() {
rotateBlock(blocks[0]);
rotateBlock(blocks[1]);
/** Set camera info */
engine->renderer.beginFrame(CameraInfo3D(&cameraPosition, &cameraLookAt));
{
/**
* usePipeline() uploads pipeline's VU1 programs into VU1 memory and allows
* us to use it.
*/
engine->renderer.renderer3D.usePipeline(mcpip);
{
/** Render cobblestone */
mcpip.render({&blocks[0].renderData}, textureAtlas);
/** Render block using 6 textures from atlas (top-bottom) */
mcpip.render({&blocks[1].renderData}, textureAtlas, true);
}
}
engine->renderer.endFrame();
}
void Tutorial03::loadTexture() {
auto& repo = engine->renderer.getTextureRepository();
textureAtlas = repo.add(FileUtils::fromCwd("atlas.png"));
}
TutorialBlock Tutorial03::getBlock(const u8& atlasX, const u8& atlasY,
const float& translationX) {
TutorialBlock result;
// --- Set texture atlas offset
const u8 texturesInAtlasRow = 16;
const float textureOffset = 1.0F / texturesInAtlasRow;
/**
* Offset is X/Y coordinate of left up texture corner.
* Percentage is in range of 0.0F to 1.0F.
*/
result.atlasOffset = Vec4(atlasX * textureOffset, atlasY * textureOffset);
// --- Set default color
result.color = Color(128.0F, 128.0F, 128.0F, 128.0F);
result.translation.translateX(translationX);
/** Build final matrix which will be used in renderer */
result.updateModelMatrix();
return result;
}
void Tutorial03::rotateBlock(TutorialBlock& block) {
block.rotation.rotate(Vec4(0.01F, 0.02F, 0.03F));
block.updateModelMatrix();
}
} // namespace Tyra
@@ -0,0 +1,50 @@
/*
# _____ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licensed under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#include <tyra>
#include "tutorial_block.hpp"
namespace Tyra {
TutorialBlock::TutorialBlock() {
/** Set identity value for matrices (instead of random numbers) */
translation = M4x4::Identity;
rotation = M4x4::Identity;
scale = M4x4::Identity;
setRenderData();
}
/** Copy constructor */
TutorialBlock::TutorialBlock(const TutorialBlock& v) {
translation = v.translation;
rotation = v.rotation;
scale = v.scale;
model = v.model;
color = v.color;
atlasOffset = v.atlasOffset;
setRenderData();
}
TutorialBlock::~TutorialBlock() {}
/** Fill block's render data object */
void TutorialBlock::setRenderData() {
renderData.color = &color;
renderData.model = &model;
renderData.textureOffset = &atlasOffset;
}
void TutorialBlock::updateModelMatrix() {
model = translation * rotation * scale;
}
} // namespace Tyra