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; [ buildInputs = with pkgs; [
libGL libGL
libpng
libjpeg
]; ];
makeFlags = [ "PREFIX=$(out)" ]; makeFlags = [ "PREFIX=$(out)" ];
}; };

View file

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

View file

@ -3,8 +3,8 @@
#include <string.h> #include <string.h>
#include <GL/gl.h> #include <GL/gl.h>
#include <stdlib.h> #include <stdlib.h>
#include <libpng16/png.h>
#include "renderer.h" #include "renderer.h"
#include "stb_image.h"
/// returns 0 if failed. /// returns 0 if failed.
@ -48,6 +48,10 @@ const char *fragment_header_src =
"uniform vec2 iResolution;\n" "uniform vec2 iResolution;\n"
"uniform float iTime;\n" "uniform float iTime;\n"
"uniform int iFrame;\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 mainImage(out vec4 fragColor, in vec2 fragCoord);\n"
"void main() {\n" "void main() {\n"
" mainImage(color, gl_FragCoord.xy);\n" " mainImage(color, gl_FragCoord.xy);\n"
@ -121,7 +125,7 @@ GLuint load_shader(const char *path) {
return shader; return shader;
} }
Renderer new_renderer() { Renderer new_renderer(char **textures, int texture_count) {
const char *version_str = (const char *)glGetString(GL_VERSION); const char *version_str = (const char *)glGetString(GL_VERSION);
const char *renderer_str = (const char *)glGetString(GL_RENDERER); const char *renderer_str = (const char *)glGetString(GL_RENDERER);
@ -159,6 +163,28 @@ Renderer new_renderer() {
); );
Renderer 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_path = "";
renderer.shader = 0; renderer.shader = 0;
renderer.vao = vao; renderer.vao = vao;
@ -195,6 +221,36 @@ void render(Renderer *state, int w, int h, double time, char *shader_path, int r
// Shader parameters. // Shader parameters.
glUseProgram(state->shader); 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"); int uniform_iResolution = glGetUniformLocation(state->shader, "iResolution");
glUniform2f(uniform_iResolution, w, h); glUniform2f(uniform_iResolution, w, h);

View file

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

7988
stb_image.h Normal file

File diff suppressed because it is too large Load diff