UI: Support for runtime geometry icons
This commit is contained in:
@@ -36,14 +36,39 @@
|
||||
|
||||
typedef void (*DrawInfoFreeFP)(void *drawinfo);
|
||||
|
||||
enum {
|
||||
/** ID preview: obj is #ID. */
|
||||
ICON_DATA_ID = 0,
|
||||
/** Preview: obj is #PreviewImage */
|
||||
ICON_DATA_PREVIEW,
|
||||
/** 2D triangles: obj is #Icon_Geom */
|
||||
ICON_DATA_GEOM,
|
||||
};
|
||||
|
||||
struct Icon {
|
||||
void *drawinfo;
|
||||
/**
|
||||
* Data defined by #obj_type
|
||||
* \note for #ICON_DATA_GEOM the memory is owned by the icon,
|
||||
* could be made into a flag if we want that to be optional.
|
||||
*/
|
||||
void *obj;
|
||||
char obj_type;
|
||||
/** Internal use only. */
|
||||
char flag;
|
||||
/** #ID_Type or 0 when not used for ID preview. */
|
||||
short id_type;
|
||||
DrawInfoFreeFP drawinfo_free;
|
||||
};
|
||||
|
||||
/** Used for #ICON_DATA_GEOM, assigned to #Icon.obj. */
|
||||
struct Icon_Geom {
|
||||
int icon_id;
|
||||
int coords_len;
|
||||
const unsigned char (*coords)[2];
|
||||
const unsigned char (*colors)[4];
|
||||
};
|
||||
|
||||
typedef struct Icon Icon;
|
||||
|
||||
struct PreviewImage;
|
||||
@@ -58,6 +83,8 @@ int BKE_icon_id_ensure(struct ID *id);
|
||||
|
||||
int BKE_icon_preview_ensure(struct ID *id, struct PreviewImage *preview);
|
||||
|
||||
int BKE_icon_geom_ensure(struct Icon_Geom *geom);
|
||||
|
||||
/* retrieve icon for id */
|
||||
struct Icon *BKE_icon_get(const int icon_id);
|
||||
|
||||
@@ -68,7 +95,8 @@ void BKE_icon_set(const int icon_id, struct Icon *icon);
|
||||
/* remove icon and free data if library object becomes invalid */
|
||||
void BKE_icon_id_delete(struct ID *id);
|
||||
|
||||
void BKE_icon_delete(const int icon_id);
|
||||
bool BKE_icon_delete(const int icon_id);
|
||||
bool BKE_icon_delete_unmanaged(const int icon_id);
|
||||
|
||||
/* report changes - icon needs to be recalculated */
|
||||
void BKE_icon_changed(const int icon_id);
|
||||
|
||||
@@ -64,6 +64,14 @@
|
||||
#include "IMB_imbuf_types.h"
|
||||
#include "IMB_thumbs.h"
|
||||
|
||||
/**
|
||||
* Only allow non-managed icons to be removed (by Python for eg).
|
||||
* Previews & ID's have their own functions to remove icons.
|
||||
*/
|
||||
enum {
|
||||
ICON_FLAG_MANAGED = (1 << 0),
|
||||
};
|
||||
|
||||
/* GLOBALS */
|
||||
|
||||
static GHash *gIcons = NULL;
|
||||
@@ -86,6 +94,13 @@ static void icon_free(void *val)
|
||||
Icon *icon = val;
|
||||
|
||||
if (icon) {
|
||||
if (icon->obj_type == ICON_DATA_GEOM) {
|
||||
struct Icon_Geom *obj = icon->obj;
|
||||
MEM_freeN((void *)obj->coords);
|
||||
MEM_freeN((void *)obj->colors);
|
||||
MEM_freeN(icon->obj);
|
||||
}
|
||||
|
||||
if (icon->drawinfo_free) {
|
||||
icon->drawinfo_free(icon->drawinfo);
|
||||
}
|
||||
@@ -96,6 +111,22 @@ static void icon_free(void *val)
|
||||
}
|
||||
}
|
||||
|
||||
static void icon_free_data(Icon *icon)
|
||||
{
|
||||
if (icon->obj_type == ICON_DATA_ID) {
|
||||
((ID *)(icon->obj))->icon_id = 0;
|
||||
}
|
||||
else if (icon->obj_type == ICON_DATA_PREVIEW) {
|
||||
((PreviewImage *)(icon->obj))->icon_id = 0;
|
||||
}
|
||||
else if (icon->obj_type == ICON_DATA_GEOM) {
|
||||
((struct Icon_Geom *)(icon->obj))->icon_id = 0;
|
||||
}
|
||||
else {
|
||||
BLI_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* create an id for a new icon and make sure that ids from deleted icons get reused
|
||||
* after the integer number range is used up */
|
||||
static int get_next_free_id(void)
|
||||
@@ -478,6 +509,7 @@ void BKE_icon_changed(const int icon_id)
|
||||
if (icon) {
|
||||
/* We *only* expect ID-tied icons here, not non-ID icon/preview! */
|
||||
BLI_assert(icon->id_type != 0);
|
||||
BLI_assert(icon->obj_type == ICON_DATA_ID);
|
||||
|
||||
/* Do not enforce creation of previews for valid ID types using BKE_previewimg_id_ensure() here ,
|
||||
* we only want to ensure *existing* preview images are properly tagged as changed/invalid, that's all. */
|
||||
@@ -494,22 +526,31 @@ void BKE_icon_changed(const int icon_id)
|
||||
}
|
||||
}
|
||||
|
||||
static int icon_id_ensure_create_icon(struct ID *id)
|
||||
static Icon *icon_create(int icon_id, int obj_type, void *obj)
|
||||
{
|
||||
BLI_assert(BLI_thread_is_main());
|
||||
Icon *new_icon = MEM_mallocN(sizeof(Icon), __func__);
|
||||
|
||||
Icon *new_icon = NULL;
|
||||
|
||||
new_icon = MEM_mallocN(sizeof(Icon), __func__);
|
||||
|
||||
new_icon->obj = id;
|
||||
new_icon->id_type = GS(id->name);
|
||||
new_icon->obj_type = obj_type;
|
||||
new_icon->obj = obj;
|
||||
new_icon->id_type = 0;
|
||||
new_icon->flag = 0;
|
||||
|
||||
/* next two lines make sure image gets created */
|
||||
new_icon->drawinfo = NULL;
|
||||
new_icon->drawinfo_free = NULL;
|
||||
|
||||
BLI_ghash_insert(gIcons, SET_INT_IN_POINTER(id->icon_id), new_icon);
|
||||
BLI_ghash_insert(gIcons, SET_INT_IN_POINTER(icon_id), new_icon);
|
||||
|
||||
return new_icon;
|
||||
}
|
||||
|
||||
static int icon_id_ensure_create_icon(struct ID *id)
|
||||
{
|
||||
BLI_assert(BLI_thread_is_main());
|
||||
|
||||
Icon *icon = icon_create(id->icon_id, ICON_DATA_ID, id);
|
||||
icon->id_type = GS(id->name);
|
||||
icon->flag = ICON_FLAG_MANAGED;
|
||||
|
||||
return id->icon_id;
|
||||
}
|
||||
@@ -544,8 +585,6 @@ int BKE_icon_id_ensure(struct ID *id)
|
||||
*/
|
||||
int BKE_icon_preview_ensure(ID *id, PreviewImage *preview)
|
||||
{
|
||||
Icon *new_icon = NULL;
|
||||
|
||||
if (!preview || G.background)
|
||||
return 0;
|
||||
|
||||
@@ -576,20 +615,28 @@ int BKE_icon_preview_ensure(ID *id, PreviewImage *preview)
|
||||
return icon_id_ensure_create_icon(id);
|
||||
}
|
||||
|
||||
new_icon = MEM_mallocN(sizeof(Icon), __func__);
|
||||
|
||||
new_icon->obj = preview;
|
||||
new_icon->id_type = 0; /* Special, tags as non-ID icon/preview. */
|
||||
|
||||
/* next two lines make sure image gets created */
|
||||
new_icon->drawinfo = NULL;
|
||||
new_icon->drawinfo_free = NULL;
|
||||
|
||||
BLI_ghash_insert(gIcons, SET_INT_IN_POINTER(preview->icon_id), new_icon);
|
||||
Icon *icon = icon_create(preview->icon_id, ICON_DATA_PREVIEW, preview);
|
||||
icon->flag = ICON_FLAG_MANAGED;
|
||||
|
||||
return preview->icon_id;
|
||||
}
|
||||
|
||||
int BKE_icon_geom_ensure(struct Icon_Geom *geom)
|
||||
{
|
||||
BLI_assert(BLI_thread_is_main());
|
||||
|
||||
if (geom->icon_id) {
|
||||
return geom->icon_id;
|
||||
}
|
||||
|
||||
geom->icon_id = get_next_free_id();
|
||||
|
||||
icon_create(geom->icon_id, ICON_DATA_GEOM, geom);
|
||||
/* Not managed for now, we may want this to be configurable per icon). */
|
||||
|
||||
return geom->icon_id;
|
||||
}
|
||||
|
||||
Icon *BKE_icon_get(const int icon_id)
|
||||
{
|
||||
BLI_assert(BLI_thread_is_main());
|
||||
@@ -647,21 +694,44 @@ void BKE_icon_id_delete(struct ID *id)
|
||||
/**
|
||||
* Remove icon and free data.
|
||||
*/
|
||||
void BKE_icon_delete(const int icon_id)
|
||||
bool BKE_icon_delete(const int icon_id)
|
||||
{
|
||||
Icon *icon;
|
||||
|
||||
if (!icon_id) return; /* no icon defined for library object */
|
||||
|
||||
icon = BLI_ghash_popkey(gIcons, SET_INT_IN_POINTER(icon_id), NULL);
|
||||
if (icon_id == 0) {
|
||||
/* no icon defined for library object */
|
||||
return false;
|
||||
}
|
||||
|
||||
Icon *icon = BLI_ghash_popkey(gIcons, SET_INT_IN_POINTER(icon_id), NULL);
|
||||
if (icon) {
|
||||
if (icon->id_type != 0) {
|
||||
((ID *)(icon->obj))->icon_id = 0;
|
||||
}
|
||||
else {
|
||||
((PreviewImage *)(icon->obj))->icon_id = 0;
|
||||
}
|
||||
icon_free_data(icon);
|
||||
icon_free(icon);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool BKE_icon_delete_unmanaged(const int icon_id)
|
||||
{
|
||||
if (icon_id == 0) {
|
||||
/* no icon defined for library object */
|
||||
return false;
|
||||
}
|
||||
|
||||
Icon *icon = BLI_ghash_popkey(gIcons, SET_INT_IN_POINTER(icon_id), NULL);
|
||||
if (icon) {
|
||||
if (UNLIKELY(icon->flag & ICON_FLAG_MANAGED)) {
|
||||
BLI_ghash_insert(gIcons, SET_INT_IN_POINTER(icon_id), icon);
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
icon_free_data(icon);
|
||||
icon_free(icon);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
|
||||
#include "GPU_draw.h"
|
||||
#include "GPU_matrix.h"
|
||||
#include "GPU_batch.h"
|
||||
#include "GPU_immediate.h"
|
||||
|
||||
#include "BLI_blenlib.h"
|
||||
@@ -98,6 +99,7 @@ typedef void (*VectorDrawFunc)(int x, int y, int w, int h, float alpha);
|
||||
#define ICON_TYPE_TEXTURE 1
|
||||
#define ICON_TYPE_BUFFER 2
|
||||
#define ICON_TYPE_VECTOR 3
|
||||
#define ICON_TYPE_GEOM 4
|
||||
|
||||
typedef struct DrawInfo {
|
||||
int type;
|
||||
@@ -107,6 +109,9 @@ typedef struct DrawInfo {
|
||||
struct {
|
||||
VectorDrawFunc func;
|
||||
} vector;
|
||||
struct {
|
||||
Gwn_Batch *batch;
|
||||
} geom;
|
||||
struct {
|
||||
IconImage *image;
|
||||
} buffer;
|
||||
@@ -742,18 +747,61 @@ void UI_icons_free_drawinfo(void *drawinfo)
|
||||
MEM_freeN(di->data.buffer.image);
|
||||
}
|
||||
}
|
||||
else if (di->type == ICON_TYPE_GEOM) {
|
||||
if (di->data.geom.batch) {
|
||||
GWN_BATCH_DISCARD_SAFE(di->data.geom.batch);
|
||||
}
|
||||
}
|
||||
|
||||
MEM_freeN(di);
|
||||
}
|
||||
}
|
||||
|
||||
static DrawInfo *icon_create_drawinfo(void)
|
||||
/**
|
||||
* #Icon.data_type and #Icon.obj
|
||||
*/
|
||||
static DrawInfo *icon_create_drawinfo(int icon_data_type, void *icon_obj)
|
||||
{
|
||||
DrawInfo *di = NULL;
|
||||
|
||||
di = MEM_callocN(sizeof(DrawInfo), "di_icon");
|
||||
di->type = ICON_TYPE_PREVIEW;
|
||||
|
||||
if (ELEM(icon_data_type, ICON_DATA_ID, ICON_DATA_PREVIEW)) {
|
||||
di->type = ICON_TYPE_PREVIEW;
|
||||
}
|
||||
else if (icon_data_type == ICON_DATA_GEOM) {
|
||||
di->type = ICON_TYPE_GEOM;
|
||||
|
||||
struct Icon_Geom *geom = icon_obj;
|
||||
static Gwn_VertFormat format = {0};
|
||||
static struct { uint pos, color; } attr_id;
|
||||
if (format.attrib_ct == 0) {
|
||||
attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_U8, 2, GWN_FETCH_INT_TO_FLOAT_UNIT);
|
||||
attr_id.color = GWN_vertformat_attr_add(&format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
|
||||
}
|
||||
Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
|
||||
GWN_vertbuf_data_alloc(vbo, geom->coords_len * 3);
|
||||
GWN_vertbuf_attr_fill(vbo, attr_id.pos, geom->coords);
|
||||
GWN_vertbuf_attr_fill(vbo, attr_id.color, geom->colors);
|
||||
|
||||
Gwn_Batch *batch = GWN_batch_create_ex(GWN_PRIM_TRIS, vbo, NULL, GWN_BATCH_OWNS_VBO);
|
||||
di->data.geom.batch = batch;
|
||||
}
|
||||
else {
|
||||
BLI_assert(0);
|
||||
}
|
||||
|
||||
return di;
|
||||
}
|
||||
|
||||
static DrawInfo *icon_ensure_drawinfo(Icon *icon)
|
||||
{
|
||||
if (icon->drawinfo) {
|
||||
return icon->drawinfo;
|
||||
}
|
||||
DrawInfo *di = icon_create_drawinfo(icon->obj_type, icon->obj);
|
||||
icon->drawinfo = di;
|
||||
icon->drawinfo_free = UI_icons_free_drawinfo;
|
||||
return di;
|
||||
}
|
||||
|
||||
@@ -771,40 +819,27 @@ int UI_icon_get_width(int icon_id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
di = (DrawInfo *)icon->drawinfo;
|
||||
if (!di) {
|
||||
di = icon_create_drawinfo();
|
||||
icon->drawinfo = di;
|
||||
}
|
||||
|
||||
if (di)
|
||||
di = icon_ensure_drawinfo(icon);
|
||||
if (di) {
|
||||
return ICON_DEFAULT_WIDTH;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int UI_icon_get_height(int icon_id)
|
||||
{
|
||||
Icon *icon = NULL;
|
||||
DrawInfo *di = NULL;
|
||||
|
||||
icon = BKE_icon_get(icon_id);
|
||||
|
||||
Icon *icon = BKE_icon_get(icon_id);
|
||||
if (icon == NULL) {
|
||||
if (G.debug & G_DEBUG)
|
||||
printf("%s: Internal error, no icon for icon ID: %d\n", __func__, icon_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
di = (DrawInfo *)icon->drawinfo;
|
||||
|
||||
if (!di) {
|
||||
di = icon_create_drawinfo();
|
||||
icon->drawinfo = di;
|
||||
}
|
||||
|
||||
if (di)
|
||||
DrawInfo *di = icon_ensure_drawinfo(icon);
|
||||
if (di) {
|
||||
return ICON_DEFAULT_HEIGHT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -861,14 +896,7 @@ void ui_icon_ensure_deferred(const bContext *C, const int icon_id, const bool bi
|
||||
Icon *icon = BKE_icon_get(icon_id);
|
||||
|
||||
if (icon) {
|
||||
DrawInfo *di = (DrawInfo *)icon->drawinfo;
|
||||
|
||||
if (!di) {
|
||||
di = icon_create_drawinfo();
|
||||
|
||||
icon->drawinfo = di;
|
||||
icon->drawinfo_free = UI_icons_free_drawinfo;
|
||||
}
|
||||
DrawInfo *di = icon_ensure_drawinfo(icon);
|
||||
|
||||
if (di) {
|
||||
switch (di->type) {
|
||||
@@ -1183,7 +1211,6 @@ static void icon_draw_size(
|
||||
{
|
||||
bTheme *btheme = UI_GetTheme();
|
||||
Icon *icon = NULL;
|
||||
DrawInfo *di = NULL;
|
||||
IconImage *iimg;
|
||||
const float fdraw_size = (float)draw_size;
|
||||
int w, h;
|
||||
@@ -1197,19 +1224,12 @@ static void icon_draw_size(
|
||||
return;
|
||||
}
|
||||
|
||||
di = (DrawInfo *)icon->drawinfo;
|
||||
|
||||
if (!di) {
|
||||
di = icon_create_drawinfo();
|
||||
|
||||
icon->drawinfo = di;
|
||||
icon->drawinfo_free = UI_icons_free_drawinfo;
|
||||
}
|
||||
|
||||
/* scale width and height according to aspect */
|
||||
w = (int)(fdraw_size / aspect + 0.5f);
|
||||
h = (int)(fdraw_size / aspect + 0.5f);
|
||||
|
||||
|
||||
DrawInfo *di = icon_ensure_drawinfo(icon);
|
||||
|
||||
if (di->type == ICON_TYPE_VECTOR) {
|
||||
/* We need to flush widget base first to ensure correct ordering. */
|
||||
UI_widgetbase_draw_cache_flush();
|
||||
@@ -1217,6 +1237,29 @@ static void icon_draw_size(
|
||||
* with untransformed coordinates like the other icons */
|
||||
di->data.vector.func((int)x, (int)y, w, h, 1.0f);
|
||||
}
|
||||
else if (di->type == ICON_TYPE_GEOM) {
|
||||
/* We need to flush widget base first to ensure correct ordering. */
|
||||
UI_widgetbase_draw_cache_flush();
|
||||
|
||||
gpuPushMatrix();
|
||||
gpuTranslate2f(x, y);
|
||||
gpuScale2f(w, h);
|
||||
|
||||
{
|
||||
struct Gwn_Batch *batch = di->data.geom.batch;
|
||||
GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_SMOOTH_COLOR_UNIFORM_ALPHA);
|
||||
GWN_batch_uniform_1f(batch, "alpha", 1.0f / UI_PIXEL_AA_JITTER);
|
||||
|
||||
for (uint i = 0; i < UI_PIXEL_AA_JITTER; i += 1) {
|
||||
gpuTranslate2f(ui_pixel_jitter[i][0] / w, ui_pixel_jitter[i][1] / h);
|
||||
GWN_batch_draw(batch);
|
||||
gpuTranslate2f(-ui_pixel_jitter[i][0] / w, -ui_pixel_jitter[i][1] / h);
|
||||
}
|
||||
GWN_batch_program_use_end(batch);
|
||||
}
|
||||
|
||||
gpuPopMatrix();
|
||||
}
|
||||
else if (di->type == ICON_TYPE_TEXTURE) {
|
||||
/* texture image use premul alpha for correct scaling */
|
||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
@@ -749,6 +749,9 @@ void ui_draw_preview_item(struct uiFontStyle *fstyle, rcti *rect, const char *na
|
||||
/* margin at top of screen for popups */
|
||||
#define UI_POPUP_MENU_TOP (int)(8 * UI_DPI_FAC)
|
||||
|
||||
#define UI_PIXEL_AA_JITTER 8
|
||||
const float ui_pixel_jitter[UI_PIXEL_AA_JITTER][2];
|
||||
|
||||
/* interface_style.c */
|
||||
void uiStyleInit(void);
|
||||
|
||||
|
||||
@@ -157,13 +157,15 @@ static const float cornervec[WIDGET_CURVE_RESOLU][2] = {
|
||||
{0.924, 0.617}, {0.98, 0.805}, {1.0, 1.0}
|
||||
};
|
||||
|
||||
#define WIDGET_AA_JITTER 8
|
||||
static const float jit[WIDGET_AA_JITTER][2] = {
|
||||
|
||||
const float ui_pixel_jitter[UI_PIXEL_AA_JITTER][2] = {
|
||||
{ 0.468813, -0.481430}, {-0.155755, -0.352820},
|
||||
{ 0.219306, -0.238501}, {-0.393286, -0.110949},
|
||||
{-0.024699, 0.013908}, { 0.343805, 0.147431},
|
||||
{-0.272855, 0.269918}, { 0.095909, 0.388710}
|
||||
};
|
||||
#define WIDGET_AA_JITTER UI_PIXEL_AA_JITTER
|
||||
#define jit ui_pixel_jitter
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Shape Preset Data
|
||||
|
||||
@@ -142,6 +142,7 @@ data_to_c_simple(shaders/gpu_shader_2D_line_dashed_frag.glsl SRC)
|
||||
data_to_c_simple(shaders/gpu_shader_2D_line_dashed_geom.glsl SRC)
|
||||
data_to_c_simple(shaders/gpu_shader_2D_smooth_color_vert.glsl SRC)
|
||||
data_to_c_simple(shaders/gpu_shader_2D_smooth_color_frag.glsl SRC)
|
||||
data_to_c_simple(shaders/gpu_shader_2D_smooth_color_uniform_alpha_vert.glsl SRC)
|
||||
data_to_c_simple(shaders/gpu_shader_2D_image_vert.glsl SRC)
|
||||
data_to_c_simple(shaders/gpu_shader_2D_image_rect_vert.glsl SRC)
|
||||
data_to_c_simple(shaders/gpu_shader_2D_image_multi_rect_vert.glsl SRC)
|
||||
|
||||
@@ -111,6 +111,7 @@ typedef enum GPUBuiltinShader {
|
||||
GPU_SHADER_2D_UNIFORM_COLOR,
|
||||
GPU_SHADER_2D_FLAT_COLOR,
|
||||
GPU_SHADER_2D_SMOOTH_COLOR,
|
||||
GPU_SHADER_2D_SMOOTH_COLOR_UNIFORM_ALPHA,
|
||||
GPU_SHADER_2D_IMAGE,
|
||||
GPU_SHADER_2D_IMAGE_COLOR,
|
||||
GPU_SHADER_2D_IMAGE_ALPHA_COLOR,
|
||||
|
||||
@@ -63,6 +63,7 @@ extern char datatoc_gpu_shader_flat_color_alpha_test_0_frag_glsl[];
|
||||
extern char datatoc_gpu_shader_flat_id_frag_glsl[];
|
||||
extern char datatoc_gpu_shader_2D_vert_glsl[];
|
||||
extern char datatoc_gpu_shader_2D_flat_color_vert_glsl[];
|
||||
extern char datatoc_gpu_shader_2D_smooth_color_uniform_alpha_vert_glsl[];
|
||||
extern char datatoc_gpu_shader_2D_smooth_color_vert_glsl[];
|
||||
extern char datatoc_gpu_shader_2D_smooth_color_frag_glsl[];
|
||||
extern char datatoc_gpu_shader_2D_image_vert_glsl[];
|
||||
@@ -699,6 +700,8 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
|
||||
datatoc_gpu_shader_flat_color_frag_glsl },
|
||||
[GPU_SHADER_2D_SMOOTH_COLOR] = { datatoc_gpu_shader_2D_smooth_color_vert_glsl,
|
||||
datatoc_gpu_shader_2D_smooth_color_frag_glsl },
|
||||
[GPU_SHADER_2D_SMOOTH_COLOR_UNIFORM_ALPHA] = { datatoc_gpu_shader_2D_smooth_color_uniform_alpha_vert_glsl,
|
||||
datatoc_gpu_shader_2D_smooth_color_frag_glsl },
|
||||
[GPU_SHADER_2D_IMAGE_LINEAR_TO_SRGB] = { datatoc_gpu_shader_2D_image_vert_glsl,
|
||||
datatoc_gpu_shader_image_linear_frag_glsl },
|
||||
[GPU_SHADER_2D_IMAGE] = { datatoc_gpu_shader_2D_image_vert_glsl,
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
|
||||
uniform mat4 ModelViewProjectionMatrix;
|
||||
uniform float alpha;
|
||||
|
||||
in vec2 pos;
|
||||
in vec4 color;
|
||||
|
||||
noperspective out vec4 finalColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
|
||||
finalColor = vec4(color[0], color[1], color[2], color[3] * alpha);
|
||||
}
|
||||
Reference in New Issue
Block a user