Material - kuimoani/defold GitHub Wiki
Materials
λ©ν°λ¦¬μΌμ κ·Έλν½ μ»΄ν¬λνΈλ€(μ€νλΌμ΄νΈ, νμΌλ§΅, ν°νΈ, GUIλ ΈνΈ λ±)μ μ΄λ»κ² λ λλ§λμ΄ νννλμ§ Defoldμ λ°©μμ λλ€. μ΄ λ§€λ΄μΌμ λ©ν°λ¦¬μΌ(materials), μμ΄λ μμ(shader constants), μνλ¬(samplers) λ€μ΄ μ΄λ»κ² λμνλμ§ μ€λͺ ν©λλ€.
Overview
λ©ν°λ¦¬μΌμ λ λλ§ ν μ€λΈμ νΈλ₯Ό μ ννκΈ° μν΄ λ λλ§ νμ΄ν λΌμΈ(rendering pipeline)μ μ¬μ©λλ μ λ³΄μΈ Tagsλ₯Ό ν¬ν¨νκ³ μμ΅λλ€. λν μ¬μ© κ°λ₯ν κ·Έλν½ APIλ₯Ό ν΅ν΄ μ»΄νμΌ λ ν κ° νλ μλ§λ€ μ»΄ν¬λνΈκ° λ λλ§λ λ κ·Έλν½ νλμ¨μ΄μμ μ€νλλ μμ΄λ νλ‘κ·Έλ¨μ λν μ°Έμ‘°λ ν¬ν¨νκ³ μμ΅λλ€. λ²ν μ€ μμ΄λ(vertex shader)λ μ»΄ν¬λνΈμ κΈ°ν ꡬ쑰(geometry)λ₯Ό κ³μ°νλ©°, μ΄λ μ€λΈμ νΈμ κ° λ²ν μ€λ₯Ό μ λ¬νκΈ° μ μ μμ μ μννκ² λ©λλ€. κ³μ° κ²°κ³Όλ‘ λ§λ€μ΄μ§ κΈ°μ΄ μμ(primitives)λ λμ€ν°(rasterized)ν λκ±°λ fragment(μ‘°κ°) νΉμ ν½μ λ‘ λλ μ§κ² λ©λλ€. μ΄λ€ κ°κ°μ νλκ·Έλ¨ΌνΈλ€μ νλκ·Έλ¨ΌνΈ μμ΄λ(fragment shader: λλ‘λ ν½μ μμ΄λλΌκ³ λ λΆλ¦Ό)λ₯Ό ν΅νμ¬ μ€νλ©λλ€. μ΄ νλκ·Έλ¨ΌνΈ μμ΄λμ λͺ©μ μ κ²°κ³Ό ν½μ (resulting pixel)μ μμμ κ²°μ νλ κ²μ΄λ©°, μ΄λ€ λ°©μμΌλ‘λ κ³μ°(calculation), ν μ€μ³ μ‘°ν(texture lookup), μ‘°ν©(combinations)μ μν΄ μνλ μ μμ΅λλ€.

Defoldλ λͺ¨λ°μΌ μ₯μΉμμ λ λλ§ νκΈ° μν΄ OpenGL ES 2.0μ μ¬μ©ν©λλ€. λ°μ€ν¬ν νκ²½μμλ λ³΄ν΅ λ€λ₯Έ λ²μ μ OpenGLμ΄ μ¬μ©λμ§λ§, μμ¦μ νλμ¨μ΄μ λλΌμ΄λ²λ μ μ νκ² νΈνλκ³ μμ΅λλ€. OpenGL ES 2.0 (μλ² λλ μμ€ν μ μν OpenGL) κ³Ό OpenGL ES μμ΄λ© μΈμ΄μ μμΈν μ¬μμ https://www.khronos.org/registry/gles/ μμ λ³Ό μ μμ΅λλ€.
λ°μ€ν¬ν νκ²½μμλ OpenGL ES 2.0 μμ μ§μλμ§ μλ κΈ°λ₯μ μ¬μ©νμ¬ μμ΄λλ₯Ό λ§λ€κ³ μ»΄νμΌ νλ κ²μ΄ κ°λ₯ν©λλ€. λ€λ§ μ΄λ κ² νλ©΄ μνΈ νΈνμ΄ κΉ¨μ§ μ μμ΅λλ€.
Creating a material
μ, λ¨μν νλ©΄(μ§ν₯μ± λΉ(directional light)μ΄ μλ)μ΄μ§λ§ μ§κ°μ΄ μλ λ©ν°λ¦¬μΌ(textured material)μ λ§λ€μ΄ λ΄ μλ€.
- Project Explorer μ°½μμ λμ ν΄λλ₯Ό μ νν©λλ€.
- File > Newβ¦β > Material File λ©λ΄λ₯Ό μ νν©λλ€. (Project Explorer μ°½μμ μ€λ₯Έμͺ½ ν΄λ¦ ν Newβ¦β > Material Fileμ μ νν΄λ λ©λλ€.)
- μ λ©ν°λ¦¬μΌ νμΌμ μ΄λ¦μ μ§μ ν©λλ€.
- μ λ©ν°λ¦¬μΌμ Material Editorμμ μ½λλ€.

μ΄μ λ²ν μ€(vertex)μ νλ κ·Έλ¨ΌνΈ μμ΄λ(fragment shader) νλ‘κ·Έλ¨ νμΌμ λ§λ€μ΄μΌ ν©λλ€. νμ¬ μ΄ μμ λ¨κ³λ μ’ λ³΅μ‘ν©λλ€.
- File > Newβ¦β > Script File μ μ νν΄μ μ€ν¬λ¦½νΈ νμΌ λ§λ€κΈ°
- μ΄ μ€ν¬λ¦½νΈ νμΌμ νμ₯μλ₯Ό ".vp" (Vertex Program)λ‘ λ°κΏλλ€.
- μ€ν¬λ¦½νΈ νμΌμ νλ λ λ§λλλ€.
- μ΄ μ€ν¬λ¦½νΈ νμΌμ νμ₯μλ₯Ό ".fp" (Fragment Program)λ‘ λ°κΏλλ€.
λ©ν°λ¦¬μΌμ μλ μμ±μ μ¬μ©νμ¬ μλ‘ μ°κ΄λ λ νλ‘κ·Έλ¨ νμΌμ μ§μ ν©λλ€.

Material tags
λΉμ μ λ λ μ€ν¬λ¦½νΈ(render script)κ° μ λ©ν°λ¦¬μΌμ μ¬μ©νλ μ»΄ν¬λνΈλ₯Ό λ λλ§ ν μ μμΌλ―λ‘ λΉμ μ λ©ν°λ¦¬μΌμ μν νκ·Έ(tag)λ₯Ό μ€μ ν΄μΌ ν©λλ€. νκ·Έλ μμ§μμ render.predicate()μ μν΄ ν¨κ» λ λλ§ν΄μΌ νλ μ»΄ν¬λνΈλ€μ μμ§νκΈ°μν΄ μ¬μ©λλ©° λΉνΈλ§μ€ν¬(bitmask)λ‘ νμλ©λλ€. μ΄λ₯Ό μννλ λ°©λ²μ μκ³ μΆλ€λ©΄ Renderingλ¬Έμλ₯Ό μ°Έκ³ λ°λλλ€.
νλ‘μ νΈμμ μ¬μ©ν μ μλ μ΅λ νκ·Έμ μλ 32κ° μ λλ€.

Constants
λ²ν μ€ μμ΄λλ κ° λ²ν μ€κ° ν΄λ¦¬ν 곡κ°(clipping space)μΌλ‘ λ°λ μ μλλ‘ λ©νΈλ¦μ€λ₯Ό νμλ‘ νλ©° λ κ°μ λ²ν μ€ μμ(vertex constants)λ₯Ό μ€μ νλ©΄ λ©λλ€.
- μμ ν κ°λ "world"λ‘ μ΄λ¦μ μ§κ³ typeμ CONSTANT_TYPE_WORLD λ‘ μ€μ ν©λλ€. μ΄λ₯Ό ν΅ν΄ μμ§μ "world"κ° μλ λ©νΈλ¦μ€λ₯Ό ν¬ν¨νκ³ μλ€λ κ²μ μ μ μμ΅λλ€.
- λλ²μ§Έλ "view_proj"λ‘ μ΄λ¦μ μ§κ³ typeμ CONSTANT_VIEW_PROJECTION μΌλ‘ μ€μ ν©λλ€. μ΄λ₯Ό ν΅ν΄ μμ§μ "view_proj"κ° νλ‘μ μ λ©νΈλ¦μ€(projection matrix)μ κ³±ν΄μ§ λ·° λ©νΈλ¦μ€(view matrix)λ₯Ό ν¬ν¨νκ³ μλ€λ κ²μ μ μ μμ΅λλ€.

Shader programs
λ©ν°λ¦¬μΌμ΄ λμνκΈ° μν΄μ, μ°λ¦¬λ λ²ν μ€μ μμ΄λ νλ‘κ·Έλ¨μ μμ ν΄μΌ ν©λλ€.
Vertex shader ("flat.vp")
// view_proj μ world λ λ²ν
μ€ μμλ‘ μ€μ λλ©°
// μ°λ¦¬λ λ²ν
μ€ μμ΄λ νλ‘κ·Έλ¨μμ μ΄λ₯Ό "uniform"μΌλ‘ μ μΈνμ¬ μμΈμ€ν¨
//
uniform mediump mat4 view_proj;
uniform mediump mat4 world;
// positionμ΄ μλμ λ²ν
μ€ ν¬μ§μ
μ μ μ§ν¨
attribute mediump vec4 position;
// texcoord0 λ μ΄ λ²ν
μ€λ₯Ό μν΄ ν
μ€μ³ μ’νλ₯Ό κ°μ§κ³ μμ
attribute mediump vec2 texcoord0;
// λ²ν
μ€ κ°μ ν
μ€μ³ μ’νλ₯Ό 보κ°νλ λ³μλ₯Ό μ μν¨
// νλ κ·Έλ¨ΌνΈ μμ΄λ(fragment shader)λ μ΄ κ°μ μ½κ²λ¨
varying mediump vec2 var_texcoord0;
void main()
{
// view, projection, world λ©νΈλ¦μ€λ₯Ό νλλ‘ κ³±ν¨
mediump mat4 mvp = view_proj * world;
// var_texcoord0μ μ΄ λ²ν
μ€μ μμΉμΈ texcoord0λ₯Ό μ€μ ν¨
var_texcoord0 = texcoord0;
// λ²ν
μ€ μμΉλ₯Ό mvp matrixλ‘ μ΄λ(translate)ν¨
// vec4(position.xyz, 1.0) λ μ΄ μμΉμ w μ»΄ν¬λνΈκ° νμ 1.0μμ 보μ₯ν¨
gl_Position = mvp * vec4(position.xyz, 1.0);
}
Fragment shader ("flat.fp")
// μ΄ νλ κ·Έλ¨ΌνΈμ ν
μ€μ³ μ’νλ λ²ν
μ€ μ¬μ΄μ λ€μνκ² μμ
varying mediump vec2 var_texcoord0;
// μ»΄ν¬λνΈμ ν
μ€μ³ λ°μ΄ν°λ sampler2Dλ₯Ό ν΅ν΄ μ‘μΈμ€λ¨
uniform sampler2D diffuse_texture;
void main()
{
// μ΄ νλ κ·Έλ¨ΌνΈ μ’νμμ ν
μ€μ³μ μμμ μ°Ύκ³ μ΄λ₯Ό νλ κ·Έλ¨ΌνΈ μμμΌλ‘ μ€μ ν¨
gl_FragColor = texture2D(diffuse_texture, var_texcoord0);
}
Setting the material
κ° κ·Έλν½ μ€λΈμ νΈμ νμ μ Material μμ±μ κ°μ§κ³ μμΌλ©° κ° μ»΄ν¬λνΈλ§λ€ νΉμ λ©ν°λ¦¬μΌμ μ€μ ν μ μμ΅λλ€. λ©ν°λ¦¬μΌμ μ€μ νμ§ μμΌλ©΄, κΈ°λ³Έ λ©ν°λ¦¬μΌμ΄ μλμΌλ‘ μ νλ©λλ€. μ§μ μλ‘ λ§λ λ©ν°λ¦¬μΌμ μ¬μ©νμ¬ λͺ¨λΈ λ λ(model render)λ₯Ό λ§λ€κΈ° μν΄μλ, Material μμ±μ μ€μ νμ¬ λ©ν°λ¦¬μΌ νμΌμ μ°Έμ‘°νλ©΄ λ©λλ€. Models λ¬Έμμμ μ΄λ»κ² 3D λͺ¨λΈμ Defoldλ‘ μν¬νΈ νλμ§ κ°μ΄λλ₯Ό λ³Ό μ μμ΅λλ€.

μ΄μ λͺ¨λΈμ κ²°κ³Ό λ λλ§μ λ³Ό μ μμ΅λλ€. μμν λ§νΌμ ν₯λ―Έλ‘μ΄ λ©ν°λ¦¬μΌμ μλμ§λ§, κ²½νμ μκΈ°μ μ’μ μΆλ°μ μ΄ λ κ²μ λλ€. λ§μ½ λΉμ μ΄ μμ΄λ νλ‘κ·Έλλ°μ μ²μ μμνλ€λ©΄, λ λλ§ νμ΄νλΌμΈμ΄ λμνλ λ°©λ²μ μ΄ν΄νκΈ° μν΄ μ΄ κ°λ¨ν μνμ μκ°μ λ€μ¬μΌ ν©λλ€.

Shader constants
μ λνΌ(Uniforms)μ μμ§μμ λ²ν μ€μ νλ κ·Έλ¨ΌνΈ μμ΄λ νλ‘κ·Έλ¨μΌλ‘ μ λ¬λλ κ°μ λλ€. μ΄λ€μ μμ΄λ νλ‘κ·Έλ¨μμ uniform ν€μλλ‘ μ μΈλλ©° material νμΌμμ vertex_constant μμ±μ΄λ fragment_constant μμ±μΌλ‘ μ μλμ΄μΌ ν©λλ€. μμ΄λ μμ(shader constatns)λ κ° λ λ ν¨μ€(render pass)μμ μΌμ νλ©° κ° νλ μλΉ ν λ²μ© λ°μν©λλ€. μλ νμ μ μ¬μ©ν μ μμ΅λλ€.
CONSTANT_TYPE_USER
μμ΄λ νλ‘κ·Έλ¨μΌλ‘ 보λ΄λ €λ 컀μ€ν λ°μ΄ν°λ₯Ό μν΄ μ¬μ©λλ 컀μ€ν μμ(custom constant)μ λλ€. μμ μ μ(constant definition)μ μλ μμλ₯Ό μ΄κΈ°κ°μΌλ‘ μ¬μ©ν μ μμ§λ§ sprite.set_constant(), sprite.reset_constant(), tilemap.set_constant(), tilemap.reset_constant(), particlefx.set_constant(), particlefx.reset_constant() ν¨μλ₯Ό ν΅ν΄ λ³κ²½ν μ μμ΅λλ€.
CONSTANT_TYPE_WORLD
μλ λ©νΈλ¦μ€(world matrix)
CONSTANT_TYPE_VIEW
λ·° λ©νΈλ¦μ€(view matrix)
CONSTANT_TYPE_PROJECTION
νλ‘μ μ λ©νΈλ¦μ€(projection matrix)
CONSTANT_TYPE_VIEWPROJ
λ·°μ νλ‘μ μ λ©νΈλ¦μ€λ₯Ό κ³±ν λ©νΈλ¦μ€
CONSTANT_TYPE_WORLDVIEW
μλμ λ·°μ νλ‘μ μ λ©νΈλ¦μ€λ₯Ό κ³±ν λ©νΈλ¦μ€
Constant buffers
λ λλ§ νμ΄νλΌμΈ(rendering pipeline)μ΄ κ·Έλ¦¬κΈ° μμ μ ν λλ κΈ°λ³Έ μμ€ν μμ λ²νΌ(default system constants buffer)μμ μμκ°λ€μ κ°μ Έμ΅λλ€. 컀μ€ν μμ λ²νΌλ κΈ°λ³Έ μμκ°μ μ€λ²λΌμ΄λ©(override) νλλ° μ¬μ©λλ©°, λμ λ λ μ€ν¬λ¦½νΈ(render script)μμ μμ΄λ νλ‘κ·Έλ¨ λ³μλ₯Ό νλ‘κ·Έλλ° λ°©μμΌλ‘ μ€μ ν μ μμ΅λλ€. κ·Έλ¦¬κ³ λμ μ΄λ€μ render.draw() ν¨μλ‘ μ λ¬ λ©λλ€.
self.constants = render.constant_buffer() [1]
self.constants.tint = vmath.vector4(1, 0, 0, 1) [2]
...
render.draw(self.my_pred, self.constants) [3]
- [1] μλ‘μ΄ μμ λ²νΌλ₯Ό λ§λ¬
- [2] "tint" μμλ₯Ό λ°μ λΉ¨κ°μμΌλ‘ μ€μ
- [3] μ°λ¦¬μ 컀μ€ν μμλ₯Ό μ¬μ©νμ¬ predicate 그리기
λ²νΌμ μμ μμ(element)λ Lua ν μ΄λΈμ²λΌ μΈλ±μ€ λ μ μμ§λ§ pairs() λ ipairs() λ‘ λ°λ³΅ ν μ λ μμ΅λλ€.
Uniform texture samplers
μ μΈλ sampler 2Dλ μλμ μΌλ‘ κ·Έλν½ μ»΄ν¬λνΈμ μ°Έμ‘°λ ν μ€μ³μ λ°μΈλ© λ©λλ€. νμ¬λ λ©ν°λ¦¬μΌ νμΌμ μνλ¬λ₯Ό μ§μ ν νμκ° μμ§λ§, μνλ κ²½μ° μνλ¬λ₯Ό μ€μ ν μ μμ΅λλ€. μλλ₯Ό μ°Έκ³ λ°λλλ€.

// μ»΄ν¬λνΈμ ν
μ€μ³ λ°μ΄ν°λ sampler2Dλ₯Ό ν΅ν΄ μ‘μΈμ€λ¨
uniform sampler2D diffuse_texture;
...
// μ΄ νλ κ·Έλ¨ΌνΈ μ’νμμ ν
μ€μ³ μμ νμνκ³
// μ΄ μμΌλ‘ νλ κ·Έλ¨ΌνΈ μμ μ€μ ν¨
gl_FragColor = texture2D(diffuse_texture, var_texcoord0);
...
νμ¬ Defoldλ λ©ν°λ¦¬μΌ λΉ ν κ°μ ν μ€μ³λ§ μ§μν©λλ€
Sampler settings
λΉμ μ μ νμ μΌλ‘ λ©ν°λ¦¬μΌ νμΌμ νΉμ μνλ¬λ₯Ό μ€μ ν μ μμ΅λλ€. μνλ¬μμ μμ΄λ νλ‘κ·Έλ¨μμ μ¬μ©λ μ΄λ¦μ λ°λΌ μ΄λ¦μ μ νκ³ wrapκ³Ό filterλ₯Ό μνλ λλ‘ μ€μ νλ©΄ λ©λλ€.

Wrap modes
wrap λͺ¨λλ U λ° V μΆμ λ 립μ μΌλ‘ μ€μ ν μ μμ΅λλ€.
WRAP_MODE_REPEAT
[0,1] λ²μ λ°μ ν μ€μ³ λ°μ΄ν°κ° λ°λ³΅λ¨
WRAP_MODE_MIRRORED_REPEAT
[0,1] λ²μ λ°μ ν μ€μ³ λ°μ΄ν°κ° λ°λ³΅λμ§λ§ λͺ¨λ λλ²μ§Έμ λ°λ³΅μ λ―Έλ¬λ§λ¨
WRAP_MODE_CLAMP_TO_EDGE
1.0λ³΄λ€ ν° κ°μ ν μ€μ³ λ°μ΄ν°λ 1.0μΌλ‘ μ€μ λκ³ 0.0λ³΄λ€ μμ κ°μ 0.0μΌλ‘ μ€μ λ¨ (μλ₯Ό λ€μ΄ κ°μ₯μ리μ ν½μ (edge pixel)μ κ°μ₯μλ¦¬λ‘ λ°λ³΅λ¨)
Filter modes
νλ(filter_mag)μ μΆμ(filter_min)λ₯Ό κ°λ³μ μΌλ‘ νν°λ§ νκΈ° μν μ€μ μ ν μ μμ΅λλ€. Nearest νν°λ§μ Linear interpolation(μ ν 보κ°)μ λΉν΄ κ³μ°μ μ κ² νμ§λ§ κ³λ¨ νμ(aliasing artifacts)μ΄ λνλ μ μμ΅λλ€. Linear interpolation νν°λ§μ κ²°κ³Όλ¬Όμ λΆλλ½κ² λ§λ€μ΄ μ€λλ€.
FILTER_MODE_NEAREST
ν½μ μ€μ¬μ κ°μ₯ κ°κΉμ΄ μ’νμ ν μ (texel)μ΄ μ¬μ©λ©λλ€.
FILTER_MODE_LINEAR
ν½μ μ μ€μ¬μ κ°μ₯ κ°κΉμ΄μ μλ ν μ μ 2x2 λ°°μ΄μ κ°μ€ μ ν νκ· (weighted linear average)μ μ¬μ©ν©λλ€.
FILTER_MODE_NEAREST_MIPMAP_NEAREST
κ°λ³ λ°λ§΅(mipmap) λ΄μμ κ°μ₯ κ°κΉμ΄ ν μ κ°μ μ νν©λλ€.
FILTER_MODE_NEAREST_MIPMAP_LINEAR
κ°μ₯ κ°κΉμ΄ λ°λ§΅ λ κ°μμ κ°μ₯ κ°κΉμ΄ ν μ (nearest texel)μ μ ννμ¬ μ΄ λ κ° μ¬μ΄λ₯Ό μ νμ μΌλ‘ 보κ°ν©λλ€.
FILTER_MODE_LINEAR_MIPMAP_NEAREST
κ°λ³ λ°λ§΅ λ΄μμ μ νμ μΌλ‘ 보κ°ν©λλ€.
FILTER_MODE_LINEAR_MIPMAP_LINEAR
μ ν 보κ°μ μ¬μ©νμ¬ λ λ§΅μ κ°κ° κ³μ°νκ³ μ΄ λ κ° μ¬μ΄λ₯Ό μ νμ μΌλ‘ 보κ°ν©λλ€.
Vertex shader attributes
νΉμ±(attribute)μ κ°λ³ λ²ν μ€μ κ΄λ ¨λ κ°μ λλ€. κ°κΈ° λ€λ₯Έ μ»΄ν¬λνΈ νμ μ κ°κΈ° λ€λ₯Έ νΉμ± λͺ¨μμ κ°μ§κ³ μμ΅λλ€. μ΄ νΉμ±μ μμΈμ€ νκΈ° μν΄μλ μμ΄λ νλ‘κ·Έλ¨μμ μ μΈνκΈ°λ§ νλ©΄ λ©λλ€.
// μ΄ λ²ν
μ€λ₯Ό μν ν¬μ§μ
κ³Ό ν
μ€μ³ μ’ν
attribute mediump vec4 position;
attribute mediump vec2 texcoord0;
...
μ¬μ© κ°λ₯ν νΉμ±μ μλμ κ°μ΅λλ€.
Sprite
position, texcoord0
Tilegrid
position, texcoord0
Spine model
position, texcoord0
GUI node
position, textcoord0, color
ParticleFX
position, texcoord0, color
Mesh
position, texcoord0, normal
Font
position, texcoord0, face_color, outline_color, shadow_color