twn_skybox.c

This commit is contained in:
2024-09-26 21:02:56 +03:00
parent 0fe1023667
commit c0dcdf8c0a
22 changed files with 268 additions and 13 deletions

View File

@ -1,5 +1,6 @@
#include "twn_rendering_c.h"
#include "twn_util.h"
#include "twn_util_c.h"
#include "twn_config.h"
#include "twn_engine_context_c.h"
#include "twn_text_c.h"
@ -464,3 +465,152 @@ void finally_draw_text(FontData const *font_data,
size_t get_text_payload_size(void) {
return sizeof (ElementIndexedQuadWithoutColor);
}
static void load_cubemap_side(const char *path, GLenum target) {
SDL_Surface *surface = textures_load_surface(path);
/* TODO: sanity check whether all of them have same dimensions? */
glTexImage2D(target,
0,
GL_RGBA8,
surface->w, surface->h,
0,
surface->format->BytesPerPixel == 4 ? GL_RGBA : GL_RGB,
GL_UNSIGNED_BYTE,
surface->pixels);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
SDL_free(surface->pixels);
SDL_FreeSurface(surface);
}
void finally_render_skybox(char *paths) {
static GLuint cubemap = 0;
static char *paths_cache = NULL;
bool loading_needed = false;
/* drop it */
if (!paths_cache || (SDL_strcmp(paths_cache, paths) != 0)) {
if (cubemap)
glDeleteTextures(1, &cubemap);
glGenTextures(1, &cubemap);
if (paths_cache)
SDL_free(paths_cache);
paths_cache = paths;
loading_needed = true;
}
Matrix4 camera_look_at_matrix_solipsist = camera_look_at_matrix;
camera_look_at_matrix_solipsist.row[3].x = 0;
camera_look_at_matrix_solipsist.row[3].y = 0;
camera_look_at_matrix_solipsist.row[3].z = 0;
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(&camera_look_at_matrix_solipsist.row[0].x);
glDisable(GL_TEXTURE_2D);
glEnable(GL_TEXTURE_CUBE_MAP);
glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap);
/* note: assumes that space pipeline is applied already */
glDisable(GL_ALPHA_TEST);
glDepthMask(GL_TRUE);
if (loading_needed) {
/* load all the sides */
char *expanded = expand_asterisk(paths, "up");
load_cubemap_side(expanded, GL_TEXTURE_CUBE_MAP_POSITIVE_Y);
SDL_free(expanded);
expanded = expand_asterisk(paths, "down");
load_cubemap_side(expanded, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y);
SDL_free(expanded);
expanded = expand_asterisk(paths, "east");
load_cubemap_side(expanded, GL_TEXTURE_CUBE_MAP_POSITIVE_X);
SDL_free(expanded);
expanded = expand_asterisk(paths, "north");
load_cubemap_side(expanded, GL_TEXTURE_CUBE_MAP_POSITIVE_Z);
SDL_free(expanded);
expanded = expand_asterisk(paths, "west");
load_cubemap_side(expanded, GL_TEXTURE_CUBE_MAP_NEGATIVE_X);
SDL_free(expanded);
expanded = expand_asterisk(paths, "south");
load_cubemap_side(expanded, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
SDL_free(expanded);
}
/* TODO: use lists at the very least */
/* TODO: figure out which coordinates to use to not have issues with far z */
glBegin(GL_QUADS); {
/* up */
glTexCoord3f(50.f, 50.f, 50.f);
glVertex3f(50.f, 50.f, 50.f);
glTexCoord3f(-50.f, 50.f, 50.f);
glVertex3f(-50.f, 50.f, 50.f);
glTexCoord3f(-50.f, 50.f, -50.f);
glVertex3f(-50.f, 50.f, -50.f);
glTexCoord3f(50.f, 50.f, -50.f);
glVertex3f(50.f, 50.f, -50.f);
/* down */
glTexCoord3f(50.f, -50.f, 50.f);
glVertex3f(50.f, -50.f, 50.f);
glTexCoord3f(50.f, -50.f, -50.f);
glVertex3f(50.f, -50.f, -50.f);
glTexCoord3f(-50.f, -50.f, -50.f);
glVertex3f(-50.f, -50.f, -50.f);
glTexCoord3f(-50.f, -50.f, 50.f);
glVertex3f(-50.f, -50.f, 50.f);
/* east */
glTexCoord3f(50.f, -50.f, 50.f);
glVertex3f(50.f, -50.f, 50.f);
glTexCoord3f(50.f, 50.f, 50.f);
glVertex3f(50.f, 50.f, 50.f);
glTexCoord3f(50.f, 50.f, -50.f);
glVertex3f(50.f, 50.f, -50.f);
glTexCoord3f(50.f, -50.f, -50.f);
glVertex3f(50.f, -50.f, -50.f);
/* west */
glTexCoord3f(-50.f, -50.f, 50.f);
glVertex3f(-50.f, -50.f, 50.f);
glTexCoord3f(-50.f, -50.f, -50.f);
glVertex3f(-50.f, -50.f, -50.f);
glTexCoord3f(-50.f, 50.f, -50.f);
glVertex3f(-50.f, 50.f, -50.f);
glTexCoord3f(-50.f, 50.f, 50.f);
glVertex3f(-50.f, 50.f, 50.f);
/* north */
glTexCoord3f(-50.f, -50.f, 50.f);
glVertex3f(-50.f, -50.f, 50.f);
glTexCoord3f(-50.f, 50.f, 50.f);
glVertex3f(-50.f, 50.f, 50.f);
glTexCoord3f(50.f, 50.f, 50.f);
glVertex3f(50.f, 50.f, 50.f);
glTexCoord3f(50.f, -50.f, 50.f);
glVertex3f(50.f, -50.f, 50.f);
/* south */
glTexCoord3f(-50.f, -50.f, -50.f);
glVertex3f(-50.f, -50.f, -50.f);
glTexCoord3f(50.f, -50.f, -50.f);
glVertex3f(50.f, -50.f, -50.f);
glTexCoord3f(50.f, 50.f, -50.f);
glVertex3f(50.f, 50.f, -50.f);
glTexCoord3f(-50.f, 50.f, -50.f);
glVertex3f(-50.f, 50.f, -50.f);
} glEnd();
glDisable(GL_TEXTURE_CUBE_MAP);
}

View File

@ -70,6 +70,7 @@ void clear_draw_buffer(void) {
(1.0f / 255) * 230,
(1.0f / 255) * 230, 1);
/* TODO: don't clear color when skybox is applied? */
glClear(GL_COLOR_BUFFER_BIT |
GL_DEPTH_BUFFER_BIT |
GL_STENCIL_BUFFER_BIT);

View File

@ -135,6 +135,7 @@ void render(void) {
clear_draw_buffer();
render_space();
render_skybox(); /* after space, as to use depth buffer for early rejection */
render_2d();
swap_buffers();
}

View File

@ -219,4 +219,8 @@ void finally_draw_text(FontData const *font_data,
Color color,
VertexBuffer buffer);
void render_skybox(void);
void finally_render_skybox(char *paths_in_use);
#endif

View File

@ -0,0 +1,26 @@
#include "twn_rendering.h"
#include "twn_rendering_c.h"
#include <SDL2/SDL.h>
char *paths_in_use;
void push_skybox(const char *paths) {
if (paths_in_use && SDL_strcmp(paths, paths_in_use) == 0)
return;
if (paths_in_use)
SDL_free(paths_in_use);
paths_in_use = SDL_strdup(paths);
}
void render_skybox(void) {
if (!paths_in_use)
return;
/* note: ownership of 'paths_in_use' goes there */
finally_render_skybox(paths_in_use);
paths_in_use = NULL;
}

View File

@ -42,7 +42,7 @@ static int load_eof_callback(void *user) {
return context->position == context->size;
}
static SDL_Surface *image_to_surface(const char *path) {
SDL_Surface *textures_load_surface(const char *path) {
SDL_RWops *handle = PHYSFSRWOPS_openRead(path);
if (handle == NULL)
goto ERR_CANNOT_OPEN_FILE;
@ -359,7 +359,7 @@ static TextureKey textures_load(TextureCache *cache, const char *path) {
if (i >= 0)
return (TextureKey){ (uint16_t)i };
SDL_Surface *surface = image_to_surface(path);
SDL_Surface *surface = textures_load_surface(path);
Texture new_texture = {
.data = surface,
.mode = infer_texture_mode(surface),

View File

@ -89,4 +89,8 @@ size_t textures_get_num_atlases(const TextureCache *cache);
/* TODO: should recieve texture_cache, get_key optimization cache should be cleared some other way */
void textures_reset_state(void);
/* uncached low-level loading */
/* warn: surface->pixels must be freed along side the surface itself */
SDL_Surface *textures_load_surface(const char *path);
#endif

View File

@ -253,3 +253,20 @@ bool repeat_ftimer(float *value, float at) {
}
return false;
}
/* TODO: handle utf8 */
char *expand_asterisk(const char *mask, const char *to) {
const char *offset = SDL_strchr(mask, '*');
if (!offset) {
CRY("Invalid path", "Asterisk should be given.");
return NULL;
}
size_t const mask_len = SDL_strlen(mask);
size_t const to_len = SDL_strlen(to);
char *str = SDL_malloc(mask_len + to_len); /* NULL included, replacing the original asterisk */
SDL_memcpy(str, mask, offset - mask);
SDL_memcpy(str + (offset - mask), to, to_len);
SDL_memcpy(str + (offset - mask) + to_len, offset + 1, mask_len - (offset - mask));
str[mask_len + to_len] = '\0';
return str;
}

7
src/twn_util_c.h Normal file
View File

@ -0,0 +1,7 @@
#ifndef TWN_UTIL_C_H
#define TWN_UTIL_C_H
/* note: you must free the returned string */
char *expand_asterisk(const char *mask, const char *to);
#endif