Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Video fixes #646

Merged
merged 6 commits into from
Oct 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion doc/Doxyfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project
#
# All text after a hash (#) is considered a comment and will be ignored
# All text after a guid (#) is considered a comment and will be ignored
# The format is:
# TAG = value [value, ...]
# For lists items can also be appended using:
Expand Down
5 changes: 3 additions & 2 deletions shaders/palette.frag
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
layout (location = 0) out vec4 color;

in vec2 tex_coord;
flat in int transparency_index;
flat in int blend_mode;
flat in int palette_offset;
flat in int palette_limit;
Expand All @@ -11,11 +12,11 @@ uniform sampler2D atlas;

void main() {
vec4 texel = texture(atlas, tex_coord);
if (texel.g == 0) discard; // Don't render if it's transparent pixel
int pal_index = int(texel.r * 255.0);
if (pal_index == transparency_index) discard; // Don't render if it's transparent pixel
if (blend_mode == 0) {
color = vec4(0.0, texel.r, 0.0, 1.0);
} else {
int pal_index = int(texel.r * 255.0);
if (pal_index <= palette_limit) {
pal_index = clamp(palette_limit, 0, pal_index + palette_offset);
}
Expand Down
9 changes: 6 additions & 3 deletions shaders/palette.vert
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,20 @@

layout (location = 0) in vec2 position;
layout (location = 1) in vec2 tex_offset;
layout (location = 2) in int mode;
layout (location = 3) in int pal_offset;
layout (location = 4) in int pal_limit;
layout (location = 2) in int transparency;
layout (location = 3) in int mode;
layout (location = 4) in int pal_offset;
layout (location = 5) in int pal_limit;
uniform mat4 projection;

out vec2 tex_coord;
flat out int transparency_index;
flat out int blend_mode;
flat out int palette_offset;
flat out int palette_limit;

void main() {
transparency_index = transparency;
blend_mode = mode;
palette_offset = pal_offset;
palette_limit = pal_limit;
Expand Down
2 changes: 0 additions & 2 deletions src/formats/fonts.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,8 @@ int sd_font_decode(const sd_font *font, sd_vga_image *o, uint8_t ch, uint8_t col
for(int k = font->h - 1; k >= 0; k--) {
if(font->chars[ch].data[i] & (1 << k)) {
o->data[t] = color;
o->stencil[t] = 1;
} else {
o->data[t] = 0;
o->stencil[t] = 0;
}
t++;
}
Expand Down
3 changes: 0 additions & 3 deletions src/formats/pcx.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,14 +152,11 @@ int pcx_font_decode(const pcx_font *font, sd_vga_image *o, uint8_t ch, int8_t pa
for(int j = font->glyphs[ch].x; j < font->glyphs[ch].x + font->glyphs[ch].width; j++) {
if(font->pcx.image.data[(i * 320) + j]) {
o->data[(k * font->glyphs[ch].width) + l] = palette_offset + (int)font->pcx.image.data[(i * 320) + j];
o->stencil[(k * font->glyphs[ch].width) + l] = 1;
} else {
o->data[(k * font->glyphs[ch].width) + l] = 0;
o->stencil[(k * font->glyphs[ch].width) + l] = 0;
}

l++;
;
}
k++;
}
Expand Down
10 changes: 2 additions & 8 deletions src/formats/sprite.c
Original file line number Diff line number Diff line change
Expand Up @@ -295,10 +295,6 @@ int sd_sprite_vga_decode(sd_vga_image *dst, const sd_sprite *src) {
return SD_SUCCESS;
}

// everything defaults to transparent
int bsize = src->width * src->height;
memset(dst->stencil, 0, bsize);

// Walk through raw sprite data
while(i < src->len) {
// read a word
Expand All @@ -320,7 +316,6 @@ int sd_sprite_vga_decode(sd_vga_image *dst, const sd_sprite *src) {
uint8_t b = src->data[i];
int pos = ((y * src->width) + x);
dst->data[pos] = b;
dst->stencil[pos] = 1;
i++; // we read 1 byte
x++;
data--;
Expand Down Expand Up @@ -364,13 +359,12 @@ int sd_sprite_vga_encode(sd_sprite *dst, const sd_vga_image *src) {
buf[i++] = 0;
rowstart = i;

// Walk through the RGBA data
// Walk through the index data
for(int pos = 0; pos < vga_size; pos++) {
uint8_t idx = src->data[pos];
uint8_t stc = src->stencil[pos];

// ignore anything but fully opaque pixels
if(stc == 1) {
if(idx != 0) {
int16_t x = pos % src->w;
int16_t y = pos / src->w;
if(y != lasty) {
Expand Down
51 changes: 2 additions & 49 deletions src/formats/vga_image.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ int sd_vga_image_create(sd_vga_image *img, unsigned int w, unsigned int h) {
img->h = h;
img->len = w * h;
img->data = omf_calloc(1, w * h);
img->stencil = omf_calloc(1, w * h);
memset(img->stencil, 1, w * h);
return SD_SUCCESS;
}

Expand All @@ -29,9 +27,7 @@ int sd_vga_image_copy(sd_vga_image *dst, const sd_vga_image *src) {
dst->h = src->h;
dst->len = src->len;
dst->data = omf_calloc(src->len, 1);
dst->stencil = omf_calloc(src->len, 1);
memcpy(dst->data, src->data, src->len);
memcpy(dst->stencil, src->stencil, src->len);
return SD_SUCCESS;
}

Expand All @@ -40,44 +36,6 @@ void sd_vga_image_free(sd_vga_image *img) {
return;
}
omf_free(img->data);
omf_free(img->stencil);
}

int sd_vga_image_stencil_index(sd_vga_image *img, int stencil_index) {
if(stencil_index > 255 || img == NULL) {
return SD_INVALID_INPUT;
}

// If stencil_index is < 0, we are just making the image opaque
if(stencil_index < 0) {
memset(img->stencil, 1, img->w * img->h);
return SD_SUCCESS;
}

// Search & destroy!
for(int i = 0; i < img->w * img->h; i++) {
img->stencil[i] = (img->data[i] != stencil_index);
}
return SD_SUCCESS;
}

int sd_vga_image_encode(sd_vga_image *dst, const sd_rgba_image *src, const palette *pal, int remapping) {
int ret;
if(dst == NULL || src == NULL || pal == NULL) {
return SD_INVALID_INPUT;
}
if((ret = sd_vga_image_create(dst, src->w, src->h)) != SD_SUCCESS) {
return ret;
}
unsigned int rgb_size = (src->w * src->h * 4);
for(int pos = 0; pos <= rgb_size; pos += 4) {
uint8_t r = src->data[pos];
uint8_t g = src->data[pos + 1];
uint8_t b = src->data[pos + 2];
// ignore alpha channel, VGA images have no transparency
dst->data[pos / 4] = palette_resolve_color(r, g, b, pal);
}
return SD_SUCCESS;
}

int sd_vga_image_decode(sd_rgba_image *dst, const sd_vga_image *src, const palette *pal, int remapping) {
Expand All @@ -92,22 +50,17 @@ int sd_vga_image_decode(sd_rgba_image *dst, const sd_vga_image *src, const palet
for(int y = src->h - 1; y >= 0; y--) {
for(int x = 0; x < src->w; x++) {
uint8_t b = src->data[y * src->w + x];
uint8_t s = src->stencil[y * src->w + x];
pos = ((y * src->w) + x) * 4;
if(remapping > -1) {
dst->data[pos + 0] = (uint8_t)pal->data[(uint8_t)pal->remaps[remapping][b]][0];
dst->data[pos + 1] = (uint8_t)pal->data[(uint8_t)pal->remaps[remapping][b]][1];
dst->data[pos + 2] = (uint8_t)pal->data[(uint8_t)pal->remaps[remapping][b]][2];
dst->data[pos + 3] = (uint8_t)255;
} else {
dst->data[pos + 0] = (uint8_t)pal->data[b][0];
dst->data[pos + 1] = (uint8_t)pal->data[b][1];
dst->data[pos + 2] = (uint8_t)pal->data[b][2];
}
// check the stencil to see if this is a real pixel
if(s == 1) {
dst->data[pos + 3] = (uint8_t)255; // fully opaque
} else {
dst->data[pos + 3] = (uint8_t)0; // fully transparent
dst->data[pos + 3] = (uint8_t)255;
}
}
}
Expand Down
47 changes: 1 addition & 46 deletions src/formats/vga_image.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,19 @@
#include "formats/palette.h"
#include "formats/rgba_image.h"

#ifdef __cplusplus
extern "C" {
#endif

/*! \brief VGA image structure
*
* Contains a paletted image and transparency stencil. The image can be exported to
* Contains a paletted image. The image can be exported to
* an omf:2097 sprite by using a proper function sd_sprite_vga_encode() and back
* sd_sprite_vga_decode() . For RGBA conversion, a valid palette is required.
*
* Invisibility is handled by setting a single palette index as the invisibility stencil.
* This can be modified with library function sd_vga_image_stencil_index().
*
* In VGA images, the len field should always be exactly w*h bytes long.
*/
typedef struct {
unsigned int w; ///< Pixel width
unsigned int h; ///< Pixel height
unsigned int len; ///< Byte length
char *data; ///< Palette representation of image data
char *stencil; ///< holds 0 or 1 indicating whether a pixel is present
} sd_vga_image;

/*! \brief Initialize VGA image structure
Expand Down Expand Up @@ -76,39 +68,6 @@ int sd_vga_image_copy(sd_vga_image *dst, const sd_vga_image *src);
*/
void sd_vga_image_free(sd_vga_image *img);

/*! \brief Regenerates the stencil from a color index
*
* This function regenerates the invisibility mask for the VGA image.
* A necative value for stencil_index will lead to a completely opaque background,
* while a value of 0-255 will create a stencil from colors of this index.
*
* \retval SD_INVALID_INPUT Bad index value or img was NULL
* \retval SD_SUCCESS All good.
*
* \param img VGA image struct to modify.
* \param stencil_index Color key to use for invisibility
*/
int sd_vga_image_stencil_index(sd_vga_image *img, int stencil_index);

/*! \brief Encode RGBA data to VGA data
*
* Encodes RGBA image data to VGA image data. Color values will be matched to exact values in
* the palette. If no matching value is found for the pixel, the pixel color will be black.
*
* Note! The output VGA image will be created here. If the image had been
* already created by using sd_vga_image_create() previously, there may
* potentially be a memory leak, since the old image internals will not be freed.
*
* \retval SD_INVALID_INPUT Dst, src or palette was NULL.
* \retval SD_SUCCESS Success.
*
* \param dst Destination VGA image pointer.
* \param src Source RGBA image pointer
* \param pal Palette that should be used for the conversion
* \param remapping Palette remapping table that should be used. -1 for none.
*/
int sd_vga_image_encode(sd_vga_image *dst, const sd_rgba_image *src, const palette *pal, int remapping);

/*! \brief Decode VGA data to RGBA format
*
* Decodes the VGA image to RGBA image format.
Expand Down Expand Up @@ -164,8 +123,4 @@ int sd_vga_image_from_png(sd_vga_image *img, const char *filename);
*/
int sd_vga_image_to_png(const sd_vga_image *img, const palette *pal, const char *filename);

#ifdef __cplusplus
}
#endif

#endif // SD_VGA_IMAGE_H
4 changes: 2 additions & 2 deletions src/game/gui/text_render.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ int text_render_char(const text_settings *settings, text_mode state, int x, int
}

// Draw the actual font
video_draw_offset(*sur, x, y, color, 255);
video_draw_offset(*sur, x, y, color - 1, 255);
return (*sur)->w;
}

Expand Down Expand Up @@ -335,7 +335,7 @@ int font_render_char_shadowed(const font *font, char ch, int x, int y, uint8_t c
video_draw_offset(*sur, x, y - 1, shadow_color, 255);

// Handle the font face itself
video_draw_offset(*sur, x, y, c, 255);
video_draw_offset(*sur, x, y, c - 1, 255);
return (*sur)->w;
}

Expand Down
2 changes: 1 addition & 1 deletion src/game/protos/intersect.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ int intersect_sprite_hitpoint(object *obj, object *target, int level, vec2i *poi
if(target_dir == OBJECT_FACE_LEFT) {
hitpoint = (ycoord * sfc->w) + (sfc->w - xcoord);
}
if(hitpoint < sfc->w * sfc->h && sfc->stencil[hitpoint] > 0) {
if(hitpoint < sfc->w * sfc->h && sfc->data[hitpoint] != sfc->transparent) {
hcoords[found++] = vec2i_create(xcoord, ycoord);
if(found >= level) {
vec2f sum = vec2f_create(0, 0);
Expand Down
10 changes: 7 additions & 3 deletions src/game/protos/scene.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
#include "game/protos/scene.h"
#include "formats/af.h"
#include "formats/move.h"
#include "game/game_player.h"
#include "game/game_state_type.h"
#include "resources/af_loader.h"
Expand Down Expand Up @@ -33,6 +31,7 @@ int scene_create(scene *scene, game_state *gs, int scene_id) {
scene->gs = gs;
scene->af_data[0] = NULL;
scene->af_data[1] = NULL;
scene->static_ticks_since_start = 0;

// Init functions
scene->userdata = NULL;
Expand Down Expand Up @@ -107,7 +106,6 @@ void scene_init(scene *scene) {
}

int scene_clone(scene *src, scene *dst, game_state *gs) {

memcpy(dst, src, sizeof(scene));
dst->gs = gs;
if(src->clone) {
Expand Down Expand Up @@ -170,6 +168,7 @@ int scene_anim_prio_override(scene *scene, int anim_id) {
}

void scene_static_tick(scene *scene, int paused) {
scene->static_ticks_since_start++;
if(scene->static_tick != NULL) {
scene->static_tick(scene, paused);
}
Expand All @@ -187,6 +186,11 @@ void scene_dynamic_tick(scene *scene, int paused) {
}

void scene_input_poll(scene *scene) {
if(scene->static_ticks_since_start < 25) {
// Wait a bit at scene startup so that inputs from previous scene
// don't bleed to this one.
return;
}
if(scene->input_poll != NULL) {
scene->input_poll(scene);
}
Expand Down
1 change: 1 addition & 0 deletions src/game/protos/scene.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ struct scene_t {
bk *bk_data;
af *af_data[2];
void *userdata;
int static_ticks_since_start;

scene_free_cb free;
scene_event_cb event;
Expand Down
Loading
Loading