int bake() { lm_context *ctx = lmCreate(32, 0.001f, 100.0f, m_lightmapSkyColor[0], m_lightmapSkyColor[1], m_lightmapSkyColor[2], 1, 100, false); if (!ctx) { fprintf(stderr, "Error: Could not initialize lightmapper.\n"); return 0; } int w = 654, h = 654; float *data = (float*)calloc(w * h * 4, sizeof(float)); lmSetTargetLightmap(ctx, data, w, h, 4); lmSetGeometry(ctx, NULL, LM_FLOAT, (unsigned char*)m_vertices + offsetof(vertex_t, p), sizeof(vertex_t), LM_FLOAT, (unsigned char*)m_vertices + offsetof(vertex_t, t), sizeof(vertex_t), m_indexCount, LM_UNSIGNED_SHORT, m_indices); int vp[4]; float viewMtx[16], projectionMtx[16]; uint8_t viewID; while (lmBegin(ctx, vp, viewMtx, projectionMtx, &viewID)) { bgfx::setViewClear(0 , BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH , 0x303030ff , 1.0f , 0 ); float progress = ((float)lmProgress(ctx) / (float)m_indexCount) * 100.0f; bgfx::dbgTextClear(); bgfx::dbgTextPrintf(0, 1, 0x0f, "Baking: %4.2f%%", progress); bgfx::touch(0); // render to lightmapper framebuffer bgfx::setViewRect(viewID, vp[0], vp[1], vp[2], vp[3]); drawLightmapScene(viewID, viewMtx, projectionMtx); lmEnd(ctx); } lmDestroy(ctx); // postprocess texture float *temp = (float*)calloc(w * h * 4, sizeof(float)); lmImageSmooth(data, temp, w, h, 4); lmImageDilate(temp, data, w, h, 4); for (int i = 0; i < 16; i++) { lmImageDilate(data, temp, w, h, 4); lmImageDilate(temp, data, w, h, 4); } lmImagePower(data, w, h, 4, 1.0f / 2.2f, 0x7); // gamma correct color channels free(temp); // save result to a file if (m_exportLightmap) { lmImageSaveTGAf("result.tga", data, w, h, 4, 1.0f); } // upload result const bgfx::Memory* mem = bgfx::alloc(w * h * 4); for (int i = 0; i < (w * h * 4); ++i) mem->data[i] = (uint8_t)(data[i] * 255); bgfx::destroyTexture(m_lightmap); m_lightmap = bgfx::createTexture2D(w, h, false, 1, bgfx::TextureFormat::RGBA8, 0, mem); free(data); return 1; }
static int bake(scene_t *scene) { lm_context *ctx = lmCreate(32, 0.001f, 100.0f, 1.0f, 1.0f, 1.0f); if (!ctx) { fprintf(stderr, "Error: Could not initialize lightmapper.\n"); return 0; } int w = scene->w, h = scene->h; float *data = calloc(w * h * 4, sizeof(float)); lmSetTargetLightmap(ctx, data, w, h, 4); lmSetGeometry(ctx, NULL, LM_FLOAT, (unsigned char*)scene->vertices + offsetof(vertex_t, p), sizeof(vertex_t), LM_FLOAT, (unsigned char*)scene->vertices + offsetof(vertex_t, t), sizeof(vertex_t), scene->indexCount, LM_UNSIGNED_SHORT, scene->indices); int vp[4]; float view[16], projection[16]; double lastUpdateTime = 0.0; while (lmBegin(ctx, vp, view, projection)) { // render to lightmapper framebuffer glViewport(vp[0], vp[1], vp[2], vp[3]); drawScene(scene, view, projection); // display progress every second (printf is expensive) double time = glfwGetTime(); if (time - lastUpdateTime > 1.0) { lastUpdateTime = time; printf("\r%d/%d ", lmProgress(ctx) / 3, scene->indexCount / 3); fflush(stdout); } lmEnd(ctx); } printf("\rFinished baking %d triangles.\n", scene->indexCount / 3); lmDestroy(ctx); // postprocess texture float *temp = calloc(w * h * 4, sizeof(float)); lmImageSmooth(data, temp, w, h, 4); lmImageDilate(temp, data, w, h, 4); for (int i = 0; i < 16; i++) { lmImageDilate(data, temp, w, h, 4); lmImageDilate(temp, data, w, h, 4); } lmImagePower(data, w, h, 4, 1.0f / 2.2f, 0x7); // gamma correct color channels free(temp); // save result to a file if (lmImageSaveTGAf("result.tga", data, w, h, 4, 1.0f)) printf("Saved result.tga\n"); // upload result glBindTexture(GL_TEXTURE_2D, scene->lightmap); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_FLOAT, data); free(data); return 1; }
static int bake(scene_t *scene) { lm_context *ctx = lmCreate( 64, // hemisphere resolution (power of two, max=512) 0.001f, 100.0f, // zNear, zFar of hemisphere cameras 1.0f, 1.0f, 1.0f, // background color (white for ambient occlusion) 2, 0.01f, // lightmap interpolation threshold (small differences are interpolated rather than sampled) // check debug_interpolation.tga for an overview of sampled (red) vs interpolated (green) pixels. 0.0f); // modifier for camera-to-surface distance for hemisphere rendering. // tweak this to trade-off between interpolated normals quality and other artifacts (see declaration). if (!ctx) { fprintf(stderr, "Error: Could not initialize lightmapper.\n"); return 0; } int w = scene->w, h = scene->h; float *data = calloc(w * h * 4, sizeof(float)); lmSetTargetLightmap(ctx, data, w, h, 4); lmSetGeometry(ctx, NULL, // no transformation in this example LM_FLOAT, (unsigned char*)scene->vertices + offsetof(vertex_t, p), sizeof(vertex_t), LM_NONE , NULL , 0 , // no interpolated normals in this example LM_FLOAT, (unsigned char*)scene->vertices + offsetof(vertex_t, t), sizeof(vertex_t), scene->indexCount, LM_UNSIGNED_SHORT, scene->indices); int vp[4]; float view[16], projection[16]; double lastUpdateTime = 0.0; while (lmBegin(ctx, vp, view, projection)) { // render to lightmapper framebuffer glViewport(vp[0], vp[1], vp[2], vp[3]); drawScene(scene, view, projection); // display progress every second (printf is expensive) double time = glfwGetTime(); if (time - lastUpdateTime > 1.0) { lastUpdateTime = time; printf("\r%6.2f%%", lmProgress(ctx) * 100.0f); fflush(stdout); } lmEnd(ctx); } printf("\rFinished baking %d triangles.\n", scene->indexCount / 3); lmDestroy(ctx); // postprocess texture float *temp = calloc(w * h * 4, sizeof(float)); for (int i = 0; i < 16; i++) { lmImageDilate(data, temp, w, h, 4); lmImageDilate(temp, data, w, h, 4); } lmImageSmooth(data, temp, w, h, 4); lmImageDilate(temp, data, w, h, 4); lmImagePower(data, w, h, 4, 1.0f / 2.2f, 0x7); // gamma correct color channels free(temp); // save result to a file if (lmImageSaveTGAf("result.tga", data, w, h, 4, 1.0f)) printf("Saved result.tga\n"); // upload result glBindTexture(GL_TEXTURE_2D, scene->lightmap); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_FLOAT, data); free(data); return 1; }