Skip to content

Instantly share code, notes, and snippets.

@guycalledfrank
Created November 12, 2019 15:49
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save guycalledfrank/cf0342c4736460d238a5442bbb156d63 to your computer and use it in GitHub Desktop.
Save guycalledfrank/cf0342c4736460d238a5442bbb156d63 to your computer and use it in GitHub Desktop.
#pragma once
#include "alphaBufferGenInterface.h"
#include "uvGBufferGenInterface.h"
#include "BakeryHelperInterface.h"
#include "stdint.h"
#include <cstdio>
#include <vector>
#include <string>
namespace Bakery
{
const int NO_TEXTURE = 0xFFFF;
struct Mesh
{
// Offset into global vertex buffer set with SetVertex*() functions
uint32_t vertexBufferOffset;
// Offset/length into global index buffer set with SetIndices()
uint32_t indexOffset;
uint32_t indexCount;
// IDs corresponding to the ones set via SetColorMaps/SetAlphaMaps
// Albedo must be always set, alpha and emissive are optional (set to NO_TEXTURE)
uint16_t albedoID, alphaID, emissiveID;
// Multiplier for emissive texture
float emissiveMul;
// Lightmap ID to which this mesh belongs
int32_t lmid;
// Should seam fixing take this mesh into account?
bool seamFixEnabled;
void SetDefault();
Mesh() { SetDefault(); }
};
enum TextureType
{
ShaderResourceViewD3D11, // ID3D11ShaderResourceView*
TextureD3D11, // ID3D11Texture2D*
ArrayRGBA8, // uint8_t r,g,b,a
ArrayRGBA32 // float r,g,b,a
};
enum GlobalFlag
{
None = 0,
CompressedGBuffer = 1, // UVGBuffer is LZ4-compressed
CompressedOutput = 2 // All lightmaps are LZ4-compressed
};
struct DirectionalLight
{
float direction[3]; // light direction, must be normalized
float color[3]; // linear RGB color (premultiply with intensity if needed), can be any positive value
float shadowSpread; // shadow blurriness (0-1; useful values are 0-0.1)
int samples; // quality (4 - 64 are typical values)
bool ignoreNormal; // ignore surface normal and only calculate distance falloff / shadow visibility?
const char* name; // optional name for lightmaps with this light
float indirectIntensity; // GI multiplier
void SetDefault();
DirectionalLight() { SetDefault(); }
};
struct SkyTexture
{
TextureType texType;
void* data;
float matrix[3 * 3];
bool isLinear; // linear or sRGB?
const char* name; // optional name to avoid duplicated data in temp folder
void SetDefault();
SkyTexture() { SetDefault(); }
};
struct SkyLight
{
float color[3]; // linear RGB color (premultiply with intensity if needed), can be any positive value
int samples; // quality (16 - 64 are typical values)
bool hemispherical; // only use upper hemisphere?
SkyTexture* texture; // HDRI, if any
const char* name; // optional name for lightmaps with this light
float indirectIntensity;// GI multiplier
void SetDefault();
SkyLight() { SetDefault(); }
};
enum PointLightProjection
{
Omni, // plain omnidirectional point light
Cookie, // directional 2D texture projector
Cubemap, // omnidirectional cubemap texture projector
IES, // omnidirectional IES data projector
Cone // classic spot light
};
struct CookieLightSettings
{
float rotationMatrix[3 * 3];
float angle; // projection angle
TextureType textureType;
void* textureData;
const char* textureName;
void SetDefault();
};
struct CubemapLightSettings
{
float rotationMatrix[3 * 3];
TextureType textureType;
void* textureData;
const char* textureName;
void SetDefault();
};
struct IESLightSettings
{
float rotationMatrix[3 * 3];
const char* iesPath; // path to IES file
const char* textureName;
void SetDefault();
};
struct ConeLightSettings
{
float direction[3];
float innerAngle;
float outerAngle;
void SetDefault();
};
struct PointLight
{
float color[3]; // linear RGB color (premultiply with intensity if needed), can be any positive value
float position[3];
int samples; // quality (1-64 are typical values)
float cutoff; // distance limit
float falloffMinRadius; // falloff tweaking, see: https://geom.io/bakery/wiki/index.php?title=Point_Light_Attenuation
// most of the time you want it to be 1cm in your world units
float shadowSpread; // virtual sphere radius that affects shadow blurriness
bool ignoreNormal; // ignore surface normal and only calculate distance falloff / shadow visibility?
const char* name; // optional name for lightmaps with this light
float indirectIntensity;// GI multiplier
PointLightProjection projectionMode; // additional projection mask
union
{
CookieLightSettings projCookie;
CubemapLightSettings projCubemap;
IESLightSettings projIES;
ConeLightSettings projCone;
};
void SetDefault();
PointLight() { SetDefault(); }
};
// TODO: arealight API
struct GISettings
{
uint32_t samples; // quality (16 - 64 are typical values)
float backFaceWeight; // how much frontface lighting is transferred to backfaces
void SetDefault();
GISettings() { SetDefault(); }
};
enum RenderPass
{
Color = 1, // HDR color
ShadowMask = 2,
Direction = 4,
RNM = 8,
SH = 16,
ProbeSH = 32
};
typedef int LightmapOutput;
enum ColorOutputFormat
{
RGBM = 0, // RGBM-encoded 8-bit color
RGBA32 = 2 // plain float RGBA
};
enum Status
{
NotBaking,
Baking,
Error
};
class Lightmapper
{
struct ftLightmap
{
char* name;
uint32_t nameLen;
uint32_t size;
};
struct ftCommand
{
std::string commandline;
std::string outputName;
int LMID;
int passes;
float indirectWeight;
bool useInGI;
};
struct h2vbCommand
{
std::string input;
void* output;
int format;
};
struct exeCommand
{
int etype;
std::string commandline;
};
struct Command
{
int ctype, cid;
};
uvGBufferGen uvgb;
alphaBufferGen abg;
BakeryHelper helper;
int globalFlags;
int uvgbGlobalFlags;
char* binPath;
char* scenePath;
wchar_t* scenePathW;
int binPathLength, scenePathLength;
char* errMsg;
char* tempBuff;
size_t tempBuffOffset;
char* origWorkDir;
FILE* f;
void* asyncProc;
ftLightmap* lightmaps;
size_t lmCount;
uint32_t vertexCount;
float* vpos;
float* vnorm;
float* vuv;
float* vuv2;
float* vuv2_packed;
float* vtangent;
uint32_t* indices;
uint32_t* sortedIndices;
uint16_t* triangleAlphaIDs;
size_t indexCount, opaqueIndexCount;
Mesh* meshes;
size_t meshCount;
void* colorMaps;
uint32_t colorMapCount;
TextureType colorMapType;
void* alphaMaps;
float* alphaRefs;
uint32_t alphaMapCount;
TextureType alphaMapType;
int tileSize;
int denoiserTileSize;
std::vector<ftCommand> ftCommands;
std::vector<h2vbCommand> h2vbCommands;
std::vector<exeCommand> exeCommands;
std::vector<Command> commands;
void SetError(const char* msg);
size_t AllocStr(char** dest, const char* src);
bool SetBakeryDir();
bool UnsetBakeryDir();
void TempStringStart();
void TempStringAdd(const char* str);
void TempStringAdd(int val);
void TempStringAdd(float val);
bool TempStringOverflow();
void FreeLightmapDefinitions();
bool WriteFileStart(const char* fname);
bool WriteFileEnd(const char* fname);
bool ValidateRefs();
bool SortIndices();
bool GeneratePackedUVs();
bool WriteSettings();
bool WriteLightmapDefinitions();
bool WriteUVGB();
bool WriteLMLOD();
bool WriteObjects();
bool WriteMeshes();
bool WriteLMIDs();
bool WriteSeamFix();
bool WriteSubMeshes();
bool WriteAlbedoIDs();
bool WriteEmissiveIDs();
bool WriteEmissiveMul();
bool WriteHeightmapIDs();
bool WriteAlphaIDs();
bool WriteVBFull();
bool WriteVBTrace();
bool WriteVBTraceTex();
bool WriteVBUV();
bool WriteIB();
bool WriteIB32();
bool WriteHeightmaps();
bool ExportAlphas();
bool ExportUVGBuffer();
bool ValidatePasses(int passes);
int ftraceCommand(void* data, size_t dataSize,
const char* renderMode, int LMID, const char* outputName, const char* name, int passes, int dilate,
float indirectWeight, float normalOffset = 0.0f, bool useNormalOffset = false, const char* directFilename = NULL);
LightmapOutput CombineOutputs(size_t count, void* outputs, const char* outputName, int albedoLMID,
float* weights, bool outputsAreNames);
LightmapOutput AddColorOutputsAndMultiplyByAlbedo(int albedoLMID, size_t count, LightmapOutput* outputIDs, float* weights = NULL,
const char* outputName = NULL);
LightmapOutput RenderGI(int LMID, GISettings& data, bool finalBounce, int passes = RenderPass::Color, int dilate = 16,
const char* outputName = NULL,
int contributingLMIDCount = 0,
int* contributingLMIDs = NULL);
bool RunProc(const char* p, bool setDir = true);
public:
// ===== Global setup =====
// Use RTX acceleration?
bool rtxMode;
Lightmapper();
~Lightmapper();
// Get last error message
const char* GetError();
// Get texture name for the output
const char* GetOutputName(LightmapOutput id);
// Call it first
bool Init(const char* binariesPath, const char* scenePath, int flags, void* d3d11device = NULL);
// Size of uninterrupted GPU raytrace jobs (optimal values are 512-1024)
bool SetTileSize(size_t size);
// Size of uninterrupted GPU denoising jobs (set to a high value, decrease if denoising fails)
bool SetDenoiserTileSize(size_t size);
// ===== Scene setup =====
// Set number of scene lightmaps
bool SetLightmapCount(size_t count);
// Set name and resolution (both width and height) for a lightmap
bool SetLightmapOptions(size_t id, const char* name, size_t size);
// Set scene vertex buffer
bool SetVertexCount(size_t count);
bool SetVertexPositions(float* data);
bool SetVertexNormals(float* data);
bool SetVertexLightmapUVs(float* data);
bool SetVertexTextureUVs(float* data);
bool SetVertexTangents(float* data);
// Set scene index buffer
bool SetIndices(size_t count, uint32_t* data);
// Set scene meshes
bool SetMeshes(size_t count, Mesh* data);
// Set scene textures
bool SetColorMaps(TextureType texType, size_t count, void** maps);
bool SetAlphaMaps(TextureType texType, size_t count, void** maps, float* alphaRefValues);
// Must be called after setting scene data and before any command functions
bool ExportScene();
// ===== Baking commands =====
// Clear the list of commands
void ClearCommands();
// Optimize sample positions generated by ExportScene()
// Can prevent light/shadow leaks
bool AdjustSamples(int LMID, float normalOffset = 0.0f, const char* outputName = NULL);
// Light baking commands
// LMID: lightmap id to render
// data: light settings
// passes: outputs to produce
// dilate = number of dilations (extending pixels into background)
// outputName = set specific name for a resulting lightmap
LightmapOutput RenderDirectionalLight(int LMID, DirectionalLight& data, int passes = RenderPass::Color, int dilate = 0,
const char* outputName = NULL);
LightmapOutput RenderSkyLight(int LMID, SkyLight& data, int passes = RenderPass::Color, int dilate = 0,
const char* outputName = NULL);
LightmapOutput RenderPointLight(int LMID, PointLight& data, int passes = RenderPass::Color, int dilate = 0,
const char* outputName = NULL);
// Load previously rendered lightmap
LightmapOutput LoadRendered(int LMID, const char* outputName, int passes = RenderPass::Color, float indirectIntensity = 1.0f);
// Add multiple weighted lightmaps into one
LightmapOutput AddColorOutputs(size_t count, LightmapOutput* outputIDs, float* weights = NULL,
const char* outputName = NULL);
// Render GI using all previously rendered/loaded lightmaps.
// bounces: number of light bounces
// gi: settings
// [outputs]: optional array to receive final illuminated outputs for every scene lightmap.
// array size must be the same as set in SetLightmapCount()
//
// [inputCount, inputs]: optional specific lightmap array to use during GI
// [outputCount, outputLMIDs]: optional array of specific lightmap IDs for which GI should be calculated.
// outputs array will then receive results for every specified lightmap ID.
bool RenderGI(uint32_t bounces, GISettings& gi, LightmapOutput* outputs = 0,
size_t inputCount = 0, LightmapOutput* inputs = 0,
size_t outputCount = 0, int* outputLMIDs = 0);
bool Denoise(LightmapOutput input, bool fixBrightEdges = false);
bool FixSeams(int LMID, LightmapOutput input);
bool ColorOutputToHDR(LightmapOutput input, const char* outputName = NULL);
bool ColorOutputToArray(LightmapOutput input, void* output, ColorOutputFormat format, const char* outputName = NULL);
bool ExecuteCommands();
bool ExecuteCommandsAsync();
Status GetBakingStatus();
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment