Use raylib drawing function for baking

This commit is contained in:
Alexander Klingenbeck 2023-06-17 09:43:20 +02:00
parent 03a6079549
commit 75b8f12e9b
1 changed files with 54 additions and 88 deletions

View File

@ -3,9 +3,11 @@
#include <math.h>
#include <stddef.h>
#include <assert.h>
#include <string.h>
#include <raylib.h>
#include <rlgl.h>
#include <raymath.h>
#include <external/glad.h>
#define LIGHTMAPPER_IMPLEMENTATION
#define LM_DEBUG_INTERPOLATION
@ -27,7 +29,7 @@ typedef struct
GLint u_lightmap;
GLint u_mvp;
Texture raylib_texture;
GLuint lightmap;
//GLuint lightmap;
int w, h;
Model raylib_model;
Camera camera;
@ -37,23 +39,36 @@ static int initScene(scene_t *scene);
static void drawScene(scene_t *scene, float *view, float *projection);
static void destroyScene(scene_t *scene);
static void convertArrayToStruct(float *array, struct Matrix *matrix) {
matrix->m0 = array[0];
matrix->m1 = array[1];
matrix->m2 = array[2];
matrix->m3 = array[3];
matrix->m4 = array[4];
matrix->m5 = array[5];
matrix->m6 = array[6];
matrix->m7 = array[7];
matrix->m8 = array[8];
matrix->m9 = array[9];
matrix->m10 = array[10];
matrix->m11 = array[11];
matrix->m12 = array[12];
matrix->m13 = array[13];
matrix->m14 = array[14];
matrix->m15 = array[15];
}
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)
0.1f, 0.15f, 0.5f, // 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);
@ -69,18 +84,29 @@ static int bake(scene_t *scene)
int vp[4];
float view[16], projection[16];
double lastUpdateTime = 0.0;
rlEnableDepthTest();
rlDisableColorBlend();
Shader oldShader = scene->raylib_model.materials[0].shader;
scene->raylib_model.materials[0].shader = scene->raylib_shader;
scene->raylib_model.materials[0].maps[0].texture = scene->raylib_texture;
while (lmBegin(ctx, vp, view, projection))
{
// render to lightmapper framebuffer
rlViewport(vp[0], vp[1], vp[2], vp[3]);
Matrix matView, matProj;
convertArrayToStruct(view, &matView);
convertArrayToStruct(projection, &matProj);
rlSetMatrixModelview(matView);
rlSetMatrixProjection(matProj);
drawScene(scene, view, projection);
DrawModel(scene->raylib_model, (Vector3){ 0,0,0 }, 1, WHITE);
// display progress every second (printf is expensive)
double time = GetTime();
if (time - lastUpdateTime > 1.0)
if (time - lastUpdateTime > 0.05)
{
lastUpdateTime = time;
printf("\r%6.2f%%", lmProgress(ctx) * 100.0f);
@ -91,8 +117,7 @@ static int bake(scene_t *scene)
}
rlDisableDepthTest();
rlEnableColorBlend();
//printf("\rFinished baking %d triangles.\n", scene->indexCount / 3);
scene->raylib_model.materials[0].shader = oldShader;
lmDestroy(ctx);
@ -118,10 +143,9 @@ static int bake(scene_t *scene)
ExportImage(im,"result.png");
// upload result
rlUnloadTexture(scene->lightmap);
scene->lightmap = rlLoadTexture(tempub, w, h, RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, 1);
UnloadTexture(scene->raylib_texture);
Texture texture;
texture.id = scene->lightmap;
texture.id = rlLoadTexture(tempub, w, h, RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, 1);
texture.width = w;
texture.height = h;
texture.mipmaps = 1;
@ -139,36 +163,6 @@ static int bake(scene_t *scene)
return 1;
}
static int first = 1;
static void mainLoop(scene_t *scene)
{
if (first){
bake(scene);
first = 0;
}
int w = GetScreenWidth() * GetWindowScaleDPI().x;
int h = GetScreenHeight() * GetWindowScaleDPI().y;
rlViewport(0, 0, w, h);
// camera for glfw window
float view[16], projection[16];
//fpsCameraViewMatrix(view);
//perspectiveMatrix(projection, 45.0f, (float)w / (float)h, 0.01f, 100.0f);
BeginDrawing();
BeginMode3D(scene->camera);
ClearBackground(BLUE);
rlEnableDepthTest();
//drawScene(scene, view, projection);
DrawModel(scene->raylib_model, (Vector3) {0.0f,0.0f,0.0f}, 1, WHITE);
rlDisableDepthTest();
EndMode3D();
EndDrawing();
}
int main(int argc, char* argv[])
{
SetConfigFlags(FLAG_MSAA_4X_HINT | FLAG_WINDOW_HIGHDPI | FLAG_VSYNC_HINT);
@ -176,22 +170,22 @@ int main(int argc, char* argv[])
InitWindow(1024,768,"Test");
scene_t scene = {0};
if (!initScene(&scene))
{
fprintf(stderr, "Could not initialize scene.\n");
return EXIT_FAILURE;
}
printf("Ambient Occlusion Baking Example.\n");
printf("Use your mouse and the W, A, S, D, E, Q keys to navigate.\n");
printf("Press SPACE to start baking one light bounce!\n");
printf("This will take a few seconds and bake a lightmap illuminated by:\n");
printf("1. The mesh itself (initially black)\n");
printf("2. A white sky (1.0f, 1.0f, 1.0f)\n");
initScene(&scene);
bake(&scene);
while (!WindowShouldClose())
{
mainLoop(&scene);
int w = GetScreenWidth() * GetWindowScaleDPI().x;
int h = GetScreenHeight() * GetWindowScaleDPI().y;
rlViewport(0, 0, w, h);
BeginDrawing();
BeginMode3D(scene.camera);
ClearBackground(BLUE);
DrawModel(scene.raylib_model, (Vector3) {0.0f,0.0f,0.0f}, 1, WHITE);
EndMode3D();
EndDrawing();
}
destroyScene(&scene);
@ -211,7 +205,7 @@ static int initScene(scene_t *scene)
scene->w = 512;
scene->h = 512;
scene->lightmap = LoadTextureFromImage(GenImageColor(1,1,BLACK)).id;
scene->raylib_texture = LoadTextureFromImage(GenImageColor(1,1,BLACK));
// load shader
const char *vp =
@ -238,50 +232,22 @@ static int initScene(scene_t *scene)
"o_color = vec4(texture(texture0, v_texcoord).rgb, gl_FrontFacing ? 1.0 : 0.0);\n"
"}\n";
//scene->program = rlLoadShaderCode(vp, fp);
scene->raylib_shader = LoadShaderFromMemory(vp, fp);
scene->u_lightmap = rlGetLocationUniform(scene->raylib_shader.id, "texture0");
scene->u_mvp = rlGetLocationUniform(scene->raylib_shader.id, "mvp");
//scene->raylib_model.materials[0].shader = scene->raylib_shader;
Camera camera = { 0 };
camera.position = (Vector3){ 1.0f, 0.5f, 1.0f }; // Camera position
camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point
camera.target = (Vector3){ 0.0f, 0.35f, 0.0f }; // Camera looking at point
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
camera.fovy = 45.0f; // Camera field-of-view Y
camera.projection = CAMERA_PERSPECTIVE; // Camera mode type
scene->camera = camera;
return 1;
}
static void multiplyMatrices(float *out, float *a, float *b)
{
for (int y = 0; y < 4; y++)
for (int x = 0; x < 4; x++)
out[y * 4 + x] = a[x] * b[y * 4] + a[4 + x] * b[y * 4 + 1] + a[8 + x] * b[y * 4 + 2] + a[12 + x] * b[y * 4 + 3];
}
static void drawScene(scene_t *scene, float *view, float *projection)
{
Mesh m = scene->raylib_model.meshes[0];
rlEnableShader(scene->raylib_shader.id);
float mvp[16];
multiplyMatrices(mvp, projection, view);
glUniformMatrix4fv(scene->u_mvp, 1, GL_FALSE, mvp);
glBindTexture(GL_TEXTURE_2D, scene->lightmap);
//glBindVertexArray(scene->vao);
//glDrawElements(GL_TRIANGLES, scene->indexCount, GL_UNSIGNED_SHORT, 0);
glBindVertexArray(m.vaoId);
glDrawArrays(GL_TRIANGLES, 0, m.vertexCount);
}
static void destroyScene(scene_t *scene)
{
UnloadModel(scene->raylib_model);