Preliminary work on lightmaps
This commit is contained in:
parent
ecce403966
commit
6b39e39fe1
0
gameenv/data/shaders/lightmap.glsl
Normal file
0
gameenv/data/shaders/lightmap.glsl
Normal file
@ -307,6 +307,11 @@ void MPFW::Quake::Maps::MapFile::LoadBSPMap(std::string path)
|
||||
|
||||
|
||||
|
||||
for (int i = 0; i < data.lightMaps.size(); i++) {
|
||||
rlUnloadTexture(data.lightMaps[i].glTextureID);
|
||||
}
|
||||
data.lightMaps.clear();
|
||||
|
||||
std::print("Loading mip textures manually for now\n");
|
||||
|
||||
|
||||
@ -368,8 +373,22 @@ void MPFW::Quake::Maps::MapFile::LoadBSPMap(std::string path)
|
||||
|
||||
data.renderFaces.clear();
|
||||
|
||||
data.lightmap.clear();
|
||||
|
||||
data.lightmap.resize(data.header.lightmaps.size);
|
||||
std::memcpy(data.lightmap.data(), Utils::Strings::IterativeStringExcerpt(buffer, data.header.lightmaps.offset, data.header.lightmaps.size).data(), data.header.lightmaps.size);
|
||||
|
||||
std::print("Precalculating faces and texture coordinates\n");
|
||||
|
||||
data.planes.clear();
|
||||
data.planes.resize(data.header.planes.size / sizeof(Plane));
|
||||
|
||||
std::memcpy(
|
||||
data.planes.data(),
|
||||
Utils::Strings::IterativeStringExcerpt(buffer, data.header.planes.offset, data.header.planes.size).data(),
|
||||
data.header.planes.size
|
||||
);
|
||||
|
||||
for (int i = 0; i < data.faces.size(); i++) {
|
||||
CalculatedFace cface;
|
||||
|
||||
@ -425,20 +444,87 @@ void MPFW::Quake::Maps::MapFile::LoadBSPMap(std::string path)
|
||||
}
|
||||
if (data.textures[data.texInfo[data.faces[i].texinfoId].textureId].name == "clip") cface.clipFace = true;
|
||||
if (data.textures[data.texInfo[data.faces[i].texinfoId].textureId].name == "trigger") cface.triggerFace = true;
|
||||
int lmbase = data.faces[i].lightmap;
|
||||
if (lmbase != -1) {
|
||||
|
||||
// int lmw = data.textures[data.texInfo[data.faces[i].texinfoId].textureId].width;
|
||||
// int lmh = data.textures[data.texInfo[data.faces[i].texinfoId].textureId].height;
|
||||
|
||||
|
||||
std::vector<Vector3> polygon;
|
||||
|
||||
for (int v = 0; v < cface.vertices.size(); v++) {
|
||||
polygon.push_back(RLVec2qVec(cface.vertices[v]));
|
||||
}
|
||||
|
||||
BoundingBox faceBB = GenerateBoundingBoxPolygon(polygon);
|
||||
|
||||
int planeType = data.planes[data.faces[i].planeId].type;
|
||||
int valueForgotten =
|
||||
planeType == 0 || planeType == 3 ? 0 :
|
||||
planeType == 1 || planeType == 4 ? 1 :
|
||||
2;
|
||||
|
||||
int lmw, lmh;
|
||||
|
||||
switch (valueForgotten) {
|
||||
case 0: // forgetting x
|
||||
|
||||
lmw = static_cast<int>((faceBB.max.y - faceBB.min.y) / 16);
|
||||
lmh = static_cast<int>((faceBB.max.z - faceBB.min.z) / 16);
|
||||
|
||||
break;
|
||||
case 1: // forgetting y
|
||||
|
||||
lmw = static_cast<int>((faceBB.max.x - faceBB.min.x) / 16);
|
||||
lmh = static_cast<int>((faceBB.max.z - faceBB.min.z) / 16);
|
||||
|
||||
break;
|
||||
case 2: // forgetting z
|
||||
|
||||
lmw = static_cast<int>((faceBB.max.x - faceBB.min.x) / 16);
|
||||
lmh = static_cast<int>((faceBB.max.y - faceBB.min.y) / 16);
|
||||
|
||||
break;
|
||||
default:
|
||||
throw;
|
||||
}
|
||||
|
||||
Image lightmap = GenImageColor(lmw, lmh, WHITE);
|
||||
cface.hasLightMap = true;
|
||||
for (int y = 0; y < lmh; y++) {
|
||||
for (int x = 0; x < lmw; x++) {
|
||||
unsigned char lightValue = data.lightmap[y*lmw+x + lmbase];
|
||||
ImageDrawPixel(&lightmap, x, y, {
|
||||
lightValue,
|
||||
lightValue,
|
||||
lightValue,
|
||||
255
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Texture lightmapTexture = LoadTextureFromImage(lightmap);
|
||||
|
||||
rlMipTex lightmapRLMipTex;
|
||||
lightmapRLMipTex.glTextureID = lightmapTexture.id;
|
||||
lightmapRLMipTex.width = lightmapTexture.width;
|
||||
lightmapRLMipTex.height = lightmapTexture.height;
|
||||
lightmapRLMipTex.type = lightmapTexture.format;
|
||||
data.lightMaps.push_back(lightmapRLMipTex);
|
||||
|
||||
cface.glLightmapTextureId = lightmapTexture.id;
|
||||
|
||||
UnloadImage(lightmap);
|
||||
|
||||
}
|
||||
|
||||
data.renderFaces.push_back(cface);
|
||||
|
||||
|
||||
}
|
||||
|
||||
data.planes.clear();
|
||||
data.planes.resize(data.header.planes.size / sizeof(Plane));
|
||||
|
||||
std::memcpy(
|
||||
data.planes.data(),
|
||||
Utils::Strings::IterativeStringExcerpt(buffer, data.header.planes.offset, data.header.planes.size).data(),
|
||||
data.header.planes.size
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
@ -455,6 +541,20 @@ Vector3 MPFW::Quake::Maps::RLVec2qVec(Vector3 q) {
|
||||
return { q.z * 2, q.x * 2, q.y * 2 };
|
||||
}
|
||||
|
||||
BoundingBox MPFW::Quake::Maps::GenerateBoundingBoxPolygon(std::vector<Vector3> poly)
|
||||
{
|
||||
std::vector<Vector3> polyCopy = poly;
|
||||
|
||||
std::sort(polyCopy.begin(), polyCopy.end(), [](Vector3 a, Vector3 b) {
|
||||
return Vector3Distance({ 0,0,0 }, a) < Vector3Distance({ 0,0,0 }, b);
|
||||
});
|
||||
|
||||
BoundingBox retval;
|
||||
retval.min = polyCopy[0];
|
||||
retval.max = polyCopy[polyCopy.size() - 1];
|
||||
return retval;
|
||||
}
|
||||
|
||||
void MPFW::Quake::Maps::Palette::LoadPalette(std::string path)
|
||||
{
|
||||
std::ifstream i(path, std::ios::binary);
|
||||
|
@ -103,11 +103,12 @@ namespace MPFW {
|
||||
struct CalculatedFace {
|
||||
std::vector<Vector3> vertices;
|
||||
std::vector<Vector2> texCoords;
|
||||
int glTextureId, glTextureWidth, glTextureHeight;
|
||||
int glTextureId, glTextureWidth, glTextureHeight, glLightmapTextureId;
|
||||
bool hasLightMap = false;
|
||||
bool skyFace = false;
|
||||
bool triggerFace = false;
|
||||
bool clipFace = false;
|
||||
|
||||
|
||||
unsigned char baselight;
|
||||
|
||||
};
|
||||
@ -172,7 +173,7 @@ namespace MPFW {
|
||||
struct MapData {
|
||||
BSPHeader header;
|
||||
|
||||
|
||||
std::vector<unsigned char> lightmap;
|
||||
std::vector<Vector3> vertices;
|
||||
std::vector<Edge> edges;
|
||||
std::vector<qModel> models;
|
||||
@ -186,7 +187,7 @@ namespace MPFW {
|
||||
|
||||
std::vector<CalculatedFace> renderFaces;
|
||||
|
||||
|
||||
std::vector<rlMipTex> lightMaps; // purely for unloading <3
|
||||
};
|
||||
|
||||
class MapFile {
|
||||
@ -211,6 +212,8 @@ namespace MPFW {
|
||||
void LoadBSPMap(std::string path);
|
||||
~MapFile(){}
|
||||
};
|
||||
|
||||
BoundingBox GenerateBoundingBoxPolygon(std::vector<Vector3> poly);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -306,22 +306,41 @@ int main() {
|
||||
if (chr.cvars["vid_2d_background"] == "true") DrawRectangleGradientV(0, 0, GetScreenWidth(), GetScreenHeight(), WHITE, LIGHTGRAY);
|
||||
|
||||
if (chr.cvars["vid_3d_renderer"] == "true") {
|
||||
bool cullSky = chr.cvars["vid_3d_cull_sky"] == "true";
|
||||
bool cullClips = chr.cvars["vid_3d_cull_clips"] == "true";
|
||||
bool cullTriggers = chr.cvars["vid_3d_cull_triggers"] == "true";
|
||||
|
||||
// Grab booleans once at the start of rendering instead of continuously grabbing them
|
||||
// 66->536 FPS on Quake start.bsp
|
||||
// 500->8000 on test pre-lightmapping
|
||||
|
||||
bool cullSky = chr.cvars["vid_3d_cull_sky"] == "true"; // if texture name starts by "sky"
|
||||
bool cullClips = chr.cvars["vid_3d_cull_clips"] == "true"; // if texture name == "clip"
|
||||
bool cullTriggers = chr.cvars["vid_3d_cull_triggers"] == "true"; // if texture name == "trigger"
|
||||
|
||||
BeginMode3D(camera);
|
||||
if(chr.cvars["vid_3d_grid"] == "true") DrawGrid(10000, 10);
|
||||
rlColor4ub(255, 255, 255, 255);
|
||||
for (int i = 0; i < map.data.renderFaces.size(); i++) {
|
||||
|
||||
// verify culling parameters before rendering
|
||||
if (
|
||||
!(cullSky && map.data.renderFaces[i].skyFace) &&
|
||||
!(cullClips && map.data.renderFaces[i].clipFace) &&
|
||||
!(cullTriggers && map.data.renderFaces[i].triggerFace)
|
||||
){
|
||||
|
||||
rlSetTexture(map.data.renderFaces[i].glTextureId);
|
||||
|
||||
rlColor4ub(
|
||||
255,// - (unsigned char)map.data.renderFaces[i].baselight,
|
||||
255,// - (unsigned char)map.data.renderFaces[i].baselight,
|
||||
255,// - (unsigned char)map.data.renderFaces[i].baselight,
|
||||
255);
|
||||
|
||||
if (map.data.renderFaces[i].hasLightMap) rlSetTexture(map.data.renderFaces[i].glLightmapTextureId);
|
||||
else rlSetTexture(map.data.renderFaces[i].glTextureId);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
for (int j = 1; j < map.data.renderFaces[i].vertices.size(); j++) {
|
||||
rlBegin(RL_QUADS); // for texturing reasons because rlgl
|
||||
@ -341,7 +360,7 @@ int main() {
|
||||
rlVertex3f(b.x, b.y, b.z);
|
||||
rlTexCoord2f(ct.x, ct.y);
|
||||
rlVertex3f(c.x, c.y, c.z);
|
||||
rlVertex3f(c.x, c.y, c.z);
|
||||
rlVertex3f(c.x, c.y, c.z); // why does RLGL fuck up triangles? is there something i'm missing?
|
||||
|
||||
|
||||
rlEnd();
|
||||
@ -352,7 +371,10 @@ int main() {
|
||||
}
|
||||
EndMode3D();
|
||||
}
|
||||
DrawFPS(0, 0);
|
||||
|
||||
|
||||
|
||||
DrawFPS(0, 0); // draw fps behind console for readability
|
||||
|
||||
if (consoleOn) {
|
||||
DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight() / 2, {0,0,0,200});
|
||||
@ -379,6 +401,7 @@ int main() {
|
||||
|
||||
}
|
||||
uiRenderer.Render();
|
||||
|
||||
EndDrawing();
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user