29 |
29 |
30 #include "ascension/context.h" |
30 #include "ascension/context.h" |
31 #include "ascension/glcontext.h" |
31 #include "ascension/glcontext.h" |
32 #include "ascension/error.h" |
32 #include "ascension/error.h" |
33 #include "ascension/mesh.h" |
33 #include "ascension/mesh.h" |
|
34 #include "ascension/shader.h" |
34 #include "ascension/constants.h" |
35 #include "ascension/constants.h" |
35 |
36 |
36 #include <GL/glew.h> |
37 #include <GL/glew.h> |
37 |
38 |
38 |
39 |
39 struct asc_sprite_shader_s { |
40 struct asc_sprite_shader_s { |
40 AscShaderProgram program; |
41 AscShaderProgram program; |
41 int tex; |
42 int tex; |
42 }; |
43 }; |
|
44 |
|
45 typedef struct asc_sprite_shader_s AscSpriteShader; |
43 |
46 |
44 static void *asc_sprite_shader_create(bool rect) { |
47 static void *asc_sprite_shader_create(bool rect) { |
45 AscShaderCodes codes; |
48 AscShaderCodes codes; |
46 if (asc_shader_load_code_files((AscShaderCodeInfo){ |
49 if (asc_shader_load_code_files((AscShaderCodeInfo){ |
47 .files.vtx = "sprite_vtx.glsl", |
50 .files.vtx = "sprite_vtx.glsl", |
49 .defines.frag = rect ? "#define USE_RECT" : NULL, |
52 .defines.frag = rect ? "#define USE_RECT" : NULL, |
50 }, &codes)) { |
53 }, &codes)) { |
51 asc_error("Loading sprite shader failed."); |
54 asc_error("Loading sprite shader failed."); |
52 return NULL; |
55 return NULL; |
53 } |
56 } |
54 struct asc_sprite_shader_s *shader = asc_shader_create(codes, sizeof(*shader)); |
57 AscSpriteShader *shader = asc_shader_create(codes, sizeof(*shader)); |
55 if (asc_has_error()) { |
58 if (asc_has_error()) { |
56 asc_shader_free_codes(codes); |
59 asc_shader_free_codes(codes); |
57 return NULL; |
60 return NULL; |
58 } |
61 } |
59 shader->tex = glGetUniformLocation(shader->program.gl_id, "tex"); |
62 shader->tex = glGetUniformLocation(shader->program.gl_id, "tex"); |
68 return asc_sprite_shader_create(true); |
71 return asc_sprite_shader_create(true); |
69 } |
72 } |
70 |
73 |
71 static AscShaderProgram *asc_sprite_shader_uv_create() { |
74 static AscShaderProgram *asc_sprite_shader_uv_create() { |
72 return asc_sprite_shader_create(false); |
75 return asc_sprite_shader_create(false); |
|
76 } |
|
77 |
|
78 static const AscSpriteShader *asc_sprite_shader_rect(void) { |
|
79 return asc_shader_lookup_or_create(ASC_SHADER_SPRITE_RECT, asc_sprite_shader_rect_create); |
|
80 } |
|
81 |
|
82 static const AscSpriteShader *asc_sprite_shader_uv(void) { |
|
83 return asc_shader_lookup_or_create(ASC_SHADER_SPRITE_UV, asc_sprite_shader_uv_create); |
73 } |
84 } |
74 |
85 |
75 static void asc_sprite_destroy(AscSceneNode *node) { |
86 static void asc_sprite_destroy(AscSceneNode *node) { |
76 AscSprite *sprite = (AscSprite *) node; |
87 AscSprite *sprite = (AscSprite *) node; |
77 asc_mesh_destroy(&sprite->mesh); |
88 asc_mesh_destroy(&sprite->mesh); |
111 |
122 |
112 // basic node parameters |
123 // basic node parameters |
113 AscSceneNode *node = (AscSceneNode *) sprite; |
124 AscSceneNode *node = (AscSceneNode *) sprite; |
114 asc_scene_node_name(node, args.name); |
125 asc_scene_node_name(node, args.name); |
115 node->render_group = args.opaque |
126 node->render_group = args.opaque |
116 ? ASC_RENDER_GROUP_SPRITE_OPAQUE_UV |
127 ? ASC_RENDER_GROUP_SPRITE_OPAQUE |
117 : ASC_RENDER_GROUP_SPRITE_BLEND_UV; |
128 : ASC_RENDER_GROUP_SPRITE_BLEND; |
118 node->update_func = asc_sprite_update; |
129 node->update_func = asc_sprite_update; |
119 node->destroy_func = asc_sprite_destroy; |
130 node->destroy_func = asc_sprite_destroy; |
120 |
131 |
121 node->position = asc_vec3f_new(args.x, args.y, ASC_SCENE_2D_DEPTH_OFFSET); |
132 node->position = asc_vec3f_new(args.x, args.y, ASC_SCENE_2D_DEPTH_OFFSET); |
122 node->scale = asc_vec3f_one; |
133 node->scale = asc_vec3f_one; |
123 |
134 |
124 asc_node_update(node); |
135 asc_node_update(node); |
125 return node; |
136 return node; |
126 } |
137 } |
127 |
138 |
128 const AscShaderProgram *asc_sprite_shader_rect(void) { |
139 void asc_sprite_draw(const AscCamera *camera, const AscSprite *node) { |
129 return asc_shader_lookup_or_create(ASC_SHADER_SPRITE_RECT, asc_sprite_shader_rect_create); |
140 // Activate shader |
130 } |
141 const AscSpriteShader *shader = |
131 |
142 node->texture->target == GL_TEXTURE_RECTANGLE |
132 const AscShaderProgram *asc_sprite_shader_uv(void) { |
143 ? asc_sprite_shader_rect() |
133 return asc_shader_lookup_or_create(ASC_SHADER_SPRITE_UV, asc_sprite_shader_uv_create); |
144 : asc_sprite_shader_uv(); |
134 } |
145 asc_shader_use(&shader->program, camera); |
135 |
|
136 void asc_sprite_draw(const AscShaderProgram *program, const AscSprite *node) { |
|
137 asc_ptr_cast(const struct asc_sprite_shader_s, shader, program); |
|
138 |
146 |
139 // Upload model matrix |
147 // Upload model matrix |
140 glUniformMatrix4fv(shader->program.model, 1, |
148 glUniformMatrix4fv(shader->program.model, 1, |
141 GL_FALSE, node->data.world_transform); |
149 GL_FALSE, node->data.world_transform); |
142 |
150 |