Port lightmapper to java

This commit is contained in:
Alexander Klingenbeck 2023-06-19 23:24:30 +02:00
parent 5eee29160c
commit 5adc402c26
10 changed files with 768 additions and 547 deletions

View File

@ -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 include)
target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE src) target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE src)
target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE thirdparty/raygui/src) target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE thirdparty/raygui/src)
target_link_libraries(${CMAKE_PROJECT_NAME} quickjs raylib) target_link_libraries(${CMAKE_PROJECT_NAME} quickjs raylib lightmapper)
add_executable(lightmapper_example src/lightmapper_example.c)
target_include_directories(lightmapper_example PRIVATE include)
target_link_libraries(lightmapper_example raylib lightmapper)

View File

@ -68,6 +68,30 @@ function main(){
const reasingsFunctions = parser.parseFunctions(reasingsHeader); const reasingsFunctions = parser.parseFunctions(reasingsHeader);
reasingsFunctions.forEach(x => api.functions.push(x)) 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 // Custom Rayjs functions
api.functions.push({ api.functions.push({
name: "SetModelMaterial", name: "SetModelMaterial",
@ -87,6 +111,12 @@ function main(){
returnType: "Color", returnType: "Color",
params: [{type: "Image *",name:"image"},{type:"int",name:"x"},{type:"int",name:"y"}] 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 // Define a new header
const core = new RayLibHeader("raylib_core") const core = new RayLibHeader("raylib_core")
@ -97,6 +127,8 @@ function main(){
core.includes.line("#define RLIGHTS_IMPLEMENTATION") core.includes.line("#define RLIGHTS_IMPLEMENTATION")
core.includes.include("rlights.h") core.includes.include("rlights.h")
core.includes.include("reasings.h") core.includes.include("reasings.h")
core.includes.line("#define RLIGHTMAPPER_IMPLEMENTATION")
core.includes.include("rlightmapper.h")
getStruct(api.structs, "Color")!.binding = { getStruct(api.structs, "Color")!.binding = {
properties: { properties: {

View File

@ -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();

View File

@ -361,6 +361,26 @@ interface Light {
declare var Light: { declare var Light: {
prototype: 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 */ /** Initialize window and OpenGL context */
declare function initWindow(width: number, height: number, title: string | undefined | null): void; declare function initWindow(width: number, height: number, title: string | undefined | null): void;
/** Check if KEY_ESCAPE pressed or Close icon pressed */ /** 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; declare function easeBounceInOut(t: number, b: number, c: number, d: number): number;
/** Elastic Easing functions */ /** Elastic Easing functions */
declare function easeElasticIn(t: number, b: number, c: number, d: number): number; 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 */ /** Replace material in slot materialIndex */
declare function setModelMaterial(model: Model, materialIndex: number, material: Material): void; declare function setModelMaterial(model: Model, materialIndex: number, material: Material): void;
/** Set shader constant in shader locations array */ /** Set shader constant in shader locations array */
declare function setShaderLocation(shader: Shader, shaderConstant: number, location: number): void; declare function setShaderLocation(shader: Shader, shaderConstant: number, location: number): void;
/** Read a single pixel from an image */ /** Read a single pixel from an image */
declare function imageReadPixel(image: Image, x: number, y: number): Color; 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) */ /** (PI/180.0) */
declare var DEG2RAD: number; declare var DEG2RAD: number;
/** (180.0/PI) */ /** (180.0/PI) */

View File

@ -1009,6 +1009,29 @@ function main() {
const reasingsHeader = (0, fs_1.readFileSync)("include/reasings.h", "utf8"); const reasingsHeader = (0, fs_1.readFileSync)("include/reasings.h", "utf8");
const reasingsFunctions = parser.parseFunctions(reasingsHeader); const reasingsFunctions = parser.parseFunctions(reasingsHeader);
reasingsFunctions.forEach(x => api.functions.push(x)); 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 // Custom Rayjs functions
api.functions.push({ api.functions.push({
name: "SetModelMaterial", name: "SetModelMaterial",
@ -1028,6 +1051,12 @@ function main() {
returnType: "Color", returnType: "Color",
params: [{ type: "Image *", name: "image" }, { type: "int", name: "x" }, { type: "int", name: "y" }] 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 // Define a new header
const core = new raylib_header_1.RayLibHeader("raylib_core"); const core = new raylib_header_1.RayLibHeader("raylib_core");
core.includes.include("raymath.h"); core.includes.include("raymath.h");
@ -1037,6 +1066,8 @@ function main() {
core.includes.line("#define RLIGHTS_IMPLEMENTATION"); core.includes.line("#define RLIGHTS_IMPLEMENTATION");
core.includes.include("rlights.h"); core.includes.include("rlights.h");
core.includes.include("reasings.h"); core.includes.include("reasings.h");
core.includes.line("#define RLIGHTMAPPER_IMPLEMENTATION");
core.includes.include("rlightmapper.h");
getStruct(api.structs, "Color").binding = { getStruct(api.structs, "Color").binding = {
properties: { properties: {
r: { get: true, set: true }, r: { get: true, set: true },

View File

@ -14,6 +14,8 @@
#define RLIGHTS_IMPLEMENTATION #define RLIGHTS_IMPLEMENTATION
#include <rlights.h> #include <rlights.h>
#include <reasings.h> #include <reasings.h>
#define RLIGHTMAPPER_IMPLEMENTATION
#include <rlightmapper.h>
#ifndef countof #ifndef countof
#define countof(x) (sizeof(x) / sizeof((x)[0])) #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_VrStereoConfig_class_id;
static JSClassID js_FilePathList_class_id; static JSClassID js_FilePathList_class_id;
static JSClassID js_Light_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) { static void js_Vector2_finalizer(JSRuntime * rt, JSValue val) {
Vector2* ptr = JS_GetOpaque(val, js_Vector2_class_id); Vector2* ptr = JS_GetOpaque(val, js_Vector2_class_id);
@ -2095,6 +2099,192 @@ static int js_declare_Light(JSContext * ctx, JSModuleDef * m) {
return 0; 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) { static JSValue js_Vector2_constructor(JSContext * ctx, JSValueConst this_val, int argc, JSValueConst * argv) {
double _double_x; double _double_x;
JS_ToFloat64(ctx, &_double_x, argv[0]); JS_ToFloat64(ctx, &_double_x, argv[0]);
@ -10057,6 +10247,94 @@ static JSValue js_easeElasticIn(JSContext * ctx, JSValueConst this_val, int argc
return ret; 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) { 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); Model* model = (Model*)JS_GetOpaque2(ctx, argv[0], js_Model_class_id);
if(model == NULL) return JS_EXCEPTION; if(model == NULL) return JS_EXCEPTION;
@ -10095,6 +10373,19 @@ static JSValue js_imageReadPixel(JSContext * ctx, JSValueConst this_val, int arg
return ret; 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[] = { static const JSCFunctionListEntry js_raylib_core_funcs[] = {
JS_CFUNC_DEF("initWindow",3,js_initWindow), JS_CFUNC_DEF("initWindow",3,js_initWindow),
JS_CFUNC_DEF("windowShouldClose",0,js_windowShouldClose), 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("easeBounceOut",4,js_easeBounceOut),
JS_CFUNC_DEF("easeBounceInOut",4,js_easeBounceInOut), JS_CFUNC_DEF("easeBounceInOut",4,js_easeBounceInOut),
JS_CFUNC_DEF("easeElasticIn",4,js_easeElasticIn), 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("setModelMaterial",3,js_setModelMaterial),
JS_CFUNC_DEF("setShaderLocation",3,js_setShaderLocation), JS_CFUNC_DEF("setShaderLocation",3,js_setShaderLocation),
JS_CFUNC_DEF("imageReadPixel",3,js_imageReadPixel), JS_CFUNC_DEF("imageReadPixel",3,js_imageReadPixel),
JS_CFUNC_DEF("getModelMesh",2,js_getModelMesh),
}; };
static int js_raylib_core_init(JSContext * ctx, JSModuleDef * m) { 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_VrStereoConfig(ctx, m);
js_declare_FilePathList(ctx, m); js_declare_FilePathList(ctx, m);
js_declare_Light(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_struct = { 200, 200, 200, 255 };
Color* LIGHTGRAY_js_ptr = (Color*)js_malloc(ctx, sizeof(Color)); Color* LIGHTGRAY_js_ptr = (Color*)js_malloc(ctx, sizeof(Color));
*LIGHTGRAY_js_ptr = LIGHTGRAY_struct; *LIGHTGRAY_js_ptr = LIGHTGRAY_struct;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -4,6 +4,7 @@
#include <errno.h> #include <errno.h>
#include <quickjs.h> #include <quickjs.h>
//#include <quickjs-libc.h> //#include <quickjs-libc.h>
#include <external/glad.h>
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include <raylib.h> #include <raylib.h>
@ -212,6 +213,12 @@ void SetModelMaterial(Model *model, int materialIndex, Material material)
model->materials[materialIndex] = 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){ void SetShaderLocation(Shader *shader, int constant, int location){
shader->locs[constant] = location; shader->locs[constant] = location;
} }

View File

@ -1,74 +1,89 @@
#ifndef RLIGHTMAPPER_H #ifndef RLIGHTMAPPER_H
#define RLIGHTMAPPER_H #define RLIGHTMAPPER_H
#include <raylib.h> // ...
typedef struct {
typedef struct Lightmapper { void *lm_handle;
void * lm_handle; float *data;
float * data; int w;
int w; int h;
int h; float progress;
float progress;
} Lightmapper; } Lightmapper;
typedef struct LightmapperConfig { // ...
int hemisphereSize; typedef struct {
float zNear; int hemisphereSize;
float zFar; float zNear;
Color backgroundColor; float zFar;
int interpolationPasses; Color backgroundColor;
float interpolationThreshold; int interpolationPasses;
float cameraToSurfaceDistanceModifier; float interpolationThreshold;
float cameraToSurfaceDistanceModifier;
} LightmapperConfig; } LightmapperConfig;
LightmapperConfig GetDefaultLightmapperConfig(); #define RLMAPI
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);
// ...
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 #endif
#if defined(RLIGHTMAPPER_IMPLEMENTATION) #if defined(RLIGHTMAPPER_IMPLEMENTATION)
#include <rlgl.h>
#define LIGHTMAPPER_IMPLEMENTATION #define LIGHTMAPPER_IMPLEMENTATION
//#define LM_DEBUG_INTERPOLATION // #define LM_DEBUG_INTERPOLATION
#include "lightmapper.h" #include "lightmapper.h"
static const char* fs = static const char *fs =
"#version 330\n" "#version 330\n"
"in vec2 fragTexCoord;\n" "in vec2 fragTexCoord;\n"
"in vec4 fragColor;\n" "in vec4 fragColor;\n"
"out vec4 finalColor;\n" "out vec4 finalColor;\n"
"uniform sampler2D texture0;\n" "uniform sampler2D texture0;\n"
"uniform vec4 colDiffuse;\n" "uniform sampler2D texture1;\n"
"void main()\n" "uniform vec4 colDiffuse;\n"
"{\n" "void main()\n"
" vec4 texelColor = texture(texture0, fragTexCoord);\n" "{\n"
" texelColor = texelColor * colDiffuse * fragColor * vec4(intensity, intensity, intensity, 1.0);\n" " vec4 texelColor = texture(texture0, fragTexCoord);\n"
" finalColor = vec4(texelColor.rgb, (gl_FrontFacing ? 1.0 : 0.0));\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" const char *vs = "#version 330\n"
"in vec3 vertexPosition;\n" "in vec3 vertexPosition;\n"
"in vec2 vertexTexCoord;\n" "in vec2 vertexTexCoord;\n"
"in vec4 vertexColor;\n" "in vec4 vertexColor;\n"
"out vec2 fragTexCoord;\n" "out vec2 fragTexCoord;\n"
"out vec4 fragColor;\n" "out vec4 fragColor;\n"
"uniform mat4 mvp;\n" "uniform mat4 mvp;\n"
"void main()\n" "void main()\n"
"{\n" "{\n"
" fragTexCoord = vertexTexCoord;\n" " fragTexCoord = vertexTexCoord;\n"
" fragColor = vertexColor;\n" " fragColor = vertexColor;\n"
" gl_Position = mvp * vec4(vertexPosition, 1.0);\n" " gl_Position = mvp * vec4(vertexPosition, 1.0);\n"
"}"; "}";
static void FloatVToMatrix(float *array, struct Matrix *matrix) { static void FloatVToMatrix(float *array, struct Matrix *matrix)
{
matrix->m0 = array[0]; matrix->m0 = array[0];
matrix->m1 = array[1]; matrix->m1 = array[1];
matrix->m2 = array[2]; matrix->m2 = array[2];
@ -87,64 +102,75 @@ static void FloatVToMatrix(float *array, struct Matrix *matrix) {
matrix->m15 = array[15]; matrix->m15 = array[15];
} }
LightmapperConfig GetDefaultLightmapperConfig(){ LightmapperConfig GetDefaultLightmapperConfig()
return (LightmapperConfig){ {
64, 0.001f, 100.0f, WHITE, 2, 0.01f, 0.0f return (LightmapperConfig){
}; 64, 0.001f, 100.0f, WHITE, 2, 0.01f, 0.0f};
} }
static Shader defaultShader; static Shader defaultShader;
Material LoadMaterialLightmapper(Color emissiveColor, float emissiveIntensity) Material LoadMaterialLightmapper(Color emissiveColor, float emissiveIntensity)
{ {
if(defaultShader.id == 0) defaultShader = LoadShaderFromMemory(vs, fs); if (defaultShader.id == 0)
defaultShader = LoadShaderFromMemory(vs, fs);
Material mat = LoadMaterialDefault(); Material mat = LoadMaterialDefault();
mat.shader = defaultShader; mat.shader = defaultShader;
mat.maps[MATERIAL_MAP_DIFFUSE].color = emissiveColor; // Diffuse color float colF[4] = {emissiveColor.r * emissiveIntensity, emissiveColor.g * emissiveIntensity, emissiveColor.b * emissiveIntensity, emissiveColor.a * emissiveIntensity};
//mat.params[0] = 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; 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);
Lightmapper LoadLightmapper(int w, int h, Mesh mesh, LightmapperConfig cfg){ if (ctx == NULL)
Lightmapper lm = {0}; {
lm_context* ctx = lm.lm_handle = lmCreate(cfg.hemisphereSize, cfg.zNear, cfg.zFar, TraceLog(LOG_ERROR, "Unable to create lightmapper. Init failed.");
cfg.backgroundColor.r / (float)255, cfg.backgroundColor.g / (float)255, cfg.backgroundColor.b / (float)255, goto RETURN;
cfg.interpolationPasses, cfg.interpolationThreshold, cfg.cameraToSurfaceDistanceModifier); }
if(ctx == NULL){ lm.w = w;
TraceLog(LOG_ERROR, "Unable to create lightmapper. Init failed."); lm.h = h;
goto RETURN; float *data = lm.data = calloc(w * h * 4, sizeof(float));
} lmSetTargetLightmap(ctx, data, w, h, 4);
lm.w = w; const void *indices = NULL;
lm.h = h; lm_type indicesType = LM_NONE;
float *data = lm.data = calloc(w * h * 4, sizeof(float)); int count = mesh.vertexCount;
lmSetTargetLightmap(ctx, data, w, h, 4); if (mesh.indices != NULL)
{
indices = mesh.indices;
indicesType = LM_UNSIGNED_SHORT;
count = mesh.triangleCount * 3;
}
const void* indices = NULL; lmSetGeometry(ctx, NULL,
lm_type indicesType = LM_NONE; LM_FLOAT, (unsigned char *)mesh.vertices, 0,
int count = mesh.vertexCount; LM_FLOAT, (unsigned char *)mesh.normals, 0,
if(mesh.indices != NULL){ LM_FLOAT, (unsigned char *)mesh.texcoords, 0,
indices = mesh.indices; count, indicesType, indices);
indicesType = LM_UNSIGNED_SHORT;
count = mesh.triangleCount * 3;
}
lmSetGeometry(ctx, NULL, RETURN:
LM_FLOAT, (unsigned char*)mesh.vertices, 0, return lm;
LM_FLOAT , (unsigned char*)mesh.normals, 0,
LM_FLOAT, (unsigned char*)mesh.texcoords, 0,
count, indicesType, indices);
RETURN:
return lm;
} }
void UnloadLightmapper(Lightmapper lm){ void UnloadLightmapper(Lightmapper lm)
free(lm.data); {
lmDestroy((lm_context *)lm.lm_handle); free(lm.data);
lmDestroy((lm_context *)lm.lm_handle);
} }
static Matrix mProjection; static Matrix mProjection;
@ -152,82 +178,90 @@ static Matrix mModelview;
void BeginLightmap() void BeginLightmap()
{ {
rlEnableDepthTest(); rlEnableDepthTest();
rlDisableColorBlend(); rlDisableColorBlend();
rlDisableBackfaceCulling(); rlDisableBackfaceCulling();
mProjection = rlGetMatrixProjection(); mProjection = rlGetMatrixProjection();
mModelview = rlGetMatrixModelview(); mModelview = rlGetMatrixModelview();
} }
void EndLightmap(){ void EndLightmap()
//rlDisableDepthTest(); {
rlEnableColorBlend(); // rlDisableDepthTest();
rlEnableBackfaceCulling(); rlEnableColorBlend();
int w = GetScreenWidth() * GetWindowScaleDPI().x; rlEnableBackfaceCulling();
int h = GetScreenHeight() * GetWindowScaleDPI().y; int w = GetScreenWidth() * GetWindowScaleDPI().x;
rlViewport(0, 0, w, h); int h = GetScreenHeight() * GetWindowScaleDPI().y;
rlDisableFramebuffer(); rlViewport(0, 0, w, h);
glUseProgram(0); rlDisableFramebuffer();
glBindTexture(GL_TEXTURE_2D, 0); glUseProgram(0);
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); glBindTexture(GL_TEXTURE_2D, 0);
glBindVertexArray(0); glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindVertexArray(0);
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
rlSetMatrixModelview(mModelview); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
rlSetMatrixProjection(mProjection); rlSetMatrixModelview(mModelview);
rlSetMatrixProjection(mProjection);
} }
static int vp[4]; static int vp[4];
static float view[16], projection[16]; static float view[16], projection[16];
static Matrix matView, matProj; static Matrix matView, matProj;
bool BeginLightmapFragment(Lightmapper * lm){ bool BeginLightmapFragment(Lightmapper *lm)
lm_bool status = lmBegin((lm_context *)lm->lm_handle, vp, view, projection); {
if(status){ lm_bool status = lmBegin((lm_context *)lm->lm_handle, vp, view, projection);
rlViewport(vp[0], vp[1], vp[2], vp[3]); if (status)
FloatVToMatrix(view, &matView); {
FloatVToMatrix(projection, &matProj); rlViewport(vp[0], vp[1], vp[2], vp[3]);
rlSetMatrixModelview(matView); FloatVToMatrix(view, &matView);
rlSetMatrixProjection(matProj); FloatVToMatrix(projection, &matProj);
} else { rlSetMatrixModelview(matView);
lm->progress = 1.0f; rlSetMatrixProjection(matProj);
} }
return (bool)status; else
{
lm->progress = 1.0f;
}
return (bool)status;
} }
void EndLightmapFragment(Lightmapper * lm){ void EndLightmapFragment(Lightmapper *lm)
lm->progress = lmProgress((lm_context *)lm->lm_handle); {
lmEnd((lm_context *)lm->lm_handle); lm->progress = lmProgress((lm_context *)lm->lm_handle);
lmEnd((lm_context *)lm->lm_handle);
} }
Image LoadImageFromLightmapper(Lightmapper lm){ Image LoadImageFromLightmapper(Lightmapper lm)
Image im = { 0 }; {
Image im = {0};
if(lm.progress < 1.0f){ if (lm.progress < 1.0f)
TraceLog(LOG_ERROR, "Lightmapping is not finished"); {
return im; TraceLog(LOG_ERROR, "Lightmapping is not finished");
} return im;
// postprocess texture }
float *temp = calloc(lm.w * lm.h * 4, sizeof(float)); // postprocess texture
for (int i = 0; i < 16; i++) 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); 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); lmImageSmooth(lm.data, temp, lm.w, lm.h, 4);
lmImagePower(lm.data, lm.w, lm.h, 4, 1.0f / 2.2f, 0x7); // gamma correct color channels lmImageDilate(temp, lm.data, lm.w, lm.h, 4);
free(temp); 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)); 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); lmImageFtoUB(lm.data, tempub, lm.w, lm.h, 4, 1.0f);
im.data = tempub; im.data = tempub;
im.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8; im.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
im.height = lm.w; im.height = lm.w;
im.width = lm.h; im.width = lm.h;
im.mipmaps = 1; im.mipmaps = 1;
return im; return im;
} }
#endif #endif