Added a function to generate texture templates. Drawn some stupid textures for my stupid cylinders

This commit is contained in:
Андреев Григорий 2025-07-27 10:51:33 +03:00
parent a666755c03
commit f66c1618d2
22 changed files with 1500 additions and 845 deletions

8
.gitignore vendored
View File

@ -2,5 +2,9 @@
cmake-build-debug/
.idea/
vgcore.*
gen/
*.pdf
/gen/
*.pdf
*.r8g8b8a8
*.r8b8g8
*.r8
*.xcf

View File

@ -15,6 +15,9 @@ add_executable(1_test src/l1/tests/t1.c)
add_executable(0_render_test src/l2/tests/r0.c)
target_link_libraries(0_render_test -lvulkan -lX11 -lm)
add_executable(0_render_test_tex_init_prep src/l2/tests/r0_tex_init_prep.c)
target_link_libraries(0_render_test_tex_init_prep -lm)
add_executable(0_play_test src/l3/tests/p0.c)
target_link_libraries(0_play_test -lncurses)

View File

@ -21,9 +21,16 @@ ConstSpanU8 ConstSpanU8_from_cstr(const char* dc) {
}
#define cstr(dc) ConstSpanU8_from_cstr(dc)
/* Not thread safe (for stdout) !*/
void ConstSpanU8_print(ConstSpanU8 str) {
for (size_t i = 0; i < str.len; i++)
putchar((int)*ConstSpanU8_at(str, i));
putc((int)*ConstSpanU8_at(str, i), stdout);
}
/* Not thread safe (for `stream`) ! */
void ConstSpanU8_fprint( ConstSpanU8 str, FILE* stream) {
for (size_t i = 0; i < str.len; i++)
putc((int)*ConstSpanU8_at(str, i), stream);
}
SpanT_VecT_trivmove_COMPLETE_Definition(U16)

View File

@ -57,5 +57,7 @@ T MAX_##T (T a, T b){ return a < b ? b : a; }
int_minmax_function_Definition(U8)
int_minmax_function_Definition(U32)
int_minmax_function_Definition(U64)
int_minmax_function_Definition(float)
int_minmax_function_Definition(double)
#endif

View File

@ -0,0 +1,772 @@
#ifndef PROTOTYPE_SRC_L1_GEN_GEOM_AND_TEXTURES_H
#define PROTOTYPE_SRC_L1_GEN_GEOM_AND_TEXTURES_H
#include <stdio.h>
#include "../system/fileio.h"
#include "../core/VecU8_format.h"
NODISCARD VecU8 begin_header(ConstSpanU8 guard) {
VecU8 res = VecU8_new();
VecU8_append_span(&res, cstr("#ifndef "));
VecU8_append_span(&res, guard);
VecU8_append_span(&res, cstr("\n#define "));
VecU8_append_span(&res, guard);
VecU8_append_span(&res, cstr("\n/* Automatically generated file. Do not edit it. */\n\n"));
return res;
}
/* Codegen script's working directory should be `gen` */
void finish_header(VecU8 text_before_endif, const char* filename) {
VecU8_append_span(&text_before_endif, cstr("#endif\n"));
write_whole_file_or_abort(filename, VecU8_to_ConstSpanU8(&text_before_endif));
VecU8_drop(text_before_endif);
}
#define SPACE4 " "
#define SPACE8 " "
#define SPACE12 " "
void string_append_vec_field_name(VecU8* str, int ci) {
assert(0 <= ci && ci < 4);
VecU8_append(str, ci == 3 ? 'w' : 'x' + ci);
}
void string_append_xvecy(VecU8* str, ConstSpanU8 xvec, int cc) {
VecU8_append_span(str, xvec);
VecU8_append(str, '0' + cc);
}
NODISCARD VecU8 generate_xvecy_struct_definition(ConstSpanU8 xvec, ConstSpanU8 member, int cc) {
assert(2 <= cc && cc <= 4);
VecU8 res = VecU8_new();
VecU8_append_span(&res, cstr("typedef struct {\n"));
for (int ci = 0; ci < cc; ci++) {
VecU8_append_span(&res, cstr(SPACE4));
VecU8_append_span(&res, member);
VecU8_append(&res, ' ');
string_append_vec_field_name(&res, ci);
VecU8_append_span(&res, cstr(";\n"));
}
VecU8_append_span(&res, cstr("} "));
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr(";\n\n"));
return res;
}
NODISCARD VecU8 generate_xvecy_method_add_xvecy(ConstSpanU8 xvec, ConstSpanU8 member, int cc) {
VecU8 res = VecU8_new();
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr(" "));
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr("_add_"));
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr("("));
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr(" A, "));
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr(" B) {\n" SPACE4 "return ("));
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr("){ "));
for (int ci = 0; ci < cc; ci++) {
if (ci)
VecU8_append_span(&res, cstr(", "));
VecU8_append_span(&res, cstr("A."));
string_append_vec_field_name(&res, ci);
VecU8_append_span(&res, cstr(" + B."));
string_append_vec_field_name(&res, ci);
}
VecU8_append_span(&res, cstr(" };\n}\n\n"));
return res;
}
NODISCARD VecU8 generate_xvecy_method_minus_xvecy(ConstSpanU8 xvec, ConstSpanU8 member, int cc) {
VecU8 res = VecU8_new();
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr(" "));
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr("_minus_"));
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr("("));
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr(" A, "));
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr(" B) {\n" SPACE4 "return ("));
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr("){ "));
for (int ci = 0; ci < cc; ci++) {
if (ci)
VecU8_append_span(&res, cstr(", "));
VecU8_append_span(&res, cstr("A."));
string_append_vec_field_name(&res, ci);
VecU8_append_span(&res, cstr(" - B."));
string_append_vec_field_name(&res, ci);
}
VecU8_append_span(&res, cstr(" };\n}\n\n"));
return res;
}
NODISCARD VecU8 generate_xvecy_method_minus(ConstSpanU8 xvec, ConstSpanU8 member, int cc) {
VecU8 res = VecU8_new();
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr(" "));
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr("_minus("));
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr(" A) {\n" SPACE4 "return("));
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr("){ "));
for (int ci = 0; ci < cc; ci++) {
if (ci)
VecU8_append_span(&res, cstr(", "));
VecU8_append_span(&res, cstr("-A."));
string_append_vec_field_name(&res, ci);
}
VecU8_append_span(&res, cstr(" };\n}\n\n"));
return res;
}
NODISCARD VecU8 generate_xvecy_method_mul_scal(ConstSpanU8 xvec, ConstSpanU8 member, int cc) {
VecU8 res = VecU8_new();
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr(" "));
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr("_mul_scal("));
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr(" A, "));
VecU8_append_span(&res, member);
VecU8_append_span(&res, cstr(" B) {\n" SPACE4 "return ("));
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr("){ "));
for (int ci = 0; ci < cc; ci++) {
if (ci)
VecU8_append_span(&res, cstr(", "));
VecU8_append_span(&res, cstr("A."));
string_append_vec_field_name(&res, ci);
VecU8_append_span(&res, cstr(" * B"));
}
VecU8_append_span(&res, cstr(" };\n}\n\n"));
return res;
}
NODISCARD VecU8 generate_xvecy_method_div_by_scal(ConstSpanU8 xvec, ConstSpanU8 member, int cc) {
VecU8 res = VecU8_new();
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr(" "));
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr("_div_by_scal("));
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr(" A, "));
VecU8_append_span(&res, member);
VecU8_append_span(&res, cstr(" B){\n" SPACE4 "return "));
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr("_mul_scal(A, 1/B);\n}\n\n"));
return res;
}
void string_append_xmatnm(VecU8* str, ConstSpanU8 xmat, int cols, int rows) {
VecU8_append_span(str, xmat);
VecU8_append(str, '0' + cols);
if (rows != cols) {
VecU8_append(str, 'x');
VecU8_append(str, '0' + rows);
}
}
/* With columns padded to 16 bytes (for std140, std140 is our everything) */
NODISCARD VecU8 generate_xmatnm_structure_definition(ConstSpanU8 xmat, ConstSpanU8 xvec, int cols, int rows, int sizeof_member) {
int sv = (rows * sizeof_member) % 16;
VecU8 res = VecU8_from_cstr("typedef struct {\n");
for (int x = 0; x < cols; x++) {
VecU8_append_span(&res, cstr(SPACE4));
string_append_xvecy(&res, xvec, rows);
VecU8_append_span(&res, cstr(" "));
string_append_vec_field_name(&res, x);
VecU8_append_span(&res, cstr(";\n"));
if (sv) {
VecU8_append_vec(&res, VecU8_format(SPACE4 "char _padding_%d[%d];\n", x, 16 - sv));
}
}
VecU8_append_span(&res, cstr("} "));
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append_span(&res, cstr(";\n\n"));
return res;
}
void string_append_mat_col_definition(VecU8* str, int ci) {
VecU8_append(str, '.');
string_append_vec_field_name(str, ci);
VecU8_append_span(str, cstr(" = "));
}
void string_append_mat_el_access(VecU8* str, int x, int y) {
VecU8_append(str, '.');
string_append_vec_field_name(str, x);
VecU8_append(str, '.');
string_append_vec_field_name(str, y);
}
NODISCARD VecU8 generate_xmatnm_method_new(ConstSpanU8 xmat, ConstSpanU8 xvec, ConstSpanU8 member, int cols, int rows) {
VecU8 res = VecU8_new();
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append(&res, ' ');
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append_span(&res, cstr("_new("));
for (int y = 0; y < rows; y++) {
for (int x = 0; x < cols; x++) {
if (x > 0 || y > 0)
VecU8_append_span(&res, cstr(", "));
VecU8_append_span(&res, member);
VecU8_append(&res, ' ');
string_append_vec_field_name(&res, x);
string_append_vec_field_name(&res, y);
}
}
VecU8_append_span(&res, cstr(") {\n" SPACE4 "return ("));
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append_span(&res, cstr("){ "));
for (int x = 0; x < cols; x++) {
if (x)
VecU8_append_span(&res, cstr(", "));
string_append_mat_col_definition(&res, x);
VecU8_append_span(&res, cstr("{ "));
for (int y = 0; y < rows; y++) {
if (y)
VecU8_append_span(&res, cstr(", "));
string_append_vec_field_name(&res, x);
string_append_vec_field_name(&res, y);
}
VecU8_append_span(&res, cstr(" }"));
}
VecU8_append_span(&res, cstr(" };\n}\n\n"));
return res;
}
NODISCARD VecU8 generate_square_xmatnn_E_definition(ConstSpanU8 xmat, int n) {
VecU8 res = VecU8_from_cstr("const ");
string_append_xmatnm(&res, xmat, n, n);
VecU8_append(&res, ' ');
string_append_xmatnm(&res, xmat, n, n);
VecU8_append_span(&res, cstr("_E = { "));
for (int x = 0; x < n; x++) {
if (x)
VecU8_append_span(&res, cstr(", "));
string_append_mat_col_definition(&res, x);
VecU8_append_span(&res, cstr("{ "));
for (int y = 0; y < n; y++) {
if (y)
VecU8_append_span(&res, cstr(", "));
VecU8_append(&res, '0' + (x == y));
}
VecU8_append_span(&res, cstr(" }"));
}
VecU8_append_span(&res, cstr(" };\n\n"));
return res;
}
NODISCARD VecU8 generate_xmatnm_method_add_xmatnm(ConstSpanU8 xmat, ConstSpanU8 xvec, ConstSpanU8 member, int cols, int rows) {
VecU8 res = VecU8_new();
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append(&res, ' ');
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append_span(&res, cstr("_add_"));
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append_span(&res, cstr("("));
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append_span(&res, cstr(" A, "));
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append_span(&res, cstr(" B) {\n" SPACE4 "return ("));
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append_span(&res, cstr("){ "));
for (int x = 0; x < cols; x++) {
if (x)
VecU8_append_span(&res, cstr(", "));
string_append_mat_col_definition(&res, x);
string_append_xvecy(&res, xvec, rows);
VecU8_append_span(&res, cstr("_add_"));
string_append_xvecy(&res, xvec, rows);
VecU8_append_span(&res, cstr("(A."));
string_append_vec_field_name(&res, x);
VecU8_append_span(&res, cstr(", B."));
string_append_vec_field_name(&res, x);
VecU8_append_span(&res, cstr(")"));
}
VecU8_append_span(&res, cstr(" };\n}\n\n"));
return res;
}
NODISCARD VecU8 generate_xmatnm_method_minus_xmatnm(ConstSpanU8 xmat, ConstSpanU8 xvec, ConstSpanU8 member, int cols, int rows) {
VecU8 res = VecU8_new();
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append(&res, ' ');
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append_span(&res, cstr("_minus_"));
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append_span(&res, cstr("("));
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append_span(&res, cstr(" A, "));
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append_span(&res, cstr(" B) {\n" SPACE4 "return ("));
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append_span(&res, cstr("){ "));
for (int x = 0; x < cols; x++) {
if (x)
VecU8_append_span(&res, cstr(", "));
string_append_mat_col_definition(&res, x);
string_append_xvecy(&res, xvec, rows);
VecU8_append_span(&res, cstr("_minus_"));
string_append_xvecy(&res, xvec, rows);
VecU8_append_span(&res, cstr("(A."));
string_append_vec_field_name(&res, x);
VecU8_append_span(&res, cstr(", B."));
string_append_vec_field_name(&res, x);
VecU8_append_span(&res, cstr(")"));
}
VecU8_append_span(&res, cstr(" };\n}\n\n"));
return res;
}
NODISCARD VecU8 generate_xmatnm_method_minus(ConstSpanU8 xmat, ConstSpanU8 xvec, ConstSpanU8 member, int cols, int rows) {
VecU8 res = VecU8_new();
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append(&res, ' ');
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append_span(&res, cstr("_minus("));
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append_span(&res, cstr(" A) {\n" SPACE4 "return ("));
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append_span(&res, cstr("){ "));
for (int x = 0; x < cols; x++) {
if (x)
VecU8_append_span(&res, cstr(", "));
string_append_mat_col_definition(&res, x);
string_append_xvecy(&res, xvec, rows);
VecU8_append_span(&res, cstr("_minus(A."));
string_append_vec_field_name(&res, x);
VecU8_append_span(&res, cstr(")"));
}
VecU8_append_span(&res, cstr(" };\n}\n\n"));
return res;
}
NODISCARD VecU8 generate_xmatnm_method_mul_scal(ConstSpanU8 xmat, ConstSpanU8 xvec, ConstSpanU8 member, int cols, int rows) {
VecU8 res = VecU8_new();
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append(&res, ' ');
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append_span(&res, cstr("_mul_scal("));
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append_span(&res, cstr(" A, "));
VecU8_append_span(&res, member);
VecU8_append_span(&res, cstr(" B) {\n" SPACE4 "return ("));
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append_span(&res, cstr("){ "));
for (int x = 0; x < cols; x++) {
if (x)
VecU8_append_span(&res, cstr(", "));
string_append_mat_col_definition(&res, x);
string_append_xvecy(&res, xvec, rows);
VecU8_append_span(&res, cstr("_mul_scal(A."));
string_append_vec_field_name(&res, x);
VecU8_append_span(&res, cstr(", B)"));
}
VecU8_append_span(&res, cstr(" };\n}\n\n"));
return res;
}
NODISCARD VecU8 generate_xmatnm_method_div_by_scal(ConstSpanU8 xmat, ConstSpanU8 xvec, ConstSpanU8 member, int cols, int rows) {
VecU8 res = VecU8_new();
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append(&res, ' ');
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append_span(&res, cstr("_div_by_scal("));
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append_span(&res, cstr(" A, "));
VecU8_append_span(&res, member);
VecU8_append_span(&res, cstr(" B) {\n" SPACE4 "return "));
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append_span(&res, cstr("_mul_scal(A, 1/B);\n}\n\n"));
return res;
}
NODISCARD VecU8 generate_xvecn_method_dot_xvecn(ConstSpanU8 xvec, ConstSpanU8 member, int n) {
VecU8 res = VecU8_from_span(member);
VecU8_append(&res, ' ');
string_append_xvecy(&res, xvec, n);
VecU8_append_span(&res, cstr("_dot_"));
string_append_xvecy(&res, xvec, n);
VecU8_append(&res, '(');
string_append_xvecy(&res, xvec, n);
VecU8_append_span(&res, cstr(" A, "));
string_append_xvecy(&res, xvec, n);
VecU8_append_span(&res, cstr(" B) {\n" SPACE4 "return "));
for (int i = 0; i < n; i++) {
if (i)
VecU8_append_span(&res, cstr(" + "));
VecU8_append_span(&res, cstr("A."));
string_append_vec_field_name(&res, i);
VecU8_append_span(&res, cstr(" * B."));
string_append_vec_field_name(&res, i);
}
VecU8_append_span(&res, cstr(";\n}\n\n"));
return res;
}
NODISCARD VecU8 generate_xmatnm_method_mul_xvecn(ConstSpanU8 xmat, ConstSpanU8 xvec, int n, int m) {
VecU8 res = VecU8_new();
string_append_xvecy(&res, xvec, m);
VecU8_append(&res, ' ');
string_append_xmatnm(&res, xmat, n, m);
VecU8_append_span(&res, cstr("_mul_"));
string_append_xvecy(&res, xvec, n);
VecU8_append_span(&res, cstr("("));
string_append_xmatnm(&res, xmat, n, m);
VecU8_append_span(&res, cstr(" A, "));
string_append_xvecy(&res, xvec, n);
VecU8_append_span(&res, cstr(" B) {\n" SPACE4 "return ("));
string_append_xvecy(&res, xvec, m);
VecU8_append_span(&res, cstr("){"));
for (int ci = 0; ci < m; ci++) {
if (ci)
VecU8_append(&res, ',');
VecU8_append_span(&res, cstr("\n" SPACE8));
for (int x = 0; x < n; x++) {
if (x)
VecU8_append_span(&res, cstr(" + "));
VecU8_append_span(&res, cstr("A"));
string_append_mat_el_access(&res, x, ci);
VecU8_append_span(&res, cstr(" * B."));
string_append_vec_field_name(&res, x);
}
}
VecU8_append_span(&res, cstr(" };\n}\n\n"));
return res;
}
NODISCARD VecU8 generate_xmatnm_method_mul_xmatkn(ConstSpanU8 xmat, int n, int m, int k) {
VecU8 res = VecU8_new();
string_append_xmatnm(&res, xmat, k, m);
VecU8_append(&res, ' ');
string_append_xmatnm(&res, xmat, n, m);
VecU8_append_span(&res, cstr("_mul_"));
string_append_xmatnm(&res, xmat, k, n);
VecU8_append_span(&res, cstr("("));
string_append_xmatnm(&res, xmat, n, m);
VecU8_append_span(&res, cstr(" A, "));
string_append_xmatnm(&res, xmat, k, n);
VecU8_append_span(&res, cstr(" B) {\n" SPACE4 "return ("));
string_append_xmatnm(&res, xmat, k, m);
VecU8_append_span(&res, cstr("){"));
for (int x = 0; x < k; x++) {
if (x)
VecU8_append_span(&res, cstr(","));
VecU8_append_span(&res, cstr("\n" SPACE8));
string_append_mat_col_definition(&res, x);
VecU8_append_span(&res, cstr("{ "));
for (int y = 0; y < m; y++) {
if (y)
VecU8_append_span(&res, cstr(", "));
for (int z = 0; z < n; z++) {
if (z)
VecU8_append_span(&res, cstr(" + "));
VecU8_append_span(&res, cstr("A"));
string_append_mat_el_access(&res, z, y);
VecU8_append_span(&res, cstr(" * B"));
string_append_mat_el_access(&res, x, z);
}
}
VecU8_append_span(&res, cstr(" }"));
}
VecU8_append_span(&res, cstr(" };\n}\n\n"));
return res;
}
VecU8 generate_xmatnm_method_transpose(ConstSpanU8 xmat, ConstSpanU8 xvec, ConstSpanU8 member, int n, int m) {
VecU8 res = VecU8_new();
string_append_xmatnm(&res, xmat, m, n);
VecU8_append(&res, ' ');
string_append_xmatnm(&res, xmat, n, m);
VecU8_append_span(&res, cstr("_transpose("));
string_append_xmatnm(&res, xmat, n, m);
VecU8_append_span(&res, cstr(" A) {\n" SPACE4 "return ("));
string_append_xmatnm(&res, xmat, m, n);
VecU8_append_span(&res, cstr("){ "));
for (int bx = 0; bx < m; bx++) {
if (bx)
VecU8_append_span(&res, cstr(", "));
string_append_mat_col_definition(&res, bx);
VecU8_append_span(&res, cstr("{ "));
for (int by = 0; by < n; by++) {
if (by)
VecU8_append_span(&res, cstr(", "));
VecU8_append_span(&res, cstr("A"));
string_append_mat_el_access(&res, by, bx);
}
VecU8_append_span(&res, cstr(" }"));
}
VecU8_append_span(&res, cstr(" };\n}\n\n"));
return res;
}
NODISCARD VecU8 generate_xvec234_structs_and_methods(ConstSpanU8 xvec, ConstSpanU8 member) {
VecU8 res = VecU8_new();
for (int cc = 2; cc <= 4; cc++) {
VecU8_append_vec(&res, generate_xvecy_struct_definition(xvec, member, cc));
VecU8_append_vec(&res, generate_xvecy_method_add_xvecy(xvec, member, cc));
VecU8_append_vec(&res, generate_xvecy_method_minus_xvecy(xvec, member, cc));
VecU8_append_vec(&res, generate_xvecy_method_minus(xvec, member, cc));
VecU8_append_vec(&res, generate_xvecy_method_mul_scal(xvec, member, cc));
VecU8_append_vec(&res, generate_xvecy_method_div_by_scal(xvec, member, cc));
}
return res;
}
NODISCARD VecU8 generate_xmat234x234_structs_and_methods(ConstSpanU8 xmat, ConstSpanU8 xvec, ConstSpanU8 member, int sizeof_member) {
VecU8 res = VecU8_new();
for (int cols = 2; cols <= 4; cols++) {
for (int rows = 2; rows <= 4; rows++) {
VecU8_append_vec(&res, generate_xmatnm_structure_definition(xmat, xvec, cols, rows, sizeof_member));
}
}
for (int cols = 2; cols <= 4; cols++) {
for (int rows = 2; rows <= 4; rows++) {
VecU8_append_vec(&res, generate_xmatnm_method_new(xmat, xvec, member, cols, rows));
VecU8_append_vec(&res, generate_xmatnm_method_add_xmatnm(xmat, xvec, member, cols, rows));
VecU8_append_vec(&res, generate_xmatnm_method_minus_xmatnm(xmat, xvec, member, cols, rows));
VecU8_append_vec(&res, generate_xmatnm_method_minus(xmat, xvec, member, cols, rows));
VecU8_append_vec(&res, generate_xmatnm_method_mul_scal(xmat, xvec, member, cols, rows));
VecU8_append_vec(&res, generate_xmatnm_method_div_by_scal(xmat, xvec, member, cols, rows));
VecU8_append_vec(&res, generate_xmatnm_method_transpose(xmat, xvec, member, cols, rows));
}
}
for (int n = 2; n <= 4; n++) {
VecU8_append_vec(&res, generate_square_xmatnn_E_definition(xmat, n));
}
for (int n = 2; n <= 4; n++) {
for (int m = 2; m <= 4; m++) {
VecU8_append_vec(&res, generate_xmatnm_method_mul_xvecn(xmat, xvec, n, m));
}
}
for (int n = 2; n <= 4; n++) {
for (int m = 2; m <= 4; m++) {
for (int k = 2; k <= 4; k++) {
VecU8_append_vec(&res, generate_xmatnm_method_mul_xmatkn(xmat, n, m, k));
}
}
}
return res;
}
void generate_geom_header() {
VecU8 res = begin_header(cstr("PROTOTYPE1_GEN_GEOM"));
VecU8_append_span(&res, cstr("#include \"../src/l1/core/int_primitives.h\"\n\n"));
VecU8_append_vec(&res, generate_xvec234_structs_and_methods(cstr("cvec"), cstr("U8")));
VecU8_append_vec(&res, generate_xvec234_structs_and_methods(cstr("ivec"), cstr("S32")));
VecU8_append_vec(&res, generate_xvec234_structs_and_methods(cstr("vec"), cstr("float")));
VecU8_append_vec(&res, generate_xvec234_structs_and_methods(cstr("dvec"), cstr("double")));
VecU8_append_vec(&res, generate_xmat234x234_structs_and_methods(cstr("mat"), cstr("vec"), cstr("float"), sizeof(float)));
VecU8_append_vec(&res, generate_xmat234x234_structs_and_methods(cstr("dmat"), cstr("dvec"), cstr("double"), sizeof(double)));
finish_header(res, "geom.h");
}
VecU8 generate_type_triv_methods_and_vec(ConstSpanU8 member) {
VecU8 res = VecU8_from_cstr("#define ");
VecU8_append_span(&res, member);
VecU8_append_span(&res, cstr("_drop(x) {}\n#define "));
VecU8_append_span(&res, member);
VecU8_append_span(&res, cstr("_clone(xp) (*(xp))\n\n"));
VecU8_append_span(&res, cstr("VecT_trivmove_struct_Definition("));
VecU8_append_span(&res, member);
VecU8_append_span(&res, cstr(")\nVecT_trivmove_method_Definition("));
VecU8_append_span(&res, member);
VecU8_append_span(&res, cstr(")\nVecT_primitive_zeroinit_method_Definition("));
VecU8_append_span(&res, member);
VecU8_append_span(&res, cstr(")\n\n"));
return res;
}
/* code generation function. We don't append vector data to vecu8, we append vector name to string in VecU8 */
void VecU8_append_vecoft(VecU8* str, ConstSpanU8 t) {
VecU8_append_span(str, cstr("Vec"));
VecU8_append_span(str, t);
}
void VecU8_append_resoftexdatat(VecU8* str, ConstSpanU8 texdatat) {
VecU8_append_span(str, cstr("Result"));
VecU8_append_span(str, texdatat);
VecU8_append_span(str, cstr("OrConstSpanU8"));
}
/* Used to generate both _at() and _cat() methods */
VecU8 generate_texture_data_method_at(ConstSpanU8 texdatat, ConstSpanU8 member, bool const_access) {
VecU8 res = VecU8_from_span(member);
VecU8_append_span(&res, cstr("* "));
VecU8_append_span(&res, texdatat);
VecU8_append_span(&res, const_access ? cstr("_cat") : cstr("_at"));
VecU8_append_span(&res, cstr("("));
VecU8_append_span(&res, texdatat);
VecU8_append_span(&res, cstr("* self, size_t x, size_t y) {\n" SPACE4 "assert(x < self->width);\n"
SPACE4 "return "));
VecU8_append_vecoft(&res, member);
VecU8_append_span(&res, const_access ? cstr("_cat") : cstr("_at"));
VecU8_append_span(&res, cstr("(&self->pixels, x + y * self->width);\n}\n\n"));
return res;
}
VecU8 generate_texture_data_struct_and_necc_methods(ConstSpanU8 texdatat, ConstSpanU8 member) {
VecU8 res = VecU8_from_cstr("typedef struct {\n" SPACE4);
VecU8_append_vecoft(&res, member);
VecU8_append_span(&res, cstr(" pixels;\n" SPACE4 "size_t width;\n} "));
VecU8_append_span(&res, texdatat);
VecU8_append_span(&res, cstr(";\n\n"));
/* Method _new() */
VecU8_append_span(&res, texdatat);
VecU8_append_span(&res, cstr(" "));
VecU8_append_span(&res, texdatat);
VecU8_append_span(&res, cstr("_new(U32 width, U32 height) {\n"
SPACE4 "assert(!(SIZE_MAX / width / height < 100 || UINT32_MAX / width < 10 || UINT32_MAX / height < 10));\n"
SPACE4 "return ("));
VecU8_append_span(&res, texdatat);
VecU8_append_span(&res, cstr("){.pixels = "));
VecU8_append_vecoft(&res, member);
VecU8_append_span(&res, cstr("_new_zeroinit((size_t)width * height), .width = width};\n}\n\n"));
/* Method _drop() */
VecU8_append_span(&res, cstr("void "));
VecU8_append_span(&res, texdatat);
VecU8_append_span(&res, cstr("_drop("));
VecU8_append_span(&res, texdatat);
VecU8_append_span(&res, cstr(" self) {\n" SPACE4));
VecU8_append_vecoft(&res, member);
VecU8_append_span(&res, cstr("_drop(self.pixels);\n}\n\n"));
/* Method _get_height() */
VecU8_append_span(&res, cstr("size_t "));
VecU8_append_span(&res, texdatat);
VecU8_append_span(&res, cstr("_get_height(const "));
VecU8_append_span(&res, texdatat);
VecU8_append_span(&res, cstr("* self) {\n" SPACE4 "return self->pixels.len / self->width;\n}\n\n"));
/* Methods _at and _cat */
VecU8_append_vec(&res, generate_texture_data_method_at(texdatat, member, false));
VecU8_append_span(&res, cstr("const "));
VecU8_append_vec(&res, generate_texture_data_method_at(texdatat, member, true));
/* Method _get_size_in_bytes */
VecU8_append_span(&res, cstr("size_t "));
VecU8_append_span(&res, texdatat);
VecU8_append_span(&res, cstr("_get_size_in_bytes(const "));
VecU8_append_span(&res, texdatat);
VecU8_append_span(&res, cstr("* self) {\n" SPACE4 "return self->pixels.len * sizeof("));
VecU8_append_span(&res, member);
VecU8_append_span(&res, cstr(");\n}\n\n"));
/* Method _to_bitmap_text()
* We use the assumption that bytes in type member are tightly packed */
VecU8_append_span(&res, cstr("VecU8 "));
VecU8_append_span(&res, texdatat);
VecU8_append_span(&res, cstr("_to_bitmap_text(const "));
VecU8_append_span(&res, texdatat);
VecU8_append_span(&res, cstr("* self) {\n"
SPACE4 "assert(SIZE_MAX / self->pixels.len >= 100);\n"
SPACE4 "size_t len = self->pixels.len * sizeof("));
VecU8_append_span(&res, member);
VecU8_append_span(&res, cstr(");\n"
SPACE4 "VecU8 res = VecU8_new_zeroinit(8 + len);\n"
SPACE4 "size_t width = self->width;\n"
SPACE4 "size_t height = self->pixels.len / self->width;\n"
SPACE4 "assert(UINT32_MAX / width >= 10 && UINT32_MAX / height >= 10);\n"
SPACE4 "for (int i = 0; i < 4; i++)\n"
SPACE4 SPACE4 "*VecU8_at(&res, 0 + i) = (width >> (8 * i)) & 0xff;\n"
SPACE4 "for (int i = 0; i < 4; i++)\n"
SPACE4 SPACE4 "*VecU8_at(&res, 4 + i) = (height >> (8 * i)) & 0xff;\n"
SPACE4 "memcpy(res.buf + 8, self->pixels.buf, len);\n"
SPACE4 "return res;\n"
"}\n\n"));
/* Method _write_to_file
* Aborts on failure */
VecU8_append_span(&res, cstr("void "));
VecU8_append_span(&res, texdatat);
VecU8_append_span(&res, cstr("_write_to_file(const "));
VecU8_append_span(&res, texdatat);
VecU8_append_span(&res, cstr("* self, const char* path) {\n" SPACE4 "VecU8 data = "));
VecU8_append_span(&res, texdatat);
VecU8_append_span(&res, cstr("_to_bitmap_text(self);\n"
SPACE4 "write_whole_file_or_abort(path, VecU8_to_ConstSpanU8(&data));\n"
SPACE4 "VecU8_drop(data);\n"
"}\n\n"));
/* Result<texdatat, ConstSpanU8> stucture */
VecU8_append_span(&res, cstr("typedef struct {\n" SPACE4 "Result_variant variant;\n" SPACE4 "union {\n" SPACE8 ));
VecU8_append_span(&res, texdatat);
VecU8_append_span(&res, cstr(" ok;\n" SPACE4 SPACE4 "ConstSpanU8 err;\n" SPACE4 "};\n} "));
VecU8_append_resoftexdatat(&res, texdatat);
VecU8_append_span(&res, cstr(";\n\n"));
/* Method _from_bitmap_text()
* We assume that bytes are tightly packed in member type
*/
VecU8_append_resoftexdatat(&res, texdatat);
VecU8_append(&res, ' ');
VecU8_append_span(&res, texdatat);
VecU8_append_span(&res, cstr("_from_bitmap_text(ConstSpanU8 text) {\n"
SPACE4 "if (text.len < 8)\n"
SPACE4 SPACE4 "return ("));
VecU8_append_resoftexdatat(&res, texdatat);
VecU8_append_span(&res, cstr("){.variant = Result_Err, "
".err = cstr(\"No header *crying emoji*\")};\n"
SPACE4 "size_t width = 0, height = 0;\n"
SPACE4 "for (int i = 0; i < 4; i++)\n"
SPACE4 SPACE4 "width |= (((size_t)*ConstSpanU8_at(text, 0 + i)) << (8 * i));\n"
SPACE4 "for (int i = 0; i < 4; i++)\n"
SPACE4 SPACE4 "height |= (((size_t)*ConstSpanU8_at(text, 4 + i)) << (8 * i));\n"
SPACE4 "if (SIZE_MAX / width / height < 100 || UINT32_MAX / width < 10 || UINT32_MAX / height < 10)\n"
SPACE4 SPACE4 "return ("));
VecU8_append_resoftexdatat(&res, texdatat);
VecU8_append_span(&res, cstr("){.variant = Result_Err, "
".err = cstr(\"Image is too big\")};\n"
SPACE4 "size_t len = width * height * sizeof("));
VecU8_append_span(&res, member);
VecU8_append_span(&res, cstr(");\n"
SPACE4 "if (text.len < 8 + len)\n"
SPACE4 SPACE4 "return ("));
VecU8_append_resoftexdatat(&res, texdatat);
VecU8_append_span(&res, cstr("){.variant = Result_Err, "
".err = cstr(\"Texture size and file size mismatch\")};\n" SPACE4));
VecU8_append_span(&res, texdatat);
VecU8_append_span(&res, cstr(" res = "));
VecU8_append_span(&res, texdatat);
VecU8_append_span(&res, cstr("_new(width, height);\n"
SPACE4 "memcpy(res.pixels.buf, text.data + 8, len);\n"
SPACE4 "return ("));
VecU8_append_resoftexdatat(&res, texdatat);
VecU8_append_span(&res, cstr("){.variant = Result_Ok, .ok = res};\n}\n\n"));
/* Method _read_from_file */
VecU8_append_span(&res, texdatat);
VecU8_append(&res, ' ');
VecU8_append_span(&res, texdatat);
VecU8_append_span(&res, cstr("_read_from_file(const char* path) {\n"
SPACE4 "VecU8 data = read_whole_file_or_abort(path);\n" SPACE4));
VecU8_append_resoftexdatat(&res, texdatat);
VecU8_append_span(&res, cstr(" res = "));
VecU8_append_span(&res, texdatat);
VecU8_append_span(&res, cstr("_from_bitmap_text(VecU8_to_ConstSpanU8(&data));\n"
SPACE4 "if (res.variant != Result_Ok) {\n"
SPACE8 "fprintf(stderr, \"Tried loading bitmap texture from file, but encountered decoding error: \");\n"
SPACE8 "ConstSpanU8_fprint(res.err, stderr);\n"
SPACE8 "abortf(\"\\n\");\n" SPACE4 "}\n" SPACE4 "VecU8_drop(data);\n" SPACE4 "return res.ok;\n}\n\n"));
return res;
}
void generate_pixel_masses_header() {
VecU8 res = begin_header(cstr("PROTOTYPE1_GEN_PIXEL_MASSES"));
VecU8_append_span(&res, cstr("#include \"geom.h\"\n\n"));
VecU8_append_span(&res, cstr("#include \"../src/l1/core/VecSpan_int_primitives.h\"\n\n"));
VecU8_append_span(&res, cstr("#include \"../src/l1/system/fileio.h\"\n\n"));
VecU8_append_vec(&res, generate_type_triv_methods_and_vec(cstr("cvec3")));
VecU8_append_vec(&res, generate_type_triv_methods_and_vec(cstr("cvec4")));
VecU8_append_vec(&res, generate_texture_data_struct_and_necc_methods(cstr("TextureDataR8"), cstr("U8")));
VecU8_append_vec(&res, generate_texture_data_struct_and_necc_methods(cstr("TextureDataR8G8B8"), cstr("cvec3")));
VecU8_append_vec(&res, generate_texture_data_struct_and_necc_methods(cstr("TextureDataR8G8B8A8"), cstr("cvec4")));
finish_header(res, "pixel_masses.h");
}
#endif

View File

@ -1,573 +1,6 @@
#include <stdio.h>
#include "system/fileio.h"
#include "core/VecU8_format.h"
NODISCARD VecU8 begin_header(ConstSpanU8 guard) {
VecU8 res = VecU8_new();
VecU8_append_span(&res, cstr("#ifndef "));
VecU8_append_span(&res, guard);
VecU8_append_span(&res, cstr("\n#define "));
VecU8_append_span(&res, guard);
VecU8_append_span(&res, cstr("\n/* Automatically generated file. Do not edit it. */\n\n"
"#include \"../src/l1/core/int_primitives.h\"\n\n"));
return res;
}
void finish_header(VecU8 text_before_endif) {
VecU8_append_span(&text_before_endif, cstr("#endif\n"));
write_whole_file_or_abort("geom.h", VecU8_to_ConstSpanU8(&text_before_endif));
VecU8_drop(text_before_endif);
}
#define SPACE4 " "
void string_append_vec_field_name(VecU8* str, int ci) {
assert(0 <= ci && ci < 4);
VecU8_append(str, ci == 3 ? 'w' : 'x' + ci);
}
void string_append_xvecy(VecU8* str, ConstSpanU8 xvec, int cc) {
VecU8_append_span(str, xvec);
VecU8_append(str, '0' + cc);
}
NODISCARD VecU8 generate_xvecy_struct_definition(ConstSpanU8 xvec, ConstSpanU8 member, int cc) {
assert(2 <= cc && cc <= 4);
VecU8 res = VecU8_new();
VecU8_append_span(&res, cstr("typedef struct {\n"));
for (int ci = 0; ci < cc; ci++) {
VecU8_append_span(&res, cstr(SPACE4));
VecU8_append_span(&res, member);
VecU8_append(&res, ' ');
string_append_vec_field_name(&res, ci);
VecU8_append_span(&res, cstr(";\n"));
}
VecU8_append_span(&res, cstr("} "));
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr(";\n\n"));
return res;
}
NODISCARD VecU8 generate_xvecy_method_add_xvecy(ConstSpanU8 xvec, ConstSpanU8 member, int cc) {
VecU8 res = VecU8_new();
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr(" "));
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr("_add_"));
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr("("));
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr(" A, "));
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr(" B) {\n" SPACE4 "return ("));
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr("){ "));
for (int ci = 0; ci < cc; ci++) {
if (ci)
VecU8_append_span(&res, cstr(", "));
VecU8_append_span(&res, cstr("A."));
string_append_vec_field_name(&res, ci);
VecU8_append_span(&res, cstr(" + B."));
string_append_vec_field_name(&res, ci);
}
VecU8_append_span(&res, cstr(" };\n}\n\n"));
return res;
}
NODISCARD VecU8 generate_xvecy_method_minus_xvecy(ConstSpanU8 xvec, ConstSpanU8 member, int cc) {
VecU8 res = VecU8_new();
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr(" "));
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr("_minus_"));
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr("("));
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr(" A, "));
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr(" B) {\n" SPACE4 "return ("));
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr("){ "));
for (int ci = 0; ci < cc; ci++) {
if (ci)
VecU8_append_span(&res, cstr(", "));
VecU8_append_span(&res, cstr("A."));
string_append_vec_field_name(&res, ci);
VecU8_append_span(&res, cstr(" - B."));
string_append_vec_field_name(&res, ci);
}
VecU8_append_span(&res, cstr(" };\n}\n\n"));
return res;
}
NODISCARD VecU8 generate_xvecy_method_minus(ConstSpanU8 xvec, ConstSpanU8 member, int cc) {
VecU8 res = VecU8_new();
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr(" "));
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr("_minus("));
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr(" A) {\n" SPACE4 "return("));
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr("){ "));
for (int ci = 0; ci < cc; ci++) {
if (ci)
VecU8_append_span(&res, cstr(", "));
VecU8_append_span(&res, cstr("-A."));
string_append_vec_field_name(&res, ci);
}
VecU8_append_span(&res, cstr(" };\n}\n\n"));
return res;
}
NODISCARD VecU8 generate_xvecy_method_mul_scal(ConstSpanU8 xvec, ConstSpanU8 member, int cc) {
VecU8 res = VecU8_new();
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr(" "));
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr("_mul_scal("));
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr(" A, "));
VecU8_append_span(&res, member);
VecU8_append_span(&res, cstr(" B) {\n" SPACE4 "return ("));
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr("){ "));
for (int ci = 0; ci < cc; ci++) {
if (ci)
VecU8_append_span(&res, cstr(", "));
VecU8_append_span(&res, cstr("A."));
string_append_vec_field_name(&res, ci);
VecU8_append_span(&res, cstr(" * B"));
}
VecU8_append_span(&res, cstr(" };\n}\n\n"));
return res;
}
NODISCARD VecU8 generate_xvecy_method_div_by_scal(ConstSpanU8 xvec, ConstSpanU8 member, int cc) {
VecU8 res = VecU8_new();
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr(" "));
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr("_div_by_scal("));
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr(" A, "));
VecU8_append_span(&res, member);
VecU8_append_span(&res, cstr(" B){\n" SPACE4 "return "));
string_append_xvecy(&res, xvec, cc);
VecU8_append_span(&res, cstr("_mul_scal(A, 1/B);\n}\n\n"));
return res;
}
void string_append_xmatnm(VecU8* str, ConstSpanU8 xmat, int cols, int rows) {
VecU8_append_span(str, xmat);
VecU8_append(str, '0' + cols);
if (rows != cols) {
VecU8_append(str, 'x');
VecU8_append(str, '0' + rows);
}
}
/* With columns padded to 16 bytes (for std140, std140 is our everything) */
NODISCARD VecU8 generate_xmatnm_structure_definition(ConstSpanU8 xmat, ConstSpanU8 xvec, int cols, int rows, int sizeof_member) {
int sv = (rows * sizeof_member) % 16;
VecU8 res = VecU8_from_cstr("typedef struct {\n");
for (int x = 0; x < cols; x++) {
VecU8_append_span(&res, cstr(SPACE4));
string_append_xvecy(&res, xvec, rows);
VecU8_append_span(&res, cstr(" "));
string_append_vec_field_name(&res, x);
VecU8_append_span(&res, cstr(";\n"));
if (sv) {
VecU8_append_vec(&res, VecU8_format(SPACE4 "char _padding_%d[%d];\n", x, 16 - sv));
}
}
VecU8_append_span(&res, cstr("} "));
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append_span(&res, cstr(";\n\n"));
return res;
}
void string_append_mat_col_definition(VecU8* str, int ci) {
VecU8_append(str, '.');
string_append_vec_field_name(str, ci);
VecU8_append_span(str, cstr(" = "));
}
void string_append_mat_el_access(VecU8* str, int x, int y) {
VecU8_append(str, '.');
string_append_vec_field_name(str, x);
VecU8_append(str, '.');
string_append_vec_field_name(str, y);
}
NODISCARD VecU8 generate_xmatnm_method_new(ConstSpanU8 xmat, ConstSpanU8 xvec, ConstSpanU8 member, int cols, int rows) {
VecU8 res = VecU8_new();
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append(&res, ' ');
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append_span(&res, cstr("_new("));
for (int y = 0; y < rows; y++) {
for (int x = 0; x < cols; x++) {
if (x > 0 || y > 0)
VecU8_append_span(&res, cstr(", "));
VecU8_append_span(&res, member);
VecU8_append(&res, ' ');
string_append_vec_field_name(&res, x);
string_append_vec_field_name(&res, y);
}
}
VecU8_append_span(&res, cstr(") {\n" SPACE4 "return ("));
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append_span(&res, cstr("){ "));
for (int x = 0; x < cols; x++) {
if (x)
VecU8_append_span(&res, cstr(", "));
string_append_mat_col_definition(&res, x);
VecU8_append_span(&res, cstr("{ "));
for (int y = 0; y < rows; y++) {
if (y)
VecU8_append_span(&res, cstr(", "));
string_append_vec_field_name(&res, x);
string_append_vec_field_name(&res, y);
}
VecU8_append_span(&res, cstr(" }"));
}
VecU8_append_span(&res, cstr(" };\n}\n\n"));
return res;
}
NODISCARD VecU8 generate_square_xmatnn_E_definition(ConstSpanU8 xmat, int n) {
VecU8 res = VecU8_from_cstr("const ");
string_append_xmatnm(&res, xmat, n, n);
VecU8_append(&res, ' ');
string_append_xmatnm(&res, xmat, n, n);
VecU8_append_span(&res, cstr("_E = { "));
for (int x = 0; x < n; x++) {
if (x)
VecU8_append_span(&res, cstr(", "));
string_append_mat_col_definition(&res, x);
VecU8_append_span(&res, cstr("{ "));
for (int y = 0; y < n; y++) {
if (y)
VecU8_append_span(&res, cstr(", "));
VecU8_append(&res, '0' + (x == y));
}
VecU8_append_span(&res, cstr(" }"));
}
VecU8_append_span(&res, cstr(" };\n\n"));
return res;
}
NODISCARD VecU8 generate_xmatnm_method_add_xmatnm(ConstSpanU8 xmat, ConstSpanU8 xvec, ConstSpanU8 member, int cols, int rows) {
VecU8 res = VecU8_new();
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append(&res, ' ');
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append_span(&res, cstr("_add_"));
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append_span(&res, cstr("("));
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append_span(&res, cstr(" A, "));
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append_span(&res, cstr(" B) {\n" SPACE4 "return ("));
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append_span(&res, cstr("){ "));
for (int x = 0; x < cols; x++) {
if (x)
VecU8_append_span(&res, cstr(", "));
string_append_mat_col_definition(&res, x);
string_append_xvecy(&res, xvec, rows);
VecU8_append_span(&res, cstr("_add_"));
string_append_xvecy(&res, xvec, rows);
VecU8_append_span(&res, cstr("(A."));
string_append_vec_field_name(&res, x);
VecU8_append_span(&res, cstr(", B."));
string_append_vec_field_name(&res, x);
VecU8_append_span(&res, cstr(")"));
}
VecU8_append_span(&res, cstr(" };\n}\n\n"));
return res;
}
NODISCARD VecU8 generate_xmatnm_method_minus_xmatnm(ConstSpanU8 xmat, ConstSpanU8 xvec, ConstSpanU8 member, int cols, int rows) {
VecU8 res = VecU8_new();
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append(&res, ' ');
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append_span(&res, cstr("_minus_"));
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append_span(&res, cstr("("));
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append_span(&res, cstr(" A, "));
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append_span(&res, cstr(" B) {\n" SPACE4 "return ("));
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append_span(&res, cstr("){ "));
for (int x = 0; x < cols; x++) {
if (x)
VecU8_append_span(&res, cstr(", "));
string_append_mat_col_definition(&res, x);
string_append_xvecy(&res, xvec, rows);
VecU8_append_span(&res, cstr("_minus_"));
string_append_xvecy(&res, xvec, rows);
VecU8_append_span(&res, cstr("(A."));
string_append_vec_field_name(&res, x);
VecU8_append_span(&res, cstr(", B."));
string_append_vec_field_name(&res, x);
VecU8_append_span(&res, cstr(")"));
}
VecU8_append_span(&res, cstr(" };\n}\n\n"));
return res;
}
NODISCARD VecU8 generate_xmatnm_method_minus(ConstSpanU8 xmat, ConstSpanU8 xvec, ConstSpanU8 member, int cols, int rows) {
VecU8 res = VecU8_new();
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append(&res, ' ');
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append_span(&res, cstr("_minus("));
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append_span(&res, cstr(" A) {\n" SPACE4 "return ("));
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append_span(&res, cstr("){ "));
for (int x = 0; x < cols; x++) {
if (x)
VecU8_append_span(&res, cstr(", "));
string_append_mat_col_definition(&res, x);
string_append_xvecy(&res, xvec, rows);
VecU8_append_span(&res, cstr("_minus(A."));
string_append_vec_field_name(&res, x);
VecU8_append_span(&res, cstr(")"));
}
VecU8_append_span(&res, cstr(" };\n}\n\n"));
return res;
}
NODISCARD VecU8 generate_xmatnm_method_mul_scal(ConstSpanU8 xmat, ConstSpanU8 xvec, ConstSpanU8 member, int cols, int rows) {
VecU8 res = VecU8_new();
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append(&res, ' ');
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append_span(&res, cstr("_mul_scal("));
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append_span(&res, cstr(" A, "));
VecU8_append_span(&res, member);
VecU8_append_span(&res, cstr(" B) {\n" SPACE4 "return ("));
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append_span(&res, cstr("){ "));
for (int x = 0; x < cols; x++) {
if (x)
VecU8_append_span(&res, cstr(", "));
string_append_mat_col_definition(&res, x);
string_append_xvecy(&res, xvec, rows);
VecU8_append_span(&res, cstr("_mul_scal(A."));
string_append_vec_field_name(&res, x);
VecU8_append_span(&res, cstr(", B)"));
}
VecU8_append_span(&res, cstr(" };\n}\n\n"));
return res;
}
NODISCARD VecU8 generate_xmatnm_method_div_by_scal(ConstSpanU8 xmat, ConstSpanU8 xvec, ConstSpanU8 member, int cols, int rows) {
VecU8 res = VecU8_new();
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append(&res, ' ');
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append_span(&res, cstr("_div_by_scal("));
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append_span(&res, cstr(" A, "));
VecU8_append_span(&res, member);
VecU8_append_span(&res, cstr(" B) {\n" SPACE4 "return "));
string_append_xmatnm(&res, xmat, cols, rows);
VecU8_append_span(&res, cstr("_mul_scal(A, 1/B);\n}\n\n"));
return res;
}
NODISCARD VecU8 generate_xvecn_method_dot_xvecn(ConstSpanU8 xvec, ConstSpanU8 member, int n) {
VecU8 res = VecU8_from_span(member);
VecU8_append(&res, ' ');
string_append_xvecy(&res, xvec, n);
VecU8_append_span(&res, cstr("_dot_"));
string_append_xvecy(&res, xvec, n);
VecU8_append(&res, '(');
string_append_xvecy(&res, xvec, n);
VecU8_append_span(&res, cstr(" A, "));
string_append_xvecy(&res, xvec, n);
VecU8_append_span(&res, cstr(" B) {\n" SPACE4 "return "));
for (int i = 0; i < n; i++) {
if (i)
VecU8_append_span(&res, cstr(" + "));
VecU8_append_span(&res, cstr("A."));
string_append_vec_field_name(&res, i);
VecU8_append_span(&res, cstr(" * B."));
string_append_vec_field_name(&res, i);
}
VecU8_append_span(&res, cstr(";\n}\n\n"));
return res;
}
NODISCARD VecU8 generate_xmatnm_method_mul_xvecn(ConstSpanU8 xmat, ConstSpanU8 xvec, int n, int m) {
VecU8 res = VecU8_new();
string_append_xvecy(&res, xvec, m);
VecU8_append(&res, ' ');
string_append_xmatnm(&res, xmat, n, m);
VecU8_append_span(&res, cstr("_mul_"));
string_append_xvecy(&res, xvec, n);
VecU8_append_span(&res, cstr("("));
string_append_xmatnm(&res, xmat, n, m);
VecU8_append_span(&res, cstr(" A, "));
string_append_xvecy(&res, xvec, n);
VecU8_append_span(&res, cstr(" B) {\n" SPACE4 "return ("));
string_append_xvecy(&res, xvec, m);
VecU8_append_span(&res, cstr("){"));
for (int ci = 0; ci < m; ci++) {
if (ci)
VecU8_append(&res, ',');
VecU8_append_span(&res, cstr("\n" SPACE4 SPACE4));
for (int x = 0; x < n; x++) {
if (x)
VecU8_append_span(&res, cstr(" + "));
VecU8_append_span(&res, cstr("A"));
string_append_mat_el_access(&res, x, ci);
VecU8_append_span(&res, cstr(" * B."));
string_append_vec_field_name(&res, x);
}
}
VecU8_append_span(&res, cstr(" };\n}\n\n"));
return res;
}
NODISCARD VecU8 generate_xmatnm_method_mul_xmatkn(ConstSpanU8 xmat, int n, int m, int k) {
VecU8 res = VecU8_new();
string_append_xmatnm(&res, xmat, k, m);
VecU8_append(&res, ' ');
string_append_xmatnm(&res, xmat, n, m);
VecU8_append_span(&res, cstr("_mul_"));
string_append_xmatnm(&res, xmat, k, n);
VecU8_append_span(&res, cstr("("));
string_append_xmatnm(&res, xmat, n, m);
VecU8_append_span(&res, cstr(" A, "));
string_append_xmatnm(&res, xmat, k, n);
VecU8_append_span(&res, cstr(" B) {\n" SPACE4 "return ("));
string_append_xmatnm(&res, xmat, k, m);
VecU8_append_span(&res, cstr("){"));
for (int x = 0; x < k; x++) {
if (x)
VecU8_append_span(&res, cstr(","));
VecU8_append_span(&res, cstr("\n" SPACE4 SPACE4));
string_append_mat_col_definition(&res, x);
VecU8_append_span(&res, cstr("{ "));
for (int y = 0; y < m; y++) {
if (y)
VecU8_append_span(&res, cstr(", "));
for (int z = 0; z < n; z++) {
if (z)
VecU8_append_span(&res, cstr(" + "));
VecU8_append_span(&res, cstr("A"));
string_append_mat_el_access(&res, z, y);
VecU8_append_span(&res, cstr(" * B"));
string_append_mat_el_access(&res, x, z);
}
}
VecU8_append_span(&res, cstr(" }"));
}
VecU8_append_span(&res, cstr(" };\n}\n\n"));
return res;
}
VecU8 generate_xmatnm_method_transpose(ConstSpanU8 xmat, ConstSpanU8 xvec, ConstSpanU8 member, int n, int m) {
VecU8 res = VecU8_new();
string_append_xmatnm(&res, xmat, m, n);
VecU8_append(&res, ' ');
string_append_xmatnm(&res, xmat, n, m);
VecU8_append_span(&res, cstr("_transpose("));
string_append_xmatnm(&res, xmat, n, m);
VecU8_append_span(&res, cstr(" A) {\n" SPACE4 "return ("));
string_append_xmatnm(&res, xmat, m, n);
VecU8_append_span(&res, cstr("){ "));
for (int bx = 0; bx < m; bx++) {
if (bx)
VecU8_append_span(&res, cstr(", "));
string_append_mat_col_definition(&res, bx);
VecU8_append_span(&res, cstr("{ "));
for (int by = 0; by < n; by++) {
if (by)
VecU8_append_span(&res, cstr(", "));
VecU8_append_span(&res, cstr("A"));
string_append_mat_el_access(&res, by, bx);
}
VecU8_append_span(&res, cstr(" }"));
}
VecU8_append_span(&res, cstr(" };\n}\n\n"));
return res;
}
NODISCARD VecU8 generate_xvec234_structs_and_methods(ConstSpanU8 xvec, ConstSpanU8 member) {
VecU8 res = VecU8_new();
for (int cc = 2; cc <= 4; cc++) {
VecU8_append_vec(&res, generate_xvecy_struct_definition(xvec, member, cc));
VecU8_append_vec(&res, generate_xvecy_method_add_xvecy(xvec, member, cc));
VecU8_append_vec(&res, generate_xvecy_method_minus_xvecy(xvec, member, cc));
VecU8_append_vec(&res, generate_xvecy_method_minus(xvec, member, cc));
VecU8_append_vec(&res, generate_xvecy_method_mul_scal(xvec, member, cc));
VecU8_append_vec(&res, generate_xvecy_method_div_by_scal(xvec, member, cc));
}
return res;
}
NODISCARD VecU8 generate_xmat234x234_structs_and_methods(ConstSpanU8 xmat, ConstSpanU8 xvec, ConstSpanU8 member, int sizeof_member) {
VecU8 res = VecU8_new();
for (int cols = 2; cols <= 4; cols++) {
for (int rows = 2; rows <= 4; rows++) {
VecU8_append_vec(&res, generate_xmatnm_structure_definition(xmat, xvec, cols, rows, sizeof_member));
}
}
for (int cols = 2; cols <= 4; cols++) {
for (int rows = 2; rows <= 4; rows++) {
VecU8_append_vec(&res, generate_xmatnm_method_new(xmat, xvec, member, cols, rows));
VecU8_append_vec(&res, generate_xmatnm_method_add_xmatnm(xmat, xvec, member, cols, rows));
VecU8_append_vec(&res, generate_xmatnm_method_minus_xmatnm(xmat, xvec, member, cols, rows));
VecU8_append_vec(&res, generate_xmatnm_method_minus(xmat, xvec, member, cols, rows));
VecU8_append_vec(&res, generate_xmatnm_method_mul_scal(xmat, xvec, member, cols, rows));
VecU8_append_vec(&res, generate_xmatnm_method_div_by_scal(xmat, xvec, member, cols, rows));
VecU8_append_vec(&res, generate_xmatnm_method_transpose(xmat, xvec, member, cols, rows));
}
}
for (int n = 2; n <= 4; n++) {
VecU8_append_vec(&res, generate_square_xmatnn_E_definition(xmat, n));
}
for (int n = 2; n <= 4; n++) {
for (int m = 2; m <= 4; m++) {
VecU8_append_vec(&res, generate_xmatnm_method_mul_xvecn(xmat, xvec, n, m));
}
}
for (int n = 2; n <= 4; n++) {
for (int m = 2; m <= 4; m++) {
for (int k = 2; k <= 4; k++) {
VecU8_append_vec(&res, generate_xmatnm_method_mul_xmatkn(xmat, n, m, k));
}
}
}
return res;
}
void generate_geometry_header() {
VecU8 res = begin_header(cstr("PROTOTYPE1_GEN_GEOM"));
VecU8_append_vec(&res, generate_xvec234_structs_and_methods(cstr("cvec"), cstr("U8")));
VecU8_append_vec(&res, generate_xvec234_structs_and_methods(cstr("ivec"), cstr("S32")));
VecU8_append_vec(&res, generate_xvec234_structs_and_methods(cstr("vec"), cstr("float")));
VecU8_append_vec(&res, generate_xvec234_structs_and_methods(cstr("dvec"), cstr("double")));
VecU8_append_vec(&res, generate_xmat234x234_structs_and_methods(cstr("mat"), cstr("vec"), cstr("float"), sizeof(float)));
VecU8_append_vec(&res, generate_xmat234x234_structs_and_methods(cstr("dmat"), cstr("dvec"), cstr("double"), sizeof(double)));
finish_header(res);
}
#include "gen/geom_and_textures.h"
int main() {
generate_geometry_header();
generate_geom_header();
generate_pixel_masses_header();
}

View File

@ -3,8 +3,6 @@
#include "../../l1/core/VecSpan_int_primitives.h"
// todo: move this out of margaret (may still keep it in l2)
U8 U8_to_lowercase(U8 ch) {
if ('A' <= ch && ch <= 'Z')
return ch - 'A' + 'a';

View File

@ -74,5 +74,4 @@ mat3 margaret_simple_camera_rot_m_basis_in_cols(float yaw, float pitch, float ro
};
}
#endif

View File

@ -8,11 +8,12 @@
#include <X11/Xutil.h>
#include <vulkan/vulkan.h>
#include <vulkan/vulkan_xlib.h>
#include "stringop.h"
#include "../core/stringop.h"
// #include <stdio.h>
#include <time.h>
// #include <stdint.h>
#include <stdlib.h>
#include "../../l1/system/fileio.h"
typedef struct timespec margaret_ns_time;
@ -478,6 +479,59 @@ ResultMargaretChosenSwapchainDetailsOrConstSpanU8 margaret_choose_swapchain_deta
};
}
SpanT_struct_Definition(VkFormat)
SpanT_method_Definition(VkFormat)
OptionT_struct_Definition(VkFormat)
OptionT_method_Definition(VkFormat)
OptionVkFormat margaret_find_supported_format_for_linear_tiling(
VkPhysicalDevice physical_device, ConstSpanVkFormat candidates, VkFormatFeatureFlags required_features
) {
for (size_t i = 0; i < candidates.len; i++) {
VkFormat format = *ConstSpanVkFormat_at(candidates, i);
VkFormatProperties properties;
vkGetPhysicalDeviceFormatProperties(physical_device, format, &properties);
if ((properties.linearTilingFeatures & required_features) == required_features)
return Some_VkFormat(format);
}
return None_VkFormat();
}
OptionVkFormat margaret_find_supported_format_for_optimal_tiling(
VkPhysicalDevice physical_device, ConstSpanVkFormat candidates, VkFormatFeatureFlags required_features
) {
for (size_t i = 0; i < candidates.len; i++) {
VkFormat format = *ConstSpanVkFormat_at(candidates, i);
VkFormatProperties properties;
vkGetPhysicalDeviceFormatProperties(physical_device, format, &properties);
if ((properties.optimalTilingFeatures & required_features) == required_features)
return Some_VkFormat(format);
}
return None_VkFormat();
}
OptionVkFormat margaret_find_supported_zbuffer_format(VkPhysicalDevice physical_device) {
VkFormat candidates[3] = { VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT };
return margaret_find_supported_format_for_optimal_tiling(physical_device,
(ConstSpanVkFormat){.data = candidates, .len = ARRAY_SIZE(candidates)}, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT);
}
OptionVkFormat margaret_find_supported_hdr_buffer_format(VkPhysicalDevice physical_device) {
// todo: use format without alpha component (even though they are probably not supported)
VkFormat candidates[] = { /*VK_FORMAT_R16G16B16_SFLOAT, VK_FORMAT_R32G32B32_SFLOAT,*/
VK_FORMAT_R16G16B16A16_SFLOAT, VK_FORMAT_R32G32B32A32_SFLOAT };
return margaret_find_supported_format_for_optimal_tiling(physical_device,
(ConstSpanVkFormat){.data = candidates, .len = ARRAY_SIZE(candidates)},
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT );
}
bool margaret_is_format_supported_for_textures(VkPhysicalDevice physical_device, VkFormat format) {
VkFormatProperties props;
vkGetPhysicalDeviceFormatProperties(physical_device, format, &props);
return props.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
}
typedef struct {
VkPhysicalDevice physical_device;
S64 score;
@ -532,6 +586,14 @@ MargaretScoredPhysicalDevice margaret_score_physical_device(
if (swapchain_details.variant == Result_Err) {
return (MargaretScoredPhysicalDevice){dev, -1, cstr("Physical device lacks nice swapchain support")};
}
if (!margaret_is_format_supported_for_textures(dev, VK_FORMAT_R8_UNORM))
return (MargaretScoredPhysicalDevice){dev, -1, cstr("R8_UNORM format can't be used for optimal tiling of textures")};
if (!margaret_is_format_supported_for_textures(dev, VK_FORMAT_R8G8B8A8_SRGB))
return (MargaretScoredPhysicalDevice){dev, -1, cstr("R8G8B8A8_SRGB format can't be used for optimal tiling of textures")};
if (!margaret_is_format_supported_for_textures(dev, VK_FORMAT_R8G8B8A8_UNORM))
return (MargaretScoredPhysicalDevice){dev, -1, cstr("R8G8B8A8_UNORM format can't be used for optimal tiling of textures")};
if (!margaret_is_format_supported_for_textures(dev, VK_FORMAT_R16G16B16A16_SFLOAT))
return (MargaretScoredPhysicalDevice){dev, -1, cstr("VK_FORMAT_R16G16B16A16_SFLOAT format can't be used for optimal tiling of textures")};
return (MargaretScoredPhysicalDevice){dev, score, ""};
}
@ -1271,44 +1333,6 @@ VkSampler margaret_create_sampler(VkPhysicalDevice physical_device, VkDevice dev
return sampler;
}
SpanT_struct_Definition(VkFormat)
SpanT_method_Definition(VkFormat)
OptionT_struct_Definition(VkFormat)
OptionT_method_Definition(VkFormat)
OptionVkFormat margaret_find_supported_format_for_linear_tiling(
VkPhysicalDevice physical_device, ConstSpanVkFormat candidates, VkFormatFeatureFlags required_features
) {
for (size_t i = 0; i < candidates.len; i++) {
VkFormat format = *ConstSpanVkFormat_at(candidates, i);
VkFormatProperties properties;
vkGetPhysicalDeviceFormatProperties(physical_device, format, &properties);
if ((properties.linearTilingFeatures & required_features) == required_features)
return Some_VkFormat(format);
}
return None_VkFormat();
}
OptionVkFormat margaret_find_supported_format_for_optimal_tiling(
VkPhysicalDevice physical_device, ConstSpanVkFormat candidates, VkFormatFeatureFlags required_features
) {
for (size_t i = 0; i < candidates.len; i++) {
VkFormat format = *ConstSpanVkFormat_at(candidates, i);
VkFormatProperties properties;
vkGetPhysicalDeviceFormatProperties(physical_device, format, &properties);
if ((properties.optimalTilingFeatures & required_features) == required_features)
return Some_VkFormat(format);
}
return None_VkFormat();
}
OptionVkFormat margaret_find_supported_zbuffer_format(VkPhysicalDevice physical_device) {
VkFormat candidates[3] = { VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT };
return margaret_find_supported_format_for_optimal_tiling(physical_device,
(ConstSpanVkFormat){.data = candidates, .len = ARRAY_SIZE(candidates)}, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT);
}
#define VkDescriptorPoolSize_drop(v) {}
#define VkDescriptorPoolSize_clone(p) (*(p))

View File

@ -3,9 +3,8 @@
#include <math.h>
#include "../../l1/system/fileio.h"
#include <time.h>
#include "r0_assets.h"
// Only for linux
#include <sys/wait.h>
#include "r0_scene.h"
#include <sys/wait.h> // Only for linux
// todo: generate this class in l2
typedef struct {
@ -22,39 +21,57 @@ void destroy_graphics_pipeline_hands(VkDevice device, PipelineHands hands) {
}
// todo: generate this function in l2
VkRenderPass create_render_pass_0(VkDevice logical_device, VkFormat image_format) {
// Color attachments array for our render pass
VkAttachmentDescription all_attachments[1] = { (VkAttachmentDescription){
.format = image_format,
.samples = VK_SAMPLE_COUNT_1_BIT,
.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
} };
VkRenderPass create_render_pass_0(VkDevice logical_device, VkFormat colorbuffer_format, VkFormat zbuffer_format) {
VkAttachmentDescription all_attachments[2] = {
{
.format = colorbuffer_format,
.samples = VK_SAMPLE_COUNT_1_BIT,
.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
},
{
.format = zbuffer_format,
.samples = VK_SAMPLE_COUNT_1_BIT,
.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
}
};
// For our one single render subpass
VkAttachmentReference color_attachment_refs[1] = { (VkAttachmentReference){
.attachment = 0,
.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VkAttachmentReference color_attachments_refs[1] = {
{
.attachment = 0,
.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
} };
VkAttachmentReference depth_attachment_ref = {
.attachment = 1,
.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
};
VkSubpassDescription subpasses_descr[1] = { (VkSubpassDescription){
.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
.colorAttachmentCount = ARRAY_SIZE(color_attachment_refs),
.pColorAttachments = color_attachment_refs,
.colorAttachmentCount = ARRAY_SIZE(color_attachments_refs),
.pColorAttachments = color_attachments_refs,
.pDepthStencilAttachment = &depth_attachment_ref,
} };
VkSubpassDependency subpass_dependencies[1] = {
// subpass_0_external
(VkSubpassDependency) {
.srcSubpass = VK_SUBPASS_EXTERNAL,
.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
.srcAccessMask = 0,
.dstSubpass = 0,
.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,
.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,
.srcAccessMask = 0,
.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
}};
@ -136,8 +153,8 @@ PipelineHands create_graphics_pipeline_0(
.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
.depthClampEnable = VK_FALSE,
.polygonMode = VK_POLYGON_MODE_FILL,
// .cullMode = VK_CULL_MODE_BACK_BIT,
.cullMode = VK_CULL_MODE_NONE,
.cullMode = VK_CULL_MODE_BACK_BIT,
// .cullMode = VK_CULL_MODE_NONE,
.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE,
.depthBiasEnable = VK_FALSE,
.depthBiasConstantFactor = 0.0f,
@ -156,6 +173,13 @@ PipelineHands create_graphics_pipeline_0(
.alphaToOneEnable = VK_FALSE,
};
VkPipelineDepthStencilStateCreateInfo depth_stencil_state_crinfo = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
.depthTestEnable = VK_TRUE,
.depthWriteEnable = VK_TRUE,
.depthCompareOp = VK_COMPARE_OP_LESS
};
// For one framebuffer
VkPipelineColorBlendAttachmentState color_blend_attachments[1] = {(VkPipelineColorBlendAttachmentState){
.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,
@ -186,7 +210,7 @@ PipelineHands create_graphics_pipeline_0(
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
// our shader variable is not an array of descriptors, so this stays 1
.descriptorCount = 1,
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
},
{
.binding = 1,
@ -204,12 +228,18 @@ PipelineHands create_graphics_pipeline_0(
if (vkCreateDescriptorSetLayout(device, &descriptor_set_layout_crinfo, NULL, &my_descriptor_set_layout) != VK_SUCCESS)
abortf("vkCreateDescriptorSetLayout");
VkPushConstantRange pc_ranges[] = {
{
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
.offset = 0, .size = sizeof(mat4)
}};
VkPipelineLayoutCreateInfo layout_crinfo = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
.setLayoutCount = 1,
.pSetLayouts = &my_descriptor_set_layout,
.pushConstantRangeCount = 0,
.pPushConstantRanges = NULL,
.pushConstantRangeCount = ARRAY_SIZE(pc_ranges),
.pPushConstantRanges = pc_ranges,
};
VkPipelineLayout pipeline_layout;
if (vkCreatePipelineLayout(device, &layout_crinfo, NULL, &pipeline_layout) != VK_SUCCESS)
@ -223,7 +253,7 @@ PipelineHands create_graphics_pipeline_0(
.pViewportState = &viewport_state,
.pRasterizationState = &rasterizer_crinfo,
.pMultisampleState = &multisampling_crinfo,
.pDepthStencilState = NULL,
.pDepthStencilState = &depth_stencil_state_crinfo,
.pColorBlendState = &color_blending_crinfo,
.pDynamicState = &dynamic_state_crinfo,
.layout = pipeline_layout,
@ -442,15 +472,16 @@ PipelineHands create_graphics_pipeline_1(
}
VkFramebuffer create_IT1_framebuffer(VkDevice device, VkImageView IT1_view, VkRenderPass render_pass_0, VkExtent2D MAX_WIN_SIZE) {
VkImageView attachments[1] = {IT1_view};
VkFramebuffer create_IT1_framebuffer(VkDevice device, VkImageView IT1_view, VkImageView zbuffer_view, VkRenderPass render_pass_0,
U32 MAX_WIN_WIDTH, U32 MAX_WIN_HEIGHT) {
VkImageView attachments[2] = {IT1_view, zbuffer_view};
VkFramebufferCreateInfo framebuffer_crinfo = {
.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
.renderPass = render_pass_0,
.attachmentCount = ARRAY_SIZE(attachments),
.pAttachments = attachments,
.width = MAX_WIN_SIZE.width,
.height = MAX_WIN_SIZE.height,
.width = MAX_WIN_WIDTH,
.height = MAX_WIN_HEIGHT,
.layers = 1
};
VkFramebuffer framebuffer;
@ -463,7 +494,7 @@ void reset_and_record_command_buffer_0(
VkCommandBuffer command_buffer, VkRenderPass render_pass_0,
const PipelineHands* pipeline_and_layout,
VkFramebuffer swapchain_image_framebuffer, VkExtent2D image_extent,
const Scene* scene, VkDescriptorSet my_descriptor_set
const Scene* scene, VkDescriptorSet my_descriptor_set, mat4 t_mat
) {
if (vkResetCommandBuffer(command_buffer, 0) != VK_SUCCESS)
abortf("vkResetCommandBuffer");
@ -471,15 +502,15 @@ void reset_and_record_command_buffer_0(
if (vkBeginCommandBuffer(command_buffer, &info_begin) != VK_SUCCESS)
abortf("vkBeginCommandBuffer");
VkClearValue clear_color[1] = {{.color = scene->color}};
VkClearValue clear_values[2] = {{.color = scene->color}, {.depthStencil = {.depth = 1, .stencil = 0}}};
VkRenderPassBeginInfo renderpass_begin = {
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
.renderPass = render_pass_0,
.framebuffer = swapchain_image_framebuffer,
.renderArea.offset = (VkOffset2D){0, 0},
.renderArea.extent = image_extent,
.clearValueCount = ARRAY_SIZE(clear_color),
.pClearValues = clear_color,
.clearValueCount = ARRAY_SIZE(clear_values),
.pClearValues = clear_values,
};
vkCmdBeginRenderPass(command_buffer, &renderpass_begin, VK_SUBPASS_CONTENTS_INLINE);
@ -502,16 +533,19 @@ void reset_and_record_command_buffer_0(
};
vkCmdSetScissor(command_buffer, 0, 1, &scissor);
for (size_t i = 0; i < scene->models.len; i++) {
const ModelOnScene* models = VecModelOnScene_cat(&scene->models, i);
VkBuffer attached_buffers[1] = { models->vbo };
const UsedModelOnScene* model = VecUsedModelOnScene_cat(&scene->models, i);
VkBuffer attached_buffers[1] = { model->model.vbo };
// We use our whole buffer, no need for offset
VkDeviceSize offsets_in_buffers[1] = {0};
vkCmdBindVertexBuffers(command_buffer, 0, 1, attached_buffers, offsets_in_buffers);
vkCmdBindIndexBuffer(command_buffer, models->ebo, 0, VK_INDEX_TYPE_UINT32);
vkCmdBindIndexBuffer(command_buffer, model->model.ebo, 0, VK_INDEX_TYPE_UINT32);
mat4 tt = mat4_mul_mat4(t_mat, model->model_t);
vkCmdPushConstants(command_buffer, pipeline_and_layout->pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT,
0, sizeof(mat4), &tt);
vkCmdBindDescriptorSets(
command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_and_layout->pipeline_layout, 0,
1, &my_descriptor_set, 0, NULL);
vkCmdDrawIndexed(command_buffer, models->indexes, 1, 0, 0, 0);
vkCmdDrawIndexed(command_buffer, model->model.indexes, 1, 0, 0, 0);
}
vkCmdEndRenderPass(command_buffer);
@ -661,9 +695,15 @@ int main() {
MargaretChosenSwapchainDetails swapchain_details = swapchain_details_res.ok;
// We hope that the image format won't be changed even when window gets resized
// VkSurfaceFormatKHR image_format = choose_surface_format_i_want(swap_chain_support).value();
// (swapchain_details.surface_format.format)
OptionVkFormat zbuffer_format = margaret_find_supported_zbuffer_format(physical_device);
if (zbuffer_format.variant != Option_Some)
abortf("Could not find supported zbuffer format\n");
OptionVkFormat IT1_format = margaret_find_supported_hdr_buffer_format(physical_device);
if (IT1_format.variant != Option_Some)
abortf("Could not find supported hdr buffer format\n");
VkRenderPass render_pass_0 = create_render_pass_0(device, swapchain_details.surface_format.format);
VkRenderPass render_pass_0 = create_render_pass_0(device, IT1_format.some, zbuffer_format.some);
PipelineHands pipeline_hands_0 = create_graphics_pipeline_0(device, render_pass_0, 0);
VkRenderPass render_pass_1 = create_render_pass_1(device, swapchain_details.surface_format.format);
@ -674,14 +714,15 @@ int main() {
// Filling scene info
ModelTopology cylinder_1 = generate_one_fourth_of_a_cylinder(10, 2, 6);
ModelTopology cylinder_2 = generate_one_fourth_of_a_cylinder(5, 5, 10);
TextureDataR8G8B8A8 wood_texture_data = generate_wood_texture();
// TextureDataR8G8B8A8 wood_texture_data = generate_texture_for_one_fourth_of_a_cylinder(20, 10, 2, 6);
TextureDataR8G8B8A8 wood_texture_data = TextureDataR8G8B8A8_read_from_file("test_textures/log_10_2_6.r8g8b8a8");
// We have only one staging buffer in host memory (because we don't really need more)
MargaretBufferInMemoryInfo host_mem_buffer = (MargaretBufferInMemoryInfo){ .sz =
MAX_U64(ModelTopology_get_space_needed_for_staging_buffer(&cylinder_1),
MAX_U64(ModelTopology_get_space_needed_for_staging_buffer(&cylinder_2),
MAX_U64(sizeof(Pipeline0UBO),
MAX_U64(TextureDataR8G8B8A8_get_space_needed_for_staging_buffer(&wood_texture_data), 0))))
MAX_U64(TextureDataR8G8B8A8_get_size_in_bytes(&wood_texture_data), 0))))
, .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT };
VkDeviceMemory host_mem = margaret_initialize_buffers_and_images(physical_device, device,
(SpanMargaretBufferInMemoryInfo){.data = &host_mem_buffer, .len = 1}, (SpanMargaretImageInMemoryInfo){ 0 },
@ -697,7 +738,8 @@ int main() {
MargaretImageInMemoryInfo device_mem_images[] = {
margaret_prep_image_mem_info_of_gpu_texture_rgba(wood_texture_data.width,
TextureDataR8G8B8A8_get_height(&wood_texture_data)),
margaret_prep_image_mem_info_of_colorbuffer(MAX_WIN_WIDTH, MAX_WIN_HEIGHT, swapchain_details.surface_format.format),
margaret_prep_image_mem_info_of_colorbuffer(MAX_WIN_WIDTH, MAX_WIN_HEIGHT, IT1_format.some),
margaret_prep_image_mem_info_of_zbuffer(MAX_WIN_WIDTH, MAX_WIN_HEIGHT, zbuffer_format.some),
};
VkDeviceMemory device_mem = margaret_initialize_buffers_and_images(physical_device, device,
(SpanMargaretBufferInMemoryInfo){ .data = device_mem_buffers, .len = ARRAY_SIZE(device_mem_buffers)},
@ -710,6 +752,7 @@ int main() {
MargaretBufferInMemoryInfo device_ubo_my_buffer = device_mem_buffers[4];
MargaretImageInMemoryInfo device_wood_texture = device_mem_images[0];
MargaretImageInMemoryInfo device_IT1_image = device_mem_images[1];
MargaretImageInMemoryInfo device_zbuffer_image = device_mem_images[2];
VkCommandPool command_pool = margaret_create_resettable_command_pool(device, queue_fam.for_graphics);
VkCommandBuffer rendering_command_buffer_0 = margaret_allocate_command_buffer(device, command_pool);
@ -748,25 +791,27 @@ int main() {
device_ebo_2_buffer.buffer, host_mem_buffer.buffer, size);
}
memcpy(host_mem_buffer_mem, wood_texture_data.pixels.buf,
TextureDataR8G8B8A8_get_space_needed_for_staging_buffer(&wood_texture_data));
TextureDataR8G8B8A8_get_size_in_bytes(&wood_texture_data));
margaret_copy_buffer_to_texture_for_frag_shader_imm(device, command_pool, graphics_queue,
&device_wood_texture, host_mem_buffer.buffer);
// We sent everything we needed. but host_mem_buffer_mem may be used later
// My wood texture needs VkImageView
VkImageView wood_texture_view = margaret_create_view_for_image(device, &device_wood_texture, VK_IMAGE_ASPECT_COLOR_BIT);
// My zbuffer also needs a view
VkImageView zbuffer_view = margaret_create_view_for_image(device, &device_zbuffer_image, VK_IMAGE_ASPECT_DEPTH_BIT);
/* Here we create an image view into a temporary IT1 texture and a framebuffer for scene rendering */
VkImageView IT1_view = margaret_create_view_for_image(device, &device_IT1_image, VK_IMAGE_ASPECT_COLOR_BIT);
VkFramebuffer IT1_framebuffer = create_IT1_framebuffer(device, IT1_view, render_pass_0,
(VkExtent2D){.width = MAX_WIN_WIDTH, .height = MAX_WIN_HEIGHT});
VkFramebuffer IT1_framebuffer = create_IT1_framebuffer(device, IT1_view, zbuffer_view, render_pass_0,
MAX_WIN_WIDTH, MAX_WIN_HEIGHT);
Scene scene;
scene.models = VecModelOnScene_new_zeroinit(2);
*VecModelOnScene_at(&scene.models, 0) = (ModelOnScene){
.vbo = device_vbo_1_buffer.buffer, .ebo = device_ebo_1_buffer.buffer, .indexes = cylinder_1.indexes.len };
// *VecModelOnScene_at(&scene.models, 1) = (ModelOnScene){
// .vbo = device_vbo_2_buffer.buffer, .ebo = device_ebo_2_buffer.buffer, .indexes = cylinder_2.indexes.len };
Scene scene = Scene_new();
VecUsedModelOnScene_append(&scene.models, (UsedModelOnScene){.model = {
.vbo = device_vbo_1_buffer.buffer, .ebo = device_ebo_1_buffer.buffer, .indexes = cylinder_1.indexes.len
}, .model_t = margaret_translation_mat4((vec3){1, -1, 5}) });
VecUsedModelOnScene_append(&scene.models, (UsedModelOnScene){.model = {
.vbo = device_vbo_2_buffer.buffer, .ebo = device_ebo_2_buffer.buffer, .indexes = cylinder_2.indexes.len
}, .model_t = margaret_translation_mat4((vec3){6, -3, 7}) });
// Sampler is global for a lot of my future textures
VkSampler my_texture_sampler = margaret_create_sampler(physical_device, device);
@ -902,9 +947,16 @@ int main() {
mat4 camera_rotation_matrix = margaret_mat3_to_mat4_transposed(my_cam_control_info.cam_basis);
mat4 camera_translation_matrix = margaret_translation_mat4(vec3_minus(my_cam_control_info.pos));
mat4 t_mat = mat4_mul_mat4(projection_matrix, mat4_mul_mat4(camera_rotation_matrix, camera_translation_matrix));
// mat4 t_mat = mat4_mul_mat4(camera_rotation_matrix, camera_translation_matrix);
{
*(Pipeline0UBO*)host_mem_buffer_mem = (Pipeline0UBO){.t = t_mat};
assert(scene.spotlights.len < pipeline_0_ubo_spotlight_max_count);
assert(scene.point_lights.len < pipeline_0_ubo_point_light_max_count);
Pipeline0UBO* subo = (Pipeline0UBO*)host_mem_buffer_mem;
// todo: speed it up a little
subo->spotlight_count = (int)scene.spotlights.len;
memcpy(&subo->spotlight_arr, scene.spotlights.buf, scene.spotlights.len * sizeof(Pipeline0Spotlight));
subo->point_light_count = (int)scene.point_lights.len;
memcpy(&subo->point_light_arr, scene.point_lights.buf, scene.point_lights.len * sizeof(Pipeline0PointLight));
VkCommandBuffer command_buffers[1] = { uniform_transfer_command_buffer };
VkSemaphore signaling_semaphores[1] = { swfb.in_frame_transfer_complete };
VkSubmitInfo ubo_copying_cmd_buffer_submit = {
@ -918,7 +970,7 @@ int main() {
}
reset_and_record_command_buffer_0(rendering_command_buffer_0, render_pass_0, &pipeline_hands_0,
IT1_framebuffer, swfb.extent, &scene, descriptor_set_for_pipeline_0);
IT1_framebuffer, swfb.extent, &scene, descriptor_set_for_pipeline_0, t_mat);
reset_and_record_command_buffer_1(rendering_command_buffer_1, render_pass_1, &pipeline_hands_1,
*VecVkFramebuffer_cat(&swfb.framebuffers, ij),

View File

@ -3,27 +3,16 @@
#include "../margaret/graphics_geom.h"
#include "../../l1/core/util.h"
#include "../../l1/core/VecSpan_int_primitives.h"
#include "../../l1/system/fileio.h"
#include <math.h>
#include "../../../gen/pixel_masses.h"
typedef struct {
vec3 pos;
vec2 tex;
} Vertex;
/* No offset yet */
typedef struct {
VkBuffer vbo;
VkBuffer ebo;
size_t indexes;
} ModelOnScene;
#define ModelOnScene_drop(vp) {}
#define ModelOnScene_clone(vp) (*(vp))
VecT_trivmove_struct_Definition(ModelOnScene)
VecT_trivmove_method_Definition(ModelOnScene)
VecT_primitive_zeroinit_method_Definition(ModelOnScene)
#define Vertex_drop(vp) {}
#define Vertex_clone(vp) (*(vp))
@ -44,62 +33,6 @@ void ModelTopology_drop(ModelTopology self) {
VecU32_drop(self.indexes);
}
ModelTopology generate_one_fourth_of_a_cylinder(float w, float r, U32 k) {
assert(k >= 1);
const float a = M_PI_2f / (float)k;
const float l = 2 * r * sin(M_PI_4f / (float)k);
const vec2 v0tex = {r / (2 * r + w), 1 / (2 + k * l)};
const vec2 v1tex = {(r + w) / (2 * r + w), 1 / (2 + k * l)};
const vec2 v2tex = {r / (2 * r + w), 2 / (2 + k * l)};
const vec2 v3tex = {(r + w) / (2 * r + w), 2 / (2 + k * l)};
VecVertex vertices = VecVertex_new(); // todo: reserve 4 * k + 6
VecVertex_append(&vertices, (Vertex){.pos = {0, 0, 0}, .tex = v0tex});
VecVertex_append(&vertices, (Vertex){.pos = {w, 0, 0}, .tex = v1tex});
VecVertex_append(&vertices, (Vertex){.pos = {0, r, 0}, .tex = v2tex});
VecVertex_append(&vertices, (Vertex){.pos = {w, r, 0}, .tex = v3tex});
VecVertex_append(&vertices, (Vertex){.pos = {0, 0, r}, .tex = {r / (2 * r + w), 0}});
VecVertex_append(&vertices, (Vertex){.pos = {w, 0, r}, .tex = {(r + w) / (2 * r + w), 0}});
for (U32 i = 1; i <= k; i++) {
VecVertex_append(&vertices, (Vertex){
.pos = {0, cosf(a * i) * r, sinf(a * i) * r},
.tex = vec2_add_vec2(v0tex, (vec2){r / (2 * r + w) * -sinf(a * i), 1 / (2 + k * l) * cos(a * i)})
});
}
for (U32 i = 1; i <= k; i++) {
VecVertex_append(&vertices, (Vertex){
.pos = {w, cosf(a * i) * r, sinf(a * i) * r},
.tex = vec2_add_vec2(v1tex, (vec2){r / (2 * r + w) * sinf(a * i), 1 / (2 + k * l) * cos(a * i)})
});
}
for (U32 i = 1; i <= k; i++) {
VecVertex_append(&vertices, (Vertex){
.pos = {0, cosf(a * i) * r, sinf(a * i) * r},
.tex = {v2tex.x, v2tex.y + i * l / (2 + k * l)}
});
}
for (U32 i = 1; i <= k; i++) {
VecVertex_append(&vertices, (Vertex){
.pos = {w, cosf(a * i) * r, sinf(a * i) * r},
.tex = {v3tex.x, v3tex.y + i * l / (2 + k * l)}
});
}
VecU32 indexes = VecU32_new(); // todo: reserve 3 * (2+2+2*k+2*k)<
{
U32 _span_0[] = { 5, 0, 1, 5, 4, 0, 1, 0, 3, 3, 0, 2 };
VecU32_append_span(&indexes, (ConstSpanU32){.data = _span_0, .len = ARRAY_SIZE(_span_0)});
}
for (U32 i = 1; i <= k; i++) {
U32 _span_1[] = {
0, 5 + i, i > 1 ? 5 + i - 1 : 2,
1, i > 1 ? 5 + k + i - 1 : 3, 5 + k + i,
i > 1 ? 5 + 2 * k + i - 1 : 2, 5 + 2 * k + i, i > 1 ? 5 + 3 * k + i - 1 : 3,
5 + 3 * k + i, i > 1 ? 5 + 3 * k + i - 1 : 3, 5 + 2 * k + i
};
VecU32_append_span(&indexes, (ConstSpanU32){.data = _span_1, .len = ARRAY_SIZE(_span_1)});
}
return (ModelTopology){.vertices = vertices, .indexes = indexes};
}
typedef struct {
vec2 win_scale;
} Pipeline1PushRangeVertex;
@ -112,37 +45,163 @@ typedef struct {
} Pipeline1PushRangeFragment;
typedef struct {
mat4 t;
} Pipeline0UBO;
vec3 pos;
char _padding_0[4];
vec3 dir;
char _padding_1[4];
vec3 color;
char _padding_2[4];
float d;
char _padding_3[12];
} Pipeline0Spotlight;
#define cvec4_drop(vp) {}
#define cvec4_clone(vp) (*(vp))
#define Pipeline0Spotlight_drop(x) {}
#define Pipeline0Spotlight_clone(x) (*(x))
VecT_trivmove_struct_Definition(cvec4)
VecT_trivmove_method_Definition(cvec4)
VecT_primitive_zeroinit_method_Definition(cvec4)
VecT_trivmove_struct_Definition(Pipeline0Spotlight)
VecT_trivmove_method_Definition(Pipeline0Spotlight)
VecT_primitive_zeroinit_method_Definition(Pipeline0Spotlight)
typedef struct {
// I hate this so much uuuh. Capacity is not actually useful here...
Veccvec4 pixels;
size_t width;
} TextureDataR8G8B8A8;
vec3 pos;
char _padding_0[4];
vec3 color;
char _padding_1[4];
} Pipeline0PointLight;
TextureDataR8G8B8A8 TextureDataR8G8B8A8_new(size_t width, size_t height) {
return (TextureDataR8G8B8A8){.pixels = Veccvec4_new_zeroinit(width * height), .width = width};
#define Pipeline0PointLight_drop(x) {}
#define Pipeline0PointLight_clone(x) (*(x))
VecT_trivmove_struct_Definition(Pipeline0PointLight)
VecT_trivmove_method_Definition(Pipeline0PointLight)
VecT_primitive_zeroinit_method_Definition(Pipeline0PointLight)
const size_t pipeline_0_ubo_point_light_max_count = 20;
const size_t pipeline_0_ubo_spotlight_max_count = 20;
typedef struct {
int spotlight_count;
int point_light_count;
char _padding_1[8];
Pipeline0PointLight point_light_arr[20];
Pipeline0Spotlight spotlight_arr[120];
} Pipeline0UBO;
size_t ModelTopology_get_space_needed_for_staging_buffer(const ModelTopology* self) {
return MAX_U64(self->vertices.len * sizeof(Vertex), self->indexes.len * sizeof(U32));
}
size_t TextureDataR8G8B8A8_get_height(const TextureDataR8G8B8A8* self) {
return self->pixels.len / self->width;
void TextureDataR8_pixel_maxing(TextureDataR8* self, S32 x, S32 y, U8 val) {
if (x < 0 || y < 0 || x >= self->width)
return;
size_t p = (size_t)x + (size_t)y * self->width;
if (p >= self->pixels.len)
return;
U8 b = *TextureDataR8_at(self, x, y);
*TextureDataR8_at(self, x, y) = MAX_U8(b, val);
}
void TextureDataR8G8B8A8_drop(TextureDataR8G8B8A8 self) {
Veccvec4_drop(self.pixels);
U8 a_small_cute_gradient(float r_cut, float r_decay, float dist) {
return dist > r_cut ? 0 : (dist < r_decay) ? 255 : (U8)roundf( 255.f * (r_cut - dist) / (r_cut - r_decay) );
}
cvec4* TextureDataR8G8B8A8_at(TextureDataR8G8B8A8* self, size_t x, size_t y) {
assert(x < self->width);
return Veccvec4_at(&self->pixels, x + y * self->width);
void TextureDataR8_seg_vertical_strip_maxing(TextureDataR8* self, S32 x, float y_real, float vert_r_cut, float vert_r_decay) {
S32 y = (S32)roundf(y_real - 0.5f);
S32 k = (S32)ceilf(vert_r_cut);
for (S32 j = -k+y; j <= y+k; j++) {
float dist = fabsf(.5f + (float)j - y_real);
TextureDataR8_pixel_maxing(self, x, j, a_small_cute_gradient(vert_r_cut, vert_r_decay, dist));
}
}
void TextureDataR8_seg_horizontal_strip_maxing(TextureDataR8* self, float x_real, S32 y, float hor_r_cut, float hor_r_decay) {
S32 x = (S32)roundf(x_real - 0.5f);
S32 k = (S32)ceilf(hor_r_cut);
for (S32 i = -k+x; i < x+k; i++) {
float dist = fabsf(.5f + (float)i - x_real);
TextureDataR8_pixel_maxing(self, i, y, a_small_cute_gradient(hor_r_cut, hor_r_decay, dist));
}
}
// todo: complete rewrite
/* abs(y2 - y1) < abs(x2 - x1) x1 <= x2 */
void TextureDataR8_draw_horizontal_inner_line_maxing(TextureDataR8* self,
float x1, float y1, float x2, float y2, float r_cut, float r_decay) {
S32 sx1 = (S32)roundf(x1 - 0.5f);
S32 sx2 = (S32)roundf(x2 - 0.5f);
if (sx1 + 1 >= sx2)
return;
float dx = x2 - x1;
float dy = y2 - y1;
float xdds = 1 / dx;
float inv_sin_a = sqrtf(dx*dx + dy*dy) / dx;
float vert_r_cut = r_cut * inv_sin_a;
float vert_r_decay = r_decay * inv_sin_a;
for (S32 x = sx1 + 1; x < sx2; x++) {
float real_x = (float)x + 0.5f;
float real_y = y1 + dy * (real_x - x1) * xdds;
TextureDataR8_seg_vertical_strip_maxing(self, x, real_y, vert_r_cut, vert_r_decay);
}
}
/* abs(x2 - x1) < abs(y2 - y1) y1 <= y2 */
void TextureDataR8_draw_vertical_inner_line_maxing(TextureDataR8* self,
float x1, float y1, float x2, float y2, float r_cut, float r_decay) {
S32 sy1 = (S32)roundf(y1 - 0.5f);
S32 sy2 = (S32)roundf(y2 - 0.5f);
if (sy1 + 1 >= sy2)
return;
float dx = x2 - x1;
float dy = y2 - y1;
float ydds = 1 / dy;
float inv_sin_a = sqrtf(dx*dx + dy*dy) / dy;
float hor_r_cut = r_cut * inv_sin_a;
float hor_r_decay = r_decay * inv_sin_a;
for (S32 y = sy1 + 1; y < sy2; y++) {
float real_y = (float)y + 0.5f;
float real_x = x1 + dx * (real_y - y1) * ydds;
TextureDataR8_seg_horizontal_strip_maxing(self, real_x, y, hor_r_cut, hor_r_decay);
}
}
void TextureDataR8_draw_inner_line_maxing(TextureDataR8* self,
float x1, float y1, float x2, float y2, float r_cut, float r_decay) {
float dx = fabsf(x2 - x1);
float dy = fabsf(y2 - y1);
if (dx > dy) {
if (x1 < x2) {
TextureDataR8_draw_horizontal_inner_line_maxing(self, x1, y1, x2, y2, r_cut, r_decay);
} else {
TextureDataR8_draw_horizontal_inner_line_maxing(self, x2, y2, x1, y1, r_cut, r_decay);
}
} else {
if (y1 < y2) {
TextureDataR8_draw_vertical_inner_line_maxing(self, x1, y1, x2, y2, r_cut, r_decay);
} else {
TextureDataR8_draw_vertical_inner_line_maxing(self, x2, y2, x1, y1, r_cut, r_decay);
}
}
}
void TextureDataR8_draw_spot_maxing(TextureDataR8* self, float x, float y, float r_cut, float r_decay) {
S32 sx = (S32)roundf(x - .5f);
S32 sy = (S32)roundf(y - .5f);
S32 k = (S32)ceilf(r_cut);
for (S32 i = sx-k; i <= sx+k; i++) {
for (S32 j = sy-k; j <= sy+k; j++) {
float dx = 0.5f + (float)i - x;
float dy = 0.5f + (float)j - y;
float dist = sqrtf(dx*dx + dy*dy);
TextureDataR8_pixel_maxing(self, i, j, a_small_cute_gradient(r_cut, r_decay, dist));
}
}
}
void TextureDataR8G8B8A8_draw_one_segment_maxing_alpha(TextureDataR8* self,
float x1, float y1, float x2, float y2, float r_cut, float r_decay) {
TextureDataR8_draw_spot_maxing(self, x1, y1, r_cut, r_decay);
TextureDataR8_draw_spot_maxing(self, x2, y2, r_cut, r_decay);
TextureDataR8_draw_inner_line_maxing(self, x1, y1, x2, y2, r_cut, r_decay);
}
TextureDataR8G8B8A8 generate_wood_texture() {
@ -172,85 +231,114 @@ TextureDataR8G8B8A8 generate_wood_texture() {
return res;
}
size_t ModelTopology_get_space_needed_for_staging_buffer(const ModelTopology* self) {
return MAX_U64(self->vertices.len * sizeof(Vertex), self->indexes.len * sizeof(U32));
ModelTopology generate_one_fourth_of_a_cylinder(float w, float r, U32 k) {
assert(k >= 1);
const float a = M_PI_2f / (float)k;
const float l = 2 * r * sin(M_PI_4f / (float)k);
const vec2 v0tex = {r / (2 * r + w), r / (2 * r + k * l)};
const vec2 v1tex = {(r + w) / (2 * r + w), r / (2 * r + k * l)};
const vec2 v2tex = {r / (2 * r + w), 2 * r / (2 * r + k * l)};
const vec2 v3tex = {(r + w) / (2 * r + w), 2 * r / (2 * r + k * l)};
VecVertex vertices = VecVertex_new(); // todo: reserve 4 * k + 6
VecVertex_append(&vertices, (Vertex){.pos = {0, 0, 0}, .tex = v0tex});
VecVertex_append(&vertices, (Vertex){.pos = {w, 0, 0}, .tex = v1tex});
VecVertex_append(&vertices, (Vertex){.pos = {0, r, 0}, .tex = v2tex});
VecVertex_append(&vertices, (Vertex){.pos = {w, r, 0}, .tex = v3tex});
VecVertex_append(&vertices, (Vertex){.pos = {0, 0, r}, .tex = {r / (2 * r + w), 0}});
VecVertex_append(&vertices, (Vertex){.pos = {w, 0, r}, .tex = {(r + w) / (2 * r + w), 0}});
for (U32 i = 1; i <= k; i++) {
VecVertex_append(&vertices, (Vertex){
.pos = {0, cosf(a * i) * r, sinf(a * i) * r},
.tex = vec2_add_vec2(v0tex, (vec2){r / (2 * r + w) * -sinf(a * i), r / (2 * r + k * l) * cos(a * i)})
});
}
for (U32 i = 1; i <= k; i++) {
VecVertex_append(&vertices, (Vertex){
.pos = {w, cosf(a * i) * r, sinf(a * i) * r},
.tex = vec2_add_vec2(v1tex, (vec2){r / (2 * r + w) * sinf(a * i), r / (2*r + k * l) * cos(a * i)})
});
}
for (U32 i = 1; i <= k; i++) {
VecVertex_append(&vertices, (Vertex){
.pos = {0, cosf(a * i) * r, sinf(a * i) * r},
.tex = {v2tex.x, v2tex.y + i * l / (2*r + k * l)}
});
}
for (U32 i = 1; i <= k; i++) {
VecVertex_append(&vertices, (Vertex){
.pos = {w, cosf(a * i) * r, sinf(a * i) * r},
.tex = {v3tex.x, v3tex.y + i * l / (2*r + k * l)}
});
}
VecU32 indexes = VecU32_new(); // todo: reserve 3 * (2+2+2*k+2*k)<
{
U32 _span_0[] = { 5, 0, 1, 5, 4, 0, 1, 0, 3, 3, 0, 2 };
VecU32_append_span(&indexes, (ConstSpanU32){.data = _span_0, .len = ARRAY_SIZE(_span_0)});
}
for (U32 i = 1; i <= k; i++) {
U32 _span_1[] = {
0, 5 + i, i > 1 ? 5 + i - 1 : 2,
1, i > 1 ? 5 + k + i - 1 : 3, 5 + k + i,
i > 1 ? 5 + 2 * k + i - 1 : 2, 5 + 2 * k + i, i > 1 ? 5 + 3 * k + i - 1 : 3,
5 + 3 * k + i, i > 1 ? 5 + 3 * k + i - 1 : 3, 5 + 2 * k + i
};
VecU32_append_span(&indexes, (ConstSpanU32){.data = _span_1, .len = ARRAY_SIZE(_span_1)});
}
return (ModelTopology){.vertices = vertices, .indexes = indexes};
}
size_t TextureDataR8G8B8A8_get_space_needed_for_staging_buffer(const TextureDataR8G8B8A8* self) {
return self->pixels.len * sizeof(cvec4);
#define vec2_drop(x) {}
#define vec2_clone(x) (*(x))
VecT_trivmove_struct_Definition(vec2)
VecT_trivmove_method_Definition(vec2)
VecT_primitive_zeroinit_method_Definition(vec2)
TextureDataR8 generate_tex_template_for_one_fourth_of_a_cylinder(float s_resol, float w, float r, U32 k) {
assert(k >= 1);
assert(k >= 1);
const float a = M_PI_2f / (float)k;
const float l = 2 * r * sin(M_PI_4f / (float)k);
// We will multiply everything by s_resol at the end
const vec2 v0tex = {r, r};
const vec2 v1tex = {r + w, r};
const vec2 v2tex = {r, 2 * r};
const vec2 v3tex = {r + w, 2 * r};
TextureDataR8 res = TextureDataR8_new((size_t)ceilf((float)s_resol * (2 * r + w)),
(size_t)ceilf((float)s_resol * (2 * r + k * l)));
Vecvec2 P = Vecvec2_new(); // todo: reserve 6 + k * 4
Vecvec2_append(&P, v0tex);
Vecvec2_append(&P, (vec2){r, 0}); // 4
Vecvec2_append(&P, (vec2){r + w, 0}); // 5
Vecvec2_append(&P, v1tex);
for (size_t i = k; i > 0; i--) {
Vecvec2_append(&P, (vec2){r + w + r * sinf(a * i), r + r * cos(a * i)});
}
Vecvec2_append(&P, v3tex);
for (size_t i = 1; i <= k; i++) {
Vecvec2_append(&P, (vec2){r + w, 2 * r + i * l});
}
for (size_t i = k; i > 0; i--) {
Vecvec2_append(&P, (vec2){r, 2 * r + i * l});
}
Vecvec2_append(&P, v2tex);
for (size_t i = 1; i <= k; i++) {
Vecvec2_append(&P, (vec2){r - r * sinf(a * i), r + r * cos(a * i)});
}
size_t S = 6 + 4 * k;
assert(P.len == S);
float r_cut = 2;
float r_decay = 1;
for (size_t i = 0; i < S; i++) {
vec2 p = vec2_mul_scal(*Vecvec2_at(&P, i), s_resol);
TextureDataR8_draw_spot_maxing(&res, p.x, p.y, r_cut, r_decay);
}
for (size_t i = 0; i < S; i++) {
vec2 pp = vec2_mul_scal(*Vecvec2_at(&P, i ? i - 1 : S - 1), s_resol);
vec2 p = vec2_mul_scal(*Vecvec2_at(&P, i), s_resol);
TextureDataR8_draw_inner_line_maxing(&res, pp.x, pp.y, p.x, p.y, r_cut, r_decay);
}
return res;
}
typedef struct {
float fov;
mat3 cam_basis;
vec3 pos;
float speed;
float sensitivity;
float pitch_cap;
} CamControlInfo;
void CamControlInfo_forward(CamControlInfo* self, float fl) {
self->pos = vec3_add_vec3(self->pos, vec3_mul_scal(self->cam_basis.z, -self->speed * fl));
}
void CamControlInfo_backward(CamControlInfo* self, float fl) {
self->pos = vec3_add_vec3(self->pos, vec3_mul_scal(self->cam_basis.z, self->speed * fl));
}
void CamControlInfo_left(CamControlInfo* self, float fl) {
self->pos = vec3_add_vec3(self->pos, vec3_mul_scal(self->cam_basis.x, -self->speed * fl));
}
void CamControlInfo_right(CamControlInfo* self, float fl) {
self->pos = vec3_add_vec3(self->pos, vec3_mul_scal(self->cam_basis.x, self->speed * fl));
}
void CamControlInfo_down(CamControlInfo* self, float fl) {
self->pos = vec3_add_vec3(self->pos, vec3_mul_scal((vec3){0, -1, 0}, self->speed * fl));
}
void CamControlInfo_up(CamControlInfo* self, float fl) {
self->pos = vec3_add_vec3(self->pos, vec3_mul_scal((vec3){0, 1, 0}, self->speed * fl));
}
CamControlInfo CamControlInfo_new() {
return (CamControlInfo){
.fov = 1.5, .cam_basis = margaret_simple_camera_rot_m_basis_in_cols(0, 0, 0), .pos = {0, 0, 0},
.speed = 2.7, .sensitivity = 0.5f * M_PIf / 180, .pitch_cap = M_PI * 0.49
};
}
float clamp_float(float a, float l, float r) {
return (a < l) ? l : ((a <= r) ? a : r);
}
void CamControlInfo_update_direction(CamControlInfo* self, int win_width, int win_height, int pointer_x, int pointer_y) {
float yaw = (float)(win_width / 2 - pointer_x) * self->sensitivity;
float pitch = clamp_float(
(float)(win_height / 2 - pointer_y) * self->sensitivity,
-self->pitch_cap, self->pitch_cap
);
self->cam_basis = margaret_simple_camera_rot_m_basis_in_cols(yaw, pitch, 0);
}
typedef struct {
VecModelOnScene models;
VkClearColorValue color;
float gamma_correction_factor;
float hdr_factor;
float lsd_factor;
float anim_time; // A timer, passed to functions that push push constants
} Scene;
Scene Scene_new() {
return (Scene){.models = VecModelOnScene_new(), .color = {.float32 = {1, 0.5, 0.7}},
.gamma_correction_factor = 2.2, .hdr_factor = 1, .lsd_factor = 0, .anim_time = 0};
}
void Scene_drop(Scene self) {
VecModelOnScene_drop(self.models);
}
#endif

109
src/l2/tests/r0_scene.h Normal file
View File

@ -0,0 +1,109 @@
#ifndef PROTOTYPE1_SRC_L2_TESTS_R0_SCENE_H
#define PROTOTYPE1_SRC_L2_TESTS_R0_SCENE_H
#include "r0_assets.h"
/* No offset yet */
typedef struct {
VkBuffer vbo;
VkBuffer ebo;
size_t indexes;
} ModelOnScene;
#define ModelOnScene_drop(vp) {}
#define ModelOnScene_clone(vp) (*(vp))
VecT_trivmove_struct_Definition(ModelOnScene)
VecT_trivmove_method_Definition(ModelOnScene)
VecT_primitive_zeroinit_method_Definition(ModelOnScene)
typedef struct {
ModelOnScene model;
mat4 model_t;
} UsedModelOnScene;
#define UsedModelOnScene_drop(vp) {}
#define UsedModelOnScene_clone(vp) (*(vp))
VecT_trivmove_struct_Definition(UsedModelOnScene)
VecT_trivmove_method_Definition(UsedModelOnScene)
VecT_primitive_zeroinit_method_Definition(UsedModelOnScene)
typedef struct {
float fov;
mat3 cam_basis;
vec3 pos;
float speed;
float sensitivity;
float pitch_cap;
} CamControlInfo;
void CamControlInfo_forward(CamControlInfo* self, float fl) {
self->pos = vec3_add_vec3(self->pos, vec3_mul_scal(self->cam_basis.z, -self->speed * fl));
}
void CamControlInfo_backward(CamControlInfo* self, float fl) {
self->pos = vec3_add_vec3(self->pos, vec3_mul_scal(self->cam_basis.z, self->speed * fl));
}
void CamControlInfo_left(CamControlInfo* self, float fl) {
self->pos = vec3_add_vec3(self->pos, vec3_mul_scal(self->cam_basis.x, -self->speed * fl));
}
void CamControlInfo_right(CamControlInfo* self, float fl) {
self->pos = vec3_add_vec3(self->pos, vec3_mul_scal(self->cam_basis.x, self->speed * fl));
}
void CamControlInfo_down(CamControlInfo* self, float fl) {
self->pos = vec3_add_vec3(self->pos, vec3_mul_scal((vec3){0, -1, 0}, self->speed * fl));
}
void CamControlInfo_up(CamControlInfo* self, float fl) {
self->pos = vec3_add_vec3(self->pos, vec3_mul_scal((vec3){0, 1, 0}, self->speed * fl));
}
CamControlInfo CamControlInfo_new() {
return (CamControlInfo){
.fov = 1.5, .cam_basis = margaret_simple_camera_rot_m_basis_in_cols(0, 0, 0), .pos = {0, 0, 0},
.speed = 2.7, .sensitivity = 0.5f * M_PIf / 180, .pitch_cap = M_PI * 0.49
};
}
float clamp_float(float a, float l, float r) {
return (a < l) ? l : ((a <= r) ? a : r);
}
void CamControlInfo_update_direction(CamControlInfo* self, int win_width, int win_height, int pointer_x, int pointer_y) {
float yaw = (float)(win_width / 2 - pointer_x) * self->sensitivity;
float pitch = clamp_float(
(float)(win_height / 2 - pointer_y) * self->sensitivity,
-self->pitch_cap, self->pitch_cap
);
self->cam_basis = margaret_simple_camera_rot_m_basis_in_cols(yaw, pitch, 0);
}
typedef struct {
VecUsedModelOnScene models;
VkClearColorValue color;
float gamma_correction_factor;
float hdr_factor;
float lsd_factor;
float anim_time; // A timer, passed to functions that push push constants
VecPipeline0Spotlight spotlights;
VecPipeline0PointLight point_lights;
} Scene;
Scene Scene_new() {
return (Scene){.models = VecUsedModelOnScene_new(), .color = {.float32 = {1, 0.5, 0.7}},
.gamma_correction_factor = 2.2, .hdr_factor = 1, .lsd_factor = 0, .anim_time = 0,
.spotlights = VecPipeline0Spotlight_new(), .point_lights = VecPipeline0PointLight_new()};
}
void Scene_drop(Scene self) {
VecUsedModelOnScene_drop(self.models);
}
#endif

View File

@ -0,0 +1,9 @@
#include "r0_assets.h"
#include "../../l1/system/fileio.h"
int main() {
TextureDataR8 tex_1 = generate_tex_template_for_one_fourth_of_a_cylinder(20, 10, 2, 6);
TextureDataR8_write_to_file(&tex_1, "log_10_2_6_TEMPLATE.r8");
TextureDataR8_drop(tex_1);
return 0;
}

View File

@ -1,4 +1,6 @@
#!/usr/bin/env bash
set +x
cd test_shaders
function compile(){
@ -9,3 +11,11 @@ function compile(){
compile 0
compile 1
#cd ../test_textures
#
#function png_to_r8g8b8a8 {
# python bitmap_convert.py to_bmp "$1.png" "$1.r8g8b8"
#}
#
#png_to_r8g8b8a8 log_10_2_6

View File

@ -6,6 +6,30 @@ layout(location = 0) out vec4 fin_color;
layout(binding = 1) uniform sampler2D color_tex;
struct Pipeline0Spotlight
{
vec3 pos;
vec3 dir;
vec3 colour;
float range;
};
struct Pipeline0PointLight
{
vec3 pos;
vec3 colour;
};
layout(std140, binding = 0) uniform Pipeline0UBO
{
int spotlight_count;
int point_light_count;
Pipeline0PointLight point_light_arr[20];
Pipeline0Spotlight spotlight_arr [120];
};
void main(){
fin_color = texture(color_tex, fsin_tex);
}
}

View File

@ -5,12 +5,14 @@ layout(location = 1) in vec2 tex;
layout(location = 0) out vec2 vsout_tex;
layout(binding = 0) uniform ubo {
layout(push_constant, std430) uniform pc {
/* Individual transformation for a model. Fits in push constant range
Includes global perspective matrix and camera matrix, but for each model there is a distinct
transformation matrix. Right now I only have one instance for each model,
otherwise I would use per-instance vertex attribute */
mat4 t;
};
// todo: add my ubo (location = 0) into the mix
// todo: add my woiod_texture (location = 1) into the mix
void main(){
vsout_tex = tex;
gl_Position = t * vec4(pos, 1);

View File

@ -0,0 +1,119 @@
#!/usr/bin/env python3
"""
raw_png_conv.py
===============
Convert between custom bottomup raw files (.r8g8b8a8 / .r8b8g8 / .r8)
and normal PNG using Pillow.
Format
------
uint32 width (littleendian)
uint32 height (littleendian)
pixel data rows bottomfirst:
* .r8g8b8a8 : R G B A (4× uint8)
* .r8b8g8 : R G B (3× uint8)
* .r8 : R (1× uint8 <- grayscale)
CLI
---
raw -> png : python raw_png_conv.py to_png input.raw output.png
png -> raw : python raw_png_conv.py to_raw input.png output.raw
"""
import argparse
import struct
from pathlib import Path
from PIL import Image
# --------------------------------------------------------------------- #
# Helpers
# --------------------------------------------------------------------- #
RAW_FORMATS = {
".r8g8b8a8": {"pix_size": 4, "mode": "RGBA"},
".r8b8g8": {"pix_size": 3, "mode": "RGB"},
".r8": {"pix_size": 1, "mode": "L"},
}
def get_fmt(path: Path):
fmt = RAW_FORMATS.get(path.suffix.lower())
if not fmt:
raise ValueError(f"Unknown raw extension: {path.suffix}")
return fmt
def read_raw(path: Path) -> Image.Image:
"""Load any supported raw file -> Pillow Image."""
spec = get_fmt(path)
with path.open("rb") as f:
header = f.read(8)
if len(header) != 8:
raise ValueError("File too short for header")
w, h = struct.unpack("<II", header)
expected = w * h * spec["pix_size"]
data = f.read()
if len(data) != expected:
raise ValueError(
f"Pixel data length mismatch: expected {expected}, got {len(data)}"
)
row_len = w * spec["pix_size"]
rows = [data[i : i + row_len] for i in range(0, expected, row_len)]
img_bytes = b"".join(reversed(rows)) # flip bottomup -> topdown
return Image.frombytes(spec["mode"], (w, h), img_bytes)
def write_raw(img: Image.Image, path: Path) -> None:
"""Write Pillow Image -> raw file chosen by path suffix."""
spec = get_fmt(path)
# Convert to required mode
if img.mode != spec["mode"]:
if spec["mode"] == "L":
img = img.convert("L")
elif spec["mode"] == "RGB":
img = img.convert("RGB")
else: # RGBA
img = img.convert("RGBA")
w, h = img.size
data = img.tobytes()
row_len = w * spec["pix_size"]
rows = [data[i : i + row_len] for i in range(0, len(data), row_len)]
bottom_first = b"".join(reversed(rows)) # topdown -> bottomup
with path.open("wb") as f:
f.write(struct.pack("<II", w, h))
f.write(bottom_first)
# --------------------------------------------------------------------- #
# CLI
# --------------------------------------------------------------------- #
def to_png(src: Path, dst: Path):
read_raw(src).save(dst, "PNG")
def to_raw(src: Path, dst: Path):
write_raw(Image.open(src), dst)
def main():
ap = argparse.ArgumentParser(description="Convert raw <-> PNG")
sub = ap.add_subparsers(dest="cmd", required=True)
p_png = sub.add_parser("to_png", help="raw -> png")
p_png.add_argument("src", type=Path)
p_png.add_argument("dst", type=Path)
p_raw = sub.add_parser("to_raw", help="png -> raw")
p_raw.add_argument("src", type=Path)
p_raw.add_argument("dst", type=Path)
args = ap.parse_args()
if args.cmd == "to_png":
to_png(args.src, args.dst)
else:
to_raw(args.src, args.dst)
if __name__ == "__main__":
main()

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB