r3d_material.odin 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471
  1. /* r3d_material.odin -- R3D Material Module.
  2. *
  3. * Copyright (c) 2025-2026 Le Juez Victor
  4. *
  5. * This software is provided 'as-is', without any express or implied warranty.
  6. * For conditions of distribution and use, see accompanying LICENSE file.
  7. */
  8. package r3d
  9. import rl "vendor:raylib"
  10. when ODIN_OS == .Windows {
  11. foreign import lib {
  12. "windows/libr3d.a",
  13. "system:raylib",
  14. "system:assimp",
  15. }
  16. } else when ODIN_OS == .Linux {
  17. foreign import lib {
  18. "linux/libr3d.a",
  19. "system:raylib",
  20. "system:assimp",
  21. }
  22. } else when ODIN_OS == .Darwin {
  23. foreign import lib {
  24. "darwin/libr3d.a",
  25. "system:raylib",
  26. "system:assimp",
  27. }
  28. }
  29. /**
  30. * @brief Transparency modes.
  31. *
  32. * This enumeration defines how a material handles transparency during rendering.
  33. * It controls whether transparency is disabled, rendered using a depth pre-pass,
  34. * or rendered with standard alpha blending.
  35. */
  36. TransparencyMode :: enum u32 {
  37. DISABLED = 0, ///< No transparency, supports alpha cutoff.
  38. PREPASS = 1, ///< Supports transparency with shadows. Writes shadows for alpha > 0.1 and depth for alpha > 0.99.
  39. ALPHA = 2, ///< Standard transparency without shadows or depth writes.
  40. }
  41. /**
  42. * @brief Billboard modes.
  43. *
  44. * This enumeration defines how a 3D object aligns itself relative to the camera.
  45. * It provides options to disable billboarding or to enable specific modes of alignment.
  46. */
  47. BillboardMode :: enum u32 {
  48. DISABLED = 0, ///< Billboarding is disabled; the object retains its original orientation.
  49. FRONT = 1, ///< Full billboarding; the object fully faces the camera, rotating on all axes.
  50. Y_AXIS = 2, /**< Y-axis constrained billboarding; the object rotates only around the Y-axis,
  51. keeping its "up" orientation fixed. This is suitable for upright objects like characters or signs. */
  52. }
  53. /**
  54. * @brief Blend modes.
  55. *
  56. * Defines common blending modes used in 3D rendering to combine source and destination colors.
  57. * @note The blend mode is applied only if you are in forward rendering mode or auto-detect mode.
  58. */
  59. BlendMode :: enum u32 {
  60. MIX = 0, ///< Default mode: the result will be opaque or alpha blended depending on the transparency mode.
  61. ADDITIVE = 1, ///< Additive blending: source color is added to the destination, making bright effects.
  62. MULTIPLY = 2, ///< Multiply blending: source color is multiplied with the destination, darkening the image.
  63. PREMULTIPLIED_ALPHA = 3, ///< Premultiplied alpha blending: source color is blended with the destination assuming the source color is already multiplied by its alpha.
  64. }
  65. /**
  66. * @brief Comparison modes.
  67. *
  68. * Defines how fragments are tested against the depth/stencil buffer during rendering.
  69. * @note The depth/stencil comparison mode affects both forward and deferred rendering passes.
  70. */
  71. CompareMode :: enum u32 {
  72. LESS = 0, ///< Passes if 'value' < 'buffer' (default)
  73. LEQUAL = 1, ///< Passes if 'value' <= 'buffer'
  74. EQUAL = 2, ///< Passes if 'value' == 'buffer'
  75. GREATER = 3, ///< Passes if 'value' > 'buffer'
  76. GEQUAL = 4, ///< Passes if 'value' >= 'buffer'
  77. NOTEQUAL = 5, ///< Passes if 'value' != 'buffer'
  78. ALWAYS = 6, ///< Always passes
  79. NEVER = 7, ///< Never passes
  80. }
  81. /**
  82. * @brief Stencil buffer operations.
  83. *
  84. * Defines how the stencil buffer value is modified based on test results.
  85. */
  86. StencilOp :: enum u32 {
  87. KEEP = 0, ///< Keep the current stencil value
  88. ZERO = 1, ///< Set stencil value to 0
  89. REPLACE = 2, ///< Replace with reference value
  90. INCR = 3, ///< Increment stencil value (clamped)
  91. DECR = 4, ///< Decrement stencil value (clamped)
  92. }
  93. /**
  94. * @brief Face culling modes.
  95. *
  96. * Specifies which faces of a geometry are discarded during rendering based on their winding order.
  97. */
  98. CullMode :: enum u32 {
  99. NONE = 0, ///< No culling; all faces are rendered.
  100. BACK = 1, ///< Cull back-facing polygons (faces with clockwise winding order).
  101. FRONT = 2, ///< Cull front-facing polygons (faces with counter-clockwise winding order).
  102. }
  103. /**
  104. * @brief Albedo (base color) map.
  105. *
  106. * Provides the base color texture and a color multiplier.
  107. */
  108. AlbedoMap :: struct {
  109. texture: rl.Texture2D, ///< Base color texture (default: WHITE)
  110. color: rl.Color, ///< rl.Color multiplier (default: WHITE)
  111. }
  112. /**
  113. * @brief Emission map.
  114. *
  115. * Provides emission texture, color, and energy multiplier.
  116. */
  117. EmissionMap :: struct {
  118. texture: rl.Texture2D, ///< Emission texture (default: WHITE)
  119. color: rl.Color, ///< Emission color (default: WHITE)
  120. energy: f32, ///< Emission strength (default: 0.0f)
  121. }
  122. /**
  123. * @brief Normal map.
  124. *
  125. * Provides normal map texture and scale factor.
  126. */
  127. NormalMap :: struct {
  128. texture: rl.Texture2D, ///< Normal map texture (default: Front Facing)
  129. scale: f32, ///< Normal scale (default: 1.0f)
  130. }
  131. /**
  132. * @brief Combined Occlusion-Roughness-Metalness (ORM) map.
  133. *
  134. * Provides texture and individual multipliers for occlusion, roughness, and metalness.
  135. */
  136. OrmMap :: struct {
  137. texture: rl.Texture2D, ///< ORM texture (default: WHITE)
  138. occlusion: f32, ///< Occlusion multiplier (default: 1.0f)
  139. roughness: f32, ///< Roughness multiplier (default: 1.0f)
  140. metalness: f32, ///< Metalness multiplier (default: 0.0f)
  141. }
  142. /**
  143. * @brief Depth buffer state configuration.
  144. *
  145. * Controls how fragments interact with the depth buffer during rendering..
  146. *
  147. * @note This structure does not directly control depth buffer writes for technical reasons.
  148. * To render objects without writing to the depth buffer, use alpha blending mode instead.
  149. */
  150. DepthState :: struct {
  151. mode: CompareMode, ///< Comparison function for depth test (default: LESS)
  152. offsetFactor: f32, ///< Scales the maximum depth slope for polygon offset (default: 0.0f)
  153. offsetUnits: f32, ///< Constant depth offset value (default: 0.0f)
  154. rangeNear: f32, ///< Near clipping plane for depth range mapping (default: 0.0f)
  155. rangeFar: f32, ///< Far clipping plane for depth range mapping (default: 1.0f)
  156. }
  157. /**
  158. * @brief Stencil buffer state configuration.
  159. *
  160. * Controls how fragments interact with the stencil buffer during rendering.
  161. * The stencil buffer can be used for effects like x-ray vision, outlines,
  162. * portals, and masking.
  163. */
  164. StencilState :: struct {
  165. mode: CompareMode, ///< Comparison function for stencil test (default: ALWAYS)
  166. ref: u8, ///< Reference value (0-255) for comparison and replace operations (default: 0x00)
  167. mask: u8, ///< Bit mask applied to both reference and stencil values during comparison (default: 0xFF)
  168. opFail: StencilOp, ///< Operation when stencil test fails (default: KEEP)
  169. opZFail: StencilOp, ///< Operation when stencil test passes but depth test fails (default: KEEP)
  170. opPass: StencilOp, ///< Operation when both stencil and depth tests pass (default: REPLACE)
  171. }
  172. /**
  173. * @brief Material definition.
  174. *
  175. * Combines multiple texture maps and rendering parameters for shading.
  176. */
  177. Material :: struct {
  178. albedo: AlbedoMap, ///< Albedo map
  179. emission: EmissionMap, ///< Emission map
  180. normal: NormalMap, ///< Normal map
  181. orm: OrmMap, ///< Occlusion-Roughness-Metalness map
  182. uvOffset: rl.Vector2, ///< UV offset (default: {0.0f, 0.0f})
  183. uvScale: rl.Vector2, ///< UV scale (default: {1.0f, 1.0f})
  184. alphaCutoff: f32, ///< Alpha cutoff threshold (default: 0.01f)
  185. depth: DepthState, ///< Depth test configuration (default: standard)
  186. stencil: StencilState, ///< Stencil test configuration (default: disabled)
  187. transparencyMode: TransparencyMode, ///< Transparency mode (default: DISABLED)
  188. billboardMode: BillboardMode, ///< Billboard mode (default: DISABLED)
  189. blendMode: BlendMode, ///< Blend mode (default: MIX)
  190. cullMode: CullMode, ///< Face culling mode (default: BACK)
  191. unlit: bool, ///< If true, material does not participate in lighting (default: false)
  192. shader: ^SurfaceShader, ///< Custom shader applied to the material (default: NULL)
  193. }
  194. @(default_calling_convention="c", link_prefix="R3D_")
  195. foreign lib {
  196. /**
  197. * @brief Get the default material configuration.
  198. *
  199. * Returns `R3D_MATERIAL_BASE` by default,
  200. * or the material defined via `R3D_SetDefaultMaterial()`.
  201. *
  202. * @return Default material structure with standard properties.
  203. */
  204. GetDefaultMaterial :: proc() -> Material ---
  205. /**
  206. * @brief Set the default material configuration.
  207. *
  208. * Allows you to override the default material.
  209. * The default material will be used as the basis for loading 3D models.
  210. *
  211. * @param material Default material to define.
  212. */
  213. SetDefaultMaterial :: proc(material: Material) ---
  214. /**
  215. * @brief Load materials from a file.
  216. *
  217. * Parses a 3D model file and loads its associated materials.
  218. *
  219. * @param filePath Path to the 3D model file.
  220. * @param materialCount Pointer to an integer to store the number of loaded materials.
  221. * @return Pointer to an array of loaded R3D_Material, or NULL on failure.
  222. */
  223. LoadMaterials :: proc(filePath: cstring, materialCount: ^i32) -> ^Material ---
  224. /**
  225. * @brief Load materials from memory.
  226. *
  227. * Loads materials directly from a memory buffer containing 3D model data.
  228. *
  229. * @param data Pointer to the memory buffer containing the model data.
  230. * @param size Size of the data buffer in bytes.
  231. * @param hint Hint on the model format (can be NULL).
  232. * @param materialCount Pointer to an integer to store the number of loaded materials.
  233. * @return Pointer to an array of loaded R3D_Material, or NULL on failure.
  234. */
  235. LoadMaterialsFromMemory :: proc(data: rawptr, size: u32, hint: cstring, materialCount: ^i32) -> ^Material ---
  236. /**
  237. * @brief Load materials from an importer.
  238. *
  239. * Loads materials that were previously imported via an R3D_Importer instance.
  240. *
  241. * @param importer Pointer to a valid R3D_Importer.
  242. * @param materialCount Pointer to an integer to store the number of loaded materials.
  243. * @return Pointer to an array of loaded R3D_Material, or NULL on failure.
  244. */
  245. LoadMaterialsFromImporter :: proc(importer: ^Importer, materialCount: ^i32) -> ^Material ---
  246. /**
  247. * @brief Unload a material and its associated textures.
  248. *
  249. * Frees all memory associated with a material, including its textures.
  250. * This function will unload all textures that are not default textures.
  251. *
  252. * @warning Only call this function if you are certain that the textures
  253. * are not shared with other materials or objects, as this will permanently
  254. * free the texture data.
  255. *
  256. * @param material Pointer to the material structure to be unloaded.
  257. */
  258. UnloadMaterial :: proc(material: Material) ---
  259. /**
  260. * @brief Load an albedo (base color) map from file.
  261. *
  262. * Loads an image, uploads it as an sRGB texture (if enabled),
  263. * and applies the provided tint color.
  264. *
  265. * @param fileName Path to the texture file.
  266. * @param color Multiplicative tint applied in the shader.
  267. * @return Albedo map structure. Returns an empty map on failure.
  268. */
  269. LoadAlbedoMap :: proc(fileName: cstring, color: rl.Color) -> AlbedoMap ---
  270. /**
  271. * @brief Load an albedo (base color) map from memory.
  272. *
  273. * Same behavior as R3D_LoadAlbedoMap(), but reads from memory instead of disk.
  274. *
  275. * @param fileType rl.Image format hint (e.g. "png", "jpg").
  276. * @param fileData Pointer to image data.
  277. * @param dataSize Size of image data in bytes.
  278. * @param color Multiplicative tint applied in the shader.
  279. * @return Albedo map structure. Returns an empty map on failure.
  280. */
  281. LoadAlbedoMapFromMemory :: proc(fileType: cstring, fileData: rawptr, dataSize: i32, color: rl.Color) -> AlbedoMap ---
  282. /**
  283. * @brief Unload an albedo map texture.
  284. *
  285. * Frees the underlying texture unless it is a default texture.
  286. *
  287. * @param map Albedo map to unload.
  288. */
  289. UnloadAlbedoMap :: proc(_map: AlbedoMap) ---
  290. /**
  291. * @brief Load an emission map from file.
  292. *
  293. * Loads an emissive texture (sRGB if enabled) and sets color + energy.
  294. *
  295. * @param fileName Path to the texture file.
  296. * @param color Emission color.
  297. * @param energy Emission intensity multiplier.
  298. * @return Emission map. Returns an empty map on failure.
  299. */
  300. LoadEmissionMap :: proc(fileName: cstring, color: rl.Color, energy: f32) -> EmissionMap ---
  301. /**
  302. * @brief Load an emission map from memory.
  303. *
  304. * Same behavior as R3D_LoadEmissionMap(), but reads from memory.
  305. *
  306. * @param fileType rl.Image format hint.
  307. * @param fileData Pointer to image data.
  308. * @param dataSize Size of image data in bytes.
  309. * @param color Emission color.
  310. * @param energy Emission intensity multiplier.
  311. * @return Emission map. Returns an empty map on failure.
  312. */
  313. LoadEmissionMapFromMemory :: proc(fileType: cstring, fileData: rawptr, dataSize: i32, color: rl.Color, energy: f32) -> EmissionMap ---
  314. /**
  315. * @brief Unload an emission map texture.
  316. *
  317. * Frees the texture unless it is a default texture.
  318. *
  319. * @param map Emission map to unload.
  320. */
  321. UnloadEmissionMap :: proc(_map: EmissionMap) ---
  322. /**
  323. * @brief Load a normal map from file.
  324. *
  325. * Uploads the texture in linear space and stores the normal scale factor.
  326. *
  327. * @param fileName Path to the texture file.
  328. * @param scale Normal intensity multiplier.
  329. * @return Normal map. Returns an empty map on failure.
  330. */
  331. LoadNormalMap :: proc(fileName: cstring, scale: f32) -> NormalMap ---
  332. /**
  333. * @brief Load a normal map from memory.
  334. *
  335. * Same behavior as R3D_LoadNormalMap(), but reads from memory.
  336. *
  337. * @param fileType rl.Image format hint.
  338. * @param fileData Pointer to image data.
  339. * @param dataSize Size of image data in bytes.
  340. * @param scale Normal intensity multiplier.
  341. * @return Normal map. Returns an empty map on failure.
  342. */
  343. LoadNormalMapFromMemory :: proc(fileType: cstring, fileData: rawptr, dataSize: i32, scale: f32) -> NormalMap ---
  344. /**
  345. * @brief Unload a normal map texture.
  346. *
  347. * Frees the texture unless it is a default texture.
  348. *
  349. * @param map Normal map to unload.
  350. */
  351. UnloadNormalMap :: proc(_map: NormalMap) ---
  352. /**
  353. * @brief Load a combined ORM (Occlusion-Roughness-Metalness) map from file.
  354. *
  355. * Uploads the texture in linear space and applies the provided multipliers.
  356. *
  357. * @param fileName Path to the ORM texture.
  358. * @param occlusion Occlusion multiplier.
  359. * @param roughness Roughness multiplier.
  360. * @param metalness Metalness multiplier.
  361. * @return ORM map. Returns an empty map on failure.
  362. */
  363. LoadOrmMap :: proc(fileName: cstring, occlusion: f32, roughness: f32, metalness: f32) -> OrmMap ---
  364. /**
  365. * @brief Load a combined ORM (Occlusion-Roughness-Metalness) map from memory.
  366. *
  367. * Same behavior as R3D_LoadOrmMap(), but reads from memory.
  368. *
  369. * @param fileType rl.Image format hint.
  370. * @param fileData Pointer to image data.
  371. * @param dataSize Size of image data in bytes.
  372. * @param occlusion Occlusion multiplier.
  373. * @param roughness Roughness multiplier.
  374. * @param metalness Metalness multiplier.
  375. * @return ORM map. Returns an empty map on failure.
  376. */
  377. LoadOrmMapFromMemory :: proc(fileType: cstring, fileData: rawptr, dataSize: i32, occlusion: f32, roughness: f32, metalness: f32) -> OrmMap ---
  378. /**
  379. * @brief Unload an ORM map texture.
  380. *
  381. * Frees the texture unless it is a default texture.
  382. *
  383. * @param map ORM map to unload.
  384. */
  385. UnloadOrmMap :: proc(_map: OrmMap) ---
  386. }
  387. /**
  388. * @brief Default material configuration.
  389. *
  390. * Initializes an R3D_Material structure with sensible default values for all
  391. * rendering parameters. Use this as a starting point for custom configurations.
  392. */
  393. MATERIAL_BASE :: Material {
  394. albedo = {
  395. texture = {},
  396. color = {255, 255, 255, 255},
  397. },
  398. emission = {
  399. texture = {},
  400. color = {255, 255, 255, 255},
  401. energy = 0.0,
  402. },
  403. normal = {
  404. texture = {},
  405. scale = 1.0,
  406. },
  407. orm = {
  408. texture = {},
  409. occlusion = 1.0,
  410. roughness = 1.0,
  411. metalness = 0.0,
  412. },
  413. uvOffset = {0.0, 0.0},
  414. uvScale = {1.0, 1.0},
  415. alphaCutoff = 0.01,
  416. depth = {
  417. mode = .LESS,
  418. offsetFactor = 0.0,
  419. offsetUnits = 0.0,
  420. rangeNear = 0.0,
  421. rangeFar = 1.0,
  422. },
  423. stencil = {
  424. mode = .ALWAYS,
  425. ref = 0x00,
  426. mask = 0xFF,
  427. opFail = .KEEP,
  428. opZFail = .KEEP,
  429. opPass = .REPLACE,
  430. },
  431. transparencyMode = .DISABLED,
  432. billboardMode = .DISABLED,
  433. blendMode = .MIX,
  434. cullMode = .BACK,
  435. unlit = false,
  436. shader = nil,
  437. }