paddle fragment shader
This commit is contained in:
parent
5164754a26
commit
405d6b95a1
@ -14,8 +14,7 @@ extern "C" {
|
|||||||
uint length;
|
uint length;
|
||||||
};
|
};
|
||||||
|
|
||||||
void render(struct mesh paddle_mesh,
|
void render(struct mesh brick_mesh,
|
||||||
struct mesh brick_mesh,
|
|
||||||
struct mesh ball_mesh,
|
struct mesh ball_mesh,
|
||||||
uint attrib_position,
|
uint attrib_position,
|
||||||
uint attrib_texture,
|
uint attrib_texture,
|
||||||
@ -41,6 +40,16 @@ extern "C" {
|
|||||||
uint uniform_time,
|
uint uniform_time,
|
||||||
struct game_state * state);
|
struct game_state * state);
|
||||||
|
|
||||||
|
void render_paddle(struct mesh paddle_mesh,
|
||||||
|
uint attrib_position,
|
||||||
|
uint attrib_texture,
|
||||||
|
uint attrib_normal,
|
||||||
|
uint uniform_trans,
|
||||||
|
uint uniform_normal_trans,
|
||||||
|
uint uniform_light_pos,
|
||||||
|
uint uniform_time,
|
||||||
|
struct game_state * state);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
19
include/shader/paddle.fp.glsl.h
Normal file
19
include/shader/paddle.fp.glsl.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern uint32_t _binary_src_shader_paddle_fp_glsl_start __asm("_binary_src_shader_paddle_fp_glsl_start");
|
||||||
|
extern uint32_t _binary_src_shader_paddle_fp_glsl_end __asm("_binary_src_shader_paddle_fp_glsl_end");
|
||||||
|
extern uint32_t _binary_src_shader_paddle_fp_glsl_size __asm("_binary_src_shader_paddle_fp_glsl_size");
|
||||||
|
|
||||||
|
#define src_shader_paddle_fp_glsl_start ((const char *)&_binary_src_shader_paddle_fp_glsl_start)
|
||||||
|
#define src_shader_paddle_fp_glsl_end ((const char *)&_binary_src_shader_paddle_fp_glsl_end)
|
||||||
|
#define src_shader_paddle_fp_glsl_size (src_shader_paddle_fp_glsl_end - src_shader_paddle_fp_glsl_start)
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
36
src/main.c
36
src/main.c
@ -1,6 +1,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include "glad/glad.h"
|
#include "glad/glad.h"
|
||||||
|
|
||||||
@ -12,6 +13,7 @@
|
|||||||
#include "shader/font.vp.glsl.h"
|
#include "shader/font.vp.glsl.h"
|
||||||
#include "shader/background.fp.glsl.h"
|
#include "shader/background.fp.glsl.h"
|
||||||
#include "shader/background.vp.glsl.h"
|
#include "shader/background.vp.glsl.h"
|
||||||
|
#include "shader/paddle.fp.glsl.h"
|
||||||
|
|
||||||
#include "font/ter_u32n.data.h"
|
#include "font/ter_u32n.data.h"
|
||||||
|
|
||||||
@ -145,6 +147,7 @@ int main()
|
|||||||
uint uniform_normal_trans = glGetUniformLocation(program, "normal_trans");
|
uint uniform_normal_trans = glGetUniformLocation(program, "normal_trans");
|
||||||
uint uniform_base_color = glGetUniformLocation(program, "base_color");
|
uint uniform_base_color = glGetUniformLocation(program, "base_color");
|
||||||
uint uniform_light_pos = glGetUniformLocation(program, "light_pos");
|
uint uniform_light_pos = glGetUniformLocation(program, "light_pos");
|
||||||
|
printf("attrib_t %d\n", attrib_texture);
|
||||||
|
|
||||||
// font
|
// font
|
||||||
|
|
||||||
@ -157,6 +160,7 @@ int main()
|
|||||||
uint font__uniform_trans = glGetUniformLocation(font_program, "trans");
|
uint font__uniform_trans = glGetUniformLocation(font_program, "trans");
|
||||||
uint font__uniform_texture_trans = glGetUniformLocation(font_program, "texture_trans");
|
uint font__uniform_texture_trans = glGetUniformLocation(font_program, "texture_trans");
|
||||||
uint font__uniform_texture0 = glGetUniformLocation(font_program, "texture0");
|
uint font__uniform_texture0 = glGetUniformLocation(font_program, "texture0");
|
||||||
|
printf("attrib_t %d\n", font__attrib_texture);
|
||||||
|
|
||||||
// background
|
// background
|
||||||
|
|
||||||
@ -169,6 +173,20 @@ int main()
|
|||||||
uint bg__uniform_trans = glGetUniformLocation(bg_program, "trans");
|
uint bg__uniform_trans = glGetUniformLocation(bg_program, "trans");
|
||||||
uint bg__uniform_time = glGetUniformLocation(bg_program, "time");
|
uint bg__uniform_time = glGetUniformLocation(bg_program, "time");
|
||||||
|
|
||||||
|
// paddle
|
||||||
|
|
||||||
|
uint paddle_program = compile_shader(src_shader_vertex_color_vp_glsl_start,
|
||||||
|
src_shader_vertex_color_vp_glsl_size,
|
||||||
|
src_shader_paddle_fp_glsl_start,
|
||||||
|
src_shader_paddle_fp_glsl_size);
|
||||||
|
uint paddle__attrib_position = glGetAttribLocation(paddle_program, "position");
|
||||||
|
uint paddle__attrib_texture = glGetAttribLocation(paddle_program, "_texture");
|
||||||
|
uint paddle__attrib_normal = glGetAttribLocation(paddle_program, "normal");
|
||||||
|
uint paddle__uniform_trans = glGetUniformLocation(paddle_program, "trans");
|
||||||
|
uint paddle__uniform_normal_trans = glGetUniformLocation(paddle_program, "normal_trans");
|
||||||
|
uint paddle__uniform_light_pos = glGetUniformLocation(paddle_program, "light_pos");
|
||||||
|
uint paddle__uniform_time = glGetUniformLocation(paddle_program, "time");
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// textures
|
// textures
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
@ -283,9 +301,7 @@ int main()
|
|||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
glDepthFunc(GL_GREATER);
|
glDepthFunc(GL_GREATER);
|
||||||
glUseProgram(program);
|
glUseProgram(program);
|
||||||
|
render(block_mesh,
|
||||||
render(paddle_mesh,
|
|
||||||
block_mesh,
|
|
||||||
ball_mesh,
|
ball_mesh,
|
||||||
attrib_position,
|
attrib_position,
|
||||||
attrib_texture,
|
attrib_texture,
|
||||||
@ -296,10 +312,22 @@ int main()
|
|||||||
uniform_light_pos,
|
uniform_light_pos,
|
||||||
&state);
|
&state);
|
||||||
|
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
glDepthFunc(GL_GREATER);
|
||||||
|
glUseProgram(paddle_program);
|
||||||
|
render_paddle(paddle_mesh,
|
||||||
|
paddle__attrib_position,
|
||||||
|
paddle__attrib_texture,
|
||||||
|
paddle__attrib_normal,
|
||||||
|
paddle__uniform_trans,
|
||||||
|
paddle__uniform_normal_trans,
|
||||||
|
paddle__uniform_light_pos,
|
||||||
|
paddle__uniform_time,
|
||||||
|
&state);
|
||||||
|
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
glDepthFunc(GL_ALWAYS);
|
glDepthFunc(GL_ALWAYS);
|
||||||
glUseProgram(font_program);
|
glUseProgram(font_program);
|
||||||
|
|
||||||
render_font(plane_mesh,
|
render_font(plane_mesh,
|
||||||
font__attrib_position,
|
font__attrib_position,
|
||||||
font__attrib_texture,
|
font__attrib_texture,
|
||||||
|
|||||||
151
src/render.cpp
151
src/render.cpp
@ -74,8 +74,25 @@ static inline float py(float y)
|
|||||||
levels are 13x28
|
levels are 13x28
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void render(mesh paddle_mesh,
|
static inline mat4x4 aspect_mat()
|
||||||
mesh block_mesh,
|
{
|
||||||
|
float aspect = (float)vp_height / (float)vp_width;
|
||||||
|
mat4x4 p = perspective(-1, 1, 0, 1);
|
||||||
|
mat4x4 tt = translate(vec3(-1.2f, 1.4f, 2.0f));
|
||||||
|
mat4x4 a = scale(vec3(aspect, 1.0f, 1.0f)) * p * tt * scale(0.05f);
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
static float light_pos_theta = 0;
|
||||||
|
|
||||||
|
static inline vec3 _light_pos()
|
||||||
|
{
|
||||||
|
vec3 p = vec3(1, 1, 1);
|
||||||
|
vec3 pos = normalize(rotate_z(light_pos_theta) * p);
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
void render(mesh block_mesh,
|
||||||
mesh ball_mesh,
|
mesh ball_mesh,
|
||||||
uint attrib_position,
|
uint attrib_position,
|
||||||
uint attrib_texture,
|
uint attrib_texture,
|
||||||
@ -86,15 +103,7 @@ void render(mesh paddle_mesh,
|
|||||||
uint uniform_light_pos,
|
uint uniform_light_pos,
|
||||||
struct game_state * state)
|
struct game_state * state)
|
||||||
{
|
{
|
||||||
static float theta = 0;
|
light_pos_theta += 0.01;
|
||||||
|
|
||||||
float aspect = (float)vp_height / (float)vp_width;
|
|
||||||
|
|
||||||
mat4x4 p = perspective(-1, 1, 0, 1);
|
|
||||||
mat4x4 tt = translate(vec3(-1.2f, 1.4f, 2.0f));
|
|
||||||
mat4x4 a = scale(vec3(aspect, 1.0f, 1.0f)) * p * tt * scale(0.05f);// * rotate_x(PI / 4.0f);
|
|
||||||
|
|
||||||
theta += 0.01;
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// render blocks
|
// render blocks
|
||||||
@ -128,7 +137,8 @@ void render(mesh paddle_mesh,
|
|||||||
glEnableVertexAttribArray(attrib_texture);
|
glEnableVertexAttribArray(attrib_texture);
|
||||||
glEnableVertexAttribArray(attrib_normal);
|
glEnableVertexAttribArray(attrib_normal);
|
||||||
|
|
||||||
vec3 light_pos = normalize(rotate_z(theta) * vec3(1, 1, 1));
|
mat4x4 a = aspect_mat();
|
||||||
|
vec3 light_pos = _light_pos();
|
||||||
|
|
||||||
for (int y = 0; y < 28; y++) {
|
for (int y = 0; y < 28; y++) {
|
||||||
for (int x = 0; x < 13; x++) {
|
for (int x = 0; x < 13; x++) {
|
||||||
@ -170,57 +180,6 @@ void render(mesh paddle_mesh,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
// render paddle
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
{
|
|
||||||
mat4x4 rx = rotate_y(PI / 2.0f);
|
|
||||||
mat4x4 ry = rotate_x((float)state->time);
|
|
||||||
|
|
||||||
mat4x4 t = translate(vec3(state->paddle_x * 4.0f, -state->paddle_y * 2.0f, 0.0));
|
|
||||||
|
|
||||||
mat4x4 trans = a * t * ry * rx;
|
|
||||||
mat3x3 normal_trans = submatrix(ry * rx, 3, 3);
|
|
||||||
vec4 base_color = vec4(0.5f, 0.5f, 0.5f, 1.0f);
|
|
||||||
//vec3 light_pos = vec3(-1, -1, 1);
|
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, paddle_mesh.vtx);
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, paddle_mesh.idx);
|
|
||||||
|
|
||||||
glVertexAttribPointer(attrib_position,
|
|
||||||
3,
|
|
||||||
GL_FLOAT,
|
|
||||||
GL_FALSE,
|
|
||||||
(sizeof (float)) * 8,
|
|
||||||
(void*)(0 * 4)
|
|
||||||
);
|
|
||||||
glVertexAttribPointer(attrib_texture,
|
|
||||||
2,
|
|
||||||
GL_FLOAT,
|
|
||||||
GL_FALSE,
|
|
||||||
(sizeof (float)) * 8,
|
|
||||||
(void*)(3 * 4)
|
|
||||||
);
|
|
||||||
glVertexAttribPointer(attrib_normal,
|
|
||||||
3,
|
|
||||||
GL_FLOAT,
|
|
||||||
GL_FALSE,
|
|
||||||
(sizeof (float)) * 8,
|
|
||||||
(void*)(5 * 4)
|
|
||||||
);
|
|
||||||
glEnableVertexAttribArray(attrib_position);
|
|
||||||
glEnableVertexAttribArray(attrib_texture);
|
|
||||||
glEnableVertexAttribArray(attrib_normal);
|
|
||||||
|
|
||||||
glUniform4fv(uniform_trans, 4, &trans[0][0]);
|
|
||||||
glUniform3fv(uniform_normal_trans, 3, &normal_trans[0][0]);
|
|
||||||
glUniform4fv(uniform_base_color, 1, &base_color[0]);
|
|
||||||
glUniform3fv(uniform_light_pos, 1, &light_pos[0]);
|
|
||||||
|
|
||||||
glDrawElements(GL_TRIANGLES, paddle_mesh.length, GL_UNSIGNED_INT, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// render balls
|
// render balls
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
@ -235,12 +194,10 @@ void render(mesh paddle_mesh,
|
|||||||
|
|
||||||
mat4x4 trans = a * t * ry * rx;
|
mat4x4 trans = a * t * ry * rx;
|
||||||
mat3x3 normal_trans = submatrix(ry * rx, 3, 3);
|
mat3x3 normal_trans = submatrix(ry * rx, 3, 3);
|
||||||
//vec4 base_color = vec4(0.5f, 0.5f, 0.5f, 1.0f);
|
|
||||||
float hue = state->time - ball.launch_time;
|
float hue = state->time - ball.launch_time;
|
||||||
hue = hue - floorf(hue);
|
hue = hue - floorf(hue);
|
||||||
vec3 c = hsv_to_rgb(hue, 1.0f, 1.0f);
|
vec3 c = hsv_to_rgb(hue, 1.0f, 1.0f);
|
||||||
vec4 base_color = vec4(c.x, c.y, c.z, 1.0f);
|
vec4 base_color = vec4(c.x, c.y, c.z, 1.0f);
|
||||||
//vec3 light_pos = vec3(-1, -1, 1);
|
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, ball_mesh.vtx);
|
glBindBuffer(GL_ARRAY_BUFFER, ball_mesh.vtx);
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ball_mesh.idx);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ball_mesh.idx);
|
||||||
@ -275,7 +232,7 @@ void render(mesh paddle_mesh,
|
|||||||
glUniform4fv(uniform_base_color, 1, &base_color[0]);
|
glUniform4fv(uniform_base_color, 1, &base_color[0]);
|
||||||
glUniform3fv(uniform_light_pos, 1, &light_pos[0]);
|
glUniform3fv(uniform_light_pos, 1, &light_pos[0]);
|
||||||
|
|
||||||
glDrawElements(GL_TRIANGLES, paddle_mesh.length, GL_UNSIGNED_INT, 0);
|
glDrawElements(GL_TRIANGLES, ball_mesh.length, GL_UNSIGNED_INT, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -391,3 +348,65 @@ void render_background(struct mesh plane_mesh,
|
|||||||
|
|
||||||
glDrawElements(GL_TRIANGLES, plane_mesh.length, GL_UNSIGNED_INT, 0);
|
glDrawElements(GL_TRIANGLES, plane_mesh.length, GL_UNSIGNED_INT, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// render paddle
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void render_paddle(mesh paddle_mesh,
|
||||||
|
uint attrib_position,
|
||||||
|
uint attrib_texture,
|
||||||
|
uint attrib_normal,
|
||||||
|
uint uniform_trans,
|
||||||
|
uint uniform_normal_trans,
|
||||||
|
uint uniform_light_pos,
|
||||||
|
uint uniform_time,
|
||||||
|
struct game_state * state)
|
||||||
|
{
|
||||||
|
mat4x4 rx = rotate_y(PI / 2.0f);
|
||||||
|
mat4x4 ry = rotate_x((float)state->time);
|
||||||
|
|
||||||
|
mat4x4 t = translate(vec3(state->paddle_x * 4.0f, -state->paddle_y * 2.0f, 0.0));
|
||||||
|
mat4x4 a = aspect_mat();
|
||||||
|
|
||||||
|
mat4x4 trans = a * t * ry * rx;
|
||||||
|
mat3x3 normal_trans = submatrix(ry * rx, 3, 3);
|
||||||
|
vec3 light_pos = _light_pos();
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, paddle_mesh.vtx);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, paddle_mesh.idx);
|
||||||
|
|
||||||
|
glVertexAttribPointer(attrib_position,
|
||||||
|
3,
|
||||||
|
GL_FLOAT,
|
||||||
|
GL_FALSE,
|
||||||
|
(sizeof (float)) * 8,
|
||||||
|
(void*)(0 * 4)
|
||||||
|
);
|
||||||
|
glVertexAttribPointer(attrib_texture,
|
||||||
|
2,
|
||||||
|
GL_FLOAT,
|
||||||
|
GL_FALSE,
|
||||||
|
(sizeof (float)) * 8,
|
||||||
|
(void*)(3 * 4)
|
||||||
|
);
|
||||||
|
glVertexAttribPointer(attrib_normal,
|
||||||
|
3,
|
||||||
|
GL_FLOAT,
|
||||||
|
GL_FALSE,
|
||||||
|
(sizeof (float)) * 8,
|
||||||
|
(void*)(5 * 4)
|
||||||
|
);
|
||||||
|
glEnableVertexAttribArray(attrib_position);
|
||||||
|
glEnableVertexAttribArray(attrib_texture);
|
||||||
|
glEnableVertexAttribArray(attrib_normal);
|
||||||
|
|
||||||
|
glUniform4fv(uniform_trans, 4, &trans[0][0]);
|
||||||
|
glUniform3fv(uniform_normal_trans, 3, &normal_trans[0][0]);
|
||||||
|
glUniform3fv(uniform_light_pos, 1, &light_pos[0]);
|
||||||
|
glUniform1f(uniform_time, state->time);
|
||||||
|
|
||||||
|
glDrawElements(GL_TRIANGLES, paddle_mesh.length, GL_UNSIGNED_INT, 0);
|
||||||
|
}
|
||||||
|
|||||||
@ -17,5 +17,5 @@ void main()
|
|||||||
float d = length(uv);
|
float d = length(uv);
|
||||||
float td = time * 0.5 + d;
|
float td = time * 0.5 + d;
|
||||||
|
|
||||||
gl_FragColor = vec4(palette(td) * 0.2, 1);
|
gl_FragColor = vec4(palette(td) * 0.1, 1);
|
||||||
}
|
}
|
||||||
|
|||||||
41
src/shader/paddle.fp.glsl
Normal file
41
src/shader/paddle.fp.glsl
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#version 120
|
||||||
|
|
||||||
|
uniform vec3 light_pos;
|
||||||
|
uniform float time;
|
||||||
|
|
||||||
|
varying vec3 fp_position;
|
||||||
|
varying vec2 fp_texture;
|
||||||
|
varying vec3 fp_normal;
|
||||||
|
|
||||||
|
vec3 palette(float d) {
|
||||||
|
vec3 v = d + vec3(0, 0.33, 0.67);
|
||||||
|
v = v * 6.28318548202514648438;
|
||||||
|
v = cos(v);
|
||||||
|
return vec3(0.5, 0.5, 0.5) * v + vec3(0.5, 0.5, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec3 light_dir = normalize(light_pos - fp_position);
|
||||||
|
float diffuse = max(dot(fp_normal, light_dir), 0.0);
|
||||||
|
|
||||||
|
vec2 uv = fp_texture;
|
||||||
|
float td = uv.x + -time;
|
||||||
|
|
||||||
|
float d = sin(dot(uv, uv) * 8.0 + time * 6) / 8.0;
|
||||||
|
d = abs(d);
|
||||||
|
d = 0.05 / d;
|
||||||
|
|
||||||
|
float dy = 0;
|
||||||
|
/*
|
||||||
|
float dy = sin(uv.y * 8.0 + time * 6) / 8.0;
|
||||||
|
dy = abs(dy);
|
||||||
|
dy = 0.05 / dy;
|
||||||
|
*/
|
||||||
|
|
||||||
|
vec3 colorA = palette(td) * (d + dy);
|
||||||
|
vec3 colorB = palette(td);
|
||||||
|
|
||||||
|
gl_FragColor = vec4(mix(colorA, colorB, 0.5) * (diffuse), 1);
|
||||||
|
//gl_FragColor = vec4(abs(fp_texture.xy), 0, 1);
|
||||||
|
}
|
||||||
@ -4,8 +4,8 @@ uniform vec4 base_color;
|
|||||||
uniform vec3 light_pos;
|
uniform vec3 light_pos;
|
||||||
|
|
||||||
varying vec3 fp_position;
|
varying vec3 fp_position;
|
||||||
varying vec3 fp_normal;
|
|
||||||
varying vec2 fp_texture;
|
varying vec2 fp_texture;
|
||||||
|
varying vec3 fp_normal;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user