Skip to content

Instantly share code, notes, and snippets.

@jsimmons
Created May 9, 2013 18:43
Show Gist options
  • Save jsimmons/c7f76de823d5d58829d8 to your computer and use it in GitHub Desktop.
Save jsimmons/c7f76de823d5d58829d8 to your computer and use it in GitHub Desktop.
#include <assert.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <math.h>
#ifndef M_PI
#define M_PI 3.14159265358979323846264338327
#endif
#include "sgl.h"
#include "jsb_chrono.h"
#include "jsb_vec.h"
#include "jsb_mat.h"
#include "gl_core_3_3.h"
static const char *vert_shader_src =
"#version 150\n"
"uniform mat4 clip_from_model;"
"layout(location = 0) in vec3 position;"
"layout(location = 1) in vec3 color;"
"layout(location = 2) out vec3 vert_color;"
"out gl_PerVertex"
"{"
" vec4 gl_Position;"
" float gl_PointSize;"
"};"
"void main() {"
" vert_color = color;"
" gl_Position = clip_from_model * vec4(position, 1.0);"
" gl_PointSize = 2.0;"
"}";
static const char *frag_shader_src =
"#version 150\n"
"layout(location = 2) in vec3 color;"
"layout(location = 0) out vec3 frag_color;"
"void main() {"
" frag_color = color;"
"}";
static unsigned vao, vbo;
static unsigned vert, frag, pipe;
static int clip_from_model_uniform;
static struct jsb_mat4 view_from_world = {.mat={0}}, clip_from_view = {.mat={0}}, clip_from_model = {.mat={0}};
static void check_program(unsigned program)
{
int linked;
glGetProgramiv(program, GL_LINK_STATUS, &linked);
if(linked == GL_FALSE)
{
int info_log_size;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &info_log_size);
char *info_log = malloc(info_log_size);
glGetProgramInfoLog(program, info_log_size, NULL, info_log);
fprintf(stderr, "error compiling shader program:\n%s", info_log);
free(info_log);
exit(1);
}
}
static void check_pipeline(unsigned pipeline)
{
int validated;
glValidateProgramPipeline(pipeline);
glGetProgramPipelineiv(pipeline, GL_VALIDATE_STATUS, &validated);
if(validated == GL_FALSE)
{
int info_log_size;
glGetProgramPipelineiv(pipeline, GL_INFO_LOG_LENGTH, &info_log_size);
char *info_log = malloc(info_log_size);
glGetProgramPipelineInfoLog(pipeline, info_log_size, NULL, info_log);
fprintf(stderr, "error validating program pipeline:\n%s", info_log);
free(info_log);
exit(1);
}
}
static struct jsb_vec3 hello_cube[] = {
{.xyz={ 1.0f, 1.0f, 1.0f}}, {.xyz={1.0f, 0.0f, 0.0f}}, {.xyz={-1.0f, 1.0f, 1.0f}}, {.xyz={1.0f, 0.0f, 0.0f}}, {.xyz={-1.0f,-1.0f, 1.0f}}, {.xyz={1.0f, 0.0f, 0.0f}}, // v0-v1-v2 (front)
{.xyz={-1.0f,-1.0f, 1.0f}}, {.xyz={1.0f, 0.0f, 0.0f}}, {.xyz={ 1.0f,-1.0f, 1.0f}}, {.xyz={1.0f, 0.0f, 0.0f}}, {.xyz={ 1.0f, 1.0f, 1.0f}}, {.xyz={1.0f, 0.0f, 0.0f}}, // v2-v3-v0
{.xyz={ 1.0f, 1.0f, 1.0f}}, {.xyz={0.0f, 1.0f, 0.0f}}, {.xyz={ 1.0f,-1.0f, 1.0f}}, {.xyz={0.0f, 1.0f, 0.0f}}, {.xyz={ 1.0f,-1.0f,-1.0f}}, {.xyz={0.0f, 1.0f, 0.0f}}, // v0-v3-v4 (right)
{.xyz={ 1.0f,-1.0f,-1.0f}}, {.xyz={0.0f, 1.0f, 0.0f}}, {.xyz={ 1.0f, 1.0f,-1.0f}}, {.xyz={0.0f, 1.0f, 0.0f}}, {.xyz={ 1.0f, 1.0f, 1.0f}}, {.xyz={0.0f, 1.0f, 0.0f}}, // v4-v5-v0
{.xyz={ 1.0f, 1.0f, 1.0f}}, {.xyz={0.0f, 0.0f, 1.0f}}, {.xyz={ 1.0f, 1.0f,-1.0f}}, {.xyz={0.0f, 0.0f, 1.0f}}, {.xyz={-1.0f, 1.0f,-1.0f}}, {.xyz={0.0f, 0.0f, 1.0f}}, // v0-v5-v6 (top)
{.xyz={-1.0f, 1.0f,-1.0f}}, {.xyz={0.0f, 0.0f, 1.0f}}, {.xyz={-1.0f, 1.0f, 1.0f}}, {.xyz={0.0f, 0.0f, 1.0f}}, {.xyz={ 1.0f, 1.0f, 1.0f}}, {.xyz={0.0f, 0.0f, 1.0f}}, // v6-v1-v0
{.xyz={-1.0f, 1.0f, 1.0f}}, {.xyz={1.0f, 1.0f, 0.0f}}, {.xyz={-1.0f, 1.0f,-1.0f}}, {.xyz={1.0f, 1.0f, 0.0f}}, {.xyz={-1.0f,-1.0f,-1.0f}}, {.xyz={1.0f, 1.0f, 0.0f}}, // v1-v6-v7 (left)
{.xyz={-1.0f,-1.0f,-1.0f}}, {.xyz={1.0f, 1.0f, 0.0f}}, {.xyz={-1.0f,-1.0f, 1.0f}}, {.xyz={1.0f, 1.0f, 0.0f}}, {.xyz={-1.0f, 1.0f, 1.0f}}, {.xyz={1.0f, 1.0f, 0.0f}}, // v7-v2-v1
{.xyz={-1.0f,-1.0f,-1.0f}}, {.xyz={0.0f, 1.0f, 1.0f}}, {.xyz={ 1.0f,-1.0f,-1.0f}}, {.xyz={0.0f, 1.0f, 1.0f}}, {.xyz={ 1.0f,-1.0f, 1.0f}}, {.xyz={0.0f, 1.0f, 1.0f}}, // v7-v4-v3 (bottom)
{.xyz={ 1.0f,-1.0f, 1.0f}}, {.xyz={0.0f, 1.0f, 1.0f}}, {.xyz={-1.0f,-1.0f, 1.0f}}, {.xyz={0.0f, 1.0f, 1.0f}}, {.xyz={-1.0f,-1.0f,-1.0f}}, {.xyz={0.0f, 1.0f, 1.0f}}, // v3-v2-v7
{.xyz={ 1.0f,-1.0f,-1.0f}}, {.xyz={1.0f, 1.0f, 1.0f}}, {.xyz={-1.0f,-1.0f,-1.0f}}, {.xyz={1.0f, 1.0f, 1.0f}}, {.xyz={-1.0f, 1.0f,-1.0f}}, {.xyz={1.0f, 1.0f, 1.0f}}, // v4-v7-v6 (back)
{.xyz={-1.0f, 1.0f,-1.0f}}, {.xyz={1.0f, 1.0f, 1.0f}}, {.xyz={ 1.0f, 1.0f,-1.0f}}, {.xyz={1.0f, 1.0f, 1.0f}}, {.xyz={ 1.0f,-1.0f,-1.0f}}, {.xyz={1.0f, 1.0f, 1.0f}} // v6-v5-v4
};
struct point_set
{
size_t num_points;
struct jsb_vec3 *points;
};
static struct point_set ps;
static inline float random_float(float min, float max)
{
return min + (float)rand() / ((float)RAND_MAX / (max - min));
}
static void build_point_set(struct point_set *self, size_t num_points)
{
srand((unsigned)time(0));
self->num_points = num_points;
self->points = malloc(sizeof(struct jsb_vec3) * num_points);
for(size_t i = 0; i < num_points; i++)
{
// comma operatorrrr
float x = random_float(-100.0f, 100.0f), y = random_float(-100.0f, 100.0f), z = random_float(-100.0f, 100.0f);
self->points[i].xyz[0] = x;
self->points[i].xyz[1] = y;
self->points[i].xyz[2] = z;
}
}
static void turn_setup(void)
{
(void)hello_cube; // unused
glGenProgramPipelines(1, &pipe);
glBindProgramPipeline(pipe);
vert = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &vert_shader_src);
check_program(vert);
glUseProgramStages(pipe, GL_VERTEX_SHADER_BIT, vert);
frag = glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, &frag_shader_src);
check_program(frag);
glUseProgramStages(pipe, GL_FRAGMENT_SHADER_BIT, frag);
check_pipeline(pipe);
clip_from_model_uniform = glGetUniformLocation(vert, "clip_from_model");
uint64_t build_point_set_begin = jsb_chrono_monotonic();
build_point_set(&ps, 16384);
uint64_t build_point_set_end = jsb_chrono_monotonic();
printf("build point set took %zuµs\n", build_point_set_end - build_point_set_begin);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glNamedBufferDataEXT(vbo, ps.num_points * sizeof(struct jsb_vec3), ps.points, GL_STATIC_DRAW);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
//glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(0);
//glEnableVertexAttribArray(1);
jsb_mat4_perspective(clip_from_view.mat, M_PI * 0.5, 1366.0f / 768.0f, 0.5, 500.0f);
}
struct jsb_vec3 eye = {.xyz = {100.0f, 100.0f, 100.0f}};
static float accum = 0.0f;
static void turn_draw(void)
{
accum += 0.0025;
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
struct jsb_vec3 at = {.xyz = {0.0f, 0.0f, 0.0f}};
struct jsb_vec3 up = {.xyz = {0.0f, 0.0f, 1.0f}};
jsb_mat4_look_at(view_from_world.mat, eye.xyz, at.xyz, up.xyz);
struct jsb_mat4 world_from_model;
struct jsb_vec3 rotation_axis = {.xyz={0.0f, 0.0f, 1.0f}};
jsb_mat4_rotate(world_from_model.mat, JSB_MAT4_IDENTITY.mat, accum, rotation_axis.xyz);
struct jsb_mat4 clip_from_world;
jsb_mat4_mul(clip_from_world.mat, clip_from_view.mat, view_from_world.mat);
jsb_mat4_mul(clip_from_model.mat, clip_from_world.mat, world_from_model.mat);
glProgramUniformMatrix4fvEXT(vert, clip_from_model_uniform, 1, false, clip_from_model.mat);
glEnable(GL_CULL_FACE);
glEnable(GL_PROGRAM_POINT_SIZE);
glDrawArrays(GL_POINTS, 0, ps.num_points);
}
static void turn_entry(void)
{
jsb_chrono_startup();
sgl_startup();
struct sgl_window_options window_options = {
.x = 0,
.y = 0,
.width = 800,
.height = 600,
.colour_bits = 32,
.depth_bits = 24,
.stencil_bits = 8,
.msaa_samples = 4,
.double_buffer = true,
.vertical_sync = true,
.stereo = false
};
struct sgl_window *window = sgl_window_create(&window_options);
assert(window);
sgl_window_set_title(window, "TURN");
sgl_window_set_cursor_visible(window, false);
sgl_window_set_fullscreen(window, true);
sgl_window_set_monitors(window, 0, 0, 0, 0);
struct sgl_context_options context_options = {
.version_major = 3,
.version_minor = 3,
.core_profile = true, /* core profile */
.forward_compatible = true, /* forward compatibility */
.debug = true, /* enable context debugging */
.share = NULL /* pass a struct sgl_context * to share
data between contexts */
};
struct sgl_context *context = sgl_context_create(window, &context_options);
assert(context);
sgl_context_bind(window, context);
gl_core_load();
turn_setup();
struct sgl_event event;
for(;;)
{
while(sgl_event_read(window, &event))
{
switch(event.type)
{
case SGL_EVENT_GEOMETRY:
break;
case SGL_EVENT_LEAVE:
case SGL_EVENT_FOCUS_OUT:
break;
case SGL_EVENT_ENTER:
case SGL_EVENT_FOCUS_IN:
break;
case SGL_EVENT_BUTTON_PRESS:
break;
case SGL_EVENT_BUTTON_RELEASE:
break;
case SGL_EVENT_KEY_PRESS:
switch(event.device.unicode)
{
case 'w':
eye.xyz[1] -= 10.0;
break;
case 's':
eye.xyz[1] += 10.0;
break;
case 'a':
eye.xyz[0] -= 10.0;
break;
case 'd':
eye.xyz[0] += 10.0;
break;
case 'z':
eye.xyz[2] += 10.0;
break;
case 'x':
eye.xyz[2] -= 10.0;
break;
case '\x1B':
goto shutdown;
default:
break;
}
break;
case SGL_EVENT_KEY_RELEASE:
break;
case SGL_EVENT_MOTION:
break;
case SGL_EVENT_RAW_MOTION:
break;
case SGL_EVENT_CLOSE:
printf("shutting down!\n");
goto shutdown;
break;
default:
break;
}
}
turn_draw();
sgl_window_swap(window);
}
shutdown:
sgl_context_unbind();
sgl_context_destroy(context);
sgl_window_destroy(window);
sgl_cleanup();
}
int main(int argc, const char **argv)
{
(void)argc;
(void)argv;
turn_entry();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment