Class: Bestguigui::Render3D::Shader
- Inherits:
-
Object
- Object
- Bestguigui::Render3D::Shader
- Includes:
- OpenGL
- Defined in:
- lib/bestguigui/render_3d/shader.rb
Overview
Programme shader GLSL (vertex + fragment) compilé et linké. ObjModel et Billboard utilisent un shader par défaut fourni par la gem (Shader.default) — n'en écris un toi-même que si tu veux un rendu différent (éclairage, effet...).
Constant Summary collapse
- DEFAULT_VERTEX =
<<~GLSL #version 330 core layout(location = 0) in vec3 a_position; layout(location = 1) in vec2 a_texcoord; uniform mat4 u_model; uniform mat4 u_view; uniform mat4 u_projection; out vec2 v_texcoord; void main() { gl_Position = u_projection * u_view * u_model * vec4(a_position, 1.0); v_texcoord = a_texcoord; } GLSL
- DEFAULT_FRAGMENT =
<<~GLSL #version 330 core in vec2 v_texcoord; out vec4 frag_color; uniform sampler2D u_texture; uniform bool u_alpha_test; uniform vec3 u_tint; void main() { vec4 tex_color = texture(u_texture, v_texcoord); if (u_alpha_test && tex_color.a <= 0.0) discard; frag_color = vec4(tex_color.rgb * u_tint, tex_color.a); } GLSL
- GOURAUD_VERTEX =
<<~GLSL #version 330 core layout(location = 0) in vec3 a_position; layout(location = 1) in vec2 a_texcoord; layout(location = 2) in vec3 a_normal; uniform mat4 u_model; uniform mat4 u_view; uniform mat4 u_projection; uniform vec3 u_light_dir; // vers la lumière, normalisé uniform vec3 u_light_color; uniform float u_ambient; out vec2 v_texcoord; out vec3 v_light; void main() { gl_Position = u_projection * u_view * u_model * vec4(a_position, 1.0); v_texcoord = a_texcoord; // Lighting computed per-vertex here (not per-pixel in the // fragment shader), then interpolated across the face - real // Gouraud shading, PS1/FF7-style. Ignores non-uniform model // scale (raw mat3(u_model)) - good enough for a jam. vec3 n = normalize(mat3(u_model) * a_normal); // u_light_dir = direction vers laquelle la lumière voyage (ex: un // soleil au-dessus pointe vers le bas) -> on l'inverse ici pour // avoir la direction vers la source, celle qu'attend Lambert. float diffuse = max(dot(n, -u_light_dir), 0.0); v_light = u_light_color * (u_ambient + (1.0 - u_ambient) * diffuse); } GLSL
- GOURAUD_FRAGMENT =
<<~GLSL #version 330 core in vec2 v_texcoord; in vec3 v_light; out vec4 frag_color; uniform sampler2D u_texture; uniform bool u_alpha_test; uniform vec3 u_tint; void main() { vec4 tex_color = texture(u_texture, v_texcoord); if (u_alpha_test && tex_color.a <= 0.0) discard; frag_color = vec4(tex_color.rgb * v_light * u_tint, tex_color.a); } GLSL
Class Method Summary collapse
-
.default ⇒ Object
Shader unlit texturé + alpha-test optionnel, utilisé par défaut par ObjModel et Billboard.
-
.gouraud ⇒ Object
Shader texturé + éclairage Gouraud (une lumière directionnelle, voir Bestguigui::Render3D::Light), utilisé par ObjModel.new(..., lighting: true).
Instance Method Summary collapse
-
#initialize(vertex_src, fragment_src) ⇒ Shader
constructor
A new instance of Shader.
- #set_bool(name, value) ⇒ Object
- #set_float(name, value) ⇒ Object
- #set_int(name, value) ⇒ Object
- #set_mat4(name, mat4) ⇒ Object
- #set_vec3(name, r, g, b) ⇒ Object
- #use ⇒ Object
Constructor Details
#initialize(vertex_src, fragment_src) ⇒ Shader
Returns a new instance of Shader.
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
# File 'lib/bestguigui/render_3d/shader.rb', line 10 def initialize(vertex_src, fragment_src) vs = compile(GL_VERTEX_SHADER, vertex_src) fs = compile(GL_FRAGMENT_SHADER, fragment_src) @program = glCreateProgram() glAttachShader(@program, vs) glAttachShader(@program, fs) glLinkProgram(@program) status = status_buffer glGetProgramiv(@program, GL_LINK_STATUS, status) if status.unpack1("L").zero? log = " " * 2048 glGetProgramInfoLog(@program, 2048, nil, log) raise "Bestguigui::Render3D::Shader link error: #{log.unpack1('Z*')}" end end |
Class Method Details
.default ⇒ Object
Shader unlit texturé + alpha-test optionnel, utilisé par défaut par ObjModel et Billboard. Une seule instance partagée.
91 92 93 |
# File 'lib/bestguigui/render_3d/shader.rb', line 91 def self.default @default ||= new(DEFAULT_VERTEX, DEFAULT_FRAGMENT) end |
.gouraud ⇒ Object
Shader texturé + éclairage Gouraud (une lumière directionnelle,
voir Bestguigui::Render3D::Light), utilisé par
ObjModel.new(..., lighting: true). A besoin de normales par sommet
dans le Mesh (layout: :pos_uv_normal) — sans ça, comportement
indéfini côté attribut a_normal.
150 151 152 |
# File 'lib/bestguigui/render_3d/shader.rb', line 150 def self.gouraud @gouraud ||= new(GOURAUD_VERTEX, GOURAUD_FRAGMENT) end |
Instance Method Details
#set_bool(name, value) ⇒ Object
42 43 44 |
# File 'lib/bestguigui/render_3d/shader.rb', line 42 def set_bool(name, value) set_int(name, value ? 1 : 0) end |
#set_float(name, value) ⇒ Object
46 47 48 49 |
# File 'lib/bestguigui/render_3d/shader.rb', line 46 def set_float(name, value) loc = glGetUniformLocation(@program, name) glUniform1f(loc, value) end |
#set_int(name, value) ⇒ Object
37 38 39 40 |
# File 'lib/bestguigui/render_3d/shader.rb', line 37 def set_int(name, value) loc = glGetUniformLocation(@program, name) glUniform1i(loc, value) end |
#set_mat4(name, mat4) ⇒ Object
32 33 34 35 |
# File 'lib/bestguigui/render_3d/shader.rb', line 32 def set_mat4(name, mat4) loc = glGetUniformLocation(@program, name) glUniformMatrix4fv(loc, 1, GL_FALSE, mat4.to_a.pack("F16")) end |
#set_vec3(name, r, g, b) ⇒ Object
51 52 53 54 |
# File 'lib/bestguigui/render_3d/shader.rb', line 51 def set_vec3(name, r, g, b) loc = glGetUniformLocation(@program, name) glUniform3f(loc, r, g, b) end |
#use ⇒ Object
28 29 30 |
# File 'lib/bestguigui/render_3d/shader.rb', line 28 def use glUseProgram(@program) end |