
рд╕рднреА рдХреЛ рдирдорд╕реНрдХрд╛рд░!
рд╣рдорд╛рд░реА рдХрдВрдкрдиреА рдСрдирд▓рд╛рдЗрди рдЧреЗрдо рд╡рд┐рдХрд╕рд┐рдд рдХрд░ рд░рд╣реА рд╣реИ рдФрд░ рдЕрдм рд╣рдо рдЕрдкрдиреЗ рдореБрдЦреНрдп рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХреЗ рдореЛрдмрд╛рдЗрд▓ рд╕рдВрд╕реНрдХрд░рдг рдкрд░ рдХрд╛рдо рдХрд░ рд░рд╣реЗ рд╣реИрдВред рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рд╣рдо рдПрдХ Android рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХреЗ рд▓рд┐рдП GLSL рд╢реЗрдб рдмрдирд╛рдиреЗ рдХреЗ рдЕрдиреБрднрд╡ рдХреЛ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдФрд░
рд╕реНрд░реЛрддреЛрдВ рдХреЗ рд╕рд╛рде рд╕рд╛рдЭрд╛ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ
рд╣реИрдВ ред
рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ
рдкреНрд░рд╛рд░рдВрдн рдореЗрдВ, рдЦреЗрд▓ рдлреНрд▓реИрд╢ рдкрд░ рдмреНрд░рд╛рдЙрдЬрд╝рд░-рдЖрдзрд╛рд░рд┐рдд рдерд╛, рд▓реЗрдХрд┐рди рдлреНрд▓реИрд╢ рдХреЗ рд▓рд┐рдП рдЖрд╕рдиреНрди рд╕рдорд╛рдкреНрддрд┐ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕рдорд╛рдЪрд╛рд░ рдиреЗ рд╣рдореЗрдВ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЛ рдПрдЪрдЯреАрдПрдордПрд▓ 5 рдореЗрдВ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдордЬрдмреВрд░ рдХрд┐рдпрд╛ред рдХреЛрдЯрд▓рд┐рди рдХреЛ рд╡рд┐рдХрд╛рд╕ рднрд╛рд╖рд╛ рдХреЗ рд░реВрдк рдореЗрдВ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдФрд░ рдЫрд╣ рдорд╣реАрдиреЗ рдмрд╛рдж рд╣рдо рдПрдВрдбреНрд░реЙрдЗрдб рдкрд░ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рд▓реЙрдиреНрдЪ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рдереЗред рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ, рдореЛрдмрд╛рдЗрд▓ рдЙрдкрдХрд░рдгреЛрдВ рдкрд░ рдЕрдиреБрдХреВрд▓рди рдХреЗ рдмрд┐рдирд╛, рдЦреЗрд▓ рдореЗрдВ рдкреНрд░рджрд░реНрд╢рди рдХреА рдХрдореА рдереАред
рдПрдлрдкреАрдПрд╕ рдмрдврд╝рд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдЧреНрд░рд╛рдлрд┐рдХреНрд╕ рдЗрдВрдЬрди рдХреЛ рдлрд┐рд░ рд╕реЗ рдбрд┐рдЬрд╝рд╛рдЗрди рдХрд░рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓рд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рд╣рдо рдХрдИ рд╕рд╛рд░реНрд╡рднреМрдорд┐рдХ рд╢реЗрдбреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рдереЗ, рд▓реЗрдХрд┐рди рдЕрдм рдкреНрд░рддреНрдпреЗрдХ рдкреНрд░рднрд╛рд╡ рдХреЗ рд▓рд┐рдП рд╣рдордиреЗ рдПрдХ рдЕрд▓рдЧ рд╢реЗрдбрд░ рд▓рд┐рдЦрдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛, рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдХрд╛рд░реНрдп рдХреЗ рд▓рд┐рдП рддреЗрдЬ рдХрд┐рдпрд╛, рддрд╛рдХрд┐ рдЙрдирдХреЗ рдХрд╛рдо рдХреЛ рдФрд░ рдЕрдзрд┐рдХ рдХреБрд╢рд▓ рдмрдирд╛рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛ рд╕рдХреЗрдВред
рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдХреНрдпрд╛ рдХрдореА рдереА
рд╢реЗрдбреНрд╕ рдХреЛ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдореЗрдВ рд╕рдВрдЧреНрд░рд╣рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рд╡рд┐рдзрд┐ рд╡рд╛рдХреНрдпрд╡рд┐рдиреНрдпрд╛рд╕ рдЬрд╛рдБрдЪ рдФрд░ рдкреНрд░рдХрд╛рд░ рдорд┐рд▓рд╛рди рдХреЛ рд╕рдорд╛рдкреНрдд рдХрд░ рджреЗрддреА рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЖрдорддреМрд░ рдкрд░ рд╢реЗрдбреНрд╕ рдХреЛ рдПрд╕реЗрдЯреНрд╕ рдпрд╛ рд░реЙ рдлрд╝рд╛рдЗрд▓реЛрдВ рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдЖрдкрдХреЛ рдПрдВрдбреНрд░реЙрдЗрдб рд╕реНрдЯреВрдбрд┐рдпреЛ рдХреЗ рд▓рд┐рдП рдкреНрд▓рдЧ-рдЗрди рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдХреЗ рд╕рддреНрдпрд╛рдкрди рдХреЛ рд╕рдХреНрд╖рдо рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдореЗрдВ рдПрдХ рдЦрд╛рдореА рднреА рд╣реИ - рдкреБрди: рдЙрдкрдпреЛрдЧ рдХреА рдХрдореА: рдЫреЛрдЯреЗ рд╕рдВрдкрд╛рджрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдПрдХ рдирдИ shader рдлрд╝рд╛рдЗрд▓ рдмрдирд╛рдиреА рд╣реЛрдЧреАред
рддрд╛рдХрд┐:
- рдХреЛрдЯрд▓рд┐рди рдкрд░ рд╢реЗрдбреНрд╕ рд╡рд┐рдХрд╕рд┐рдд рдХрд░реЗрдВ,
- рд╕рдВрдХрд▓рди рдЪрд░рдг рдореЗрдВ рдПрдХ рд╡рд╛рдХреНрдпрд╡рд┐рдиреНрдпрд╛рд╕ рдЬрд╛рдБрдЪ рдХрд░реЗрдВ,
- shaders рдХреЗ рдмреАрдЪ рдХреЛрдб рдХрд╛ рдкреБрди: рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛ,
рдореБрдЭреЗ GLSL рдХреЗ рд▓рд┐рдП рдПрдХ "рдХрдирд╡рд░реНрдЯрд░" рдХреЛрдЯрд▓рд┐рди рд▓рд┐рдЦрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдереАред
рд╡рд╛рдВрдЫрд┐рдд рдкрд░рд┐рдгрд╛рдо: рд╢реЗрдбрд░ рдХреЛрдб рдХреЛ рдХреЛрдЯрд▓рд┐рди рд╡рд░реНрдЧ рдХреЗ рд░реВрдк рдореЗрдВ рд╡рд░реНрдгрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рдЧреБрдг, рднрд┐рдиреНрдирддрд╛, рд╡рд░реНрджреА рдЗрд╕ рд╡рд░реНрдЧ рдХреЗ рдЧреБрдг рд╣реИрдВред рд╡рд░реНрдЧ рдХреЗ рдкреНрд░рд╛рдердорд┐рдХ рдирд┐рд░реНрдорд╛рддрд╛ рдХреЗ рдорд╛рдкрджрдВрдбреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рд╕реНрдерд┐рд░ рд╢рд╛рдЦрд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдЖрдкрдХреЛ рд╢реЗрд╖ рдХреЛрдб рдХрд╛ рдкреБрди: рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдЗрдирд┐рдЯ рдмреНрд▓реЙрдХ рд╢реИрдбрд░ рдХрд╛ рд╢рд░реАрд░ рд╣реИред
рдирд┐рд░реНрдгрдп
рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд▓рд┐рдП, рдХреЛрдЯрд▓рд┐рди
рдкреНрд░рддрд┐рдирд┐рдзрд┐рдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдЙрдиреНрд╣реЛрдВрдиреЗ рд░рдирдЯрд╛рдЗрдо рдХреЛ рдкреНрд░рддреНрдпрд╛рдпреЛрдЬрд┐рдд рд╕рдВрдкрддреНрддрд┐ рдХреЗ рдирд╛рдо рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рдиреЗ, рдХреЙрд▓ рдХреЗ рдХреНрд╖рдгреЛрдВ рдХреЛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдФрд░ рдЙрдиреНрд╣реЗрдВ рд╕реЗрдЯ рдХрд░рдиреЗ рдФрд░ рд╕рднреА рд╢реЗрдбреНрд╕ рдХреЗ рдЖрдзрд╛рд░ рд╡рд░реНрдЧ - ShaderBuilder рдХреЛ рд╕реВрдЪрд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреАред
class ShaderBuilder { val uniforms = HashSet<String>() val attributes = HashSet<String>() val varyings = HashSet<String>() val instructions = ArrayList<Instruction>() ... fun getSource(): String = ... }
рдкреНрд░рддрд┐рдирд┐рдзрд┐ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрдирднрд┐рдиреНрди рдкреНрд░рддрд┐рдирд┐рдзрд┐:
class VaryingDelegate<T : Variable>(private val factory: (ShaderBuilder) -> T) { private lateinit var v: T operator fun provideDelegate(ref: ShaderBuilder, p: KProperty<*>): VaryingDelegate<T> { v = factory(ref) v.value = p.name return this } operator fun getValue(thisRef: ShaderBuilder, property: KProperty<*>): T { thisRef.varyings.add("${v.typeName} ${property.name}") return v } operator fun setValue(thisRef: ShaderBuilder, property: KProperty<*>, value: T) { thisRef.varyings.add("${v.typeName} ${property.name}") thisRef.instructions.add(Instruction.assign(property.name, value.value)) } }
GitHub рдкрд░ рд╢реЗрд╖ рдкреНрд░рддрд┐рдирд┐рдзрд┐рдпреЛрдВ рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрдиред
рд╢реЗрдбрд░ рдЙрджрд╛рд╣рд░рдг:
// useAlphaTest , // , , , // . class FragmentShader(useAlphaTest: Boolean) : ShaderBuilder() { private val alphaTestThreshold by uniform(::GLFloat) private val texture by uniform(::Sampler2D) private val uv by varying(::Vec2) init { var color by vec4() color = texture2D(texture, uv) // static branching if (useAlphaTest) { // dynamic branching If(color.w lt alphaTestThreshold) { discard() } } // ShaderBuilder. gl_FragColor = color } }
рдФрд░ рдпрд╣рд╛рдБ рдкрд░рд┐рдгрд╛рдореА GLSL рд╕реНрд░реЛрдд (FragmentShader (useAlphaTest = true) .getSource ()) рдХрд╛ рдкрд░рд┐рдгрд╛рдо рд╣реИред рдХреЛрдб рдХреА рд╕рд╛рдордЧреНрд░реА рдФрд░ рд╕рдВрд░рдЪрдирд╛ рд╕рдВрд░рдХреНрд╖рд┐рдд рд╣реИ:
uniform sampler2D texture; uniform float alphaTestThreshold; varying vec2 uv; void main(void) { vec4 color; color = texture2D(texture, uv); if ((color.w < alphaTestThreshold)) { discard; } gl_FragColor = color; }
рд╕реНрд░реЛрдд рдХреЛ рдЗрдХрдЯреНрдард╛ рдХрд░рддреЗ рд╕рдордп рд╡рд┐рднрд┐рдиреНрди рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдХреЗ shader рдХреЛрдб рдХрд╛ рдкреБрди: рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдкреБрди: рдЙрдкрдпреЛрдЧ рдХреА рд╕рдорд╕реНрдпрд╛ рдХреЛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╣рд▓ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред рдорд╛рдорд▓реЗ рдореЗрдВ рдЬрдм рдЖрдкрдХреЛ рдЕрд▓рдЧ-рдЕрд▓рдЧ рд╢реЗрдбреНрд╕ рдореЗрдВ рдПрдХ рд╣реА рдХреЛрдб рд▓рд┐рдЦрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рддреЛ рдЖрдк рдЗрди рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХреЛ рдПрдХ рдЕрд▓рдЧ ShaderBuilderComponent рдореЗрдВ рдбрд╛рд▓ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЙрдиреНрд╣реЗрдВ рдореБрдЦреНрдп ShaderBuilders рдореЗрдВ рдЖрд╡рд╢реНрдпрдХрддрд╛рдиреБрд╕рд╛рд░ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ:
class ShadowReceiveComponent : ShaderBuilderComponent() { тАж fun vertex(parent: ShaderBuilder, inp: Vec4) { vShadowCoord = shadowMVP * inp ... parent.appendComponent(this) } fun fragment(parent: ShaderBuilder, brightness: GLFloat) { var pixel by float() pixel = texture2D(shadowTexture, vShadowCoord.xy).x ... parent.appendComponent(this) } }
рд╣реБрд░реНрд░реЗ, рдкреНрд░рд╛рдкреНрдд рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдЖрдкрдХреЛ рдХреЛрдЯрд▓рд┐рди рдкрд░ рдЫрд╛рдпрд╛рдВрдХрди рд▓рд┐рдЦрдиреЗ, рдХреЛрдб рдХрд╛ рдкреБрди: рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ, рд╡рд╛рдХреНрдпрд╡рд┐рдиреНрдпрд╛рд╕ рдХреА рдЬрд╛рдВрдЪ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреА рд╣реИ!
рдЕрдм, рдЪрд▓реЛ GLSL рдореЗрдВ
Swizzling рдХреЛ рдпрд╛рдж рдХрд░рддреЗ рд╣реИрдВ рдФрд░ Vec2, Vec3, Vec4 рдореЗрдВ рдЗрд╕рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рджреЗрдЦрддреЗ рд╣реИрдВред
class Vec2 { var x by ComponentDelegate(::GLFloat) var y by ComponentDelegate(::GLFloat) } class Vec3 { var x by ComponentDelegate(::GLFloat) ... // 9 Vec2 var xx by ComponentDelegate(::Vec2) var xy by ComponentDelegate(::Vec2) ... } class Vec4 { var x by ComponentDelegate(::GLFloat) ... // 16 Vec2 var xy by ComponentDelegate(::Vec2) ... // 64 Vec3 var xxx by ComponentDelegate(::Vec3) ... }
рд╣рдорд╛рд░реА рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ, shader рд╕рдВрдХрд▓рди рдорд╛рдВрдЧ рдкрд░ рдЦреЗрд▓ рдЪрдХреНрд░ рдореЗрдВ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рдФрд░ рдЗрд╕ рддрд░рд╣ рдХреЗ рдСрдмреНрдЬреЗрдХреНрдЯ рдЖрд╡рдВрдЯрди рдкреНрд░рдореБрдЦ GC рдХреЙрд▓ рдЙрддреНрдкрдиреНрди рдХрд░рддреЗ рд╣реИрдВ, рд▓реИрдЧреНрд╕ рджрд┐рдЦрд╛рдИ рджреЗрддреЗ рд╣реИрдВред рдЗрд╕рд▓рд┐рдП, рд╣рдордиреЗ рд╢реЗрдбрд░ рд╕реНрд░реЛрддреЛрдВ рдХреА рдЕрд╕реЗрдВрдмрд▓реА рдХреЛ рдПрдиреЛрдЯреЗрд╢рди рдкреНрд░реЛрд╕реЗрд╕рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕рдВрдХрд▓рди рдЪрд░рдг рдореЗрдВ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓рд┐рдпрд╛ред
рд╣рдо рд╢реНрд░реЗрдгреА рдХреЛ ShaderProgram рдПрдиреЛрдЯреЗрд╢рди рдХреЗ рд╕рд╛рде рдЪрд┐рд╣реНрдирд┐рдд рдХрд░рддреЗ рд╣реИрдВ:
@ShaderProgram(VertexShader::class, FragmentShader::class) class ShaderProgramName(alphaTest: Boolean)
рдФрд░ рдПрдиреЛрдЯреЗрд╢рди рдкреНрд░реЛрд╕реЗрд╕рд░ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рд╡рд░реНрдЯреЗрдХреНрд╕ рдФрд░ рдЯреБрдХрдбрд╝рд╛ рд╡рд░реНрдЧреЛрдВ рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХреЗ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рд╕рднреА рдкреНрд░рдХрд╛рд░ рдХреЗ рд╢реЗрдбреНрд╕ рдПрдХрддреНрд░ рдХрд░рддрд╛ рд╣реИ:
class ShaderProgramNameSources { enum class Sources(vertex: String, fragment: String): ShaderProgramSources { Source0("<vertex code>", "<fragment code>") ... } fun get(alphaTest: Boolean) { if (alphaTest) return Source0 else return Source1 } }
рдЕрдм рдЖрдк рдЙрддреНрдкрдиреНрди рд╡рд░реНрдЧ рд╕реЗ shader рдкрд╛рда рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
val sources = ShaderProgramNameSources.get(replaceAlpha = true) println(sources.vertex) println(sources.fragment)
рдЪреВрдБрдХрд┐ рдкреНрд░рд╛рдкреНрдд рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдкрд░рд┐рдгрд╛рдо - ShaderProgramSource, enum рд╕реЗ рдорд╛рди рд╣реИ, рдЗрд╕рд▓рд┐рдП рдкреНрд░реЛрдЧреНрд░рд╛рдо рд░рдЬрд┐рд╕реНрдЯреНрд░реА (ShaderProgramSources) -> CompiledShaderProgram рдореЗрдВ рдХреБрдВрдЬрд┐рдпреЛрдВ рдХреЗ рд░реВрдк рдореЗрдВ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИред
рдЧрд┐рдЯрд╣рдм рдХреЗ рдкрд╛рд╕ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рд▓рд┐рдП рд╕реНрд░реЛрдд рдХреЛрдб рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рдПрдиреЛрдЯреЗрд╢рди рдкреНрд░реЛрд╕реЗрд╕рд░ рдФрд░ рд╢реЗрдбрд░реНрд╕ рдФрд░ рдШрдЯрдХреЛрдВ рдХреЗ рд╕рд░рд▓ рдЙрджрд╛рд╣рд░рдг рд╢рд╛рдорд┐рд▓ рд╣реИрдВред