Skip to content

Instantly share code, notes, and snippets.

@binaryfox0
Created July 4, 2025 14:28
Show Gist options
  • Select an option

  • Save binaryfox0/f1849a6a1ce7274ef119ccc9afd9a431 to your computer and use it in GitHub Desktop.

Select an option

Save binaryfox0/f1849a6a1ce7274ef119ccc9afd9a431 to your computer and use it in GitHub Desktop.
C-version of cznull's vsbm
// ported code of https://github.com/cznull/cznull.github.io/blob/master/vsbm.html
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <math.h>
#include "GL/glew.h"
#include "GLFW/glfw3.h"
#define min(a, b) ((a) < (b) ? (a) : (b))
void print_shader_log(GLuint id, bool program) {
GLint success = 0;
program ? glGetProgramiv(id, GL_LINK_STATUS, &success) : glGetShaderiv(id, GL_COMPILE_STATUS, &success);
if(!success) {
GLint log_len = 0;
(program ? glGetProgramiv : glGetShaderiv)(id, GL_INFO_LOG_LENGTH, &log_len);
char* str = malloc(log_len);
glGetShaderInfoLog(id, log_len, 0, str);
fprintf(stderr, "%s log: %s\n", program ? "Link" : "Compile" , str);
free(str);
}
}
GLuint init_shader()
{
const char* vertex_shader =
"#version 330 core\n"
"layout (location = 0) in vec4 position;\n"
"out vec3 dir;\n"
"out vec3 localdir;\n"
"uniform vec3 right, forward, up, origin;\n"
// x and y will always be 1, the window size is a square
// "uniform float x,y;\n"
"void main() {\n"
" gl_Position = position; \n"
" dir = forward + right * position.x + up * position.y;\n"
" localdir.x = position.x;\n"
" localdir.y = position.y;\n"
" localdir.z = -1.0;\n"
"} ";
GLuint vertex = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex, 1, &vertex_shader, 0);
glCompileShader(vertex);
print_shader_log(vertex, false);
const char* fragment_shader =
"#version 330 core\n"
"#define PI 3.14159265358979324\n"
"#define M_L 0.3819660113\n"
"#define M_R 0.6180339887\n"
"#define MAXR 8\n"
"#define SOLVER 8\n"
"float kernal(vec3 ver){\n"
" vec3 a;\n"
"float b,c,d,e;\n"
" a=ver;\n"
" for(int i=0;i<5;i++){\n"
" b = length(a);\n"
" c = atan(a.y, a.x)*8.0;\n"
" e = 1.0/b;\n"
" d = acos(a.z/b)*8.0;\n"
" b = pow(b,8.0);\n"
" a = vec3(b*sin(d)*cos(c),b*sin(d)*sin(c),b*cos(d))+ver;\n"
" if(b > 6.0){\n"
" break;\n"
" }\n"
" }"
" return 4.0-a.x*a.x-a.y*a.y-a.z*a.z;"
"}"
"uniform vec3 right, forward, up, origin;\n"
"in vec3 dir;\n"
"in vec3 localdir;\n"
"uniform float len;\n"
"vec3 ver;\n"
"int sign;"
"float v, v1, v2;\n"
"float r1, r2, r3, r4, m1, m2, m3, m4;\n"
"vec3 n, reflect;\n"
"const float step = 0.002;\n"
"vec3 color;\n"
"void main() {\n"
" color.r=0.0;\n"
" color.g=0.0;\n"
" color.b=0.0;\n"
" sign=0;"
" v1 = kernal(origin + dir * (step*len));\n"
" v2 = kernal(origin);\n"
" for (int k = 2; k < 1002; k++) {\n"
" ver = origin + dir * (step*len*float(k));\n"
" v = kernal(ver);\n"
" if (v > 0.0 && v1 < 0.0) {\n"
" r1 = step * len*float(k - 1);\n"
" r2 = step * len*float(k);\n"
" m1 = kernal(origin + dir * r1);\n"
" m2 = kernal(origin + dir * r2);\n"
" for (int l = 0; l < SOLVER; l++) {\n"
" r3 = r1 * 0.5 + r2 * 0.5;\n"
" m3 = kernal(origin + dir * r3);\n"
" if (m3 > 0.0) {\n"
" r2 = r3;\n"
" m2 = m3;\n"
" }\n"
" else {\n"
" r1 = r3;\n"
" m1 = m3;\n"
" }\n"
" }\n"
" if (r3 < 2.0 * len) {\n"
" sign=1;"
" break;\n"
" }\n"
" }\n"
" if (v < v1&&v1>v2&&v1 < 0.0 && (v1*2.0 > v || v1 * 2.0 > v2)) {\n"
" r1 = step * len*float(k - 2);\n"
" r2 = step * len*(float(k) - 2.0 + 2.0*M_L);\n"
" r3 = step * len*(float(k) - 2.0 + 2.0*M_R);\n"
" r4 = step * len*float(k);\n"
" m2 = kernal(origin + dir * r2);\n"
" m3 = kernal(origin + dir * r3);\n"
" for (int l = 0; l < MAXR; l++) {\n"
" if (m2 > m3) {\n"
" r4 = r3;\n"
" r3 = r2;\n"
" r2 = r4 * M_L + r1 * M_R;\n"
" m3 = m2;\n"
" m2 = kernal(origin + dir * r2);\n"
" }\n"
" else {\n"
" r1 = r2;\n"
" r2 = r3;\n"
" r3 = r4 * M_R + r1 * M_L;\n"
" m2 = m3;\n"
" m3 = kernal(origin + dir * r3);\n"
" }\n"
" }\n"
" if (m2 > 0.0) {\n"
" r1 = step * len*float(k - 2);\n"
" r2 = r2;\n"
" m1 = kernal(origin + dir * r1);\n"
" m2 = kernal(origin + dir * r2);\n"
" for (int l = 0; l < SOLVER; l++) {\n"
" r3 = r1 * 0.5 + r2 * 0.5;\n"
" m3 = kernal(origin + dir * r3);\n"
" if (m3 > 0.0) {\n"
" r2 = r3;\n"
" m2 = m3;\n"
" }\n"
" else {\n"
" r1 = r3;\n"
" m1 = m3;\n"
" }\n"
" }\n"
" if (r3 < 2.0 * len&&r3> step*len) {\n"
" sign=1;"
" break;\n"
" }\n"
" }\n"
" else if (m3 > 0.0) {\n"
" r1 = step * len*float(k - 2);\n"
" r2 = r3;\n"
" m1 = kernal(origin + dir * r1);\n"
" m2 = kernal(origin + dir * r2);\n"
" for (int l = 0; l < SOLVER; l++) {\n"
" r3 = r1 * 0.5 + r2 * 0.5;\n"
" m3 = kernal(origin + dir * r3);\n"
" if (m3 > 0.0) {\n"
" r2 = r3;\n"
" m2 = m3;\n"
" }\n"
" else {\n"
" r1 = r3;\n"
" m1 = m3;\n"
" }\n"
" }\n"
" if (r3 < 2.0 * len&&r3> step*len) {\n"
" sign=1;"
" break;\n"
" }\n"
" }\n"
" }\n"
" v2 = v1;\n"
" v1 = v;\n"
" }\n"
" if (sign==1) {\n"
" ver = origin + dir*r3 ;\n"
" r1=ver.x*ver.x+ver.y*ver.y+ver.z*ver.z;"
" n.x = kernal(ver - right * (r3*0.00025)) - kernal(ver + right * (r3*0.00025));\n"
" n.y = kernal(ver - up * (r3*0.00025)) - kernal(ver + up * (r3*0.00025));\n"
" n.z = kernal(ver + forward * (r3*0.00025)) - kernal(ver - forward * (r3*0.00025));\n"
" r3 = n.x*n.x+n.y*n.y+n.z*n.z;\n"
" n = n * (1.0 / sqrt(r3));\n"
" ver = localdir;\n"
" r3 = ver.x*ver.x+ver.y*ver.y+ver.z*ver.z;\n"
" ver = ver * (1.0 / sqrt(r3));\n"
" reflect = n * (-2.0*dot(ver, n)) + ver;\n"
" r3 = reflect.x*0.276+reflect.y*0.920+reflect.z*0.276;\n"
" r4 = n.x*0.276+n.y*0.920+n.z*0.276;\n"
" r3 = max(0.0,r3);\n"
" r3 = r3 * r3*r3*r3;\n"
" r3 = r3 * 0.45 + r4 * 0.25 + 0.3;\n"
" n.x = sin(r1*10.0)*0.5+0.5;\n"
" n.y = sin(r1*10.0+2.05)*0.5+0.5;\n"
" n.z = sin(r1*10.0-2.05)*0.5+0.5;\n"
" color = n*r3;\n"
" }\n"
" gl_FragColor = vec4(color.x, color.y, color.z, 1.0);\n"
"}";
GLuint fragment = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment, 1, &fragment_shader, 0);
glCompileShader(fragment);
print_shader_log(fragment, false);
GLuint program = glCreateProgram();
glAttachShader(program, vertex);
glAttachShader(program, fragment);
glLinkProgram(program);
print_shader_log(program, true);
glDeleteShader(vertex);
glDeleteShader(fragment);
return program;
}
bool ml = false, mr = false;
void mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
{
if(action == GLFW_PRESS) {
if(button == GLFW_MOUSE_BUTTON_LEFT)
;
}
if(action == GLFW_RELEASE) {
}
}
GLfloat len = 1.6f;
GLfloat ang1 = 2.8f, ang2 = 0.4f;
GLdouble mx = 0, my = 0;
GLfloat cenx = 0.0f, ceny = 0.0f, cenz = 0.0f;
int size = 0;
void cursor_pos_callback(GLFWwindow* window, double xpos, double ypos)
{
if (ml == 1) {
ang1 += (xpos - mx) * 0.002;
ang2 += (ypos - my) * 0.002;
}
if (mr == 1) {
double l = len * 4.0 / (size + size);
cenx += l * (-(xpos - mx) * sin(ang1) - (ypos - my) * sin(ang2) * cos(ang1));
ceny += l * ((ypos - my) * cos(ang2));
cenz += l * ((xpos - mx) * cos(ang1) - (ypos - my) * sin(ang2) * sin(ang1));
}
mx = xpos;
my = ypos;
}
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) {
len *= exp(-0.1 * yoffset);
}
int main() {
if(!glfwInit()) {
return 1;
}
const GLFWvidmode* mode = glfwGetVideoMode(glfwGetPrimaryMonitor());
size = min(mode->width, min(mode->height, 720));
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
GLFWwindow* window = glfwCreateWindow(size, size, "vsbm", 0, 0);
if(!window) {
glfwTerminate();
return 1;
}
glfwMakeContextCurrent(window);
glfwSetMouseButtonCallback(window, mouse_button_callback);
glfwSetCursorPosCallback(window, cursor_pos_callback);
glfwSetScrollCallback(window, scroll_callback);
if(glewInit() != GLEW_OK) {
glfwDestroyWindow(window);
glfwTerminate();
return 1;
}
GLuint shader = init_shader();
float vertices[] = {
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
-1.0f, -1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f
};
GLuint vao, vbo = 0;
glGenVertexArrays(1, &vao);
glGenBuffers(1, &vbo);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
GLint right_loc = glGetUniformLocation(shader, "right");
GLint forward_loc = glGetUniformLocation(shader, "forward");
GLint up_loc = glGetUniformLocation(shader, "up");
GLint origin_loc = glGetUniformLocation(shader, "origin");
GLint x_loc = glGetUniformLocation(shader, "x");
GLint y_loc = glGetUniformLocation(shader, "y");
GLint len_loc = glGetUniformLocation(shader, "len");
while(!glfwWindowShouldClose(window)) {
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shader);
// glUniform1f(x_loc, size * 2.0 / (size + size));
// glUniform1f(y_loc, size * 2.0 / (size + size));
glUniform1f(len_loc, len);
glUniform3f(origin_loc, len * cos(ang1) * cos(ang2) + cenx, len * sin(ang2) + ceny, len * sin(ang1) * cos(ang2) + cenz);
glUniform3f(right_loc, sin(ang1), 0, -cos(ang1));
glUniform3f(up_loc, -sin(ang2) * cos(ang1), cos(ang2), -sin(ang2) * sin(ang1));
glUniform3f(forward_loc, -cos(ang1) * cos(ang2), -sin(ang2), -sin(ang1) * cos(ang2));
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, 6);
ang1 += 0.01;
glfwSwapBuffers(window);
glfwPollEvents();
}
glDeleteVertexArrays(1, &vao);
glDeleteBuffers(1, &vbo);
glDeleteShader(shader);
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment