61 .defines.frag_list_select = flags |
61 .defines.frag_list_select = flags |
62 }, &codes)) { |
62 }, &codes)) { |
63 asc_error("Loading rectangle shader failed."); |
63 asc_error("Loading rectangle shader failed."); |
64 return NULL; |
64 return NULL; |
65 } |
65 } |
66 // TODO: find better way to deal with inheritance (&shader->program just looks bad) |
66 AscShaderProgram *shader = asc_shader_create(codes, sizeof(AscRectangleShader)); |
67 AscRectangleShader *shader = asc_shader_create(codes, sizeof(*shader)); |
67 if (asc_shader_invalid(shader)) { |
68 if (asc_shader_invalid(&shader->program)) { |
|
69 asc_shader_free_codes(codes); |
68 asc_shader_free_codes(codes); |
70 return (AscShaderProgram*) shader; |
69 return shader; |
71 } |
70 } |
72 shader->size = asc_shader_get_uniform_loc(&shader->program, "size"); |
71 asc_ptr_cast(AscRectangleShader, rect_shader, shader); |
|
72 rect_shader->size = asc_shader_get_uniform_loc(shader, "size"); |
73 if (asc_test_flag(flags, ASC_RECTANGLE_SHADER_FLAG_FILL)) { |
73 if (asc_test_flag(flags, ASC_RECTANGLE_SHADER_FLAG_FILL)) { |
74 shader->color = asc_shader_get_uniform_loc(&shader->program, "color"); |
74 rect_shader->color = asc_shader_get_uniform_loc(shader, "color"); |
75 } else { |
75 } else { |
76 shader->color = -1; |
76 rect_shader->color = -1; |
77 } |
77 } |
78 if (asc_test_flag(flags, ASC_RECTANGLE_SHADER_FLAG_BORDER)) { |
78 if (asc_test_flag(flags, ASC_RECTANGLE_SHADER_FLAG_BORDER)) { |
79 shader->thickness = asc_shader_get_uniform_loc(&shader->program, "thickness"); |
79 rect_shader->thickness = asc_shader_get_uniform_loc(shader, "thickness"); |
80 shader->border_color = asc_shader_get_uniform_loc(&shader->program, "border_color"); |
80 rect_shader->border_color = asc_shader_get_uniform_loc(shader, "border_color"); |
81 } else { |
81 } else { |
82 shader->thickness = -1; |
82 rect_shader->thickness = -1; |
83 shader->border_color = -1; |
83 rect_shader->border_color = -1; |
84 } |
84 } |
85 if (asc_test_flag(flags, ASC_RECTANGLE_SHADER_FLAG_ROUND)) { |
85 if (asc_test_flag(flags, ASC_RECTANGLE_SHADER_FLAG_ROUND)) { |
86 shader->radius = asc_shader_get_uniform_loc(&shader->program, "radius"); |
86 rect_shader->radius = asc_shader_get_uniform_loc(shader, "radius"); |
87 } else { |
87 } else { |
88 shader->radius = -1; |
88 rect_shader->radius = -1; |
89 } |
89 } |
90 asc_shader_free_codes(codes); |
90 asc_shader_free_codes(codes); |
91 |
91 |
92 asc_error_catch_all_gl(); |
92 asc_error_catch_all_gl(); |
93 |
93 |
94 return (AscShaderProgram*) shader; |
94 return shader; |
95 } |
95 } |
96 |
96 |
97 static void asc_rectangle_destroy(AscSceneNode *node) { |
97 static void asc_rectangle_destroy(AscSceneNode *node) { |
98 asc_ptr_cast(AscRectangle, rectangle, node); |
98 asc_ptr_cast(AscRectangle, rectangle, node); |
99 asc_mesh_destroy(&rectangle->mesh); |
99 asc_mesh_destroy(&rectangle->mesh); |
103 asc_ptr_cast(AscRectangle, rectangle, node); |
103 asc_ptr_cast(AscRectangle, rectangle, node); |
104 asc_mesh_plane_2d(&rectangle->mesh, .size = rectangle->size, .uv_scale = rectangle->size); |
104 asc_mesh_plane_2d(&rectangle->mesh, .size = rectangle->size, .uv_scale = rectangle->size); |
105 } |
105 } |
106 |
106 |
107 static void asc_rectangle_draw(const AscCamera *camera, const AscSceneNode *node) { |
107 static void asc_rectangle_draw(const AscCamera *camera, const AscSceneNode *node) { |
108 asc_ptr_cast(AscRectangle, rectangle, node); |
108 asc_cptr_cast(AscRectangle, rectangle, node); |
109 const bool filled = rectangle->filled; |
109 const bool filled = rectangle->filled; |
110 const bool round = rectangle->radius > 0; |
110 const bool round = rectangle->radius > 0; |
111 const bool border = rectangle->thickness > 0; |
111 const bool border = rectangle->thickness > 0; |
112 |
112 |
113 // Compute shader flags |
113 // Compute shader flags |
127 ASC_SHADER_RECTANGLE_DRAW_ROUND, |
127 ASC_SHADER_RECTANGLE_DRAW_ROUND, |
128 ASC_SHADER_RECTANGLE_FILL_BORDER_ROUND, |
128 ASC_SHADER_RECTANGLE_FILL_BORDER_ROUND, |
129 }; |
129 }; |
130 |
130 |
131 // Look up and activate shader |
131 // Look up and activate shader |
132 const AscRectangleShader *shader = asc_shader_lookup_or_create( |
132 const AscShaderProgram *shader = asc_shader_lookup_or_create( |
133 shader_ids[shader_flags], asc_rectangle_shader_create, shader_flags); |
133 shader_ids[shader_flags], asc_rectangle_shader_create, shader_flags); |
134 // TODO: how to remove the following cast? |
134 if (asc_shader_use(shader, camera)) return; |
135 if (asc_shader_invalid((AscShaderProgram*)shader)) return; |
135 asc_cptr_cast(AscRectangleShader, rect_shader, shader); |
136 asc_shader_use(&shader->program, camera); |
|
137 |
136 |
138 // Upload uniforms |
137 // Upload uniforms |
139 asc_shader_upload_model_matrix(&shader->program, node); |
138 asc_shader_upload_model_matrix(shader, node); |
140 |
139 |
141 if (filled) { |
140 if (filled) { |
142 asc_shader_upload_col4f(shader->color, rectangle->color); |
141 asc_shader_upload_col4f(rect_shader->color, rectangle->color); |
143 } |
142 } |
144 asc_shader_upload_vec2f(shader->size, rectangle->size); |
143 asc_shader_upload_vec2f(rect_shader->size, rectangle->size); |
145 |
144 |
146 if (border) { |
145 if (border) { |
147 asc_shader_upload_float(shader->thickness, rectangle->thickness); |
146 asc_shader_upload_float(rect_shader->thickness, rectangle->thickness); |
148 asc_shader_upload_col4f(shader->border_color, rectangle->border_color); |
147 asc_shader_upload_col4f(rect_shader->border_color, rectangle->border_color); |
149 } |
148 } |
150 if (round) { |
149 if (round) { |
151 asc_shader_upload_float(shader->radius, rectangle->radius); |
150 asc_shader_upload_float(rect_shader->radius, rectangle->radius); |
152 } |
151 } |
153 |
152 |
154 // Draw mesh |
153 // Draw mesh |
155 asc_mesh_draw_triangle_strip(&rectangle->mesh); |
154 asc_mesh_draw_triangle_strip(&rectangle->mesh); |
156 } |
155 } |