Skip to content

Commit

Permalink
support mipmaps and anisotropy (not used until we have premultiplied …
Browse files Browse the repository at this point in the history
…alpha)
  • Loading branch information
Akaricchi committed Jul 11, 2018
1 parent b4a6f5d commit c57d113
Show file tree
Hide file tree
Showing 24 changed files with 947 additions and 565 deletions.
28 changes: 6 additions & 22 deletions resources/shader/texture_post_load.frag.glsl
Expand Up @@ -2,28 +2,12 @@

#include "interface/standard.glslh"

UNIFORM(1) int width;
UNIFORM(2) int height;

vec2 tc_normalize(ivec2 tc) {
return vec2(tc) / vec2(width, height);
}

ivec2 tc_denormalize(vec2 tc) {
return ivec2(tc * vec2(width, height));
}

vec4 replace_color(vec4 texel, vec4 neighbour) {
return mix(texel, neighbour, float(neighbour.a > texel.a));
}

vec4 sampleofs(ivec2 origin, int ofsx, int ofsy) {
return texture(tex, tc_normalize(origin + ivec2(ofsx, ofsy)));
}

void main(void) {
ivec2 tc = tc_denormalize(texCoordRaw);
vec4 texel = texture(tex, texCoordRaw);
vec4 texel = textureLod(tex, texCoordRaw, 0);
vec4 new_texel = texel;

/*
Expand All @@ -33,11 +17,11 @@ void main(void) {
* As a workaround, we change the RGB values of such pixels to those of the most opaque nearby one.
*/

new_texel = replace_color(new_texel, sampleofs(tc, 0, 1));
new_texel = replace_color(new_texel, sampleofs(tc, 1, 0));
new_texel = replace_color(new_texel, sampleofs(tc, 0, -1));
new_texel = replace_color(new_texel, sampleofs(tc, -1, 0));
texel = mix(texel, vec4(new_texel.rgb, texel.a), float(texel.a <= 0.0));
new_texel = replace_color(new_texel, textureLodOffset(tex, texCoordRaw, 0, ivec2( 0, 1)));
new_texel = replace_color(new_texel, textureLodOffset(tex, texCoordRaw, 0, ivec2( 1, 0)));
new_texel = replace_color(new_texel, textureLodOffset(tex, texCoordRaw, 0, ivec2( 0, -1)));
new_texel = replace_color(new_texel, textureLodOffset(tex, texCoordRaw, 0, ivec2(-1, 0)));
texel = mix(texel, vec4(new_texel.rgb, texel.a), float(texel.a <= 0.5));

fragColor = texel;
}
32 changes: 22 additions & 10 deletions src/renderer/api.c
Expand Up @@ -325,20 +325,28 @@ void r_texture_create(Texture *tex, const TextureParams *params) {
B.texture_create(tex, params);
}

void r_texture_fill(Texture *tex, void *image_data) {
B.texture_fill(tex, image_data);
void r_texture_get_params(Texture *tex, TextureParams *params) {
B.texture_get_params(tex, params);
}

void r_texture_fill_region(Texture *tex, uint x, uint y, uint w, uint h, void *image_data) {
B.texture_fill_region(tex, x, y, w, h, image_data);
void r_texture_set_filter(Texture *tex, TextureFilterMode fmin, TextureFilterMode fmag) {
B.texture_set_filter(tex, fmin, fmag);
}

void r_texture_invalidate(Texture *tex) {
B.texture_invalidate(tex);
void r_texture_set_wrap(Texture *tex, TextureWrapMode ws, TextureWrapMode wt) {
B.texture_set_wrap(tex, ws, wt);
}

void r_texture_fill(Texture *tex, uint mipmap, void *image_data) {
B.texture_fill(tex, mipmap, image_data);
}

void r_texture_fill_region(Texture *tex, uint mipmap, uint x, uint y, uint w, uint h, void *image_data) {
B.texture_fill_region(tex, mipmap, x, y, w, h, image_data);
}

void r_texture_replace(Texture *tex, TextureType type, uint w, uint h, void *image_data) {
B.texture_replace(tex, type, w, h, image_data);
void r_texture_invalidate(Texture *tex) {
B.texture_invalidate(tex);
}

void r_texture_destroy(Texture *tex) {
Expand All @@ -358,14 +366,18 @@ void r_framebuffer_create(Framebuffer *fb) {
B.framebuffer_create(fb);
}

void r_framebuffer_attach(Framebuffer *fb, Texture *tex, FramebufferAttachment attachment) {
B.framebuffer_attach(fb, tex, attachment);
void r_framebuffer_attach(Framebuffer *fb, Texture *tex, uint mipmap, FramebufferAttachment attachment) {
B.framebuffer_attach(fb, tex, mipmap, attachment);
}

Texture* r_framebuffer_get_attachment(Framebuffer *fb, FramebufferAttachment attachment) {
return B.framebuffer_get_attachment(fb, attachment);
}

uint r_framebuffer_get_attachment_mipmap(Framebuffer *fb, FramebufferAttachment attachment) {
return B.framebuffer_get_attachment_mipmap(fb, attachment);
}

void r_framebuffer_viewport(Framebuffer *fb, int x, int y, int w, int h) {
r_framebuffer_viewport_rect(fb, (IntRect) { x, y, w, h });
}
Expand Down
44 changes: 30 additions & 14 deletions src/renderer/api.h
Expand Up @@ -48,44 +48,57 @@ typedef enum MatrixMode {
} MatrixMode;

typedef enum TextureType {
TEX_TYPE_DEFAULT,
TEX_TYPE_R,
TEX_TYPE_RG,
TEX_TYPE_RGB,
// NOTE: whichever is placed first here is considered the "default" where applicable.
TEX_TYPE_RGBA,
TEX_TYPE_RGB,
TEX_TYPE_RG,
TEX_TYPE_R,
TEX_TYPE_DEPTH,
} TextureType;

typedef enum TextureFilterMode {
TEX_FILTER_DEFAULT,
TEX_FILTER_NEAREST,
// NOTE: whichever is placed first here is considered the "default" where applicable.
TEX_FILTER_LINEAR,
TEX_FILTER_LINEAR_MIPMAP_NEAREST,
TEX_FILTER_LINEAR_MIPMAP_LINEAR,
TEX_FILTER_NEAREST,
TEX_FILTER_NEAREST_MIPMAP_NEAREST,
TEX_FILTER_NEAREST_MIPMAP_LINEAR,
} TextureFilterMode;

typedef enum TextureWrapMode {
TEX_WRAP_DEFAULT,
// NOTE: whichever is placed first here is considered the "default" where applicable.
TEX_WRAP_REPEAT,
TEX_WRAP_MIRROR,
TEX_WRAP_CLAMP,
} TextureWrapMode;

typedef enum TextureMipmapMode {
TEX_MIPMAP_MANUAL,
TEX_MIPMAP_AUTO,
} TextureMipmapMode;

#define TEX_ANISOTROPY_DEFAULT 1
#define TEX_MIPMAPS_MAX ((uint)(-1))

typedef struct TextureParams {
uint width;
uint height;
TextureType type;

struct {
TextureFilterMode upscale;
TextureFilterMode downscale;
TextureFilterMode mag;
TextureFilterMode min;
} filter;

struct {
TextureWrapMode s;
TextureWrapMode t;
} wrap;

int anisotropy;
uint mipmaps;
uint8_t *image_data;
TextureMipmapMode mipmap_mode;
bool stream;
} attr_designated_init TextureParams;

Expand Down Expand Up @@ -404,18 +417,21 @@ UniformType r_uniform_type(Uniform *uniform);
void r_draw(Primitive prim, uint first, uint count, uint32_t *indices, uint instances, uint base_instance);

void r_texture_create(Texture *tex, const TextureParams *params) attr_nonnull(1, 2);
void r_texture_fill(Texture *tex, void *image_data) attr_nonnull(1, 2);
void r_texture_fill_region(Texture *tex, uint x, uint y, uint w, uint h, void *image_data) attr_nonnull(1, 6);
void r_texture_get_params(Texture *tex, TextureParams *params) attr_nonnull(1, 2);
void r_texture_set_filter(Texture *tex, TextureFilterMode fmin, TextureFilterMode fmag) attr_nonnull(1);
void r_texture_set_wrap(Texture *tex, TextureWrapMode ws, TextureWrapMode wt) attr_nonnull(1);
void r_texture_fill(Texture *tex, uint mipmap, void *image_data) attr_nonnull(1, 3);
void r_texture_fill_region(Texture *tex, uint mipmap, uint x, uint y, uint w, uint h, void *image_data) attr_nonnull(1, 7);
void r_texture_invalidate(Texture *tex) attr_nonnull(1);
void r_texture_replace(Texture *tex, TextureType type, uint w, uint h, void *image_data) attr_nonnull(1);
void r_texture_destroy(Texture *tex) attr_nonnull(1);

void r_texture_ptr(uint unit, Texture *tex);
Texture* r_texture_current(uint unit);

void r_framebuffer_create(Framebuffer *fb) attr_nonnull(1);
void r_framebuffer_attach(Framebuffer *fb, Texture *tex, FramebufferAttachment attachment) attr_nonnull(1);
void r_framebuffer_attach(Framebuffer *fb, Texture *tex, uint mipmap, FramebufferAttachment attachment) attr_nonnull(1);
Texture* r_framebuffer_get_attachment(Framebuffer *fb, FramebufferAttachment attachment) attr_nonnull(1);
uint r_framebuffer_get_attachment_mipmap(Framebuffer *fb, FramebufferAttachment attachment) attr_nonnull(1);
void r_framebuffer_viewport(Framebuffer *fb, int x, int y, int w, int h);
void r_framebuffer_viewport_rect(Framebuffer *fb, IntRect viewport);
void r_framebuffer_viewport_current(Framebuffer *fb, IntRect *viewport) attr_nonnull(2);
Expand Down
11 changes: 7 additions & 4 deletions src/renderer/common/backend.h
Expand Up @@ -46,21 +46,24 @@ typedef struct RendererFuncs {
UniformType (*uniform_type)(Uniform *uniform);

void (*texture_create)(Texture *tex, const TextureParams *params);
void (*texture_get_params)(Texture *tex, TextureParams *params);
void (*texture_set_filter)(Texture *tex, TextureFilterMode fmin, TextureFilterMode fmag);
void (*texture_set_wrap)(Texture *tex, TextureWrapMode ws, TextureWrapMode wt);
void (*texture_destroy)(Texture *tex);
void (*texture_invalidate)(Texture *tex);
void (*texture_fill)(Texture *tex, void *image_data);
void (*texture_fill_region)(Texture *tex, uint x, uint y, uint w, uint h, void *image_data);
void (*texture_replace)(Texture *tex, TextureType type, uint w, uint h, void *image_data);
void (*texture_fill)(Texture *tex, uint mipmap, void *image_data);
void (*texture_fill_region)(Texture *tex, uint mipmap, uint x, uint y, uint w, uint h, void *image_data);

void (*texture)(uint unit, Texture *tex);
Texture* (*texture_current)(uint unit);

void (*framebuffer_create)(Framebuffer *framebuffer);
void (*framebuffer_destroy)(Framebuffer *framebuffer);
void (*framebuffer_attach)(Framebuffer *framebuffer, Texture *tex, FramebufferAttachment attachment);
void (*framebuffer_attach)(Framebuffer *framebuffer, Texture *tex, uint mipmap, FramebufferAttachment attachment);
void (*framebuffer_viewport)(Framebuffer *framebuffer, IntRect vp);
void (*framebuffer_viewport_current)(Framebuffer *framebuffer, IntRect *vp);
Texture* (*framebuffer_get_attachment)(Framebuffer *framebuffer, FramebufferAttachment attachment);
uint (*framebuffer_get_attachment_mipmap)(Framebuffer *framebuffer, FramebufferAttachment attachment);

void (*framebuffer)(Framebuffer *framebuffer);
Framebuffer* (*framebuffer_current)(void);
Expand Down
20 changes: 13 additions & 7 deletions src/renderer/gl33/core.c
Expand Up @@ -278,15 +278,14 @@ static void gl33_sync_viewport(void) {
}

static void gl33_sync_state(void) {

gl33_sync_capabilities();
gl33_sync_shader();
r_uniform("r_modelViewMatrix", 1, _r_matrices.modelview.head);
r_uniform("r_projectionMatrix", 1, _r_matrices.projection.head);
r_uniform("r_textureMatrix", 1, _r_matrices.texture.head);
r_uniform("r_color", 1, R.color);
gl33_sync_uniforms(R.progs.active);
gl33_sync_texunits();
gl33_sync_texunits(true);
gl33_sync_framebuffer();
gl33_sync_viewport();
gl33_sync_vertex_array();
Expand Down Expand Up @@ -323,7 +322,7 @@ void gl33_sync_capabilities(void) {
R.capabilities.active = R.capabilities.pending;
}

void gl33_sync_texunit(uint unit) {
void gl33_sync_texunit(uint unit, bool prepare_rendering) {
TextureUnit *u = R.texunits.indexed + unit;
Texture *tex = u->tex2d.pending;

Expand All @@ -340,11 +339,15 @@ void gl33_sync_texunit(uint unit) {
u->tex2d.gl_handle = tex->impl->gl_handle;
u->tex2d.active = tex;
}

if(prepare_rendering && u->tex2d.active != NULL) {
gl33_texture_prepare(u->tex2d.active);
}
}

void gl33_sync_texunits(void) {
void gl33_sync_texunits(bool prepare_rendering) {
for(uint i = 0; i < R_MAX_TEXUNITS; ++i) {
gl33_sync_texunit(i);
gl33_sync_texunit(i, prepare_rendering);
}
}

Expand Down Expand Up @@ -416,7 +419,7 @@ void gl33_sync_framebuffer(void) {
}

if(R.framebuffer.active) {
gl33_framebuffer_initialize(R.framebuffer.active);
gl33_framebuffer_prepare(R.framebuffer.active);
}
}

Expand Down Expand Up @@ -880,17 +883,20 @@ RendererBackend _r_backend_gl33 = {
.uniform = gl33_uniform,
.uniform_type = gl33_uniform_type,
.texture_create = gl33_texture_create,
.texture_get_params = gl33_texture_get_params,
.texture_set_filter = gl33_texture_set_filter,
.texture_set_wrap = gl33_texture_set_wrap,
.texture_destroy = gl33_texture_destroy,
.texture_invalidate = gl33_texture_invalidate,
.texture_fill = gl33_texture_fill,
.texture_fill_region = gl33_texture_fill_region,
.texture_replace = gl33_texture_replace,
.texture = gl33_texture,
.texture_current = gl33_texture_current,
.framebuffer_create = gl33_framebuffer_create,
.framebuffer_destroy = gl33_framebuffer_destroy,
.framebuffer_attach = gl33_framebuffer_attach,
.framebuffer_get_attachment = gl33_framebuffer_get_attachment,
.framebuffer_get_attachment_mipmap = gl33_framebuffer_get_attachment_mipmap,
.framebuffer_viewport = gl33_framebuffer_viewport,
.framebuffer_viewport_current = gl33_framebuffer_viewport_current,
.framebuffer = gl33_framebuffer,
Expand Down
4 changes: 2 additions & 2 deletions src/renderer/gl33/core.h
Expand Up @@ -24,8 +24,8 @@ void gl33_bind_vao(GLuint vao);
void gl33_bind_vbo(GLuint vbo);

void gl33_sync_shader(void);
void gl33_sync_texunit(uint unit);
void gl33_sync_texunits(void);
void gl33_sync_texunit(uint unit, bool prepare_rendering);
void gl33_sync_texunits(bool prepare_rendering);
void gl33_sync_framebuffer(void);
void gl33_sync_vertex_array(void);
void gl33_sync_blend_mode(void);
Expand Down
32 changes: 21 additions & 11 deletions src/renderer/gl33/framebuffer.c
Expand Up @@ -27,8 +27,9 @@ void gl33_framebuffer_create(Framebuffer *framebuffer) {
glGenFramebuffers(1, &framebuffer->impl->gl_fbo);
}

void gl33_framebuffer_attach(Framebuffer *framebuffer, Texture *tex, FramebufferAttachment attachment) {
void gl33_framebuffer_attach(Framebuffer *framebuffer, Texture *tex, uint mipmap, FramebufferAttachment attachment) {
assert(attachment >= 0 && attachment < FRAMEBUFFER_MAX_ATTACHMENTS);
assert(mipmap < tex->impl->params.mipmaps);

GLuint gl_tex = tex ? tex->impl->gl_handle : 0;
Framebuffer *prev_fb = r_framebuffer_current();
Expand All @@ -38,10 +39,11 @@ void gl33_framebuffer_attach(Framebuffer *framebuffer, Texture *tex, Framebuffer

r_framebuffer(framebuffer);
gl33_sync_framebuffer();
glFramebufferTexture2D(GL_FRAMEBUFFER, r_attachment_to_gl_attachment[attachment], GL_TEXTURE_2D, gl_tex, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, r_attachment_to_gl_attachment[attachment], GL_TEXTURE_2D, gl_tex, mipmap);
r_framebuffer(prev_fb);

framebuffer->impl->attachments[attachment] = tex;
framebuffer->impl->attachment_mipmaps[attachment] = mipmap;

// need to update draw buffers
framebuffer->impl->initialized = false;
Expand All @@ -61,6 +63,14 @@ Texture* gl33_framebuffer_get_attachment(Framebuffer *framebuffer, FramebufferAt
return framebuffer->impl->attachments[attachment];
}


uint gl33_framebuffer_get_attachment_mipmap(Framebuffer *framebuffer, FramebufferAttachment attachment) {
assert(framebuffer->impl != NULL);
assert(attachment >= 0 && attachment < FRAMEBUFFER_MAX_ATTACHMENTS);

return framebuffer->impl->attachment_mipmaps[attachment];
}

void gl33_framebuffer_destroy(Framebuffer *framebuffer) {
if(framebuffer->impl != NULL) {
gl33_framebuffer_deleted(framebuffer);
Expand All @@ -70,7 +80,15 @@ void gl33_framebuffer_destroy(Framebuffer *framebuffer) {
}
}

void gl33_framebuffer_initialize(Framebuffer *framebuffer) {
void gl33_framebuffer_taint(Framebuffer *framebuffer) {
for(uint i = 0; i < FRAMEBUFFER_MAX_ATTACHMENTS; ++i) {
if(framebuffer->impl->attachments[i] != NULL) {
gl33_texture_taint(framebuffer->impl->attachments[i]);
}
}
}

void gl33_framebuffer_prepare(Framebuffer *framebuffer) {
if(!framebuffer->impl->initialized) {
// NOTE: this framebuffer is guaranteed to be active at this point

Expand All @@ -87,13 +105,5 @@ void gl33_framebuffer_initialize(Framebuffer *framebuffer) {

glDrawBuffers(FRAMEBUFFER_MAX_COLOR_ATTACHMENTS, drawbufs);
}

Color cc_saved = r_clear_color_current();
r_clear_color4(0, 0, 0, 0);
// NOTE: r_clear would cause an infinite recursion here
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
r_clear_color(cc_saved);

framebuffer->impl->initialized = true;
}
}

0 comments on commit c57d113

Please sign in to comment.