diff --git a/.vscode/settings.json b/.vscode/settings.json index 489d783..184a5f1 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -8,6 +8,7 @@ "glad.h": "c", "lightmapper.h": "c", "compare": "c", - "memory": "c" + "memory": "c", + "rlgl.h": "c" } } \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index e9c92ad..0d45b64 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,4 +44,5 @@ target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE thirdparty/raygui/src) target_link_libraries(${CMAKE_PROJECT_NAME} quickjs raylib) add_executable(lightmapper_example src/lightmapper_example.c) +target_include_directories(lightmapper_example PRIVATE include) target_link_libraries(lightmapper_example raylib lightmapper) diff --git a/src/lightmapper_example.c b/src/lightmapper_example.c index 5e4a7ff..059d587 100644 --- a/src/lightmapper_example.c +++ b/src/lightmapper_example.c @@ -1,18 +1,12 @@ -#define _USE_MATH_DEFINES #include #include #include #include #include -//#include "glad/glad.h" -#define GLAD_MALLOC(sz) malloc(sz) -#define GLAD_FREE(sz) free(sz) -//#define GLAD_GL_IMPLEMENTATION -#include "../thirdparty/raylib/src/external/glad.h" -//#include "GLFW/glfw3.h" -#include "raylib.h" -#include "rlgl.h" +#include +#include +#include #define LIGHTMAPPER_IMPLEMENTATION #define LM_DEBUG_INTERPOLATION #include "lightmapper.h" @@ -28,14 +22,15 @@ typedef struct { typedef struct { - GLuint program; + //GLuint program; + Shader raylib_shader; GLint u_lightmap; - GLint u_projection; - GLint u_view; - + GLint u_mvp; + Texture raylib_texture; GLuint lightmap; int w, h; Model raylib_model; + Camera camera; } scene_t; static int initScene(scene_t *scene); @@ -74,10 +69,13 @@ static int bake(scene_t *scene) int vp[4]; float view[16], projection[16]; double lastUpdateTime = 0.0; + rlEnableDepthTest(); + rlDisableColorBlend(); while (lmBegin(ctx, vp, view, projection)) { // render to lightmapper framebuffer rlViewport(vp[0], vp[1], vp[2], vp[3]); + drawScene(scene, view, projection); // display progress every second (printf is expensive) @@ -91,6 +89,9 @@ static int bake(scene_t *scene) lmEnd(ctx); } + rlDisableDepthTest(); + rlEnableColorBlend(); + //printf("\rFinished baking %d triangles.\n", scene->indexCount / 3); lmDestroy(ctx); @@ -119,7 +120,16 @@ static int bake(scene_t *scene) // upload result rlUnloadTexture(scene->lightmap); scene->lightmap = rlLoadTexture(tempub, w, h, RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, 1); + Texture texture; + texture.id = scene->lightmap; + texture.width = w; + texture.height = h; + texture.mipmaps = 1; + texture.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8; + scene->raylib_texture = texture; free(tempub); + + scene->raylib_model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = texture; // // save result to a file // if (lmImageSaveTGAf("result.tga", data, w, h, 4, 1.0f)) @@ -129,14 +139,6 @@ static int bake(scene_t *scene) return 1; } -static void error_callback(int error, const char *description) -{ - fprintf(stderr, "Error: %s\n", description); -} - -static void fpsCameraViewMatrix(float *view); -static void perspectiveMatrix(float *out, float fovy, float aspect, float zNear, float zFar); - static int first = 1; static void mainLoop(scene_t *scene) @@ -149,19 +151,21 @@ static void mainLoop(scene_t *scene) int w = GetScreenWidth() * GetWindowScaleDPI().x; int h = GetScreenHeight() * GetWindowScaleDPI().y; - glViewport(0, 0, w, h); + 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); + //fpsCameraViewMatrix(view); + //perspectiveMatrix(projection, 45.0f, (float)w / (float)h, 0.01f, 100.0f); BeginDrawing(); - // draw to screen with a blueish sky - glClearColor(0.6f, 0.8f, 1.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - drawScene(scene, view, projection); - + 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(); } @@ -195,10 +199,6 @@ int main(int argc, char* argv[]) return EXIT_SUCCESS; } -// helpers //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -static int loadSimpleObjFile(const char *filename, vertex_t **vertices, unsigned int *vertexCount, unsigned short **indices, unsigned int *indexCount); -static GLuint loadProgram(const char *vp, const char *fp, const char **attributes, int attributeCount); - static int initScene(scene_t *scene) { // load mesh @@ -207,96 +207,72 @@ static int initScene(scene_t *scene) if(m.normals != NULL) puts("Has normals"); if(m.texcoords != NULL) puts("Has texcoords"); if(m.texcoords2 != NULL) puts("Has texcoords2"); - //scene->vertices = myModel.meshes[0]. - // if (!loadSimpleObjFile("thirdparty/lightmapper/example/gazebo.obj", &scene->vertices, &scene->vertexCount, &scene->indices, &scene->indexCount)) - // { - // fprintf(stderr, "Error loading obj file\n"); - // return 0; - // } - - // glGenVertexArrays(1, &scene->vao); - // glBindVertexArray(scene->vao); - - // glGenBuffers(1, &scene->vbo); - // glBindBuffer(GL_ARRAY_BUFFER, scene->vbo); - // glBufferData(GL_ARRAY_BUFFER, scene->vertexCount * sizeof(vertex_t), scene->vertices, GL_STATIC_DRAW); - - // glGenBuffers(1, &scene->ibo); - // glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, scene->ibo); - // glBufferData(GL_ELEMENT_ARRAY_BUFFER, scene->indexCount * sizeof(unsigned short), scene->indices, GL_STATIC_DRAW); - - // glEnableVertexAttribArray(0); - // glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (void*)offsetof(vertex_t, p)); - // glEnableVertexAttribArray(1); - // glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (void*)offsetof(vertex_t, t)); - - // create lightmap texture - scene->w = 654; - scene->h = 654; - glGenTextures(1, &scene->lightmap); - glBindTexture(GL_TEXTURE_2D, scene->lightmap); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - unsigned char emissive[] = { 0, 0, 0, 255 }; - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, emissive); + if(m.indices != NULL) puts("Has indices"); + + scene->w = 512; + scene->h = 512; + scene->lightmap = LoadTextureFromImage(GenImageColor(1,1,BLACK)).id; // load shader const char *vp = "#version 150 core\n" - "in vec3 a_position;\n" - "in vec2 a_texcoord;\n" - "uniform mat4 u_view;\n" - "uniform mat4 u_projection;\n" + "in vec3 vertexPosition;\n" + "in vec2 vertexTexCoord;\n" + "uniform mat4 mvp;\n" "out vec2 v_texcoord;\n" "void main()\n" "{\n" - "gl_Position = u_projection * (u_view * vec4(a_position, 1.0));\n" - "v_texcoord = vec2(a_texcoord.x, a_texcoord.y);\n" + "gl_Position = mvp * vec4(vertexPosition, 1.0);\n" + "v_texcoord = vertexTexCoord;\n" "}\n"; const char *fp = "#version 150 core\n" "in vec2 v_texcoord;\n" - "uniform sampler2D u_lightmap;\n" + "uniform sampler2D texture0;\n" "out vec4 o_color;\n" "void main()\n" "{\n" - "o_color = vec4(texture(u_lightmap, v_texcoord).rgb, gl_FrontFacing ? 1.0 : 0.0);\n" + "o_color = vec4(texture(texture0, v_texcoord).rgb, gl_FrontFacing ? 1.0 : 0.0);\n" "}\n"; - const char *attribs[] = - { - "a_position", - "a_texcoord" - }; + //scene->program = rlLoadShaderCode(vp, fp); + scene->raylib_shader = LoadShaderFromMemory(vp, fp); - scene->program = loadProgram(vp, fp, attribs, 2); - if (!scene->program) - { - fprintf(stderr, "Error loading shader\n"); - return 0; - } - scene->u_view = glGetUniformLocation(scene->program, "u_view"); - scene->u_projection = glGetUniformLocation(scene->program, "u_projection"); - scene->u_lightmap = glGetUniformLocation(scene->program, "u_lightmap"); + 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.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]; - glEnable(GL_DEPTH_TEST); - glDisable(GL_BLEND); - glUseProgram(scene->program); - glUniform1i(scene->u_lightmap, 0); - glUniformMatrix4fv(scene->u_projection, 1, GL_FALSE, projection); - glUniformMatrix4fv(scene->u_view, 1, GL_FALSE, view); + 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); @@ -308,250 +284,7 @@ static void drawScene(scene_t *scene, float *view, float *projection) static void destroyScene(scene_t *scene) { - // free(scene->vertices); - // free(scene->indices); - // glDeleteVertexArrays(1, &scene->vao); - // glDeleteBuffers(1, &scene->vbo); - // glDeleteBuffers(1, &scene->ibo); - glDeleteTextures(1, &scene->lightmap); - glDeleteProgram(scene->program); -} - -static int loadSimpleObjFile(const char *filename, vertex_t **vertices, unsigned int *vertexCount, unsigned short **indices, unsigned int *indexCount) -{ - FILE *file = fopen(filename, "rt"); - if (!file) - return 0; - char line[1024]; - - // first pass - unsigned int np = 0, nn = 0, nt = 0, nf = 0; - while (!feof(file)) - { - fgets(line, 1024, file); - if (line[0] == '#') continue; - if (line[0] == 'v') - { - if (line[1] == ' ') { np++; continue; } - if (line[1] == 'n') { nn++; continue; } - if (line[1] == 't') { nt++; continue; } - assert(!"unknown vertex attribute"); - } - if (line[0] == 'f') { nf++; continue; } - assert(!"unknown identifier"); - } - assert(np && np == nn && np == nt && nf); // only supports obj files without separately indexed vertex attributes - - // allocate memory - *vertexCount = np; - *vertices = calloc(np, sizeof(vertex_t)); - *indexCount = nf * 3; - *indices = calloc(nf * 3, sizeof(unsigned short)); - - // second pass - fseek(file, 0, SEEK_SET); - unsigned int cp = 0, cn = 0, ct = 0, cf = 0; - while (!feof(file)) - { - fgets(line, 1024, file); - if (line[0] == '#') continue; - if (line[0] == 'v') - { - if (line[1] == ' ') { float *p = (*vertices)[cp++].p; char *e1, *e2; p[0] = (float)strtod(line + 2, &e1); p[1] = (float)strtod(e1, &e2); p[2] = (float)strtod(e2, 0); continue; } - if (line[1] == 'n') { /*float *n = (*vertices)[cn++].n; char *e1, *e2; n[0] = (float)strtod(line + 3, &e1); n[1] = (float)strtod(e1, &e2); n[2] = (float)strtod(e2, 0);*/ continue; } // no normals needed - if (line[1] == 't') { float *t = (*vertices)[ct++].t; char *e1; t[0] = (float)strtod(line + 3, &e1); t[1] = (float)strtod(e1, 0); continue; } - assert(!"unknown vertex attribute"); - } - if (line[0] == 'f') - { - unsigned short *tri = (*indices) + cf; - cf += 3; - char *e1, *e2, *e3 = line + 1; - for (int i = 0; i < 3; i++) - { - unsigned long pi = strtoul(e3 + 1, &e1, 10); - assert(e1[0] == '/'); - unsigned long ti = strtoul(e1 + 1, &e2, 10); - assert(e2[0] == '/'); - unsigned long ni = strtoul(e2 + 1, &e3, 10); - assert(pi == ti && pi == ni); - tri[i] = (unsigned short)(pi - 1); - } - continue; - } - assert(!"unknown identifier"); - } - - fclose(file); - return 1; -} - -static GLuint loadShader(GLenum type, const char *source) -{ - GLuint shader = glCreateShader(type); - if (shader == 0) - { - fprintf(stderr, "Could not create shader!\n"); - return 0; - } - glShaderSource(shader, 1, &source, NULL); - glCompileShader(shader); - GLint compiled; - glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); - if (!compiled) - { - fprintf(stderr, "Could not compile shader!\n"); - GLint infoLen = 0; - glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen); - if (infoLen) - { - char* infoLog = (char*)malloc(infoLen); - glGetShaderInfoLog(shader, infoLen, NULL, infoLog); - fprintf(stderr, "%s\n", infoLog); - free(infoLog); - } - glDeleteShader(shader); - return 0; - } - return shader; -} -static GLuint loadProgram(const char *vp, const char *fp, const char **attributes, int attributeCount) -{ - GLuint vertexShader = loadShader(GL_VERTEX_SHADER, vp); - if (!vertexShader) - return 0; - GLuint fragmentShader = loadShader(GL_FRAGMENT_SHADER, fp); - if (!fragmentShader) - { - glDeleteShader(vertexShader); - return 0; - } - - GLuint program = glCreateProgram(); - if (program == 0) - { - fprintf(stderr, "Could not create program!\n"); - return 0; - } - glAttachShader(program, vertexShader); - glAttachShader(program, fragmentShader); - - for (int i = 0; i < attributeCount; i++) - glBindAttribLocation(program, i, attributes[i]); - - glLinkProgram(program); - glDeleteShader(vertexShader); - glDeleteShader(fragmentShader); - GLint linked; - glGetProgramiv(program, GL_LINK_STATUS, &linked); - if (!linked) - { - fprintf(stderr, "Could not link program!\n"); - GLint infoLen = 0; - glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLen); - if (infoLen) - { - char* infoLog = (char*)malloc(sizeof(char) * infoLen); - glGetProgramInfoLog(program, infoLen, NULL, infoLog); - fprintf(stderr, "%s\n", infoLog); - free(infoLog); - } - glDeleteProgram(program); - return 0; - } - return program; -} - -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 translationMatrix(float *out, float x, float y, float z) -{ - out[ 0] = 1.0f; out[ 1] = 0.0f; out[ 2] = 0.0f; out[ 3] = 0.0f; - out[ 4] = 0.0f; out[ 5] = 1.0f; out[ 6] = 0.0f; out[ 7] = 0.0f; - out[ 8] = 0.0f; out[ 9] = 0.0f; out[10] = 1.0f; out[11] = 0.0f; - out[12] = x; out[13] = y; out[14] = z; out[15] = 1.0f; -} -static void rotationMatrix(float *out, float angle, float x, float y, float z) -{ - angle *= (float)M_PI / 180.0f; - float c = cosf(angle), s = sinf(angle), c2 = 1.0f - c; - out[ 0] = x*x*c2 + c; out[ 1] = y*x*c2 + z*s; out[ 2] = x*z*c2 - y*s; out[ 3] = 0.0f; - out[ 4] = x*y*c2 - z*s; out[ 5] = y*y*c2 + c; out[ 6] = y*z*c2 + x*s; out[ 7] = 0.0f; - out[ 8] = x*z*c2 + y*s; out[ 9] = y*z*c2 - x*s; out[10] = z*z*c2 + c; out[11] = 0.0f; - out[12] = 0.0f; out[13] = 0.0f; out[14] = 0.0f; out[15] = 1.0f; -} -static void transformPosition(float *out, float *m, float *p) -{ - float d = 1.0f / (m[3] * p[0] + m[7] * p[1] + m[11] * p[2] + m[15]); - out[2] = d * (m[2] * p[0] + m[6] * p[1] + m[10] * p[2] + m[14]); - out[1] = d * (m[1] * p[0] + m[5] * p[1] + m[ 9] * p[2] + m[13]); - out[0] = d * (m[0] * p[0] + m[4] * p[1] + m[ 8] * p[2] + m[12]); -} -static void transposeMatrix(float *out, float *m) -{ - out[ 0] = m[0]; out[ 1] = m[4]; out[ 2] = m[ 8]; out[ 3] = m[12]; - out[ 4] = m[1]; out[ 5] = m[5]; out[ 6] = m[ 9]; out[ 7] = m[13]; - out[ 8] = m[2]; out[ 9] = m[6]; out[10] = m[10]; out[11] = m[14]; - out[12] = m[3]; out[13] = m[7]; out[14] = m[11]; out[15] = m[15]; -} -static void perspectiveMatrix(float *out, float fovy, float aspect, float zNear, float zFar) -{ - float f = 1.0f / tanf(fovy * (float)M_PI / 360.0f); - float izFN = 1.0f / (zNear - zFar); - out[ 0] = f / aspect; out[ 1] = 0.0f; out[ 2] = 0.0f; out[ 3] = 0.0f; - out[ 4] = 0.0f; out[ 5] = f; out[ 6] = 0.0f; out[ 7] = 0.0f; - out[ 8] = 0.0f; out[ 9] = 0.0f; out[10] = (zFar + zNear) * izFN; out[11] = -1.0f; - out[12] = 0.0f; out[13] = 0.0f; out[14] = 2.0f * zFar * zNear * izFN; out[15] = 0.0f; -} - -static void fpsCameraViewMatrix(float *view) -{ - // initial camera config - static float position[] = { 0.0f, 0.3f, 1.5f }; - static float rotation[] = { 0.0f, 0.0f }; - - // mouse look - static double lastMouse[] = { 0.0, 0.0 }; - Vector2 m = GetMousePosition(); - double mouse[2] = { m.x, m.y }; - //glfwGetCursorPos(window, &mouse[0], &mouse[1]); - - if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) - { - rotation[0] += (float)(mouse[1] - lastMouse[1]) * -0.2f; - rotation[1] += (float)(mouse[0] - lastMouse[0]) * -0.2f; - } - lastMouse[0] = mouse[0]; - lastMouse[1] = mouse[1]; - - float rotationY[16], rotationX[16], rotationYX[16]; - rotationMatrix(rotationX, rotation[0], 1.0f, 0.0f, 0.0f); - rotationMatrix(rotationY, rotation[1], 0.0f, 1.0f, 0.0f); - multiplyMatrices(rotationYX, rotationY, rotationX); - - // keyboard movement (WSADEQ) - float speed = (IsKeyDown(KEY_LEFT_SHIFT)) ? 0.1f : 0.01f; - float movement[3] = {0}; - // if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) movement[2] -= speed; - // if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) movement[2] += speed; - // if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) movement[0] -= speed; - // if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) movement[0] += speed; - // if (glfwGetKey(window, GLFW_KEY_E) == GLFW_PRESS) movement[1] -= speed; - // if (glfwGetKey(window, GLFW_KEY_Q) == GLFW_PRESS) movement[1] += speed; - - float worldMovement[3]; - transformPosition(worldMovement, rotationYX, movement); - position[0] += worldMovement[0]; - position[1] += worldMovement[1]; - position[2] += worldMovement[2]; - - // construct view matrix - float inverseRotation[16], inverseTranslation[16]; - transposeMatrix(inverseRotation, rotationYX); - translationMatrix(inverseTranslation, -position[0], -position[1], -position[2]); - multiplyMatrices(view, inverseRotation, inverseTranslation); // = inverse(translation(position) * rotationYX); -} + UnloadModel(scene->raylib_model); + UnloadTexture(scene->raylib_texture); + UnloadShader(scene->raylib_shader); +} \ No newline at end of file