Created
July 4, 2025 14:28
-
-
Save binaryfox0/f1849a6a1ce7274ef119ccc9afd9a431 to your computer and use it in GitHub Desktop.
C-version of cznull's vsbm
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // 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