Files
filament/samples/hellopbr.cpp
2026-02-16 10:30:53 -08:00

181 lines
6.0 KiB
C++

/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "common/arguments.h"
#include <filament/Engine.h>
#include <filament/LightManager.h>
#include <filament/Material.h>
#include <filament/RenderableManager.h>
#include <filament/Scene.h>
#include <filament/TransformManager.h>
#include <filament/View.h>
#include <utils/EntityManager.h>
#include <filameshio/MeshReader.h>
#include <filamentapp/Config.h>
#include <filamentapp/FilamentApp.h>
#include <getopt/getopt.h>
#include <iostream>
#include <string>// for printing usage/help
#include "filament/MaterialInstance.h"
#include "generated/resources/resources.h"
#include "generated/resources/monkey.h"
#include <utils/Log.h>
using namespace filament;
using namespace filamesh;
using namespace filament::math;
namespace {
std::vector<MaterialInstance*> instances;
}
using Backend = Engine::Backend;
struct App {
Config config;
utils::Entity light;
Material* material;
MaterialInstance* materialInstance;
MeshReader::Mesh mesh;
mat4f transform;
};
static const char* IBL_FOLDER = "assets/ibl/lightroom_14b";
static void printUsage(char* name) {
std::string exec_name(utils::Path(name).getName());
std::string usage(
"EXEC renders a simple PBR example\n"
"Usage:\n"
" EXEC [options]\n"
"Options:\n"
" --help, -h\n"
" Prints this message\n\n"
"API_USAGE"
);
const std::string from("EXEC");
for (size_t pos = usage.find(from); pos != std::string::npos; pos = usage.find(from, pos)) {
usage.replace(pos, from.length(), exec_name);
}
const std::string apiUsage("API_USAGE");
for (size_t pos = usage.find(apiUsage); pos != std::string::npos; pos = usage.find(apiUsage, pos)) {
usage.replace(pos, apiUsage.length(), samples::getBackendAPIArgumentsUsage());
}
std::cout << usage;
}
static int handleCommandLineArguments(int argc, char* argv[], App* app) {
static constexpr const char* OPTSTR = "ha:";
static const struct option OPTIONS[] = {
{ "help", no_argument, nullptr, 'h' },
{ "api", required_argument, nullptr, 'a' },
{ nullptr, 0, nullptr, 0 }
};
int opt;
int option_index = 0;
while ((opt = getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(optarg ? optarg : "");
switch (opt) {
default:
case 'h':
printUsage(argv[0]);
exit(0);
case 'a':
app->config.backend = samples::parseArgumentsForBackend(arg);
break;
}
}
return optind;
}
int main(int argc, char** argv) {
App app;
app.config.title = "hellopbr";
app.config.iblDirectory = FilamentApp::getRootAssetsPath() + IBL_FOLDER;
handleCommandLineArguments(argc, argv, &app);
auto setup = [config=app.config, &app](Engine* engine, View* view, Scene* scene) {
auto& tcm = engine->getTransformManager();
auto& rcm = engine->getRenderableManager();
auto& em = utils::EntityManager::get();
// Instantiate material.
app.material = Material::Builder()
.package(RESOURCES_AIDEFAULTMAT_DATA, RESOURCES_AIDEFAULTMAT_SIZE).build(*engine);
auto mi = app.materialInstance = app.material->createInstance();
mi->setParameter("baseColor", RgbType::LINEAR, float3{0.8});
mi->setParameter("metallic", 1.0f);
mi->setParameter("roughness", 0.4f);
mi->setParameter("reflectance", 0.5f);
// Add geometry into the scene.
app.mesh = MeshReader::loadMeshFromBuffer(engine, MONKEY_SUZANNE_DATA, nullptr, nullptr, mi);
auto ti = tcm.getInstance(app.mesh.renderable);
app.transform = mat4f{ mat3f(1), float3(0, 0, -4) } * tcm.getWorldTransform(ti);
rcm.setCastShadows(rcm.getInstance(app.mesh.renderable), false);
scene->addEntity(app.mesh.renderable);
// Add light sources into the scene.
app.light = em.create();
LightManager::Builder(LightManager::Type::SUN)
.color(Color::toLinear<ACCURATE>(sRGBColor(0.98f, 0.92f, 0.89f)))
.intensity(110000)
.direction({ 0.7, -1, -0.8 })
.sunAngularRadius(1.9f)
.castShadows(false)
.build(*engine, app.light);
scene->addEntity(app.light);
};
auto cleanup = [&app](Engine* engine, View*, Scene*) {
engine->destroy(app.light);
engine->destroy(app.mesh.renderable);
engine->destroy(app.materialInstance);
engine->destroy(app.material);
};
FilamentApp::get().animate([&app](Engine* engine, View* view, double now) {
auto& tcm = engine->getTransformManager();
auto ti = tcm.getInstance(app.mesh.renderable);
tcm.setTransform(ti, app.transform * mat4f::rotation(now, float3{ 0, 1, 0 }));
static int count = 0;
constexpr int allSize = 12000;
if (count++ == 5) {
for (size_t i = 0; i < allSize; ++i) {
auto mi = app.materialInstance = app.material->createInstance();
mi->setParameter("baseColor", RgbType::LINEAR, float3{0.8});
mi->setParameter("metallic", 1.0f);
mi->setParameter("roughness", 0.4f);
mi->setParameter("reflectance", 0.5f);
instances.push_back(mi);
}
}
});
FilamentApp::get().run(app.config, setup, cleanup);
return 0;
}