lightmapping support
parent
f5b664efe1
commit
985b4de0d2
16
bind/v4k.lua
16
bind/v4k.lua
|
@ -2957,7 +2957,8 @@ unsigned num_textures;
|
|||
handle *textures;
|
||||
char **texture_names;
|
||||
material_t* materials;
|
||||
texture_t *lightmap;
|
||||
texture_t lightmap;
|
||||
float *lmdata;
|
||||
unsigned num_meshes;
|
||||
unsigned num_triangles;
|
||||
unsigned num_joints;
|
||||
|
@ -2969,6 +2970,8 @@ mat44 pivot;
|
|||
int stride;
|
||||
void *verts;
|
||||
int num_verts;
|
||||
void *tris;
|
||||
int num_tris;
|
||||
handle vao, ibo, vbo, vao_instanced;
|
||||
unsigned flags;
|
||||
unsigned billboard;
|
||||
|
@ -3004,14 +3007,15 @@ anim_t* anims;
|
|||
typedef struct lightmap_t {
|
||||
struct lm_context *ctx;
|
||||
bool ready;
|
||||
texture_t lightmap;
|
||||
int w, h;
|
||||
int atlas_w, atlas_h;
|
||||
texture_t atlas;
|
||||
model_t** models;
|
||||
unsigned shader;
|
||||
} lightmap_t;
|
||||
lightmap_t lightmap(int hmsize , float near, float far, vec3 color , int passes , float threshold , float distmod );
|
||||
void lightmap_setup(lightmap_t *lm, int w, int h);
|
||||
void lightmap_addmodel(lightmap_t *lm, model_t *m);
|
||||
void lightmap_bake(lightmap_t *lm, int bounces, void (*drawscene)(lightmap_t *lm, float *view, float *proj, void *userdata), void *userdata);
|
||||
void lightmap_clear(lightmap_t *lm);
|
||||
void lightmap_bake(lightmap_t *lm, int bounces, void (*drawscene)(lightmap_t *lm, model_t *m, float *view, float *proj, void *userdata), void *userdata);
|
||||
void lightmap_destroy(lightmap_t *lm);
|
||||
typedef struct skybox_t {
|
||||
handle program;
|
||||
|
@ -3337,7 +3341,7 @@ unsigned play;
|
|||
bool paused;
|
||||
struct atlas_t *a;
|
||||
} sprite_t;
|
||||
enum { OBJTYPE_sprite_t = 10 }; typedef struct { unsigned static_assert_on_L__LINE__ : !!(10 <= 255); } static_assert_on_Lconcat(_L,3954)___COUNTER__; typedef struct { unsigned static_assert_on_L__LINE__ : !!(sizeof(sprite_t)); } static_assert_on_Lconcat(_L,3954)___COUNTER__;;
|
||||
enum { OBJTYPE_sprite_t = 10 }; typedef struct { unsigned static_assert_on_L__LINE__ : !!(10 <= 255); } static_assert_on_Lconcat(_L,3959)___COUNTER__; typedef struct { unsigned static_assert_on_L__LINE__ : !!(sizeof(sprite_t)); } static_assert_on_Lconcat(_L,3959)___COUNTER__;;
|
||||
void sprite_ctor(sprite_t *s);
|
||||
void sprite_dtor(sprite_t *s);
|
||||
void sprite_tick(sprite_t *s);
|
||||
|
|
426
demos/99-lmap.c
426
demos/99-lmap.c
|
@ -1,407 +1,63 @@
|
|||
#include "v4k.h"
|
||||
|
||||
#define LIGHTMAPPER_IMPLEMENTATION
|
||||
//#define LM_DEBUG_INTERPOLATION
|
||||
#include "3rd_lightmapper.h"
|
||||
skybox_t sky;
|
||||
model_t litm;
|
||||
|
||||
#define scene_t scene_t2
|
||||
|
||||
typedef struct {
|
||||
float p[3];
|
||||
float t[2];
|
||||
} vertex_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GLuint program;
|
||||
GLint u_lightmap;
|
||||
GLint u_projection;
|
||||
GLint u_view;
|
||||
|
||||
GLuint lightmap;
|
||||
int w, h;
|
||||
|
||||
GLuint vao, vbo, ibo;
|
||||
vertex_t *vertices;
|
||||
unsigned short *indices;
|
||||
unsigned int vertexCount, indexCount;
|
||||
} scene_t;
|
||||
|
||||
static int initScene(scene_t *scene);
|
||||
static void drawScene(scene_t *scene, float *view, float *projection);
|
||||
static void destroyScene(scene_t *scene);
|
||||
|
||||
static int bake(scene_t *scene)
|
||||
{
|
||||
lm_context *ctx = lmCreate(
|
||||
64, // hemisphere resolution (power of two, max=512)
|
||||
0.001f, 100.0f, // zNear, zFar of hemisphere cameras
|
||||
1.0f, 1.0f, 1.0f, // background color (white for ambient occlusion)
|
||||
2, 0.01f, // lightmap interpolation threshold (small differences are interpolated rather than sampled)
|
||||
// check debug_interpolation.tga for an overview of sampled (red) vs interpolated (green) pixels.
|
||||
0.0f); // modifier for camera-to-surface distance for hemisphere rendering.
|
||||
// tweak this to trade-off between interpolated normals quality and other artifacts (see declaration).
|
||||
|
||||
if (!ctx)
|
||||
{
|
||||
fprintf(stderr, "Error: Could not initialize lightmapper.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w = scene->w, h = scene->h;
|
||||
float *data = CALLOC(w * h * 4, sizeof(float));
|
||||
for (int b = 0; b < 1; b++) {
|
||||
memset(data, 0, w*h*4);
|
||||
lmSetTargetLightmap(ctx, data, w, h, 4);
|
||||
|
||||
lmSetGeometry(ctx, NULL, // no transformation in this example
|
||||
LM_FLOAT, (unsigned char*)scene->vertices + offsetof(vertex_t, p), sizeof(vertex_t),
|
||||
LM_NONE , NULL , 0 , // no interpolated normals in this example
|
||||
LM_FLOAT, (unsigned char*)scene->vertices + offsetof(vertex_t, t), sizeof(vertex_t),
|
||||
scene->indexCount, LM_UNSIGNED_SHORT, scene->indices);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
int vp[4];
|
||||
float view[16], projection[16];
|
||||
double lastUpdateTime = 0.0;
|
||||
while (lmBegin(ctx, vp, view, projection))
|
||||
{
|
||||
// render to lightmapper framebuffer
|
||||
glViewport(vp[0], vp[1], vp[2], vp[3]);
|
||||
drawScene(scene, view, projection);
|
||||
|
||||
// display progress every second (printf is expensive)
|
||||
double time = time_ms() / 1000.0;
|
||||
if (time - lastUpdateTime > 1.0)
|
||||
{
|
||||
lastUpdateTime = time;
|
||||
printf("\r%6.2f%%", lmProgress(ctx) * 100.0f);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
lmEnd(ctx);
|
||||
// window_swap();
|
||||
}
|
||||
printf("\rFinished baking %d triangles.\n", scene->indexCount / 3);
|
||||
}
|
||||
|
||||
lmDestroy(ctx);
|
||||
|
||||
// postprocess texture
|
||||
float *temp = CALLOC(w * h * 4, sizeof(float));
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
lmImageDilate(data, temp, w, h, 4);
|
||||
lmImageDilate(temp, data, w, h, 4);
|
||||
}
|
||||
lmImageSmooth(data, temp, w, h, 4);
|
||||
lmImageDilate(temp, data, w, h, 4);
|
||||
lmImagePower(data, w, h, 4, 1.0f / 2.2f, 0x7); // gamma correct color channels
|
||||
FREE(temp);
|
||||
|
||||
// save result to a file
|
||||
if (lmImageSaveTGAf("result.tga", data, w, h, 4, 1.0f))
|
||||
printf("Saved result.tga\n");
|
||||
|
||||
// upload result
|
||||
glBindTexture(GL_TEXTURE_2D, scene->lightmap);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_FLOAT, data);
|
||||
FREE(data);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void fpsCameraViewMatrix(float *view);
|
||||
|
||||
static void mainLoop(scene_t *scene)
|
||||
{
|
||||
glViewport(0, 0, window_width(), window_height());
|
||||
|
||||
// camera for glfw window
|
||||
float view[16], projection[16];
|
||||
fpsCameraViewMatrix(view);
|
||||
perspective44(projection, 45.0f, window_aspect(), 0.01f, 100.0f);
|
||||
|
||||
// draw to screen with a blueish sky
|
||||
glClearColor(0.6f, 0.8f, 1.0f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
drawScene(scene, view, projection);
|
||||
void bakedrawmodel(lightmap_t *lm, model_t *m, float *view, float *proj, void *userdata) {
|
||||
shader_bind(lm->shader);
|
||||
model_render(*m, proj, view, m->pivot, lm->shader);
|
||||
shader_float("u_litboost", 4.0);
|
||||
model_render(litm, proj, view, litm.pivot, lm->shader);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
window_create(0.5, WINDOW_VSYNC_DISABLED);
|
||||
|
||||
scene_t scene = {0};
|
||||
if (!initScene(&scene))
|
||||
camera_t cam = camera();
|
||||
sky = skybox(0, 0); skybox_mie_calc_sh(&sky, 2.0f);
|
||||
model_t mdl = model("gazebo.obj", 0);
|
||||
litm = model("cube.obj", MODEL_MATCAPS);
|
||||
{
|
||||
fprintf(stderr, "Could not initialize scene.\n");
|
||||
return EXIT_FAILURE;
|
||||
mat44 lp; scaling44(lp, 0.3, 0.3, 0.3); translate44(lp, 8,4,0);
|
||||
copy44(litm.pivot, lp);
|
||||
}
|
||||
rotate44(mdl.pivot, -90, 1, 0, 0);
|
||||
scale44(mdl.pivot, 4,4,4);
|
||||
shader_bind(mdl.program);
|
||||
shader_vec3v("u_coefficients_sh", 9, sky.cubemap.sh);
|
||||
// shader_bool("u_texmod", 0);
|
||||
|
||||
unsigned char emissive[] = { 255, 180, 0, 255 };
|
||||
texture_t emission = texture_create(1,1,4,emissive,TEXTURE_LINEAR);
|
||||
model_set_texture(litm, emission);
|
||||
|
||||
lightmap_t baker = lightmap(64, 0.001, 1000, vec3(0,0,0), 2, 0.01, 0.0);
|
||||
lightmap_setup(&baker, 640, 640);
|
||||
array_push(baker.models, &mdl);
|
||||
|
||||
window_title("AO Baking demo");
|
||||
|
||||
while (window_swap())
|
||||
{
|
||||
mainLoop(&scene);
|
||||
while (window_swap() && !input(KEY_ESC)) {
|
||||
bool active = ui_active() || ui_hover() || gizmo_active() ? false : input(MOUSE_L) || input(MOUSE_M) || input(MOUSE_R);
|
||||
if( active ) cam.speed = clampf(cam.speed + input_diff(MOUSE_W) / 10, 0.05f, 5.0f);
|
||||
vec2 mouse = scale2(vec2(input_diff(MOUSE_X), -input_diff(MOUSE_Y)), 0.2f * active);
|
||||
vec3 wasdecq = scale3(vec3(input(KEY_D)-input(KEY_A),input(KEY_E)-(input(KEY_C)||input(KEY_Q)),input(KEY_W)-input(KEY_S)), cam.speed);
|
||||
camera_moveby(&cam, wasdecq);
|
||||
camera_fps(&cam, mouse.x,mouse.y);
|
||||
window_cursor( !active );
|
||||
|
||||
skybox_render(&sky, cam.proj, cam.view);
|
||||
model_render(mdl, cam.proj, cam.view, mdl.pivot, 0);
|
||||
model_render(litm, cam.proj, cam.view, litm.pivot, 0);
|
||||
|
||||
if( ui_panel("Lightmapper", PANEL_OPEN) ) {
|
||||
ui_label2("Freecam", "Mouse + W/A/S/D/E/Q keys");
|
||||
ui_label("Warning " ICON_MD_WARNING "@This will take a few seconds and bake a lightmap illuminated by: The mesh itself (initially black) + A white sky (1.0f, 1.0f, 1.0f)");
|
||||
if( ui_button("Bake 1 light bounce") ) {
|
||||
bake(&scene);
|
||||
int b=2;
|
||||
if( ui_button(va("Bake %d light bounce", b)) ) {
|
||||
lightmap_bake(&baker, b, bakedrawmodel, 0);
|
||||
}
|
||||
ui_panel_end();
|
||||
}
|
||||
}
|
||||
|
||||
destroyScene(&scene);
|
||||
}
|
||||
|
||||
// helpers ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
static int loadSimpleObjFile(const char *filename, vertex_t **vertices, unsigned int *vertexCount, unsigned short **indices, unsigned int *indexCount);
|
||||
|
||||
static int initScene(scene_t *scene)
|
||||
{
|
||||
// load mesh
|
||||
if (!loadSimpleObjFile("demos/art/meshes/gazebo.obj", &scene->vertices, &scene->vertexCount, &scene->indices, &scene->indexCount))
|
||||
{
|
||||
fprintf(stderr, "Error loading obj file\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
glGenVertexArrays(1, &scene->vao);
|
||||
glBindVertexArray(scene->vao);
|
||||
|
||||
glGenBuffers(1, &scene->vbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, scene->vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, scene->vertexCount * sizeof(vertex_t), scene->vertices, GL_STATIC_DRAW);
|
||||
|
||||
glGenBuffers(1, &scene->ibo);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, scene->ibo);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, scene->indexCount * sizeof(unsigned short), scene->indices, GL_STATIC_DRAW);
|
||||
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (void*)offsetof(vertex_t, p));
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (void*)offsetof(vertex_t, t));
|
||||
|
||||
// create lightmap texture
|
||||
scene->w = 654;
|
||||
scene->h = 654;
|
||||
glGenTextures(1, &scene->lightmap);
|
||||
glBindTexture(GL_TEXTURE_2D, scene->lightmap);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
unsigned char emissive[] = { 0, 0, 0, 255 };
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, emissive);
|
||||
|
||||
// load shader
|
||||
const char *vp =
|
||||
"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 =
|
||||
"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";
|
||||
|
||||
scene->program = shader(vp, fp, "a_position,a_texcoord", "o_color", NULL);
|
||||
if (!scene->program)
|
||||
{
|
||||
fprintf(stderr, "Error loading shader\n");
|
||||
return 0;
|
||||
}
|
||||
scene->u_view = glGetUniformLocation(scene->program, "u_view");
|
||||
scene->u_projection = glGetUniformLocation(scene->program, "u_projection");
|
||||
scene->u_lightmap = glGetUniformLocation(scene->program, "u_lightmap");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void drawScene(scene_t *scene, float *view, float *projection)
|
||||
{
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
glUseProgram(scene->program);
|
||||
glUniform1i(scene->u_lightmap, 0);
|
||||
glUniformMatrix4fv(scene->u_projection, 1, GL_FALSE, projection);
|
||||
glUniformMatrix4fv(scene->u_view, 1, GL_FALSE, view);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, scene->lightmap);
|
||||
|
||||
glBindVertexArray(scene->vao);
|
||||
glDrawElements(GL_TRIANGLES, scene->indexCount, GL_UNSIGNED_SHORT, 0);
|
||||
}
|
||||
|
||||
static void destroyScene(scene_t *scene)
|
||||
{
|
||||
FREE(scene->vertices);
|
||||
FREE(scene->indices);
|
||||
glDeleteVertexArrays(1, &scene->vao);
|
||||
glDeleteBuffers(1, &scene->vbo);
|
||||
glDeleteBuffers(1, &scene->ibo);
|
||||
glDeleteTextures(1, &scene->lightmap);
|
||||
glDeleteProgram(scene->program);
|
||||
}
|
||||
|
||||
static int loadSimpleObjFile(const char *filename, vertex_t **vertices, unsigned int *vertexCount, unsigned short **indices, unsigned int *indexCount)
|
||||
{
|
||||
FILE *file = fopen(filename, "rt");
|
||||
if (!file)
|
||||
return 0;
|
||||
char line[1024];
|
||||
|
||||
// first pass
|
||||
unsigned int np = 0, nn = 0, nt = 0, nf = 0;
|
||||
while (!feof(file))
|
||||
{
|
||||
fgets(line, 1024, file);
|
||||
if (line[0] == '#') continue;
|
||||
if (line[0] == 'v')
|
||||
{
|
||||
if (line[1] == ' ') { np++; continue; }
|
||||
if (line[1] == 'n') { nn++; continue; }
|
||||
if (line[1] == 't') { nt++; continue; }
|
||||
assert(!"unknown vertex attribute");
|
||||
}
|
||||
if (line[0] == 'f') { nf++; continue; }
|
||||
assert(!"unknown identifier");
|
||||
}
|
||||
assert(np && np == nn && np == nt && nf); // only supports obj files without separately indexed vertex attributes
|
||||
|
||||
// allocate memory
|
||||
*vertexCount = np;
|
||||
*vertices = CALLOC(np, sizeof(vertex_t));
|
||||
*indexCount = nf * 3;
|
||||
*indices = CALLOC(nf * 3, sizeof(unsigned short));
|
||||
|
||||
// second pass
|
||||
fseek(file, 0, SEEK_SET);
|
||||
unsigned int cp = 0, cn = 0, ct = 0, cf = 0;
|
||||
while (!feof(file))
|
||||
{
|
||||
fgets(line, 1024, file);
|
||||
if (line[0] == '#') continue;
|
||||
if (line[0] == 'v')
|
||||
{
|
||||
if (line[1] == ' ') { float *p = (*vertices)[cp++].p; char *e1, *e2; p[0] = (float)strtod(line + 2, &e1); p[1] = (float)strtod(e1, &e2); p[2] = (float)strtod(e2, 0); continue; }
|
||||
if (line[1] == 'n') { /*float *n = (*vertices)[cn++].n; char *e1, *e2; n[0] = (float)strtod(line + 3, &e1); n[1] = (float)strtod(e1, &e2); n[2] = (float)strtod(e2, 0);*/ continue; } // no normals needed
|
||||
if (line[1] == 't') { float *t = (*vertices)[ct++].t; char *e1; t[0] = (float)strtod(line + 3, &e1); t[1] = (float)strtod(e1, 0); continue; }
|
||||
assert(!"unknown vertex attribute");
|
||||
}
|
||||
if (line[0] == 'f')
|
||||
{
|
||||
unsigned short *tri = (*indices) + cf;
|
||||
cf += 3;
|
||||
char *e1, *e2, *e3 = line + 1;
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
unsigned long pi = strtoul(e3 + 1, &e1, 10);
|
||||
assert(e1[0] == '/');
|
||||
unsigned long ti = strtoul(e1 + 1, &e2, 10);
|
||||
assert(e2[0] == '/');
|
||||
unsigned long ni = strtoul(e2 + 1, &e3, 10);
|
||||
assert(pi == ti && pi == ni);
|
||||
tri[i] = (unsigned short)(pi - 1);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
assert(!"unknown identifier");
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void fpsCameraViewMatrix(float *view)
|
||||
{
|
||||
// initial camera config
|
||||
static float position[] = { 0.0f, 0.3f, 1.5f };
|
||||
static float rotation[] = { 0.0f, 0.0f };
|
||||
|
||||
// mouse look
|
||||
static double lastMouse[] = { 0.0, 0.0 };
|
||||
double mouse_coord[2];
|
||||
mouse_coord[0] = input(MOUSE_X);
|
||||
mouse_coord[1] = input(MOUSE_Y);
|
||||
if (input(MOUSE_L))
|
||||
{
|
||||
rotation[0] += (float)(mouse_coord[1] - lastMouse[1]) * -0.2f;
|
||||
rotation[1] += (float)(mouse_coord[0] - lastMouse[0]) * -0.2f;
|
||||
}
|
||||
lastMouse[0] = mouse_coord[0];
|
||||
lastMouse[1] = mouse_coord[1];
|
||||
|
||||
float rotationY[16], rotationX[16], rotationYX[16];
|
||||
rotation44(rotationX, rotation[0], 1.0f, 0.0f, 0.0f);
|
||||
rotation44(rotationY, rotation[1], 0.0f, 1.0f, 0.0f);
|
||||
multiply44x2(rotationYX, rotationY, rotationX);
|
||||
|
||||
// keyboard movement (WSADEQ)
|
||||
float speed = input(KEY_SHIFT) ? 0.1f : 0.01f;
|
||||
vec3 movement = {0};
|
||||
if (input(KEY_W)) movement.z -= speed;
|
||||
if (input(KEY_S)) movement.z += speed;
|
||||
if (input(KEY_A)) movement.x -= speed;
|
||||
if (input(KEY_D)) movement.x += speed;
|
||||
if (input(KEY_E)) movement.y -= speed;
|
||||
if (input(KEY_Q)) movement.y += speed;
|
||||
|
||||
vec3 worldMovement = transform344(rotationYX, movement);
|
||||
position[0] += worldMovement.x;
|
||||
position[1] += worldMovement.y;
|
||||
position[2] += worldMovement.z;
|
||||
|
||||
// construct view matrix
|
||||
float inverseRotation[16], inverseTranslation[16];
|
||||
transpose44(inverseRotation, rotationYX);
|
||||
translation44(inverseTranslation, -position[0], -position[1], -position[2]);
|
||||
multiply44x2(view, inverseRotation, inverseTranslation); // = inverse(translation(position) * rotationYX);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
#######################################################################
|
||||
76702 17.93% rendered hemicubes integrated to lightmap texels.
|
||||
179388 41.94% interpolated lightmap texels.
|
||||
171626 40.13% wasted lightmap texels.
|
||||
|
||||
29.95% of used texels were rendered.
|
||||
#######################################################################
|
||||
Finished baking 731 triangles.
|
||||
Saved result.tga
|
||||
|
||||
vs
|
||||
|
||||
#######################################################################
|
||||
124 0.05% rendered hemicubes integrated to lightmap texels.
|
||||
201 0.08% interpolated lightmap texels.
|
||||
261947 99.88% wasted lightmap texels.
|
||||
|
||||
38.15% of used texels were rendered.
|
||||
#######################################################################
|
||||
Finished baking 731 triangles.
|
||||
Saved result.tga
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -6,6 +6,12 @@ uniform bool u_lit = false;
|
|||
uniform bool u_matcaps = false;
|
||||
uniform vec4 u_diffuse = vec4(1.0,1.0,1.0,1.0);
|
||||
|
||||
// lightmapping
|
||||
uniform sampler2D u_lightmap;
|
||||
uniform bool u_texlit;
|
||||
uniform bool u_texmod = true;
|
||||
uniform float u_litboost = 1.0;
|
||||
|
||||
in vec3 v_position;
|
||||
in vec3 v_position_ws;
|
||||
#ifdef RIM
|
||||
|
@ -16,7 +22,7 @@ uniform vec3 u_rimpivot = vec3(0,0,0);
|
|||
uniform bool u_rimambient = true;
|
||||
#endif
|
||||
in vec3 v_normal, v_normal_ws;
|
||||
in vec2 v_texcoord;
|
||||
in vec2 v_texcoord, v_texcoord2;
|
||||
in vec4 v_color;
|
||||
out vec4 fragcolor;
|
||||
|
||||
|
@ -110,12 +116,7 @@ vec3 lighting() {
|
|||
return lit;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec3 n = normalize(v_normal_ws);
|
||||
|
||||
vec4 lit = vec4(1.0, 1.0, 1.0, 1.0);
|
||||
// SH lighting
|
||||
{
|
||||
vec3 sh_lighting(vec3 n) {
|
||||
vec3 SHLightResult[9];
|
||||
SHLightResult[0] = 0.282095f * u_coefficients_sh[0];
|
||||
SHLightResult[1] = -0.488603f * u_coefficients_sh[1] * n.y;
|
||||
|
@ -129,6 +130,35 @@ void main() {
|
|||
vec3 result = vec3(0.0);
|
||||
for (int i = 0; i < 9; ++i)
|
||||
result += SHLightResult[i];
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef LIGHTMAP_BAKING
|
||||
void main() {
|
||||
vec3 n = normalize(v_normal_ws);
|
||||
vec4 diffuse;
|
||||
|
||||
if(u_textured) {
|
||||
diffuse = texture(u_texture2d, v_texcoord);
|
||||
} else {
|
||||
diffuse = u_diffuse; // * v_color;
|
||||
}
|
||||
|
||||
if (u_texlit) {
|
||||
vec4 litsample = texture(u_lightmap, v_texcoord);
|
||||
diffuse *= litsample;
|
||||
}
|
||||
|
||||
fragcolor = vec4(diffuse.rgb*u_litboost, 1.0);
|
||||
}
|
||||
#else
|
||||
void main() {
|
||||
vec3 n = normalize(v_normal_ws);
|
||||
|
||||
vec4 lit = vec4(1.0, 1.0, 1.0, 1.0);
|
||||
// SH lighting
|
||||
if (!u_texlit) {
|
||||
vec3 result = sh_lighting(n);
|
||||
if( (result.x*result.x+result.y*result.y+result.z*result.z) > 0.0 ) lit = vec4(result, 1.0);
|
||||
}
|
||||
|
||||
|
@ -147,6 +177,18 @@ void main() {
|
|||
diffuse = u_diffuse; // * v_color;
|
||||
}
|
||||
|
||||
if (u_texlit) {
|
||||
vec4 litsample = texture(u_lightmap, v_texcoord);
|
||||
|
||||
if (u_texmod) {
|
||||
diffuse *= litsample;
|
||||
} else {
|
||||
diffuse += litsample;
|
||||
}
|
||||
|
||||
diffuse.rgb += sh_lighting(n);
|
||||
}
|
||||
|
||||
// lighting mix
|
||||
fragcolor = diffuse * lit * shadowing();
|
||||
|
||||
|
@ -164,3 +206,4 @@ void main() {
|
|||
fragcolor += vec4(col, 1.0);}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -49,7 +49,6 @@ uniform sampler2DArray blend_shapes; // @todo: implement me
|
|||
|
||||
in vec3 att_position; // @todo: reorder ass2iqe to emit p3 n3 u2 t3 b3 c4B i4 w4 instead
|
||||
in vec2 att_texcoord;
|
||||
in vec2 att_texcoord2;
|
||||
in vec3 att_normal;
|
||||
in vec4 att_tangent; // vec3 + bi sign
|
||||
in mat4 att_instanced_matrix; // for instanced rendering
|
||||
|
@ -58,10 +57,11 @@ in vec4 att_weights; // @todo: downgrade from float to byte
|
|||
in float att_vertexindex; // for blendshapes
|
||||
in vec4 att_color;
|
||||
in vec3 att_bitangent; // @todo: remove? also, ass2iqe might output this
|
||||
in vec2 att_texcoord2;
|
||||
out vec4 v_color;
|
||||
out vec3 v_position, v_position_ws;
|
||||
out vec3 v_normal, v_normal_ws;
|
||||
out vec2 v_texcoord;
|
||||
out vec2 v_texcoord, v_texcoord2;
|
||||
|
||||
|
||||
|
||||
|
@ -118,6 +118,7 @@ void main() {
|
|||
v_normal = normalize(v_normal);
|
||||
v_position = att_position;
|
||||
v_texcoord = att_texcoord;
|
||||
v_texcoord2 = att_texcoord2;
|
||||
v_color = att_color;
|
||||
mat4 modelView = view * att_instanced_matrix;
|
||||
mat4 l_model = att_instanced_matrix;
|
|
@ -17511,7 +17511,9 @@ typedef struct model_t {
|
|||
handle *textures;
|
||||
char **texture_names;
|
||||
array(material_t) materials;
|
||||
texture_t *lightmap;
|
||||
|
||||
texture_t lightmap;
|
||||
float *lmdata;
|
||||
|
||||
unsigned num_meshes;
|
||||
unsigned num_triangles;
|
||||
|
@ -17525,6 +17527,8 @@ typedef struct model_t {
|
|||
int stride; // usually 68 bytes for a p3 u2 u2 n3 t4 i4B w4B c4B vertex stream
|
||||
void *verts;
|
||||
int num_verts;
|
||||
void *tris;
|
||||
int num_tris;
|
||||
handle vao, ibo, vbo, vao_instanced;
|
||||
|
||||
unsigned flags;
|
||||
|
@ -17576,15 +17580,16 @@ API anims_t animations(const char *pathfile, int flags);
|
|||
typedef struct lightmap_t {
|
||||
struct lm_context *ctx; // private
|
||||
bool ready;
|
||||
texture_t lightmap; //@fixme: do we need it per-model?
|
||||
int w, h;
|
||||
int atlas_w, atlas_h; //@fixme: implement
|
||||
texture_t atlas; //@fixme: implement this
|
||||
array(model_t*) models;
|
||||
unsigned shader;
|
||||
} lightmap_t;
|
||||
|
||||
API lightmap_t lightmap(int hmsize /*64*/, float near, float far, vec3 color /*1,1,1 for AO*/, int passes /*2*/, float threshold /*0.01f*/, float distmod /*0.0f*/);
|
||||
API void lightmap_setup(lightmap_t *lm, int w, int h);
|
||||
API void lightmap_addmodel(lightmap_t *lm, model_t *m);
|
||||
API void lightmap_bake(lightmap_t *lm, int bounces, void (*drawscene)(lightmap_t *lm, float *view, float *proj, void *userdata), void *userdata);
|
||||
API void lightmap_clear(lightmap_t *lm);
|
||||
API void lightmap_bake(lightmap_t *lm, int bounces, void (*drawscene)(lightmap_t *lm, model_t *m, float *view, float *proj, void *userdata), void *userdata);
|
||||
API void lightmap_destroy(lightmap_t *lm);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -369322,13 +369327,13 @@ struct iqmbounds {
|
|||
typedef struct iqm_vertex {
|
||||
GLfloat position[3];
|
||||
GLfloat texcoord[2];
|
||||
GLfloat texcoord2[2];
|
||||
GLfloat normal[3];
|
||||
GLfloat tangent[4];
|
||||
GLubyte blendindexes[4];
|
||||
GLubyte blendweights[4];
|
||||
GLfloat blendvertexindex;
|
||||
GLubyte color[4];
|
||||
GLfloat texcoord2[2];
|
||||
} iqm_vertex;
|
||||
|
||||
typedef struct iqm_t {
|
||||
|
@ -369438,6 +369443,13 @@ void model_set_uniforms(model_t m, int shader, mat44 mv, mat44 proj, mat44 view,
|
|||
if( (loc = glGetUniformLocation(shader, "u_billboard")) >= 0 ) {
|
||||
glUniform1i( loc, m.billboard );
|
||||
}
|
||||
if( (loc = glGetUniformLocation(shader, "texlit")) >= 0 ) {
|
||||
glUniform1i( loc, (m.lightmap.w != 0) );
|
||||
}
|
||||
else
|
||||
if( (loc = glGetUniformLocation(shader, "u_texlit")) >= 0 ) {
|
||||
glUniform1i( loc, (m.lightmap.w != 0) );
|
||||
}
|
||||
#if 0
|
||||
// @todo: mat44 projview (useful?)
|
||||
#endif
|
||||
|
@ -369482,28 +369494,26 @@ void model_set_state(model_t m) {
|
|||
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, position) );
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, texcoord) );
|
||||
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, texcoord2) );
|
||||
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, normal) );
|
||||
glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, tangent) );
|
||||
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, normal) );
|
||||
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, tangent) );
|
||||
|
||||
glEnableVertexAttribArray(0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glEnableVertexAttribArray(2);
|
||||
glEnableVertexAttribArray(3);
|
||||
glEnableVertexAttribArray(4);
|
||||
|
||||
// vertex color
|
||||
glVertexAttribPointer(12, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex,color) );
|
||||
glEnableVertexAttribArray(12);
|
||||
glVertexAttribPointer(11, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex,color) );
|
||||
glEnableVertexAttribArray(11);
|
||||
|
||||
// animation
|
||||
if(numframes > 0) {
|
||||
glVertexAttribPointer( 9, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex,blendindexes) );
|
||||
glVertexAttribPointer( 10, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex,blendweights) );
|
||||
glVertexAttribPointer(11, 1, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, blendvertexindex) );
|
||||
glVertexAttribPointer( 8, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex,blendindexes) );
|
||||
glVertexAttribPointer( 9, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex,blendweights) );
|
||||
glVertexAttribPointer(10, 1, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, blendvertexindex) );
|
||||
glEnableVertexAttribArray(8);
|
||||
glEnableVertexAttribArray(9);
|
||||
glEnableVertexAttribArray(10);
|
||||
glEnableVertexAttribArray(11);
|
||||
}
|
||||
|
||||
// mat4 attribute; for instanced rendering
|
||||
|
@ -369515,22 +369525,26 @@ void model_set_state(model_t m) {
|
|||
glBindBuffer(GL_ARRAY_BUFFER, m.vao_instanced);
|
||||
glBufferData(GL_ARRAY_BUFFER, m.num_instances * mat4_size, m.instanced_matrices, GL_STATIC_DRAW);
|
||||
|
||||
glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, 4 * vec4_size, (GLvoid*)(((char*)NULL)+(0 * vec4_size)));
|
||||
glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, 4 * vec4_size, (GLvoid*)(((char*)NULL)+(1 * vec4_size)));
|
||||
glVertexAttribPointer(7, 4, GL_FLOAT, GL_FALSE, 4 * vec4_size, (GLvoid*)(((char*)NULL)+(2 * vec4_size)));
|
||||
glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, 4 * vec4_size, (GLvoid*)(((char*)NULL)+(3 * vec4_size)));
|
||||
glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, 4 * vec4_size, (GLvoid*)(((char*)NULL)+(0 * vec4_size)));
|
||||
glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, 4 * vec4_size, (GLvoid*)(((char*)NULL)+(1 * vec4_size)));
|
||||
glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, 4 * vec4_size, (GLvoid*)(((char*)NULL)+(2 * vec4_size)));
|
||||
glVertexAttribPointer(7, 4, GL_FLOAT, GL_FALSE, 4 * vec4_size, (GLvoid*)(((char*)NULL)+(3 * vec4_size)));
|
||||
|
||||
glEnableVertexAttribArray(4);
|
||||
glEnableVertexAttribArray(5);
|
||||
glEnableVertexAttribArray(6);
|
||||
glEnableVertexAttribArray(7);
|
||||
glEnableVertexAttribArray(8);
|
||||
|
||||
glVertexAttribDivisor(4, 1);
|
||||
glVertexAttribDivisor(5, 1);
|
||||
glVertexAttribDivisor(6, 1);
|
||||
glVertexAttribDivisor(7, 1);
|
||||
glVertexAttribDivisor(8, 1);
|
||||
}
|
||||
|
||||
// lmap data
|
||||
glVertexAttribPointer(12, 2, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, texcoord2) );
|
||||
glEnableVertexAttribArray(12);
|
||||
|
||||
// 7 bitangent? into texcoord.z?
|
||||
|
||||
glBindVertexArray( 0 );
|
||||
|
@ -369595,6 +369609,8 @@ bool model_load_meshes(iqm_t *q, const struct iqmheader *hdr, model_t *m) {
|
|||
}
|
||||
|
||||
struct iqmtriangle *tris = (struct iqmtriangle *)&buf[hdr->ofs_triangles];
|
||||
m->num_tris = hdr->num_triangles;
|
||||
m->tris = (void*)tris;
|
||||
|
||||
glGenVertexArrays(1, &vao);
|
||||
glBindVertexArray(vao);
|
||||
|
@ -369650,8 +369666,8 @@ if(inblendweightf) m->stride += sizeof(verts[0].blendweights);
|
|||
if(invertexcolor8) m->stride += sizeof(verts[0].color);
|
||||
#endif
|
||||
//for( int i = 0; i < 16; ++i ) printf("%.9g%s", ((float*)verts)[i], (i % 3) == 2 ? "\n" : ",");
|
||||
//m->verts = verts; //FREE(verts);
|
||||
m->verts = 0; FREE(verts);
|
||||
m->verts = verts;
|
||||
/*m->verts = 0; FREE(verts);*/
|
||||
|
||||
textures = CALLOC(hdr->num_meshes * 8, sizeof(GLuint));
|
||||
colormaps = CALLOC(hdr->num_meshes * 8, sizeof(vec4));
|
||||
|
@ -369883,8 +369899,8 @@ model_t model_from_mem(const void *mem, int len, int flags) {
|
|||
// static int shaderprog = -1;
|
||||
// if( shaderprog < 0 ) {
|
||||
const char *symbols[] = { "{{include-shadowmap}}", vfs_read("shaders/fs_0_0_shadowmap_lit.glsl") }; // #define RIM
|
||||
int shaderprog = shader(strlerp(1,symbols,vfs_read("shaders/vs_3223444143_16_332_model.glsl")), strlerp(1,symbols,vfs_read("shaders/fs_32_4_model.glsl")), //fs,
|
||||
"att_position,att_texcoord,att_texcoord2,att_normal,att_tangent,att_instanced_matrix,,,,att_indexes,att_weights,att_vertexindex,att_color,att_bitangent","fragColor",
|
||||
int shaderprog = shader(strlerp(1,symbols,vfs_read("shaders/vs_323444143_16_3322_model.glsl")), strlerp(1,symbols,vfs_read("shaders/fs_32_4_model.glsl")), //fs,
|
||||
"att_position,att_texcoord,att_normal,att_tangent,att_instanced_matrix,,,,att_indexes,att_weights,att_vertexindex,att_color,att_bitangent,att_texcoord2","fragColor",
|
||||
va("SHADING_PHONG,%s", (flags&MODEL_RIMLIGHT)?"RIM":""));
|
||||
// }
|
||||
// ASSERT(shaderprog > 0);
|
||||
|
@ -370126,7 +370142,7 @@ float model_animate(model_t m, float curframe) {
|
|||
}
|
||||
|
||||
static
|
||||
void model_draw_call(model_t m) {
|
||||
void model_draw_call(model_t m, int shader) {
|
||||
if(!m.iqm) return;
|
||||
iqm_t *q = m.iqm;
|
||||
|
||||
|
@ -370138,17 +370154,21 @@ void model_draw_call(model_t m) {
|
|||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, textures[i] );
|
||||
glUniform1i(glGetUniformLocation(m.program, "fsDiffTex"), 0 /*<-- unit!*/ );
|
||||
glUniform1i(glGetUniformLocation(shader, "u_texture2d"), 0 );
|
||||
|
||||
int loc;
|
||||
if ((loc = glGetUniformLocation(m.program, "u_textured")) >= 0) {
|
||||
if ((loc = glGetUniformLocation(shader, "u_textured")) >= 0) {
|
||||
bool textured = !!textures[i] && textures[i] != texture_checker().id; // m.materials[i].layer[0].texture != texture_checker().id;
|
||||
glUniform1i(loc, textured ? GL_TRUE : GL_FALSE);
|
||||
if ((loc = glGetUniformLocation(m.program, "u_diffuse")) >= 0) {
|
||||
if ((loc = glGetUniformLocation(shader, "u_diffuse")) >= 0) {
|
||||
glUniform4f(loc, m.materials[i].layer[0].color.r, m.materials[i].layer[0].color.g, m.materials[i].layer[0].color.b, m.materials[i].layer[0].color.a);
|
||||
}
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, m.lightmap.id);
|
||||
glUniform1i(glGetUniformLocation(shader, "u_lightmap"), 1 );
|
||||
|
||||
glDrawElementsInstanced(GL_TRIANGLES, 3*im->num_triangles, GL_UNSIGNED_INT, &tris[im->first_triangle], m.num_instances);
|
||||
profile_incstat("Render.num_drawcalls", +1);
|
||||
profile_incstat("Render.num_triangles", +im->num_triangles);
|
||||
|
@ -370170,7 +370190,7 @@ void model_render_instanced(model_t m, mat44 proj, mat44 view, mat44* models, in
|
|||
}
|
||||
|
||||
model_set_uniforms(m, shader > 0 ? shader : m.program, mv, proj, view, models[0]);
|
||||
model_draw_call(m);
|
||||
model_draw_call(m, shader > 0 ? shader : m.program);
|
||||
}
|
||||
|
||||
void model_render(model_t m, mat44 proj, mat44 view, mat44 model, int shader) {
|
||||
|
@ -370287,116 +370307,101 @@ lightmap_t lightmap(int hmsize, float cnear, float cfar, vec3 color, int passes,
|
|||
return lm;
|
||||
}
|
||||
|
||||
return lm;
|
||||
}
|
||||
const char *symbols[] = { "{{include-shadowmap}}", vfs_read("shaders/fs_0_0_shadowmap_lit.glsl") }; // #define RIM
|
||||
lm.shader = shader(strlerp(1,symbols,vfs_read("shaders/vs_323444143_16_3322_model.glsl")), strlerp(1,symbols,vfs_read("shaders/fs_32_4_model.glsl")), //fs,
|
||||
"att_position,att_texcoord,att_normal,att_tangent,att_instanced_matrix,,,,att_indexes,att_weights,att_vertexindex,att_color,att_bitangent,att_texcoord2","fragColor",
|
||||
va("%s", "LIGHTMAP_BAKING"));
|
||||
|
||||
static
|
||||
void lightmap_destroytexture(lightmap_t *lm) {
|
||||
texture_destroy(&lm->lightmap);
|
||||
for (int i = 0; i < array_count(lm->models); i++) {
|
||||
lm->models[i]->lightmap = NULL;
|
||||
}
|
||||
return lm;
|
||||
}
|
||||
|
||||
void lightmap_destroy(lightmap_t *lm) {
|
||||
lmDestroy(lm->ctx);
|
||||
lightmap_destroytexture(lm);
|
||||
shader_destroy(lm->shader);
|
||||
//
|
||||
}
|
||||
|
||||
void lightmap_setup(lightmap_t *lm, int w, int h) {
|
||||
if (lm->ready) {
|
||||
lightmap_destroytexture(lm);
|
||||
}
|
||||
lm->ready=1;
|
||||
|
||||
lm->lightmap = texture_create(w, h, 4, 0, TEXTURE_LINEAR);
|
||||
glBindTexture(GL_TEXTURE_2D, lm->lightmap.id);
|
||||
unsigned char emissive[] = { 0, 0, 0, 255 };
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, emissive);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
//@fixme: prep atlas for lightmaps
|
||||
lm->w = w;
|
||||
lm->h = h;
|
||||
}
|
||||
|
||||
void lightmap_addmodel(lightmap_t *lm, model_t *m) {
|
||||
array_push(lm->models, m);
|
||||
}
|
||||
|
||||
void lightmap_bake(lightmap_t *lm, int bounces, void (*drawscene)(lightmap_t *lm, float *view, float *proj, void *userdata), void *userdata) {
|
||||
void lightmap_bake(lightmap_t *lm, int bounces, void (*drawscene)(lightmap_t *lm, model_t *m, float *view, float *proj, void *userdata), void *userdata) {
|
||||
ASSERT(lm->ready);
|
||||
// @fixme: use xatlas to UV pack all models, update their UV1 and upload them to GPU.
|
||||
// @fixme: combine all verts data together and push to lmSetGeometry
|
||||
|
||||
// int w = lm->lightmap->w, h = lm->lightmap->h;
|
||||
// float *data = CALLOC(w * h * 4, sizeof(float));
|
||||
// memset(data, 0, w*h*4);
|
||||
// for (int b = 0; b < bounces; b++) {
|
||||
// lmSetTargetLightmap(lm->ctx, data, w, h, 4);
|
||||
GLint cullface=0;
|
||||
glGetIntegerv(GL_CULL_FACE, &cullface);
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
// lmSetGeometry(lm->ctx, NULL,
|
||||
// LM_FLOAT, (unsigned char*)scene->vertices + offsetof(vertex_t, p), sizeof(vertex_t),
|
||||
// LM_NONE , NULL , 0 , // no interpolated normals in this example
|
||||
// LM_FLOAT, (unsigned char*)scene->vertices + offsetof(vertex_t, t), sizeof(vertex_t),
|
||||
// scene->indexCount, LM_UNSIGNED_SHORT, scene->indices);
|
||||
|
||||
|
||||
// glDisable(GL_BLEND);
|
||||
|
||||
// int vp[4];
|
||||
// float view[16], projection[16];
|
||||
// double lastUpdateTime = 0.0;
|
||||
// while (lmBegin(ctx, vp, view, projection))
|
||||
// {
|
||||
// // render to lightmapper framebuffer
|
||||
// glViewport(vp[0], vp[1], vp[2], vp[3]);
|
||||
// drawScene(scene, view, projection);
|
||||
|
||||
// // display progress every second (printf is expensive)
|
||||
// double time = time_ms() / 1000.0;
|
||||
// if (time - lastUpdateTime > 1.0)
|
||||
// {
|
||||
// lastUpdateTime = time;
|
||||
// printf("\r%6.2f%%", lmProgress(ctx) * 100.0f);
|
||||
// fflush(stdout);
|
||||
// }
|
||||
|
||||
// lmEnd(ctx);
|
||||
// // window_swap();
|
||||
// }
|
||||
// printf("\rFinished baking %d triangles.\n", scene->indexCount / 3);
|
||||
// }
|
||||
|
||||
// lmDestroy(ctx);
|
||||
|
||||
// // postprocess texture
|
||||
// float *temp = CALLOC(w * h * 4, sizeof(float));
|
||||
// for (int i = 0; i < 16; i++)
|
||||
// {
|
||||
// lmImageDilate(data, temp, w, h, 4);
|
||||
// lmImageDilate(temp, data, w, h, 4);
|
||||
// }
|
||||
// lmImageSmooth(data, temp, w, h, 4);
|
||||
// lmImageDilate(temp, data, w, h, 4);
|
||||
// lmImagePower(data, w, h, 4, 1.0f / 2.2f, 0x7); // gamma correct color channels
|
||||
// FREE(temp);
|
||||
|
||||
// // save result to a file
|
||||
// if (lmImageSaveTGAf("result.tga", data, w, h, 4, 1.0f))
|
||||
// printf("Saved result.tga\n");
|
||||
|
||||
// // upload result
|
||||
// glBindTexture(GL_TEXTURE_2D, scene->lightmap);
|
||||
// glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_FLOAT, data);
|
||||
// FREE(data);
|
||||
int w = lm->w, h = lm->h;
|
||||
for (int i = 0; i < array_count(lm->models); i++) {
|
||||
model_t *m = lm->models[i];
|
||||
if (m->lightmap.w != 0) {
|
||||
texture_destroy(&m->lightmap);
|
||||
}
|
||||
|
||||
void lightmap_clear(lightmap_t *lm) {
|
||||
ASSERT(lm->ready);
|
||||
glBindTexture(GL_TEXTURE_2D, lm->lightmap.id);
|
||||
m->lightmap = texture_create(w, h, 4, 0, TEXTURE_LINEAR|TEXTURE_FLOAT);
|
||||
glBindTexture(GL_TEXTURE_2D, m->lightmap.id);
|
||||
unsigned char emissive[] = { 0, 0, 0, 255 };
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, emissive);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
for (int b = 0; b < bounces; b++) {
|
||||
for (int i = 0; i < array_count(lm->models); i++) {
|
||||
model_t *m = lm->models[i];
|
||||
if (!m->lmdata) {
|
||||
m->lmdata = CALLOC(w*h*4, sizeof(float));
|
||||
}
|
||||
memset(m->lmdata, 0, w*h*4);
|
||||
lmSetTargetLightmap(lm->ctx, m->lmdata, w, h, 4);
|
||||
lmSetGeometry(lm->ctx, m->pivot,
|
||||
LM_FLOAT, (uint8_t*)m->verts + offsetof(iqm_vertex, position), sizeof(iqm_vertex),
|
||||
LM_FLOAT, (uint8_t*)m->verts + offsetof(iqm_vertex, normal), sizeof(iqm_vertex),
|
||||
LM_FLOAT, (uint8_t*)m->verts + offsetof(iqm_vertex, texcoord), sizeof(iqm_vertex),
|
||||
m->num_tris*3, LM_UNSIGNED_INT, m->tris);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
int vp[4];
|
||||
float view[16], projection[16];
|
||||
while (lmBegin(lm->ctx, vp, view, projection))
|
||||
{
|
||||
// render to lightmapper framebuffer
|
||||
glViewport(vp[0], vp[1], vp[2], vp[3]);
|
||||
drawscene(lm, m, view, projection, userdata);
|
||||
lmEnd(lm->ctx);
|
||||
}
|
||||
}
|
||||
|
||||
// postprocess texture
|
||||
for (int i = 0; i < array_count(lm->models); i++) {
|
||||
model_t *m = lm->models[i];
|
||||
float *temp = CALLOC(w * h * 4, sizeof(float));
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
lmImageDilate(m->lmdata, temp, w, h, 4);
|
||||
lmImageDilate(temp, m->lmdata, w, h, 4);
|
||||
}
|
||||
lmImageSmooth(m->lmdata, temp, w, h, 4);
|
||||
lmImageDilate(temp, m->lmdata, w, h, 4);
|
||||
lmImagePower(m->lmdata, w, h, 4, 1.0f / 2.2f, 0x7); // gamma correct color channels
|
||||
FREE(temp);
|
||||
|
||||
// save result to a file
|
||||
// if (lmImageSaveTGAf("result.tga", m->lmdata, w, h, 4, 1.0f))
|
||||
// printf("Saved result.tga\n");
|
||||
// upload result
|
||||
glBindTexture(GL_TEXTURE_2D, m->lightmap.id);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_FLOAT, m->lmdata);
|
||||
FREE(m->lmdata); m->lmdata = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (cullface) glEnable(GL_CULL_FACE);
|
||||
}
|
||||
|
||||
#line 0
|
||||
|
||||
#line 1 "v4k_renderdd.c"
|
||||
|
|
|
@ -2766,13 +2766,13 @@ struct iqmbounds {
|
|||
typedef struct iqm_vertex {
|
||||
GLfloat position[3];
|
||||
GLfloat texcoord[2];
|
||||
GLfloat texcoord2[2];
|
||||
GLfloat normal[3];
|
||||
GLfloat tangent[4];
|
||||
GLubyte blendindexes[4];
|
||||
GLubyte blendweights[4];
|
||||
GLfloat blendvertexindex;
|
||||
GLubyte color[4];
|
||||
GLfloat texcoord2[2];
|
||||
} iqm_vertex;
|
||||
|
||||
typedef struct iqm_t {
|
||||
|
@ -2882,6 +2882,13 @@ void model_set_uniforms(model_t m, int shader, mat44 mv, mat44 proj, mat44 view,
|
|||
if( (loc = glGetUniformLocation(shader, "u_billboard")) >= 0 ) {
|
||||
glUniform1i( loc, m.billboard );
|
||||
}
|
||||
if( (loc = glGetUniformLocation(shader, "texlit")) >= 0 ) {
|
||||
glUniform1i( loc, (m.lightmap.w != 0) );
|
||||
}
|
||||
else
|
||||
if( (loc = glGetUniformLocation(shader, "u_texlit")) >= 0 ) {
|
||||
glUniform1i( loc, (m.lightmap.w != 0) );
|
||||
}
|
||||
#if 0
|
||||
// @todo: mat44 projview (useful?)
|
||||
#endif
|
||||
|
@ -2926,28 +2933,26 @@ void model_set_state(model_t m) {
|
|||
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, position) );
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, texcoord) );
|
||||
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, texcoord2) );
|
||||
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, normal) );
|
||||
glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, tangent) );
|
||||
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, normal) );
|
||||
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, tangent) );
|
||||
|
||||
glEnableVertexAttribArray(0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glEnableVertexAttribArray(2);
|
||||
glEnableVertexAttribArray(3);
|
||||
glEnableVertexAttribArray(4);
|
||||
|
||||
// vertex color
|
||||
glVertexAttribPointer(12, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex,color) );
|
||||
glEnableVertexAttribArray(12);
|
||||
glVertexAttribPointer(11, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex,color) );
|
||||
glEnableVertexAttribArray(11);
|
||||
|
||||
// animation
|
||||
if(numframes > 0) {
|
||||
glVertexAttribPointer( 9, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex,blendindexes) );
|
||||
glVertexAttribPointer( 10, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex,blendweights) );
|
||||
glVertexAttribPointer(11, 1, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, blendvertexindex) );
|
||||
glVertexAttribPointer( 8, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex,blendindexes) );
|
||||
glVertexAttribPointer( 9, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex,blendweights) );
|
||||
glVertexAttribPointer(10, 1, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, blendvertexindex) );
|
||||
glEnableVertexAttribArray(8);
|
||||
glEnableVertexAttribArray(9);
|
||||
glEnableVertexAttribArray(10);
|
||||
glEnableVertexAttribArray(11);
|
||||
}
|
||||
|
||||
// mat4 attribute; for instanced rendering
|
||||
|
@ -2959,22 +2964,26 @@ void model_set_state(model_t m) {
|
|||
glBindBuffer(GL_ARRAY_BUFFER, m.vao_instanced);
|
||||
glBufferData(GL_ARRAY_BUFFER, m.num_instances * mat4_size, m.instanced_matrices, GL_STATIC_DRAW);
|
||||
|
||||
glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, 4 * vec4_size, (GLvoid*)(((char*)NULL)+(0 * vec4_size)));
|
||||
glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, 4 * vec4_size, (GLvoid*)(((char*)NULL)+(1 * vec4_size)));
|
||||
glVertexAttribPointer(7, 4, GL_FLOAT, GL_FALSE, 4 * vec4_size, (GLvoid*)(((char*)NULL)+(2 * vec4_size)));
|
||||
glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, 4 * vec4_size, (GLvoid*)(((char*)NULL)+(3 * vec4_size)));
|
||||
glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, 4 * vec4_size, (GLvoid*)(((char*)NULL)+(0 * vec4_size)));
|
||||
glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, 4 * vec4_size, (GLvoid*)(((char*)NULL)+(1 * vec4_size)));
|
||||
glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, 4 * vec4_size, (GLvoid*)(((char*)NULL)+(2 * vec4_size)));
|
||||
glVertexAttribPointer(7, 4, GL_FLOAT, GL_FALSE, 4 * vec4_size, (GLvoid*)(((char*)NULL)+(3 * vec4_size)));
|
||||
|
||||
glEnableVertexAttribArray(4);
|
||||
glEnableVertexAttribArray(5);
|
||||
glEnableVertexAttribArray(6);
|
||||
glEnableVertexAttribArray(7);
|
||||
glEnableVertexAttribArray(8);
|
||||
|
||||
glVertexAttribDivisor(4, 1);
|
||||
glVertexAttribDivisor(5, 1);
|
||||
glVertexAttribDivisor(6, 1);
|
||||
glVertexAttribDivisor(7, 1);
|
||||
glVertexAttribDivisor(8, 1);
|
||||
}
|
||||
|
||||
// lmap data
|
||||
glVertexAttribPointer(12, 2, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, texcoord2) );
|
||||
glEnableVertexAttribArray(12);
|
||||
|
||||
// 7 bitangent? into texcoord.z?
|
||||
|
||||
glBindVertexArray( 0 );
|
||||
|
@ -3039,6 +3048,8 @@ bool model_load_meshes(iqm_t *q, const struct iqmheader *hdr, model_t *m) {
|
|||
}
|
||||
|
||||
struct iqmtriangle *tris = (struct iqmtriangle *)&buf[hdr->ofs_triangles];
|
||||
m->num_tris = hdr->num_triangles;
|
||||
m->tris = (void*)tris;
|
||||
|
||||
glGenVertexArrays(1, &vao);
|
||||
glBindVertexArray(vao);
|
||||
|
@ -3094,8 +3105,8 @@ if(inblendweightf) m->stride += sizeof(verts[0].blendweights);
|
|||
if(invertexcolor8) m->stride += sizeof(verts[0].color);
|
||||
#endif
|
||||
//for( int i = 0; i < 16; ++i ) printf("%.9g%s", ((float*)verts)[i], (i % 3) == 2 ? "\n" : ",");
|
||||
//m->verts = verts; //FREE(verts);
|
||||
m->verts = 0; FREE(verts);
|
||||
m->verts = verts;
|
||||
/*m->verts = 0; FREE(verts);*/
|
||||
|
||||
textures = CALLOC(hdr->num_meshes * 8, sizeof(GLuint));
|
||||
colormaps = CALLOC(hdr->num_meshes * 8, sizeof(vec4));
|
||||
|
@ -3327,8 +3338,8 @@ model_t model_from_mem(const void *mem, int len, int flags) {
|
|||
// static int shaderprog = -1;
|
||||
// if( shaderprog < 0 ) {
|
||||
const char *symbols[] = { "{{include-shadowmap}}", vfs_read("shaders/fs_0_0_shadowmap_lit.glsl") }; // #define RIM
|
||||
int shaderprog = shader(strlerp(1,symbols,vfs_read("shaders/vs_3223444143_16_332_model.glsl")), strlerp(1,symbols,vfs_read("shaders/fs_32_4_model.glsl")), //fs,
|
||||
"att_position,att_texcoord,att_texcoord2,att_normal,att_tangent,att_instanced_matrix,,,,att_indexes,att_weights,att_vertexindex,att_color,att_bitangent","fragColor",
|
||||
int shaderprog = shader(strlerp(1,symbols,vfs_read("shaders/vs_323444143_16_3322_model.glsl")), strlerp(1,symbols,vfs_read("shaders/fs_32_4_model.glsl")), //fs,
|
||||
"att_position,att_texcoord,att_normal,att_tangent,att_instanced_matrix,,,,att_indexes,att_weights,att_vertexindex,att_color,att_bitangent,att_texcoord2","fragColor",
|
||||
va("SHADING_PHONG,%s", (flags&MODEL_RIMLIGHT)?"RIM":""));
|
||||
// }
|
||||
// ASSERT(shaderprog > 0);
|
||||
|
@ -3570,7 +3581,7 @@ float model_animate(model_t m, float curframe) {
|
|||
}
|
||||
|
||||
static
|
||||
void model_draw_call(model_t m) {
|
||||
void model_draw_call(model_t m, int shader) {
|
||||
if(!m.iqm) return;
|
||||
iqm_t *q = m.iqm;
|
||||
|
||||
|
@ -3582,17 +3593,21 @@ void model_draw_call(model_t m) {
|
|||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, textures[i] );
|
||||
glUniform1i(glGetUniformLocation(m.program, "fsDiffTex"), 0 /*<-- unit!*/ );
|
||||
glUniform1i(glGetUniformLocation(shader, "u_texture2d"), 0 );
|
||||
|
||||
int loc;
|
||||
if ((loc = glGetUniformLocation(m.program, "u_textured")) >= 0) {
|
||||
if ((loc = glGetUniformLocation(shader, "u_textured")) >= 0) {
|
||||
bool textured = !!textures[i] && textures[i] != texture_checker().id; // m.materials[i].layer[0].texture != texture_checker().id;
|
||||
glUniform1i(loc, textured ? GL_TRUE : GL_FALSE);
|
||||
if ((loc = glGetUniformLocation(m.program, "u_diffuse")) >= 0) {
|
||||
if ((loc = glGetUniformLocation(shader, "u_diffuse")) >= 0) {
|
||||
glUniform4f(loc, m.materials[i].layer[0].color.r, m.materials[i].layer[0].color.g, m.materials[i].layer[0].color.b, m.materials[i].layer[0].color.a);
|
||||
}
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, m.lightmap.id);
|
||||
glUniform1i(glGetUniformLocation(shader, "u_lightmap"), 1 );
|
||||
|
||||
glDrawElementsInstanced(GL_TRIANGLES, 3*im->num_triangles, GL_UNSIGNED_INT, &tris[im->first_triangle], m.num_instances);
|
||||
profile_incstat("Render.num_drawcalls", +1);
|
||||
profile_incstat("Render.num_triangles", +im->num_triangles);
|
||||
|
@ -3614,7 +3629,7 @@ void model_render_instanced(model_t m, mat44 proj, mat44 view, mat44* models, in
|
|||
}
|
||||
|
||||
model_set_uniforms(m, shader > 0 ? shader : m.program, mv, proj, view, models[0]);
|
||||
model_draw_call(m);
|
||||
model_draw_call(m, shader > 0 ? shader : m.program);
|
||||
}
|
||||
|
||||
void model_render(model_t m, mat44 proj, mat44 view, mat44 model, int shader) {
|
||||
|
@ -3731,113 +3746,98 @@ lightmap_t lightmap(int hmsize, float cnear, float cfar, vec3 color, int passes,
|
|||
return lm;
|
||||
}
|
||||
|
||||
return lm;
|
||||
}
|
||||
const char *symbols[] = { "{{include-shadowmap}}", vfs_read("shaders/fs_0_0_shadowmap_lit.glsl") }; // #define RIM
|
||||
lm.shader = shader(strlerp(1,symbols,vfs_read("shaders/vs_323444143_16_3322_model.glsl")), strlerp(1,symbols,vfs_read("shaders/fs_32_4_model.glsl")), //fs,
|
||||
"att_position,att_texcoord,att_normal,att_tangent,att_instanced_matrix,,,,att_indexes,att_weights,att_vertexindex,att_color,att_bitangent,att_texcoord2","fragColor",
|
||||
va("%s", "LIGHTMAP_BAKING"));
|
||||
|
||||
static
|
||||
void lightmap_destroytexture(lightmap_t *lm) {
|
||||
texture_destroy(&lm->lightmap);
|
||||
for (int i = 0; i < array_count(lm->models); i++) {
|
||||
lm->models[i]->lightmap = NULL;
|
||||
}
|
||||
return lm;
|
||||
}
|
||||
|
||||
void lightmap_destroy(lightmap_t *lm) {
|
||||
lmDestroy(lm->ctx);
|
||||
lightmap_destroytexture(lm);
|
||||
shader_destroy(lm->shader);
|
||||
//
|
||||
}
|
||||
|
||||
void lightmap_setup(lightmap_t *lm, int w, int h) {
|
||||
if (lm->ready) {
|
||||
lightmap_destroytexture(lm);
|
||||
}
|
||||
lm->ready=1;
|
||||
|
||||
lm->lightmap = texture_create(w, h, 4, 0, TEXTURE_LINEAR);
|
||||
glBindTexture(GL_TEXTURE_2D, lm->lightmap.id);
|
||||
unsigned char emissive[] = { 0, 0, 0, 255 };
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, emissive);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
//@fixme: prep atlas for lightmaps
|
||||
lm->w = w;
|
||||
lm->h = h;
|
||||
}
|
||||
|
||||
void lightmap_addmodel(lightmap_t *lm, model_t *m) {
|
||||
array_push(lm->models, m);
|
||||
}
|
||||
|
||||
void lightmap_bake(lightmap_t *lm, int bounces, void (*drawscene)(lightmap_t *lm, float *view, float *proj, void *userdata), void *userdata) {
|
||||
void lightmap_bake(lightmap_t *lm, int bounces, void (*drawscene)(lightmap_t *lm, model_t *m, float *view, float *proj, void *userdata), void *userdata) {
|
||||
ASSERT(lm->ready);
|
||||
// @fixme: use xatlas to UV pack all models, update their UV1 and upload them to GPU.
|
||||
// @fixme: combine all verts data together and push to lmSetGeometry
|
||||
|
||||
// int w = lm->lightmap->w, h = lm->lightmap->h;
|
||||
// float *data = CALLOC(w * h * 4, sizeof(float));
|
||||
// memset(data, 0, w*h*4);
|
||||
// for (int b = 0; b < bounces; b++) {
|
||||
// lmSetTargetLightmap(lm->ctx, data, w, h, 4);
|
||||
GLint cullface=0;
|
||||
glGetIntegerv(GL_CULL_FACE, &cullface);
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
// lmSetGeometry(lm->ctx, NULL,
|
||||
// LM_FLOAT, (unsigned char*)scene->vertices + offsetof(vertex_t, p), sizeof(vertex_t),
|
||||
// LM_NONE , NULL , 0 , // no interpolated normals in this example
|
||||
// LM_FLOAT, (unsigned char*)scene->vertices + offsetof(vertex_t, t), sizeof(vertex_t),
|
||||
// scene->indexCount, LM_UNSIGNED_SHORT, scene->indices);
|
||||
|
||||
|
||||
// glDisable(GL_BLEND);
|
||||
|
||||
// int vp[4];
|
||||
// float view[16], projection[16];
|
||||
// double lastUpdateTime = 0.0;
|
||||
// while (lmBegin(ctx, vp, view, projection))
|
||||
// {
|
||||
// // render to lightmapper framebuffer
|
||||
// glViewport(vp[0], vp[1], vp[2], vp[3]);
|
||||
// drawScene(scene, view, projection);
|
||||
|
||||
// // display progress every second (printf is expensive)
|
||||
// double time = time_ms() / 1000.0;
|
||||
// if (time - lastUpdateTime > 1.0)
|
||||
// {
|
||||
// lastUpdateTime = time;
|
||||
// printf("\r%6.2f%%", lmProgress(ctx) * 100.0f);
|
||||
// fflush(stdout);
|
||||
// }
|
||||
|
||||
// lmEnd(ctx);
|
||||
// // window_swap();
|
||||
// }
|
||||
// printf("\rFinished baking %d triangles.\n", scene->indexCount / 3);
|
||||
// }
|
||||
|
||||
// lmDestroy(ctx);
|
||||
|
||||
// // postprocess texture
|
||||
// float *temp = CALLOC(w * h * 4, sizeof(float));
|
||||
// for (int i = 0; i < 16; i++)
|
||||
// {
|
||||
// lmImageDilate(data, temp, w, h, 4);
|
||||
// lmImageDilate(temp, data, w, h, 4);
|
||||
// }
|
||||
// lmImageSmooth(data, temp, w, h, 4);
|
||||
// lmImageDilate(temp, data, w, h, 4);
|
||||
// lmImagePower(data, w, h, 4, 1.0f / 2.2f, 0x7); // gamma correct color channels
|
||||
// FREE(temp);
|
||||
|
||||
// // save result to a file
|
||||
// if (lmImageSaveTGAf("result.tga", data, w, h, 4, 1.0f))
|
||||
// printf("Saved result.tga\n");
|
||||
|
||||
// // upload result
|
||||
// glBindTexture(GL_TEXTURE_2D, scene->lightmap);
|
||||
// glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_FLOAT, data);
|
||||
// FREE(data);
|
||||
int w = lm->w, h = lm->h;
|
||||
for (int i = 0; i < array_count(lm->models); i++) {
|
||||
model_t *m = lm->models[i];
|
||||
if (m->lightmap.w != 0) {
|
||||
texture_destroy(&m->lightmap);
|
||||
}
|
||||
|
||||
void lightmap_clear(lightmap_t *lm) {
|
||||
ASSERT(lm->ready);
|
||||
glBindTexture(GL_TEXTURE_2D, lm->lightmap.id);
|
||||
m->lightmap = texture_create(w, h, 4, 0, TEXTURE_LINEAR|TEXTURE_FLOAT);
|
||||
glBindTexture(GL_TEXTURE_2D, m->lightmap.id);
|
||||
unsigned char emissive[] = { 0, 0, 0, 255 };
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, emissive);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
for (int b = 0; b < bounces; b++) {
|
||||
for (int i = 0; i < array_count(lm->models); i++) {
|
||||
model_t *m = lm->models[i];
|
||||
if (!m->lmdata) {
|
||||
m->lmdata = CALLOC(w*h*4, sizeof(float));
|
||||
}
|
||||
memset(m->lmdata, 0, w*h*4);
|
||||
lmSetTargetLightmap(lm->ctx, m->lmdata, w, h, 4);
|
||||
lmSetGeometry(lm->ctx, m->pivot,
|
||||
LM_FLOAT, (uint8_t*)m->verts + offsetof(iqm_vertex, position), sizeof(iqm_vertex),
|
||||
LM_FLOAT, (uint8_t*)m->verts + offsetof(iqm_vertex, normal), sizeof(iqm_vertex),
|
||||
LM_FLOAT, (uint8_t*)m->verts + offsetof(iqm_vertex, texcoord), sizeof(iqm_vertex),
|
||||
m->num_tris*3, LM_UNSIGNED_INT, m->tris);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
int vp[4];
|
||||
float view[16], projection[16];
|
||||
while (lmBegin(lm->ctx, vp, view, projection))
|
||||
{
|
||||
// render to lightmapper framebuffer
|
||||
glViewport(vp[0], vp[1], vp[2], vp[3]);
|
||||
drawscene(lm, m, view, projection, userdata);
|
||||
lmEnd(lm->ctx);
|
||||
}
|
||||
}
|
||||
|
||||
// postprocess texture
|
||||
for (int i = 0; i < array_count(lm->models); i++) {
|
||||
model_t *m = lm->models[i];
|
||||
float *temp = CALLOC(w * h * 4, sizeof(float));
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
lmImageDilate(m->lmdata, temp, w, h, 4);
|
||||
lmImageDilate(temp, m->lmdata, w, h, 4);
|
||||
}
|
||||
lmImageSmooth(m->lmdata, temp, w, h, 4);
|
||||
lmImageDilate(temp, m->lmdata, w, h, 4);
|
||||
lmImagePower(m->lmdata, w, h, 4, 1.0f / 2.2f, 0x7); // gamma correct color channels
|
||||
FREE(temp);
|
||||
|
||||
// save result to a file
|
||||
// if (lmImageSaveTGAf("result.tga", m->lmdata, w, h, 4, 1.0f))
|
||||
// printf("Saved result.tga\n");
|
||||
// upload result
|
||||
glBindTexture(GL_TEXTURE_2D, m->lightmap.id);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_FLOAT, m->lmdata);
|
||||
FREE(m->lmdata); m->lmdata = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (cullface) glEnable(GL_CULL_FACE);
|
||||
}
|
||||
|
||||
|
|
|
@ -520,7 +520,9 @@ typedef struct model_t {
|
|||
handle *textures;
|
||||
char **texture_names;
|
||||
array(material_t) materials;
|
||||
texture_t *lightmap;
|
||||
|
||||
texture_t lightmap;
|
||||
float *lmdata;
|
||||
|
||||
unsigned num_meshes;
|
||||
unsigned num_triangles;
|
||||
|
@ -534,6 +536,8 @@ typedef struct model_t {
|
|||
int stride; // usually 68 bytes for a p3 u2 u2 n3 t4 i4B w4B c4B vertex stream
|
||||
void *verts;
|
||||
int num_verts;
|
||||
void *tris;
|
||||
int num_tris;
|
||||
handle vao, ibo, vbo, vao_instanced;
|
||||
|
||||
unsigned flags;
|
||||
|
@ -585,15 +589,16 @@ API anims_t animations(const char *pathfile, int flags);
|
|||
typedef struct lightmap_t {
|
||||
struct lm_context *ctx; // private
|
||||
bool ready;
|
||||
texture_t lightmap; //@fixme: do we need it per-model?
|
||||
int w, h;
|
||||
int atlas_w, atlas_h; //@fixme: implement
|
||||
texture_t atlas; //@fixme: implement this
|
||||
array(model_t*) models;
|
||||
unsigned shader;
|
||||
} lightmap_t;
|
||||
|
||||
API lightmap_t lightmap(int hmsize /*64*/, float near, float far, vec3 color /*1,1,1 for AO*/, int passes /*2*/, float threshold /*0.01f*/, float distmod /*0.0f*/);
|
||||
API void lightmap_setup(lightmap_t *lm, int w, int h);
|
||||
API void lightmap_addmodel(lightmap_t *lm, model_t *m);
|
||||
API void lightmap_bake(lightmap_t *lm, int bounces, void (*drawscene)(lightmap_t *lm, float *view, float *proj, void *userdata), void *userdata);
|
||||
API void lightmap_clear(lightmap_t *lm);
|
||||
API void lightmap_bake(lightmap_t *lm, int bounces, void (*drawscene)(lightmap_t *lm, model_t *m, float *view, float *proj, void *userdata), void *userdata);
|
||||
API void lightmap_destroy(lightmap_t *lm);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
228
engine/v4k.c
228
engine/v4k.c
|
@ -19682,13 +19682,13 @@ struct iqmbounds {
|
|||
typedef struct iqm_vertex {
|
||||
GLfloat position[3];
|
||||
GLfloat texcoord[2];
|
||||
GLfloat texcoord2[2];
|
||||
GLfloat normal[3];
|
||||
GLfloat tangent[4];
|
||||
GLubyte blendindexes[4];
|
||||
GLubyte blendweights[4];
|
||||
GLfloat blendvertexindex;
|
||||
GLubyte color[4];
|
||||
GLfloat texcoord2[2];
|
||||
} iqm_vertex;
|
||||
|
||||
typedef struct iqm_t {
|
||||
|
@ -19798,6 +19798,13 @@ void model_set_uniforms(model_t m, int shader, mat44 mv, mat44 proj, mat44 view,
|
|||
if( (loc = glGetUniformLocation(shader, "u_billboard")) >= 0 ) {
|
||||
glUniform1i( loc, m.billboard );
|
||||
}
|
||||
if( (loc = glGetUniformLocation(shader, "texlit")) >= 0 ) {
|
||||
glUniform1i( loc, (m.lightmap.w != 0) );
|
||||
}
|
||||
else
|
||||
if( (loc = glGetUniformLocation(shader, "u_texlit")) >= 0 ) {
|
||||
glUniform1i( loc, (m.lightmap.w != 0) );
|
||||
}
|
||||
#if 0
|
||||
// @todo: mat44 projview (useful?)
|
||||
#endif
|
||||
|
@ -19842,28 +19849,26 @@ void model_set_state(model_t m) {
|
|||
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, position) );
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, texcoord) );
|
||||
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, texcoord2) );
|
||||
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, normal) );
|
||||
glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, tangent) );
|
||||
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, normal) );
|
||||
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, tangent) );
|
||||
|
||||
glEnableVertexAttribArray(0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glEnableVertexAttribArray(2);
|
||||
glEnableVertexAttribArray(3);
|
||||
glEnableVertexAttribArray(4);
|
||||
|
||||
// vertex color
|
||||
glVertexAttribPointer(12, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex,color) );
|
||||
glEnableVertexAttribArray(12);
|
||||
glVertexAttribPointer(11, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex,color) );
|
||||
glEnableVertexAttribArray(11);
|
||||
|
||||
// animation
|
||||
if(numframes > 0) {
|
||||
glVertexAttribPointer( 9, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex,blendindexes) );
|
||||
glVertexAttribPointer( 10, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex,blendweights) );
|
||||
glVertexAttribPointer(11, 1, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, blendvertexindex) );
|
||||
glVertexAttribPointer( 8, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex,blendindexes) );
|
||||
glVertexAttribPointer( 9, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex,blendweights) );
|
||||
glVertexAttribPointer(10, 1, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, blendvertexindex) );
|
||||
glEnableVertexAttribArray(8);
|
||||
glEnableVertexAttribArray(9);
|
||||
glEnableVertexAttribArray(10);
|
||||
glEnableVertexAttribArray(11);
|
||||
}
|
||||
|
||||
// mat4 attribute; for instanced rendering
|
||||
|
@ -19875,22 +19880,26 @@ void model_set_state(model_t m) {
|
|||
glBindBuffer(GL_ARRAY_BUFFER, m.vao_instanced);
|
||||
glBufferData(GL_ARRAY_BUFFER, m.num_instances * mat4_size, m.instanced_matrices, GL_STATIC_DRAW);
|
||||
|
||||
glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, 4 * vec4_size, (GLvoid*)(((char*)NULL)+(0 * vec4_size)));
|
||||
glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, 4 * vec4_size, (GLvoid*)(((char*)NULL)+(1 * vec4_size)));
|
||||
glVertexAttribPointer(7, 4, GL_FLOAT, GL_FALSE, 4 * vec4_size, (GLvoid*)(((char*)NULL)+(2 * vec4_size)));
|
||||
glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, 4 * vec4_size, (GLvoid*)(((char*)NULL)+(3 * vec4_size)));
|
||||
glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, 4 * vec4_size, (GLvoid*)(((char*)NULL)+(0 * vec4_size)));
|
||||
glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, 4 * vec4_size, (GLvoid*)(((char*)NULL)+(1 * vec4_size)));
|
||||
glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, 4 * vec4_size, (GLvoid*)(((char*)NULL)+(2 * vec4_size)));
|
||||
glVertexAttribPointer(7, 4, GL_FLOAT, GL_FALSE, 4 * vec4_size, (GLvoid*)(((char*)NULL)+(3 * vec4_size)));
|
||||
|
||||
glEnableVertexAttribArray(4);
|
||||
glEnableVertexAttribArray(5);
|
||||
glEnableVertexAttribArray(6);
|
||||
glEnableVertexAttribArray(7);
|
||||
glEnableVertexAttribArray(8);
|
||||
|
||||
glVertexAttribDivisor(4, 1);
|
||||
glVertexAttribDivisor(5, 1);
|
||||
glVertexAttribDivisor(6, 1);
|
||||
glVertexAttribDivisor(7, 1);
|
||||
glVertexAttribDivisor(8, 1);
|
||||
}
|
||||
|
||||
// lmap data
|
||||
glVertexAttribPointer(12, 2, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, texcoord2) );
|
||||
glEnableVertexAttribArray(12);
|
||||
|
||||
// 7 bitangent? into texcoord.z?
|
||||
|
||||
glBindVertexArray( 0 );
|
||||
|
@ -19955,6 +19964,8 @@ bool model_load_meshes(iqm_t *q, const struct iqmheader *hdr, model_t *m) {
|
|||
}
|
||||
|
||||
struct iqmtriangle *tris = (struct iqmtriangle *)&buf[hdr->ofs_triangles];
|
||||
m->num_tris = hdr->num_triangles;
|
||||
m->tris = (void*)tris;
|
||||
|
||||
glGenVertexArrays(1, &vao);
|
||||
glBindVertexArray(vao);
|
||||
|
@ -20010,8 +20021,8 @@ if(inblendweightf) m->stride += sizeof(verts[0].blendweights);
|
|||
if(invertexcolor8) m->stride += sizeof(verts[0].color);
|
||||
#endif
|
||||
//for( int i = 0; i < 16; ++i ) printf("%.9g%s", ((float*)verts)[i], (i % 3) == 2 ? "\n" : ",");
|
||||
//m->verts = verts; //FREE(verts);
|
||||
m->verts = 0; FREE(verts);
|
||||
m->verts = verts;
|
||||
/*m->verts = 0; FREE(verts);*/
|
||||
|
||||
textures = CALLOC(hdr->num_meshes * 8, sizeof(GLuint));
|
||||
colormaps = CALLOC(hdr->num_meshes * 8, sizeof(vec4));
|
||||
|
@ -20243,8 +20254,8 @@ model_t model_from_mem(const void *mem, int len, int flags) {
|
|||
// static int shaderprog = -1;
|
||||
// if( shaderprog < 0 ) {
|
||||
const char *symbols[] = { "{{include-shadowmap}}", vfs_read("shaders/fs_0_0_shadowmap_lit.glsl") }; // #define RIM
|
||||
int shaderprog = shader(strlerp(1,symbols,vfs_read("shaders/vs_3223444143_16_332_model.glsl")), strlerp(1,symbols,vfs_read("shaders/fs_32_4_model.glsl")), //fs,
|
||||
"att_position,att_texcoord,att_texcoord2,att_normal,att_tangent,att_instanced_matrix,,,,att_indexes,att_weights,att_vertexindex,att_color,att_bitangent","fragColor",
|
||||
int shaderprog = shader(strlerp(1,symbols,vfs_read("shaders/vs_323444143_16_3322_model.glsl")), strlerp(1,symbols,vfs_read("shaders/fs_32_4_model.glsl")), //fs,
|
||||
"att_position,att_texcoord,att_normal,att_tangent,att_instanced_matrix,,,,att_indexes,att_weights,att_vertexindex,att_color,att_bitangent,att_texcoord2","fragColor",
|
||||
va("SHADING_PHONG,%s", (flags&MODEL_RIMLIGHT)?"RIM":""));
|
||||
// }
|
||||
// ASSERT(shaderprog > 0);
|
||||
|
@ -20486,7 +20497,7 @@ float model_animate(model_t m, float curframe) {
|
|||
}
|
||||
|
||||
static
|
||||
void model_draw_call(model_t m) {
|
||||
void model_draw_call(model_t m, int shader) {
|
||||
if(!m.iqm) return;
|
||||
iqm_t *q = m.iqm;
|
||||
|
||||
|
@ -20498,17 +20509,21 @@ void model_draw_call(model_t m) {
|
|||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, textures[i] );
|
||||
glUniform1i(glGetUniformLocation(m.program, "fsDiffTex"), 0 /*<-- unit!*/ );
|
||||
glUniform1i(glGetUniformLocation(shader, "u_texture2d"), 0 );
|
||||
|
||||
int loc;
|
||||
if ((loc = glGetUniformLocation(m.program, "u_textured")) >= 0) {
|
||||
if ((loc = glGetUniformLocation(shader, "u_textured")) >= 0) {
|
||||
bool textured = !!textures[i] && textures[i] != texture_checker().id; // m.materials[i].layer[0].texture != texture_checker().id;
|
||||
glUniform1i(loc, textured ? GL_TRUE : GL_FALSE);
|
||||
if ((loc = glGetUniformLocation(m.program, "u_diffuse")) >= 0) {
|
||||
if ((loc = glGetUniformLocation(shader, "u_diffuse")) >= 0) {
|
||||
glUniform4f(loc, m.materials[i].layer[0].color.r, m.materials[i].layer[0].color.g, m.materials[i].layer[0].color.b, m.materials[i].layer[0].color.a);
|
||||
}
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, m.lightmap.id);
|
||||
glUniform1i(glGetUniformLocation(shader, "u_lightmap"), 1 );
|
||||
|
||||
glDrawElementsInstanced(GL_TRIANGLES, 3*im->num_triangles, GL_UNSIGNED_INT, &tris[im->first_triangle], m.num_instances);
|
||||
profile_incstat("Render.num_drawcalls", +1);
|
||||
profile_incstat("Render.num_triangles", +im->num_triangles);
|
||||
|
@ -20530,7 +20545,7 @@ void model_render_instanced(model_t m, mat44 proj, mat44 view, mat44* models, in
|
|||
}
|
||||
|
||||
model_set_uniforms(m, shader > 0 ? shader : m.program, mv, proj, view, models[0]);
|
||||
model_draw_call(m);
|
||||
model_draw_call(m, shader > 0 ? shader : m.program);
|
||||
}
|
||||
|
||||
void model_render(model_t m, mat44 proj, mat44 view, mat44 model, int shader) {
|
||||
|
@ -20647,116 +20662,101 @@ lightmap_t lightmap(int hmsize, float cnear, float cfar, vec3 color, int passes,
|
|||
return lm;
|
||||
}
|
||||
|
||||
return lm;
|
||||
}
|
||||
const char *symbols[] = { "{{include-shadowmap}}", vfs_read("shaders/fs_0_0_shadowmap_lit.glsl") }; // #define RIM
|
||||
lm.shader = shader(strlerp(1,symbols,vfs_read("shaders/vs_323444143_16_3322_model.glsl")), strlerp(1,symbols,vfs_read("shaders/fs_32_4_model.glsl")), //fs,
|
||||
"att_position,att_texcoord,att_normal,att_tangent,att_instanced_matrix,,,,att_indexes,att_weights,att_vertexindex,att_color,att_bitangent,att_texcoord2","fragColor",
|
||||
va("%s", "LIGHTMAP_BAKING"));
|
||||
|
||||
static
|
||||
void lightmap_destroytexture(lightmap_t *lm) {
|
||||
texture_destroy(&lm->lightmap);
|
||||
for (int i = 0; i < array_count(lm->models); i++) {
|
||||
lm->models[i]->lightmap = NULL;
|
||||
}
|
||||
return lm;
|
||||
}
|
||||
|
||||
void lightmap_destroy(lightmap_t *lm) {
|
||||
lmDestroy(lm->ctx);
|
||||
lightmap_destroytexture(lm);
|
||||
shader_destroy(lm->shader);
|
||||
//
|
||||
}
|
||||
|
||||
void lightmap_setup(lightmap_t *lm, int w, int h) {
|
||||
if (lm->ready) {
|
||||
lightmap_destroytexture(lm);
|
||||
}
|
||||
lm->ready=1;
|
||||
|
||||
lm->lightmap = texture_create(w, h, 4, 0, TEXTURE_LINEAR);
|
||||
glBindTexture(GL_TEXTURE_2D, lm->lightmap.id);
|
||||
unsigned char emissive[] = { 0, 0, 0, 255 };
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, emissive);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
//@fixme: prep atlas for lightmaps
|
||||
lm->w = w;
|
||||
lm->h = h;
|
||||
}
|
||||
|
||||
void lightmap_addmodel(lightmap_t *lm, model_t *m) {
|
||||
array_push(lm->models, m);
|
||||
}
|
||||
|
||||
void lightmap_bake(lightmap_t *lm, int bounces, void (*drawscene)(lightmap_t *lm, float *view, float *proj, void *userdata), void *userdata) {
|
||||
void lightmap_bake(lightmap_t *lm, int bounces, void (*drawscene)(lightmap_t *lm, model_t *m, float *view, float *proj, void *userdata), void *userdata) {
|
||||
ASSERT(lm->ready);
|
||||
// @fixme: use xatlas to UV pack all models, update their UV1 and upload them to GPU.
|
||||
// @fixme: combine all verts data together and push to lmSetGeometry
|
||||
|
||||
// int w = lm->lightmap->w, h = lm->lightmap->h;
|
||||
// float *data = CALLOC(w * h * 4, sizeof(float));
|
||||
// memset(data, 0, w*h*4);
|
||||
// for (int b = 0; b < bounces; b++) {
|
||||
// lmSetTargetLightmap(lm->ctx, data, w, h, 4);
|
||||
GLint cullface=0;
|
||||
glGetIntegerv(GL_CULL_FACE, &cullface);
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
// lmSetGeometry(lm->ctx, NULL,
|
||||
// LM_FLOAT, (unsigned char*)scene->vertices + offsetof(vertex_t, p), sizeof(vertex_t),
|
||||
// LM_NONE , NULL , 0 , // no interpolated normals in this example
|
||||
// LM_FLOAT, (unsigned char*)scene->vertices + offsetof(vertex_t, t), sizeof(vertex_t),
|
||||
// scene->indexCount, LM_UNSIGNED_SHORT, scene->indices);
|
||||
|
||||
|
||||
// glDisable(GL_BLEND);
|
||||
|
||||
// int vp[4];
|
||||
// float view[16], projection[16];
|
||||
// double lastUpdateTime = 0.0;
|
||||
// while (lmBegin(ctx, vp, view, projection))
|
||||
// {
|
||||
// // render to lightmapper framebuffer
|
||||
// glViewport(vp[0], vp[1], vp[2], vp[3]);
|
||||
// drawScene(scene, view, projection);
|
||||
|
||||
// // display progress every second (printf is expensive)
|
||||
// double time = time_ms() / 1000.0;
|
||||
// if (time - lastUpdateTime > 1.0)
|
||||
// {
|
||||
// lastUpdateTime = time;
|
||||
// printf("\r%6.2f%%", lmProgress(ctx) * 100.0f);
|
||||
// fflush(stdout);
|
||||
// }
|
||||
|
||||
// lmEnd(ctx);
|
||||
// // window_swap();
|
||||
// }
|
||||
// printf("\rFinished baking %d triangles.\n", scene->indexCount / 3);
|
||||
// }
|
||||
|
||||
// lmDestroy(ctx);
|
||||
|
||||
// // postprocess texture
|
||||
// float *temp = CALLOC(w * h * 4, sizeof(float));
|
||||
// for (int i = 0; i < 16; i++)
|
||||
// {
|
||||
// lmImageDilate(data, temp, w, h, 4);
|
||||
// lmImageDilate(temp, data, w, h, 4);
|
||||
// }
|
||||
// lmImageSmooth(data, temp, w, h, 4);
|
||||
// lmImageDilate(temp, data, w, h, 4);
|
||||
// lmImagePower(data, w, h, 4, 1.0f / 2.2f, 0x7); // gamma correct color channels
|
||||
// FREE(temp);
|
||||
|
||||
// // save result to a file
|
||||
// if (lmImageSaveTGAf("result.tga", data, w, h, 4, 1.0f))
|
||||
// printf("Saved result.tga\n");
|
||||
|
||||
// // upload result
|
||||
// glBindTexture(GL_TEXTURE_2D, scene->lightmap);
|
||||
// glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_FLOAT, data);
|
||||
// FREE(data);
|
||||
int w = lm->w, h = lm->h;
|
||||
for (int i = 0; i < array_count(lm->models); i++) {
|
||||
model_t *m = lm->models[i];
|
||||
if (m->lightmap.w != 0) {
|
||||
texture_destroy(&m->lightmap);
|
||||
}
|
||||
|
||||
void lightmap_clear(lightmap_t *lm) {
|
||||
ASSERT(lm->ready);
|
||||
glBindTexture(GL_TEXTURE_2D, lm->lightmap.id);
|
||||
m->lightmap = texture_create(w, h, 4, 0, TEXTURE_LINEAR|TEXTURE_FLOAT);
|
||||
glBindTexture(GL_TEXTURE_2D, m->lightmap.id);
|
||||
unsigned char emissive[] = { 0, 0, 0, 255 };
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, emissive);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
for (int b = 0; b < bounces; b++) {
|
||||
for (int i = 0; i < array_count(lm->models); i++) {
|
||||
model_t *m = lm->models[i];
|
||||
if (!m->lmdata) {
|
||||
m->lmdata = CALLOC(w*h*4, sizeof(float));
|
||||
}
|
||||
memset(m->lmdata, 0, w*h*4);
|
||||
lmSetTargetLightmap(lm->ctx, m->lmdata, w, h, 4);
|
||||
lmSetGeometry(lm->ctx, m->pivot,
|
||||
LM_FLOAT, (uint8_t*)m->verts + offsetof(iqm_vertex, position), sizeof(iqm_vertex),
|
||||
LM_FLOAT, (uint8_t*)m->verts + offsetof(iqm_vertex, normal), sizeof(iqm_vertex),
|
||||
LM_FLOAT, (uint8_t*)m->verts + offsetof(iqm_vertex, texcoord), sizeof(iqm_vertex),
|
||||
m->num_tris*3, LM_UNSIGNED_INT, m->tris);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
int vp[4];
|
||||
float view[16], projection[16];
|
||||
while (lmBegin(lm->ctx, vp, view, projection))
|
||||
{
|
||||
// render to lightmapper framebuffer
|
||||
glViewport(vp[0], vp[1], vp[2], vp[3]);
|
||||
drawscene(lm, m, view, projection, userdata);
|
||||
lmEnd(lm->ctx);
|
||||
}
|
||||
}
|
||||
|
||||
// postprocess texture
|
||||
for (int i = 0; i < array_count(lm->models); i++) {
|
||||
model_t *m = lm->models[i];
|
||||
float *temp = CALLOC(w * h * 4, sizeof(float));
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
lmImageDilate(m->lmdata, temp, w, h, 4);
|
||||
lmImageDilate(temp, m->lmdata, w, h, 4);
|
||||
}
|
||||
lmImageSmooth(m->lmdata, temp, w, h, 4);
|
||||
lmImageDilate(temp, m->lmdata, w, h, 4);
|
||||
lmImagePower(m->lmdata, w, h, 4, 1.0f / 2.2f, 0x7); // gamma correct color channels
|
||||
FREE(temp);
|
||||
|
||||
// save result to a file
|
||||
// if (lmImageSaveTGAf("result.tga", m->lmdata, w, h, 4, 1.0f))
|
||||
// printf("Saved result.tga\n");
|
||||
// upload result
|
||||
glBindTexture(GL_TEXTURE_2D, m->lightmap.id);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_FLOAT, m->lmdata);
|
||||
FREE(m->lmdata); m->lmdata = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (cullface) glEnable(GL_CULL_FACE);
|
||||
}
|
||||
|
||||
#line 0
|
||||
|
||||
#line 1 "v4k_renderdd.c"
|
||||
|
|
15
engine/v4k.h
15
engine/v4k.h
|
@ -3578,7 +3578,9 @@ typedef struct model_t {
|
|||
handle *textures;
|
||||
char **texture_names;
|
||||
array(material_t) materials;
|
||||
texture_t *lightmap;
|
||||
|
||||
texture_t lightmap;
|
||||
float *lmdata;
|
||||
|
||||
unsigned num_meshes;
|
||||
unsigned num_triangles;
|
||||
|
@ -3592,6 +3594,8 @@ typedef struct model_t {
|
|||
int stride; // usually 68 bytes for a p3 u2 u2 n3 t4 i4B w4B c4B vertex stream
|
||||
void *verts;
|
||||
int num_verts;
|
||||
void *tris;
|
||||
int num_tris;
|
||||
handle vao, ibo, vbo, vao_instanced;
|
||||
|
||||
unsigned flags;
|
||||
|
@ -3643,15 +3647,16 @@ API anims_t animations(const char *pathfile, int flags);
|
|||
typedef struct lightmap_t {
|
||||
struct lm_context *ctx; // private
|
||||
bool ready;
|
||||
texture_t lightmap; //@fixme: do we need it per-model?
|
||||
int w, h;
|
||||
int atlas_w, atlas_h; //@fixme: implement
|
||||
texture_t atlas; //@fixme: implement this
|
||||
array(model_t*) models;
|
||||
unsigned shader;
|
||||
} lightmap_t;
|
||||
|
||||
API lightmap_t lightmap(int hmsize /*64*/, float near, float far, vec3 color /*1,1,1 for AO*/, int passes /*2*/, float threshold /*0.01f*/, float distmod /*0.0f*/);
|
||||
API void lightmap_setup(lightmap_t *lm, int w, int h);
|
||||
API void lightmap_addmodel(lightmap_t *lm, model_t *m);
|
||||
API void lightmap_bake(lightmap_t *lm, int bounces, void (*drawscene)(lightmap_t *lm, float *view, float *proj, void *userdata), void *userdata);
|
||||
API void lightmap_clear(lightmap_t *lm);
|
||||
API void lightmap_bake(lightmap_t *lm, int bounces, void (*drawscene)(lightmap_t *lm, model_t *m, float *view, float *proj, void *userdata), void *userdata);
|
||||
API void lightmap_destroy(lightmap_t *lm);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 1.6 MiB |
Loading…
Reference in New Issue