mirror of https://github.com/mode777/rayjs.git
				
				
				
			Port lightmapper to java
This commit is contained in:
		
							parent
							
								
									5eee29160c
								
							
						
					
					
						commit
						5adc402c26
					
				|  | @ -41,8 +41,4 @@ add_executable(${CMAKE_PROJECT_NAME} ${files}) | |||
| target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE include) | ||||
| target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE src) | ||||
| 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) | ||||
| target_link_libraries(${CMAKE_PROJECT_NAME} quickjs raylib lightmapper) | ||||
|  |  | |||
|  | @ -68,6 +68,30 @@ function main(){ | |||
|     const reasingsFunctions = parser.parseFunctions(reasingsHeader); | ||||
|     reasingsFunctions.forEach(x => api.functions.push(x)) | ||||
| 
 | ||||
|     const rlightmapperHeader = readFileSync("src/rlightmapper.h", "utf8"); | ||||
|     const rlightmapperFunctions = parser.parseFunctionDefinitions(rlightmapperHeader); | ||||
|     const rlightmapperStructs = parser.parseStructs(rlightmapperHeader); | ||||
|     rlightmapperFunctions.forEach(x => api.functions.push(x)); | ||||
|     rlightmapperStructs.forEach(x => api.structs.push(x)); | ||||
|     rlightmapperStructs[0].binding = { | ||||
|         properties: { | ||||
|             w: { get: true }, | ||||
|             h: { get: true }, | ||||
|             progress: { get: true } | ||||
|         } | ||||
|     } | ||||
|     rlightmapperStructs[1].binding = { | ||||
|         properties: { | ||||
|             hemisphereSize: { get: true, set: true }, | ||||
|             zNear: { get: true, set: true }, | ||||
|             zFar: { get: true, set: true }, | ||||
|             backgroundColor: { get: true, set: true }, | ||||
|             interpolationPasses: { get: true, set: true }, | ||||
|             interpolationThreshold: { get: true, set: true }, | ||||
|             cameraToSurfaceDistanceModifier: { get: true, set: true }, | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     // Custom Rayjs functions
 | ||||
|     api.functions.push({ | ||||
|         name: "SetModelMaterial", | ||||
|  | @ -87,6 +111,12 @@ function main(){ | |||
|         returnType: "Color", | ||||
|         params: [{type: "Image *",name:"image"},{type:"int",name:"x"},{type:"int",name:"y"}] | ||||
|     }) | ||||
|     api.functions.push({ | ||||
|         name: "GetModelMesh", | ||||
|         description: "Get a single mesh from a model", | ||||
|         returnType: "Mesh", | ||||
|         params: [{type: "Model *",name:"model"},{type:"int",name:"meshIndex"}] | ||||
|     }) | ||||
| 
 | ||||
|     // Define a new header
 | ||||
|     const core = new RayLibHeader("raylib_core") | ||||
|  | @ -97,6 +127,8 @@ function main(){ | |||
|     core.includes.line("#define RLIGHTS_IMPLEMENTATION") | ||||
|     core.includes.include("rlights.h") | ||||
|     core.includes.include("reasings.h") | ||||
|     core.includes.line("#define RLIGHTMAPPER_IMPLEMENTATION") | ||||
|     core.includes.include("rlightmapper.h") | ||||
| 
 | ||||
|     getStruct(api.structs, "Color")!.binding = { | ||||
|         properties: { | ||||
|  |  | |||
|  | @ -0,0 +1,88 @@ | |||
| function drawScene(scene){ | ||||
| 	drawModel(scene.raylib_model, new Vector3(0,0,0), 1, WHITE); | ||||
| } | ||||
| 
 | ||||
| setConfigFlags(FLAG_MSAA_4X_HINT | FLAG_WINDOW_HIGHDPI | FLAG_VSYNC_HINT); | ||||
| 
 | ||||
| initWindow(1024,768,"Test"); | ||||
| 
 | ||||
| const scene = {} | ||||
| 
 | ||||
| scene.raylib_model = loadModel("models/resources/models/obj/bridge.obj"); | ||||
| 
 | ||||
| scene.w = 512; | ||||
| scene.h = 512; | ||||
| scene.raylib_texture = loadTextureFromImage(genImageColor(1,1,BLACK)); | ||||
| const defMat = loadMaterialDefault(); | ||||
| setMaterialTexture(defMat, MATERIAL_MAP_ALBEDO, scene.raylib_texture); | ||||
| setModelMaterial(scene.raylib_model, 0, defMat); | ||||
| 
 | ||||
| const position = new Vector3( 0.0, 10.0, 30.0 ); // Camera position
 | ||||
| const target = new Vector3( 0.0, 0.35, 0.0);     // Camera looking at point
 | ||||
| const up = new Vector3(0.0, 1.0, 0.0);          // Camera up vector (rotation towards target)
 | ||||
| const fovy = 45.0;                                // Camera field-of-view Y
 | ||||
| const projection = CAMERA_PERSPECTIVE;                   // Camera mode type
 | ||||
| scene.camera = new Camera3D(position, target, up, fovy, projection); | ||||
| const config = getDefaultLightmapperConfig(); | ||||
| //config.backgroundColor = new Color(6,0,10);
 | ||||
| //config.hemisphereSize = 512;
 | ||||
| const mesh = getModelMesh(scene.raylib_model, 0); | ||||
| const lm = loadLightmapper(scene.w, scene.h, mesh, config); | ||||
| const lmMat = loadMaterialLightmapper(BLACK, 0); | ||||
| const light = genMeshCube(0.2,0.2,0.2); | ||||
| const lightMaterial = loadMaterialLightmapper(ORANGE, 0.005);  | ||||
| 
 | ||||
| while (!windowShouldClose()) | ||||
| { | ||||
|     if(isMouseButtonDown(MOUSE_BUTTON_LEFT)) | ||||
|         updateCamera(scene.camera, CAMERA_THIRD_PERSON); | ||||
| 
 | ||||
|     if(lm.progress < 1.0){ | ||||
|         let startTime = getTime(); | ||||
|         beginLightmap(); | ||||
|         while(beginLightmapFragment(lm)){ | ||||
|             drawMesh(mesh, lmMat, matrixIdentity()); | ||||
|             // drawMesh(light, lightMaterial, matrixTranslate(0.0,0.3,0.5));
 | ||||
|             // drawMesh(light, lightMaterial, matrixTranslate(0.0,0.3,-0.5));
 | ||||
|             // drawMesh(light, lightMaterial, matrixMultiply(matrixScale(2,1,2), matrixTranslate(0.0,1.3,0)));
 | ||||
|             // drawMesh(light, lightMaterial, matrixTranslate(0.5,0.3,0));
 | ||||
|             // drawMesh(light, lightMaterial, matrixTranslate(-0.5,0.3,0));
 | ||||
|             endLightmapFragment(lm); | ||||
|             // display progress every second (printf is expensive)
 | ||||
|             let time = getTime(); | ||||
|             if (getTime() - startTime > 0.03) break; | ||||
|         } | ||||
|         endLightmap(); | ||||
|         if(lm.progress == 1.0){ | ||||
|             const img = loadImageFromLightmapper(lm); | ||||
|             //exportImage(img, "my_result.png");
 | ||||
|             const old = scene.raylib_texture; | ||||
|             scene.raylib_texture = loadTextureFromImage(img); | ||||
|             unloadTexture(old); | ||||
|             let mat = loadMaterialDefault(); | ||||
|             setMaterialTexture(mat, MATERIAL_MAP_DIFFUSE, scene.raylib_texture); | ||||
|             setModelMaterial(scene.raylib_model, 0, mat); | ||||
|             unloadLightmapper(lm); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     beginDrawing(); | ||||
|         clearBackground(BLUE); | ||||
|          | ||||
|             beginMode3D(scene.camera); | ||||
|             //float intensity = 1.0f;
 | ||||
|             //SetShaderValue(scene.shader, scene.u_intensity, &intensity, SHADER_UNIFORM_FLOAT);
 | ||||
|             drawScene(scene); | ||||
|             endMode3D(); | ||||
|          | ||||
|         // printf("%d\n",(int)(lm.progress*GetScreenWidth()));
 | ||||
|         if(lm.progress < 1.0){ | ||||
|             drawRectangle(0,0,getScreenWidth(),20, fade(GREEN,0.5)); | ||||
|             drawRectangle(0,0,getScreenWidth()*lm.progress,20, GREEN); | ||||
|         } | ||||
|     endDrawing(); | ||||
| } | ||||
| 
 | ||||
| unloadModel(scene.raylib_model); | ||||
| unloadTexture(scene.raylib_texture); | ||||
| closeWindow(); | ||||
|  | @ -361,6 +361,26 @@ interface Light { | |||
| declare var Light: { | ||||
|     prototype: Light; | ||||
| } | ||||
| interface Lightmapper { | ||||
|     w: number, | ||||
|     h: number, | ||||
|     progress: number, | ||||
| } | ||||
| declare var Lightmapper: { | ||||
|     prototype: Lightmapper; | ||||
| } | ||||
| interface LightmapperConfig { | ||||
|     hemisphereSize: number, | ||||
|     zNear: number, | ||||
|     zFar: number, | ||||
|     backgroundColor: Color, | ||||
|     interpolationPasses: number, | ||||
|     interpolationThreshold: number, | ||||
|     cameraToSurfaceDistanceModifier: number, | ||||
| } | ||||
| declare var LightmapperConfig: { | ||||
|     prototype: LightmapperConfig; | ||||
| } | ||||
| /** Initialize window and OpenGL context */ | ||||
| declare function initWindow(width: number, height: number, title: string | undefined | null): void; | ||||
| /** Check if KEY_ESCAPE pressed or Close icon pressed */ | ||||
|  | @ -1616,12 +1636,32 @@ declare function easeBounceOut(t: number, b: number, c: number, d: number): numb | |||
| declare function easeBounceInOut(t: number, b: number, c: number, d: number): number; | ||||
| /** Elastic Easing functions */ | ||||
| declare function easeElasticIn(t: number, b: number, c: number, d: number): number; | ||||
| /**  */ | ||||
| declare function getDefaultLightmapperConfig(): LightmapperConfig; | ||||
| /**  */ | ||||
| declare function loadLightmapper(w: number, h: number, mesh: Mesh, cfg: LightmapperConfig): Lightmapper; | ||||
| /**  */ | ||||
| declare function loadMaterialLightmapper(emissiveColor: Color, intensity: number): Material; | ||||
| /**  */ | ||||
| declare function unloadLightmapper(lm: Lightmapper): void; | ||||
| /**  */ | ||||
| declare function beginLightmap(): void; | ||||
| /**  */ | ||||
| declare function endLightmap(): void; | ||||
| /**  */ | ||||
| declare function beginLightmapFragment(lm: Lightmapper): boolean; | ||||
| /**  */ | ||||
| declare function endLightmapFragment(lm: Lightmapper): void; | ||||
| /**  */ | ||||
| declare function loadImageFromLightmapper(lm: Lightmapper): Image; | ||||
| /** Replace material in slot materialIndex */ | ||||
| declare function setModelMaterial(model: Model, materialIndex: number, material: Material): void; | ||||
| /** Set shader constant in shader locations array */ | ||||
| declare function setShaderLocation(shader: Shader, shaderConstant: number, location: number): void; | ||||
| /** Read a single pixel from an image */ | ||||
| declare function imageReadPixel(image: Image, x: number, y: number): Color; | ||||
| /** Get a single mesh from a model */ | ||||
| declare function getModelMesh(model: Model, meshIndex: number): Mesh; | ||||
| /** (PI/180.0) */ | ||||
| declare var DEG2RAD: number; | ||||
| /** (180.0/PI) */ | ||||
|  |  | |||
|  | @ -1009,6 +1009,29 @@ function main() { | |||
|     const reasingsHeader = (0, fs_1.readFileSync)("include/reasings.h", "utf8"); | ||||
|     const reasingsFunctions = parser.parseFunctions(reasingsHeader); | ||||
|     reasingsFunctions.forEach(x => api.functions.push(x)); | ||||
|     const rlightmapperHeader = (0, fs_1.readFileSync)("src/rlightmapper.h", "utf8"); | ||||
|     const rlightmapperFunctions = parser.parseFunctionDefinitions(rlightmapperHeader); | ||||
|     const rlightmapperStructs = parser.parseStructs(rlightmapperHeader); | ||||
|     rlightmapperFunctions.forEach(x => api.functions.push(x)); | ||||
|     rlightmapperStructs.forEach(x => api.structs.push(x)); | ||||
|     rlightmapperStructs[0].binding = { | ||||
|         properties: { | ||||
|             w: { get: true }, | ||||
|             h: { get: true }, | ||||
|             progress: { get: true } | ||||
|         } | ||||
|     }; | ||||
|     rlightmapperStructs[1].binding = { | ||||
|         properties: { | ||||
|             hemisphereSize: { get: true, set: true }, | ||||
|             zNear: { get: true, set: true }, | ||||
|             zFar: { get: true, set: true }, | ||||
|             backgroundColor: { get: true, set: true }, | ||||
|             interpolationPasses: { get: true, set: true }, | ||||
|             interpolationThreshold: { get: true, set: true }, | ||||
|             cameraToSurfaceDistanceModifier: { get: true, set: true }, | ||||
|         } | ||||
|     }; | ||||
|     // Custom Rayjs functions
 | ||||
|     api.functions.push({ | ||||
|         name: "SetModelMaterial", | ||||
|  | @ -1028,6 +1051,12 @@ function main() { | |||
|         returnType: "Color", | ||||
|         params: [{ type: "Image *", name: "image" }, { type: "int", name: "x" }, { type: "int", name: "y" }] | ||||
|     }); | ||||
|     api.functions.push({ | ||||
|         name: "GetModelMesh", | ||||
|         description: "Get a single mesh from a model", | ||||
|         returnType: "Mesh", | ||||
|         params: [{ type: "Model *", name: "model" }, { type: "int", name: "meshIndex" }] | ||||
|     }); | ||||
|     // Define a new header
 | ||||
|     const core = new raylib_header_1.RayLibHeader("raylib_core"); | ||||
|     core.includes.include("raymath.h"); | ||||
|  | @ -1037,6 +1066,8 @@ function main() { | |||
|     core.includes.line("#define RLIGHTS_IMPLEMENTATION"); | ||||
|     core.includes.include("rlights.h"); | ||||
|     core.includes.include("reasings.h"); | ||||
|     core.includes.line("#define RLIGHTMAPPER_IMPLEMENTATION"); | ||||
|     core.includes.include("rlightmapper.h"); | ||||
|     getStruct(api.structs, "Color").binding = { | ||||
|         properties: { | ||||
|             r: { get: true, set: true }, | ||||
|  |  | |||
|  | @ -14,6 +14,8 @@ | |||
| #define RLIGHTS_IMPLEMENTATION | ||||
| #include <rlights.h> | ||||
| #include <reasings.h> | ||||
| #define RLIGHTMAPPER_IMPLEMENTATION | ||||
| #include <rlightmapper.h> | ||||
| 
 | ||||
| #ifndef countof | ||||
| #define countof(x) (sizeof(x) / sizeof((x)[0])) | ||||
|  | @ -53,6 +55,8 @@ static JSClassID js_VrDeviceInfo_class_id; | |||
| static JSClassID js_VrStereoConfig_class_id; | ||||
| static JSClassID js_FilePathList_class_id; | ||||
| static JSClassID js_Light_class_id; | ||||
| static JSClassID js_Lightmapper_class_id; | ||||
| static JSClassID js_LightmapperConfig_class_id; | ||||
| 
 | ||||
| static void js_Vector2_finalizer(JSRuntime * rt, JSValue val) { | ||||
|     Vector2* ptr = JS_GetOpaque(val, js_Vector2_class_id); | ||||
|  | @ -2095,6 +2099,192 @@ static int js_declare_Light(JSContext * ctx, JSModuleDef * m) { | |||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| static void js_Lightmapper_finalizer(JSRuntime * rt, JSValue val) { | ||||
|     Lightmapper* ptr = JS_GetOpaque(val, js_Lightmapper_class_id); | ||||
|     if(ptr) { | ||||
|         js_free_rt(rt, ptr); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static JSValue js_Lightmapper_get_w(JSContext* ctx, JSValueConst this_val) { | ||||
|     Lightmapper* ptr = JS_GetOpaque2(ctx, this_val, js_Lightmapper_class_id); | ||||
|     int w = ptr->w; | ||||
|     JSValue ret = JS_NewInt32(ctx, w); | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| static JSValue js_Lightmapper_get_h(JSContext* ctx, JSValueConst this_val) { | ||||
|     Lightmapper* ptr = JS_GetOpaque2(ctx, this_val, js_Lightmapper_class_id); | ||||
|     int h = ptr->h; | ||||
|     JSValue ret = JS_NewInt32(ctx, h); | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| static JSValue js_Lightmapper_get_progress(JSContext* ctx, JSValueConst this_val) { | ||||
|     Lightmapper* ptr = JS_GetOpaque2(ctx, this_val, js_Lightmapper_class_id); | ||||
|     float progress = ptr->progress; | ||||
|     JSValue ret = JS_NewFloat64(ctx, progress); | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| static const JSCFunctionListEntry js_Lightmapper_proto_funcs[] = { | ||||
|     JS_CGETSET_DEF("w",js_Lightmapper_get_w,NULL), | ||||
|     JS_CGETSET_DEF("h",js_Lightmapper_get_h,NULL), | ||||
|     JS_CGETSET_DEF("progress",js_Lightmapper_get_progress,NULL), | ||||
|     JS_PROP_STRING_DEF("[Symbol.toStringTag]","Lightmapper", JS_PROP_CONFIGURABLE), | ||||
| }; | ||||
| 
 | ||||
| static int js_declare_Lightmapper(JSContext * ctx, JSModuleDef * m) { | ||||
|     JS_NewClassID(&js_Lightmapper_class_id); | ||||
|     JSClassDef js_Lightmapper_def = { .class_name = "Lightmapper", .finalizer = js_Lightmapper_finalizer }; | ||||
|     JS_NewClass(JS_GetRuntime(ctx), js_Lightmapper_class_id, &js_Lightmapper_def); | ||||
|     JSValue proto = JS_NewObject(ctx); | ||||
|     JS_SetPropertyFunctionList(ctx, proto, js_Lightmapper_proto_funcs, countof(js_Lightmapper_proto_funcs)); | ||||
|     JS_SetClassProto(ctx, js_Lightmapper_class_id, proto); | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| static void js_LightmapperConfig_finalizer(JSRuntime * rt, JSValue val) { | ||||
|     LightmapperConfig* ptr = JS_GetOpaque(val, js_LightmapperConfig_class_id); | ||||
|     if(ptr) { | ||||
|         js_free_rt(rt, ptr); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static JSValue js_LightmapperConfig_get_hemisphereSize(JSContext* ctx, JSValueConst this_val) { | ||||
|     LightmapperConfig* ptr = JS_GetOpaque2(ctx, this_val, js_LightmapperConfig_class_id); | ||||
|     int hemisphereSize = ptr->hemisphereSize; | ||||
|     JSValue ret = JS_NewInt32(ctx, hemisphereSize); | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| static JSValue js_LightmapperConfig_set_hemisphereSize(JSContext* ctx, JSValueConst this_val, JSValueConst v) { | ||||
|     LightmapperConfig* ptr = JS_GetOpaque2(ctx, this_val, js_LightmapperConfig_class_id); | ||||
|     int value; | ||||
|     JS_ToInt32(ctx, &value, v); | ||||
|     ptr->hemisphereSize = value; | ||||
|     return JS_UNDEFINED; | ||||
| } | ||||
| 
 | ||||
| static JSValue js_LightmapperConfig_get_zNear(JSContext* ctx, JSValueConst this_val) { | ||||
|     LightmapperConfig* ptr = JS_GetOpaque2(ctx, this_val, js_LightmapperConfig_class_id); | ||||
|     float zNear = ptr->zNear; | ||||
|     JSValue ret = JS_NewFloat64(ctx, zNear); | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| static JSValue js_LightmapperConfig_set_zNear(JSContext* ctx, JSValueConst this_val, JSValueConst v) { | ||||
|     LightmapperConfig* ptr = JS_GetOpaque2(ctx, this_val, js_LightmapperConfig_class_id); | ||||
|     double _double_value; | ||||
|     JS_ToFloat64(ctx, &_double_value, v); | ||||
|     float value = (float)_double_value; | ||||
|     ptr->zNear = value; | ||||
|     return JS_UNDEFINED; | ||||
| } | ||||
| 
 | ||||
| static JSValue js_LightmapperConfig_get_zFar(JSContext* ctx, JSValueConst this_val) { | ||||
|     LightmapperConfig* ptr = JS_GetOpaque2(ctx, this_val, js_LightmapperConfig_class_id); | ||||
|     float zFar = ptr->zFar; | ||||
|     JSValue ret = JS_NewFloat64(ctx, zFar); | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| static JSValue js_LightmapperConfig_set_zFar(JSContext* ctx, JSValueConst this_val, JSValueConst v) { | ||||
|     LightmapperConfig* ptr = JS_GetOpaque2(ctx, this_val, js_LightmapperConfig_class_id); | ||||
|     double _double_value; | ||||
|     JS_ToFloat64(ctx, &_double_value, v); | ||||
|     float value = (float)_double_value; | ||||
|     ptr->zFar = value; | ||||
|     return JS_UNDEFINED; | ||||
| } | ||||
| 
 | ||||
| static JSValue js_LightmapperConfig_get_backgroundColor(JSContext* ctx, JSValueConst this_val) { | ||||
|     LightmapperConfig* ptr = JS_GetOpaque2(ctx, this_val, js_LightmapperConfig_class_id); | ||||
|     Color backgroundColor = ptr->backgroundColor; | ||||
|     Color* ret_ptr = (Color*)js_malloc(ctx, sizeof(Color)); | ||||
|     *ret_ptr = backgroundColor; | ||||
|     JSValue ret = JS_NewObjectClass(ctx, js_Color_class_id); | ||||
|     JS_SetOpaque(ret, ret_ptr); | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| static JSValue js_LightmapperConfig_set_backgroundColor(JSContext* ctx, JSValueConst this_val, JSValueConst v) { | ||||
|     LightmapperConfig* ptr = JS_GetOpaque2(ctx, this_val, js_LightmapperConfig_class_id); | ||||
|     Color* value_ptr = (Color*)JS_GetOpaque2(ctx, v, js_Color_class_id); | ||||
|     if(value_ptr == NULL) return JS_EXCEPTION; | ||||
|     Color value = *value_ptr; | ||||
|     ptr->backgroundColor = value; | ||||
|     return JS_UNDEFINED; | ||||
| } | ||||
| 
 | ||||
| static JSValue js_LightmapperConfig_get_interpolationPasses(JSContext* ctx, JSValueConst this_val) { | ||||
|     LightmapperConfig* ptr = JS_GetOpaque2(ctx, this_val, js_LightmapperConfig_class_id); | ||||
|     int interpolationPasses = ptr->interpolationPasses; | ||||
|     JSValue ret = JS_NewInt32(ctx, interpolationPasses); | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| static JSValue js_LightmapperConfig_set_interpolationPasses(JSContext* ctx, JSValueConst this_val, JSValueConst v) { | ||||
|     LightmapperConfig* ptr = JS_GetOpaque2(ctx, this_val, js_LightmapperConfig_class_id); | ||||
|     int value; | ||||
|     JS_ToInt32(ctx, &value, v); | ||||
|     ptr->interpolationPasses = value; | ||||
|     return JS_UNDEFINED; | ||||
| } | ||||
| 
 | ||||
| static JSValue js_LightmapperConfig_get_interpolationThreshold(JSContext* ctx, JSValueConst this_val) { | ||||
|     LightmapperConfig* ptr = JS_GetOpaque2(ctx, this_val, js_LightmapperConfig_class_id); | ||||
|     float interpolationThreshold = ptr->interpolationThreshold; | ||||
|     JSValue ret = JS_NewFloat64(ctx, interpolationThreshold); | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| static JSValue js_LightmapperConfig_set_interpolationThreshold(JSContext* ctx, JSValueConst this_val, JSValueConst v) { | ||||
|     LightmapperConfig* ptr = JS_GetOpaque2(ctx, this_val, js_LightmapperConfig_class_id); | ||||
|     double _double_value; | ||||
|     JS_ToFloat64(ctx, &_double_value, v); | ||||
|     float value = (float)_double_value; | ||||
|     ptr->interpolationThreshold = value; | ||||
|     return JS_UNDEFINED; | ||||
| } | ||||
| 
 | ||||
| static JSValue js_LightmapperConfig_get_cameraToSurfaceDistanceModifier(JSContext* ctx, JSValueConst this_val) { | ||||
|     LightmapperConfig* ptr = JS_GetOpaque2(ctx, this_val, js_LightmapperConfig_class_id); | ||||
|     float cameraToSurfaceDistanceModifier = ptr->cameraToSurfaceDistanceModifier; | ||||
|     JSValue ret = JS_NewFloat64(ctx, cameraToSurfaceDistanceModifier); | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| static JSValue js_LightmapperConfig_set_cameraToSurfaceDistanceModifier(JSContext* ctx, JSValueConst this_val, JSValueConst v) { | ||||
|     LightmapperConfig* ptr = JS_GetOpaque2(ctx, this_val, js_LightmapperConfig_class_id); | ||||
|     double _double_value; | ||||
|     JS_ToFloat64(ctx, &_double_value, v); | ||||
|     float value = (float)_double_value; | ||||
|     ptr->cameraToSurfaceDistanceModifier = value; | ||||
|     return JS_UNDEFINED; | ||||
| } | ||||
| 
 | ||||
| static const JSCFunctionListEntry js_LightmapperConfig_proto_funcs[] = { | ||||
|     JS_CGETSET_DEF("hemisphereSize",js_LightmapperConfig_get_hemisphereSize,js_LightmapperConfig_set_hemisphereSize), | ||||
|     JS_CGETSET_DEF("zNear",js_LightmapperConfig_get_zNear,js_LightmapperConfig_set_zNear), | ||||
|     JS_CGETSET_DEF("zFar",js_LightmapperConfig_get_zFar,js_LightmapperConfig_set_zFar), | ||||
|     JS_CGETSET_DEF("backgroundColor",js_LightmapperConfig_get_backgroundColor,js_LightmapperConfig_set_backgroundColor), | ||||
|     JS_CGETSET_DEF("interpolationPasses",js_LightmapperConfig_get_interpolationPasses,js_LightmapperConfig_set_interpolationPasses), | ||||
|     JS_CGETSET_DEF("interpolationThreshold",js_LightmapperConfig_get_interpolationThreshold,js_LightmapperConfig_set_interpolationThreshold), | ||||
|     JS_CGETSET_DEF("cameraToSurfaceDistanceModifier",js_LightmapperConfig_get_cameraToSurfaceDistanceModifier,js_LightmapperConfig_set_cameraToSurfaceDistanceModifier), | ||||
|     JS_PROP_STRING_DEF("[Symbol.toStringTag]","LightmapperConfig", JS_PROP_CONFIGURABLE), | ||||
| }; | ||||
| 
 | ||||
| static int js_declare_LightmapperConfig(JSContext * ctx, JSModuleDef * m) { | ||||
|     JS_NewClassID(&js_LightmapperConfig_class_id); | ||||
|     JSClassDef js_LightmapperConfig_def = { .class_name = "LightmapperConfig", .finalizer = js_LightmapperConfig_finalizer }; | ||||
|     JS_NewClass(JS_GetRuntime(ctx), js_LightmapperConfig_class_id, &js_LightmapperConfig_def); | ||||
|     JSValue proto = JS_NewObject(ctx); | ||||
|     JS_SetPropertyFunctionList(ctx, proto, js_LightmapperConfig_proto_funcs, countof(js_LightmapperConfig_proto_funcs)); | ||||
|     JS_SetClassProto(ctx, js_LightmapperConfig_class_id, proto); | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| static JSValue js_Vector2_constructor(JSContext * ctx, JSValueConst this_val, int argc, JSValueConst * argv) { | ||||
|     double _double_x; | ||||
|     JS_ToFloat64(ctx, &_double_x, argv[0]); | ||||
|  | @ -10057,6 +10247,94 @@ static JSValue js_easeElasticIn(JSContext * ctx, JSValueConst this_val, int argc | |||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| static JSValue js_getDefaultLightmapperConfig(JSContext * ctx, JSValueConst this_val, int argc, JSValueConst * argv) { | ||||
|     LightmapperConfig returnVal = GetDefaultLightmapperConfig(); | ||||
|     LightmapperConfig* ret_ptr = (LightmapperConfig*)js_malloc(ctx, sizeof(LightmapperConfig)); | ||||
|     *ret_ptr = returnVal; | ||||
|     JSValue ret = JS_NewObjectClass(ctx, js_LightmapperConfig_class_id); | ||||
|     JS_SetOpaque(ret, ret_ptr); | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| static JSValue js_loadLightmapper(JSContext * ctx, JSValueConst this_val, int argc, JSValueConst * argv) { | ||||
|     int w; | ||||
|     JS_ToInt32(ctx, &w, argv[0]); | ||||
|     int h; | ||||
|     JS_ToInt32(ctx, &h, argv[1]); | ||||
|     Mesh* mesh_ptr = (Mesh*)JS_GetOpaque2(ctx, argv[2], js_Mesh_class_id); | ||||
|     if(mesh_ptr == NULL) return JS_EXCEPTION; | ||||
|     Mesh mesh = *mesh_ptr; | ||||
|     LightmapperConfig* cfg_ptr = (LightmapperConfig*)JS_GetOpaque2(ctx, argv[3], js_LightmapperConfig_class_id); | ||||
|     if(cfg_ptr == NULL) return JS_EXCEPTION; | ||||
|     LightmapperConfig cfg = *cfg_ptr; | ||||
|     Lightmapper returnVal = LoadLightmapper(w, h, mesh, cfg); | ||||
|     Lightmapper* ret_ptr = (Lightmapper*)js_malloc(ctx, sizeof(Lightmapper)); | ||||
|     *ret_ptr = returnVal; | ||||
|     JSValue ret = JS_NewObjectClass(ctx, js_Lightmapper_class_id); | ||||
|     JS_SetOpaque(ret, ret_ptr); | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| static JSValue js_loadMaterialLightmapper(JSContext * ctx, JSValueConst this_val, int argc, JSValueConst * argv) { | ||||
|     Color* emissiveColor_ptr = (Color*)JS_GetOpaque2(ctx, argv[0], js_Color_class_id); | ||||
|     if(emissiveColor_ptr == NULL) return JS_EXCEPTION; | ||||
|     Color emissiveColor = *emissiveColor_ptr; | ||||
|     double _double_intensity; | ||||
|     JS_ToFloat64(ctx, &_double_intensity, argv[1]); | ||||
|     float intensity = (float)_double_intensity; | ||||
|     Material returnVal = LoadMaterialLightmapper(emissiveColor, intensity); | ||||
|     Material* ret_ptr = (Material*)js_malloc(ctx, sizeof(Material)); | ||||
|     *ret_ptr = returnVal; | ||||
|     JSValue ret = JS_NewObjectClass(ctx, js_Material_class_id); | ||||
|     JS_SetOpaque(ret, ret_ptr); | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| static JSValue js_unloadLightmapper(JSContext * ctx, JSValueConst this_val, int argc, JSValueConst * argv) { | ||||
|     Lightmapper* lm_ptr = (Lightmapper*)JS_GetOpaque2(ctx, argv[0], js_Lightmapper_class_id); | ||||
|     if(lm_ptr == NULL) return JS_EXCEPTION; | ||||
|     Lightmapper lm = *lm_ptr; | ||||
|     UnloadLightmapper(lm); | ||||
|     return JS_UNDEFINED; | ||||
| } | ||||
| 
 | ||||
| static JSValue js_beginLightmap(JSContext * ctx, JSValueConst this_val, int argc, JSValueConst * argv) { | ||||
|     BeginLightmap(); | ||||
|     return JS_UNDEFINED; | ||||
| } | ||||
| 
 | ||||
| static JSValue js_endLightmap(JSContext * ctx, JSValueConst this_val, int argc, JSValueConst * argv) { | ||||
|     EndLightmap(); | ||||
|     return JS_UNDEFINED; | ||||
| } | ||||
| 
 | ||||
| static JSValue js_beginLightmapFragment(JSContext * ctx, JSValueConst this_val, int argc, JSValueConst * argv) { | ||||
|     Lightmapper* lm = (Lightmapper*)JS_GetOpaque2(ctx, argv[0], js_Lightmapper_class_id); | ||||
|     if(lm == NULL) return JS_EXCEPTION; | ||||
|     bool returnVal = BeginLightmapFragment(lm); | ||||
|     JSValue ret = JS_NewBool(ctx, returnVal); | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| static JSValue js_endLightmapFragment(JSContext * ctx, JSValueConst this_val, int argc, JSValueConst * argv) { | ||||
|     Lightmapper* lm = (Lightmapper*)JS_GetOpaque2(ctx, argv[0], js_Lightmapper_class_id); | ||||
|     if(lm == NULL) return JS_EXCEPTION; | ||||
|     EndLightmapFragment(lm); | ||||
|     return JS_UNDEFINED; | ||||
| } | ||||
| 
 | ||||
| static JSValue js_loadImageFromLightmapper(JSContext * ctx, JSValueConst this_val, int argc, JSValueConst * argv) { | ||||
|     Lightmapper* lm_ptr = (Lightmapper*)JS_GetOpaque2(ctx, argv[0], js_Lightmapper_class_id); | ||||
|     if(lm_ptr == NULL) return JS_EXCEPTION; | ||||
|     Lightmapper lm = *lm_ptr; | ||||
|     Image returnVal = LoadImageFromLightmapper(lm); | ||||
|     Image* ret_ptr = (Image*)js_malloc(ctx, sizeof(Image)); | ||||
|     *ret_ptr = returnVal; | ||||
|     JSValue ret = JS_NewObjectClass(ctx, js_Image_class_id); | ||||
|     JS_SetOpaque(ret, ret_ptr); | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| static JSValue js_setModelMaterial(JSContext * ctx, JSValueConst this_val, int argc, JSValueConst * argv) { | ||||
|     Model* model = (Model*)JS_GetOpaque2(ctx, argv[0], js_Model_class_id); | ||||
|     if(model == NULL) return JS_EXCEPTION; | ||||
|  | @ -10095,6 +10373,19 @@ static JSValue js_imageReadPixel(JSContext * ctx, JSValueConst this_val, int arg | |||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| static JSValue js_getModelMesh(JSContext * ctx, JSValueConst this_val, int argc, JSValueConst * argv) { | ||||
|     Model* model = (Model*)JS_GetOpaque2(ctx, argv[0], js_Model_class_id); | ||||
|     if(model == NULL) return JS_EXCEPTION; | ||||
|     int meshIndex; | ||||
|     JS_ToInt32(ctx, &meshIndex, argv[1]); | ||||
|     Mesh returnVal = GetModelMesh(model, meshIndex); | ||||
|     Mesh* ret_ptr = (Mesh*)js_malloc(ctx, sizeof(Mesh)); | ||||
|     *ret_ptr = returnVal; | ||||
|     JSValue ret = JS_NewObjectClass(ctx, js_Mesh_class_id); | ||||
|     JS_SetOpaque(ret, ret_ptr); | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| static const JSCFunctionListEntry js_raylib_core_funcs[] = { | ||||
|     JS_CFUNC_DEF("initWindow",3,js_initWindow), | ||||
|     JS_CFUNC_DEF("windowShouldClose",0,js_windowShouldClose), | ||||
|  | @ -10711,9 +11002,19 @@ static const JSCFunctionListEntry js_raylib_core_funcs[] = { | |||
|     JS_CFUNC_DEF("easeBounceOut",4,js_easeBounceOut), | ||||
|     JS_CFUNC_DEF("easeBounceInOut",4,js_easeBounceInOut), | ||||
|     JS_CFUNC_DEF("easeElasticIn",4,js_easeElasticIn), | ||||
|     JS_CFUNC_DEF("getDefaultLightmapperConfig",0,js_getDefaultLightmapperConfig), | ||||
|     JS_CFUNC_DEF("loadLightmapper",4,js_loadLightmapper), | ||||
|     JS_CFUNC_DEF("loadMaterialLightmapper",2,js_loadMaterialLightmapper), | ||||
|     JS_CFUNC_DEF("unloadLightmapper",1,js_unloadLightmapper), | ||||
|     JS_CFUNC_DEF("beginLightmap",0,js_beginLightmap), | ||||
|     JS_CFUNC_DEF("endLightmap",0,js_endLightmap), | ||||
|     JS_CFUNC_DEF("beginLightmapFragment",1,js_beginLightmapFragment), | ||||
|     JS_CFUNC_DEF("endLightmapFragment",1,js_endLightmapFragment), | ||||
|     JS_CFUNC_DEF("loadImageFromLightmapper",1,js_loadImageFromLightmapper), | ||||
|     JS_CFUNC_DEF("setModelMaterial",3,js_setModelMaterial), | ||||
|     JS_CFUNC_DEF("setShaderLocation",3,js_setShaderLocation), | ||||
|     JS_CFUNC_DEF("imageReadPixel",3,js_imageReadPixel), | ||||
|     JS_CFUNC_DEF("getModelMesh",2,js_getModelMesh), | ||||
| }; | ||||
| 
 | ||||
| static int js_raylib_core_init(JSContext * ctx, JSModuleDef * m) { | ||||
|  | @ -10777,6 +11078,8 @@ static int js_raylib_core_init(JSContext * ctx, JSModuleDef * m) { | |||
|     js_declare_VrStereoConfig(ctx, m); | ||||
|     js_declare_FilePathList(ctx, m); | ||||
|     js_declare_Light(ctx, m); | ||||
|     js_declare_Lightmapper(ctx, m); | ||||
|     js_declare_LightmapperConfig(ctx, m); | ||||
|     Color LIGHTGRAY_struct = { 200, 200, 200, 255 }; | ||||
|     Color* LIGHTGRAY_js_ptr = (Color*)js_malloc(ctx, sizeof(Color)); | ||||
|     *LIGHTGRAY_js_ptr = LIGHTGRAY_struct; | ||||
|  |  | |||
|  | @ -1,118 +0,0 @@ | |||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| #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 RLIGHTMAPPER_IMPLEMENTATION | ||||
| #include "rlightmapper.h" | ||||
| 
 | ||||
| typedef struct | ||||
| { | ||||
| 	//Shader raylib_shader;
 | ||||
| 	Texture raylib_texture; | ||||
| 	int w, h; | ||||
|     Model raylib_model; | ||||
| 	Model model2; | ||||
| 	Camera camera; | ||||
| 	Shader shader; | ||||
| 	GLuint u_intensity; | ||||
| } scene_t; | ||||
| 
 | ||||
| static void drawScene(scene_t *scene){ | ||||
| 	DrawModel(scene->raylib_model, (Vector3){ 0,0,0 }, 1, WHITE); | ||||
| 	//DrawModel(scene->model2, (Vector3){ -10,10,0.0 }, 3,RAYWHITE);
 | ||||
| } | ||||
| 
 | ||||
| int main(int argc, char* argv[]) | ||||
| { | ||||
| 	SetConfigFlags(FLAG_MSAA_4X_HINT | FLAG_WINDOW_HIGHDPI | FLAG_VSYNC_HINT); | ||||
| 
 | ||||
| 	InitWindow(1024,768,"Test"); | ||||
| 
 | ||||
| 	scene_t scene = {0}; | ||||
| 	 | ||||
| 	scene.shader = LoadShader("assets/shaders/glsl330/default.vs","assets/shaders/glsl330/default.fs"); | ||||
| 	scene.u_intensity = GetShaderLocation(scene.shader, "intensity"); | ||||
| 	// load mesh
 | ||||
|     scene.raylib_model = LoadModel("monkey.obj"); | ||||
| 	scene.raylib_model.materials[0].shader = scene.shader; | ||||
|     scene.model2 = LoadModel("thirdparty/lightmapper/example/cube.obj"); | ||||
| 	scene.model2.materials[0].shader = scene.shader; | ||||
|      | ||||
| 	scene.w = 512; | ||||
| 	scene.h = 512; | ||||
| 	scene.raylib_texture = LoadTextureFromImage(GenImageColor(1,1,BLACK)); | ||||
| 	scene.raylib_model.materials[0].maps[0].texture = scene.raylib_texture; | ||||
| 
 | ||||
| 	Camera camera = { 0 }; | ||||
|     camera.position = (Vector3){ 0.0f, 0.5f, 1.5f }; // Camera position
 | ||||
|     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; | ||||
| 
 | ||||
| 	LightmapperConfig config = GetDefaultLightmapperConfig(); | ||||
| 	config.backgroundColor = (Color){6,0,10}; | ||||
| 	//config.hemisphereSize = 512;
 | ||||
| 	Lightmapper lm = LoadLightmapper(scene.w, scene.h, scene.raylib_model.meshes[0], config); | ||||
| 	Material lmMat = LoadMaterialLightmapper(BLACK, 0); | ||||
| 	Mesh light = GenMeshCube(0.3,0.3, 0.3); | ||||
| 	Material lightMaterial = LoadMaterialLightmapper(ORANGE, 1.0f);  | ||||
| 
 | ||||
| 	while (!WindowShouldClose()) | ||||
| 	{ | ||||
| 		if(IsMouseButtonDown(MOUSE_BUTTON_LEFT)) | ||||
| 			UpdateCamera(&scene.camera, CAMERA_THIRD_PERSON); | ||||
| 
 | ||||
| 		if(lm.progress < 1.0f){ | ||||
| 			double startTime = GetTime(); | ||||
| 			BeginLightmap(); | ||||
| 			while(BeginLightmapFragment(&lm)){ | ||||
| 				DrawMesh(scene.raylib_model.meshes[0], lmMat, MatrixIdentity()); | ||||
| 				DrawMesh(light, lightMaterial, MatrixTranslate(0,1.0,0)); | ||||
| 				EndLightmapFragment(&lm); | ||||
| 				// display progress every second (printf is expensive)
 | ||||
| 				double time = GetTime(); | ||||
| 				if (GetTime() - startTime > 0.03) break; | ||||
| 			} | ||||
| 			EndLightmap(); | ||||
| 			if(lm.progress == 1.0f){ | ||||
| 				Image img = LoadImageFromLightmapper(lm); | ||||
| 				//ExportImage(img, "my_result.png");
 | ||||
| 				UnloadTexture(scene.raylib_texture); | ||||
| 				scene.raylib_texture = LoadTextureFromImage(img); | ||||
| 				scene.raylib_model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = scene.raylib_texture; | ||||
| 				UnloadLightmapper(lm); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		BeginDrawing(); | ||||
| 			ClearBackground(BLUE); | ||||
| 			 | ||||
| 				BeginMode3D(scene.camera); | ||||
| 				float intensity = 1.0f; | ||||
| 				SetShaderValue(scene.shader, scene.u_intensity, &intensity, SHADER_UNIFORM_FLOAT); | ||||
| 				drawScene(&scene); | ||||
| 				EndMode3D(); | ||||
| 			 | ||||
| 			// printf("%d\n",(int)(lm.progress*GetScreenWidth()));
 | ||||
| 			if(lm.progress < 1.0f){ | ||||
| 				DrawRectangle(0,0,GetScreenWidth(),20, Fade(GREEN,0.5)); | ||||
| 				DrawRectangle(0,0,GetScreenWidth()*lm.progress,20, GREEN); | ||||
| 			} | ||||
| 		EndDrawing(); | ||||
| 	} | ||||
| 
 | ||||
| 	UnloadModel(scene.raylib_model); | ||||
| 	UnloadTexture(scene.raylib_texture); | ||||
| 	CloseWindow(); | ||||
| 	return EXIT_SUCCESS; | ||||
| } | ||||
|  | @ -1,192 +0,0 @@ | |||
| #include <stdlib.h> | ||||
| #include "raylib.h" | ||||
| #include "rlgl.h" | ||||
| #define GLAD_MALLOC(sz) malloc(sz) | ||||
| #define GLAD_FREE(sz) free(sz) | ||||
| //#define GLAD_GL_IMPLEMENTATION | ||||
| #include "../thirdparty/raylib/src/external/glad.h" | ||||
| 
 | ||||
| #define LIGHTMAPPER_IMPLEMENTATION | ||||
| #define LM_DEBUG_INTERPOLATION | ||||
| #include "lightmapper.h" | ||||
| 
 | ||||
| // 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" | ||||
| 	"out vec2 v_texcoord;\n" | ||||
| 
 | ||||
| 	"void main()\n" | ||||
| 	"{\n" | ||||
| 	"gl_Position = u_projection * (u_view * vec4(a_position, 1.0));\n" | ||||
| 	"v_texcoord = a_texcoord;\n" | ||||
| 	"}\n"; | ||||
| 
 | ||||
| const char *fp = | ||||
| 	"#version 150 core\n" | ||||
| 	"in vec2 v_texcoord;\n" | ||||
| 	"uniform sampler2D u_lightmap;\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" | ||||
| 	"}\n"; | ||||
| 
 | ||||
| const char *attribs[] = | ||||
| { | ||||
| 	"a_position", | ||||
| 	"a_texcoord" | ||||
| }; | ||||
| 
 | ||||
| int main(void) | ||||
| { | ||||
|     // Initialization | ||||
|     //-------------------------------------------------------------------------------------- | ||||
|     const int screenWidth = 800; | ||||
|     const int screenHeight = 450; | ||||
| 
 | ||||
|     InitWindow(screenWidth, screenHeight, "raylib [models] lightmapping"); | ||||
| 
 | ||||
|      | ||||
| 
 | ||||
|     Model model = LoadModel("thirdparty/lightmapper/example/gazebo.obj"); | ||||
| 	Shader shader = LoadShaderFromMemory(vp, fp);  | ||||
| 	Texture texture = LoadTextureFromImage(GenImageColor(1,1,BLACK)); | ||||
| 	int u_view = GetShaderLocation(shader, "u_view"); | ||||
| 	int u_projection = GetShaderLocation(shader, "u_projection"); | ||||
| 	int u_lightmap = GetShaderLocation(shader, "u_lightmap"); | ||||
| 
 | ||||
| 	 | ||||
|     Vector3 position = { 0.0f, 0.0f, 0.0f };  | ||||
| 
 | ||||
|     //-------------------------------------------------------------------------------------- | ||||
| 
 | ||||
| 	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) TraceLog(LOG_ERROR, "Lightmapper not initialized"); | ||||
| 
 | ||||
| 	int w = 512; | ||||
| 	int h = 512; | ||||
| 	float *data = calloc(w*h*4,sizeof(float)); | ||||
| 
 | ||||
| 	lmSetTargetLightmap(ctx, data, w, h, 4); | ||||
| 
 | ||||
| 	Mesh m = model.meshes[0]; | ||||
| 
 | ||||
| 	lmSetGeometry(ctx, NULL,                                                                 // no transformation in this example | ||||
| 		LM_FLOAT, m.vertices, 0, | ||||
| 		LM_NONE , NULL, 0, | ||||
| 		LM_FLOAT, m.texcoords, 0, | ||||
| 		m.vertexCount, LM_NONE, 0); | ||||
| 
 | ||||
| 	printf("%p\n", m.texcoords); | ||||
| 
 | ||||
| 	int vp[4]; | ||||
| 	Matrix view, projection; | ||||
| 	double lastUpdateTime = 0.0; | ||||
| 
 | ||||
| 	Mesh mesh = model.meshes[0]; | ||||
| 	//SetTargetFPS(10000); | ||||
| 	while (lmBegin(ctx, vp, (float*)&view, (float*)&projection)) | ||||
| 	{ | ||||
| 		glViewport(vp[0], vp[1], vp[2], vp[3]); | ||||
| 		glEnable(GL_DEPTH_TEST); | ||||
| 
 | ||||
| 		glUseProgram(shader.id); | ||||
| 		glUniform1i(u_lightmap, 0); | ||||
| 		glUniformMatrix4fv(u_projection, 1, GL_FALSE, (float *)&projection); | ||||
| 		glUniformMatrix4fv(u_view, 1, GL_FALSE, (float *)&view); | ||||
| 
 | ||||
| 		glBindTexture(GL_TEXTURE_2D, texture.id); | ||||
| 
 | ||||
| 		glBindVertexArray(mesh.vaoId); | ||||
| 		glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount); | ||||
| 
 | ||||
| 		double time = GetTime(); | ||||
| 		if (time - lastUpdateTime > 1.0) | ||||
| 		{ | ||||
| 			lastUpdateTime = time; | ||||
| 			printf("\r%6.2f%%", lmProgress(ctx) * 100.0f); | ||||
| 			fflush(stdout); | ||||
| 		} | ||||
| 
 | ||||
| 		lmEnd(ctx); | ||||
| 		if(WindowShouldClose()) break; | ||||
| 
 | ||||
| 	} | ||||
| 
 | ||||
| 	// 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"); | ||||
| 
 | ||||
| 	rlViewport(0,0, screenWidth, screenHeight); | ||||
| 
 | ||||
| 	 | ||||
| // Define the camera to look into our 3d world | ||||
|     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 | ||||
| 
 | ||||
|     SetTargetFPS(60);               // Set our game to run at 60 frames-per-second | ||||
| 
 | ||||
|     // Main game loop | ||||
|     while (!WindowShouldClose())    // Detect window close button or ESC key | ||||
|     { | ||||
|         // Update | ||||
|         //---------------------------------------------------------------------------------- | ||||
|         //UpdateCamera(&camera, CAMERA_FIRST_PERSON);        | ||||
| 
 | ||||
|         //---------------------------------------------------------------------------------- | ||||
| 
 | ||||
|         // Draw | ||||
|         //---------------------------------------------------------------------------------- | ||||
|         BeginDrawing(); | ||||
| 
 | ||||
|             ClearBackground(RAYWHITE); | ||||
| 
 | ||||
|             BeginMode3D(camera); | ||||
| 
 | ||||
|                 DrawModel(model, position, 1.0f, WHITE); | ||||
| 
 | ||||
|             EndMode3D(); | ||||
| 
 | ||||
|         EndDrawing(); | ||||
|         //---------------------------------------------------------------------------------- | ||||
|     } | ||||
| 
 | ||||
|     // De-Initialization | ||||
|     //-------------------------------------------------------------------------------------- | ||||
|     //UnloadTexture(texture);     // Unload texture | ||||
|     UnloadModel(model);         // Unload model | ||||
| 
 | ||||
|     CloseWindow();              // Close window and OpenGL context | ||||
|     //-------------------------------------------------------------------------------------- | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
|  | @ -4,6 +4,7 @@ | |||
| #include <errno.h> | ||||
| #include <quickjs.h> | ||||
| //#include <quickjs-libc.h>
 | ||||
| #include <external/glad.h> | ||||
| #include <GLFW/glfw3.h> | ||||
| #include <raylib.h> | ||||
| 
 | ||||
|  | @ -212,6 +213,12 @@ void SetModelMaterial(Model *model, int materialIndex, Material material) | |||
|     model->materials[materialIndex] = material; | ||||
| } | ||||
| 
 | ||||
| Mesh GetModelMesh(Model *model, int meshIndex){ | ||||
|     Mesh m = { 0 }; | ||||
|     if(model->meshCount <= meshIndex) return m; | ||||
|     return model->meshes[meshIndex]; | ||||
| } | ||||
| 
 | ||||
| void SetShaderLocation(Shader *shader, int constant, int location){ | ||||
|     shader->locs[constant] = location; | ||||
| } | ||||
|  |  | |||
|  | @ -1,233 +1,267 @@ | |||
| #ifndef RLIGHTMAPPER_H | ||||
| #define RLIGHTMAPPER_H | ||||
| 
 | ||||
| #include <raylib.h> | ||||
| 
 | ||||
| typedef struct Lightmapper { | ||||
| 	void * lm_handle; | ||||
| 	float * data; | ||||
| 	int w; | ||||
| 	int h; | ||||
| 	float progress; | ||||
| } Lightmapper; | ||||
| 
 | ||||
| typedef struct LightmapperConfig { | ||||
| 	int hemisphereSize; | ||||
| 	float zNear; | ||||
| 	float zFar; | ||||
| 	Color backgroundColor; | ||||
| 	int interpolationPasses; | ||||
| 	float interpolationThreshold; | ||||
| 	float cameraToSurfaceDistanceModifier; | ||||
| } LightmapperConfig; | ||||
| 
 | ||||
| LightmapperConfig GetDefaultLightmapperConfig(); | ||||
| Lightmapper LoadLightmapper(int w, int h, Mesh mesh, LightmapperConfig cfg); | ||||
| Material LoadMaterialLightmapper(Color emissiveColor, float intensity); | ||||
| void UnloadLightmapper(Lightmapper lm); | ||||
| void BeginLightmap(); | ||||
| void EndLightmap(); | ||||
| bool BeginLightmapFragment(Lightmapper * lm); | ||||
| void EndLightmapFragment(Lightmapper * lm); | ||||
| Image LoadImageFromLightmapper(Lightmapper lm); | ||||
| 
 | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| #if defined(RLIGHTMAPPER_IMPLEMENTATION) | ||||
| 
 | ||||
| #define LIGHTMAPPER_IMPLEMENTATION | ||||
| //#define LM_DEBUG_INTERPOLATION
 | ||||
| #include "lightmapper.h" | ||||
| 
 | ||||
| static const char* fs =  | ||||
| "#version 330\n" | ||||
| "in vec2 fragTexCoord;\n" | ||||
| "in vec4 fragColor;\n" | ||||
| "out vec4 finalColor;\n" | ||||
| "uniform sampler2D texture0;\n" | ||||
| "uniform vec4 colDiffuse;\n" | ||||
| "void main()\n" | ||||
| "{\n" | ||||
| "    vec4 texelColor = texture(texture0, fragTexCoord);\n" | ||||
| "    texelColor = texelColor * colDiffuse * fragColor * vec4(intensity, intensity, intensity, 1.0);\n" | ||||
| "    finalColor = vec4(texelColor.rgb, (gl_FrontFacing ? 1.0 : 0.0));\n" | ||||
| "}"; | ||||
| 
 | ||||
| const char* vs = "#version 330\n" | ||||
| "in vec3 vertexPosition;\n" | ||||
| "in vec2 vertexTexCoord;\n" | ||||
| "in vec4 vertexColor;\n" | ||||
| "out vec2 fragTexCoord;\n" | ||||
| "out vec4 fragColor;\n" | ||||
| "uniform mat4 mvp;\n" | ||||
| "void main()\n" | ||||
| "{\n" | ||||
| "    fragTexCoord = vertexTexCoord;\n" | ||||
| "    fragColor = vertexColor;\n" | ||||
| "    gl_Position = mvp * vec4(vertexPosition, 1.0);\n" | ||||
| "}"; | ||||
| 
 | ||||
| static void FloatVToMatrix(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]; | ||||
| } | ||||
| 
 | ||||
| LightmapperConfig GetDefaultLightmapperConfig(){ | ||||
| 	return (LightmapperConfig){ | ||||
| 		64, 0.001f, 100.0f, WHITE, 2, 0.01f, 0.0f | ||||
| 	}; | ||||
| } | ||||
| 
 | ||||
| static Shader defaultShader;  | ||||
| 
 | ||||
| Material LoadMaterialLightmapper(Color emissiveColor, float emissiveIntensity) | ||||
| { | ||||
| 	if(defaultShader.id == 0) defaultShader = LoadShaderFromMemory(vs, fs); | ||||
| 
 | ||||
| 	Material mat = LoadMaterialDefault(); | ||||
| 	mat.shader = defaultShader; | ||||
| 	mat.maps[MATERIAL_MAP_DIFFUSE].color = emissiveColor;    // Diffuse color
 | ||||
| 	//mat.params[0] = emissiveIntensity;
 | ||||
|     return mat; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| Lightmapper LoadLightmapper(int w, int h, Mesh mesh, LightmapperConfig cfg){ | ||||
| 	Lightmapper lm = {0}; | ||||
| 	lm_context* ctx = lm.lm_handle = lmCreate(cfg.hemisphereSize, cfg.zNear, cfg.zFar,  | ||||
| 		cfg.backgroundColor.r / (float)255, cfg.backgroundColor.g / (float)255, cfg.backgroundColor.b / (float)255, | ||||
| 		cfg.interpolationPasses, cfg.interpolationThreshold, cfg.cameraToSurfaceDistanceModifier); | ||||
| 
 | ||||
| 	if(ctx == NULL){ | ||||
| 		TraceLog(LOG_ERROR, "Unable to create lightmapper. Init failed."); | ||||
| 		goto RETURN; | ||||
| 	} | ||||
| 
 | ||||
| 	lm.w = w; | ||||
| 	lm.h = h; | ||||
| 	float *data = lm.data = calloc(w * h * 4, sizeof(float)); | ||||
| 	lmSetTargetLightmap(ctx, data, w, h, 4); | ||||
| 
 | ||||
| 	const void* indices = NULL; | ||||
| 	lm_type indicesType = LM_NONE; | ||||
| 	int count = mesh.vertexCount; | ||||
| 	if(mesh.indices != NULL){ | ||||
| 		indices = mesh.indices; | ||||
| 		indicesType = LM_UNSIGNED_SHORT; | ||||
| 		count = mesh.triangleCount * 3; | ||||
| 	} | ||||
| 
 | ||||
| 	lmSetGeometry(ctx, NULL, | ||||
| 		LM_FLOAT, (unsigned char*)mesh.vertices, 0, | ||||
| 		LM_FLOAT , (unsigned char*)mesh.normals, 0,   | ||||
| 		LM_FLOAT, (unsigned char*)mesh.texcoords, 0, | ||||
| 		count, indicesType, indices); | ||||
| 
 | ||||
| 	RETURN: | ||||
| 	return lm; | ||||
| } | ||||
| 
 | ||||
| void UnloadLightmapper(Lightmapper lm){ | ||||
| 	free(lm.data); | ||||
| 	lmDestroy((lm_context *)lm.lm_handle); | ||||
| } | ||||
| 
 | ||||
| static Matrix mProjection; | ||||
| static Matrix mModelview; | ||||
| 
 | ||||
| void BeginLightmap() | ||||
| { | ||||
| 	rlEnableDepthTest(); | ||||
| 	rlDisableColorBlend(); | ||||
| 	rlDisableBackfaceCulling(); | ||||
| 	mProjection = rlGetMatrixProjection(); | ||||
| 	mModelview = rlGetMatrixModelview(); | ||||
| } | ||||
| 
 | ||||
| void EndLightmap(){ | ||||
| 	//rlDisableDepthTest();
 | ||||
| 	rlEnableColorBlend(); | ||||
| 	rlEnableBackfaceCulling(); | ||||
| 	int w = GetScreenWidth() * GetWindowScaleDPI().x; | ||||
| 	int h = GetScreenHeight() * GetWindowScaleDPI().y; | ||||
| 	rlViewport(0, 0, w, h); | ||||
| 	rlDisableFramebuffer(); | ||||
| 	glUseProgram(0); | ||||
| 	glBindTexture(GL_TEXTURE_2D, 0); | ||||
| 	glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); | ||||
| 	glBindVertexArray(0); | ||||
| 	glBindFramebuffer(GL_FRAMEBUFFER, 0); | ||||
| 	glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); | ||||
| 	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); | ||||
| 	rlSetMatrixModelview(mModelview); | ||||
| 	rlSetMatrixProjection(mProjection); | ||||
| } | ||||
| 
 | ||||
| static int vp[4]; | ||||
| static float view[16], projection[16]; | ||||
| static Matrix matView, matProj; | ||||
| 
 | ||||
| bool BeginLightmapFragment(Lightmapper * lm){ | ||||
| 	lm_bool status = lmBegin((lm_context *)lm->lm_handle, vp, view, projection); | ||||
| 	if(status){ | ||||
| 		rlViewport(vp[0], vp[1], vp[2], vp[3]); | ||||
| 		FloatVToMatrix(view, &matView); | ||||
| 		FloatVToMatrix(projection, &matProj); | ||||
| 		rlSetMatrixModelview(matView); | ||||
| 		rlSetMatrixProjection(matProj); | ||||
| 	} else { | ||||
| 		lm->progress = 1.0f; | ||||
| 	} | ||||
| 	return (bool)status; | ||||
| } | ||||
| 
 | ||||
| void EndLightmapFragment(Lightmapper * lm){ | ||||
| 	lm->progress = lmProgress((lm_context *)lm->lm_handle); | ||||
| 	lmEnd((lm_context *)lm->lm_handle); | ||||
| } | ||||
| 
 | ||||
| Image LoadImageFromLightmapper(Lightmapper lm){ | ||||
| 	Image im = { 0 }; | ||||
| 
 | ||||
| 	if(lm.progress < 1.0f){ | ||||
| 		TraceLog(LOG_ERROR, "Lightmapping is not finished"); | ||||
| 		return im;  | ||||
| 	} | ||||
| 	// postprocess texture
 | ||||
| 	float *temp = calloc(lm.w * lm.h * 4, sizeof(float)); | ||||
| 	for (int i = 0; i < 16; i++) | ||||
| 	{ | ||||
| 		lmImageDilate(lm.data, temp, lm.w, lm.h, 4); | ||||
| 		lmImageDilate(temp, lm.data, lm.w, lm.h, 4); | ||||
| 	} | ||||
| 	lmImageSmooth(lm.data, temp, lm.w, lm.h, 4); | ||||
| 	lmImageDilate(temp, lm.data, lm.w, lm.h, 4); | ||||
| 	lmImagePower(lm.data, lm.w, lm.h, 4, 1.0f / 2.2f, 0x7); // gamma correct color channels
 | ||||
| 	free(temp); | ||||
| 
 | ||||
| 	unsigned char *tempub = (unsigned char*)calloc(lm.w * lm.h * 4, sizeof(unsigned char)); | ||||
| 	lmImageFtoUB(lm.data, tempub, lm.w, lm.h, 4, 1.0f); | ||||
| 
 | ||||
| 	im.data = tempub; | ||||
| 	im.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8; | ||||
| 	im.height = lm.w; | ||||
| 	im.width = lm.h; | ||||
| 	im.mipmaps = 1; | ||||
| 	return im; | ||||
| } | ||||
| #ifndef RLIGHTMAPPER_H | ||||
| #define RLIGHTMAPPER_H | ||||
| 
 | ||||
| // ...
 | ||||
| typedef struct { | ||||
|     void *lm_handle; | ||||
|     float *data; | ||||
|     int w; | ||||
|     int h; | ||||
|     float progress; | ||||
| } Lightmapper; | ||||
| 
 | ||||
| // ...
 | ||||
| typedef struct { | ||||
|     int hemisphereSize; | ||||
|     float zNear; | ||||
|     float zFar; | ||||
|     Color backgroundColor; | ||||
|     int interpolationPasses; | ||||
|     float interpolationThreshold; | ||||
|     float cameraToSurfaceDistanceModifier; | ||||
| } LightmapperConfig; | ||||
| 
 | ||||
| #define RLMAPI | ||||
| 
 | ||||
| // ...
 | ||||
| RLMAPI LightmapperConfig GetDefaultLightmapperConfig(void); | ||||
| // ...
 | ||||
| RLMAPI Lightmapper LoadLightmapper(int w, int h, Mesh mesh, LightmapperConfig cfg); | ||||
| // ...
 | ||||
| RLMAPI Material LoadMaterialLightmapper(Color emissiveColor, float intensity); | ||||
| // ...
 | ||||
| RLMAPI void UnloadLightmapper(Lightmapper lm); | ||||
| // ...
 | ||||
| RLMAPI void BeginLightmap(void); | ||||
| // ...
 | ||||
| RLMAPI void EndLightmap(void); | ||||
| // ..
 | ||||
| RLMAPI bool BeginLightmapFragment(Lightmapper *lm); | ||||
| // ...
 | ||||
| RLMAPI void EndLightmapFragment(Lightmapper *lm); | ||||
| // ...
 | ||||
| RLMAPI Image LoadImageFromLightmapper(Lightmapper lm); | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| #if defined(RLIGHTMAPPER_IMPLEMENTATION) | ||||
| 
 | ||||
| #include <rlgl.h> | ||||
| 
 | ||||
| #define LIGHTMAPPER_IMPLEMENTATION | ||||
| // #define LM_DEBUG_INTERPOLATION
 | ||||
| #include "lightmapper.h" | ||||
| 
 | ||||
| static const char *fs = | ||||
|     "#version 330\n" | ||||
|     "in vec2 fragTexCoord;\n" | ||||
|     "in vec4 fragColor;\n" | ||||
|     "out vec4 finalColor;\n" | ||||
|     "uniform sampler2D texture0;\n" | ||||
|     "uniform sampler2D texture1;\n" | ||||
|     "uniform vec4 colDiffuse;\n" | ||||
|     "void main()\n" | ||||
|     "{\n" | ||||
|     "    vec4 texelColor = texture(texture0, fragTexCoord);\n" | ||||
|     "    vec4 emissionColor = texture(texture1, fragTexCoord);\n" | ||||
|     "    texelColor = texelColor * colDiffuse * fragColor * emissionColor;\n" | ||||
|     "    finalColor = vec4(texelColor.rgb, (gl_FrontFacing ? 1.0 : 0.0));\n" | ||||
|     "}"; | ||||
| 
 | ||||
| const char *vs = "#version 330\n" | ||||
|                  "in vec3 vertexPosition;\n" | ||||
|                  "in vec2 vertexTexCoord;\n" | ||||
|                  "in vec4 vertexColor;\n" | ||||
|                  "out vec2 fragTexCoord;\n" | ||||
|                  "out vec4 fragColor;\n" | ||||
|                  "uniform mat4 mvp;\n" | ||||
|                  "void main()\n" | ||||
|                  "{\n" | ||||
|                  "    fragTexCoord = vertexTexCoord;\n" | ||||
|                  "    fragColor = vertexColor;\n" | ||||
|                  "    gl_Position = mvp * vec4(vertexPosition, 1.0);\n" | ||||
|                  "}"; | ||||
| 
 | ||||
| static void FloatVToMatrix(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]; | ||||
| } | ||||
| 
 | ||||
| LightmapperConfig GetDefaultLightmapperConfig() | ||||
| { | ||||
|     return (LightmapperConfig){ | ||||
|         64, 0.001f, 100.0f, WHITE, 2, 0.01f, 0.0f}; | ||||
| } | ||||
| 
 | ||||
| static Shader defaultShader; | ||||
| 
 | ||||
| Material LoadMaterialLightmapper(Color emissiveColor, float emissiveIntensity) | ||||
| { | ||||
|     if (defaultShader.id == 0) | ||||
|         defaultShader = LoadShaderFromMemory(vs, fs); | ||||
| 
 | ||||
|     Material mat = LoadMaterialDefault(); | ||||
|     mat.shader = defaultShader; | ||||
|     float colF[4] = {emissiveColor.r * emissiveIntensity, emissiveColor.g * emissiveIntensity, emissiveColor.b * emissiveIntensity, emissiveColor.a * emissiveIntensity}; | ||||
|     Texture tex = {0}; | ||||
|     tex.format = PIXELFORMAT_UNCOMPRESSED_R32G32B32A32; | ||||
|     tex.width = 1; | ||||
|     tex.height = 1; | ||||
|     tex.mipmaps = 1; | ||||
|     tex.id = rlLoadTexture(colF, 1, 1, RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32, 1); | ||||
|     mat.maps[MATERIAL_MAP_SPECULAR].texture = tex; | ||||
|     // mat.params[0] = emissiveIntensity;
 | ||||
|     return mat; | ||||
| } | ||||
| 
 | ||||
| Lightmapper LoadLightmapper(int w, int h, Mesh mesh, LightmapperConfig cfg) | ||||
| { | ||||
|     Lightmapper lm = {0}; | ||||
|     lm_context *ctx = lm.lm_handle = lmCreate(cfg.hemisphereSize, cfg.zNear, cfg.zFar, | ||||
|                                               cfg.backgroundColor.r / (float)255, cfg.backgroundColor.g / (float)255, cfg.backgroundColor.b / (float)255, | ||||
|                                               cfg.interpolationPasses, cfg.interpolationThreshold, cfg.cameraToSurfaceDistanceModifier); | ||||
| 
 | ||||
|     if (ctx == NULL) | ||||
|     { | ||||
|         TraceLog(LOG_ERROR, "Unable to create lightmapper. Init failed."); | ||||
|         goto RETURN; | ||||
|     } | ||||
| 
 | ||||
|     lm.w = w; | ||||
|     lm.h = h; | ||||
|     float *data = lm.data = calloc(w * h * 4, sizeof(float)); | ||||
|     lmSetTargetLightmap(ctx, data, w, h, 4); | ||||
| 
 | ||||
|     const void *indices = NULL; | ||||
|     lm_type indicesType = LM_NONE; | ||||
|     int count = mesh.vertexCount; | ||||
|     if (mesh.indices != NULL) | ||||
|     { | ||||
|         indices = mesh.indices; | ||||
|         indicesType = LM_UNSIGNED_SHORT; | ||||
|         count = mesh.triangleCount * 3; | ||||
|     } | ||||
| 
 | ||||
|     lmSetGeometry(ctx, NULL, | ||||
|                   LM_FLOAT, (unsigned char *)mesh.vertices, 0, | ||||
|                   LM_FLOAT, (unsigned char *)mesh.normals, 0, | ||||
|                   LM_FLOAT, (unsigned char *)mesh.texcoords, 0, | ||||
|                   count, indicesType, indices); | ||||
| 
 | ||||
| RETURN: | ||||
|     return lm; | ||||
| } | ||||
| 
 | ||||
| void UnloadLightmapper(Lightmapper lm) | ||||
| { | ||||
|     free(lm.data); | ||||
|     lmDestroy((lm_context *)lm.lm_handle); | ||||
| } | ||||
| 
 | ||||
| static Matrix mProjection; | ||||
| static Matrix mModelview; | ||||
| 
 | ||||
| void BeginLightmap() | ||||
| { | ||||
|     rlEnableDepthTest(); | ||||
|     rlDisableColorBlend(); | ||||
|     rlDisableBackfaceCulling(); | ||||
|     mProjection = rlGetMatrixProjection(); | ||||
|     mModelview = rlGetMatrixModelview(); | ||||
| } | ||||
| 
 | ||||
| void EndLightmap() | ||||
| { | ||||
|     // rlDisableDepthTest();
 | ||||
|     rlEnableColorBlend(); | ||||
|     rlEnableBackfaceCulling(); | ||||
|     int w = GetScreenWidth() * GetWindowScaleDPI().x; | ||||
|     int h = GetScreenHeight() * GetWindowScaleDPI().y; | ||||
|     rlViewport(0, 0, w, h); | ||||
|     rlDisableFramebuffer(); | ||||
|     glUseProgram(0); | ||||
|     glBindTexture(GL_TEXTURE_2D, 0); | ||||
|     glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); | ||||
|     glBindVertexArray(0); | ||||
|     glBindFramebuffer(GL_FRAMEBUFFER, 0); | ||||
|     glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); | ||||
|     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); | ||||
|     rlSetMatrixModelview(mModelview); | ||||
|     rlSetMatrixProjection(mProjection); | ||||
| } | ||||
| 
 | ||||
| static int vp[4]; | ||||
| static float view[16], projection[16]; | ||||
| static Matrix matView, matProj; | ||||
| 
 | ||||
| bool BeginLightmapFragment(Lightmapper *lm) | ||||
| { | ||||
|     lm_bool status = lmBegin((lm_context *)lm->lm_handle, vp, view, projection); | ||||
|     if (status) | ||||
|     { | ||||
|         rlViewport(vp[0], vp[1], vp[2], vp[3]); | ||||
|         FloatVToMatrix(view, &matView); | ||||
|         FloatVToMatrix(projection, &matProj); | ||||
|         rlSetMatrixModelview(matView); | ||||
|         rlSetMatrixProjection(matProj); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         lm->progress = 1.0f; | ||||
|     } | ||||
|     return (bool)status; | ||||
| } | ||||
| 
 | ||||
| void EndLightmapFragment(Lightmapper *lm) | ||||
| { | ||||
|     lm->progress = lmProgress((lm_context *)lm->lm_handle); | ||||
|     lmEnd((lm_context *)lm->lm_handle); | ||||
| } | ||||
| 
 | ||||
| Image LoadImageFromLightmapper(Lightmapper lm) | ||||
| { | ||||
|     Image im = {0}; | ||||
| 
 | ||||
|     if (lm.progress < 1.0f) | ||||
|     { | ||||
|         TraceLog(LOG_ERROR, "Lightmapping is not finished"); | ||||
|         return im; | ||||
|     } | ||||
|     // postprocess texture
 | ||||
|     float *temp = calloc(lm.w * lm.h * 4, sizeof(float)); | ||||
|     for (int i = 0; i < 16; i++) | ||||
|     { | ||||
|         lmImageDilate(lm.data, temp, lm.w, lm.h, 4); | ||||
|         lmImageDilate(temp, lm.data, lm.w, lm.h, 4); | ||||
|     } | ||||
|     lmImageSmooth(lm.data, temp, lm.w, lm.h, 4); | ||||
|     lmImageDilate(temp, lm.data, lm.w, lm.h, 4); | ||||
|     lmImagePower(lm.data, lm.w, lm.h, 4, 1.0f / 2.2f, 0x7); // gamma correct color channels
 | ||||
|     free(temp); | ||||
| 
 | ||||
|     unsigned char *tempub = (unsigned char *)calloc(lm.w * lm.h * 4, sizeof(unsigned char)); | ||||
|     lmImageFtoUB(lm.data, tempub, lm.w, lm.h, 4, 1.0f); | ||||
| 
 | ||||
|     im.data = tempub; | ||||
|     im.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8; | ||||
|     im.height = lm.w; | ||||
|     im.width = lm.h; | ||||
|     im.mipmaps = 1; | ||||
|     return im; | ||||
| } | ||||
| #endif | ||||
		Loading…
	
		Reference in New Issue