finished tutorial 03
This commit is contained in:
@@ -1,7 +1,5 @@
|
||||
------------ 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
|
||||
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,
|
||||
* 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);
|
||||
|
||||
inline const float& getTextureOffset() const {
|
||||
|
||||
@@ -27,6 +27,7 @@ class Renderer3D {
|
||||
|
||||
/** Deinitialize previous pipeline and initialize new pipeline */
|
||||
void usePipeline(Renderer3DPipeline* pipeline);
|
||||
void usePipeline(Renderer3DPipeline& pipeline);
|
||||
|
||||
private:
|
||||
Renderer3DPipeline* currentPipeline;
|
||||
|
||||
@@ -16,11 +16,11 @@ namespace Tyra {
|
||||
|
||||
class CameraInfo3D {
|
||||
public:
|
||||
CameraInfo3D(Vec4* cameraPosition, Vec4* cameraLooksAt,
|
||||
Vec4* cameraUp = nullptr);
|
||||
CameraInfo3D(const Vec4* cameraPosition, const Vec4* cameraLooksAt,
|
||||
const Vec4* cameraUp = nullptr);
|
||||
~CameraInfo3D();
|
||||
|
||||
Vec4 *position, *looksAt, *up;
|
||||
const Vec4 *position, *looksAt, *up;
|
||||
|
||||
private:
|
||||
static Vec4 defaultCameraUp;
|
||||
|
||||
@@ -29,7 +29,7 @@ class Path3 {
|
||||
|
||||
void sendDrawFinishTag();
|
||||
void clearScreen(zbuffer_t* z, const Color& color);
|
||||
void sendTexture(Texture* texture,
|
||||
void sendTexture(const Texture* texture,
|
||||
const RendererCoreTextureBuffers& texBuffers);
|
||||
|
||||
private:
|
||||
|
||||
@@ -45,7 +45,7 @@ class Texture {
|
||||
|
||||
float getSizeInMB() const;
|
||||
|
||||
inline texwrap_t* getWrapSettings() { return &wrap; }
|
||||
inline const texwrap_t* getWrapSettings() const { return &wrap; }
|
||||
|
||||
inline const std::vector<TextureLink>& getTextureLinks() const {
|
||||
return links;
|
||||
|
||||
@@ -27,7 +27,7 @@ class RendererCoreTexture {
|
||||
clutbuffer_t clut;
|
||||
TextureRepository repository;
|
||||
|
||||
RendererCoreTextureBuffers useTexture(Texture* t_tex);
|
||||
RendererCoreTextureBuffers useTexture(const Texture* t_tex);
|
||||
|
||||
/** Called by renderer during initialization */
|
||||
void init(RendererCoreGS* gs, Path3* path3);
|
||||
|
||||
@@ -27,7 +27,7 @@ class RendererCoreTextureSender {
|
||||
|
||||
void init(Path3* path3, RendererCoreGS* gs);
|
||||
|
||||
RendererCoreTextureBuffers allocate(Texture* t_texture);
|
||||
RendererCoreTextureBuffers allocate(const Texture* t_texture);
|
||||
|
||||
void deallocate(const RendererCoreTextureBuffers& texBuffers);
|
||||
|
||||
@@ -37,8 +37,8 @@ class RendererCoreTextureSender {
|
||||
RendererCoreGS* gs;
|
||||
Path3* path3;
|
||||
TextureBpp getBppByPsm(const u32& psm);
|
||||
texbuffer_t* allocateTextureCore(Texture* t_texture);
|
||||
texbuffer_t* allocateTextureClut(Texture* t_texture);
|
||||
texbuffer_t* allocateTextureCore(const Texture* t_texture);
|
||||
texbuffer_t* allocateTextureClut(const Texture* t_texture);
|
||||
};
|
||||
|
||||
} // namespace Tyra
|
||||
|
||||
@@ -83,8 +83,8 @@ void MinecraftPipeline::initBBox() {
|
||||
bbox = new RenderBBox(block.vertices, block.count);
|
||||
}
|
||||
|
||||
void MinecraftPipeline::render(std::vector<McpipBlock*> blocks, Texture* t_tex,
|
||||
const bool& isMulti,
|
||||
void MinecraftPipeline::render(std::vector<McpipBlock*> blocks,
|
||||
const Texture* t_tex, const bool& isMulti,
|
||||
const bool& fullClipChecks) {
|
||||
auto texBuffers = rendererCore->texture.useTexture(t_tex);
|
||||
|
||||
|
||||
@@ -19,6 +19,10 @@ Renderer3D::~Renderer3D() {}
|
||||
|
||||
void Renderer3D::init(RendererCore* core) { utility.init(core); }
|
||||
|
||||
void Renderer3D::usePipeline(Renderer3DPipeline& pipeline) {
|
||||
usePipeline(&pipeline);
|
||||
}
|
||||
|
||||
void Renderer3D::usePipeline(Renderer3DPipeline* pipeline) {
|
||||
if (currentPipeline != pipeline) {
|
||||
if (currentPipeline) currentPipeline->onUseEnd();
|
||||
|
||||
@@ -14,8 +14,9 @@ namespace Tyra {
|
||||
|
||||
Vec4 CameraInfo3D::defaultCameraUp = Vec4(0.0F, 1.0F, 0.0F);
|
||||
|
||||
CameraInfo3D::CameraInfo3D(Vec4* t_cameraPosition, Vec4* t_cameraLooksAt,
|
||||
Vec4* t_cameraUp) {
|
||||
CameraInfo3D::CameraInfo3D(const Vec4* t_cameraPosition,
|
||||
const Vec4* t_cameraLooksAt,
|
||||
const Vec4* t_cameraUp) {
|
||||
position = t_cameraPosition;
|
||||
looksAt = t_cameraLooksAt;
|
||||
|
||||
@@ -25,6 +26,7 @@ CameraInfo3D::CameraInfo3D(Vec4* t_cameraPosition, Vec4* t_cameraLooksAt,
|
||||
up = t_cameraUp;
|
||||
}
|
||||
}
|
||||
|
||||
CameraInfo3D::~CameraInfo3D() {}
|
||||
|
||||
} // namespace Tyra
|
||||
|
||||
@@ -61,7 +61,7 @@ void Path3::clearScreen(zbuffer_t* z, const Color& color) {
|
||||
dma_channel_send_packet2(clearScreenPacket, DMA_CHANNEL_GIF, true);
|
||||
}
|
||||
|
||||
void Path3::sendTexture(Texture* texture,
|
||||
void Path3::sendTexture(const Texture* texture,
|
||||
const RendererCoreTextureBuffers& texBuffers) {
|
||||
packet2_reset(texturePacket, false);
|
||||
|
||||
@@ -83,8 +83,9 @@ void Path3::sendTexture(Texture* texture,
|
||||
|
||||
packet2_chain_open_cnt(texturePacket, 0, 0, 0);
|
||||
packet2_update(texturePacket,
|
||||
draw_texture_wrapping(texturePacket->next, 0,
|
||||
texture->getWrapSettings()));
|
||||
draw_texture_wrapping(
|
||||
texturePacket->next, 0,
|
||||
const_cast<texwrap_t*>(texture->getWrapSettings())));
|
||||
packet2_chain_close_tag(texturePacket);
|
||||
|
||||
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!");
|
||||
|
||||
auto allocated = getAllocatedBuffersByTextureId(t_tex->id);
|
||||
|
||||
@@ -23,7 +23,7 @@ void RendererCoreTextureSender::init(Path3* t_path3, RendererCoreGS* t_gs) {
|
||||
}
|
||||
|
||||
RendererCoreTextureBuffers RendererCoreTextureSender::allocate(
|
||||
Texture* t_texture) {
|
||||
const Texture* t_texture) {
|
||||
texbuffer_t* core = allocateTextureCore(t_texture);
|
||||
texbuffer_t* clut = nullptr;
|
||||
|
||||
@@ -54,7 +54,7 @@ void RendererCoreTextureSender::deallocate(
|
||||
}
|
||||
|
||||
texbuffer_t* RendererCoreTextureSender::allocateTextureCore(
|
||||
Texture* t_texture) {
|
||||
const Texture* t_texture) {
|
||||
auto* result = new texbuffer_t;
|
||||
const auto* core = t_texture->core;
|
||||
|
||||
@@ -73,7 +73,7 @@ texbuffer_t* RendererCoreTextureSender::allocateTextureCore(
|
||||
}
|
||||
|
||||
texbuffer_t* RendererCoreTextureSender::allocateTextureClut(
|
||||
Texture* t_texture) {
|
||||
const Texture* t_texture) {
|
||||
auto* result = new texbuffer_t;
|
||||
const auto* clut = t_texture->clut;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
TARGET := tutorial_01.elf
|
||||
TARGET := tutorial_02.elf
|
||||
ENGINEDIR := ../../engine
|
||||
|
||||
#The Directories, Source, Includes, Objects, Binary and Resources
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <tyra>
|
||||
#include <memory.h>
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
|
||||
@@ -32,7 +32,10 @@ Tutorial02::~Tutorial02() {
|
||||
void Tutorial02::init() {
|
||||
engine->renderer.setClearScreenColor(Color(32.0F, 32.0F, 32.0F));
|
||||
|
||||
/** Sprite contains rectangle information. */
|
||||
loadSprite();
|
||||
|
||||
/** Texture contains png image. */
|
||||
loadTexture();
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -0,0 +1,4 @@
|
||||
# Ignore everything in this directory
|
||||
*
|
||||
# Except this file
|
||||
!.gitignore
|
||||
@@ -0,0 +1,4 @@
|
||||
# Ignore everything in this directory
|
||||
*
|
||||
# Except this file
|
||||
!.gitignore
|
||||
@@ -0,0 +1,4 @@
|
||||
$ConfigFile = Join-Path $PSScriptRoot '../../windows-pcsx2.ps1'
|
||||
. $ConfigFile
|
||||
|
||||
RunPCSX2
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user