31 #include "ascension/shader.h" |
31 #include "ascension/shader.h" |
32 |
32 |
33 #include <GL/glew.h> |
33 #include <GL/glew.h> |
34 |
34 |
35 static void asc_text_draw(AscText const *node) { |
35 static void asc_text_draw(AscText const *node) { |
36 if (node->color.alpha == 0 || node->hidden || node->internal.tex_id == 0) { |
36 if (node->color.alpha == 0 || node->hidden || node->tex_id == 0) { |
37 return; |
37 return; |
38 } |
38 } |
39 |
39 |
40 // TODO: when we group draw calls, we don't need to activate shader here |
40 // Upload model matrix |
41 glUseProgram(ASC_SHADER_FONT.base.id); |
|
42 |
|
43 // TODO: when we group UI draw calls, we don't need to upload matrices here |
|
44 // Upload matrices |
|
45 glUniformMatrix4fv(ASC_SHADER_FONT.base.projection, 1, |
|
46 GL_FALSE, asc_context.active_window->projection); |
|
47 glUniformMatrix4fv(ASC_SHADER_FONT.base.model, 1, |
41 glUniformMatrix4fv(ASC_SHADER_FONT.base.model, 1, |
48 GL_FALSE, node->base.transform); |
42 GL_FALSE, node->base.transform); |
49 |
43 |
50 // Upload surface |
44 // Upload surface |
51 glActiveTexture(GL_TEXTURE0); |
45 glActiveTexture(GL_TEXTURE0); |
52 glBindTexture(GL_TEXTURE_RECTANGLE, node->internal.tex_id); |
46 glBindTexture(GL_TEXTURE_RECTANGLE, node->tex_id); |
53 glUniform1i(ASC_SHADER_FONT.surface, 0); |
47 glUniform1i(ASC_SHADER_FONT.surface, 0); |
54 |
48 |
55 // Draw mesh |
49 // Draw mesh |
56 asc_primitives_draw_plane(); |
50 asc_primitives_draw_plane(); |
|
51 } |
|
52 |
|
53 static void asc_text_update_transform(AscText *node) { |
|
54 asc_transform_scale(node->base.transform, (float) node->dimension.width, (float) node->dimension.height, 0); |
|
55 asc_transform_translate2i(node->base.transform, node->position); |
57 } |
56 } |
58 |
57 |
59 static void asc_text_update(AscText *node) { |
58 static void asc_text_update(AscText *node) { |
60 // short circuit if fully transparent or hidden, we don't need anything |
59 // short circuit if fully transparent or hidden, we don't need anything |
61 if (node->color.alpha == 0 || node->hidden) { |
60 if (node->color.alpha == 0 || node->hidden) { |
62 return; |
61 return; |
63 } |
62 } |
64 |
63 |
65 // Generate new texture, if required |
64 // Generate new texture, if required |
66 if (node->internal.tex_id == 0) { |
65 if (node->tex_id == 0) { |
67 glGenTextures(1, &node->internal.tex_id); |
66 glGenTextures(1, &node->tex_id); |
68 glBindTexture(GL_TEXTURE_RECTANGLE, node->internal.tex_id); |
67 glBindTexture(GL_TEXTURE_RECTANGLE, node->tex_id); |
69 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
68 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
70 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
69 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
71 asc_dprintf("Generated new texture for text node: %u", node->internal.tex_id); |
70 asc_dprintf("Generated new texture for text node: %u", node->tex_id); |
72 } |
71 } |
73 |
72 |
74 // Render text onto a surface |
73 // Render text onto a surface |
75 SDL_Surface *surface = TTF_RenderUTF8_Blended_Wrapped( |
74 SDL_Surface *surface = TTF_RenderUTF8_Blended_Wrapped( |
76 asc_font_cache_validate(node->font)->ptr, |
75 asc_font_cache_validate(node->font)->ptr, |
80 ); |
79 ); |
81 if (surface == NULL) { |
80 if (surface == NULL) { |
82 asc_error(SDL_GetError()); |
81 asc_error(SDL_GetError()); |
83 return; |
82 return; |
84 } |
83 } |
85 |
84 node->dimension.width = surface->w; |
86 // Transform |
85 node->dimension.height = surface->h; |
87 asc_transform_scale(node->base.transform, (float) surface->w, (float) surface->h, 0); |
86 asc_node_update_transform(node); |
88 asc_transform_translate2i(node->base.transform, node->position); |
|
89 |
87 |
90 // Transfer Image Data |
88 // Transfer Image Data |
91 // TODO: move the image data transfer to a separate function - we will need it more often |
89 // TODO: move the image data transfer to a separate function - we will need it more often |
92 glBindTexture(GL_TEXTURE_RECTANGLE, node->internal.tex_id); |
90 glBindTexture(GL_TEXTURE_RECTANGLE, node->tex_id); |
93 glPixelStorei(GL_UNPACK_ROW_LENGTH, surface->pitch / surface->format->BytesPerPixel); |
91 glPixelStorei(GL_UNPACK_ROW_LENGTH, surface->pitch / surface->format->BytesPerPixel); |
94 glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA, |
92 glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA, |
95 surface->w, surface->h, |
93 surface->w, surface->h, |
96 0, GL_BGRA, GL_UNSIGNED_BYTE, surface->pixels); |
94 0, GL_BGRA, GL_UNSIGNED_BYTE, surface->pixels); |
97 |
95 |
104 if (node == NULL) { |
102 if (node == NULL) { |
105 asc_error("Out of memory."); |
103 asc_error("Out of memory."); |
106 return NULL; |
104 return NULL; |
107 } |
105 } |
108 |
106 |
|
107 node->base.render_group = ASC_RENDER_GROUP_FONTS; |
109 node->base.free_func = (asc_scene_free_func) asc_text_free; |
108 node->base.free_func = (asc_scene_free_func) asc_text_free; |
110 node->base.update_func = (asc_scene_update_func) asc_text_update; |
109 node->base.update_func = (asc_scene_update_func) asc_text_update; |
|
110 node->base.transform_update_func = (asc_scene_update_func) asc_text_update_transform; |
111 node->base.draw_func = (asc_scene_draw_func) asc_text_draw; |
111 node->base.draw_func = (asc_scene_draw_func) asc_text_draw; |
112 |
112 |
113 node->position.x = x; |
113 node->position.x = x; |
114 node->position.y = y; |
114 node->position.y = y; |
115 node->font = asc_context.active_font; |
115 node->font = asc_context.active_font; |
116 node->color = asc_context.ink; |
116 node->color = asc_context.ink; |
117 if (text != NULL) { |
117 if (text != NULL) { |
118 node->text = strdup(text); |
118 node->text = strdup(text); |
119 } |
119 } |
120 |
120 |
|
121 // initialize |
|
122 asc_text_update(node); |
|
123 asc_text_update_transform(node); |
|
124 |
121 return &node->base; |
125 return &node->base; |
122 } |
126 } |
123 |
127 |
124 void asc_text_free(AscText *node) { |
128 void asc_text_free(AscText *node) { |
125 asc_dprintf("Release text node texture: %u", node->internal.tex_id); |
129 asc_dprintf("Release text node texture: %u", node->tex_id); |
126 glDeleteTextures(1, &node->internal.tex_id); |
130 glDeleteTextures(1, &node->tex_id); |
127 free(node->text); |
131 free(node->text); |
128 free(node); |
132 free(node); |
129 } |
133 } |