twn_skybox.c

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

1
.gitattributes vendored
View File

@ -1,3 +1,4 @@
*.png filter=lfs diff=lfs merge=lfs -text
*.ogg filter=lfs diff=lfs merge=lfs -text
*.xm filter=lfs diff=lfs merge=lfs -text
*.tga filter=lfs diff=lfs merge=lfs -text

View File

@ -99,6 +99,7 @@ set(TWN_SOURCE_FILES
src/rendering/twn_text.c
src/rendering/twn_triangles.c
src/rendering/twn_circles.c
src/rendering/twn_skybox.c
# for dynamic load based solution main is compiled in a separate target
$<$<NOT:$<BOOL:${TWN_FEATURE_DYNLIB_GAME}>>:src/twn_main.c
@ -300,6 +301,8 @@ function(use_townengine target sources output_directory data_dir)
set(TWN_BOOTSTRAP_EXEC_ARGS
"$<IF:$<BOOL:${TWN_ARCHIVE_DATA}>,--data-dir ./data.${PACKAGE_EXTENSION},--data-dir ${data_dir}>")
# todo: generate by python script instead
# todo: handle the case where no numerical trace exists
string(JOIN "\n" TWN_BOOTSTRAP_SH
"#!/bin/env sh"
"cd \"$(dirname \"$0\")\""

View File

@ -58,28 +58,30 @@ static void ingame_tick(State *state) {
for (int y = 64; y--;) {
for (int x = 64; x--;) {
float d0 = stb_perlin_noise3((float)x * TERRAIN_FREQUENCY, (float)y * TERRAIN_FREQUENCY, 0, 0, 0, 0) * 20 - 6;
float d1 = stb_perlin_noise3((float)(x + 1) * TERRAIN_FREQUENCY, (float)y * TERRAIN_FREQUENCY, 0, 0, 0, 0) * 20 - 6;
float d2 = stb_perlin_noise3((float)(x + 1) * TERRAIN_FREQUENCY, (float)(y - 1) * TERRAIN_FREQUENCY, 0, 0, 0, 0) * 20 - 6;
float d3 = stb_perlin_noise3((float)x * TERRAIN_FREQUENCY, (float)(y - 1) * TERRAIN_FREQUENCY, 0, 0, 0, 0) * 20 - 6;
float d0 = stb_perlin_noise3((float)x * TERRAIN_FREQUENCY, (float)y * TERRAIN_FREQUENCY, 0, 0, 0, 0) * 3 - 6;
float d1 = stb_perlin_noise3((float)(x + 1) * TERRAIN_FREQUENCY, (float)y * TERRAIN_FREQUENCY, 0, 0, 0, 0) * 3 - 6;
float d2 = stb_perlin_noise3((float)(x + 1) * TERRAIN_FREQUENCY, (float)(y - 1) * TERRAIN_FREQUENCY, 0, 0, 0, 0) * 3 - 6;
float d3 = stb_perlin_noise3((float)x * TERRAIN_FREQUENCY, (float)(y - 1) * TERRAIN_FREQUENCY, 0, 0, 0, 0) * 3 - 6;
unfurl_triangle("/assets/grass.gif",
unfurl_triangle("/assets/grass.png",
(Vec3){ (float)x, d0, (float)y },
(Vec3){ (float)x + 1, d1, (float)y },
(Vec3){ (float)x, d3, (float)y - 1 },
(Vec2sh){ 1024, 768 },
(Vec2sh){ 1024, 0 },
(Vec2sh){ 0, 768 });
(Vec2sh){ 128, 128 },
(Vec2sh){ 128, 0 },
(Vec2sh){ 0, 128 });
unfurl_triangle("/assets/grass.gif",
unfurl_triangle("/assets/grass.png",
(Vec3){ (float)x + 1, d1, (float)y },
(Vec3){ (float)x + 1, d2, (float)y - 1 },
(Vec3){ (float)x, d3, (float)y - 1 },
(Vec2sh){ 1024, 0 },
(Vec2sh){ 128, 0 },
(Vec2sh){ 0, 0 },
(Vec2sh){ 0, 768 });
(Vec2sh){ 0, 128 });
}
}
push_skybox("/assets/miramar/miramar_*.tga");
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 373 KiB

BIN
data/assets/grass.png (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,15 @@
THIS SKY WAS UPDATED AT THE 27TH
THE ORIG HAD SOME ERRORS
MIRAMAR
high res 1024^2 environment map
ships as TGA.
By Jockum Skoglund aka hipshot
hipshot@zfight.com
www.zfight.com
Stockholm, 2005 08 25
Modify however you like, just cred me for my work, maybe link to my page.

BIN
data/assets/miramar/miramar_down.tga (Stored with Git LFS) Normal file

Binary file not shown.

BIN
data/assets/miramar/miramar_east.tga (Stored with Git LFS) Normal file

Binary file not shown.

BIN
data/assets/miramar/miramar_north.tga (Stored with Git LFS) Normal file

Binary file not shown.

BIN
data/assets/miramar/miramar_south.tga (Stored with Git LFS) Normal file

Binary file not shown.

BIN
data/assets/miramar/miramar_up.tga (Stored with Git LFS) Normal file

Binary file not shown.

BIN
data/assets/miramar/miramar_west.tga (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -73,4 +73,7 @@ TWN_API void unfurl_triangle(const char *path,
/* pushes a camera state to be used for all future unfurl_* commands */
TWN_API void set_camera(const Camera *camera);
/* expects '*' masks that will be expanded to 6 names: 'up', 'down', 'east', 'west', 'north' and 'south' */
TWN_API void push_skybox(const char *paths);
#endif

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