I've been reading over the samples and docs trying to compile a simple exercise, but I haven't had any luck.
#include <filament/FilamentAPI.h>
#include <filament/Engine.h>
#include <utils/EntityManager.h>
#include <filament/View.h>
#include <filament/RenderableManager.h>
#include <filament/Scene.h>
#include <filament/LightManager.h>
#include <SDL2/SDL.h>
#include <math/norm.h>
static constexpr uint8_t BAKED_MATERIAL_PACKAGE[] = {
#include "materials/aiDefaultMat.inc"
};
using namespace filament;
using namespace utils;
using namespace math;
void *createSDLwindow()
{
SDL_Window *win = SDL_CreateWindow("Hello World!", 100, 100, 1920, 1080, SDL_WINDOW_OPENGL);
if (win == nullptr)
{
std::cout << "SDL_CreateWindow Error: " << SDL_GetError() << std::endl;
SDL_Quit();
return NULL;
}
return win;
}
int main()
{
const static uint32_t indices[] = {
0, 1, 2, 2, 3, 0};
const static math::float3 vertices[] = {
{-10, 0, -10},
{-10, 0, 10},
{10, 0, 10},
{10, 0, -10},
};
short4 tbn = math::packSnorm16(
mat3f::packTangentFrame(
math::mat3f{
float3{1.0f, 0.0f, 0.0f}, float3{0.0f, 0.0f, 1.0f},
float3{0.0f, 1.0f, 0.0f}})
.xyzw);
const static math::short4 normals[]{tbn, tbn, tbn, tbn};
Engine *engine = Engine::create();
SwapChain *swapChain = engine->createSwapChain(createSDLwindow());
Renderer *renderer = engine->createRenderer();
Camera *camera = engine->createCamera();
View *view = engine->createView();
Scene *scene = engine->createScene();
view->setCamera(camera);
view->setScene(scene);
VertexBuffer *vertexBuffer = VertexBuffer::Builder()
.vertexCount(4)
.bufferCount(2)
.attribute(VertexAttribute::POSITION, 0, VertexBuffer::AttributeType::FLOAT3)
.attribute(VertexAttribute::TANGENTS, 1, VertexBuffer::AttributeType::SHORT4)
.normalized(VertexAttribute::TANGENTS)
.build(*engine);
vertexBuffer->setBufferAt(*engine, 0, VertexBuffer::BufferDescriptor(vertices, vertexBuffer->getVertexCount() * sizeof(vertices[0])));
vertexBuffer->setBufferAt(*engine, 1, VertexBuffer::BufferDescriptor(normals, vertexBuffer->getVertexCount() * sizeof(normals[0])));
IndexBuffer *indexBuffer = IndexBuffer::Builder()
.indexCount(6)
.build(*engine);
indexBuffer->setBuffer(*engine, IndexBuffer::BufferDescriptor(
indices, indexBuffer->getIndexCount() * sizeof(uint32_t)));
Material *material = Material::Builder()
.package((void *)BAKED_MATERIAL_PACKAGE, sizeof(BAKED_MATERIAL_PACKAGE))
.build(*engine);
MaterialInstance *materialInstance = material->createInstance();
Entity renderable = EntityManager::get().create();
Entity light = EntityManager::get().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(true)
.build(*engine, light);
scene->addEntity(light);
// build a quad
RenderableManager::Builder(1)
.boundingBox({{-1, -1, -1}, {1, 1, 1}})
.material(0, materialInstance)
.geometry(0, RenderableManager::PrimitiveType::TRIANGLES, vertexBuffer, indexBuffer, 0, 6)
.culling(false)
.build(*engine, renderable);
scene->addEntity(renderable);
while (1)
{
// beginFrame() returns false if we need to skip a frame
if (renderer->beginFrame(swapChain))
{
// for each View
renderer->render(view);
renderer->endFrame();
}
}
return 0;
}
I get it to compile, but when I run it I get a black SDL window that freezes and a terminal filled with:
...
CommandStream used too much space: 2095520, out of 1048576 (will block)
...
I feel like I'm swinging in the dark here. Especially with the .inc files. Some guidance would be appreciated.
Thanks
The file materials/aiDefaultMat.inc must be generated by matc (using the flag to output the compiled material as an include file). This is done for our samples by the CMakeLists.txt file in the samples directory.
The reason you are getting this error about the command stream is because you are rendering as fast as possible (faster than the GPU can process the commands). You should either use vsync or use SDL_Delay(16); to space our your frames.
I also notice that you didn't setup your camera (you need to specify the projection) nor the viewport (see View::setViewport). See function configureCamerasForWindow() in FilamentApp.cpp in the samples.
We have planned to rewrite the samples from scratch so they're cleaner and easier to understand.
Please let us know if you have further questions.
Sorry for not getting back sooner and thanks for following up. I've added a delay and setup the camera and window like the sample app:
#include <filament/FilamentAPI.h>
#include <filament/Engine.h>
#include <utils/EntityManager.h>
#include <filament/View.h>
#include <filament/RenderableManager.h>
#include <filament/Scene.h>
#include <filament/LightManager.h>
#include <SDL2/SDL.h>
#include <thread>
#include <chrono>
#include <math/norm.h>
static constexpr uint8_t BAKED_MATERIAL_PACKAGE[] = {
#include "materials/aiDefaultMat.inc"
};
using namespace filament;
using namespace utils;
using namespace math;
SDL_Window *createSDLwindow()
{
const uint32_t windowFlags = SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI;
SDL_Window *win = SDL_CreateWindow("Hello World!", 100, 100, 1920, 1080, windowFlags);
if (win == nullptr)
{
std::cout << "SDL_CreateWindow Error: " << SDL_GetError() << std::endl;
SDL_Quit();
return NULL;
}
return win;
}
int main()
{
const static uint32_t indices[] = {
0, 1, 2, 2, 3, 0};
const static math::float3 vertices[] = {
{-10, 0, -10},
{-10, 0, 10},
{10, 0, 10},
{10, 0, -10},
};
short4 tbn = math::packSnorm16(
mat3f::packTangentFrame(
math::mat3f{
float3{1.0f, 0.0f, 0.0f}, float3{0.0f, 0.0f, 1.0f},
float3{0.0f, 1.0f, 0.0f}})
.xyzw);
const static math::short4 normals[]{tbn, tbn, tbn, tbn};
SDL_Window *window = createSDLwindow();
Engine *engine = Engine::create();
SwapChain *swapChain = engine->createSwapChain(window);
Renderer *renderer = engine->createRenderer();
Camera *camera = engine->createCamera();
View *view = engine->createView();
Scene *scene = engine->createScene();
view->setCamera(camera);
// Determine the current size of the window in physical pixels.
uint32_t w, h;
SDL_GL_GetDrawableSize(window, (int *)&w, (int *)&h);
// mWidth = (size_t)w;
// mHeight = (size_t)h;
// Compute the "virtual pixels to physical pixels" scale factor that the
// the platform uses for UI elements.
// int virtualWidth, virtualHeight;
// SDL_GetWindowSize(window, &virtualWidth, &virtualHeight);
// float dpiScaleX = (float)w / virtualWidth;
// float dpiScaleY = (float)h / virtualHeight;
camera->setProjection(45.0, double(w) / h, 0.1, 50, Camera::Fov::VERTICAL);
view->setViewport({0, 0, w, h});
view->setScene(scene);
VertexBuffer *vertexBuffer = VertexBuffer::Builder()
.vertexCount(4)
.bufferCount(2)
.attribute(VertexAttribute::POSITION, 0, VertexBuffer::AttributeType::FLOAT3)
.attribute(VertexAttribute::TANGENTS, 1, VertexBuffer::AttributeType::SHORT4)
.normalized(VertexAttribute::TANGENTS)
.build(*engine);
vertexBuffer->setBufferAt(*engine, 0, VertexBuffer::BufferDescriptor(vertices, vertexBuffer->getVertexCount() * sizeof(vertices[0])));
vertexBuffer->setBufferAt(*engine, 1, VertexBuffer::BufferDescriptor(normals, vertexBuffer->getVertexCount() * sizeof(normals[0])));
IndexBuffer *indexBuffer = IndexBuffer::Builder()
.indexCount(6)
.build(*engine);
indexBuffer->setBuffer(*engine, IndexBuffer::BufferDescriptor(
indices, indexBuffer->getIndexCount() * sizeof(uint32_t)));
Material *material = Material::Builder()
.package((void *)BAKED_MATERIAL_PACKAGE, sizeof(BAKED_MATERIAL_PACKAGE))
.build(*engine);
MaterialInstance *materialInstance = material->createInstance();
Entity renderable = EntityManager::get().create();
Entity light = EntityManager::get().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(true)
.build(*engine, light);
scene->addEntity(light);
// build a quad
RenderableManager::Builder(1)
.boundingBox({{-1, -1, -1}, {1, 1, 1}})
.material(0, materialInstance)
.geometry(0, RenderableManager::PrimitiveType::TRIANGLES, vertexBuffer, indexBuffer, 0, 6)
.culling(false)
.build(*engine, renderable);
scene->addEntity(renderable);
// for (int i = 0; i < 6000; i++)
while (1)
{
// beginFrame() returns false if we need to skip a frame
if (renderer->beginFrame(swapChain))
{
// for each View
renderer->render(view);
renderer->endFrame();
}
SDL_Delay(16);
// std::this_thread::sleep_for(std::chrono::milliseconds(20));
}
engine->destroy(camera);
return 0;
}
But now I'm getting other errors.
[rfebbo@dextella ~]$ echo $XDG_SESSION_TYPE
x11
[rfebbo@dextella renderTest]$ ./a.out
FEngine (64 bits) created at 0x5631175ec080 (threading is enabled)
FEngine resolved backend: OpenGL
HwFence: 16
GLIndexBuffer: 24
GLSamplerBuffer: 24
GLRenderPrimitive: 48
GLTexture: 64
OpenGLProgram: 56
GLRenderTarget: 72
GLVertexBuffer: 112
GLUniformBuffer: 32
GLStream: 128
Intel Open Source Technology Center
Mesa DRI Intel(R) HD Graphics 630 (Kaby Lake GT2)
4.5 (Core Profile) Mesa 18.2.5
4.50
OS version: 0
GL_MAX_RENDERBUFFER_SIZE = 16384
GL_MAX_UNIFORM_BLOCK_SIZE = 65536
GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT = 32
X Error of failed request: BadDrawable (invalid Pixmap or Window parameter)
Major opcode of failed request: 155 (DRI2)
Minor opcode of failed request: 3 (DRI2CreateDrawable)
Resource id in failed request: 0x175eacd0
Serial number of failed request: 33
Current serial number in output stream: 34
The samples compile and run fine.
I'm using x11 primarily, but I switched over to wayland to see if the issue resolved, but I just got different errors.
[rfebbo@dextella ~]$ echo $XDG_SESSION_TYPE
wayland
[rfebbo@dextella ~]$ cd Documents/git/renderTest/
[rfebbo@dextella renderTest]$ ./a.out
FEngine (64 bits) created at 0x7f5400eca010 (threading is enabled)
FEngine resolved backend: OpenGL
X Error of failed request: GLXBadFBConfig
Major opcode of failed request: 151 (GLX)
Minor opcode of failed request: 34 ()
Serial number of failed request: 21
Current serial number in output stream: 19
[rfebbo@dextella renderTest]$ primusrun ./a.out
Segmentation fault (core dumped)
[rfebbo@dextella renderTest]$ optirun ./a.out
FEngine (64 bits) created at 0x7f996eece010 (threading is enabled)
FEngine resolved backend: OpenGL
HwFence: 16
GLIndexBuffer: 24
GLSamplerBuffer: 24
GLRenderPrimitive: 48
GLTexture: 64
OpenGLProgram: 56
GLRenderTarget: 72
GLVertexBuffer: 112
GLUniformBuffer: 32
GLStream: 128
NVIDIA Corporation
GeForce GTX 1050/PCIe/SSE2
4.1.0 NVIDIA 415.18
4.10 NVIDIA via Cg compiler
OS version: 0
GL_MAX_RENDERBUFFER_SIZE = 32768
GL_MAX_UNIFORM_BLOCK_SIZE = 65536
GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT = 256
X Error of failed request: BadWindow (invalid Window parameter)
Major opcode of failed request: 3 (X_GetWindowAttributes)
Resource id in failed request: 0xdf395a90
Serial number of failed request: 29
Current serial number in output stream: 30
glxgears runs fine on integrated and the GTX 1050 Ti.
SDL_Window *window = createSDLwindow(); Engine *engine = Engine::create(); SwapChain *swapChain = engine->createSwapChain(window);
You need to pass the native x11 window to createSwapChain, not the SDL
window. Use this helper (from apps/Native*):
void* getNativeWindow(SDL_Window* sdlWindow)
{
SDL_SysWMinfo wmi;
SDL_VERSION(&wmi.version);
SDL_GetWindowWMInfo(sdlWindow, &wmi);
Window win = (Window) wmi.info.x11.window;
return (void*) win;
}
and feed the pointer you get from this function into createSwapChain.
Cheers,
Kasper
That was it thank you!
You should either use vsync or use SDL_Delay(16); to space our your frames.
Any tips on how we could enable vsync.
For example, I'm on windows (WGL) and in order to do that, I have to either call SDL_GL_SetSwapInterval or wglSwapIntervalEXT - both don't work because the current gl context is not on the main thread (I suppose). I can create another gl context using sdl, on the main thread, but of course that does not work as well.
I guess I can edit filament and enable it there (f.e. in PlatformWGL), but my idea was to not do that directly.
P.S. I see you've added an issue on supporting that.
@uromastix87
Can you please share the entire file? I am trying this sample but I have no luck so far :(
Here it is fixed with some input too. Sorry, it's messy. I haven't tested it with the most recent Filament.
#include <SDL2/SDL.h>
#include <filament/Engine.h>
#include <filament/FilamentAPI.h>
#include <filament/LightManager.h>
#include <filament/RenderableManager.h>
#include <filament/Scene.h>
#include <filament/View.h>
#include <thread>
#include <utils/EntityManager.h>
#include <filament/TransformManager.h>
// #include <Cocoa/Cocoa.h>
#include <math/norm.h>
static constexpr uint8_t BAKED_MATERIAL_PACKAGE[] = {
#include "materials/aiDefaultMat.inc"
};
using namespace filament;
using namespace utils;
using namespace math;
using namespace std;
#include <SDL2/SDL_syswm.h>
void* getNativeWindow(SDL_Window* sdlWindow) {
SDL_SysWMinfo wmi;
SDL_VERSION(&wmi.version);
SDL_GetWindowWMInfo(sdlWindow, &wmi);
Window win = (Window) wmi.info.x11.window;
return (void*) win;
}
SDL_Window* createSDLwindow() {
const uint32_t windowFlags =
SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI;
SDL_Window* win =
SDL_CreateWindow("Hello World!", 100, 100, 1920, 1080, windowFlags);
if (win == nullptr) {
std::cout << "SDL_CreateWindow Error: " << SDL_GetError() << std::endl;
SDL_Quit();
return NULL;
}
return win;
}
void translateVerts(float3 v[], float3 t, int n) {
for (int i = 0; i < n; i++) {
v[i] += t;
}
}
int main() {
const static uint32_t indices[] = { 0, 1, 2, 2, 3, 0 };
float3 vertices[] = {
{ -10, 0, -10 },
{ -10, 0, 10 },
{ 10, 0, 10 },
{ 10, 0, -10 },
};
// translateVerts(vertices, float3(-3, 0, 0), 4);
short4 tbn = math::packSnorm16(
mat3f::packTangentFrame(math::mat3f{ float3{ 1.0f, 0.0f, 0.0f },
float3{ 0.0f, 0.0f, 1.0f },
float3{ 0.0f, 1.0f, 0.0f } })
.xyzw);
const static math::short4 normals[]{ tbn, tbn, tbn, tbn };
SDL_Window* window = createSDLwindow();
Engine* engine = Engine::create();
SwapChain* swapChain = engine->createSwapChain(getNativeWindow(window));
Renderer* renderer = engine->createRenderer();
TransformManager& tcm = engine->getTransformManager();
Camera* camera = engine->createCamera();
View* view = engine->createView();
Scene* scene = engine->createScene();
view->setCamera(camera);
// Determine the current size of the window in physical pixels.
uint32_t w, h;
SDL_GL_GetDrawableSize(window, (int*) &w, (int*) &h);
// mWidth = (size_t)w;
// mHeight = (size_t)h;
// Compute the "virtual pixels to physical pixels" scale factor that the
// the platform uses for UI elements.
// int virtualWidth, virtualHeight;
// SDL_GetWindowSize(window, &virtualWidth, &virtualHeight);
// float dpiScaleX = (float)w / virtualWidth;
// float dpiScaleY = (float)h / virtualHeight;
camera->setProjection(45.0, double(w) / h, 0.1, 50, Camera::Fov::VERTICAL);
view->setViewport({ 0, 0, w, h });
view->setScene(scene);
VertexBuffer* vertexBuffer =
VertexBuffer::Builder()
.vertexCount(4)
.bufferCount(2)
.attribute(VertexAttribute::POSITION, 0,
VertexBuffer::AttributeType::FLOAT3)
.attribute(VertexAttribute::TANGENTS, 1,
VertexBuffer::AttributeType::SHORT4)
.normalized(VertexAttribute::TANGENTS)
.build(*engine);
vertexBuffer->setBufferAt(
*engine, 0,
VertexBuffer::BufferDescriptor(vertices, vertexBuffer->getVertexCount() * sizeof(vertices[0])));
vertexBuffer->setBufferAt(
*engine, 1,
VertexBuffer::BufferDescriptor(normals, vertexBuffer->getVertexCount() * sizeof(normals[0])));
IndexBuffer* indexBuffer =
IndexBuffer::Builder().indexCount(6).build(*engine);
indexBuffer->setBuffer(
*engine, IndexBuffer::BufferDescriptor(indices, indexBuffer->getIndexCount() * sizeof(uint32_t)));
Material* material = Material::Builder()
.package((void*) BAKED_MATERIAL_PACKAGE,
sizeof(BAKED_MATERIAL_PACKAGE))
.build(*engine);
material->setDefaultParameter("baseColor", RgbType::LINEAR, float3{ 0.8, 0, 0 });
material->setDefaultParameter("metallic", 0.0f);
material->setDefaultParameter("roughness", 0.4f);
material->setDefaultParameter("reflectance", 0.5f);
MaterialInstance* materialInstance = material->createInstance();
Entity renderable = EntityManager::get().create();
Entity light = EntityManager::get().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(true)
.build(*engine, light);
scene->addEntity(light);
// build a quad
RenderableManager::Builder(1)
.boundingBox({ { -1, -1, -1 }, { 1, 1, 1 } })
.material(0, materialInstance)
.geometry(0, RenderableManager::PrimitiveType::TRIANGLES, vertexBuffer,
indexBuffer, 0, 6)
.culling(false)
.build(*engine, renderable);
scene->addEntity(renderable);
mat4f origTransform = math::mat4f::translate(float3{ 0, -1, -100 }) * mat4f::rotate(0.5 * M_PI, float3{ 1, 0, 0 });
mat4f camTrans = camera->getModelMatrix();
tcm.setTransform(tcm.getInstance(renderable), origTransform);
constexpr double speed = 100.0;
bool run = true;
double g_discoAngle = 0;
double g_discoAngularSpeed = 1;
double lastTime = 0;
float3 pos = 0;
while (run) {
// beginFrame() returns false if we need to skip a frame
if (renderer->beginFrame(swapChain)) {
// for each View
renderer->render(view);
renderer->endFrame();
}
double now = (double) SDL_GetPerformanceCounter() / SDL_GetPerformanceFrequency();
double dT = now - lastTime;
SDL_Event event;
int numEvents = 0;
while (SDL_PollEvent(&event) && numEvents < 16) {
switch (event.type) {
case SDL_QUIT:
run = false;
break;
case SDL_KEYDOWN: {
switch ((int) event.key.keysym.scancode) {
case SDL_SCANCODE_ESCAPE: {
run = false;
break;
}
case SDL_SCANCODE_W: {
pos.z += dT * speed;
break;
}
case SDL_SCANCODE_A: {
pos.x -= dT * speed;
break;
}
case SDL_SCANCODE_S: {
pos.z -= dT * speed;
break;
}
case SDL_SCANCODE_D: {
pos.x += dT * speed;
break;
}
}
break;
}
}
numEvents++;
}
SDL_Delay(16);
camera->setModelMatrix(mat4f::translate(pos));
// float3 transform = float3(0,2,-4)
mat4f transform = mat4f::translate(float3{ 0, -1, -50 }) * mat4f::rotate(g_discoAngle, float3{ 0, 0, 1 });
transform *= origTransform;
tcm.setTransform(tcm.getInstance(renderable), transform);
g_discoAngle += g_discoAngularSpeed * dT;
lastTime = now;
}
engine->destroy(camera);
return 0;
}
Most helpful comment
The file
materials/aiDefaultMat.incmust be generated bymatc(using the flag to output the compiled material as an include file). This is done for our samples by theCMakeLists.txtfile in the samples directory.The reason you are getting this error about the command stream is because you are rendering as fast as possible (faster than the GPU can process the commands). You should either use vsync or use
SDL_Delay(16);to space our your frames.I also notice that you didn't setup your camera (you need to specify the projection) nor the viewport (see
View::setViewport). See functionconfigureCamerasForWindow()inFilamentApp.cppin the samples.We have planned to rewrite the samples from scratch so they're cleaner and easier to understand.