initial commit

This commit is contained in:
Jason Ly 2025-09-26 21:25:28 -04:00
commit 5afb395e8c
3 changed files with 401 additions and 0 deletions

79
README.md Normal file
View File

@ -0,0 +1,79 @@
# joomer-bella-basic-renderer
basic rendering using bella engine sdk
<img src="resources/jump_right_in.png">
# Demonstrates
- basic rendering
- bella events to monitor render process
# Usage
```
# Compile the program (one long line)
cl /std:c++14 /DNDEBUG /Ibella_engine_sdk\src /EHsc joomer-bella-basic-renderer.cpp ^
/link /LIBPATH:bella_engine_sdk\lib bella_engine_sdk.lib /OUT:joomer-bella-basic-renderer.exe
# Set up library path and run
set PATH=%PATH%;bella_engine_sdk\lib
joomer-bella-basic-renderer.exe
```
[todo] create makefile
# Build
```
learndir/
└── joomer-bella-basic-renderer/
└── build_engine_sdk/
```
## MacOS (kasm-monterey)
- [ ] Install Xcode
```
mkdir learndir
cd learndir
curl -LO https://downloads.bellarender.com/bella_engine_sdk-25.3.0-macos.zip
unzip bella_engine_sdk-25.3.0-macos.zip
git clone https://git.indoodle.com/jason/joomer-bella-basic-renderer.git
cd joomer-bella-basic-renderer
make all -j4
bin/Darwin/release/poomer-bella-sine -r
open ./joomer-bella-basic-renderer.png
```
## Ubuntu Linux (kasm-ubuntu)
```
sudo apt install -y build-essential curl
mkdir learndir
cd learndir
curl -LO https://downloads.bellarender.com/bella_engine_sdk-25.3.0-linux.tar.gz
tar -xvf bella_engine_sdk-25.3.0.tar.gz
git clone https://git.indoodle.com/jason/joomer-bella-basic-renderer.git
cd joomer-bella-basic-renderer
make all -j4
bin/Linux/release/joomer-bella-basic-renderer -r
file ./joomer-bella-basic-renderer.png
```
## Windows (win10)
- [optioanl] Install https://git-scm.com
- Download Visual Studio Community Edition 2022
- Run VisualStudioSetup.exe
- Workload = [x] Desktop developemnt with C++
- Individial components = [x] Git For Windows
Run **x64 Native Tools Command Prompt for VS 2022**
```
cd %USERPROFILE%
mkdir learndir
cd learndir
curl -LO https://downloads.bellarender.com/bella_engine_sdk-25.3.0-win32.zip
tar -xf bella_engine_sdk-25.3.0-win32.zip
git clone https://git.indoodle.com/jason/joomer-bella-basic-renderer.git
cd joomer-bella-basic-renderer
joomer-bella-basic-renderer.exe
start mspaint joomer-bella-basic-renderer.png
```

View File

@ -0,0 +1,161 @@
#include "bella_engine_sdk/src/bella_sdk/bella_engine.h" // Core rendering engine
#include "bella_engine_sdk/src/bella_sdk/bella_scene.h" // Scene management
#include "bella_engine_sdk/src/dl_core/dl_logging.h" // Logging utilities
#include <thread> // For std::this_thread (C++ standard library)
#include <chrono> // For timing operations (C++ standard library)
// ============================================================================
// 🔍 C++ Concept: Observer Pattern
// This lets us "listen" for events from the rendering engine.
// When something happens (rendering starts, progress updates, etc.),
// our functions get called automatically.
// ============================================================================
struct MyEngineObserver : public dl::bella_sdk::EngineObserver {
// 🔔 Called when rendering begins
void onStarted(dl::String pass) override {
dl::logInfo("🚀 Rendering started: %s", pass.buf());
}
// 🔔 Called repeatedly as rendering progresses (0.0 to 1.0)
void onProgress(dl::String pass, dl::bella_sdk::Progress progress) override {
dl::logInfo("⏳ Progress: %.1f%% - %s",
progress.progress() * 100.0, progress.toString().buf());
}
// 🔔 Called when we get the final rendered image
void onImage(dl::String pass, dl::bella_sdk::Image image) override {
dl::logInfo("🖼️ Got image: %dx%d pixels", image.width(), image.height());
}
// 🔔 Called when rendering finishes
void onStopped(dl::String pass) override {
dl::logInfo("✅ Rendering complete: %s", pass.buf());
}
};
// ============================================================================
// 🎬 Main Function: Building Our 3D Scene
// ============================================================================
int main() {
// Step 1: Create the rendering engine and scene
dl::bella_sdk::Engine engine; // The renderer itself
dl::bella_sdk::Scene scene = engine.scene(); // Container for all our objects
scene.loadDefs(); // Load built-in object types
// Get the "world" - this is the root of our scene tree
dl::bella_sdk::Node world = scene.world();
// ========================================================================
// 📷 Step 2: Create the Camera System
// Every camera needs: sensor (film) + lens + positioning
// ========================================================================
// Create a digital "film" sensor (30mm x 30mm)
dl::bella_sdk::Node sensor = scene.createNode("sensor");
sensor["size"] = dl::Vec2::make(30.0, 30.0);
// Create a simple lens (like a magnifying glass)
auto lens = scene.createNode("thinLens"); // 'auto' = let C++ figure out the type
// Create camera positioning system + the camera itself
auto cameraXform = scene.createNode("xform"); // Transform = position/rotation
cameraXform.parentTo(world); // Attach to our world
auto camera = scene.createNode("camera"); // The actual camera
camera["resolution"] = dl::Vec2::make(320, 320); // 320x320 pixel image
camera["lens"] = lens; // Connect our lens
camera["sensor"] = sensor; // Connect our sensor
camera.parentTo(cameraXform); // Put camera in the positioning system
// Tell the scene to use this camera for rendering
auto settings = scene.settings();
settings["camera"] = camera;
// ========================================================================
// ☀️ Step 3: Add Lighting
// ========================================================================
auto skyDome = scene.createNode("skyDome"); // Simulates sky lighting
skyDome.parentTo(world);
settings["environment"] = skyDome; // Use this for scene lighting
// ========================================================================
// 🎨 Step 4: Create Materials (like paint or metal finishes)
// ========================================================================
// Golden metal material for our sphere
auto sphereMaterial = scene.createNode("conductor"); // Metal material
sphereMaterial["reflectance"] = dl::Rgba::make(0.8, 0.6, 0.2, 1.0); // Golden color (R,G,B,Alpha)
sphereMaterial["roughness"] = 26.1; // Slightly rough surface
// Glass-like material for the ground
auto groundMaterial = scene.createNode("dielectric"); // Glass/plastic material
groundMaterial["roughness"] = dl::Real(41.0); // Rough surface
// ========================================================================
// 🏀 Step 5: Create Objects (Sphere + Ground)
// ========================================================================
// Golden sphere in the center
auto sphereXform = scene.createNode("xform"); // Position controller for sphere
sphereXform["material"] = sphereMaterial; // Apply golden material
sphereXform.parentTo(world); // Add to scene
auto sphere = scene.createNode("sphere"); // The actual sphere shape
sphere["radius"] = dl::Real(1.0); // 1 unit radius
sphere.parentTo(sphereXform); // Put sphere in its position controller
// Large disk as ground plane
auto groundXform = scene.createNode("xform"); // Position controller for ground
groundXform["name"] = dl::String("groundXform"); // Give it a name (optional)
groundXform["material"] = groundMaterial; // Apply glass material
groundXform.parentTo(world); // Add to scene
auto ground = scene.createNode("disk"); // Flat circular disk
ground["radius"] = 10.0; // Large radius (10 units)
ground.parentTo(groundXform); // Put ground in its position controller
// ========================================================================
// 🎥 Step 6: Setup Rendering (what/where to save)
// ========================================================================
auto beautyPass = scene.createNode("beautyPass"); // Defines what to render
beautyPass["saveImage"] = true; // Save the image to disk
beautyPass["outputName"] = "poomer-bella-basic-renderer"; // Filename (will be my_render.png)
auto outputImagePath = scene.createNode("outputImagePath"); // Where to save
outputImagePath["dir"] = "."; // Current directory
beautyPass["overridePath"] = outputImagePath; // Connect save location
settings["beautyPass"] = beautyPass; // Tell scene to use this render setup
// ========================================================================
// 📱 Step 7: Connect Our Observer + Position Camera
// ========================================================================
MyEngineObserver observer; // Create our notification listener
engine.subscribe(&observer); // Connect it to the engine
// Position camera to look at the scene (like framing a photo)
dl::bella_sdk::zoomExtents(
scene.cameraPath(), // Camera's position controller (not camera itself!)
dl::Vec3{ 0,0,0 }, // Look at the origin (center of sphere)
3.0 // Distance from center
);
// Tilt camera down 75 degrees (like looking down from above)
dl::bella_sdk::orbitCamera(scene.cameraPath(), dl::Vec2{ 0.0, -75.0 });
// ========================================================================
// 🚀 Step 8: Render!
// ========================================================================
engine.start(); // Begin rendering
// Wait for rendering to complete (check every 100ms)
while (engine.rendering()) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
engine.stop(); // Clean shutdown
engine.unsubscribe(&observer); // Disconnect our listener
return 0; // Tell operating system: "Success!"
}

161
jump_right_in.cpp Normal file
View File

@ -0,0 +1,161 @@
#include "bella_engine_sdk/src/bella_sdk/bella_engine.h" // Core rendering engine
#include "bella_engine_sdk/src/bella_sdk/bella_scene.h" // Scene management
#include "bella_engine_sdk/src/dl_core/dl_logging.h" // Logging utilities
#include <thread> // For std::this_thread (C++ standard library)
#include <chrono> // For timing operations (C++ standard library)
// ============================================================================
// 🔍 C++ Concept: Observer Pattern
// This lets us "listen" for events from the rendering engine.
// When something happens (rendering starts, progress updates, etc.),
// our functions get called automatically.
// ============================================================================
struct MyEngineObserver : public dl::bella_sdk::EngineObserver {
// 🔔 Called when rendering begins
void onStarted(dl::String pass) override {
dl::logInfo("🚀 Rendering started: %s", pass.buf());
}
// 🔔 Called repeatedly as rendering progresses (0.0 to 1.0)
void onProgress(dl::String pass, dl::bella_sdk::Progress progress) override {
dl::logInfo("⏳ Progress: %.1f%% - %s",
progress.progress() * 100.0, progress.toString().buf());
}
// 🔔 Called when we get the final rendered image
void onImage(dl::String pass, dl::bella_sdk::Image image) override {
dl::logInfo("🖼️ Got image: %dx%d pixels", image.width(), image.height());
}
// 🔔 Called when rendering finishes
void onStopped(dl::String pass) override {
dl::logInfo("✅ Rendering complete: %s", pass.buf());
}
};
// ============================================================================
// 🎬 Main Function: Building Our 3D Scene
// ============================================================================
int main() {
// Step 1: Create the rendering engine and scene
dl::bella_sdk::Engine engine; // The renderer itself
dl::bella_sdk::Scene scene = engine.scene(); // Container for all our objects
scene.loadDefs(); // Load built-in object types
// Get the "world" - this is the root of our scene tree
dl::bella_sdk::Node world = scene.world();
// ========================================================================
// 📷 Step 2: Create the Camera System
// Every camera needs: sensor (film) + lens + positioning
// ========================================================================
// Create a digital "film" sensor (30mm x 30mm)
dl::bella_sdk::Node sensor = scene.createNode("sensor");
sensor["size"] = dl::Vec2::make(30.0, 30.0);
// Create a simple lens (like a magnifying glass)
auto lens = scene.createNode("thinLens"); // 'auto' = let C++ figure out the type
// Create camera positioning system + the camera itself
auto cameraXform = scene.createNode("xform"); // Transform = position/rotation
cameraXform.parentTo(world); // Attach to our world
auto camera = scene.createNode("camera"); // The actual camera
camera["resolution"] = dl::Vec2::make(320, 320); // 320x320 pixel image
camera["lens"] = lens; // Connect our lens
camera["sensor"] = sensor; // Connect our sensor
camera.parentTo(cameraXform); // Put camera in the positioning system
// Tell the scene to use this camera for rendering
auto settings = scene.settings();
settings["camera"] = camera;
// ========================================================================
// ☀️ Step 3: Add Lighting
// ========================================================================
auto skyDome = scene.createNode("skyDome"); // Simulates sky lighting
skyDome.parentTo(world);
settings["environment"] = skyDome; // Use this for scene lighting
// ========================================================================
// 🎨 Step 4: Create Materials (like paint or metal finishes)
// ========================================================================
// Golden metal material for our sphere
auto sphereMaterial = scene.createNode("conductor"); // Metal material
sphereMaterial["reflectance"] = dl::Rgba::make(0.8, 0.6, 0.2, 1.0); // Golden color (R,G,B,Alpha)
sphereMaterial["roughness"] = 26.1; // Slightly rough surface
// Glass-like material for the ground
auto groundMaterial = scene.createNode("dielectric"); // Glass/plastic material
groundMaterial["roughness"] = dl::Real(41.0); // Rough surface
// ========================================================================
// 🏀 Step 5: Create Objects (Sphere + Ground)
// ========================================================================
// Golden sphere in the center
auto sphereXform = scene.createNode("xform"); // Position controller for sphere
sphereXform["material"] = sphereMaterial; // Apply golden material
sphereXform.parentTo(world); // Add to scene
auto sphere = scene.createNode("sphere"); // The actual sphere shape
sphere["radius"] = dl::Real(1.0); // 1 unit radius
sphere.parentTo(sphereXform); // Put sphere in its position controller
// Large disk as ground plane
auto groundXform = scene.createNode("xform"); // Position controller for ground
groundXform["name"] = dl::String("groundXform"); // Give it a name (optional)
groundXform["material"] = groundMaterial; // Apply glass material
groundXform.parentTo(world); // Add to scene
auto ground = scene.createNode("disk"); // Flat circular disk
ground["radius"] = 10.0; // Large radius (10 units)
ground.parentTo(groundXform); // Put ground in its position controller
// ========================================================================
// 🎥 Step 6: Setup Rendering (what/where to save)
// ========================================================================
auto beautyPass = scene.createNode("beautyPass"); // Defines what to render
beautyPass["saveImage"] = true; // Save the image to disk
beautyPass["outputName"] = "jump_right_in"; // Filename (will be my_render.png)
auto outputImagePath = scene.createNode("outputImagePath"); // Where to save
outputImagePath["dir"] = "."; // Current directory
beautyPass["overridePath"] = outputImagePath; // Connect save location
settings["beautyPass"] = beautyPass; // Tell scene to use this render setup
// ========================================================================
// 📱 Step 7: Connect Our Observer + Position Camera
// ========================================================================
MyEngineObserver observer; // Create our notification listener
engine.subscribe(&observer); // Connect it to the engine
// Position camera to look at the scene (like framing a photo)
dl::bella_sdk::zoomExtents(
scene.cameraPath(), // Camera's position controller (not camera itself!)
dl::Vec3{ 0,0,0 }, // Look at the origin (center of sphere)
3.0 // Distance from center
);
// Tilt camera down 75 degrees (like looking down from above)
dl::bella_sdk::orbitCamera(scene.cameraPath(), dl::Vec2{ 0.0, -75.0 });
// ========================================================================
// 🚀 Step 8: Render!
// ========================================================================
engine.start(); // Begin rendering
// Wait for rendering to complete (check every 100ms)
while (engine.rendering()) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
engine.stop(); // Clean shutdown
engine.unsubscribe(&observer); // Disconnect our listener
return 0; // Tell operating system: "Success!"
}