diff options
Diffstat (limited to 'drivers/gles2/rasterizer_scene_gles2.cpp')
-rw-r--r-- | drivers/gles2/rasterizer_scene_gles2.cpp | 319 |
1 files changed, 234 insertions, 85 deletions
diff --git a/drivers/gles2/rasterizer_scene_gles2.cpp b/drivers/gles2/rasterizer_scene_gles2.cpp index 2c52895bda..3c8822175d 100644 --- a/drivers/gles2/rasterizer_scene_gles2.cpp +++ b/drivers/gles2/rasterizer_scene_gles2.cpp @@ -42,8 +42,6 @@ #define glClearDepth glClearDepthf #endif -#define _DEPTH_COMPONENT24_OES 0x81A6 - static const GLenum _cube_side_enum[6] = { GL_TEXTURE_CUBE_MAP_NEGATIVE_X, @@ -62,6 +60,7 @@ RID RasterizerSceneGLES2::shadow_atlas_create() { ShadowAtlas *shadow_atlas = memnew(ShadowAtlas); shadow_atlas->fbo = 0; shadow_atlas->depth = 0; + shadow_atlas->color = 0; shadow_atlas->size = 0; shadow_atlas->smallest_subdiv = 0; @@ -84,11 +83,19 @@ void RasterizerSceneGLES2::shadow_atlas_set_size(RID p_atlas, int p_size) { // erase the old atlast if (shadow_atlas->fbo) { - glDeleteTextures(1, &shadow_atlas->depth); + if (storage->config.use_rgba_3d_shadows) { + glDeleteRenderbuffers(1, &shadow_atlas->depth); + } else { + glDeleteTextures(1, &shadow_atlas->depth); + } glDeleteFramebuffers(1, &shadow_atlas->fbo); + if (shadow_atlas->color) { + glDeleteTextures(1, &shadow_atlas->color); + } shadow_atlas->fbo = 0; shadow_atlas->depth = 0; + shadow_atlas->color = 0; } // erase shadow atlast references from lights @@ -108,17 +115,36 @@ void RasterizerSceneGLES2::shadow_atlas_set_size(RID p_atlas, int p_size) { // create a depth texture glActiveTexture(GL_TEXTURE0); - glGenTextures(1, &shadow_atlas->depth); - glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth); - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, shadow_atlas->size, shadow_atlas->size, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + if (storage->config.use_rgba_3d_shadows) { + + //maximum compatibility, renderbuffer and RGBA shadow + glGenRenderbuffers(1, &shadow_atlas->depth); + glBindRenderbuffer(GL_RENDERBUFFER, directional_shadow.depth); + glRenderbufferStorage(GL_RENDERBUFFER, storage->config.depth_internalformat, shadow_atlas->size, shadow_atlas->size); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, shadow_atlas->depth); + + glGenTextures(1, &shadow_atlas->color); + glBindTexture(GL_TEXTURE_2D, shadow_atlas->color); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, shadow_atlas->size, shadow_atlas->size, 0, GL_RGBA, GL_UNSIGNED_BYTE, 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); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, shadow_atlas->color, 0); + } else { + //just depth texture + glGenTextures(1, &shadow_atlas->depth); + glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth); + glTexImage2D(GL_TEXTURE_2D, 0, storage->config.depth_internalformat, shadow_atlas->size, shadow_atlas->size, 0, GL_DEPTH_COMPONENT, storage->config.depth_type, NULL); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadow_atlas->depth, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadow_atlas->depth, 0); + } glViewport(0, 0, shadow_atlas->size, shadow_atlas->size); glDepthMask(GL_TRUE); @@ -143,7 +169,7 @@ void RasterizerSceneGLES2::shadow_atlas_set_quadrant_subdivision(RID p_atlas, in subdiv = int(Math::sqrt((float)subdiv)); - if (shadow_atlas->quadrants[p_quadrant].shadows.size() == subdiv) + if (shadow_atlas->quadrants[p_quadrant].shadows.size() == (int)subdiv) return; // erase all data from the quadrant @@ -459,10 +485,11 @@ RID RasterizerSceneGLES2::reflection_probe_instance_create(RID p_probe) { for (int i = 0; i < 6; i++) { glGenFramebuffers(1, &rpi->fbo[i]); + glGenTextures(1, &rpi->color[i]); } - glGenFramebuffers(1, &rpi->fbo_blur); glGenRenderbuffers(1, &rpi->depth); + rpi->cubemap = 0; //glGenTextures(1, &rpi->cubemap); @@ -510,9 +537,14 @@ bool RasterizerSceneGLES2::reflection_probe_instance_begin_render(RID p_instance GLenum type = GL_UNSIGNED_BYTE; glActiveTexture(GL_TEXTURE0); + + glBindRenderbuffer(GL_RENDERBUFFER, rpi->depth); + glRenderbufferStorage(GL_RENDERBUFFER, storage->config.depth_internalformat, size, size); + if (rpi->cubemap != 0) { glDeleteTextures(1, &rpi->cubemap); } + glGenTextures(1, &rpi->cubemap); glBindTexture(GL_TEXTURE_CUBE_MAP, rpi->cubemap); #if 1 @@ -523,17 +555,15 @@ bool RasterizerSceneGLES2::reflection_probe_instance_begin_render(RID p_instance glGenerateMipmap(GL_TEXTURE_CUBE_MAP); - glBindRenderbuffer(GL_RENDERBUFFER, rpi->depth); //resize depth buffer -#ifdef JAVASCRIPT_ENABLED - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, size, size); -#else - glRenderbufferStorage(GL_RENDERBUFFER, _DEPTH_COMPONENT24_OES, size, size); -#endif - + //Generate framebuffers for rendering for (int i = 0; i < 6; i++) { glBindFramebuffer(GL_FRAMEBUFFER, rpi->fbo[i]); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, _cube_side_enum[i], rpi->cubemap, 0); + glBindTexture(GL_TEXTURE_2D, rpi->color[i]); + glTexImage2D(GL_TEXTURE_2D, 0, internal_format, size, size, 0, format, type, NULL); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rpi->color[i], 0); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rpi->depth); + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + ERR_CONTINUE(status != GL_FRAMEBUFFER_COMPLETE); } #else @@ -550,8 +580,6 @@ bool RasterizerSceneGLES2::reflection_probe_instance_begin_render(RID p_instance //adjust framebuffer glBindFramebuffer(GL_FRAMEBUFFER, rpi->fbo[i]); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, _cube_side_enum[i], rpi->cubemap, 0); - glBindRenderbuffer(GL_RENDERBUFFER, rpi->depth); - glRenderbufferStorage(GL_RENDERBUFFER, _DEPTH_COMPONENT24_OES, size, size); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rpi->depth); #ifdef DEBUG_ENABLED @@ -570,6 +598,8 @@ bool RasterizerSceneGLES2::reflection_probe_instance_begin_render(RID p_instance glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES2::system_fbo); } return true; @@ -579,6 +609,7 @@ bool RasterizerSceneGLES2::reflection_probe_instance_postprocess_step(RID p_inst ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); ERR_FAIL_COND_V(!rpi, false); + ERR_FAIL_COND_V(rpi->current_resolution == 0, false); int size = rpi->probe_ptr->resolution; @@ -596,16 +627,23 @@ bool RasterizerSceneGLES2::reflection_probe_instance_postprocess_step(RID p_inst } } + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_CUBE_MAP, rpi->cubemap); + glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); //use linear, no mipmaps so it does not read from what is being written to + + //first of all, copy rendered textures to cubemap + for (int i = 0; i < 6; i++) { + glBindFramebuffer(GL_FRAMEBUFFER, rpi->fbo[i]); + glViewport(0, 0, size, size); + glCopyTexSubImage2D(_cube_side_enum[i], 0, 0, 0, 0, 0, size, size); + } + //do filtering //vdc cache glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, storage->resources.radical_inverse_vdc_cache_tex); - glBindFramebuffer(GL_FRAMEBUFFER, rpi->fbo_blur); // now render to the framebuffer, mipmap level for mipmap level int lod = 1; - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_CUBE_MAP, rpi->cubemap); - glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); //use linear, no mipmaps so it does not read from what is being written to size >>= 1; int mipmaps = 6; @@ -613,13 +651,20 @@ bool RasterizerSceneGLES2::reflection_probe_instance_postprocess_step(RID p_inst storage->shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES2::USE_SOURCE_PANORAMA, false); storage->shaders.cubemap_filter.bind(); + glBindFramebuffer(GL_FRAMEBUFFER, storage->resources.mipmap_blur_fbo); + //blur while (size >= 1) { + glActiveTexture(GL_TEXTURE3); + glBindTexture(GL_TEXTURE_2D, storage->resources.mipmap_blur_color); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, size, size, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, storage->resources.mipmap_blur_color, 0); + glViewport(0, 0, size, size); + glActiveTexture(GL_TEXTURE0); + for (int i = 0; i < 6; i++) { - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, _cube_side_enum[i], rpi->cubemap, lod); - glViewport(0, 0, size, size); storage->bind_quad_array(); storage->shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES2::FACE_ID, i); float roughness = CLAMP(lod / (float)(mipmaps - 1), 0, 1); @@ -627,6 +672,7 @@ bool RasterizerSceneGLES2::reflection_probe_instance_postprocess_step(RID p_inst storage->shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES2::Z_FLIP, false); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + glCopyTexSubImage2D(_cube_side_enum[i], lod, 0, 0, 0, 0, size, size); } size >>= 1; @@ -635,9 +681,14 @@ bool RasterizerSceneGLES2::reflection_probe_instance_postprocess_step(RID p_inst } // restore ranges - + glActiveTexture(GL_TEXTURE0); glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindTexture(GL_TEXTURE_2D, 0); + glActiveTexture(GL_TEXTURE3); //back to panorama + glBindTexture(GL_TEXTURE_2D, 0); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, 0); + glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES2::system_fbo); return true; } @@ -1120,10 +1171,10 @@ void RasterizerSceneGLES2::_fill_render_list(InstanceBase **p_cull_result, int p int num_surfaces = mesh->surfaces.size(); - for (int i = 0; i < num_surfaces; i++) { - int material_index = instance->materials[i].is_valid() ? i : -1; + for (int j = 0; j < num_surfaces; j++) { + int material_index = instance->materials[j].is_valid() ? j : -1; - RasterizerStorageGLES2::Surface *surface = mesh->surfaces[i]; + RasterizerStorageGLES2::Surface *surface = mesh->surfaces[j]; _add_geometry(surface, instance, NULL, material_index, p_depth_pass, p_shadow_pass); } @@ -1143,8 +1194,8 @@ void RasterizerSceneGLES2::_fill_render_list(InstanceBase **p_cull_result, int p int ssize = mesh->surfaces.size(); - for (int i = 0; i < ssize; i++) { - RasterizerStorageGLES2::Surface *s = mesh->surfaces[i]; + for (int j = 0; j < ssize; j++) { + RasterizerStorageGLES2::Surface *s = mesh->surfaces[j]; _add_geometry(s, instance, multi_mesh, -1, p_depth_pass, p_shadow_pass); } } break; @@ -1178,9 +1229,19 @@ bool RasterizerSceneGLES2::_setup_material(RasterizerStorageGLES2::Material *p_m state.scene_shader.set_custom_shader(p_material->shader->custom_code_id); + if (p_material->shader->spatial.uses_screen_texture && storage->frame.current_rt) { + glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4); + glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->copy_screen_effect.color); + } + + if (p_material->shader->spatial.uses_depth_texture && storage->frame.current_rt) { + glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4); + glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth); + } + bool shader_rebind = state.scene_shader.bind(); - if (p_material->shader->spatial.no_depth_test) { + if (p_material->shader->spatial.no_depth_test || p_material->shader->spatial.uses_depth_texture) { glDisable(GL_DEPTH_TEST); } else { glEnable(GL_DEPTH_TEST); @@ -1190,19 +1251,16 @@ bool RasterizerSceneGLES2::_setup_material(RasterizerStorageGLES2::Material *p_m case RasterizerStorageGLES2::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS: case RasterizerStorageGLES2::Shader::Spatial::DEPTH_DRAW_OPAQUE: { - glDepthMask(!p_alpha_pass); + glDepthMask(!p_alpha_pass && !p_material->shader->spatial.uses_depth_texture); } break; case RasterizerStorageGLES2::Shader::Spatial::DEPTH_DRAW_ALWAYS: { - glDepthMask(GL_TRUE); + glDepthMask(GL_TRUE && !p_material->shader->spatial.uses_depth_texture); } break; case RasterizerStorageGLES2::Shader::Spatial::DEPTH_DRAW_NEVER: { glDepthMask(GL_FALSE); } break; } - // TODO whyyyyy???? - p_reverse_cull = true; - switch (p_material->shader->spatial.cull_mode) { case RasterizerStorageGLES2::Shader::Spatial::CULL_MODE_DISABLED: { glDisable(GL_CULL_FACE); @@ -1219,9 +1277,9 @@ bool RasterizerSceneGLES2::_setup_material(RasterizerStorageGLES2::Material *p_m } int tc = p_material->textures.size(); - Pair<StringName, RID> *textures = p_material->textures.ptrw(); + const Pair<StringName, RID> *textures = p_material->textures.ptr(); - ShaderLanguage::ShaderNode::Uniform::Hint *texture_hints = p_material->shader->texture_hints.ptrw(); + const ShaderLanguage::ShaderNode::Uniform::Hint *texture_hints = p_material->shader->texture_hints.ptr(); state.scene_shader.set_uniform(SceneShaderGLES2::SKELETON_TEXTURE_SIZE, p_skeleton_tex_size); @@ -1254,12 +1312,12 @@ bool RasterizerSceneGLES2::_setup_material(RasterizerStorageGLES2::Material *p_m continue; } - t = t->get_ptr(); - if (t->redraw_if_visible) { //must check before proxy because this is often used with proxies VisualServerRaster::redraw_request(); } + t = t->get_ptr(); + #ifdef TOOLS_ENABLED if (t->detect_3d) { t->detect_3d(t->detect_3d_ud); @@ -1300,7 +1358,7 @@ void RasterizerSceneGLES2::_setup_geometry(RenderList::Element *p_element, Raste for (int i = 0; i < VS::ARRAY_MAX - 1; i++) { if (s->attribs[i].enabled) { glEnableVertexAttribArray(i); - glVertexAttribPointer(s->attribs[i].index, s->attribs[i].size, s->attribs[i].type, s->attribs[i].normalized, s->attribs[i].stride, (uint8_t *)0 + s->attribs[i].offset); + glVertexAttribPointer(s->attribs[i].index, s->attribs[i].size, s->attribs[i].type, s->attribs[i].normalized, s->attribs[i].stride, CAST_INT_TO_UCHAR_PTR(s->attribs[i].offset)); } else { glDisableVertexAttribArray(i); switch (i) { @@ -1461,7 +1519,7 @@ void RasterizerSceneGLES2::_setup_geometry(RenderList::Element *p_element, Raste for (int i = 0; i < VS::ARRAY_MAX - 1; i++) { if (s->attribs[i].enabled) { glEnableVertexAttribArray(i); - glVertexAttribPointer(s->attribs[i].index, s->attribs[i].size, s->attribs[i].type, s->attribs[i].normalized, s->attribs[i].stride, (uint8_t *)0 + s->attribs[i].offset); + glVertexAttribPointer(s->attribs[i].index, s->attribs[i].size, s->attribs[i].type, s->attribs[i].normalized, s->attribs[i].stride, CAST_INT_TO_UCHAR_PTR(s->attribs[i].offset)); } else { glDisableVertexAttribArray(i); switch (i) { @@ -1508,8 +1566,10 @@ void RasterizerSceneGLES2::_render_geometry(RenderList::Element *p_element) { if (s->index_array_len > 0) { glDrawElements(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0); + storage->info.render.vertices_count += s->index_array_len; } else { glDrawArrays(gl_primitive[s->primitive], 0, s->array_len); + storage->info.render.vertices_count += s->array_len; } /* if (p_element->instance->skeleton.is_valid() && s->attribs[VS::ARRAY_BONES].enabled && s->attribs[VS::ARRAY_WEIGHTS].enabled) { @@ -1564,6 +1624,8 @@ void RasterizerSceneGLES2::_render_geometry(RenderList::Element *p_element) { } else { glVertexAttrib4fv(INSTANCE_ATTRIB_BASE + 3, buffer + color_ofs); } + } else { + glVertexAttrib4f(INSTANCE_ATTRIB_BASE + 3, 1.0, 1.0, 1.0, 1.0); } if (multi_mesh->custom_data_floats) { @@ -1577,8 +1639,10 @@ void RasterizerSceneGLES2::_render_geometry(RenderList::Element *p_element) { if (s->index_array_len > 0) { glDrawElements(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0); + storage->info.render.vertices_count += s->index_array_len; } else { glDrawArrays(gl_primitive[s->primitive], 0, s->array_len); + storage->info.render.vertices_count += s->array_len; } } @@ -1611,11 +1675,10 @@ void RasterizerSceneGLES2::_render_geometry(RenderList::Element *p_element) { if (c.texture.is_valid() && storage->texture_owner.owns(c.texture)) { RasterizerStorageGLES2::Texture *t = storage->texture_owner.get(c.texture); - t = t->get_ptr(); - if (t->redraw_if_visible) { VisualServerRaster::redraw_request(); } + t = t->get_ptr(); #ifdef TOOLS_ENABLED if (t->detect_3d) { @@ -1639,7 +1702,7 @@ void RasterizerSceneGLES2::_render_geometry(RenderList::Element *p_element) { if (!c.normals.empty()) { glEnableVertexAttribArray(VS::ARRAY_NORMAL); glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Vector3) * vertices, c.normals.ptr()); - glVertexAttribPointer(VS::ARRAY_NORMAL, 3, GL_FLOAT, GL_FALSE, sizeof(Vector3), ((uint8_t *)NULL) + buf_ofs); + glVertexAttribPointer(VS::ARRAY_NORMAL, 3, GL_FLOAT, GL_FALSE, sizeof(Vector3), CAST_INT_TO_UCHAR_PTR(buf_ofs)); buf_ofs += sizeof(Vector3) * vertices; } else { glDisableVertexAttribArray(VS::ARRAY_NORMAL); @@ -1648,7 +1711,7 @@ void RasterizerSceneGLES2::_render_geometry(RenderList::Element *p_element) { if (!c.tangents.empty()) { glEnableVertexAttribArray(VS::ARRAY_TANGENT); glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Plane) * vertices, c.tangents.ptr()); - glVertexAttribPointer(VS::ARRAY_TANGENT, 4, GL_FLOAT, GL_FALSE, sizeof(Plane), ((uint8_t *)NULL) + buf_ofs); + glVertexAttribPointer(VS::ARRAY_TANGENT, 4, GL_FLOAT, GL_FALSE, sizeof(Plane), CAST_INT_TO_UCHAR_PTR(buf_ofs)); buf_ofs += sizeof(Plane) * vertices; } else { glDisableVertexAttribArray(VS::ARRAY_TANGENT); @@ -1657,7 +1720,7 @@ void RasterizerSceneGLES2::_render_geometry(RenderList::Element *p_element) { if (!c.colors.empty()) { glEnableVertexAttribArray(VS::ARRAY_COLOR); glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Color) * vertices, c.colors.ptr()); - glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, GL_FALSE, sizeof(Color), ((uint8_t *)NULL) + buf_ofs); + glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, GL_FALSE, sizeof(Color), CAST_INT_TO_UCHAR_PTR(buf_ofs)); buf_ofs += sizeof(Color) * vertices; } else { glDisableVertexAttribArray(VS::ARRAY_COLOR); @@ -1666,7 +1729,7 @@ void RasterizerSceneGLES2::_render_geometry(RenderList::Element *p_element) { if (!c.uvs.empty()) { 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, GL_FALSE, sizeof(Vector2), ((uint8_t *)NULL) + buf_ofs); + glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buf_ofs)); buf_ofs += sizeof(Vector2) * vertices; } else { glDisableVertexAttribArray(VS::ARRAY_TEX_UV); @@ -1675,7 +1738,7 @@ void RasterizerSceneGLES2::_render_geometry(RenderList::Element *p_element) { if (!c.uv2s.empty()) { glEnableVertexAttribArray(VS::ARRAY_TEX_UV2); glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Vector2) * vertices, c.uv2s.ptr()); - glVertexAttribPointer(VS::ARRAY_TEX_UV2, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), ((uint8_t *)NULL) + buf_ofs); + glVertexAttribPointer(VS::ARRAY_TEX_UV2, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buf_ofs)); buf_ofs += sizeof(Vector2) * vertices; } else { glDisableVertexAttribArray(VS::ARRAY_TEX_UV2); @@ -1683,7 +1746,7 @@ void RasterizerSceneGLES2::_render_geometry(RenderList::Element *p_element) { glEnableVertexAttribArray(VS::ARRAY_VERTEX); glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Vector3) * vertices, c.vertices.ptr()); - glVertexAttribPointer(VS::ARRAY_VERTEX, 3, GL_FLOAT, GL_FALSE, sizeof(Vector3), ((uint8_t *)NULL) + buf_ofs); + glVertexAttribPointer(VS::ARRAY_VERTEX, 3, GL_FLOAT, GL_FALSE, sizeof(Vector3), CAST_INT_TO_UCHAR_PTR(buf_ofs)); glDrawArrays(gl_primitive[c.primitive], 0, c.vertices.size()); } @@ -1742,7 +1805,11 @@ void RasterizerSceneGLES2::_setup_light_type(LightInstance *p_light, ShadowAtlas if (!state.render_no_shadows && p_light->light_ptr->shadow) { state.scene_shader.set_conditional(SceneShaderGLES2::USE_SHADOW, true); glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 3); - glBindTexture(GL_TEXTURE_2D, directional_shadow.depth); + if (storage->config.use_rgba_3d_shadows) { + glBindTexture(GL_TEXTURE_2D, directional_shadow.color); + } else { + glBindTexture(GL_TEXTURE_2D, directional_shadow.depth); + } state.scene_shader.set_conditional(SceneShaderGLES2::SHADOW_MODE_PCF_5, shadow_filter_mode == SHADOW_FILTER_PCF5); state.scene_shader.set_conditional(SceneShaderGLES2::SHADOW_MODE_PCF_13, shadow_filter_mode == SHADOW_FILTER_PCF13); } @@ -1754,7 +1821,11 @@ void RasterizerSceneGLES2::_setup_light_type(LightInstance *p_light, ShadowAtlas if (!state.render_no_shadows && shadow_atlas && p_light->light_ptr->shadow) { state.scene_shader.set_conditional(SceneShaderGLES2::USE_SHADOW, true); glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 3); - glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth); + if (storage->config.use_rgba_3d_shadows) { + glBindTexture(GL_TEXTURE_2D, shadow_atlas->color); + } else { + glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth); + } state.scene_shader.set_conditional(SceneShaderGLES2::SHADOW_MODE_PCF_5, shadow_filter_mode == SHADOW_FILTER_PCF5); state.scene_shader.set_conditional(SceneShaderGLES2::SHADOW_MODE_PCF_13, shadow_filter_mode == SHADOW_FILTER_PCF13); } @@ -1765,7 +1836,11 @@ void RasterizerSceneGLES2::_setup_light_type(LightInstance *p_light, ShadowAtlas if (!state.render_no_shadows && shadow_atlas && p_light->light_ptr->shadow) { state.scene_shader.set_conditional(SceneShaderGLES2::USE_SHADOW, true); glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 3); - glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth); + if (storage->config.use_rgba_3d_shadows) { + glBindTexture(GL_TEXTURE_2D, shadow_atlas->color); + } else { + glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth); + } state.scene_shader.set_conditional(SceneShaderGLES2::SHADOW_MODE_PCF_5, shadow_filter_mode == SHADOW_FILTER_PCF5); state.scene_shader.set_conditional(SceneShaderGLES2::SHADOW_MODE_PCF_13, shadow_filter_mode == SHADOW_FILTER_PCF13); } @@ -1786,6 +1861,9 @@ void RasterizerSceneGLES2::_setup_light(LightInstance *light, ShadowAtlas *shado Color color = light_ptr->color * sign * energy * Math_PI; state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_COLOR, color); + Color shadow_color = light_ptr->shadow_color.to_linear(); + state.scene_shader.set_uniform(SceneShaderGLES2::SHADOW_COLOR, shadow_color); + //specific parameters switch (light_ptr->type) { @@ -2029,7 +2107,7 @@ void RasterizerSceneGLES2::_setup_refprobes(ReflectionProbeInstance *p_refprobe1 state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE2_USE_BOX_PROJECT, p_refprobe2->probe_ptr->box_projection); state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE2_BOX_EXTENTS, p_refprobe2->probe_ptr->extents); state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE2_BOX_OFFSET, p_refprobe2->probe_ptr->origin_offset); - state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE2_EXTERIOR, !p_refprobe2->probe_ptr->interior); + state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE2_EXTERIOR, p_refprobe2->probe_ptr->interior); state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE2_INTENSITY, p_refprobe2->probe_ptr->intensity); Color ambient; @@ -2108,6 +2186,8 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements, float lightmap_energy = 1.0; bool prev_use_lightmap_capture = false; + storage->info.render.draw_call_count += p_element_count; + for (int i = 0; i < p_element_count; i++) { RenderList::Element *e = p_elements[i]; @@ -2315,11 +2395,17 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements, if (e->owner != prev_owner || e->geometry != prev_geometry || skeleton != prev_skeleton) { _setup_geometry(e, skeleton); + storage->info.render.surface_switch_count++; } bool shader_rebind = false; if (rebind || material != prev_material) { + + storage->info.render.material_switch_count++; shader_rebind = _setup_material(material, p_reverse_cull, p_alpha_pass, Size2i(skeleton ? skeleton->size * 3 : 0, 0)); + if (shader_rebind) { + storage->info.render.shader_rebind_count++; + } } if (i == 0 || shader_rebind) { //first time must rebind @@ -2337,7 +2423,7 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements, Transform sky_orientation(p_env->sky_orientation, Vector3(0.0, 0.0, 0.0)); state.scene_shader.set_uniform(SceneShaderGLES2::RADIANCE_INVERSE_XFORM, sky_orientation.affine_inverse() * p_view_transform); } else { - // would be a bit weird if we dont have this... + // would be a bit weird if we don't have this... state.scene_shader.set_uniform(SceneShaderGLES2::RADIANCE_INVERSE_XFORM, p_view_transform); } } @@ -2352,7 +2438,7 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements, } else { state.scene_shader.set_uniform(SceneShaderGLES2::BG_ENERGY, 1.0); state.scene_shader.set_uniform(SceneShaderGLES2::AMBIENT_SKY_CONTRIBUTION, 1.0); - state.scene_shader.set_uniform(SceneShaderGLES2::AMBIENT_COLOR, Color(1.0, 1.0, 1.0, 1.0)); + state.scene_shader.set_uniform(SceneShaderGLES2::AMBIENT_COLOR, state.default_ambient); state.scene_shader.set_uniform(SceneShaderGLES2::AMBIENT_ENERGY, 1.0); } @@ -2412,6 +2498,12 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements, state.scene_shader.set_uniform(SceneShaderGLES2::WORLD_TRANSFORM, e->instance->transform); + if (skeleton) { + state.scene_shader.set_uniform(SceneShaderGLES2::SKELETON_IN_WORLD_COORDS, skeleton->use_world_transform); + state.scene_shader.set_uniform(SceneShaderGLES2::SKELETON_TRANSFORM, skeleton->world_transform); + state.scene_shader.set_uniform(SceneShaderGLES2::SKELETON_TRANSFORM_INVERSE, skeleton->world_transform_inverse); + } + if (use_lightmap_capture) { //this is per instance, must be set always if present glUniform4fv(state.scene_shader.get_uniform_location(SceneShaderGLES2::LIGHTMAP_CAPTURES), 12, (const GLfloat *)e->instance->lightmap_capture_data.ptr()); state.scene_shader.set_uniform(SceneShaderGLES2::LIGHTMAP_CAPTURE_SKY, false); @@ -2448,6 +2540,7 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements, state.scene_shader.set_conditional(SceneShaderGLES2::FOG_DEPTH_ENABLED, false); state.scene_shader.set_conditional(SceneShaderGLES2::FOG_HEIGHT_ENABLED, false); state.scene_shader.set_conditional(SceneShaderGLES2::USE_RADIANCE_MAP, false); + state.scene_shader.set_conditional(SceneShaderGLES2::USE_DEPTH_PREPASS, false); } void RasterizerSceneGLES2::_draw_sky(RasterizerStorageGLES2::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) { @@ -2464,7 +2557,6 @@ void RasterizerSceneGLES2::_draw_sky(RasterizerStorageGLES2::Sky *p_sky, const C glDisable(GL_CULL_FACE); glDisable(GL_BLEND); glDepthFunc(GL_LEQUAL); - glColorMask(1, 1, 1, 1); // Camera CameraMatrix camera; @@ -2518,7 +2610,7 @@ void RasterizerSceneGLES2::_draw_sky(RasterizerStorageGLES2::Sky *p_sky, const C // bind sky vertex array.... glVertexAttribPointer(VS::ARRAY_VERTEX, 3, GL_FLOAT, GL_FALSE, sizeof(Vector3) * 2, 0); - 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_VERTEX); glEnableVertexAttribArray(VS::ARRAY_TEX_UV); @@ -2555,11 +2647,21 @@ void RasterizerSceneGLES2::_draw_sky(RasterizerStorageGLES2::Sky *p_sky, const C void RasterizerSceneGLES2::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) { + Transform cam_transform = p_cam_transform; + + storage->info.render.object_count += p_cull_count; + GLuint current_fb = 0; Environment *env = NULL; int viewport_width, viewport_height; bool probe_interior = false; + bool reverse_cull = false; + + if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP]) { + cam_transform.basis.set_axis(1, -cam_transform.basis.get_axis(1)); + reverse_cull = true; + } if (p_reflection_probe.is_valid()) { ReflectionProbeInstance *probe = reflection_probe_instance_owner.getornull(p_reflection_probe); @@ -2586,6 +2688,7 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const viewport_height = storage->frame.current_rt->height; } + state.used_screen_texture = false; state.viewport_size.x = viewport_width; state.viewport_size.y = viewport_height; state.screen_pixel_size.x = 1.0 / viewport_width; @@ -2594,7 +2697,7 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const //push back the directional lights if (p_light_cull_count) { - //harcoded limit of 256 lights + //hardcoded limit of 256 lights render_light_instance_count = MIN(RenderList::MAX_LIGHTS, p_light_cull_count); render_light_instances = (LightInstance **)alloca(sizeof(LightInstance *) * render_light_instance_count); render_directional_lights = 0; @@ -2608,7 +2711,7 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const if (light->light_ptr->type == VS::LIGHT_DIRECTIONAL) { render_directional_lights++; - //as goin in reverse, directional lights are always first anyway + //as going in reverse, directional lights are always first anyway } light->light_index = index; @@ -2657,7 +2760,7 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const // clear color - Color clear_color(0, 0, 0, 0); + Color clear_color(0, 0, 0, 1); if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { clear_color = Color(0, 0, 0, 0); @@ -2678,6 +2781,8 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const glClearColor(clear_color.r, clear_color.g, clear_color.b, clear_color.a); } + state.default_ambient = Color(clear_color.r, clear_color.g, clear_color.b, 1.0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1); @@ -2709,18 +2814,23 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const if (env && env->bg_mode == VS::ENV_BG_SKY && (!storage->frame.current_rt || !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT])) { if (sky && sky->panorama.is_valid()) { - _draw_sky(sky, p_cam_projection, p_cam_transform, false, env->sky_custom_fov, env->bg_energy, env->sky_orientation); + _draw_sky(sky, p_cam_projection, cam_transform, false, env->sky_custom_fov, env->bg_energy, env->sky_orientation); } } if (probe_interior) { env_radiance_tex = 0; //do not use radiance texture on interiors + state.default_ambient = Color(0, 0, 0, 1); //black as default ambient for interior } // render opaque things first render_list.sort_by_key(false); - _render_render_list(render_list.elements, render_list.element_count, p_cam_transform, p_cam_projection, p_shadow_atlas, env, env_radiance_tex, 0.0, 0.0, false, false, false); + _render_render_list(render_list.elements, render_list.element_count, cam_transform, p_cam_projection, p_shadow_atlas, env, env_radiance_tex, 0.0, 0.0, reverse_cull, false, false); + if (storage->frame.current_rt && state.used_screen_texture) { + //copy screen texture + storage->canvas->_copy_screen(Rect2()); + } // alpha pass glBlendEquation(GL_FUNC_ADD); @@ -2728,7 +2838,7 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const render_list.sort_by_depth(true); - _render_render_list(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, p_cam_transform, p_cam_projection, p_shadow_atlas, env, env_radiance_tex, 0.0, 0.0, false, true, false); + _render_render_list(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, cam_transform, p_cam_projection, p_shadow_atlas, env, env_radiance_tex, 0.0, 0.0, reverse_cull, true, false); glDisable(GL_DEPTH_TEST); @@ -2899,7 +3009,7 @@ void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_ if (light->type == VS::LIGHT_OMNI) { // cubemap only - if (light->omni_shadow_mode == VS::LIGHT_OMNI_SHADOW_CUBE && storage->config.support_write_depth) { + if (light->omni_shadow_mode == VS::LIGHT_OMNI_SHADOW_CUBE && storage->config.support_shadow_cubemaps) { int cubemap_index = shadow_cubemaps.size() - 1; // find an appropriate cubemap to render to @@ -2968,7 +3078,9 @@ void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_ glBindFramebuffer(GL_FRAMEBUFFER, fbo); glDepthMask(GL_TRUE); - glColorMask(0, 0, 0, 0); + if (!storage->config.use_rgba_3d_shadows) { + glColorMask(0, 0, 0, 0); + } if (custom_vp_size) { glViewport(0, 0, custom_vp_size, custom_vp_size); @@ -2995,7 +3107,7 @@ void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_ state.scene_shader.set_conditional(SceneShaderGLES2::RENDER_DEPTH_DUAL_PARABOLOID, false); // convert cubemap to dual paraboloid if needed - if (light->type == VS::LIGHT_OMNI && (light->omni_shadow_mode == VS::LIGHT_OMNI_SHADOW_CUBE && storage->config.support_write_depth) && p_pass == 5) { + if (light->type == VS::LIGHT_OMNI && (light->omni_shadow_mode == VS::LIGHT_OMNI_SHADOW_CUBE && storage->config.support_shadow_cubemaps) && p_pass == 5) { ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas); glBindFramebuffer(GL_FRAMEBUFFER, shadow_atlas->fbo); @@ -3041,8 +3153,12 @@ void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_ } } - glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height); - glColorMask(1, 1, 1, 1); + if (storage->frame.current_rt) { + glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height); + } + if (!storage->config.use_rgba_3d_shadows) { + glColorMask(1, 1, 1, 1); + } } void RasterizerSceneGLES2::set_scene_pass(uint64_t p_pass) { @@ -3080,6 +3196,16 @@ bool RasterizerSceneGLES2::free(RID p_rid) { ReflectionProbeInstance *reflection_instance = reflection_probe_instance_owner.get(p_rid); + for (int i = 0; i < 6; i++) { + glDeleteFramebuffers(1, &reflection_instance->fbo[i]); + glDeleteTextures(1, &reflection_instance->color[i]); + } + + if (reflection_instance->cubemap != 0) { + glDeleteTextures(1, &reflection_instance->cubemap); + } + glDeleteRenderbuffers(1, &reflection_instance->depth); + reflection_probe_release_atlas_index(p_rid); reflection_probe_instance_owner.free(p_rid); memdelete(reflection_instance); @@ -3096,6 +3222,8 @@ void RasterizerSceneGLES2::set_debug_draw_mode(VS::ViewportDebugDraw p_debug_dra void RasterizerSceneGLES2::initialize() { state.scene_shader.init(); + + state.scene_shader.set_conditional(SceneShaderGLES2::USE_RGBA_SHADOWS, storage->config.use_rgba_3d_shadows); state.cube_to_dp_shader.init(); render_list.init(); @@ -3157,7 +3285,7 @@ void RasterizerSceneGLES2::initialize() { } // cubemaps for shadows - if (storage->config.support_write_depth) { //not going to be used + if (storage->config.support_shadow_cubemaps) { //not going to be used int max_shadow_cubemap_sampler_size = 512; int cube_size = max_shadow_cubemap_sampler_size; @@ -3174,7 +3302,8 @@ void RasterizerSceneGLES2::initialize() { glBindTexture(GL_TEXTURE_CUBE_MAP, cube.cubemap); for (int i = 0; i < 6; i++) { - glTexImage2D(_cube_side_enum[i], 0, GL_DEPTH_COMPONENT, cube_size, cube_size, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); + + glTexImage2D(_cube_side_enum[i], 0, storage->config.depth_internalformat, cube_size, cube_size, 0, GL_DEPTH_COMPONENT, storage->config.depth_type, NULL); } glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); @@ -3205,17 +3334,35 @@ void RasterizerSceneGLES2::initialize() { glGenFramebuffers(1, &directional_shadow.fbo); glBindFramebuffer(GL_FRAMEBUFFER, directional_shadow.fbo); - glGenTextures(1, &directional_shadow.depth); - glBindTexture(GL_TEXTURE_2D, directional_shadow.depth); + if (storage->config.use_rgba_3d_shadows) { + //maximum compatibility, renderbuffer and RGBA shadow + glGenRenderbuffers(1, &directional_shadow.depth); + glBindRenderbuffer(GL_RENDERBUFFER, directional_shadow.depth); + glRenderbufferStorage(GL_RENDERBUFFER, storage->config.depth_internalformat, directional_shadow.size, directional_shadow.size); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, directional_shadow.depth); + + glGenTextures(1, &directional_shadow.color); + glBindTexture(GL_TEXTURE_2D, directional_shadow.color); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, directional_shadow.size, directional_shadow.size, 0, GL_RGBA, GL_UNSIGNED_BYTE, 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); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, directional_shadow.color, 0); + } else { + //just a depth buffer + glGenTextures(1, &directional_shadow.depth); + glBindTexture(GL_TEXTURE_2D, directional_shadow.depth); - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, directional_shadow.size, directional_shadow.size, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, storage->config.depth_internalformat, directional_shadow.size, directional_shadow.size, 0, GL_DEPTH_COMPONENT, storage->config.depth_type, NULL); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, directional_shadow.depth, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, directional_shadow.depth, 0); + } GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) { @@ -3224,6 +3371,8 @@ void RasterizerSceneGLES2::initialize() { } shadow_filter_mode = SHADOW_FILTER_NEAREST; + + glFrontFace(GL_CW); } void RasterizerSceneGLES2::iteration() { |