Skip to content
Open

v2 #15

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
strategy:
matrix:
operating-system: ['ubuntu-latest']
php-versions: ['8.1', '8.2']
php-versions: ['8.2', '8.3', '8.4', '8.5']
phpunit-versions: ['9.6']

steps:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ docs/docs-assets/
.phpdoc/
docs/api
bin/phpDocumentor.phar
/examples/resources/assets/
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
},
"require-dev": {
"phpunit/phpunit": "^9.5",
"phpstan/phpstan": "^1.8",
"phpstan/phpstan": "^2.2",
"phpgl/ide-stubs": "dev-main",
"phpbench/phpbench": "^1.2"
},
Expand Down
32 changes: 32 additions & 0 deletions examples/bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,37 @@
*/
$container = require __DIR__ . '/../bootstrap.php';

/**
* ---------------------------------------------------------------
* Download Assets for the example
* ---------------------------------------------------------------
*/
$exampleAssetsUrl = 'https://github.com/phpgl/visu-example-assets/archive/refs/heads/master.zip';
$exampleAssetsPath = VISU_PATH_RESOURCES . DS . 'assets';

if (!is_dir($exampleAssetsPath)) {
if (!extension_loaded('zip')) {
echo "Error: PHP Zip extension is required to download and extract example assets.\n";
echo "Please install the PHP Zip extension and try again.\n";
exit(1);
}

echo "Downloading example assets...\n";
$zipFile = VISU_PATH_CACHE . DS . 'visu-example-assets.zip';
file_put_contents($zipFile, fopen($exampleAssetsUrl, 'r'));
$zip = new ZipArchive();
if ($zip->open($zipFile) === TRUE) {
$zip->extractTo(VISU_PATH_RESOURCES);
$zip->close();
rename(VISU_PATH_RESOURCES . DS . 'visu-example-assets-master', $exampleAssetsPath);
unlink($zipFile);
echo "[ok] Example assets downloaded and extracted.\n";
} else {
echo "[error] Failed to download example assets.\n";
}
} else {
echo "[ok] Example assets already present.\n";
}

// forward the container
return $container;
112 changes: 112 additions & 0 deletions examples/rendering/cubemap_skybox_demo.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
<?php

/**
* Cubemap/Skybox Rendering Example
*
* This example demonstrates how to render a cubemap as a skybox using
* the CubemapRenderer and CubemapPass classes.
*
* The example loads a cubemap from an HDRI file, or falls back to
* a test cubemap with solid colors if the HDRI file is not found.
*
* To use with a real HDRI file, place your .hdr file at:
* examples/resources/assets/environment.hdr
*
* Free HDRI files can be downloaded from:
* - https://polyhaven.com/hdris
* - https://hdrihaven.com/
*/

use GL\Math\Vec3;
use VISU\Graphics\Cubemap;
use VISU\Graphics\HDRIToCubemap;
use VISU\Graphics\Rendering\Pass\CameraData;
use VISU\Graphics\Rendering\Renderer\CubemapRenderer;
use VISU\Graphics\Rendering\RenderContext;
use VISU\Graphics\Rendering\Resource\RenderTargetResource;
use VISU\Quickstart;
use VISU\Quickstart\QuickstartApp;
use VISU\Quickstart\QuickstartOptions;
use VISU\System\VISUCameraSystem;

// HDRI conversion can take a while, so lift the execution time limit
set_time_limit(0);

$container = require __DIR__ . '/../bootstrap.php';

/**
* Custom QuickstartApp that renders an HDRI-derived cubemap as a skybox
*/
class CubemapDemoApp extends QuickstartApp
{
public Cubemap $cubemap;
public CubemapRenderer $cubemapRenderer;
public VISUCameraSystem $cameraSystem;

public function setupDrawAfter(RenderContext $context, RenderTargetResource $renderTarget): void
{
// get camera data from the context (set by camera system during render)
$cameraData = $context->data->get(CameraData::class);

// import cubemap into the render pipeline
$cubemapRes = $context->pipeline->importCubemap('skybox_cubemap', $this->cubemap);

// add the skybox pass (pass reads camera data internally)
$this->cubemapRenderer->attachSkyboxPass(
$context->pipeline,
$renderTarget,
$cubemapRes,
);
}
}

/**
* Main Entry Point
*
* ----------------------------------------------------------------------------
*/
$quickstart = new Quickstart(function(QuickstartOptions $app) use($container)
{
// Initalize the application
// --------------------------------------------------------------------
$app->container = $container;
$app->windowTitle = 'VISU Cubemap / Skybox Demo';
$app->appClass = CubemapDemoApp::class;

$app->ready = function(CubemapDemoApp $app) {
// define path to HDRI file - change this to point to your HDRI file
$hdriPath = VISU_PATH_RESOURCES . '/assets/hdri/cowboy_town_saloon_2k.hdr';

// create HDRI to cubemap converter
$converter = new HDRIToCubemap($app->gl);

// convert HDRI to cubemap (1024x1024 faces)
$app->cubemap = $converter->convert($hdriPath, 1024);

// create the cubemap renderer
$app->cubemapRenderer = new CubemapRenderer($app->shaders);

// create camera system for 3D navigation
$app->cameraSystem = new VISUCameraSystem($app->input, $app->dispatcher);

// register the camera system
$app->bindSystems([$app->cameraSystem]);
};

$app->initializeScene = function(CubemapDemoApp $app) {
// spawn a flying camera at origin
$app->cameraSystem->spawnDefaultFlyingCamera($app->entities, new Vec3(0.0, 0.0, 0.0));
};

$app->update = function(CubemapDemoApp $app) {
// update the camera system
$app->updateSystem($app->cameraSystem);
};

$app->render = function(CubemapDemoApp $app, RenderContext $context, RenderTargetResource $target) {
// render the camera system (this sets up CameraData in the context)
$app->renderSystem($app->cameraSystem, $context);
};
});

$quickstart->run();
117 changes: 117 additions & 0 deletions examples/rendering/low_poly_pipeline_basic.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
<?php

use GL\Math\{GLM, Quat, Vec3};
use VISU\Component\VISULowPoly\LPDynamicModel;
use VISU\Geo\Transform;
use VISU\Graphics\Rendering\RenderContext;
use VISU\Graphics\Rendering\Resource\RenderTargetResource;
use VISU\Quickstart;
use VISU\Quickstart\{QuickstartApp, QuickstartOptions};
use VISU\System\VISUCameraSystem;
use VISU\System\VISULowPoly\{LPModelCollection, LPObjLoader, LPRenderingSystem};

$container = require __DIR__ . '/../bootstrap.php';

// Demo State
// --------------------------------------------------------------------
class LowPolyRendererDemoState
{
public VISUCameraSystem $cameraSystem;
public LPRenderingSystem $renderingSystem;
public LPModelCollection $models;

// logo entity
public int $logoEntity;

// rotation state for interpolation
public Quat $logoRotationPrevious;
public Quat $logoRotationCurrent;
}

$state = new LowPolyRendererDemoState;

/**
* Main Entry Point
*
* ----------------------------------------------------------------------------
*/
$quickstart = new Quickstart(function(QuickstartOptions $app) use(&$state, $container)
{
// Initalize the application
// --------------------------------------------------------------------
$app->container = $container;
$app->ready = function(QuickstartApp $app) use(&$state)
{
// create a model collection and load
$state->models = new LPModelCollection();
$state->renderingSystem = new LPRenderingSystem($app->gl, $app->shaders, $state->models);

// load the VISU models coming with the engine
$loader = new LPObjLoader($app->gl);
$loader->loadAllInDirectory(VISU_PATH_FRAMEWORK_RESOURCES . '/model/visu', $state->models);

// to render 3D we need a camera
$state->cameraSystem = new VISUCameraSystem($app->input, $app->dispatcher);

// register the rendering system
$app->bindSystems([
$state->renderingSystem,
$state->cameraSystem
]);
};

// Initalize the scene
// --------------------------------------------------------------------
$app->initializeScene = function(QuickstartApp $app) use(&$state)
{
$state->cameraSystem->spawnDefaultFlyingCamera($app->entities, new Vec3(0.0, 0.0, 2.0));

// spawn a visu model in the middle
$state->logoEntity = $app->entities->create();
$app->entities->attach($state->logoEntity, new LPDynamicModel('visu_logo'));
$transform = $app->entities->attach($state->logoEntity, new Transform());
$transform->orientation->rotate(GLM::radians(90.0), new Vec3(1.0, 0.0, 0.0));

// initialize rotation state for interpolation
$state->logoRotationPrevious = $transform->orientation->copy();
$state->logoRotationCurrent = $transform->orientation->copy();
};

// Update the scene
// --------------------------------------------------------------------
$app->update = function(QuickstartApp $app) use(&$state)
{
$app->updateSystem($state->cameraSystem);

// store previous state before updating
$state->logoRotationPrevious = $state->logoRotationCurrent->copy();

// rotate the logo by a fixed amount per tick
$state->logoRotationCurrent->rotate(GLM::radians(1.0), new Vec3(0.0, 0.0, 1.0));
};

// Render the scene
// --------------------------------------------------------------------
$app->render = function(QuickstartApp $app, RenderContext $context, RenderTargetResource $target) use(&$state)
{
// interpolate between previous and current rotation state using compensation
// this way you get butter smooth rotation
$transform = $app->entities->get($state->logoEntity, Transform::class);
$transform->orientation = Quat::slerp($state->logoRotationPrevious, $state->logoRotationCurrent, $context->compensation);
$transform->markDirty();

// make sure to tell the low poly rendering system which render target we are using
$state->renderingSystem->setRenderTarget($target);

$app->renderSystem($state->cameraSystem, $context);
$app->renderSystem($state->renderingSystem, $context);

// Example: You can override the ouput texture to any texture generated in the pipeline
// the the code below we "debug" output the SSAO texture instead of the final render
// $ssaoData = $context->data->get(SSAOData::class);
// $quickstartPassData = $context->data->get(QuickstartPassData::class);
// $quickstartPassData->outputTexture = $ssaoData->ssaoTexture;
};
});

$quickstart->run();
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

use GL\Math\GLM;
use GL\Math\Vec3;
use VISU\Component\VISULowPoly\DynamicRenderableModel;
use VISU\Component\VISULowPoly\LPDynamicModel;
use VISU\Component\VISULowPoly\LPStaticModel;
use VISU\Geo\Transform;
use VISU\Graphics\Rendering\Pass\GBufferPassData;
use VISU\Graphics\Rendering\Pass\SSAOData;
Expand Down Expand Up @@ -41,13 +42,15 @@ class LowPolyRendererDemoState
$app->container = $container;
$app->ready = function(QuickstartApp $app) use(&$state)
{
// $app->loadCompatGPUProfiler();

// create a model collection and load
$state->models = new LPModelCollection();
$state->renderingSystem = new LPRenderingSystem($app->gl, $app->shaders, $state->models);

// load the VISU models coming with the engine
$loader = new LPObjLoader($app->gl);
$loader->loadAllInDirectory(VISU_PATH_FRAMEWORK_RESOURCES . '/model/visu', $state->models);
$loader->loadAllInDirectory(VISU_PATH_RESOURCES . '/assets/models/lp/', $state->models);

// to render 3D we need a camera
$state->cameraSystem = new VISUCameraSystem($app->input, $app->dispatcher);
Expand All @@ -65,22 +68,39 @@ class LowPolyRendererDemoState
{
$state->cameraSystem->spawnDefaultFlyingCamera($app->entities, new Vec3(0.0, 0.0, 2.0));

// spawn a visu model in the middle
$logoEntity = $app->entities->create();
$app->entities->attach($logoEntity, new DynamicRenderableModel('visu_logo.obj'));
$transform = $app->entities->attach($logoEntity, new Transform());
$transform->orientation->rotate(GLM::radians(90.0), new Vec3(1.0, 0.0, 0.0));
// we spawn 5000 random low poly models in the scene
$availableModels = $state->models->models;

for ($i = 0; $i < 50000; $i++) {
$modelIndex = rand(0, count($availableModels) - 1);
$modelName = array_keys($availableModels)[$modelIndex];

$entity = $app->entities->create();
$transform = $app->entities->attach($entity, new Transform());

// random position
$transform->position = new Vec3(
rand(-1000, 1000) / 10.0,
rand(-1000, 1000) / 10.0,
rand(-1000, 1000) / 10.0
);

// random rotation
$transform->orientation->rotate(GLM::radians(rand(0, 360)), new Vec3(0.0, 1.0, 0.0));
$transform->orientation->rotate(GLM::radians(rand(0, 360)), new Vec3(1.0, 0.0, 0.0));

// random scale
$scale = rand(5, 20) / 10.0;
$transform->scale = new Vec3($scale, $scale, $scale);

// attach the low poly model component
$app->entities->attach($entity, new LPStaticModel($modelName));
}
};

$app->update = function(QuickstartApp $app) use(&$state)
{
$app->updateSystem($state->cameraSystem);

// rotate the logo
$model = $app->entities->firstWith(DynamicRenderableModel::class);
$transform = $app->entities->get($model, Transform::class);
$transform->orientation->rotate(GLM::radians(1.0), new Vec3(0.0, 0.0, 1.0));
$transform->markDirty();
};

$app->render = function(QuickstartApp $app, RenderContext $context, RenderTargetResource $target) use(&$state)
Expand Down
Loading
Loading