diff options
-rw-r--r-- | assets/ball_f.glsl | 19 | ||||
-rw-r--r-- | assets/ball_v.glsl | 9 | ||||
-rw-r--r-- | assets/platform_f.glsl | 2 | ||||
-rw-r--r-- | assets/platform_v.glsl | 3 | ||||
-rw-r--r-- | sim.c | 78 | ||||
-rw-r--r-- | sim.h | 17 |
6 files changed, 113 insertions, 15 deletions
diff --git a/assets/ball_f.glsl b/assets/ball_f.glsl new file mode 100644 index 0000000..e3dfdb3 --- /dev/null +++ b/assets/ball_f.glsl @@ -0,0 +1,19 @@ +varying vec4 color; +varying vec2 pos; +uniform vec2 center; +uniform float radius; + +void main() { + float dist_squared = dot(pos - center, pos - center); + float threshold = 0.9 * radius; // radius border starts at + float thickness = radius - threshold; + + if (dist_squared > threshold * threshold && dist_squared < radius * radius) { + float dist = sqrt(dist_squared); + float v = (dist - threshold) / thickness; + v = 2.0 * v - 1.0; + gl_FragColor = color * (1.0 - v * v); + } else { + discard; + } +} diff --git a/assets/ball_v.glsl b/assets/ball_v.glsl new file mode 100644 index 0000000..7908bc7 --- /dev/null +++ b/assets/ball_v.glsl @@ -0,0 +1,9 @@ +varying vec4 color; +varying vec2 pos; +uniform mat4 transform; + +void main() { + gl_Position = transform * gl_Vertex; + pos = gl_Vertex.xy; + color = gl_Color; +} diff --git a/assets/platform_f.glsl b/assets/platform_f.glsl index 1969a46..82c8740 100644 --- a/assets/platform_f.glsl +++ b/assets/platform_f.glsl @@ -5,11 +5,13 @@ uniform float thickness; void main() { // thanks to https://www.youtube.com/watch?v=PMltMdi1Wzg + // (calculates distance to line segment p1-p2) float h = clamp(dot(pos-p1, p2-p1) / dot(p2-p1, p2-p1), 0.0, 1.0); float d = length(pos - p1 - (p2-p1) * h); float v = max(thickness - d, 0.0); v /= thickness; + v *= v; gl_FragColor = color * v; } diff --git a/assets/platform_v.glsl b/assets/platform_v.glsl index 472f9df..8f57aab 100644 --- a/assets/platform_v.glsl +++ b/assets/platform_v.glsl @@ -4,9 +4,10 @@ varying vec4 color; varying vec2 p1, p2; varying vec2 pos; uniform float thickness; +uniform mat4 transform; void main() { - gl_Position = gl_Vertex; + gl_Position = transform * gl_Vertex; pos = gl_Vertex.xy; color = gl_Color; #if 1 @@ -22,7 +22,7 @@ // compile a vertex or fragment shader static GLuint shader_compile_from_file(GL *gl, char const *filename, GLenum shader_type) { FILE *fp = fopen(filename, "rb"); - if (filename) { + if (fp) { char code[16384] = {0}; char log[4096] = {0}; char const *const_code = code; @@ -41,6 +41,7 @@ static GLuint shader_compile_from_file(GL *gl, char const *filename, GLenum shad } return shader; } else { + logln("File does not exist: %s.", filename); return 0; } } @@ -124,16 +125,26 @@ static bool shader_needs_reloading(ShaderBase *shader) { #endif static void shader_platform_load(GL *gl, ShaderPlatform *shader) { - shader_load(gl, &shader->base, "assets/platform_v.glsl", "assets/platform_f.glsl"); - shader->vertex_p1 = shader_attrib_location(gl, &shader->base, "vertex_p1"); - shader->vertex_p2 = shader_attrib_location(gl, &shader->base, "vertex_p2"); - shader->uniform_thickness = shader_uniform_location(gl, &shader->base, "thickness"); - // @TODO: transform matrix + ShaderBase *base = &shader->base; + shader_load(gl, base, "assets/platform_v.glsl", "assets/platform_f.glsl"); + shader->vertex_p1 = shader_attrib_location(gl, base, "vertex_p1"); + shader->vertex_p2 = shader_attrib_location(gl, base, "vertex_p2"); + shader->uniform_thickness = shader_uniform_location(gl, base, "thickness"); + shader->uniform_transform = shader_uniform_location(gl, base, "transform"); +} + +static void shader_ball_load(GL *gl, ShaderBall *shader) { + ShaderBase *base = &shader->base; + shader_load(gl, base, "assets/ball_v.glsl", "assets/ball_f.glsl"); + shader->uniform_transform = shader_uniform_location(gl, base, "transform"); + shader->uniform_center = shader_uniform_location(gl, base, "center"); + shader->uniform_radius = shader_uniform_location(gl, base, "radius"); } static void shaders_load(State *state) { GL *gl = &state->gl; shader_platform_load(gl, &state->shader_platform); + shader_ball_load(gl, &state->shader_ball); } #if DEBUG @@ -141,18 +152,24 @@ static void shaders_reload_if_necessary(State *state) { GL *gl = &state->gl; if (shader_needs_reloading(&state->shader_platform.base)) shader_platform_load(gl, &state->shader_platform); + if (shader_needs_reloading(&state->shader_ball.base)) + shader_ball_load(gl, &state->shader_ball); } #endif - +// render the given platforms static void platforms_render(State *state, Platform *platforms, u32 nplatforms) { GL *gl = &state->gl; ShaderPlatform *shader = &state->shader_platform; - glColor3f(1,0,1); - float thickness = 0.01f; + float thickness = 0.005f; + shader_start_using(gl, &shader->base); + gl->Uniform1f(shader->uniform_thickness, thickness); + gl->UniformMatrix4fv(shader->uniform_transform, 1, GL_FALSE, state->transform.e); + glBegin(GL_QUADS); + glColor3f(1,0,1); for (Platform *platform = platforms, *end = platform + nplatforms; platform != end; ++platform) { // calculate endpoints of platform maybe_unused float radius = platform->size * 0.5f; @@ -176,6 +193,29 @@ static void platforms_render(State *state, Platform *platforms, u32 nplatforms) shader_stop_using(gl); } +// render the ball +static void ball_render(State *state) { + GL *gl = &state->gl; + float ball_x = 0.5f, ball_y = 0.8f; + float ball_r = 0.02f; + ShaderBall *shader = &state->shader_ball; + + shader_start_using(gl, &shader->base); + + gl->UniformMatrix4fv(shader->uniform_transform, 1, GL_FALSE, state->transform.e); + gl->Uniform2f(shader->uniform_center, ball_x, ball_y); + gl->Uniform1f(shader->uniform_radius, ball_r); + + glBegin(GL_QUADS); + glColor3f(1,1,1); + glVertex2f(ball_x-ball_r, ball_y-ball_r); + glVertex2f(ball_x-ball_r, ball_y+ball_r); + glVertex2f(ball_x+ball_r, ball_y+ball_r); + glVertex2f(ball_x+ball_r, ball_y-ball_r); + glEnd(); + shader_stop_using(gl); +} + #ifdef _WIN32 __declspec(dllexport) #endif @@ -197,16 +237,24 @@ void sim_frame(Frame *frame) { state->win_width = width; state->win_height = height; + state->gl_width = (float)width / (float)height; + state->dt = (float)frame->dt; + state->transform = m4_ortho(0, state->gl_width, 0, 1, -1, +1); + // set up GL glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glViewport(0, 0, width, height); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - //glOrtho(, -1, +1); + glOrtho(0, state->gl_width, 0, 1, -1, +1); glClearColor(0, 0, 0, 1); glClear(GL_COLOR_BUFFER_BIT); + + if (keys_pressed[KEY_F5]) { + memset(state, 0, sizeof *state); + } if (!state->initialized) { @@ -252,11 +300,16 @@ void sim_frame(Frame *frame) { shaders_load(state); - state->nplatforms = 1; + state->nplatforms = 2; Platform *p = &state->platforms[0]; p->center = V2(0.5f, 0.5f); - p->angle = 0;//PIf * 0.3f; + p->angle = PIf * 0.3f; p->size = 0.2f; + ++p; + p->center = V2(0.2f, 0.5f); + p->angle = PIf * 0.6f; + p->size = 0.1f; + state->initialized = true; #if DEBUG @@ -273,6 +326,7 @@ void sim_frame(Frame *frame) { #endif platforms_render(state, state->platforms, state->nplatforms); + ball_render(state); #if DEBUG GLuint error = glGetError(); @@ -90,12 +90,19 @@ typedef struct { typedef GLuint VertexAttributeLocation; typedef GLint UniformLocation; +// shader for platforms typedef struct { ShaderBase base; - VertexAttributeLocation vertex_p1, vertex_p2; - UniformLocation uniform_thickness; + VertexAttributeLocation vertex_p1, vertex_p2; // endpoints of platform + UniformLocation uniform_thickness; // this is half the "width" of the platform + UniformLocation uniform_transform; // 4x4 matrix position is multiplied by } ShaderPlatform; +typedef struct { + ShaderBase base; + UniformLocation uniform_transform, uniform_center, uniform_radius; +} ShaderBall; + typedef struct { v2 center; float size; @@ -104,10 +111,16 @@ typedef struct { typedef struct { bool initialized; + i32 win_width, win_height; // width,height of window + float gl_width; // width of window in GL coordinates; height is always 1 + + float dt; // time in seconds since last frame + m4 transform; // the transform for converting our coordinates to GL coordinates GL gl; // gl functions ShaderPlatform shader_platform; + ShaderBall shader_ball; u32 nplatforms; Platform platforms[1000]; |