Rendering Optimization
ΠΡΠ½ΠΎΠ²Π½ΡΠ΅ ΡΠ΅Ρ Π½ΠΈΠΊΠΈ ΠΎΠΏΡΠΈΠΌΠΈΠ·Π°ΡΠΈΠΈ
ΠΡΡΠ΅ΡΠ΅Π½ΠΈΠ΅ Π½Π΅Π²ΠΈΠ΄ΠΈΠΌΡΡ ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ² (Culling)
Wudgine ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅Ρ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΠΌΠ΅ΡΠΎΠ΄ΠΎΠ² ΠΎΡΡΠ΅ΡΠ΅Π½ΠΈΡ Π΄Π»Ρ ΡΠΌΠ΅Π½ΡΡΠ΅Π½ΠΈΡ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²Π° ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ², ΠΎΡΠΏΡΠ°Π²Π»ΡΠ΅ΠΌΡΡ Π½Π° ΡΠ΅Π½Π΄Π΅ΡΠΈΠ½Π³:
Frustum Culling
ΠΡΡΠ΅ΡΠ΅Π½ΠΈΠ΅ ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ², Π½Π°Ρ ΠΎΠ΄ΡΡΠΈΡ ΡΡ Π·Π° ΠΏΡΠ΅Π΄Π΅Π»Π°ΠΌΠΈ Π²ΠΈΠ΄ΠΈΠΌΠΎΠΉ ΠΎΠ±Π»Π°ΡΡΠΈ ΠΊΠ°ΠΌΠ΅ΡΡ.
Occlusion Culling
ΠΡΡΠ΅ΡΠ΅Π½ΠΈΠ΅ ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ², Π·Π°ΠΊΡΡΡΡΡ Π΄ΡΡΠ³ΠΈΠΌΠΈ ΠΎΠ±ΡΠ΅ΠΊΡΠ°ΠΌΠΈ.
Portal Culling
ΠΠΏΡΠΈΠΌΠΈΠ·Π°ΡΠΈΡ Π΄Π»Ρ ΡΡΠ΅Π½ Ρ ΠΊΠΎΠΌΠ½Π°ΡΠ°ΠΌΠΈ ΠΈ ΠΏΠΎΡΡΠ°Π»Π°ΠΌΠΈ.
Detail Culling
ΠΡΡΠ΅ΡΠ΅Π½ΠΈΠ΅ ΠΌΠ΅Π»ΠΊΠΈΡ Π΄Π΅ΡΠ°Π»Π΅ΠΉ Π½Π° Π±ΠΎΠ»ΡΡΠΎΠΌ ΡΠ°ΡΡΡΠΎΡΠ½ΠΈΠΈ.
// ΠΠ°ΡΡΡΠΎΠΉΠΊΠ° Frustum Culling
auto& renderer = engine.getRenderer();
renderer.enableFrustumCulling(true);
// ΠΠ°ΡΡΡΠΎΠΉΠΊΠ° Occlusion Culling
renderer.enableOcclusionCulling(true);
renderer.setOcclusionCullingPrecision(OcclusionPrecision::Medium);
// ΠΠ°ΡΡΡΠΎΠΉΠΊΠ° Detail Culling
renderer.setDetailCullingDistance(100.0f);
renderer.setDetailCullingSize(0.01f);
Π£ΡΠΎΠ²Π½ΠΈ Π΄Π΅ΡΠ°Π»ΠΈΠ·Π°ΡΠΈΠΈ (LOD)
Π‘ΠΈΡΡΠ΅ΠΌΠ° LOD Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΈ ΡΠ½ΠΈΠΆΠ°Π΅Ρ Π΄Π΅ΡΠ°Π»ΠΈΠ·Π°ΡΠΈΡ ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ² Π½Π° Π±ΠΎΠ»ΡΡΠΎΠΌ ΡΠ°ΡΡΡΠΎΡΠ½ΠΈΠΈ:
// Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ LOD Π΄Π»Ρ ΠΌΠΎΠ΄Π΅Π»ΠΈ
auto& lodGroup = entity.addComponent<LODGroupComponent>();
lodGroup.addLOD(0, "assets/models/character/character_high.mesh", 0.0f);
lodGroup.addLOD(1, "assets/models/character/character_medium.mesh", 10.0f);
lodGroup.addLOD(2, "assets/models/character/character_low.mesh", 30.0f);
lodGroup.addLOD(3, "assets/models/character/character_very_low.mesh", 60.0f);
lodGroup.setCrossFadeEnabled(true);
lodGroup.setCrossFadeDuration(0.5f);
ΠΠ½ΡΡΠ°Π½ΡΠΈΠ½Π³
ΠΠ½ΡΡΠ°Π½ΡΠΈΠ½Π³ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ ΡΡΡΠ΅ΠΊΡΠΈΠ²Π½ΠΎ ΡΠ΅Π½Π΄Π΅ΡΠΈΡΡ ΠΌΠ½ΠΎΠΆΠ΅ΡΡΠ²ΠΎ ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²ΡΡ ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ²:
// Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΠΈΠ½ΡΡΠ°Π½ΡΠΈΡΠΎΠ²Π°Π½Π½ΠΎΠ³ΠΎ ΡΠ΅Π½Π΄Π΅ΡΠ΅ΡΠ°
auto& instanceRenderer = entity.addComponent<InstancedMeshRendererComponent>();
instanceRenderer.setMesh("assets/models/grass/grass_blade.mesh");
instanceRenderer.setMaterial("assets/materials/grass.mat");
// ΠΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ ΠΈΠ½ΡΡΠ°Π½ΡΠΎΠ²
for (int i = 0; i < 1000; ++i) {
Transform transform;
transform.position = Vector3(Random::range(-50.0f, 50.0f), 0.0f, Random::range(-50.0f, 50.0f));
transform.rotation = Quaternion::fromEuler(0.0f, Random::range(0.0f, 360.0f), 0.0f);
transform.scale = Vector3(1.0f, Random::range(0.8f, 1.2f), 1.0f);
instanceRenderer.addInstance(transform);
}
ΠΠ°ΡΡΠΈΠ½Π³
ΠΠ°ΡΡΠΈΠ½Π³ ΠΎΠ±ΡΠ΅Π΄ΠΈΠ½ΡΠ΅Ρ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ² Π² ΠΎΠ΄ΠΈΠ½ Π΄Π»Ρ ΡΠΌΠ΅Π½ΡΡΠ΅Π½ΠΈΡ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²Π° Π²ΡΠ·ΠΎΠ²ΠΎΠ² ΠΎΡΡΠΈΡΠΎΠ²ΠΊΠΈ:
- Static Batching Π΄Π»Ρ Π½Π΅ΠΏΠΎΠ΄Π²ΠΈΠΆΠ½ΡΡ ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ²
- Dynamic Batching Π΄Π»Ρ Π΄Π²ΠΈΠΆΡΡΠΈΡ ΡΡ ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ² Ρ ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²ΡΠΌΠΈ ΠΌΠ°ΡΠ΅ΡΠΈΠ°Π»Π°ΠΌΠΈ
- GPU Instancing Π΄Π»Ρ ΠΌΠ½ΠΎΠΆΠ΅ΡΡΠ²Π° ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²ΡΡ ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ²
// ΠΠ°ΡΡΡΠΎΠΉΠΊΠ° Static Batching
auto& renderer = engine.getRenderer();
renderer.enableStaticBatching(true);
renderer.setStaticBatchingThreshold(100); // ΠΠΈΠ½ΠΈΠΌΠ°Π»ΡΠ½ΠΎΠ΅ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ Π²Π΅ΡΡΠΈΠ½ Π΄Π»Ρ Π±Π°ΡΡΠΈΠ½Π³Π°
// ΠΠΎΠΌΠ΅ΡΠΊΠ° ΠΎΠ±ΡΠ΅ΠΊΡΠ° ΠΊΠ°ΠΊ ΡΡΠ°ΡΠΈΡΠ΅ΡΠΊΠΎΠ³ΠΎ Π΄Π»Ρ Π±Π°ΡΡΠΈΠ½Π³Π°
auto& meshRenderer = entity.getComponent<MeshRendererComponent>();
meshRenderer.setStaticBatching(true);
ΠΠΏΡΠΈΠΌΠΈΠ·Π°ΡΠΈΡ Π³ΡΠ°ΡΠΈΡΠ΅ΡΠΊΠΎΠ³ΠΎ ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅ΡΠ°
ΠΠ½ΠΎΠ³ΠΎΠΏΠΎΡΠΎΡΠ½Π°Ρ ΠΏΠΎΠ΄Π³ΠΎΡΠΎΠ²ΠΊΠ° ΠΊΠΎΠΌΠ°Π½Π΄
Wudgine ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅Ρ ΠΌΠ½ΠΎΠ³ΠΎΠΏΠΎΡΠΎΡΠ½ΠΎΡΡΡ Π΄Π»Ρ ΠΏΠΎΠ΄Π³ΠΎΡΠΎΠ²ΠΊΠΈ ΠΊΠΎΠΌΠ°Π½Π΄ ΡΠ΅Π½Π΄Π΅ΡΠΈΠ½Π³Π°:
// ΠΠ°ΡΡΡΠΎΠΉΠΊΠ° ΠΌΠ½ΠΎΠ³ΠΎΠΏΠΎΡΠΎΡΠ½ΠΎΠΉ ΠΏΠΎΠ΄Π³ΠΎΡΠΎΠ²ΠΊΠΈ ΠΊΠΎΠΌΠ°Π½Π΄
auto& renderer = engine.getRenderer();
renderer.enableMultithreadedRendering(true);
renderer.setRenderThreadCount(4); // ΠΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ ΠΏΠΎΡΠΎΠΊΠΎΠ² Π΄Π»Ρ ΡΠ΅Π½Π΄Π΅ΡΠΈΠ½Π³Π°
ΠΡΠΈΠ½Ρ ΡΠΎΠ½Π½ΡΠ΅ Π²ΡΡΠΈΡΠ»Π΅Π½ΠΈΡ
ΠΡΠΈΠ½Ρ ΡΠΎΠ½Π½ΡΠ΅ Π²ΡΡΠΈΡΠ»Π΅Π½ΠΈΡ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡΡ Π²ΡΠΏΠΎΠ»Π½ΡΡΡ Π½Π΅ΠΊΠΎΡΠΎΡΡΠ΅ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΈ ΠΏΠ°ΡΠ°Π»Π»Π΅Π»ΡΠ½ΠΎ Ρ ΠΎΡΠ½ΠΎΠ²Π½ΡΠΌ ΡΠ΅Π½Π΄Π΅ΡΠΈΠ½Π³ΠΎΠΌ:
// ΠΠ°ΡΡΡΠΎΠΉΠΊΠ° Π°ΡΠΈΠ½Ρ
ΡΠΎΠ½Π½ΡΡ
Π²ΡΡΠΈΡΠ»Π΅Π½ΠΈΠΉ
auto& renderer = engine.getRenderer();
renderer.enableAsyncCompute(true);
renderer.setAsyncComputeQueues({
AsyncComputeQueue::Physics,
AsyncComputeQueue::ParticleSimulation,
AsyncComputeQueue::OcclusionCulling
});
ΠΠΏΡΠΈΠΌΠΈΠ·Π°ΡΠΈΡ ΡΠ΅ΠΉΠ΄Π΅ΡΠΎΠ²
// ΠΠΏΡΠΈΠΌΠΈΠ·ΠΈΡΠΎΠ²Π°Π½Π½ΡΠΉ ΡΡΠ°Π³ΠΌΠ΅Π½ΡΠ½ΡΠΉ ΡΠ΅ΠΉΠ΄Π΅Ρ
void main() {
// ΠΡΠ΅Π΄Π²Π°ΡΠΈΡΠ΅Π»ΡΠ½ΡΠ΅ Π²ΡΡΠΈΡΠ»Π΅Π½ΠΈΡ
vec3 viewDir = normalize(camera.position - inWorldPos);
float NdotV = max(dot(normal, viewDir), 0.0);
// ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΏΡΠ΅Π΄Π²Π°ΡΠΈΡΠ΅Π»ΡΠ½ΠΎ Π²ΡΡΠΈΡΠ»Π΅Π½Π½ΡΡ
Π·Π½Π°ΡΠ΅Π½ΠΈΠΉ
vec3 F0 = mix(vec3(0.04), albedo, metallic);
vec3 F = fresnelSchlick(NdotV, F0);
// ΠΠ·Π±Π΅Π³Π°Π½ΠΈΠ΅ Π²Π΅ΡΠ²Π»Π΅Π½ΠΈΠΉ
float roughnessFactor = mix(roughness, 1.0, step(roughness, 0.01));
}
// ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ ΡΠ΅ΠΊΡΡΡΡΠ½ΡΡ
ΠΌΠ°ΡΡΠΈΠ²ΠΎΠ²
layout(set = 2, binding = 0) uniform sampler2DArray materialTextures;
void main() {
// ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΡΠ΅ΠΌΠΏΠ»Π΅ΡΠ° Π΄Π»Ρ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΈΡ
ΡΠ΅ΠΊΡΡΡΡ
vec3 albedo = texture(materialTextures, vec3(inTexCoord, 0)).rgb;
vec3 normal = texture(materialTextures, vec3(inTexCoord, 1)).rgb * 2.0 - 1.0;
float metallic = texture(materialTextures, vec3(inTexCoord, 2)).r;
float roughness = texture(materialTextures, vec3(inTexCoord, 3)).r;
}
ΠΠΏΡΠΈΠΌΠΈΠ·Π°ΡΠΈΡ ΡΠ΅ΡΡΡΡΠΎΠ²
Π£ΠΏΡΠ°Π²Π»Π΅Π½ΠΈΠ΅ ΡΠ΅ΠΊΡΡΡΡΠ°ΠΌΠΈ
- Π’Π΅ΠΊΡΡΡΡΠ½ΡΠ΅ Π°ΡΠ»Π°ΡΡ Π΄Π»Ρ ΡΠΌΠ΅Π½ΡΡΠ΅Π½ΠΈΡ ΠΏΠ΅ΡΠ΅ΠΊΠ»ΡΡΠ΅Π½ΠΈΠΉ ΡΠ΅ΠΊΡΡΡΡ
- Π‘ΠΆΠ°ΡΠΈΠ΅ ΡΠ΅ΠΊΡΡΡΡ (BC7, ASTC) Π΄Π»Ρ ΡΠΌΠ΅Π½ΡΡΠ΅Π½ΠΈΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ ΠΏΠ°ΠΌΡΡΠΈ
- ΠΠΈΠΏΠΌΠ°ΠΏΠΏΠΈΠ½Π³ Π΄Π»Ρ ΠΎΠΏΡΠΈΠΌΠΈΠ·Π°ΡΠΈΠΈ Π½Π° ΡΠ°Π·Π½ΡΡ ΡΠ°ΡΡΡΠΎΡΠ½ΠΈΡΡ
- ΠΠΎΡΠΎΠΊΠΎΠ²Π°Ρ Π·Π°Π³ΡΡΠ·ΠΊΠ° ΡΠ΅ΠΊΡΡΡΡ Π΄Π»Ρ Π±ΠΎΠ»ΡΡΠΈΡ ΠΎΡΠΊΡΡΡΡΡ ΠΌΠΈΡΠΎΠ²
// Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΡΠ΅ΠΊΡΡΡΡΠ½ΠΎΠ³ΠΎ Π°ΡΠ»Π°ΡΠ°
TextureAtlas atlas = TextureAtlas::create(2048, 2048);
atlas.addTexture("grass", "assets/textures/terrain/grass.png");
atlas.addTexture("dirt", "assets/textures/terrain/dirt.png");
atlas.addTexture("rock", "assets/textures/terrain/rock.png");
atlas.addTexture("sand", "assets/textures/terrain/sand.png");
atlas.build();
// ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ ΡΠ΅ΠΊΡΡΡΡΠ½ΠΎΠ³ΠΎ Π°ΡΠ»Π°ΡΠ°
auto& material = entity.getComponent<MeshRendererComponent>().getMaterial();
material.setTextureAtlas("albedo", atlas);
material.setTextureRegion("albedo", "grass");
Π£ΠΏΡΠ°Π²Π»Π΅Π½ΠΈΠ΅ ΠΌΠ΅ΡΠ°ΠΌΠΈ
ΠΠΏΡΠΈΠΌΠΈΠ·Π°ΡΠΈΡ ΠΌΠ΅Ρ-Π΄Π°Π½Π½ΡΡ Π΄Π»Ρ ΡΠ»ΡΡΡΠ΅Π½ΠΈΡ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΠ΅Π»ΡΠ½ΠΎΡΡΠΈ:
- ΠΠΏΡΠΈΠΌΠΈΠ·Π°ΡΠΈΡ ΡΠΎΠΏΠΎΠ»ΠΎΠ³ΠΈΠΈ Π΄Π»Ρ ΡΠΌΠ΅Π½ΡΡΠ΅Π½ΠΈΡ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²Π° Π²Π΅ΡΡΠΈΠ½ ΠΈ ΡΡΠ΅ΡΠ³ΠΎΠ»ΡΠ½ΠΈΠΊΠΎΠ²
- ΠΡΠ΅Π΄Π²Π°ΡΠΈΡΠ΅Π»ΡΠ½ΠΎΠ΅ Π²ΡΡΠΈΡΠ»Π΅Π½ΠΈΠ΅ ΡΠ°Π½Π³Π΅Π½ΡΠΎΠ² ΠΈ Π±ΠΈΠ½ΠΎΡΠΌΠ°Π»Π΅ΠΉ
- Π‘ΠΆΠ°ΡΠΈΠ΅ Π²Π΅ΡΡΠΈΠ½Π½ΡΡ Π΄Π°Π½Π½ΡΡ
- Π£ΡΠΎΠ²Π½ΠΈ Π΄Π΅ΡΠ°Π»ΠΈΠ·Π°ΡΠΈΠΈ (LOD)
// ΠΠΏΡΠΈΠΌΠΈΠ·Π°ΡΠΈΡ ΠΌΠ΅ΡΠ°
Mesh mesh = Mesh::load("assets/models/character/character.mesh");
mesh.optimize();
mesh.generateLODs(4); // ΠΠ΅Π½Π΅ΡΠ°ΡΠΈΡ 4 ΡΡΠΎΠ²Π½Π΅ΠΉ LOD
mesh.compressVertexData();
mesh.save("assets/models/character/character_optimized.mesh");
ΠΡΠΎΡΠΈΠ»ΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ ΠΈ ΠΎΡΠ»Π°Π΄ΠΊΠ°
ΠΠ½ΡΡΡΡΠΌΠ΅Π½ΡΡ ΠΏΡΠΎΡΠΈΠ»ΠΈΡΠΎΠ²Π°Π½ΠΈΡ
Wudgine ΠΏΡΠ΅Π΄ΠΎΡΡΠ°Π²Π»ΡΠ΅Ρ Π²ΡΡΡΠΎΠ΅Π½Π½ΡΠ΅ ΠΈΠ½ΡΡΡΡΠΌΠ΅Π½ΡΡ Π΄Π»Ρ ΠΏΡΠΎΡΠΈΠ»ΠΈΡΠΎΠ²Π°Π½ΠΈΡ ΡΠ΅Π½Π΄Π΅ΡΠΈΠ½Π³Π°:
// ΠΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅ ΠΏΡΠΎΡΠΈΠ»ΠΈΡΠΎΠ²Π°Π½ΠΈΡ ΡΠ΅Π½Π΄Π΅ΡΠΈΠ½Π³Π°
auto& profiler = engine.getProfiler();
profiler.enableRendererProfiling(true);
// ΠΠΎΠ»ΡΡΠ΅Π½ΠΈΠ΅ ΡΡΠ°ΡΠΈΡΡΠΈΠΊΠΈ ΡΠ΅Π½Π΄Π΅ΡΠΈΠ½Π³Π°
auto stats = profiler.getRendererStats();
Debug::log("Draw calls: {}", stats.drawCalls);
Debug::log("Triangles: {}", stats.triangles);
Debug::log("Vertices: {}", stats.vertices);
Debug::log("Render time: {} ms", stats.renderTimeMs);
ΠΠΈΠ·ΡΠ°Π»ΠΈΠ·Π°ΡΠΈΡ ΠΎΡΠ»Π°Π΄ΠΊΠΈ
// ΠΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅ Π²ΠΈΠ·ΡΠ°Π»ΠΈΠ·Π°ΡΠΈΠΈ ΠΎΡΠ»Π°Π΄ΠΊΠΈ
auto& debugRenderer = engine.getDebugRenderer();
debugRenderer.enableFrustumVisualization(true);
debugRenderer.enableOcclusionCullingVisualization(true);
debugRenderer.enableLODVisualization(true);
ΠΠΏΡΠΈΠΌΠΈΠ·Π°ΡΠΈΡ Π΄Π»Ρ ΡΠ°Π·Π½ΡΡ ΠΏΠ»Π°ΡΡΠΎΡΠΌ
ΠΠΎΠ±ΠΈΠ»ΡΠ½ΡΠ΅ ΡΡΡΡΠΎΠΉΡΡΠ²Π°
Π Π΅ΠΊΠΎΠΌΠ΅Π½Π΄Π°ΡΠΈΠΈ Π΄Π»Ρ ΠΎΠΏΡΠΈΠΌΠΈΠ·Π°ΡΠΈΠΈ Π½Π° ΠΌΠΎΠ±ΠΈΠ»ΡΠ½ΡΡ ΡΡΡΡΠΎΠΉΡΡΠ²Π°Ρ :
- Π£ΠΌΠ΅Π½ΡΡΠ΅Π½ΠΈΠ΅ ΡΠ°Π·ΡΠ΅ΡΠ΅Π½ΠΈΡ ΡΠ΅Π½Π΄Π΅ΡΠΈΠ½Π³Π°
- ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΎΠ±Π»Π΅Π³ΡΠ΅Π½Π½ΡΡ ΡΠ΅ΠΉΠ΄Π΅ΡΠΎΠ²
- ΠΠ³ΡΠ΅ΡΡΠΈΠ²Π½ΠΎΠ΅ ΠΎΡΡΠ΅ΡΠ΅Π½ΠΈΠ΅ ΠΈ LOD
- ΠΠΏΡΠΈΠΌΠΈΠ·Π°ΡΠΈΡ Π΄Π»Ρ ΡΠ°ΠΉΠ»ΠΎΠ²ΡΡ ΡΠ΅Π½Π΄Π΅ΡΠ΅ΡΠΎΠ²
- Π£ΠΌΠ΅Π½ΡΡΠ΅Π½ΠΈΠ΅ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²Π° ΠΏΡΠΎΠ·ΡΠ°ΡΠ½ΡΡ ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ²
// ΠΠ°ΡΡΡΠΎΠΉΠΊΠ° Π΄Π»Ρ ΠΌΠΎΠ±ΠΈΠ»ΡΠ½ΡΡ
ΡΡΡΡΠΎΠΉΡΡΠ²
if (Platform::isMobile()) {
auto& renderer = engine.getRenderer();
renderer.setRenderScale(0.75f); // Π Π΅Π½Π΄Π΅ΡΠΈΠ½Π³ Π² 75% ΠΎΡ ΡΠ°Π·ΡΠ΅ΡΠ΅Π½ΠΈΡ ΡΠΊΡΠ°Π½Π°
renderer.setShaderQuality(ShaderQuality::Low);
renderer.setLODBias(2.0f); // ΠΠΎΠ»Π΅Π΅ Π°Π³ΡΠ΅ΡΡΠΈΠ²Π½ΠΎΠ΅ ΠΏΠ΅ΡΠ΅ΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅ LOD
renderer.setMaxLights(4);
renderer.disableEffect(PostProcessEffectType::SSAO);
renderer.disableEffect(PostProcessEffectType::DepthOfField);
}
ΠΠΎΠ½ΡΠΎΠ»ΠΈ
ΠΠΏΡΠΈΠΌΠΈΠ·Π°ΡΠΈΡ Π΄Π»Ρ ΠΈΠ³ΡΠΎΠ²ΡΡ ΠΊΠΎΠ½ΡΠΎΠ»Π΅ΠΉ:
// ΠΠ°ΡΡΡΠΎΠΉΠΊΠ° Π΄Π»Ρ ΠΊΠΎΠ½ΡΠΎΠ»Π΅ΠΉ
if (Platform::isConsole()) {
auto& renderer = engine.getRenderer();
if (Platform::getConsoleType() == ConsoleType::HighEnd) {
// ΠΠ°ΡΡΡΠΎΠΉΠΊΠΈ Π΄Π»Ρ Π²ΡΡΠΎΠΊΠΎΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΠ΅Π»ΡΠ½ΡΡ
ΠΊΠΎΠ½ΡΠΎΠ»Π΅ΠΉ
renderer.setRenderResolution(RenderResolution::UHD);
renderer.enableRayTracedShadows(true);
renderer.enableRayTracedAmbientOcclusion(true);
} else {
// ΠΠ°ΡΡΡΠΎΠΉΠΊΠΈ Π΄Π»Ρ ΠΊΠΎΠ½ΡΠΎΠ»Π΅ΠΉ ΡΡΠ΅Π΄Π½Π΅Π³ΠΎ ΡΡΠΎΠ²Π½Ρ
renderer.setRenderResolution(RenderResolution::FullHD);
renderer.setTargetFrameRate(60);
}
// ΠΠΏΡΠΈΠΌΠΈΠ·Π°ΡΠΈΡ Π΄Π»Ρ ΡΠ½ΠΈΡΠΈΡΠΈΡΠΎΠ²Π°Π½Π½ΠΎΠΉ ΠΏΠ°ΠΌΡΡΠΈ
renderer.enableUnifiedMemoryOptimizations(true);
}
Π‘Π»Π΅Π΄ΡΡΡΠΈΠ΅ ΡΠ°Π³ΠΈ
Π’Π΅ΠΏΠ΅ΡΡ, ΠΊΠΎΠ³Π΄Π° Π²Ρ ΠΎΠ·Π½Π°ΠΊΠΎΠΌΠΈΠ»ΠΈΡΡ Ρ ΠΌΠ΅ΡΠΎΠ΄Π°ΠΌΠΈ ΠΎΠΏΡΠΈΠΌΠΈΠ·Π°ΡΠΈΠΈ ΡΠ΅Π½Π΄Π΅ΡΠΈΠ½Π³Π° Π² Wudgine, ΡΠ΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡΠ΅ΠΌ: