5#include <smk/Color.hpp>
6#include <smk/Drawable.hpp>
7#include <smk/RenderTarget.hpp>
8#include <smk/Texture.hpp>
11bool g_invalidate_textures =
false;
14RenderTarget* render_target =
nullptr;
15RenderState cached_render_state_;
17const Texture& WhiteTexture() {
19 static const uint8_t data[4] = {255, 255, 255, 255};
28void RenderTarget::Bind(RenderTarget* target) {
29 if (render_target == target) {
32 render_target = target;
33 glBindFramebuffer(GL_FRAMEBUFFER, render_target->frame_buffer_);
34 glViewport(0, 0, render_target->width_, render_target->height_);
43 operator=(std::move(other));
48 std::swap(width_, other.width_);
49 std::swap(height_, other.height_);
50 std::swap(projection_matrix_, other.projection_matrix_);
51 std::swap(view_, other.view_);
52 std::swap(vertex_shader_2d_, other.vertex_shader_2d_);
53 std::swap(fragment_shader_2d_, other.fragment_shader_2d_);
54 std::swap(shader_program_2d_, other.shader_program_2d_);
55 std::swap(vertex_shader_3d_, other.vertex_shader_3d_);
56 std::swap(fragment_shader_3d_, other.fragment_shader_3d_);
57 std::swap(shader_program_3d_, other.shader_program_3d_);
58 std::swap(shader_program_, other.shader_program_);
59 std::swap(frame_buffer_, other.frame_buffer_);
67 glClearColor(color.r, color.g, color.b, color.a);
68 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
69 glDisable(GL_DEPTH_TEST);
70 glDisable(GL_CULL_FACE);
77 float z_x = +2.F /
view.width_;
78 float z_y = -2.F /
view.height_;
79 float t_x = -
view.
x_ * z_x;
80 float t_y = -
view.y_ * z_y;
81 SetView(glm::mat4(z_x, 0.F, 0.F, 0.F,
91 projection_matrix_ = mat;
141 shader_program_ = shader_program;
142 shader_program_.
Use();
144 shader_program_.
SetUniform(
"color", glm::vec4(1.F, 1.F, 1.F, 1.F));
145 shader_program_.
SetUniform(
"projection", glm::mat4(1.F));
146 shader_program_.
SetUniform(
"view", glm::mat4(1.F));
152 return shader_program_2d_;
157 return shader_program_3d_;
166 state.
view = glm::mat4(1.F);
169 drawable.
Draw(*
this, state);
176 if (cached_render_state_.vertex_array != state.
vertex_array) {
182 if (cached_render_state_.shader_program != state.
shader_program) {
184 cached_render_state_.shader_program.
Use();
188 if (cached_render_state_.color != state.
color) {
189 cached_render_state_.color = state.
color;
190 cached_render_state_.shader_program.SetUniform(
"color", state.
color);
199 if (cached_render_state_.texture != texture || g_invalidate_textures) {
200 cached_render_state_.texture = texture;
202 g_invalidate_textures =
false;
205 if (cached_render_state_.blend_mode != state.
blend_mode) {
206 cached_render_state_.blend_mode = state.
blend_mode;
208 glBlendEquationSeparate(state.
blend_mode.equation_rgb,
220 return glm::vec2(width_, height_);
235void RenderTarget::InitRenderTarget() {
237 default_view.
SetCenter(
float(width_) / 2.F,
float(height_) / 2.F);
238 default_view.
SetSize(
float(width_),
float(height_));
242 layout(location = 0) in vec2 space_position;
243 layout(location = 1) in vec2 texture_position;
245 uniform mat4 projection;
248 out vec2 f_texture_position;
251 f_texture_position = texture_position;
252 gl_Position = projection * view * vec4(space_position, 0.F, 1.F);
258 in vec2 f_texture_position;
259 uniform sampler2D texture_0;
264 out_color = texture(texture_0, f_texture_position) * color;
269 shader_program_2d_.AddShader(vertex_shader_2d_);
270 shader_program_2d_.AddShader(fragment_shader_2d_);
271 shader_program_2d_.Link();
274 layout(location = 0) in vec3 space_position;
275 layout(location = 1) in vec3 normal;
276 layout(location = 2) in vec2 texture_position;
278 uniform mat4 projection;
286 fTexture = texture_position;
287 fPosition = view * vec4(space_position,1.F);
288 fNormal = vec3(view * vec4(normal,0.F));
290 gl_Position = projection * fPosition;
296 uniform sampler2D texture_0;
299 uniform vec4 light_position;
300 uniform float ambient;
301 uniform float diffuse;
302 uniform float specular;
303 uniform float specular_power;
313 vec3 object_dir =-normalize(fPosition.xyz);
314 vec3 normal_dir = normalize(fNormal);
315 vec3 light_dir = normalize(light_position.xyz-fPosition.xyz);
316 vec3 reflect_dir = -reflect(object_dir,normal_dir);
318 float diffuse_strength = max(0.F, dot(normal_dir, light_dir));
319 float specular_strength = pow(max(0.F, dot(reflect_dir, light_dir)),
322 out_color = texture(texture_0, fTexture);
323 out_color.rgb *= ambient +
324 diffuse * diffuse_strength +
325 specular * specular_strength;
331 shader_program_3d_.AddShader(vertex_shader_3d_);
332 shader_program_3d_.AddShader(fragment_shader_3d_);
333 shader_program_3d_.Link();
335 shader_program_3d_.Use();
336 constexpr auto default_light_position = glm::vec4(0.F, 5.F, 0.F, 1.F);
337 constexpr auto default_ambient = 0.3F;
338 constexpr auto default_diffuse = 0.5F;
339 constexpr auto default_specular = 0.5F;
340 constexpr auto default_specular_power = 4.F;
341 shader_program_3d_.
SetUniform(
"light_position", default_light_position);
342 shader_program_3d_.
SetUniform(
"ambient", default_ambient);
343 shader_program_3d_.
SetUniform(
"diffuse", default_diffuse);
344 shader_program_3d_.
SetUniform(
"specular", default_specular);
345 shader_program_3d_.
SetUniform(
"specular_power", default_specular_power);
Interface for class that can be draw to a smk::RenderTarget.
virtual void Draw(RenderTarget &target, RenderState state) const =0
RenderTarget & operator=(RenderTarget &&other) noexcept
Move operator.
void SetView(const View &view)
Set the View to use.
void SetShaderProgram(ShaderProgram &shader_program)
Set the ShaderProgram to be used.
ShaderProgram & shader_program_2d()
Return the default predefined 2D shader program. It is bound by default.
const View & view() const
Return the View currently assigned to this RenderTarget.
int height() const
the height of the surface.
virtual void Draw(const Drawable &drawable)
Draw on the surface.
ShaderProgram & shader_program_3d()
Return the default predefined 3D shader program.
RenderTarget()
Build an invalid RenderTarget. It can be replaced later by using the move operator.
glm::vec2 dimensions() const
the dimension (width, height) of the drawing area.
void Clear(const glm::vec4 &color)
Clear the surface with a single color.
int width() const
the width of the surface.
A shader program is a set of shader (for instance vertex shader + pixel shader) defining the renderin...
void SetUniform(const std::string &name, float x, float y, float z)
Assign shader vec3 uniform.
void AddShader(const Shader &shader)
Add a Shader to the program list. This must called multiple time for each shader components before ca...
void Use() const
Bind the ShaderProgram. Future draw will use it. This unbind any previously bound ShaderProgram.
void Link() const
Add a Shader to the program list.
static Shader FromString(const std::string &content, GLenum type)
Load a shader from a std::string.
size_t size() const
The size of the GPU array.
void SetCenter(float x, float y)
Set the center position of the in-game view. param x The center of the view along the horizontal axis...
void SetSize(float width, float height)
Set the size of the in-game view. param width The size of the view along the horizontal axis....
const glm::vec4 White
White.
static const BlendMode Alpha
destination = source * source.a + destination * (1 - souce.a)
Contain all the data needed to draw.
glm::mat4 view
The "view" transformation.
glm::vec4 color
The masking color.
Texture texture
The texture 0 bound.
BlendMode blend_mode
The OpenGL BlendMode.
VertexArray vertex_array
The shape to to be drawn.
ShaderProgram shader_program
The shader used.
GLuint id() const
Access the ID of the texture.