ADD: Normal mapping
This commit is contained in:
@@ -20,4 +20,8 @@
|
||||
|
||||
- Materials & sRGB
|
||||
- See `docs/asset_manager.md` for mesh/material creation and sRGB/UNORM handling.
|
||||
- Conventions:
|
||||
- Albedo/base color → sRGB
|
||||
- Metallic-Roughness → UNORM (G=roughness, B=metallic)
|
||||
- Normal map → UNORM (+Y green up)
|
||||
|
||||
|
||||
@@ -32,6 +32,11 @@
|
||||
- Third‑party deps
|
||||
- Vendored under `third_party/` and brought in via CMake. Do not edit headers directly; update through targets.
|
||||
|
||||
- Optional: MikkTSpace tangents
|
||||
- Enable at configure time: `-DENABLE_MIKKTS=ON` (default ON if found).
|
||||
- Requires `third_party/MikkTSpace/mikktspace.c` and `mikktspace.h` (provided).
|
||||
- Disable to use the built‑in Gram–Schmidt generator: `-DENABLE_MIKKTS=OFF`.
|
||||
|
||||
- Validation Layers
|
||||
- Enabled in Debug (`kUseValidationLayers = true` in `src/core/config.h`).
|
||||
- Disable by building Release or toggling the flag during local experimentation.
|
||||
|
||||
@@ -18,6 +18,12 @@
|
||||
- Name SPIR‑V files with full extension, e.g. `fullscreen.vert.spv`, `deferred_lighting.frag.spv`.
|
||||
- Use `EngineContext::getAssets()->shaderPath("<name>.spv")` when registering pipelines.
|
||||
- Use sRGB formats for albedo textures and UNORM for PBR control textures (see `docs/asset_manager.md`).
|
||||
- Material UBO layout (`GLTFMaterialData`):
|
||||
- `vec4 colorFactors;`
|
||||
- `vec4 metal_rough_factors; // x = metallic, y = roughness`
|
||||
- `vec4 extra[14]; // extra[0].x = normalScale`
|
||||
- Material texture bindings (set=1):
|
||||
- binding=1 `colorTex`, binding=2 `metalRoughTex`, binding=3 `normalMap`.
|
||||
|
||||
- Adding a pipeline (graphics)
|
||||
- Fill `GraphicsPipelineCreateInfo` with shader paths, descriptor set layouts, optional push constants, and a `configure(PipelineBuilder&)` callback to set topology, raster, depth/blend, and attachment formats.
|
||||
|
||||
@@ -24,3 +24,13 @@
|
||||
- Confirm the `.spv` file changed (timestamp) and click “Reload Changed” in the Pipelines window.
|
||||
- Ensure you are editing the correct files referenced by `shaderPath()`.
|
||||
|
||||
- GLSL error: `no such field in structure 'materialData': extra`
|
||||
- Ensure `shaders/input_structures.glsl` defines `vec4 extra[14];` inside `GLTFMaterialData` to match C++ `MaterialConstants`.
|
||||
|
||||
- Normals look inverted when using normal maps
|
||||
- The engine expects +Y (green up) tangent-space normals. Flip the green channel in your texture if needed.
|
||||
|
||||
- Tangent seams or artifacts
|
||||
- Build with MikkTSpace enabled: `-DENABLE_MIKKTS=ON`.
|
||||
- Check that your mesh has non-degenerate UVs.
|
||||
|
||||
|
||||
@@ -40,9 +40,11 @@ Use either the convenience descriptor (`MeshCreateInfo`) or the direct overload
|
||||
struct AssetManager::MaterialOptions {
|
||||
std::string albedoPath; // resolved through AssetManager
|
||||
std::string metalRoughPath; // resolved through AssetManager
|
||||
std::string normalPath; // resolved through AssetManager (tangent-space normal)
|
||||
bool albedoSRGB = true; // VK_FORMAT_R8G8B8A8_SRGB when true
|
||||
bool metalRoughSRGB = false; // VK_FORMAT_R8G8B8A8_UNORM when false
|
||||
GLTFMetallic_Roughness::MaterialConstants constants{};
|
||||
bool normalSRGB = false; // normal maps should be UNORM
|
||||
GLTFMetallic_Roughness::MaterialConstants constants{}; // extra[0].x as normalScale
|
||||
MaterialPass pass = MaterialPass::MainColor; // or Transparent
|
||||
};
|
||||
|
||||
@@ -113,7 +115,7 @@ ctx->scene->addMeshInstance("sphere.instance", sphere,
|
||||
glm::translate(glm::mat4(1.f), glm::vec3(2.f, 0.f, -2.f)));
|
||||
```
|
||||
|
||||
Textured primitive (albedo + metal-rough):
|
||||
Textured primitive (albedo + metal-rough + normal):
|
||||
|
||||
```c++
|
||||
AssetManager::MeshCreateInfo ti{};
|
||||
@@ -124,7 +126,9 @@ ti.geometry.vertices = std::span<Vertex>(v.data(), v.size());
|
||||
ti.geometry.indices = std::span<uint32_t>(i.data(), i.size());
|
||||
ti.material.kind = AssetManager::MeshMaterialDesc::Kind::Textured;
|
||||
ti.material.options.albedoPath = "textures/ground_albedo.png"; // sRGB
|
||||
ti.material.options.metalRoughPath = "textures/ground_mr.png"; // UNORM
|
||||
ti.material.options.metalRoughPath = "textures/ground_mr.png"; // UNORM, G=roughness, B=metallic
|
||||
ti.material.options.normalPath = "textures/ground_n.png"; // UNORM
|
||||
ti.material.options.constants.extra[0].x = 1.0f; // normalScale
|
||||
// ti.material.options.pass = MaterialPass::Transparent; // optional
|
||||
|
||||
auto texturedPlane = ctx->getAssets()->createMesh(ti);
|
||||
@@ -156,4 +160,5 @@ ctx->scene->removeGLTFInstance("chair01");
|
||||
- Reuse by name: `createMesh("name", ...)` returns the cached mesh if it already exists. Use a unique name or call `removeMesh(name)` to replace.
|
||||
- sRGB/UNORM: Albedo is sRGB by default, metal-rough is UNORM by default. Adjust via `MaterialOptions`.
|
||||
- Hot reload: Shaders are resolved via `shaderPath()`; pipeline hot reload is handled by the pipeline manager, not the AssetManager.
|
||||
- Normal maps: Not wired into the default GLTF PBR material in this branch. Adding them would require descriptor and shader updates.
|
||||
- Normal maps: Supported. If `normalPath` is empty, a flat normal is used.
|
||||
- Tangents: Loaded from glTF when present; otherwise generated. Enable MikkTSpace at configure time with `-DENABLE_MIKKTS=ON`.
|
||||
|
||||
43
docs/materials.md
Normal file
43
docs/materials.md
Normal file
@@ -0,0 +1,43 @@
|
||||
Materials and Textures Overview (PBR)
|
||||
|
||||
Current state (as of Nov 1, 2025)
|
||||
- PBR textures bound per material (set=1):
|
||||
- binding=0: GLTFMaterialData (UBO)
|
||||
- binding=1: `colorTex` (albedo/base color) — sRGB
|
||||
- binding=2: `metalRoughTex` (G=roughness, B=metallic) — UNORM
|
||||
- binding=3: `normalMap` (tangent-space normal, UNORM)
|
||||
- G‑Buffer writes world‑space normals. Tangent‑space normal maps are decoded with TBN using a sign‑correct bitangent (B = sign * cross(N, T)).
|
||||
- Numeric fallbacks via `MaterialConstants` (CPU) / `GLTFMaterialData` (GPU):
|
||||
- `colorFactors` (RGBA). Defaults to 1 if zero.
|
||||
- `metal_rough_factors` (X=metallic, Y=roughness). Roughness is clamped to ≥ 0.04 in shaders.
|
||||
- `extra[0].x` = `normalScale` (scalar, default 1.0). Multiplies the XY of decoded normal.
|
||||
- Defaults when a texture is missing:
|
||||
- Albedo → checkerboard error texture
|
||||
- MR → white (no effect)
|
||||
- Normal → 1×1 flat normal (0.5, 0.5, 1.0)
|
||||
|
||||
Implications for primitive meshes
|
||||
- Primitives can use:
|
||||
- Albedo + MR + Normal textures, or
|
||||
- Numeric factors only, or
|
||||
- Any mix (missing textures fall back to defaults).
|
||||
|
||||
Texture conventions
|
||||
- Albedo/base color: sRGB.
|
||||
- Metallic-Roughness: UNORM; channels: G=roughness, B=metallic.
|
||||
- Normal map: UNORM; expected +Y (green up). If your maps look inverted, flip the green channel offline.
|
||||
|
||||
Notes on tangent space
|
||||
- Tangents are loaded from glTF when present (`TANGENT` attribute, vec4 where w is handedness).
|
||||
- If missing, the engine generates tangents:
|
||||
- Default: robust Gram–Schmidt with handedness.
|
||||
- Preferred: MikkTSpace (enabled by CMake option `ENABLE_MIKKTS=ON`).
|
||||
|
||||
Notes on MikkTSpace
|
||||
- Recommended for parity with content tools. Enable at configure time: `-DENABLE_MIKKTS=ON`.
|
||||
- Falls back automatically to the internal generator if disabled or if MikkTS fails.
|
||||
|
||||
Usage Examples
|
||||
- Adjust normal strength per material: set `material.constants.extra[0].x` (CPU) or `normalTexture.scale` in glTF.
|
||||
- Primitive with PBR textures:
|
||||
- Set `MeshMaterialDesc::Kind::Textured` and fill `albedoPath`, `metalRoughPath`, and `normalPath`.
|
||||
Reference in New Issue
Block a user