diff options
Diffstat (limited to 'drivers/gles3')
23 files changed, 2210 insertions, 1024 deletions
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index c9bdc6f5c3..edffe852a2 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -146,10 +146,15 @@ void RasterizerCanvasGLES3::canvas_begin() { if (storage->frame.current_rt && storage->frame.clear_request) { // a clear request may be pending, so do it + bool transparent = storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]; - glClearColor(storage->frame.clear_request_color.r, storage->frame.clear_request_color.g, storage->frame.clear_request_color.b, storage->frame.clear_request_color.a); + glClearColor(storage->frame.clear_request_color.r, + storage->frame.clear_request_color.g, + storage->frame.clear_request_color.b, + transparent ? storage->frame.clear_request_color.a : 1.0); glClear(GL_COLOR_BUFFER_BIT); storage->frame.clear_request = false; + glColorMask(1, 1, 1, transparent ? 1 : 0); } reset_canvas(); @@ -158,7 +163,10 @@ void RasterizerCanvasGLES3::canvas_begin() { state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_LIGHTING, false); state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_SHADOWS, false); state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_NEAREST, false); + state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF3, false); state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF5, false); + state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF7, false); + state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF9, false); state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF13, false); state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_DISTANCE_FIELD, false); state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_NINEPATCH, false); @@ -190,6 +198,9 @@ void RasterizerCanvasGLES3::canvas_end() { glBindVertexArray(0); glBindBufferBase(GL_UNIFORM_BUFFER, 0, 0); + glColorMask(1, 1, 1, 1); + + glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1); state.using_texture_rect = false; state.using_ninepatch = false; @@ -259,6 +270,7 @@ RasterizerStorageGLES3::Texture *RasterizerCanvasGLES3::_bind_canvas_texture(con } normal_map = normal_map->get_ptr(); + glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, normal_map->tex_id); state.current_normal = p_normal_map; @@ -317,12 +329,9 @@ void RasterizerCanvasGLES3::_draw_polygon(const int *p_indices, int p_index_coun uint32_t buffer_ofs = 0; //vertex -#ifdef DEBUG_ENABLED - ERR_FAIL_COND(buffer_ofs > data.polygon_buffer_size); -#endif glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_vertices); glEnableVertexAttribArray(VS::ARRAY_VERTEX); - glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, false, sizeof(Vector2), ((uint8_t *)0) + buffer_ofs); + glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, false, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buffer_ofs)); buffer_ofs += sizeof(Vector2) * p_vertex_count; //color #ifdef DEBUG_ENABLED @@ -340,7 +349,7 @@ void RasterizerCanvasGLES3::_draw_polygon(const int *p_indices, int p_index_coun glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Color) * p_vertex_count, p_colors); glEnableVertexAttribArray(VS::ARRAY_COLOR); - glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, false, sizeof(Color), ((uint8_t *)0) + buffer_ofs); + glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, false, sizeof(Color), CAST_INT_TO_UCHAR_PTR(buffer_ofs)); buffer_ofs += sizeof(Color) * p_vertex_count; } @@ -352,7 +361,7 @@ void RasterizerCanvasGLES3::_draw_polygon(const int *p_indices, int p_index_coun glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_uvs); glEnableVertexAttribArray(VS::ARRAY_TEX_UV); - glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, false, sizeof(Vector2), ((uint8_t *)0) + buffer_ofs); + glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, false, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buffer_ofs)); buffer_ofs += sizeof(Vector2) * p_vertex_count; } else { @@ -368,12 +377,12 @@ void RasterizerCanvasGLES3::_draw_polygon(const int *p_indices, int p_index_coun glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(int) * 4 * p_vertex_count, p_bones); glEnableVertexAttribArray(VS::ARRAY_BONES); //glVertexAttribPointer(VS::ARRAY_BONES, 4, GL_UNSIGNED_INT, false, sizeof(int) * 4, ((uint8_t *)0) + buffer_ofs); - glVertexAttribIPointer(VS::ARRAY_BONES, 4, GL_UNSIGNED_INT, sizeof(int) * 4, ((uint8_t *)0) + buffer_ofs); + glVertexAttribIPointer(VS::ARRAY_BONES, 4, GL_UNSIGNED_INT, sizeof(int) * 4, CAST_INT_TO_UCHAR_PTR(buffer_ofs)); buffer_ofs += sizeof(int) * 4 * p_vertex_count; glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(float) * 4 * p_vertex_count, p_weights); glEnableVertexAttribArray(VS::ARRAY_WEIGHTS); - glVertexAttribPointer(VS::ARRAY_WEIGHTS, 4, GL_FLOAT, false, sizeof(float) * 4, ((uint8_t *)0) + buffer_ofs); + glVertexAttribPointer(VS::ARRAY_WEIGHTS, 4, GL_FLOAT, false, sizeof(float) * 4, CAST_INT_TO_UCHAR_PTR(buffer_ofs)); buffer_ofs += sizeof(float) * 4 * p_vertex_count; } else if (state.using_skeleton) { @@ -413,7 +422,7 @@ void RasterizerCanvasGLES3::_draw_generic(GLuint p_primitive, int p_vertex_count //vertex glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_vertices); glEnableVertexAttribArray(VS::ARRAY_VERTEX); - glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, false, sizeof(Vector2), ((uint8_t *)0) + buffer_ofs); + glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, false, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buffer_ofs)); buffer_ofs += sizeof(Vector2) * p_vertex_count; //color @@ -428,7 +437,7 @@ void RasterizerCanvasGLES3::_draw_generic(GLuint p_primitive, int p_vertex_count glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Color) * p_vertex_count, p_colors); glEnableVertexAttribArray(VS::ARRAY_COLOR); - glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, false, sizeof(Color), ((uint8_t *)0) + buffer_ofs); + glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, false, sizeof(Color), CAST_INT_TO_UCHAR_PTR(buffer_ofs)); buffer_ofs += sizeof(Color) * p_vertex_count; } @@ -436,7 +445,7 @@ void RasterizerCanvasGLES3::_draw_generic(GLuint p_primitive, int p_vertex_count glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_uvs); glEnableVertexAttribArray(VS::ARRAY_TEX_UV); - glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, false, sizeof(Vector2), ((uint8_t *)0) + buffer_ofs); + glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, false, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buffer_ofs)); buffer_ofs += sizeof(Vector2) * p_vertex_count; } else { @@ -571,10 +580,10 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur #ifdef GLES_OVER_GL if (line->antialiased) { glEnable(GL_LINE_SMOOTH); - for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { Vector2 vertsl[2] = { - verts[i], - verts[(i + 1) % 4], + verts[j], + verts[(j + 1) % 4], }; _draw_gui_primitive(2, vertsl, NULL, NULL); } @@ -684,7 +693,7 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur state.canvas_shader.set_uniform(CanvasShaderGLES3::DST_RECT, Color(dst_rect.position.x, dst_rect.position.y, dst_rect.size.x, dst_rect.size.y)); state.canvas_shader.set_uniform(CanvasShaderGLES3::SRC_RECT, Color(src_rect.position.x, src_rect.position.y, src_rect.size.x, src_rect.size.y)); - state.canvas_shader.set_uniform(CanvasShaderGLES3::CLIP_RECT_UV, (rect->flags & CANVAS_RECT_CLIP_UV) ? true : false); + state.canvas_shader.set_uniform(CanvasShaderGLES3::CLIP_RECT_UV, rect->flags & CANVAS_RECT_CLIP_UV); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); @@ -772,8 +781,8 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur } if (primitive->colors.size() == 1 && primitive->points.size() > 1) { - Color c = primitive->colors[0]; - glVertexAttrib4f(VS::ARRAY_COLOR, c.r, c.g, c.b, c.a); + Color col = primitive->colors[0]; + glVertexAttrib4f(VS::ARRAY_COLOR, col.r, col.g, col.b, col.a); } else if (primitive->colors.empty()) { glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1); @@ -816,6 +825,8 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, texpixel_size); } + state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX, state.final_transform * mesh->transform); + RasterizerStorageGLES3::Mesh *mesh_data = storage->mesh_owner.getornull(mesh->mesh); if (mesh_data) { @@ -824,6 +835,8 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur // materials are ignored in 2D meshes, could be added but many things (ie, lighting mode, reading from screen, etc) would break as they are not meant be set up at this point of drawing glBindVertexArray(s->array_id); + glVertexAttrib4f(VS::ARRAY_COLOR, mesh->modulate.r, mesh->modulate.g, mesh->modulate.b, mesh->modulate.a); + if (s->index_array_len) { glDrawElements(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0); } else { @@ -833,6 +846,8 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur glBindVertexArray(0); } } + state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX, state.final_transform); + } break; case Item::Command::TYPE_MULTIMESH: { @@ -861,7 +876,11 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, texpixel_size); } - int amount = MAX(multi_mesh->size, multi_mesh->visible_instances); + int amount = MIN(multi_mesh->size, multi_mesh->visible_instances); + + if (amount == -1) { + amount = multi_mesh->size; + } for (int j = 0; j < mesh_data->surfaces.size(); j++) { RasterizerStorageGLES3::Surface *s = mesh_data->surfaces[j]; @@ -872,17 +891,17 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur int stride = (multi_mesh->xform_floats + multi_mesh->color_floats + multi_mesh->custom_data_floats) * 4; glEnableVertexAttribArray(8); - glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + 0); + glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(0)); glVertexAttribDivisor(8, 1); glEnableVertexAttribArray(9); - glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + 4 * 4); + glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(4 * 4)); glVertexAttribDivisor(9, 1); int color_ofs; if (multi_mesh->transform_format == VS::MULTIMESH_TRANSFORM_3D) { glEnableVertexAttribArray(10); - glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + 8 * 4); + glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(8 * 4)); glVertexAttribDivisor(10, 1); color_ofs = 12 * 4; } else { @@ -901,14 +920,14 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur } break; case VS::MULTIMESH_COLOR_8BIT: { glEnableVertexAttribArray(11); - glVertexAttribPointer(11, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, ((uint8_t *)NULL) + color_ofs); + glVertexAttribPointer(11, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, CAST_INT_TO_UCHAR_PTR(color_ofs)); glVertexAttribDivisor(11, 1); custom_data_ofs += 4; } break; case VS::MULTIMESH_COLOR_FLOAT: { glEnableVertexAttribArray(11); - glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + color_ofs); + glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(color_ofs)); glVertexAttribDivisor(11, 1); custom_data_ofs += 4 * 4; } break; @@ -922,13 +941,13 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur } break; case VS::MULTIMESH_CUSTOM_DATA_8BIT: { glEnableVertexAttribArray(12); - glVertexAttribPointer(12, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, ((uint8_t *)NULL) + custom_data_ofs); + glVertexAttribPointer(12, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, CAST_INT_TO_UCHAR_PTR(custom_data_ofs)); glVertexAttribDivisor(12, 1); } break; case VS::MULTIMESH_CUSTOM_DATA_FLOAT: { glEnableVertexAttribArray(12); - glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + custom_data_ofs); + glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(custom_data_ofs)); glVertexAttribDivisor(12, 1); } break; } @@ -976,7 +995,7 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur RasterizerStorageGLES3::Texture *texture = _bind_canvas_texture(particles_cmd->texture, particles_cmd->normal_map); if (texture) { - Size2 texpixel_size(1.0 / (texture->width / particles_cmd->h_frames), 1.0 / (texture->height / particles_cmd->v_frames)); + Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height); state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, texpixel_size); } else { state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, Vector2(1.0, 1.0)); @@ -993,9 +1012,6 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX, state.final_transform * inv_xf); } - state.canvas_shader.set_uniform(CanvasShaderGLES3::H_FRAMES, particles_cmd->h_frames); - state.canvas_shader.set_uniform(CanvasShaderGLES3::V_FRAMES, particles_cmd->v_frames); - glBindVertexArray(data.particle_quad_array); //use particle quad array glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffers[0]); //bind particle buffer @@ -1006,43 +1022,41 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur if (particles->draw_order != VS::PARTICLES_DRAW_ORDER_LIFETIME) { glEnableVertexAttribArray(8); //xform x - glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 3); + glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 3)); glVertexAttribDivisor(8, 1); glEnableVertexAttribArray(9); //xform y - glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 4); + glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 4)); glVertexAttribDivisor(9, 1); glEnableVertexAttribArray(10); //xform z - glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 5); + glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 5)); glVertexAttribDivisor(10, 1); glEnableVertexAttribArray(11); //color - glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + 0); + glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, NULL); glVertexAttribDivisor(11, 1); glEnableVertexAttribArray(12); //custom - glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 2); + glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 2)); glVertexAttribDivisor(12, 1); glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, amount); } else { //split - - int stride = sizeof(float) * 4 * 6; int split = int(Math::ceil(particles->phase * particles->amount)); if (amount - split > 0) { glEnableVertexAttribArray(8); //xform x - glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + stride * split + sizeof(float) * 4 * 3); + glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + sizeof(float) * 4 * 3)); glVertexAttribDivisor(8, 1); glEnableVertexAttribArray(9); //xform y - glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + stride * split + sizeof(float) * 4 * 4); + glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + sizeof(float) * 4 * 4)); glVertexAttribDivisor(9, 1); glEnableVertexAttribArray(10); //xform z - glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + stride * split + sizeof(float) * 4 * 5); + glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + sizeof(float) * 4 * 5)); glVertexAttribDivisor(10, 1); glEnableVertexAttribArray(11); //color - glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + stride * split + 0); + glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + 0)); glVertexAttribDivisor(11, 1); glEnableVertexAttribArray(12); //custom - glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + stride * split + sizeof(float) * 4 * 2); + glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + sizeof(float) * 4 * 2)); glVertexAttribDivisor(12, 1); glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, amount - split); @@ -1050,19 +1064,19 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur if (split > 0) { glEnableVertexAttribArray(8); //xform x - glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 3); + glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 3)); glVertexAttribDivisor(8, 1); glEnableVertexAttribArray(9); //xform y - glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 4); + glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 4)); glVertexAttribDivisor(9, 1); glEnableVertexAttribArray(10); //xform z - glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 5); + glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 5)); glVertexAttribDivisor(10, 1); glEnableVertexAttribArray(11); //color - glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + 0); + glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, NULL); glVertexAttribDivisor(11, 1); glEnableVertexAttribArray(12); //custom - glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 2); + glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 2)); glVertexAttribDivisor(12, 1); glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, split); @@ -1072,8 +1086,8 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur glBindVertexArray(0); state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCE_CUSTOM, false); - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCING, false); state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_PARTICLES, false); + state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCING, false); state.using_texture_rect = true; _set_texture_rect_mode(false); @@ -1088,12 +1102,12 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur points[numpoints] = circle->pos; int indices[numpoints * 3]; - for (int i = 0; i < numpoints; i++) { + for (int j = 0; j < numpoints; j++) { - points[i] = circle->pos + Vector2(Math::sin(i * Math_PI * 2.0 / numpoints), Math::cos(i * Math_PI * 2.0 / numpoints)) * circle->radius; - indices[i * 3 + 0] = i; - indices[i * 3 + 1] = (i + 1) % numpoints; - indices[i * 3 + 2] = numpoints; + points[j] = circle->pos + Vector2(Math::sin(j * Math_PI * 2.0 / numpoints), Math::cos(j * Math_PI * 2.0 / numpoints)) * circle->radius; + indices[j * 3 + 0] = j; + indices[j * 3 + 1] = (j + 1) % numpoints; + indices[j * 3 + 2] = numpoints; } _bind_canvas_texture(RID(), RID()); @@ -1142,6 +1156,8 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur void RasterizerCanvasGLES3::_copy_texscreen(const Rect2 &p_rect) { + ERR_FAIL_COND_MSG(storage->frame.current_rt->effects.mip_maps[0].sizes.size() == 0, "Can't use screen texture copying in a render target configured without copy buffers."); + glDisable(GL_BLEND); state.canvas_texscreen_used = true; @@ -1223,10 +1239,6 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons bool rebind_shader = true; - Size2 rt_size = Size2(storage->frame.current_rt->width, storage->frame.current_rt->height); - - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_DISTANCE_FIELD, false); - glBindBuffer(GL_UNIFORM_BUFFER, state.canvas_item_ubo); glBufferData(GL_UNIFORM_BUFFER, sizeof(CanvasItemUBO), &state.canvas_item_ubo_data, GL_DYNAMIC_DRAW); glBindBuffer(GL_UNIFORM_BUFFER, 0); @@ -1310,6 +1322,8 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 1); glBindTexture(GL_TEXTURE_2D, skeleton->texture); state.using_skeleton = true; + state.canvas_shader.set_uniform(CanvasShaderGLES3::SKELETON_TRANSFORM, state.skeleton_transform); + state.canvas_shader.set_uniform(CanvasShaderGLES3::SKELETON_TRANSFORM_INVERSE, state.skeleton_transform_inverse); } else { state.using_skeleton = false; } @@ -1344,7 +1358,7 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons last_blend_mode = last_blend_mode != RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_DISABLED ? last_blend_mode : -1; } - if (shader_ptr != shader_cache) { + if (shader_ptr != shader_cache || rebind_shader) { if (shader_ptr->canvas_item.uses_time) { VisualServerRaster::redraw_request(); @@ -1555,15 +1569,12 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_SHADOWS, has_shadow); if (has_shadow) { state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_USE_GRADIENT, light->shadow_gradient_length > 0); - switch (light->shadow_filter) { - - case VS::CANVAS_LIGHT_FILTER_NONE: state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_NEAREST, true); break; - case VS::CANVAS_LIGHT_FILTER_PCF3: state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF3, true); break; - case VS::CANVAS_LIGHT_FILTER_PCF5: state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF5, true); break; - case VS::CANVAS_LIGHT_FILTER_PCF7: state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF7, true); break; - case VS::CANVAS_LIGHT_FILTER_PCF9: state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF9, true); break; - case VS::CANVAS_LIGHT_FILTER_PCF13: state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF13, true); break; - } + state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_NEAREST, light->shadow_filter == VS::CANVAS_LIGHT_FILTER_NONE); + state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF3, light->shadow_filter == VS::CANVAS_LIGHT_FILTER_PCF3); + state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF5, light->shadow_filter == VS::CANVAS_LIGHT_FILTER_PCF5); + state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF7, light->shadow_filter == VS::CANVAS_LIGHT_FILTER_PCF7); + state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF9, light->shadow_filter == VS::CANVAS_LIGHT_FILTER_PCF9); + state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF13, light->shadow_filter == VS::CANVAS_LIGHT_FILTER_PCF13); } bool light_rebind = state.canvas_shader.bind(); @@ -1573,6 +1584,11 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons state.canvas_shader.set_uniform(CanvasShaderGLES3::FINAL_MODULATE, state.canvas_item_modulate); state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX, state.final_transform); state.canvas_shader.set_uniform(CanvasShaderGLES3::EXTRA_MATRIX, Transform2D()); + if (storage->frame.current_rt) { + state.canvas_shader.set_uniform(CanvasShaderGLES3::SCREEN_PIXEL_SIZE, Vector2(1.0 / storage->frame.current_rt->width, 1.0 / storage->frame.current_rt->height)); + } else { + state.canvas_shader.set_uniform(CanvasShaderGLES3::SCREEN_PIXEL_SIZE, Vector2(1.0, 1.0)); + } } glBindBufferBase(GL_UNIFORM_BUFFER, 1, static_cast<LightInternal *>(light->light_internal.get_data())->ubo); @@ -1661,6 +1677,14 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons if (current_clip) { glDisable(GL_SCISSOR_TEST); } + //disable states that may have been used + state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_DISTANCE_FIELD, false); + state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_SKELETON, false); + state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCE_CUSTOM, false); + state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_PARTICLES, false); + state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCING, false); + state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_LIGHTING, false); + state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_SHADOWS, false); } void RasterizerCanvasGLES3::canvas_debug_viewport_shadows(Light *p_lights_with_shadow) { @@ -1687,6 +1711,8 @@ void RasterizerCanvasGLES3::canvas_debug_viewport_shadows(Light *p_lights_with_s light = light->shadows_next_ptr; } + + canvas_end(); } void RasterizerCanvasGLES3::canvas_light_shadow_buffer_update(RID p_buffer, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders, CameraMatrix *p_xform_cache) { @@ -1871,13 +1897,46 @@ void RasterizerCanvasGLES3::draw_generic_textured_rect(const Rect2 &p_rect, cons glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } +void RasterizerCanvasGLES3::draw_lens_distortion_rect(const Rect2 &p_rect, float p_k1, float p_k2, const Vector2 &p_eye_center, float p_oversample) { + Vector2 half_size; + if (storage->frame.current_rt) { + half_size = Vector2(storage->frame.current_rt->width, storage->frame.current_rt->height); + } else { + half_size = OS::get_singleton()->get_window_size(); + } + half_size *= 0.5; + Vector2 offset((p_rect.position.x - half_size.x) / half_size.x, (p_rect.position.y - half_size.y) / half_size.y); + Vector2 scale(p_rect.size.x / half_size.x, p_rect.size.y / half_size.y); + + float aspect_ratio = p_rect.size.x / p_rect.size.y; + + // setup our lens shader + state.lens_shader.bind(); + state.lens_shader.set_uniform(LensDistortedShaderGLES3::OFFSET, offset); + state.lens_shader.set_uniform(LensDistortedShaderGLES3::SCALE, scale); + state.lens_shader.set_uniform(LensDistortedShaderGLES3::K1, p_k1); + state.lens_shader.set_uniform(LensDistortedShaderGLES3::K2, p_k2); + state.lens_shader.set_uniform(LensDistortedShaderGLES3::EYE_CENTER, p_eye_center); + state.lens_shader.set_uniform(LensDistortedShaderGLES3::UPSCALE, p_oversample); + state.lens_shader.set_uniform(LensDistortedShaderGLES3::ASPECT_RATIO, aspect_ratio); + + glBindBufferBase(GL_UNIFORM_BUFFER, 0, state.canvas_item_ubo); + glBindVertexArray(data.canvas_quad_array); + + // and draw + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + glBindVertexArray(0); + glBindBufferBase(GL_UNIFORM_BUFFER, 0, 0); +} + void RasterizerCanvasGLES3::draw_window_margins(int *black_margin, RID *black_image) { Vector2 window_size = OS::get_singleton()->get_window_size(); int window_h = window_size.height; int window_w = window_size.width; - glBindFramebuffer(GL_FRAMEBUFFER, storage->system_fbo); + glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo); glViewport(0, 0, window_size.width, window_size.height); canvas_begin(); @@ -1989,13 +2048,14 @@ void RasterizerCanvasGLES3::initialize() { glEnableVertexAttribArray(VS::ARRAY_VERTEX); glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, 0); glEnableVertexAttribArray(VS::ARRAY_TEX_UV); - glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, (float *)0 + 2); + glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, CAST_INT_TO_UCHAR_PTR(8)); glBindVertexArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind } { uint32_t poly_size = GLOBAL_DEF_RST("rendering/limits/buffers/canvas_polygon_buffer_size_kb", 128); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/buffers/canvas_polygon_buffer_size_kb", PropertyInfo(Variant::INT, "rendering/limits/buffers/canvas_polygon_buffer_size_kb", PROPERTY_HINT_RANGE, "0,256,1,or_greater")); poly_size *= 1024; //kb poly_size = MAX(poly_size, (2 + 2 + 4) * 4 * sizeof(float)); glGenBuffers(1, &data.polygon_buffer); @@ -2025,16 +2085,16 @@ void RasterizerCanvasGLES3::initialize() { } glEnableVertexAttribArray(VS::ARRAY_VERTEX); - glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + 0); + glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, stride, NULL); if (i & 1) { glEnableVertexAttribArray(VS::ARRAY_COLOR); - glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + color_ofs); + glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(color_ofs)); } if (i & 2) { glEnableVertexAttribArray(VS::ARRAY_TEX_UV); - glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + uv_ofs); + glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(uv_ofs)); } glBindVertexArray(0); @@ -2043,6 +2103,7 @@ void RasterizerCanvasGLES3::initialize() { glGenVertexArrays(1, &data.polygon_buffer_pointer_array); uint32_t index_size = GLOBAL_DEF_RST("rendering/limits/buffers/canvas_polygon_index_buffer_size_kb", 128); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/buffers/canvas_polygon_index_buffer_size_kb", PropertyInfo(Variant::INT, "rendering/limits/buffers/canvas_polygon_index_buffer_size_kb", PROPERTY_HINT_RANGE, "0,256,1,or_greater")); index_size *= 1024; //kb glGenBuffers(1, &data.polygon_index_buffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer); @@ -2060,6 +2121,7 @@ void RasterizerCanvasGLES3::initialize() { state.canvas_shader.init(); state.canvas_shader.set_base_material_tex_index(2); state.canvas_shadow_shader.init(); + state.lens_shader.init(); state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_RGBA_SHADOWS, storage->config.use_rgba_2d_shadows); state.canvas_shadow_shader.set_conditional(CanvasShadowShaderGLES3::USE_RGBA_SHADOWS, storage->config.use_rgba_2d_shadows); diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h index bc4ea80328..bf5ef30820 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.h +++ b/drivers/gles3/rasterizer_canvas_gles3.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -35,6 +35,7 @@ #include "servers/visual/rasterizer.h" #include "shaders/canvas_shadow.glsl.gen.h" +#include "shaders/lens_distorted.glsl.gen.h" class RasterizerSceneGLES3; @@ -72,6 +73,7 @@ public: bool canvas_texscreen_used; CanvasShaderGLES3 canvas_shader; CanvasShadowShaderGLES3 canvas_shadow_shader; + LensDistortedShaderGLES3 lens_shader; bool using_texture_rect; bool using_ninepatch; @@ -141,6 +143,7 @@ public: virtual void reset_canvas(); void draw_generic_textured_rect(const Rect2 &p_rect, const Rect2 &p_src); + void draw_lens_distortion_rect(const Rect2 &p_rect, float p_k1, float p_k2, const Vector2 &p_eye_center, float p_oversample); void initialize(); void finalize(); diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index d3f6dcd497..ea15a278d6 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,7 +32,6 @@ #include "core/os/os.h" #include "core/project_settings.h" -#include "gl_context/context_gl.h" RasterizerStorage *RasterizerGLES3::get_storage() { @@ -73,12 +72,12 @@ RasterizerScene *RasterizerGLES3::get_scene() { #define _EXT_DEBUG_SEVERITY_LOW_ARB 0x9148 #define _EXT_DEBUG_OUTPUT 0x92E0 -#if (defined WINDOWS_ENABLED) && !(defined UWP_ENABLED) -#define GLAPIENTRY APIENTRY -#else -#define GLAPIENTRY +#if defined(MINGW_ENABLED) || defined(_MSC_VER) +#define strcpy strcpy_s #endif +#ifdef GLAD_ENABLED +// Restricting to GLAD as only used in initialize() with GLAD_GL_ARB_debug_output static void GLAPIENTRY _gl_debug_print(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const GLvoid *userParam) { if (type == _EXT_DEBUG_TYPE_OTHER_ARB) @@ -123,6 +122,7 @@ static void GLAPIENTRY _gl_debug_print(GLenum source, GLenum type, GLuint id, GL ERR_PRINTS(output); } +#endif // GLAD_ENABLED typedef void (*DEBUGPROCARB)(GLenum source, GLenum type, @@ -252,11 +252,16 @@ void RasterizerGLES3::set_current_render_target(RID p_render_target) { } } -void RasterizerGLES3::restore_render_target() { +void RasterizerGLES3::restore_render_target(bool p_3d_was_drawn) { ERR_FAIL_COND(storage->frame.current_rt == NULL); RasterizerStorageGLES3::RenderTarget *rt = storage->frame.current_rt; - glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo); + if (p_3d_was_drawn && rt->external.fbo != 0) { + // our external render buffer is now leading, render 2d into that. + glBindFramebuffer(GL_FRAMEBUFFER, rt->external.fbo); + } else { + glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo); + } glViewport(0, 0, rt->width, rt->height); } @@ -268,7 +273,7 @@ void RasterizerGLES3::clear_render_target(const Color &p_color) { storage->frame.clear_request_color = p_color; } -void RasterizerGLES3::set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale) { +void RasterizerGLES3::set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter) { if (p_image.is_null() || p_image->empty()) return; @@ -291,7 +296,7 @@ void RasterizerGLES3::set_boot_image(const Ref<Image> &p_image, const Color &p_c canvas->canvas_begin(); RID texture = storage->texture_create(); - storage->texture_allocate(texture, p_image->get_width(), p_image->get_height(), 0, p_image->get_format(), VS::TEXTURE_TYPE_2D, VS::TEXTURE_FLAG_FILTER); + storage->texture_allocate(texture, p_image->get_width(), p_image->get_height(), 0, p_image->get_format(), VS::TEXTURE_TYPE_2D, p_use_filter ? VS::TEXTURE_FLAG_FILTER : 0); storage->texture_set_data(texture, p_image); Rect2 imgrect(0, 0, p_image->get_width(), p_image->get_height()); @@ -338,7 +343,11 @@ void RasterizerGLES3::blit_render_target_to_screen(RID p_render_target, const Re #if 1 Size2 win_size = OS::get_singleton()->get_window_size(); - glBindFramebuffer(GL_READ_FRAMEBUFFER, rt->fbo); + if (rt->external.fbo != 0) { + glBindFramebuffer(GL_READ_FRAMEBUFFER, rt->external.fbo); + } else { + glBindFramebuffer(GL_READ_FRAMEBUFFER, rt->fbo); + } glReadBuffer(GL_COLOR_ATTACHMENT0); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo); glBlitFramebuffer(0, 0, rt->width, rt->height, p_screen_rect.position.x, win_size.height - p_screen_rect.position.y - p_screen_rect.size.height, p_screen_rect.position.x + p_screen_rect.size.width, win_size.height - p_screen_rect.position.y, GL_COLOR_BUFFER_BIT, GL_NEAREST); @@ -359,6 +368,26 @@ void RasterizerGLES3::blit_render_target_to_screen(RID p_render_target, const Re #endif } +void RasterizerGLES3::output_lens_distorted_to_screen(RID p_render_target, const Rect2 &p_screen_rect, float p_k1, float p_k2, const Vector2 &p_eye_center, float p_oversample) { + ERR_FAIL_COND(storage->frame.current_rt); + + RasterizerStorageGLES3::RenderTarget *rt = storage->render_target_owner.getornull(p_render_target); + ERR_FAIL_COND(!rt); + + glDisable(GL_BLEND); + + // render to our framebuffer + glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo); + + // output our texture + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, rt->color); + + canvas->draw_lens_distortion_rect(p_screen_rect, p_k1, p_k2, p_eye_center, p_oversample); + + glBindTexture(GL_TEXTURE_2D, 0); +} + void RasterizerGLES3::end_frame(bool p_swap_buffers) { if (OS::get_singleton()->is_layered_allowed()) { @@ -405,10 +434,10 @@ void RasterizerGLES3::make_current() { void RasterizerGLES3::register_config() { - GLOBAL_DEF("rendering/quality/filters/use_nearest_mipmap_filter", false); GLOBAL_DEF("rendering/quality/filters/anisotropic_filter_level", 4); ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/filters/anisotropic_filter_level", PropertyInfo(Variant::INT, "rendering/quality/filters/anisotropic_filter_level", PROPERTY_HINT_RANGE, "1,16,1")); GLOBAL_DEF("rendering/limits/time/time_rollover_secs", 3600); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/time/time_rollover_secs", PropertyInfo(Variant::REAL, "rendering/limits/time/time_rollover_secs", PROPERTY_HINT_RANGE, "0,10000,1,or_greater")); } RasterizerGLES3::RasterizerGLES3() { diff --git a/drivers/gles3/rasterizer_gles3.h b/drivers/gles3/rasterizer_gles3.h index 0a264caf8f..8fa208a1aa 100644 --- a/drivers/gles3/rasterizer_gles3.h +++ b/drivers/gles3/rasterizer_gles3.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -51,14 +51,15 @@ public: virtual RasterizerCanvas *get_canvas(); virtual RasterizerScene *get_scene(); - virtual void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale); + virtual void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter = true); virtual void initialize(); virtual void begin_frame(double frame_step); virtual void set_current_render_target(RID p_render_target); - virtual void restore_render_target(); + virtual void restore_render_target(bool p_3d_was_drawn); virtual void clear_render_target(const Color &p_color); virtual void blit_render_target_to_screen(RID p_render_target, const Rect2 &p_screen_rect, int p_screen = 0); + virtual void output_lens_distorted_to_screen(RID p_render_target, const Rect2 &p_screen_rect, float p_k1, float p_k2, const Vector2 &p_eye_center, float p_oversample); virtual void end_frame(bool p_swap_buffers); virtual void finalize(); @@ -66,6 +67,8 @@ public: static void make_current(); static void register_config(); + virtual bool is_low_end() const { return false; } + RasterizerGLES3(); ~RasterizerGLES3(); }; diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 086829f9ba..35f414cf09 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -34,6 +34,7 @@ #include "core/os/os.h" #include "core/project_settings.h" #include "rasterizer_canvas_gles3.h" +#include "servers/camera/camera_feed.h" #include "servers/visual/visual_server_raster.h" #ifndef GLES_OVER_GL @@ -51,26 +52,6 @@ static const GLenum _cube_side_enum[6] = { }; -static _FORCE_INLINE_ void store_transform2d(const Transform2D &p_mtx, float *p_array) { - - p_array[0] = p_mtx.elements[0][0]; - p_array[1] = p_mtx.elements[0][1]; - p_array[2] = 0; - p_array[3] = 0; - p_array[4] = p_mtx.elements[1][0]; - p_array[5] = p_mtx.elements[1][1]; - p_array[6] = 0; - p_array[7] = 0; - p_array[8] = 0; - p_array[9] = 0; - p_array[10] = 1; - p_array[11] = 0; - p_array[12] = p_mtx.elements[2][0]; - p_array[13] = p_mtx.elements[2][1]; - p_array[14] = 0; - p_array[15] = 1; -} - static _FORCE_INLINE_ void store_transform(const Transform &p_mtx, float *p_array) { p_array[0] = p_mtx.basis.elements[0][0]; p_array[1] = p_mtx.basis.elements[1][0]; @@ -673,7 +654,7 @@ bool RasterizerSceneGLES3::reflection_probe_instance_begin_render(RID p_instance int best_free = -1; int best_used = -1; - uint64_t best_used_frame; + uint64_t best_used_frame = 0; for (int i = 0; i < reflection_atlas->reflections.size(); i++) { if (reflection_atlas->reflections[i].owner == RID()) { @@ -811,6 +792,14 @@ void RasterizerSceneGLES3::environment_set_sky_custom_fov(RID p_env, float p_sca env->sky_custom_fov = p_scale; } +void RasterizerSceneGLES3::environment_set_sky_orientation(RID p_env, const Basis &p_orientation) { + + Environment *env = environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + + env->sky_orientation = p_orientation; +} + void RasterizerSceneGLES3::environment_set_bg_color(RID p_env, const Color &p_color) { Environment *env = environment_owner.getornull(p_env); @@ -842,6 +831,12 @@ void RasterizerSceneGLES3::environment_set_ambient_light(RID p_env, const Color env->ambient_energy = p_energy; env->ambient_sky_contribution = p_sky_contribution; } +void RasterizerSceneGLES3::environment_set_camera_feed_id(RID p_env, int p_camera_feed_id) { + Environment *env = environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + + env->camera_feed_id = p_camera_feed_id; +} void RasterizerSceneGLES3::environment_set_dof_blur_far(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, VS::EnvironmentDOFBlurQuality p_quality) { @@ -866,7 +861,7 @@ void RasterizerSceneGLES3::environment_set_dof_blur_near(RID p_env, bool p_enabl env->dof_blur_near_amount = p_amount; env->dof_blur_near_quality = p_quality; } -void RasterizerSceneGLES3::environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_bloom_threshold, VS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, bool p_bicubic_upscale) { +void RasterizerSceneGLES3::environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_bloom_threshold, VS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, bool p_bicubic_upscale) { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND(!env); @@ -879,6 +874,7 @@ void RasterizerSceneGLES3::environment_set_glow(RID p_env, bool p_enable, int p_ env->glow_blend_mode = p_blend_mode; env->glow_hdr_bleed_threshold = p_hdr_bleed_threshold; env->glow_hdr_bleed_scale = p_hdr_bleed_scale; + env->glow_hdr_luminance_cap = p_hdr_luminance_cap; env->glow_bicubic_upscale = p_bicubic_upscale; } void RasterizerSceneGLES3::environment_set_fog(RID p_env, bool p_enable, float p_begin, float p_end, RID p_gradient_texture) { @@ -954,13 +950,14 @@ void RasterizerSceneGLES3::environment_set_fog(RID p_env, bool p_enable, const C env->fog_sun_amount = p_sun_amount; } -void RasterizerSceneGLES3::environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_curve, bool p_transmit, float p_transmit_curve) { +void RasterizerSceneGLES3::environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_end, float p_depth_curve, bool p_transmit, float p_transmit_curve) { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND(!env); env->fog_depth_enabled = p_enable; env->fog_depth_begin = p_depth_begin; + env->fog_depth_end = p_depth_end; env->fog_depth_curve = p_depth_curve; env->fog_transmit_enabled = p_transmit; env->fog_transmit_curve = p_transmit_curve; @@ -1011,7 +1008,7 @@ RID RasterizerSceneGLES3::light_instance_create(RID p_light) { if (!light_instance->light_ptr) { memdelete(light_instance); - ERR_FAIL_COND_V(!light_instance->light_ptr, RID()); + ERR_FAIL_V_MSG(RID(), "Condition ' !light_instance->light_ptr ' is true."); } light_instance->self = light_instance_owner.make_rid(light_instance); @@ -1071,12 +1068,11 @@ void RasterizerSceneGLES3::gi_probe_instance_set_light_data(RID p_probe, RID p_b if (p_data.is_valid()) { RasterizerStorageGLES3::GIProbeData *gipd = storage->gi_probe_data_owner.getornull(p_data); ERR_FAIL_COND(!gipd); - if (gipd) { - gipi->tex_cache = gipd->tex_id; - gipi->cell_size_cache.x = 1.0 / gipd->width; - gipi->cell_size_cache.y = 1.0 / gipd->height; - gipi->cell_size_cache.z = 1.0 / gipd->depth; - } + + gipi->tex_cache = gipd->tex_id; + gipi->cell_size_cache.x = 1.0 / gipd->width; + gipi->cell_size_cache.y = 1.0 / gipd->height; + gipi->cell_size_cache.z = 1.0 / gipd->depth; } } void RasterizerSceneGLES3::gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform) { @@ -1124,13 +1120,23 @@ bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material *p_m if (state.current_depth_draw != p_material->shader->spatial.depth_draw_mode) { switch (p_material->shader->spatial.depth_draw_mode) { - case RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS: + case RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS: { + glDepthMask(GL_TRUE); + // If some transparent objects write to depth, we need to re-copy depth texture when we need it + if (p_alpha_pass && !state.used_depth_prepass) { + state.prepared_depth_texture = false; + } + } break; case RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_OPAQUE: { glDepthMask(!p_alpha_pass); } break; case RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALWAYS: { glDepthMask(GL_TRUE); + // If some transparent objects write to depth, we need to re-copy depth texture when we need it + if (p_alpha_pass) { + state.prepared_depth_texture = false; + } } break; case RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_NEVER: { glDepthMask(GL_FALSE); @@ -1202,7 +1208,7 @@ bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material *p_m glActiveTexture(GL_TEXTURE0 + i); - GLenum target; + GLenum target = GL_TEXTURE_2D; GLuint tex = 0; RasterizerStorageGLES3::Texture *t = storage->texture_owner.getptr(textures[i]); @@ -1214,6 +1220,7 @@ bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material *p_m } t = t->get_ptr(); //resolve for proxies + #ifdef TOOLS_ENABLED if (t->detect_3d) { t->detect_3d(t->detect_3d_ud); @@ -1266,22 +1273,29 @@ bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material *p_m case ShaderLanguage::TYPE_SAMPLER3D: { target = GL_TEXTURE_3D; + tex = storage->resources.white_tex_3d; - switch (texture_hints[i]) { - - // TODO - default: { - tex = storage->resources.white_tex_3d; - } break; - } + //switch (texture_hints[i]) { + // TODO + //} } break; case ShaderLanguage::TYPE_ISAMPLER2DARRAY: case ShaderLanguage::TYPE_USAMPLER2DARRAY: case ShaderLanguage::TYPE_SAMPLER2DARRAY: { + + target = GL_TEXTURE_2D_ARRAY; + tex = storage->resources.white_tex_array; + + //switch (texture_hints[i]) { // TODO + //} + } break; + + default: { + } } } @@ -1379,17 +1393,17 @@ void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e, const Transfo int stride = (multi_mesh->xform_floats + multi_mesh->color_floats + multi_mesh->custom_data_floats) * 4; glEnableVertexAttribArray(8); - glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + 0); + glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, NULL); glVertexAttribDivisor(8, 1); glEnableVertexAttribArray(9); - glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + 4 * 4); + glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(4 * 4)); glVertexAttribDivisor(9, 1); int color_ofs; if (multi_mesh->transform_format == VS::MULTIMESH_TRANSFORM_3D) { glEnableVertexAttribArray(10); - glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + 8 * 4); + glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(8 * 4)); glVertexAttribDivisor(10, 1); color_ofs = 12 * 4; } else { @@ -1408,14 +1422,14 @@ void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e, const Transfo } break; case VS::MULTIMESH_COLOR_8BIT: { glEnableVertexAttribArray(11); - glVertexAttribPointer(11, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, ((uint8_t *)NULL) + color_ofs); + glVertexAttribPointer(11, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, CAST_INT_TO_UCHAR_PTR(color_ofs)); glVertexAttribDivisor(11, 1); custom_data_ofs += 4; } break; case VS::MULTIMESH_COLOR_FLOAT: { glEnableVertexAttribArray(11); - glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + color_ofs); + glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(color_ofs)); glVertexAttribDivisor(11, 1); custom_data_ofs += 4 * 4; } break; @@ -1429,13 +1443,13 @@ void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e, const Transfo } break; case VS::MULTIMESH_CUSTOM_DATA_8BIT: { glEnableVertexAttribArray(12); - glVertexAttribPointer(12, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, ((uint8_t *)NULL) + custom_data_ofs); + glVertexAttribPointer(12, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, CAST_INT_TO_UCHAR_PTR(custom_data_ofs)); glVertexAttribDivisor(12, 1); } break; case VS::MULTIMESH_CUSTOM_DATA_FLOAT: { glEnableVertexAttribArray(12); - glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + custom_data_ofs); + glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(custom_data_ofs)); glVertexAttribDivisor(12, 1); } break; } @@ -1449,7 +1463,16 @@ void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e, const Transfo if (particles->draw_order == VS::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->particle_valid_histories[1]) { glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffer_histories[1]); //modify the buffer, this was used 2 frames ago so it should be good enough for flushing - RasterizerGLES3Particle *particle_array = (RasterizerGLES3Particle *)glMapBufferRange(GL_ARRAY_BUFFER, 0, particles->amount * 24 * sizeof(float), GL_MAP_READ_BIT | GL_MAP_WRITE_BIT); + RasterizerGLES3Particle *particle_array; +#ifndef __EMSCRIPTEN__ + particle_array = static_cast<RasterizerGLES3Particle *>(glMapBufferRange(GL_ARRAY_BUFFER, 0, particles->amount * 24 * sizeof(float), GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)); +#else + PoolVector<RasterizerGLES3Particle> particle_vector; + particle_vector.resize(particles->amount); + PoolVector<RasterizerGLES3Particle>::Write particle_writer = particle_vector.write(); + particle_array = particle_writer.ptr(); + glGetBufferSubData(GL_ARRAY_BUFFER, 0, particles->amount * sizeof(RasterizerGLES3Particle), particle_array); +#endif SortArray<RasterizerGLES3Particle, RasterizerGLES3ParticleSort> sorter; @@ -1461,7 +1484,17 @@ void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e, const Transfo sorter.sort(particle_array, particles->amount); +#ifndef __EMSCRIPTEN__ glUnmapBuffer(GL_ARRAY_BUFFER); +#else + particle_writer.release(); + particle_array = NULL; + { + PoolVector<RasterizerGLES3Particle>::Read r = particle_vector.read(); + glBufferSubData(GL_ARRAY_BUFFER, 0, particles->amount * sizeof(RasterizerGLES3Particle), r.ptr()); + } + particle_vector = PoolVector<RasterizerGLES3Particle>(); +#endif #ifdef DEBUG_ENABLED if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_WIREFRAME && s->instancing_array_wireframe_id) { glBindVertexArray(s->instancing_array_wireframe_id); // use the wireframe instancing array ID @@ -1492,23 +1525,25 @@ void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e, const Transfo if (particles->draw_order != VS::PARTICLES_DRAW_ORDER_LIFETIME) { glEnableVertexAttribArray(8); //xform x - glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 3); + glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 3)); glVertexAttribDivisor(8, 1); glEnableVertexAttribArray(9); //xform y - glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 4); + glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 4)); glVertexAttribDivisor(9, 1); glEnableVertexAttribArray(10); //xform z - glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 5); + glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 5)); glVertexAttribDivisor(10, 1); glEnableVertexAttribArray(11); //color - glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + 0); + glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, NULL); glVertexAttribDivisor(11, 1); glEnableVertexAttribArray(12); //custom - glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 2); + glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 2)); glVertexAttribDivisor(12, 1); } } break; + default: { + } } } @@ -1612,11 +1647,10 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) { RasterizerStorageGLES3::Texture *t = storage->texture_owner.get(c.texture); - t = t->get_ptr(); //resolve for proxies - if (t->redraw_if_visible) { VisualServerRaster::redraw_request(); } + t = t->get_ptr(); //resolve for proxies #ifdef TOOLS_ENABLED if (t->detect_3d) { @@ -1643,7 +1677,7 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) { glEnableVertexAttribArray(VS::ARRAY_NORMAL); glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Vector3) * vertices, c.normals.ptr()); - glVertexAttribPointer(VS::ARRAY_NORMAL, 3, GL_FLOAT, false, sizeof(Vector3), ((uint8_t *)NULL) + buf_ofs); + glVertexAttribPointer(VS::ARRAY_NORMAL, 3, GL_FLOAT, false, sizeof(Vector3), CAST_INT_TO_UCHAR_PTR(buf_ofs)); buf_ofs += sizeof(Vector3) * vertices; } else { @@ -1655,7 +1689,7 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) { glEnableVertexAttribArray(VS::ARRAY_TANGENT); glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Plane) * vertices, c.tangents.ptr()); - glVertexAttribPointer(VS::ARRAY_TANGENT, 4, GL_FLOAT, false, sizeof(Plane), ((uint8_t *)NULL) + buf_ofs); + glVertexAttribPointer(VS::ARRAY_TANGENT, 4, GL_FLOAT, false, sizeof(Plane), CAST_INT_TO_UCHAR_PTR(buf_ofs)); buf_ofs += sizeof(Plane) * vertices; } else { @@ -1667,7 +1701,7 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) { glEnableVertexAttribArray(VS::ARRAY_COLOR); glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Color) * vertices, c.colors.ptr()); - glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, false, sizeof(Color), ((uint8_t *)NULL) + buf_ofs); + glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, false, sizeof(Color), CAST_INT_TO_UCHAR_PTR(buf_ofs)); buf_ofs += sizeof(Color) * vertices; } else { @@ -1680,7 +1714,7 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) { glEnableVertexAttribArray(VS::ARRAY_TEX_UV); glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Vector2) * vertices, c.uvs.ptr()); - glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, false, sizeof(Vector2), ((uint8_t *)NULL) + buf_ofs); + glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, false, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buf_ofs)); buf_ofs += sizeof(Vector2) * vertices; } else { @@ -1692,7 +1726,7 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) { glEnableVertexAttribArray(VS::ARRAY_TEX_UV2); glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Vector2) * vertices, c.uvs2.ptr()); - glVertexAttribPointer(VS::ARRAY_TEX_UV2, 2, GL_FLOAT, false, sizeof(Vector2), ((uint8_t *)NULL) + buf_ofs); + glVertexAttribPointer(VS::ARRAY_TEX_UV2, 2, GL_FLOAT, false, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buf_ofs)); buf_ofs += sizeof(Vector2) * vertices; } else { @@ -1702,7 +1736,7 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) { glEnableVertexAttribArray(VS::ARRAY_VERTEX); glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Vector3) * vertices, c.vertices.ptr()); - glVertexAttribPointer(VS::ARRAY_VERTEX, 3, GL_FLOAT, false, sizeof(Vector3), ((uint8_t *)NULL) + buf_ofs); + glVertexAttribPointer(VS::ARRAY_VERTEX, 3, GL_FLOAT, false, sizeof(Vector3), CAST_INT_TO_UCHAR_PTR(buf_ofs)); glDrawArrays(gl_primitive[c.primitive], 0, c.vertices.size()); } @@ -1731,19 +1765,19 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) { if (amount - split > 0) { glEnableVertexAttribArray(8); //xform x - glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + stride * split + sizeof(float) * 4 * 3); + glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + sizeof(float) * 4 * 3)); glVertexAttribDivisor(8, 1); glEnableVertexAttribArray(9); //xform y - glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + stride * split + sizeof(float) * 4 * 4); + glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + sizeof(float) * 4 * 4)); glVertexAttribDivisor(9, 1); glEnableVertexAttribArray(10); //xform z - glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + stride * split + sizeof(float) * 4 * 5); + glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + sizeof(float) * 4 * 5)); glVertexAttribDivisor(10, 1); glEnableVertexAttribArray(11); //color - glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + stride * split + 0); + glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + 0)); glVertexAttribDivisor(11, 1); glEnableVertexAttribArray(12); //custom - glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + stride * split + sizeof(float) * 4 * 2); + glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + sizeof(float) * 4 * 2)); glVertexAttribDivisor(12, 1); #ifdef DEBUG_ENABLED @@ -1769,19 +1803,19 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) { if (split > 0) { glEnableVertexAttribArray(8); //xform x - glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 3); + glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 3)); glVertexAttribDivisor(8, 1); glEnableVertexAttribArray(9); //xform y - glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 4); + glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 4)); glVertexAttribDivisor(9, 1); glEnableVertexAttribArray(10); //xform z - glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 5); + glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 5)); glVertexAttribDivisor(10, 1); glEnableVertexAttribArray(11); //color - glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + 0); + glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, NULL); glVertexAttribDivisor(11, 1); glEnableVertexAttribArray(12); //custom - glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 2); + glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 2)); glVertexAttribDivisor(12, 1); #ifdef DEBUG_ENABLED @@ -1815,6 +1849,7 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) { storage->info.render.vertices_count += s->index_array_len * amount; } else #endif + if (s->index_array_len > 0) { glDrawElementsInstanced(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0, amount); @@ -1830,6 +1865,8 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) { } } break; + default: { + } } } @@ -2025,7 +2062,7 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_ int current_blend_mode = -1; int prev_shading = -1; - RID prev_skeleton; + RasterizerStorageGLES3::Skeleton *prev_skeleton = NULL; state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS, true); //by default unshaded (easier to set) @@ -2039,7 +2076,10 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_ RenderList::Element *e = p_elements[i]; RasterizerStorageGLES3::Material *material = e->material; - RID skeleton = e->instance->skeleton; + RasterizerStorageGLES3::Skeleton *skeleton = NULL; + if (e->instance->skeleton.is_valid()) { + skeleton = storage->skeleton_owner.getornull(e->instance->skeleton); + } bool rebind = first; @@ -2186,15 +2226,14 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_ } if (prev_skeleton != skeleton) { - if (prev_skeleton.is_valid() != skeleton.is_valid()) { - state.scene_shader.set_conditional(SceneShaderGLES3::USE_SKELETON, skeleton.is_valid()); + if ((prev_skeleton == NULL) != (skeleton == NULL)) { + state.scene_shader.set_conditional(SceneShaderGLES3::USE_SKELETON, skeleton != NULL); rebind = true; } - if (skeleton.is_valid()) { - RasterizerStorageGLES3::Skeleton *sk = storage->skeleton_owner.getornull(skeleton); + if (skeleton) { glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 1); - glBindTexture(GL_TEXTURE_2D, sk->texture); + glBindTexture(GL_TEXTURE_2D, skeleton->texture); } } @@ -2221,7 +2260,6 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_ _set_cull(e->sort_key & RenderList::SORT_KEY_MIRROR_FLAG, e->sort_key & RenderList::SORT_KEY_CULL_DISABLED_FLAG, p_reverse_cull); - state.scene_shader.set_uniform(SceneShaderGLES3::NORMAL_MULT, e->instance->mirror ? -1.0 : 1.0); state.scene_shader.set_uniform(SceneShaderGLES3::WORLD_TRANSFORM, e->instance->transform); _render_geometry(e); @@ -2325,9 +2363,13 @@ void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::G state.used_screen_texture = true; } + if (p_material->shader->spatial.uses_depth_texture) { + state.used_depth_texture = true; + } + if (p_depth_pass) { - if (has_blend_alpha || p_material->shader->spatial.uses_depth_texture || (has_base_alpha && p_material->shader->spatial.depth_draw_mode != RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS)) + if (has_blend_alpha || p_material->shader->spatial.uses_depth_texture || (has_base_alpha && p_material->shader->spatial.depth_draw_mode != RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) || p_material->shader->spatial.depth_draw_mode == RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_NEVER || p_material->shader->spatial.no_depth_test || p_instance->cast_shadows == VS::SHADOW_CASTING_SETTING_OFF) return; //bye if (!p_material->shader->spatial.uses_alpha_scissor && !p_material->shader->spatial.writes_modelview_or_projection && !p_material->shader->spatial.uses_vertex && !p_material->shader->spatial.uses_discard && p_material->shader->spatial.depth_draw_mode != RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) { @@ -2344,7 +2386,7 @@ void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::G has_alpha = false; } - RenderList::Element *e = has_alpha ? render_list.add_alpha_element() : render_list.add_element(); + RenderList::Element *e = (has_alpha || p_material->shader->spatial.no_depth_test) ? render_list.add_alpha_element() : render_list.add_element(); if (!e) return; @@ -2389,7 +2431,7 @@ void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::G e->sort_key |= SORT_KEY_LIGHTMAP_CAPTURE_FLAG; } - e->sort_key |= uint64_t(p_material->render_priority + 128) << RenderList::SORT_KEY_PRIORITY_SHIFT; + e->sort_key |= (uint64_t(p_material->render_priority) + 128) << RenderList::SORT_KEY_PRIORITY_SHIFT; } /* @@ -2425,7 +2467,7 @@ void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::G } } -void RasterizerSceneGLES3::_draw_sky(RasterizerStorageGLES3::Sky *p_sky, const CameraMatrix &p_projection, const Transform &p_transform, bool p_vflip, float p_custom_fov, float p_energy) { +void RasterizerSceneGLES3::_draw_sky(RasterizerStorageGLES3::Sky *p_sky, const CameraMatrix &p_projection, const Transform &p_transform, bool p_vflip, float p_custom_fov, float p_energy, const Basis &p_sky_orientation) { ERR_FAIL_COND(!p_sky); @@ -2517,7 +2559,12 @@ void RasterizerSceneGLES3::_draw_sky(RasterizerStorageGLES3::Sky *p_sky, const C storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_PANORAMA, !asymmetrical); storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_MULTIPLIER, true); storage->shaders.copy.bind(); + storage->shaders.copy.set_uniform(CopyShaderGLES3::MULTIPLIER, p_energy); + + // don't know why but I always have problems setting a uniform mat3, so we're using a transform + storage->shaders.copy.set_uniform(CopyShaderGLES3::SKY_TRANSFORM, Transform(p_sky_orientation, Vector3(0.0, 0.0, 0.0)).affine_inverse()); + if (asymmetrical) { // pack the bits we need from our projection matrix storage->shaders.copy.set_uniform(CopyShaderGLES3::ASYM_PROJ, camera.matrix[2][0], camera.matrix[0][0], camera.matrix[2][1], camera.matrix[1][1]); @@ -2535,7 +2582,8 @@ void RasterizerSceneGLES3::_draw_sky(RasterizerStorageGLES3::Sky *p_sky, const C storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_PANORAMA, false); } -void RasterizerSceneGLES3::_setup_environment(Environment *env, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform) { +void RasterizerSceneGLES3::_setup_environment(Environment *env, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_no_fog) { + Transform sky_orientation; //store camera into ubo store_camera(p_cam_projection, state.ubo_data.projection_matrix); @@ -2576,6 +2624,9 @@ void RasterizerSceneGLES3::_setup_environment(Environment *env, const CameraMatr state.ubo_data.bg_color[2] = bg_color.b; state.ubo_data.bg_color[3] = bg_color.a; + //use the inverse of our sky_orientation, we may need to skip this if we're using a reflection probe? + sky_orientation = Transform(env->sky_orientation, Vector3(0.0, 0.0, 0.0)).affine_inverse(); + state.env_radiance_data.ambient_contribution = env->ambient_sky_contribution; state.ubo_data.ambient_occlusion_affect_light = env->ssao_light_affect; state.ubo_data.ambient_occlusion_affect_ssao = env->ssao_ao_channel_affect; @@ -2586,7 +2637,8 @@ void RasterizerSceneGLES3::_setup_environment(Environment *env, const CameraMatr state.ubo_data.fog_color_enabled[0] = linear_fog.r; state.ubo_data.fog_color_enabled[1] = linear_fog.g; state.ubo_data.fog_color_enabled[2] = linear_fog.b; - state.ubo_data.fog_color_enabled[3] = env->fog_enabled ? 1.0 : 0.0; + state.ubo_data.fog_color_enabled[3] = (!p_no_fog && env->fog_enabled) ? 1.0 : 0.0; + state.ubo_data.fog_density = linear_fog.a; Color linear_sun = env->fog_sun_color.to_linear(); state.ubo_data.fog_sun_color_amount[0] = linear_sun.r; @@ -2595,6 +2647,7 @@ void RasterizerSceneGLES3::_setup_environment(Environment *env, const CameraMatr state.ubo_data.fog_sun_color_amount[3] = env->fog_sun_amount; state.ubo_data.fog_depth_enabled = env->fog_depth_enabled; state.ubo_data.fog_depth_begin = env->fog_depth_begin; + state.ubo_data.fog_depth_end = env->fog_depth_end; state.ubo_data.fog_depth_curve = env->fog_depth_curve; state.ubo_data.fog_transmit_enabled = env->fog_transmit_enabled; state.ubo_data.fog_transmit_curve = env->fog_transmit_curve; @@ -2642,7 +2695,7 @@ void RasterizerSceneGLES3::_setup_environment(Environment *env, const CameraMatr //fill up environment - store_transform(p_cam_transform, state.env_radiance_data.transform); + store_transform(sky_orientation * p_cam_transform, state.env_radiance_data.transform); glBindBuffer(GL_UNIFORM_BUFFER, state.env_radiance_ubo); glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(State::EnvironmentRadianceUBO), &state.env_radiance_data); @@ -2715,9 +2768,7 @@ void RasterizerSceneGLES3::_setup_directional_light(int p_index, const Transform width /= 2; height /= 2; - if (j == 0) { - - } else if (j == 1) { + if (j == 1) { x += width; } else if (j == 2) { y += height; @@ -2730,9 +2781,7 @@ void RasterizerSceneGLES3::_setup_directional_light(int p_index, const Transform height /= 2; - if (j == 0) { - - } else { + if (j != 0) { y += height; } } @@ -2749,7 +2798,7 @@ void RasterizerSceneGLES3::_setup_directional_light(int p_index, const Transform CameraMatrix shadow_mtx = rectm * bias * li->shadow_transform[j].camera * modelview; - store_camera(shadow_mtx, &ubo_data.shadow_matrix1[16 * j]); + store_camera(shadow_mtx, &ubo_data.shadow.matrix[16 * j]); ubo_data.light_clamp[0] = atlas_rect.position.x; ubo_data.light_clamp[1] = atlas_rect.position.y; @@ -2779,7 +2828,7 @@ void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result, int p_light_c for (int i = 0; i < p_light_cull_count; i++) { - ERR_BREAK(i >= RenderList::MAX_LIGHTS); + ERR_BREAK(i >= render_list.max_lights); LightInstance *li = light_instance_owner.getptr(p_light_cull_result[i]); @@ -2860,7 +2909,7 @@ void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result, int p_light_c Transform proj = (p_camera_inverse_transform * li->transform).inverse(); - store_transform(proj, ubo_data.shadow_matrix1); + store_transform(proj, ubo_data.shadow.matrix1); ubo_data.light_params[3] = 1.0; //means it has shadow ubo_data.light_clamp[0] = float(x) / atlas_size; @@ -2949,7 +2998,7 @@ void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result, int p_light_c CameraMatrix shadow_mtx = rectm * bias * li->shadow_transform[0].camera * modelview; - store_camera(shadow_mtx, ubo_data.shadow_matrix1); + store_camera(shadow_mtx, ubo_data.shadow.matrix1); } li->light_index = state.spot_light_count; @@ -3036,19 +3085,17 @@ void RasterizerSceneGLES3::_setup_reflections(RID *p_reflection_probe_cull_resul reflection_ubo.ambient[3] = rpi->probe_ptr->interior_ambient_probe_contrib; } else { Color ambient_linear; - float contrib = 0; if (p_env) { ambient_linear = p_env->ambient_color.to_linear(); ambient_linear.r *= p_env->ambient_energy; ambient_linear.g *= p_env->ambient_energy; ambient_linear.b *= p_env->ambient_energy; - contrib = p_env->ambient_sky_contribution; } reflection_ubo.ambient[0] = ambient_linear.r; reflection_ubo.ambient[1] = ambient_linear.g; reflection_ubo.ambient[2] = ambient_linear.b; - reflection_ubo.ambient[3] = 0; + reflection_ubo.ambient[3] = 0; //not used in exterior mode, since it just blends with regular ambient light } int cell_size = reflection_atlas->size / reflection_atlas->subdiv; @@ -3087,7 +3134,7 @@ void RasterizerSceneGLES3::_copy_screen(bool p_invalidate_color, bool p_invalida GLenum attachments[2] = { GL_COLOR_ATTACHMENT0, - GL_DEPTH_STENCIL_ATTACHMENT + GL_DEPTH_ATTACHMENT }; glInvalidateFramebuffer(GL_FRAMEBUFFER, p_invalidate_depth ? 2 : 1, attachments); @@ -3132,6 +3179,8 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p current_material_index = 0; state.used_sss = false; state.used_screen_texture = false; + state.used_depth_texture = false; + //fill list for (int i = 0; i < p_cull_count; i++) { @@ -3146,10 +3195,10 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p int ssize = mesh->surfaces.size(); - for (int i = 0; i < ssize; i++) { + for (int j = 0; j < ssize; j++) { - int mat_idx = inst->materials[i].is_valid() ? i : -1; - RasterizerStorageGLES3::Surface *s = mesh->surfaces[i]; + int mat_idx = inst->materials[j].is_valid() ? j : -1; + RasterizerStorageGLES3::Surface *s = mesh->surfaces[j]; _add_geometry(s, inst, NULL, mat_idx, p_depth_pass, p_shadow_pass); } @@ -3170,9 +3219,9 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p int ssize = mesh->surfaces.size(); - for (int i = 0; i < ssize; i++) { + for (int j = 0; j < ssize; j++) { - RasterizerStorageGLES3::Surface *s = mesh->surfaces[i]; + RasterizerStorageGLES3::Surface *s = mesh->surfaces[j]; _add_geometry(s, inst, multi_mesh, -1, p_depth_pass, p_shadow_pass); } @@ -3190,9 +3239,9 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p RasterizerStorageGLES3::Particles *particles = storage->particles_owner.getptr(inst->base); ERR_CONTINUE(!particles); - for (int i = 0; i < particles->draw_passes.size(); i++) { + for (int j = 0; j < particles->draw_passes.size(); j++) { - RID pmesh = particles->draw_passes[i]; + RID pmesh = particles->draw_passes[j]; if (!pmesh.is_valid()) continue; RasterizerStorageGLES3::Mesh *mesh = storage->mesh_owner.get(pmesh); @@ -3201,14 +3250,16 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p int ssize = mesh->surfaces.size(); - for (int j = 0; j < ssize; j++) { + for (int k = 0; k < ssize; k++) { - RasterizerStorageGLES3::Surface *s = mesh->surfaces[j]; + RasterizerStorageGLES3::Surface *s = mesh->surfaces[k]; _add_geometry(s, inst, particles, -1, p_depth_pass, p_shadow_pass); } } } break; + default: { + } } } } @@ -3246,6 +3297,29 @@ void RasterizerSceneGLES3::_blur_effect_buffer() { } } +void RasterizerSceneGLES3::_prepare_depth_texture() { + if (!state.prepared_depth_texture) { + //resolve depth buffer + glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo); + glReadBuffer(GL_COLOR_ATTACHMENT0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->fbo); + glBlitFramebuffer(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, 0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, GL_DEPTH_BUFFER_BIT, GL_NEAREST); + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + state.prepared_depth_texture = true; + } +} + +void RasterizerSceneGLES3::_bind_depth_texture() { + if (!state.bound_depth_texture) { + ERR_FAIL_COND(!state.prepared_depth_texture); + //bind depth for read + glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 8); + glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth); + state.bound_depth_texture = true; + } +} + void RasterizerSceneGLES3::_render_mrts(Environment *env, const CameraMatrix &p_cam_projection) { glDepthMask(GL_FALSE); @@ -3253,6 +3327,8 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env, const CameraMatrix &p_ glDisable(GL_CULL_FACE); glDisable(GL_BLEND); + _prepare_depth_texture(); + if (env->ssao_enabled || env->ssr_enabled) { //copy normal and roughness to effect buffer @@ -3585,7 +3661,6 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p if (storage->frame.current_rt->buffers.active) { //transfer to effect buffer if using buffers, also resolve MSAA - glReadBuffer(GL_COLOR_ATTACHMENT0); glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo); glBlitFramebuffer(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, 0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, GL_COLOR_BUFFER_BIT, GL_NEAREST); @@ -3594,12 +3669,16 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); } - if (!env || storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { + if (!env || storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT] || storage->frame.current_rt->width < 4 || storage->frame.current_rt->height < 4) { //no post process on small render targets //no environment or transparent render, simply return and convert to SRGB - glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo); + if (storage->frame.current_rt->external.fbo != 0) { + glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->external.fbo); + } else { + glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo); + } glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color); - storage->shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB, true); + storage->shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB, !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_KEEP_3D_LINEAR]); storage->shaders.copy.set_conditional(CopyShaderGLES3::V_FLIP, storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP]); storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]); storage->shaders.copy.bind(); @@ -3896,6 +3975,7 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h)); state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::LOD, float(i)); state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::GLOW_STRENGTH, env->glow_strength); + state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::LUMINANCE_CAP, env->glow_hdr_luminance_cap); glActiveTexture(GL_TEXTURE0); if (i == 0) { @@ -3938,14 +4018,18 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height); } - glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo); + if (storage->frame.current_rt->external.fbo != 0) { + glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->external.fbo); + } else { + glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo); + } glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, composite_from); state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_FILMIC_TONEMAPPER, env->tone_mapper == VS::ENV_TONE_MAPPER_FILMIC); state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_ACES_TONEMAPPER, env->tone_mapper == VS::ENV_TONE_MAPPER_ACES); - state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_REINDHART_TONEMAPPER, env->tone_mapper == VS::ENV_TONE_MAPPER_REINHARDT); + state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_REINHARD_TONEMAPPER, env->tone_mapper == VS::ENV_TONE_MAPPER_REINHARD); state.tonemap_shader.set_conditional(TonemapShaderGLES3::KEEP_3D_LINEAR, storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_KEEP_3D_LINEAR]); state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_AUTO_EXPOSURE, env->auto_exposure); @@ -4032,7 +4116,7 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_AUTO_EXPOSURE, false); state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_FILMIC_TONEMAPPER, false); state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_ACES_TONEMAPPER, false); - state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_REINDHART_TONEMAPPER, false); + state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_REINHARD_TONEMAPPER, false); state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL1, false); state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL2, false); state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL3, false); @@ -4097,15 +4181,37 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const state.ubo_data.screen_pixel_size[1] = 1.0 / storage->frame.current_rt->height; } - _setup_environment(env, p_cam_projection, p_cam_transform); + _setup_environment(env, p_cam_projection, p_cam_transform, p_reflection_probe.is_valid()); bool fb_cleared = false; glDepthFunc(GL_LEQUAL); - state.used_contact_shadows = true; + state.used_contact_shadows = false; + state.prepared_depth_texture = false; + state.bound_depth_texture = false; + + for (int i = 0; i < p_light_cull_count; i++) { - if (!storage->config.no_depth_prepass && storage->frame.current_rt && state.debug_draw != VS::VIEWPORT_DEBUG_DRAW_OVERDRAW) { //detect with state.used_contact_shadows too + ERR_BREAK(i >= render_list.max_lights); + + LightInstance *li = light_instance_owner.getptr(p_light_cull_result[i]); + if (li->light_ptr->param[VS::LIGHT_PARAM_CONTACT_SHADOW_SIZE] > CMP_EPSILON) { + state.used_contact_shadows = true; + } + } + + // Do depth prepass if it's explicitly enabled + bool use_depth_prepass = storage->config.use_depth_prepass; + + // If contact shadows are used then we need to do depth prepass even if it's otherwise disabled + use_depth_prepass = use_depth_prepass || state.used_contact_shadows; + + // Never do depth prepass if effects are disabled or if we render overdraws + use_depth_prepass = use_depth_prepass && storage->frame.current_rt && !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_NO_3D_EFFECTS]; + use_depth_prepass = use_depth_prepass && state.debug_draw != VS::VIEWPORT_DEBUG_DRAW_OVERDRAW; + + if (use_depth_prepass) { //pre z pass glDisable(GL_BLEND); @@ -4119,7 +4225,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const glColorMask(0, 0, 0, 0); glClearDepth(1.0f); - glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + glClear(GL_DEPTH_BUFFER_BIT); render_list.clear(); _fill_render_list(p_cull_result, p_cull_count, true, false); @@ -4132,22 +4238,15 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const if (state.used_contact_shadows) { - glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo); - glReadBuffer(GL_COLOR_ATTACHMENT0); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->fbo); - glBlitFramebuffer(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, 0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, GL_DEPTH_BUFFER_BIT, GL_NEAREST); - glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - //bind depth for read - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 8); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth); + _prepare_depth_texture(); + _bind_depth_texture(); } fb_cleared = true; render_pass++; - state.using_contact_shadows = true; + state.used_depth_prepass = true; } else { - state.using_contact_shadows = false; + state.used_depth_prepass = false; } _setup_lights(p_light_cull_result, p_light_cull_count, p_cam_transform.affine_inverse(), p_cam_projection, p_shadow_atlas); @@ -4194,12 +4293,12 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const } else { - use_mrt = env && (state.used_sss || env->ssao_enabled || env->ssr_enabled); //only enable MRT rendering if any of these is enabled + use_mrt = env && (state.used_sss || env->ssao_enabled || env->ssr_enabled || env->dof_blur_far_enabled || env->dof_blur_near_enabled); //only enable MRT rendering if any of these is enabled //effects disabled and transparency also prevent using MRTs use_mrt = use_mrt && !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]; use_mrt = use_mrt && !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_NO_3D_EFFECTS]; use_mrt = use_mrt && state.debug_draw != VS::VIEWPORT_DEBUG_DRAW_OVERDRAW; - use_mrt = use_mrt && env && (env->bg_mode != VS::ENV_BG_KEEP && env->bg_mode != VS::ENV_BG_CANVAS); + use_mrt = use_mrt && (env->bg_mode != VS::ENV_BG_KEEP && env->bg_mode != VS::ENV_BG_CANVAS); glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height); @@ -4231,6 +4330,10 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const if (storage->frame.current_rt->buffers.active) { current_fbo = storage->frame.current_rt->buffers.fbo; } else { + if (storage->frame.current_rt->effects.mip_maps[0].sizes.size() == 0) { + ERR_PRINT_ONCE("Can't use canvas background mode in a render target configured without sampling"); + return; + } current_fbo = storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo; } @@ -4244,12 +4347,14 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const } if (!fb_cleared) { - glClearBufferfi(GL_DEPTH_STENCIL, 0, 1.0, 0); + glClearDepth(1.0f); + glClear(GL_DEPTH_BUFFER_BIT); } Color clear_color(0, 0, 0, 0); RasterizerStorageGLES3::Sky *sky = NULL; + Ref<CameraFeed> feed; GLuint env_radiance_tex = 0; if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_OVERDRAW) { @@ -4284,6 +4389,9 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const clear_color = env->bg_color.to_linear(); storage->frame.clear_request = false; + } else if (env->bg_mode == VS::ENV_BG_CAMERA_FEED) { + feed = CameraServer::get_singleton()->get_feed_by_id(env->camera_feed_id); + storage->frame.clear_request = false; } else { storage->frame.clear_request = false; } @@ -4292,10 +4400,11 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const glClearBufferfv(GL_COLOR, 0, clear_color.components); // specular } + VS::EnvironmentBG bg_mode = (!env || (probe && env->bg_mode == VS::ENV_BG_CANVAS)) ? VS::ENV_BG_CLEAR_COLOR : env->bg_mode; //if no environment, or canvas while rendering a probe (invalid use case), use color. + if (env) { - switch (env->bg_mode) { + switch (bg_mode) { case VS::ENV_BG_COLOR_SKY: - case VS::ENV_BG_SKY: sky = storage->sky_owner.getornull(env->sky); @@ -4333,9 +4442,72 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); break; + case VS::ENV_BG_CAMERA_FEED: + if (feed.is_valid() && (feed->get_base_width() > 0) && (feed->get_base_height() > 0)) { + // copy our camera feed to our background + + glDisable(GL_BLEND); + glDepthMask(GL_FALSE); + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + + storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_DISPLAY_TRANSFORM, true); + storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, true); + storage->shaders.copy.set_conditional(CopyShaderGLES3::SRGB_TO_LINEAR, true); + + if (feed->get_datatype() == CameraFeed::FEED_RGB) { + RID camera_RGBA = feed->get_texture(CameraServer::FEED_RGBA_IMAGE); + + VS::get_singleton()->texture_bind(camera_RGBA, 0); + } else if (feed->get_datatype() == CameraFeed::FEED_YCBCR) { + RID camera_YCbCr = feed->get_texture(CameraServer::FEED_YCBCR_IMAGE); + + VS::get_singleton()->texture_bind(camera_YCbCr, 0); + + storage->shaders.copy.set_conditional(CopyShaderGLES3::YCBCR_TO_SRGB, true); + + } else if (feed->get_datatype() == CameraFeed::FEED_YCBCR_SEP) { + RID camera_Y = feed->get_texture(CameraServer::FEED_Y_IMAGE); + RID camera_CbCr = feed->get_texture(CameraServer::FEED_CBCR_IMAGE); + + VS::get_singleton()->texture_bind(camera_Y, 0); + VS::get_singleton()->texture_bind(camera_CbCr, 1); + + storage->shaders.copy.set_conditional(CopyShaderGLES3::SEP_CBCR_TEXTURE, true); + storage->shaders.copy.set_conditional(CopyShaderGLES3::YCBCR_TO_SRGB, true); + }; + + storage->shaders.copy.bind(); + storage->shaders.copy.set_uniform(CopyShaderGLES3::DISPLAY_TRANSFORM, feed->get_transform()); + + _copy_screen(true, true); + + //turn off everything used + storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_DISPLAY_TRANSFORM, false); + storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, false); + storage->shaders.copy.set_conditional(CopyShaderGLES3::SRGB_TO_LINEAR, false); + storage->shaders.copy.set_conditional(CopyShaderGLES3::SEP_CBCR_TEXTURE, false); + storage->shaders.copy.set_conditional(CopyShaderGLES3::YCBCR_TO_SRGB, false); + + //restore + glEnable(GL_BLEND); + glDepthMask(GL_TRUE); + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + } else { + // don't have a feed, just show greenscreen :) + clear_color = Color(0.0, 1.0, 0.0, 1.0); + } + break; + default: { + } } } + if (probe && probe->probe_ptr->interior) { + env_radiance_tex = 0; //for rendering probe interiors, radiance must not be used. + } + state.texscreen_copied = false; glBlendEquation(GL_FUNC_ADD); @@ -4379,7 +4551,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const */ if (sky && sky->panorama.is_valid()) - _draw_sky(sky, p_cam_projection, p_cam_transform, false, env->sky_custom_fov, env->bg_energy); + _draw_sky(sky, p_cam_projection, p_cam_transform, false, env->sky_custom_fov, env->bg_energy, env->sky_orientation); } //_render_list_forward(&alpha_render_list,camera_transform,camera_transform_inverse,camera_projection,false,fragment_lighting,true); @@ -4388,9 +4560,15 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const //state.scene_shader.set_conditional( SceneShaderGLES3::USE_FOG,false); if (use_mrt) { + _render_mrts(env, p_cam_projection); } else { - //FIXME: check that this is possible to use + // Here we have to do the blits/resolves that otherwise are done in the MRT rendering, in particular + // - prepare screen texture for any geometry that uses a shader with screen texture + // - prepare depth texture for any geometry that uses a shader with depth texture + + bool framebuffer_dirty = false; + if (storage->frame.current_rt && storage->frame.current_rt->buffers.active && state.used_screen_texture) { glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo); glReadBuffer(GL_COLOR_ATTACHMENT0); @@ -4399,12 +4577,25 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); _blur_effect_buffer(); - //restored framebuffer + framebuffer_dirty = true; + } + + if (storage->frame.current_rt && storage->frame.current_rt->buffers.active && state.used_depth_texture) { + _prepare_depth_texture(); + framebuffer_dirty = true; + } + + if (framebuffer_dirty) { + // Restore framebuffer glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo); glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height); } } + if (storage->frame.current_rt && state.used_depth_texture && storage->frame.current_rt->buffers.active) { + _bind_depth_texture(); + } + if (storage->frame.current_rt && state.used_screen_texture && storage->frame.current_rt->buffers.active) { glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 7); glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color); @@ -4433,9 +4624,11 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const return; } + if (env && (env->dof_blur_far_enabled || env->dof_blur_near_enabled) && storage->frame.current_rt && storage->frame.current_rt->buffers.active) + _prepare_depth_texture(); _post_process(env, p_cam_projection); - - if (false && shadow_atlas) { + // Needed only for debugging + /* if (shadow_atlas && storage->frame.current_rt) { //_copy_texture_to_front_buffer(shadow_atlas->depth); storage->canvas->canvas_begin(); @@ -4445,7 +4638,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1)); } - if (false && storage->frame.current_rt) { + if (storage->frame.current_rt) { //_copy_texture_to_front_buffer(shadow_atlas->depth); storage->canvas->canvas_begin(); @@ -4455,7 +4648,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 16, storage->frame.current_rt->height / 16), Rect2(0, 0, 1, 1)); } - if (false && reflection_atlas && storage->frame.current_rt) { + if (reflection_atlas && storage->frame.current_rt) { //_copy_texture_to_front_buffer(shadow_atlas->depth); storage->canvas->canvas_begin(); @@ -4464,7 +4657,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1)); } - if (false && directional_shadow.fbo) { + if (directional_shadow.fbo) { //_copy_texture_to_front_buffer(shadow_atlas->depth); storage->canvas->canvas_begin(); @@ -4474,7 +4667,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1)); } - if (false && env_radiance_tex) { + if ( env_radiance_tex) { //_copy_texture_to_front_buffer(shadow_atlas->depth); storage->canvas->canvas_begin(); @@ -4485,8 +4678,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1)); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } - + }*/ //disable all stuff } @@ -4501,7 +4693,7 @@ void RasterizerSceneGLES3::render_shadow(RID p_light, RID p_shadow_atlas, int p_ RasterizerStorageGLES3::Light *light = storage->light_owner.getornull(light_instance->light); ERR_FAIL_COND(!light); - uint32_t x, y, width, height, vp_height; + uint32_t x, y, width, height; float dp_direction = 0.0; float zfar = 0; @@ -4512,7 +4704,7 @@ void RasterizerSceneGLES3::render_shadow(RID p_light, RID p_shadow_atlas, int p_ float bias = 0; float normal_bias = 0; - state.using_contact_shadows = false; + state.used_depth_prepass = false; CameraMatrix light_projection; Transform light_transform; @@ -4556,9 +4748,7 @@ void RasterizerSceneGLES3::render_shadow(RID p_light, RID p_shadow_atlas, int p_ width /= 2; height /= 2; - if (p_pass == 0) { - - } else if (p_pass == 1) { + if (p_pass == 1) { x += width; } else if (p_pass == 2) { y += height; @@ -4583,7 +4773,6 @@ void RasterizerSceneGLES3::render_shadow(RID p_light, RID p_shadow_atlas, int p_ bias = light->param[VS::LIGHT_PARAM_SHADOW_BIAS] * bias_mult; normal_bias = light->param[VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] * bias_mult; fbo = directional_shadow.fbo; - vp_height = directional_shadow.size; } else { //set from shadow atlas @@ -4593,7 +4782,6 @@ void RasterizerSceneGLES3::render_shadow(RID p_light, RID p_shadow_atlas, int p_ ERR_FAIL_COND(!shadow_atlas->shadow_owners.has(p_light)); fbo = shadow_atlas->fbo; - vp_height = shadow_atlas->size; uint32_t key = shadow_atlas->shadow_owners[p_light]; @@ -4807,6 +4995,20 @@ bool RasterizerSceneGLES3::free(RID p_rid) { reflection_probe_instance_owner.free(p_rid); memdelete(reflection_instance); + } else if (environment_owner.owns(p_rid)) { + + Environment *environment = environment_owner.get(p_rid); + + environment_owner.free(p_rid); + memdelete(environment); + + } else if (gi_probe_instance_owner.owns(p_rid)) { + + GIProbeInstance *gi_probe_instance = gi_probe_instance_owner.get(p_rid); + + gi_probe_instance_owner.free(p_rid); + memdelete(gi_probe_instance); + } else { return false; } @@ -4871,10 +5073,11 @@ void RasterizerSceneGLES3::initialize() { glBindBuffer(GL_UNIFORM_BUFFER, 0); render_list.max_elements = GLOBAL_DEF_RST("rendering/limits/rendering/max_renderable_elements", (int)RenderList::DEFAULT_MAX_ELEMENTS); - if (render_list.max_elements > 1000000) - render_list.max_elements = 1000000; - if (render_list.max_elements < 1024) - render_list.max_elements = 1024; + ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/rendering/max_renderable_elements", PropertyInfo(Variant::INT, "rendering/limits/rendering/max_renderable_elements", PROPERTY_HINT_RANGE, "1024,1000000,1")); + render_list.max_lights = GLOBAL_DEF("rendering/limits/rendering/max_renderable_lights", (int)RenderList::DEFAULT_MAX_LIGHTS); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/rendering/max_renderable_lights", PropertyInfo(Variant::INT, "rendering/limits/rendering/max_renderable_lights", PROPERTY_HINT_RANGE, "16,4096,1")); + render_list.max_reflections = GLOBAL_DEF("rendering/limits/rendering/max_renderable_reflections", (int)RenderList::DEFAULT_MAX_REFLECTIONS); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/rendering/max_renderable_reflections", PropertyInfo(Variant::INT, "rendering/limits/rendering/max_renderable_reflections", PROPERTY_HINT_RANGE, "8,1024,1")); { //quad buffers @@ -4889,7 +5092,7 @@ void RasterizerSceneGLES3::initialize() { glBindBuffer(GL_ARRAY_BUFFER, state.sky_verts); glVertexAttribPointer(VS::ARRAY_VERTEX, 3, GL_FLOAT, GL_FALSE, sizeof(Vector3) * 2, 0); glEnableVertexAttribArray(VS::ARRAY_VERTEX); - glVertexAttribPointer(VS::ARRAY_TEX_UV, 3, GL_FLOAT, GL_FALSE, sizeof(Vector3) * 2, ((uint8_t *)NULL) + sizeof(Vector3)); + glVertexAttribPointer(VS::ARRAY_TEX_UV, 3, GL_FLOAT, GL_FALSE, sizeof(Vector3) * 2, CAST_INT_TO_UCHAR_PTR(sizeof(Vector3))); glEnableVertexAttribArray(VS::ARRAY_TEX_UV); glBindVertexArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind @@ -4969,7 +5172,7 @@ void RasterizerSceneGLES3::initialize() { glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &max_ubo_size); const int ubo_light_size = 160; state.ubo_light_size = ubo_light_size; - state.max_ubo_lights = MIN(RenderList::MAX_LIGHTS, max_ubo_size / ubo_light_size); + state.max_ubo_lights = MIN(render_list.max_lights, max_ubo_size / ubo_light_size); state.spot_array_tmp = (uint8_t *)memalloc(ubo_light_size * state.max_ubo_lights); state.omni_array_tmp = (uint8_t *)memalloc(ubo_light_size * state.max_ubo_lights); @@ -4994,7 +5197,7 @@ void RasterizerSceneGLES3::initialize() { state.scene_shader.add_custom_define("#define MAX_LIGHT_DATA_STRUCTS " + itos(state.max_ubo_lights) + "\n"); state.scene_shader.add_custom_define("#define MAX_FORWARD_LIGHTS " + itos(state.max_forward_lights_per_object) + "\n"); - state.max_ubo_reflections = MIN(RenderList::MAX_REFLECTIONS, max_ubo_size / sizeof(ReflectionProbeDataUBO)); + state.max_ubo_reflections = MIN(render_list.max_reflections, max_ubo_size / (int)sizeof(ReflectionProbeDataUBO)); state.reflection_array_tmp = (uint8_t *)memalloc(sizeof(ReflectionProbeDataUBO) * state.max_ubo_reflections); @@ -5014,7 +5217,7 @@ void RasterizerSceneGLES3::initialize() { { //reflection cubemaps int max_reflection_cubemap_sampler_size = 512; - int cube_size = max_reflection_cubemap_sampler_size; + int rcube_size = max_reflection_cubemap_sampler_size; glActiveTexture(GL_TEXTURE0); @@ -5024,10 +5227,10 @@ void RasterizerSceneGLES3::initialize() { GLenum format = GL_RGBA; GLenum type = use_float ? GL_HALF_FLOAT : GL_UNSIGNED_INT_2_10_10_10_REV; - while (cube_size >= 32) { + while (rcube_size >= 32) { ReflectionCubeMap cube; - cube.size = cube_size; + cube.size = rcube_size; glGenTextures(1, &cube.depth); glBindTexture(GL_TEXTURE_2D, cube.depth); @@ -5066,13 +5269,14 @@ void RasterizerSceneGLES3::initialize() { reflection_cubemaps.push_back(cube); - cube_size >>= 1; + rcube_size >>= 1; } } { uint32_t immediate_buffer_size = GLOBAL_DEF("rendering/limits/buffers/immediate_buffer_size_kb", 2048); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/buffers/immediate_buffer_size_kb", PropertyInfo(Variant::INT, "rendering/limits/buffers/immediate_buffer_size_kb", PROPERTY_HINT_RANGE, "0,8192,1,or_greater")); glGenBuffers(1, &state.immediate_buffer); glBindBuffer(GL_ARRAY_BUFFER, state.immediate_buffer); @@ -5106,7 +5310,7 @@ void RasterizerSceneGLES3::initialize() { GLOBAL_DEF("rendering/quality/subsurface_scattering/follow_surface", false); GLOBAL_DEF("rendering/quality/subsurface_scattering/weight_samples", true); - GLOBAL_DEF("rendering/quality/voxel_cone_tracing/high_quality", true); + GLOBAL_DEF("rendering/quality/voxel_cone_tracing/high_quality", false); } exposure_shrink_size = 243; @@ -5121,12 +5325,15 @@ void RasterizerSceneGLES3::initialize() { glGenTextures(1, &e.color); glBindTexture(GL_TEXTURE_2D, e.color); -#ifdef IPHONE_ENABLED - ///@TODO ugly hack to get around iOS not supporting 32bit single channel floating point textures... - glTexImage2D(GL_TEXTURE_2D, 0, GL_R16F, max_exposure_shrink_size, max_exposure_shrink_size, 0, GL_RED, GL_FLOAT, NULL); -#else - glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, max_exposure_shrink_size, max_exposure_shrink_size, 0, GL_RED, GL_FLOAT, NULL); -#endif + + if (storage->config.framebuffer_float_supported) { + glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, max_exposure_shrink_size, max_exposure_shrink_size, 0, GL_RED, GL_FLOAT, NULL); + } else if (storage->config.framebuffer_half_float_supported) { + glTexImage2D(GL_TEXTURE_2D, 0, GL_R16F, max_exposure_shrink_size, max_exposure_shrink_size, 0, GL_RED, GL_HALF_FLOAT, NULL); + } else { + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB10_A2, max_exposure_shrink_size, max_exposure_shrink_size, 0, GL_RED, GL_UNSIGNED_INT_2_10_10_10_REV, NULL); + } + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, e.color, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index b4c4a0558f..3d09adcfeb 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -114,7 +114,7 @@ public: TonemapShaderGLES3 tonemap_shader; struct SceneDataUBO { - //this is a std140 compatible struct. Please read the OpenGL 3.3 Specificaiton spec before doing any changes + //this is a std140 compatible struct. Please read the OpenGL 3.3 Specification spec before doing any changes float projection_matrix[16]; float inv_projection_matrix[16]; float camera_inverse_matrix[16]; @@ -145,6 +145,8 @@ public: uint32_t fog_depth_enabled; float fog_depth_begin; + float fog_depth_end; + float fog_density; float fog_depth_curve; uint32_t fog_transmit_enabled; float fog_transmit_curve; @@ -202,7 +204,12 @@ public: bool cull_disabled; bool used_sss; bool used_screen_texture; - bool using_contact_shadows; + + bool used_depth_prepass; + + bool used_depth_texture; + bool prepared_depth_texture; + bool bound_depth_texture; VS::ViewportDebugDraw debug_draw; } state; @@ -363,11 +370,14 @@ public: RID sky; float sky_custom_fov; + Basis sky_orientation; Color bg_color; float bg_energy; float sky_ambient; + int camera_feed_id; + Color ambient_color; float ambient_energy; float ambient_sky_contribution; @@ -402,6 +412,7 @@ public: VS::EnvironmentGlowBlendMode glow_blend_mode; float glow_hdr_bleed_threshold; float glow_hdr_bleed_scale; + float glow_hdr_luminance_cap; bool glow_bicubic_upscale; VS::EnvironmentToneMapper tone_mapper; @@ -438,6 +449,7 @@ public: bool fog_depth_enabled; float fog_depth_begin; + float fog_depth_end; float fog_depth_curve; bool fog_transmit_enabled; float fog_transmit_curve; @@ -446,87 +458,78 @@ public: float fog_height_max; float fog_height_curve; - 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; - - ssr_enabled = false; - ssr_max_steps = 64; - ssr_fade_in = 0.15; - ssr_fade_out = 2.0; - ssr_depth_tolerance = 0.2; - ssr_roughness = true; - - ssao_enabled = false; - ssao_intensity = 1.0; - ssao_radius = 1.0; - ssao_intensity2 = 1.0; - ssao_radius2 = 0.0; - ssao_bias = 0.01; - ssao_light_affect = 0; - ssao_ao_channel_affect = 0; - ssao_filter = VS::ENV_SSAO_BLUR_3x3; - ssao_quality = VS::ENV_SSAO_QUALITY_LOW; - ssao_bilateral_sharpness = 4; - - tone_mapper = VS::ENV_TONE_MAPPER_LINEAR; - tone_mapper_exposure = 1.0; - tone_mapper_exposure_white = 1.0; - auto_exposure = false; - auto_exposure_speed = 0.5; - auto_exposure_min = 0.05; - auto_exposure_max = 8; - auto_exposure_grey = 0.4; - - glow_enabled = false; - glow_levels = (1 << 2) | (1 << 4); - glow_intensity = 0.8; - glow_strength = 1.0; - glow_bloom = 0.0; - glow_blend_mode = VS::GLOW_BLEND_MODE_SOFTLIGHT; - glow_hdr_bleed_threshold = 1.0; - glow_hdr_bleed_scale = 2.0; - glow_bicubic_upscale = false; - - dof_blur_far_enabled = false; - dof_blur_far_distance = 10; - dof_blur_far_transition = 5; - dof_blur_far_amount = 0.1; - dof_blur_far_quality = VS::ENV_DOF_BLUR_QUALITY_MEDIUM; - - dof_blur_near_enabled = false; - dof_blur_near_distance = 2; - dof_blur_near_transition = 1; - dof_blur_near_amount = 0.1; - dof_blur_near_quality = VS::ENV_DOF_BLUR_QUALITY_MEDIUM; - - adjustments_enabled = false; - adjustments_brightness = 1.0; - adjustments_contrast = 1.0; - adjustments_saturation = 1.0; - - fog_enabled = false; - fog_color = Color(0.5, 0.5, 0.5); - fog_sun_color = Color(0.8, 0.8, 0.0); - fog_sun_amount = 0; - - fog_depth_enabled = true; - - fog_depth_begin = 10; - fog_depth_curve = 1; - - fog_transmit_enabled = true; - fog_transmit_curve = 1; - - fog_height_enabled = false; - fog_height_min = 0; - fog_height_max = 100; - fog_height_curve = 1; + Environment() : + bg_mode(VS::ENV_BG_CLEAR_COLOR), + sky_custom_fov(0.0), + bg_energy(1.0), + sky_ambient(0), + camera_feed_id(0), + ambient_energy(1.0), + ambient_sky_contribution(0.0), + canvas_max_layer(0), + ssr_enabled(false), + ssr_max_steps(64), + ssr_fade_in(0.15), + ssr_fade_out(2.0), + ssr_depth_tolerance(0.2), + ssr_roughness(true), + ssao_enabled(false), + ssao_intensity(1.0), + ssao_radius(1.0), + ssao_intensity2(1.0), + ssao_radius2(0.0), + ssao_bias(0.01), + ssao_light_affect(0), + ssao_ao_channel_affect(0), + ssao_quality(VS::ENV_SSAO_QUALITY_LOW), + ssao_bilateral_sharpness(4), + ssao_filter(VS::ENV_SSAO_BLUR_3x3), + glow_enabled(false), + glow_levels((1 << 2) | (1 << 4)), + glow_intensity(0.8), + glow_strength(1.0), + glow_bloom(0.0), + glow_blend_mode(VS::GLOW_BLEND_MODE_SOFTLIGHT), + glow_hdr_bleed_threshold(1.0), + glow_hdr_bleed_scale(2.0), + glow_hdr_luminance_cap(12.0), + glow_bicubic_upscale(false), + tone_mapper(VS::ENV_TONE_MAPPER_LINEAR), + tone_mapper_exposure(1.0), + tone_mapper_exposure_white(1.0), + auto_exposure(false), + auto_exposure_speed(0.5), + auto_exposure_min(0.05), + auto_exposure_max(8), + auto_exposure_grey(0.4), + dof_blur_far_enabled(false), + dof_blur_far_distance(10), + dof_blur_far_transition(5), + dof_blur_far_amount(0.1), + dof_blur_far_quality(VS::ENV_DOF_BLUR_QUALITY_MEDIUM), + dof_blur_near_enabled(false), + dof_blur_near_distance(2), + dof_blur_near_transition(1), + dof_blur_near_amount(0.1), + dof_blur_near_quality(VS::ENV_DOF_BLUR_QUALITY_MEDIUM), + adjustments_enabled(false), + adjustments_brightness(1.0), + adjustments_contrast(1.0), + adjustments_saturation(1.0), + fog_enabled(false), + fog_color(Color(0.5, 0.5, 0.5)), + fog_sun_color(Color(0.8, 0.8, 0.0)), + fog_sun_amount(0), + fog_depth_enabled(true), + fog_depth_begin(10), + fog_depth_end(0), + fog_depth_curve(1), + fog_transmit_enabled(true), + fog_transmit_curve(1), + fog_height_enabled(false), + fog_height_min(10), + fog_height_max(0), + fog_height_curve(1) { } }; @@ -537,14 +540,16 @@ public: virtual void environment_set_background(RID p_env, VS::EnvironmentBG p_bg); virtual void environment_set_sky(RID p_env, RID p_sky); virtual void environment_set_sky_custom_fov(RID p_env, float p_scale); + virtual void environment_set_sky_orientation(RID p_env, const Basis &p_orientation); virtual void environment_set_bg_color(RID p_env, const Color &p_color); virtual void environment_set_bg_energy(RID p_env, float p_energy); virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer); virtual void environment_set_ambient_light(RID p_env, const Color &p_color, float p_energy = 1.0, float p_sky_contribution = 0.0); + virtual void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id); virtual void environment_set_dof_blur_near(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, VS::EnvironmentDOFBlurQuality p_quality); virtual void environment_set_dof_blur_far(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, VS::EnvironmentDOFBlurQuality p_quality); - virtual void environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_bloom_threshold, VS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, bool p_bicubic_upscale); + virtual void environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_bloom_threshold, VS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, bool p_bicubic_upscale); virtual void environment_set_fog(RID p_env, bool p_enable, float p_begin, float p_end, RID p_gradient_texture); virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_in, float p_fade_out, float p_depth_tolerance, bool p_roughness); @@ -555,7 +560,7 @@ public: virtual void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, RID p_ramp); virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_color, const Color &p_sun_color, float p_sun_amount); - virtual void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_curve, bool p_transmit, float p_transmit_curve); + virtual void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_end, float p_depth_curve, bool p_transmit, float p_transmit_curve); virtual void environment_set_fog_height(RID p_env, bool p_enable, float p_min_height, float p_max_height, float p_height_curve); virtual bool is_environment(RID p_env); @@ -573,10 +578,15 @@ public: float light_params[4]; //spot attenuation, spot angle, specular, shadow enabled float light_clamp[4]; float light_shadow_color_contact[4]; - float shadow_matrix1[16]; //up to here for spot and omni, rest is for directional - float shadow_matrix2[16]; - float shadow_matrix3[16]; - float shadow_matrix4[16]; + union { + struct { + float matrix1[16]; //up to here for spot and omni, rest is for directional + float matrix2[16]; + float matrix3[16]; + float matrix4[16]; + }; + float matrix[4 * 16]; + } shadow; float shadow_split_offsets[4]; }; @@ -637,9 +647,9 @@ public: Vector3 bounds; Transform transform_to_data; - GIProbeInstance() { - probe = NULL; - tex_cache = 0; + GIProbeInstance() : + probe(NULL), + tex_cache(0) { } }; @@ -659,8 +669,8 @@ public: SORT_FLAG_SKELETON = 1, SORT_FLAG_INSTANCING = 2, MAX_DIRECTIONAL_LIGHTS = 16, - MAX_LIGHTS = 4096, - MAX_REFLECTIONS = 1024, + DEFAULT_MAX_LIGHTS = 4096, + DEFAULT_MAX_REFLECTIONS = 1024, SORT_KEY_PRIORITY_SHIFT = 56, SORT_KEY_PRIORITY_MASK = 0xFF, @@ -691,6 +701,8 @@ public: }; int max_elements; + int max_lights; + int max_reflections; struct Element { @@ -803,6 +815,8 @@ public: RenderList() { max_elements = DEFAULT_MAX_ELEMENTS; + max_lights = DEFAULT_MAX_LIGHTS; + max_reflections = DEFAULT_MAX_REFLECTIONS; } ~RenderList() { @@ -829,9 +843,9 @@ public: _FORCE_INLINE_ void _add_geometry_with_material(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, RasterizerStorageGLES3::Material *p_material, bool p_depth_pass, bool p_shadow_pass); - void _draw_sky(RasterizerStorageGLES3::Sky *p_sky, const CameraMatrix &p_projection, const Transform &p_transform, bool p_vflip, float p_custom_fov, float p_energy); + void _draw_sky(RasterizerStorageGLES3::Sky *p_sky, const CameraMatrix &p_projection, const Transform &p_transform, bool p_vflip, float p_custom_fov, float p_energy, const Basis &p_sky_orientation); - void _setup_environment(Environment *env, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform); + void _setup_environment(Environment *env, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_no_fog = false); void _setup_directional_light(int p_index, const Transform &p_camera_inverse_transform, bool p_use_shadows); void _setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, const CameraMatrix &p_camera_projection, RID p_shadow_atlas); void _setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, const CameraMatrix &p_camera_projection, RID p_reflection_atlas, Environment *p_env); @@ -845,6 +859,9 @@ public: void _render_mrts(Environment *env, const CameraMatrix &p_cam_projection); void _post_process(Environment *env, const CameraMatrix &p_cam_projection); + void _prepare_depth_texture(); + void _bind_depth_texture(); + 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); diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 25e7bd0424..95be67a5b7 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -101,6 +101,23 @@ #define _EXT_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E #define _EXT_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F +#ifndef GLES_OVER_GL +#define glClearDepth glClearDepthf +#endif + +#ifdef __EMSCRIPTEN__ +#include <emscripten/emscripten.h> + +void glGetBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data) { + + /* clang-format off */ + EM_ASM({ + GLctx.getBufferSubData($0, $1, HEAPU8, $2, $3); + }, target, offset, data, size); + /* clang-format on */ +} +#endif + void glTexStorage2DCustom(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type) { #ifdef GLES_OVER_GL @@ -610,6 +627,26 @@ void RasterizerStorageGLES3::texture_allocate(RID p_texture, int p_width, int p_ p_flags &= ~VS::TEXTURE_FLAG_MIPMAPS; // no mipies for video } +#ifndef GLES_OVER_GL + switch (p_format) { + case Image::FORMAT_RF: + case Image::FORMAT_RGF: + case Image::FORMAT_RGBF: + case Image::FORMAT_RGBAF: + case Image::FORMAT_RH: + case Image::FORMAT_RGH: + case Image::FORMAT_RGBH: + case Image::FORMAT_RGBAH: { + if (!config.texture_float_linear_supported) { + // disable linear texture filtering when not supported for float format on some devices (issue #24295) + p_flags &= ~VS::TEXTURE_FLAG_FILTER; + } + } break; + default: { + } + } +#endif + Texture *texture = texture_owner.get(p_texture); ERR_FAIL_COND(!texture); texture->width = p_width; @@ -666,14 +703,18 @@ void RasterizerStorageGLES3::texture_allocate(RID p_texture, int p_width, int p_ int mipmaps = 0; - while (width != 1 && height != 1) { - glTexImage3D(texture->target, 0, internal_format, width, height, depth, 0, format, type, NULL); + while (width > 0 || height > 0 || (p_type == VS::TEXTURE_TYPE_3D && depth > 0)) { + width = MAX(1, width); + height = MAX(1, height); + depth = MAX(1, depth); + + glTexImage3D(texture->target, mipmaps, internal_format, width, height, depth, 0, format, type, NULL); - width = MAX(1, width / 2); - height = MAX(1, height / 2); + width /= 2; + height /= 2; if (p_type == VS::TEXTURE_TYPE_3D) { - depth = MAX(1, depth / 2); + depth /= 2; } mipmaps++; @@ -712,7 +753,11 @@ void RasterizerStorageGLES3::texture_set_data(RID p_texture, const Ref<Image> &p if (config.keep_original_textures && !(texture->flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING)) { texture->images.write[p_layer] = p_image; } - +#ifndef GLES_OVER_GL + if (p_image->is_compressed() && p_image->has_mipmaps() && !p_image->is_size_po2()) { + ERR_PRINTS("Texuture '" + texture->path + "' is compressed, has mipmaps but is not of powerf-of-2 size. This does not work on OpenGL ES 3.0."); + } +#endif Image::Format real_format; Ref<Image> img = _get_gl_image_and_format(p_image, p_image->get_format(), texture->flags, real_format, format, internal_format, type, compressed, srgb); @@ -730,7 +775,7 @@ void RasterizerStorageGLES3::texture_set_data(RID p_texture, const Ref<Image> &p } }; - GLenum blit_target; + GLenum blit_target = GL_TEXTURE_2D; switch (texture->type) { case VS::TEXTURE_TYPE_2D: { @@ -852,8 +897,6 @@ void RasterizerStorageGLES3::texture_set_data(RID p_texture, const Ref<Image> &p int size, ofs; img->get_mipmap_offset_and_size(i, ofs, size); - //print_line("mipmap: "+itos(i)+" size: "+itos(size)+" w: "+itos(mm_w)+", h: "+itos(mm_h)); - if (texture->type == VS::TEXTURE_TYPE_2D || texture->type == VS::TEXTURE_TYPE_CUBEMAP) { if (texture->compressed) { @@ -892,6 +935,9 @@ void RasterizerStorageGLES3::texture_set_data(RID p_texture, const Ref<Image> &p h = MAX(1, h >> 1); } + // Handle array and 3D textures, as those set their data per layer. + tsize *= MAX(texture->alloc_depth, 1); + info.texture_mem -= texture->total_data_size; texture->total_data_size = tsize; info.texture_mem += texture->total_data_size; @@ -948,7 +994,7 @@ void RasterizerStorageGLES3::texture_set_data_partial(RID p_texture, const Ref<I Image::Format real_format; Ref<Image> img = _get_gl_image_and_format(p_sub_img, p_sub_img->get_format(), texture->flags, real_format, format, internal_format, type, compressed, srgb); - GLenum blit_target; + GLenum blit_target = GL_TEXTURE_2D; switch (texture->type) { case VS::TEXTURE_TYPE_2D: { @@ -1017,6 +1063,132 @@ Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, int p_layer) return texture->images[p_layer]; } + // 3D textures and 2D texture arrays need special treatment, as the glGetTexImage reads **the whole** + // texture to host-memory. 3D textures and 2D texture arrays are potentially very big, so reading + // everything just to throw everything but one layer away is A Bad Idea. + // + // Unfortunately, to solve this, the copy shader has to read the data out via a shader and store it + // in a temporary framebuffer. The data from the framebuffer can then be read using glReadPixels. + if (texture->type == VS::TEXTURE_TYPE_2D_ARRAY || texture->type == VS::TEXTURE_TYPE_3D) { + // can't read a layer that doesn't exist + ERR_FAIL_INDEX_V(p_layer, texture->alloc_depth, Ref<Image>()); + + // get some information about the texture + Image::Format real_format; + GLenum gl_format; + GLenum gl_internal_format; + GLenum gl_type; + + bool compressed; + bool srgb; + + _get_gl_image_and_format( + Ref<Image>(), + texture->format, + texture->flags, + real_format, + gl_format, + gl_internal_format, + gl_type, + compressed, + srgb); + + PoolVector<uint8_t> data; + + // TODO need to decide between RgbaUnorm and RgbaFloat32 for output + int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, Image::FORMAT_RGBA8, false); + + data.resize(data_size * 2); // add some more memory at the end, just in case for buggy drivers + PoolVector<uint8_t>::Write wb = data.write(); + + // generate temporary resources + GLuint tmp_fbo; + glGenFramebuffers(1, &tmp_fbo); + + GLuint tmp_color_attachment; + glGenTextures(1, &tmp_color_attachment); + + // now bring the OpenGL context into the correct state + { + glBindFramebuffer(GL_FRAMEBUFFER, tmp_fbo); + + // back color attachment with memory, then set properties + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, tmp_color_attachment); + // TODO support HDR properly + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->alloc_width, texture->alloc_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + // use the color texture as color attachment for this render pass + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tmp_color_attachment, 0); + + // more GL state, wheeeey + glDepthMask(GL_FALSE); + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + glDisable(GL_BLEND); + glDepthFunc(GL_LEQUAL); + glColorMask(1, 1, 1, 1); + + // use volume tex for reading + glActiveTexture(GL_TEXTURE0); + glBindTexture(texture->target, texture->tex_id); + + glViewport(0, 0, texture->alloc_width, texture->alloc_height); + + // set up copy shader for proper use + shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB, !srgb); + shaders.copy.set_conditional(CopyShaderGLES3::USE_TEXTURE3D, texture->type == VS::TEXTURE_TYPE_3D); + shaders.copy.set_conditional(CopyShaderGLES3::USE_TEXTURE2DARRAY, texture->type == VS::TEXTURE_TYPE_2D_ARRAY); + shaders.copy.bind(); + + float layer; + if (texture->type == VS::TEXTURE_TYPE_2D_ARRAY) + layer = (float)p_layer; + else + // calculate the normalized z coordinate for the layer + layer = (float)p_layer / (float)texture->alloc_depth; + + shaders.copy.set_uniform(CopyShaderGLES3::LAYER, layer); + + glBindVertexArray(resources.quadie_array); + } + + // clear color attachment, then perform copy + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + // read the image into the host buffer + glReadPixels(0, 0, texture->alloc_width, texture->alloc_height, GL_RGBA, GL_UNSIGNED_BYTE, &wb[0]); + + // remove temp resources and unset some GL state + { + shaders.copy.set_conditional(CopyShaderGLES3::USE_TEXTURE3D, false); + shaders.copy.set_conditional(CopyShaderGLES3::USE_TEXTURE2DARRAY, false); + shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB, false); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + glDeleteTextures(1, &tmp_color_attachment); + glDeleteFramebuffers(1, &tmp_fbo); + } + + wb.release(); + + data.resize(data_size); + + Image *img = memnew(Image(texture->alloc_width, texture->alloc_height, false, Image::FORMAT_RGBA8, data)); + if (!texture->compressed) { + img->convert(real_format); + } + + return Ref<Image>(img); + } + #ifdef GLES_OVER_GL Image::Format real_format; @@ -1029,7 +1201,7 @@ Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, int p_layer) PoolVector<uint8_t> data; - int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, real_format, texture->mipmaps > 1 ? -1 : 0); + int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, real_format, texture->mipmaps > 1); data.resize(data_size * 2); //add some memory at the end, just in case for buggy drivers PoolVector<uint8_t>::Write wb = data.write(); @@ -1040,14 +1212,9 @@ Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, int p_layer) glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); - //print_line("GET FORMAT: " + Image::get_format_name(texture->format) + " mipmaps: " + itos(texture->mipmaps)); - for (int i = 0; i < texture->mipmaps; i++) { - int ofs = 0; - if (i > 0) { - ofs = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, real_format, i - 1); - } + int ofs = Image::get_image_mipmap_offset(texture->alloc_width, texture->alloc_height, real_format, i); if (texture->compressed) { @@ -1072,7 +1239,7 @@ Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, int p_layer) uint32_t *ptr = (uint32_t *)wb.ptr(); uint32_t num_pixels = data_size / 4; - for (int ofs = 0; ofs < num_pixels; ofs++) { + for (uint32_t ofs = 0; ofs < num_pixels; ofs++) { uint32_t px = ptr[ofs]; uint32_t a = px >> 30 & 0xFF; @@ -1085,17 +1252,84 @@ Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, int p_layer) img_format = real_format; } - wb = PoolVector<uint8_t>::Write(); + wb.release(); data.resize(data_size); - Image *img = memnew(Image(texture->alloc_width, texture->alloc_height, texture->mipmaps > 1 ? true : false, img_format, data)); + Image *img = memnew(Image(texture->alloc_width, texture->alloc_height, texture->mipmaps > 1, img_format, data)); return Ref<Image>(img); #else - ERR_EXPLAIN("Sorry, It's not possible to obtain images back in OpenGL ES"); - ERR_FAIL_V(Ref<Image>()); + Image::Format real_format; + GLenum gl_format; + GLenum gl_internal_format; + GLenum gl_type; + bool compressed; + bool srgb; + _get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, real_format, gl_format, gl_internal_format, gl_type, compressed, srgb); + + PoolVector<uint8_t> data; + + int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, Image::FORMAT_RGBA8, false); + + data.resize(data_size * 2); //add some memory at the end, just in case for buggy drivers + PoolVector<uint8_t>::Write wb = data.write(); + + GLuint temp_framebuffer; + glGenFramebuffers(1, &temp_framebuffer); + + GLuint temp_color_texture; + glGenTextures(1, &temp_color_texture); + + glBindFramebuffer(GL_FRAMEBUFFER, temp_framebuffer); + + glBindTexture(GL_TEXTURE_2D, temp_color_texture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->alloc_width, texture->alloc_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, temp_color_texture, 0); + + glDepthMask(GL_FALSE); + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + glDisable(GL_BLEND); + glDepthFunc(GL_LEQUAL); + glColorMask(1, 1, 1, 1); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, texture->tex_id); + + glViewport(0, 0, texture->alloc_width, texture->alloc_height); + + shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB, !srgb); + shaders.copy.bind(); + + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + glBindVertexArray(resources.quadie_array); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + glBindVertexArray(0); + + glReadPixels(0, 0, texture->alloc_width, texture->alloc_height, GL_RGBA, GL_UNSIGNED_BYTE, &wb[0]); + + shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB, false); + + glDeleteTextures(1, &temp_color_texture); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glDeleteFramebuffers(1, &temp_framebuffer); + + wb.release(); + + data.resize(data_size); + + Image *img = memnew(Image(texture->alloc_width, texture->alloc_height, false, Image::FORMAT_RGBA8, data)); + if (!texture->compressed) { + img->convert(real_format); + } + + return Ref<Image>(img); #endif } @@ -1207,6 +1441,15 @@ uint32_t RasterizerStorageGLES3::texture_get_texid(RID p_texture) const { return texture->tex_id; } +void RasterizerStorageGLES3::texture_bind(RID p_texture, uint32_t p_texture_no) { + + Texture *texture = texture_owner.getornull(p_texture); + + ERR_FAIL_COND(!texture); + + glActiveTexture(GL_TEXTURE0 + p_texture_no); + glBindTexture(texture->target, texture->tex_id); +} uint32_t RasterizerStorageGLES3::texture_get_width(RID p_texture) const { Texture *texture = texture_owner.get(p_texture); @@ -1275,7 +1518,7 @@ void RasterizerStorageGLES3::texture_debug_usage(List<VS::TextureInfo> *r_info) tinfo.format = t->format; tinfo.width = t->alloc_width; tinfo.height = t->alloc_height; - tinfo.depth = 0; + tinfo.depth = t->alloc_depth; tinfo.bytes = t->total_data_size; r_info->push_back(tinfo); } @@ -1322,7 +1565,7 @@ RID RasterizerStorageGLES3::texture_create_radiance_cubemap(RID p_source, int p_ ERR_FAIL_COND_V(!texture, RID()); ERR_FAIL_COND_V(texture->type != VS::TEXTURE_TYPE_CUBEMAP, RID()); - bool use_float = config.hdr_supported; + bool use_float = config.framebuffer_half_float_supported; if (p_resolution < 0) { p_resolution = texture->width; @@ -1461,6 +1704,17 @@ RID RasterizerStorageGLES3::texture_create_radiance_cubemap(RID p_source, int p_ return texture_owner.make_rid(ctex); } +Size2 RasterizerStorageGLES3::texture_size_with_proxy(RID p_texture) const { + + const Texture *texture = texture_owner.getornull(p_texture); + ERR_FAIL_COND_V(!texture, Size2()); + if (texture->proxy) { + return Size2(texture->proxy->width, texture->proxy->height); + } else { + return Size2(texture->width, texture->height); + } +} + void RasterizerStorageGLES3::texture_set_proxy(RID p_texture, RID p_proxy) { Texture *texture = texture_owner.get(p_texture); @@ -1559,7 +1813,7 @@ void RasterizerStorageGLES3::sky_set_texture(RID p_sky, RID p_panorama, int p_ra int array_level = 6; - bool use_float = config.hdr_supported; + bool use_float = config.framebuffer_half_float_supported; GLenum internal_format = use_float ? GL_RGBA16F : GL_RGB10_A2; GLenum format = GL_RGBA; @@ -1671,7 +1925,7 @@ void RasterizerStorageGLES3::sky_set_texture(RID p_sky, RID p_panorama, int p_ra int mm_level = mipmaps; - bool use_float = config.hdr_supported; + bool use_float = config.framebuffer_half_float_supported; GLenum internal_format = use_float ? GL_RGBA16F : GL_RGB10_A2; GLenum format = GL_RGBA; @@ -1811,6 +2065,10 @@ void RasterizerStorageGLES3::_update_shader(Shader *p_shader) const { p_shader->uniforms.clear(); + if (p_shader->code == String()) { + return; //just invalid, but no error + } + ShaderCompilerGLES3::GeneratedCode gen_code; ShaderCompilerGLES3::IdentifierActions *actions = NULL; @@ -1905,11 +2163,14 @@ void RasterizerStorageGLES3::_update_shader(Shader *p_shader) const { actions = &shaders.actions_particles; actions->uniforms = &p_shader->uniforms; } break; + case VS::SHADER_MAX: + break; // Can't happen, but silences warning } Error err = shaders.compiler.compile(p_shader->mode, p_shader->code, actions, p_shader->path, gen_code); - - ERR_FAIL_COND(err != OK); + if (err != OK) { + return; + } p_shader->shader->set_custom_shader_code(p_shader->custom_code_id, gen_code.vertex, gen_code.vertex_global, gen_code.fragment, gen_code.light, gen_code.fragment_global, gen_code.uniforms, gen_code.texture_uniforms, gen_code.defines); @@ -1987,7 +2248,7 @@ void RasterizerStorageGLES3::shader_get_param_list(RID p_shader, List<PropertyIn pi.type = Variant::INT; if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_RANGE) { pi.hint = PROPERTY_HINT_RANGE; - pi.hint_string = rtos(u.hint_range[0]) + "," + rtos(u.hint_range[1]); + pi.hint_string = rtos(u.hint_range[0]) + "," + rtos(u.hint_range[1]) + "," + rtos(u.hint_range[2]); } } break; @@ -2028,6 +2289,14 @@ void RasterizerStorageGLES3::shader_get_param_list(RID p_shader, List<PropertyIn pi.hint = PROPERTY_HINT_RESOURCE_TYPE; pi.hint_string = "Texture"; } break; + case ShaderLanguage::TYPE_SAMPLER2DARRAY: + case ShaderLanguage::TYPE_ISAMPLER2DARRAY: + case ShaderLanguage::TYPE_USAMPLER2DARRAY: { + + pi.type = Variant::OBJECT; + pi.hint = PROPERTY_HINT_RESOURCE_TYPE; + pi.hint_string = "TextureArray"; + } break; case ShaderLanguage::TYPE_SAMPLER3D: case ShaderLanguage::TYPE_ISAMPLER3D: case ShaderLanguage::TYPE_USAMPLER3D: { @@ -2148,8 +2417,9 @@ Variant RasterizerStorageGLES3::material_get_param_default(RID p_material, const if (material->shader) { if (material->shader->uniforms.has(p_param)) { - Vector<ShaderLanguage::ConstantNode::Value> default_value = material->shader->uniforms[p_param].default_value; - return ShaderLanguage::constant_value_to_variant(default_value, material->shader->uniforms[p_param].type); + ShaderLanguage::ShaderNode::Uniform uniform = material->shader->uniforms[p_param]; + Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value; + return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.hint); } } return Variant(); @@ -2253,27 +2523,27 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy int v = value; GLuint *gui = (GLuint *)data; - gui[0] = v & 1 ? GL_TRUE : GL_FALSE; - gui[1] = v & 2 ? GL_TRUE : GL_FALSE; + gui[0] = (v & 1) ? GL_TRUE : GL_FALSE; + gui[1] = (v & 2) ? GL_TRUE : GL_FALSE; } break; case ShaderLanguage::TYPE_BVEC3: { int v = value; GLuint *gui = (GLuint *)data; - gui[0] = v & 1 ? GL_TRUE : GL_FALSE; - gui[1] = v & 2 ? GL_TRUE : GL_FALSE; - gui[2] = v & 4 ? GL_TRUE : GL_FALSE; + gui[0] = (v & 1) ? GL_TRUE : GL_FALSE; + gui[1] = (v & 2) ? GL_TRUE : GL_FALSE; + gui[2] = (v & 4) ? GL_TRUE : GL_FALSE; } break; case ShaderLanguage::TYPE_BVEC4: { int v = value; GLuint *gui = (GLuint *)data; - gui[0] = v & 1 ? GL_TRUE : GL_FALSE; - gui[1] = v & 2 ? GL_TRUE : GL_FALSE; - gui[2] = v & 4 ? GL_TRUE : GL_FALSE; - gui[3] = v & 8 ? GL_TRUE : GL_FALSE; + gui[0] = (v & 1) ? GL_TRUE : GL_FALSE; + gui[1] = (v & 2) ? GL_TRUE : GL_FALSE; + gui[2] = (v & 4) ? GL_TRUE : GL_FALSE; + gui[3] = (v & 8) ? GL_TRUE : GL_FALSE; } break; case ShaderLanguage::TYPE_INT: { @@ -2493,7 +2763,8 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy gui[14] = v.origin.z; gui[15] = 1; } break; - default: {} + default: { + } } } @@ -2661,7 +2932,8 @@ _FORCE_INLINE_ static void _fill_std140_ubo_value(ShaderLanguage::DataType type, gui[i] = value[i].real; } } break; - default: {} + default: { + } } } @@ -2684,7 +2956,9 @@ _FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type, case ShaderLanguage::TYPE_BVEC3: case ShaderLanguage::TYPE_IVEC3: case ShaderLanguage::TYPE_UVEC3: - case ShaderLanguage::TYPE_VEC3: + case ShaderLanguage::TYPE_VEC3: { + zeromem(data, 12); + } break; case ShaderLanguage::TYPE_BVEC4: case ShaderLanguage::TYPE_IVEC4: case ShaderLanguage::TYPE_UVEC4: @@ -2704,7 +2978,8 @@ _FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type, zeromem(data, 64); } break; - default: {} + default: { + } } } @@ -2729,7 +3004,7 @@ void RasterizerStorageGLES3::_update_material(Material *material) { if (material->shader && material->shader->mode == VS::SHADER_SPATIAL) { if (material->shader->spatial.blend_mode == Shader::Spatial::BLEND_MODE_MIX && - (!material->shader->spatial.uses_alpha || (material->shader->spatial.uses_alpha && material->shader->spatial.depth_draw_mode == Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS))) { + (!material->shader->spatial.uses_alpha || material->shader->spatial.depth_draw_mode == Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS)) { can_cast_shadow = true; } @@ -2750,7 +3025,7 @@ void RasterizerStorageGLES3::_update_material(Material *material) { } for (Map<RasterizerScene::InstanceBase *, int>::Element *E = material->instance_owners.front(); E; E = E->next()) { - E->key()->base_material_changed(); + E->key()->base_changed(false, true); } } } @@ -2786,9 +3061,6 @@ void RasterizerStorageGLES3::_update_material(Material *material) { if (E->get().order < 0) continue; // texture, does not go here - //if (material->shader->mode == VS::SHADER_PARTICLES) { - // print_line("uniform " + String(E->key()) + " order " + itos(E->get().order) + " offset " + itos(material->shader->ubo_offsets[E->get().order])); - //} //regular uniform uint8_t *data = &local_ubo[material->shader->ubo_offsets[E->get().order]]; @@ -2922,8 +3194,7 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh, uint32_t p_format, VS: //must have index and bones, both. { uint32_t bones_weight = VS::ARRAY_FORMAT_BONES | VS::ARRAY_FORMAT_WEIGHTS; - ERR_EXPLAIN("Array must have both bones and weights in format or none."); - ERR_FAIL_COND((p_format & bones_weight) && (p_format & bones_weight) != bones_weight); + ERR_FAIL_COND_MSG((p_format & bones_weight) && (p_format & bones_weight) != bones_weight, "Array must have both bones and weights in format or none."); } //bool has_morph = p_blend_shapes.size(); @@ -3176,7 +3447,7 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh, uint32_t p_format, VS: glGenBuffers(1, &surface->vertex_id); glBindBuffer(GL_ARRAY_BUFFER, surface->vertex_id); - glBufferData(GL_ARRAY_BUFFER, array_size, vr.ptr(), p_format & VS::ARRAY_FLAG_USE_DYNAMIC_UPDATE ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, array_size, vr.ptr(), (p_format & VS::ARRAY_FLAG_USE_DYNAMIC_UPDATE) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind if (p_format & VS::ARRAY_FORMAT_INDEX) { @@ -3211,9 +3482,9 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh, uint32_t p_format, VS: continue; if (attribs[i].integer) { - glVertexAttribIPointer(attribs[i].index, attribs[i].size, attribs[i].type, attribs[i].stride, ((uint8_t *)0) + attribs[i].offset); + glVertexAttribIPointer(attribs[i].index, attribs[i].size, attribs[i].type, attribs[i].stride, CAST_INT_TO_UCHAR_PTR(attribs[i].offset)); } else { - glVertexAttribPointer(attribs[i].index, attribs[i].size, attribs[i].type, attribs[i].normalized, attribs[i].stride, ((uint8_t *)0) + attribs[i].offset); + glVertexAttribPointer(attribs[i].index, attribs[i].size, attribs[i].type, attribs[i].normalized, attribs[i].stride, CAST_INT_TO_UCHAR_PTR(attribs[i].offset)); } glEnableVertexAttribArray(attribs[i].index); } @@ -3245,7 +3516,7 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh, uint32_t p_format, VS: if (p_vertex_count < (1 << 16)) { //read 16 bit indices const uint16_t *src_idx = (const uint16_t *)ir.ptr(); - for (int i = 0; i < index_count; i += 6) { + for (int i = 0; i + 5 < index_count; i += 6) { wr[i + 0] = src_idx[i / 2]; wr[i + 1] = src_idx[i / 2 + 1]; @@ -3259,7 +3530,7 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh, uint32_t p_format, VS: //read 16 bit indices const uint32_t *src_idx = (const uint32_t *)ir.ptr(); - for (int i = 0; i < index_count; i += 6) { + for (int i = 0; i + 5 < index_count; i += 6) { wr[i + 0] = src_idx[i / 2]; wr[i + 1] = src_idx[i / 2 + 1]; @@ -3275,7 +3546,7 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh, uint32_t p_format, VS: index_count = p_vertex_count * 2; wf_indices.resize(index_count); PoolVector<uint32_t>::Write wr = wf_indices.write(); - for (int i = 0; i < index_count; i += 6) { + for (int i = 0; i + 5 < index_count; i += 6) { wr[i + 0] = i / 2; wr[i + 1] = i / 2 + 1; @@ -3316,9 +3587,9 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh, uint32_t p_format, VS: continue; if (attribs[i].integer) { - glVertexAttribIPointer(attribs[i].index, attribs[i].size, attribs[i].type, attribs[i].stride, ((uint8_t *)0) + attribs[i].offset); + glVertexAttribIPointer(attribs[i].index, attribs[i].size, attribs[i].type, attribs[i].stride, CAST_INT_TO_UCHAR_PTR(attribs[i].offset)); } else { - glVertexAttribPointer(attribs[i].index, attribs[i].size, attribs[i].type, attribs[i].normalized, attribs[i].stride, ((uint8_t *)0) + attribs[i].offset); + glVertexAttribPointer(attribs[i].index, attribs[i].size, attribs[i].type, attribs[i].normalized, attribs[i].stride, CAST_INT_TO_UCHAR_PTR(attribs[i].offset)); } glEnableVertexAttribArray(attribs[i].index); } @@ -3361,9 +3632,9 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh, uint32_t p_format, VS: continue; if (attribs[j].integer) { - glVertexAttribIPointer(attribs[j].index, attribs[j].size, attribs[j].type, attribs[j].stride, ((uint8_t *)0) + attribs[j].offset); + glVertexAttribIPointer(attribs[j].index, attribs[j].size, attribs[j].type, attribs[j].stride, CAST_INT_TO_UCHAR_PTR(attribs[j].offset)); } else { - glVertexAttribPointer(attribs[j].index, attribs[j].size, attribs[j].type, attribs[j].normalized, attribs[j].stride, ((uint8_t *)0) + attribs[j].offset); + glVertexAttribPointer(attribs[j].index, attribs[j].size, attribs[j].type, attribs[j].normalized, attribs[j].stride, CAST_INT_TO_UCHAR_PTR(attribs[j].offset)); } glEnableVertexAttribArray(attribs[j].index); } @@ -3376,7 +3647,7 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh, uint32_t p_format, VS: } mesh->surfaces.push_back(surface); - mesh->instance_change_notify(); + mesh->instance_change_notify(true, true); info.vertex_mem += surface->total_data_size; } @@ -3390,6 +3661,7 @@ void RasterizerStorageGLES3::mesh_set_blend_shape_count(RID p_mesh, int p_amount ERR_FAIL_COND(p_amount < 0); mesh->blend_shape_count = p_amount; + mesh->instance_change_notify(true, false); } int RasterizerStorageGLES3::mesh_get_blend_shape_count(RID p_mesh) const { @@ -3449,7 +3721,7 @@ void RasterizerStorageGLES3::mesh_surface_set_material(RID p_mesh, int p_surface _material_add_geometry(mesh->surfaces[p_surface]->material, mesh->surfaces[p_surface]); } - mesh->instance_material_change_notify(); + mesh->instance_change_notify(false, true); } RID RasterizerStorageGLES3::mesh_surface_get_material(RID p_mesh, int p_surface) const { @@ -3485,21 +3757,26 @@ PoolVector<uint8_t> RasterizerStorageGLES3::mesh_surface_get_array(RID p_mesh, i Surface *surface = mesh->surfaces[p_surface]; - glBindBuffer(GL_ARRAY_BUFFER, surface->vertex_id); - void *data = glMapBufferRange(GL_ARRAY_BUFFER, 0, surface->array_byte_size, GL_MAP_READ_BIT); - - ERR_FAIL_COND_V(!data, PoolVector<uint8_t>()); - PoolVector<uint8_t> ret; ret.resize(surface->array_byte_size); + glBindBuffer(GL_ARRAY_BUFFER, surface->vertex_id); +#if defined(GLES_OVER_GL) || defined(__EMSCRIPTEN__) + { + PoolVector<uint8_t>::Write w = ret.write(); + glGetBufferSubData(GL_ARRAY_BUFFER, 0, surface->array_byte_size, w.ptr()); + } +#else + void *data = glMapBufferRange(GL_ARRAY_BUFFER, 0, surface->array_byte_size, GL_MAP_READ_BIT); + ERR_FAIL_NULL_V(data, PoolVector<uint8_t>()); { - PoolVector<uint8_t>::Write w = ret.write(); copymem(w.ptr(), data, surface->array_byte_size); } glUnmapBuffer(GL_ARRAY_BUFFER); +#endif + glBindBuffer(GL_ARRAY_BUFFER, 0); return ret; } @@ -3510,23 +3787,29 @@ PoolVector<uint8_t> RasterizerStorageGLES3::mesh_surface_get_index_array(RID p_m Surface *surface = mesh->surfaces[p_surface]; - ERR_FAIL_COND_V(surface->index_array_len == 0, PoolVector<uint8_t>()); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, surface->index_id); - void *data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, surface->index_array_byte_size, GL_MAP_READ_BIT); - - ERR_FAIL_COND_V(!data, PoolVector<uint8_t>()); - PoolVector<uint8_t> ret; ret.resize(surface->index_array_byte_size); - { + if (surface->index_array_byte_size > 0) { + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, surface->index_id); - PoolVector<uint8_t>::Write w = ret.write(); - copymem(w.ptr(), data, surface->index_array_byte_size); - } +#if defined(GLES_OVER_GL) || defined(__EMSCRIPTEN__) + { + PoolVector<uint8_t>::Write w = ret.write(); + glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, surface->index_array_byte_size, w.ptr()); + } +#else + void *data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, surface->index_array_byte_size, GL_MAP_READ_BIT); + ERR_FAIL_NULL_V(data, PoolVector<uint8_t>()); + { + PoolVector<uint8_t>::Write w = ret.write(); + copymem(w.ptr(), data, surface->index_array_byte_size); + } + glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); +#endif - glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + } return ret; } @@ -3568,23 +3851,26 @@ Vector<PoolVector<uint8_t> > RasterizerStorageGLES3::mesh_surface_get_blend_shap for (int i = 0; i < mesh->surfaces[p_surface]->blend_shapes.size(); i++) { - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->surfaces[p_surface]->blend_shapes[i].vertex_id); - void *data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, mesh->surfaces[p_surface]->array_byte_size, GL_MAP_READ_BIT); - - ERR_FAIL_COND_V(!data, Vector<PoolVector<uint8_t> >()); - PoolVector<uint8_t> ret; ret.resize(mesh->surfaces[p_surface]->array_byte_size); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->surfaces[p_surface]->blend_shapes[i].vertex_id); +#if defined(GLES_OVER_GL) || defined(__EMSCRIPTEN__) + { + PoolVector<uint8_t>::Write w = ret.write(); + glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, mesh->surfaces[p_surface]->array_byte_size, w.ptr()); + } +#else + void *data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, mesh->surfaces[p_surface]->array_byte_size, GL_MAP_READ_BIT); + ERR_FAIL_COND_V(!data, Vector<PoolVector<uint8_t> >()); { - PoolVector<uint8_t>::Write w = ret.write(); copymem(w.ptr(), data, mesh->surfaces[p_surface]->array_byte_size); } + glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); +#endif bsarr.push_back(ret); - - glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); } return bsarr; @@ -3633,13 +3919,11 @@ void RasterizerStorageGLES3::mesh_remove_surface(RID p_mesh, int p_surface) { info.vertex_mem -= surface->total_data_size; - mesh->instance_material_change_notify(); - memdelete(surface); mesh->surfaces.remove(p_surface); - mesh->instance_change_notify(); + mesh->instance_change_notify(true, true); } int RasterizerStorageGLES3::mesh_get_surface_count(RID p_mesh) const { @@ -3655,7 +3939,7 @@ void RasterizerStorageGLES3::mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb ERR_FAIL_COND(!mesh); mesh->custom_aabb = p_aabb; - mesh->instance_change_notify(); + mesh->instance_change_notify(true, false); } AABB RasterizerStorageGLES3::mesh_get_custom_aabb(RID p_mesh) const { @@ -3671,12 +3955,14 @@ AABB RasterizerStorageGLES3::mesh_get_aabb(RID p_mesh, RID p_skeleton) const { Mesh *mesh = mesh_owner.get(p_mesh); ERR_FAIL_COND_V(!mesh, AABB()); - if (mesh->custom_aabb != AABB()) + if (mesh->custom_aabb != AABB()) { return mesh->custom_aabb; + } Skeleton *sk = NULL; - if (p_skeleton.is_valid()) + if (p_skeleton.is_valid()) { sk = skeleton_owner.get(p_skeleton); + } AABB aabb; @@ -3715,6 +4001,7 @@ AABB RasterizerStorageGLES3::mesh_get_aabb(RID p_mesh, RID p_skeleton) const { mtx.origin.y = texture[base_ofs + 3]; AABB baabb = mtx.xform(skbones[j]); + if (first) { laabb = baabb; first = false; @@ -3862,7 +4149,7 @@ void RasterizerStorageGLES3::mesh_render_blend_shapes(Surface *s, const float *p for (int ti = 0; ti < mtc; ti++) { float weight = p_weights[ti]; - if (weight < 0.001) //not bother with this one + if (weight < 0.00001) //not bother with this one continue; glBindVertexArray(s->blend_shapes[ti].array_id); @@ -3880,44 +4167,44 @@ void RasterizerStorageGLES3::mesh_render_blend_shapes(Surface *s, const float *p case VS::ARRAY_VERTEX: { if (s->format & VS::ARRAY_FLAG_USE_2D_VERTICES) { - glVertexAttribPointer(i + 8, 2, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)0) + ofs); + glVertexAttribPointer(i + 8, 2, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs)); ofs += 2 * 4; } else { - glVertexAttribPointer(i + 8, 3, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)0) + ofs); + glVertexAttribPointer(i + 8, 3, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs)); ofs += 3 * 4; } } break; case VS::ARRAY_NORMAL: { - glVertexAttribPointer(i + 8, 3, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)0) + ofs); + glVertexAttribPointer(i + 8, 3, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs)); ofs += 3 * 4; } break; case VS::ARRAY_TANGENT: { - glVertexAttribPointer(i + 8, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)0) + ofs); + glVertexAttribPointer(i + 8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs)); ofs += 4 * 4; } break; case VS::ARRAY_COLOR: { - glVertexAttribPointer(i + 8, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)0) + ofs); + glVertexAttribPointer(i + 8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs)); ofs += 4 * 4; } break; case VS::ARRAY_TEX_UV: { - glVertexAttribPointer(i + 8, 2, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)0) + ofs); + glVertexAttribPointer(i + 8, 2, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs)); ofs += 2 * 4; } break; case VS::ARRAY_TEX_UV2: { - glVertexAttribPointer(i + 8, 2, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)0) + ofs); + glVertexAttribPointer(i + 8, 2, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs)); ofs += 2 * 4; } break; case VS::ARRAY_BONES: { - glVertexAttribIPointer(i + 8, 4, GL_UNSIGNED_INT, stride, ((uint8_t *)0) + ofs); + glVertexAttribIPointer(i + 8, 4, GL_UNSIGNED_INT, stride, CAST_INT_TO_UCHAR_PTR(ofs)); ofs += 4 * 4; } break; case VS::ARRAY_WEIGHTS: { - glVertexAttribPointer(i + 8, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)0) + ofs); + glVertexAttribPointer(i + 8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs)); ofs += 4 * 4; } break; @@ -3950,44 +4237,44 @@ void RasterizerStorageGLES3::mesh_render_blend_shapes(Surface *s, const float *p case VS::ARRAY_VERTEX: { if (s->format & VS::ARRAY_FLAG_USE_2D_VERTICES) { - glVertexAttribPointer(i, 2, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)0) + ofs); + glVertexAttribPointer(i, 2, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs)); ofs += 2 * 4; } else { - glVertexAttribPointer(i, 3, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)0) + ofs); + glVertexAttribPointer(i, 3, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs)); ofs += 3 * 4; } } break; case VS::ARRAY_NORMAL: { - glVertexAttribPointer(i, 3, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)0) + ofs); + glVertexAttribPointer(i, 3, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs)); ofs += 3 * 4; } break; case VS::ARRAY_TANGENT: { - glVertexAttribPointer(i, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)0) + ofs); + glVertexAttribPointer(i, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs)); ofs += 4 * 4; } break; case VS::ARRAY_COLOR: { - glVertexAttribPointer(i, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)0) + ofs); + glVertexAttribPointer(i, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs)); ofs += 4 * 4; } break; case VS::ARRAY_TEX_UV: { - glVertexAttribPointer(i, 2, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)0) + ofs); + glVertexAttribPointer(i, 2, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs)); ofs += 2 * 4; } break; case VS::ARRAY_TEX_UV2: { - glVertexAttribPointer(i, 2, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)0) + ofs); + glVertexAttribPointer(i, 2, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs)); ofs += 2 * 4; } break; case VS::ARRAY_BONES: { - glVertexAttribIPointer(i, 4, GL_UNSIGNED_INT, stride, ((uint8_t *)0) + ofs); + glVertexAttribIPointer(i, 4, GL_UNSIGNED_INT, stride, CAST_INT_TO_UCHAR_PTR(ofs)); ofs += 4 * 4; } break; case VS::ARRAY_WEIGHTS: { - glVertexAttribPointer(i, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)0) + ofs); + glVertexAttribPointer(i, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs)); ofs += 4 * 4; } break; @@ -4057,35 +4344,37 @@ void RasterizerStorageGLES3::multimesh_allocate(RID p_multimesh, int p_instances multimesh->data.resize(format_floats * p_instances); + float *dataptr = multimesh->data.ptrw(); + for (int i = 0; i < p_instances * format_floats; i += format_floats) { int color_from = 0; int custom_data_from = 0; if (multimesh->transform_format == VS::MULTIMESH_TRANSFORM_2D) { - multimesh->data.write[i + 0] = 1.0; - multimesh->data.write[i + 1] = 0.0; - multimesh->data.write[i + 2] = 0.0; - multimesh->data.write[i + 3] = 0.0; - multimesh->data.write[i + 4] = 0.0; - multimesh->data.write[i + 5] = 1.0; - multimesh->data.write[i + 6] = 0.0; - multimesh->data.write[i + 7] = 0.0; + dataptr[i + 0] = 1.0; + dataptr[i + 1] = 0.0; + dataptr[i + 2] = 0.0; + dataptr[i + 3] = 0.0; + dataptr[i + 4] = 0.0; + dataptr[i + 5] = 1.0; + dataptr[i + 6] = 0.0; + dataptr[i + 7] = 0.0; color_from = 8; custom_data_from = 8; } else { - multimesh->data.write[i + 0] = 1.0; - multimesh->data.write[i + 1] = 0.0; - multimesh->data.write[i + 2] = 0.0; - multimesh->data.write[i + 3] = 0.0; - multimesh->data.write[i + 4] = 0.0; - multimesh->data.write[i + 5] = 1.0; - multimesh->data.write[i + 6] = 0.0; - multimesh->data.write[i + 7] = 0.0; - multimesh->data.write[i + 8] = 0.0; - multimesh->data.write[i + 9] = 0.0; - multimesh->data.write[i + 10] = 1.0; - multimesh->data.write[i + 11] = 0.0; + dataptr[i + 0] = 1.0; + dataptr[i + 1] = 0.0; + dataptr[i + 2] = 0.0; + dataptr[i + 3] = 0.0; + dataptr[i + 4] = 0.0; + dataptr[i + 5] = 1.0; + dataptr[i + 6] = 0.0; + dataptr[i + 7] = 0.0; + dataptr[i + 8] = 0.0; + dataptr[i + 9] = 0.0; + dataptr[i + 10] = 1.0; + dataptr[i + 11] = 0.0; color_from = 12; custom_data_from = 12; } @@ -4100,14 +4389,14 @@ void RasterizerStorageGLES3::multimesh_allocate(RID p_multimesh, int p_instances } cu; cu.colu = 0xFFFFFFFF; - multimesh->data.write[i + color_from + 0] = cu.colf; + dataptr[i + color_from + 0] = cu.colf; custom_data_from = color_from + 1; } else if (multimesh->color_format == VS::MULTIMESH_COLOR_FLOAT) { - multimesh->data.write[i + color_from + 0] = 1.0; - multimesh->data.write[i + color_from + 1] = 1.0; - multimesh->data.write[i + color_from + 2] = 1.0; - multimesh->data.write[i + color_from + 3] = 1.0; + dataptr[i + color_from + 0] = 1.0; + dataptr[i + color_from + 1] = 1.0; + dataptr[i + color_from + 2] = 1.0; + dataptr[i + color_from + 3] = 1.0; custom_data_from = color_from + 4; } @@ -4121,13 +4410,13 @@ void RasterizerStorageGLES3::multimesh_allocate(RID p_multimesh, int p_instances } cu; cu.colu = 0; - multimesh->data.write[i + custom_data_from + 0] = cu.colf; + dataptr[i + custom_data_from + 0] = cu.colf; } else if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_FLOAT) { - multimesh->data.write[i + custom_data_from + 0] = 0.0; - multimesh->data.write[i + custom_data_from + 1] = 0.0; - multimesh->data.write[i + custom_data_from + 2] = 0.0; - multimesh->data.write[i + custom_data_from + 3] = 0.0; + dataptr[i + custom_data_from + 0] = 0.0; + dataptr[i + custom_data_from + 1] = 0.0; + dataptr[i + custom_data_from + 2] = 0.0; + dataptr[i + custom_data_from + 3] = 0.0; } } @@ -4361,7 +4650,6 @@ Transform2D RasterizerStorageGLES3::multimesh_instance_get_transform_2d(RID p_mu } Color RasterizerStorageGLES3::multimesh_instance_get_color(RID p_multimesh, int p_index) const { - MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); ERR_FAIL_COND_V(!multimesh, Color()); ERR_FAIL_INDEX_V(p_index, multimesh->size, Color()); @@ -4552,7 +4840,7 @@ void RasterizerStorageGLES3::update_dirty_multimeshes() { multimesh->dirty_aabb = false; multimesh->dirty_data = false; - multimesh->instance_change_notify(); + multimesh->instance_change_notify(true, false); multimesh_update_list.remove(multimesh_update_list.first()); } @@ -4663,7 +4951,7 @@ void RasterizerStorageGLES3::immediate_end(RID p_immediate) { im->building = false; - im->instance_change_notify(); + im->instance_change_notify(true, false); } void RasterizerStorageGLES3::immediate_clear(RID p_immediate) { @@ -4672,7 +4960,7 @@ void RasterizerStorageGLES3::immediate_clear(RID p_immediate) { ERR_FAIL_COND(im->building); im->chunks.clear(); - im->instance_change_notify(); + im->instance_change_notify(true, false); } AABB RasterizerStorageGLES3::immediate_get_aabb(RID p_immediate) const { @@ -4687,7 +4975,7 @@ void RasterizerStorageGLES3::immediate_set_material(RID p_immediate, RID p_mater Immediate *im = immediate_owner.get(p_immediate); ERR_FAIL_COND(!im); im->material = p_material; - im->instance_material_change_notify(); + im->instance_change_notify(false, true); } RID RasterizerStorageGLES3::immediate_get_material(RID p_immediate) const { @@ -4893,7 +5181,7 @@ void RasterizerStorageGLES3::update_dirty_skeletons() { } for (Set<RasterizerScene::InstanceBase *>::Element *E = skeleton->instances.front(); E; E = E->next()) { - E->get()->base_changed(); + E->get()->base_changed(true, false); } skeleton_update_list.remove(skeleton_update_list.first()); @@ -4930,6 +5218,7 @@ RID RasterizerStorageGLES3::light_create(VS::LightType p_type) { light->directional_blend_splits = false; light->directional_range_mode = VS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE; light->reverse_cull = false; + light->use_gi = true; light->version = 0; return light_owner.make_rid(light); @@ -4959,8 +5248,10 @@ void RasterizerStorageGLES3::light_set_param(RID p_light, VS::LightParam p_param case VS::LIGHT_PARAM_SHADOW_BIAS: { light->version++; - light->instance_change_notify(); + light->instance_change_notify(true, false); } break; + default: { + } } light->param[p_param] = p_value; @@ -4972,7 +5263,7 @@ void RasterizerStorageGLES3::light_set_shadow(RID p_light, bool p_enabled) { light->shadow = p_enabled; light->version++; - light->instance_change_notify(); + light->instance_change_notify(true, false); } void RasterizerStorageGLES3::light_set_shadow_color(RID p_light, const Color &p_color) { @@ -5005,7 +5296,7 @@ void RasterizerStorageGLES3::light_set_cull_mask(RID p_light, uint32_t p_mask) { light->cull_mask = p_mask; light->version++; - light->instance_change_notify(); + light->instance_change_notify(true, false); } void RasterizerStorageGLES3::light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) { @@ -5014,8 +5305,20 @@ void RasterizerStorageGLES3::light_set_reverse_cull_face_mode(RID p_light, bool ERR_FAIL_COND(!light); light->reverse_cull = p_enabled; + + light->version++; + light->instance_change_notify(true, false); } +void RasterizerStorageGLES3::light_set_use_gi(RID p_light, bool p_enabled) { + Light *light = light_owner.getornull(p_light); + ERR_FAIL_COND(!light); + + light->use_gi = p_enabled; + + light->version++; + light->instance_change_notify(true, false); +} void RasterizerStorageGLES3::light_omni_set_shadow_mode(RID p_light, VS::LightOmniShadowMode p_mode) { Light *light = light_owner.getornull(p_light); @@ -5024,7 +5327,7 @@ void RasterizerStorageGLES3::light_omni_set_shadow_mode(RID p_light, VS::LightOm light->omni_shadow_mode = p_mode; light->version++; - light->instance_change_notify(); + light->instance_change_notify(true, false); } VS::LightOmniShadowMode RasterizerStorageGLES3::light_omni_get_shadow_mode(RID p_light) { @@ -5042,7 +5345,7 @@ void RasterizerStorageGLES3::light_omni_set_shadow_detail(RID p_light, VS::Light light->omni_shadow_detail = p_detail; light->version++; - light->instance_change_notify(); + light->instance_change_notify(true, false); } void RasterizerStorageGLES3::light_directional_set_shadow_mode(RID p_light, VS::LightDirectionalShadowMode p_mode) { @@ -5052,7 +5355,7 @@ void RasterizerStorageGLES3::light_directional_set_shadow_mode(RID p_light, VS:: light->directional_shadow_mode = p_mode; light->version++; - light->instance_change_notify(); + light->instance_change_notify(true, false); } void RasterizerStorageGLES3::light_directional_set_blend_splits(RID p_light, bool p_enable) { @@ -5062,7 +5365,7 @@ void RasterizerStorageGLES3::light_directional_set_blend_splits(RID p_light, boo light->directional_blend_splits = p_enable; light->version++; - light->instance_change_notify(); + light->instance_change_notify(true, false); } bool RasterizerStorageGLES3::light_directional_get_blend_splits(RID p_light) const { @@ -5121,6 +5424,13 @@ Color RasterizerStorageGLES3::light_get_color(RID p_light) { return light->color; } +bool RasterizerStorageGLES3::light_get_use_gi(RID p_light) { + Light *light = light_owner.getornull(p_light); + ERR_FAIL_COND_V(!light, false); + + return light->use_gi; +} + bool RasterizerStorageGLES3::light_has_shadow(RID p_light) const { const Light *light = light_owner.getornull(p_light); @@ -5149,21 +5459,19 @@ AABB RasterizerStorageGLES3::light_get_aabb(RID p_light) const { float len = light->param[VS::LIGHT_PARAM_RANGE]; float size = Math::tan(Math::deg2rad(light->param[VS::LIGHT_PARAM_SPOT_ANGLE])) * len; return AABB(Vector3(-size, -size, -len), Vector3(size * 2, size * 2, len)); - } break; + }; case VS::LIGHT_OMNI: { float r = light->param[VS::LIGHT_PARAM_RANGE]; return AABB(-Vector3(r, r, r), Vector3(r, r, r) * 2); - } break; + }; case VS::LIGHT_DIRECTIONAL: { return AABB(); - } break; - default: {} + }; } ERR_FAIL_V(AABB()); - return AABB(); } /* PROBE API */ @@ -5175,6 +5483,8 @@ RID RasterizerStorageGLES3::reflection_probe_create() { reflection_probe->intensity = 1.0; reflection_probe->interior_ambient = Color(); reflection_probe->interior_ambient_energy = 1.0; + reflection_probe->interior_ambient_probe_contrib = 0.0; + reflection_probe->max_distance = 0; reflection_probe->extents = Vector3(1, 1, 1); reflection_probe->origin_offset = Vector3(0, 0, 0); @@ -5193,7 +5503,7 @@ void RasterizerStorageGLES3::reflection_probe_set_update_mode(RID p_probe, VS::R ERR_FAIL_COND(!reflection_probe); reflection_probe->update_mode = p_mode; - reflection_probe->instance_change_notify(); + reflection_probe->instance_change_notify(true, false); } void RasterizerStorageGLES3::reflection_probe_set_intensity(RID p_probe, float p_intensity) { @@ -5234,7 +5544,7 @@ void RasterizerStorageGLES3::reflection_probe_set_max_distance(RID p_probe, floa ERR_FAIL_COND(!reflection_probe); reflection_probe->max_distance = p_distance; - reflection_probe->instance_change_notify(); + reflection_probe->instance_change_notify(true, false); } void RasterizerStorageGLES3::reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) { @@ -5242,7 +5552,7 @@ void RasterizerStorageGLES3::reflection_probe_set_extents(RID p_probe, const Vec ERR_FAIL_COND(!reflection_probe); reflection_probe->extents = p_extents; - reflection_probe->instance_change_notify(); + reflection_probe->instance_change_notify(true, false); } void RasterizerStorageGLES3::reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) { @@ -5250,7 +5560,7 @@ void RasterizerStorageGLES3::reflection_probe_set_origin_offset(RID p_probe, con ERR_FAIL_COND(!reflection_probe); reflection_probe->origin_offset = p_offset; - reflection_probe->instance_change_notify(); + reflection_probe->instance_change_notify(true, false); } void RasterizerStorageGLES3::reflection_probe_set_as_interior(RID p_probe, bool p_enable) { @@ -5259,6 +5569,7 @@ void RasterizerStorageGLES3::reflection_probe_set_as_interior(RID p_probe, bool ERR_FAIL_COND(!reflection_probe); reflection_probe->interior = p_enable; + reflection_probe->instance_change_notify(true, false); } void RasterizerStorageGLES3::reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) { @@ -5274,7 +5585,7 @@ void RasterizerStorageGLES3::reflection_probe_set_enable_shadows(RID p_probe, bo ERR_FAIL_COND(!reflection_probe); reflection_probe->enable_shadows = p_enable; - reflection_probe->instance_change_notify(); + reflection_probe->instance_change_notify(true, false); } void RasterizerStorageGLES3::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) { @@ -5282,7 +5593,10 @@ void RasterizerStorageGLES3::reflection_probe_set_cull_mask(RID p_probe, uint32_ ERR_FAIL_COND(!reflection_probe); reflection_probe->cull_mask = p_layers; - reflection_probe->instance_change_notify(); + reflection_probe->instance_change_notify(true, false); +} + +void RasterizerStorageGLES3::reflection_probe_set_resolution(RID p_probe, int p_resolution) { } AABB RasterizerStorageGLES3::reflection_probe_get_aabb(RID p_probe) const { @@ -5367,7 +5681,7 @@ void RasterizerStorageGLES3::gi_probe_set_bounds(RID p_probe, const AABB &p_boun gip->bounds = p_bounds; gip->version++; - gip->instance_change_notify(); + gip->instance_change_notify(true, false); } AABB RasterizerStorageGLES3::gi_probe_get_bounds(RID p_probe) const { @@ -5384,7 +5698,7 @@ void RasterizerStorageGLES3::gi_probe_set_cell_size(RID p_probe, float p_size) { gip->cell_size = p_size; gip->version++; - gip->instance_change_notify(); + gip->instance_change_notify(true, false); } float RasterizerStorageGLES3::gi_probe_get_cell_size(RID p_probe) const { @@ -5417,7 +5731,7 @@ void RasterizerStorageGLES3::gi_probe_set_dynamic_data(RID p_probe, const PoolVe gip->dynamic_data = p_data; gip->version++; - gip->instance_change_notify(); + gip->instance_change_notify(true, false); } PoolVector<int> RasterizerStorageGLES3::gi_probe_get_dynamic_data(RID p_probe) const { @@ -5649,7 +5963,7 @@ void RasterizerStorageGLES3::lightmap_capture_set_bounds(RID p_capture, const AA LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture); ERR_FAIL_COND(!capture); capture->bounds = p_bounds; - capture->instance_change_notify(); + capture->instance_change_notify(true, false); } AABB RasterizerStorageGLES3::lightmap_capture_get_bounds(RID p_capture) const { @@ -5670,7 +5984,7 @@ void RasterizerStorageGLES3::lightmap_capture_set_octree(RID p_capture, const Po PoolVector<uint8_t>::Read r = p_octree.read(); copymem(w.ptr(), r.ptr(), p_octree.size()); } - capture->instance_change_notify(); + capture->instance_change_notify(true, false); } PoolVector<uint8_t> RasterizerStorageGLES3::lightmap_capture_get_octree(RID p_capture) const { @@ -5748,10 +6062,7 @@ void RasterizerStorageGLES3::particles_set_emitting(RID p_particles, bool p_emit Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); - if (p_emitting != particles->emitting) { - // Restart is overridden by set_emitting - particles->restart_request = false; - } + particles->emitting = p_emitting; } @@ -5783,9 +6094,9 @@ void RasterizerStorageGLES3::particles_set_amount(RID p_particles, int p_amount) glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffers[i]); glBufferData(GL_ARRAY_BUFFER, floats * sizeof(float), data, GL_STATIC_DRAW); - for (int i = 0; i < 6; i++) { - glEnableVertexAttribArray(i); - glVertexAttribPointer(i, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 4 * 6, ((uint8_t *)0) + (i * 16)); + for (int j = 0; j < 6; j++) { + glEnableVertexAttribArray(j); + glVertexAttribPointer(j, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 4 * 6, CAST_INT_TO_UCHAR_PTR(j * 16)); } } @@ -5799,7 +6110,7 @@ void RasterizerStorageGLES3::particles_set_amount(RID p_particles, int p_amount) for (int j = 0; j < 6; j++) { glEnableVertexAttribArray(j); - glVertexAttribPointer(j, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 4 * 6, ((uint8_t *)0) + (j * 16)); + glVertexAttribPointer(j, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 4 * 6, CAST_INT_TO_UCHAR_PTR(j * 16)); } particles->particle_valid_histories[i] = false; } @@ -5877,7 +6188,7 @@ void RasterizerStorageGLES3::_particles_update_histories(Particles *particles) { for (int j = 0; j < 6; j++) { glEnableVertexAttribArray(j); - glVertexAttribPointer(j, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 4 * 6, ((uint8_t *)0) + (j * 16)); + glVertexAttribPointer(j, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 4 * 6, CAST_INT_TO_UCHAR_PTR(j * 16)); } particles->particle_valid_histories[i] = false; @@ -5893,7 +6204,7 @@ void RasterizerStorageGLES3::particles_set_custom_aabb(RID p_particles, const AA ERR_FAIL_COND(!particles); particles->custom_aabb = p_aabb; _particles_update_histories(particles); - particles->instance_change_notify(); + particles->instance_change_notify(true, false); } void RasterizerStorageGLES3::particles_set_speed_scale(RID p_particles, float p_scale) { @@ -5983,9 +6294,21 @@ AABB RasterizerStorageGLES3::particles_get_current_aabb(RID p_particles) { const Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND_V(!particles, AABB()); + const float *data; glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffers[0]); - float *data = (float *)glMapBufferRange(GL_ARRAY_BUFFER, 0, particles->amount * 16 * 6, GL_MAP_READ_BIT); +#if defined(GLES_OVER_GL) || defined(__EMSCRIPTEN__) + PoolVector<uint8_t> vector; + vector.resize(particles->amount * 16 * 6); + { + PoolVector<uint8_t>::Write w = vector.write(); + glGetBufferSubData(GL_ARRAY_BUFFER, 0, particles->amount * 16 * 6, w.ptr()); + } + PoolVector<uint8_t>::Read r = vector.read(); + data = reinterpret_cast<const float *>(r.ptr()); +#else + data = (float *)glMapBufferRange(GL_ARRAY_BUFFER, 0, particles->amount * 16 * 6, GL_MAP_READ_BIT); +#endif AABB aabb; Transform inv = particles->emission_transform.affine_inverse(); @@ -6002,7 +6325,13 @@ AABB RasterizerStorageGLES3::particles_get_current_aabb(RID p_particles) { aabb.expand_to(pos); } +#if defined(GLES_OVER_GL) || defined(__EMSCRIPTEN__) + r.release(); + vector = PoolVector<uint8_t>(); +#else glUnmapBuffer(GL_ARRAY_BUFFER); +#endif + glBindBuffer(GL_ARRAY_BUFFER, 0); float longest_axis = 0; @@ -6131,7 +6460,6 @@ void RasterizerStorageGLES3::update_particles() { Particles *particles = particle_update_list.first()->self(); if (particles->restart_request) { - particles->emitting = true; //restart from zero particles->prev_ticks = 0; particles->phase = 0; particles->prev_phase = 0; @@ -6301,12 +6629,19 @@ void RasterizerStorageGLES3::update_particles() { particles->particle_valid_histories[0] = true; } - particles->instance_change_notify(); //make sure shadows are updated + particles->instance_change_notify(true, false); //make sure shadows are updated } glDisable(GL_RASTERIZER_DISCARD); } +bool RasterizerStorageGLES3::particles_is_inactive(RID p_particles) const { + + const Particles *particles = particles_owner.getornull(p_particles); + ERR_FAIL_COND_V(!particles, false); + return !particles->emitting && particles->inactive; +} + //////// void RasterizerStorageGLES3::instance_add_skeleton(RID p_skeleton, RasterizerScene::InstanceBase *p_instance) { @@ -6362,9 +6697,7 @@ void RasterizerStorageGLES3::instance_add_dependency(RID p_base, RasterizerScene ERR_FAIL_COND(!inst); } break; default: { - if (!inst) { - ERR_FAIL(); - } + ERR_FAIL(); } } @@ -6409,15 +6742,10 @@ void RasterizerStorageGLES3::instance_remove_dependency(RID p_base, RasterizerSc ERR_FAIL_COND(!inst); } break; default: { - - if (!inst) { - ERR_FAIL(); - } + ERR_FAIL(); } } - ERR_FAIL_COND(!inst); - inst->instance_list.remove(&p_instance->dependency_item); } @@ -6474,6 +6802,24 @@ void RasterizerStorageGLES3::_render_target_clear(RenderTarget *rt) { glDeleteTextures(1, &rt->exposure.color); rt->exposure.fbo = 0; } + + if (rt->external.fbo != 0) { + // free this + glDeleteFramebuffers(1, &rt->external.fbo); + + // clean up our texture + Texture *t = texture_owner.get(rt->external.texture); + t->alloc_height = 0; + t->alloc_width = 0; + t->width = 0; + t->height = 0; + t->active = false; + texture_owner.free(rt->external.texture); + memdelete(t); + + rt->external.fbo = 0; + } + Texture *tex = texture_owner.get(rt->texture); tex->alloc_height = 0; tex->alloc_width = 0; @@ -6513,7 +6859,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { GLuint color_type; Image::Format image_format; - bool hdr = rt->flags[RENDER_TARGET_HDR] && config.hdr_supported; + bool hdr = rt->flags[RENDER_TARGET_HDR] && config.framebuffer_half_float_supported; //hdr = false; if (!hdr || rt->flags[RENDER_TARGET_NO_3D]) { @@ -6549,8 +6895,9 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { glGenTextures(1, &rt->depth); glBindTexture(GL_TEXTURE_2D, rt->depth); - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, rt->width, rt->height, 0, - GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, rt->width, rt->height, 0, + GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); @@ -6617,9 +6964,9 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { glGenRenderbuffers(1, &rt->buffers.depth); glBindRenderbuffer(GL_RENDERBUFFER, rt->buffers.depth); if (msaa == 0) - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, rt->width, rt->height); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, rt->width, rt->height); else - glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, GL_DEPTH24_STENCIL8, rt->width, rt->height); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, GL_DEPTH_COMPONENT24, rt->width, rt->height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->buffers.depth); @@ -6767,7 +7114,14 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { glGenTextures(1, &rt->exposure.color); glBindTexture(GL_TEXTURE_2D, rt->exposure.color); - glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, 1, 1, 0, GL_RED, GL_FLOAT, NULL); + if (config.framebuffer_float_supported) { + glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, 1, 1, 0, GL_RED, GL_FLOAT, NULL); + } else if (config.framebuffer_half_float_supported) { + glTexImage2D(GL_TEXTURE_2D, 0, GL_R16F, 1, 1, 0, GL_RED, GL_HALF_FLOAT, NULL); + } else { + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB10_A2, 1, 1, 0, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, NULL); + } + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->exposure.color, 0); status = glCheckFramebufferStatus(GL_FRAMEBUFFER); @@ -6825,7 +7179,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, level); glDisable(GL_SCISSOR_TEST); glColorMask(1, 1, 1, 1); - if (rt->buffers.active == false) { + if (!rt->buffers.active) { glDepthMask(GL_TRUE); } @@ -6852,7 +7206,8 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { glViewport(0, 0, rt->effects.mip_maps[i].sizes[j].width, rt->effects.mip_maps[i].sizes[j].height); glClearBufferfv(GL_COLOR, 0, zero); if (used_depth) { - glClearBufferfi(GL_DEPTH_STENCIL, 0, 1.0, 0); + glClearDepth(1.0); + glClear(GL_DEPTH_BUFFER_BIT); } } @@ -6875,6 +7230,7 @@ RID RasterizerStorageGLES3::render_target_create() { Texture *t = memnew(Texture); + t->type = VS::TEXTURE_TYPE_2D; t->flags = 0; t->width = 0; t->height = 0; @@ -6900,6 +7256,10 @@ RID RasterizerStorageGLES3::render_target_create() { return render_target_owner.make_rid(rt); } +void RasterizerStorageGLES3::render_target_set_position(RID p_render_target, int p_x, int p_y) { + //only used in GLES2 +} + void RasterizerStorageGLES3::render_target_set_size(RID p_render_target, int p_width, int p_height) { RenderTarget *rt = render_target_owner.getornull(p_render_target); @@ -6919,7 +7279,99 @@ RID RasterizerStorageGLES3::render_target_get_texture(RID p_render_target) const RenderTarget *rt = render_target_owner.getornull(p_render_target); ERR_FAIL_COND_V(!rt, RID()); - return rt->texture; + if (rt->external.fbo == 0) { + return rt->texture; + } else { + return rt->external.texture; + } +} + +void RasterizerStorageGLES3::render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) { + RenderTarget *rt = render_target_owner.getornull(p_render_target); + ERR_FAIL_COND(!rt); + + if (p_texture_id == 0) { + if (rt->external.fbo != 0) { + // free this + glDeleteFramebuffers(1, &rt->external.fbo); + + // clean up our texture + Texture *t = texture_owner.get(rt->external.texture); + t->alloc_height = 0; + t->alloc_width = 0; + t->width = 0; + t->height = 0; + t->active = false; + texture_owner.free(rt->external.texture); + memdelete(t); + + rt->external.fbo = 0; + } + } else { + Texture *t; + + if (rt->external.fbo == 0) { + // create our fbo + glGenFramebuffers(1, &rt->external.fbo); + glBindFramebuffer(GL_FRAMEBUFFER, rt->external.fbo); + + // allocate a texture + t = memnew(Texture); + + t->type = VS::TEXTURE_TYPE_2D; + t->flags = 0; + t->width = 0; + t->height = 0; + t->alloc_height = 0; + t->alloc_width = 0; + t->format = Image::FORMAT_RGBA8; + t->target = GL_TEXTURE_2D; + t->gl_format_cache = 0; + t->gl_internal_format_cache = 0; + t->gl_type_cache = 0; + t->data_size = 0; + t->compressed = false; + t->srgb = false; + t->total_data_size = 0; + t->ignore_mipmaps = false; + t->mipmaps = 1; + t->active = true; + t->tex_id = 0; + t->render_target = rt; + + rt->external.texture = texture_owner.make_rid(t); + } else { + // bind our frame buffer + glBindFramebuffer(GL_FRAMEBUFFER, rt->external.fbo); + + // find our texture + t = texture_owner.get(rt->external.texture); + } + + // set our texture + t->tex_id = p_texture_id; + + // size shouldn't be different + t->width = rt->width; + t->height = rt->height; + t->alloc_height = rt->width; + t->alloc_width = rt->height; + + // is there a point to setting the internal formats? we don't know them.. + + // set our texture as the destination for our framebuffer + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, p_texture_id, 0); + + // check status and unbind + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo); + + if (status != GL_FRAMEBUFFER_COMPLETE) { + printf("framebuffer fail, status: %x\n", status); + } + + ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE); + } } void RasterizerStorageGLES3::render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) { @@ -6939,7 +7391,8 @@ void RasterizerStorageGLES3::render_target_set_flag(RID p_render_target, RenderT _render_target_allocate(rt); } break; - default: {} + default: { + } } } bool RasterizerStorageGLES3::render_target_was_used(RID p_render_target) { @@ -7200,7 +7653,7 @@ bool RasterizerStorageGLES3::free(RID p_rid) { // delete the texture Shader *shader = shader_owner.get(p_rid); - if (shader->shader) + if (shader->shader && shader->custom_code_id) shader->shader->free_custom_shader(shader->custom_code_id); if (shader->dirty_list.in_list()) @@ -7351,7 +7804,7 @@ bool RasterizerStorageGLES3::free(RID p_rid) { GIProbeData *gi_probe_data = gi_probe_data_owner.get(p_rid); glDeleteTextures(1, &gi_probe_data->tex_id); - gi_probe_owner.free(p_rid); + gi_probe_data_owner.free(p_rid); memdelete(gi_probe_data); } else if (lightmap_capture_data_owner.owns(p_rid)) { @@ -7359,7 +7812,7 @@ bool RasterizerStorageGLES3::free(RID p_rid) { LightmapCapture *lightmap_capture = lightmap_capture_data_owner.get(p_rid); lightmap_capture->instance_remove_deps(); - gi_probe_owner.free(p_rid); + lightmap_capture_data_owner.free(p_rid); memdelete(lightmap_capture); } else if (canvas_occluder_owner.owns(p_rid)) { @@ -7521,15 +7974,21 @@ void RasterizerStorageGLES3::initialize() { config.latc_supported = config.extensions.has("GL_EXT_texture_compression_latc"); config.bptc_supported = config.extensions.has("GL_ARB_texture_compression_bptc"); #ifdef GLES_OVER_GL - config.hdr_supported = true; config.etc2_supported = false; config.s3tc_supported = true; config.rgtc_supported = true; //RGTC - core since OpenGL version 3.0 + config.texture_float_linear_supported = true; + config.framebuffer_float_supported = true; + config.framebuffer_half_float_supported = true; + #else config.etc2_supported = true; - config.hdr_supported = false; config.s3tc_supported = config.extensions.has("GL_EXT_texture_compression_dxt1") || config.extensions.has("GL_EXT_texture_compression_s3tc") || config.extensions.has("WEBGL_compressed_texture_s3tc"); - config.rgtc_supported = config.extensions.has("GL_EXT_texture_compression_rgtc") || config.extensions.has("GL_ARB_texture_compression_rgtc"); + config.rgtc_supported = config.extensions.has("GL_EXT_texture_compression_rgtc") || config.extensions.has("GL_ARB_texture_compression_rgtc") || config.extensions.has("EXT_texture_compression_rgtc"); + config.texture_float_linear_supported = config.extensions.has("GL_OES_texture_float_linear"); + config.framebuffer_float_supported = config.extensions.has("GL_EXT_color_buffer_float"); + config.framebuffer_half_float_supported = config.extensions.has("GL_EXT_color_buffer_half_float") || config.framebuffer_float_supported; + #endif config.pvrtc_supported = config.extensions.has("GL_IMG_texture_compression_pvrtc"); @@ -7609,16 +8068,20 @@ void RasterizerStorageGLES3::initialize() { glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 0); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 0); + + glGenTextures(1, &resources.white_tex_array); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D_ARRAY, resources.white_tex_array); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGB, 8, 8, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); + glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 8, 8, 1, GL_RGB, GL_UNSIGNED_BYTE, whitetexdata); + glGenerateMipmap(GL_TEXTURE_2D_ARRAY); + glBindTexture(GL_TEXTURE_2D, 0); } glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &config.max_texture_image_units); glGetIntegerv(GL_MAX_TEXTURE_SIZE, &config.max_texture_size); -#ifdef GLES_OVER_GL - config.use_rgba_2d_shadows = false; -#else - config.use_rgba_2d_shadows = true; -#endif + config.use_rgba_2d_shadows = !config.framebuffer_float_supported; //generic quadie for copying @@ -7657,7 +8120,7 @@ void RasterizerStorageGLES3::initialize() { glBindBuffer(GL_ARRAY_BUFFER, resources.quadie); glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, 0); glEnableVertexAttribArray(0); - glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, ((uint8_t *)NULL) + 8); + glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, CAST_INT_TO_UCHAR_PTR(8)); glEnableVertexAttribArray(4); glBindVertexArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind @@ -7668,6 +8131,8 @@ void RasterizerStorageGLES3::initialize() { { //transform feedback buffers uint32_t xf_feedback_size = GLOBAL_DEF_RST("rendering/limits/buffers/blend_shape_max_buffer_size_kb", 4096); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/buffers/blend_shape_max_buffer_size_kb", PropertyInfo(Variant::INT, "rendering/limits/buffers/blend_shape_max_buffer_size_kb", PROPERTY_HINT_RANGE, "0,8192,1,or_greater")); + for (int i = 0; i < 2; i++) { glGenBuffers(1, &resources.transform_feedback_buffers[i]); @@ -7681,7 +8146,7 @@ void RasterizerStorageGLES3::initialize() { } shaders.cubemap_filter.init(); - bool ggx_hq = GLOBAL_GET("rendering/quality/reflections/high_quality_ggx.mobile"); + bool ggx_hq = GLOBAL_GET("rendering/quality/reflections/high_quality_ggx"); shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::LOW_QUALITY, !ggx_hq); shaders.particles.init(); @@ -7700,8 +8165,8 @@ void RasterizerStorageGLES3::initialize() { String renderer = (const char *)glGetString(GL_RENDERER); - config.no_depth_prepass = !bool(GLOBAL_GET("rendering/quality/depth_prepass/enable")); - if (!config.no_depth_prepass) { + config.use_depth_prepass = bool(GLOBAL_GET("rendering/quality/depth_prepass/enable")); + if (config.use_depth_prepass) { String vendors = GLOBAL_GET("rendering/quality/depth_prepass/disable_for_vendors"); Vector<String> vendor_match = vendors.split(","); @@ -7711,7 +8176,7 @@ void RasterizerStorageGLES3::initialize() { continue; if (renderer.findn(v) != -1) { - config.no_depth_prepass = true; + config.use_depth_prepass = false; } } } diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index 0bd9c22be5..84632308b4 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -43,6 +43,11 @@ #include "shaders/cubemap_filter.glsl.gen.h" #include "shaders/particles.glsl.gen.h" +// WebGL 2.0 has no MapBufferRange/UnmapBuffer, but offers a non-ES style BufferSubData API instead. +#ifdef __EMSCRIPTEN__ +void glGetBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data); +#endif + class RasterizerCanvasGLES3; class RasterizerSceneGLES3; @@ -77,10 +82,12 @@ public: bool etc2_supported; bool pvrtc_supported; - bool hdr_supported; - bool srgb_decode_supported; + bool texture_float_linear_supported; + bool framebuffer_float_supported; + bool framebuffer_half_float_supported; + bool use_rgba_2d_shadows; float anisotropic_level; @@ -96,7 +103,7 @@ public: bool keep_original_textures; - bool no_depth_prepass; + bool use_depth_prepass; bool force_vertex_shading; } config; @@ -125,6 +132,7 @@ public: GLuint aniso_tex; GLuint white_tex_3d; + GLuint white_tex_array; GLuint quadie; GLuint quadie_array; @@ -175,22 +183,12 @@ public: SelfList<RasterizerScene::InstanceBase>::List instance_list; - _FORCE_INLINE_ void instance_change_notify() { + _FORCE_INLINE_ void instance_change_notify(bool p_aabb, bool p_materials) { 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->self()->base_changed(p_aabb, p_materials); instances = instances->next(); } } @@ -289,29 +287,32 @@ public: VisualServer::TextureDetectCallback detect_normal; void *detect_normal_ud; - Texture() { - - using_srgb = false; - stored_cube_sides = 0; - ignore_mipmaps = false; - render_target = NULL; - flags = width = height = 0; - tex_id = 0; - data_size = 0; - format = Image::FORMAT_L8; - active = false; - compressed = false; - total_data_size = 0; - target = GL_TEXTURE_2D; - mipmaps = 0; - detect_3d = NULL; - detect_3d_ud = NULL; - detect_srgb = NULL; - detect_srgb_ud = NULL; - detect_normal = NULL; - detect_normal_ud = NULL; - proxy = NULL; - redraw_if_visible = false; + Texture() : + proxy(NULL), + flags(0), + width(0), + height(0), + format(Image::FORMAT_L8), + type(VS::TEXTURE_TYPE_2D), + target(GL_TEXTURE_2D), + data_size(0), + compressed(false), + srgb(false), + total_data_size(0), + ignore_mipmaps(false), + mipmaps(0), + active(false), + tex_id(0), + using_srgb(false), + redraw_if_visible(false), + stored_cube_sides(0), + render_target(NULL), + detect_3d(NULL), + detect_3d_ud(NULL), + detect_srgb(NULL), + detect_srgb_ud(NULL), + detect_normal(NULL), + detect_normal_ud(NULL) { } _ALWAYS_INLINE_ Texture *get_ptr() { @@ -357,6 +358,7 @@ public: virtual uint32_t texture_get_height(RID p_texture) const; virtual uint32_t texture_get_depth(RID p_texture) const; virtual void texture_set_size_override(RID p_texture, int p_width, int p_height, int p_depth); + virtual void texture_bind(RID p_texture, uint32_t p_texture_no); virtual void texture_set_path(RID p_texture, const String &p_path); virtual String texture_get_path(RID p_texture) const; @@ -374,6 +376,8 @@ public: virtual void texture_set_detect_normal_callback(RID p_texture, VisualServer::TextureDetectCallback p_callback, void *p_userdata); virtual void texture_set_proxy(RID p_texture, RID p_proxy); + virtual Size2 texture_size_with_proxy(RID p_texture) const; + virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable); /* SKY API */ @@ -443,6 +447,7 @@ public: }; int light_mode; + bool uses_screen_texture; bool uses_screen_uv; bool uses_time; @@ -556,16 +561,16 @@ public: bool is_animated_cache; Material() : + shader(NULL), + ubo_id(0), + ubo_size(0), list(this), - dirty_list(this) { - can_cast_shadow_cache = false; - is_animated_cache = false; - shader = NULL; - line_width = 1.0; - ubo_id = 0; - ubo_size = 0; - last_pass = 0; - render_priority = 0; + dirty_list(this), + line_width(1.0), + render_priority(0), + last_pass(0), + can_cast_shadow_cache(false), + is_animated_cache(false) { } }; @@ -658,40 +663,37 @@ public: bool active; virtual void material_changed_notify() { - mesh->instance_material_change_notify(); + mesh->instance_change_notify(false, true); mesh->update_multimeshes(); } int total_data_size; - Surface() { - - array_byte_size = 0; - index_array_byte_size = 0; - mesh = NULL; - format = 0; - array_id = 0; - vertex_id = 0; - index_id = 0; - array_len = 0; + Surface() : + mesh(NULL), + format(0), + array_id(0), + vertex_id(0), + index_id(0), + index_wireframe_id(0), + array_wireframe_id(0), + instancing_array_wireframe_id(0), + index_wireframe_len(0), + array_len(0), + index_array_len(0), + array_byte_size(0), + index_array_byte_size(0), + primitive(VS::PRIMITIVE_POINTS), + active(false), + total_data_size(0) { type = GEOMETRY_SURFACE; - primitive = VS::PRIMITIVE_POINTS; - index_array_len = 0; - active = false; - - total_data_size = 0; - - index_wireframe_id = 0; - array_wireframe_id = 0; - instancing_array_wireframe_id = 0; - index_wireframe_len = 0; } ~Surface() { } }; - class MultiMesh; + struct MultiMesh; struct Mesh : public GeometryOwner { @@ -706,16 +708,16 @@ public: SelfList<MultiMesh> *mm = multimeshes.first(); while (mm) { - mm->self()->instance_material_change_notify(); + mm->self()->instance_change_notify(false, true); mm = mm->next(); } } - Mesh() { - blend_shape_mode = VS::BLEND_SHAPE_MODE_NORMALIZED; - blend_shape_count = 0; - last_pass = 0; - active = false; + Mesh() : + active(false), + blend_shape_count(0), + blend_shape_mode(VS::BLEND_SHAPE_MODE_NORMALIZED), + last_pass(0) { } }; @@ -783,19 +785,19 @@ public: bool dirty_data; MultiMesh() : + size(0), + transform_format(VS::MULTIMESH_TRANSFORM_2D), + color_format(VS::MULTIMESH_COLOR_NONE), + custom_data_format(VS::MULTIMESH_CUSTOM_DATA_NONE), 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; - buffer = 0; - transform_format = VS::MULTIMESH_TRANSFORM_2D; - color_format = VS::MULTIMESH_COLOR_NONE; - custom_data_format = VS::MULTIMESH_CUSTOM_DATA_NONE; + mesh_list(this), + buffer(0), + visible_instances(-1), + xform_floats(0), + color_floats(0), + custom_data_floats(0), + dirty_aabb(true), + dirty_data(true) { } }; @@ -814,7 +816,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; @@ -892,11 +894,10 @@ public: Transform2D base_transform_2d; Skeleton() : + use_2d(false), + size(0), + texture(0), update_list(this) { - size = 0; - - use_2d = false; - texture = 0; } }; @@ -927,6 +928,7 @@ public: bool shadow; bool negative; bool reverse_cull; + bool use_gi; uint32_t cull_mask; VS::LightOmniShadowMode omni_shadow_mode; VS::LightOmniShadowDetail omni_shadow_detail; @@ -948,6 +950,7 @@ public: virtual void light_set_negative(RID p_light, bool p_enable); virtual void light_set_cull_mask(RID p_light, uint32_t p_mask); virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled); + virtual void light_set_use_gi(RID p_light, bool p_enabled); virtual void light_omni_set_shadow_mode(RID p_light, VS::LightOmniShadowMode p_mode); virtual void light_omni_set_shadow_detail(RID p_light, VS::LightOmniShadowDetail p_detail); @@ -967,6 +970,7 @@ public: virtual VS::LightType light_get_type(RID p_light) const; virtual float light_get_param(RID p_light, VS::LightParam p_param); virtual Color light_get_color(RID p_light); + virtual bool light_get_use_gi(RID p_light); virtual AABB light_get_aabb(RID p_light) const; virtual uint64_t light_get_version(RID p_light) const; @@ -1005,6 +1009,7 @@ public: virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable); virtual void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable); virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers); + virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution); virtual AABB reflection_probe_get_aabb(RID p_probe) const; virtual VS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const; @@ -1176,37 +1181,31 @@ public: Transform emission_transform; Particles() : - particle_element(this) { - cycle_number = 0; - emitting = false; - one_shot = false; - amount = 0; - lifetime = 1.0; - pre_process_time = 0.0; - explosiveness = 0.0; - randomness = 0.0; - use_local_coords = true; - fixed_fps = 0; - fractional_delta = false; - frame_remainder = 0; - histories_enabled = false; - speed_scale = 1.0; - random_seed = 0; - - restart_request = false; - - custom_aabb = AABB(Vector3(-4, -4, -4), Vector3(8, 8, 8)); - - draw_order = VS::PARTICLES_DRAW_ORDER_INDEX; + inactive(true), + inactive_time(0.0), + emitting(false), + one_shot(false), + amount(0), + lifetime(1.0), + pre_process_time(0.0), + explosiveness(0.0), + randomness(0.0), + restart_request(false), + custom_aabb(AABB(Vector3(-4, -4, -4), Vector3(8, 8, 8))), + use_local_coords(true), + draw_order(VS::PARTICLES_DRAW_ORDER_INDEX), + histories_enabled(false), + particle_element(this), + prev_ticks(0), + random_seed(0), + cycle_number(0), + speed_scale(1.0), + fixed_fps(0), + fractional_delta(false), + frame_remainder(0), + clear(true) { particle_buffers[0] = 0; particle_buffers[1] = 0; - - prev_ticks = 0; - - clear = true; - inactive = true; - inactive_time = 0.0; - glGenBuffers(2, particle_buffers); glGenVertexArrays(2, particle_vaos); } @@ -1263,6 +1262,8 @@ public: virtual int particles_get_draw_passes(RID p_particles) const; virtual RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const; + virtual bool particles_is_inactive(RID p_particles) const; + /* INSTANCE */ virtual void instance_add_skeleton(RID p_skeleton, RasterizerScene::InstanceBase *p_instance); @@ -1309,9 +1310,9 @@ public: GLuint color; int levels; - MipMaps() { - color = 0; - levels = 0; + MipMaps() : + color(0), + levels(0) { } }; @@ -1326,10 +1327,10 @@ public: Vector<GLuint> depth_mipmap_fbos; //fbos for depth mipmapsla ver - SSAO() { + SSAO() : + linear_depth(0) { blur_fbo[0] = 0; blur_fbo[1] = 0; - linear_depth = 0; } } ssao; @@ -1341,9 +1342,19 @@ public: GLuint fbo; GLuint color; - Exposure() { fbo = 0; } + Exposure() : + fbo(0) {} } exposure; + // External FBO to render our final result to (mostly used for ARVR) + struct External { + GLuint fbo; + RID texture; + + External() : + fbo(0) {} + } external; + uint64_t last_exposure_tick; int width, height; @@ -1355,26 +1366,23 @@ public: RID texture; - RenderTarget() { - - msaa = VS::VIEWPORT_MSAA_DISABLED; - width = 0; - height = 0; - depth = 0; - fbo = 0; + RenderTarget() : + fbo(0), + depth(0), + last_exposure_tick(0), + width(0), + height(0), + used_in_frame(false), + msaa(VS::VIEWPORT_MSAA_DISABLED) { exposure.fbo = 0; buffers.fbo = 0; - used_in_frame = false; - + external.fbo = 0; for (int i = 0; i < RENDER_TARGET_FLAG_MAX; i++) { flags[i] = false; } flags[RENDER_TARGET_HDR] = true; - buffers.active = false; buffers.effects_active = false; - - last_exposure_tick = 0; } }; @@ -1384,8 +1392,10 @@ public: void _render_target_allocate(RenderTarget *rt); virtual RID render_target_create(); + virtual void render_target_set_position(RID p_render_target, int p_x, int p_y); virtual void render_target_set_size(RID p_render_target, int p_width, int p_height); virtual RID render_target_get_texture(RID p_render_target) const; + virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id); virtual void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value); virtual bool render_target_was_used(RID p_render_target); diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp index 350107de69..7499962da3 100644 --- a/drivers/gles3/shader_compiler_gles3.cpp +++ b/drivers/gles3/shader_compiler_gles3.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -79,6 +79,12 @@ static int _get_datatype_size(SL::DataType p_type) { case SL::TYPE_SAMPLER2D: return 16; case SL::TYPE_ISAMPLER2D: return 16; case SL::TYPE_USAMPLER2D: return 16; + case SL::TYPE_SAMPLER2DARRAY: return 16; + case SL::TYPE_ISAMPLER2DARRAY: return 16; + case SL::TYPE_USAMPLER2DARRAY: return 16; + case SL::TYPE_SAMPLER3D: return 16; + case SL::TYPE_ISAMPLER3D: return 16; + case SL::TYPE_USAMPLER3D: return 16; case SL::TYPE_SAMPLERCUBE: return 16; } @@ -112,6 +118,12 @@ static int _get_datatype_alignment(SL::DataType p_type) { case SL::TYPE_SAMPLER2D: return 16; case SL::TYPE_ISAMPLER2D: return 16; case SL::TYPE_USAMPLER2D: return 16; + case SL::TYPE_SAMPLER2DARRAY: return 16; + case SL::TYPE_ISAMPLER2DARRAY: return 16; + case SL::TYPE_USAMPLER2DARRAY: return 16; + case SL::TYPE_SAMPLER3D: return 16; + case SL::TYPE_ISAMPLER3D: return 16; + case SL::TYPE_USAMPLER3D: return 16; case SL::TYPE_SAMPLERCUBE: return 16; } @@ -121,8 +133,7 @@ static String _interpstr(SL::DataInterpolation p_interp) { switch (p_interp) { case SL::INTERPOLATION_FLAT: return "flat "; - case SL::INTERPOLATION_NO_PERSPECTIVE: return "noperspective "; - case SL::INTERPOLATION_SMOOTH: return "smooth "; + case SL::INTERPOLATION_SMOOTH: return ""; } return ""; } @@ -155,15 +166,17 @@ static String _opstr(SL::Operator p_op) { static String _mkid(const String &p_id) { - return "m_" + p_id; + String id = "m_" + p_id; + return id.replace("__", "_dus_"); //doubleunderscore is reserved in glsl } static String f2sp0(float p_float) { - if (int(p_float) == p_float) - return itos(p_float) + ".0"; - else - return rtoss(p_float); + String num = rtoss(p_float); + if (num.find(".") == -1 && num.find("e") == -1) { + num += ".0"; + } + return num; } static String get_constant_text(SL::DataType p_type, const Vector<SL::ConstantNode::Value> &p_values) { @@ -216,7 +229,7 @@ static String get_constant_text(SL::DataType p_type, const Vector<SL::ConstantNo text += ")"; return text; } break; - case SL::TYPE_FLOAT: return f2sp0(p_values[0].real) + "f"; + case SL::TYPE_FLOAT: return f2sp0(p_values[0].real); case SL::TYPE_VEC2: case SL::TYPE_VEC3: case SL::TYPE_VEC4: { @@ -360,7 +373,7 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener ucode = "uniform "; } - ucode += _prestr(E->get().precission); + ucode += _prestr(E->get().precision); ucode += _typestr(E->get().type); ucode += " " + _mkid(E->key()); ucode += ";\n"; @@ -451,19 +464,38 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener String vcode; String interp_mode = _interpstr(E->get().interpolation); - vcode += _prestr(E->get().precission); + vcode += _prestr(E->get().precision); vcode += _typestr(E->get().type); vcode += " " + _mkid(E->key()); + if (E->get().array_size > 0) { + vcode += "["; + vcode += itos(E->get().array_size); + vcode += "]"; + } vcode += ";\n"; r_gen_code.vertex_global += interp_mode + "out " + vcode; r_gen_code.fragment_global += interp_mode + "in " + vcode; } + for (Map<StringName, SL::ShaderNode::Constant>::Element *E = pnode->constants.front(); E; E = E->next()) { + String gcode; + gcode += "const "; + gcode += _prestr(E->get().precision); + gcode += _typestr(E->get().type); + gcode += " " + _mkid(E->key()); + gcode += "="; + gcode += _dump_node_code(E->get().initializer, p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + gcode += ";\n"; + r_gen_code.vertex_global += gcode; + r_gen_code.fragment_global += gcode; + } + Map<StringName, String> function_code; //code for functions for (int i = 0; i < pnode->functions.size(); i++) { SL::FunctionNode *fnode = pnode->functions[i].function; + current_func_name = fnode->name; function_code[fnode->name] = _dump_node_code(fnode->body, p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); } @@ -528,7 +560,12 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener case SL::Node::TYPE_VARIABLE_DECLARATION: { SL::VariableDeclarationNode *vdnode = (SL::VariableDeclarationNode *)p_node; - String declaration = _prestr(vdnode->precision) + _typestr(vdnode->datatype); + String declaration; + if (vdnode->is_const) { + declaration += "const "; + } + declaration += _prestr(vdnode->precision); + declaration += _typestr(vdnode->datatype); for (int i = 0; i < vdnode->declarations.size(); i++) { if (i > 0) { declaration += ","; @@ -580,6 +617,93 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener } } break; + case SL::Node::TYPE_ARRAY_DECLARATION: { + + SL::ArrayDeclarationNode *adnode = (SL::ArrayDeclarationNode *)p_node; + + String declaration; + if (adnode->is_const) { + declaration += "const "; + } + declaration += _prestr(adnode->precision); + declaration += _typestr(adnode->datatype); + for (int i = 0; i < adnode->declarations.size(); i++) { + if (i > 0) { + declaration += ","; + } else { + declaration += " "; + } + declaration += _mkid(adnode->declarations[i].name); + declaration += "["; + declaration += itos(adnode->declarations[i].size); + declaration += "]"; + int sz = adnode->declarations[i].initializer.size(); + if (sz > 0) { + declaration += "="; + declaration += _typestr(adnode->datatype); + declaration += "["; + declaration += itos(sz); + declaration += "]"; + declaration += "("; + for (int j = 0; j < sz; j++) { + declaration += _dump_node_code(adnode->declarations[i].initializer[j], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + if (j != sz - 1) { + declaration += ", "; + } + } + declaration += ")"; + } + } + + code += declaration; + } break; + case SL::Node::TYPE_ARRAY: { + SL::ArrayNode *anode = (SL::ArrayNode *)p_node; + + if (p_assigning && p_actions.write_flag_pointers.has(anode->name)) { + *p_actions.write_flag_pointers[anode->name] = true; + } + + if (p_default_actions.usage_defines.has(anode->name) && !used_name_defines.has(anode->name)) { + String define = p_default_actions.usage_defines[anode->name]; + if (define.begins_with("@")) { + define = p_default_actions.usage_defines[define.substr(1, define.length())]; + } + r_gen_code.defines.push_back(define.utf8()); + used_name_defines.insert(anode->name); + } + + if (p_actions.usage_flag_pointers.has(anode->name) && !used_flag_pointers.has(anode->name)) { + *p_actions.usage_flag_pointers[anode->name] = true; + used_flag_pointers.insert(anode->name); + } + + if (p_default_actions.renames.has(anode->name)) + code = p_default_actions.renames[anode->name]; + else + code = _mkid(anode->name); + + if (anode->call_expression != NULL) { + code += "."; + code += _dump_node_code(anode->call_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + } + + if (anode->index_expression != NULL) { + code += "["; + code += _dump_node_code(anode->index_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + code += "]"; + } + + if (anode->name == time_name) { + if (current_func_name == vertex_name) { + r_gen_code.uses_vertex_time = true; + } + if (current_func_name == fragment_name || current_func_name == light_name) { + r_gen_code.uses_fragment_time = true; + } + } + + } break; case SL::Node::TYPE_CONSTANT: { SL::ConstantNode *cnode = (SL::ConstantNode *)p_node; return get_constant_text(cnode->datatype, cnode->values); @@ -653,11 +777,13 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener } break; case SL::OP_SELECT_IF: { + code += "("; code += _dump_node_code(onode->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); code += "?"; code += _dump_node_code(onode->arguments[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); code += ":"; code += _dump_node_code(onode->arguments[2], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + code += ")"; } break; @@ -680,6 +806,20 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener code += _mktab(p_level) + "else\n"; code += _dump_node_code(cfnode->blocks[1], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); } + } else if (cfnode->flow_op == SL::FLOW_OP_SWITCH) { + code += _mktab(p_level) + "switch (" + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ")\n"; + code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); + } else if (cfnode->flow_op == SL::FLOW_OP_CASE) { + code += _mktab(p_level) + "case " + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ":\n"; + code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); + } else if (cfnode->flow_op == SL::FLOW_OP_DEFAULT) { + code += _mktab(p_level) + "default:\n"; + code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); + } else if (cfnode->flow_op == SL::FLOW_OP_DO) { + code += _mktab(p_level) + "do"; + code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); + code += _mktab(p_level) + "while (" + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ");"; + } else if (cfnode->flow_op == SL::FLOW_OP_WHILE) { code += _mktab(p_level) + "while (" + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ")\n"; @@ -734,7 +874,7 @@ Error ShaderCompilerGLES3::compile(VS::ShaderMode p_mode, const String &p_code, Vector<String> shader = p_code.split("\n"); for (int i = 0; i < shader.size(); i++) { - print_line(itos(i) + " " + shader[i]); + print_line(itos(i + 1) + " " + shader[i]); } _err_print_error(NULL, p_path.utf8().get_data(), parser.get_error_line(), parser.get_error_text().utf8().get_data(), ERR_HANDLER_SHADER); @@ -772,7 +912,7 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() { /** CANVAS ITEM SHADER **/ actions[VS::SHADER_CANVAS_ITEM].renames["VERTEX"] = "outvec.xy"; - actions[VS::SHADER_CANVAS_ITEM].renames["UV"] = "uv_interp"; + actions[VS::SHADER_CANVAS_ITEM].renames["UV"] = "uv"; actions[VS::SHADER_CANVAS_ITEM].renames["POINT_SIZE"] = "gl_PointSize"; actions[VS::SHADER_CANVAS_ITEM].renames["WORLD_MATRIX"] = "modelview_matrix"; @@ -801,6 +941,7 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() { actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_UV"] = "light_uv"; actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT"] = "light"; actions[VS::SHADER_CANVAS_ITEM].renames["SHADOW_COLOR"] = "shadow_color"; + actions[VS::SHADER_CANVAS_ITEM].renames["SHADOW_VEC"] = "shadow_vec"; actions[VS::SHADER_CANVAS_ITEM].usage_defines["COLOR"] = "#define COLOR_USED\n"; actions[VS::SHADER_CANVAS_ITEM].usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n"; @@ -809,6 +950,7 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() { actions[VS::SHADER_CANVAS_ITEM].usage_defines["NORMAL"] = "#define NORMAL_USED\n"; actions[VS::SHADER_CANVAS_ITEM].usage_defines["NORMALMAP"] = "#define NORMALMAP_USED\n"; actions[VS::SHADER_CANVAS_ITEM].usage_defines["LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n"; + actions[VS::SHADER_CANVAS_ITEM].usage_defines["SHADOW_VEC"] = "#define SHADOW_VEC_USED\n"; actions[VS::SHADER_CANVAS_ITEM].render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n"; /** SPATIAL SHADER **/ @@ -824,6 +966,7 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() { actions[VS::SHADER_SPATIAL].renames["NORMAL"] = "normal"; actions[VS::SHADER_SPATIAL].renames["TANGENT"] = "tangent"; actions[VS::SHADER_SPATIAL].renames["BINORMAL"] = "binormal"; + actions[VS::SHADER_SPATIAL].renames["POSITION"] = "position"; actions[VS::SHADER_SPATIAL].renames["UV"] = "uv_interp"; actions[VS::SHADER_SPATIAL].renames["UV2"] = "uv2_interp"; actions[VS::SHADER_SPATIAL].renames["COLOR"] = "color_interp"; @@ -860,6 +1003,7 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() { actions[VS::SHADER_SPATIAL].renames["SCREEN_UV"] = "screen_uv"; actions[VS::SHADER_SPATIAL].renames["SCREEN_TEXTURE"] = "screen_texture"; actions[VS::SHADER_SPATIAL].renames["DEPTH_TEXTURE"] = "depth_buffer"; + actions[VS::SHADER_SPATIAL].renames["DEPTH"] = "gl_FragDepth"; actions[VS::SHADER_SPATIAL].renames["ALPHA_SCISSOR"] = "alpha_scissor"; actions[VS::SHADER_SPATIAL].renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB"; @@ -888,6 +1032,7 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() { actions[VS::SHADER_SPATIAL].usage_defines["COLOR"] = "#define ENABLE_COLOR_INTERP\n"; actions[VS::SHADER_SPATIAL].usage_defines["INSTANCE_CUSTOM"] = "#define ENABLE_INSTANCE_CUSTOM\n"; actions[VS::SHADER_SPATIAL].usage_defines["ALPHA_SCISSOR"] = "#define ALPHA_SCISSOR_USED\n"; + actions[VS::SHADER_SPATIAL].usage_defines["POSITION"] = "#define OVERRIDE_POSITION\n"; actions[VS::SHADER_SPATIAL].usage_defines["SSS_STRENGTH"] = "#define ENABLE_SSS\n"; actions[VS::SHADER_SPATIAL].usage_defines["TRANSMISSION"] = "#define TRANSMISSION_USED\n"; @@ -927,13 +1072,14 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() { actions[VS::SHADER_SPATIAL].render_mode_defines["specular_disabled"] = "#define SPECULAR_DISABLED\n"; actions[VS::SHADER_SPATIAL].render_mode_defines["shadows_disabled"] = "#define SHADOWS_DISABLED\n"; actions[VS::SHADER_SPATIAL].render_mode_defines["ambient_light_disabled"] = "#define AMBIENT_LIGHT_DISABLED\n"; + actions[VS::SHADER_SPATIAL].render_mode_defines["shadow_to_opacity"] = "#define USE_SHADOW_TO_OPACITY\n"; /* PARTICLES SHADER */ actions[VS::SHADER_PARTICLES].renames["COLOR"] = "out_color"; actions[VS::SHADER_PARTICLES].renames["VELOCITY"] = "out_velocity_active.xyz"; actions[VS::SHADER_PARTICLES].renames["MASS"] = "mass"; - actions[VS::SHADER_PARTICLES].renames["ACTIVE"] = "active"; + actions[VS::SHADER_PARTICLES].renames["ACTIVE"] = "shader_active"; actions[VS::SHADER_PARTICLES].renames["RESTART"] = "restart"; actions[VS::SHADER_PARTICLES].renames["CUSTOM"] = "out_custom"; actions[VS::SHADER_PARTICLES].renames["TRANSFORM"] = "xform"; @@ -946,9 +1092,9 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() { actions[VS::SHADER_PARTICLES].renames["EMISSION_TRANSFORM"] = "emission_transform"; actions[VS::SHADER_PARTICLES].renames["RANDOM_SEED"] = "random_seed"; - actions[VS::SHADER_SPATIAL].render_mode_defines["disable_force"] = "#define DISABLE_FORCE\n"; - actions[VS::SHADER_SPATIAL].render_mode_defines["disable_velocity"] = "#define DISABLE_VELOCITY\n"; - actions[VS::SHADER_SPATIAL].render_mode_defines["keep_data"] = "#define ENABLE_KEEP_DATA\n"; + actions[VS::SHADER_PARTICLES].render_mode_defines["disable_force"] = "#define DISABLE_FORCE\n"; + actions[VS::SHADER_PARTICLES].render_mode_defines["disable_velocity"] = "#define DISABLE_VELOCITY\n"; + actions[VS::SHADER_PARTICLES].render_mode_defines["keep_data"] = "#define ENABLE_KEEP_DATA\n"; vertex_name = "vertex"; fragment_name = "fragment"; diff --git a/drivers/gles3/shader_compiler_gles3.h b/drivers/gles3/shader_compiler_gles3.h index 1f903b8935..79f5c50f88 100644 --- a/drivers/gles3/shader_compiler_gles3.h +++ b/drivers/gles3/shader_compiler_gles3.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp index 799179e8d4..ac911993be 100644 --- a/drivers/gles3/shader_gles3.cpp +++ b/drivers/gles3/shader_gles3.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -133,15 +133,6 @@ bool ShaderGLES3::bind() { active = this; uniforms_dirty = true; - /* - * why on earth is this code here? - for (int i=0;i<texunit_pair_count;i++) { - - glUniform1i(texunit_pairs[i].location, texunit_pairs[i].index); - DEBUG_TEST_ERROR("Uniform 1 i"); - } - -*/ return true; } @@ -219,20 +210,15 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() { strings.push_back("#version 300 es\n"); #endif - int define_line_ofs = 1; - for (int i = 0; i < custom_defines.size(); i++) { strings.push_back(custom_defines[i].get_data()); - define_line_ofs++; } for (int j = 0; j < conditional_count; j++) { bool enable = ((1 << j) & conditional_version.version); strings.push_back(enable ? conditional_defines[j] : ""); - if (enable) - define_line_ofs++; if (enable) { DEBUG_PRINT(conditional_defines[j]); @@ -253,7 +239,6 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() { ERR_FAIL_COND_V(!custom_code_map.has(conditional_version.code_version), NULL); cc = &custom_code_map[conditional_version.code_version]; v.code_version = cc->version; - define_line_ofs += 2; } /* CREATE PROGRAM */ @@ -493,7 +478,7 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() { glDeleteShader(v.vert_id); glDeleteProgram(v.id); v.id = 0; - ERR_FAIL_COND_V(iloglen <= 0, NULL); + ERR_FAIL_COND_V(iloglen < 0, NULL); } if (iloglen == 0) { @@ -565,6 +550,9 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() { glUseProgram(0); v.ok = true; + if (cc) { + cc->versions.insert(conditional_version.version); + } return &v; } @@ -747,8 +735,26 @@ void ShaderGLES3::set_custom_shader(uint32_t p_code_id) { void ShaderGLES3::free_custom_shader(uint32_t p_code_id) { ERR_FAIL_COND(!custom_code_map.has(p_code_id)); - if (conditional_version.code_version == p_code_id) - conditional_version.code_version = 0; //bye + if (conditional_version.code_version == p_code_id) { + conditional_version.code_version = 0; //do not keep using a version that is going away + unbind(); + } + + VersionKey key; + key.code_version = p_code_id; + for (Set<uint32_t>::Element *E = custom_code_map[p_code_id].versions.front(); E; E = E->next()) { + key.version = E->get(); + ERR_CONTINUE(!version_map.has(key)); + Version &v = version_map[key]; + + glDeleteShader(v.vert_id); + glDeleteShader(v.frag_id); + glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); + v.id = 0; + + version_map.erase(key); + } custom_code_map.erase(p_code_id); } diff --git a/drivers/gles3/shader_gles3.h b/drivers/gles3/shader_gles3.h index 9db4942163..d8d49868f4 100644 --- a/drivers/gles3/shader_gles3.h +++ b/drivers/gles3/shader_gles3.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -45,10 +45,6 @@ #include <stdio.h> -/** - @author Juan Linietsky <reduzio@gmail.com> -*/ - class ShaderGLES3 { protected: struct Enum { @@ -117,6 +113,7 @@ private: uint32_t version; Vector<StringName> texture_uniforms; Vector<CharString> custom_defines; + Set<uint32_t> versions; }; struct Version { @@ -128,11 +125,13 @@ private: Vector<GLint> texture_uniform_locations; uint32_t code_version; bool ok; - Version() { - code_version = 0; - ok = false; - uniform_location = NULL; - } + Version() : + id(0), + vert_id(0), + frag_id(0), + uniform_location(NULL), + code_version(0), + ok(false) {} }; Version *version; @@ -286,7 +285,9 @@ private: glUniformMatrix4fv(p_uniform, 1, false, matrix); } break; - default: { ERR_FAIL(); } // do nothing + default: { + ERR_FAIL(); + } // do nothing } } diff --git a/drivers/gles3/shaders/SCsub b/drivers/gles3/shaders/SCsub index f1811fa7b5..27fd1514e7 100644 --- a/drivers/gles3/shaders/SCsub +++ b/drivers/gles3/shaders/SCsub @@ -20,3 +20,4 @@ if 'GLES3_GLSL' in env['BUILDERS']: env.GLES3_GLSL('exposure.glsl'); env.GLES3_GLSL('tonemap.glsl'); env.GLES3_GLSL('particles.glsl'); + env.GLES3_GLSL('lens_distorted.glsl'); diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl index 5203f53fa2..e83f53d648 100644 --- a/drivers/gles3/shaders/canvas.glsl +++ b/drivers/gles3/shaders/canvas.glsl @@ -92,11 +92,6 @@ const bool at_light_pass = true; const bool at_light_pass = false; #endif -#ifdef USE_PARTICLES -uniform int h_frames; -uniform int v_frames; -#endif - #if defined(USE_MATERIAL) /* clang-format off */ @@ -122,7 +117,12 @@ void main() { #ifdef USE_INSTANCING mat4 extra_matrix_instance = extra_matrix * transpose(mat4(instance_xform0, instance_xform1, instance_xform2, vec4(0.0, 0.0, 0.0, 1.0))); color *= instance_color; + +#ifdef USE_INSTANCE_CUSTOM vec4 instance_custom = instance_custom_data; +#else + vec4 instance_custom = vec4(0.0); +#endif #else mat4 extra_matrix_instance = extra_matrix; @@ -146,19 +146,12 @@ void main() { #ifdef USE_PARTICLES //scale by texture size outvec.xy /= color_texpixel_size; - - //compute h and v frames and adjust UV interp for animation - int total_frames = h_frames * v_frames; - int frame = min(int(float(total_frames) * instance_custom.z), total_frames - 1); - float frame_w = 1.0 / float(h_frames); - float frame_h = 1.0 / float(v_frames); - uv_interp.x = uv_interp.x * frame_w + frame_w * float(frame % h_frames); - uv_interp.y = uv_interp.y * frame_h + frame_h * float(frame / h_frames); - #endif #define extra_matrix extra_matrix_instance + //for compatibility with the fragment shader we need to use uv here + vec2 uv = uv_interp; { /* clang-format off */ @@ -167,6 +160,8 @@ VERTEX_SHADER_CODE /* clang-format on */ } + uv_interp = uv; + #ifdef USE_NINEPATCH pixel_size_interp = abs(dst_rect.zw) * vertex; @@ -182,8 +177,10 @@ VERTEX_SHADER_CODE color_interp = color; #ifdef USE_PIXEL_SNAP - outvec.xy = floor(outvec + 0.5).xy; + // precision issue on some hardware creates artifacts within texture + // offset uv by a small amount to avoid + uv_interp += 1e-5; #endif #ifdef USE_SKELETON @@ -348,6 +345,7 @@ void light_compute( inout vec4 light_color, vec2 light_uv, inout vec4 shadow_color, + inout vec2 shadow_vec, vec3 normal, vec2 uv, #if defined(SCREEN_UV_USED) @@ -492,6 +490,7 @@ void main() { #if defined(NORMALMAP_USED) vec3 normal_map = vec3(0.0, 0.0, 1.0); + normal_used = true; #endif /* clang-format off */ @@ -505,7 +504,7 @@ FRAGMENT_SHADER_CODE #endif } #ifdef DEBUG_ENCODED_32 - highp float enc32 = dot(color, highp vec4(1.0 / (256.0 * 256.0 * 256.0), 1.0 / (256.0 * 256.0), 1.0 / 256.0, 1)); + highp float enc32 = dot(color, highp vec4(1.0 / (256.0 * 256.0 * 256.0), 1.0 / (256.0 * 256.0), 1.0 / 256.0, 1.0)); color = vec4(vec3(enc32), 1.0); #endif @@ -514,6 +513,7 @@ FRAGMENT_SHADER_CODE #ifdef USE_LIGHTING vec2 light_vec = transformed_light_uv; + vec2 shadow_vec = transformed_light_uv; if (normal_used) { normal.xy = mat2(local_rot.xy, local_rot.zw) * normal.xy; @@ -541,6 +541,7 @@ FRAGMENT_SHADER_CODE real_light_color, light_uv, real_light_shadow_color, + shadow_vec, normal, uv, #if defined(SCREEN_UV_USED) @@ -559,8 +560,16 @@ FRAGMENT_SHADER_CODE color *= light; #ifdef USE_SHADOWS - light_vec = light_uv_interp.zw; //for shadows - float angle_to_light = -atan(light_vec.x, light_vec.y); +#ifdef SHADOW_VEC_USED + mat3 inverse_light_matrix = mat3(light_matrix); + inverse_light_matrix[0] = normalize(inverse_light_matrix[0]); + inverse_light_matrix[1] = normalize(inverse_light_matrix[1]); + inverse_light_matrix[2] = normalize(inverse_light_matrix[2]); + shadow_vec = (mat3(inverse_light_matrix) * vec3(shadow_vec, 0.0)).xy; +#else + shadow_vec = light_uv_interp.zw; +#endif + float angle_to_light = -atan(shadow_vec.x, shadow_vec.y); float PI = 3.14159265358979323846264; /*int i = int(mod(floor((angle_to_light+7.0*PI/6.0)/(4.0*PI/6.0))+1.0, 3.0)); // +1 pq os indices estao em ordem 2,0,1 nos arrays float ang*/ @@ -571,18 +580,18 @@ FRAGMENT_SHADER_CODE vec2 point; float sh; if (abs_angle < 45.0 * PI / 180.0) { - point = light_vec; + point = shadow_vec; sh = 0.0 + (1.0 / 8.0); } else if (abs_angle > 135.0 * PI / 180.0) { - point = -light_vec; + point = -shadow_vec; sh = 0.5 + (1.0 / 8.0); } else if (angle_to_light > 0.0) { - point = vec2(light_vec.y, -light_vec.x); + point = vec2(shadow_vec.y, -shadow_vec.x); sh = 0.25 + (1.0 / 8.0); } else { - point = vec2(-light_vec.y, light_vec.x); + point = vec2(-shadow_vec.y, shadow_vec.x); sh = 0.75 + (1.0 / 8.0); } @@ -596,7 +605,7 @@ FRAGMENT_SHADER_CODE #ifdef USE_RGBA_SHADOWS -#define SHADOW_DEPTH(m_tex, m_uv) dot(texture((m_tex), (m_uv)), vec4(1.0 / (256.0 * 256.0 * 256.0), 1.0 / (256.0 * 256.0), 1.0 / 256.0, 1)) +#define SHADOW_DEPTH(m_tex, m_uv) dot(texture((m_tex), (m_uv)), vec4(1.0 / (255.0 * 255.0 * 255.0), 1.0 / (255.0 * 255.0), 1.0 / 255.0, 1.0)) #else diff --git a/drivers/gles3/shaders/canvas_shadow.glsl b/drivers/gles3/shaders/canvas_shadow.glsl index 68d0713385..4f706c5505 100644 --- a/drivers/gles3/shaders/canvas_shadow.glsl +++ b/drivers/gles3/shaders/canvas_shadow.glsl @@ -35,8 +35,8 @@ void main() { #ifdef USE_RGBA_SHADOWS - highp vec4 comp = fract(depth * vec4(256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0)); - comp -= comp.xxyz * vec4(0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0); + highp vec4 comp = fract(depth * vec4(255.0 * 255.0 * 255.0, 255.0 * 255.0, 255.0, 1.0)); + comp -= comp.xxyz * vec4(0.0, 1.0 / 255.0, 1.0 / 255.0, 1.0 / 255.0); distance_buf = comp; #else diff --git a/drivers/gles3/shaders/copy.glsl b/drivers/gles3/shaders/copy.glsl index a5637537d2..1952e201aa 100644 --- a/drivers/gles3/shaders/copy.glsl +++ b/drivers/gles3/shaders/copy.glsl @@ -18,10 +18,19 @@ out vec2 uv_interp; out vec2 uv2_interp; +// These definitions are here because the shader-wrapper builder does +// not understand `#elif defined()` +#ifdef USE_DISPLAY_TRANSFORM +#endif + #ifdef USE_COPY_SECTION uniform vec4 copy_section; +#elif defined(USE_DISPLAY_TRANSFORM) + +uniform highp mat4 display_transform; + #endif void main() { @@ -44,6 +53,9 @@ void main() { uv_interp = copy_section.xy + uv_interp * copy_section.zw; gl_Position.xy = (copy_section.xy + (gl_Position.xy * 0.5 + 0.5) * copy_section.zw) * 2.0 - 1.0; +#elif defined(USE_DISPLAY_TRANSFORM) + + uv_interp = (display_transform * vec4(uv_in, 1.0, 1.0)).xy; #endif } @@ -61,24 +73,47 @@ in vec3 cube_interp; #else in vec2 uv_interp; #endif -/* clang-format on */ #ifdef USE_ASYM_PANO uniform highp mat4 pano_transform; uniform highp vec4 asym_proj; #endif +// These definitions are here because the shader-wrapper builder does +// not understand `#elif defined()` +#ifdef USE_TEXTURE3D +#endif +#ifdef USE_TEXTURE2DARRAY +#endif +#ifdef YCBCR_TO_SRGB +#endif + #ifdef USE_CUBEMAP uniform samplerCube source_cube; //texunit:0 +#elif defined(USE_TEXTURE3D) +uniform sampler3D source_3d; //texunit:0 +#elif defined(USE_TEXTURE2DARRAY) +uniform sampler2DArray source_2d_array; //texunit:0 #else uniform sampler2D source; //texunit:0 #endif +#ifdef SEP_CBCR_TEXTURE +uniform sampler2D CbCr; //texunit:1 +#endif + +/* clang-format on */ + +#if defined(USE_TEXTURE3D) || defined(USE_TEXTURE2DARRAY) +uniform float layer; +#endif + #ifdef USE_MULTIPLIER uniform float multiplier; #endif #if defined(USE_PANORAMA) || defined(USE_ASYM_PANO) +uniform highp mat4 sky_transform; vec4 texturePanorama(vec3 normal, sampler2D pano) { @@ -96,7 +131,6 @@ vec4 texturePanorama(vec3 normal, sampler2D pano) { #endif -uniform float stuff; uniform vec2 pixel_size; in vec2 uv2_interp; @@ -121,19 +155,24 @@ void main() { #ifdef USE_PANORAMA - vec4 color = texturePanorama(normalize(cube_interp), source); + vec3 cube_normal = normalize(cube_interp); + cube_normal.z = -cube_normal.z; + cube_normal = mat3(sky_transform) * cube_normal; + cube_normal.z = -cube_normal.z; + + vec4 color = texturePanorama(cube_normal, source); #elif defined(USE_ASYM_PANO) // When an asymmetrical projection matrix is used (applicable for stereoscopic rendering i.e. VR) we need to do this calculation per fragment to get a perspective correct result. - // Note that we're ignoring the x-offset for IPD, with Z sufficiently in the distance it becomes neglectible, as a result we could probably just set cube_normal.z to -1. + // Asymmetrical projection means the center of projection is no longer in the center of the screen but shifted. // The Matrix[2][0] (= asym_proj.x) and Matrix[2][1] (= asym_proj.z) values are what provide the right shift in the image. vec3 cube_normal; - cube_normal.z = -1000000.0; + cube_normal.z = -1.0; cube_normal.x = (cube_normal.z * (-uv_interp.x - asym_proj.x)) / asym_proj.y; cube_normal.y = (cube_normal.z * (-uv_interp.y - asym_proj.z)) / asym_proj.a; - cube_normal = mat3(pano_transform) * cube_normal; + cube_normal = mat3(sky_transform) * mat3(pano_transform) * cube_normal; cube_normal.z = -cube_normal.z; vec4 color = texturePanorama(normalize(cube_normal.xyz), source); @@ -141,14 +180,34 @@ void main() { #elif defined(USE_CUBEMAP) vec4 color = texture(source_cube, normalize(cube_interp)); +#elif defined(USE_TEXTURE3D) + vec4 color = textureLod(source_3d, vec3(uv_interp, layer), 0.0); +#elif defined(USE_TEXTURE2DARRAY) + vec4 color = textureLod(source_2d_array, vec3(uv_interp, layer), 0.0); +#elif defined(SEP_CBCR_TEXTURE) + vec4 color; + color.r = textureLod(source, uv_interp, 0.0).r; + color.gb = textureLod(CbCr, uv_interp, 0.0).rg - vec2(0.5, 0.5); + color.a = 1.0; #else vec4 color = textureLod(source, uv_interp, 0.0); #endif #ifdef LINEAR_TO_SRGB - //regular Linear -> SRGB conversion + // regular Linear -> SRGB conversion vec3 a = vec3(0.055); color.rgb = mix((vec3(1.0) + a) * pow(color.rgb, vec3(1.0 / 2.4)) - a, 12.92 * color.rgb, lessThan(color.rgb, vec3(0.0031308))); + +#elif defined(YCBCR_TO_SRGB) + + // YCbCr -> SRGB conversion + // Using BT.709 which is the standard for HDTV + color.rgb = mat3( + vec3(1.00000, 1.00000, 1.00000), + vec3(0.00000, -0.18732, 1.85560), + vec3(1.57481, -0.46813, 0.00000)) * + color.rgb; + #endif #ifdef SRGB_TO_LINEAR diff --git a/drivers/gles3/shaders/cubemap_filter.glsl b/drivers/gles3/shaders/cubemap_filter.glsl index f65f798ff0..619e29b130 100644 --- a/drivers/gles3/shaders/cubemap_filter.glsl +++ b/drivers/gles3/shaders/cubemap_filter.glsl @@ -163,7 +163,7 @@ vec2 Hammersley(uint i, uint N) { #else -#define SAMPLE_COUNT 512u +#define SAMPLE_COUNT 1024u #endif diff --git a/drivers/gles3/shaders/effect_blur.glsl b/drivers/gles3/shaders/effect_blur.glsl index b67d06bc10..ff5a9f326f 100644 --- a/drivers/gles3/shaders/effect_blur.glsl +++ b/drivers/gles3/shaders/effect_blur.glsl @@ -94,6 +94,7 @@ uniform sampler2D source_dof_original; //texunit:2 uniform float exposure; uniform float white; +uniform highp float luminance_cap; #ifdef GLOW_USE_AUTO_EXPOSURE @@ -116,12 +117,13 @@ void main() { #ifdef GAUSSIAN_HORIZONTAL vec2 pix_size = pixel_size; pix_size *= 0.5; //reading from larger buffer, so use more samples + // sigma 2 vec4 color = textureLod(source_color, uv_interp + vec2(0.0, 0.0) * pix_size, lod) * 0.214607; color += textureLod(source_color, uv_interp + vec2(1.0, 0.0) * pix_size, lod) * 0.189879; - color += textureLod(source_color, uv_interp + vec2(2.0, 0.0) * pix_size, lod) * 0.157305; + color += textureLod(source_color, uv_interp + vec2(2.0, 0.0) * pix_size, lod) * 0.131514; color += textureLod(source_color, uv_interp + vec2(3.0, 0.0) * pix_size, lod) * 0.071303; color += textureLod(source_color, uv_interp + vec2(-1.0, 0.0) * pix_size, lod) * 0.189879; - color += textureLod(source_color, uv_interp + vec2(-2.0, 0.0) * pix_size, lod) * 0.157305; + color += textureLod(source_color, uv_interp + vec2(-2.0, 0.0) * pix_size, lod) * 0.131514; color += textureLod(source_color, uv_interp + vec2(-3.0, 0.0) * pix_size, lod) * 0.071303; frag_color = color; #endif @@ -271,7 +273,7 @@ void main() { float luminance = max(frag_color.r, max(frag_color.g, frag_color.b)); float feedback = max(smoothstep(glow_hdr_threshold, glow_hdr_threshold + glow_hdr_scale, luminance), glow_bloom); - frag_color *= feedback; + frag_color = min(frag_color * feedback, vec4(luminance_cap)); #endif diff --git a/drivers/gles3/shaders/lens_distorted.glsl b/drivers/gles3/shaders/lens_distorted.glsl new file mode 100644 index 0000000000..7b9d0b347f --- /dev/null +++ b/drivers/gles3/shaders/lens_distorted.glsl @@ -0,0 +1,64 @@ +/* clang-format off */ +[vertex] + +layout(location = 0) in highp vec4 vertex_attrib; +/* clang-format on */ + +uniform vec2 offset; +uniform vec2 scale; + +out vec2 uv_interp; + +void main() { + + uv_interp = vertex_attrib.xy * 2.0 - 1.0; + + vec2 v = vertex_attrib.xy * scale + offset; + gl_Position = vec4(v, 0.0, 1.0); +} + +/* clang-format off */ +[fragment] + +uniform sampler2D source; //texunit:0 +/* clang-format on */ + +uniform vec2 eye_center; +uniform float k1; +uniform float k2; +uniform float upscale; +uniform float aspect_ratio; + +in vec2 uv_interp; + +layout(location = 0) out vec4 frag_color; + +void main() { + vec2 coords = uv_interp; + vec2 offset = coords - eye_center; + + // take aspect ratio into account + offset.y /= aspect_ratio; + + // distort + vec2 offset_sq = offset * offset; + float radius_sq = offset_sq.x + offset_sq.y; + float radius_s4 = radius_sq * radius_sq; + float distortion_scale = 1.0 + (k1 * radius_sq) + (k2 * radius_s4); + offset *= distortion_scale; + + // reapply aspect ratio + offset.y *= aspect_ratio; + + // add our eye center back in + coords = offset + eye_center; + coords /= upscale; + + // and check our color + if (coords.x < -1.0 || coords.y < -1.0 || coords.x > 1.0 || coords.y > 1.0) { + frag_color = vec4(0.0, 0.0, 0.0, 1.0); + } else { + coords = (coords + vec2(1.0)) / vec2(2.0); + frag_color = textureLod(source, coords, 0.0); + } +} diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index 7da20dfa00..403de25dd0 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -42,11 +42,9 @@ layout(location = 4) in vec2 uv_attrib; layout(location = 5) in vec2 uv2_attrib; #endif -uniform float normal_mult; - #ifdef USE_SKELETON layout(location = 6) in uvec4 bone_indices; // attrib:6 -layout(location = 7) in vec4 bone_weights; // attrib:7 +layout(location = 7) in highp vec4 bone_weights; // attrib:7 #endif #ifdef USE_INSTANCING @@ -98,6 +96,8 @@ layout(std140) uniform SceneData { // ubo:0 bool fog_depth_enabled; highp float fog_depth_begin; + highp float fog_depth_end; + mediump float fog_density; highp float fog_depth_curve; bool fog_transmit_enabled; highp float fog_transmit_curve; @@ -167,15 +167,61 @@ out vec4 specular_light_interp; void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, float roughness, inout vec3 diffuse, inout vec3 specular) { - float dotNL = max(dot(N, L), 0.0); - diffuse += dotNL * light_color / M_PI; + float NdotL = dot(N, L); + float cNdotL = max(NdotL, 0.0); // clamped NdotL + float NdotV = dot(N, V); + float cNdotV = max(NdotV, 0.0); + +#if defined(DIFFUSE_OREN_NAYAR) + vec3 diffuse_brdf_NL; +#else + float diffuse_brdf_NL; // BRDF times N.L for calculating diffuse radiance +#endif + +#if defined(DIFFUSE_LAMBERT_WRAP) + // energy conserving lambert wrap shader + diffuse_brdf_NL = max(0.0, (NdotL + roughness) / ((1.0 + roughness) * (1.0 + roughness))); + +#elif defined(DIFFUSE_OREN_NAYAR) + + { + // see http://mimosa-pudica.net/improved-oren-nayar.html + float LdotV = dot(L, V); + + float s = LdotV - NdotL * NdotV; + float t = mix(1.0, max(NdotL, NdotV), step(0.0, s)); + + float sigma2 = roughness * roughness; // TODO: this needs checking + vec3 A = 1.0 + sigma2 * (-0.5 / (sigma2 + 0.33) + 0.17 * diffuse_color / (sigma2 + 0.13)); + float B = 0.45 * sigma2 / (sigma2 + 0.09); + + diffuse_brdf_NL = cNdotL * (A + vec3(B) * s / t) * (1.0 / M_PI); + } +#else + // lambert by default for everything else + diffuse_brdf_NL = cNdotL * (1.0 / M_PI); +#endif + + diffuse += light_color * diffuse_brdf_NL; if (roughness > 0.0) { + // D + float specular_brdf_NL = 0.0; + +#if !defined(SPECULAR_DISABLED) + //normalized blinn always unless disabled vec3 H = normalize(V + L); - float dotNH = max(dot(N, H), 0.0); - float intensity = (roughness >= 1.0 ? 1.0 : pow(dotNH, (1.0 - roughness) * 256.0)); - specular += light_color * intensity; + float cNdotH = max(dot(N, H), 0.0); + float cVdotH = max(dot(V, H), 0.0); + float cLdotH = max(dot(L, H), 0.0); + float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25; + float blinn = pow(cNdotH, shininess); + blinn *= (shininess + 8.0) * (1.0 / (8.0 * M_PI)); + specular_brdf_NL = (blinn) / max(4.0 * cNdotV * cNdotL, 0.75); +#endif + + specular += specular_brdf_NL * light_color * (1.0 / M_PI); } } @@ -268,7 +314,7 @@ void main() { highp vec4 vertex = vertex_attrib; // vec4(vertex_attrib.xyz * data_attrib.x,1.0); - mat4 world_matrix = world_transform; + highp mat4 world_matrix = world_transform; #ifdef USE_INSTANCING @@ -278,11 +324,10 @@ void main() { } #endif - vec3 normal = normal_attrib * normal_mult; + vec3 normal = normal_attrib; #if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY) vec3 tangent = tangent_attrib.xyz; - tangent *= normal_mult; float binormalf = tangent_attrib.a; #endif @@ -307,6 +352,10 @@ void main() { uv2_interp = uv2_attrib; #endif +#ifdef OVERRIDE_POSITION + highp vec4 position; +#endif + #if defined(USE_INSTANCING) && defined(ENABLE_INSTANCE_CUSTOM) vec4 instance_custom = instance_custom_data; #else @@ -346,44 +395,46 @@ void main() { ivec4 bone_indicesi = ivec4(bone_indices); // cast to signed int ivec2 tex_ofs = ivec2(bone_indicesi.x % 256, (bone_indicesi.x / 256) * 3); - highp mat3x4 m; - m = mat3x4( + highp mat4 m; + m = mat4( texelFetch(skeleton_texture, tex_ofs, 0), texelFetch(skeleton_texture, tex_ofs + ivec2(0, 1), 0), - texelFetch(skeleton_texture, tex_ofs + ivec2(0, 2), 0)) * + texelFetch(skeleton_texture, tex_ofs + ivec2(0, 2), 0), + vec4(0.0, 0.0, 0.0, 1.0)) * bone_weights.x; tex_ofs = ivec2(bone_indicesi.y % 256, (bone_indicesi.y / 256) * 3); - m += mat3x4( + m += mat4( texelFetch(skeleton_texture, tex_ofs, 0), texelFetch(skeleton_texture, tex_ofs + ivec2(0, 1), 0), - texelFetch(skeleton_texture, tex_ofs + ivec2(0, 2), 0)) * + texelFetch(skeleton_texture, tex_ofs + ivec2(0, 2), 0), + vec4(0.0, 0.0, 0.0, 1.0)) * bone_weights.y; tex_ofs = ivec2(bone_indicesi.z % 256, (bone_indicesi.z / 256) * 3); - m += mat3x4( + m += mat4( texelFetch(skeleton_texture, tex_ofs, 0), texelFetch(skeleton_texture, tex_ofs + ivec2(0, 1), 0), - texelFetch(skeleton_texture, tex_ofs + ivec2(0, 2), 0)) * + texelFetch(skeleton_texture, tex_ofs + ivec2(0, 2), 0), + vec4(0.0, 0.0, 0.0, 1.0)) * bone_weights.z; tex_ofs = ivec2(bone_indicesi.w % 256, (bone_indicesi.w / 256) * 3); - m += mat3x4( + m += mat4( texelFetch(skeleton_texture, tex_ofs, 0), texelFetch(skeleton_texture, tex_ofs + ivec2(0, 1), 0), - texelFetch(skeleton_texture, tex_ofs + ivec2(0, 2), 0)) * + texelFetch(skeleton_texture, tex_ofs + ivec2(0, 2), 0), + vec4(0.0, 0.0, 0.0, 1.0)) * bone_weights.w; - mat4 bone_matrix = transpose(mat4(m[0], m[1], m[2], vec4(0.0, 0.0, 0.0, 1.0))); - - world_matrix = bone_matrix * world_matrix; + world_matrix = world_matrix * transpose(m); } #endif - mat4 modelview = camera_inverse_matrix * world_matrix; + highp mat4 modelview = camera_inverse_matrix * world_matrix; { /* clang-format off */ @@ -462,7 +513,11 @@ VERTEX_SHADER_CODE #endif //RENDER_DEPTH +#ifdef OVERRIDE_POSITION + gl_Position = position; +#else gl_Position = projection_matrix * vec4(vertex_interp, 1.0); +#endif position_interp = gl_Position; @@ -675,6 +730,8 @@ layout(std140) uniform SceneData { bool fog_depth_enabled; highp float fog_depth_begin; + highp float fog_depth_end; + mediump float fog_density; highp float fog_depth_curve; bool fog_transmit_enabled; highp float fog_transmit_curve; @@ -920,13 +977,14 @@ float GTR1(float NdotH, float a) { return (a2 - 1.0) / (M_PI * log(a2) * t); } -vec3 metallic_to_specular_color(float metallic, float specular, vec3 albedo) { - float dielectric = (0.034 * 2.0) * specular; - // energy conservation - return mix(vec3(dielectric), albedo, metallic); // TODO: reference? +vec3 F0(float metallic, float specular, vec3 albedo) { + float dielectric = 0.16 * specular * specular; + // use albedo * metallic as colored specular reflectance at 0 angle for metallic materials; + // see https://google.github.io/filament/Filament.md.html + return mix(vec3(dielectric), albedo, vec3(metallic)); } -void light_compute(vec3 N, vec3 L, vec3 V, vec3 B, vec3 T, vec3 light_color, vec3 attenuation, vec3 diffuse_color, vec3 transmission, float specular_blob_intensity, float roughness, float metallic, float rim, float rim_tint, float clearcoat, float clearcoat_gloss, float anisotropy, inout vec3 diffuse_light, inout vec3 specular_light) { +void light_compute(vec3 N, vec3 L, vec3 V, vec3 B, vec3 T, vec3 light_color, vec3 attenuation, vec3 diffuse_color, vec3 transmission, float specular_blob_intensity, float roughness, float metallic, float specular, float rim, float rim_tint, float clearcoat, float clearcoat_gloss, float anisotropy, inout vec3 diffuse_light, inout vec3 specular_light, inout float alpha) { #if defined(USE_LIGHT_SHADER_CODE) // light is written by the light shader @@ -948,6 +1006,18 @@ LIGHT_SHADER_CODE float NdotV = dot(N, V); float cNdotV = max(NdotV, 0.0); +#if defined(DIFFUSE_BURLEY) || defined(SPECULAR_BLINN) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_USE_CLEARCOAT) + vec3 H = normalize(V + L); +#endif + +#if defined(SPECULAR_BLINN) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_USE_CLEARCOAT) + float cNdotH = max(dot(N, H), 0.0); +#endif + +#if defined(DIFFUSE_BURLEY) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_USE_CLEARCOAT) + float cLdotH = max(dot(L, H), 0.0); +#endif + if (metallic < 1.0) { #if defined(DIFFUSE_OREN_NAYAR) vec3 diffuse_brdf_NL; @@ -982,13 +1052,9 @@ LIGHT_SHADER_CODE #elif defined(DIFFUSE_BURLEY) { - - vec3 H = normalize(V + L); - float cLdotH = max(0.0, dot(L, H)); - - float FD90 = 0.5 + 2.0 * cLdotH * cLdotH * roughness; - float FdV = 1.0 + (FD90 - 1.0) * SchlickFresnel(cNdotV); - float FdL = 1.0 + (FD90 - 1.0) * SchlickFresnel(cNdotL); + float FD90_minus_1 = 2.0 * cLdotH * cLdotH * roughness - 0.5; + float FdV = 1.0 + FD90_minus_1 * SchlickFresnel(cNdotV); + float FdL = 1.0 + FD90_minus_1 * SchlickFresnel(cNdotL); diffuse_brdf_NL = (1.0 / M_PI) * FdV * FdL * cNdotL; /* float energyBias = mix(roughness, 0.0, 0.5); @@ -1025,13 +1091,9 @@ LIGHT_SHADER_CODE #if defined(SPECULAR_BLINN) //normalized blinn - vec3 H = normalize(V + L); - float cNdotH = max(dot(N, H), 0.0); - float cVdotH = max(dot(V, H), 0.0); - float cLdotH = max(dot(L, H), 0.0); float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25; float blinn = pow(cNdotH, shininess); - blinn *= (shininess + 8.0) / (8.0 * 3.141592654); + blinn *= (shininess + 8.0) * (1.0 / (8.0 * M_PI)); float intensity = (blinn) / max(4.0 * cNdotV * cNdotL, 0.75); specular_light += light_color * intensity * specular_blob_intensity * attenuation; @@ -1042,7 +1104,7 @@ LIGHT_SHADER_CODE float cRdotV = max(0.0, dot(R, V)); float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25; float phong = pow(cRdotV, shininess); - phong *= (shininess + 8.0) / (8.0 * 3.141592654); + phong *= (shininess + 8.0) * (1.0 / (8.0 * M_PI)); float intensity = (phong) / max(4.0 * cNdotV * cNdotL, 0.75); specular_light += light_color * intensity * specular_blob_intensity * attenuation; @@ -1062,59 +1124,51 @@ LIGHT_SHADER_CODE #elif defined(SPECULAR_SCHLICK_GGX) // shlick+ggx as default - vec3 H = normalize(V + L); - - float cNdotH = max(dot(N, H), 0.0); - float cLdotH = max(dot(L, H), 0.0); - #if defined(LIGHT_USE_ANISOTROPY) + float alpha_ggx = roughness * roughness; float aspect = sqrt(1.0 - anisotropy * 0.9); - float rx = roughness / aspect; - float ry = roughness * aspect; - float ax = rx * rx; - float ay = ry * ry; + float ax = alpha_ggx / aspect; + float ay = alpha_ggx * aspect; float XdotH = dot(T, H); float YdotH = dot(B, H); float D = D_GGX_anisotropic(cNdotH, ax, ay, XdotH, YdotH); float G = G_GGX_anisotropic_2cos(cNdotL, ax, ay, XdotH, YdotH) * G_GGX_anisotropic_2cos(cNdotV, ax, ay, XdotH, YdotH); #else - float alpha = roughness * roughness; - float D = D_GGX(cNdotH, alpha); - float G = G_GGX_2cos(cNdotL, alpha) * G_GGX_2cos(cNdotV, alpha); + float alpha_ggx = roughness * roughness; + float D = D_GGX(cNdotH, alpha_ggx); + float G = G_GGX_2cos(cNdotL, alpha_ggx) * G_GGX_2cos(cNdotV, alpha_ggx); #endif // F - //float F0 = 1.0; - //float cLdotH5 = SchlickFresnel(cLdotH); - //float F = mix(cLdotH5, 1.0, F0); + vec3 f0 = F0(metallic, specular, diffuse_color); + float cLdotH5 = SchlickFresnel(cLdotH); + vec3 F = mix(vec3(cLdotH5), vec3(1.0), f0); - float specular_brdf_NL = cNdotL * D /* F */ * G; + vec3 specular_brdf_NL = cNdotL * D * F * G; specular_light += specular_brdf_NL * light_color * specular_blob_intensity * attenuation; #endif #if defined(LIGHT_USE_CLEARCOAT) - if (clearcoat_gloss > 0.0) { -#if !defined(SPECULAR_SCHLICK_GGX) && !defined(SPECULAR_BLINN) - vec3 H = normalize(V + L); -#endif + #if !defined(SPECULAR_SCHLICK_GGX) - float cNdotH = max(dot(N, H), 0.0); - float cLdotH = max(dot(L, H), 0.0); - float cLdotH5 = SchlickFresnel(cLdotH); + float cLdotH5 = SchlickFresnel(cLdotH); #endif - float Dr = GTR1(cNdotH, mix(.1, .001, clearcoat_gloss)); - float Fr = mix(.04, 1.0, cLdotH5); - float Gr = G_GGX_2cos(cNdotL, .25) * G_GGX_2cos(cNdotV, .25); + float Dr = GTR1(cNdotH, mix(.1, .001, clearcoat_gloss)); + float Fr = mix(.04, 1.0, cLdotH5); + float Gr = G_GGX_2cos(cNdotL, .25) * G_GGX_2cos(cNdotV, .25); - float specular_brdf_NL = 0.25 * clearcoat * Gr * Fr * Dr * cNdotL; + float clearcoat_specular_brdf_NL = 0.25 * clearcoat * Gr * Fr * Dr * cNdotL; - specular_light += specular_brdf_NL * light_color * specular_blob_intensity * attenuation; - } + specular_light += clearcoat_specular_brdf_NL * light_color * specular_blob_intensity * attenuation; #endif } +#ifdef USE_SHADOW_TO_OPACITY + alpha = min(alpha, clamp(1.0 - length(attenuation), 0.0, 1.0)); +#endif + #endif //defined(USE_LIGHT_SHADER_CODE) } @@ -1136,8 +1190,9 @@ float sample_shadow(highp sampler2DShadow shadow, vec2 shadow_pixel_size, vec2 p avg += textureProj(shadow, vec4(pos + vec2(0.0, shadow_pixel_size.y * 2.0), depth, 1.0)); avg += textureProj(shadow, vec4(pos + vec2(0.0, -shadow_pixel_size.y * 2.0), depth, 1.0)); return avg * (1.0 / 13.0); +#endif -#elif defined(SHADOW_MODE_PCF_5) +#ifdef SHADOW_MODE_PCF_5 float avg = textureProj(shadow, vec4(pos, depth, 1.0)); avg += textureProj(shadow, vec4(pos + vec2(shadow_pixel_size.x, 0.0), depth, 1.0)); @@ -1146,7 +1201,9 @@ float sample_shadow(highp sampler2DShadow shadow, vec2 shadow_pixel_size, vec2 p avg += textureProj(shadow, vec4(pos + vec2(0.0, -shadow_pixel_size.y), depth, 1.0)); return avg * (1.0 / 5.0); -#else +#endif + +#if !defined(SHADOW_MODE_PCF_5) || !defined(SHADOW_MODE_PCF_13) return textureProj(shadow, vec4(pos, depth, 1.0)); @@ -1188,7 +1245,7 @@ vec3 light_transmittance(float translucency,vec3 light_vec, vec3 normal, vec3 po } #endif -void light_process_omni(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 binormal, vec3 tangent, vec3 albedo, vec3 transmission, float roughness, float metallic, float rim, float rim_tint, float clearcoat, float clearcoat_gloss, float anisotropy, float p_blob_intensity, inout vec3 diffuse_light, inout vec3 specular_light) { +void light_process_omni(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 binormal, vec3 tangent, vec3 albedo, vec3 transmission, float roughness, float metallic, float specular, float rim, float rim_tint, float clearcoat, float clearcoat_gloss, float anisotropy, float p_blob_intensity, inout vec3 diffuse_light, inout vec3 specular_light, inout float alpha) { vec3 light_rel_vec = omni_lights[idx].light_pos_inv_radius.xyz - vertex; float light_length = length(light_rel_vec); @@ -1242,10 +1299,10 @@ void light_process_omni(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 bi light_attenuation *= mix(omni_lights[idx].shadow_color_contact.rgb, vec3(1.0), shadow); } #endif //SHADOWS_DISABLED - light_compute(normal, normalize(light_rel_vec), eye_vec, binormal, tangent, omni_lights[idx].light_color_energy.rgb, light_attenuation, albedo, transmission, omni_lights[idx].light_params.z * p_blob_intensity, roughness, metallic, rim * omni_attenuation, rim_tint, clearcoat, clearcoat_gloss, anisotropy, diffuse_light, specular_light); + light_compute(normal, normalize(light_rel_vec), eye_vec, binormal, tangent, omni_lights[idx].light_color_energy.rgb, light_attenuation, albedo, transmission, omni_lights[idx].light_params.z * p_blob_intensity, roughness, metallic, specular, rim * omni_attenuation, rim_tint, clearcoat, clearcoat_gloss, anisotropy, diffuse_light, specular_light, alpha); } -void light_process_spot(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 binormal, vec3 tangent, vec3 albedo, vec3 transmission, float roughness, float metallic, float rim, float rim_tint, float clearcoat, float clearcoat_gloss, float anisotropy, float p_blob_intensity, inout vec3 diffuse_light, inout vec3 specular_light) { +void light_process_spot(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 binormal, vec3 tangent, vec3 albedo, vec3 transmission, float roughness, float metallic, float specular, float rim, float rim_tint, float clearcoat, float clearcoat_gloss, float anisotropy, float p_blob_intensity, inout vec3 diffuse_light, inout vec3 specular_light, inout float alpha) { vec3 light_rel_vec = spot_lights[idx].light_pos_inv_radius.xyz - vertex; float light_length = length(light_rel_vec); @@ -1277,7 +1334,7 @@ void light_process_spot(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 bi } #endif //SHADOWS_DISABLED - light_compute(normal, normalize(light_rel_vec), eye_vec, binormal, tangent, spot_lights[idx].light_color_energy.rgb, light_attenuation, albedo, transmission, spot_lights[idx].light_params.z * p_blob_intensity, roughness, metallic, rim * spot_attenuation, rim_tint, clearcoat, clearcoat_gloss, anisotropy, diffuse_light, specular_light); + light_compute(normal, normalize(light_rel_vec), eye_vec, binormal, tangent, spot_lights[idx].light_color_energy.rgb, light_attenuation, albedo, transmission, spot_lights[idx].light_params.z * p_blob_intensity, roughness, metallic, specular, rim * spot_attenuation, rim_tint, clearcoat, clearcoat_gloss, anisotropy, diffuse_light, specular_light, alpha); } void reflection_process(int idx, vec3 vertex, vec3 normal, vec3 binormal, vec3 tangent, float roughness, float anisotropy, vec3 ambient, vec3 skybox, inout highp vec4 reflection_accum, inout highp vec4 ambient_accum) { @@ -1337,7 +1394,7 @@ void reflection_process(int idx, vec3 vertex, vec3 normal, vec3 binormal, vec3 t reflection_accum += reflection; } -#ifndef USE_LIGHTMAP +#if !defined(USE_LIGHTMAP) && !defined(USE_LIGHTMAP_CAPTURE) if (reflections[idx].ambient.a > 0.0) { //compute ambient using skybox vec3 local_amb_vec = (reflections[idx].local_matrix * vec4(normal, 0.0)).xyz; @@ -1468,8 +1525,8 @@ void gi_probe_compute(mediump sampler3D probe, mat4 probe_xform, vec3 bounds, ve #define MAX_CONE_DIRS 6 vec3 cone_dirs[MAX_CONE_DIRS] = vec3[]( - vec3(0, 0, 1), - vec3(0.866025, 0, 0.5), + vec3(0.0, 0.0, 1.0), + vec3(0.866025, 0.0, 0.5), vec3(0.267617, 0.823639, 0.5), vec3(-0.700629, 0.509037, 0.5), vec3(-0.700629, -0.509037, 0.5), @@ -1483,10 +1540,10 @@ void gi_probe_compute(mediump sampler3D probe, mat4 probe_xform, vec3 bounds, ve #define MAX_CONE_DIRS 4 vec3 cone_dirs[MAX_CONE_DIRS] = vec3[]( - vec3(0.707107, 0, 0.707107), - vec3(0, 0.707107, 0.707107), - vec3(-0.707107, 0, 0.707107), - vec3(0, -0.707107, 0.707107)); + vec3(0.707107, 0.0, 0.707107), + vec3(0.0, 0.707107, 0.707107), + vec3(-0.707107, 0.0, 0.707107), + vec3(0.0, -0.707107, 0.707107)); float cone_weights[MAX_CONE_DIRS] = float[](0.25, 0.25, 0.25, 0.25); float cone_angle_tan = 0.98269; @@ -1507,7 +1564,7 @@ void gi_probe_compute(mediump sampler3D probe, mat4 probe_xform, vec3 bounds, ve //irradiance - vec3 irr_light = voxel_cone_trace(probe, cell_size, probe_pos, environment, blend_ambient, ref_vec, max(min_ref_tan, tan(roughness * 0.5 * M_PI)), max_distance, p_bias); + vec3 irr_light = voxel_cone_trace(probe, cell_size, probe_pos, environment, blend_ambient, ref_vec, max(min_ref_tan, tan(roughness * 0.5 * M_PI * 0.99)), max_distance, p_bias); irr_light *= multiplier; //irr_light=vec3(0.0); @@ -1522,7 +1579,7 @@ void gi_probes_compute(vec3 pos, vec3 normal, float roughness, inout vec3 out_sp vec3 ref_vec = normalize(reflect(normalize(pos), normal)); //find arbitrary tangent and bitangent, then build a matrix - vec3 v0 = abs(normal.z) < 0.999 ? vec3(0, 0, 1) : vec3(0, 1, 0); + vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0); vec3 tangent = normalize(cross(v0, normal)); vec3 bitangent = normalize(cross(tangent, normal)); mat3 normal_mat = mat3(tangent, bitangent, normal); @@ -1568,6 +1625,7 @@ void main() { //lay out everything, whathever is unused is optimized away anyway highp vec3 vertex = vertex_interp; + vec3 view = -normalize(vertex_interp); vec3 albedo = vec3(1.0); vec3 transmission = vec3(0.0); float metallic = 0.0; @@ -1588,24 +1646,24 @@ void main() { float alpha = 1.0; -#if defined(DO_SIDE_CHECK) - float side = gl_FrontFacing ? 1.0 : -1.0; -#else - float side = 1.0; -#endif - #if defined(ALPHA_SCISSOR_USED) float alpha_scissor = 0.5; #endif #if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY) - vec3 binormal = normalize(binormal_interp) * side; - vec3 tangent = normalize(tangent_interp) * side; + vec3 binormal = normalize(binormal_interp); + vec3 tangent = normalize(tangent_interp); #else vec3 binormal = vec3(0.0); vec3 tangent = vec3(0.0); #endif - vec3 normal = normalize(normal_interp) * side; + vec3 normal = normalize(normal_interp); + +#if defined(DO_SIDE_CHECK) + if (!gl_FrontFacing) { + normal = -normal; + } +#endif #if defined(ENABLE_UV_INTERP) vec2 uv = uv_interp; @@ -1642,11 +1700,13 @@ FRAGMENT_SHADER_CODE /* clang-format on */ } +#if !defined(USE_SHADOW_TO_OPACITY) + #if defined(ALPHA_SCISSOR_USED) if (alpha < alpha_scissor) { discard; } -#endif +#endif // ALPHA_SCISSOR_USED #ifdef USE_OPAQUE_PREPASS @@ -1654,14 +1714,16 @@ FRAGMENT_SHADER_CODE discard; } -#endif +#endif // USE_OPAQUE_PREPASS + +#endif // !USE_SHADOW_TO_OPACITY #if defined(ENABLE_NORMALMAP) normalmap.xy = normalmap.xy * 2.0 - 1.0; normalmap.z = sqrt(max(0.0, 1.0 - dot(normalmap.xy, normalmap.xy))); //always ignore Z, as it can be RG packed, Z may be pos/neg, etc. - normal = normalize(mix(normal_interp, tangent * normalmap.x + binormal * normalmap.y + normal * normalmap.z, normaldepth)) * side; + normal = normalize(mix(normal, tangent * normalmap.x + binormal * normalmap.y + normal * normalmap.z, normaldepth)); #endif @@ -1702,7 +1764,7 @@ FRAGMENT_SHADER_CODE vec3 ambient_light; vec3 env_reflection_light = vec3(0.0, 0.0, 0.0); - vec3 eye_vec = -normalize(vertex_interp); + vec3 eye_vec = view; #ifdef USE_RADIANCE_MAP @@ -1739,6 +1801,7 @@ FRAGMENT_SHADER_CODE ambient_light = vec3(0.0, 0.0, 0.0); #else ambient_light = ambient_light_color.rgb; + env_reflection_light = bg_color.rgb * bg_energy; #endif //AMBIENT_LIGHT_DISABLED #endif @@ -1746,10 +1809,98 @@ FRAGMENT_SHADER_CODE ambient_light *= ambient_energy; float specular_blob_intensity = 1.0; + #if defined(SPECULAR_TOON) specular_blob_intensity *= specular * 2.0; #endif +#ifdef USE_GI_PROBES + gi_probes_compute(vertex, normal, roughness, env_reflection_light, ambient_light); + +#endif + +#ifdef USE_LIGHTMAP + ambient_light = texture(lightmap, uv2).rgb * lightmap_energy; +#endif + +#ifdef USE_LIGHTMAP_CAPTURE + { + vec3 cone_dirs[12] = vec3[]( + vec3(0.0, 0.0, 1.0), + vec3(0.866025, 0.0, 0.5), + vec3(0.267617, 0.823639, 0.5), + vec3(-0.700629, 0.509037, 0.5), + vec3(-0.700629, -0.509037, 0.5), + vec3(0.267617, -0.823639, 0.5), + vec3(0.0, 0.0, -1.0), + vec3(0.866025, 0.0, -0.5), + vec3(0.267617, 0.823639, -0.5), + vec3(-0.700629, 0.509037, -0.5), + vec3(-0.700629, -0.509037, -0.5), + vec3(0.267617, -0.823639, -0.5)); + + vec3 local_normal = normalize(camera_matrix * vec4(normal, 0.0)).xyz; + vec4 captured = vec4(0.0); + float sum = 0.0; + for (int i = 0; i < 12; i++) { + float amount = max(0.0, dot(local_normal, cone_dirs[i])); //not correct, but creates a nice wrap around effect + captured += lightmap_captures[i] * amount; + sum += amount; + } + + captured /= sum; + + if (lightmap_capture_sky) { + ambient_light = mix(ambient_light, captured.rgb, captured.a); + } else { + ambient_light = captured.rgb; + } + } +#endif + +#ifdef USE_FORWARD_LIGHTING + + highp vec4 reflection_accum = vec4(0.0, 0.0, 0.0, 0.0); + highp vec4 ambient_accum = vec4(0.0, 0.0, 0.0, 0.0); + for (int i = 0; i < reflection_count; i++) { + reflection_process(reflection_indices[i], vertex, normal, binormal, tangent, roughness, anisotropy, ambient_light, env_reflection_light, reflection_accum, ambient_accum); + } + + if (reflection_accum.a > 0.0) { + specular_light += reflection_accum.rgb / reflection_accum.a; + } else { + specular_light += env_reflection_light; + } +#if !defined(USE_LIGHTMAP) && !defined(USE_LIGHTMAP_CAPTURE) + if (ambient_accum.a > 0.0) { + ambient_light = ambient_accum.rgb / ambient_accum.a; + } +#endif +#endif + + { + +#if defined(DIFFUSE_TOON) + //simplify for toon, as + specular_light *= specular * metallic * albedo * 2.0; +#else + + // scales the specular reflections, needs to be be computed before lighting happens, + // but after environment, GI, and reflection probes are added + // Environment brdf approximation (Lazarov 2013) + // see https://www.unrealengine.com/en-US/blog/physically-based-shading-on-mobile + const vec4 c0 = vec4(-1.0, -0.0275, -0.572, 0.022); + const vec4 c1 = vec4(1.0, 0.0425, 1.04, -0.04); + vec4 r = roughness * c0 + c1; + float ndotv = clamp(dot(normal, eye_vec), 0.0, 1.0); + float a004 = min(r.x * r.x, exp2(-9.28 * ndotv)) * r.x + r.y; + vec2 env = vec2(-1.04, 1.04) * a004 + r.zw; + + vec3 f0 = F0(metallic, specular, albedo); + specular_light *= env.x * f0 + env.y; +#endif + } + #if defined(USE_LIGHT_DIRECTIONAL) vec3 light_attenuation = vec3(1.0); @@ -1892,91 +2043,49 @@ FRAGMENT_SHADER_CODE specular_light *= mix(vec3(1.0), light_attenuation, specular_light_interp.a); #else - light_compute(normal, -light_direction_attenuation.xyz, eye_vec, binormal, tangent, light_color_energy.rgb, light_attenuation, albedo, transmission, light_params.z * specular_blob_intensity, roughness, metallic, rim, rim_tint, clearcoat, clearcoat_gloss, anisotropy, diffuse_light, specular_light); + light_compute(normal, -light_direction_attenuation.xyz, eye_vec, binormal, tangent, light_color_energy.rgb, light_attenuation, albedo, transmission, light_params.z * specular_blob_intensity, roughness, metallic, specular, rim, rim_tint, clearcoat, clearcoat_gloss, anisotropy, diffuse_light, specular_light, alpha); #endif #endif //#USE_LIGHT_DIRECTIONAL -#ifdef USE_GI_PROBES - gi_probes_compute(vertex, normal, roughness, env_reflection_light, ambient_light); - -#endif - -#ifdef USE_LIGHTMAP - ambient_light = texture(lightmap, uv2).rgb * lightmap_energy; -#endif - -#ifdef USE_LIGHTMAP_CAPTURE - { - vec3 cone_dirs[12] = vec3[]( - vec3(0, 0, 1), - vec3(0.866025, 0, 0.5), - vec3(0.267617, 0.823639, 0.5), - vec3(-0.700629, 0.509037, 0.5), - vec3(-0.700629, -0.509037, 0.5), - vec3(0.267617, -0.823639, 0.5), - vec3(0, 0, -1), - vec3(0.866025, 0, -0.5), - vec3(0.267617, 0.823639, -0.5), - vec3(-0.700629, 0.509037, -0.5), - vec3(-0.700629, -0.509037, -0.5), - vec3(0.267617, -0.823639, -0.5)); - - vec3 local_normal = normalize(camera_matrix * vec4(normal, 0.0)).xyz; - vec4 captured = vec4(0.0); - float sum = 0.0; - for (int i = 0; i < 12; i++) { - float amount = max(0.0, dot(local_normal, cone_dirs[i])); //not correct, but creates a nice wrap around effect - captured += lightmap_captures[i] * amount; - sum += amount; - } - - captured /= sum; - - if (lightmap_capture_sky) { - ambient_light = mix(ambient_light, captured.rgb, captured.a); - } else { - ambient_light = captured.rgb; - } - } -#endif - #ifdef USE_FORWARD_LIGHTING - highp vec4 reflection_accum = vec4(0.0, 0.0, 0.0, 0.0); - highp vec4 ambient_accum = vec4(0.0, 0.0, 0.0, 0.0); - for (int i = 0; i < reflection_count; i++) { - reflection_process(reflection_indices[i], vertex, normal, binormal, tangent, roughness, anisotropy, ambient_light, env_reflection_light, reflection_accum, ambient_accum); - } - - if (reflection_accum.a > 0.0) { - specular_light += reflection_accum.rgb / reflection_accum.a; - } else { - specular_light += env_reflection_light; - } -#ifndef USE_LIGHTMAP - if (ambient_accum.a > 0.0) { - ambient_light = ambient_accum.rgb / ambient_accum.a; - } -#endif - #ifdef USE_VERTEX_LIGHTING diffuse_light *= albedo; #else for (int i = 0; i < omni_light_count; i++) { - light_process_omni(omni_light_indices[i], vertex, eye_vec, normal, binormal, tangent, albedo, transmission, roughness, metallic, rim, rim_tint, clearcoat, clearcoat_gloss, anisotropy, specular_blob_intensity, diffuse_light, specular_light); + light_process_omni(omni_light_indices[i], vertex, eye_vec, normal, binormal, tangent, albedo, transmission, roughness, metallic, specular, rim, rim_tint, clearcoat, clearcoat_gloss, anisotropy, specular_blob_intensity, diffuse_light, specular_light, alpha); } for (int i = 0; i < spot_light_count; i++) { - light_process_spot(spot_light_indices[i], vertex, eye_vec, normal, binormal, tangent, albedo, transmission, roughness, metallic, rim, rim_tint, clearcoat, clearcoat_gloss, anisotropy, specular_blob_intensity, diffuse_light, specular_light); + light_process_spot(spot_light_indices[i], vertex, eye_vec, normal, binormal, tangent, albedo, transmission, roughness, metallic, specular, rim, rim_tint, clearcoat, clearcoat_gloss, anisotropy, specular_blob_intensity, diffuse_light, specular_light, alpha); } #endif //USE_VERTEX_LIGHTING #endif +#ifdef USE_SHADOW_TO_OPACITY + alpha = min(alpha, clamp(length(ambient_light), 0.0, 1.0)); + +#if defined(ALPHA_SCISSOR_USED) + if (alpha < alpha_scissor) { + discard; + } +#endif // ALPHA_SCISSOR_USED + +#ifdef USE_OPAQUE_PREPASS + + if (alpha < opaque_prepass_threshold) { + discard; + } + +#endif // USE_OPAQUE_PREPASS + +#endif // USE_SHADOW_TO_OPACITY + #ifdef RENDER_DEPTH //nothing happens, so a tree-ssa optimizer will result in no fragment shader :) #else @@ -1991,30 +2100,10 @@ FRAGMENT_SHADER_CODE diffuse_light *= ao_light_affect; #endif - //energy conservation + // base color remapping diffuse_light *= 1.0 - metallic; // TODO: avoid all diffuse and ambient light calculations when metallic == 1 up to this point ambient_light *= 1.0 - metallic; - { - -#if defined(DIFFUSE_TOON) - //simplify for toon, as - specular_light *= specular * metallic * albedo * 2.0; -#else - // Environment brdf approximation (Lazarov 2013) - // see https://www.unrealengine.com/en-US/blog/physically-based-shading-on-mobile - const vec4 c0 = vec4(-1.0, -0.0275, -0.572, 0.022); - const vec4 c1 = vec4(1.0, 0.0425, 1.04, -0.04); - vec4 r = roughness * c0 + c1; - float ndotv = clamp(dot(normal, eye_vec), 0.0, 1.0); - float a004 = min(r.x * r.x, exp2(-9.28 * ndotv)) * r.x + r.y; - vec2 AB = vec2(-1.04, 1.04) * a004 + r.zw; - - vec3 specular_color = metallic_to_specular_color(metallic, specular, albedo); - specular_light *= AB.x * specular_color + AB.y; -#endif - } - if (fog_color_enabled.a > 0.5) { float fog_amount = 0.0; @@ -2030,10 +2119,11 @@ FRAGMENT_SHADER_CODE //apply fog if (fog_depth_enabled) { + float fog_far = fog_depth_end > 0.0 ? fog_depth_end : z_far; - float fog_z = smoothstep(fog_depth_begin, z_far, length(vertex)); + float fog_z = smoothstep(fog_depth_begin, fog_far, length(vertex)); - fog_amount = pow(fog_z, fog_depth_curve); + fog_amount = pow(fog_z, fog_depth_curve) * fog_density; if (fog_transmit_enabled) { vec3 total_light = emission + ambient_light + specular_light + diffuse_light; float transmit = pow(fog_z, fog_transmit_curve); @@ -2050,7 +2140,7 @@ FRAGMENT_SHADER_CODE emission = emission * rev_amount + fog_color * fog_amount; ambient_light *= rev_amount; - specular_light *rev_amount; + specular_light *= rev_amount; diffuse_light *= rev_amount; } diff --git a/drivers/gles3/shaders/screen_space_reflection.glsl b/drivers/gles3/shaders/screen_space_reflection.glsl index 86546319a0..39f1ea6155 100644 --- a/drivers/gles3/shaders/screen_space_reflection.glsl +++ b/drivers/gles3/shaders/screen_space_reflection.glsl @@ -77,7 +77,7 @@ void main() { return; } //ray_dir = normalize(view_dir - normal * dot(normal,view_dir) * 2.0); - //ray_dir = normalize(vec3(1, 1, -1)); + //ray_dir = normalize(vec3(1.0, 1.0, -1.0)); //////////////// diff --git a/drivers/gles3/shaders/ssao.glsl b/drivers/gles3/shaders/ssao.glsl index be44365169..d9cdc3fc1f 100644 --- a/drivers/gles3/shaders/ssao.glsl +++ b/drivers/gles3/shaders/ssao.glsl @@ -16,15 +16,15 @@ void main() { #define TWO_PI 6.283185307179586476925286766559 #ifdef SSAO_QUALITY_HIGH -#define NUM_SAMPLES (80) +#define NUM_SAMPLES (16) #endif #ifdef SSAO_QUALITY_LOW -#define NUM_SAMPLES (15) +#define NUM_SAMPLES (8) #endif #if !defined(SSAO_QUALITY_LOW) && !defined(SSAO_QUALITY_HIGH) -#define NUM_SAMPLES (40) +#define NUM_SAMPLES (12) #endif // If using depth mip levels, the log of the maximum pixel offset before we need to switch to a lower diff --git a/drivers/gles3/shaders/tonemap.glsl b/drivers/gles3/shaders/tonemap.glsl index dd6d78849b..f1fe1742eb 100644 --- a/drivers/gles3/shaders/tonemap.glsl +++ b/drivers/gles3/shaders/tonemap.glsl @@ -124,13 +124,16 @@ vec4 texture2D_bicubic(sampler2D tex, vec2 uv, int p_lod) { #endif vec3 tonemap_filmic(vec3 color, float white) { - const float A = 0.15f; - const float B = 0.50f; + // exposure bias: input scale (color *= bias, white *= bias) to make the brightness consistent with other tonemappers + // also useful to scale the input to the range that the tonemapper is designed for (some require very high input values) + // has no effect on the curve's general shape or visual properties + const float exposure_bias = 2.0f; + const float A = 0.22f * exposure_bias * exposure_bias; // bias baked into constants for performance + const float B = 0.30f * exposure_bias; const float C = 0.10f; const float D = 0.20f; - const float E = 0.02f; + const float E = 0.01f; const float F = 0.30f; - const float W = 11.2f; vec3 color_tonemapped = ((color * (A * color + C * B) + D * E) / (color * (A * color + B) + D * F)) - E / F; float white_tonemapped = ((white * (A * white + C * B) + D * E) / (white * (A * white + B) + D * F)) - E / F; @@ -139,10 +142,11 @@ vec3 tonemap_filmic(vec3 color, float white) { } vec3 tonemap_aces(vec3 color, float white) { - const float A = 2.51f; - const float B = 0.03f; - const float C = 2.43f; - const float D = 0.59f; + const float exposure_bias = 0.85f; + const float A = 2.51f * exposure_bias * exposure_bias; + const float B = 0.03f * exposure_bias; + const float C = 2.43f * exposure_bias * exposure_bias; + const float D = 0.59f * exposure_bias; const float E = 0.14f; vec3 color_tonemapped = (color * (A * color + B)) / (color * (C * color + D) + E); @@ -151,8 +155,8 @@ vec3 tonemap_aces(vec3 color, float white) { return clamp(color_tonemapped / white_tonemapped, vec3(0.0f), vec3(1.0f)); } -vec3 tonemap_reindhart(vec3 color, float white) { - return clamp((color) / (1.0f + color) * (1.0f + (color / (white))), vec3(0.0f), vec3(1.0f)); // whitepoint is probably not in linear space here! +vec3 tonemap_reinhard(vec3 color, float white) { + return clamp((white * color + color) / (color * white + white), vec3(0.0f), vec3(1.0f)); } vec3 linear_to_srgb(vec3 color) { // convert linear rgb to srgb, assumes clamped input in range [0;1] @@ -160,9 +164,10 @@ vec3 linear_to_srgb(vec3 color) { // convert linear rgb to srgb, assumes clamped return mix((vec3(1.0f) + a) * pow(color.rgb, vec3(1.0f / 2.4f)) - a, 12.92f * color.rgb, lessThan(color.rgb, vec3(0.0031308f))); } -vec3 apply_tonemapping(vec3 color, float white) { // inputs are LINEAR, always outputs clamped [0;1] color -#ifdef USE_REINDHART_TONEMAPPER - return tonemap_reindhart(color, white); +// inputs are LINEAR, If Linear tonemapping is selected no transform is performed else outputs are clamped [0, 1] color +vec3 apply_tonemapping(vec3 color, float white) { +#ifdef USE_REINHARD_TONEMAPPER + return tonemap_reinhard(color, white); #endif #ifdef USE_FILMIC_TONEMAPPER @@ -173,7 +178,7 @@ vec3 apply_tonemapping(vec3 color, float white) { // inputs are LINEAR, always o return tonemap_aces(color, white); #endif - return clamp(color, vec3(0.0f), vec3(1.0f)); // no other selected -> linear + return color; // no other selected -> linear: no color transform applied } vec3 gather_glow(sampler2D tex, vec2 uv) { // sample all selected glow levels @@ -216,10 +221,14 @@ vec3 apply_glow(vec3 color, vec3 glow) { // apply glow using the selected blendi #endif #ifdef USE_GLOW_SCREEN + //need color clamping + color = clamp(color, vec3(0.0f), vec3(1.0f)); color = max((color + glow) - (color * glow), vec3(0.0)); #endif #ifdef USE_GLOW_SOFTLIGHT + //need color clamping + color = clamp(color, vec3(0.0f), vec3(1.0)); glow = glow * vec3(0.5f) + vec3(0.5f); color.r = (glow.r <= 0.5f) ? (color.r - (1.0f - 2.0f * glow.r) * color.r * (1.0f - color.r)) : (((glow.r > 0.5f) && (color.r <= 0.25f)) ? (color.r + (2.0f * glow.r - 1.0f) * (4.0f * color.r * (4.0f * color.r + 1.0f) * (color.r - 1.0f) + 7.0f * color.r)) : (color.r + (2.0f * glow.r - 1.0f) * (sqrt(color.r) - color.r))); @@ -261,14 +270,16 @@ void main() { color *= exposure; - // Early Tonemap & SRGB Conversion + // Early Tonemap & SRGB Conversion; note that Linear tonemapping does not clamp to [0, 1]; some operations below expect a [0, 1] range and will clamp color = apply_tonemapping(color, white); #ifdef KEEP_3D_LINEAR // leave color as is (-> don't convert to SRGB) #else - color = linear_to_srgb(color); // regular linear -> SRGB conversion + //need color clamping + color = clamp(color, vec3(0.0f), vec3(1.0f)); + color = linear_to_srgb(color); // regular linear -> SRGB conversion (needs clamped values) #endif // Glow @@ -278,6 +289,7 @@ void main() { // high dynamic range -> SRGB glow = apply_tonemapping(glow, white); + glow = clamp(glow, vec3(0.0f), vec3(1.0f)); glow = linear_to_srgb(glow); color = apply_glow(color, glow); |