add initial GLES2 3D renderer

This commit is contained in:
karroffel 2018-02-24 14:48:22 +01:00
parent bfb21be871
commit b64171e79c
18 changed files with 6372 additions and 2330 deletions

View file

@ -54,10 +54,26 @@ void RasterizerCanvasGLES2::_set_uniforms() {
state.canvas_shader.set_uniform(CanvasShaderGLES2::EXTRA_MATRIX, state.uniforms.extra_matrix);
state.canvas_shader.set_uniform(CanvasShaderGLES2::FINAL_MODULATE, state.uniforms.final_modulate);
state.canvas_shader.set_uniform(CanvasShaderGLES2::TIME, storage->frame.time[0]);
if (storage->frame.current_rt) {
Vector2 screen_pixel_size;
screen_pixel_size.x = 1.0 / storage->frame.current_rt->width;
screen_pixel_size.y = 1.0 / storage->frame.current_rt->height;
state.canvas_shader.set_uniform(CanvasShaderGLES2::SCREEN_PIXEL_SIZE, screen_pixel_size);
}
}
void RasterizerCanvasGLES2::canvas_begin() {
state.canvas_shader.bind();
if (storage->frame.current_rt) {
glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo);
glColorMask(1, 1, 1, 1);
}
if (storage->frame.clear_request) {
glClearColor(storage->frame.clear_request_color.r,
storage->frame.clear_request_color.g,
@ -67,10 +83,12 @@ void RasterizerCanvasGLES2::canvas_begin() {
storage->frame.clear_request = false;
}
/*
if (storage->frame.current_rt) {
glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo);
glColorMask(1, 1, 1, 1);
}
*/
reset_canvas();
@ -312,7 +330,7 @@ void RasterizerCanvasGLES2::_draw_gui_primitive(int p_points, const Vector2 *p_v
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *current_clip, bool &reclip) {
void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *current_clip, bool &reclip, RasterizerStorageGLES2::Material *p_material) {
int command_count = p_item->commands.size();
Item::Command **commands = p_item->commands.ptrw();
@ -329,9 +347,10 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, false);
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_UV_ATTRIBUTE, false);
state.canvas_shader.bind();
_set_uniforms();
if (state.canvas_shader.bind()) {
_set_uniforms();
state.canvas_shader.use_material((void *)p_material, 2);
}
_bind_canvas_texture(RID(), RID());
@ -359,7 +378,6 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
_draw_gui_primitive(4, verts, NULL, NULL);
}
} break;
case Item::Command::TYPE_RECT: {
@ -373,8 +391,10 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, true);
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_UV_ATTRIBUTE, false);
if (state.canvas_shader.bind())
if (state.canvas_shader.bind()) {
_set_uniforms();
state.canvas_shader.use_material((void *)p_material, 2);
}
RasterizerStorageGLES2::Texture *tex = _bind_canvas_texture(r->texture, r->normal_map);
@ -454,8 +474,10 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, false);
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_UV_ATTRIBUTE, true);
if (state.canvas_shader.bind())
if (state.canvas_shader.bind()) {
_set_uniforms();
state.canvas_shader.use_material((void *)p_material, 2);
}
glDisableVertexAttribArray(VS::ARRAY_COLOR);
glVertexAttrib4fv(VS::ARRAY_COLOR, np->color.components);
@ -472,8 +494,16 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
// state.canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX, state.uniforms.modelview_matrix);
state.canvas_shader.set_uniform(CanvasShaderGLES2::COLOR_TEXPIXEL_SIZE, texpixel_size);
Rect2 source = np->source;
if (source.size.x == 0 && source.size.y == 0) {
source.size.x = tex->width;
source.size.y = tex->height;
}
// prepare vertex buffer
// this buffer contains [ POS POS UV UV ] *
float buffer[16 * 2 + 16 * 2];
{
@ -483,106 +513,106 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
buffer[(0 * 4 * 4) + 0] = np->rect.position.x;
buffer[(0 * 4 * 4) + 1] = np->rect.position.y;
buffer[(0 * 4 * 4) + 2] = np->source.position.x * texpixel_size.x;
buffer[(0 * 4 * 4) + 3] = np->source.position.y * texpixel_size.y;
buffer[(0 * 4 * 4) + 2] = source.position.x * texpixel_size.x;
buffer[(0 * 4 * 4) + 3] = source.position.y * texpixel_size.y;
buffer[(0 * 4 * 4) + 4] = np->rect.position.x + np->margin[MARGIN_LEFT];
buffer[(0 * 4 * 4) + 5] = np->rect.position.y;
buffer[(0 * 4 * 4) + 6] = (np->source.position.x + np->margin[MARGIN_LEFT]) * texpixel_size.x;
buffer[(0 * 4 * 4) + 7] = np->source.position.y * texpixel_size.y;
buffer[(0 * 4 * 4) + 6] = (source.position.x + np->margin[MARGIN_LEFT]) * texpixel_size.x;
buffer[(0 * 4 * 4) + 7] = source.position.y * texpixel_size.y;
buffer[(0 * 4 * 4) + 8] = np->rect.position.x + np->rect.size.x - np->margin[MARGIN_RIGHT];
buffer[(0 * 4 * 4) + 9] = np->rect.position.y;
buffer[(0 * 4 * 4) + 10] = (np->source.position.x + np->source.size.x - np->margin[MARGIN_RIGHT]) * texpixel_size.x;
buffer[(0 * 4 * 4) + 11] = np->source.position.y * texpixel_size.y;
buffer[(0 * 4 * 4) + 10] = (source.position.x + source.size.x - np->margin[MARGIN_RIGHT]) * texpixel_size.x;
buffer[(0 * 4 * 4) + 11] = source.position.y * texpixel_size.y;
buffer[(0 * 4 * 4) + 12] = np->rect.position.x + np->rect.size.x;
buffer[(0 * 4 * 4) + 13] = np->rect.position.y;
buffer[(0 * 4 * 4) + 14] = (np->source.position.x + np->source.size.x) * texpixel_size.x;
buffer[(0 * 4 * 4) + 15] = np->source.position.y * texpixel_size.y;
buffer[(0 * 4 * 4) + 14] = (source.position.x + source.size.x) * texpixel_size.x;
buffer[(0 * 4 * 4) + 15] = source.position.y * texpixel_size.y;
// second row
buffer[(1 * 4 * 4) + 0] = np->rect.position.x;
buffer[(1 * 4 * 4) + 1] = np->rect.position.y + np->margin[MARGIN_TOP];
buffer[(1 * 4 * 4) + 2] = np->source.position.x * texpixel_size.x;
buffer[(1 * 4 * 4) + 3] = (np->source.position.y + np->margin[MARGIN_TOP]) * texpixel_size.y;
buffer[(1 * 4 * 4) + 2] = source.position.x * texpixel_size.x;
buffer[(1 * 4 * 4) + 3] = (source.position.y + np->margin[MARGIN_TOP]) * texpixel_size.y;
buffer[(1 * 4 * 4) + 4] = np->rect.position.x + np->margin[MARGIN_LEFT];
buffer[(1 * 4 * 4) + 5] = np->rect.position.y + np->margin[MARGIN_TOP];
buffer[(1 * 4 * 4) + 6] = (np->source.position.x + np->margin[MARGIN_LEFT]) * texpixel_size.x;
buffer[(1 * 4 * 4) + 7] = (np->source.position.y + np->margin[MARGIN_TOP]) * texpixel_size.y;
buffer[(1 * 4 * 4) + 6] = (source.position.x + np->margin[MARGIN_LEFT]) * texpixel_size.x;
buffer[(1 * 4 * 4) + 7] = (source.position.y + np->margin[MARGIN_TOP]) * texpixel_size.y;
buffer[(1 * 4 * 4) + 8] = np->rect.position.x + np->rect.size.x - np->margin[MARGIN_RIGHT];
buffer[(1 * 4 * 4) + 9] = np->rect.position.y + np->margin[MARGIN_TOP];
buffer[(1 * 4 * 4) + 10] = (np->source.position.x + np->source.size.x - np->margin[MARGIN_RIGHT]) * texpixel_size.x;
buffer[(1 * 4 * 4) + 11] = (np->source.position.y + np->margin[MARGIN_TOP]) * texpixel_size.y;
buffer[(1 * 4 * 4) + 10] = (source.position.x + source.size.x - np->margin[MARGIN_RIGHT]) * texpixel_size.x;
buffer[(1 * 4 * 4) + 11] = (source.position.y + np->margin[MARGIN_TOP]) * texpixel_size.y;
buffer[(1 * 4 * 4) + 12] = np->rect.position.x + np->rect.size.x;
buffer[(1 * 4 * 4) + 13] = np->rect.position.y + np->margin[MARGIN_TOP];
buffer[(1 * 4 * 4) + 14] = (np->source.position.x + np->source.size.x) * texpixel_size.x;
buffer[(1 * 4 * 4) + 15] = (np->source.position.y + np->margin[MARGIN_TOP]) * texpixel_size.y;
buffer[(1 * 4 * 4) + 14] = (source.position.x + source.size.x) * texpixel_size.x;
buffer[(1 * 4 * 4) + 15] = (source.position.y + np->margin[MARGIN_TOP]) * texpixel_size.y;
// thrid row
buffer[(2 * 4 * 4) + 0] = np->rect.position.x;
buffer[(2 * 4 * 4) + 1] = np->rect.position.y + np->rect.size.y - np->margin[MARGIN_BOTTOM];
buffer[(2 * 4 * 4) + 2] = np->source.position.x * texpixel_size.x;
buffer[(2 * 4 * 4) + 3] = (np->source.position.y + np->source.size.y - np->margin[MARGIN_BOTTOM]) * texpixel_size.y;
buffer[(2 * 4 * 4) + 2] = source.position.x * texpixel_size.x;
buffer[(2 * 4 * 4) + 3] = (source.position.y + source.size.y - np->margin[MARGIN_BOTTOM]) * texpixel_size.y;
buffer[(2 * 4 * 4) + 4] = np->rect.position.x + np->margin[MARGIN_LEFT];
buffer[(2 * 4 * 4) + 5] = np->rect.position.y + np->rect.size.y - np->margin[MARGIN_BOTTOM];
buffer[(2 * 4 * 4) + 6] = (np->source.position.x + np->margin[MARGIN_LEFT]) * texpixel_size.x;
buffer[(2 * 4 * 4) + 7] = (np->source.position.y + np->source.size.y - np->margin[MARGIN_BOTTOM]) * texpixel_size.y;
buffer[(2 * 4 * 4) + 6] = (source.position.x + np->margin[MARGIN_LEFT]) * texpixel_size.x;
buffer[(2 * 4 * 4) + 7] = (source.position.y + source.size.y - np->margin[MARGIN_BOTTOM]) * texpixel_size.y;
buffer[(2 * 4 * 4) + 8] = np->rect.position.x + np->rect.size.x - np->margin[MARGIN_RIGHT];
buffer[(2 * 4 * 4) + 9] = np->rect.position.y + np->rect.size.y - np->margin[MARGIN_BOTTOM];
buffer[(2 * 4 * 4) + 10] = (np->source.position.x + np->source.size.x - np->margin[MARGIN_RIGHT]) * texpixel_size.x;
buffer[(2 * 4 * 4) + 11] = (np->source.position.y + np->source.size.y - np->margin[MARGIN_BOTTOM]) * texpixel_size.y;
buffer[(2 * 4 * 4) + 10] = (source.position.x + source.size.x - np->margin[MARGIN_RIGHT]) * texpixel_size.x;
buffer[(2 * 4 * 4) + 11] = (source.position.y + source.size.y - np->margin[MARGIN_BOTTOM]) * texpixel_size.y;
buffer[(2 * 4 * 4) + 12] = np->rect.position.x + np->rect.size.x;
buffer[(2 * 4 * 4) + 13] = np->rect.position.y + np->rect.size.y - np->margin[MARGIN_BOTTOM];
buffer[(2 * 4 * 4) + 14] = (np->source.position.x + np->source.size.x) * texpixel_size.x;
buffer[(2 * 4 * 4) + 15] = (np->source.position.y + np->source.size.y - np->margin[MARGIN_BOTTOM]) * texpixel_size.y;
buffer[(2 * 4 * 4) + 14] = (source.position.x + source.size.x) * texpixel_size.x;
buffer[(2 * 4 * 4) + 15] = (source.position.y + source.size.y - np->margin[MARGIN_BOTTOM]) * texpixel_size.y;
// fourth row
buffer[(3 * 4 * 4) + 0] = np->rect.position.x;
buffer[(3 * 4 * 4) + 1] = np->rect.position.y + np->rect.size.y;
buffer[(3 * 4 * 4) + 2] = np->source.position.x * texpixel_size.x;
buffer[(3 * 4 * 4) + 3] = (np->source.position.y + np->source.size.y) * texpixel_size.y;
buffer[(3 * 4 * 4) + 2] = source.position.x * texpixel_size.x;
buffer[(3 * 4 * 4) + 3] = (source.position.y + source.size.y) * texpixel_size.y;
buffer[(3 * 4 * 4) + 4] = np->rect.position.x + np->margin[MARGIN_LEFT];
buffer[(3 * 4 * 4) + 5] = np->rect.position.y + np->rect.size.y;
buffer[(3 * 4 * 4) + 6] = (np->source.position.x + np->margin[MARGIN_LEFT]) * texpixel_size.x;
buffer[(3 * 4 * 4) + 7] = (np->source.position.y + np->source.size.y) * texpixel_size.y;
buffer[(3 * 4 * 4) + 6] = (source.position.x + np->margin[MARGIN_LEFT]) * texpixel_size.x;
buffer[(3 * 4 * 4) + 7] = (source.position.y + source.size.y) * texpixel_size.y;
buffer[(3 * 4 * 4) + 8] = np->rect.position.x + np->rect.size.x - np->margin[MARGIN_RIGHT];
buffer[(3 * 4 * 4) + 9] = np->rect.position.y + np->rect.size.y;
buffer[(3 * 4 * 4) + 10] = (np->source.position.x + np->source.size.x - np->margin[MARGIN_RIGHT]) * texpixel_size.x;
buffer[(3 * 4 * 4) + 11] = (np->source.position.y + np->source.size.y) * texpixel_size.y;
buffer[(3 * 4 * 4) + 10] = (source.position.x + source.size.x - np->margin[MARGIN_RIGHT]) * texpixel_size.x;
buffer[(3 * 4 * 4) + 11] = (source.position.y + source.size.y) * texpixel_size.y;
buffer[(3 * 4 * 4) + 12] = np->rect.position.x + np->rect.size.x;
buffer[(3 * 4 * 4) + 13] = np->rect.position.y + np->rect.size.y;
buffer[(3 * 4 * 4) + 14] = (np->source.position.x + np->source.size.x) * texpixel_size.x;
buffer[(3 * 4 * 4) + 15] = (np->source.position.y + np->source.size.y) * texpixel_size.y;
buffer[(3 * 4 * 4) + 14] = (source.position.x + source.size.x) * texpixel_size.x;
buffer[(3 * 4 * 4) + 15] = (source.position.y + source.size.y) * texpixel_size.y;
// print_line(String::num((np->source.position.y + np->source.size.y) * texpixel_size.y));
// print_line(String::num((source.position.y + source.size.y) * texpixel_size.y));
}
glBindBuffer(GL_ARRAY_BUFFER, data.ninepatch_vertices);
@ -610,8 +640,10 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, false);
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_UV_ATTRIBUTE, false);
if (state.canvas_shader.bind())
if (state.canvas_shader.bind()) {
_set_uniforms();
state.canvas_shader.use_material((void *)p_material, 2);
}
static const int num_points = 32;
@ -639,8 +671,10 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, false);
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_UV_ATTRIBUTE, true);
if (state.canvas_shader.bind())
if (state.canvas_shader.bind()) {
_set_uniforms();
state.canvas_shader.use_material((void *)p_material, 2);
}
RasterizerStorageGLES2::Texture *texture = _bind_canvas_texture(polygon->texture, polygon->normal_map);
@ -658,8 +692,10 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, false);
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_UV_ATTRIBUTE, false);
if (state.canvas_shader.bind())
if (state.canvas_shader.bind()) {
_set_uniforms();
state.canvas_shader.use_material((void *)p_material, 2);
}
_bind_canvas_texture(RID(), RID());
@ -689,8 +725,10 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, false);
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_UV_ATTRIBUTE, true);
if (state.canvas_shader.bind())
if (state.canvas_shader.bind()) {
_set_uniforms();
state.canvas_shader.use_material((void *)p_material, 2);
}
ERR_CONTINUE(primitive->points.size() < 1);
@ -759,42 +797,6 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
void RasterizerCanvasGLES2::_copy_texscreen(const Rect2 &p_rect) {
// This isn't really working yet, so disabling for now.
/*
glDisable(GL_BLEND);
state.canvas_texscreen_used = true;
Vector2 wh(storage->frame.current_rt->width, storage->frame.current_rt->height);
Color copy_section(p_rect.position.x / wh.x, p_rect.position.y / wh.y, p_rect.size.x / wh.x, p_rect.size.y / wh.y);
if (p_rect != Rect2()) {
// only use section
storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_COPY_SECTION, true);
}
storage->shaders.copy.bind();
storage->shaders.copy.set_uniform(CopyShaderGLES2::COPY_SECTION, copy_section);
_bind_quad_buffer();
glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->copy_screen_effect.fbo);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glDisableVertexAttribArray(VS::ARRAY_VERTEX);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo);
state.canvas_shader.bind();
_bind_canvas_texture(state.current_tex, state.current_normal);
glEnable(GL_BLEND);
*/
}
void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light, const Transform2D &p_base_transform) {
@ -850,10 +852,10 @@ void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, cons
Item *material_owner = ci->material_owner ? ci->material_owner : ci;
RID material = material_owner->material;
RasterizerStorageGLES2::Material *material_ptr = storage->material_owner.getornull(material);
if (material != canvas_last_material || rebind_shader) {
RasterizerStorageGLES2::Material *material_ptr = storage->material_owner.getornull(material);
RasterizerStorageGLES2::Shader *shader_ptr = NULL;
if (material_ptr) {
@ -880,7 +882,7 @@ void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, cons
}
int tc = material_ptr->textures.size();
RID *textures = material_ptr->textures.ptrw();
Pair<StringName, RID> *textures = material_ptr->textures.ptrw();
ShaderLanguage::ShaderNode::Uniform::Hint *texture_hints = shader_ptr->texture_hints.ptrw();
@ -888,7 +890,7 @@ void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, cons
glActiveTexture(GL_TEXTURE2 + i);
RasterizerStorageGLES2::Texture *t = storage->texture_owner.getornull(textures[i]);
RasterizerStorageGLES2::Texture *t = storage->texture_owner.getornull(textures[i].second);
if (!t) {
@ -919,10 +921,12 @@ void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, cons
glBindTexture(t->target, t->tex_id);
}
} else {
state.canvas_shader.set_custom_shader(0);
state.canvas_shader.bind();
}
state.canvas_shader.use_material((void *)material_ptr, 2);
shader_cache = shader_ptr;
@ -977,7 +981,7 @@ void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, cons
_set_uniforms();
_canvas_item_render_commands(p_item_list, NULL, reclip);
_canvas_item_render_commands(p_item_list, NULL, reclip, material_ptr);
rebind_shader = true; // hacked in for now.

View file

@ -103,7 +103,7 @@ public:
_FORCE_INLINE_ void _draw_polygon(const int *p_indices, int p_index_count, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor);
_FORCE_INLINE_ void _draw_generic(GLuint p_primitive, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor);
_FORCE_INLINE_ void _canvas_item_render_commands(Item *p_item, Item *current_clip, bool &reclip);
_FORCE_INLINE_ void _canvas_item_render_commands(Item *p_item, Item *current_clip, bool &reclip, RasterizerStorageGLES2::Material *p_material);
_FORCE_INLINE_ void _copy_texscreen(const Rect2 &p_rect);
virtual void canvas_render_items(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light, const Transform2D &p_base_transform);

View file

@ -348,10 +348,10 @@ void RasterizerGLES2::blit_render_target_to_screen(RID p_render_target, const Re
canvas->state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, true);
canvas->state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_UV_ATTRIBUTE, false);
canvas->state.canvas_shader.set_custom_shader(0);
canvas->state.canvas_shader.bind();
canvas->canvas_begin();
canvas->state.canvas_shader.set_uniform(CanvasShaderGLES2::BLIT_PASS, true);
glDisable(GL_BLEND);
glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES2::system_fbo);
glActiveTexture(GL_TEXTURE0);
@ -361,8 +361,6 @@ void RasterizerGLES2::blit_render_target_to_screen(RID p_render_target, const Re
canvas->draw_generic_textured_rect(p_screen_rect, Rect2(0, 0, 1, -1));
canvas->state.canvas_shader.set_uniform(CanvasShaderGLES2::BLIT_PASS, false);
glBindTexture(GL_TEXTURE_2D, 0);
canvas->canvas_end();
}

File diff suppressed because it is too large Load diff

View file

@ -33,10 +33,10 @@
/* Must come before shaders or the Windows build fails... */
#include "rasterizer_storage_gles2.h"
#include "shaders/cube_to_dp.glsl.gen.h"
#include "shaders/scene.glsl.gen.h"
/*
#include "drivers/gles3/shaders/cube_to_dp.glsl.gen.h"
#include "drivers/gles3/shaders/effect_blur.glsl.gen.h"
#include "drivers/gles3/shaders/exposure.glsl.gen.h"
#include "drivers/gles3/shaders/resolve.glsl.gen.h"
@ -52,6 +52,13 @@
class RasterizerSceneGLES2 : public RasterizerScene {
public:
RID default_material;
RID default_material_twosided;
RID default_shader;
RID default_shader_twosided;
uint64_t scene_pass;
RasterizerStorageGLES2 *storage;
struct State {
@ -63,7 +70,10 @@ public:
GLuint current_main_tex;
SceneShaderGLES2 scene_shader;
// CubeToDpShaderGLES3 cube_to_dp_shader;
CubeToDpShaderGLES2 cube_to_dp_shader;
GLuint sky_verts;
// ResolveShaderGLES3 resolve_shader;
// ScreenSpaceReflectionShaderGLES3 ssr_shader;
// EffectBlurShaderGLES3 effect_blur_shader;
@ -128,7 +138,6 @@ public:
GLuint env_radiance_ubo;
GLuint sky_verts;
GLuint sky_array;
GLuint directional_ubo;
@ -169,11 +178,72 @@ public:
/* SHADOW ATLAS API */
uint64_t shadow_atlas_realloc_tolerance_msec;
struct ShadowAtlas : public RID_Data {
enum {
QUADRANT_SHIFT = 27,
SHADOW_INDEX_MASK = (1 << QUADRANT_SHIFT) - 1,
SHADOW_INVALID = 0xFFFFFFFF,
};
struct Quadrant {
uint32_t subdivision;
struct Shadow {
RID owner;
uint64_t version;
uint64_t alloc_tick;
Shadow() {
version = 0;
alloc_tick = 0;
}
};
Vector<Shadow> shadows;
Quadrant() {
subdivision = 0;
}
} quadrants[4];
int size_order[4];
uint32_t smallest_subdiv;
int size;
GLuint fbo;
GLuint depth;
Map<RID, uint32_t> shadow_owners;
};
struct ShadowCubeMap {
GLuint fbo[6];
GLuint cubemap;
uint32_t size;
};
Vector<ShadowCubeMap> shadow_cubemaps;
RID_Owner<ShadowAtlas> shadow_atlas_owner;
RID shadow_atlas_create();
void shadow_atlas_set_size(RID p_atlas, int p_size);
void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision);
bool _shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, int &r_quadrant, int &r_shadow);
bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version);
struct DirectionalShadow {
GLuint fbo;
GLuint depth;
int light_count;
int size;
int current_light;
} directional_shadow;
virtual int get_directional_light_shadow_size(RID p_light_intance);
virtual void set_directional_shadow_count(int p_count);
@ -196,6 +266,36 @@ public:
virtual bool reflection_probe_instance_postprocess_step(RID p_instance);
/* ENVIRONMENT API */
struct Environment : public RID_Data {
VS::EnvironmentBG bg_mode;
RID sky;
float sky_custom_fov;
Color bg_color;
float bg_energy;
float sky_ambient;
Color ambient_color;
float ambient_energy;
float ambient_sky_contribution;
int canvas_max_layer;
Environment() {
bg_mode = VS::ENV_BG_CLEAR_COLOR;
sky_custom_fov = 0.0;
bg_energy = 1.0;
sky_ambient = 0;
ambient_energy = 1.0;
ambient_sky_contribution = 0.0;
canvas_max_layer = 0;
}
};
mutable RID_Owner<Environment> environment_owner;
virtual RID environment_create();
virtual void environment_set_background(RID p_env, VS::EnvironmentBG p_bg);
@ -228,6 +328,43 @@ public:
virtual int environment_get_canvas_max_layer(RID p_env);
/* LIGHT INSTANCE */
struct LightInstance : public RID_Data {
struct ShadowTransform {
CameraMatrix camera;
Transform transform;
float farplane;
float split;
float bias_scale;
};
ShadowTransform shadow_transform[4];
RID self;
RID light;
RasterizerStorageGLES2::Light *light_ptr;
Transform transform;
Vector3 light_vector;
Vector3 spot_vector;
float linear_att;
// TODO passes and all that stuff ?
uint64_t last_scene_pass;
uint64_t last_scene_shadow_pass;
uint16_t light_index;
uint16_t light_directional_index;
Rect2 directional_rect;
Set<RID> shadow_atlases; // atlases where this light is registered
};
mutable RID_Owner<LightInstance> light_instance_owner;
virtual RID light_instance_create(RID p_light);
virtual void light_instance_set_transform(RID p_light_instance, const Transform &p_transform);
virtual void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale = 1.0);
@ -242,6 +379,180 @@ public:
/* RENDER LIST */
struct RenderList {
enum {
DEFAULT_MAX_ELEMENTS = 65536,
SORT_FLAG_SKELETON = 1,
SORT_FLAG_INSTANCING = 2,
MAX_DIRECTIONAL_LIGHTS = 16,
MAX_LIGHTS = 4096,
MAX_REFLECTIONS = 1024,
SORT_KEY_PRIORITY_SHIFT = 56,
SORT_KEY_PRIORITY_MASK = 0xFF,
//depth layer for opaque (56-52)
SORT_KEY_OPAQUE_DEPTH_LAYER_SHIFT = 52,
SORT_KEY_OPAQUE_DEPTH_LAYER_MASK = 0xF,
//64 bits unsupported in MSVC
#define SORT_KEY_UNSHADED_FLAG (uint64_t(1) << 49)
#define SORT_KEY_NO_DIRECTIONAL_FLAG (uint64_t(1) << 48)
#define SORT_KEY_LIGHTMAP_CAPTURE_FLAG (uint64_t(1) << 47)
#define SORT_KEY_LIGHTMAP_FLAG (uint64_t(1) << 46)
#define SORT_KEY_GI_PROBES_FLAG (uint64_t(1) << 45)
#define SORT_KEY_VERTEX_LIT_FLAG (uint64_t(1) << 44)
SORT_KEY_SHADING_SHIFT = 44,
SORT_KEY_SHADING_MASK = 63,
//44-28 material index
SORT_KEY_MATERIAL_INDEX_SHIFT = 28,
//28-8 geometry index
SORT_KEY_GEOMETRY_INDEX_SHIFT = 8,
//bits 5-7 geometry type
SORT_KEY_GEOMETRY_TYPE_SHIFT = 5,
//bits 0-5 for flags
SORT_KEY_OPAQUE_PRE_PASS = 8,
SORT_KEY_CULL_DISABLED_FLAG = 4,
SORT_KEY_SKELETON_FLAG = 2,
SORT_KEY_MIRROR_FLAG = 1
};
int max_elements;
struct Element {
RasterizerScene::InstanceBase *instance;
RasterizerStorageGLES2::Geometry *geometry;
RasterizerStorageGLES2::Material *material;
RasterizerStorageGLES2::GeometryOwner *owner;
uint64_t sort_key;
};
Element *base_elements;
Element **elements;
int element_count;
int alpha_element_count;
void clear() {
element_count = 0;
alpha_element_count = 0;
}
// sorts
struct SortByKey {
_FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const {
return A->sort_key < B->sort_key;
}
};
void sort_by_key(bool p_alpha) {
SortArray<Element *, SortByKey> sorter;
if (p_alpha) {
sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count);
} else {
sorter.sort(elements, element_count);
}
}
struct SortByDepth {
_FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const {
return A->instance->depth < B->instance->depth;
}
};
void sort_by_depth(bool p_alpha) { //used for shadows
SortArray<Element *, SortByDepth> sorter;
if (p_alpha) {
sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count);
} else {
sorter.sort(elements, element_count);
}
}
struct SortByReverseDepthAndPriority {
_FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const {
uint32_t layer_A = uint32_t(A->sort_key >> SORT_KEY_PRIORITY_SHIFT);
uint32_t layer_B = uint32_t(B->sort_key >> SORT_KEY_PRIORITY_SHIFT);
if (layer_A == layer_B) {
return A->instance->depth > B->instance->depth;
} else {
return layer_A < layer_B;
}
}
};
void sort_by_reverse_depth_and_priority(bool p_alpha) { //used for alpha
SortArray<Element *, SortByReverseDepthAndPriority> sorter;
if (p_alpha) {
sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count);
} else {
sorter.sort(elements, element_count);
}
}
// element adding and stuff
_FORCE_INLINE_ Element *add_element() {
if (element_count + alpha_element_count >= max_elements)
return NULL;
elements[element_count] = &base_elements[element_count];
return elements[element_count++];
}
_FORCE_INLINE_ Element *add_alpha_element() {
if (element_count + alpha_element_count >= max_elements) {
return NULL;
}
int idx = max_elements - alpha_element_count - 1;
elements[idx] = &base_elements[idx];
alpha_element_count++;
return elements[idx];
}
void init() {
element_count = 0;
alpha_element_count = 0;
elements = memnew_arr(Element *, max_elements);
base_elements = memnew_arr(Element, max_elements);
for (int i = 0; i < max_elements; i++) {
elements[i] = &base_elements[i];
}
}
RenderList() {
max_elements = DEFAULT_MAX_ELEMENTS;
}
~RenderList() {
memdelete_arr(elements);
memdelete_arr(base_elements);
}
};
RenderList render_list;
void _add_geometry(RasterizerStorageGLES2::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES2::GeometryOwner *p_owner, int p_material, bool p_depth_pass, bool p_shadow_pass);
void _add_geometry_with_material(RasterizerStorageGLES2::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES2::GeometryOwner *p_owner, RasterizerStorageGLES2::Material *p_material, bool p_depth_pass, bool p_shadow_pass);
void _fill_render_list(InstanceBase **p_cull_result, int p_cull_count, bool p_depth_pass, bool p_shadow_pass);
void _render_render_list(RenderList::Element **p_elements, int p_element_count, const RID *p_light_cull_result, int p_light_cull_count, const Transform &p_view_transform, const CameraMatrix &p_projection, RID p_shadow_atlas, Environment *p_env, GLuint p_base_env, float p_shadow_bias, float p_shadow_normal_bias, bool p_reverse_cull, bool p_alpha_pass, bool p_shadow, bool p_directional_add, bool p_directional_shadows);
void _draw_sky(RasterizerStorageGLES2::Sky *p_sky, const CameraMatrix &p_projection, const Transform &p_transform, bool p_vflip, float p_custom_fov, float p_energy);
void _setup_material(RasterizerStorageGLES2::Material *p_material, bool p_use_radiance_map, bool p_reverse_cull, bool p_shadow_atlas = false, bool p_skeleton_tex = false, Size2i p_skeleton_tex_size = Size2i(0, 0));
void _setup_geometry(RenderList::Element *p_element, RasterizerStorageGLES2::Skeleton *p_skeleton);
void _render_geometry(RenderList::Element *p_element);
virtual void render_scene(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
virtual void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count);
virtual bool free(RID p_rid);

File diff suppressed because it is too large Load diff

View file

@ -30,6 +30,7 @@
#ifndef RASTERIZERSTORAGEGLES2_H
#define RASTERIZERSTORAGEGLES2_H
#include "dvector.h"
#include "self_list.h"
#include "servers/visual/rasterizer.h"
#include "servers/visual/shader_language.h"
@ -37,11 +38,11 @@
#include "shader_gles2.h"
#include "shaders/copy.glsl.gen.h"
#include "shaders/cubemap_filter.glsl.gen.h"
/*
#include "shaders/blend_shape.glsl.gen.h"
#include "shaders/canvas.glsl.gen.h"
#include "shaders/copy.glsl.gen.h"
#include "shaders/cubemap_filter.glsl.gen.h"
#include "shaders/particles.glsl.gen.h"
*/
@ -76,6 +77,10 @@ public:
Set<String> extensions;
bool float_texture_supported;
bool s3tc_supported;
bool etc1_supported;
bool keep_original_textures;
bool no_depth_prepass;
@ -89,8 +94,13 @@ public:
GLuint normal_tex;
GLuint aniso_tex;
GLuint radical_inverse_vdc_cache_tex;
GLuint quadie;
GLuint quadie_array;
size_t skeleton_transform_buffer_size;
GLuint skeleton_transform_buffer;
PoolVector<float> skeleton_transform_cpu_buffer;
} resources;
@ -99,6 +109,7 @@ public:
ShaderCompilerGLES2 compiler;
CopyShaderGLES2 copy;
CubemapFilterShaderGLES2 cubemap_filter;
ShaderCompilerGLES2::IdentifierActions actions_canvas;
ShaderCompilerGLES2::IdentifierActions actions_scene;
@ -139,10 +150,72 @@ public:
} info;
void bind_quad_array() const;
/////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////DATA///////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
struct Instanciable : public RID_Data {
SelfList<RasterizerScene::InstanceBase>::List instance_list;
_FORCE_INLINE_ void instance_change_notify() {
SelfList<RasterizerScene::InstanceBase> *instances = instance_list.first();
while (instances) {
instances->self()->base_changed();
instances = instances->next();
}
}
_FORCE_INLINE_ void instance_material_change_notify() {
SelfList<RasterizerScene::InstanceBase> *instances = instance_list.first();
while (instances) {
instances->self()->base_material_changed();
instances = instances->next();
}
}
_FORCE_INLINE_ void instance_remove_deps() {
SelfList<RasterizerScene::InstanceBase> *instances = instance_list.first();
while (instances) {
instances->self()->base_removed();
instances = instances->next();
}
}
Instanciable() {}
virtual ~Instanciable() {}
};
struct GeometryOwner : public Instanciable {
};
struct Geometry : public Instanciable {
enum Type {
GEOMETRY_INVALID,
GEOMETRY_SURFACE,
GEOMETRY_IMMEDIATE,
GEOMETRY_MULTISURFACE
};
Type type;
RID material;
uint64_t last_pass;
uint32_t index;
virtual void material_changed_notify() {}
Geometry() {
last_pass = 0;
index = 0;
}
};
/////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////API////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
@ -171,6 +244,10 @@ public:
int total_data_size;
bool ignore_mipmaps;
bool compressed;
bool srgb;
int mipmaps;
bool active;
@ -184,6 +261,15 @@ public:
bool redraw_if_visible;
VisualServer::TextureDetectCallback detect_3d;
void *detect_3d_ud;
VisualServer::TextureDetectCallback detect_srgb;
void *detect_srgb_ud;
VisualServer::TextureDetectCallback detect_normal;
void *detect_normal_ud;
Texture() {
flags = 0;
width = 0;
@ -198,6 +284,8 @@ public:
total_data_size = 0;
ignore_mipmaps = false;
compressed = false;
active = false;
tex_id = 0;
@ -236,7 +324,7 @@ public:
mutable RID_Owner<Texture> texture_owner;
Ref<Image> _get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type);
Ref<Image> _get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed);
virtual RID texture_create();
virtual void texture_allocate(RID p_texture, int p_width, int p_height, Image::Format p_format, uint32_t p_flags = VS::TEXTURE_FLAGS_DEFAULT);
@ -272,6 +360,15 @@ public:
/* SKY API */
struct Sky : public RID_Data {
RID panorama;
GLuint radiance;
int radiance_size;
};
mutable RID_Owner<Sky> sky_owner;
virtual RID sky_create();
virtual void sky_set_texture(RID p_sky, RID p_panorama, int p_radiance_size);
@ -332,7 +429,6 @@ public:
} canvas_item;
/*
struct Spatial {
enum BlendMode {
@ -369,6 +465,7 @@ public:
bool uses_discard;
bool uses_sss;
bool uses_screen_texture;
bool uses_depth_texture;
bool uses_time;
bool writes_modelview_or_projection;
bool uses_vertex_lighting;
@ -379,7 +476,6 @@ public:
struct Particles {
} particles;
*/
bool uses_vertex_time;
bool uses_fragment_time;
@ -419,7 +515,7 @@ public:
Map<StringName, Variant> params;
SelfList<Material> list;
SelfList<Material> dirty_list;
Vector<RID> textures;
Vector<Pair<StringName, RID> > textures;
float line_width;
int render_priority;
@ -449,6 +545,11 @@ public:
mutable SelfList<Material>::List _material_dirty_list;
void _material_make_dirty(Material *p_material) const;
void _material_add_geometry(RID p_material, Geometry *p_geometry);
void _material_remove_geometry(RID p_material, Geometry *p_geometry);
void _update_material(Material *p_material);
mutable RID_Owner<Material> material_owner;
virtual RID material_create();
@ -473,6 +574,109 @@ public:
void update_dirty_materials();
/* MESH API */
struct Mesh;
struct Surface : public Geometry {
struct Attrib {
bool enabled;
bool integer;
GLuint index;
GLint size;
GLenum type;
GLboolean normalized;
GLsizei stride;
uint32_t offset;
};
Attrib attribs[VS::ARRAY_MAX];
Mesh *mesh;
uint32_t format;
GLuint vertex_id;
GLuint index_id;
struct BlendShape {
GLuint vertex_id;
GLuint array_id;
};
Vector<BlendShape> blend_shapes;
AABB aabb;
int array_len;
int index_array_len;
int max_bone;
int array_byte_size;
int index_array_byte_size;
VS::PrimitiveType primitive;
Vector<AABB> skeleton_bone_aabb;
Vector<bool> skeleton_bone_used;
bool active;
PoolVector<uint8_t> data;
PoolVector<uint8_t> index_data;
int total_data_size;
Surface() {
array_byte_size = 0;
index_array_byte_size = 0;
array_len = 0;
index_array_len = 0;
mesh = NULL;
primitive = VS::PRIMITIVE_POINTS;
active = false;
total_data_size = 0;
}
};
struct MultiMesh;
struct Mesh : public GeometryOwner {
bool active;
Vector<Surface *> surfaces;
int blend_shape_count;
VS::BlendShapeMode blend_shape_mode;
AABB custom_aabb;
mutable uint64_t last_pass;
SelfList<MultiMesh>::List multimeshes;
_FORCE_INLINE_ void update_multimeshes() {
SelfList<MultiMesh> *mm = multimeshes.first();
while (mm) {
mm->self()->instance_material_change_notify();
mm = mm->next();
}
}
Mesh() {
blend_shape_mode = VS::BLEND_SHAPE_MODE_NORMALIZED;
blend_shape_count = 0;
}
};
mutable RID_Owner<Mesh> mesh_owner;
virtual RID mesh_create();
virtual void mesh_add_surface(RID p_mesh, uint32_t p_format, VS::PrimitiveType p_primitive, const PoolVector<uint8_t> &p_array, int p_vertex_count, const PoolVector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<PoolVector<uint8_t> > &p_blend_shapes = Vector<PoolVector<uint8_t> >(), const Vector<AABB> &p_bone_aabbs = Vector<AABB>());
@ -512,6 +716,55 @@ public:
/* MULTIMESH API */
struct MultiMesh : public GeometryOwner {
RID mesh;
int size;
VS::MultimeshTransformFormat transform_format;
VS::MultimeshColorFormat color_format;
VS::MultimeshCustomDataFormat custom_data_format;
Vector<float> data;
AABB aabb;
SelfList<MultiMesh> update_list;
SelfList<MultiMesh> mesh_list;
int visible_instances;
int xform_floats;
int color_floats;
int custom_data_floats;
bool dirty_aabb;
bool dirty_data;
MultiMesh() :
update_list(this),
mesh_list(this) {
dirty_aabb = true;
dirty_data = true;
xform_floats = 0;
color_floats = 0;
custom_data_floats = 0;
visible_instances = -1;
size = 0;
transform_format = VS::MULTIMESH_TRANSFORM_2D;
color_format = VS::MULTIMESH_COLOR_NONE;
custom_data_format = VS::MULTIMESH_CUSTOM_DATA_NONE;
}
};
mutable RID_Owner<MultiMesh> multimesh_owner;
SelfList<MultiMesh>::List multimesh_update_list;
virtual RID multimesh_create();
virtual void multimesh_allocate(RID p_multimesh, int p_instances, VS::MultimeshTransformFormat p_transform_format, VS::MultimeshColorFormat p_color_format, VS::MultimeshCustomDataFormat p_data = VS::MULTIMESH_CUSTOM_DATA_NONE);
@ -521,7 +774,7 @@ public:
virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform &p_transform);
virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform);
virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color);
virtual void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color);
virtual void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_custom_data);
virtual RID multimesh_get_mesh(RID p_multimesh) const;
@ -557,6 +810,33 @@ public:
/* SKELETON API */
struct Skeleton : RID_Data {
bool use_2d;
int size;
// TODO use float textures for storage
Vector<float> bone_data;
GLuint tex_id;
SelfList<Skeleton> update_list;
Set<RasterizerScene::InstanceBase *> instances;
Skeleton() :
update_list(this) {
tex_id = 0;
size = 0;
use_2d = false;
}
};
mutable RID_Owner<Skeleton> skeleton_owner;
SelfList<Skeleton>::List skeleton_update_list;
void update_dirty_skeletons();
virtual RID skeleton_create();
@ -568,8 +848,38 @@ public:
virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const;
virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform);
void _update_skeleton_transform_buffer(const PoolVector<float> &p_data, size_t p_size);
/* Light API */
struct Light : Instanciable {
VS::LightType type;
float param[VS::LIGHT_PARAM_MAX];
Color color;
Color shadow_color;
RID projector;
bool shadow;
bool negative;
bool reverse_cull;
uint32_t cull_mask;
VS::LightOmniShadowMode omni_shadow_mode;
VS::LightOmniShadowDetail omni_shadow_detail;
VS::LightDirectionalShadowMode directional_shadow_mode;
VS::LightDirectionalShadowDepthRangeMode directional_range_mode;
bool directional_blend_splits;
uint64_t version;
};
mutable RID_Owner<Light> light_owner;
virtual RID light_create(VS::LightType p_type);
virtual void light_set_color(RID p_light, const Color &p_color);
@ -831,6 +1141,8 @@ public:
void initialize();
void finalize();
void _copy_screen();
virtual bool has_os_feature(const String &p_feature) const;
virtual void update_dirty_resources();

View file

@ -325,7 +325,7 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
uniform_code += ";\n";
if (SL::is_sampler_type(E->get().type)) {
r_gen_code.texture_uniforms.write[E->get().texture_order] = _mkid(E->key());
r_gen_code.texture_uniforms.write[E->get().texture_order] = E->key();
r_gen_code.texture_hints.write[E->get().texture_order] = E->get().hint;
} else {
r_gen_code.uniforms.write[E->get().order] = E->key();
@ -507,7 +507,6 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
case SL::OP_ASSIGN_DIV:
case SL::OP_ASSIGN_SHIFT_LEFT:
case SL::OP_ASSIGN_SHIFT_RIGHT:
case SL::OP_ASSIGN_MOD:
case SL::OP_ASSIGN_BIT_AND:
case SL::OP_ASSIGN_BIT_OR:
case SL::OP_ASSIGN_BIT_XOR: {
@ -518,6 +517,16 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
code += _dump_node_code(op_node->arguments[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
} break;
case SL::OP_ASSIGN_MOD: {
code += _dump_node_code(op_node->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, true);
code += " = ";
code += "mod(";
code += _dump_node_code(op_node->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, true);
code += ", ";
code += _dump_node_code(op_node->arguments[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
code += ")";
} break;
case SL::OP_BIT_INVERT:
case SL::OP_NEGATE:
case SL::OP_NOT:
@ -552,6 +561,45 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
code += "textureCube";
}
} else if (var_node->name == "textureLod") {
// emit texture call
if (op_node->arguments[1]->get_datatype() == SL::TYPE_SAMPLER2D) {
code += "texture2DLod";
} else if (op_node->arguments[1]->get_datatype() == SL::TYPE_SAMPLERCUBE) {
code += "textureCubeLod";
}
} else if (var_node->name == "mix") {
switch (op_node->arguments[3]->get_datatype()) {
case SL::TYPE_BVEC2: {
code += "select2";
} break;
case SL::TYPE_BVEC3: {
code += "select3";
} break;
case SL::TYPE_BVEC4: {
code += "select4";
} break;
case SL::TYPE_VEC2:
case SL::TYPE_VEC3:
case SL::TYPE_VEC4:
case SL::TYPE_FLOAT: {
code += "mix";
} break;
default: {
SL::DataType type = op_node->arguments[3]->get_datatype();
print_line(String("uhhhh invalid mix with type: ") + itos(type));
} break;
}
} else if (p_default_actions.renames.has(var_node->name)) {
code += p_default_actions.renames[var_node->name];
} else if (internal_functions.has(var_node->name)) {
@ -590,6 +638,15 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
code += _dump_node_code(op_node->arguments[2], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
} break;
case SL::OP_MOD: {
code += "mod(";
code += _dump_node_code(op_node->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
code += ", ";
code += _dump_node_code(op_node->arguments[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
code += ")";
} break;
default: {
code += "(";
code += _dump_node_code(op_node->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
@ -751,10 +808,10 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() {
/** SPATIAL SHADER **/
actions[VS::SHADER_SPATIAL].renames["WORLD_MATRIX"] = "world_transform";
actions[VS::SHADER_SPATIAL].renames["INV_CAMERA_MATRIX"] = "camera_inverse_matrix";
actions[VS::SHADER_SPATIAL].renames["CAMERA_MATRIX"] = "camera_matrix";
actions[VS::SHADER_SPATIAL].renames["INV_CAMERA_MATRIX"] = "camera_matrix";
actions[VS::SHADER_SPATIAL].renames["CAMERA_MATRIX"] = "camera_inverse_matrix";
actions[VS::SHADER_SPATIAL].renames["PROJECTION_MATRIX"] = "projection_matrix";
actions[VS::SHADER_SPATIAL].renames["INV_PROJECTION_MATRIX"] = "inv_projection_matrix";
actions[VS::SHADER_SPATIAL].renames["INV_PROJECTION_MATRIX"] = "projection_inverse_matrix";
actions[VS::SHADER_SPATIAL].renames["MODELVIEW_MATRIX"] = "modelview";
actions[VS::SHADER_SPATIAL].renames["VERTEX"] = "vertex.xyz";

View file

@ -33,7 +33,10 @@
#include "print_string.h"
#include "string_builder.h"
//#define DEBUG_OPENGL
#include "rasterizer_gles2.h"
#include "rasterizer_storage_gles2.h"
// #define DEBUG_OPENGL
// #include "shaders/copy.glsl.gen.h"
@ -54,7 +57,7 @@
ShaderGLES2 *ShaderGLES2::active = NULL;
//#define DEBUG_SHADER
// #define DEBUG_SHADER
#ifdef DEBUG_SHADER
@ -83,7 +86,10 @@ void ShaderGLES2::bind_uniforms() {
continue;
}
const Variant &v = E->value();
Variant v;
v = E->value();
_set_uniform_variant(location, v);
E = E->next();
}
@ -128,6 +134,28 @@ bool ShaderGLES2::bind() {
glUseProgram(version->id);
// find out uniform names and locations
int count;
glGetProgramiv(version->id, GL_ACTIVE_UNIFORMS, &count);
version->uniform_names.resize(count);
for (int i = 0; i < count; i++) {
GLchar uniform_name[1024];
int len = 0;
GLint size = 0;
GLenum type;
glGetActiveUniform(version->id, i, 1024, &len, &size, &type, uniform_name);
uniform_name[len] = '\0';
String name = String((const char *)uniform_name);
version->uniform_names.write[i] = name;
}
bind_uniforms();
DEBUG_TEST_ERROR("use program");
active = this;
@ -228,7 +256,7 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() {
}
if (!_v)
version_map[conditional_version];
version_map[conditional_version] = Version();
Version &v = version_map[conditional_version];
@ -389,6 +417,10 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() {
strings.push_back(fragment_code3.get_data());
#ifdef DEBUG_SHADER
if (cc) {
DEBUG_PRINT("\nFragment Code:\n\n" + String(cc->fragment_globals));
}
DEBUG_PRINT("\nFragment Code:\n\n" + String(code_string.get_data()));
#endif
@ -500,9 +532,18 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() {
}
if (cc) {
v.custom_uniform_locations.resize(cc->custom_uniforms.size());
// uniforms
for (int i = 0; i < cc->custom_uniforms.size(); i++) {
v.custom_uniform_locations.write[i] = glGetUniformLocation(v.id, String(cc->custom_uniforms[i]).ascii().get_data());
StringName native_uniform_name = "m_" + cc->custom_uniforms[i];
GLint location = glGetUniformLocation(v.id, ((String)native_uniform_name).ascii().get_data());
v.custom_uniform_locations[cc->custom_uniforms[i]] = location;
}
// textures
for (int i = 0; i < cc->texture_uniforms.size(); i++) {
StringName native_uniform_name = "m_" + cc->texture_uniforms[i];
GLint location = glGetUniformLocation(v.id, ((String)native_uniform_name).ascii().get_data());
v.custom_uniform_locations[cc->texture_uniforms[i]] = location;
}
}
@ -660,6 +701,7 @@ void ShaderGLES2::set_custom_shader_code(uint32_t p_code_id,
cc->light = p_light;
cc->custom_uniforms = p_uniforms;
cc->custom_defines = p_custom_defines;
cc->texture_uniforms = p_texture_uniforms;
cc->version++;
}
@ -675,6 +717,341 @@ void ShaderGLES2::free_custom_shader(uint32_t p_code_id) {
custom_code_map.erase(p_code_id);
}
void ShaderGLES2::use_material(void *p_material, int p_num_predef_textures) {
RasterizerStorageGLES2::Material *material = (RasterizerStorageGLES2::Material *)p_material;
if (!material) {
return;
}
if (!material->shader) {
return;
}
Version *v = version_map.getptr(conditional_version);
CustomCode *cc = NULL;
if (v) {
cc = custom_code_map.getptr(v->code_version);
}
// bind uniforms
for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = material->shader->uniforms.front(); E; E = E->next()) {
if (E->get().texture_order >= 0)
continue; // this is a texture, doesn't go here
Map<StringName, Variant>::Element *V = material->params.find(E->key());
Pair<ShaderLanguage::DataType, Vector<ShaderLanguage::ConstantNode::Value> > value;
value.first = E->get().type;
value.second = E->get().default_value;
if (V) {
value.second = Vector<ShaderLanguage::ConstantNode::Value>();
value.second.resize(E->get().default_value.size());
switch (E->get().type) {
case ShaderLanguage::TYPE_BOOL: {
if (value.second.size() < 1)
value.second.resize(1);
value.second.write[0].boolean = V->get();
} break;
case ShaderLanguage::TYPE_BVEC2: {
if (value.second.size() < 2)
value.second.resize(2);
int flags = V->get();
value.second.write[0].boolean = flags & 1;
value.second.write[1].boolean = flags & 2;
} break;
case ShaderLanguage::TYPE_BVEC3: {
if (value.second.size() < 3)
value.second.resize(3);
int flags = V->get();
value.second.write[0].boolean = flags & 1;
value.second.write[1].boolean = flags & 2;
value.second.write[2].boolean = flags & 4;
} break;
case ShaderLanguage::TYPE_BVEC4: {
if (value.second.size() < 4)
value.second.resize(4);
int flags = V->get();
value.second.write[0].boolean = flags & 1;
value.second.write[1].boolean = flags & 2;
value.second.write[2].boolean = flags & 4;
value.second.write[3].boolean = flags & 8;
} break;
case ShaderLanguage::TYPE_INT: {
if (value.second.size() < 1)
value.second.resize(1);
int val = V->get();
value.second.write[0].sint = val;
} break;
case ShaderLanguage::TYPE_IVEC2: {
if (value.second.size() < 2)
value.second.resize(2);
PoolIntArray val = V->get();
for (int i = 0; i < val.size(); i++) {
value.second.write[i].sint = val[i];
}
} break;
case ShaderLanguage::TYPE_IVEC3: {
if (value.second.size() < 3)
value.second.resize(3);
PoolIntArray val = V->get();
for (int i = 0; i < val.size(); i++) {
value.second.write[i].sint = val[i];
}
} break;
case ShaderLanguage::TYPE_IVEC4: {
if (value.second.size() < 4)
value.second.resize(4);
PoolIntArray val = V->get();
for (int i = 0; i < val.size(); i++) {
value.second.write[i].sint = val[i];
}
} break;
case ShaderLanguage::TYPE_UINT: {
if (value.second.size() < 1)
value.second.resize(1);
uint32_t val = V->get();
value.second.write[0].uint = val;
} break;
case ShaderLanguage::TYPE_UVEC2: {
if (value.second.size() < 2)
value.second.resize(2);
PoolIntArray val = V->get();
for (int i = 0; i < val.size(); i++) {
value.second.write[i].uint = val[i];
}
} break;
case ShaderLanguage::TYPE_UVEC3: {
if (value.second.size() < 3)
value.second.resize(3);
PoolIntArray val = V->get();
for (int i = 0; i < val.size(); i++) {
value.second.write[i].uint = val[i];
}
} break;
case ShaderLanguage::TYPE_UVEC4: {
if (value.second.size() < 4)
value.second.resize(4);
PoolIntArray val = V->get();
for (int i = 0; i < val.size(); i++) {
value.second.write[i].uint = val[i];
}
} break;
case ShaderLanguage::TYPE_FLOAT: {
if (value.second.size() < 1)
value.second.resize(1);
value.second.write[0].real = V->get();
} break;
case ShaderLanguage::TYPE_VEC2: {
if (value.second.size() < 2)
value.second.resize(2);
Vector2 val = V->get();
value.second.write[0].real = val.x;
value.second.write[1].real = val.y;
} break;
case ShaderLanguage::TYPE_VEC3: {
if (value.second.size() < 3)
value.second.resize(3);
Vector3 val = V->get();
value.second.write[0].real = val.x;
value.second.write[1].real = val.y;
value.second.write[2].real = val.z;
} break;
case ShaderLanguage::TYPE_VEC4: {
if (value.second.size() < 4)
value.second.resize(4);
if (V->get().get_type() == Variant::PLANE) {
Plane val = V->get();
value.second.write[0].real = val.normal.x;
value.second.write[1].real = val.normal.y;
value.second.write[2].real = val.normal.z;
value.second.write[3].real = val.d;
} else {
Color val = V->get();
value.second.write[0].real = val.r;
value.second.write[1].real = val.g;
value.second.write[2].real = val.b;
value.second.write[3].real = val.a;
}
} break;
case ShaderLanguage::TYPE_MAT2: {
Transform2D val = V->get();
// TODO
} break;
case ShaderLanguage::TYPE_MAT3: {
Basis val = V->get();
// TODO
} break;
case ShaderLanguage::TYPE_MAT4: {
Transform val = V->get();
// TODO
} break;
case ShaderLanguage::TYPE_SAMPLER2D: {
} break;
case ShaderLanguage::TYPE_ISAMPLER2D: {
} break;
case ShaderLanguage::TYPE_USAMPLER2D: {
} break;
case ShaderLanguage::TYPE_SAMPLERCUBE: {
} break;
}
} else {
if (value.second.size() == 0) {
// No default value set... weird, let's just use zero for everything
size_t default_arg_size = 1;
bool is_float = false;
switch (E->get().type) {
case ShaderLanguage::TYPE_BOOL:
case ShaderLanguage::TYPE_INT:
case ShaderLanguage::TYPE_UINT: {
default_arg_size = 1;
} break;
case ShaderLanguage::TYPE_FLOAT: {
default_arg_size = 1;
is_float = true;
} break;
case ShaderLanguage::TYPE_BVEC2:
case ShaderLanguage::TYPE_IVEC2:
case ShaderLanguage::TYPE_UVEC2: {
default_arg_size = 2;
} break;
case ShaderLanguage::TYPE_VEC2: {
default_arg_size = 2;
is_float = true;
} break;
case ShaderLanguage::TYPE_BVEC3:
case ShaderLanguage::TYPE_IVEC3:
case ShaderLanguage::TYPE_UVEC3: {
default_arg_size = 3;
} break;
case ShaderLanguage::TYPE_VEC3: {
default_arg_size = 3;
is_float = true;
} break;
case ShaderLanguage::TYPE_BVEC4:
case ShaderLanguage::TYPE_IVEC4:
case ShaderLanguage::TYPE_UVEC4: {
default_arg_size = 4;
} break;
case ShaderLanguage::TYPE_VEC4: {
default_arg_size = 4;
is_float = true;
} break;
default: {
// TODO matricies and all that stuff
default_arg_size = 1;
} break;
}
value.second.resize(default_arg_size);
for (int i = 0; i < default_arg_size; i++) {
if (is_float) {
value.second.write[i].real = 0.0;
} else {
value.second.write[i].uint = 0;
}
}
}
}
// GLint location = get_uniform_location(E->key());
GLint location;
if (v->custom_uniform_locations.has(E->key())) {
location = v->custom_uniform_locations[E->key()];
} else {
int idx = v->uniform_names.find(E->key()); // TODO maybe put those in a Map?
if (idx < 0) {
location = -1;
} else {
location = v->uniform_location[idx];
}
}
_set_uniform_value(location, value);
}
// bind textures
int tc = material->textures.size();
Pair<StringName, RID> *textures = material->textures.ptrw();
ShaderLanguage::ShaderNode::Uniform::Hint *texture_hints = material->shader->texture_hints.ptrw();
for (int i = 0; i < tc; i++) {
Pair<ShaderLanguage::DataType, Vector<ShaderLanguage::ConstantNode::Value> > value;
value.first = ShaderLanguage::TYPE_INT;
value.second.resize(1);
value.second.write[0].sint = p_num_predef_textures + i;
// GLint location = get_uniform_location(textures[i].first);
// if (location < 0) {
// location = material->shader->uniform_locations[textures[i].first];
// }
GLint location = -1;
if (v->custom_uniform_locations.has(textures[i].first)) {
location = v->custom_uniform_locations[textures[i].first];
} else {
location = get_uniform_location(textures[i].first);
}
_set_uniform_value(location, value);
}
}
void ShaderGLES2::set_base_material_tex_index(int p_idx) {
}

View file

@ -44,6 +44,11 @@
#include "map.h"
#include "variant.h"
#include "core/pair.h"
#include "servers/visual/shader_language.h"
class RasterizerStorageGLES2;
class ShaderGLES2 {
protected:
struct Enum {
@ -105,9 +110,10 @@ private:
GLuint id;
GLuint vert_id;
GLuint frag_id;
Vector<StringName> uniform_names;
GLint *uniform_location;
Vector<GLint> texture_uniform_locations;
Vector<GLint> custom_uniform_locations;
Map<StringName, GLint> custom_uniform_locations;
uint32_t code_version;
bool ok;
Version() {
@ -169,6 +175,168 @@ private:
int max_image_units;
Map<uint32_t, Variant> uniform_defaults;
Map<uint32_t, CameraMatrix> uniform_cameras;
Map<StringName, Pair<ShaderLanguage::DataType, Vector<ShaderLanguage::ConstantNode::Value> > > uniform_values;
protected:
_FORCE_INLINE_ int _get_uniform(int p_which) const;
_FORCE_INLINE_ void _set_conditional(int p_which, bool p_value);
void setup(const char **p_conditional_defines,
int p_conditional_count,
const char **p_uniform_names,
int p_uniform_count,
const AttributePair *p_attribute_pairs,
int p_attribute_count,
const TexUnitPair *p_texunit_pairs,
int p_texunit_pair_count,
const char *p_vertex_code,
const char *p_fragment_code,
int p_vertex_code_start,
int p_fragment_code_start);
ShaderGLES2();
public:
enum {
CUSTOM_SHADER_DISABLED = 0
};
GLint get_uniform_location(const String &p_name) const;
GLint get_uniform_location(int p_index) const;
static _FORCE_INLINE_ ShaderGLES2 *get_active() { return active; }
bool bind();
void unbind();
void bind_uniforms();
inline GLuint get_program() const { return version ? version->id : 0; }
void clear_caches();
_FORCE_INLINE_ void _set_uniform_value(GLint p_uniform, const Pair<ShaderLanguage::DataType, Vector<ShaderLanguage::ConstantNode::Value> > &value) {
if (p_uniform < 0)
return;
const Vector<ShaderLanguage::ConstantNode::Value> &values = value.second;
switch (value.first) {
case ShaderLanguage::TYPE_BOOL: {
glUniform1i(p_uniform, values[0].boolean);
} break;
case ShaderLanguage::TYPE_BVEC2: {
glUniform2i(p_uniform, values[0].boolean, values[1].boolean);
} break;
case ShaderLanguage::TYPE_BVEC3: {
glUniform3i(p_uniform, values[0].boolean, values[1].boolean, values[2].boolean);
} break;
case ShaderLanguage::TYPE_BVEC4: {
glUniform4i(p_uniform, values[0].boolean, values[1].boolean, values[2].boolean, values[3].boolean);
} break;
case ShaderLanguage::TYPE_INT: {
glUniform1i(p_uniform, values[0].sint);
} break;
case ShaderLanguage::TYPE_IVEC2: {
glUniform2i(p_uniform, values[0].sint, values[1].sint);
} break;
case ShaderLanguage::TYPE_IVEC3: {
glUniform3i(p_uniform, values[0].sint, values[1].sint, values[2].sint);
} break;
case ShaderLanguage::TYPE_IVEC4: {
glUniform4i(p_uniform, values[0].sint, values[1].sint, values[2].sint, values[3].sint);
} break;
case ShaderLanguage::TYPE_UINT: {
glUniform1i(p_uniform, values[0].uint);
} break;
case ShaderLanguage::TYPE_UVEC2: {
glUniform2i(p_uniform, values[0].uint, values[1].uint);
} break;
case ShaderLanguage::TYPE_UVEC3: {
glUniform3i(p_uniform, values[0].uint, values[1].uint, values[2].uint);
} break;
case ShaderLanguage::TYPE_UVEC4: {
glUniform4i(p_uniform, values[0].uint, values[1].uint, values[2].uint, values[3].uint);
} break;
case ShaderLanguage::TYPE_FLOAT: {
glUniform1f(p_uniform, values[0].real);
} break;
case ShaderLanguage::TYPE_VEC2: {
glUniform2f(p_uniform, values[0].real, values[1].real);
} break;
case ShaderLanguage::TYPE_VEC3: {
glUniform3f(p_uniform, values[0].real, values[1].real, values[2].real);
} break;
case ShaderLanguage::TYPE_VEC4: {
glUniform4f(p_uniform, values[0].real, values[1].real, values[2].real, values[3].real);
} break;
case ShaderLanguage::TYPE_MAT2: {
GLfloat mat[4];
for (int i = 0; i < 4; i++) {
mat[i] = values[i].real;
}
glUniformMatrix2fv(p_uniform, 1, GL_FALSE, mat);
} break;
case ShaderLanguage::TYPE_MAT3: {
GLfloat mat[9];
for (int i = 0; i < 0; i++) {
mat[i] = values[i].real;
}
glUniformMatrix3fv(p_uniform, 1, GL_FALSE, mat);
} break;
case ShaderLanguage::TYPE_MAT4: {
GLfloat mat[16];
for (int i = 0; i < 0; i++) {
mat[i] = values[i].real;
}
glUniformMatrix4fv(p_uniform, 1, GL_FALSE, mat);
} break;
case ShaderLanguage::TYPE_SAMPLER2D: {
} break;
case ShaderLanguage::TYPE_ISAMPLER2D: {
} break;
case ShaderLanguage::TYPE_USAMPLER2D: {
} break;
case ShaderLanguage::TYPE_SAMPLERCUBE: {
} break;
}
}
_FORCE_INLINE_ void _set_uniform_variant(GLint p_uniform, const Variant &p_value) {
if (p_uniform < 0)
@ -261,50 +429,14 @@ private:
};
glUniformMatrix4fv(p_uniform, 1, false, matrix);
} break;
case Variant::OBJECT: {
} break;
default: { ERR_FAIL(); } // do nothing
}
}
Map<uint32_t, Variant> uniform_defaults;
Map<uint32_t, CameraMatrix> uniform_cameras;
protected:
_FORCE_INLINE_ int _get_uniform(int p_which) const;
_FORCE_INLINE_ void _set_conditional(int p_which, bool p_value);
void setup(const char **p_conditional_defines,
int p_conditional_count,
const char **p_uniform_names,
int p_uniform_count,
const AttributePair *p_attribute_pairs,
int p_attribute_count,
const TexUnitPair *p_texunit_pairs,
int p_texunit_pair_count,
const char *p_vertex_code,
const char *p_fragment_code,
int p_vertex_code_start,
int p_fragment_code_start);
ShaderGLES2();
public:
enum {
CUSTOM_SHADER_DISABLED = 0
};
GLint get_uniform_location(const String &p_name) const;
GLint get_uniform_location(int p_index) const;
static _FORCE_INLINE_ ShaderGLES2 *get_active() { return active; }
bool bind();
void unbind();
void bind_uniforms();
inline GLuint get_program() const { return version ? version->id : 0; }
void clear_caches();
uint32_t create_custom_shader();
void set_custom_shader_code(uint32_t p_code_id,
const String &p_vertex,
@ -331,6 +463,10 @@ public:
uniforms_dirty = true;
}
// this void* is actually a RasterizerStorageGLES2::Material, but C++ doesn't
// like forward declared nested classes.
void use_material(void *p_material, int p_num_predef_textures);
uint32_t get_version() const { return new_conditional_version.version; }
void set_uniform_camera(int p_idx, const CameraMatrix &p_mat) {

View file

@ -8,8 +8,8 @@ if 'GLES2_GLSL' in env['BUILDERS']:
env.GLES2_GLSL('canvas.glsl');
# env.GLES2_GLSL('canvas_shadow.glsl');
env.GLES2_GLSL('scene.glsl');
# env.GLES2_GLSL('cubemap_filter.glsl');
# env.GLES2_GLSL('cube_to_dp.glsl');
env.GLES2_GLSL('cubemap_filter.glsl');
env.GLES2_GLSL('cube_to_dp.glsl');
# env.GLES2_GLSL('blend_shape.glsl');
# env.GLES2_GLSL('screen_space_reflection.glsl');
# env.GLES2_GLSL('effect_blur.glsl');

View file

@ -27,7 +27,7 @@ uniform vec4 src_rect;
#endif
uniform bool blit_pass;
uniform highp float time;
VERTEX_SHADER_GLOBALS
@ -103,7 +103,7 @@ uniform mediump sampler2D normal_texture; // texunit:1
varying mediump vec2 uv_interp;
varying mediump vec4 color_interp;
uniform bool blit_pass;
uniform highp float time;
uniform vec4 final_modulate;
@ -127,6 +127,10 @@ void main() {
vec4 color = color_interp;
color *= texture2D(color_texture, uv_interp);
#ifdef SCREEN_UV_USED
vec2 screen_uv = gl_FragCoord.xy * screen_pixel_size;
#endif
{
FRAGMENT_SHADER_CODE

View file

@ -9,11 +9,20 @@ precision mediump int;
#endif
attribute highp vec4 vertex_attrib; // attrib:0
#if defined(USE_CUBEMAP) || defined(USE_PANORAMA)
attribute vec3 cube_in; // attrib:4
#else
attribute vec2 uv_in; // attrib:4
#endif
attribute vec2 uv2_in; // attrib:5
#if defined(USE_CUBEMAP) || defined(USE_PANORAMA)
varying vec3 cube_interp;
#else
varying vec2 uv_interp;
#endif
varying vec2 uv2_interp;
#ifdef USE_COPY_SECTION
@ -22,7 +31,12 @@ uniform vec4 copy_section;
void main() {
#if defined(USE_CUBEMAP) || defined(USE_PANORAMA)
cube_interp = cube_in;
#else
uv_interp = uv_in;
#endif
uv2_interp = uv2_in;
gl_Position = vertex_attrib;
@ -34,6 +48,8 @@ void main() {
[fragment]
#define M_PI 3.14159265359
#ifdef USE_GLES_OVER_GL
#define mediump
#define highp
@ -42,21 +58,59 @@ precision mediump float;
precision mediump int;
#endif
#if defined(USE_CUBEMAP) || defined(USE_PANORAMA)
varying vec3 cube_interp;
#else
varying vec2 uv_interp;
#endif
#ifdef USE_CUBEMAP
uniform samplerCube source_cube; // texunit:0
#else
uniform sampler2D source; // texunit:0
#endif
varying vec2 uv2_interp;
#ifdef USE_MULTIPLIER
uniform float multiplier;
#endif
#ifdef USE_CUSTOM_ALPHA
uniform float custom_alpha;
#endif
#if defined(USE_PANORAMA) || defined(USE_ASYM_PANO)
vec4 texturePanorama(sampler2D pano, vec3 normal) {
vec2 st = vec2(
atan(normal.x, normal.z),
acos(normal.y)
);
if(st.x < 0.0)
st.x += M_PI*2.0;
st/=vec2(M_PI*2.0,M_PI);
return texture2D(pano,st);
}
#endif
void main() {
//vec4 color = color_interp;
#ifdef USE_PANORAMA
vec4 color = texturePanorama(source, normalize(cube_interp));
#elif defined(USE_CUBEMAP)
vec4 color = textureCube(source_cube, normalize(cube_interp));
#else
vec4 color = texture2D( source, uv_interp );
#endif
#ifdef USE_NO_ALPHA
@ -67,6 +121,9 @@ void main() {
color.a=custom_alpha;
#endif
#ifdef USE_MULTIPLIER
color.rgb *= multiplier;
#endif
gl_FragColor = color;
}

View file

@ -1,10 +1,17 @@
[vertex]
#ifdef USE_GLES_OVER_GL
#define mediump
#define highp
#else
precision mediump float;
precision mediump int;
#endif
layout(location=0) in highp vec4 vertex_attrib;
layout(location=4) in vec2 uv_in;
attribute highp vec4 vertex_attrib; // attrib:0
attribute vec2 uv_in; // attrib:4
out vec2 uv_interp;
varying vec2 uv_interp;
void main() {
@ -14,9 +21,16 @@ void main() {
[fragment]
#ifdef USE_GLES_OVER_GL
#define mediump
#define highp
#else
precision mediump float;
precision mediump int;
#endif
uniform highp samplerCube source_cube; //texunit:0
in vec2 uv_interp;
varying vec2 uv_interp;
uniform bool z_flip;
uniform highp float z_far;
@ -49,7 +63,7 @@ void main() {
}
//normal = normalize(vec3( uv_interp * 2.0 - 1.0, 1.0 ));
float depth = texture(source_cube,normal).r;
float depth = textureCube(source_cube,normal).r;
// absolute values for direction cosines, bigger value equals closer to basis axis
vec3 unorm = abs(normal);

View file

@ -1,11 +1,17 @@
[vertex]
#ifdef USE_GLES_OVER_GL
#define mediump
#define highp
#else
precision mediump float;
precision mediump int;
#endif
layout(location=0) in highp vec2 vertex;
attribute highp vec2 vertex; // attrib:0
attribute highp vec2 uv; // attrib:4
layout(location=4) in highp vec2 uv;
out highp vec2 uv_interp;
varying highp vec2 uv_interp;
void main() {
@ -15,106 +21,99 @@ void main() {
[fragment]
#extension GL_ARB_shader_texture_lod : require
precision highp float;
precision highp int;
#ifdef USE_GLES_OVER_GL
#define mediump
#define highp
#else
precision mediump float;
precision mediump int;
#endif
#ifdef USE_SOURCE_PANORAMA
uniform sampler2D source_panorama; //texunit:0
#endif
#ifdef USE_SOURCE_DUAL_PARABOLOID_ARRAY
uniform sampler2DArray source_dual_paraboloid_array; //texunit:0
uniform int source_array_index;
#endif
#if !defined(USE_SOURCE_DUAL_PARABOLOID_ARRAY) && !defined(USE_SOURCE_PANORAMA)
#else
uniform samplerCube source_cube; //texunit:0
#endif
uniform int face_id;
uniform float roughness;
in highp vec2 uv_interp;
layout(location = 0) out vec4 frag_color;
varying highp vec2 uv_interp;
uniform sampler2D radical_inverse_vdc_cache; // texunit:1
#define M_PI 3.14159265359
#ifdef LOW_QUALITY
vec3 texelCoordToVec(vec2 uv, int faceID)
{
mat3 faceUvVectors[6];
/*
// -x
faceUvVectors[1][0] = vec3(0.0, 0.0, 1.0); // u -> +z
faceUvVectors[1][1] = vec3(0.0, -1.0, 0.0); // v -> -y
faceUvVectors[1][2] = vec3(-1.0, 0.0, 0.0); // -x face
#define SAMPLE_COUNT 64
// +x
faceUvVectors[0][0] = vec3(0.0, 0.0, -1.0); // u -> -z
faceUvVectors[0][1] = vec3(0.0, -1.0, 0.0); // v -> -y
faceUvVectors[0][2] = vec3(1.0, 0.0, 0.0); // +x face
#else
// -y
faceUvVectors[3][0] = vec3(1.0, 0.0, 0.0); // u -> +x
faceUvVectors[3][1] = vec3(0.0, 0.0, -1.0); // v -> -z
faceUvVectors[3][2] = vec3(0.0, -1.0, 0.0); // -y face
#define SAMPLE_COUNT 512
// +y
faceUvVectors[2][0] = vec3(1.0, 0.0, 0.0); // u -> +x
faceUvVectors[2][1] = vec3(0.0, 0.0, 1.0); // v -> +z
faceUvVectors[2][2] = vec3(0.0, 1.0, 0.0); // +y face
#endif
// -z
faceUvVectors[5][0] = vec3(-1.0, 0.0, 0.0); // u -> -x
faceUvVectors[5][1] = vec3(0.0, -1.0, 0.0); // v -> -y
faceUvVectors[5][2] = vec3(0.0, 0.0, -1.0); // -z face
#ifdef USE_SOURCE_PANORAMA
// +z
faceUvVectors[4][0] = vec3(1.0, 0.0, 0.0); // u -> +x
faceUvVectors[4][1] = vec3(0.0, -1.0, 0.0); // v -> -y
faceUvVectors[4][2] = vec3(0.0, 0.0, 1.0); // +z face
*/
vec4 texturePanorama(sampler2D pano, vec3 normal) {
// -x
faceUvVectors[0][0] = vec3(0.0, 0.0, 1.0); // u -> +z
faceUvVectors[0][1] = vec3(0.0, -1.0, 0.0); // v -> -y
faceUvVectors[0][2] = vec3(-1.0, 0.0, 0.0); // -x face
vec2 st = vec2(
atan(normal.x, normal.z),
acos(normal.y)
);
// +x
faceUvVectors[1][0] = vec3(0.0, 0.0, -1.0); // u -> -z
faceUvVectors[1][1] = vec3(0.0, -1.0, 0.0); // v -> -y
faceUvVectors[1][2] = vec3(1.0, 0.0, 0.0); // +x face
if(st.x < 0.0)
st.x += M_PI*2.0;
// -y
faceUvVectors[2][0] = vec3(1.0, 0.0, 0.0); // u -> +x
faceUvVectors[2][1] = vec3(0.0, 0.0, -1.0); // v -> -z
faceUvVectors[2][2] = vec3(0.0, -1.0, 0.0); // -y face
st/=vec2(M_PI*2.0,M_PI);
// +y
faceUvVectors[3][0] = vec3(1.0, 0.0, 0.0); // u -> +x
faceUvVectors[3][1] = vec3(0.0, 0.0, 1.0); // v -> +z
faceUvVectors[3][2] = vec3(0.0, 1.0, 0.0); // +y face
return texture2DLod(pano,st,0.0);
// -z
faceUvVectors[4][0] = vec3(-1.0, 0.0, 0.0); // u -> -x
faceUvVectors[4][1] = vec3(0.0, -1.0, 0.0); // v -> -y
faceUvVectors[4][2] = vec3(0.0, 0.0, -1.0); // -z face
// +z
faceUvVectors[5][0] = vec3(1.0, 0.0, 0.0); // u -> +x
faceUvVectors[5][1] = vec3(0.0, -1.0, 0.0); // v -> -y
faceUvVectors[5][2] = vec3(0.0, 0.0, 1.0); // +z face
// out = u * s_faceUv[0] + v * s_faceUv[1] + s_faceUv[2].
vec3 result = (faceUvVectors[faceID][0] * uv.x) + (faceUvVectors[faceID][1] * uv.y) + faceUvVectors[faceID][2];
return normalize(result);
}
vec3 ImportanceSampleGGX(vec2 Xi, float Roughness, vec3 N)
{
#endif
vec3 texelCoordToVec(vec2 uv, int faceID) {
mat3 faceUvVectors[6];
// -x
faceUvVectors[0][0] = vec3(0.0, 0.0, 1.0); // u -> +z
faceUvVectors[0][1] = vec3(0.0, -1.0, 0.0); // v -> -y
faceUvVectors[0][2] = vec3(-1.0, 0.0, 0.0); // -x face
// +x
faceUvVectors[1][0] = vec3(0.0, 0.0, -1.0); // u -> -z
faceUvVectors[1][1] = vec3(0.0, -1.0, 0.0); // v -> -y
faceUvVectors[1][2] = vec3(1.0, 0.0, 0.0); // +x face
// -y
faceUvVectors[2][0] = vec3(1.0, 0.0, 0.0); // u -> +x
faceUvVectors[2][1] = vec3(0.0, 0.0, -1.0); // v -> -z
faceUvVectors[2][2] = vec3(0.0, -1.0, 0.0); // -y face
// +y
faceUvVectors[3][0] = vec3(1.0, 0.0, 0.0); // u -> +x
faceUvVectors[3][1] = vec3(0.0, 0.0, 1.0); // v -> +z
faceUvVectors[3][2] = vec3(0.0, 1.0, 0.0); // +y face
// -z
faceUvVectors[4][0] = vec3(-1.0, 0.0, 0.0); // u -> -x
faceUvVectors[4][1] = vec3(0.0, -1.0, 0.0); // v -> -y
faceUvVectors[4][2] = vec3(0.0, 0.0, -1.0); // -z face
// +z
faceUvVectors[5][0] = vec3(1.0, 0.0, 0.0); // u -> +x
faceUvVectors[5][1] = vec3(0.0, -1.0, 0.0); // v -> -y
faceUvVectors[5][2] = vec3(0.0, 0.0, 1.0); // +z face
// out = u * s_faceUv[0] + v * s_faceUv[1] + s_faceUv[2].
vec3 result = (faceUvVectors[faceID][0] * uv.x) + (faceUvVectors[faceID][1] * uv.y) + faceUvVectors[faceID][2];
return normalize(result);
}
vec3 ImportanceSampleGGX(vec2 Xi, float Roughness, vec3 N) {
float a = Roughness * Roughness; // DISNEY'S ROUGHNESS [see Burley'12 siggraph]
// Compute distribution direction
@ -136,159 +135,53 @@ vec3 ImportanceSampleGGX(vec2 Xi, float Roughness, vec3 N)
return TangentX * H.x + TangentY * H.y + N * H.z;
}
// http://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html
float GGX(float NdotV, float a)
{
float k = a / 2.0;
return NdotV / (NdotV * (1.0 - k) + k);
float radical_inverse_VdC(int i) {
return texture2D(radical_inverse_vdc_cache, vec2(float(i) / 512.0, 0.0)).x;
}
// http://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html
float G_Smith(float a, float nDotV, float nDotL)
{
return GGX(nDotL, a * a) * GGX(nDotV, a * a);
vec2 Hammersley(int i, int N) {
return vec2(float(i) / float(N), radical_inverse_VdC(i));
}
float radicalInverse_VdC(uint bits) {
bits = (bits << 16u) | (bits >> 16u);
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
return float(bits) * 2.3283064365386963e-10; // / 0x100000000
}
vec2 Hammersley(uint i, uint N) {
return vec2(float(i)/float(N), radicalInverse_VdC(i));
}
#ifdef LOW_QUALITY
#define SAMPLE_COUNT 64u
#else
#define SAMPLE_COUNT 512u
#endif
uniform bool z_flip;
#ifdef USE_SOURCE_PANORAMA
vec4 texturePanorama(vec3 normal,sampler2D pano ) {
vec2 st = vec2(
atan(normal.x, normal.z),
acos(normal.y)
);
if(st.x < 0.0)
st.x += M_PI*2.0;
st/=vec2(M_PI*2.0,M_PI);
return textureLod(pano,st,0.0);
}
#endif
#ifdef USE_SOURCE_DUAL_PARABOLOID_ARRAY
vec4 textureDualParaboloidArray(vec3 normal) {
vec3 norm = normalize(normal);
norm.xy/=1.0+abs(norm.z);
norm.xy=norm.xy * vec2(0.5,0.25) + vec2(0.5,0.25);
if (norm.z<0.0) {
norm.y=0.5-norm.y+0.5;
}
return textureLod(source_dual_paraboloid_array, vec3(norm.xy, float(source_array_index) ), 0.0);
}
#endif
void main() {
#ifdef USE_DUAL_PARABOLOID
vec3 color = vec3(0.0);
vec3 N = vec3( uv_interp * 2.0 - 1.0, 0.0 );
N.z = 0.5 - 0.5*((N.x * N.x) + (N.y * N.y));
N = normalize(N);
vec2 uv = (uv_interp * 2.0) - 1.0;
vec3 N = texelCoordToVec(uv, face_id);
if (z_flip) {
N.y=-N.y; //y is flipped to improve blending between both sides
N.z=-N.z;
}
vec4 sum = vec4(0.0);
for (int sample_num = 0; sample_num < SAMPLE_COUNT; sample_num++) {
#else
vec2 uv = (uv_interp * 2.0) - 1.0;
vec3 N = texelCoordToVec(uv, face_id);
#endif
//vec4 color = color_interp;
vec2 xi = Hammersley(sample_num, SAMPLE_COUNT);
#ifdef USE_DIRECT_WRITE
vec3 H = ImportanceSampleGGX(xi, roughness, N);
vec3 V = N;
vec3 L = normalize(2.0 * dot(V, H) * H - V);
float NdotL = clamp(dot(N, L), 0.0, 1.0);
if (NdotL > 0.0) {
#ifdef USE_SOURCE_PANORAMA
frag_color=vec4(texturePanorama(N,source_panorama).rgb,1.0);
#endif
#ifdef USE_SOURCE_DUAL_PARABOLOID_ARRAY
frag_color=vec4(textureDualParaboloidArray(N).rgb,1.0);
#endif
#if !defined(USE_SOURCE_DUAL_PARABOLOID_ARRAY) && !defined(USE_SOURCE_PANORAMA)
N.y=-N.y;
frag_color=vec4(texture(N,source_cube).rgb,1.0);
#endif
sum.rgb += texturePanorama(source_panorama, H).rgb * NdotL;
#else
vec4 sum = vec4(0.0, 0.0, 0.0, 0.0);
for(uint sampleNum = 0u; sampleNum < SAMPLE_COUNT; sampleNum++) {
vec2 xi = Hammersley(sampleNum, SAMPLE_COUNT);
vec3 H = ImportanceSampleGGX( xi, roughness, N );
vec3 V = N;
vec3 L = normalize(2.0 * dot( V, H ) * H - V);
float ndotl = clamp(dot(N, L),0.0,1.0);
if (ndotl>0.0) {
#ifdef USE_SOURCE_PANORAMA
sum.rgb += texturePanorama(H,source_panorama).rgb *ndotl;
H.y = -H.y;
sum.rgb += textureCubeLod(source_cube, H, 0.0).rgb * NdotL;
#endif
#ifdef USE_SOURCE_DUAL_PARABOLOID_ARRAY
sum.a += NdotL;
sum.rgb += textureDualParaboloidArray(H).rgb *ndotl;
#endif
#if !defined(USE_SOURCE_DUAL_PARABOLOID_ARRAY) && !defined(USE_SOURCE_PANORAMA)
H.y=-H.y;
sum.rgb += textureLod(source_cube, H, 0.0).rgb *ndotl;
#endif
sum.a += ndotl;
}
}
sum /= sum.a;
frag_color = vec4(sum.rgb, 1.0);
#endif
gl_FragColor = vec4(sum.rgb, 1.0);
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,45 @@
vec2 select2(vec2 a, vec2 b, bvec2 c)
{
vec2 ret;
ret.x = c.x ? b.x : a.x;
ret.y = c.y ? b.y : a.y;
return ret;
}
vec3 select3(vec3 a, vec3 b, bvec3 c)
{
vec3 ret;
ret.x = c.x ? b.x : a.x;
ret.y = c.y ? b.y : a.y;
ret.z = c.z ? b.z : a.z;
return ret;
}
vec4 select4(vec4 a, vec4 b, bvec4 c)
{
vec4 ret;
ret.x = c.x ? b.x : a.x;
ret.y = c.y ? b.y : a.y;
ret.z = c.z ? b.z : a.z;
ret.w = c.w ? b.w : a.w;
return ret;
}
highp vec4 texel2DFetch(highp sampler2D tex, ivec2 size, ivec2 coord)
{
float x_coord = float(2 * coord.x + 1) / float(size.x * 2);
float y_coord = float(2 * coord.y + 1) / float(size.y * 2);
x_coord = float(coord.x) / float(size.x);
y_coord = float(coord.y) / float(size.y);
return texture2DLod(tex, vec2(x_coord, y_coord), 0.0);
}

View file

@ -259,6 +259,7 @@ def build_legacygl_header(filename, include, class_suffix, output_attribs, gles2
fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, int32_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); }\n\n")
fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Color& p_color) { _FU GLfloat col[4]={p_color.r,p_color.g,p_color.b,p_color.a}; glUniform4fv(get_uniform(p_uniform),1,col); }\n\n")
fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Vector2& p_vec2) { _FU GLfloat vec2[2]={p_vec2.x,p_vec2.y}; glUniform2fv(get_uniform(p_uniform),1,vec2); }\n\n")
fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Size2i& p_vec2) { _FU GLint vec2[2]={p_vec2.x,p_vec2.y}; glUniform2iv(get_uniform(p_uniform),1,vec2); }\n\n")
fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Vector3& p_vec3) { _FU GLfloat vec3[3]={p_vec3.x,p_vec3.y,p_vec3.z}; glUniform3fv(get_uniform(p_uniform),1,vec3); }\n\n")
fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, float p_a, float p_b) { _FU glUniform2f(get_uniform(p_uniform),p_a,p_b); }\n\n")
fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, float p_a, float p_b, float p_c) { _FU glUniform3f(get_uniform(p_uniform),p_a,p_b,p_c); }\n\n")