texture support

This commit is contained in:
Rakarake 2026-03-12 14:03:37 +01:00
parent d4a5fea127
commit b17759b34a
6 changed files with 8087 additions and 14 deletions

5
examples/texture.glsl Normal file
View file

@ -0,0 +1,5 @@
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution;
// mixes two textures
fragColor = mix(texture(iChannel0, uv), texture(iChannel1, uv), 0.2);
}

View file

@ -22,8 +22,6 @@
];
buildInputs = with pkgs; [
libGL
libpng
libjpeg
];
makeFlags = [ "PREFIX=$(out)" ];
};

View file

@ -11,16 +11,28 @@
#include "wayland.h"
#include <string.h>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
void print_help(FILE *channel, char *bin_path) {
fprintf(channel, "Usage: %s [OPTION]... [PATH]\n", bin_path);
}
/// What is the argument parser currently reading?
enum list_state {
list_none,
list_ouptut,
list_texture,
};
int main(int argc, char *argv[]) {
char *shader_path = NULL;
int output_type = OUTPUT_WINDOW;
bool currently_reading_output = false;
enum list_state list_state = list_none;
char **output_list = NULL;
int output_count;
char **texture_list = NULL;
int output_count = 0;
int texture_count = 0;
// syntax: --window for a normal window or --layer for a wallpaper
for (int i = 1; i < argc; i++) {
if (strcmp("--help", argv[i]) == 0) {
@ -29,24 +41,36 @@ int main(int argc, char *argv[]) {
}
else if (strcmp("--window", argv[i]) == 0) {
output_type = OUTPUT_WINDOW;
currently_reading_output = false;
list_state = list_none;
}
else if (strcmp("--layer", argv[i]) == 0) {
output_type = OUTPUT_LAYER;
currently_reading_output = false;
list_state = list_none;
}
else if (strcmp("--output", argv[i]) == 0) {
output_count = 0;
output_list = &argv[i + 1];
currently_reading_output = true;
list_state = list_ouptut;
}
else if (strcmp("--texture", argv[i]) == 0) {
texture_count = 0;
texture_list = &argv[i + 1];
list_state = list_texture;
}
else if (strcmp("--", argv[i]) == 0) {
currently_reading_output = false;
list_state = list_none;
}
else if (currently_reading_output) {
else if (list_state == list_ouptut) {
output_count++;
}
else if (!currently_reading_output) {
else if (list_state == list_texture) {
texture_count++;
if (texture_count > 4) {
fprintf(stderr, "maximum number of textures is 4\n");
return 1;
}
}
else if (list_state == list_none) {
// path to fragment shader
if (shader_path != NULL) {
fprintf(stderr, "Tried supplying '%s' as a shader file while one has already been selected.\n", argv[i]);
@ -74,7 +98,7 @@ int main(int argc, char *argv[]) {
int height = event.data.draw.height;
double time = event.data.draw.time / 1000.0;
if (!renderer_initialized) {
renderer = new_renderer();
renderer = new_renderer(texture_list, texture_count);
renderer_initialized = true;
}
render(&renderer, width, height, time, shader_path, 0);

View file

@ -3,8 +3,8 @@
#include <string.h>
#include <GL/gl.h>
#include <stdlib.h>
#include <libpng16/png.h>
#include "renderer.h"
#include "stb_image.h"
/// returns 0 if failed.
@ -48,6 +48,10 @@ const char *fragment_header_src =
"uniform vec2 iResolution;\n"
"uniform float iTime;\n"
"uniform int iFrame;\n"
"uniform sampler2D iChannel0;\n"
"uniform sampler2D iChannel1;\n"
"uniform sampler2D iChannel2;\n"
"uniform sampler2D iChannel3;\n"
"void mainImage(out vec4 fragColor, in vec2 fragCoord);\n"
"void main() {\n"
" mainImage(color, gl_FragCoord.xy);\n"
@ -121,7 +125,7 @@ GLuint load_shader(const char *path) {
return shader;
}
Renderer new_renderer() {
Renderer new_renderer(char **textures, int texture_count) {
const char *version_str = (const char *)glGetString(GL_VERSION);
const char *renderer_str = (const char *)glGetString(GL_RENDERER);
@ -159,6 +163,28 @@ Renderer new_renderer() {
);
Renderer renderer;
renderer.texture_count = texture_count;
// textures
for (int i = 0; i < texture_count; i++) {
glGenTextures(1, &renderer.textures[i]);
glBindTexture(GL_TEXTURE_2D, renderer.textures[i]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
int width, height, nr_channels;
unsigned char *data = stbi_load(textures[i], &width, &height, &nr_channels, 0);
if (data) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
}
else {
fprintf(stderr, "failed to load texture %d\n", i);
}
stbi_image_free(data);
}
renderer.shader_path = "";
renderer.shader = 0;
renderer.vao = vao;
@ -195,6 +221,36 @@ void render(Renderer *state, int w, int h, double time, char *shader_path, int r
// Shader parameters.
glUseProgram(state->shader);
// Bind texture
for (int i = 0; i < state->texture_count; i++) {
switch (i) {
case 0:
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, state->textures[i]);
glUniform1i(glGetUniformLocation(state->shader, "iChannel0"), i);
break;
case 1:
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, state->textures[i]);
glUniform1i(glGetUniformLocation(state->shader, "iChannel1"), i);
break;
case 2:
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, state->textures[i]);
glUniform1i(glGetUniformLocation(state->shader, "iChannel2"), i);
break;
case 3:
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, state->textures[i]);
glUniform1i(glGetUniformLocation(state->shader, "iChannel3"), i);
break;
default:
fprintf(stderr, "texture index > 3 not allowed\n");
exit(1);
break;
}
}
int uniform_iResolution = glGetUniformLocation(state->shader, "iResolution");
glUniform2f(uniform_iResolution, w, h);

View file

@ -10,9 +10,11 @@ typedef struct Renderer {
/// The currently rendered frame.
unsigned int frame_nr;
struct stat shader_file_modified;
unsigned int textures[4];
int texture_count;
} Renderer;
Renderer new_renderer();
Renderer new_renderer(char **textures, int texture_count);
void render(Renderer *renderer, int w, int h, double time, char *shader_path, int reload_shader);
#endif

7988
stb_image.h Normal file

File diff suppressed because it is too large Load diff