Documentation

Materials Shaders

Π’ этом Ρ€Π°Π·Π΄Π΅Π»Π΅ описываСтся систСма ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»ΠΎΠ² ΠΈ ΡˆΠ΅ΠΉΠ΄Π΅Ρ€ΠΎΠ² Wudgine.

БистСма ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»ΠΎΠ²

ΠœΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»Ρ‹ Π² Wudgine ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΡŽΡ‚ Π²ΠΈΠ·ΡƒΠ°Π»ΡŒΠ½Ρ‹Π΅ свойства повСрхностСй ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ². БистСма ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»ΠΎΠ² тСсно ΠΈΠ½Ρ‚Π΅Π³Ρ€ΠΈΡ€ΠΎΠ²Π°Π½Π° с физичСски ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½Ρ‹ΠΌ Ρ€Π΅Π½Π΄Π΅Ρ€ΠΈΠ½Π³ΠΎΠΌ (PBR).

ΠžΡΠ½ΠΎΠ²Π½Ρ‹Π΅ свойства ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»ΠΎΠ²

// ΠŸΡ€ΠΈΠΌΠ΅Ρ€ создания ΠΈ настройки ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»Π°
Material material = Material::create("MyMaterial");

// Π‘Π°Π·ΠΎΠ²Ρ‹Π΅ тСкстуры PBR
material.setTexture(TextureType::Albedo, "assets/textures/metal/albedo.png");
material.setTexture(TextureType::Normal, "assets/textures/metal/normal.png");
material.setTexture(TextureType::Metallic, "assets/textures/metal/metallic.png");
material.setTexture(TextureType::Roughness, "assets/textures/metal/roughness.png");
material.setTexture(TextureType::AmbientOcclusion, "assets/textures/metal/ao.png");
material.setTexture(TextureType::Emissive, "assets/textures/metal/emissive.png");

// ΠŸΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹ ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»Π°
material.setParameter("albedoFactor", Vector3(1.0f, 1.0f, 1.0f));
material.setParameter("metallicFactor", 1.0f);
material.setParameter("roughnessFactor", 0.5f);
material.setParameter("emissiveIntensity", 2.0f);

Π Π΅Π΄Π°ΠΊΡ‚ΠΎΡ€ ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»ΠΎΠ²

Π Π΅Π΄Π°ΠΊΡ‚ΠΎΡ€ ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»ΠΎΠ² позволяСт Π½Π°ΡΡ‚Ρ€Π°ΠΈΠ²Π°Ρ‚ΡŒ свойства ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»ΠΎΠ² Π²ΠΈΠ·ΡƒΠ°Π»ΡŒΠ½ΠΎ:

  • ΠŸΡ€Π΅Π΄ΠΏΡ€ΠΎΡΠΌΠΎΡ‚Ρ€ ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»Π° Π² Ρ€Π΅Π°Π»ΡŒΠ½ΠΎΠΌ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ
  • Настройка тСкстур ΠΈ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ²
  • Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ слоТных ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»ΠΎΠ² с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Π½ΠΎΠ΄ΠΎΠ²ΠΎΠ³ΠΎ Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΎΡ€Π°
  • Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° Π³ΠΎΡ‚ΠΎΠ²Ρ‹Ρ… ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»ΠΎΠ²

БистСма ΡˆΠ΅ΠΉΠ΄Π΅Ρ€ΠΎΠ²

Wudgine ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ ΡΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ систСму ΡˆΠ΅ΠΉΠ΄Π΅Ρ€ΠΎΠ², ΠΎΡΠ½ΠΎΠ²Π°Π½Π½ΡƒΡŽ Π½Π° GLSL с Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΡΠΌΠΈ для Vulkan.

Π‘Ρ‚Ρ€ΡƒΠΊΡ‚ΡƒΡ€Π° ΡˆΠ΅ΠΉΠ΄Π΅Ρ€ΠΎΠ²

// ΠŸΡ€ΠΈΠΌΠ΅Ρ€ Π²Π΅Ρ€ΡˆΠΈΠ½Π½ΠΎΠ³ΠΎ ΡˆΠ΅ΠΉΠ΄Π΅Ρ€Π° (vertex.glsl)
#version 450
#extension GL_ARB_separate_shader_objects : enable

layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec3 inNormal;
layout(location = 2) in vec2 inTexCoord;
layout(location = 3) in vec3 inTangent;
layout(location = 4) in vec3 inBitangent;

layout(set = 0, binding = 0) uniform CameraUBO {
    mat4 view;
    mat4 proj;
    vec3 position;
} camera;

layout(set = 1, binding = 0) uniform ModelUBO {
    mat4 model;
    mat4 normalMatrix;
} model;

layout(location = 0) out vec3 outWorldPos;
layout(location = 1) out vec2 outTexCoord;
layout(location = 2) out mat3 outTBN;

void main() {
    vec4 worldPos = model.model * vec4(inPosition, 1.0);
    outWorldPos = worldPos.xyz;
    outTexCoord = inTexCoord;
    
    vec3 T = normalize(vec3(model.normalMatrix * vec4(inTangent, 0.0)));
    vec3 B = normalize(vec3(model.normalMatrix * vec4(inBitangent, 0.0)));
    vec3 N = normalize(vec3(model.normalMatrix * vec4(inNormal, 0.0)));
    outTBN = mat3(T, B, N);
    
    gl_Position = camera.proj * camera.view * worldPos;
}
// ΠŸΡ€ΠΈΠΌΠ΅Ρ€ Ρ„Ρ€Π°Π³ΠΌΠ΅Π½Ρ‚Π½ΠΎΠ³ΠΎ ΡˆΠ΅ΠΉΠ΄Π΅Ρ€Π° (fragment.glsl)
#version 450
#extension GL_ARB_separate_shader_objects : enable

layout(location = 0) in vec3 inWorldPos;
layout(location = 1) in vec2 inTexCoord;
layout(location = 2) in mat3 inTBN;

layout(set = 0, binding = 0) uniform CameraUBO {
    mat4 view;
    mat4 proj;
    vec3 position;
} camera;

layout(set = 2, binding = 0) uniform MaterialUBO {
    vec3 albedoFactor;
    float metallicFactor;
    float roughnessFactor;
    float emissiveIntensity;
} material;

layout(set = 2, binding = 1) uniform sampler2D albedoMap;
layout(set = 2, binding = 2) uniform sampler2D normalMap;
layout(set = 2, binding = 3) uniform sampler2D metallicMap;
layout(set = 2, binding = 4) uniform sampler2D roughnessMap;
layout(set = 2, binding = 5) uniform sampler2D aoMap;
layout(set = 2, binding = 6) uniform sampler2D emissiveMap;

layout(location = 0) out vec4 outPosition;
layout(location = 1) out vec4 outNormal;
layout(location = 2) out vec4 outAlbedo;
layout(location = 3) out vec4 outPBR;
layout(location = 4) out vec4 outEmissive;

void main() {
    // Π˜Π·Π²Π»Π΅Ρ‡Π΅Π½ΠΈΠ΅ Π΄Π°Π½Π½Ρ‹Ρ… ΠΈΠ· тСкстур
    vec3 albedo = texture(albedoMap, inTexCoord).rgb * material.albedoFactor;
    float metallic = texture(metallicMap, inTexCoord).r * material.metallicFactor;
    float roughness = texture(roughnessMap, inTexCoord).r * material.roughnessFactor;
    float ao = texture(aoMap, inTexCoord).r;
    vec3 emissive = texture(emissiveMap, inTexCoord).rgb * material.emissiveIntensity;
    
    // Нормали ΠΈΠ· ΠΊΠ°Ρ€Ρ‚Ρ‹ Π½ΠΎΡ€ΠΌΠ°Π»Π΅ΠΉ
    vec3 normal = texture(normalMap, inTexCoord).rgb * 2.0 - 1.0;
    normal = normalize(inTBN * normal);
    
    // Π’Ρ‹Π²ΠΎΠ΄ Π² G-Π±ΡƒΡ„Π΅Ρ€
    outPosition = vec4(inWorldPos, 1.0);
    outNormal = vec4(normal, 1.0);
    outAlbedo = vec4(albedo, 1.0);
    outPBR = vec4(metallic, roughness, ao, 1.0);
    outEmissive = vec4(emissive, 1.0);
}

ΠšΠΎΠΌΠΏΠΈΠ»ΡΡ†ΠΈΡ ΡˆΠ΅ΠΉΠ΄Π΅Ρ€ΠΎΠ²

Wudgine автоматичСски ΠΊΠΎΠΌΠΏΠΈΠ»ΠΈΡ€ΡƒΠ΅Ρ‚ ΡˆΠ΅ΠΉΠ΄Π΅Ρ€Ρ‹ ΠΏΡ€ΠΈ сборкС ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π°:

# ΠšΠΎΠΌΠΏΠΈΠ»ΡΡ†ΠΈΡ ΡˆΠ΅ΠΉΠ΄Π΅Ρ€ΠΎΠ² с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ glslc
glslc vertex.glsl -o vertex.spv
glslc fragment.glsl -o fragment.spv

Π¨Π΅ΠΉΠ΄Π΅Ρ€Π½Ρ‹Π΅ Π²Π°Ρ€ΠΈΠ°Ρ†ΠΈΠΈ

БистСма ΡˆΠ΅ΠΉΠ΄Π΅Ρ€ΠΎΠ² Wudgine ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ Π²Π°Ρ€ΠΈΠ°Ρ†ΠΈΠΈ для ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ:

// ΠŸΡ€ΠΈΠΌΠ΅Ρ€ создания ΡˆΠ΅ΠΉΠ΄Π΅Ρ€Π° с вариациями
ShaderProgram shader = ShaderProgram::create("assets/shaders/pbr");

// Π”ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ Π²Π°Ρ€ΠΈΠ°Ρ†ΠΈΠΉ
shader.addVariation("HAS_ALBEDO_MAP", { true, false });
shader.addVariation("HAS_NORMAL_MAP", { true, false });
shader.addVariation("HAS_METALLIC_MAP", { true, false });
shader.addVariation("HAS_ROUGHNESS_MAP", { true, false });
shader.addVariation("HAS_AO_MAP", { true, false });
shader.addVariation("HAS_EMISSIVE_MAP", { true, false });
shader.addVariation("MAX_LIGHTS", { 1, 4, 8, 16 });

// ΠšΠΎΠΌΠΏΠΈΠ»ΡΡ†ΠΈΡ всСх Π²Π°Ρ€ΠΈΠ°Ρ†ΠΈΠΉ
shader.compileVariations();

Нодовый Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΎΡ€ ΡˆΠ΅ΠΉΠ΄Π΅Ρ€ΠΎΠ²

Wudgine Π²ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ Π²ΠΈΠ·ΡƒΠ°Π»ΡŒΠ½Ρ‹ΠΉ Π½ΠΎΠ΄ΠΎΠ²Ρ‹ΠΉ Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΎΡ€ ΡˆΠ΅ΠΉΠ΄Π΅Ρ€ΠΎΠ² для создания слоТных ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»ΠΎΠ² Π±Π΅Π· написания ΠΊΠΎΠ΄Π°:

  • Π˜Π½Ρ‚ΡƒΠΈΡ‚ΠΈΠ²Π½Ρ‹ΠΉ интСрфСйс для создания ΡˆΠ΅ΠΉΠ΄Π΅Ρ€ΠΎΠ²
  • Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° Π³ΠΎΡ‚ΠΎΠ²Ρ‹Ρ… Π½ΠΎΠ΄ΠΎΠ² для Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Ρ… эффСктов
  • ΠŸΡ€Π΅Π΄ΠΏΡ€ΠΎΡΠΌΠΎΡ‚Ρ€ Π² Ρ€Π΅Π°Π»ΡŒΠ½ΠΎΠΌ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ
  • АвтоматичСская гСнСрация GLSL ΠΊΠΎΠ΄Π°

ΠŸΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΈΠ΅ ΡˆΠ΅ΠΉΠ΄Π΅Ρ€Ρ‹

Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΈΡ… ΡˆΠ΅ΠΉΠ΄Π΅Ρ€ΠΎΠ² для ΡΠΏΠ΅Ρ†ΠΈΠ°Π»ΡŒΠ½Ρ‹Ρ… эффСктов:

// Π€Ρ€Π°Π³ΠΌΠ΅Π½Ρ‚ ΡˆΠ΅ΠΉΠ΄Π΅Ρ€Π° для Π²ΠΎΠ΄Ρ‹
vec2 distortedUV = inTexCoord;
distortedUV.x += sin(inTexCoord.y * 40.0 + time * 0.5) * 0.01;
distortedUV.y += cos(inTexCoord.x * 40.0 + time * 0.5) * 0.01;

vec3 normal = texture(normalMap, distortedUV).rgb * 2.0 - 1.0;
normal = normalize(inTBN * normal);

// ΠžΡ‚Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ ΠΈ ΠΏΡ€Π΅Π»ΠΎΠΌΠ»Π΅Π½ΠΈΠ΅
vec3 viewDir = normalize(camera.position - inWorldPos);
vec3 reflection = reflect(-viewDir, normal);
vec4 reflectionColor = texture(reflectionMap, reflection.xy);

Π‘Π»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ шаги

Π’Π΅ΠΏΠ΅Ρ€ΡŒ, ΠΊΠΎΠ³Π΄Π° Π²Ρ‹ ознакомились с систСмой ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»ΠΎΠ² ΠΈ ΡˆΠ΅ΠΉΠ΄Π΅Ρ€ΠΎΠ² Wudgine, Ρ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡƒΠ΅ΠΌ:

ΠžΡΠ²Π΅Ρ‰Π΅Π½ΠΈΠ΅ ΠΈ Ρ‚Π΅Π½ΠΈ

Π˜Π·ΡƒΡ‡ΠΈΡ‚Π΅ систСму освСщСния ΠΈ Ρ‚Π΅Π½Π΅ΠΉ Wudgine.

ΠŸΠΎΡΡ‚ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ°

ΠŸΠΎΠ·Π½Π°ΠΊΠΎΠΌΡŒΡ‚Π΅ΡΡŒ с эффСктами постобработки.

Wudgine β€’ Β© 2025