/******************************************************************************
* File - simple_render_scene . cpp
* Author - Joey Pollack
* Date - 2021 / 10 / 27 ( y / m / d )
* Mod Date - 2021 / 10 / 27 ( y / m / d )
* Description - Displays a simple scene that tests basic render features .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include "simple_render_scene.h"
# include <core/core.h>
# include <gui/gui.h>
# include <utils/helpers.h>
# include <utils/logger.h>
# include <renderer/texture.h>
# include <renderer/frame_buffer.h>
# include <renderer/orthographic_camera.h>
# include <input/input_manager.h>
# include <utils/stb/std_image_write.h>
# include <utils/stb/stb_image.h>
# include <thread>
# include <chrono>
# include <cstdlib>
# include <ctime>
namespace lunarium
{
SimpleRenderScene : : SimpleRenderScene ( uint32_t logCat )
: BaseScene ( logCat ) , mTestMode ( TestMode : : Basic ) , mFrameTime ( 0.0 ) , mNumFrames ( 0 ) , mpTestImageLoad3 ( nullptr )
{
srand ( ( u32 ) time ( 0 ) ) ;
}
SimpleRenderScene : : ~ SimpleRenderScene ( )
{
delete mpTestImageLoad ;
}
void SimpleRenderScene : : OnLoad ( )
{
Logger : : Info ( mLogCat , " Running Simple Render Test Scene " ) ;
mTextBoxWidth = 500 ;
// Currently the full default window size
mImageSize . Width = 1280 ;
mImageSize . Height = 720 ;
// Create the render textures
mFrameBufferOne = FrameBuffer : : Create ( mImageSize . Width , mImageSize . Height ) ; //Core::Graphics().CreateRenderTexture(mImageSize.Width, mImageSize.Height, 4);
mFrameBufferTwo = FrameBuffer : : Create ( 1024 , 1024 ) ; //Core::Graphics().CreateRenderTexture(1024, 1024, 4);
// Load test image
int w , h , n ;
stbi_set_flip_vertically_on_load ( 1 ) ;
unsigned char * buffer = stbi_load ( " LinkToThePast1_sized.png " , & w , & h , & n , 0 ) ;
TextureFormat format = TextureFormat : : RGBA ;
if ( n = = 3 )
{
format = TextureFormat : : RGB ;
}
mpTestImageLoad = Texture : : Create ( buffer , w , h , format ) ;
mSrcWidth = w ;
mSrcHeight = h ;
delete [ ] buffer ;
stbi_set_flip_vertically_on_load ( 0 ) ;
buffer = stbi_load ( " debug_texture.jpeg " , & w , & h , & n , 0 ) ;
//buffer = stbi_load("lunarium_text_test.png", &w, &h, &n, 0);
format = TextureFormat : : RGBA ;
if ( n = = 3 )
{
format = TextureFormat : : RGB ;
}
else if ( n = = 1 )
{
format = TextureFormat : : RED ;
}
mpTestImageLoad2 = Texture : : Create ( buffer , w , h , format ) ;
delete [ ] buffer ;
stbi_set_flip_vertically_on_load ( 0 ) ;
buffer = stbi_load ( " lunarium_text_test.png " , & w , & h , & n , 0 ) ;
format = TextureFormat : : RGBA ;
if ( n = = 3 )
{
format = TextureFormat : : RGB ;
}
else if ( n = = 1 )
{
format = TextureFormat : : RED ;
}
mpTestImageLoad3 = Texture : : Create ( buffer , w , h , format ) ;
delete [ ] buffer ;
mQuads = new Rectangle [ NUM_QUADS ] ;
for ( int i = 0 ; i < NUM_QUADS ; i + + )
{
float x = ( rand ( ) % 1000 ) ;
float y = ( rand ( ) % 600 ) ;
float w = ( rand ( ) % 200 ) + 10 ;
float h = ( rand ( ) % 200 ) + 10 ;
mQuads [ i ] = Rectangle ( x , y , w , h ) ;
}
mQuadColors = new Color [ NUM_QUADS ] ;
mQuadTexures = new Texture * [ NUM_QUADS ] ;
for ( int i = 0 ; i < NUM_QUADS ; i + + )
{
mQuadTexures [ i ] = ( i % 2 = = 0 ) ? mpTestImageLoad : mpTestImageLoad2 ;
mQuadColors [ i ] . R = ( ( float ) ( rand ( ) % 10000 ) ) / 10000.0f ;
mQuadColors [ i ] . G = ( ( float ) ( rand ( ) % 10000 ) ) / 10000.0f ;
mQuadColors [ i ] . B = ( ( float ) ( rand ( ) % 10000 ) ) / 10000.0f ;
mQuadColors [ i ] . A = 1.0f ;
}
angle = 0.0f ;
box_angle = 0.0f ;
mTextDebugPosX = 200 ;
mSubTex = Rectangle : : MakeFromTopLeft ( 0 , 0 , 256 , 256 ) ;
}
void SimpleRenderScene : : OnTick ( double delta )
{
if ( Core : : Input ( ) . IsKeyDown ( KeyCode : : ESCAPE ) )
{
Core : : GetInstance ( ) . SignalShutdown ( ) ;
}
// Textbox size adjustment
if ( Core : : Input ( ) . IsKeyDown ( KeyCode : : LEFT ) )
{
if ( mTestMode = = TestMode : : Basic )
mTextBoxWidth - = 10 ;
if ( mTestMode = = TestMode : : String )
mTextDebugPosX - = 10 ;
}
if ( Core : : Input ( ) . IsKeyDown ( KeyCode : : RIGHT ) )
{
mTextBoxWidth + = 10 ;
if ( mTestMode = = TestMode : : Basic )
mTextBoxWidth + = 10 ;
if ( mTestMode = = TestMode : : String )
mTextDebugPosX + = 10 ;
}
if ( Core : : Input ( ) . IsKeyDown ( KeyCode : : R ) )
{
mSrcWidth - = 10.0f ;
mSrcHeight - = 10.0f ;
}
if ( Core : : Input ( ) . IsKeyDown ( KeyCode : : F ) )
{
mSrcWidth + = 10.0f ;
mSrcHeight + = 10.0f ;
}
mTextBoxWidth = Math : : ClampI ( mTextBoxWidth , 20 , 500 ) ;
// Image Size adjustment
if ( Core : : Input ( ) . IsKeyDown ( KeyCode : : DOWN ) )
{
mImageSize . Width - = 10 ;
mImageSize . Height - = 10 ;
}
if ( Core : : Input ( ) . IsKeyDown ( KeyCode : : UP ) )
{
mImageSize . Width + = 10 ;
mImageSize . Height + = 10 ;
}
if ( Core : : Input ( ) . IsKeyDown ( KeyCode : : PAGE_UP ) )
{
angle + = 0.1f ;
}
if ( Core : : Input ( ) . IsKeyDown ( KeyCode : : PAGE_DOWN ) )
{
angle - = 0.1f ;
}
if ( Core : : Input ( ) . IsKeyPressed ( KeyCode : : TAB ) )
{
if ( mTestMode = = TestMode : : Basic )
mTestMode = TestMode : : Stress ;
else if ( mTestMode = = TestMode : : Stress )
{
mSubTex = Rectangle : : MakeFromTopLeft ( 2858 , 0 , 32 , 32 ) ;
mTestMode = TestMode : : String ;
}
else if ( mTestMode = = TestMode : : String )
{
mTestMode = TestMode : : Basic ;
mSubTex = Rectangle : : MakeFromTopLeft ( 0 , 0 , 256 , 256 ) ;
}
}
if ( Core : : Input ( ) . IsKeyPressed ( KeyCode : : Q ) )
{
// Test writing out a rendered image with transparency
Renderer2D & g = Core : : Graphics ( ) ;
Color prev = g . GetClearColor ( ) ;
g . SetClearColor ( Color ( 0.0f , 0.0f , 0.0f , 0.0f ) ) ;
mFrameBufferTwo - > Bind ( ) ;
OrthographicCamera cam ( Vec2f { 0.0f , 0.0f } , Sizef { ( float ) mFrameBufferTwo - > GetTexture ( ) - > GetWidth ( ) , ( float ) mFrameBufferTwo - > GetTexture ( ) - > GetHeight ( ) } ) ;
g . BeginDraw ( & cam ) ;
// if (Failed(result))
// {
// Logger::Warn(mLogCat, "Unable to render to texture: %s", result.Description.c_str());
// return;
// }
Logger : : Info ( mLogCat , " Running transparent image test " ) ;
g . DrawQuad ( Rectangle ( 500 , 400 , 300 , 300 ) , Color ( 0.5f , 0.0f , 0.75f , 1.0f ) ) ;
g . DrawQuad ( Rectangle ( 200 , 300 , 100 , 100 ) , Color ( 0.2f , 0.5f , 0.4f , 1.0f ) , nullptr , 45.0f ) ;
g . DrawString ( " This is a test of rendering an image with transparency " ,
Rectangle : : MakeFromTopLeft ( 50 , 50 , 600 , 200 ) , Color ( 0.0f , 1.0f , 0.2f , 1.0f ) , 0.5f ) ;
g . EndDraw ( ) ;
mpRenderedImage = mFrameBufferTwo - > GetTexture ( ) ;
mFrameBufferTwo - > Unbind ( ) ;
//mpRenderedImage = Core::GetInstance().EndRenderToTexture();
g . SetClearColor ( prev ) ;
stbi_flip_vertically_on_write ( 1 ) ;
stbi_write_png ( " lunarium_test_image.png " , mpRenderedImage - > GetWidth ( ) , mpRenderedImage - > GetHeight ( ) , 4 ,
mpRenderedImage - > GetPixels ( ) , mpRenderedImage - > GetWidth ( ) * 4 ) ;
//Logger::Info(mLogCat, "")
}
if ( Core : : Input ( ) . IsKeyPressed ( KeyCode : : T ) )
{
Texture * dt = Core : : Graphics ( ) . GetTextDebugTexture ( ) ;
stbi_flip_vertically_on_write ( 0 ) ;
stbi_write_png ( " lunarium_text_test.png " , dt - > GetWidth ( ) , dt - > GetHeight ( ) , 1 ,
dt - > GetPixels ( ) , dt - > GetWidth ( ) * 1 ) ;
Logger : : Info ( mLogCat , " Saved Text test image " ) ;
}
mImageSize . Width = Math : : ClampI ( mImageSize . Width , 320 , 1280 ) ;
mImageSize . Height = Math : : ClampI ( mImageSize . Height , 180 , 720 ) ;
// Render to texture testing
// mFrameBufferOne->Bind();
// OrthographicCamera cam(Vec2f{0.0f, 0.0f}, Sizef{(float)mFrameBufferOne->GetTexture()->GetWidth(), (float)mFrameBufferOne->GetTexture()->GetHeight()});
// Renderer2D& g = Core::Graphics();
// g.BeginDraw(&cam);
// // OpRes result = Core::GetInstance().BeginRenderToTexture(mFrameBufferOne);
// // if (Failed(result))
// // {
// // Logger::Error(mLogCat, "Unable to render to texture: %s", result.Description.c_str());
// // return;
// // }
// g.DrawQuad(Rectangle(300, 300, 150, 150), Color::Red());
// g.DrawQuad(Rectangle(200, 300, 100, 100), Color(0.2f, 0.5f, 0.4f, 1.0f), nullptr, 45.0f);
// //g.DrawFilledEllipse(glm::vec2(600, 300), glm::vec2(100, 150), Color(1.0f, 0.0f, 1.0f, 1.0f), 100);
// // g.DrawString("This is a test of the text renderer!", Rectangle::MakeFromTopLeft(100, 200, mTextBoxWidth, 300),
// // Color(0.0f, 1.0f, 1.0f, 1.0f), 0.5f, g.DefaultFont());
// //mpRenderedImage = Core::GetInstance().EndRenderToTexture();
// g.EndDraw();
// mpRenderedImage = mFrameBufferOne->GetTexture();
box_angle + = 0.01f ;
int w , h ;
Core : : MainWindow ( ) . GetFramebufferSize ( & w , & h ) ;
OrthographicCamera main_cam ( Vec2f { 0.0f , 0.0f } , Sizef { ( float ) w , ( float ) h } ) ;
Core : : GUI ( ) . NewFrame ( ) ;
mTimer . Reset ( ) ;
Core : : Graphics ( ) . BeginDraw ( & main_cam ) ;
switch ( mTestMode )
{
case TestMode : : Basic : RenderScene ( Core : : Graphics ( ) ) ; break ;
case TestMode : : Stress : RenderBatchStressTest ( Core : : Graphics ( ) ) ; break ;
case TestMode : : String : RenderStringTest ( Core : : Graphics ( ) ) ; break ;
}
Core : : Graphics ( ) . EndDraw ( ) ; // Graphics end draw must happen before GUI end frame
DrawStatsGUI ( ) ;
Core : : GUI ( ) . EndFrame ( ) ;
Core : : MainWindow ( ) . SwapBuffers ( ) ;
mFrameTime + = mTimer . GetElapsedSeconds ( ) ;
mNumFrames + + ;
mRenderStats = Core : : Graphics ( ) . GetFrameStats ( ) ;
Core : : Graphics ( ) . ResetFrameStats ( ) ;
//std::this_thread::sleep_for (std::chrono::seconds(2));
}
void SimpleRenderScene : : RenderScene ( Renderer2D & g )
{
// g.DrawImage(*mpRenderedImage, Rectangle::MakeFromTopLeft(0.0f, 0.0f, (float)mpRenderedImage->GetWidth(), (float)mpRenderedImage->GetHeight()),
// Rectangle::MakeFromTopLeft(0.0f, 0.0f, (float)mImageSize.Width, (float)mImageSize.Height), Color(1.0f, 1.0f, 1.0f, 1.0f), angle);
//g.DrawQuad(Rectangle::MakeFromTopLeft(0.0f, 0.0f, (float)mImageSize.Width, (float)mImageSize.Height), Color(1.0f, 1.0f, 0.0f, 1.0f), nullptr, angle);
g . DrawQuad ( Rectangle ( 100 , 100 , 16 , 16 ) , Color : : White ( ) , mpTestImageLoad2 , 0.0f , mSubTex ) ;
g . DrawSprite ( mpTestImageLoad2 , glm : : vec2 ( 600 , 200 ) , Rectangle : : MakeFromTopLeft ( 255 , 255 , 255 , 255 ) ) ;
// g.DrawQuad(Rectangle(200, 200, 128.0f, 128.0f), Color(0.0f, 1.0f, 0.0f, 1.0f));//, nullptr, box_angle);
// g.DrawQuad(Rectangle(400, 300, 64.0f, 64.0f), Color(0.0f, 1.0f, 1.0f, 1.0f), nullptr, box_angle);
// g.DrawQuad(Rectangle(600, 300, 100.0f, 100.0f), Color::Blue(), nullptr, 45.0f);
// g.DrawQuad(Rectangle(500, 600, 100.0f, 100.0f), Color(0.25f, 0.75f, 0.8f), nullptr, 65.0f);
// g.DrawQuad(Rectangle(800, 500, 100.0f, 100.0f), Color(0.75f, 0.5f, 0.425f), nullptr, 90.0f);
// g.DrawQuad(Rectangle(300, 400, 64.0f, 64.0f), Color(0.25f, 0.5f, 1.0f, 1.0f), nullptr, box_angle * -1);
//g.DrawQuads(mQuads, NUM_QUADS, mQuadColors);
//g->DrawImage(*mpTestImageLoad, glm::vec2(0.0f, 0.0f), Color::White());
//Rectangle src = Rectangle::MakeFromTopLeft(0.0f, 0.0f, (float)mpTestImageLoad->GetWidth(), (float)mpTestImageLoad->GetHeight());
//Rectangle src = Rectangle::MakeFromTopLeft(0.0f, 0.0f, mSrcWidth, mSrcHeight);
// Rectangle src = Rectangle::MakeFromTopLeft(0.0f, 0.0f, 16, 16);
// Rectangle dest = Rectangle::MakeFromTopLeft(100.0f, 100.0f, 512.0f, 512.0f);
//g.DrawImage(*mpTestImageLoad, src, dest, Color(1.0f, 1.0f, 1.0f, 0.9f));
// g->DrawImage(*mpTestImageLoad, src,
// dest, Color(1.0f, 1.0f, 1.0f, 0.8f));
}
void SimpleRenderScene : : RenderBatchStressTest ( Renderer2D & g )
{
for ( int i = 0 ; i < mNumQuadsToRender ; i + + )
{
Texture * t = mUseTextures ? mQuadTexures [ i ] : nullptr ;
g . DrawQuad ( mQuads [ i ] , mQuadColors [ i ] , t , box_angle + ( i / 10.0f ) ) ;
}
}
void SimpleRenderScene : : RenderStringTest ( Renderer2D & g )
{
Texture * dt = g . GetTextDebugTexture ( ) ;
g . DrawQuad ( Rectangle ( mTextDebugPosX , 300 , dt - > GetWidth ( ) , dt - > GetHeight ( ) ) , Color : : Blue ( ) , dt ) ;
g . DrawQuad ( Rectangle ( 200 , 100 , 32 , 32 ) , Color ( 0.25f , 0.75f , 0.6f , 1.0f ) , mpTestImageLoad3 , 0.0f , mSubTex ) ;
g . DrawString ( " A " , Rectangle ( 200 , 170 , 32 , 32 ) , Color ( 0.25f , 0.75f , 0.6f , 1.0f ) ) ;
g . DrawString ( " This is a test string! " , Rectangle : : MakeFromTopLeft ( 100 , 500 , 500 , 50 ) , Color : : Green ( ) ) ;
g . DrawString ( " This is a very long string that should end up on more than one line when printed out test string! " , Rectangle : : MakeFromTopLeft ( 300 , 50 , 400 , 500 ) , Color : : Red ( ) ) ;
}
void SimpleRenderScene : : DrawStatsGUI ( )
{
std : : string mode_names [ 3 ] = { " Basic " , " Stress " , " String " } ;
ImGui : : SetNextWindowPos ( ImVec2 ( 0 , 0 ) , ImGuiCond_FirstUseEver ) ;
ImGui : : SetNextWindowSize ( ImVec2 ( 400 , 800 ) ) ;
ImGui : : Begin ( " RENDER INFO " ) ;
ImGui : : BeginChild ( " Scene Info " , ImVec2 ( ImGui : : GetWindowSize ( ) . x - 15 , ImGui : : GetFrameHeightWithSpacing ( ) * 3.5f ) , true ) ;
ImGui : : Text ( " Scene Info " ) ;
ImGui : : Separator ( ) ;
ImGui : : Text ( " Scene Mode: %s " , mode_names [ mTestMode ] . c_str ( ) ) ;
ImGui : : EndChild ( ) ;
ImGui : : BeginChild ( " Per Frame " , ImVec2 ( ImGui : : GetWindowSize ( ) . x - 15 , ImGui : : GetFrameHeightWithSpacing ( ) * 3.5f ) , true ) ;
ImGui : : Text ( " Per Frame " ) ;
ImGui : : Separator ( ) ;
ImGui : : Text ( " Number of triangles: %d " , mRenderStats . NumTris ) ;
ImGui : : Text ( " Draw calls: %d " , mRenderStats . DrawCalls ) ;
ImGui : : EndChild ( ) ;
ImGui : : BeginChild ( " General " , ImVec2 ( ImGui : : GetWindowSize ( ) . x - 15 , ImGui : : GetFrameHeightWithSpacing ( ) * 4.5f ) , true ) ;
ImGui : : Text ( " General Info " ) ;
ImGui : : Separator ( ) ;
ImGui : : Text ( " Average Render time: %f " , Core : : GetInstance ( ) . GetFrameData ( ) . AverageFrameTime ) ;
ImGui : : Text ( " FPS: %d " , Core : : GetInstance ( ) . GetFrameData ( ) . CurrentFPS ) ;
ImGui : : Text ( " Frame Number: %d " , mNumFrames ) ;
ImGui : : EndChild ( ) ;
ImGui : : BeginChild ( " Settings " , ImVec2 ( ImGui : : GetWindowSize ( ) . x - 15 , ImGui : : GetFrameHeightWithSpacing ( ) * 4.5f ) , true ) ;
ImGui : : Text ( " Settings " ) ;
ImGui : : Separator ( ) ;
ImGui : : InputInt ( " Number of Quads to draw " , & mNumQuadsToRender ) ;
ImGui : : Checkbox ( " Draw Textures " , & mUseTextures ) ;
float vals [ 4 ] = { mSubTex . left ( ) , mSubTex . top ( ) , mSubTex . HalfWidth * 2 , mSubTex . HalfHeight * 2 } ;
if ( ImGui : : DragFloat4 ( " Sub Texture Rect " , vals ) )
{
mSubTex = Rectangle : : MakeFromTopLeft ( vals [ 0 ] , vals [ 1 ] , vals [ 2 ] , vals [ 3 ] ) ;
}
ImGui : : EndChild ( ) ;
ImGui : : End ( ) ;
mNumQuadsToRender = Math : : ClampI ( mNumQuadsToRender , 0 , NUM_QUADS ) ;
}
}