first Dicom Viewer commit

This commit is contained in:
2026-03-26 18:54:05 +01:00
parent b89d622f3c
commit c86b8cbd00
7 changed files with 937 additions and 458 deletions

188
.gitignore vendored
View File

@@ -1,93 +1,95 @@
# ---> C++
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Executables
*.exe
*.out
*.app
# ---> C
# Prerequisites
*.d
# Object files
*.o
*.ko
*.obj
*.elf
# Linker output
*.ilk
*.map
*.exp
# Precompiled Headers
*.gch
*.pch
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf
# ---> CMake
CMakeLists.txt.user
CMakeCache.txt
CMakeFiles
CMakeScripts
Testing
Makefile
cmake_install.cmake
install_manifest.txt
compile_commands.json
CTestTestfile.cmake
_deps
CMakeUserPresets.json
build
bin
lib
# ---> C++
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Executables
*.exe
*.out
*.app
# ---> C
# Prerequisites
*.d
# Object files
*.o
*.ko
*.obj
*.elf
# Linker output
*.ilk
*.map
*.exp
# Precompiled Headers
*.gch
*.pch
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf
# ---> CMake
CMakeLists.txt.user
CMakeCache.txt
CMakeFiles
CMakeScripts
Testing
Makefile
cmake_install.cmake
install_manifest.txt
compile_commands.json
CTestTestfile.cmake
_deps
CMakeUserPresets.json
build
bin
lib
DCM

2
TSE

Submodule TSE updated: f50b68c9ba...51a6ea1328

View File

@@ -1,232 +1,281 @@
#include "game.hpp"
#include "elements/Transformable.hpp"
#include "BehaviourScripts/TileMap.hpp"
#include "BehaviourScripts/OrdererSpriteSet.hpp"
#include "BehaviourScripts/Renderable.hpp"
#include "elements/ShaderRegistry.hpp"
#include "Vector2.hpp"
#include <cmath>
#include "PerlinNoise.hpp"
#include "BehaviourScripts/Camera.hpp"
#include "interfaces/IRenderTexture.hpp"
#include "BehaviourScripts/MeshContainer.hpp"
#include "BehaviourScripts/CameraSizeChangeNotifyer.hpp"
#include "BehaviourScripts/RenderTextureResizes.hpp"
#include "BehaviourScripts/CanvasScaler.hpp"
#include "Random.hpp"
#define circleRadius 32
#define circleFallof 25
#define treeCircleRadius 27
#define treeCircleFallof 20
void game::setup(TSE::Scene* s, TSE::IWindow* wnd)
{
using namespace TSE;
s->AddLayer(&gameLayer);
s->AddLayer(&propsLayer);
TileMap* maps[4];
OrdererSpriteSet* props;
Material* tileMapMaterial = new Material("tileSetMat", ShaderRegistry::GetShader("TileMapShader v2"));
tileMapMaterial->SetValue("spritePivot", Vector2(0,0));
Texture* setTexture = new Texture("tiles.png");
TileSet* set = new TileSet(setTexture, 10, 10);
for (int i = 0; i < 4; i++)
{
Transformable* tileMap = new Transformable("tileMapL" + std::to_string(i));
tileMap->position += {0,0.5f * i,0};
gameLayer.AddTransformable(tileMap);
TileMap* map = new TileMap();
map->chunkSize = 12;
map->set = set;
Renderable* rnd = new Renderable(tileMapMaterial);
tileMap->AddBehaviourScript(map);
tileMap->AddBehaviourScript(rnd);
maps[i] = map;
}
Material* objectsMaterial = new Material("objectsTileSetMat", ShaderRegistry::GetShader("Basic Ordered Sprite Set Shader"));
Texture* treeSetTexture = new Texture("trees.png");
TileSet* treeSet = new TileSet(treeSetTexture, 6, 2);
Transformable* tileMap = new Transformable("propMap");
propsLayer.AddTransformable(tileMap);
OrdererSpriteSet* map = new OrdererSpriteSet();
map->chunkSize = 12;
map->set = treeSet;
//map->SpriteScale = Vector2(1,2);
Renderable* rend = new Renderable(objectsMaterial);
tileMap->AddBehaviourScript(map);
tileMap->AddBehaviourScript(rend);
props = map;
Random rnd = Random(12345u);
const siv::PerlinNoise perlin{ rnd.nextUInt() };
const siv::PerlinNoise perlin2{ rnd.nextUInt() };
for (int x = circleRadius * -4; x < circleRadius * 4; x++)
{
for (int y = circleRadius * -4; y < circleRadius * 4; y++)
{
float noise = (float)perlin.octave2D_01(x * 0.05f,y * 0.05f, 4);
float treeNoise = (float)perlin2.octave2D_01(x * 0.05f,y * 0.05f, 2);
float noiseFallof = 1;
float treeNoiseFallof = 1;
Vector2 realpos = maps[0]->TileMapToRealPos(Vector2(x,y));
Vector2 realposprop = (maps[0]->TileMapToRealPos(Vector2(x,y)) + Vector2(0, 0.25f)) * Vector2(1,0.5f);
realpos *= {1,1.5f};
float dist = realpos.Length();
if(dist <= circleRadius && dist >= circleFallof)
{
float reldist = dist - circleFallof;
noiseFallof = (reldist / (circleRadius - circleFallof) - 1) * -1;
}
if(dist <= treeCircleRadius && dist >= treeCircleFallof)
{
float reldist = dist - treeCircleFallof;
treeNoiseFallof = (reldist / (treeCircleRadius - treeCircleFallof) - 1) * -1;
}
else if (dist > treeCircleRadius)
treeNoiseFallof = 0;
noise *= noiseFallof;
treeNoise *= treeNoiseFallof;
if(dist <= circleRadius && noise >= 0.2f)
{
float treernd = rnd.nextFloat01();
int treeid = 0;
if(noise >= 0.8f)
{
if(treeNoise > 0.5f && treernd > 0.4f)
{
treeid = rnd.nextInt(0,5);
props->SetSprite(realposprop + Vector2(0, 0.75f), Vector2(treeid, 1), 4.5f / 10.0f, Vector2(1,2), Vector2(treeid, 0));
}
maps[3]->SetTile(Vector2(x, y), {0,9}, {1,9});
}
else if(noise >= 0.6f)
{
if(treeNoise > 0.5f && treernd > 0.4f)
{
treeid = rnd.nextInt(0,5);
props->SetSprite(realposprop + Vector2(0, 0.5f), Vector2(treeid, 1), 3.5f / 10.0f, Vector2(1,2), Vector2(treeid, 0));
}
maps[2]->SetTile(Vector2(x, y), {0,9}, {1,9});
}
else if(noise >= 0.4f)
{
if(treeNoise > 0.5f && treernd > 0.4f)
{
treeid = rnd.nextInt(0,5);
props->SetSprite(realposprop + Vector2(0, 0.25f), Vector2(treeid, 1), 2.5f / 10.0f, Vector2(1,2), Vector2(treeid, 0));
}
maps[1]->SetTile(Vector2(x, y), {0,9}, {1,9});
}
else
{
if(treeNoise > 0.5f && treernd > 0.4f)
{
treeid = rnd.nextInt(0,5);
props->SetSprite(realposprop, Vector2(treeid, 1), 1.5f / 10.0f, Vector2(1,2), Vector2(treeid, 0));
}
maps[0]->SetTile(Vector2(x, y), {0,9}, {1,9});
}
}
}
}
//RenderingLayer
s->AddLayer(&renderingLayer);
s->AddLayer(&characterLayer);
Transformable* player = new Transformable("Player");
Transformable* lastPassCamera = new Transformable("lastPassCamera");
Camera* lpCam = new Camera();
lpCam->SetRenderTarget(wnd);
lpCam->SetRenderScale(1);
lpCam->layersNotToRender.push_back(gameLayer.GetID());
lpCam->layersNotToRender.push_back(propsLayer.GetID());
lpCam->layersNotToRender.push_back(characterLayer.GetID());
lastPassCamera->AddBehaviourScript(lpCam);
CameraSizeChangeNotifyer* camNotifyer = new CameraSizeChangeNotifyer();
camNotifyer->lastSize = {0,0};
camNotifyer->camToObserver = lpCam;
lastPassCamera->AddBehaviourScript(camNotifyer);
Vector2 canvasSize = wnd->GetSize() / 4.0f;
IRenderTexture* rt = IRenderTexture::factory->CreateTextureHeap(canvasSize, 3);
Transformable* firstPassCamera = new Transformable("firstPassCamera");
Camera* fpCam = new Camera();
fpCam->SetRenderScale(256);
fpCam->SetRenderTarget(rt);
fpCam->layersNotToRender.push_back(renderingLayer.GetID());
fpCam->layersNotToRender.push_back(propsLayer.GetID());
fpCam->layersNotToRender.push_back(characterLayer.GetID());
firstPassCamera->AddBehaviourScript(fpCam);
RenderTextureResizes* resizer = new RenderTextureResizes();
resizer->rt = rt;
camNotifyer->Observe(resizer);
firstPassCamera->AddBehaviourScript(resizer);
firstPassCamera->SetParent(player);
IRenderTexture* rtProps = IRenderTexture::factory->CreateTextureHeap(canvasSize, 3);
Transformable* secondPassCamera = new Transformable("secondPassCamera");
Camera* spCam = new Camera();
spCam->SetRenderScale(256);
spCam->SetRenderTarget(rtProps);
spCam->layersNotToRender.push_back(renderingLayer.GetID());
spCam->layersNotToRender.push_back(gameLayer.GetID());
spCam->layersNotToRender.push_back(characterLayer.GetID());
secondPassCamera->AddBehaviourScript(spCam);
RenderTextureResizes* resizerProps = new RenderTextureResizes();
resizerProps->rt = rtProps;
camNotifyer->Observe(resizerProps);
secondPassCamera->AddBehaviourScript(resizerProps);
secondPassCamera->SetParent(player);
//Render pipeline setup
characterLayer.AddTransformable(player);
renderingLayer.AddTransformable(lastPassCamera);
//final
Mesh* canvasMesh = new Mesh(Mesh::GetQuadMesh());
for(auto& vertex : canvasMesh->vertecies)
{
vertex *= wnd->GetSize();
}
MeshContainer* canvasContainer = new MeshContainer(canvasMesh);
Material* canvasMat = new Material("canvasMat", ShaderRegistry::GetShader("LastPassShader"));
canvasMat->SetValue<float>("threshold", 0.01f);
canvasMat->SetValue<float>("darken", 0.15f);
canvasMat->SetValue<uint>("colorTextureID", rt->GetTextureId(0));
canvasMat->SetValue<uint>("heightTextureID", rt->GetTextureId(1));
canvasMat->SetValue<uint>("depthTextureID", rt->GetTextureId(2));
canvasMat->SetValue<uint>("colorTexture2ID", rtProps->GetTextureId(0));
canvasMat->SetValue<uint>("heightTexture2ID", rtProps->GetTextureId(1));
canvasMat->SetValue<uint>("depthTexture2ID", rtProps->GetTextureId(2));
Renderable* canvasRenderer = new Renderable(canvasMat);
CanvasScaler* canvasScaler = new CanvasScaler();
canvasScaler->mesh = canvasMesh;
camNotifyer->Observe(canvasScaler);
lastPassCamera->AddBehaviourScript(canvasContainer);
lastPassCamera->AddBehaviourScript(canvasRenderer);
lastPassCamera->AddBehaviourScript(canvasScaler);
//propper resize stuff for prior passes, and canvas, and implement LastPassShader siehe dazu den chat: https://chatgpt.com/c/69985c47-6a50-838b-852d-45bb0b8454e5
#include "game.hpp"
#include "elements/Transformable.hpp"
#include "BehaviourScripts/TileMap.hpp"
#include "BehaviourScripts/OrdererSpriteSet.hpp"
#include "BehaviourScripts/Renderable.hpp"
#include "elements/ShaderRegistry.hpp"
#include "Vector2.hpp"
#include "Vector3.hpp"
#include <cmath>
#include "PerlinNoise.hpp"
#include "BehaviourScripts/Camera.hpp"
#include "interfaces/IRenderTexture.hpp"
#include "BehaviourScripts/MeshContainer.hpp"
#include "BehaviourScripts/CameraSizeChangeNotifyer.hpp"
#include "BehaviourScripts/RenderTextureResizes.hpp"
#include "BehaviourScripts/CanvasScaler.hpp"
#include "Random.hpp"
#include "elements/VolumeTexture3D.hpp"
#define circleRadius 32
#define circleFallof 25
#define treeCircleRadius 27
#define treeCircleFallof 20
void game::setup(TSE::Scene* s, TSE::IWindow* wnd)
{
using namespace TSE;
//s->AddLayer(&gameLayer);
// s->AddLayer(&propsLayer);
// TileMap* maps[4];
// OrdererSpriteSet* props;
// Material* tileMapMaterial = new Material("tileSetMat", ShaderRegistry::GetShader("TileMapShader v2"));
// tileMapMaterial->SetValue("spritePivot", Vector2(0,0));
// Texture* setTexture = new Texture("tiles.png");
// TileSet* set = new TileSet(setTexture, 10, 10);
// for (int i = 0; i < 4; i++)
// {
// Transformable* tileMap = new Transformable("tileMapL" + std::to_string(i));
// tileMap->position += {0,0.5f * i,0};
// gameLayer.AddTransformable(tileMap);
// TileMap* map = new TileMap();
// map->chunkSize = 12;
// map->set = set;
// Renderable* rnd = new Renderable(tileMapMaterial);
// tileMap->AddBehaviourScript(map);
// tileMap->AddBehaviourScript(rnd);
// maps[i] = map;
// }
// Material* objectsMaterial = new Material("objectsTileSetMat", ShaderRegistry::GetShader("Basic Ordered Sprite Set Shader"));
// Texture* treeSetTexture = new Texture("trees.png");
// TileSet* treeSet = new TileSet(treeSetTexture, 6, 2);
// Transformable* tileMap = new Transformable("propMap");
// propsLayer.AddTransformable(tileMap);
// OrdererSpriteSet* map = new OrdererSpriteSet();
// map->chunkSize = 12;
// map->set = treeSet;
// //map->SpriteScale = Vector2(1,2);
// Renderable* rend = new Renderable(objectsMaterial);
// tileMap->AddBehaviourScript(map);
// tileMap->AddBehaviourScript(rend);
// props = map;
// Random rnd = Random(12345u);
// const siv::PerlinNoise perlin{ rnd.nextUInt() };
// const siv::PerlinNoise perlin2{ rnd.nextUInt() };
// for (int x = circleRadius * -4; x < circleRadius * 4; x++)
// {
// for (int y = circleRadius * -4; y < circleRadius * 4; y++)
// {
// float noise = (float)perlin.octave2D_01(x * 0.05f,y * 0.05f, 4);
// float treeNoise = (float)perlin2.octave2D_01(x * 0.05f,y * 0.05f, 2);
// float noiseFallof = 1;
// float treeNoiseFallof = 1;
// Vector2 realpos = maps[0]->TileMapToRealPos(Vector2(x,y));
// Vector2 realposprop = (maps[0]->TileMapToRealPos(Vector2(x,y)) + Vector2(0, 0.25f)) * Vector2(1,0.5f);
// realpos *= {1,1.5f};
// float dist = realpos.Length();
// if(dist <= circleRadius && dist >= circleFallof)
// {
// float reldist = dist - circleFallof;
// noiseFallof = (reldist / (circleRadius - circleFallof) - 1) * -1;
// }
// if(dist <= treeCircleRadius && dist >= treeCircleFallof)
// {
// float reldist = dist - treeCircleFallof;
// treeNoiseFallof = (reldist / (treeCircleRadius - treeCircleFallof) - 1) * -1;
// }
// else if (dist > treeCircleRadius)
// treeNoiseFallof = 0;
// noise *= noiseFallof;
// treeNoise *= treeNoiseFallof;
// if(dist <= circleRadius && noise >= 0.2f)
// {
// float treernd = rnd.nextFloat01();
// int treeid = 0;
// if(noise >= 0.8f)
// {
// if(treeNoise > 0.5f && treernd > 0.4f)
// {
// treeid = rnd.nextInt(0,5);
// props->SetSprite(realposprop + Vector2(0, 0.75f), Vector2(treeid, 1), 4.5f / 10.0f, Vector2(1,2), Vector2(treeid, 0));
// }
// maps[3]->SetTile(Vector2(x, y), {0,9}, {1,9});
// }
// else if(noise >= 0.6f)
// {
// if(treeNoise > 0.5f && treernd > 0.4f)
// {
// treeid = rnd.nextInt(0,5);
// props->SetSprite(realposprop + Vector2(0, 0.5f), Vector2(treeid, 1), 3.5f / 10.0f, Vector2(1,2), Vector2(treeid, 0));
// }
// maps[2]->SetTile(Vector2(x, y), {0,9}, {1,9});
// }
// else if(noise >= 0.4f)
// {
// if(treeNoise > 0.5f && treernd > 0.4f)
// {
// treeid = rnd.nextInt(0,5);
// props->SetSprite(realposprop + Vector2(0, 0.25f), Vector2(treeid, 1), 2.5f / 10.0f, Vector2(1,2), Vector2(treeid, 0));
// }
// maps[1]->SetTile(Vector2(x, y), {0,9}, {1,9});
// }
// else
// {
// if(treeNoise > 0.5f && treernd > 0.4f)
// {
// treeid = rnd.nextInt(0,5);
// props->SetSprite(realposprop, Vector2(treeid, 1), 1.5f / 10.0f, Vector2(1,2), Vector2(treeid, 0));
// }
// maps[0]->SetTile(Vector2(x, y), {0,9}, {1,9});
// }
// }
// }
// }
//RenderingLayer
s->AddLayer(&renderingLayer);
float smallDicomDevider = 8.0f;
VolumeTexture3D* dicom = new VolumeTexture3D("./DCM");
Vector3 textureSize = {dicom->Width(), dicom->Height(), dicom->Depth()};
Vector3 smallTextureSize = { ceilf(textureSize.x / smallDicomDevider), ceilf(textureSize.y / smallDicomDevider), ceilf(textureSize.z / smallDicomDevider)};
VolumeTexture3D* dicomSmall = new VolumeTexture3D(smallTextureSize, 32);
for(int x = 0; x < smallTextureSize.x; x++)
{
for(int y = 0; y < smallTextureSize.y; y++)
{
for(int z = 0; z < smallTextureSize.z; z++)
{
float value = 0;
for(int sx = 0; sx < smallDicomDevider; sx++)
{
for(int sy = 0; sy < smallDicomDevider; sy++)
{
for(int sz = 0; sz < smallDicomDevider; sz++)
{
Color c;
Vector3 pos = Vector3(x * 8 + sx, y * 8 + sy, z * 8 + sz);
if(pos.x < dicom->Width() && pos.y < dicom->Height() && pos.z < dicom->Depth())
{
dicom->GetPixel(pos, c);
value = fmax(value, c.r);
}
}
}
}
dicomSmall->SetPixelNoApply(x,y,z, Color(value, value, value, value));
}
}
}
dicomSmall->Apply();
//s->AddLayer(&characterLayer);
Transformable* player = new Transformable("Player");
Transformable* lastPassCamera = new Transformable("lastPassCamera");
Camera* lpCam = new Camera();
lpCam->SetRenderTarget(wnd);
lpCam->SetRenderScale(0.0025f);
lpCam->SetFarClippingPlane(1000);
lpCam->layersNotToRender.push_back(gameLayer.GetID());
lpCam->layersNotToRender.push_back(propsLayer.GetID());
lpCam->layersNotToRender.push_back(characterLayer.GetID());
lastPassCamera->AddBehaviourScript(lpCam);
CameraSizeChangeNotifyer* camNotifyer = new CameraSizeChangeNotifyer();
camNotifyer->lastSize = {0,0};
camNotifyer->camToObserver = lpCam;
lastPassCamera->AddBehaviourScript(camNotifyer);
lastPassCamera->position = Vector3(-0.7f, -0.1f, 0);
lastPassCamera->SetEuler(Vector3(-16.7f, 0.3f, -0.2f));
Vector2 canvasSize = wnd->GetSize() / 4.0f;
// IRenderTexture* rt = IRenderTexture::factory->CreateTextureHeap(canvasSize, 3);
// Transformable* firstPassCamera = new Transformable("firstPassCamera");
// Camera* fpCam = new Camera();
// fpCam->SetRenderScale(256);
// fpCam->SetRenderTarget(rt);
// fpCam->layersNotToRender.push_back(renderingLayer.GetID());
// fpCam->layersNotToRender.push_back(propsLayer.GetID());
// fpCam->layersNotToRender.push_back(characterLayer.GetID());
// firstPassCamera->AddBehaviourScript(fpCam);
// RenderTextureResizes* resizer = new RenderTextureResizes();
// resizer->rt = rt;
// camNotifyer->Observe(resizer);
// firstPassCamera->AddBehaviourScript(resizer);
// firstPassCamera->SetParent(player);
// IRenderTexture* rtProps = IRenderTexture::factory->CreateTextureHeap(canvasSize, 3);
// Transformable* secondPassCamera = new Transformable("secondPassCamera");
// Camera* spCam = new Camera();
// spCam->SetRenderScale(256);
// spCam->SetRenderTarget(rtProps);
// spCam->layersNotToRender.push_back(renderingLayer.GetID());
// spCam->layersNotToRender.push_back(gameLayer.GetID());
// spCam->layersNotToRender.push_back(characterLayer.GetID());
// secondPassCamera->AddBehaviourScript(spCam);
// RenderTextureResizes* resizerProps = new RenderTextureResizes();
// resizerProps->rt = rtProps;
// camNotifyer->Observe(resizerProps);
// secondPassCamera->AddBehaviourScript(resizerProps);
// secondPassCamera->SetParent(player);
//Render pipeline setup
// characterLayer.AddTransformable(player);
renderingLayer.AddTransformable(lastPassCamera);
//final
Mesh* canvasMesh = new Mesh(Mesh::GetQuadMesh());
for(auto& vertex : canvasMesh->vertecies)
{
vertex *= 2;
}
MeshContainer* canvasContainer = new MeshContainer(canvasMesh);
Material* canvasMat = new Material("canvasMat", ShaderRegistry::GetShader("DICOMShader"));
canvasMat->SetValue<float>("threshold", 0.4f);
canvasMat->SetValue<float>("stepSize", 0.01f);
canvasMat->SetValue<Vector3>("texSize", textureSize);
canvasMat->SetValue<Vector3>("smallTexSize", smallTextureSize);
Vector3 objectScale = Vector3(1,1,1);
canvasMat->SetValue<Vector3>("ObjectScale", objectScale);
canvasMat->SetValue<ITexture*>("DICOM", dicom);
canvasMat->SetValue<ITexture*>("DICOMsmall", dicomSmall);
// canvasMat->SetValue<uint>("heightTextureID", rt->GetTextureId(1));
// canvasMat->SetValue<uint>("depthTextureID", rt->GetTextureId(2));
// canvasMat->SetValue<uint>("colorTexture2ID", rtProps->GetTextureId(0));
// canvasMat->SetValue<uint>("heightTexture2ID", rtProps->GetTextureId(1));
// canvasMat->SetValue<uint>("depthTexture2ID", rtProps->GetTextureId(2));
Renderable* canvasRenderer = new Renderable(canvasMat);
CanvasScaler* canvasScaler = new CanvasScaler();
canvasScaler->mesh = canvasMesh;
camNotifyer->Observe(canvasScaler);
lastPassCamera->AddBehaviourScript(canvasContainer);
lastPassCamera->AddBehaviourScript(canvasRenderer);
lastPassCamera->AddBehaviourScript(canvasScaler);
//propper resize stuff for prior passes, and canvas, and implement LastPassShader siehe dazu den chat: https://chatgpt.com/c/69985c47-6a50-838b-852d-45bb0b8454e5
}

View File

@@ -1,134 +1,141 @@
#include <iostream>
#include "GL/gl3w.h"
#include "globalVars.hpp"
#include "WindowManager.hpp"
#if defined(TSE_GLFW)
#include "WindowGlfw.hpp"
#elif defined(TSE_SDL3)
#include "WindowSdl3.hpp"
#endif
#include "OpenGLRenderingBackend.hpp"
#include "imgui/imgui.h"
#include "shader/defaultShaderHandler.cpp"
#include "DefaultRendererOpenGL.hpp"
#include "BehaviourScripts/RectBase.hpp"
#include "BehaviourScripts/Renderable.hpp"
#include "BehaviourScripts/Camera.hpp"
#include "elements/Sprite.hpp"
#include "elements/Texture.hpp"
#include "elements/Layer.hpp"
#include "elements/Scene.hpp"
#include "EditorSubsystem.hpp"
#include "game.hpp"
#include "shaders/TileMapShader.hpp"
#include "shaders/LastPassShader.hpp"
#define USE_EDITOR
using namespace TSE;
#if defined(TSE_GLFW)
using namespace TSE::GLFW;
#elif defined(TSE_SDL3)
using namespace TSE::SDL3;
#endif
using namespace TSE::OpenGL;
using namespace TSE::EDITOR;
IWindow* wnd = nullptr;
DefaultRendererOpenGL* rend = nullptr;
Scene* currentScene = nullptr;
Layer* planeteryLayer = nullptr;
EditorSubsystem* editor;
void SetupWindow()
{
Color backColor(0.0f, 0.0f, 0.0f, 0.0f);
#if defined(TSE_GLFW)
#ifdef USE_EDITOR
wnd = new WindowGlfw(PROJECT_NAME, 800, 600, new OpenGLRenderingBackend(backColor, false, 8, true), WindowType::Maximized);
editor = new EditorSubsystem();
#else
wnd = new WindowGlfw(PROJECT_NAME, 1920, 1080, new OpenGLRenderingBackend(backColor, false, 8, false), WindowType::Fullscreen);
#endif
#elif defined(TSE_SDL3)
#ifdef USE_EDITOR
wnd = new WindowSdl3(PROJECT_NAME, 800, 600, new OpenGLRenderingBackend(backColor, false, 8, true), WindowType::Maximized);
editor = new EditorSubsystem();
#else
wnd = new WindowSdl3(PROJECT_NAME, 1920, 1080, new OpenGLRenderingBackend(backColor, false, 8, false), WindowType::Fullscreen);
#endif
#endif
LoadBasicShaders(wnd->GetSize().x, wnd->GetSize().y);
TileMapShader::Init(wnd->GetSize().x, wnd->GetSize().y);
LastPassShader::Init(wnd->GetSize().x, wnd->GetSize().y);
ShaderRegistry::SetShader("TileMapShader v2", TileMapShader::Instance());
ShaderRegistry::SetShader("LastPassShader", LastPassShader::Instance());
rend = new DefaultRendererOpenGL(*BasicShader::Instance());
currentScene = new Scene();
#ifdef USE_EDITOR
((Camera*)Transformable::Find(".EditorCamera")->GetBehaviourScript(CAMERA))->layersNotToRender.push_back(game::renderingLayer.GetID());
((Camera*)Transformable::Find(".EditorCamera")->GetBehaviourScript(CAMERA))->SetRenderScale(128);
currentScene->AddLayer(&editor->editorLayer);
editor->hv.SetScene(currentScene);
#endif
game::setup(currentScene, wnd);
wnd->DoneSetup();
}
void CleanUp()
{
#ifdef USE_EDITOR
delete(editor);
#endif
UnLoadBasicShaders();
}
void GameLoop()
{
while(!wnd->ShouldClose())
{
wnd->Clear();
rend->Begin();
if(currentScene != nullptr)
currentScene->Render(*rend, *wnd);
rend->End();
rend->Flush();
if(currentScene != nullptr)
currentScene->DoneRender();
#ifdef USE_EDITOR
editor->controller.Update();
#endif
wnd->Update();
if(currentScene != nullptr)
currentScene->Update();
}
}
int main(int argc, char** argv)
{
SetupWindow();
GameLoop();
CleanUp();
return 0;
}
#if defined(_WIN32)
extern "C" {
__declspec(dllexport) unsigned long NvOptimusEnablement = 0x00000001; // NVIDIA
__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; // AMD
}
#include <iostream>
#include "GL/gl3w.h"
#include "globalVars.hpp"
#include "WindowManager.hpp"
#if defined(TSE_GLFW)
#include "WindowGlfw.hpp"
#elif defined(TSE_SDL3)
#include "WindowSdl3.hpp"
#endif
#include "OpenGLRenderingBackend.hpp"
#include "imgui/imgui.h"
#include "shader/defaultShaderHandler.cpp"
#include "DefaultRendererOpenGL.hpp"
#include "BehaviourScripts/RectBase.hpp"
#include "BehaviourScripts/Renderable.hpp"
#include "BehaviourScripts/Camera.hpp"
#include "elements/Sprite.hpp"
#include "elements/Texture.hpp"
#include "elements/Layer.hpp"
#include "elements/Scene.hpp"
#include "EditorSubsystem.hpp"
#include "game.hpp"
#include "shaders/TileMapShader.hpp"
#include "shaders/LastPassShader.hpp"
#include "shaders/DICOMShader.hpp"
#define USE_EDITOR
using namespace TSE;
#if defined(TSE_GLFW)
using namespace TSE::GLFW;
#elif defined(TSE_SDL3)
using namespace TSE::SDL3;
#endif
using namespace TSE::OpenGL;
using namespace TSE::EDITOR;
IWindow* wnd = nullptr;
DefaultRendererOpenGL* rend = nullptr;
Scene* currentScene = nullptr;
Layer* planeteryLayer = nullptr;
EditorSubsystem* editor;
void SetupWindow()
{
Color backColor(0.0f, 0.0f, 0.0f, 0.0f);
#if defined(TSE_GLFW)
#ifdef USE_EDITOR
wnd = new WindowGlfw(PROJECT_NAME, 800, 600, new OpenGLRenderingBackend(backColor, false, 8, true), WindowType::Maximized);
editor = new EditorSubsystem();
#else
wnd = new WindowGlfw(PROJECT_NAME, 1920, 1080, new OpenGLRenderingBackend(backColor, false, 8, false), WindowType::Fullscreen);
#endif
#elif defined(TSE_SDL3)
#ifdef USE_EDITOR
wnd = new WindowSdl3(PROJECT_NAME, 800, 600, new OpenGLRenderingBackend(backColor, false, 8, true), WindowType::Maximized);
editor = new EditorSubsystem();
#else
wnd = new WindowSdl3(PROJECT_NAME, 1920, 1080, new OpenGLRenderingBackend(backColor, false, 8, false), WindowType::Fullscreen);
#endif
#endif
LoadBasicShaders(wnd->GetSize().x, wnd->GetSize().y);
TileMapShader::Init(wnd->GetSize().x, wnd->GetSize().y);
LastPassShader::Init(wnd->GetSize().x, wnd->GetSize().y);
DICOMShader::Init(wnd->GetSize().x, wnd->GetSize().y);
ShaderRegistry::SetShader("TileMapShader v2", TileMapShader::Instance());
ShaderRegistry::SetShader("LastPassShader", LastPassShader::Instance());
ShaderRegistry::SetShader("DICOMShader", DICOMShader::Instance());
rend = new DefaultRendererOpenGL(*BasicShader::Instance());
currentScene = new Scene();
#ifdef USE_EDITOR
//((Camera*)Transformable::Find(".EditorCamera")->GetBehaviourScript(CAMERA))->layersNotToRender.push_back(game::renderingLayer.GetID());
((Camera*)Transformable::Find(".EditorCamera")->GetBehaviourScript(CAMERA))->SetRenderScale(0.002f);
((Camera*)Transformable::Find(".EditorCamera")->GetBehaviourScript(CAMERA))->SetFarClippingPlane(1000);
((Camera*)Transformable::Find(".EditorCamera")->GetBehaviourScript(CAMERA))->SetNearClippingPlane(0.1f);
Transformable::Find(".EditorCamera")->position = Vector3(-30.678f, 618.352f, 139.872f);
Transformable::Find(".EditorCamera")->rotation = Quaternion::FromEulerAngles(Vector3(86.348f, -0.450f, 9.699f));
currentScene->AddLayer(&editor->editorLayer);
editor->hv.SetScene(currentScene);
#endif
game::setup(currentScene, wnd);
wnd->DoneSetup();
}
void CleanUp()
{
#ifdef USE_EDITOR
delete(editor);
#endif
UnLoadBasicShaders();
}
void GameLoop()
{
while(!wnd->ShouldClose())
{
wnd->Clear();
rend->Begin();
if(currentScene != nullptr)
currentScene->Render(*rend, *wnd);
rend->End();
rend->Flush();
if(currentScene != nullptr)
currentScene->DoneRender();
#ifdef USE_EDITOR
editor->controller.Update();
#endif
wnd->Update();
if(currentScene != nullptr)
currentScene->Update();
}
}
int main(int argc, char** argv)
{
SetupWindow();
GameLoop();
CleanUp();
return 0;
}
#if defined(_WIN32)
extern "C" {
__declspec(dllexport) unsigned long NvOptimusEnablement = 0x00000001; // NVIDIA
__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; // AMD
}
#endif

View File

@@ -0,0 +1,124 @@
#include "DICOMShader.hpp"
#include "DICOMShaderGLSL.hpp"
#include "BehaviourScripts/Renderable.hpp"
#include "Color.hpp"
using namespace TSE;
using namespace TSE::OpenGL;
#define SHADER_VERTEX_INDEX 0
#define SHADER_UV_INDEX 1
#define SHADER_PACKAGE_SIZE (sizeof(float) * (3 + 2))
DICOMShader* DICOMShader::instance = nullptr;
DICOMShader *DICOMShader::Instance()
{
return instance;
}
void DICOMShader::Destroy()
{
if(instance != nullptr)
delete instance;
instance = nullptr;
}
void DICOMShader::Init(float width, float height)
{
std::vector<std::unique_ptr<ShaderPart>> parts;
parts.push_back(ShaderPart::LoadFromString(vertDICOM, GL_VERTEX_SHADER));
parts.push_back(ShaderPart::LoadFromString(fragDICOM, GL_FRAGMENT_SHADER));
instance = new DICOMShader(std::move(parts));
instance->Enable();
instance->SetUniform("DICOMTexture", 0);
instance->SetUniform("SmallDICOMTexture", 1);
instance->SetUniform("Threshold", 0.5f);
instance->SetUniform("TexSize", &Vector3::zero);
instance->SetUniform("SmallTexSize", &Vector3::zero);
instance->SetUniform("StepSize", 0.5f);
instance->Disable();
}
DICOMShader::DICOMShader(std::vector<std::unique_ptr<TSE::OpenGL::ShaderPart>> &&parts) : Shader(parts)
{
PackageSize = SHADER_PACKAGE_SIZE;
}
void DICOMShader::OnEnable() const
{
glEnableVertexAttribArray(SHADER_VERTEX_INDEX);
glVertexAttribPointer(SHADER_VERTEX_INDEX, 3, GL_FLOAT, false, SHADER_PACKAGE_SIZE, (void*)0);
glEnableVertexAttribArray(SHADER_UV_INDEX);
glVertexAttribPointer(SHADER_UV_INDEX, 2, GL_FLOAT, false, SHADER_PACKAGE_SIZE, (void*)(sizeof(float) * 3));
}
void DICOMShader::OnDisable() const
{
glDisableVertexAttribArray(SHADER_VERTEX_INDEX);
glDisableVertexAttribArray(SHADER_UV_INDEX);
}
void DICOMShader::OnFlush()
{
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_3D, DICOM->GetTextureId());
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_3D, SmallDICOM->GetTextureId());
SetUniform("Threshold", Threshold);
if(stepSize < 0.001f) stepSize = 0.001f;
SetUniform("StepSize", stepSize);
SetUniform("TexSize", &size);
SetUniform("SmallTexSize", &smallSize);
SetUniform("ObjectScale", &scale);
SetUniform("BrickScale", 8.0f);
}
void DICOMShader::OnDrawCall(int indexCount)
{
glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_SHORT, NULL);
}
void DICOMShader::OnSubmit(const TSE::Transformable &t, float *&target, TSE::TransformationStack &stack, void (*restartDrawcall)(TSE::IRenderer &), TSE::IRenderer &rnd)
{
auto* r = dynamic_cast<Renderable*>(t.GetBehaviourScript(RENDERABLE));
if (!r) return;
if(!r->GetMaterial()->HasValue("threshold")) return;
if(!r->GetMaterial()->HasValue("texSize")) return;
if(!r->GetMaterial()->HasValue("smallTexSize")) return;
if(!r->GetMaterial()->HasValue("DICOM")) return;
if(!r->GetMaterial()->HasValue("DICOMsmall")) return;
if(!r->GetMaterial()->HasValue("stepSize")) return;
if(!r->GetMaterial()->HasValue("ObjectScale")) return;
Threshold = r->GetMaterial()->GetValue<float>("threshold");
stepSize = r->GetMaterial()->GetValue<float>("stepSize");
size = r->GetMaterial()->GetValue<Vector3>("texSize");
smallSize = r->GetMaterial()->GetValue<Vector3>("smallTexSize");
scale = r->GetMaterial()->GetValue<Vector3>("ObjectScale");
DICOM = r->GetMaterial()->GetValue<ITexture*>("DICOM");
SmallDICOM = r->GetMaterial()->GetValue<ITexture*>("DICOMsmall");
const Vector3* verts = r->GetVertices();
const Vector2* uvs = r->GetUVs();
ushort vCount = r->GetVertexCount();
Matrix4x4 matr = t.GetLocalMatrix();
stack.Push(matr);
const Matrix4x4& top = stack.Top();
for (ushort i = 0; i < vCount; i++) {
Vector3 p = top * verts[i];
Vector2 uv = uvs[i];
*target++ = p.x;
*target++ = p.y;
*target++ = p.z;
*target++ = uv.x;
*target++ = uv.y;
}
stack.Pop();
}

View File

@@ -0,0 +1,33 @@
#pragma once
#include "GL/gl3w.h"
#include "GL/gl.h"
#include "shader/Shader.hpp"
#include "Types.hpp"
#include "interfaces/ITexture.hpp"
class DICOMShader : public TSE::OpenGL::Shader
{
private:
static DICOMShader* instance;
TSE::ITexture* DICOM;
TSE::ITexture* SmallDICOM;
TSE::Vector3 size;
TSE::Vector3 smallSize;
TSE::Vector3 scale;
float Threshold;
float stepSize;
public:
static DICOMShader* Instance();
static void Destroy();
static void Init(float width, float height);
DICOMShader(std::vector<std::unique_ptr<TSE::OpenGL::ShaderPart>>&& parts);
protected:
void OnEnable() const override;
void OnDisable() const override;
void OnFlush() override;
void OnDrawCall(int indexCount) override;
void OnSubmit(const TSE::Transformable& t, float*& target, TSE::TransformationStack& stack, void (*restartDrawcall)(TSE::IRenderer&), TSE::IRenderer& rnd) override;
};

View File

@@ -0,0 +1,264 @@
#pragma once
inline const char* vertDICOM = R"(
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec2 uv;
uniform mat4 prMatrix;
uniform mat4 camMatrix;
out DATA
{
vec2 uv_out;
} vs_out;
void main()
{
gl_Position = vec4(position.x, position.y, 0.0, 1.0);
vs_out.uv_out = uv;
}
)";
inline const char* fragDICOM = R"(
#version 330 core
layout (location = 0) out vec4 color;
uniform sampler3D DICOMTexture;
uniform sampler3D SmallDICOMTexture;
uniform vec3 CamPos;
uniform vec3 CamRight;
uniform vec3 CamUp;
uniform vec3 CamForward;
uniform float OrthoLeft;
uniform float OrthoRight;
uniform float OrthoBottom;
uniform float OrthoTop;
uniform float NearPlane;
uniform float FarPlane;
uniform float Threshold;
uniform float StepSize;
uniform vec3 TexSize;
uniform vec3 SmallTexSize;
uniform vec3 ObjectScale;
uniform float BrickScale;
in DATA
{
vec2 uv_out;
} fs_in;
bool IntersectAABB(vec3 rayOrigin, vec3 rayDir, vec3 boxMin, vec3 boxMax, out float tEnter, out float tExit)
{
vec3 invDir = 1.0 / rayDir;
vec3 t0 = (boxMin - rayOrigin) * invDir;
vec3 t1 = (boxMax - rayOrigin) * invDir;
vec3 tMin3 = min(t0, t1);
vec3 tMax3 = max(t0, t1);
tEnter = max(max(tMin3.x, tMin3.y), tMin3.z);
tExit = min(min(tMax3.x, tMax3.y), tMax3.z);
return tExit >= max(tEnter, 0.0);
}
void BuildOrthoRay(out vec3 rayOrigin, out vec3 rayDir)
{
vec2 uv = fs_in.uv_out;
float xView = mix(OrthoLeft, OrthoRight, uv.x);
float yView = mix(OrthoBottom, OrthoTop, uv.y);
rayOrigin = CamPos
+ CamRight * xView
+ CamUp * yView
+ CamForward * NearPlane;
rayDir = CamForward;
}
float TraverseFineBlock(vec3 rayOrigin, vec3 rayDir, float blockTEnter, float blockTExit, ivec3 brickCoord, float brickScaleF, ivec3 gridSize)
{
int brickSize = int(brickScaleF);
ivec3 blockVoxelMin = brickCoord * brickSize;
ivec3 blockVoxelMax = min(blockVoxelMin + ivec3(brickSize - 1), gridSize - ivec3(1));
float t = blockTEnter + 1e-4;
vec3 pos = rayOrigin + rayDir * t;
ivec3 voxel = ivec3(floor(pos / ObjectScale));
voxel = clamp(voxel, blockVoxelMin, blockVoxelMax);
ivec3 step;
step.x = (rayDir.x > 0.0) ? 1 : ((rayDir.x < 0.0) ? -1 : 0);
step.y = (rayDir.y > 0.0) ? 1 : ((rayDir.y < 0.0) ? -1 : 0);
step.z = (rayDir.z > 0.0) ? 1 : ((rayDir.z < 0.0) ? -1 : 0);
vec3 tDelta;
tDelta.x = (step.x != 0) ? abs(ObjectScale.x / rayDir.x) : 1e30;
tDelta.y = (step.y != 0) ? abs(ObjectScale.y / rayDir.y) : 1e30;
tDelta.z = (step.z != 0) ? abs(ObjectScale.z / rayDir.z) : 1e30;
vec3 nextBoundary;
nextBoundary.x = (step.x > 0) ? (float(voxel.x) + 1.0) * ObjectScale.x : float(voxel.x) * ObjectScale.x;
nextBoundary.y = (step.y > 0) ? (float(voxel.y) + 1.0) * ObjectScale.y : float(voxel.y) * ObjectScale.y;
nextBoundary.z = (step.z > 0) ? (float(voxel.z) + 1.0) * ObjectScale.z : float(voxel.z) * ObjectScale.z;
vec3 tMax;
tMax.x = (step.x != 0) ? ((nextBoundary.x - rayOrigin.x) / rayDir.x) : 1e30;
tMax.y = (step.y != 0) ? ((nextBoundary.y - rayOrigin.y) / rayDir.y) : 1e30;
tMax.z = (step.z != 0) ? ((nextBoundary.z - rayOrigin.z) / rayDir.z) : 1e30;
int maxIters = brickSize * 3 + 8;
float hits = 0;
for (int i = 0; i < maxIters; ++i)
{
if (t > blockTExit)
break;
float density = texelFetch(DICOMTexture, voxel, 0).r;
if (density >= Threshold)
hits++;
if (tMax.x <= tMax.y && tMax.x <= tMax.z)
{
voxel.x += step.x;
if (voxel.x < blockVoxelMin.x || voxel.x > blockVoxelMax.x) break;
t = tMax.x;
tMax.x += tDelta.x;
}
else if (tMax.y <= tMax.z)
{
voxel.y += step.y;
if (voxel.y < blockVoxelMin.y || voxel.y > blockVoxelMax.y) break;
t = tMax.y;
tMax.y += tDelta.y;
}
else
{
voxel.z += step.z;
if (voxel.z < blockVoxelMin.z || voxel.z > blockVoxelMax.z) break;
t = tMax.z;
tMax.z += tDelta.z;
}
}
return hits;
}
vec4 RenderVoxelDDA(vec3 rayOrigin, vec3 rayDir)
{
ivec3 gridSize = ivec3(TexSize);
ivec3 smallGridSize = ivec3(SmallTexSize);
float brickScaleF = max(BrickScale, 1.0);
int brickSize = int(brickScaleF);
vec3 scaledSize = TexSize * ObjectScale;
vec3 boxMin = vec3(0.0);
vec3 boxMax = scaledSize;
float tEnter, tExit;
if (!IntersectAABB(rayOrigin, rayDir, boxMin, boxMax, tEnter, tExit))
return vec4(0.0, 0.0, 0.0, 1.0);
tEnter = max(tEnter, 0.0);
tExit = min(tExit, FarPlane - NearPlane);
vec3 brickWorldSize = ObjectScale * brickScaleF;
float t = tEnter + 1e-4;
vec3 pos = rayOrigin + rayDir * t;
ivec3 brick = ivec3(floor(pos / brickWorldSize));
ivec3 brickMax = smallGridSize - ivec3(1);
brick = clamp(brick, ivec3(0), brickMax);
ivec3 step;
step.x = (rayDir.x > 0.0) ? 1 : ((rayDir.x < 0.0) ? -1 : 0);
step.y = (rayDir.y > 0.0) ? 1 : ((rayDir.y < 0.0) ? -1 : 0);
step.z = (rayDir.z > 0.0) ? 1 : ((rayDir.z < 0.0) ? -1 : 0);
vec3 tDelta;
tDelta.x = (step.x != 0) ? abs(brickWorldSize.x / rayDir.x) : 1e30;
tDelta.y = (step.y != 0) ? abs(brickWorldSize.y / rayDir.y) : 1e30;
tDelta.z = (step.z != 0) ? abs(brickWorldSize.z / rayDir.z) : 1e30;
vec3 nextBoundary;
nextBoundary.x = (step.x > 0) ? (float(brick.x) + 1.0) * brickWorldSize.x : float(brick.x) * brickWorldSize.x;
nextBoundary.y = (step.y > 0) ? (float(brick.y) + 1.0) * brickWorldSize.y : float(brick.y) * brickWorldSize.y;
nextBoundary.z = (step.z > 0) ? (float(brick.z) + 1.0) * brickWorldSize.z : float(brick.z) * brickWorldSize.z;
vec3 tMax;
tMax.x = (step.x != 0) ? ((nextBoundary.x - rayOrigin.x) / rayDir.x) : 1e30;
tMax.y = (step.y != 0) ? ((nextBoundary.y - rayOrigin.y) / rayDir.y) : 1e30;
tMax.z = (step.z != 0) ? ((nextBoundary.z - rayOrigin.z) / rayDir.z) : 1e30;
int maxIters = smallGridSize.x + smallGridSize.y + smallGridSize.z + 8;
float count = 0;
float increment = StepSize;
for (int i = 0; i < maxIters; ++i)
{
if (t > tExit)
break;
float brickDensity = texelFetch(SmallDICOMTexture, brick, 0).r;
float cellTExit = min(min(tMax.x, tMax.y), tMax.z);
cellTExit = min(cellTExit, tExit);
if (brickDensity >= Threshold)
{
float hits = TraverseFineBlock(rayOrigin, rayDir, t, cellTExit, brick, brickScaleF, gridSize);
count += hits * increment;
if(count >= 1) break;
}
if (tMax.x <= tMax.y && tMax.x <= tMax.z)
{
brick.x += step.x;
if (brick.x < 0 || brick.x > brickMax.x) break;
t = tMax.x;
tMax.x += tDelta.x;
}
else if (tMax.y <= tMax.z)
{
brick.y += step.y;
if (brick.y < 0 || brick.y > brickMax.y) break;
t = tMax.y;
tMax.y += tDelta.y;
}
else
{
brick.z += step.z;
if (brick.z < 0 || brick.z > brickMax.z) break;
t = tMax.z;
tMax.z += tDelta.z;
}
}
count = clamp(count, 0.0, 1.0);
return vec4(count, count, count, 1.0);
}
void main()
{
vec3 rayOrigin, rayDir;
BuildOrthoRay(rayOrigin, rayDir);
color = RenderVoxelDDA(rayOrigin, rayDir);
}
)";