Skip to content

Commit

Permalink
Add high quality LDR version. Use average pixel color from 4 faces fo…
Browse files Browse the repository at this point in the history
…r the stretch method
  • Loading branch information
bottiger1 committed May 27, 2021
1 parent e5d9e35 commit 326ced4
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 7 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,16 @@ Sometimes the dn VTF is missing. Open the VMT file with the same name (example t
VTF file used (example $basetexture cs_italy/black). Find the actual VTF file, and copy and paste it into the same place
with the rest of the VTFs and give it the proper name (example theskybox_dn.vtf).

Two files will be produced
These files will be made

* theskybox_cubemap.vtf
* theskybox_cubemap.vtf.hq
* theskybox_cubemap.vmt
* theskybox_cubemap.hdr.vmt

If you want less disk usage, delete **theskybox_cubemap.vtf.hq**. If you want higher quality, delete **theskybox_cubemap.vtf**
and rename **theskybox_cubemap.vtf.hq** to **theskybox_cubemap.vtf**

Move these files to **materials/cubemap_skyboxes** or edit **theskybox_cubemap.vmt** to use a different path.

Now you can create a **func_brush** with this texture around your **sky_camera** and toggle it on and off whenever you want.
Expand Down
55 changes: 49 additions & 6 deletions sln/vs2017/cubemaker/cubemaker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,17 @@ All 6 of these VTF files must be in the same directory. Sometimes the dn VTF is
file with the same name, find the VTF it points to, copy and paste it into the same folder as the VMT
and give it the same name except with the extension VTF.
3 files will be created: theskybox_cubemap.vtf, theskybox_cubemap.vmt, theskybox_cubemap.hdr.vmt
4 files will be created: theskybox_cubemap.vtf, theskybox_cubemap.vtf.hq, theskybox_cubemap.vmt, theskybox_cubemap.hdr.vmt
Edit theskybox_cubemap.vmt and change the path if needed. Then copy the 3 files to that path.
If you want a smaller file size, delete theskybox_cubemap.vtf.hq. If you want higher quality skybox,
delete theskybox_cubemap.vtf and rename the .hq version to theskybox_cubemap.vtf
Edit theskybox_cubemap.vmt and change the path if needed. Then copy the files to that path.
You can now apply theskybox_cubemap to the faces around the sky_camera.
You can optionally delete the hdr.vmt if you are compiling LDR only. If you compile in HDR without this
file, then the material will be replaced with a blinding white one.
file, the skybox will be pure white for people with HDR enabled.
)";

const char* g_completed = R"(DONE
Expand Down Expand Up @@ -228,6 +231,10 @@ int main(int argc, char* argv[])
auto cubemap = VTFLib::CVTFFile();

vlByte* main_buffer[6];
vlUInt lastPixel[6]; // get the last pixel for face sides for stretching method
vlUInt lastPixelAverage;

// convert to RGBA8888 internally because sphere face making process in VTFLib and Valve both do that already
for (int i = 0; i < 6; i++)
{
auto face_width = faces[i]->GetWidth();
Expand All @@ -240,7 +247,33 @@ int main(int argc, char* argv[])
PressKeyToContinue();
std::terminate();
}
vlUInt* pixelPtr = (vlUInt*)main_buffer[i];
lastPixel[i] = pixelPtr[face_height * face_width - 1];
}

// calculate average last pixel color for stretch method
{
float r = 0.0, g = 0.0, b = 0.0, a = 0.0;
for (int i = 0; i <= 3; i++)
{
auto channels = (vlByte*)&lastPixel[i];
r += channels[0];
g += channels[1];
b += channels[2];
a += channels[3];
}

auto lastPixelChannels = (vlByte*)&lastPixelAverage;
lastPixelChannels[0] = (vlByte)round(r / 4.0);
lastPixelChannels[1] = (vlByte)round(g / 4.0);
lastPixelChannels[2] = (vlByte)round(b / 4.0);
lastPixelChannels[3] = (vlByte)round(a / 4.0);
}

for(int i = 0; i < 6; i++)
{
auto face_width = faces[i]->GetWidth();
auto face_height = faces[i]->GetHeight();
if (face_width != width || face_height != height)
{
printf("%s%s.vtf has a different dimension %i x %i. attempting to resize.\n", base_nopath, g_faceorder[i], face_width, face_height);
Expand All @@ -254,10 +287,9 @@ int main(int argc, char* argv[])
vlByte* resized = (vlByte*)malloc(4 * face_width * face_width);
memcpy(resized, main_buffer[i], 4 * face_width * face_height);
vlUInt* resizedPixelPtr = (vlUInt*)resized;
vlUInt32 lastPixel = resizedPixelPtr[face_width * face_height - 1];
for (vlUInt i = face_width * face_height; i < face_width * face_width; i++)
{
resizedPixelPtr[i] = lastPixel;
resizedPixelPtr[i] = lastPixelAverage;
}
free(main_buffer[i]);
main_buffer[i] = resized;
Expand All @@ -278,7 +310,7 @@ int main(int argc, char* argv[])
{
filter = VTFMipmapFilter::MIPMAP_FILTER_MITCHELL;
}
success = cubemap.Resize(main_buffer[i], resized, face_width, face_height, width, height, filter, VTFSharpenFilter::SHARPEN_FILTER_SHARPENSOFT);
bool success = cubemap.Resize(main_buffer[i], resized, face_width, face_height, width, height, filter, VTFSharpenFilter::SHARPEN_FILTER_SHARPENSOFT);
if (!success)
{
printf("resize failed: %s\n", vlGetLastError());
Expand Down Expand Up @@ -372,6 +404,17 @@ int main(int argc, char* argv[])
}
ldr.Destroy();

auto ldr_hq = VTFLib::CVTFFile(cubemap, VTFImageFormat::IMAGE_FORMAT_RGB888);
snprintf(output_name, sizeof(output_name), "%s_cubemap.vtf.hq", base);
success = ldr_hq.Save(output_name);
if (!success)
{
printf("LDR high quality Save Error %s\n", vlGetLastError());
PressKeyToContinue();
std::terminate();
}
ldr_hq.Destroy();

auto hdr = VTFLib::CVTFFile(cubemap, VTFImageFormat::IMAGE_FORMAT_RGBA16161616F);
ConvertImageToFloat(&hdr);
snprintf(output_name, sizeof(output_name), "%s_cubemap.hdr.vtf", base);
Expand Down

0 comments on commit 326ced4

Please sign in to comment.