From 22d83bc9f655d5ae7a1b49709c4c1b663725daf5 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Mon, 3 Oct 2016 16:33:42 -0300 Subject: Begining of GLES3 renderer: -Most 2D drawing is implemented -Missing shaders -Missing all 3D -Editor needs to be set on update always to be used, otherwise it does not refresh -Large parts of editor not working --- drivers/gles3/SCsub | 5 + drivers/gles3/rasterizer_canvas_gles3.cpp | 1461 ++++++++++++++++++++ drivers/gles3/rasterizer_canvas_gles3.h | 102 ++ drivers/gles3/rasterizer_gles3.cpp | 266 ++++ drivers/gles3/rasterizer_gles3.h | 38 + drivers/gles3/rasterizer_storage_gles3.cpp | 2045 ++++++++++++++++++++++++++++ drivers/gles3/rasterizer_storage_gles3.h | 445 ++++++ drivers/gles3/shader_gles3.cpp | 754 ++++++++++ drivers/gles3/shader_gles3.h | 377 +++++ drivers/gles3/shaders/SCsub | 7 + drivers/gles3/shaders/canvas.glsl | 428 ++++++ drivers/gles3/shaders/canvas_shadow.glsl | 49 + drivers/gles3/shaders/copy.glsl | 52 + 13 files changed, 6029 insertions(+) create mode 100644 drivers/gles3/SCsub create mode 100644 drivers/gles3/rasterizer_canvas_gles3.cpp create mode 100644 drivers/gles3/rasterizer_canvas_gles3.h create mode 100644 drivers/gles3/rasterizer_gles3.cpp create mode 100644 drivers/gles3/rasterizer_gles3.h create mode 100644 drivers/gles3/rasterizer_storage_gles3.cpp create mode 100644 drivers/gles3/rasterizer_storage_gles3.h create mode 100644 drivers/gles3/shader_gles3.cpp create mode 100644 drivers/gles3/shader_gles3.h create mode 100644 drivers/gles3/shaders/SCsub create mode 100644 drivers/gles3/shaders/canvas.glsl create mode 100644 drivers/gles3/shaders/canvas_shadow.glsl create mode 100644 drivers/gles3/shaders/copy.glsl (limited to 'drivers/gles3') diff --git a/drivers/gles3/SCsub b/drivers/gles3/SCsub new file mode 100644 index 0000000000..a17335b41b --- /dev/null +++ b/drivers/gles3/SCsub @@ -0,0 +1,5 @@ +Import('env') + +env.add_source_files(env.drivers_sources,"*.cpp") + +SConscript("shaders/SCsub") diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp new file mode 100644 index 0000000000..f24560763f --- /dev/null +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -0,0 +1,1461 @@ +#include "rasterizer_canvas_gles3.h" +#include "os/os.h" + +static _FORCE_INLINE_ void store_matrix32(const Matrix32& 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]; + p_array[ 2]=p_mtx.basis.elements[2][0]; + p_array[ 3]=0; + p_array[ 4]=p_mtx.basis.elements[0][1]; + p_array[ 5]=p_mtx.basis.elements[1][1]; + p_array[ 6]=p_mtx.basis.elements[2][1]; + p_array[ 7]=0; + p_array[ 8]=p_mtx.basis.elements[0][2]; + p_array[ 9]=p_mtx.basis.elements[1][2]; + p_array[10]=p_mtx.basis.elements[2][2]; + p_array[11]=0; + p_array[12]=p_mtx.origin.x; + p_array[13]=p_mtx.origin.y; + p_array[14]=p_mtx.origin.z; + p_array[15]=1; +} + +static _FORCE_INLINE_ void store_camera(const CameraMatrix& p_mtx, float* p_array) { + + for (int i=0;i<4;i++) { + for (int j=0;j<4;j++) { + + p_array[i*4+j]=p_mtx.matrix[i][j]; + } + } +} + + +RID RasterizerCanvasGLES3::light_internal_create() { + + LightInternal * li = memnew( LightInternal ); + + glGenBuffers(1, &li->ubo); + glBindBuffer(GL_UNIFORM_BUFFER, li->ubo); + glBufferData(GL_UNIFORM_BUFFER, sizeof(LightInternal::UBOData), &state.canvas_item_ubo_data, GL_DYNAMIC_DRAW); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + + return light_internal_owner.make_rid(li); +} + +void RasterizerCanvasGLES3::light_internal_update(RID p_rid, Light* p_light) { + + LightInternal * li = light_internal_owner.getornull(p_rid); + ERR_FAIL_COND(!li); + + store_matrix32(p_light->light_shader_xform,li->ubo_data.light_matrix); + store_matrix32(p_light->xform_cache.affine_inverse(),li->ubo_data.local_matrix); + store_camera(p_light->shadow_matrix_cache,li->ubo_data.shadow_matrix); + + for(int i=0;i<4;i++) { + + li->ubo_data.color[i]=p_light->color[i]*p_light->energy; + li->ubo_data.shadow_color[i]=p_light->shadow_color[i]; + } + + li->ubo_data.light_pos[0]=p_light->light_shader_pos.x; + li->ubo_data.light_pos[1]=p_light->light_shader_pos.y; + li->ubo_data.shadowpixel_size=1.0/p_light->shadow_buffer_size; + li->ubo_data.light_outside_alpha=p_light->mode==VS::CANVAS_LIGHT_MODE_MASK?1.0:0.0; + li->ubo_data.light_height=p_light->height; + if (p_light->radius_cache==0) + li->ubo_data.shadow_gradient=0; + else + li->ubo_data.shadow_gradient=p_light->shadow_gradient_length/(p_light->radius_cache*1.1);; + + li->ubo_data.shadow_distance_mult=(p_light->radius_cache*1.1); + + + glBindBuffer(GL_UNIFORM_BUFFER, li->ubo); + glBufferSubData(GL_UNIFORM_BUFFER, 0,sizeof(LightInternal::UBOData), &li->ubo_data); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + +} + +void RasterizerCanvasGLES3::light_internal_free(RID p_rid) { + + LightInternal * li = light_internal_owner.getornull(p_rid); + ERR_FAIL_COND(!li); + + glDeleteBuffers(1,&li->ubo); + light_internal_owner.free(p_rid); + memdelete(li); + +} + +void RasterizerCanvasGLES3::canvas_begin(){ + + /*canvas_shader.unbind(); + canvas_shader.set_custom_shader(0); + canvas_shader.set_conditional(CanvasShaderGLES2::USE_MODULATE,false); + canvas_shader.bind(); + canvas_shader.set_uniform(CanvasShaderGLES2::TEXTURE, 0); + canvas_use_modulate=false;*/ + + reset_canvas(); + + state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_TEXTURE_RECT,true); + 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_PCF5,false); + state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF13,false); + state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_DISTANCE_FIELD,false); + + + state.canvas_shader.bind(); + state.canvas_shader.set_uniform(CanvasShaderGLES3::FINAL_MODULATE,Color(1,1,1,1)); + state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX,Matrix32()); + state.canvas_shader.set_uniform(CanvasShaderGLES3::EXTRA_MATRIX,Matrix32()); + + + + +// state.canvas_shader.set_uniform(CanvasShaderGLES3::PROJECTION_MATRIX,state.vp); + //state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX,Transform()); + //state.canvas_shader.set_uniform(CanvasShaderGLES3::EXTRA_MATRIX,Transform()); + + glBindBufferBase(GL_UNIFORM_BUFFER,0,state.canvas_item_ubo); + glBindVertexArray(data.canvas_quad_array); + state.using_texture_rect=true; + + +} + + +void RasterizerCanvasGLES3::canvas_end(){ + + + glBindVertexArray(0); + glBindBufferBase(GL_UNIFORM_BUFFER,0,0); + + state.using_texture_rect=false; + +} + + + +RasterizerStorageGLES3::Texture* RasterizerCanvasGLES3::_bind_canvas_texture(const RID& p_texture) { + + if (p_texture==state.current_tex) { + return state.current_tex_ptr; + } + + if (p_texture.is_valid()) { + + + RasterizerStorageGLES3::Texture*texture=storage->texture_owner.getornull(p_texture); + + if (!texture) { + state.current_tex=RID(); + state.current_tex_ptr=NULL; + glBindTexture(GL_TEXTURE_2D,storage->resources.white_tex); + return NULL; + } + + if (texture->render_target) + texture->render_target->used_in_frame=true; + + glBindTexture(GL_TEXTURE_2D,texture->tex_id); + state.current_tex=p_texture; + state.current_tex_ptr=texture; + + return texture; + + + } else { + + + glBindTexture(GL_TEXTURE_2D,storage->resources.white_tex); + state.current_tex=RID(); + state.current_tex_ptr=NULL; + } + + + return NULL; +} + +void RasterizerCanvasGLES3::_set_texture_rect_mode(bool p_enable) { + + if (state.using_texture_rect==p_enable) + return; + + if (p_enable) { + glBindVertexArray(data.canvas_quad_array); + + + } else { + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER,0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); + + + } + + state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_TEXTURE_RECT,p_enable); + state.canvas_shader.bind(); + 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,state.extra_matrix); + + + state.using_texture_rect=p_enable; +} + + +void RasterizerCanvasGLES3::_draw_polygon(int p_vertex_count, const int* p_indices, const Vector2* p_vertices, const Vector2* p_uvs, const Color* p_colors,const RID& p_texture,bool p_singlecolor) { + + bool do_colors=false; + Color m; + if (p_singlecolor) { + m = *p_colors; + glVertexAttrib4f(VS::ARRAY_COLOR,m.r,m.g,m.b,m.a); + } else if (!p_colors) { + + glVertexAttrib4f(VS::ARRAY_COLOR,1,1,1,1); + } else + do_colors=true; + + RasterizerStorageGLES3::Texture *texture = _bind_canvas_texture(p_texture); + +#ifndef GLES_NO_CLIENT_ARRAYS + glEnableVertexAttribArray(VS::ARRAY_VERTEX); + glVertexAttribPointer( VS::ARRAY_VERTEX, 2 ,GL_FLOAT, false, sizeof(Vector2), p_vertices ); + if (do_colors) { + + glEnableVertexAttribArray(VS::ARRAY_COLOR); + glVertexAttribPointer( VS::ARRAY_COLOR, 4 ,GL_FLOAT, false, sizeof(Color), p_colors ); + } else { + glDisableVertexAttribArray(VS::ARRAY_COLOR); + } + + if (texture && p_uvs) { + + glEnableVertexAttribArray(VS::ARRAY_TEX_UV); + glVertexAttribPointer( VS::ARRAY_TEX_UV, 2 ,GL_FLOAT, false, sizeof(Vector2), p_uvs ); + } else { + glDisableVertexAttribArray(VS::ARRAY_TEX_UV); + } + + if (p_indices) { +#ifdef GLEW_ENABLED + glDrawElements(GL_TRIANGLES, p_vertex_count, GL_UNSIGNED_INT, p_indices ); +#else + static const int _max_draw_poly_indices = 16*1024; // change this size if needed!!! + ERR_FAIL_COND(p_vertex_count > _max_draw_poly_indices); + static uint16_t _draw_poly_indices[_max_draw_poly_indices]; + for (int i=0; i MAX_POLYGON_VERTICES){ + print_line("Too many vertices to render"); + return; + } + glEnableVertexAttribArray(VS::ARRAY_VERTEX); + glVertexAttribPointer( VS::ARRAY_VERTEX, 2 ,GL_FLOAT, false, sizeof(float)*2, ((float*)0)+ofs ); + for(int i=0;i _max_draw_poly_indices); + static uint16_t _draw_poly_indices[_max_draw_poly_indices]; + for (int i=0; iprint("ind: %d ", p_indices[i]); + }; + + //copy the data to GPU. + glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, p_vertex_count * sizeof(uint16_t), &_draw_poly_indices[0]); + + //draw the triangles. + glDrawElements(GL_TRIANGLES, p_vertex_count, GL_UNSIGNED_SHORT, 0); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); +#endif + + storage->frame.canvas_draw_commands++; + +} + +void RasterizerCanvasGLES3::_draw_gui_primitive(int p_points, const Vector2 *p_vertices, const Color* p_colors, const Vector2 *p_uvs) { + + + + static const GLenum prim[5]={GL_POINTS,GL_POINTS,GL_LINES,GL_TRIANGLES,GL_TRIANGLE_FAN}; + + + //#define GLES_USE_PRIMITIVE_BUFFER + +#ifndef GLES_NO_CLIENT_ARRAYS + + glEnableVertexAttribArray(VS::ARRAY_VERTEX); + glVertexAttribPointer( VS::ARRAY_VERTEX, 2 ,GL_FLOAT, false, sizeof(Vector2), p_vertices ); + + if (p_colors) { + + glEnableVertexAttribArray(VS::ARRAY_COLOR); + glVertexAttribPointer( VS::ARRAY_COLOR, 4 ,GL_FLOAT, false, sizeof(Color), p_colors ); + } else { + glDisableVertexAttribArray(VS::ARRAY_COLOR); + } + + if (p_uvs) { + + glEnableVertexAttribArray(VS::ARRAY_TEX_UV); + glVertexAttribPointer( VS::ARRAY_TEX_UV, 2 ,GL_FLOAT, false, sizeof(Vector2), p_uvs ); + } else { + glDisableVertexAttribArray(VS::ARRAY_TEX_UV); + } + + glDrawArrays(prim[p_points],0,p_points); + +#else + + glBindBuffer(GL_ARRAY_BUFFER,gui_quad_buffer); + float b[32]; + int ofs=0; + glEnableVertexAttribArray(VS::ARRAY_VERTEX); + glVertexAttribPointer( VS::ARRAY_VERTEX, 2 ,GL_FLOAT, false, sizeof(float)*2, ((float*)0)+ofs ); + for(int i=0;iframe.canvas_draw_commands++; +} + +void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item,Item *current_clip,bool &reclip) { + + int cc=p_item->commands.size(); + Item::Command **commands = p_item->commands.ptr(); + + + for(int i=0;itype) { + case Item::Command::TYPE_LINE: { + + + Item::CommandLine* line = static_cast(c); + _set_texture_rect_mode(false); + + + _bind_canvas_texture(RID()); + + glVertexAttrib4f(VS::ARRAY_COLOR,line->color.r,line->color.g,line->color.b,line->color.a); + + Vector2 verts[2]={ + Vector2(line->from.x,line->from.y), + Vector2(line->to.x,line->to.y) + }; + +#ifdef GLEW_ENABLED + if (line->antialiased) + glEnable(GL_LINE_SMOOTH); +#endif + glLineWidth(line->width); + _draw_gui_primitive(2,verts,NULL,NULL); + +#ifdef GLEW_ENABLED + if (line->antialiased) + glDisable(GL_LINE_SMOOTH); +#endif + + + } break; + case Item::Command::TYPE_RECT: { + + Item::CommandRect* rect = static_cast(c); + + _set_texture_rect_mode(true); + + //set color + glVertexAttrib4f(VS::ARRAY_COLOR,rect->modulate.r,rect->modulate.g,rect->modulate.b,rect->modulate.a); + + RasterizerStorageGLES3::Texture* texture = _bind_canvas_texture(rect->texture); + + if ( texture ) { + + bool untile=false; + + if (rect->flags&CANVAS_RECT_TILE && !(texture->flags&VS::TEXTURE_FLAG_REPEAT)) { + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); + untile=true; + } + + Size2 texpixel_size( 1.0/texture->width, 1.0/texture->height ); + Rect2 src_rect = (rect->flags&CANVAS_RECT_REGION) ? Rect2( rect->source.pos * texpixel_size, rect->source.size * texpixel_size ) : Rect2(0,0,1,1); + + if (rect->flags&CANVAS_RECT_FLIP_H) { + src_rect.size.x*=-1; + } + + if (rect->flags&CANVAS_RECT_FLIP_V) { + src_rect.size.x*=-1; + } + + if (rect->flags&CANVAS_RECT_TRANSPOSE) { + //err.. + } + + + glVertexAttrib4f(1,rect->rect.pos.x,rect->rect.pos.y,rect->rect.size.x,rect->rect.size.y); + glVertexAttrib4f(2,src_rect.pos.x,src_rect.pos.y,src_rect.size.x,src_rect.size.y); + glDrawArrays(GL_TRIANGLE_FAN,0,4); + + + if (untile) { + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); + } + + } else { + + + glVertexAttrib4f(1,rect->rect.pos.x,rect->rect.pos.y,rect->rect.size.x,rect->rect.size.y); + glVertexAttrib4f(2,0,0,1,1); + glDrawArrays(GL_TRIANGLE_FAN,0,4); + + + } + + storage->frame.canvas_draw_commands++; + + } break; + + case Item::Command::TYPE_NINEPATCH: { + + Item::CommandNinePatch* np = static_cast(c); + + _set_texture_rect_mode(true); + + glVertexAttrib4f(VS::ARRAY_COLOR,np->color.r,np->color.g,np->color.b,np->color.a); + + + RasterizerStorageGLES3::Texture* texture = _bind_canvas_texture(np->texture); + + if ( !texture ) { + + glVertexAttrib4f(1,np->rect.pos.x,np->rect.pos.y,np->rect.size.x,np->rect.size.y); + glVertexAttrib4f(2,0,0,1,1); + glDrawArrays(GL_TRIANGLE_FAN,0,4); + continue; + } + + + Size2 texpixel_size( 1.0/texture->width, 1.0/texture->height ); + +#define DSTRECT(m_x,m_y,m_w,m_h) glVertexAttrib4f(1,m_x,m_y,m_w,m_h) +#define SRCRECT(m_x,m_y,m_w,m_h) glVertexAttrib4f(2,(m_x)*texpixel_size.x,(m_y)*texpixel_size.y,(m_w)*texpixel_size.x,(m_h)*texpixel_size.y) + + //top left + DSTRECT(np->rect.pos.x,np->rect.pos.y,np->margin[MARGIN_LEFT],np->margin[MARGIN_TOP]); + SRCRECT(0,0,np->margin[MARGIN_LEFT],np->margin[MARGIN_TOP]); + glDrawArrays(GL_TRIANGLE_FAN,0,4); + + //top right + DSTRECT(np->rect.pos.x+np->rect.size.x-np->margin[MARGIN_RIGHT],np->rect.pos.y,np->margin[MARGIN_RIGHT],np->margin[MARGIN_TOP]); + SRCRECT(texture->width-np->margin[MARGIN_RIGHT],0,np->margin[MARGIN_RIGHT],np->margin[MARGIN_TOP]); + glDrawArrays(GL_TRIANGLE_FAN,0,4); + + //bottom right + DSTRECT(np->rect.pos.x+np->rect.size.x-np->margin[MARGIN_RIGHT],np->rect.pos.y+np->rect.size.y-np->margin[MARGIN_BOTTOM],np->margin[MARGIN_RIGHT],np->margin[MARGIN_BOTTOM]); + SRCRECT(texture->width-np->margin[MARGIN_RIGHT],texture->height-np->margin[MARGIN_BOTTOM],np->margin[MARGIN_RIGHT],np->margin[MARGIN_BOTTOM]); + glDrawArrays(GL_TRIANGLE_FAN,0,4); + + //bottom left + DSTRECT(np->rect.pos.x,np->rect.pos.y+np->rect.size.y-np->margin[MARGIN_BOTTOM],np->margin[MARGIN_LEFT],np->margin[MARGIN_BOTTOM]); + SRCRECT(0,texture->height-np->margin[MARGIN_BOTTOM],np->margin[MARGIN_LEFT],np->margin[MARGIN_BOTTOM]); + glDrawArrays(GL_TRIANGLE_FAN,0,4); + + + //top + DSTRECT(np->rect.pos.x+np->margin[MARGIN_LEFT],np->rect.pos.y,np->rect.size.width-np->margin[MARGIN_LEFT]-np->margin[MARGIN_RIGHT],np->margin[MARGIN_TOP]); + SRCRECT(np->margin[MARGIN_LEFT],0,texture->width-np->margin[MARGIN_LEFT]-np->margin[MARGIN_RIGHT],np->margin[MARGIN_TOP]); + glDrawArrays(GL_TRIANGLE_FAN,0,4); + + //bottom + DSTRECT(np->rect.pos.x+np->margin[MARGIN_LEFT],np->rect.pos.y+np->rect.size.y-np->margin[MARGIN_BOTTOM],np->rect.size.width-np->margin[MARGIN_LEFT]-np->margin[MARGIN_RIGHT],np->margin[MARGIN_TOP]); + SRCRECT(np->margin[MARGIN_LEFT],texture->height-np->margin[MARGIN_BOTTOM],texture->width-np->margin[MARGIN_LEFT]-np->margin[MARGIN_LEFT],np->margin[MARGIN_TOP]); + glDrawArrays(GL_TRIANGLE_FAN,0,4); + + + //left + DSTRECT(np->rect.pos.x,np->rect.pos.y+np->margin[MARGIN_TOP],np->margin[MARGIN_LEFT],np->rect.size.height-np->margin[MARGIN_TOP]-np->margin[MARGIN_BOTTOM]); + SRCRECT(0,np->margin[MARGIN_TOP],np->margin[MARGIN_LEFT],texture->height-np->margin[MARGIN_TOP]-np->margin[MARGIN_BOTTOM]); + glDrawArrays(GL_TRIANGLE_FAN,0,4); + + //right + DSTRECT(np->rect.pos.x+np->rect.size.width-np->margin[MARGIN_RIGHT],np->rect.pos.y+np->margin[MARGIN_TOP],np->margin[MARGIN_RIGHT],np->rect.size.height-np->margin[MARGIN_TOP]-np->margin[MARGIN_BOTTOM]); + SRCRECT(texture->width-np->margin[MARGIN_RIGHT],np->margin[MARGIN_TOP],np->margin[MARGIN_RIGHT],texture->height-np->margin[MARGIN_TOP]-np->margin[MARGIN_BOTTOM]); + glDrawArrays(GL_TRIANGLE_FAN,0,4); + + if (np->draw_center) { + + //center + DSTRECT(np->rect.pos.x+np->margin[MARGIN_LEFT],np->rect.pos.y+np->margin[MARGIN_TOP],np->rect.size.x-np->margin[MARGIN_LEFT]-np->margin[MARGIN_RIGHT],np->rect.size.height-np->margin[MARGIN_TOP]-np->margin[MARGIN_BOTTOM]); + SRCRECT(np->margin[MARGIN_LEFT],np->margin[MARGIN_TOP],texture->width-np->margin[MARGIN_LEFT]-np->margin[MARGIN_RIGHT],texture->height-np->margin[MARGIN_TOP]-np->margin[MARGIN_BOTTOM]); + glDrawArrays(GL_TRIANGLE_FAN,0,4); + + } + +#undef SRCRECT +#undef DSTRECT + + storage->frame.canvas_draw_commands++; + } break; + + case Item::Command::TYPE_PRIMITIVE: { + + Item::CommandPrimitive* primitive = static_cast(c); + _set_texture_rect_mode(false); + + ERR_CONTINUE( primitive->points.size()<1); + + _bind_canvas_texture(primitive->texture); + + 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); + + } else if (primitive->colors.empty()) { + glVertexAttrib4f(VS::ARRAY_COLOR,1,1,1,1); + } + + _draw_gui_primitive(primitive->points.size(),primitive->points.ptr(),primitive->colors.ptr(),primitive->uvs.ptr()); + + } break; + case Item::Command::TYPE_POLYGON: { + + Item::CommandPolygon* polygon = static_cast(c); + _set_texture_rect_mode(false); + _draw_polygon(polygon->count,polygon->indices.ptr(),polygon->points.ptr(),polygon->uvs.ptr(),polygon->colors.ptr(),polygon->texture,polygon->colors.size()==1); + + } break; + case Item::Command::TYPE_CIRCLE: { + + _set_texture_rect_mode(false); + + Item::CommandCircle* circle = static_cast(c); + static const int numpoints=32; + Vector2 points[numpoints+1]; + points[numpoints]=circle->pos; + int indices[numpoints*3]; + + for(int i=0;ipos+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; + } + _draw_polygon(numpoints*3,indices,points,NULL,&circle->color,RID(),true); + //canvas_draw_circle(circle->indices.size(),circle->indices.ptr(),circle->points.ptr(),circle->uvs.ptr(),circle->colors.ptr(),circle->texture,circle->colors.size()==1); + } break; + case Item::Command::TYPE_TRANSFORM: { + + Item::CommandTransform* transform = static_cast(c); + state.extra_matrix=transform->xform; + state.canvas_shader.set_uniform(CanvasShaderGLES3::EXTRA_MATRIX,state.extra_matrix); + + } break; + case Item::Command::TYPE_CLIP_IGNORE: { + + Item::CommandClipIgnore* ci = static_cast(c); + if (current_clip) { + + if (ci->ignore!=reclip) { + if (ci->ignore) { + + glDisable(GL_SCISSOR_TEST); + reclip=true; + } else { + + glEnable(GL_SCISSOR_TEST); + //glScissor(viewport.x+current_clip->final_clip_rect.pos.x,viewport.y+ (viewport.height-(current_clip->final_clip_rect.pos.y+current_clip->final_clip_rect.size.height)), + //current_clip->final_clip_rect.size.width,current_clip->final_clip_rect.size.height); + + int x = current_clip->final_clip_rect.pos.x; + int y = storage->frame.current_rt->height - ( current_clip->final_clip_rect.pos.y + current_clip->final_clip_rect.size.y ); + int w = current_clip->final_clip_rect.size.x; + int h = current_clip->final_clip_rect.size.y; + + glScissor(x,y,w,h); + + reclip=false; + } + } + } + + + + } break; + } + } +} + +#if 0 +void RasterizerGLES2::_canvas_item_setup_shader_params(CanvasItemMaterial *material,Shader* shader) { + + if (canvas_shader.bind()) + rebind_texpixel_size=true; + + if (material->shader_version!=shader->version) { + //todo optimize uniforms + material->shader_version=shader->version; + } + + if (shader->has_texscreen && framebuffer.active) { + + int x = viewport.x; + int y = window_size.height-(viewport.height+viewport.y); + + canvas_shader.set_uniform(CanvasShaderGLES2::TEXSCREEN_SCREEN_MULT,Vector2(float(viewport.width)/framebuffer.width,float(viewport.height)/framebuffer.height)); + canvas_shader.set_uniform(CanvasShaderGLES2::TEXSCREEN_SCREEN_CLAMP,Color(float(x)/framebuffer.width,float(y)/framebuffer.height,float(x+viewport.width)/framebuffer.width,float(y+viewport.height)/framebuffer.height)); + canvas_shader.set_uniform(CanvasShaderGLES2::TEXSCREEN_TEX,max_texture_units-1); + glActiveTexture(GL_TEXTURE0+max_texture_units-1); + glBindTexture(GL_TEXTURE_2D,framebuffer.sample_color); + if (framebuffer.scale==1 && !canvas_texscreen_used) { +#ifdef GLEW_ENABLED + if (current_rt) { + glReadBuffer(GL_COLOR_ATTACHMENT0); + } else { + glReadBuffer(GL_BACK); + } +#endif + if (current_rt) { + glCopyTexSubImage2D(GL_TEXTURE_2D,0,viewport.x,viewport.y,viewport.x,viewport.y,viewport.width,viewport.height); + canvas_shader.set_uniform(CanvasShaderGLES2::TEXSCREEN_SCREEN_CLAMP,Color(float(x)/framebuffer.width,float(viewport.y)/framebuffer.height,float(x+viewport.width)/framebuffer.width,float(y+viewport.height)/framebuffer.height)); + //window_size.height-(viewport.height+viewport.y) + } else { + glCopyTexSubImage2D(GL_TEXTURE_2D,0,x,y,x,y,viewport.width,viewport.height); + } +// if (current_clip) { +// // print_line(" a clip "); +// } + + canvas_texscreen_used=true; + } + + glActiveTexture(GL_TEXTURE0); + + } + + if (shader->has_screen_uv) { + canvas_shader.set_uniform(CanvasShaderGLES2::SCREEN_UV_MULT,Vector2(1.0/viewport.width,1.0/viewport.height)); + } + + + uses_texpixel_size=shader->uses_texpixel_size; + +} + +#endif + +void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list,int p_z,const Color& p_modulate,Light *p_light) { + + + if (storage->frame.clear_request) { + // a clear request may be pending, so do it + 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 ); + glClear(GL_COLOR_BUFFER_BIT); + storage->frame.clear_request=false; + + + } + + Item *current_clip=NULL; + RasterizerStorageGLES3::Shader *shader_cache=NULL; + + 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); + + state.current_tex=RID(); + state.current_tex_ptr=NULL; + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,storage->resources.white_tex); + + + RID canvas_last_material; + + bool prev_distance_field=false; + + while(p_item_list) { + + Item *ci=p_item_list; + + + if (prev_distance_field!=ci->distance_field) { + + state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_DISTANCE_FIELD,ci->distance_field); + prev_distance_field=ci->distance_field; + rebind_shader=true; + } + + + if (current_clip!=ci->final_clip_owner) { + + current_clip=ci->final_clip_owner; + + //setup clip + if (current_clip) { + + glEnable(GL_SCISSOR_TEST); + glScissor(current_clip->final_clip_rect.pos.x,(rt_size.height-(current_clip->final_clip_rect.pos.y+current_clip->final_clip_rect.size.height)),current_clip->final_clip_rect.size.width,current_clip->final_clip_rect.size.height); + + + } else { + + glDisable(GL_SCISSOR_TEST); + } + } +#if 0 + if (ci->copy_back_buffer && framebuffer.active && framebuffer.scale==1) { + + Rect2 rect; + int x,y; + + if (ci->copy_back_buffer->full) { + + x = viewport.x; + y = window_size.height-(viewport.height+viewport.y); + } else { + x = viewport.x+ci->copy_back_buffer->screen_rect.pos.x; + y = window_size.height-(viewport.y+ci->copy_back_buffer->screen_rect.pos.y+ci->copy_back_buffer->screen_rect.size.y); + } + glActiveTexture(GL_TEXTURE0+max_texture_units-1); + glBindTexture(GL_TEXTURE_2D,framebuffer.sample_color); + +#ifdef GLEW_ENABLED + if (current_rt) { + glReadBuffer(GL_COLOR_ATTACHMENT0); + } else { + glReadBuffer(GL_BACK); + } +#endif + if (current_rt) { + glCopyTexSubImage2D(GL_TEXTURE_2D,0,viewport.x,viewport.y,viewport.x,viewport.y,viewport.width,viewport.height); + //window_size.height-(viewport.height+viewport.y) + } else { + glCopyTexSubImage2D(GL_TEXTURE_2D,0,x,y,x,y,viewport.width,viewport.height); + } + + canvas_texscreen_used=true; + glActiveTexture(GL_TEXTURE0); + + } + +#endif + + + //begin rect + Item *material_owner = ci->material_owner?ci->material_owner:ci; + + RID material = material_owner->material; + + if (material!=canvas_last_material || rebind_shader) { +#if 0 + Shader *shader = NULL; + if (material && material->shader.is_valid()) { + shader = shader_owner.get(material->shader); + if (shader && !shader->valid) { + shader=NULL; + } + } + + shader_cache=shader; + + if (shader) { + canvas_shader.set_custom_shader(shader->custom_code_id); + _canvas_item_setup_shader_params(material,shader); + } else { + shader_cache=NULL; + canvas_shader.set_custom_shader(0); + canvas_shader.bind(); + uses_texpixel_size=false; + + } + + + canvas_shader.set_uniform(CanvasShaderGLES3::PROJECTION_MATRIX,canvas_transform); + if (canvas_use_modulate) + reset_modulate=true; + canvas_last_material=material; + rebind_shader=false; +#endif + } + + if (material.is_valid() && shader_cache) { +#if 0 + _canvas_item_setup_shader_uniforms(material,shader_cache); +#endif + } + + bool unshaded = false; //(material && material->shading_mode==VS::CANVAS_ITEM_SHADING_UNSHADED) || ci->blend_mode!=VS::MATERIAL_BLEND_MODE_MIX; + bool reclip=false; +#if 0 + if (ci==p_item_list || ci->blend_mode!=canvas_blend_mode) { + + switch(ci->blend_mode) { + + case VS::MATERIAL_BLEND_MODE_MIX: { + glBlendEquation(GL_FUNC_ADD); + if (current_rt && current_rt_transparent) { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } + else { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + + } break; + case VS::MATERIAL_BLEND_MODE_ADD: { + + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA,GL_ONE); + + } break; + case VS::MATERIAL_BLEND_MODE_SUB: { + + glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); + glBlendFunc(GL_SRC_ALPHA,GL_ONE); + } break; + case VS::MATERIAL_BLEND_MODE_MUL: { + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_DST_COLOR,GL_ZERO); + } break; + case VS::MATERIAL_BLEND_MODE_PREMULT_ALPHA: { + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA); + } break; + + } + + canvas_blend_mode=ci->blend_mode; + } +#endif + +// canvas_shader.set_uniform(CanvasShaderGLES3::CANVAS_MODULATE,unshaded ? Color(1,1,1,1) : p_modulate); + + state.canvas_item_modulate = unshaded ? ci->final_modulate : Color( + ci->final_modulate.r * p_modulate.r, + ci->final_modulate.g * p_modulate.g, + ci->final_modulate.b * p_modulate.b, + ci->final_modulate.a * p_modulate.a ); + + state.final_transform = ci->final_transform; + state.extra_matrix=Matrix32(); + + 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,state.extra_matrix); + + + if (unshaded || (state.canvas_item_modulate.a>0.001 && (!material.is_valid() /*|| material->shading_mode!=VS::CANVAS_ITEM_SHADING_ONLY_LIGHT*/) && !ci->light_masked )) + _canvas_item_render_commands(ci,current_clip,reclip); + + if (/*canvas_blend_mode==VS::MATERIAL_BLEND_MODE_MIX &&*/ p_light && !unshaded) { + + Light *light = p_light; + bool light_used=false; + VS::CanvasLightMode mode=VS::CANVAS_LIGHT_MODE_ADD; + state.canvas_item_modulate=ci->final_modulate; // remove the canvas modulate + + + while(light) { + + + if (ci->light_mask&light->item_mask && p_z>=light->z_min && p_z<=light->z_max && ci->global_rect_cache.intersects_transformed(light->xform_cache,light->rect_cache)) { + + //intersects this light + + if (!light_used || mode!=light->mode) { + + mode=light->mode; + + switch(mode) { + + case VS::CANVAS_LIGHT_MODE_ADD: { + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA,GL_ONE); + + } break; + case VS::CANVAS_LIGHT_MODE_SUB: { + glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); + glBlendFunc(GL_SRC_ALPHA,GL_ONE); + } break; + case VS::CANVAS_LIGHT_MODE_MIX: + case VS::CANVAS_LIGHT_MODE_MASK: { + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + } break; + } + + } + + if (!light_used) { + + state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_LIGHTING,true); + light_used=true; + + } + + + bool has_shadow = light->shadow_buffer.is_valid() && ci->light_mask&light->item_shadow_mask; + + + 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_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; + } + + + } + + bool light_rebind = state.canvas_shader.bind(); + + if (light_rebind) { +#if 0 + if (material && shader_cache) { + _canvas_item_setup_shader_params(material,shader_cache); + _canvas_item_setup_shader_uniforms(material,shader_cache); + } +#endif + 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,Matrix32()); + + } + + glBindBufferBase(GL_UNIFORM_BUFFER,1,static_cast(light->light_internal.get_data())->ubo); + + if (has_shadow) { + + RasterizerStorageGLES3::CanvasLightShadow *cls = storage->canvas_light_shadow_owner.get(light->shadow_buffer); + glActiveTexture(GL_TEXTURE0+storage->config.max_texture_image_units-2); + glBindTexture(GL_TEXTURE_2D,cls->distance); + + /*canvas_shader.set_uniform(CanvasShaderGLES3::SHADOW_MATRIX,light->shadow_matrix_cache); + canvas_shader.set_uniform(CanvasShaderGLES3::SHADOW_ESM_MULTIPLIER,light->shadow_esm_mult); + canvas_shader.set_uniform(CanvasShaderGLES3::LIGHT_SHADOW_COLOR,light->shadow_color);*/ + + } + + glActiveTexture(GL_TEXTURE0+storage->config.max_texture_image_units-1); + RasterizerStorageGLES3::Texture *t = storage->texture_owner.getornull(light->texture); + if (!t) { + glBindTexture(GL_TEXTURE_2D,storage->resources.white_tex); + } else { + + glBindTexture(t->target,t->tex_id); + } + + glActiveTexture(GL_TEXTURE0); + _canvas_item_render_commands(ci,current_clip,reclip); //redraw using light + + } + + light=light->next_ptr; + } + + if (light_used) { + + + 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_PCF9,false); + state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF13,false); + + + state.canvas_shader.bind(); +#if 0 + if (material && shader_cache) { + _canvas_item_setup_shader_params(material,shader_cache); + _canvas_item_setup_shader_uniforms(material,shader_cache); + } +#endif + + state.canvas_item_modulate = unshaded ? ci->final_modulate : Color( + ci->final_modulate.r * p_modulate.r, + ci->final_modulate.g * p_modulate.g, + ci->final_modulate.b * p_modulate.b, + ci->final_modulate.a * p_modulate.a ); + + + state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX,state.final_transform); + state.canvas_shader.set_uniform(CanvasShaderGLES3::EXTRA_MATRIX,Matrix32()); + state.canvas_shader.set_uniform(CanvasShaderGLES3::FINAL_MODULATE,state.canvas_item_modulate); + + + glBlendEquation(GL_FUNC_ADD); + + if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } else { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + + //@TODO RESET canvas_blend_mode + } + + + } + + if (reclip) { + + glEnable(GL_SCISSOR_TEST); + glScissor(current_clip->final_clip_rect.pos.x,(rt_size.height-(current_clip->final_clip_rect.pos.y+current_clip->final_clip_rect.size.height)),current_clip->final_clip_rect.size.width,current_clip->final_clip_rect.size.height); + + + } + + + + p_item_list=p_item_list->next; + } + + if (current_clip) { + glDisable(GL_SCISSOR_TEST); + } + +} + +void RasterizerCanvasGLES3::canvas_debug_viewport_shadows(Light* p_lights_with_shadow){ + + Light* light=p_lights_with_shadow; + + canvas_begin(); //reset + glVertexAttrib4f(VS::ARRAY_COLOR,1,1,1,1); + int h = 10; + int w = storage->frame.current_rt->width; + int ofs = h; + glDisable(GL_BLEND); + + //print_line(" debug lights "); + while(light) { + + + // print_line("debug light"); + if (light->shadow_buffer.is_valid()) { + + // print_line("sb is valid"); + RasterizerStorageGLES3::CanvasLightShadow * sb = storage->canvas_light_shadow_owner.get(light->shadow_buffer); + if (sb) { + glBindTexture(GL_TEXTURE_2D,sb->distance); + //glBindTexture(GL_TEXTURE_2D,storage->resources.white_tex); + draw_generic_textured_rect(Rect2(h,ofs,w-h*2,h),Rect2(0,0,1,1)); + ofs+=h*2; + + } + } + + light=light->shadows_next_ptr; + } +} + + +void RasterizerCanvasGLES3::canvas_light_shadow_buffer_update(RID p_buffer, const Matrix32& p_light_xform, int p_light_mask,float p_near, float p_far, LightOccluderInstance* p_occluders, CameraMatrix *p_xform_cache) { + + RasterizerStorageGLES3::CanvasLightShadow *cls = storage->canvas_light_shadow_owner.get(p_buffer); + ERR_FAIL_COND(!cls); + + + glDisable(GL_BLEND); + glDisable(GL_SCISSOR_TEST); + glDisable(GL_DITHER); + glDisable(GL_CULL_FACE); + glDepthFunc(GL_LEQUAL); + glEnable(GL_DEPTH_TEST); + glDepthMask(true); + + glBindFramebuffer(GL_FRAMEBUFFER, cls->fbo); + + glEnableVertexAttribArray(VS::ARRAY_VERTEX); + state.canvas_shadow_shader.bind(); + + glViewport(0, 0, cls->size,cls->height); + glClearDepth(1.0f); + glClearColor(1,1,1,1); + glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + + VS::CanvasOccluderPolygonCullMode cull=VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; + + + for(int i=0;i<4;i++) { + + //make sure it remains orthogonal, makes easy to read angle later + + Transform light; + light.origin[0]=p_light_xform[2][0]; + light.origin[1]=p_light_xform[2][1]; + light.basis[0][0]=p_light_xform[0][0]; + light.basis[0][1]=p_light_xform[1][0]; + light.basis[1][0]=p_light_xform[0][1]; + light.basis[1][1]=p_light_xform[1][1]; + + //light.basis.scale(Vector3(to_light.elements[0].length(),to_light.elements[1].length(),1)); + + /// p_near=1; + CameraMatrix projection; + { + real_t fov = 90; + real_t near = p_near; + real_t far = p_far; + real_t aspect = 1.0; + + real_t ymax = near * Math::tan( Math::deg2rad( fov * 0.5 ) ); + real_t ymin = - ymax; + real_t xmin = ymin * aspect; + real_t xmax = ymax * aspect; + + projection.set_frustum( xmin, xmax, ymin, ymax, near, far ); + } + + Vector3 cam_target=Matrix3(Vector3(0,0,Math_PI*2*(i/4.0))).xform(Vector3(0,1,0)); + projection = projection * CameraMatrix(Transform().looking_at(cam_target,Vector3(0,0,-1)).affine_inverse()); + + state.canvas_shadow_shader.set_uniform(CanvasShadowShaderGLES3::PROJECTION_MATRIX,projection); + state.canvas_shadow_shader.set_uniform(CanvasShadowShaderGLES3::LIGHT_MATRIX,light); + state.canvas_shadow_shader.set_uniform(CanvasShadowShaderGLES3::DISTANCE_NORM,1.0/p_far); + + + if (i==0) + *p_xform_cache=projection; + + glViewport(0, (cls->height/4)*i, cls->size,cls->height/4); + + LightOccluderInstance *instance=p_occluders; + + while(instance) { + + RasterizerStorageGLES3::CanvasOccluder *cc = storage->canvas_occluder_owner.get(instance->polygon_buffer); + if (!cc || cc->len==0 || !(p_light_mask&instance->light_mask)) { + + instance=instance->next; + continue; + } + + state.canvas_shadow_shader.set_uniform(CanvasShadowShaderGLES3::WORLD_MATRIX,instance->xform_cache); + if (cull!=instance->cull_cache) { + + cull=instance->cull_cache; + switch(cull) { + case VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED: { + + glDisable(GL_CULL_FACE); + + } break; + case VS::CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE: { + + glEnable(GL_CULL_FACE); + glCullFace(GL_FRONT); + } break; + case VS::CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE: { + + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + + } break; + } + } +/* + if (i==0) { + for(int i=0;ilines.size();i++) { + Vector2 p = instance->xform_cache.xform(cc->lines.get(i)); + Plane pp(Vector3(p.x,p.y,0),1); + pp.normal = light.xform(pp.normal); + pp = projection.xform4(pp); + print_line(itos(i)+": "+pp.normal/pp.d); + //pp=light_mat.xform4(pp); + //print_line(itos(i)+": "+pp.normal/pp.d); + } + } +*/ + glBindBuffer(GL_ARRAY_BUFFER,cc->vertex_id); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,cc->index_id); + glVertexAttribPointer(VS::ARRAY_VERTEX, 3, GL_FLOAT, false, 0, 0); + glDrawElements(GL_TRIANGLES,cc->len*3,GL_UNSIGNED_SHORT,0); + + + instance=instance->next; + } + + + } + + glDisableVertexAttribArray(VS::ARRAY_VERTEX); + glBindBuffer(GL_ARRAY_BUFFER,0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); +} +void RasterizerCanvasGLES3::reset_canvas() { + + + if (storage->frame.current_rt) { + glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->front.fbo); + glColorMask(1,1,1,1); //don't touch alpha + } + + + glBindVertexArray(0); + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glDisable(GL_SCISSOR_TEST); +#ifdef GLEW_ENABLED + glDisable(GL_POINT_SPRITE); + glDisable(GL_VERTEX_PROGRAM_POINT_SIZE); +#endif + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } + else { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + //glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); + glLineWidth(1.0); + glBindBuffer(GL_ARRAY_BUFFER,0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); + for(int i=0;iresources.white_tex ); + + + glVertexAttrib4f(VS::ARRAY_COLOR,1,1,1,1); + + Transform canvas_transform; + + if (storage->frame.current_rt) { + + float csy = 1.0; + if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP]) { + csy = -1.0; + } + canvas_transform.translate(-(storage->frame.current_rt->width / 2.0f), -(storage->frame.current_rt->height / 2.0f), 0.0f); + canvas_transform.scale( Vector3( 2.0f / storage->frame.current_rt->width, csy * -2.0f / storage->frame.current_rt->height, 1.0f ) ); + } else { + Vector2 ssize = OS::get_singleton()->get_window_size(); + canvas_transform.translate(-(ssize.width / 2.0f), -(ssize.height / 2.0f), 0.0f); + canvas_transform.scale( Vector3( 2.0f / ssize.width, -2.0f / ssize.height, 1.0f ) ); + + } + + state.vp=canvas_transform; + + store_transform(canvas_transform,state.canvas_item_ubo_data.projection_matrix); + + glBindBuffer(GL_UNIFORM_BUFFER, state.canvas_item_ubo); + glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(CanvasItemUBO), &state.canvas_item_ubo_data); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + + + state.canvas_texscreen_used=false; + + +} + + +void RasterizerCanvasGLES3::draw_generic_textured_rect(const Rect2& p_rect, const Rect2& p_src) { + + + glVertexAttrib4f(1,p_rect.pos.x,p_rect.pos.y,p_rect.size.x,p_rect.size.y); + glVertexAttrib4f(2,p_src.pos.x,p_src.pos.y,p_src.size.x,p_src.size.y); + glDrawArrays(GL_TRIANGLE_FAN,0,4); +} + +void RasterizerCanvasGLES3::initialize() { + + + { + //quad buffers + + glGenBuffers(1,&data.canvas_quad_vertices); + glBindBuffer(GL_ARRAY_BUFFER,data.canvas_quad_vertices); + { + const float qv[8]={ + 0,0, + 0,1, + 1,1, + 1,0 + }; + + glBufferData(GL_ARRAY_BUFFER,sizeof(float)*8,qv,GL_STATIC_DRAW); + } + + glBindBuffer(GL_ARRAY_BUFFER,0); //unbind + + + glGenVertexArrays(1,&data.canvas_quad_array); + glBindVertexArray(data.canvas_quad_array); + glBindBuffer(GL_ARRAY_BUFFER,data.canvas_quad_vertices); + glVertexAttribPointer(0,2,GL_FLOAT,GL_FALSE,sizeof(float)*2,0); + glEnableVertexAttribArray(0); + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER,0); //unbind + } + + + store_transform(Transform(),state.canvas_item_ubo_data.projection_matrix); + + + + glGenBuffers(1, &state.canvas_item_ubo); + 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); + + state.canvas_shader.init(); + state.canvas_shadow_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); + + +} + + +void RasterizerCanvasGLES3::finalize() { + + glDeleteBuffers(1,&data.canvas_quad_vertices); + glDeleteVertexArrays(1,&data.canvas_quad_array); +} + +RasterizerCanvasGLES3::RasterizerCanvasGLES3() +{ + +} diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h new file mode 100644 index 0000000000..1f72a8dbcf --- /dev/null +++ b/drivers/gles3/rasterizer_canvas_gles3.h @@ -0,0 +1,102 @@ +#ifndef RASTERIZERCANVASGLES3_H +#define RASTERIZERCANVASGLES3_H + +#include "servers/visual/rasterizer.h" +#include "rasterizer_storage_gles3.h" +#include "shaders/canvas_shadow.glsl.h" + +class RasterizerCanvasGLES3 : public RasterizerCanvas { +public: + + struct CanvasItemUBO { + + float projection_matrix[16]; + + }; + + struct Data { + + GLuint canvas_quad_vertices; + GLuint canvas_quad_array; + + } data; + + struct State { + CanvasItemUBO canvas_item_ubo_data; + GLuint canvas_item_ubo; + bool canvas_texscreen_used; + CanvasShaderGLES3 canvas_shader; + CanvasShadowShaderGLES3 canvas_shadow_shader; + + bool using_texture_rect; + + + RID current_tex; + RasterizerStorageGLES3::Texture *current_tex_ptr; + + Transform vp; + + Color canvas_item_modulate; + Matrix32 extra_matrix; + Matrix32 final_transform; + + } state; + + RasterizerStorageGLES3 *storage; + + struct LightInternal : public RID_Data { + + struct UBOData { + + float light_matrix[16]; + float local_matrix[16]; + float shadow_matrix[16]; + float color[4]; + float shadow_color[4]; + float light_pos[2]; + float shadowpixel_size; + float shadow_gradient; + float light_height; + float light_outside_alpha; + float shadow_distance_mult; + } ubo_data; + + GLuint ubo; + }; + + RID_Owner light_internal_owner; + + virtual RID light_internal_create(); + virtual void light_internal_update(RID p_rid, Light* p_light); + virtual void light_internal_free(RID p_rid); + + + virtual void canvas_begin(); + virtual void canvas_end(); + + _FORCE_INLINE_ void _set_texture_rect_mode(bool p_enable); + _FORCE_INLINE_ RasterizerStorageGLES3::Texture* _bind_canvas_texture(const RID& p_texture); + + _FORCE_INLINE_ void _draw_gui_primitive(int p_points, const Vector2 *p_vertices, const Color* p_colors, const Vector2 *p_uvs); + _FORCE_INLINE_ void _draw_polygon(int p_vertex_count, const int* p_indices, const Vector2* p_vertices, const Vector2* p_uvs, const Color* p_colors,const RID& p_texture,bool p_singlecolor); + _FORCE_INLINE_ void _canvas_item_render_commands(Item *p_item,Item *current_clip,bool &reclip); + + + virtual void canvas_render_items(Item *p_item_list,int p_z,const Color& p_modulate,Light *p_light); + virtual void canvas_debug_viewport_shadows(Light* p_lights_with_shadow); + + virtual void canvas_light_shadow_buffer_update(RID p_buffer, const Matrix32& p_light_xform, int p_light_mask,float p_near, float p_far, LightOccluderInstance* p_occluders, CameraMatrix *p_xform_cache); + + + virtual void reset_canvas(); + + void draw_generic_textured_rect(const Rect2& p_rect, const Rect2& p_src); + + + void initialize(); + void finalize(); + + RasterizerCanvasGLES3(); +}; + +#endif // RASTERIZERCANVASGLES3_H diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp new file mode 100644 index 0000000000..ba83a572e5 --- /dev/null +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -0,0 +1,266 @@ +#include "rasterizer_gles3.h" +#include "os/os.h" +#include "globals.h" +#include "gl_context/context_gl.h" +#include +RasterizerStorage *RasterizerGLES3::get_storage() { + + return storage; +} + +RasterizerCanvas *RasterizerGLES3::get_canvas() { + + return canvas; +} + +RasterizerScene *RasterizerGLES3::get_scene() { + + return NULL; +} + + +static void _gl_debug_print(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const GLvoid *userParam) +{ + + if (type==GL_DEBUG_TYPE_OTHER_ARB) + return; + + print_line("mesege"); + char debSource[256], debType[256], debSev[256]; + if(source == GL_DEBUG_SOURCE_API_ARB) + strcpy(debSource, "OpenGL"); + else if(source == GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB) + strcpy(debSource, "Windows"); + else if(source == GL_DEBUG_SOURCE_SHADER_COMPILER_ARB) + strcpy(debSource, "Shader Compiler"); + else if(source == GL_DEBUG_SOURCE_THIRD_PARTY_ARB) + strcpy(debSource, "Third Party"); + else if(source == GL_DEBUG_SOURCE_APPLICATION_ARB) + strcpy(debSource, "Application"); + else if(source == GL_DEBUG_SOURCE_OTHER_ARB) + strcpy(debSource, "Other"); + + if(type == GL_DEBUG_TYPE_ERROR_ARB) + strcpy(debType, "Error"); + else if(type == GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB) + strcpy(debType, "Deprecated behavior"); + else if(type == GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB) + strcpy(debType, "Undefined behavior"); + else if(type == GL_DEBUG_TYPE_PORTABILITY_ARB) + strcpy(debType, "Portability"); + else if(type == GL_DEBUG_TYPE_PERFORMANCE_ARB) + strcpy(debType, "Performance"); + else if(type == GL_DEBUG_TYPE_OTHER_ARB) + strcpy(debType, "Other"); + + if(severity == GL_DEBUG_SEVERITY_HIGH_ARB) + strcpy(debSev, "High"); + else if(severity == GL_DEBUG_SEVERITY_MEDIUM_ARB) + strcpy(debSev, "Medium"); + else if(severity == GL_DEBUG_SEVERITY_LOW_ARB) + strcpy(debSev, "Low"); + + String output = String()+ "GL ERROR: Source: " + debSource + "\tType: " + debType + "\tID: " + itos(id) + "\tSeverity: " + debSev + "\tMessage: " + message; + + ERR_PRINTS(output); + +} + + +void RasterizerGLES3::initialize() { + + if (OS::get_singleton()->is_stdout_verbose()) { + print_line("Using GLES3 video driver"); + } + +#ifdef GLEW_ENABLED + GLuint res = glewInit(); + ERR_FAIL_COND(res!=GLEW_OK); + if (OS::get_singleton()->is_stdout_verbose()) { + print_line(String("GLES2: Using GLEW ") + (const char*) glewGetString(GLEW_VERSION)); + } + + // Check for GL 2.1 compatibility, if not bail out + if (!glewIsSupported("GL_VERSION_3_0")) { + ERR_PRINT("Your system's graphic drivers seem not to support OpenGL 3.0+ / GLES 3.0, sorry :(\n" + "Try a drivers update, buy a new GPU or try software rendering on Linux; Godot will now crash with a segmentation fault."); + OS::get_singleton()->alert("Your system's graphic drivers seem not to support OpenGL 3.0+ / GLES 3.0, sorry :(\n" + "Godot Engine will self-destruct as soon as you acknowledge this error message.", + "Fatal error: Insufficient OpenGL / GLES drivers"); + // TODO: If it's even possible, we should stop the execution without segfault and memory leaks :) + } +#endif + + glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB); + glDebugMessageCallbackARB(_gl_debug_print, NULL); + glEnable(GL_DEBUG_OUTPUT); + + +/* glDebugMessageControlARB(GL_DEBUG_SOURCE_API_ARB,GL_DEBUG_TYPE_ERROR_ARB,GL_DEBUG_SEVERITY_HIGH_ARB,0,NULL,GL_TRUE); + glDebugMessageControlARB(GL_DEBUG_SOURCE_API_ARB,GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB,GL_DEBUG_SEVERITY_HIGH_ARB,0,NULL,GL_TRUE); + glDebugMessageControlARB(GL_DEBUG_SOURCE_API_ARB,GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB,GL_DEBUG_SEVERITY_HIGH_ARB,0,NULL,GL_TRUE); + glDebugMessageControlARB(GL_DEBUG_SOURCE_API_ARB,GL_DEBUG_TYPE_PORTABILITY_ARB,GL_DEBUG_SEVERITY_HIGH_ARB,0,NULL,GL_TRUE); + glDebugMessageControlARB(GL_DEBUG_SOURCE_API_ARB,GL_DEBUG_TYPE_PERFORMANCE_ARB,GL_DEBUG_SEVERITY_HIGH_ARB,0,NULL,GL_TRUE); + glDebugMessageControlARB(GL_DEBUG_SOURCE_API_ARB,GL_DEBUG_TYPE_OTHER_ARB,GL_DEBUG_SEVERITY_HIGH_ARB,0,NULL,GL_TRUE); + glDebugMessageInsertARB( + + GL_DEBUG_SOURCE_API_ARB, + GL_DEBUG_TYPE_OTHER_ARB, 1, + GL_DEBUG_SEVERITY_HIGH_ARB,5, "hello"); + +*/ + storage->initialize(); + canvas->initialize(); +} + +void RasterizerGLES3::begin_frame(){ + + +} +void RasterizerGLES3::set_current_render_target(RID p_render_target){ + + if (!p_render_target.is_valid() && storage->frame.current_rt && storage->frame.clear_request) { + //handle pending clear request, if the framebuffer was not cleared + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->front.fbo); + 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 ); + + glClear(GL_COLOR_BUFFER_BIT); + + } + + if (p_render_target.is_valid()) { + RasterizerStorageGLES3::RenderTarget * rt = storage->render_target_owner.getornull(p_render_target); + if (!rt) { + storage->frame.current_rt=NULL; + } + ERR_FAIL_COND(!rt); + storage->frame.current_rt=rt; + storage->frame.clear_request=false; + + glViewport(0,0,rt->width,rt->height); + + } else { + storage->frame.current_rt=NULL; + storage->frame.clear_request=false; + glViewport(0,0,OS::get_singleton()->get_window_size().width,OS::get_singleton()->get_window_size().height); + glBindFramebuffer(GL_FRAMEBUFFER,storage->config.system_fbo); + } +} + +void RasterizerGLES3::restore_render_target() { + + ERR_FAIL_COND(storage->frame.current_rt==NULL); + RasterizerStorageGLES3::RenderTarget * rt = storage->frame.current_rt; + glViewport(0,0,rt->width,rt->height); + +} + +void RasterizerGLES3::clear_render_target(const Color& p_color) { + + ERR_FAIL_COND(!storage->frame.current_rt); + + storage->frame.clear_request=true; + storage->frame.clear_request_color=p_color; + +} + +void RasterizerGLES3::blit_render_target_to_screen(RID p_render_target,const Rect2& p_screen_rect,int p_screen){ + + ERR_FAIL_COND( storage->frame.current_rt ); + + RasterizerStorageGLES3::RenderTarget *rt = storage->render_target_owner.getornull(p_render_target); + ERR_FAIL_COND(!rt); + + canvas->canvas_begin(); + glBindFramebuffer(GL_FRAMEBUFFER,storage->config.system_fbo); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,rt->front.color); + canvas->draw_generic_textured_rect(p_screen_rect,Rect2(0,0,1,-1)); + glBindTexture(GL_TEXTURE_2D,0); + canvas->canvas_end(); +} + +void RasterizerGLES3::end_frame(){ + +#if 0 + canvas->canvas_begin(); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,storage->resources.white_tex); + glDisable(GL_BLEND); + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + + + float vtx[8]={0,0, + 0,1, + 1,1, + 1,0 + }; + + glBindBuffer(GL_ARRAY_BUFFER,0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); + + glEnableVertexAttribArray(VS::ARRAY_VERTEX); + glVertexAttribPointer( VS::ARRAY_VERTEX, 2 ,GL_FLOAT, false, 0, vtx ); + + +// glBindBuffer(GL_ARRAY_BUFFER,canvas->data.canvas_quad_vertices); +// glEnableVertexAttribArray(VS::ARRAY_VERTEX); +// glVertexAttribPointer( VS::ARRAY_VERTEX, 2 ,GL_FLOAT, false, 0, 0 ); + + glBindVertexArray(canvas->data.canvas_quad_array); + + canvas->draw_generic_textured_rect(Rect2(0,0,15,15),Rect2(0,0,1,1)); +#endif + if (ContextGL::get_singleton()) + ContextGL::get_singleton()->swap_buffers(); +} + +void RasterizerGLES3::finalize(){ + + storage->finalize(); + canvas->finalize(); +} + + +Rasterizer *RasterizerGLES3::_create_current() { + + return memnew( RasterizerGLES3 ); +} + +void RasterizerGLES3::make_current() { + _create_func=_create_current; +} + + +void RasterizerGLES3::register_config() { + + GLOBAL_DEF("rendering/gles3/framebuffer_format",RasterizerStorageGLES3::FBO_FORMAT_FLOAT); + Globals::get_singleton()->set_custom_property_info("rendering/gles3/framebuffer_format",PropertyInfo(Variant::INT,"",PROPERTY_HINT_ENUM,"16 Bits,32 Bits,Half Float")); + GLOBAL_DEF("rendering/gles3/lighting_technique",1); + Globals::get_singleton()->set_custom_property_info("rendering/gles3/lighting_technique",PropertyInfo(Variant::INT,"",PROPERTY_HINT_ENUM,"Forward,Deferred")); + GLOBAL_DEF("rendering/gles3/use_nearest_mipmap_filter",false); + GLOBAL_DEF("rendering/gles3/anisotropic_filter_level",4.0); + + +} + +RasterizerGLES3::RasterizerGLES3() +{ + + storage = memnew( RasterizerStorageGLES3 ); + canvas = memnew( RasterizerCanvasGLES3 ); + canvas->storage=storage; + + +} + +RasterizerGLES3::~RasterizerGLES3() { + + memdelete(storage); + memdelete(canvas); +} diff --git a/drivers/gles3/rasterizer_gles3.h b/drivers/gles3/rasterizer_gles3.h new file mode 100644 index 0000000000..d461664ea2 --- /dev/null +++ b/drivers/gles3/rasterizer_gles3.h @@ -0,0 +1,38 @@ +#ifndef RASTERIZERGLES3_H +#define RASTERIZERGLES3_H + +#include "servers/visual/rasterizer.h" +#include "rasterizer_storage_gles3.h" +#include "rasterizer_canvas_gles3.h" + + +class RasterizerGLES3 : public Rasterizer { + + static Rasterizer *_create_current(); + + RasterizerStorageGLES3 *storage; + RasterizerCanvasGLES3 *canvas; +public: + + virtual RasterizerStorage *get_storage(); + virtual RasterizerCanvas *get_canvas(); + virtual RasterizerScene *get_scene(); + + virtual void initialize(); + virtual void begin_frame(); + virtual void set_current_render_target(RID p_render_target); + virtual void restore_render_target(); + 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 end_frame(); + virtual void finalize(); + + static void make_current(); + + + static void register_config(); + RasterizerGLES3(); + ~RasterizerGLES3(); +}; + +#endif // RASTERIZERGLES3_H diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp new file mode 100644 index 0000000000..b29de876a4 --- /dev/null +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -0,0 +1,2045 @@ +#include "rasterizer_storage_gles3.h" +#include "globals.h" + +/* TEXTURE API */ + +#define _EXT_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00 +#define _EXT_COMPRESSED_RGB_PVRTC_2BPPV1_IMG 0x8C01 +#define _EXT_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02 +#define _EXT_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG 0x8C03 + +#define _EXT_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT 0x8A54 +#define _EXT_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT 0x8A55 +#define _EXT_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT 0x8A56 +#define _EXT_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT 0x8A57 + + +#define _EXT_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 +#define _EXT_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 +#define _EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 + +#define _EXT_COMPRESSED_LUMINANCE_LATC1_EXT 0x8C70 +#define _EXT_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT 0x8C71 +#define _EXT_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT 0x8C72 +#define _EXT_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT 0x8C73 + + +#define _EXT_COMPRESSED_RED_RGTC1_EXT 0x8DBB +#define _EXT_COMPRESSED_RED_RGTC1 0x8DBB +#define _EXT_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC +#define _EXT_COMPRESSED_RG_RGTC2 0x8DBD +#define _EXT_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE +#define _EXT_COMPRESSED_SIGNED_RED_RGTC1_EXT 0x8DBC +#define _EXT_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD +#define _EXT_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE +#define _EXT_ETC1_RGB8_OES 0x8D64 + + + +#define _EXT_SLUMINANCE_NV 0x8C46 +#define _EXT_SLUMINANCE_ALPHA_NV 0x8C44 +#define _EXT_SRGB8_NV 0x8C41 +#define _EXT_SLUMINANCE8_NV 0x8C47 +#define _EXT_SLUMINANCE8_ALPHA8_NV 0x8C45 + + +#define _EXT_COMPRESSED_SRGB_S3TC_DXT1_NV 0x8C4C +#define _EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_NV 0x8C4D +#define _EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_NV 0x8C4E +#define _EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_NV 0x8C4F + + + +#define _EXT_ATC_RGB_AMD 0x8C92 +#define _EXT_ATC_RGBA_EXPLICIT_ALPHA_AMD 0x8C93 +#define _EXT_ATC_RGBA_INTERPOLATED_ALPHA_AMD 0x87EE + + +#define _TEXTURE_SRGB_DECODE_EXT 0x8A48 +#define _DECODE_EXT 0x8A49 +#define _SKIP_DECODE_EXT 0x8A4A + + +#define _GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE +#define _GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF + + + +Image RasterizerStorageGLES3::_get_gl_image_and_format(const Image& p_image, Image::Format p_format, uint32_t p_flags,GLenum& r_gl_format,GLenum& r_gl_internal_format,GLenum &r_gl_type,bool &r_compressed,bool &srgb) { + + + r_compressed=false; + r_gl_format=0; + Image image=p_image; + srgb=false; + + bool need_decompress=false; + + switch(p_format) { + + case Image::FORMAT_L8: { + r_gl_internal_format=GL_LUMINANCE; + r_gl_format=GL_LUMINANCE; + r_gl_type=GL_UNSIGNED_BYTE; + + } break; + case Image::FORMAT_LA8: { + + r_gl_internal_format=GL_LUMINANCE_ALPHA; + r_gl_format=GL_LUMINANCE_ALPHA; + r_gl_type=GL_UNSIGNED_BYTE; + + } break; + case Image::FORMAT_R8: { + + r_gl_internal_format=GL_R8; + r_gl_format=GL_RED; + r_gl_type=GL_UNSIGNED_BYTE; + + } break; + case Image::FORMAT_RG8: { + + r_gl_internal_format=GL_RG8; + r_gl_format=GL_RG; + r_gl_type=GL_UNSIGNED_BYTE; + + } break; + case Image::FORMAT_RGB8: { + + r_gl_internal_format=(config.srgb_decode_supported || p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?GL_SRGB8:GL_RGB8; + r_gl_format=GL_RGB; + r_gl_type=GL_UNSIGNED_BYTE; + srgb=true; + + } break; + case Image::FORMAT_RGBA8: { + + r_gl_format=GL_RGBA; + r_gl_internal_format=(config.srgb_decode_supported || p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?GL_SRGB8_ALPHA8:GL_RGBA8; + r_gl_type=GL_UNSIGNED_BYTE; + srgb=true; + + } break; + case Image::FORMAT_RGB565: { + + r_gl_internal_format=GL_RGB565; + r_gl_format=GL_RGB; + r_gl_type=GL_UNSIGNED_SHORT_5_6_5; + + } break; + case Image::FORMAT_RGBA4444: { + + r_gl_internal_format=GL_RGBA4; + r_gl_format=GL_RGBA; + r_gl_type=GL_UNSIGNED_SHORT_4_4_4_4; + + } break; + case Image::FORMAT_RGBA5551: { + + r_gl_internal_format=GL_RGB5_A1; + r_gl_format=GL_RGBA; + r_gl_type=GL_UNSIGNED_SHORT_5_5_5_1; + + + } break; + case Image::FORMAT_RF: { + + + r_gl_internal_format=GL_R32F; + r_gl_format=GL_RED; + r_gl_type=GL_FLOAT; + + } break; + case Image::FORMAT_RGF: { + + r_gl_internal_format=GL_RG32F; + r_gl_format=GL_RG; + r_gl_type=GL_FLOAT; + + } break; + case Image::FORMAT_RGBF: { + + r_gl_internal_format=GL_RGB32F; + r_gl_format=GL_RGB; + r_gl_type=GL_FLOAT; + + } break; + case Image::FORMAT_RGBAF: { + + r_gl_internal_format=GL_RGBA32F; + r_gl_format=GL_RGBA; + r_gl_type=GL_FLOAT; + + } break; + case Image::FORMAT_RH: { + r_gl_internal_format=GL_R32F; + r_gl_format=GL_RED; + r_gl_type=GL_HALF_FLOAT; + } break; + case Image::FORMAT_RGH: { + r_gl_internal_format=GL_RG32F; + r_gl_format=GL_RG; + r_gl_type=GL_HALF_FLOAT; + + } break; + case Image::FORMAT_RGBH: { + r_gl_internal_format=GL_RGB32F; + r_gl_format=GL_RGB; + r_gl_type=GL_HALF_FLOAT; + + } break; + case Image::FORMAT_RGBAH: { + r_gl_internal_format=GL_RGBA32F; + r_gl_format=GL_RGBA; + r_gl_type=GL_HALF_FLOAT; + + } break; + case Image::FORMAT_DXT1: { + + if (config.s3tc_supported) { + + + r_gl_internal_format=(config.srgb_decode_supported || p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_NV:_EXT_COMPRESSED_RGBA_S3TC_DXT1_EXT; + r_gl_format=GL_RGBA; + r_gl_type=GL_UNSIGNED_BYTE; + r_compressed=true; + srgb=true; + + } else { + + need_decompress=true; + } + + + } break; + case Image::FORMAT_DXT3: { + + + if (config.s3tc_supported) { + + + r_gl_internal_format=(config.srgb_decode_supported || p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_NV:_EXT_COMPRESSED_RGBA_S3TC_DXT3_EXT; + r_gl_format=GL_RGBA; + r_gl_type=GL_UNSIGNED_BYTE; + r_compressed=true; + srgb=true; + + } else { + + need_decompress=true; + } + + + } break; + case Image::FORMAT_DXT5: { + + if (config.s3tc_supported) { + + + r_gl_internal_format=(config.srgb_decode_supported || p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_NV:_EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT; + r_gl_format=GL_RGBA; + r_gl_type=GL_UNSIGNED_BYTE; + r_compressed=true; + srgb=true; + + } else { + + need_decompress=true; + } + + + } break; + case Image::FORMAT_ATI1: { + + if (config.latc_supported) { + + + r_gl_internal_format=_EXT_COMPRESSED_LUMINANCE_LATC1_EXT; + r_gl_format=GL_RGBA; + r_gl_type=GL_UNSIGNED_BYTE; + r_compressed=true; + srgb=true; + + } else { + + need_decompress=true; + } + + + + } break; + case Image::FORMAT_ATI2: { + + if (config.latc_supported) { + + + r_gl_internal_format=_EXT_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT; + r_gl_format=GL_RGBA; + r_gl_type=GL_UNSIGNED_BYTE; + r_compressed=true; + } else { + + need_decompress=true; + } + + } break; + case Image::FORMAT_BPTC_RGBA: { + + if (config.bptc_supported) { + + + r_gl_internal_format=(config.srgb_decode_supported || p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:GL_COMPRESSED_RGBA_BPTC_UNORM; + r_gl_format=GL_RGBA; + r_gl_type=GL_UNSIGNED_BYTE; + r_compressed=true; + srgb=true; + + } else { + + need_decompress=true; + } + } break; + case Image::FORMAT_BPTC_RGBF: { + + if (config.bptc_supported) { + + + r_gl_internal_format=GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT; + r_gl_format=GL_RGB; + r_gl_type=GL_FLOAT; + r_compressed=true; + } else { + + need_decompress=true; + } + } break; + case Image::FORMAT_BPTC_RGBFU: { + if (config.bptc_supported) { + + + r_gl_internal_format=GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT; + r_gl_format=GL_RGB; + r_gl_type=GL_FLOAT; + r_compressed=true; + } else { + + need_decompress=true; + } + } break; + case Image::FORMAT_PVRTC2: { + + if (config.pvrtc_supported) { + + + r_gl_internal_format=(config.srgb_decode_supported || p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT:_EXT_COMPRESSED_RGB_PVRTC_2BPPV1_IMG; + r_gl_format=GL_RGBA; + r_gl_type=GL_UNSIGNED_BYTE; + r_compressed=true; + srgb=true; + + } else { + + need_decompress=true; + } + } break; + case Image::FORMAT_PVRTC2A: { + + if (config.pvrtc_supported) { + + + r_gl_internal_format=(config.srgb_decode_supported || p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT:_EXT_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG; + r_gl_format=GL_RGBA; + r_gl_type=GL_UNSIGNED_BYTE; + r_compressed=true; + srgb=true; + + } else { + + need_decompress=true; + } + + + } break; + case Image::FORMAT_PVRTC4: { + + if (config.pvrtc_supported) { + + + r_gl_internal_format=(config.srgb_decode_supported || p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT:_EXT_COMPRESSED_RGB_PVRTC_4BPPV1_IMG; + r_gl_format=GL_RGBA; + r_gl_type=GL_UNSIGNED_BYTE; + r_compressed=true; + srgb=true; + + } else { + + need_decompress=true; + } + + } break; + case Image::FORMAT_PVRTC4A: { + + if (config.pvrtc_supported) { + + + r_gl_internal_format=(config.srgb_decode_supported || p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT:_EXT_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; + r_gl_format=GL_RGBA; + r_gl_type=GL_UNSIGNED_BYTE; + r_compressed=true; + srgb=true; + + } else { + + need_decompress=true; + } + + + } break; + case Image::FORMAT_ETC: { + + if (config.etc_supported) { + + r_gl_internal_format=_EXT_ETC1_RGB8_OES; + r_gl_format=GL_RGBA; + r_gl_type=GL_UNSIGNED_BYTE; + r_compressed=true; + + } else { + + need_decompress=true; + } + + } break; + case Image::FORMAT_ETC2_R11: { + + if (config.etc2_supported) { + + r_gl_internal_format=GL_COMPRESSED_R11_EAC; + r_gl_format=GL_RED; + r_gl_type=GL_UNSIGNED_BYTE; + r_compressed=true; + + } else { + + need_decompress=true; + } + } break; + case Image::FORMAT_ETC2_R11S: { + + if (config.etc2_supported) { + + r_gl_internal_format=GL_COMPRESSED_SIGNED_R11_EAC; + r_gl_format=GL_RED; + r_gl_type=GL_UNSIGNED_BYTE; + r_compressed=true; + + } else { + + need_decompress=true; + } + } break; + case Image::FORMAT_ETC2_RG11: { + + if (config.etc2_supported) { + + r_gl_internal_format=GL_COMPRESSED_RG11_EAC; + r_gl_format=GL_RG; + r_gl_type=GL_UNSIGNED_BYTE; + r_compressed=true; + + } else { + + need_decompress=true; + } + } break; + case Image::FORMAT_ETC2_RG11S: { + if (config.etc2_supported) { + + r_gl_internal_format=GL_COMPRESSED_SIGNED_RG11_EAC; + r_gl_format=GL_RG; + r_gl_type=GL_UNSIGNED_BYTE; + r_compressed=true; + + } else { + need_decompress=true; + } + } break; + case Image::FORMAT_ETC2_RGB8: { + + if (config.etc2_supported) { + + r_gl_internal_format=(config.srgb_decode_supported || p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?GL_COMPRESSED_SRGB8_ETC2:GL_COMPRESSED_RGB8_ETC2; + r_gl_format=GL_RGB; + r_gl_type=GL_UNSIGNED_BYTE; + r_compressed=true; + srgb=true; + + + } else { + + need_decompress=true; + } + } break; + case Image::FORMAT_ETC2_RGBA8: { + + if (config.etc2_supported) { + + r_gl_internal_format=(config.srgb_decode_supported || p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:GL_COMPRESSED_RGBA8_ETC2_EAC; + r_gl_format=GL_RGBA; + r_gl_type=GL_UNSIGNED_BYTE; + r_compressed=true; + srgb=true; + + + } else { + + need_decompress=true; + } + } break; + case Image::FORMAT_ETC2_RGB8A1: { + + if (config.etc2_supported) { + + r_gl_internal_format=(config.srgb_decode_supported || p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2; + r_gl_format=GL_RGBA; + r_gl_type=GL_UNSIGNED_BYTE; + r_compressed=true; + srgb=true; + + + } else { + + need_decompress=true; + } + } break; + default: { + + ERR_FAIL_V(Image()); + } + } + + if (need_decompress) { + + if (!image.empty()) { + image.decompress(); + ERR_FAIL_COND_V(image.is_compressed(),image); + image.convert(Image::FORMAT_RGBA8); + } + + + r_gl_format=GL_RGBA; + r_gl_internal_format=(config.srgb_decode_supported || p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?GL_SRGB8_ALPHA8:GL_RGBA8; + r_gl_type=GL_UNSIGNED_BYTE; + r_compressed=false; + srgb=true; + + return image; + + } + + + return image; +} + +static const GLenum _cube_side_enum[6]={ + + GL_TEXTURE_CUBE_MAP_NEGATIVE_X, + GL_TEXTURE_CUBE_MAP_POSITIVE_X, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, + GL_TEXTURE_CUBE_MAP_POSITIVE_Y, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, + GL_TEXTURE_CUBE_MAP_POSITIVE_Z, + +}; + +RID RasterizerStorageGLES3::texture_create() { + + Texture *texture = memnew(Texture); + ERR_FAIL_COND_V(!texture,RID()); + glGenTextures(1, &texture->tex_id); + texture->active=false; + texture->total_data_size=0; + + return texture_owner.make_rid( texture ); + +} + +void RasterizerStorageGLES3::texture_allocate(RID p_texture,int p_width, int p_height,Image::Format p_format,uint32_t p_flags) { + + int components; + GLenum format; + GLenum internal_format; + GLenum type; + + bool compressed; + bool srgb; + + if (p_flags&VS::TEXTURE_FLAG_USED_FOR_STREAMING) { + p_flags&=~VS::TEXTURE_FLAG_MIPMAPS; // no mipies for video + } + + + Texture *texture = texture_owner.get( p_texture ); + ERR_FAIL_COND(!texture); + texture->width=p_width; + texture->height=p_height; + texture->format=p_format; + texture->flags=p_flags; + texture->target = (p_flags & VS::TEXTURE_FLAG_CUBEMAP) ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D; + + _get_gl_image_and_format(Image(),texture->format,texture->flags,format,internal_format,type,compressed,srgb); + + texture->alloc_width = texture->width; + texture->alloc_height = texture->height; + + + texture->gl_format_cache=format; + texture->gl_type_cache=type; + texture->gl_internal_format_cache=internal_format; + texture->compressed=compressed; + texture->srgb=srgb; + texture->data_size=0; + texture->mipmaps=1; + + + glActiveTexture(GL_TEXTURE0); + glBindTexture(texture->target, texture->tex_id); + + + if (p_flags&VS::TEXTURE_FLAG_USED_FOR_STREAMING) { + //prealloc if video + glTexImage2D(texture->target, 0, internal_format, p_width, p_height, 0, format, type,NULL); + } + + texture->active=true; +} + +void RasterizerStorageGLES3::texture_set_data(RID p_texture,const Image& p_image,VS::CubeMapSide p_cube_side) { + + Texture * texture = texture_owner.get(p_texture); + + ERR_FAIL_COND(!texture); + ERR_FAIL_COND(!texture->active); + ERR_FAIL_COND(texture->render_target); + ERR_FAIL_COND(texture->format != p_image.get_format() ); + ERR_FAIL_COND( p_image.empty() ); + + GLenum type; + GLenum format; + GLenum internal_format; + bool compressed; + bool srgb; + + + Image img = _get_gl_image_and_format(p_image, p_image.get_format(),texture->flags,format,internal_format,type,compressed,srgb); + + if (config.shrink_textures_x2 && (p_image.has_mipmaps() || !p_image.is_compressed()) && !(texture->flags&VS::TEXTURE_FLAG_USED_FOR_STREAMING)) { + + texture->alloc_height = MAX(1,texture->alloc_height/2); + texture->alloc_width = MAX(1,texture->alloc_width/2); + + if (texture->alloc_width == img.get_width()/2 && texture->alloc_height == img.get_height()/2) { + + img.shrink_x2(); + } else if (img.get_format() <= Image::FORMAT_RGB565) { + + img.resize(texture->alloc_width, texture->alloc_height, Image::INTERPOLATE_BILINEAR); + + } + }; + + + GLenum blit_target = (texture->target == GL_TEXTURE_CUBE_MAP)?_cube_side_enum[p_cube_side]:GL_TEXTURE_2D; + + texture->data_size=img.get_data().size(); + DVector::Read read = img.get_data().read(); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(texture->target, texture->tex_id); + + texture->ignore_mipmaps = compressed && !img.has_mipmaps(); + + if (texture->flags&VS::TEXTURE_FLAG_MIPMAPS && !texture->ignore_mipmaps) + glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,config.use_fast_texture_filter?GL_LINEAR_MIPMAP_NEAREST:GL_LINEAR_MIPMAP_LINEAR); + else { + if (texture->flags&VS::TEXTURE_FLAG_FILTER) { + glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_LINEAR); + } else { + glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_NEAREST); + + } + } + + + if (config.srgb_decode_supported && srgb) { + + if (texture->flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { + + glTexParameteri(texture->target,_TEXTURE_SRGB_DECODE_EXT,_DECODE_EXT); + } else { + glTexParameteri(texture->target,_TEXTURE_SRGB_DECODE_EXT,_SKIP_DECODE_EXT); + } + } + + if (texture->flags&VS::TEXTURE_FLAG_FILTER) { + + glTexParameteri(texture->target,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // Linear Filtering + + } else { + + glTexParameteri(texture->target,GL_TEXTURE_MAG_FILTER,GL_NEAREST); // raw Filtering + } + + if ((texture->flags&VS::TEXTURE_FLAG_REPEAT || texture->flags&VS::TEXTURE_FLAG_MIRRORED_REPEAT) && texture->target != GL_TEXTURE_CUBE_MAP) { + + if (texture->flags&VS::TEXTURE_FLAG_MIRRORED_REPEAT){ + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT ); + } + else{ + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); + } + } else { + + //glTexParameterf( texture->target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE ); + glTexParameterf( texture->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); + glTexParameterf( texture->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); + } + + if (config.use_anisotropic_filter) { + + if (texture->flags&VS::TEXTURE_FLAG_ANISOTROPIC_FILTER) { + + glTexParameterf(texture->target, _GL_TEXTURE_MAX_ANISOTROPY_EXT, config.anisotropic_level); + } else { + glTexParameterf(texture->target, _GL_TEXTURE_MAX_ANISOTROPY_EXT, 1); + } + } + + int mipmaps= (texture->flags&VS::TEXTURE_FLAG_MIPMAPS && img.has_mipmaps()) ? img.get_mipmap_count() +1: 1; + + + int w=img.get_width(); + int h=img.get_height(); + + int tsize=0; + for(int i=0;icompressed) { + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + glCompressedTexImage2D( blit_target, i, format,w,h,0,size,&read[ofs] ); + + } else { + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + if (texture->flags&VS::TEXTURE_FLAG_USED_FOR_STREAMING) { + glTexSubImage2D( blit_target, i, 0,0,w, h,format,type,&read[ofs] ); + } else { + glTexImage2D(blit_target, i, internal_format, w, h, 0, format, type,&read[ofs]); + } + + } + tsize+=size; + + w = MAX(1,w>>1); + h = MAX(1,h>>1); + + } + + info.texture_mem-=texture->total_data_size; + texture->total_data_size=tsize; + info.texture_mem+=texture->total_data_size; + + //printf("texture: %i x %i - size: %i - total: %i\n",texture->width,texture->height,tsize,_rinfo.texture_mem); + + + if (texture->flags&VS::TEXTURE_FLAG_MIPMAPS && mipmaps==1 && !texture->ignore_mipmaps) { + //generate mipmaps if they were requested and the image does not contain them + glGenerateMipmap(texture->target); + } + + texture->mipmaps=mipmaps; + + //texture_set_flags(p_texture,texture->flags); + + +} + +Image RasterizerStorageGLES3::texture_get_data(RID p_texture,VS::CubeMapSide p_cube_side) const { + + Texture * texture = texture_owner.get(p_texture); + + ERR_FAIL_COND_V(!texture,Image()); + ERR_FAIL_COND_V(!texture->active,Image()); + ERR_FAIL_COND_V(texture->data_size==0,Image()); + ERR_FAIL_COND_V(texture->render_target,Image()); + +#ifdef GLEW_ENABLED + + DVector data; + + int data_size = Image::get_image_data_size(texture->width,texture->height,texture->format,texture->mipmaps>1?-1:0); + + data.resize(data_size); + DVector::Write wb = data.write(); + + glActiveTexture(GL_TEXTURE0); + + glBindTexture(texture->target,texture->tex_id); + + for(int i=0;imipmaps;i++) { + + int ofs=0; + if (i>0) { + ofs=Image::get_image_data_size(texture->alloc_width,texture->alloc_height,texture->format,i-1); + } + + if (texture->compressed) { + + glPixelStorei(GL_PACK_ALIGNMENT, 4); + glGetCompressedTexImage(texture->target,i,&wb[ofs]); + + } else { + glPixelStorei(GL_PACK_ALIGNMENT, 1); + glGetTexImage(texture->target,i,texture->gl_format_cache,texture->gl_type_cache,&wb[ofs]); + } + } + + + wb=DVector::Write(); + + Image img(texture->alloc_width,texture->alloc_height,texture->mipmaps>1?true:false,texture->format,data); + + return img; +#else + + ERR_EXPLAIN("Sorry, It's not posible to obtain images back in OpenGL ES"); +#endif +} + +void RasterizerStorageGLES3::texture_set_flags(RID p_texture,uint32_t p_flags) { + + Texture *texture = texture_owner.get( p_texture ); + ERR_FAIL_COND(!texture); + if (texture->render_target) { + + p_flags&=VS::TEXTURE_FLAG_FILTER;//can change only filter + } + + bool had_mipmaps = texture->flags&VS::TEXTURE_FLAG_MIPMAPS; + + glActiveTexture(GL_TEXTURE0); + glBindTexture(texture->target, texture->tex_id); + uint32_t cube = texture->flags & VS::TEXTURE_FLAG_CUBEMAP; + texture->flags=p_flags|cube; // can't remove a cube from being a cube + + + if ((texture->flags&VS::TEXTURE_FLAG_REPEAT || texture->flags&VS::TEXTURE_FLAG_MIRRORED_REPEAT) && texture->target != GL_TEXTURE_CUBE_MAP) { + + if (texture->flags&VS::TEXTURE_FLAG_MIRRORED_REPEAT){ + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT ); + } + else { + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); + } + } else { + //glTexParameterf( texture->target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE ); + glTexParameterf( texture->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); + glTexParameterf( texture->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); + + } + + + if (config.use_anisotropic_filter) { + + if (texture->flags&VS::TEXTURE_FLAG_ANISOTROPIC_FILTER) { + + glTexParameterf(texture->target, _GL_TEXTURE_MAX_ANISOTROPY_EXT, config.anisotropic_level); + } else { + glTexParameterf(texture->target, _GL_TEXTURE_MAX_ANISOTROPY_EXT, 1); + } + } + + if (texture->flags&VS::TEXTURE_FLAG_MIPMAPS && !texture->ignore_mipmaps) { + if (!had_mipmaps && texture->mipmaps==1) { + glGenerateMipmap(texture->target); + } + glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,config.use_fast_texture_filter?GL_LINEAR_MIPMAP_NEAREST:GL_LINEAR_MIPMAP_LINEAR); + + } else{ + if (texture->flags&VS::TEXTURE_FLAG_FILTER) { + glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_LINEAR); + } else { + glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_NEAREST); + + } + } + + + if (config.srgb_decode_supported && texture->srgb) { + + if (texture->flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { + + glTexParameteri(texture->target,_TEXTURE_SRGB_DECODE_EXT,_DECODE_EXT); + } else { + glTexParameteri(texture->target,_TEXTURE_SRGB_DECODE_EXT,_SKIP_DECODE_EXT); + } + } + + if (texture->flags&VS::TEXTURE_FLAG_FILTER) { + + glTexParameteri(texture->target,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // Linear Filtering + + } else { + + glTexParameteri(texture->target,GL_TEXTURE_MAG_FILTER,GL_NEAREST); // raw Filtering + } + +} +uint32_t RasterizerStorageGLES3::texture_get_flags(RID p_texture) const { + + Texture * texture = texture_owner.get(p_texture); + + ERR_FAIL_COND_V(!texture,0); + + return texture->flags; + +} +Image::Format RasterizerStorageGLES3::texture_get_format(RID p_texture) const { + + Texture * texture = texture_owner.get(p_texture); + + ERR_FAIL_COND_V(!texture,Image::FORMAT_L8); + + return texture->format; +} +uint32_t RasterizerStorageGLES3::texture_get_width(RID p_texture) const { + + Texture * texture = texture_owner.get(p_texture); + + ERR_FAIL_COND_V(!texture,0); + + return texture->width; +} +uint32_t RasterizerStorageGLES3::texture_get_height(RID p_texture) const { + + Texture * texture = texture_owner.get(p_texture); + + ERR_FAIL_COND_V(!texture,0); + + return texture->height; +} + + +void RasterizerStorageGLES3::texture_set_size_override(RID p_texture,int p_width, int p_height) { + + Texture * texture = texture_owner.get(p_texture); + + ERR_FAIL_COND(!texture); + ERR_FAIL_COND(texture->render_target); + + ERR_FAIL_COND(p_width<=0 || p_width>16384); + ERR_FAIL_COND(p_height<=0 || p_height>16384); + //real texture size is in alloc width and height + texture->width=p_width; + texture->height=p_height; + +} + +void RasterizerStorageGLES3::texture_set_path(RID p_texture,const String& p_path) { + Texture * texture = texture_owner.get(p_texture); + ERR_FAIL_COND(!texture); + + texture->path=p_path; + +} + +String RasterizerStorageGLES3::texture_get_path(RID p_texture) const{ + + Texture * texture = texture_owner.get(p_texture); + ERR_FAIL_COND_V(!texture,String()); + return texture->path; +} +void RasterizerStorageGLES3::texture_debug_usage(List *r_info){ + + List textures; + texture_owner.get_owned_list(&textures); + + for (List::Element *E=textures.front();E;E=E->next()) { + + Texture *t = texture_owner.get(E->get()); + if (!t) + continue; + VS::TextureInfo tinfo; + tinfo.path=t->path; + tinfo.format=t->format; + tinfo.size.x=t->alloc_width; + tinfo.size.y=t->alloc_height; + tinfo.bytes=t->total_data_size; + r_info->push_back(tinfo); + } + +} + +void RasterizerStorageGLES3::texture_set_shrink_all_x2_on_set_data(bool p_enable) { + + config.shrink_textures_x2=p_enable; +} + + + +/* SHADER API */ + + +RID RasterizerStorageGLES3::shader_create(VS::ShaderMode p_mode){ + + return RID(); +} + +void RasterizerStorageGLES3::shader_set_mode(RID p_shader,VS::ShaderMode p_mode){ + + +} +VS::ShaderMode RasterizerStorageGLES3::shader_get_mode(RID p_shader) const { + + return VS::SHADER_SPATIAL; +} +void RasterizerStorageGLES3::shader_set_code(RID p_shader, const String& p_code){ + + +} +String RasterizerStorageGLES3::shader_get_code(RID p_shader) const{ + + return String(); +} +void RasterizerStorageGLES3::shader_get_param_list(RID p_shader, List *p_param_list) const{ + + +} + +void RasterizerStorageGLES3::shader_set_default_texture_param(RID p_shader, const StringName& p_name, RID p_texture){ + + +} +RID RasterizerStorageGLES3::shader_get_default_texture_param(RID p_shader, const StringName& p_name) const{ + + return RID(); +} + + +/* COMMON MATERIAL API */ + +RID RasterizerStorageGLES3::material_create(){ + + return RID(); +} + +void RasterizerStorageGLES3::material_set_shader(RID p_shader_material, RID p_shader){ + + +} +RID RasterizerStorageGLES3::material_get_shader(RID p_shader_material) const{ + + return RID(); +} + +void RasterizerStorageGLES3::material_set_param(RID p_material, const StringName& p_param, const Variant& p_value){ + + +} +Variant RasterizerStorageGLES3::material_get_param(RID p_material, const StringName& p_param) const{ + + return Variant(); +} + +/* MESH API */ + +RID RasterizerStorageGLES3::mesh_create(){ + + return RID(); +} + +void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::PrimitiveType p_primitive,const DVector& p_array,int p_vertex_count,const DVector& p_index_array,int p_index_count,const Vector >& p_blend_shapes){ + + +} + +void RasterizerStorageGLES3::mesh_set_morph_target_count(RID p_mesh,int p_amount){ + + +} +int RasterizerStorageGLES3::mesh_get_morph_target_count(RID p_mesh) const{ + + return 0; +} + + +void RasterizerStorageGLES3::mesh_set_morph_target_mode(RID p_mesh,VS::MorphTargetMode p_mode){ + + +} +VS::MorphTargetMode RasterizerStorageGLES3::mesh_get_morph_target_mode(RID p_mesh) const{ + + return VS::MORPH_MODE_NORMALIZED; +} + +void RasterizerStorageGLES3::mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material){ + + +} +RID RasterizerStorageGLES3::mesh_surface_get_material(RID p_mesh, int p_surface) const{ + + return RID(); +} + +int RasterizerStorageGLES3::mesh_surface_get_array_len(RID p_mesh, int p_surface) const{ + + return 0; +} +int RasterizerStorageGLES3::mesh_surface_get_array_index_len(RID p_mesh, int p_surface) const{ + + + return 0; +} + +DVector RasterizerStorageGLES3::mesh_surface_get_array(RID p_mesh, int p_surface) const{ + + return DVector(); +} +DVector RasterizerStorageGLES3::mesh_surface_get_index_array(RID p_mesh, int p_surface) const{ + + + return DVector(); +} + + +uint32_t RasterizerStorageGLES3::mesh_surface_get_format(RID p_mesh, int p_surface) const{ + + return 0; +} +VS::PrimitiveType RasterizerStorageGLES3::mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const{ + + return VS::PRIMITIVE_MAX; +} + +void RasterizerStorageGLES3::mesh_remove_surface(RID p_mesh,int p_index){ + + +} +int RasterizerStorageGLES3::mesh_get_surface_count(RID p_mesh) const{ + + return 0; +} + +void RasterizerStorageGLES3::mesh_set_custom_aabb(RID p_mesh,const AABB& p_aabb){ + + +} +AABB RasterizerStorageGLES3::mesh_get_custom_aabb(RID p_mesh) const{ + + return AABB(); +} + +AABB RasterizerStorageGLES3::mesh_get_aabb(RID p_mesh) const{ + + return AABB(); +} +void RasterizerStorageGLES3::mesh_clear(RID p_mesh){ + + +} + +/* MULTIMESH API */ + + +RID RasterizerStorageGLES3::multimesh_create(){ + + return RID(); +} + +void RasterizerStorageGLES3::multimesh_allocate(RID p_multimesh,int p_instances,VS::MultimeshTransformFormat p_transform_format,VS::MultimeshColorFormat p_color_format,bool p_gen_aabb){ + + +} +int RasterizerStorageGLES3::multimesh_get_instance_count(RID p_multimesh) const{ + + return 0; +} + +void RasterizerStorageGLES3::multimesh_set_mesh(RID p_multimesh,RID p_mesh){ + + +} +void RasterizerStorageGLES3::multimesh_set_custom_aabb(RID p_multimesh,const AABB& p_aabb){ + + +} +void RasterizerStorageGLES3::multimesh_instance_set_transform(RID p_multimesh,int p_index,const Transform& p_transform){ + + +} +void RasterizerStorageGLES3::multimesh_instance_set_transform_2d(RID p_multimesh,int p_index,const Matrix32& p_transform){ + + +} +void RasterizerStorageGLES3::multimesh_instance_set_color(RID p_multimesh,int p_index,const Color& p_color){ + + +} + +RID RasterizerStorageGLES3::multimesh_get_mesh(RID p_multimesh) const{ + + + return RID(); +} +AABB RasterizerStorageGLES3::multimesh_get_custom_aabb(RID p_multimesh,const AABB& p_aabb) const{ + + return AABB(); +} + +Transform RasterizerStorageGLES3::multimesh_instance_get_transform(RID p_multimesh,int p_index) const{ + + return Transform(); +} +Matrix32 RasterizerStorageGLES3::multimesh_instance_get_transform_2d(RID p_multimesh,int p_index) const{ + + + return Matrix32(); +} +Color RasterizerStorageGLES3::multimesh_instance_get_color(RID p_multimesh,int p_index) const{ + + return Color(); +} + +void RasterizerStorageGLES3::multimesh_set_visible_instances(RID p_multimesh,int p_visible){ + + +} +int RasterizerStorageGLES3::multimesh_get_visible_instances(RID p_multimesh) const{ + + return 0; +} + +AABB RasterizerStorageGLES3::multimesh_get_aabb(RID p_mesh) const{ + + return AABB(); +} + +/* IMMEDIATE API */ + +RID RasterizerStorageGLES3::immediate_create(){ + + return RID(); +} +void RasterizerStorageGLES3::immediate_begin(RID p_immediate,VS::PrimitiveType p_rimitive,RID p_texture){ + + +} +void RasterizerStorageGLES3::immediate_vertex(RID p_immediate,const Vector3& p_vertex){ + + +} +void RasterizerStorageGLES3::immediate_vertex_2d(RID p_immediate,const Vector3& p_vertex){ + + +} +void RasterizerStorageGLES3::immediate_normal(RID p_immediate,const Vector3& p_normal){ + + +} +void RasterizerStorageGLES3::immediate_tangent(RID p_immediate,const Plane& p_tangent){ + + +} +void RasterizerStorageGLES3::immediate_color(RID p_immediate,const Color& p_color){ + + +} +void RasterizerStorageGLES3::immediate_uv(RID p_immediate,const Vector2& tex_uv){ + + +} +void RasterizerStorageGLES3::immediate_uv2(RID p_immediate,const Vector2& tex_uv){ + + +} +void RasterizerStorageGLES3::immediate_end(RID p_immediate){ + + +} +void RasterizerStorageGLES3::immediate_clear(RID p_immediate){ + + +} +void RasterizerStorageGLES3::immediate_set_material(RID p_immediate,RID p_material){ + + +} +RID RasterizerStorageGLES3::immediate_get_material(RID p_immediate) const{ + + return RID(); +} + +/* SKELETON API */ + +RID RasterizerStorageGLES3::skeleton_create(){ + + return RID(); +} +void RasterizerStorageGLES3::skeleton_allocate(RID p_skeleton,int p_bones,bool p_2d_skeleton){ + + +} +int RasterizerStorageGLES3::skeleton_get_bone_count(RID p_skeleton) const{ + + return 0; +} +void RasterizerStorageGLES3::skeleton_bone_set_transform(RID p_skeleton,int p_bone, const Transform& p_transform){ + + +} +Transform RasterizerStorageGLES3::skeleton_bone_get_transform(RID p_skeleton,int p_bone){ + + return Transform(); +} +void RasterizerStorageGLES3::skeleton_bone_set_transform_2d(RID p_skeleton,int p_bone, const Matrix32& p_transform){ + + +} +Matrix32 RasterizerStorageGLES3::skeleton_bone_get_transform_2d(RID p_skeleton,int p_bone){ + + return Matrix32(); +} + +/* Light API */ + +RID RasterizerStorageGLES3::light_create(VS::LightType p_type){ + + return RID(); +} + +void RasterizerStorageGLES3::light_set_color(RID p_light,const Color& p_color){ + + +} +void RasterizerStorageGLES3::light_set_param(RID p_light,VS::LightParam p_param,float p_value){ + + +} +void RasterizerStorageGLES3::light_set_shadow(RID p_light,bool p_enabled){ + + +} +void RasterizerStorageGLES3::light_set_projector(RID p_light,RID p_texture){ + + +} +void RasterizerStorageGLES3::light_set_attenuation_texure(RID p_light,RID p_texture){ + + +} +void RasterizerStorageGLES3::light_set_negative(RID p_light,bool p_enable){ + + +} +void RasterizerStorageGLES3::light_set_cull_mask(RID p_light,uint32_t p_mask){ + + +} +void RasterizerStorageGLES3::light_set_shader(RID p_light,RID p_shader){ + + +} + + +void RasterizerStorageGLES3::light_directional_set_shadow_mode(RID p_light,VS::LightDirectionalShadowMode p_mode){ + + +} + +/* PROBE API */ + +RID RasterizerStorageGLES3::reflection_probe_create(){ + + return RID(); +} + +void RasterizerStorageGLES3::reflection_probe_set_intensity(RID p_probe, float p_intensity){ + + +} +void RasterizerStorageGLES3::reflection_probe_set_clip(RID p_probe, float p_near, float p_far){ + + +} +void RasterizerStorageGLES3::reflection_probe_set_min_blend_distance(RID p_probe, float p_distance){ + + +} +void RasterizerStorageGLES3::reflection_probe_set_extents(RID p_probe, const Vector3& p_extents){ + + +} +void RasterizerStorageGLES3::reflection_probe_set_origin_offset(RID p_probe, const Vector3& p_offset){ + + +} +void RasterizerStorageGLES3::reflection_probe_set_enable_parallax_correction(RID p_probe, bool p_enable){ + + +} +void RasterizerStorageGLES3::reflection_probe_set_resolution(RID p_probe, int p_resolution){ + + +} +void RasterizerStorageGLES3::reflection_probe_set_hide_skybox(RID p_probe, bool p_hide){ + + +} +void RasterizerStorageGLES3::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers){ + + +} + + +/* ROOM API */ + +RID RasterizerStorageGLES3::room_create(){ + + return RID(); +} +void RasterizerStorageGLES3::room_add_bounds(RID p_room, const DVector& p_convex_polygon,float p_height,const Transform& p_transform){ + + +} +void RasterizerStorageGLES3::room_clear_bounds(){ + + +} + +/* PORTAL API */ + +// portals are only (x/y) points, forming a convex shape, which its clockwise +// order points outside. (z is 0); + +RID RasterizerStorageGLES3::portal_create(){ + + return RID(); +} +void RasterizerStorageGLES3::portal_set_shape(RID p_portal, const Vector& p_shape){ + + +} +void RasterizerStorageGLES3::portal_set_enabled(RID p_portal, bool p_enabled){ + + +} +void RasterizerStorageGLES3::portal_set_disable_distance(RID p_portal, float p_distance){ + + +} +void RasterizerStorageGLES3::portal_set_disabled_color(RID p_portal, const Color& p_color){ + + +} + + +/* RENDER TARGET */ + + +void RasterizerStorageGLES3::_render_target_clear(RenderTarget *rt) { + + if (rt->front.fbo) { + glDeleteFramebuffers(1,&rt->front.fbo); + glDeleteTextures(1,&rt->front.color); + rt->front.fbo=0; + } + + if (rt->back.fbo) { + glDeleteFramebuffers(1,&rt->back.fbo); + glDeleteTextures(1,&rt->back.color); + rt->back.fbo=0; + } + + if (rt->deferred.fbo) { + glDeleteFramebuffers(1,&rt->deferred.fbo); + glDeleteFramebuffers(1,&rt->deferred.fbo_color); + glDeleteTextures(1,&rt->deferred.albedo_ao); + glDeleteTextures(1,&rt->deferred.normal_special); + glDeleteTextures(1,&rt->deferred.metal_rough_motion); + rt->deferred.fbo=0; + rt->deferred.fbo_color=0; + } + + if (rt->depth) { + glDeleteRenderbuffers(1,&rt->depth); + rt->depth=0; + } + +} + +void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){ + + if (rt->width<=0 || rt->height<=0) + return; + + glGenFramebuffers(1, &rt->front.fbo); + glBindFramebuffer(GL_FRAMEBUFFER, rt->front.fbo); + + + glGenRenderbuffers(1, &rt->depth); + glBindRenderbuffer(GL_RENDERBUFFER, rt->depth ); + if (config.fbo_format==FBO_FORMAT_16_BITS) { + glRenderbufferStorage(GL_RENDERBUFFER,GL_DEPTH_COMPONENT16, rt->width, rt->height); + } else { + glRenderbufferStorage(GL_RENDERBUFFER,GL_DEPTH24_STENCIL8, rt->width, rt->height); + } + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth); + glBindRenderbuffer(GL_RENDERBUFFER, 0 ); + + + glGenTextures(1, &rt->front.color); + glBindTexture(GL_TEXTURE_2D, rt->front.color); + + + GLuint color_internal_format; + GLuint color_format; + GLuint color_type; + + + if (config.fbo_format==FBO_FORMAT_16_BITS) { + + if (rt->flags[RENDER_TARGET_TRANSPARENT]) { + color_internal_format=GL_RGB5_A1; + color_format=GL_RGBA; + color_type=GL_UNSIGNED_SHORT_5_5_5_1; + } else { + color_internal_format=GL_RGB565; + color_format=GL_RGB; + color_type=GL_UNSIGNED_SHORT_5_6_5; + } + + } else if (config.fbo_format==FBO_FORMAT_32_BITS) { + + if (rt->flags[RENDER_TARGET_TRANSPARENT]) { + color_internal_format=GL_RGBA8; + color_format=GL_RGBA; + color_type=GL_UNSIGNED_BYTE; + } else { + color_internal_format=GL_RGB10_A2; + color_format=GL_RGBA; + color_type=GL_UNSIGNED_INT_2_10_10_10_REV; + } + } else if (config.fbo_format==FBO_FORMAT_FLOAT) { + + color_internal_format=GL_RGBA16F; + color_format=GL_RGBA; + color_type=GL_HALF_FLOAT; + } + + glTexImage2D(GL_TEXTURE_2D, 0, color_internal_format, rt->width, rt->height, 0, color_format, color_type, 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, rt->front.color, 0); + + { + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + glBindFramebuffer(GL_FRAMEBUFFER, config.system_fbo); + + ERR_FAIL_COND( status != GL_FRAMEBUFFER_COMPLETE ); + } + + + if (!rt->flags[RENDER_TARGET_NO_SAMPLING]) { + + glGenFramebuffers(1, &rt->back.fbo); + glBindFramebuffer(GL_FRAMEBUFFER, rt->back.fbo); + + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth); + + glGenTextures(1, &rt->back.color); + glBindTexture(GL_TEXTURE_2D, rt->back.color); + + glTexImage2D(GL_TEXTURE_2D, 0, color_internal_format, rt->width, rt->height, 0, color_format, color_type, 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, rt->back.color, 0); + + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + glBindFramebuffer(GL_FRAMEBUFFER, config.system_fbo); + + if (status != GL_FRAMEBUFFER_COMPLETE) { + _render_target_clear(rt); + ERR_FAIL_COND( status != GL_FRAMEBUFFER_COMPLETE ); + } + } + + + + if (config.fbo_deferred && !rt->flags[RENDER_TARGET_NO_3D]) { + + + //regular fbo + glGenFramebuffers(1, &rt->deferred.fbo); + glBindFramebuffer(GL_FRAMEBUFFER, rt->deferred.fbo); + + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth); + + glGenTextures(1, &rt->deferred.albedo_ao); + glBindTexture(GL_TEXTURE_2D, rt->deferred.albedo_ao); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, rt->width, rt->height, 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, rt->deferred.albedo_ao, 0); + + glGenTextures(1, &rt->deferred.metal_rough_motion); + glBindTexture(GL_TEXTURE_2D, rt->deferred.metal_rough_motion); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, rt->width, rt->height, 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_ATTACHMENT1, GL_TEXTURE_2D, rt->deferred.metal_rough_motion, 0); + + glGenTextures(1, &rt->deferred.normal_special); + glBindTexture(GL_TEXTURE_2D, rt->deferred.normal_special); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, rt->width, rt->height, 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_ATTACHMENT2, GL_TEXTURE_2D, rt->deferred.normal_special, 0); + + + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + glBindFramebuffer(GL_FRAMEBUFFER, config.system_fbo); + + if (status != GL_FRAMEBUFFER_COMPLETE) { + _render_target_clear(rt); + ERR_FAIL_COND( status != GL_FRAMEBUFFER_COMPLETE ); + } + + //regular fbo with color attachment (needed for emission or objects rendered as forward) + + glGenFramebuffers(1, &rt->deferred.fbo_color); + glBindFramebuffer(GL_FRAMEBUFFER, rt->deferred.fbo_color); + + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->deferred.albedo_ao, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, rt->deferred.metal_rough_motion, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, rt->deferred.normal_special, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, rt->front.color, 0); + + + status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + glBindFramebuffer(GL_FRAMEBUFFER, config.system_fbo); + + if (status != GL_FRAMEBUFFER_COMPLETE) { + _render_target_clear(rt); + ERR_FAIL_COND( status != GL_FRAMEBUFFER_COMPLETE ); + } + } + + +} + + +RID RasterizerStorageGLES3::render_target_create(){ + + RenderTarget *rt = memnew( RenderTarget ); + return render_target_owner.make_rid(rt); +} + +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); + ERR_FAIL_COND(!rt); + + if (rt->width==p_width && rt->height==p_height) + return; + + _render_target_clear(rt); + rt->width=p_width; + rt->height=p_height; + _render_target_allocate(rt); + +} + + +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 RID(); +} +Image RasterizerStorageGLES3::render_target_get_image(RID p_render_target) const{ + + return Image(); +} +void RasterizerStorageGLES3::render_target_set_flag(RID p_render_target,RenderTargetFlags p_flag,bool p_value) { + + RenderTarget *rt = render_target_owner.getornull(p_render_target); + ERR_FAIL_COND(!rt); + + rt->flags[p_flag]=p_value; + + switch(p_flag) { + case RENDER_TARGET_NO_3D: + case RENDER_TARGET_TRANSPARENT: { + //must reset for these formats + _render_target_clear(rt); + _render_target_allocate(rt); + + } break; + default: {} + } +} + +bool RasterizerStorageGLES3::render_target_renedered_in_frame(RID p_render_target){ + + return false; +} + +/* CANVAS SHADOW */ + + +RID RasterizerStorageGLES3::canvas_light_shadow_buffer_create(int p_width) { + + CanvasLightShadow *cls = memnew( CanvasLightShadow ); + if (p_width>config.max_texture_size) + p_width=config.max_texture_size; + + cls->size=p_width; + cls->height=16; + + glActiveTexture(GL_TEXTURE0); + + glGenFramebuffers(1, &cls->fbo); + glBindFramebuffer(GL_FRAMEBUFFER, cls->fbo); + + glGenRenderbuffers(1, &cls->depth); + glBindRenderbuffer(GL_RENDERBUFFER, cls->depth ); + glRenderbufferStorage(GL_RENDERBUFFER,GL_DEPTH_COMPONENT24, cls->size, cls->height); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, cls->depth); + glBindRenderbuffer(GL_RENDERBUFFER, 0 ); + + glGenTextures(1,&cls->distance); + glBindTexture(GL_TEXTURE_2D, cls->distance); + if (config.use_rgba_2d_shadows) { + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, cls->size, cls->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + } else { + glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, cls->size, cls->height, 0, GL_RED, GL_FLOAT, 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, cls->distance, 0); + + + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + //printf("errnum: %x\n",status); + glBindFramebuffer(GL_FRAMEBUFFER, config.system_fbo); + + ERR_FAIL_COND_V( status != GL_FRAMEBUFFER_COMPLETE, RID() ); + + return canvas_light_shadow_owner.make_rid(cls); +} + +/* LIGHT SHADOW MAPPING */ + + +RID RasterizerStorageGLES3::canvas_light_occluder_create() { + + CanvasOccluder *co = memnew( CanvasOccluder ); + co->index_id=0; + co->vertex_id=0; + co->len=0; + + return canvas_occluder_owner.make_rid(co); +} + +void RasterizerStorageGLES3::canvas_light_occluder_set_polylines(RID p_occluder, const DVector& p_lines) { + + CanvasOccluder *co = canvas_occluder_owner.get(p_occluder); + ERR_FAIL_COND(!co); + + co->lines=p_lines; + + if (p_lines.size()!=co->len) { + + if (co->index_id) + glDeleteBuffers(1,&co->index_id); + if (co->vertex_id) + glDeleteBuffers(1,&co->vertex_id); + + co->index_id=0; + co->vertex_id=0; + co->len=0; + + } + + if (p_lines.size()) { + + + + DVector geometry; + DVector indices; + int lc = p_lines.size(); + + geometry.resize(lc*6); + indices.resize(lc*3); + + DVector::Write vw=geometry.write(); + DVector::Write iw=indices.write(); + + + DVector::Read lr=p_lines.read(); + + const int POLY_HEIGHT = 16384; + + for(int i=0;ivertex_id) { + glGenBuffers(1,&co->vertex_id); + glBindBuffer(GL_ARRAY_BUFFER,co->vertex_id); + glBufferData(GL_ARRAY_BUFFER,lc*6*sizeof(real_t),vw.ptr(),GL_STATIC_DRAW); + } else { + + glBindBuffer(GL_ARRAY_BUFFER,co->vertex_id); + glBufferSubData(GL_ARRAY_BUFFER,0,lc*6*sizeof(real_t),vw.ptr()); + + } + + glBindBuffer(GL_ARRAY_BUFFER,0); //unbind + + if (!co->index_id) { + + glGenBuffers(1,&co->index_id); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,co->index_id); + glBufferData(GL_ELEMENT_ARRAY_BUFFER,lc*3*sizeof(uint16_t),iw.ptr(),GL_STATIC_DRAW); + } else { + + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,co->index_id); + glBufferSubData(GL_ELEMENT_ARRAY_BUFFER,0,lc*3*sizeof(uint16_t),iw.ptr()); + } + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); //unbind + + co->len=lc; + + } + +} + +bool RasterizerStorageGLES3::free(RID p_rid){ + + if (render_target_owner.owns(p_rid)) { + + RenderTarget *rt = render_target_owner.getornull(p_rid); + _render_target_clear(rt); + render_target_owner.free(p_rid); + memdelete(rt); + + } else if (texture_owner.owns(p_rid)) { + // delete the texture + Texture *texture = texture_owner.get(p_rid); + info.texture_mem-=texture->total_data_size; + texture_owner.free(p_rid); + memdelete(texture); + } else if (canvas_occluder_owner.owns(p_rid)) { + + + CanvasOccluder *co = canvas_occluder_owner.get(p_rid); + if (co->index_id) + glDeleteBuffers(1,&co->index_id); + if (co->vertex_id) + glDeleteBuffers(1,&co->vertex_id); + + canvas_occluder_owner.free(p_rid); + memdelete(co); + + } else if (canvas_light_shadow_owner.owns(p_rid)) { + + CanvasLightShadow *cls = canvas_light_shadow_owner.get(p_rid); + glDeleteFramebuffers(1,&cls->fbo); + glDeleteRenderbuffers(1,&cls->depth); + glDeleteTextures(1,&cls->distance); + canvas_light_shadow_owner.free(p_rid); + memdelete(cls); + } else { + return false; + } + + return true; +} + +//////////////////////////////////////////// + + +void RasterizerStorageGLES3::initialize() { + + config.fbo_format=FBOFormat(int(Globals::get_singleton()->get("rendering/gles3/framebuffer_format"))); + config.fbo_deferred=int(Globals::get_singleton()->get("rendering/gles3/lighting_technique")); + + config.system_fbo=0; + + + //// extensions config + /// + + { + Vector ext= String((const char*)glGetString( GL_EXTENSIONS )).split(" ",false); + for(int i=0;iget("rendering/gles3/use_nearest_mipmap_filter")); + config.use_anisotropic_filter = config.extensions.has("GL_EXT_texture_filter_anisotropic"); + + 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.etc_supported=config.extensions.has("GL_OES_compressed_ETC1_RGB8_texture"); + config.latc_supported=config.extensions.has("GL_EXT_texture_compression_latc"); + config.bptc_supported=config.extensions.has("GL_ARB_texture_compression_bptc"); +#ifdef GLEW_ENABLED + config.etc2_supported=false; +#else + config.etc2_supported=true; +#endif + config.pvrtc_supported=config.extensions.has("GL_IMG_texture_compression_pvrtc"); + config.srgb_decode_supported=config.extensions.has("GL_EXT_texture_sRGB_decode"); + + + + config.anisotropic_level=1.0; + config.use_anisotropic_filter=config.extensions.has("GL_EXT_texture_filter_anisotropic"); + if (config.use_anisotropic_filter) { + glGetFloatv(_GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT,&config.anisotropic_level); + config.anisotropic_level=MIN(int(Globals::get_singleton()->get("rendering/gles3/anisotropic_filter_level")),config.anisotropic_level); + } + + + frame.clear_request=false; + + shaders.copy.init(); + + { + //default textures + + + glGenTextures(1, &resources.white_tex); + unsigned char whitetexdata[8*8*3]; + for(int i=0;i<8*8*3;i++) { + whitetexdata[i]=255; + } + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,resources.white_tex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE,whitetexdata); + glGenerateMipmap(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D,0); + + glGenTextures(1, &resources.black_tex); + unsigned char blacktexdata[8*8*3]; + for(int i=0;i<8*8;i++) { + blacktexdata[i]=0; + } + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,resources.black_tex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE,blacktexdata); + glGenerateMipmap(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D,0); + + glGenTextures(1, &resources.normal_tex); + unsigned char normaltexdata[8*8*3]; + for(int i=0;i<8*8*3;i+=3) { + normaltexdata[i+0]=128; + normaltexdata[i+1]=128; + normaltexdata[i+2]=255; + } + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,resources.normal_tex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE,normaltexdata); + glGenerateMipmap(GL_TEXTURE_2D); + 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 GLEW_ENABLED + config.use_rgba_2d_shadows=false; +#else + config.use_rgba_2d_shadows=true; +#endif +} + +void RasterizerStorageGLES3::finalize() { + + glDeleteTextures(1, &resources.white_tex); + glDeleteTextures(1, &resources.black_tex); + glDeleteTextures(1, &resources.normal_tex); + +} + + +RasterizerStorageGLES3::RasterizerStorageGLES3() +{ + +} diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h new file mode 100644 index 0000000000..3b2d7d752c --- /dev/null +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -0,0 +1,445 @@ +#ifndef RASTERIZERSTORAGEGLES3_H +#define RASTERIZERSTORAGEGLES3_H + +#include "servers/visual/rasterizer.h" +#include "shader_gles3.h" +#include "shaders/copy.glsl.h" +#include "shaders/canvas.glsl.h" + + + + +class RasterizerStorageGLES3 : public RasterizerStorage { +public: + + enum FBOFormat { + FBO_FORMAT_16_BITS, + FBO_FORMAT_32_BITS, + FBO_FORMAT_FLOAT, + }; + + struct Config { + + FBOFormat fbo_format; + bool fbo_deferred; + GLuint system_fbo; //on some devices, such as apple, screen is rendered to yet another fbo. + + bool shrink_textures_x2; + bool use_fast_texture_filter; + bool use_anisotropic_filter; + + bool s3tc_supported; + bool latc_supported; + bool bptc_supported; + bool etc_supported; + bool etc2_supported; + bool pvrtc_supported; + + bool srgb_decode_supported; + + bool use_rgba_2d_shadows; + + float anisotropic_level; + + int max_texture_image_units; + int max_texture_size; + + Set extensions; + } config; + + struct Shaders { + + CopyShaderGLES3 copy; + } shaders; + + struct Resources { + + GLuint white_tex; + GLuint black_tex; + GLuint normal_tex; + + } resources; + + struct Info { + + uint64_t texture_mem; + + } info; + + +///////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////DATA/////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////// + + + + + + + + + + + + + + + +///////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////API//////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////// + + + /* TEXTURE API */ + + struct RenderTarget; + + struct Texture : public RID_Data { + + String path; + uint32_t flags; + int width,height; + int alloc_width, alloc_height; + Image::Format format; + + GLenum target; + GLenum gl_format_cache; + GLenum gl_internal_format_cache; + GLenum gl_type_cache; + int data_size; //original data size, useful for retrieving back + bool compressed; + bool srgb; + int total_data_size; + bool ignore_mipmaps; + + int mipmaps; + + bool active; + GLuint tex_id; + + + RenderTarget *render_target; + + Texture() { + + 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; + + } + + ~Texture() { + + if (tex_id!=0) { + + glDeleteTextures(1,&tex_id); + } + } + }; + + mutable RID_Owner texture_owner; + + Image _get_gl_image_and_format(const Image& p_image, Image::Format p_format, uint32_t p_flags, GLenum& r_gl_format, GLenum& r_gl_internal_format, GLenum &r_type, bool &r_compressed, bool &srgb); + + virtual RID texture_create(); + virtual void texture_allocate(RID p_texture,int p_width, int p_height,Image::Format p_format,uint32_t p_flags=VS::TEXTURE_FLAGS_DEFAULT); + virtual void texture_set_data(RID p_texture,const Image& p_image,VS::CubeMapSide p_cube_side=VS::CUBEMAP_LEFT); + virtual Image texture_get_data(RID p_texture,VS::CubeMapSide p_cube_side=VS::CUBEMAP_LEFT) const; + virtual void texture_set_flags(RID p_texture,uint32_t p_flags); + virtual uint32_t texture_get_flags(RID p_texture) const; + virtual Image::Format texture_get_format(RID p_texture) const; + virtual uint32_t texture_get_width(RID p_texture) const; + virtual uint32_t texture_get_height(RID p_texture) const; + virtual void texture_set_size_override(RID p_texture,int p_width, int p_height); + + virtual void texture_set_path(RID p_texture,const String& p_path); + virtual String texture_get_path(RID p_texture) const; + + virtual void texture_set_shrink_all_x2_on_set_data(bool p_enable); + + virtual void texture_debug_usage(List *r_info); + + + /* SHADER API */ + + struct Shader : public RID_Data { + + + }; + + + virtual RID shader_create(VS::ShaderMode p_mode=VS::SHADER_SPATIAL); + + virtual void shader_set_mode(RID p_shader,VS::ShaderMode p_mode); + virtual VS::ShaderMode shader_get_mode(RID p_shader) const; + + virtual void shader_set_code(RID p_shader, const String& p_code); + virtual String shader_get_code(RID p_shader) const; + virtual void shader_get_param_list(RID p_shader, List *p_param_list) const; + + virtual void shader_set_default_texture_param(RID p_shader, const StringName& p_name, RID p_texture); + virtual RID shader_get_default_texture_param(RID p_shader, const StringName& p_name) const; + + + /* COMMON MATERIAL API */ + + virtual RID material_create(); + + virtual void material_set_shader(RID p_shader_material, RID p_shader); + virtual RID material_get_shader(RID p_shader_material) const; + + virtual void material_set_param(RID p_material, const StringName& p_param, const Variant& p_value); + virtual Variant material_get_param(RID p_material, const StringName& p_param) const; + + /* MESH API */ + + virtual RID mesh_create(); + + virtual void mesh_add_surface(RID p_mesh,uint32_t p_format,VS::PrimitiveType p_primitive,const DVector& p_array,int p_vertex_count,const DVector& p_index_array,int p_index_count,const Vector >& p_blend_shapes=Vector >()); + + virtual void mesh_set_morph_target_count(RID p_mesh,int p_amount); + virtual int mesh_get_morph_target_count(RID p_mesh) const; + + + virtual void mesh_set_morph_target_mode(RID p_mesh,VS::MorphTargetMode p_mode); + virtual VS::MorphTargetMode mesh_get_morph_target_mode(RID p_mesh) const; + + virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material); + virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const; + + virtual int mesh_surface_get_array_len(RID p_mesh, int p_surface) const; + virtual int mesh_surface_get_array_index_len(RID p_mesh, int p_surface) const; + + virtual DVector mesh_surface_get_array(RID p_mesh, int p_surface) const; + virtual DVector mesh_surface_get_index_array(RID p_mesh, int p_surface) const; + + + virtual uint32_t mesh_surface_get_format(RID p_mesh, int p_surface) const; + virtual VS::PrimitiveType mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const; + + virtual void mesh_remove_surface(RID p_mesh,int p_index); + virtual int mesh_get_surface_count(RID p_mesh) const; + + virtual void mesh_set_custom_aabb(RID p_mesh,const AABB& p_aabb); + virtual AABB mesh_get_custom_aabb(RID p_mesh) const; + + virtual AABB mesh_get_aabb(RID p_mesh) const; + virtual void mesh_clear(RID p_mesh); + + /* MULTIMESH API */ + + + virtual RID multimesh_create(); + + virtual void multimesh_allocate(RID p_multimesh,int p_instances,VS::MultimeshTransformFormat p_transform_format,VS::MultimeshColorFormat p_color_format,bool p_gen_aabb=true); + virtual int multimesh_get_instance_count(RID p_multimesh) const; + + virtual void multimesh_set_mesh(RID p_multimesh,RID p_mesh); + virtual void multimesh_set_custom_aabb(RID p_multimesh,const AABB& p_aabb); + 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 Matrix32& p_transform); + virtual void multimesh_instance_set_color(RID p_multimesh,int p_index,const Color& p_color); + + virtual RID multimesh_get_mesh(RID p_multimesh) const; + virtual AABB multimesh_get_custom_aabb(RID p_multimesh,const AABB& p_aabb) const; + + virtual Transform multimesh_instance_get_transform(RID p_multimesh,int p_index) const; + virtual Matrix32 multimesh_instance_get_transform_2d(RID p_multimesh,int p_index) const; + virtual Color multimesh_instance_get_color(RID p_multimesh,int p_index) const; + + virtual void multimesh_set_visible_instances(RID p_multimesh,int p_visible); + virtual int multimesh_get_visible_instances(RID p_multimesh) const; + + virtual AABB multimesh_get_aabb(RID p_mesh) const; + + /* IMMEDIATE API */ + + virtual RID immediate_create(); + virtual void immediate_begin(RID p_immediate,VS::PrimitiveType p_rimitive,RID p_texture=RID()); + virtual void immediate_vertex(RID p_immediate,const Vector3& p_vertex); + virtual void immediate_vertex_2d(RID p_immediate,const Vector3& p_vertex); + virtual void immediate_normal(RID p_immediate,const Vector3& p_normal); + virtual void immediate_tangent(RID p_immediate,const Plane& p_tangent); + virtual void immediate_color(RID p_immediate,const Color& p_color); + virtual void immediate_uv(RID p_immediate,const Vector2& tex_uv); + virtual void immediate_uv2(RID p_immediate,const Vector2& tex_uv); + virtual void immediate_end(RID p_immediate); + virtual void immediate_clear(RID p_immediate); + virtual void immediate_set_material(RID p_immediate,RID p_material); + virtual RID immediate_get_material(RID p_immediate) const; + + /* SKELETON API */ + + virtual RID skeleton_create(); + virtual void skeleton_allocate(RID p_skeleton,int p_bones,bool p_2d_skeleton=false); + virtual int skeleton_get_bone_count(RID p_skeleton) const; + virtual void skeleton_bone_set_transform(RID p_skeleton,int p_bone, const Transform& p_transform); + virtual Transform skeleton_bone_get_transform(RID p_skeleton,int p_bone); + virtual void skeleton_bone_set_transform_2d(RID p_skeleton,int p_bone, const Matrix32& p_transform); + virtual Matrix32 skeleton_bone_get_transform_2d(RID p_skeleton,int p_bone); + + /* Light API */ + + virtual RID light_create(VS::LightType p_type); + + virtual void light_set_color(RID p_light,const Color& p_color); + virtual void light_set_param(RID p_light,VS::LightParam p_param,float p_value); + virtual void light_set_shadow(RID p_light,bool p_enabled); + virtual void light_set_projector(RID p_light,RID p_texture); + virtual void light_set_attenuation_texure(RID p_light,RID p_texture); + 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_shader(RID p_light,RID p_shader); + + + virtual void light_directional_set_shadow_mode(RID p_light,VS::LightDirectionalShadowMode p_mode); + + /* PROBE API */ + + virtual RID reflection_probe_create(); + + virtual void reflection_probe_set_intensity(RID p_probe, float p_intensity); + virtual void reflection_probe_set_clip(RID p_probe, float p_near, float p_far); + virtual void reflection_probe_set_min_blend_distance(RID p_probe, float p_distance); + virtual void reflection_probe_set_extents(RID p_probe, const Vector3& p_extents); + virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3& p_offset); + virtual void reflection_probe_set_enable_parallax_correction(RID p_probe, bool p_enable); + virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution); + virtual void reflection_probe_set_hide_skybox(RID p_probe, bool p_hide); + virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers); + + + /* ROOM API */ + + virtual RID room_create(); + virtual void room_add_bounds(RID p_room, const DVector& p_convex_polygon,float p_height,const Transform& p_transform); + virtual void room_clear_bounds(); + + /* PORTAL API */ + + // portals are only (x/y) points, forming a convex shape, which its clockwise + // order points outside. (z is 0); + + virtual RID portal_create(); + virtual void portal_set_shape(RID p_portal, const Vector& p_shape); + virtual void portal_set_enabled(RID p_portal, bool p_enabled); + virtual void portal_set_disable_distance(RID p_portal, float p_distance); + virtual void portal_set_disabled_color(RID p_portal, const Color& p_color); + + + /* RENDER TARGET */ + + struct RenderTarget : public RID_Data { + + struct Color { + GLuint fbo; + GLuint color; + } front,back; + + GLuint depth; + + struct Deferred { + GLuint fbo; + GLuint fbo_color; + + GLuint albedo_ao; + GLuint metal_rough_motion; + GLuint normal_special; + } deferred; + + int width,height; + + bool flags[RENDER_TARGET_FLAG_MAX]; + + bool used_in_frame; + + RenderTarget() { + + width=0; + height=0; + depth=0; + front.fbo=0; + back.fbo=0; + deferred.fbo=0; + deferred.fbo_color=0; + used_in_frame=false; + + flags[RENDER_TARGET_VFLIP]=false; + flags[RENDER_TARGET_TRANSPARENT]=false; + flags[RENDER_TARGET_NO_3D]=false; + flags[RENDER_TARGET_NO_SAMPLING]=false; + } + }; + + mutable RID_Owner render_target_owner; + + void _render_target_clear(RenderTarget *rt); + void _render_target_allocate(RenderTarget *rt); + + virtual RID render_target_create(); + 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 Image render_target_get_image(RID p_render_target) const; + virtual void render_target_set_flag(RID p_render_target,RenderTargetFlags p_flag,bool p_value); + virtual bool render_target_renedered_in_frame(RID p_render_target); + + /* CANVAS SHADOW */ + + struct CanvasLightShadow : public RID_Data { + + int size; + int height; + GLuint fbo; + GLuint depth; + GLuint distance; //for older devices + }; + + RID_Owner canvas_light_shadow_owner; + + virtual RID canvas_light_shadow_buffer_create(int p_width); + + /* LIGHT SHADOW MAPPING */ + + struct CanvasOccluder : public RID_Data { + + GLuint vertex_id; // 0 means, unconfigured + GLuint index_id; // 0 means, unconfigured + DVector lines; + int len; + }; + + RID_Owner canvas_occluder_owner; + + virtual RID canvas_light_occluder_create(); + virtual void canvas_light_occluder_set_polylines(RID p_occluder, const DVector& p_lines); + + virtual bool free(RID p_rid); + + + struct Frame { + + RenderTarget *current_rt; + + bool clear_request; + Color clear_request_color; + int canvas_draw_commands; + } frame; + + void initialize(); + void finalize(); + + + + RasterizerStorageGLES3(); +}; + + +#endif // RASTERIZERSTORAGEGLES3_H diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp new file mode 100644 index 0000000000..f8c0234943 --- /dev/null +++ b/drivers/gles3/shader_gles3.cpp @@ -0,0 +1,754 @@ +/*************************************************************************/ +/* shader_gles2.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "shader_gles3.h" + + +#include "print_string.h" + +//#define DEBUG_OPENGL + +#ifdef DEBUG_OPENGL + +#define DEBUG_TEST_ERROR(m_section)\ +{\ + uint32_t err = glGetError();\ + if (err) {\ + print_line("OpenGL Error #"+itos(err)+" at: "+m_section);\ + }\ +} +#else + +#define DEBUG_TEST_ERROR(m_section) + +#endif + +ShaderGLES3 *ShaderGLES3::active=NULL; + + + +//#define DEBUG_SHADER + +#ifdef DEBUG_SHADER + +#define DEBUG_PRINT(m_text) print_line(m_text); + +#else + +#define DEBUG_PRINT(m_text) + +#endif + + +void ShaderGLES3::bind_uniforms() { + + if (!uniforms_dirty) { + return; + }; + + // upload default uniforms + const Map::Element *E =uniform_defaults.front(); + + while(E) { + int idx=E->key(); + int location=version->uniform_location[idx]; + + if (location<0) { + E=E->next(); + continue; + + } + + const Variant &v=E->value(); + _set_uniform_variant(location, v); + //print_line("uniform "+itos(location)+" value "+v+ " type "+Variant::get_type_name(v.get_type())); + E=E->next(); + }; + + const Map::Element* C = uniform_cameras.front(); + while (C) { + + int location = version->uniform_location[C->key()]; + if (location<0) { + C=C->next(); + continue; + } + + glUniformMatrix4fv(location,1,false,&(C->get().matrix[0][0])); + C = C->next(); + }; + + uniforms_dirty = false; +}; + +GLint ShaderGLES3::get_uniform_location(int p_idx) const { + + ERR_FAIL_COND_V(!version, -1); + + return version->uniform_location[p_idx]; +}; + +bool ShaderGLES3::bind() { + + if (active!=this || !version || new_conditional_version.key!=conditional_version.key) { + conditional_version=new_conditional_version; + version = get_current_version(); + } else { + + return false; + } + + ERR_FAIL_COND_V(!version,false); + + glUseProgram( version->id ); + + DEBUG_TEST_ERROR("Use Program"); + + active=this; + uniforms_dirty = true; +/* + * why on earth is this code here? + for (int i=0;i& p_code) { + + + int line=1; + String total_code; + + for(int i=0;i lines = String(total_code).split("\n"); + + for(int j=0;jversion==_v->code_version) + return _v; + } else { + return _v; + } + + } + + + + if (!_v) + version_map[conditional_version]=Version(); + + + Version &v = version_map[conditional_version]; + + if (!_v) { + + v.uniform_location = memnew_arr( GLint, uniform_count ); + + } else { + if (v.ok) { + //bye bye shaders + glDeleteShader( v.vert_id ); + glDeleteShader( v.frag_id ); + glDeleteProgram( v.id ); + v.id=0; + } + + } + + v.ok=false; + /* SETUP CONDITIONALS */ + + Vector strings; +#ifdef GLEW_ENABLED + //strings.push_back("#version 330\n"); + strings.push_back("#version 300 es\n"); +#else + strings.push_back("#version 300 es\n"); //ATI requieres this before anything +#endif + + + int define_line_ofs=1; + + for(int j=0;j0 ) { + //do custom code related stuff + + 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 */ + + v.id = glCreateProgram(); + + ERR_FAIL_COND_V(v.id==0, NULL); + + /* VERTEX SHADER */ + + + if (cc) { + for(int i=0;icustom_defines.size();i++) { + + strings.push_back(cc->custom_defines[i]); + DEBUG_PRINT("CD #"+itos(i)+": "+String(cc->custom_defines[i])); + } + } + + int strings_base_size=strings.size(); + + //vertex precision is high + strings.push_back("precision highp float;\n"); + strings.push_back("precision highp int;\n"); + +#if 0 + if (cc) { + + String _code_string = "#define VERTEX_SHADER_CODE "+cc->vertex+"\n"; + String _code_globals = "#define VERTEX_SHADER_GLOBALS "+cc->vertex_globals+"\n"; + + code_string=_code_string.ascii(); + code_globals=_code_globals.ascii(); + DEBUG_PRINT( code_globals.get_data() ); + DEBUG_PRINT( code_string.get_data() ); + strings.push_back(code_globals); + strings.push_back(code_string); + } +#endif + + + strings.push_back(vertex_code0.get_data()); + if (cc) { + code_globals=cc->vertex_globals.ascii(); + strings.push_back(code_globals.get_data()); + } + strings.push_back(vertex_code1.get_data()); + + if (cc) { + code_string=cc->vertex.ascii(); + strings.push_back(code_string.get_data()); + } + + strings.push_back(vertex_code2.get_data()); +#ifdef DEBUG_SHADER + + DEBUG_PRINT("\nVertex Code:\n\n"+String(code_string.get_data())); + for(int i=0;ifragment+"\n"; + String _code_globals = "#define FRAGMENT_SHADER_GLOBALS "+cc->fragment_globals+"\n"; + + code_string=_code_string.ascii(); + code_globals=_code_globals.ascii(); + DEBUG_PRINT( code_globals.get_data() ); + DEBUG_PRINT( code_string.get_data() ); + strings.push_back(code_globals); + strings.push_back(code_string); + } +#endif + + + strings.push_back(fragment_code0.get_data()); + if (cc) { + code_globals=cc->fragment_globals.ascii(); + strings.push_back(code_globals.get_data()); + } + strings.push_back(fragment_code1.get_data()); + + if (cc) { + code_string=cc->fragment.ascii(); + strings.push_back(code_string.get_data()); + } + + strings.push_back(fragment_code2.get_data()); + + if (cc) { + code_string2=cc->light.ascii(); + strings.push_back(code_string2.get_data()); + } + + strings.push_back(fragment_code3.get_data()); + +#ifdef DEBUG_SHADER + DEBUG_PRINT("\nFragment Code:\n\n"+String(code_string.get_data())); + for(int i=0;i=0) { + if (texunit_pairs[i].index<0) { + glUniform1i(loc,max_image_units+texunit_pairs[i].index); //negative, goes down + } else { + + glUniform1i(loc,texunit_pairs[i].index); + } + } + } + + // assign uniform block bind points + for (int i=0;i=0) + glUniformBlockBinding(v.id,loc,ubo_pairs[i].index); + } + + if ( cc ) { + + v.custom_uniform_locations.resize(cc->custom_uniforms.size()); + for(int i=0;icustom_uniforms.size();i++) { + + v.custom_uniform_locations[i]=glGetUniformLocation(v.id,String(cc->custom_uniforms[i]).ascii().get_data()); + } + } + + glUseProgram(0); + + + v.ok=true; + + return &v; +} + +GLint ShaderGLES3::get_uniform_location(const String& p_name) const { + + ERR_FAIL_COND_V(!version,-1); + return glGetUniformLocation(version->id,p_name.ascii().get_data()); +} + + +void ShaderGLES3::setup(const char** p_conditional_defines, int p_conditional_count,const char** p_uniform_names,int p_uniform_count, const AttributePair* p_attribute_pairs, int p_attribute_count, const TexUnitPair *p_texunit_pairs, int p_texunit_pair_count, const UBOPair *p_ubo_pairs, int p_ubo_pair_count,const char*p_vertex_code, const char *p_fragment_code,int p_vertex_code_start,int p_fragment_code_start) { + + ERR_FAIL_COND(version); + conditional_version.key=0; + new_conditional_version.key=0; + uniform_count=p_uniform_count; + conditional_count=p_conditional_count; + conditional_defines=p_conditional_defines; + uniform_names=p_uniform_names; + vertex_code=p_vertex_code; + fragment_code=p_fragment_code; + texunit_pairs=p_texunit_pairs; + texunit_pair_count=p_texunit_pair_count; + vertex_code_start=p_vertex_code_start; + fragment_code_start=p_fragment_code_start; + attribute_pairs=p_attribute_pairs; + attribute_pair_count=p_attribute_count; + ubo_pairs=p_ubo_pairs; + ubo_count=p_ubo_pair_count; + + //split vertex and shader code (thank you, retarded shader compiler programmers from you know what company). + { + String globals_tag="\nVERTEX_SHADER_GLOBALS"; + String code_tag="\nVERTEX_SHADER_CODE"; + String code = vertex_code; + int cpos = code.find(globals_tag); + if (cpos==-1) { + vertex_code0=code.ascii(); + } else { + vertex_code0=code.substr(0,cpos).ascii(); + code = code.substr(cpos+globals_tag.length(),code.length()); + + cpos = code.find(code_tag); + + if (cpos==-1) { + vertex_code1=code.ascii(); + } else { + + vertex_code1=code.substr(0,cpos).ascii(); + vertex_code2=code.substr(cpos+code_tag.length(),code.length()).ascii(); + } + } + } + + { + String globals_tag="\nFRAGMENT_SHADER_GLOBALS"; + String code_tag="\nFRAGMENT_SHADER_CODE"; + String light_code_tag="\nLIGHT_SHADER_CODE"; + String code = fragment_code; + int cpos = code.find(globals_tag); + if (cpos==-1) { + fragment_code0=code.ascii(); + } else { + fragment_code0=code.substr(0,cpos).ascii(); + code = code.substr(cpos+globals_tag.length(),code.length()); + + cpos = code.find(code_tag); + + if (cpos==-1) { + fragment_code1=code.ascii(); + } else { + + fragment_code1=code.substr(0,cpos).ascii(); + String code2 = code.substr(cpos+code_tag.length(),code.length()); + + cpos = code2.find(light_code_tag); + if (cpos==-1) { + fragment_code2=code2.ascii(); + } else { + + fragment_code2=code2.substr(0,cpos).ascii(); + fragment_code3 = code2.substr(cpos+light_code_tag.length(),code2.length()).ascii(); + } + } + } + } + +} + +void ShaderGLES3::finish() { + + const VersionKey *V=NULL; + while((V=version_map.next(V))) { + + Version &v=version_map[*V]; + glDeleteShader( v.vert_id ); + glDeleteShader( v.frag_id ); + glDeleteProgram( v.id ); + memdelete_arr( v.uniform_location ); + + } + +} + + +void ShaderGLES3::clear_caches() { + + const VersionKey *V=NULL; + while((V=version_map.next(V))) { + + Version &v=version_map[*V]; + glDeleteShader( v.vert_id ); + glDeleteShader( v.frag_id ); + glDeleteProgram( v.id ); + memdelete_arr( v.uniform_location ); + } + + version_map.clear(); + + custom_code_map.clear(); + version=NULL; + last_custom_code=1; + uniforms_dirty = true; + +} + +uint32_t ShaderGLES3::create_custom_shader() { + + custom_code_map[last_custom_code]=CustomCode(); + custom_code_map[last_custom_code].version=1; + return last_custom_code++; +} + +void ShaderGLES3::set_custom_shader_code(uint32_t p_code_id, const String& p_vertex, const String& p_vertex_globals,const String& p_fragment,const String& p_light, const String& p_fragment_globals,const Vector& p_uniforms,const Vector &p_custom_defines) { + + ERR_FAIL_COND(!custom_code_map.has(p_code_id)); + CustomCode *cc=&custom_code_map[p_code_id]; + + cc->vertex=p_vertex; + cc->vertex_globals=p_vertex_globals; + cc->fragment=p_fragment; + cc->fragment_globals=p_fragment_globals; + cc->light=p_light; + cc->custom_uniforms=p_uniforms; + cc->custom_defines=p_custom_defines; + cc->version++; +} + +void ShaderGLES3::set_custom_shader(uint32_t p_code_id) { + + new_conditional_version.code_version=p_code_id; +} + +void ShaderGLES3::free_custom_shader(uint32_t p_code_id) { + + /* if (! custom_code_map.has( p_code_id )) { + print_line("no code id "+itos(p_code_id)); + } else { + print_line("freed code id "+itos(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 + + custom_code_map.erase(p_code_id); + +} + + + +ShaderGLES3::ShaderGLES3() { + version=NULL; + last_custom_code=1; + uniforms_dirty = true; + + glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS,&max_image_units); +} + + +ShaderGLES3::~ShaderGLES3() { + + finish(); +} + + + diff --git a/drivers/gles3/shader_gles3.h b/drivers/gles3/shader_gles3.h new file mode 100644 index 0000000000..7aaf65d450 --- /dev/null +++ b/drivers/gles3/shader_gles3.h @@ -0,0 +1,377 @@ +/*************************************************************************/ +/* shader_gles2.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef SHADER_GLES3_H +#define SHADER_GLES3_H + + +#include "platform_config.h" +#ifndef GLES3_INCLUDE_H +#include +#else +#include GLES3_INCLUDE_H +#endif + +#include "hash_map.h" +#include "map.h" +#include "variant.h" +#include "camera_matrix.h" + +/** + @author Juan Linietsky +*/ + + +class ShaderGLES3 { +protected: + + struct Enum { + + uint64_t mask; + uint64_t shift; + const char *defines[16]; + }; + + struct EnumValue { + + uint64_t set_mask; + uint64_t clear_mask; + }; + + struct AttributePair { + + const char *name; + int index; + }; + + struct UniformPair { + const char* name; + Variant::Type type_hint; + }; + + struct TexUnitPair { + + const char *name; + int index; + }; + + struct UBOPair { + + const char *name; + int index; + }; + + bool uniforms_dirty; +private: + + //@TODO Optimize to a fixed set of shader pools and use a LRU + int uniform_count; + int texunit_pair_count; + int conditional_count; + int ubo_count; + int vertex_code_start; + int fragment_code_start; + int attribute_pair_count; + + struct CustomCode { + + String vertex; + String vertex_globals; + String fragment; + String fragment_globals; + String light; + uint32_t version; + Vector custom_uniforms; + Vector custom_defines; + + }; + + + struct Version { + + GLuint id; + GLuint vert_id; + GLuint frag_id; + GLint *uniform_location; + Vector custom_uniform_locations; + uint32_t code_version; + bool ok; + Version() { code_version=0; ok=false; uniform_location=NULL; } + }; + + Version *version; + + union VersionKey { + + struct { + uint32_t version; + uint32_t code_version; + }; + uint64_t key; + bool operator==(const VersionKey& p_key) const { return key==p_key.key; } + bool operator<(const VersionKey& p_key) const { return key version_map; + + HashMap custom_code_map; + uint32_t last_custom_code; + + + VersionKey conditional_version; + VersionKey new_conditional_version; + + virtual String get_shader_name() const=0; + + const char** conditional_defines; + const char** uniform_names; + const AttributePair *attribute_pairs; + const TexUnitPair *texunit_pairs; + const UBOPair *ubo_pairs; + const char* vertex_code; + const char* fragment_code; + CharString fragment_code0; + CharString fragment_code1; + CharString fragment_code2; + CharString fragment_code3; + + CharString vertex_code0; + CharString vertex_code1; + CharString vertex_code2; + + Version * get_current_version(); + + static ShaderGLES3 *active; + + int max_image_units; + + _FORCE_INLINE_ void _set_uniform_variant(GLint p_uniform,const Variant& p_value) { + + if (p_uniform<0) + return; // do none + switch(p_value.get_type()) { + + case Variant::BOOL: + case Variant::INT: { + + int val=p_value; + glUniform1i( p_uniform, val ); + } break; + case Variant::REAL: { + + real_t val=p_value; + glUniform1f( p_uniform, val ); + } break; + case Variant::COLOR: { + + Color val=p_value; + glUniform4f( p_uniform, val.r, val.g,val.b,val.a ); + } break; + case Variant::VECTOR2: { + + Vector2 val=p_value; + glUniform2f( p_uniform, val.x,val.y ); + } break; + case Variant::VECTOR3: { + + Vector3 val=p_value; + glUniform3f( p_uniform, val.x,val.y,val.z ); + } break; + case Variant::PLANE: { + + Plane val=p_value; + glUniform4f( p_uniform, val.normal.x,val.normal.y,val.normal.z,val.d ); + } break; + case Variant::QUAT: { + + Quat val=p_value; + glUniform4f( p_uniform, val.x,val.y,val.z,val.w ); + } break; + + case Variant::MATRIX32: { + + Matrix32 tr=p_value; + GLfloat matrix[16]={ /* build a 16x16 matrix */ + tr.elements[0][0], + tr.elements[0][1], + 0, + 0, + tr.elements[1][0], + tr.elements[1][1], + 0, + 0, + 0, + 0, + 1, + 0, + tr.elements[2][0], + tr.elements[2][1], + 0, + 1 + }; + + glUniformMatrix4fv(p_uniform,1,false,matrix); + + } break; + case Variant::MATRIX3: + case Variant::TRANSFORM: { + + Transform tr=p_value; + GLfloat matrix[16]={ /* build a 16x16 matrix */ + tr.basis.elements[0][0], + tr.basis.elements[1][0], + tr.basis.elements[2][0], + 0, + tr.basis.elements[0][1], + tr.basis.elements[1][1], + tr.basis.elements[2][1], + 0, + tr.basis.elements[0][2], + tr.basis.elements[1][2], + tr.basis.elements[2][2], + 0, + tr.origin.x, + tr.origin.y, + tr.origin.z, + 1 + }; + + + glUniformMatrix4fv(p_uniform,1,false,matrix); + } break; + default: { ERR_FAIL(); } // do nothing + + } + } + + Map uniform_defaults; + Map uniform_cameras; + + +protected: + + _FORCE_INLINE_ int _get_uniform(int p_which) const; + _FORCE_INLINE_ void _set_conditional(int p_which, bool p_value); + + void setup(const char** p_conditional_defines, int p_conditional_count,const char** p_uniform_names,int p_uniform_count, const AttributePair* p_attribute_pairs, int p_attribute_count, const TexUnitPair *p_texunit_pairs, int p_texunit_pair_count, const UBOPair *p_ubo_pairs, int p_ubo_pair_count,const char*p_vertex_code, const char *p_fragment_code,int p_vertex_code_start,int p_fragment_code_start); + + ShaderGLES3(); +public: + + enum { + CUSTOM_SHADER_DISABLED=0 + }; + + GLint get_uniform_location(const String& p_name) const; + GLint get_uniform_location(int p_uniform) const; + + static _FORCE_INLINE_ ShaderGLES3 *get_active() { return active; }; + bool bind(); + void unbind(); + void bind_uniforms(); + + + inline GLuint get_program() const { return version?version->id:0; } + + void clear_caches(); + + uint32_t create_custom_shader(); + void set_custom_shader_code(uint32_t p_id,const String& p_vertex, const String& p_vertex_globals,const String& p_fragment,const String& p_p_light,const String& p_fragment_globals,const Vector& p_uniforms,const Vector &p_custom_defines); + void set_custom_shader(uint32_t p_id); + void free_custom_shader(uint32_t p_id); + + void set_uniform_default(int p_idx, const Variant& p_value) { + + if (p_value.get_type()==Variant::NIL) { + + uniform_defaults.erase(p_idx); + } else { + + uniform_defaults[p_idx]=p_value; + } + uniforms_dirty = true; + } + + uint32_t get_version() const { return new_conditional_version.version; } + + void set_uniform_camera(int p_idx, const CameraMatrix& p_mat) { + + uniform_cameras[p_idx] = p_mat; + uniforms_dirty = true; + }; + + _FORCE_INLINE_ void set_custom_uniform(int p_idx, const Variant& p_value) { + + ERR_FAIL_COND(!version); + ERR_FAIL_INDEX(p_idx,version->custom_uniform_locations.size()); + _set_uniform_variant( version->custom_uniform_locations[p_idx], p_value ); + } + + _FORCE_INLINE_ GLint get_custom_uniform_location(int p_idx) { + + ERR_FAIL_COND_V(!version,-1); + ERR_FAIL_INDEX_V(p_idx,version->custom_uniform_locations.size(),-1); + return version->custom_uniform_locations[p_idx]; + } + + virtual void init()=0; + void finish(); + + virtual ~ShaderGLES3(); + +}; + + +// called a lot, made inline + + +int ShaderGLES3::_get_uniform(int p_which) const { + + ERR_FAIL_INDEX_V( p_which, uniform_count,-1 ); + ERR_FAIL_COND_V( !version, -1 ); + return version->uniform_location[p_which]; +} + +void ShaderGLES3::_set_conditional(int p_which, bool p_value) { + + ERR_FAIL_INDEX(p_which,conditional_count); + if (p_value) + new_conditional_version.version|=(1<135.0*PI/180.0) { + point = -light_vec; + sh = 0.5+(1.0/8.0); + } else if (angle_to_light>0.0) { + + point = vec2(light_vec.y,-light_vec.x); + sh = 0.25+(1.0/8.0); + } else { + + point = vec2(-light_vec.y,light_vec.x); + sh = 0.75+(1.0/8.0); + + } + + + highp vec4 s = shadow_matrix * vec4(point,0.0,1.0); + s.xyz/=s.w; + su=s.x*0.5+0.5; + sz=s.z*0.5+0.5; + //sz=lightlength(light_vec); + + highp float shadow_attenuation=0.0; + +#ifdef USE_RGBA_SHADOWS + +#define SHADOW_DEPTH(m_tex,m_uv) dot(texture2D((m_tex),(m_uv)),vec4(1.0 / (256.0 * 256.0 * 256.0),1.0 / (256.0 * 256.0),1.0 / 256.0,1) ) + +#else + +#define SHADOW_DEPTH(m_tex,m_uv) (texture2D((m_tex),(m_uv)).r) + +#endif + + + +#ifdef SHADOW_USE_GRADIENT + +#define SHADOW_TEST(m_ofs) { highp float sd = SHADOW_DEPTH(shadow_texture,vec2(m_ofs,sh)); shadow_attenuation+=1.0-smoothstep(sd,sd+shadow_gradient,sz); } + +#else + +#define SHADOW_TEST(m_ofs) { highp float sd = SHADOW_DEPTH(shadow_texture,vec2(m_ofs,sh)); shadow_attenuation+=step(sz,sd); } + +#endif + + +#ifdef SHADOW_FILTER_NEAREST + + SHADOW_TEST(su+shadowpixel_size); + +#endif + + +#ifdef SHADOW_FILTER_PCF3 + + SHADOW_TEST(su+shadowpixel_size); + SHADOW_TEST(su); + SHADOW_TEST(su-shadowpixel_size); + shadow_attenuation/=3.0; + +#endif + + +#ifdef SHADOW_FILTER_PCF5 + + SHADOW_TEST(su+shadowpixel_size*3.0); + SHADOW_TEST(su+shadowpixel_size*2.0); + SHADOW_TEST(su+shadowpixel_size); + SHADOW_TEST(su); + SHADOW_TEST(su-shadowpixel_size); + SHADOW_TEST(su-shadowpixel_size*2.0); + SHADOW_TEST(su-shadowpixel_size*3.0); + shadow_attenuation/=5.0; + +#endif + + +#ifdef SHADOW_FILTER_PCF9 + + SHADOW_TEST(su+shadowpixel_size*4.0); + SHADOW_TEST(su+shadowpixel_size*3.0); + SHADOW_TEST(su+shadowpixel_size*2.0); + SHADOW_TEST(su+shadowpixel_size); + SHADOW_TEST(su); + SHADOW_TEST(su-shadowpixel_size); + SHADOW_TEST(su-shadowpixel_size*2.0); + SHADOW_TEST(su-shadowpixel_size*3.0); + SHADOW_TEST(su-shadowpixel_size*4.0); + shadow_attenuation/=9.0; + +#endif + +#ifdef SHADOW_FILTER_PCF13 + + SHADOW_TEST(su+shadowpixel_size*6.0); + SHADOW_TEST(su+shadowpixel_size*5.0); + SHADOW_TEST(su+shadowpixel_size*4.0); + SHADOW_TEST(su+shadowpixel_size*3.0); + SHADOW_TEST(su+shadowpixel_size*2.0); + SHADOW_TEST(su+shadowpixel_size); + SHADOW_TEST(su); + SHADOW_TEST(su-shadowpixel_size); + SHADOW_TEST(su-shadowpixel_size*2.0); + SHADOW_TEST(su-shadowpixel_size*3.0); + SHADOW_TEST(su-shadowpixel_size*4.0); + SHADOW_TEST(su-shadowpixel_size*5.0); + SHADOW_TEST(su-shadowpixel_size*6.0); + shadow_attenuation/=13.0; + +#endif + + +#if defined(USE_OUTPUT_SHADOW_COLOR) + color=mix(shadow_color,color,shadow_attenuation); +#else + //color*=shadow_attenuation; + color=mix(light_shadow_color,color,shadow_attenuation); +#endif +//use shadows +#endif + } + +//use lighting +#endif +// color.rgb*=color.a; + frag_color = color; + +} + diff --git a/drivers/gles3/shaders/canvas_shadow.glsl b/drivers/gles3/shaders/canvas_shadow.glsl new file mode 100644 index 0000000000..c757990de0 --- /dev/null +++ b/drivers/gles3/shaders/canvas_shadow.glsl @@ -0,0 +1,49 @@ +[vertex] + + + +uniform highp mat4 projection_matrix; +uniform highp mat4 light_matrix; +uniform highp mat4 world_matrix; +uniform highp float distance_norm; + +layout(location=0) in highp vec3 vertex; + +out highp vec4 position_interp; + +void main() { + + gl_Position = projection_matrix * (light_matrix * (world_matrix * vec4(vertex,1.0))); + position_interp=gl_Position; +} + +[fragment] + +in highp vec4 position_interp; + +#ifdef USE_RGBA_SHADOWS + +layout(location=0) out lowp vec4 distance_buf; + +#else + +layout(location=0) out highp float distance_buf; + +#endif + +void main() { + + highp float depth = ((position_interp.z / position_interp.w) + 1.0) * 0.5 + 0.0;//bias; + +#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); + distance_buf=comp; +#else + + distance_buf=depth; + +#endif +} + diff --git a/drivers/gles3/shaders/copy.glsl b/drivers/gles3/shaders/copy.glsl new file mode 100644 index 0000000000..aba280186a --- /dev/null +++ b/drivers/gles3/shaders/copy.glsl @@ -0,0 +1,52 @@ +[vertex] + + +layout(location=0) in highp vec4 vertex_attrib; +#ifdef USE_CUBEMAP +layout(location=4) in vec3 cube_in; +#else +layout(location=4) in vec2 uv_in; // attrib:4 +#endif +layout(location=5) in vec2 uv2_in; // attrib:5 + +#ifdef USE_CUBEMAP +out vec3 cube_interp; +#else +out vec2 uv_interp; +#endif + +out vec2 uv2_interp; + +void main() { + +#ifdef USE_CUBEMAP + cube_interp = cube_in; +#else + uv_interp = uv_in; +#endif + uv2_interp = uv2_in; + gl_Position = vertex_attrib; +} + +[fragment] + + +#ifdef USE_CUBEMAP +in vec3 cube_interp; +uniform samplerCube source_cube; +#else +in vec2 uv_interp; +uniform sampler2D source; +#endif + +in vec2 uv2_interp; + +layout(location = 0) vec4 frag_color; //color:0 + +void main() { + + //vec4 color = color_interp; + + frag_color = color; +} + -- cgit v1.2.3 From a6e9dc615346f44b68b418483dd218d11ba4a674 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Mon, 3 Oct 2016 23:46:24 -0300 Subject: make editor update by tracking changes in visualserverraster --- drivers/gles3/rasterizer_storage_gles3.cpp | 8 ++++---- drivers/gles3/rasterizer_storage_gles3.h | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/gles3') diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index b29de876a4..515db39098 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -1199,7 +1199,7 @@ RID RasterizerStorageGLES3::multimesh_get_mesh(RID p_multimesh) const{ return RID(); } -AABB RasterizerStorageGLES3::multimesh_get_custom_aabb(RID p_multimesh,const AABB& p_aabb) const{ +AABB RasterizerStorageGLES3::multimesh_get_custom_aabb(RID p_multimesh) const{ return AABB(); } @@ -1305,7 +1305,7 @@ void RasterizerStorageGLES3::skeleton_bone_set_transform(RID p_skeleton,int p_bo } -Transform RasterizerStorageGLES3::skeleton_bone_get_transform(RID p_skeleton,int p_bone){ +Transform RasterizerStorageGLES3::skeleton_bone_get_transform(RID p_skeleton,int p_bone) const{ return Transform(); } @@ -1313,7 +1313,7 @@ void RasterizerStorageGLES3::skeleton_bone_set_transform_2d(RID p_skeleton,int p } -Matrix32 RasterizerStorageGLES3::skeleton_bone_get_transform_2d(RID p_skeleton,int p_bone){ +Matrix32 RasterizerStorageGLES3::skeleton_bone_get_transform_2d(RID p_skeleton,int p_bone) const{ return Matrix32(); } @@ -1419,7 +1419,7 @@ void RasterizerStorageGLES3::room_add_bounds(RID p_room, const DVector& } -void RasterizerStorageGLES3::room_clear_bounds(){ +void RasterizerStorageGLES3::room_clear_bounds(RID p_room){ } diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index 3b2d7d752c..eb6cd0bd92 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -249,7 +249,7 @@ public: virtual void multimesh_instance_set_color(RID p_multimesh,int p_index,const Color& p_color); virtual RID multimesh_get_mesh(RID p_multimesh) const; - virtual AABB multimesh_get_custom_aabb(RID p_multimesh,const AABB& p_aabb) const; + virtual AABB multimesh_get_custom_aabb(RID p_multimesh) const; virtual Transform multimesh_instance_get_transform(RID p_multimesh,int p_index) const; virtual Matrix32 multimesh_instance_get_transform_2d(RID p_multimesh,int p_index) const; @@ -282,9 +282,9 @@ public: virtual void skeleton_allocate(RID p_skeleton,int p_bones,bool p_2d_skeleton=false); virtual int skeleton_get_bone_count(RID p_skeleton) const; virtual void skeleton_bone_set_transform(RID p_skeleton,int p_bone, const Transform& p_transform); - virtual Transform skeleton_bone_get_transform(RID p_skeleton,int p_bone); + virtual Transform skeleton_bone_get_transform(RID p_skeleton,int p_bone) const; virtual void skeleton_bone_set_transform_2d(RID p_skeleton,int p_bone, const Matrix32& p_transform); - virtual Matrix32 skeleton_bone_get_transform_2d(RID p_skeleton,int p_bone); + virtual Matrix32 skeleton_bone_get_transform_2d(RID p_skeleton,int p_bone) const; /* Light API */ @@ -321,7 +321,7 @@ public: virtual RID room_create(); virtual void room_add_bounds(RID p_room, const DVector& p_convex_polygon,float p_height,const Transform& p_transform); - virtual void room_clear_bounds(); + virtual void room_clear_bounds(RID p_room); /* PORTAL API */ -- cgit v1.2.3 From cf5778e51a883936ffc896231da8259e5ebabc0a Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Wed, 5 Oct 2016 01:26:35 -0300 Subject: -Added ViewportContainer, this is the only way to make viewports show up in GUI now -2D editing now seems to work -Added some functions and refactoring to Viewport --- drivers/gles3/rasterizer_canvas_gles3.cpp | 18 +++++---- drivers/gles3/rasterizer_gles3.cpp | 4 +- drivers/gles3/rasterizer_storage_gles3.cpp | 64 +++++++++++++++++++++++++++--- drivers/gles3/rasterizer_storage_gles3.h | 5 ++- 4 files changed, 74 insertions(+), 17 deletions(-) (limited to 'drivers/gles3') diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index f24560763f..a1e755cb4a 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -111,6 +111,15 @@ void RasterizerCanvasGLES3::light_internal_free(RID p_rid) { void RasterizerCanvasGLES3::canvas_begin(){ + if (storage->frame.current_rt && storage->frame.clear_request) { + // a clear request may be pending, so do it + + 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 ); + glClear(GL_COLOR_BUFFER_BIT); + storage->frame.clear_request=false; + + } + /*canvas_shader.unbind(); canvas_shader.set_custom_shader(0); canvas_shader.set_conditional(CanvasShaderGLES2::USE_MODULATE,false); @@ -504,7 +513,7 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item,Item *curr } if (rect->flags&CANVAS_RECT_FLIP_V) { - src_rect.size.x*=-1; + src_rect.size.y*=-1; } if (rect->flags&CANVAS_RECT_TRANSPOSE) { @@ -769,14 +778,7 @@ void RasterizerGLES2::_canvas_item_setup_shader_params(CanvasItemMaterial *mater void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list,int p_z,const Color& p_modulate,Light *p_light) { - if (storage->frame.clear_request) { - // a clear request may be pending, so do it - 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 ); - glClear(GL_COLOR_BUFFER_BIT); - storage->frame.clear_request=false; - - } Item *current_clip=NULL; RasterizerStorageGLES3::Shader *shader_cache=NULL; diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index ba83a572e5..27b0690645 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -141,7 +141,7 @@ void RasterizerGLES3::set_current_render_target(RID p_render_target){ storage->frame.current_rt=rt; storage->frame.clear_request=false; - glViewport(0,0,rt->width,rt->height); + glViewport(0,0,rt->width,rt->height); } else { storage->frame.current_rt=NULL; @@ -155,6 +155,7 @@ void RasterizerGLES3::restore_render_target() { ERR_FAIL_COND(storage->frame.current_rt==NULL); RasterizerStorageGLES3::RenderTarget * rt = storage->frame.current_rt; + glBindFramebuffer(GL_FRAMEBUFFER,rt->front.fbo); glViewport(0,0,rt->width,rt->height); } @@ -176,6 +177,7 @@ void RasterizerGLES3::blit_render_target_to_screen(RID p_render_target,const Rec ERR_FAIL_COND(!rt); canvas->canvas_begin(); + glDisable(GL_BLEND); glBindFramebuffer(GL_FRAMEBUFFER,storage->config.system_fbo); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D,rt->front.color); diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 515db39098..b4d65080a4 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -1483,6 +1483,12 @@ void RasterizerStorageGLES3::_render_target_clear(RenderTarget *rt) { rt->depth=0; } + Texture *tex = texture_owner.get(rt->texture); + tex->alloc_height=0; + tex->alloc_width=0; + tex->width=0; + tex->height=0; + } void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){ @@ -1490,6 +1496,8 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){ if (rt->width<=0 || rt->height<=0) return; + glActiveTexture(GL_TEXTURE0); + glGenFramebuffers(1, &rt->front.fbo); glBindFramebuffer(GL_FRAMEBUFFER, rt->front.fbo); @@ -1512,6 +1520,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){ GLuint color_internal_format; GLuint color_format; GLuint color_type; + Image::Format image_format; if (config.fbo_format==FBO_FORMAT_16_BITS) { @@ -1520,28 +1529,33 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){ color_internal_format=GL_RGB5_A1; color_format=GL_RGBA; color_type=GL_UNSIGNED_SHORT_5_5_5_1; + image_format=Image::FORMAT_RGBA5551; } else { color_internal_format=GL_RGB565; color_format=GL_RGB; color_type=GL_UNSIGNED_SHORT_5_6_5; + image_format=Image::FORMAT_RGB565; } - } else if (config.fbo_format==FBO_FORMAT_32_BITS) { + } else if (config.fbo_format==FBO_FORMAT_32_BITS || (config.fbo_format==FBO_FORMAT_FLOAT && rt->flags[RENDER_TARGET_NO_3D])) { if (rt->flags[RENDER_TARGET_TRANSPARENT]) { color_internal_format=GL_RGBA8; color_format=GL_RGBA; color_type=GL_UNSIGNED_BYTE; + image_format=Image::FORMAT_RGBA8; } else { color_internal_format=GL_RGB10_A2; color_format=GL_RGBA; color_type=GL_UNSIGNED_INT_2_10_10_10_REV; + image_format=Image::FORMAT_RGBA8;//todo } } else if (config.fbo_format==FBO_FORMAT_FLOAT) { color_internal_format=GL_RGBA16F; color_format=GL_RGBA; color_type=GL_HALF_FLOAT; + image_format=Image::FORMAT_RGBAH; } glTexImage2D(GL_TEXTURE_2D, 0, color_internal_format, rt->width, rt->height, 0, color_format, color_type, NULL); @@ -1559,6 +1573,19 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){ ERR_FAIL_COND( status != GL_FRAMEBUFFER_COMPLETE ); } + Texture *tex = texture_owner.get(rt->texture); + tex->format=image_format; + tex->gl_format_cache=color_format; + tex->gl_type_cache=color_type; + tex->gl_internal_format_cache=color_internal_format; + tex->tex_id=rt->front.color; + tex->width=rt->width; + tex->alloc_width=rt->width; + tex->height=rt->height; + tex->alloc_height=rt->height; + + + texture_set_flags(rt->texture,tex->flags); if (!rt->flags[RENDER_TARGET_NO_SAMPLING]) { @@ -1662,6 +1689,31 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){ RID RasterizerStorageGLES3::render_target_create(){ RenderTarget *rt = memnew( RenderTarget ); + + Texture * t = memnew( Texture ); + + t->flags=0; + t->width=0; + t->height=0; + t->alloc_height=0; + t->alloc_width=0; + t->format=Image::FORMAT_R8; + 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=0; + t->active=true; + t->tex_id=0; + + + rt->texture=texture_owner.make_rid(t); + return render_target_owner.make_rid(rt); } @@ -1686,13 +1738,9 @@ 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 RID(); + return rt->texture; } -Image RasterizerStorageGLES3::render_target_get_image(RID p_render_target) const{ - return Image(); -} void RasterizerStorageGLES3::render_target_set_flag(RID p_render_target,RenderTargetFlags p_flag,bool p_value) { RenderTarget *rt = render_target_owner.getornull(p_render_target); @@ -1889,12 +1937,16 @@ bool RasterizerStorageGLES3::free(RID p_rid){ RenderTarget *rt = render_target_owner.getornull(p_rid); _render_target_clear(rt); + Texture *t=texture_owner.get(rt->texture); + texture_owner.free(rt->texture); + memdelete(t); render_target_owner.free(p_rid); memdelete(rt); } else if (texture_owner.owns(p_rid)) { // delete the texture Texture *texture = texture_owner.get(p_rid); + ERR_FAIL_COND_V(texture->render_target,true); //cant free the render target texture, dude info.texture_mem-=texture->total_data_size; texture_owner.free(p_rid); memdelete(texture); diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index eb6cd0bd92..9820fbc941 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -117,7 +117,6 @@ public: bool active; GLuint tex_id; - RenderTarget *render_target; Texture() { @@ -361,6 +360,8 @@ public: bool used_in_frame; + RID texture; + RenderTarget() { width=0; @@ -387,7 +388,7 @@ public: virtual RID render_target_create(); 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 Image render_target_get_image(RID p_render_target) const; + virtual void render_target_set_flag(RID p_render_target,RenderTargetFlags p_flag,bool p_value); virtual bool render_target_renedered_in_frame(RID p_render_target); -- cgit v1.2.3 From 1527cf8c0d17891dd0ebf99d484f83daa46eba3c Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Mon, 10 Oct 2016 18:31:01 -0300 Subject: 2D Shaders are working again using the new syntax, though all is buggy in general --- drivers/gles3/rasterizer_canvas_gles3.cpp | 143 +++-- drivers/gles3/rasterizer_canvas_gles3.h | 2 + drivers/gles3/rasterizer_gles3.cpp | 10 + drivers/gles3/rasterizer_storage_gles3.cpp | 899 ++++++++++++++++++++++++++++- drivers/gles3/rasterizer_storage_gles3.h | 109 +++- drivers/gles3/shader_compiler_gles3.cpp | 528 +++++++++++++++++ drivers/gles3/shader_compiler_gles3.h | 67 +++ drivers/gles3/shader_gles3.cpp | 83 ++- drivers/gles3/shader_gles3.h | 27 +- drivers/gles3/shaders/canvas.glsl | 72 ++- 10 files changed, 1824 insertions(+), 116 deletions(-) create mode 100644 drivers/gles3/shader_compiler_gles3.cpp create mode 100644 drivers/gles3/shader_compiler_gles3.h (limited to 'drivers/gles3') diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index a1e755cb4a..b2228a6cfa 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -138,6 +138,7 @@ void RasterizerCanvasGLES3::canvas_begin(){ state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_DISTANCE_FIELD,false); + state.canvas_shader.set_custom_shader(0); state.canvas_shader.bind(); state.canvas_shader.set_uniform(CanvasShaderGLES3::FINAL_MODULATE,Color(1,1,1,1)); state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX,Matrix32()); @@ -520,6 +521,8 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item,Item *curr //err.. } + state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE,texpixel_size); + glVertexAttrib4f(1,rect->rect.pos.x,rect->rect.pos.y,rect->rect.size.x,rect->rect.size.y); glVertexAttrib4f(2,src_rect.pos.x,src_rect.pos.y,src_rect.size.x,src_rect.size.y); @@ -567,6 +570,8 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item,Item *curr Size2 texpixel_size( 1.0/texture->width, 1.0/texture->height ); + state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE,texpixel_size); + #define DSTRECT(m_x,m_y,m_w,m_h) glVertexAttrib4f(1,m_x,m_y,m_w,m_h) #define SRCRECT(m_x,m_y,m_w,m_h) glVertexAttrib4f(2,(m_x)*texpixel_size.x,(m_y)*texpixel_size.y,(m_w)*texpixel_size.x,(m_h)*texpixel_size.y) @@ -634,8 +639,13 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item,Item *curr ERR_CONTINUE( primitive->points.size()<1); - _bind_canvas_texture(primitive->texture); + RasterizerStorageGLES3::Texture* texture = _bind_canvas_texture(primitive->texture); + + if (texture ) { + Size2 texpixel_size( 1.0/texture->width, 1.0/texture->height ); + state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE,texpixel_size); + } if (primitive->colors.size()==1 && primitive->points.size()>1) { Color c = primitive->colors[0]; @@ -652,6 +662,14 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item,Item *curr Item::CommandPolygon* polygon = static_cast(c); _set_texture_rect_mode(false); + + RasterizerStorageGLES3::Texture* texture = _bind_canvas_texture(polygon->texture); + + if (texture ) { + Size2 texpixel_size( 1.0/texture->width, 1.0/texture->height ); + state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE,texpixel_size); + + } _draw_polygon(polygon->count,polygon->indices.ptr(),polygon->points.ptr(),polygon->uvs.ptr(),polygon->colors.ptr(),polygon->texture,polygon->colors.size()==1); } break; @@ -800,10 +818,14 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list,int p_z,const glBindTexture(GL_TEXTURE_2D,storage->resources.white_tex); + int last_blend_mode=-1; + RID canvas_last_material; bool prev_distance_field=false; + + while(p_item_list) { Item *ci=p_item_list; @@ -878,53 +900,71 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list,int p_z,const RID material = material_owner->material; if (material!=canvas_last_material || rebind_shader) { -#if 0 - Shader *shader = NULL; - if (material && material->shader.is_valid()) { - shader = shader_owner.get(material->shader); - if (shader && !shader->valid) { - shader=NULL; + + RasterizerStorageGLES3::Material *material_ptr = storage->material_owner.getornull(material); + RasterizerStorageGLES3::Shader *shader_ptr = NULL; + + if (material_ptr) { + + shader_ptr = material_ptr->shader; + + if (shader_ptr && shader_ptr->mode!=VS::SHADER_CANVAS_ITEM) { + shader_ptr=NULL; //do not use non canvasitem shader } } - shader_cache=shader; - if (shader) { - canvas_shader.set_custom_shader(shader->custom_code_id); - _canvas_item_setup_shader_params(material,shader); - } else { - shader_cache=NULL; - canvas_shader.set_custom_shader(0); - canvas_shader.bind(); - uses_texpixel_size=false; + if (shader_ptr && shader_ptr!=shader_cache) { + + state.canvas_shader.set_custom_shader(shader_ptr->custom_code_id); + state.canvas_shader.bind(); + + if (material_ptr->ubo_id) { + glBindBufferBase(GL_UNIFORM_BUFFER,2,material_ptr->ubo_id); + } + + int tc = material_ptr->textures.size(); + RID* textures = material_ptr->textures.ptr(); + + for(int i=0;itexture_owner.getornull( textures[i] ); + if (!t) { + //check hints + glBindTexture(GL_TEXTURE_2D,storage->resources.white_tex); + continue; + } + + glBindTexture(t->target,t->tex_id); + } + + + } else if (!shader_ptr) { + state.canvas_shader.set_custom_shader(0); + state.canvas_shader.bind(); } + shader_cache=shader_ptr; - canvas_shader.set_uniform(CanvasShaderGLES3::PROJECTION_MATRIX,canvas_transform); - if (canvas_use_modulate) - reset_modulate=true; canvas_last_material=material; rebind_shader=false; -#endif - } - if (material.is_valid() && shader_cache) { -#if 0 - _canvas_item_setup_shader_uniforms(material,shader_cache); -#endif } - bool unshaded = false; //(material && material->shading_mode==VS::CANVAS_ITEM_SHADING_UNSHADED) || ci->blend_mode!=VS::MATERIAL_BLEND_MODE_MIX; + int blend_mode = shader_cache ? shader_cache->canvas_item.blend_mode : RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX; + bool unshaded = shader_cache && (shader_cache->canvas_item.light_mode==RasterizerStorageGLES3::Shader::CanvasItem::LIGHT_MODE_UNSHADED || blend_mode!=RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX); bool reclip=false; -#if 0 - if (ci==p_item_list || ci->blend_mode!=canvas_blend_mode) { - switch(ci->blend_mode) { + if (last_blend_mode!=blend_mode) { + + switch(blend_mode) { - case VS::MATERIAL_BLEND_MODE_MIX: { + case RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX: { glBlendEquation(GL_FUNC_ADD); - if (current_rt && current_rt_transparent) { + if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); } else { @@ -932,33 +972,30 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list,int p_z,const } } break; - case VS::MATERIAL_BLEND_MODE_ADD: { + case RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_ADD: { glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_SRC_ALPHA,GL_ONE); } break; - case VS::MATERIAL_BLEND_MODE_SUB: { + case RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_SUB: { glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); glBlendFunc(GL_SRC_ALPHA,GL_ONE); } break; - case VS::MATERIAL_BLEND_MODE_MUL: { + case RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MUL: { glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_DST_COLOR,GL_ZERO); } break; - case VS::MATERIAL_BLEND_MODE_PREMULT_ALPHA: { + case RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_PMALPHA: { glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA); } break; } - canvas_blend_mode=ci->blend_mode; + last_blend_mode=blend_mode; } -#endif - -// canvas_shader.set_uniform(CanvasShaderGLES3::CANVAS_MODULATE,unshaded ? Color(1,1,1,1) : p_modulate); state.canvas_item_modulate = unshaded ? ci->final_modulate : Color( ci->final_modulate.r * p_modulate.r, @@ -974,10 +1011,10 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list,int p_z,const state.canvas_shader.set_uniform(CanvasShaderGLES3::EXTRA_MATRIX,state.extra_matrix); - if (unshaded || (state.canvas_item_modulate.a>0.001 && (!material.is_valid() /*|| material->shading_mode!=VS::CANVAS_ITEM_SHADING_ONLY_LIGHT*/) && !ci->light_masked )) + if (unshaded || (state.canvas_item_modulate.a>0.001 && (!shader_cache || shader_cache->canvas_item.light_mode!=RasterizerStorageGLES3::Shader::CanvasItem::LIGHT_MODE_LIGHT_ONLY) && !ci->light_masked )) _canvas_item_render_commands(ci,current_clip,reclip); - if (/*canvas_blend_mode==VS::MATERIAL_BLEND_MODE_MIX &&*/ p_light && !unshaded) { + if ((blend_mode==RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX || RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_PMALPHA) && p_light && !unshaded) { Light *light = p_light; bool light_used=false; @@ -1046,12 +1083,7 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list,int p_z,const bool light_rebind = state.canvas_shader.bind(); if (light_rebind) { -#if 0 - if (material && shader_cache) { - _canvas_item_setup_shader_params(material,shader_cache); - _canvas_item_setup_shader_uniforms(material,shader_cache); - } -#endif + 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,Matrix32()); @@ -1100,15 +1132,12 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list,int p_z,const state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF9,false); state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF13,false); - state.canvas_shader.bind(); -#if 0 - if (material && shader_cache) { - _canvas_item_setup_shader_params(material,shader_cache); - _canvas_item_setup_shader_uniforms(material,shader_cache); - } -#endif + last_blend_mode=-1; + + /* + //this is set again, so it should not be needed anyway? state.canvas_item_modulate = unshaded ? ci->final_modulate : Color( ci->final_modulate.r * p_modulate.r, ci->final_modulate.g * p_modulate.g, @@ -1120,7 +1149,6 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list,int p_z,const state.canvas_shader.set_uniform(CanvasShaderGLES3::EXTRA_MATRIX,Matrix32()); state.canvas_shader.set_uniform(CanvasShaderGLES3::FINAL_MODULATE,state.canvas_item_modulate); - glBlendEquation(GL_FUNC_ADD); if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { @@ -1130,6 +1158,7 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list,int p_z,const } //@TODO RESET canvas_blend_mode + */ } @@ -1380,6 +1409,9 @@ void RasterizerCanvasGLES3::reset_canvas() { state.vp=canvas_transform; store_transform(canvas_transform,state.canvas_item_ubo_data.projection_matrix); + for(int i=0;i<4;i++) { + state.canvas_item_ubo_data.time[i]=storage->frame.time[i]; + } glBindBuffer(GL_UNIFORM_BUFFER, state.canvas_item_ubo); glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(CanvasItemUBO), &state.canvas_item_ubo_data); @@ -1442,6 +1474,7 @@ void RasterizerCanvasGLES3::initialize() { glBindBuffer(GL_UNIFORM_BUFFER, 0); state.canvas_shader.init(); + state.canvas_shader.set_base_material_tex_index(1); state.canvas_shadow_shader.init(); state.canvas_shader.set_conditional(CanvasShaderGLES3::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 1f72a8dbcf..8f34f07d06 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.h +++ b/drivers/gles3/rasterizer_canvas_gles3.h @@ -5,12 +5,14 @@ #include "rasterizer_storage_gles3.h" #include "shaders/canvas_shadow.glsl.h" + class RasterizerCanvasGLES3 : public RasterizerCanvas { public: struct CanvasItemUBO { float projection_matrix[16]; + float time[4]; }; diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index 27b0690645..eaa9825605 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -115,8 +115,17 @@ void RasterizerGLES3::initialize() { void RasterizerGLES3::begin_frame(){ + double time_total = double(OS::get_singleton()->get_ticks_usec())/1000000.0; + storage->frame.time[0]=time_total; + storage->frame.time[1]=Math::fmod(time_total,3600); + storage->frame.time[2]=Math::fmod(time_total,900); + storage->frame.time[3]=Math::fmod(time_total,60); + + storage->update_dirty_shaders(); + storage->update_dirty_materials(); } + void RasterizerGLES3::set_current_render_target(RID p_render_target){ if (!p_render_target.is_valid() && storage->frame.current_rt && storage->frame.clear_request) { @@ -257,6 +266,7 @@ RasterizerGLES3::RasterizerGLES3() storage = memnew( RasterizerStorageGLES3 ); canvas = memnew( RasterizerCanvasGLES3 ); canvas->storage=storage; + storage->canvas=canvas; } diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index b4d65080a4..74b7d72652 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -1,4 +1,5 @@ #include "rasterizer_storage_gles3.h" +#include "rasterizer_canvas_gles3.h" #include "globals.h" /* TEXTURE API */ @@ -1000,65 +1001,906 @@ void RasterizerStorageGLES3::texture_set_shrink_all_x2_on_set_data(bool p_enable RID RasterizerStorageGLES3::shader_create(VS::ShaderMode p_mode){ - return RID(); + Shader *shader = memnew( Shader ); + shader->mode=p_mode; + RID rid = shader_owner.make_rid(shader); + shader_set_mode(rid,p_mode); + _shader_make_dirty(shader); + shader->self=rid; + + return rid; +} + +void RasterizerStorageGLES3::_shader_make_dirty(Shader* p_shader) { + + if (p_shader->dirty_list.in_list()) + return; + + _shader_dirty_list.add(&p_shader->dirty_list); } void RasterizerStorageGLES3::shader_set_mode(RID p_shader,VS::ShaderMode p_mode){ + ERR_FAIL_INDEX(p_mode,VS::SHADER_MAX); + Shader *shader=shader_owner.get(p_shader); + ERR_FAIL_COND(!shader); + + if (shader->custom_code_id && p_mode==shader->mode) + return; + + + if (shader->custom_code_id) { + + shader->shader->free_custom_shader(shader->custom_code_id); + shader->custom_code_id=0; + } + + shader->mode=p_mode; + + ShaderGLES3* shaders[VS::SHADER_MAX]={ + &canvas->state.canvas_shader, + &canvas->state.canvas_shader, + &canvas->state.canvas_shader, + + }; + + shader->shader=shaders[p_mode]; + + shader->custom_code_id = shader->shader->create_custom_shader(); + + _shader_make_dirty(shader); } VS::ShaderMode RasterizerStorageGLES3::shader_get_mode(RID p_shader) const { - return VS::SHADER_SPATIAL; + const Shader *shader=shader_owner.get(p_shader); + ERR_FAIL_COND_V(!shader,VS::SHADER_MAX); + + return shader->mode; } void RasterizerStorageGLES3::shader_set_code(RID p_shader, const String& p_code){ + Shader *shader=shader_owner.get(p_shader); + ERR_FAIL_COND(!shader); + shader->code=p_code; + _shader_make_dirty(shader); } String RasterizerStorageGLES3::shader_get_code(RID p_shader) const{ - return String(); + const Shader *shader=shader_owner.get(p_shader); + ERR_FAIL_COND_V(!shader,String()); + + + return shader->code; } + +void RasterizerStorageGLES3::_update_shader(Shader* p_shader) const { + + + _shader_dirty_list.remove( &p_shader->dirty_list ); + + p_shader->valid=false; + + p_shader->uniforms.clear(); + + ShaderCompilerGLES3::GeneratedCode gen_code; + ShaderCompilerGLES3::IdentifierActions *actions=NULL; + + + + switch(p_shader->mode) { + case VS::SHADER_CANVAS_ITEM: { + + p_shader->canvas_item.light_mode=Shader::CanvasItem::LIGHT_MODE_NORMAL; + p_shader->canvas_item.blend_mode=Shader::CanvasItem::BLEND_MODE_MIX; + + shaders.actions_canvas.render_mode_values["blend_add"]=Pair(&p_shader->canvas_item.blend_mode,Shader::CanvasItem::BLEND_MODE_ADD); + shaders.actions_canvas.render_mode_values["blend_mix"]=Pair(&p_shader->canvas_item.blend_mode,Shader::CanvasItem::BLEND_MODE_MIX); + shaders.actions_canvas.render_mode_values["blend_sub"]=Pair(&p_shader->canvas_item.blend_mode,Shader::CanvasItem::BLEND_MODE_SUB); + shaders.actions_canvas.render_mode_values["blend_mul"]=Pair(&p_shader->canvas_item.blend_mode,Shader::CanvasItem::BLEND_MODE_MUL); + shaders.actions_canvas.render_mode_values["blend_premul_alpha"]=Pair(&p_shader->canvas_item.blend_mode,Shader::CanvasItem::BLEND_MODE_PMALPHA); + + shaders.actions_canvas.render_mode_values["unshaded"]=Pair(&p_shader->canvas_item.light_mode,Shader::CanvasItem::LIGHT_MODE_UNSHADED); + shaders.actions_canvas.render_mode_values["light_only"]=Pair(&p_shader->canvas_item.light_mode,Shader::CanvasItem::LIGHT_MODE_LIGHT_ONLY); + + actions=&shaders.actions_canvas; + actions->uniforms=&p_shader->uniforms; + + } break; + } + + + Error err = shaders.compiler.compile(p_shader->mode,p_shader->code,actions,p_shader->path,gen_code); + + ERR_FAIL_COND(err!=OK); + + 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); + + p_shader->ubo_size=gen_code.uniform_total_size; + p_shader->ubo_offsets=gen_code.uniform_offsets; + p_shader->texture_count=gen_code.texture_uniforms.size(); + + //all materials using this shader will have to be invalidated, unfortunately + + for (SelfList* E = p_shader->materials.first();E;E=E->next() ) { + + _material_make_dirty(E->self()); + } + + p_shader->valid=true; + p_shader->version++; + +} + +void RasterizerStorageGLES3::update_dirty_shaders() { + + while( _shader_dirty_list.first() ) { + _update_shader(_shader_dirty_list.first()->self() ); + } +} + void RasterizerStorageGLES3::shader_get_param_list(RID p_shader, List *p_param_list) const{ + Shader *shader=shader_owner.get(p_shader); + ERR_FAIL_COND(!shader); + + + if (shader->dirty_list.in_list()) + _update_shader(shader); // ok should be not anymore dirty + + + Map order; + + for(Map::Element *E=shader->uniforms.front();E;E=E->next()) { + + + order[E->get().order]=E->key(); + } + + + for(Map::Element *E=order.front();E;E=E->next()) { + + PropertyInfo pi; + ShaderLanguage::ShaderNode::Uniform &u=shader->uniforms[E->get()]; + pi.name=E->get(); + switch(u.type) { + case ShaderLanguage::TYPE_VOID: pi.type=Variant::NIL; break; + case ShaderLanguage::TYPE_BOOL: pi.type=Variant::BOOL; break; + case ShaderLanguage::TYPE_BVEC2: pi.type=Variant::INT; pi.hint=PROPERTY_HINT_FLAGS; pi.hint_string="x,y"; break; + case ShaderLanguage::TYPE_BVEC3: pi.type=Variant::INT; pi.hint=PROPERTY_HINT_FLAGS; pi.hint_string="x,y,z"; break; + case ShaderLanguage::TYPE_BVEC4: pi.type=Variant::INT; pi.hint=PROPERTY_HINT_FLAGS; pi.hint_string="x,y,z,w"; break; + case ShaderLanguage::TYPE_UINT: + case ShaderLanguage::TYPE_INT: { + 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]); + } + + } break; + case ShaderLanguage::TYPE_IVEC2: + case ShaderLanguage::TYPE_IVEC3: + case ShaderLanguage::TYPE_IVEC4: + case ShaderLanguage::TYPE_UVEC2: + case ShaderLanguage::TYPE_UVEC3: + case ShaderLanguage::TYPE_UVEC4: { + + pi.type=Variant::INT_ARRAY; + } break; + case ShaderLanguage::TYPE_FLOAT: { + pi.type=Variant::REAL; + 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])+","+rtos(u.hint_range[2]); + } + + } break; + case ShaderLanguage::TYPE_VEC2: pi.type=Variant::VECTOR2; break; + case ShaderLanguage::TYPE_VEC3: pi.type=Variant::VECTOR3; break; + case ShaderLanguage::TYPE_VEC4: { + if (u.hint==ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) { + pi.type=Variant::COLOR; + } else { + pi.type=Variant::PLANE; + } + } break; + case ShaderLanguage::TYPE_MAT2: pi.type=Variant::MATRIX32; break; + case ShaderLanguage::TYPE_MAT3: pi.type=Variant::MATRIX3; break; + case ShaderLanguage::TYPE_MAT4: pi.type=Variant::TRANSFORM; break; + case ShaderLanguage::TYPE_SAMPLER2D: + case ShaderLanguage::TYPE_ISAMPLER2D: + case ShaderLanguage::TYPE_USAMPLER2D: { + + pi.type=Variant::OBJECT; + pi.hint=PROPERTY_HINT_RESOURCE_TYPE; + pi.hint_string="Texture"; + } break; + case ShaderLanguage::TYPE_SAMPLERCUBE: { + + pi.type=Variant::OBJECT; + pi.hint=PROPERTY_HINT_RESOURCE_TYPE; + pi.hint_string="CubeMap"; + } break; + }; + + p_param_list->push_back(pi); + + } } void RasterizerStorageGLES3::shader_set_default_texture_param(RID p_shader, const StringName& p_name, RID p_texture){ + Shader *shader=shader_owner.get(p_shader); + ERR_FAIL_COND(!shader); + ERR_FAIL_COND(p_texture.is_valid() && !texture_owner.owns(p_texture)); + + if (p_texture.is_valid()) + shader->default_textures[p_name]=p_texture; + else + shader->default_textures.erase(p_name); + _shader_make_dirty(shader); } RID RasterizerStorageGLES3::shader_get_default_texture_param(RID p_shader, const StringName& p_name) const{ - return RID(); + const Shader *shader=shader_owner.get(p_shader); + ERR_FAIL_COND_V(!shader,RID()); + + const Map::Element *E=shader->default_textures.find(p_name); + if (!E) + return RID(); + return E->get(); } /* COMMON MATERIAL API */ +void RasterizerStorageGLES3::_material_make_dirty(Material* p_material) const { + + if (p_material->dirty_list.in_list()) + return; + + _material_dirty_list.add(&p_material->dirty_list); +} + RID RasterizerStorageGLES3::material_create(){ - return RID(); + Material *material = memnew( Material ); + + return material_owner.make_rid(material); } -void RasterizerStorageGLES3::material_set_shader(RID p_shader_material, RID p_shader){ +void RasterizerStorageGLES3::material_set_shader(RID p_material, RID p_shader){ + + Material *material = material_owner.get( p_material ); + ERR_FAIL_COND(!material); + + Shader *shader=shader_owner.getornull(p_shader); + + if (material->shader) { + //if shader, remove from previous shader material list + material->shader->materials.remove( &material->list ); + } + material->shader=shader; + + if (shader) { + shader->materials.add(&material->list); + } + _material_make_dirty(material); } -RID RasterizerStorageGLES3::material_get_shader(RID p_shader_material) const{ + +RID RasterizerStorageGLES3::material_get_shader(RID p_material) const{ + + const Material *material = material_owner.get( p_material ); + ERR_FAIL_COND_V(!material,RID()); + + if (material->shader) + return material->shader->self; return RID(); } void RasterizerStorageGLES3::material_set_param(RID p_material, const StringName& p_param, const Variant& p_value){ + Material *material = material_owner.get( p_material ); + ERR_FAIL_COND(!material); + + if (p_value.get_type()==Variant::NIL) + material->params.erase(p_param); + else + material->params[p_param]=p_value; + + _material_make_dirty(material); } Variant RasterizerStorageGLES3::material_get_param(RID p_material, const StringName& p_param) const{ + const Material *material = material_owner.get( p_material ); + ERR_FAIL_COND_V(!material,RID()); + + if (material->params.has(p_param)) + return material->params[p_param]; + return Variant(); } +_FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataType type, const Variant& value, uint8_t *data) { + switch(type) { + case ShaderLanguage::TYPE_BOOL: { + + bool v = value; + + GLuint *gui = (GLuint*)data; + *gui = v ? GL_TRUE : GL_FALSE; + } break; + case ShaderLanguage::TYPE_BVEC2: { + + int v = value; + GLuint *gui = (GLuint*)data; + 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; + + } 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; + + } break; + case ShaderLanguage::TYPE_INT: { + + int v = value; + GLint *gui = (GLint*)data; + gui[0]=v; + + } break; + case ShaderLanguage::TYPE_IVEC2: { + + DVector iv = value; + int s = iv.size(); + GLint *gui = (GLint*)data; + + DVector::Read r = iv.read(); + + for(int i=0;i<2;i++) { + if (i iv = value; + int s = iv.size(); + GLint *gui = (GLint*)data; + + DVector::Read r = iv.read(); + + for(int i=0;i<3;i++) { + if (i iv = value; + int s = iv.size(); + GLint *gui = (GLint*)data; + + DVector::Read r = iv.read(); + + for(int i=0;i<4;i++) { + if (i iv = value; + int s = iv.size(); + GLuint *gui = (GLuint*)data; + + DVector::Read r = iv.read(); + + for(int i=0;i<2;i++) { + if (i iv = value; + int s = iv.size(); + GLuint *gui = (GLuint*)data; + + DVector::Read r = iv.read(); + + for(int i=0;i<3;i++) { + if (i iv = value; + int s = iv.size(); + GLuint *gui = (GLuint*)data; + + DVector::Read r = iv.read(); + + for(int i=0;i<4;i++) { + if (i& value, uint8_t *data) { + + switch(type) { + case ShaderLanguage::TYPE_BOOL: { + + GLuint *gui = (GLuint*)data; + *gui = value[0].boolean ? GL_TRUE : GL_FALSE; + } break; + case ShaderLanguage::TYPE_BVEC2: { + + GLuint *gui = (GLuint*)data; + gui[0]=value[0].boolean ? GL_TRUE : GL_FALSE; + gui[1]=value[1].boolean ? GL_TRUE : GL_FALSE; + + } break; + case ShaderLanguage::TYPE_BVEC3: { + + GLuint *gui = (GLuint*)data; + gui[0]=value[0].boolean ? GL_TRUE : GL_FALSE; + gui[1]=value[1].boolean ? GL_TRUE : GL_FALSE; + gui[2]=value[2].boolean ? GL_TRUE : GL_FALSE; + + } break; + case ShaderLanguage::TYPE_BVEC4: { + + GLuint *gui = (GLuint*)data; + gui[0]=value[0].boolean ? GL_TRUE : GL_FALSE; + gui[1]=value[1].boolean ? GL_TRUE : GL_FALSE; + gui[2]=value[2].boolean ? GL_TRUE : GL_FALSE; + gui[3]=value[3].boolean ? GL_TRUE : GL_FALSE; + + } break; + case ShaderLanguage::TYPE_INT: { + + GLint *gui = (GLint*)data; + gui[0]=value[0].sint; + + } break; + case ShaderLanguage::TYPE_IVEC2: { + + GLint *gui = (GLint*)data; + + for(int i=0;i<2;i++) { + gui[i]=value[i].sint; + + } + + } break; + case ShaderLanguage::TYPE_IVEC3: { + + GLint *gui = (GLint*)data; + + for(int i=0;i<3;i++) { + gui[i]=value[i].sint; + + } + + } break; + case ShaderLanguage::TYPE_IVEC4: { + + GLint *gui = (GLint*)data; + + for(int i=0;i<4;i++) { + gui[i]=value[i].sint; + + } + + } break; + case ShaderLanguage::TYPE_UINT: { + + + GLuint *gui = (GLuint*)data; + gui[0]=value[0].uint; + + } break; + case ShaderLanguage::TYPE_UVEC2: { + + GLint *gui = (GLint*)data; + + for(int i=0;i<2;i++) { + gui[i]=value[i].uint; + } + } break; + case ShaderLanguage::TYPE_UVEC3: { + GLint *gui = (GLint*)data; + + for(int i=0;i<3;i++) { + gui[i]=value[i].uint; + } + + } break; + case ShaderLanguage::TYPE_UVEC4: { + GLint *gui = (GLint*)data; + + for(int i=0;i<4;i++) { + gui[i]=value[i].uint; + } + } break; + case ShaderLanguage::TYPE_FLOAT: { + + GLfloat *gui = (GLfloat*)data; + gui[0]=value[0].real; + + } break; + case ShaderLanguage::TYPE_VEC2: { + + GLfloat *gui = (GLfloat*)data; + + for(int i=0;i<2;i++) { + gui[i]=value[i].real; + } + + } break; + case ShaderLanguage::TYPE_VEC3: { + + GLfloat *gui = (GLfloat*)data; + + for(int i=0;i<3;i++) { + gui[i]=value[i].real; + } + + } break; + case ShaderLanguage::TYPE_VEC4: { + + GLfloat *gui = (GLfloat*)data; + + for(int i=0;i<4;i++) { + gui[i]=value[i].real; + } + } break; + case ShaderLanguage::TYPE_MAT2: { + GLfloat *gui = (GLfloat*)data; + + for(int i=0;i<2;i++) { + gui[i]=value[i].real; + } + } break; + case ShaderLanguage::TYPE_MAT3: { + + + + GLfloat *gui = (GLfloat*)data; + + gui[ 0]=value[0].real; + gui[ 1]=value[1].real; + gui[ 2]=value[2].real; + gui[ 3]=0; + gui[ 4]=value[3].real; + gui[ 5]=value[4].real; + gui[ 6]=value[5].real; + gui[ 7]=0; + gui[ 8]=value[6].real; + gui[ 9]=value[7].real; + gui[10]=value[8].real; + gui[11]=0; + } break; + case ShaderLanguage::TYPE_MAT4: { + + GLfloat *gui = (GLfloat*)data; + + for(int i=0;i<16;i++) { + gui[i]=value[i].real; + } + } break; + default: {} + } + +} + + +_FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type, uint8_t *data) { + + switch(type) { + + case ShaderLanguage::TYPE_BOOL: + case ShaderLanguage::TYPE_INT: + case ShaderLanguage::TYPE_UINT: + case ShaderLanguage::TYPE_FLOAT: { + zeromem(data,4); + } break; + case ShaderLanguage::TYPE_BVEC2: + case ShaderLanguage::TYPE_IVEC2: + case ShaderLanguage::TYPE_UVEC2: + case ShaderLanguage::TYPE_VEC2: { + zeromem(data,8); + } break; + case ShaderLanguage::TYPE_BVEC3: + case ShaderLanguage::TYPE_IVEC3: + case ShaderLanguage::TYPE_UVEC3: + case ShaderLanguage::TYPE_VEC3: + case ShaderLanguage::TYPE_BVEC4: + case ShaderLanguage::TYPE_IVEC4: + case ShaderLanguage::TYPE_UVEC4: + case ShaderLanguage::TYPE_VEC4: + case ShaderLanguage::TYPE_MAT2:{ + + zeromem(data,16); + } break; + case ShaderLanguage::TYPE_MAT3:{ + + zeromem(data,48); + } break; + case ShaderLanguage::TYPE_MAT4:{ + zeromem(data,64); + } break; + + default: {} + } + +} + +void RasterizerStorageGLES3::_update_material(Material* material) { + + if (material->dirty_list.in_list()) + _material_dirty_list.remove( &material->dirty_list ); + + //clear ubo if it needs to be cleared + if (material->ubo_size) { + + if (!material->shader || material->shader->ubo_size!=material->ubo_size) { + //by by ubo + glDeleteBuffers(1,&material->ubo_id); + material->ubo_id=0; + material->ubo_size=0; + } + } + + //create ubo if it needs to be created + if (material->ubo_size==0 && material->shader && material->shader->ubo_size) { + + glGenBuffers(1, &material->ubo_id); + glBindBuffer(GL_UNIFORM_BUFFER, material->ubo_id); + glBufferData(GL_UNIFORM_BUFFER, material->shader->ubo_size, NULL, GL_DYNAMIC_DRAW); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + material->ubo_size=material->shader->ubo_size; + } + + //fill up the UBO if it needs to be filled + if (material->shader && material->ubo_size) { + uint8_t* local_ubo = (uint8_t*)alloca(material->ubo_size); + + for(Map::Element *E=material->shader->uniforms.front();E;E=E->next()) { + + if (E->get().order<0) + continue; // texture, does not go here + + //regular uniform + uint8_t *data = &local_ubo[ material->shader->ubo_offsets[E->get().order] ]; + + Map::Element *V = material->params.find(E->key()); + + if (V) { + //user provided + _fill_std140_variant_ubo_value(E->get().type,V->get(),data); + } else if (E->get().default_value.size()){ + //default value + _fill_std140_ubo_value(E->get().type,E->get().default_value,data); + //value=E->get().default_value; + } else { + //zero because it was not provided + _fill_std140_ubo_empty(E->get().type,data); + } + + + } + + glBindBuffer(GL_UNIFORM_BUFFER,material->ubo_id); + glBufferSubData(GL_UNIFORM_BUFFER, 0, material->ubo_size, local_ubo); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + } + + //set up the texture array, for easy access when it needs to be drawn + if (material->shader && material->shader->texture_count) { + + material->textures.resize(material->shader->texture_count); + + for(Map::Element *E=material->shader->uniforms.front();E;E=E->next()) { + + if (E->get().texture_order<0) + continue; // not a texture, does not go here + + RID texture; + + Map::Element *V = material->params.find(E->key()); + if (V) { + texture=V->get(); + } + + if (!texture.is_valid()) { + Map::Element *W = material->shader->default_textures.find(E->key()); + if (W) { + texture=W->get(); + } + } + + material->textures[ E->get().texture_order ]=texture; + + + } + + + } else { + material->textures.clear(); + } + +} + +void RasterizerStorageGLES3::update_dirty_materials() { + + while( _material_dirty_list.first() ) { + + Material *material = _material_dirty_list.first()->self(); + + _update_material(material); + } +} + /* MESH API */ RID RasterizerStorageGLES3::mesh_create(){ @@ -1950,6 +2792,49 @@ bool RasterizerStorageGLES3::free(RID p_rid){ info.texture_mem-=texture->total_data_size; texture_owner.free(p_rid); memdelete(texture); + + } else if (shader_owner.owns(p_rid)) { + + // delete the texture + Shader *shader = shader_owner.get(p_rid); + + if (shader->shader) + shader->shader->free_custom_shader(shader->custom_code_id); + + if (shader->dirty_list.in_list()) + _shader_dirty_list.remove(&shader->dirty_list); + + while (shader->materials.first()) { + + Material *mat = shader->materials.first()->self(); + + mat->shader=NULL; + _material_make_dirty(mat); + + shader->materials.remove( shader->materials.first() ); + } + + //material_shader.free_custom_shader(shader->custom_code_id); + shader_owner.free(p_rid); + memdelete(shader); + + } else if (material_owner.owns(p_rid)) { + + // delete the texture + Material *material = material_owner.get(p_rid); + + if (material->shader) { + material->shader->materials.remove( & material->list ); + } + + if (material->ubo_id) { + glDeleteBuffers(1,&material->ubo_id); + } + + material_owner.free(p_rid); + memdelete(material); + + } else if (canvas_occluder_owner.owns(p_rid)) { diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index 9820fbc941..b7b3e607c6 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -2,16 +2,21 @@ #define RASTERIZERSTORAGEGLES3_H #include "servers/visual/rasterizer.h" +#include "servers/visual/shader_language.h" #include "shader_gles3.h" #include "shaders/copy.glsl.h" #include "shaders/canvas.glsl.h" +#include "self_list.h" +#include "shader_compiler_gles3.h" - +class RasterizerCanvasGLES3; class RasterizerStorageGLES3 : public RasterizerStorage { public: + RasterizerCanvasGLES3 *canvas; + enum FBOFormat { FBO_FORMAT_16_BITS, FBO_FORMAT_32_BITS, @@ -47,9 +52,13 @@ public: Set extensions; } config; - struct Shaders { + mutable struct Shaders { CopyShaderGLES3 copy; + + ShaderCompilerGLES3 compiler; + + ShaderCompilerGLES3::IdentifierActions actions_canvas; } shaders; struct Resources { @@ -169,11 +178,71 @@ public: /* SHADER API */ + struct Material; + struct Shader : public RID_Data { + RID self; + + VS::ShaderMode mode; + ShaderGLES3 *shader; + String code; + SelfList::List materials; + + + + Map uniforms; + Vector ubo_offsets; + uint32_t ubo_size; + + uint32_t texture_count; + + uint32_t custom_code_id; + uint32_t version; + + SelfList dirty_list; + + Map default_textures; + + bool valid; + + String path; + + struct CanvasItem { + + enum BlendMode { + BLEND_MODE_MIX, + BLEND_MODE_ADD, + BLEND_MODE_SUB, + BLEND_MODE_MUL, + BLEND_MODE_PMALPHA, + }; + + int blend_mode; + enum LightMode { + LIGHT_MODE_NORMAL, + LIGHT_MODE_UNSHADED, + LIGHT_MODE_LIGHT_ONLY + }; + + int light_mode; + + } canvas_item; + + Shader() : dirty_list(this) { + + shader=NULL; + valid=false; + custom_code_id=0; + version=1; + } }; + mutable SelfList::List _shader_dirty_list; + void _shader_make_dirty(Shader* p_shader); + + mutable RID_Owner shader_owner; virtual RID shader_create(VS::ShaderMode p_mode=VS::SHADER_SPATIAL); @@ -187,17 +256,48 @@ public: virtual void shader_set_default_texture_param(RID p_shader, const StringName& p_name, RID p_texture); virtual RID shader_get_default_texture_param(RID p_shader, const StringName& p_name) const; + void _update_shader(Shader* p_shader) const; + + void update_dirty_shaders(); /* COMMON MATERIAL API */ + struct Material : public RID_Data { + + Shader *shader; + GLuint ubo_id; + uint32_t ubo_size; + Map params; + SelfList list; + SelfList dirty_list; + Vector textures; + + Material() : list(this), dirty_list(this) { + shader=NULL; + ubo_id=0; + ubo_size=0; + } + + }; + + mutable SelfList::List _material_dirty_list; + void _material_make_dirty(Material *p_material) const; + + + mutable RID_Owner material_owner; + virtual RID material_create(); - virtual void material_set_shader(RID p_shader_material, RID p_shader); - virtual RID material_get_shader(RID p_shader_material) const; + virtual void material_set_shader(RID p_material, RID p_shader); + virtual RID material_get_shader(RID p_material) const; virtual void material_set_param(RID p_material, const StringName& p_param, const Variant& p_value); virtual Variant material_get_param(RID p_material, const StringName& p_param) const; + void _update_material(Material* material); + + void update_dirty_materials(); + /* MESH API */ virtual RID mesh_create(); @@ -432,6 +532,7 @@ public: bool clear_request; Color clear_request_color; int canvas_draw_commands; + float time[4]; } frame; void initialize(); diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp new file mode 100644 index 0000000000..49707400ca --- /dev/null +++ b/drivers/gles3/shader_compiler_gles3.cpp @@ -0,0 +1,528 @@ +#include "shader_compiler_gles3.h" +#include "os/os.h" + +#define SL ShaderLanguage + +static String _mktab(int p_level) { + + String tb; + for(int i=0;i& p_values) { + + switch(p_type) { + case SL::TYPE_BOOL: return p_values[0].boolean?"true":"false"; + case SL::TYPE_BVEC2: return String()+"bvec2("+(p_values[0].boolean?"true":"false")+(p_values[1].boolean?"true":"false")+")"; + case SL::TYPE_BVEC3: return String()+"bvec3("+(p_values[0].boolean?"true":"false")+","+(p_values[1].boolean?"true":"false")+","+(p_values[2].boolean?"true":"false")+")"; + case SL::TYPE_BVEC4: return String()+"bvec4("+(p_values[0].boolean?"true":"false")+","+(p_values[1].boolean?"true":"false")+","+(p_values[2].boolean?"true":"false")+","+(p_values[3].boolean?"true":"false")+")"; + case SL::TYPE_INT: return rtos(p_values[0].sint); + case SL::TYPE_IVEC2: return String()+"ivec2("+rtos(p_values[0].sint)+","+rtos(p_values[1].sint)+")"; + case SL::TYPE_IVEC3: return String()+"ivec3("+rtos(p_values[0].sint)+","+rtos(p_values[1].sint)+","+rtos(p_values[2].sint)+")"; + case SL::TYPE_IVEC4: return String()+"ivec4("+rtos(p_values[0].sint)+","+rtos(p_values[1].sint)+","+rtos(p_values[2].sint)+","+rtos(p_values[3].sint)+")"; + case SL::TYPE_UINT: return rtos(p_values[0].real); + case SL::TYPE_UVEC2: return String()+"uvec2("+rtos(p_values[0].real)+","+rtos(p_values[1].real)+")"; + case SL::TYPE_UVEC3: return String()+"uvec3("+rtos(p_values[0].real)+","+rtos(p_values[1].real)+","+rtos(p_values[2].real)+")"; + case SL::TYPE_UVEC4: return String()+"uvec4("+rtos(p_values[0].real)+","+rtos(p_values[1].real)+","+rtos(p_values[2].real)+","+rtos(p_values[3].real)+")"; + case SL::TYPE_FLOAT: return rtos(p_values[0].real); + case SL::TYPE_VEC2: return String()+"vec2("+rtos(p_values[0].real)+","+rtos(p_values[1].real)+")"; + case SL::TYPE_VEC3: return String()+"vec3("+rtos(p_values[0].real)+","+rtos(p_values[1].real)+","+rtos(p_values[2].real)+")"; + case SL::TYPE_VEC4: return String()+"vec4("+rtos(p_values[0].real)+","+rtos(p_values[1].real)+","+rtos(p_values[2].real)+","+rtos(p_values[3].real)+")"; + default: ERR_FAIL_V(String()); + } +} + +void ShaderCompilerGLES3::_dump_function_deps(SL::ShaderNode* p_node, const StringName& p_for_func, const Map& p_func_code, String& r_to_add, Set &added) { + + int fidx=-1; + + for(int i=0;ifunctions.size();i++) { + if (p_node->functions[i].name==p_for_func) { + fidx=i; + break; + } + } + + ERR_FAIL_COND(fidx==-1); + + for (Set::Element *E=p_node->functions[fidx].uses_function.front();E;E=E->next()) { + + if (added.has(E->get())) { + continue; //was added already + } + + _dump_function_deps(p_node,E->get(),p_func_code,r_to_add,added); + + SL::FunctionNode *fnode=NULL; + + for(int i=0;ifunctions.size();i++) { + if (p_node->functions[i].name==E->get()) { + fnode=p_node->functions[i].function; + break; + } + } + + ERR_FAIL_COND(!fnode); + + r_to_add+="\n"; + + String header; + header=_typestr(fnode->return_type)+" "+_mkid(fnode->name)+"("; + for(int i=0;iarguments.size();i++) { + + if (i>0) + header+=", "; + header+=_prestr(fnode->arguments[i].precision)+_typestr(fnode->arguments[i].type)+" "+_mkid(fnode->arguments[i].name); + } + + header+=")\n"; + r_to_add+=header; + r_to_add+=p_func_code[E->get()]; + + added.insert(E->get()); + } +} + +String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, GeneratedCode& r_gen_code, IdentifierActions &p_actions, const DefaultIdentifierActions &p_default_actions) { + + String code; + + switch(p_node->type) { + + case SL::Node::TYPE_SHADER: { + + SL::ShaderNode *pnode=(SL::ShaderNode*)p_node; + + for(int i=0;irender_modes.size();i++) { + + if (p_default_actions.render_mode_defines.has(pnode->render_modes[i]) && !used_rmode_defines.has(pnode->render_modes[i])) { + + r_gen_code.defines.push_back(p_default_actions.render_mode_defines[pnode->render_modes[i]].utf8()); + used_rmode_defines.insert(pnode->render_modes[i]); + } + + if (p_actions.render_mode_flags.has(pnode->render_modes[i])) { + *p_actions.render_mode_flags[pnode->render_modes[i]]=true; + } + + if (p_actions.render_mode_values.has(pnode->render_modes[i])) { + Pair &p = p_actions.render_mode_values[pnode->render_modes[i]]; + *p.first=p.second; + } + } + + + int max_texture_uniforms=0; + int max_uniforms=0; + + for(Map::Element *E=pnode->uniforms.front();E;E=E->next()) { + if (SL::is_sampler_type(E->get().type)) + max_texture_uniforms++; + else + max_uniforms++; + } + + r_gen_code.texture_uniforms.resize(max_texture_uniforms); + + Vector uniform_sizes; + uniform_sizes.resize(max_uniforms); + + for(Map::Element *E=pnode->uniforms.front();E;E=E->next()) { + + String ucode="uniform "; + ucode+=_prestr(E->get().precission); + ucode+=_typestr(E->get().type); + ucode+=" "+_mkid(E->key()); + ucode+=";\n"; + if (SL::is_sampler_type(E->get().type)) { + r_gen_code.vertex_global+=ucode; + r_gen_code.fragment_global+=ucode; + r_gen_code.texture_uniforms[E->get().texture_order]=_mkid(E->key()); + } else { + if (r_gen_code.uniforms.empty()) { + + r_gen_code.defines.push_back(String("#define USE_MATERIAL\n").ascii()); + } + r_gen_code.uniforms+=ucode; + uniform_sizes[E->get().order]=_get_datatype_size(E->get().type); + } + + p_actions.uniforms->insert(E->key(),E->get()); + + } + + // add up + for(int i=0;i0) + uniform_sizes[i]=uniform_sizes[i]+uniform_sizes[i-1]; + } + //offset + r_gen_code.uniform_offsets.resize(uniform_sizes.size()); + for(int i=0;i0) + r_gen_code.uniform_offsets[i]=uniform_sizes[i]-1; + else + r_gen_code.uniform_offsets[i]=0; + } + + if (uniform_sizes.size()) { + r_gen_code.uniform_total_size=uniform_sizes[ uniform_sizes.size() -1 ]; + } else { + r_gen_code.uniform_total_size=0; + } + + for(Map::Element *E=pnode->varyings.front();E;E=E->next()) { + + String vcode; + vcode+=_prestr(E->get().precission); + vcode+=_typestr(E->get().type); + vcode+=" "+String(E->key()); + vcode+=";\n"; + r_gen_code.vertex_global+="out "+vcode; + r_gen_code.fragment_global+="in "+vcode; + } + + Map function_code; + + //code for functions + for(int i=0;ifunctions.size();i++) { + SL::FunctionNode *fnode=pnode->functions[i].function; + function_code[fnode->name]=_dump_node_code(fnode->body,p_level+1,r_gen_code,p_actions,p_default_actions); + } + + //place functions in actual code + + Set added_vtx; + Set added_fragment; //share for light + + for(int i=0;ifunctions.size();i++) { + + SL::FunctionNode *fnode=pnode->functions[i].function; + + + if (fnode->name=="vertex") { + + _dump_function_deps(pnode,fnode->name,function_code,r_gen_code.vertex_global,added_vtx); + r_gen_code.vertex=function_code["vertex"]; + } + + if (fnode->name=="fragment") { + + _dump_function_deps(pnode,fnode->name,function_code,r_gen_code.fragment_global,added_fragment); + r_gen_code.fragment=function_code["fragment"]; + } + + if (fnode->name=="light") { + + _dump_function_deps(pnode,fnode->name,function_code,r_gen_code.fragment_global,added_fragment); + r_gen_code.light=function_code["light"]; + } + } + + //code+=dump_node_code(pnode->body,p_level); + } break; + case SL::Node::TYPE_FUNCTION: { + + } break; + case SL::Node::TYPE_BLOCK: { + SL::BlockNode *bnode=(SL::BlockNode*)p_node; + + //variables + code+=_mktab(p_level-1)+"{\n"; + for(Map::Element *E=bnode->variables.front();E;E=E->next()) { + + code+=_mktab(p_level)+_prestr(E->get().precision)+_typestr(E->get().type)+" "+_mkid(E->key())+";\n"; + } + + for(int i=0;istatements.size();i++) { + + String scode = _dump_node_code(bnode->statements[i],p_level,r_gen_code,p_actions,p_default_actions); + + if (bnode->statements[i]->type==SL::Node::TYPE_CONTROL_FLOW || bnode->statements[i]->type==SL::Node::TYPE_CONTROL_FLOW) { + code+=scode; //use directly + } else { + code+=_mktab(p_level)+scode+";\n"; + } + } + code+=_mktab(p_level-1)+"}\n"; + + + } break; + case SL::Node::TYPE_VARIABLE: { + SL::VariableNode *vnode=(SL::VariableNode*)p_node; + + if (p_default_actions.usage_defines.has(vnode->name) && !used_name_defines.has(vnode->name)) { + r_gen_code.defines.push_back(p_default_actions.usage_defines[vnode->name].utf8()); + used_name_defines.insert(vnode->name); + } + + if (p_actions.usage_flag_pointers.has(vnode->name) && !used_name_defines.has(vnode->name)) { + *p_actions.usage_flag_pointers[vnode->name]=true; + used_name_defines.insert(vnode->name); + } + + if (p_default_actions.renames.has(vnode->name)) + code=p_default_actions.renames[vnode->name]; + else + code=_mkid(vnode->name); + + + } break; + case SL::Node::TYPE_CONSTANT: { + SL::ConstantNode *cnode=(SL::ConstantNode*)p_node; + return get_constant_text(cnode->datatype,cnode->values); + + } break; + case SL::Node::TYPE_OPERATOR: { + SL::OperatorNode *onode=(SL::OperatorNode*)p_node; + + + switch(onode->op) { + + case SL::OP_ASSIGN: + case SL::OP_ASSIGN_ADD: + case SL::OP_ASSIGN_SUB: + case SL::OP_ASSIGN_MUL: + case SL::OP_ASSIGN_DIV: + case SL::OP_ASSIGN_SHIFT_LEFT: + case SL::OP_ASSIGN_SHIFT_RIGHT: + case SL::OP_ASSIGN_MOD: + case SL::OP_ASSIGN_BIT_AND: + case SL::OP_ASSIGN_BIT_OR: + case SL::OP_ASSIGN_BIT_XOR: + code=_dump_node_code(onode->arguments[0],p_level,r_gen_code,p_actions,p_default_actions)+_opstr(onode->op)+_dump_node_code(onode->arguments[1],p_level,r_gen_code,p_actions,p_default_actions); + break; + case SL::OP_BIT_INVERT: + case SL::OP_NEGATE: + case SL::OP_NOT: + case SL::OP_DECREMENT: + case SL::OP_INCREMENT: + code=_opstr(onode->op)+_dump_node_code(onode->arguments[0],p_level,r_gen_code,p_actions,p_default_actions); + break; + case SL::OP_POST_DECREMENT: + case SL::OP_POST_INCREMENT: + code=_dump_node_code(onode->arguments[0],p_level,r_gen_code,p_actions,p_default_actions)+_opstr(onode->op); + break; + case SL::OP_CALL: + case SL::OP_CONSTRUCT: { + + ERR_FAIL_COND_V(onode->arguments[0]->type!=SL::Node::TYPE_VARIABLE,String()); + + SL::VariableNode *vnode=(SL::VariableNode*)onode->arguments[0]; + + if (onode->op==SL::OP_CONSTRUCT) { + code+=String(vnode->name); + } else { + + if (internal_functions.has(vnode->name)) { + code+=vnode->name; + } else if (p_default_actions.renames.has(vnode->name)) { + code+=p_default_actions.renames[vnode->name]; + } else { + code+=_mkid(vnode->name); + } + } + + code+="("; + + for(int i=1;iarguments.size();i++) { + if (i>1) + code+=", "; + code+=_dump_node_code(onode->arguments[i],p_level,r_gen_code,p_actions,p_default_actions); + } + code+=")"; + } break; + default: { + + code="("+_dump_node_code(onode->arguments[0],p_level,r_gen_code,p_actions,p_default_actions)+_opstr(onode->op)+_dump_node_code(onode->arguments[1],p_level,r_gen_code,p_actions,p_default_actions)+")"; + break; + + } + } + + } break; + case SL::Node::TYPE_CONTROL_FLOW: { + SL::ControlFlowNode *cfnode=(SL::ControlFlowNode*)p_node; + if (cfnode->flow_op==SL::FLOW_OP_IF) { + + code+=_mktab(p_level)+"if ("+_dump_node_code(cfnode->expressions[0],p_level,r_gen_code,p_actions,p_default_actions)+")\n"; + code+=_dump_node_code(cfnode->blocks[0],p_level+1,r_gen_code,p_actions,p_default_actions); + if (cfnode->blocks.size()==2) { + + code+=_mktab(p_level)+"else\n"; + code+=_dump_node_code(cfnode->blocks[1],p_level+1,r_gen_code,p_actions,p_default_actions); + } + + + } else if (cfnode->flow_op==SL::FLOW_OP_RETURN) { + + if (cfnode->blocks.size()) { + code="return "+_dump_node_code(cfnode->blocks[0],p_level,r_gen_code,p_actions,p_default_actions); + } else { + code="return"; + } + } + + } break; + case SL::Node::TYPE_MEMBER: { + SL::MemberNode *mnode=(SL::MemberNode*)p_node; + code=_dump_node_code(mnode->owner,p_level,r_gen_code,p_actions,p_default_actions)+"."+mnode->name; + + } break; + } + + return code; + +} + + +Error ShaderCompilerGLES3::compile(VS::ShaderMode p_mode, const String& p_code, IdentifierActions* p_actions, const String &p_path,GeneratedCode& r_gen_code) { + + + + Error err = parser.compile(p_code,ShaderTypes::get_singleton()->get_functions(p_mode),ShaderTypes::get_singleton()->get_modes(p_mode)); + + if (err!=OK) { + _err_print_error(NULL,p_path.utf8().get_data(),parser.get_error_line(),parser.get_error_text().utf8().get_data(),ERR_HANDLER_SHADER); + return err; + } + + r_gen_code.defines.clear(); + r_gen_code.vertex=String(); + r_gen_code.vertex_global=String(); + r_gen_code.fragment=String(); + r_gen_code.fragment_global=String(); + r_gen_code.light=String(); + + + + used_name_defines.clear(); + used_rmode_defines.clear(); + + _dump_node_code(parser.get_shader(),1,r_gen_code,*p_actions,actions[p_mode]); + + return OK; + +} + + +ShaderCompilerGLES3::ShaderCompilerGLES3() { + + /** CANVAS ITEM SHADER **/ + + actions[VS::SHADER_CANVAS_ITEM].renames["SRC_VERTEX"]="vertex"; + actions[VS::SHADER_CANVAS_ITEM].renames["VERTEX"]="outvec.xy"; + actions[VS::SHADER_CANVAS_ITEM].renames["VERTEX_COLOR"]="vertex_color"; + actions[VS::SHADER_CANVAS_ITEM].renames["UV"]="uv_interp"; + actions[VS::SHADER_CANVAS_ITEM].renames["POINT_SIZE"]="gl_PointSize"; + + actions[VS::SHADER_CANVAS_ITEM].renames["WORLD_MATRIX"]="modelview_matrix"; + actions[VS::SHADER_CANVAS_ITEM].renames["PROJECTION_MATRIX"]="projection_matrix"; + actions[VS::SHADER_CANVAS_ITEM].renames["EXTRA_MATRIX"]=="extra_matrix"; + actions[VS::SHADER_CANVAS_ITEM].renames["TIME"]="time"; + + actions[VS::SHADER_CANVAS_ITEM].renames["COLOR"]="color"; + actions[VS::SHADER_CANVAS_ITEM].renames["NORMAL"]="normal"; + actions[VS::SHADER_CANVAS_ITEM].renames["NORMALMAP"]="normal_map"; + actions[VS::SHADER_CANVAS_ITEM].renames["NORMALMAP_DEPTH"]="normal_depth"; + actions[VS::SHADER_CANVAS_ITEM].renames["UV"]="uv_interp"; + actions[VS::SHADER_CANVAS_ITEM].renames["COLOR"]="color"; + actions[VS::SHADER_CANVAS_ITEM].renames["TEXTURE"]="color_texture"; + actions[VS::SHADER_CANVAS_ITEM].renames["TEXTURE_PIXEL_SIZE"]="color_texpixel_size"; + actions[VS::SHADER_CANVAS_ITEM].renames["SCREEN_UV"]="screen_uv"; + actions[VS::SHADER_CANVAS_ITEM].renames["SCREEN_TEXTURE"]="screen_texture"; + actions[VS::SHADER_CANVAS_ITEM].renames["POINT_COORD"]="gl_PointCoord"; + + actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_VEC"]="light_vec"; + actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_HEIGHT"]="light_height"; + actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_COLOR"]="light_color"; + actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_UV"]="light_uv"; + //actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_SHADOW_COLOR"]="light_shadow_color"; + actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT"]="light"; + actions[VS::SHADER_CANVAS_ITEM].renames["SHADOW_COLOR"]="shadow_color"; + + 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"; + actions[VS::SHADER_CANVAS_ITEM].usage_defines["SCREEN_UV"]="#define SCREEN_UV_USED\n"; + 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["SHADOW_COLOR"]="#define SHADOW_COLOR_USED\n"; + + actions[VS::SHADER_CANVAS_ITEM].render_mode_defines["skip_transform"]="#define SKIP_TRANSFORM_USED\n"; + + List func_list; + + ShaderLanguage::get_builtin_funcs(&func_list); + + for (List::Element *E=func_list.front();E;E=E->next()) { + internal_functions.insert(E->get()); + } +} diff --git a/drivers/gles3/shader_compiler_gles3.h b/drivers/gles3/shader_compiler_gles3.h new file mode 100644 index 0000000000..ad51b99927 --- /dev/null +++ b/drivers/gles3/shader_compiler_gles3.h @@ -0,0 +1,67 @@ +#ifndef SHADERCOMPILERGLES3_H +#define SHADERCOMPILERGLES3_H + +#include "servers/visual/shader_language.h" +#include "servers/visual/shader_types.h" +#include "servers/visual_server.h" +#include "pair.h" + +class ShaderCompilerGLES3 { +public: + struct IdentifierActions { + + Map > render_mode_values; + Map render_mode_flags; + Map usage_flag_pointers; + + Map *uniforms; + }; + + struct GeneratedCode { + + Vector defines; + Vector texture_uniforms; + Vector uniform_offsets; + uint32_t uniform_total_size; + String uniforms; + String vertex_global; + String vertex; + String fragment_global; + String fragment; + String light; + + }; + +private: + + ShaderLanguage parser; + + struct DefaultIdentifierActions { + + Map renames; + Map render_mode_defines; + Map usage_defines; + }; + + void _dump_function_deps(ShaderLanguage::ShaderNode *p_node, const StringName& p_for_func, const Map &p_func_code, String& r_to_add,Set &added); + String _dump_node_code(ShaderLanguage::Node *p_node, int p_level, GeneratedCode &r_gen_code, IdentifierActions& p_actions, const DefaultIdentifierActions& p_default_actions); + + + + Set used_name_defines; + Set used_rmode_defines; + Set internal_functions; + + + DefaultIdentifierActions actions[VS::SHADER_MAX]; + +public: + + + Error compile(VS::ShaderMode p_mode, const String& p_code, IdentifierActions* p_actions, const String& p_path, GeneratedCode& r_gen_code); + + + ShaderCompilerGLES3(); +}; + +#endif // SHADERCOMPILERGLES3_H diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp index f8c0234943..35191fecf7 100644 --- a/drivers/gles3/shader_gles3.cpp +++ b/drivers/gles3/shader_gles3.cpp @@ -214,6 +214,8 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() { } + + v.ok=false; /* SETUP CONDITIONALS */ @@ -245,6 +247,7 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() { CharString code_string; CharString code_string2; CharString code_globals; + CharString material_string; //print_line("code version? "+itos(conditional_version.code_version)); @@ -258,6 +261,7 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() { cc=&custom_code_map[conditional_version.code_version]; v.code_version=cc->version; define_line_ofs+=2; + } @@ -273,7 +277,7 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() { if (cc) { for(int i=0;icustom_defines.size();i++) { - strings.push_back(cc->custom_defines[i]); + strings.push_back(cc->custom_defines[i].get_data()); DEBUG_PRINT("CD #"+itos(i)+": "+String(cc->custom_defines[i])); } } @@ -305,14 +309,22 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() { code_globals=cc->vertex_globals.ascii(); strings.push_back(code_globals.get_data()); } + strings.push_back(vertex_code1.get_data()); + if (cc) { + material_string=cc->uniforms.ascii(); + strings.push_back(material_string.get_data()); + } + + strings.push_back(vertex_code2.get_data()); + if (cc) { code_string=cc->vertex.ascii(); strings.push_back(code_string.get_data()); } - strings.push_back(vertex_code2.get_data()); + strings.push_back(vertex_code3.get_data()); #ifdef DEBUG_SHADER DEBUG_PRINT("\nVertex Code:\n\n"+String(code_string.get_data())); @@ -367,7 +379,8 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() { ERR_FAIL_V(NULL); } - + + /* FRAGMENT SHADER */ strings.resize(strings_base_size); @@ -396,21 +409,29 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() { code_globals=cc->fragment_globals.ascii(); strings.push_back(code_globals.get_data()); } + strings.push_back(fragment_code1.get_data()); + if (cc) { + material_string=cc->uniforms.ascii(); + strings.push_back(material_string.get_data()); + } + + strings.push_back(fragment_code2.get_data()); + if (cc) { code_string=cc->fragment.ascii(); strings.push_back(code_string.get_data()); } - strings.push_back(fragment_code2.get_data()); + strings.push_back(fragment_code3.get_data()); if (cc) { code_string2=cc->light.ascii(); strings.push_back(code_string2.get_data()); } - strings.push_back(fragment_code3.get_data()); + strings.push_back(fragment_code4.get_data()); #ifdef DEBUG_SHADER DEBUG_PRINT("\nFragment Code:\n\n"+String(code_string.get_data())); @@ -463,7 +484,7 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() { ERR_FAIL_V( NULL ); } - + glAttachShader(v.id,v.frag_id); glAttachShader(v.id,v.vert_id); @@ -552,10 +573,11 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() { if ( cc ) { - v.custom_uniform_locations.resize(cc->custom_uniforms.size()); - for(int i=0;icustom_uniforms.size();i++) { + v.texture_uniform_locations.resize(cc->texture_uniforms.size()); + for(int i=0;itexture_uniforms.size();i++) { - v.custom_uniform_locations[i]=glGetUniformLocation(v.id,String(cc->custom_uniforms[i]).ascii().get_data()); + v.texture_uniform_locations[i]=glGetUniformLocation(v.id,String(cc->texture_uniforms[i]).ascii().get_data()); + glUniform1i(v.texture_uniform_locations[i],i+base_material_tex_index); } } @@ -597,6 +619,7 @@ void ShaderGLES3::setup(const char** p_conditional_defines, int p_conditional_co //split vertex and shader code (thank you, retarded shader compiler programmers from you know what company). { String globals_tag="\nVERTEX_SHADER_GLOBALS"; + String material_tag="\nMATERIAL_UNIFORMS"; String code_tag="\nVERTEX_SHADER_CODE"; String code = vertex_code; int cpos = code.find(globals_tag); @@ -606,20 +629,31 @@ void ShaderGLES3::setup(const char** p_conditional_defines, int p_conditional_co vertex_code0=code.substr(0,cpos).ascii(); code = code.substr(cpos+globals_tag.length(),code.length()); - cpos = code.find(code_tag); + cpos = code.find(material_tag); if (cpos==-1) { vertex_code1=code.ascii(); } else { vertex_code1=code.substr(0,cpos).ascii(); - vertex_code2=code.substr(cpos+code_tag.length(),code.length()).ascii(); + String code2 = code.substr(cpos+material_tag.length(),code.length()); + + cpos = code2.find(code_tag); + if (cpos==-1) { + vertex_code2=code2.ascii(); + } else { + + vertex_code2=code2.substr(0,cpos).ascii(); + vertex_code3 = code2.substr(cpos+code_tag.length(),code2.length()).ascii(); + } + } } } { String globals_tag="\nFRAGMENT_SHADER_GLOBALS"; + String material_tag="\nMATERIAL_UNIFORMS"; String code_tag="\nFRAGMENT_SHADER_CODE"; String light_code_tag="\nLIGHT_SHADER_CODE"; String code = fragment_code; @@ -630,22 +664,31 @@ void ShaderGLES3::setup(const char** p_conditional_defines, int p_conditional_co fragment_code0=code.substr(0,cpos).ascii(); code = code.substr(cpos+globals_tag.length(),code.length()); - cpos = code.find(code_tag); + cpos = code.find(material_tag); if (cpos==-1) { fragment_code1=code.ascii(); } else { fragment_code1=code.substr(0,cpos).ascii(); - String code2 = code.substr(cpos+code_tag.length(),code.length()); + String code2 = code.substr(cpos+material_tag.length(),code.length()); - cpos = code2.find(light_code_tag); + cpos = code2.find(code_tag); if (cpos==-1) { fragment_code2=code2.ascii(); } else { fragment_code2=code2.substr(0,cpos).ascii(); - fragment_code3 = code2.substr(cpos+light_code_tag.length(),code2.length()).ascii(); + String code3 = code2.substr(cpos+code_tag.length(),code2.length()); + + cpos = code3.find(light_code_tag); + if (cpos==-1) { + fragment_code3=code3.ascii(); + } else { + + fragment_code3=code3.substr(0,cpos).ascii(); + fragment_code4 = code3.substr(cpos+light_code_tag.length(),code3.length()).ascii(); + } } } } @@ -697,7 +740,7 @@ uint32_t ShaderGLES3::create_custom_shader() { return last_custom_code++; } -void ShaderGLES3::set_custom_shader_code(uint32_t p_code_id, const String& p_vertex, const String& p_vertex_globals,const String& p_fragment,const String& p_light, const String& p_fragment_globals,const Vector& p_uniforms,const Vector &p_custom_defines) { +void ShaderGLES3::set_custom_shader_code(uint32_t p_code_id, const String& p_vertex, const String& p_vertex_globals, const String& p_fragment, const String& p_light, const String& p_fragment_globals, const String &p_uniforms, const Vector &p_texture_uniforms, const Vector &p_custom_defines) { ERR_FAIL_COND(!custom_code_map.has(p_code_id)); CustomCode *cc=&custom_code_map[p_code_id]; @@ -707,7 +750,8 @@ void ShaderGLES3::set_custom_shader_code(uint32_t p_code_id, const String& p_ver cc->fragment=p_fragment; cc->fragment_globals=p_fragment_globals; cc->light=p_light; - cc->custom_uniforms=p_uniforms; + cc->texture_uniforms=p_texture_uniforms; + cc->uniforms=p_uniforms; cc->custom_defines=p_custom_defines; cc->version++; } @@ -734,13 +778,16 @@ void ShaderGLES3::free_custom_shader(uint32_t p_code_id) { } +void ShaderGLES3::set_base_material_tex_index(int p_idx) { + base_material_tex_index=p_idx; +} ShaderGLES3::ShaderGLES3() { version=NULL; last_custom_code=1; uniforms_dirty = true; - + base_material_tex_index=0; glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS,&max_image_units); } diff --git a/drivers/gles3/shader_gles3.h b/drivers/gles3/shader_gles3.h index 7aaf65d450..176a2282fd 100644 --- a/drivers/gles3/shader_gles3.h +++ b/drivers/gles3/shader_gles3.h @@ -105,9 +105,10 @@ private: String fragment; String fragment_globals; String light; + String uniforms; uint32_t version; - Vector custom_uniforms; - Vector custom_defines; + Vector texture_uniforms; + Vector custom_defines; }; @@ -118,7 +119,7 @@ private: GLuint vert_id; GLuint frag_id; GLint *uniform_location; - Vector custom_uniform_locations; + Vector texture_uniform_locations; uint32_t code_version; bool ok; Version() { code_version=0; ok=false; uniform_location=NULL; } @@ -166,10 +167,14 @@ private: CharString fragment_code1; CharString fragment_code2; CharString fragment_code3; + CharString fragment_code4; CharString vertex_code0; CharString vertex_code1; CharString vertex_code2; + CharString vertex_code3; + + int base_material_tex_index; Version * get_current_version(); @@ -308,7 +313,7 @@ public: void clear_caches(); uint32_t create_custom_shader(); - void set_custom_shader_code(uint32_t p_id,const String& p_vertex, const String& p_vertex_globals,const String& p_fragment,const String& p_p_light,const String& p_fragment_globals,const Vector& p_uniforms,const Vector &p_custom_defines); + void set_custom_shader_code(uint32_t p_id,const String& p_vertex, const String& p_vertex_globals,const String& p_fragment,const String& p_p_light,const String& p_fragment_globals,const String& p_uniforms,const Vector& p_texture_uniforms,const Vector &p_custom_defines); void set_custom_shader(uint32_t p_id); void free_custom_shader(uint32_t p_id); @@ -332,23 +337,25 @@ public: uniforms_dirty = true; }; - _FORCE_INLINE_ void set_custom_uniform(int p_idx, const Variant& p_value) { + _FORCE_INLINE_ void set_texture_uniform(int p_idx, const Variant& p_value) { ERR_FAIL_COND(!version); - ERR_FAIL_INDEX(p_idx,version->custom_uniform_locations.size()); - _set_uniform_variant( version->custom_uniform_locations[p_idx], p_value ); + ERR_FAIL_INDEX(p_idx,version->texture_uniform_locations.size()); + _set_uniform_variant( version->texture_uniform_locations[p_idx], p_value ); } - _FORCE_INLINE_ GLint get_custom_uniform_location(int p_idx) { + _FORCE_INLINE_ GLint get_texture_uniform_location(int p_idx) { ERR_FAIL_COND_V(!version,-1); - ERR_FAIL_INDEX_V(p_idx,version->custom_uniform_locations.size(),-1); - return version->custom_uniform_locations[p_idx]; + ERR_FAIL_INDEX_V(p_idx,version->texture_uniform_locations.size(),-1); + return version->texture_uniform_locations[p_idx]; } virtual void init()=0; void finish(); + void set_base_material_tex_index(int p_idx); + virtual ~ShaderGLES3(); }; diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl index eed2239ec9..cf2e0f776f 100644 --- a/drivers/gles3/shaders/canvas.glsl +++ b/drivers/gles3/shaders/canvas.glsl @@ -1,7 +1,7 @@ [vertex] -layout(location=0) in highp vec3 vertex; +layout(location=0) in highp vec2 vertex; layout(location=3) in vec4 color_attrib; #ifdef USE_TEXTURE_RECT @@ -20,6 +20,7 @@ layout(location=4) in highp vec2 uv_attrib; layout(std140) uniform CanvasItemData { //ubo:0 highp mat4 projection_matrix; + highp vec4 time; }; uniform highp mat4 modelview_matrix; @@ -29,10 +30,6 @@ uniform highp mat4 extra_matrix; out mediump vec2 uv_interp; out mediump vec4 color_interp; -#if defined(USE_TIME) -uniform float time; -#endif - #ifdef USE_LIGHTING layout(std140) uniform LightData { //ubo:1 @@ -51,6 +48,7 @@ layout(std140) uniform LightData { //ubo:1 highp float shadow_distance_mult; }; + out vec4 light_uv_interp; #if defined(NORMAL_USED) @@ -66,20 +64,30 @@ out highp vec2 pos; VERTEX_SHADER_GLOBALS +#if defined(USE_MATERIAL) + +layout(std140) uniform UniformData { //ubo:2 + +MATERIAL_UNIFORMS + +}; + +#endif + void main() { - color_interp = color_attrib; + vec4 vertex_color = color_attrib; #ifdef USE_TEXTURE_RECT - uv_interp = src_rect.xy + abs(src_rect.zw) * vertex.xy; - highp vec4 outvec = vec4(dst_rect.xy + dst_rect.zw * mix(vertex.xy,vec2(1.0,1.0)-vertex.xy,lessThan(src_rect.zw,vec2(0.0,0.0))),0.0,1.0); + uv_interp = src_rect.xy + abs(src_rect.zw) * vertex; + highp vec4 outvec = vec4(dst_rect.xy + dst_rect.zw * mix(vertex,vec2(1.0,1.0)-vertex,lessThan(src_rect.zw,vec2(0.0,0.0))),0.0,1.0); #else uv_interp = uv_attrib; - highp vec4 outvec = vec4(vertex, 1.0); + highp vec4 outvec = vec4(vertex,0.0,1.0); #endif @@ -90,16 +98,16 @@ VERTEX_SHADER_CODE } -#if !defined(USE_WORLD_VEC) +#if !defined(SKIP_TRANSFORM_USED) outvec = extra_matrix * outvec; outvec = modelview_matrix * outvec; #endif - + color_interp = vertex_color; #ifdef USE_PIXEL_SNAP - outvec.xy=floor(outvec.xy+0.5); + outvec.xy=floor(outvec+0.5); #endif @@ -132,20 +140,24 @@ VERTEX_SHADER_CODE uniform mediump sampler2D color_texture; // texunit:0 +uniform highp vec2 color_texpixel_size; in mediump vec2 uv_interp; in mediump vec4 color_interp; -#if defined(ENABLE_TEXSCREEN) +#if defined(SCREEN_TEXTURE_USED) -uniform sampler2D texscreen_tex; // texunit:-3 +uniform sampler2D screen_texture; // texunit:-3 #endif -#if defined(USE_TIME) -uniform float time; -#endif +layout(std140) uniform CanvasItemData { + + highp mat4 projection_matrix; + highp vec4 time; +}; + #ifdef USE_LIGHTING @@ -188,6 +200,17 @@ FRAGMENT_SHADER_GLOBALS layout(location=0) out mediump vec4 frag_color; + +#if defined(USE_MATERIAL) + +layout(std140) uniform UniformData { + +MATERIAL_UNIFORMS + +}; + +#endif + void main() { vec4 color = color_interp; @@ -195,6 +218,9 @@ void main() { vec3 normal = vec3(0.0,0.0,1.0); #endif +#if !defined(COLOR_USED) +//default behavior, texture by color + #ifdef USE_DISTANCE_FIELD const float smoothing = 1.0/32.0; float distance = texture(color_texture, uv_interp).a; @@ -204,6 +230,7 @@ void main() { #endif +#endif #if defined(ENABLE_SCREEN_UV) vec2 screen_uv = gl_FragCoord.xy*screen_uv_mult; @@ -211,14 +238,15 @@ void main() { { -#if defined(USE_NORMALMAP) - vec3 normal_map=vec3(0.0,0.0,1.0); float normal_depth=1.0; + +#if defined(NORMALMAP_USED) + vec3 normal_map=vec3(0.0,0.0,1.0); #endif FRAGMENT_SHADER_CODE -#if defined(USE_NORMALMAP) +#if defined(NORMALMAP_USED) normal = mix(vec3(0.0,0.0,1.0), normal_map * vec3(2.0,-2.0,1.0) - vec3( 1.0, -1.0, 0.0 ), normal_depth ); #endif @@ -246,7 +274,7 @@ FRAGMENT_SHADER_CODE vec2 light_uv = light_uv_interp.xy; vec4 light = texture(light_texture,light_uv) * light_color; -#if defined(USE_OUTPUT_SHADOW_COLOR) +#if defined(SHADOW_COLOR_USED) vec4 shadow_color=vec4(0.0,0.0,0.0,0.0); #endif @@ -409,7 +437,7 @@ LIGHT_SHADER_CODE #endif -#if defined(USE_OUTPUT_SHADOW_COLOR) +#if defined(SHADOW_COLOR_USED) color=mix(shadow_color,color,shadow_attenuation); #else //color*=shadow_attenuation; -- cgit v1.2.3 From 4428115916144b45c4697cd65d9c8c093631bec6 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Wed, 19 Oct 2016 11:14:41 -0300 Subject: Everything returning to normal in 3D, still a long way to go -implemented the scene part of visual server and rasterizer, objects without lighting and material are rendererd only --- drivers/gles3/rasterizer_canvas_gles3.cpp | 1 + drivers/gles3/rasterizer_gles3.cpp | 9 +- drivers/gles3/rasterizer_gles3.h | 3 + drivers/gles3/rasterizer_scene_gles3.cpp | 808 +++++++++++++++++++++++++++++ drivers/gles3/rasterizer_scene_gles3.h | 178 +++++++ drivers/gles3/rasterizer_storage_gles3.cpp | 720 ++++++++++++++++++++++++- drivers/gles3/rasterizer_storage_gles3.h | 200 ++++++- drivers/gles3/shader_gles3.cpp | 12 +- drivers/gles3/shaders/SCsub | 1 + drivers/gles3/shaders/scene.glsl | 351 +++++++++++++ 10 files changed, 2258 insertions(+), 25 deletions(-) create mode 100644 drivers/gles3/rasterizer_scene_gles3.cpp create mode 100644 drivers/gles3/rasterizer_scene_gles3.h create mode 100644 drivers/gles3/shaders/scene.glsl (limited to 'drivers/gles3') diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index b2228a6cfa..237b3ec3fc 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -117,6 +117,7 @@ void RasterizerCanvasGLES3::canvas_begin(){ 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 ); glClear(GL_COLOR_BUFFER_BIT); storage->frame.clear_request=false; + print_line("canvas clear?"); } diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index eaa9825605..83c40edc1d 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -15,7 +15,7 @@ RasterizerCanvas *RasterizerGLES3::get_canvas() { RasterizerScene *RasterizerGLES3::get_scene() { - return NULL; + return scene; } @@ -111,6 +111,7 @@ void RasterizerGLES3::initialize() { */ storage->initialize(); canvas->initialize(); + scene->initialize(); } void RasterizerGLES3::begin_frame(){ @@ -124,6 +125,7 @@ void RasterizerGLES3::begin_frame(){ storage->update_dirty_shaders(); storage->update_dirty_materials(); + } void RasterizerGLES3::set_current_render_target(RID p_render_target){ @@ -131,6 +133,7 @@ void RasterizerGLES3::set_current_render_target(RID p_render_target){ if (!p_render_target.is_valid() && storage->frame.current_rt && storage->frame.clear_request) { //handle pending clear request, if the framebuffer was not cleared glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->front.fbo); + print_line("unbind clear of: "+storage->frame.clear_request_color); glClearColor( storage->frame.clear_request_color.r, storage->frame.clear_request_color.g, @@ -265,8 +268,12 @@ RasterizerGLES3::RasterizerGLES3() storage = memnew( RasterizerStorageGLES3 ); canvas = memnew( RasterizerCanvasGLES3 ); + scene = memnew( RasterizerSceneGLES3 ); canvas->storage=storage; storage->canvas=canvas; + scene->storage=storage; + storage->scene=scene; + } diff --git a/drivers/gles3/rasterizer_gles3.h b/drivers/gles3/rasterizer_gles3.h index d461664ea2..f70dac506d 100644 --- a/drivers/gles3/rasterizer_gles3.h +++ b/drivers/gles3/rasterizer_gles3.h @@ -4,6 +4,7 @@ #include "servers/visual/rasterizer.h" #include "rasterizer_storage_gles3.h" #include "rasterizer_canvas_gles3.h" +#include "rasterizer_scene_gles3.h" class RasterizerGLES3 : public Rasterizer { @@ -12,6 +13,8 @@ class RasterizerGLES3 : public Rasterizer { RasterizerStorageGLES3 *storage; RasterizerCanvasGLES3 *canvas; + RasterizerSceneGLES3 *scene; + public: virtual RasterizerStorage *get_storage(); diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp new file mode 100644 index 0000000000..121620594d --- /dev/null +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -0,0 +1,808 @@ +#include "rasterizer_scene_gles3.h" +#include "globals.h" +static _FORCE_INLINE_ void store_matrix32(const Matrix32& 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]; + p_array[ 2]=p_mtx.basis.elements[2][0]; + p_array[ 3]=0; + p_array[ 4]=p_mtx.basis.elements[0][1]; + p_array[ 5]=p_mtx.basis.elements[1][1]; + p_array[ 6]=p_mtx.basis.elements[2][1]; + p_array[ 7]=0; + p_array[ 8]=p_mtx.basis.elements[0][2]; + p_array[ 9]=p_mtx.basis.elements[1][2]; + p_array[10]=p_mtx.basis.elements[2][2]; + p_array[11]=0; + p_array[12]=p_mtx.origin.x; + p_array[13]=p_mtx.origin.y; + p_array[14]=p_mtx.origin.z; + p_array[15]=1; +} + +static _FORCE_INLINE_ void store_camera(const CameraMatrix& p_mtx, float* p_array) { + + for (int i=0;i<4;i++) { + for (int j=0;j<4;j++) { + + p_array[i*4+j]=p_mtx.matrix[i][j]; + } + } +} + + + +RID RasterizerSceneGLES3::light_instance_create(RID p_light) { + + + return RID(); +} + +void RasterizerSceneGLES3::light_instance_set_transform(RID p_light_instance,const Transform& p_transform){ + + +} + + +bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material* p_material,bool p_alpha_pass) { + + if (p_material->shader->spatial.cull_mode==RasterizerStorageGLES3::Shader::Spatial::CULL_MODE_DISABLED) { + glDisable(GL_CULL_FACE); + } else { + glEnable(GL_CULL_FACE); + } + + //glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); + + /* + if (p_material->flags[VS::MATERIAL_FLAG_WIREFRAME]) + glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); + else + glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); + */ + + //if (p_material->line_width) + // glLineWidth(p_material->line_width); + + + //blend mode + if (state.current_blend_mode!=p_material->shader->spatial.blend_mode) { + + switch(p_material->shader->spatial.blend_mode) { + + case RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_MIX: { + glBlendEquation(GL_FUNC_ADD); + if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } else { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + + } break; + case RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_ADD: { + + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(p_alpha_pass?GL_SRC_ALPHA:GL_ONE,GL_ONE); + + } break; + case RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_SUB: { + + glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); + glBlendFunc(GL_SRC_ALPHA,GL_ONE); + } break; + case RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_MUL: { + glBlendEquation(GL_FUNC_ADD); + if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } else { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + + } break; + } + + state.current_blend_mode=p_material->shader->spatial.blend_mode; + + } + + //material parameters + + state.scene_shader.set_custom_shader(p_material->shader->custom_code_id); + bool rebind = state.scene_shader.bind(); + + + if (p_material->ubo_id) { + glBindBufferBase(GL_UNIFORM_BUFFER,1,p_material->ubo_id); + } + + + + int tc = p_material->textures.size(); + RID* textures = p_material->textures.ptr(); + + for(int i=0;itexture_owner.getornull( textures[i] ); + if (!t) { + //check hints + glBindTexture(GL_TEXTURE_2D,storage->resources.white_tex); + continue; + } + + glBindTexture(t->target,t->tex_id); + } + + + return rebind; + +} + + +void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e) { + + switch(e->instance->base_type) { + + case VS::INSTANCE_MESH: { + + RasterizerStorageGLES3::Surface *s = static_cast(e->geometry); + glBindVertexArray(s->array_id); // everything is so easy nowadays + } break; + } + +} + +static const GLenum gl_primitive[]={ + GL_POINTS, + GL_LINES, + GL_LINE_STRIP, + GL_LINE_LOOP, + GL_TRIANGLES, + GL_TRIANGLE_STRIP, + GL_TRIANGLE_FAN +}; + + + +void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) { + + switch(e->instance->base_type) { + + case VS::INSTANCE_MESH: { + + RasterizerStorageGLES3::Surface *s = static_cast(e->geometry); + + 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); + + } else { + + glDrawArrays(gl_primitive[s->primitive],0,s->array_len); + + } + + } break; + } + +} + +void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_element_count,const Transform& p_view_transform,const CameraMatrix& p_projection,bool p_reverse_cull,bool p_alpha_pass) { + + if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP]) { + //p_reverse_cull=!p_reverse_cull; + glFrontFace(GL_CCW); + } else { + glFrontFace(GL_CW); + } + + glBindBufferBase(GL_UNIFORM_BUFFER,0,state.scene_ubo); //bind globals ubo + + state.scene_shader.set_conditional(SceneShaderGLES3::USE_SKELETON,false); + + state.current_blend_mode=-1; + + glDisable(GL_BLEND); + + RasterizerStorageGLES3::Material* prev_material=NULL; + RasterizerStorageGLES3::Geometry* prev_geometry=NULL; + VS::InstanceType prev_base_type = VS::INSTANCE_MAX; + + for (int i=0;imaterial; + + bool rebind=i==0; + + if (material!=prev_material || rebind) { + + rebind = _setup_material(material,p_alpha_pass); +// _rinfo.mat_change_count++; + } + + + if (prev_base_type != e->instance->base_type || prev_geometry!=e->geometry) { + + _setup_geometry(e); + } + +// _set_cull(e->mirror,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(e->geometry, material, skeleton,e->owner,e->instance->transform); + + _render_geometry(e); + + prev_material=material; + prev_base_type=e->instance->base_type; + prev_geometry=e->geometry; + } + + //print_line("shaderchanges: "+itos(p_alpha_pass)+": "+itos(_rinfo.shader_change_count)); + + + glFrontFace(GL_CW); + glBindVertexArray(0); + +} + +void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner,int p_material) { + + RasterizerStorageGLES3::Material *m=NULL; + RID m_src=p_instance->material_override.is_valid() ? p_instance->material_override :(p_material>=0?p_instance->materials[p_material]:p_geometry->material); + +/* +#ifdef DEBUG_ENABLED + if (current_debug==VS::SCENARIO_DEBUG_OVERDRAW) { + m_src=overdraw_material; + } + +#endif +*/ + if (m_src.is_valid()) { + m=storage->material_owner.getornull( m_src ); + if (!m->shader) { + m=NULL; + } + } + + if (!m) { + m=storage->material_owner.getptr( default_material ); + } + + ERR_FAIL_COND(!m); + + + + //bool has_base_alpha=(m->shader_cache && m->shader_cache->has_alpha); + //bool has_blend_alpha=m->blend_mode!=VS::MATERIAL_BLEND_MODE_MIX || m->flags[VS::MATERIAL_FLAG_ONTOP]; + bool has_alpha = false; //has_base_alpha || has_blend_alpha; + +#if 0 + if (shadow) { + + if (has_blend_alpha || (has_base_alpha && m->depth_draw_mode!=VS::MATERIAL_DEPTH_DRAW_OPAQUE_PRE_PASS_ALPHA)) + return; //bye + + if (!m->shader_cache || (!m->shader_cache->writes_vertex && !m->shader_cache->uses_discard && m->depth_draw_mode!=VS::MATERIAL_DEPTH_DRAW_OPAQUE_PRE_PASS_ALPHA)) { + //shader does not use discard and does not write a vertex position, use generic material + if (p_instance->cast_shadows == VS::SHADOW_CASTING_SETTING_DOUBLE_SIDED) + m = shadow_mat_double_sided_ptr; + else + m = shadow_mat_ptr; + if (m->last_pass!=frame) { + + if (m->shader.is_valid()) { + + m->shader_cache=shader_owner.get(m->shader); + if (m->shader_cache) { + + + if (!m->shader_cache->valid) + m->shader_cache=NULL; + } else { + m->shader=RID(); + } + + } else { + m->shader_cache=NULL; + } + + m->last_pass=frame; + } + } + + render_list = &opaque_render_list; + /* notyet + if (!m->shader_cache || m->shader_cache->can_zpass) + render_list = &alpha_render_list; + } else { + render_list = &opaque_render_list; + }*/ + + } else { + if (has_alpha) { + render_list = &alpha_render_list; + } else { + render_list = &opaque_render_list; + + } + } +#endif + + RenderList::Element *e = has_alpha ? render_list.add_alpha_element() : render_list.add_element(); + + if (!e) + return; + + e->geometry=p_geometry; + e->material=m; + e->instance=p_instance; + e->owner=p_owner; + e->additive=false; + e->additive_ptr=&e->additive; + e->sort_key=0; + + if (e->geometry->last_pass!=render_pass) { + e->geometry->last_pass=render_pass; + e->geometry->index=current_geometry_index++; + } + + e->sort_key|=uint64_t(e->instance->base_type)<sort_key|=uint64_t(e->instance->base_type)<material->last_pass!=render_pass) { + e->material->last_pass=render_pass; + e->material->index=current_material_index++; + } + + e->sort_key|=uint64_t(e->material->index)<sort_key|=uint64_t(e->instance->depth_layer)<geometry->type==RasterizerStorageGLES3::Geometry::GEOMETRY_MULTISURFACE) + // e->sort_flags|=RenderList::SORT_FLAG_INSTANCING; + + bool mirror = e->instance->mirror; + +// if (m->flags[VS::MATERIAL_FLAG_INVERT_FACES]) +// e->mirror=!e->mirror; + + if (mirror) { + e->sort_key|=RenderList::SORT_KEY_MIRROR_FLAG; + } + + //e->light_type=0xFF; // no lights! + e->sort_key|=uint64_t(0xF)<sort_key|=uint64_t(0xFFFF)<depth_draw_mode==VS::MATERIAL_DEPTH_DRAW_OPAQUE_PRE_PASS_ALPHA) { + + //if nothing exists, add this element as opaque too + RenderList::Element *oe = opaque_render_list.add_element(); + + if (!oe) + return; + + memcpy(oe,e,sizeof(RenderList::Element)); + oe->additive_ptr=&oe->additive; + } +*/ + +#if 0 + if (shadow || m->flags[VS::MATERIAL_FLAG_UNSHADED] || current_debug==VS::SCENARIO_DEBUG_SHADELESS) { + + e->light_type=0x7F; //unshaded is zero + } else { + + bool duplicate=false; + + + for(int i=0;isort_key; + uint8_t light_type = VS::LIGHT_DIRECTIONAL; + if (directional_lights[i]->base->shadow_enabled) { + light_type|=0x8; + if (directional_lights[i]->base->directional_shadow_mode==VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) + light_type|=0x10; + else if (directional_lights[i]->base->directional_shadow_mode==VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) + light_type|=0x30; + + } + + RenderList::Element *ec; + if (duplicate) { + + ec = render_list->add_element(); + memcpy(ec,e,sizeof(RenderList::Element)); + } else { + + ec=e; + duplicate=true; + } + + ec->light_type=light_type; + ec->light=sort_key; + ec->additive_ptr=&e->additive; + + } + + + const RID *liptr = p_instance->light_instances.ptr(); + int ilc=p_instance->light_instances.size(); + + + + for(int i=0;ilast_pass!=scene_pass) //lit by light not in visible scene + continue; + uint8_t light_type=li->base->type|0x40; //penalty to ensure directionals always go first + if (li->base->shadow_enabled) { + light_type|=0x8; + } + uint16_t sort_key =li->sort_key; + + RenderList::Element *ec; + if (duplicate) { + + ec = render_list->add_element(); + memcpy(ec,e,sizeof(RenderList::Element)); + } else { + + duplicate=true; + ec=e; + } + + ec->light_type=light_type; + ec->light=sort_key; + ec->additive_ptr=&e->additive; + + } + + + + } + +#endif +} + +void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,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_directional_lights,int p_directional_light_count,RID p_environment){ + + + //fill up ubo + + store_camera(p_cam_projection,state.ubo_data.projection_matrix); + store_transform(p_cam_transform,state.ubo_data.camera_matrix); + store_transform(p_cam_transform.affine_inverse(),state.ubo_data.camera_inverse_matrix); + for(int i=0;i<4;i++) { + state.ubo_data.time[i]=storage->frame.time[i]; + } + + + glBindBuffer(GL_UNIFORM_BUFFER, state.scene_ubo); + glBufferSubData(GL_UNIFORM_BUFFER, 0,sizeof(State::SceneDataUBO), &state.ubo_data); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + + + render_list.clear(); + + render_pass++; + current_material_index=0; + + //fill list + + for(int i=0;ibase_type) { + + case VS::INSTANCE_MESH: { + + RasterizerStorageGLES3::Mesh *mesh = storage->mesh_owner.getptr(inst->base); + ERR_CONTINUE(!mesh); + + int ssize = mesh->surfaces.size(); + + for (int i=0;imaterials[i].is_valid() ? i : -1; + RasterizerStorageGLES3::Surface *s = mesh->surfaces[i]; + _add_geometry(s,inst,NULL,mat_idx); + } + + //mesh->last_pass=frame; + + } break; + case VS::INSTANCE_MULTIMESH: { + + } break; + case VS::INSTANCE_IMMEDIATE: { + + } break; + + } + } + + // + + + glEnable(GL_BLEND); + glDepthMask(GL_TRUE); + glEnable(GL_DEPTH_TEST); + glDisable(GL_SCISSOR_TEST); + glClearDepth(1.0); + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->front.fbo); + + + if (true) { + + if (storage->frame.clear_request) { + + 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 ); + glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + storage->frame.clear_request=false; + + } + } + + state.current_depth_test=true; + state.current_depth_mask=true; + state.texscreen_copied=false; + + glBlendEquation(GL_FUNC_ADD); + + if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } else { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + + glDisable(GL_BLEND); + //current_blend_mode=VS::MATERIAL_BLEND_MODE_MIX; + + + render_list.sort_by_key(false); + + //_render_list_forward(&opaque_render_list,camera_transform,camera_transform_inverse,camera_projection,false,fragment_lighting); +/* + if (draw_tex_background) { + + //most 3D vendors recommend drawing a texture bg or skybox here, + //after opaque geometry has been drawn + //so the zbuffer can get rid of most pixels + _draw_tex_bg(); + } +*/ + if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } else { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + +// glDisable(GL_BLEND); +// current_blend_mode=VS::MATERIAL_BLEND_MODE_MIX; +// state.scene_shader.set_conditional(SceneShaderGLES3::USE_GLOW,false); +// if (current_env && current_env->fx_enabled[VS::ENV_FX_GLOW]) { +// glColorMask(1,1,1,0); //don't touch alpha +// } + + + _render_list(render_list.elements,render_list.element_count,p_cam_transform,p_cam_projection,false,false); + + //_render_list_forward(&alpha_render_list,camera_transform,camera_transform_inverse,camera_projection,false,fragment_lighting,true); + //glColorMask(1,1,1,1); + +// state.scene_shader.set_conditional( SceneShaderGLES3::USE_FOG,false); + + glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); +#if 0 + if (use_fb) { + + + + for(int i=0;ifx_enabled[VS::ENV_FX_HDR]) { + + int hdr_tm = current_env->fx_param[VS::ENV_FX_PARAM_HDR_TONEMAPPER]; + switch(hdr_tm) { + case VS::ENV_FX_HDR_TONE_MAPPER_LINEAR: { + + + } break; + case VS::ENV_FX_HDR_TONE_MAPPER_LOG: { + copy_shader.set_conditional(CopyShaderGLES2::USE_LOG_TONEMAPPER,true); + + } break; + case VS::ENV_FX_HDR_TONE_MAPPER_REINHARDT: { + copy_shader.set_conditional(CopyShaderGLES2::USE_REINHARDT_TONEMAPPER,true); + } break; + case VS::ENV_FX_HDR_TONE_MAPPER_REINHARDT_AUTOWHITE: { + + copy_shader.set_conditional(CopyShaderGLES2::USE_REINHARDT_TONEMAPPER,true); + copy_shader.set_conditional(CopyShaderGLES2::USE_AUTOWHITE,true); + } break; + } + + + _process_hdr(); + } + if (current_env && current_env->fx_enabled[VS::ENV_FX_GLOW]) { + _process_glow_bloom(); + int glow_transfer_mode=current_env->fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_BLEND_MODE]; + if (glow_transfer_mode==1) + copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW_SCREEN,true); + if (glow_transfer_mode==2) + copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW_SOFTLIGHT,true); + } + + glBindFramebuffer(GL_FRAMEBUFFER, current_rt?current_rt->fbo:base_framebuffer); + + Size2 size; + if (current_rt) { + glBindFramebuffer(GL_FRAMEBUFFER, current_rt->fbo); + glViewport( 0,0,viewport.width,viewport.height); + size=Size2(viewport.width,viewport.height); + } else { + glBindFramebuffer(GL_FRAMEBUFFER, base_framebuffer); + glViewport( viewport.x, window_size.height-(viewport.height+viewport.y), viewport.width,viewport.height ); + size=Size2(viewport.width,viewport.height); + } + + //time to copy!!! + copy_shader.set_conditional(CopyShaderGLES2::USE_BCS,current_env && current_env->fx_enabled[VS::ENV_FX_BCS]); + copy_shader.set_conditional(CopyShaderGLES2::USE_SRGB,current_env && current_env->fx_enabled[VS::ENV_FX_SRGB]); + copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW,current_env && current_env->fx_enabled[VS::ENV_FX_GLOW]); + copy_shader.set_conditional(CopyShaderGLES2::USE_HDR,current_env && current_env->fx_enabled[VS::ENV_FX_HDR]); + copy_shader.set_conditional(CopyShaderGLES2::USE_NO_ALPHA,true); + copy_shader.set_conditional(CopyShaderGLES2::USE_FXAA,current_env && current_env->fx_enabled[VS::ENV_FX_FXAA]); + + copy_shader.bind(); + //copy_shader.set_uniform(CopyShaderGLES2::SOURCE,0); + + if (current_env && current_env->fx_enabled[VS::ENV_FX_GLOW]) { + + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, framebuffer.blur[0].color ); + glUniform1i(copy_shader.get_uniform_location(CopyShaderGLES2::GLOW_SOURCE),1); + + } + + if (current_env && current_env->fx_enabled[VS::ENV_FX_HDR]) { + + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, current_vd->lum_color ); + glUniform1i(copy_shader.get_uniform_location(CopyShaderGLES2::HDR_SOURCE),2); + copy_shader.set_uniform(CopyShaderGLES2::TONEMAP_EXPOSURE,float(current_env->fx_param[VS::ENV_FX_PARAM_HDR_EXPOSURE])); + copy_shader.set_uniform(CopyShaderGLES2::TONEMAP_WHITE,float(current_env->fx_param[VS::ENV_FX_PARAM_HDR_WHITE])); + + } + + if (current_env && current_env->fx_enabled[VS::ENV_FX_FXAA]) + copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SIZE,Size2(1.0/size.x,1.0/size.y)); + + + if (current_env && current_env->fx_enabled[VS::ENV_FX_BCS]) { + + Vector3 bcs; + bcs.x=current_env->fx_param[VS::ENV_FX_PARAM_BCS_BRIGHTNESS]; + bcs.y=current_env->fx_param[VS::ENV_FX_PARAM_BCS_CONTRAST]; + bcs.z=current_env->fx_param[VS::ENV_FX_PARAM_BCS_SATURATION]; + copy_shader.set_uniform(CopyShaderGLES2::BCS,bcs); + } + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, framebuffer.color ); + glUniform1i(copy_shader.get_uniform_location(CopyShaderGLES2::SOURCE),0); + + _copy_screen_quad(); + + copy_shader.set_conditional(CopyShaderGLES2::USE_BCS,false); + copy_shader.set_conditional(CopyShaderGLES2::USE_SRGB,false); + copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW,false); + copy_shader.set_conditional(CopyShaderGLES2::USE_HDR,false); + copy_shader.set_conditional(CopyShaderGLES2::USE_NO_ALPHA,false); + copy_shader.set_conditional(CopyShaderGLES2::USE_FXAA,false); + copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW_SCREEN,false); + copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW_SOFTLIGHT,false); + copy_shader.set_conditional(CopyShaderGLES2::USE_REINHARDT_TONEMAPPER,false); + copy_shader.set_conditional(CopyShaderGLES2::USE_AUTOWHITE,false); + copy_shader.set_conditional(CopyShaderGLES2::USE_LOG_TONEMAPPER,false); + + state.scene_shader.set_conditional(SceneShaderGLES3::USE_8BIT_HDR,false); + + + if (current_env && current_env->fx_enabled[VS::ENV_FX_HDR] && GLOBAL_DEF("rasterizer/debug_hdr",false)) { + _debug_luminances(); + } + } + + current_env=NULL; + current_debug=VS::SCENARIO_DEBUG_DISABLED; + if (GLOBAL_DEF("rasterizer/debug_shadow_maps",false)) { + _debug_shadows(); + } +// _debug_luminances(); +// _debug_samplers(); + + if (using_canvas_bg) { + using_canvas_bg=false; + glColorMask(1,1,1,1); //don't touch alpha + } +#endif +} + +bool RasterizerSceneGLES3::free(RID p_rid) { + + return false; + +} + +void RasterizerSceneGLES3::initialize() { + + state.scene_shader.init(); + + default_shader = storage->shader_create(VS::SHADER_SPATIAL); + default_material = storage->material_create(); + storage->material_set_shader(default_material,default_shader); + + glGenBuffers(1, &state.scene_ubo); + glBindBuffer(GL_UNIFORM_BUFFER, state.scene_ubo); + glBufferData(GL_UNIFORM_BUFFER, sizeof(State::SceneDataUBO), &state.scene_ubo, GL_DYNAMIC_DRAW); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + + render_list.max_elements=GLOBAL_DEF("rendering/gles3/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; + + render_list.init(); +} + +void RasterizerSceneGLES3::finalize(){ + + +} + + +RasterizerSceneGLES3::RasterizerSceneGLES3() +{ + +} diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h new file mode 100644 index 0000000000..6fba777fc8 --- /dev/null +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -0,0 +1,178 @@ +#ifndef RASTERIZERSCENEGLES3_H +#define RASTERIZERSCENEGLES3_H + +#include "rasterizer_storage_gles3.h" +#include "drivers/gles3/shaders/scene.glsl.h" + +class RasterizerSceneGLES3 : public RasterizerScene { +public: + + uint64_t render_pass; + uint32_t current_material_index; + uint32_t current_geometry_index; + + RID default_material; + RID default_shader; + + RasterizerStorageGLES3 *storage; + + + + struct State { + + bool current_depth_test; + bool current_depth_mask; + bool texscreen_copied; + int current_blend_mode; + + SceneShaderGLES3 scene_shader; + + + struct SceneDataUBO { + + float projection_matrix[16]; + float camera_inverse_matrix[16]; + float camera_matrix[16]; + float time[4]; + float ambient_light[4]; + + } ubo_data; + + GLuint scene_ubo; + + + + } state; + + struct RenderList { + + enum { + DEFAULT_MAX_ELEMENTS=65536, + MAX_LIGHTS=4, + SORT_FLAG_SKELETON=1, + SORT_FLAG_INSTANCING=2, + + SORT_KEY_DEPTH_LAYER_SHIFT=58, + SORT_KEY_LIGHT_TYPE_SHIFT=54, //type is most important + SORT_KEY_LIGHT_INDEX_SHIFT=38, //type is most important + SORT_KEY_MATERIAL_INDEX_SHIFT=22, + SORT_KEY_GEOMETRY_INDEX_SHIFT=6, + SORT_KEY_GEOMETRY_TYPE_SHIFT=2, + SORT_KEY_SKELETON_FLAG=2, + SORT_KEY_MIRROR_FLAG=1 + + }; + + int max_elements; + + struct Element { + + RasterizerScene::InstanceBase *instance; + RasterizerStorageGLES3::Geometry *geometry; + RasterizerStorageGLES3::Material *material; + RasterizerStorageGLES3::GeometryOwner *owner; + uint64_t sort_key; + bool *additive_ptr; + bool additive; + + }; + + + Element *_elements; + Element **elements; + + int element_count; + int alpha_element_count; + + void clear() { + + element_count=0; + alpha_element_count=0; + } + + //should eventually be replaced by radix + + struct SortByKey { + + _FORCE_INLINE_ bool operator()(const Element* A, const Element* B ) const { + return A->sort_key < B->sort_key; + } + }; + + void sort_by_key(bool p_alpha) { + + SortArray sorter; + if (p_alpha) { + sorter.sort(&elements[max_elements-alpha_element_count-1],alpha_element_count); + } else { + sorter.sort(elements,element_count); + } + } + + + _FORCE_INLINE_ Element* add_element() { + + if (element_count+alpha_element_count>=max_elements) + return NULL; + elements[element_count]=&_elements[element_count]; + return elements[element_count++]; + } + + _FORCE_INLINE_ Element* add_alpha_element() { + + if (element_count+alpha_element_count>=max_elements) + return NULL; + int idx = max_elements-alpha_element_count-1; + elements[idx]=&_elements[idx]; + alpha_element_count++; + return elements[idx]; + } + + void init() { + + element_count = 0; + alpha_element_count =0; + elements=memnew_arr(Element*,max_elements); + _elements=memnew_arr(Element,max_elements); + for (int i=0;istate.canvas_shader, - &canvas->state.canvas_shader, + &scene->state.scene_shader, &canvas->state.canvas_shader, }; @@ -1108,6 +1109,37 @@ void RasterizerStorageGLES3::_update_shader(Shader* p_shader) const { actions->uniforms=&p_shader->uniforms; } break; + + case VS::SHADER_SPATIAL: { + + p_shader->spatial.blend_mode=Shader::Spatial::BLEND_MODE_MIX; + p_shader->spatial.depth_draw_mode=Shader::Spatial::DEPTH_DRAW_OPAQUE; + p_shader->spatial.cull_mode=Shader::Spatial::CULL_MODE_BACK; + p_shader->spatial.uses_alpha=false; + p_shader->spatial.unshaded=false; + p_shader->spatial.ontop=false; + + shaders.actions_scene.render_mode_values["blend_add"]=Pair(&p_shader->spatial.blend_mode,Shader::Spatial::BLEND_MODE_ADD); + shaders.actions_scene.render_mode_values["blend_mix"]=Pair(&p_shader->spatial.blend_mode,Shader::Spatial::BLEND_MODE_MIX); + shaders.actions_scene.render_mode_values["blend_sub"]=Pair(&p_shader->spatial.blend_mode,Shader::Spatial::BLEND_MODE_SUB); + shaders.actions_scene.render_mode_values["blend_mul"]=Pair(&p_shader->spatial.blend_mode,Shader::Spatial::BLEND_MODE_MUL); + + shaders.actions_scene.render_mode_values["depth_draw_opaque"]=Pair(&p_shader->spatial.depth_draw_mode,Shader::Spatial::DEPTH_DRAW_OPAQUE); + shaders.actions_scene.render_mode_values["depth_draw_always"]=Pair(&p_shader->spatial.depth_draw_mode,Shader::Spatial::DEPTH_DRAW_ALWAYS); + shaders.actions_scene.render_mode_values["depth_draw_never"]=Pair(&p_shader->spatial.depth_draw_mode,Shader::Spatial::DEPTH_DRAW_NEVER); + shaders.actions_scene.render_mode_values["depth_draw_alpha_prepass"]=Pair(&p_shader->spatial.depth_draw_mode,Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS); + + shaders.actions_scene.render_mode_values["cull_front"]=Pair(&p_shader->spatial.cull_mode,Shader::Spatial::CULL_MODE_FRONT); + shaders.actions_scene.render_mode_values["cull_back"]=Pair(&p_shader->spatial.cull_mode,Shader::Spatial::CULL_MODE_BACK); + shaders.actions_scene.render_mode_values["cull_disable"]=Pair(&p_shader->spatial.cull_mode,Shader::Spatial::CULL_MODE_DISABLED); + + shaders.actions_canvas.render_mode_flags["unshaded"]=&p_shader->spatial.unshaded; + shaders.actions_canvas.render_mode_flags["ontop"]=&p_shader->spatial.ontop; + + shaders.actions_canvas.usage_flag_pointers["ALPHA"]=&p_shader->spatial.uses_alpha; + + } + } @@ -1905,97 +1937,685 @@ void RasterizerStorageGLES3::update_dirty_materials() { RID RasterizerStorageGLES3::mesh_create(){ - return RID(); + Mesh * mesh = memnew( Mesh ); + + return mesh_owner.make_rid(mesh); } -void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::PrimitiveType p_primitive,const DVector& p_array,int p_vertex_count,const DVector& p_index_array,int p_index_count,const Vector >& p_blend_shapes){ +void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::PrimitiveType p_primitive,const DVector& p_array,int p_vertex_count,const DVector& p_index_array,int p_index_count,const AABB& p_aabb,const Vector >& p_blend_shapes,const Vector& p_bone_aabbs){ + + Mesh *mesh = mesh_owner.getornull(p_mesh); + ERR_FAIL_COND(!mesh); + + ERR_FAIL_COND(!(p_format&VS::ARRAY_FORMAT_VERTEX)); + + //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 ); + } + + + bool has_morph = p_blend_shapes.size(); + + Surface::Attrib attribs[VS::ARRAY_MAX],morph_attribs[VS::ARRAY_MAX]; + + int stride=0; + int morph_stride=0; + + for(int i=0;i=(1<<16)) { + attribs[i].type=GL_UNSIGNED_INT; + attribs[i].stride=4; + } else { + attribs[i].type=GL_UNSIGNED_SHORT; + attribs[i].stride=2; + } + + attribs[i].normalized=GL_FALSE; + + } break; + + } + } + + for(int i=0;imorph_target_count); + + for(int i=0;iactive=true; + surface->array_len=p_vertex_count; + surface->index_array_len=p_index_count; + surface->primitive=p_primitive; + surface->mesh=mesh; + surface->format=p_format; + surface->skeleton_bone_aabb=p_bone_aabbs; + surface->skeleton_bone_used.resize(surface->skeleton_bone_aabb.size()); + surface->aabb=p_aabb; + surface->max_bone=p_bone_aabbs.size(); + + for(int i=0;iskeleton_bone_used.size();i++) { + if (surface->skeleton_bone_aabb[i].size.x<0 || surface->skeleton_bone_aabb[i].size.y<0 || surface->skeleton_bone_aabb[i].size.z<0) { + surface->skeleton_bone_used[i]=false; + } else { + surface->skeleton_bone_used[i]=true; + } + } + + for(int i=0;iattribs[i]=attribs[i]; + surface->morph_attribs[i]=morph_attribs[i]; + } + + { + + DVector::Read vr = p_array.read(); + + glGenBuffers(1,&surface->vertex_id); + glBindBuffer(GL_ARRAY_BUFFER,surface->vertex_id); + glBufferData(GL_ARRAY_BUFFER,array_size,vr.ptr(),GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER,0); //unbind + + + if (p_format&VS::ARRAY_FORMAT_INDEX) { + + DVector::Read ir = p_index_array.read(); + + glGenBuffers(1,&surface->index_id); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,surface->index_id); + glBufferData(GL_ELEMENT_ARRAY_BUFFER,index_array_size,ir.ptr(),GL_STATIC_DRAW); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); //unbind + } + //generate arrays for faster state switching + + glGenVertexArrays(1,&surface->array_id); + glBindVertexArray(surface->array_id); + glBindBuffer(GL_ARRAY_BUFFER,surface->vertex_id); + + for(int i=0;iindex_id) { + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,surface->index_id); + } + + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER,0); //unbind + + } + + { + + //blend shapes + + for(int i=0;i::Read vr = p_blend_shapes[i].read(); + + glGenBuffers(1,&mt.vertex_id); + glBindBuffer(GL_ARRAY_BUFFER,mt.vertex_id); + glBufferData(GL_ARRAY_BUFFER,array_size,vr.ptr(),GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER,0); //unbind + + glGenVertexArrays(1,&mt.array_id); + glBindVertexArray(mt.array_id); + glBindBuffer(GL_ARRAY_BUFFER,mt.vertex_id); + + for(int i=0;imorph_targets.push_back(mt); + + } + } + + mesh->surfaces.push_back(surface); + mesh->instance_change_notify(); } void RasterizerStorageGLES3::mesh_set_morph_target_count(RID p_mesh,int p_amount){ + Mesh *mesh = mesh_owner.getornull(p_mesh); + ERR_FAIL_COND(!mesh); + + + ERR_FAIL_COND(mesh->surfaces.size()!=0); + ERR_FAIL_COND(p_amount<0); + + mesh->morph_target_count=p_amount; } int RasterizerStorageGLES3::mesh_get_morph_target_count(RID p_mesh) const{ - return 0; + const Mesh *mesh = mesh_owner.getornull(p_mesh); + ERR_FAIL_COND_V(!mesh,0); + + return mesh->morph_target_count; } void RasterizerStorageGLES3::mesh_set_morph_target_mode(RID p_mesh,VS::MorphTargetMode p_mode){ + Mesh *mesh = mesh_owner.getornull(p_mesh); + ERR_FAIL_COND(!mesh); + + mesh->morph_target_mode=p_mode; } VS::MorphTargetMode RasterizerStorageGLES3::mesh_get_morph_target_mode(RID p_mesh) const{ - return VS::MORPH_MODE_NORMALIZED; + const Mesh *mesh = mesh_owner.getornull(p_mesh); + ERR_FAIL_COND_V(!mesh,VS::MORPH_MODE_NORMALIZED); + + return mesh->morph_target_mode; } void RasterizerStorageGLES3::mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material){ + Mesh *mesh = mesh_owner.getornull(p_mesh); + ERR_FAIL_COND(!mesh); + ERR_FAIL_INDEX(p_surface,mesh->surfaces.size()); + + mesh->surfaces[p_surface]->material=p_material; } RID RasterizerStorageGLES3::mesh_surface_get_material(RID p_mesh, int p_surface) const{ - return RID(); + const Mesh *mesh = mesh_owner.getornull(p_mesh); + ERR_FAIL_COND_V(!mesh,RID()); + ERR_FAIL_INDEX_V(p_surface,mesh->surfaces.size(),RID()); + + return mesh->surfaces[p_surface]->material; } int RasterizerStorageGLES3::mesh_surface_get_array_len(RID p_mesh, int p_surface) const{ - return 0; + const Mesh *mesh = mesh_owner.getornull(p_mesh); + ERR_FAIL_COND_V(!mesh,0); + ERR_FAIL_INDEX_V(p_surface,mesh->surfaces.size(),0); + + return mesh->surfaces[p_surface]->array_len; + } int RasterizerStorageGLES3::mesh_surface_get_array_index_len(RID p_mesh, int p_surface) const{ + const Mesh *mesh = mesh_owner.getornull(p_mesh); + ERR_FAIL_COND_V(!mesh,0); + ERR_FAIL_INDEX_V(p_surface,mesh->surfaces.size(),0); - return 0; + return mesh->surfaces[p_surface]->index_array_len; } DVector RasterizerStorageGLES3::mesh_surface_get_array(RID p_mesh, int p_surface) const{ - return DVector(); + const Mesh *mesh = mesh_owner.getornull(p_mesh); + ERR_FAIL_COND_V(!mesh,DVector()); + ERR_FAIL_INDEX_V(p_surface,mesh->surfaces.size(),DVector()); + + Surface *surface = mesh->surfaces[p_surface]; + + glBindBuffer(GL_ARRAY_BUFFER,surface->vertex_id); + void * data = glMapBufferRange(GL_ARRAY_BUFFER,0,surface->array_len,GL_MAP_READ_BIT); + + ERR_FAIL_COND_V(!data,DVector()); + + DVector ret; + ret.resize(surface->array_len); + + { + + DVector::Write w = ret.write(); + copymem(w.ptr(),data,surface->array_len); + } + glUnmapBuffer(GL_ARRAY_BUFFER); + + + return ret; } -DVector RasterizerStorageGLES3::mesh_surface_get_index_array(RID p_mesh, int p_surface) const{ +DVector RasterizerStorageGLES3::mesh_surface_get_index_array(RID p_mesh, int p_surface) const { + const Mesh *mesh = mesh_owner.getornull(p_mesh); + ERR_FAIL_COND_V(!mesh,DVector()); + ERR_FAIL_INDEX_V(p_surface,mesh->surfaces.size(),DVector()); + + Surface *surface = mesh->surfaces[p_surface]; + + ERR_FAIL_COND_V(surface->index_array_len==0,DVector()); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,surface->vertex_id); + void * data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER,0,surface->index_array_len,GL_MAP_READ_BIT); + + ERR_FAIL_COND_V(!data,DVector()); + + DVector ret; + ret.resize(surface->index_array_len); + + { + + DVector::Write w = ret.write(); + copymem(w.ptr(),data,surface->index_array_len); + } + + glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); - return DVector(); + return ret; } uint32_t RasterizerStorageGLES3::mesh_surface_get_format(RID p_mesh, int p_surface) const{ - return 0; + const Mesh *mesh = mesh_owner.getornull(p_mesh); + + ERR_FAIL_COND_V(!mesh,0); + ERR_FAIL_INDEX_V(p_surface,mesh->surfaces.size(),0); + + return mesh->surfaces[p_surface]->format; + } + VS::PrimitiveType RasterizerStorageGLES3::mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const{ - return VS::PRIMITIVE_MAX; + const Mesh *mesh = mesh_owner.getornull(p_mesh); + ERR_FAIL_COND_V(!mesh,VS::PRIMITIVE_MAX); + ERR_FAIL_INDEX_V(p_surface,mesh->surfaces.size(),VS::PRIMITIVE_MAX); + + return mesh->surfaces[p_surface]->primitive; } -void RasterizerStorageGLES3::mesh_remove_surface(RID p_mesh,int p_index){ +void RasterizerStorageGLES3::mesh_remove_surface(RID p_mesh, int p_surface){ + + Mesh *mesh = mesh_owner.getornull(p_mesh); + ERR_FAIL_COND(!mesh); + ERR_FAIL_INDEX(p_surface,mesh->surfaces.size()); + Surface *surface = mesh->surfaces[p_surface]; + ERR_FAIL_COND(surface->index_array_len==0); + + glDeleteBuffers(1,&surface->array_id); + if (surface->index_id) { + glDeleteBuffers(1,&surface->index_id); + } + + glDeleteVertexArrays(1,&surface->array_id); + + for(int i=0;imorph_targets.size();i++) { + + glDeleteBuffers(1,&surface->morph_targets[i].vertex_id); + glDeleteVertexArrays(1,&surface->morph_targets[i].array_id); + } + + memdelete(surface); + + mesh->surfaces.remove(p_surface); + + mesh->instance_change_notify(); } int RasterizerStorageGLES3::mesh_get_surface_count(RID p_mesh) const{ - return 0; + const Mesh *mesh = mesh_owner.getornull(p_mesh); + ERR_FAIL_COND_V(!mesh,0); + return mesh->surfaces.size(); + } void RasterizerStorageGLES3::mesh_set_custom_aabb(RID p_mesh,const AABB& p_aabb){ + Mesh *mesh = mesh_owner.getornull(p_mesh); + ERR_FAIL_COND(!mesh); + mesh->custom_aabb=p_aabb; } AABB RasterizerStorageGLES3::mesh_get_custom_aabb(RID p_mesh) const{ - return AABB(); + const Mesh *mesh = mesh_owner.getornull(p_mesh); + ERR_FAIL_COND_V(!mesh,AABB()); + + return mesh->custom_aabb; + } -AABB RasterizerStorageGLES3::mesh_get_aabb(RID p_mesh) const{ +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()) + return mesh->custom_aabb; +/* + Skeleton *sk=NULL; + if (p_skeleton.is_valid()) + sk=skeleton_owner.get(p_skeleton); +*/ + AABB aabb; + /* + if (sk && sk->bones.size()!=0) { + + + for (int i=0;isurfaces.size();i++) { + + AABB laabb; + if (mesh->surfaces[i]->format&VS::ARRAY_FORMAT_BONES && mesh->surfaces[i]->skeleton_bone_aabb.size()) { + + + int bs = mesh->surfaces[i]->skeleton_bone_aabb.size(); + const AABB *skbones = mesh->surfaces[i]->skeleton_bone_aabb.ptr(); + const bool *skused = mesh->surfaces[i]->skeleton_bone_used.ptr(); + + int sbs = sk->bones.size(); + ERR_CONTINUE(bs>sbs); + Skeleton::Bone *skb = sk->bones.ptr(); + + bool first=true; + for(int j=0;jsurfaces[i]->aabb; + } + + if (i==0) + aabb=laabb; + else + aabb.merge_with(laabb); + } + } else { +*/ + for (int i=0;isurfaces.size();i++) { + + if (i==0) + aabb=mesh->surfaces[i]->aabb; + else + aabb.merge_with(mesh->surfaces[i]->aabb); + } +/* + } +*/ + return aabb; - return AABB(); } void RasterizerStorageGLES3::mesh_clear(RID p_mesh){ + Mesh *mesh = mesh_owner.getornull(p_mesh); + ERR_FAIL_COND(!mesh); + while(mesh->surfaces.size()) { + mesh_remove_surface(p_mesh,0); + } } /* MULTIMESH API */ @@ -2206,6 +2826,16 @@ void RasterizerStorageGLES3::light_directional_set_shadow_mode(RID p_light,VS::L } +VS::LightType RasterizerStorageGLES3::light_get_type(RID p_light) const { + + return VS::LIGHT_DIRECTIONAL; +} + +AABB RasterizerStorageGLES3::light_get_aabb(RID p_light) const { + + return AABB(); +} + /* PROBE API */ RID RasterizerStorageGLES3::reflection_probe_create(){ @@ -2292,6 +2922,42 @@ void RasterizerStorageGLES3::portal_set_disabled_color(RID p_portal, const Color } +void RasterizerStorageGLES3::instance_add_dependency(RID p_base,RasterizerScene::InstanceBase *p_instance) { + + Instantiable *inst=NULL; + switch(p_instance->base_type) { + case VS::INSTANCE_MESH: { + inst = mesh_owner.getornull(p_base); + ERR_FAIL_COND(!inst); + } break; + default: { + ERR_FAIL(); + } + } + + inst->instance_list.add( &p_instance->dependency_item ); +} + +void RasterizerStorageGLES3::instance_remove_dependency(RID p_base,RasterizerScene::InstanceBase *p_instance){ + + Instantiable *inst=NULL; + + switch(p_instance->base_type) { + case VS::INSTANCE_MESH: { + inst = mesh_owner.getornull(p_base); + ERR_FAIL_COND(!inst); + + } break; + default: { + ERR_FAIL(); + } + } + + ERR_FAIL_COND(!inst); + + inst->instance_list.remove( &p_instance->dependency_item ); +} + /* RENDER TARGET */ @@ -2773,6 +3439,15 @@ void RasterizerStorageGLES3::canvas_light_occluder_set_polylines(RID p_occluder, } +VS::InstanceType RasterizerStorageGLES3::get_base_type(RID p_rid) const { + + if (mesh_owner.owns(p_rid)) { + return VS::INSTANCE_MESH; + } + + return VS::INSTANCE_NONE; +} + bool RasterizerStorageGLES3::free(RID p_rid){ if (render_target_owner.owns(p_rid)) { @@ -2834,6 +3509,15 @@ bool RasterizerStorageGLES3::free(RID p_rid){ material_owner.free(p_rid); memdelete(material); + } else if (mesh_owner.owns(p_rid)) { + + // delete the texture + Mesh *mesh = mesh_owner.get(p_rid); + + mesh_clear(p_rid); + + mesh_owner.free(p_rid); + memdelete(mesh); } else if (canvas_occluder_owner.owns(p_rid)) { diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index b7b3e607c6..950d65b9d0 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -10,12 +10,14 @@ #include "shader_compiler_gles3.h" class RasterizerCanvasGLES3; +class RasterizerSceneGLES3; class RasterizerStorageGLES3 : public RasterizerStorage { public: RasterizerCanvasGLES3 *canvas; + RasterizerSceneGLES3 *scene; enum FBOFormat { FBO_FORMAT_16_BITS, @@ -59,6 +61,7 @@ public: ShaderCompilerGLES3 compiler; ShaderCompilerGLES3::IdentifierActions actions_canvas; + ShaderCompilerGLES3::IdentifierActions actions_scene; } shaders; struct Resources { @@ -230,6 +233,40 @@ public: } canvas_item; + struct Spatial { + + enum BlendMode { + BLEND_MODE_MIX, + BLEND_MODE_ADD, + BLEND_MODE_SUB, + BLEND_MODE_MUL, + }; + + int blend_mode; + + enum DepthDrawMode { + DEPTH_DRAW_OPAQUE, + DEPTH_DRAW_ALWAYS, + DEPTH_DRAW_NEVER, + DEPTH_DRAW_ALPHA_PREPASS, + }; + + int depth_draw_mode; + + enum CullMode { + CULL_MODE_FRONT, + CULL_MODE_BACK, + CULL_MODE_DISABLED, + }; + + int cull_mode; + + bool uses_alpha; + bool unshaded; + bool ontop; + + } spatial; + Shader() : dirty_list(this) { shader=NULL; @@ -272,10 +309,14 @@ public: SelfList dirty_list; Vector textures; + uint32_t index; + uint64_t last_pass; + Material() : list(this), dirty_list(this) { shader=NULL; ubo_id=0; ubo_size=0; + last_pass=0; } }; @@ -300,9 +341,155 @@ public: /* MESH API */ + struct Instantiable : public RID_Data { + + enum Type { + GEOMETRY_INVALID, + GEOMETRY_SURFACE, + GEOMETRY_IMMEDIATE, + GEOMETRY_MULTISURFACE, + }; + + SelfList::List instance_list; + + _FORCE_INLINE_ void instance_change_notify() { + + SelfList *instances = instance_list.first(); + while(instances) { + + instances->self()->base_changed(); + instances=instances->next(); + } + } + + Instantiable() { } + virtual ~Instantiable() { + + while(instance_list.first()) { + instance_list.first()->self()->base_removed(); + } + } + }; + + struct Geometry : Instantiable { + + enum Type { + GEOMETRY_INVALID, + GEOMETRY_SURFACE, + GEOMETRY_IMMEDIATE, + GEOMETRY_MULTISURFACE, + }; + + Type type; + RID material; + uint64_t last_pass; + uint32_t index; + + Geometry() { + last_pass=0; + index=0; + } + + }; + + struct GeometryOwner : public Instantiable { + + virtual ~GeometryOwner() {} + }; + + struct Mesh; + struct Surface : public Geometry { + + struct Attrib { + + bool enabled; + GLuint index; + GLint size; + GLenum type; + GLboolean normalized; + GLsizei stride; + uint32_t offset; + }; + + Attrib attribs[VS::ARRAY_MAX]; + Attrib morph_attribs[VS::ARRAY_MAX]; + + + Mesh *mesh; + uint32_t format; + + GLuint array_id; + GLuint vertex_id; + GLuint index_id; + + Vector skeleton_bone_aabb; + Vector skeleton_bone_used; + + //bool packed; + + struct MorphTarget { + GLuint vertex_id; + GLuint array_id; + }; + + Vector morph_targets; + + AABB aabb; + + int array_len; + int index_array_len; + int max_bone; + + int array_bytes; + + + VS::PrimitiveType primitive; + + bool active; + + Surface() { + + array_bytes=0; + mesh=NULL; + format=0; + array_id=0; + vertex_id=0; + index_id=0; + array_len=0; + type=GEOMETRY_SURFACE; + primitive=VS::PRIMITIVE_POINTS; + index_array_len=0; + active=false; + + } + + ~Surface() { + + } + }; + + + struct Mesh : public GeometryOwner { + + bool active; + Vector surfaces; + int morph_target_count; + VS::MorphTargetMode morph_target_mode; + AABB custom_aabb; + mutable uint64_t last_pass; + Mesh() { + morph_target_mode=VS::MORPH_MODE_NORMALIZED; + morph_target_count=0; + last_pass=0; + active=false; + } + }; + + mutable RID_Owner mesh_owner; + virtual RID mesh_create(); - virtual void mesh_add_surface(RID p_mesh,uint32_t p_format,VS::PrimitiveType p_primitive,const DVector& p_array,int p_vertex_count,const DVector& p_index_array,int p_index_count,const Vector >& p_blend_shapes=Vector >()); + virtual void mesh_add_surface(RID p_mesh,uint32_t p_format,VS::PrimitiveType p_primitive,const DVector& p_array,int p_vertex_count,const DVector& p_index_array,int p_index_count,const AABB& p_aabb,const Vector >& p_blend_shapes=Vector >(),const Vector& p_bone_aabbs=Vector()); virtual void mesh_set_morph_target_count(RID p_mesh,int p_amount); virtual int mesh_get_morph_target_count(RID p_mesh) const; @@ -324,13 +511,13 @@ public: virtual uint32_t mesh_surface_get_format(RID p_mesh, int p_surface) const; virtual VS::PrimitiveType mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const; - virtual void mesh_remove_surface(RID p_mesh,int p_index); + virtual void mesh_remove_surface(RID p_mesh, int p_surface); virtual int mesh_get_surface_count(RID p_mesh) const; virtual void mesh_set_custom_aabb(RID p_mesh,const AABB& p_aabb); virtual AABB mesh_get_custom_aabb(RID p_mesh) const; - virtual AABB mesh_get_aabb(RID p_mesh) const; + virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton) const; virtual void mesh_clear(RID p_mesh); /* MULTIMESH API */ @@ -401,6 +588,8 @@ public: virtual void light_directional_set_shadow_mode(RID p_light,VS::LightDirectionalShadowMode p_mode); + virtual VS::LightType light_get_type(RID p_light) const; + virtual AABB light_get_aabb(RID p_light) const; /* PROBE API */ virtual RID reflection_probe_create(); @@ -434,6 +623,9 @@ public: virtual void portal_set_disabled_color(RID p_portal, const Color& p_color); + virtual void instance_add_dependency(RID p_base,RasterizerScene::InstanceBase *p_instance); + virtual void instance_remove_dependency(RID p_base,RasterizerScene::InstanceBase *p_instance); + /* RENDER TARGET */ struct RenderTarget : public RID_Data { @@ -522,6 +714,8 @@ public: virtual RID canvas_light_occluder_create(); virtual void canvas_light_occluder_set_polylines(RID p_occluder, const DVector& p_lines); + virtual VS::InstanceType get_base_type(RID p_rid) const; + virtual bool free(RID p_rid); diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp index 35191fecf7..ebdf60cf42 100644 --- a/drivers/gles3/shader_gles3.cpp +++ b/drivers/gles3/shader_gles3.cpp @@ -662,8 +662,8 @@ void ShaderGLES3::setup(const char** p_conditional_defines, int p_conditional_co fragment_code0=code.ascii(); } else { fragment_code0=code.substr(0,cpos).ascii(); - code = code.substr(cpos+globals_tag.length(),code.length()); - + //print_line("CODE0:\n"+String(fragment_code0.get_data())); + code = code.substr(cpos+globals_tag.length(),code.length()); cpos = code.find(material_tag); if (cpos==-1) { @@ -671,14 +671,18 @@ void ShaderGLES3::setup(const char** p_conditional_defines, int p_conditional_co } else { fragment_code1=code.substr(0,cpos).ascii(); - String code2 = code.substr(cpos+material_tag.length(),code.length()); + //print_line("CODE1:\n"+String(fragment_code1.get_data())); + String code2 = code.substr(cpos+material_tag.length(),code.length()); cpos = code2.find(code_tag); + if (cpos==-1) { fragment_code2=code2.ascii(); } else { fragment_code2=code2.substr(0,cpos).ascii(); + //print_line("CODE2:\n"+String(fragment_code2.get_data())); + String code3 = code2.substr(cpos+code_tag.length(),code2.length()); cpos = code3.find(light_code_tag); @@ -687,7 +691,9 @@ void ShaderGLES3::setup(const char** p_conditional_defines, int p_conditional_co } else { fragment_code3=code3.substr(0,cpos).ascii(); + // print_line("CODE3:\n"+String(fragment_code3.get_data())); fragment_code4 = code3.substr(cpos+light_code_tag.length(),code3.length()).ascii(); + //print_line("CODE4:\n"+String(fragment_code4.get_data())); } } } diff --git a/drivers/gles3/shaders/SCsub b/drivers/gles3/shaders/SCsub index 628fa14e4e..0fa0e3b73a 100644 --- a/drivers/gles3/shaders/SCsub +++ b/drivers/gles3/shaders/SCsub @@ -4,4 +4,5 @@ if env['BUILDERS'].has_key('GLES3_GLSL'): env.GLES3_GLSL('copy.glsl'); env.GLES3_GLSL('canvas.glsl'); env.GLES3_GLSL('canvas_shadow.glsl'); + env.GLES3_GLSL('scene.glsl'); diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl new file mode 100644 index 0000000000..4183e828f5 --- /dev/null +++ b/drivers/gles3/shaders/scene.glsl @@ -0,0 +1,351 @@ +[vertex] + + + +/* +from VisualServer: + +ARRAY_VERTEX=0, +ARRAY_NORMAL=1, +ARRAY_TANGENT=2, +ARRAY_COLOR=3, +ARRAY_TEX_UV=4, +ARRAY_TEX_UV2=5, +ARRAY_BONES=6, +ARRAY_WEIGHTS=7, +ARRAY_INDEX=8, +*/ + +//hack to use uv if no uv present so it works with lightmap + + +/* INPUT ATTRIBS */ + +layout(location=0) in highp vec4 vertex_attrib; +layout(location=1) in vec3 normal_attrib; +layout(location=2) in vec4 tangent_attrib; +layout(location=3) in vec4 color_attrib; +layout(location=4) in vec2 uv_attrib; +layout(location=5) in vec2 uv2_attrib; + +uniform float normal_mult; + +#ifdef USE_SKELETON +layout(location=6) mediump ivec4 bone_indices; // attrib:6 +layout(location=7) mediump vec4 bone_weights; // attrib:7 +uniform highp sampler2D skeleton_matrices; +#endif + +#ifdef USE_ATTRIBUTE_INSTANCING + +layout(location=8) in highp vec4 instance_xform0; +layout(location=9) in highp vec4 instance_xform1; +layout(location=10) in highp vec4 instance_xform2; +layout(location=11) in lowp vec4 instance_color; + +#endif + +layout(std140) uniform SceneData { //ubo:0 + + highp mat4 projection_matrix; + highp mat4 camera_inverse_matrix; + highp mat4 camera_matrix; + highp vec4 time; + + highp vec4 ambient_light; +}; + +uniform highp mat4 world_transform; + +/* Varyings */ + +out vec3 vertex_interp; +out vec3 normal_interp; + +#if defined(ENABLE_COLOR_INTERP) +out vec4 color_interp; +#endif + +#if defined(ENABLE_UV_INTERP) +out vec2 uv_interp; +#endif + +#if defined(ENABLE_UV2_INTERP) +out vec2 uv2_interp; +#endif + +#if defined(ENABLE_VAR1_INTERP) +out vec4 var1_interp; +#endif + +#if defined(ENABLE_VAR2_INTERP) +out vec4 var2_interp; +#endif + +#if defined(ENABLE_TANGENT_INTERP) +out vec3 tangent_interp; +out vec3 binormal_interp; +#endif + + +#if !defined(USE_DEPTH_SHADOWS) && defined(USE_SHADOW_PASS) + +varying vec4 position_interp; + +#endif + +#ifdef USE_SHADOW_PASS + +uniform highp float shadow_z_offset; +uniform highp float shadow_z_slope_scale; + +#endif + + +VERTEX_SHADER_GLOBALS + + +#if defined(USE_MATERIAL) + +layout(std140) uniform UniformData { //ubo:1 + +MATERIAL_UNIFORMS + +}; + +#endif + + +void main() { + + highp vec4 vertex_in = vertex_attrib; // vec4(vertex_attrib.xyz * data_attrib.x,1.0); + highp mat4 modelview = camera_inverse_matrix * world_transform; + vec3 normal_in = normal_attrib; + normal_in*=normal_mult; +#if defined(ENABLE_TANGENT_INTERP) + vec3 tangent_in = tangent_attrib.xyz; + tangent_in*=normal_mult; + float binormalf = tangent_attrib.a; +#endif + +#ifdef USE_SKELETON + + { + //skeleton transform + highp mat4 m=mat4(texture2D(skeleton_matrices,vec2((bone_indices.x*3.0+0.0)*skeltex_pixel_size,0.0)),texture2D(skeleton_matrices,vec2((bone_indices.x*3.0+1.0)*skeltex_pixel_size,0.0)),texture2D(skeleton_matrices,vec2((bone_indices.x*3.0+2.0)*skeltex_pixel_size,0.0)),vec4(0.0,0.0,0.0,1.0))*bone_weights.x; + m+=mat4(texture2D(skeleton_matrices,vec2((bone_indices.y*3.0+0.0)*skeltex_pixel_size,0.0)),texture2D(skeleton_matrices,vec2((bone_indices.y*3.0+1.0)*skeltex_pixel_size,0.0)),texture2D(skeleton_matrices,vec2((bone_indices.y*3.0+2.0)*skeltex_pixel_size,0.0)),vec4(0.0,0.0,0.0,1.0))*bone_weights.y; + m+=mat4(texture2D(skeleton_matrices,vec2((bone_indices.z*3.0+0.0)*skeltex_pixel_size,0.0)),texture2D(skeleton_matrices,vec2((bone_indices.z*3.0+1.0)*skeltex_pixel_size,0.0)),texture2D(skeleton_matrices,vec2((bone_indices.z*3.0+2.0)*skeltex_pixel_size,0.0)),vec4(0.0,0.0,0.0,1.0))*bone_weights.z; + m+=mat4(texture2D(skeleton_matrices,vec2((bone_indices.w*3.0+0.0)*skeltex_pixel_size,0.0)),texture2D(skeleton_matrices,vec2((bone_indices.w*3.0+1.0)*skeltex_pixel_size,0.0)),texture2D(skeleton_matrices,vec2((bone_indices.w*3.0+2.0)*skeltex_pixel_size,0.0)),vec4(0.0,0.0,0.0,1.0))*bone_weights.w; + + vertex_in = vertex_in * m; + normal_in = (vec4(normal_in,0.0) * m).xyz; +#if defined(ENABLE_TANGENT_INTERP) + tangent_in = (vec4(tangent_in,0.0) * m).xyz; +#endif + } + +#endif + + vertex_interp = (modelview * vertex_in).xyz; + normal_interp = normalize((modelview * vec4(normal_in,0.0)).xyz); + +#if defined(ENABLE_TANGENT_INTERP) + tangent_interp=normalize((modelview * vec4(tangent_in,0.0)).xyz); + binormal_interp = normalize( cross(normal_interp,tangent_interp) * binormalf ); +#endif + +#if defined(ENABLE_COLOR_INTERP) + color_interp = color_attrib; +#endif + +#if defined(ENABLE_UV_INTERP) + uv_interp = uv_attrib; +#endif +#if defined(ENABLE_UV2_INTERP) + uv2_interp = uv2_attrib; +#endif + + +VERTEX_SHADER_CODE + + +#ifdef USE_SHADOW_PASS + + float z_ofs = shadow_z_offset; + z_ofs += (1.0-abs(normal_interp.z))*shadow_z_slope_scale; + vertex_interp.z-=z_ofs; +#endif + + +#ifdef USE_FOG + + fog_interp.a = pow( clamp( (length(vertex_interp)-fog_params.x)/(fog_params.y-fog_params.x), 0.0, 1.0 ), fog_params.z ); + fog_interp.rgb = mix( fog_color_begin, fog_color_end, fog_interp.a ); +#endif + +#ifndef VERTEX_SHADER_WRITE_POSITION +//vertex shader might write a position + gl_Position = projection_matrix * vec4(vertex_interp,1.0); +#endif + + + + +} + + +[fragment] + + +//hack to use uv if no uv present so it works with lightmap + + +/* Varyings */ + +#if defined(ENABLE_COLOR_INTERP) +in vec4 color_interp; +#endif + +#if defined(ENABLE_UV_INTERP) +in vec2 uv_interp; +#endif + +#if defined(ENABLE_UV2_INTERP) +in vec2 uv2_interp; +#endif + +#if defined(ENABLE_TANGENT_INTERP) +in vec3 tangent_interp; +in vec3 binormal_interp; +#endif + +#if defined(ENABLE_VAR1_INTERP) +in vec4 var1_interp; +#endif + +#if defined(ENABLE_VAR2_INTERP) +in vec4 var2_interp; +#endif + +in vec3 vertex_interp; +in vec3 normal_interp; + + +/* Material Uniforms */ + + +FRAGMENT_SHADER_GLOBALS + + +#if defined(USE_MATERIAL) + +layout(std140) uniform UniformData { + +MATERIAL_UNIFORMS + +}; + +#endif + + +layout(std140) uniform SceneData { + + highp mat4 projection_matrix; + highp mat4 camera_inverse_matrix; + highp mat4 camera_matrix; + highp vec4 time; + + highp vec4 ambient_light; +}; + +layout(location=0) out vec4 frag_color; + +void main() { + + //lay out everything, whathever is unused is optimized away anyway + vec3 vertex = vertex_interp; + vec3 albedo = vec3(0.9,0.9,0.9); + vec3 metal = vec3(0.0,0.0,0.0); + float rough = 0.0; + float alpha = 1.0; + +#ifdef METERIAL_DOUBLESIDED + float side=float(gl_FrontFacing)*2.0-1.0; +#else + float side=1.0; +#endif + + +#if defined(ENABLE_TANGENT_INTERP) + vec3 binormal = normalize(binormal_interp)*side; + vec3 tangent = normalize(tangent_interp)*side; +#endif + vec3 normal = normalize(normal_interp)*side; + +#if defined(ENABLE_UV_INTERP) + vec2 uv = uv_interp; +#endif + +#if defined(ENABLE_UV2_INTERP) + vec2 uv2 = uv2_interp; +#endif + +#if defined(ENABLE_COLOR_INTERP) + vec4 color = color_interp; +#endif + +#if defined(ENABLE_NORMALMAP) + + vec3 normalmap = vec3(0.0); +#endif + + float normaldepth=1.0; + + + +#if defined(ENABLE_DISCARD) + bool discard_=false; +#endif + +{ + + +FRAGMENT_SHADER_CODE + +} + +#if defined(ENABLE_NORMALMAP) + + normal = normalize( mix(normal_interp,tangent_interp * normalmap.x + binormal_interp * normalmap.y + normal_interp * normalmap.z,normaldepth) ) * side; + +#endif + +#if defined(ENABLE_DISCARD) + if (discard_) { + //easy to eliminate dead code + discard; + } +#endif + +#ifdef ENABLE_CLIP_ALPHA + if (diffuse.a<0.99) { + //used for doublepass and shadowmapping + discard; + } +#endif + + + +#if defined(USE_LIGHT_SHADER_CODE) +//light is written by the light shader +{ + +LIGHT_SHADER_CODE + +} +#endif + + frag_color=vec4(albedo,alpha); +} + + -- cgit v1.2.3 From cb34b70df13ad9f7942b0c363edc71cfd417bb21 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Fri, 21 Oct 2016 07:27:13 -0300 Subject: More scene work, can display a skybox --- drivers/gles3/rasterizer_canvas_gles3.cpp | 1 - drivers/gles3/rasterizer_scene_gles3.cpp | 225 ++++++++++++++++++++++++++++- drivers/gles3/rasterizer_scene_gles3.h | 66 ++++++++- drivers/gles3/rasterizer_storage_gles3.cpp | 137 ++++++++++++++++++ drivers/gles3/rasterizer_storage_gles3.h | 8 + drivers/gles3/shaders/SCsub | 1 + drivers/gles3/shaders/copy.glsl | 17 ++- drivers/gles3/shaders/cubemap_filter.glsl | 143 ++++++++++++++++++ 8 files changed, 590 insertions(+), 8 deletions(-) create mode 100644 drivers/gles3/shaders/cubemap_filter.glsl (limited to 'drivers/gles3') diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index 237b3ec3fc..b2228a6cfa 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -117,7 +117,6 @@ void RasterizerCanvasGLES3::canvas_begin(){ 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 ); glClear(GL_COLOR_BUFFER_BIT); storage->frame.clear_request=false; - print_line("canvas clear?"); } diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 121620594d..4ce2bd2f37 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -1,5 +1,10 @@ #include "rasterizer_scene_gles3.h" #include "globals.h" + + + + + static _FORCE_INLINE_ void store_matrix32(const Matrix32& p_mtx, float* p_array) { p_array[ 0]=p_mtx.elements[0][0]; @@ -52,6 +57,121 @@ static _FORCE_INLINE_ void store_camera(const CameraMatrix& p_mtx, float* p_arra + +/* ENVIRONMENT API */ + +RID RasterizerSceneGLES3::environment_create(){ + + + Environment *env = memnew( Environment ); + + return environment_owner.make_rid(env); +} + +void RasterizerSceneGLES3::environment_set_background(RID p_env,VS::EnvironmentBG p_bg){ + + Environment *env=environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + env->bg_mode=p_bg; +} + +void RasterizerSceneGLES3::environment_set_skybox(RID p_env, RID p_skybox, int p_radiance_size, int p_irradiance_size){ + + Environment *env=environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + + if (env->skybox_color.is_valid()) { + env->skybox_color=RID(); + } + if (env->skybox_radiance.is_valid()) { + storage->free(env->skybox_radiance); + env->skybox_radiance=RID(); + } + if (env->skybox_irradiance.is_valid()) { + storage->free(env->skybox_irradiance); + env->skybox_irradiance=RID(); + } + + if (p_skybox.is_valid()) { + + env->skybox_color=p_skybox; + // env->skybox_radiance=storage->texture_create_pbr_cubemap(p_skybox,VS::PBR_CUBEMAP_RADIANCE,p_radiance_size); + //env->skybox_irradiance=storage->texture_create_pbr_cubemap(p_skybox,VS::PBR_CUBEMAP_IRRADIANCE,p_irradiance_size); + } + +} + +void RasterizerSceneGLES3::environment_set_skybox_scale(RID p_env,float p_scale) { + + Environment *env=environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + + env->skybox_scale=p_scale; + +} + +void RasterizerSceneGLES3::environment_set_bg_color(RID p_env,const Color& p_color){ + + Environment *env=environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + + env->bg_color=p_color; + +} +void RasterizerSceneGLES3::environment_set_bg_energy(RID p_env,float p_energy) { + + Environment *env=environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + + env->energy=p_energy; + +} + +void RasterizerSceneGLES3::environment_set_canvas_max_layer(RID p_env,int p_max_layer){ + + Environment *env=environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + + env->canvas_max_layer=p_max_layer; + +} +void RasterizerSceneGLES3::environment_set_ambient_light(RID p_env, const Color& p_color, float p_energy, float p_skybox_energy){ + + Environment *env=environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + + env->ambient_color=p_color; + env->ambient_anergy=p_energy; + env->skybox_ambient=p_skybox_energy; + +} + +void RasterizerSceneGLES3::environment_set_glow(RID p_env,bool p_enable,int p_radius,float p_intensity,float p_strength,float p_bloom_treshold,VS::EnvironmentGlowBlendMode p_blend_mode){ + +} +void RasterizerSceneGLES3::environment_set_fog(RID p_env,bool p_enable,float p_begin,float p_end,RID p_gradient_texture){ + +} + +void RasterizerSceneGLES3::environment_set_tonemap(RID p_env,bool p_enable,float p_exposure,float p_white,float p_min_luminance,float p_max_luminance,float p_auto_exp_speed,VS::EnvironmentToneMapper p_tone_mapper){ + +} +void RasterizerSceneGLES3::environment_set_brightness(RID p_env,bool p_enable,float p_brightness){ + +} +void RasterizerSceneGLES3::environment_set_contrast(RID p_env,bool p_enable,float p_contrast){ + +} +void RasterizerSceneGLES3::environment_set_saturation(RID p_env,bool p_enable,float p_saturation){ + +} +void RasterizerSceneGLES3::environment_set_color_correction(RID p_env,bool p_enable,RID p_ramp){ + +} + + + + RID RasterizerSceneGLES3::light_instance_create(RID p_light) { @@ -493,6 +613,70 @@ void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_g #endif } +void RasterizerSceneGLES3::_draw_skybox(RID p_skybox,CameraMatrix& p_projection,const Transform& p_transform,bool p_vflip,float p_scale) { + + RasterizerStorageGLES3::Texture *tex = storage->texture_owner.getornull(p_skybox); + + ERR_FAIL_COND(!tex); + glActiveTexture(GL_TEXTURE0); + glBindTexture(tex->target,tex->tex_id); + + glDepthMask(GL_TRUE); + glEnable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + glDisable(GL_BLEND); + glColorMask(1,1,1,1); + + float flip_sign = p_vflip?-1:1; + + Vector3 vertices[8]={ + Vector3(-1,-1*flip_sign,0.1), + Vector3( 0, 1, 0), + Vector3( 1,-1*flip_sign,0.1), + Vector3( 1, 1, 0), + Vector3( 1, 1*flip_sign,0.1), + Vector3( 1, 0, 0), + Vector3(-1, 1*flip_sign,0.1), + Vector3( 0, 0, 0), + + }; + + + + //skybox uv vectors + float vw,vh,zn; + p_projection.get_viewport_size(vw,vh); + zn=p_projection.get_z_near(); + + float scale=p_scale; + + for(int i=0;i<4;i++) { + + Vector3 uv=vertices[i*2+1]; + uv.x=(uv.x*2.0-1.0)*vw*scale; + uv.y=-(uv.y*2.0-1.0)*vh*scale; + uv.z=-zn; + vertices[i*2+1] = p_transform.basis.xform(uv).normalized(); + vertices[i*2+1].z = -vertices[i*2+1].z; + } + + glBindBuffer(GL_ARRAY_BUFFER,state.skybox_verts); + glBufferSubData(GL_ARRAY_BUFFER,0,sizeof(Vector3)*8,vertices); + glBindBuffer(GL_ARRAY_BUFFER,0); //unbind + + glBindVertexArray(state.skybox_array); + + storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_CUBEMAP,true); + storage->shaders.copy.bind(); + + glDrawArrays(GL_TRIANGLE_FAN,0,4); + + glBindVertexArray(0); + + storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_CUBEMAP,false); + +} + void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,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_directional_lights,int p_directional_light_count,RID p_environment){ @@ -561,7 +745,9 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,CameraM glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->front.fbo); - if (true) { + Environment *env = environment_owner.getornull(p_environment); + + if (!env || env->bg_mode==VS::ENV_BG_CLEAR_COLOR) { if (storage->frame.clear_request) { @@ -570,6 +756,16 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,CameraM storage->frame.clear_request=false; } + } else if (env->bg_mode==VS::ENV_BG_COLOR) { + + + glClearColor( env->bg_color.r, env->bg_color.g, env->bg_color.b, env->bg_color.a ); + glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + storage->frame.clear_request=false; + } else { + glClear(GL_DEPTH_BUFFER_BIT); + storage->frame.clear_request=false; + } state.current_depth_test=true; @@ -616,6 +812,12 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,CameraM _render_list(render_list.elements,render_list.element_count,p_cam_transform,p_cam_projection,false,false); + + if (env && env->bg_mode==VS::ENV_BG_SKYBOX) { + + _draw_skybox(env->skybox_color,p_cam_projection,p_cam_transform,storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP],env->skybox_scale); + } + //_render_list_forward(&alpha_render_list,camera_transform,camera_transform_inverse,camera_projection,false,fragment_lighting,true); //glColorMask(1,1,1,1); @@ -793,6 +995,27 @@ void RasterizerSceneGLES3::initialize() { if (render_list.max_elements<1024) render_list.max_elements=1024; + + + { + //quad buffers + + glGenBuffers(1,&state.skybox_verts); + glBindBuffer(GL_ARRAY_BUFFER,state.skybox_verts); + glBufferData(GL_ARRAY_BUFFER,sizeof(Vector3)*8,NULL,GL_DYNAMIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER,0); //unbind + + + glGenVertexArrays(1,&state.skybox_array); + glBindVertexArray(state.skybox_array); + glBindBuffer(GL_ARRAY_BUFFER,state.skybox_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)); + glEnableVertexAttribArray(VS::ARRAY_TEX_UV); + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER,0); //unbind + } render_list.init(); } diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 6fba777fc8..53088deb0d 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -16,8 +16,6 @@ public: RasterizerStorageGLES3 *storage; - - struct State { bool current_depth_test; @@ -40,10 +38,70 @@ public: GLuint scene_ubo; - + GLuint skybox_verts; + GLuint skybox_array; } state; + + + + /* ENVIRONMENT API */ + + struct Environment : public RID_Data { + + VS::EnvironmentBG bg_mode; + + RID skybox_color; + RID skybox_radiance; + RID skybox_irradiance; + float skybox_scale; + + Color bg_color; + float energy; + float skybox_ambient; + + Color ambient_color; + float ambient_anergy; + float ambient_skybox_energy; + + int canvas_max_layer; + + + Environment() { + bg_mode=VS::ENV_BG_CLEAR_COLOR; + skybox_scale=1.0; + energy=1.0; + skybox_ambient=0; + ambient_anergy=1.0; + ambient_skybox_energy=0.0; + canvas_max_layer=0; + } + }; + + RID_Owner environment_owner; + + virtual RID environment_create(); + + virtual void environment_set_background(RID p_env,VS::EnvironmentBG p_bg); + virtual void environment_set_skybox(RID p_env,RID p_skybox,int p_radiance_size,int p_irradiance_size); + virtual void environment_set_skybox_scale(RID p_env,float p_scale); + 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_skybox_energy=0.0); + + virtual void environment_set_glow(RID p_env,bool p_enable,int p_radius,float p_intensity,float p_strength,float p_bloom_treshold,VS::EnvironmentGlowBlendMode p_blend_mode); + 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_tonemap(RID p_env,bool p_enable,float p_exposure,float p_white,float p_min_luminance,float p_max_luminance,float p_auto_exp_speed,VS::EnvironmentToneMapper p_tone_mapper); + virtual void environment_set_brightness(RID p_env,bool p_enable,float p_brightness); + virtual void environment_set_contrast(RID p_env,bool p_enable,float p_contrast); + virtual void environment_set_saturation(RID p_env,bool p_enable,float p_saturation); + virtual void environment_set_color_correction(RID p_env,bool p_enable,RID p_ramp); + + /* RENDER LIST */ + struct RenderList { enum { @@ -166,6 +224,8 @@ public: _FORCE_INLINE_ void _add_geometry( RasterizerStorageGLES3::Geometry* p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner,int p_material); + void _draw_skybox(RID p_skybox, CameraMatrix& p_projection, const Transform& p_transform, bool p_vflip, float p_scale); + virtual void render_scene(const Transform& p_cam_transform,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_directional_lights,int p_directional_light_count,RID p_environment); virtual bool free(RID p_rid); diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index f633ef21cc..94ad2afabe 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -995,6 +995,104 @@ void RasterizerStorageGLES3::texture_set_shrink_all_x2_on_set_data(bool p_enable config.shrink_textures_x2=p_enable; } +RID RasterizerStorageGLES3::texture_create_pbr_cubemap(RID p_source,VS::PBRCubeMapMode p_mode,int p_resolution) const { + + Texture * texture = texture_owner.get(p_source); + ERR_FAIL_COND_V(!texture,RID()); + ERR_FAIL_COND_V(!(texture->flags&VS::TEXTURE_FLAG_CUBEMAP),RID()); + + bool use_float=true; + + if (p_resolution<0) { + p_resolution=texture->width; + } + + + glBindVertexArray(0); + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glDisable(GL_SCISSOR_TEST); +#ifdef GLEW_ENABLED + glDisable(GL_POINT_SPRITE); + glDisable(GL_VERTEX_PROGRAM_POINT_SIZE); +#endif + glDisable(GL_BLEND); + + + glActiveTexture(GL_TEXTURE1); + glBindTexture(texture->target, texture->tex_id); + + glActiveTexture(GL_TEXTURE0); + GLuint new_cubemap; + glGenTextures(1, &new_cubemap); + + + GLuint tmp_fb; + + glGenFramebuffers(1, &tmp_fb); + glBindFramebuffer(GL_FRAMEBUFFER, tmp_fb); + + + int w = texture->width; + int h = texture->height; + + int lod=0; + + shaders.cubemap_filter.bind(); + + int mipmaps=6; + + int mm_level=mipmaps; + + while(mm_level) { + + for(int i=0;i<6;i++) { + glTexImage2D(_cube_side_enum[i], lod, use_float?GL_RGBA16F:GL_RGB10_A2, w, h, 0, GL_RGBA, use_float?GL_HALF_FLOAT:GL_UNSIGNED_INT_2_10_10_10_REV, NULL); + glTexParameteri(_cube_side_enum[i], GL_TEXTURE_BASE_LEVEL, lod); + glTexParameteri(_cube_side_enum[i], GL_TEXTURE_MAX_LEVEL, lod); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, _cube_side_enum[i], new_cubemap, 0); + + glViewport(0,0,w,h); + glBindVertexArray(resources.quadie_array); + + shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::FACE_ID,i); + shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::ROUGHNESS,lod/float(mipmaps)); + + + glDrawArrays(GL_TRIANGLE_FAN,0,4); + glBindVertexArray(0); +#ifdef DEBUG_ENABLED + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + ERR_CONTINUE(status!=GL_FRAMEBUFFER_COMPLETE); +#endif + } + + + + if (w>1) + w>>=1; + if (h>1) + h>>=1; + + lod++; + mm_level--; + + } + + + for(int i=0;i<6;i++) { + //restore ranges + glTexParameteri(_cube_side_enum[i], GL_TEXTURE_BASE_LEVEL, 0); + glTexParameteri(_cube_side_enum[i], GL_TEXTURE_MAX_LEVEL, lod); + + } + + glBindFramebuffer(GL_FRAMEBUFFER, config.system_fbo); + glDeleteFramebuffers(1, &tmp_fb); + + + return RID(); +} /* SHADER API */ @@ -3649,6 +3747,45 @@ void RasterizerStorageGLES3::initialize() { #else config.use_rgba_2d_shadows=true; #endif + + + //generic quadie for copying + + { + //quad buffers + + glGenBuffers(1,&resources.quadie); + glBindBuffer(GL_ARRAY_BUFFER,resources.quadie); + { + const float qv[16]={ + -1,-1, + 0, 0, + -1, 1, + 0, 1, + 1, 1, + 1, 1, + 1,-1, + 1, 0, + }; + + glBufferData(GL_ARRAY_BUFFER,sizeof(float)*16,qv,GL_STATIC_DRAW); + } + + glBindBuffer(GL_ARRAY_BUFFER,0); //unbind + + + glGenVertexArrays(1,&resources.quadie_array); + glBindVertexArray(resources.quadie_array); + glBindBuffer(GL_ARRAY_BUFFER,resources.quadie); + glVertexAttribPointer(0,2,GL_FLOAT,GL_FALSE,sizeof(float)*4,0); + glEnableVertexAttribArray(0); + glVertexAttribPointer(1,2,GL_FLOAT,GL_FALSE,sizeof(float)*4,((uint8_t*)NULL)+8); + glEnableVertexAttribArray(1); + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER,0); //unbind + } + + shaders.cubemap_filter.init(); } void RasterizerStorageGLES3::finalize() { diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index 950d65b9d0..c3022b3ac0 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -6,6 +6,7 @@ #include "shader_gles3.h" #include "shaders/copy.glsl.h" #include "shaders/canvas.glsl.h" +#include "shaders/cubemap_filter.glsl.h" #include "self_list.h" #include "shader_compiler_gles3.h" @@ -60,6 +61,8 @@ public: ShaderCompilerGLES3 compiler; + CubemapFilterShaderGLES3 cubemap_filter; + ShaderCompilerGLES3::IdentifierActions actions_canvas; ShaderCompilerGLES3::IdentifierActions actions_scene; } shaders; @@ -70,6 +73,9 @@ public: GLuint black_tex; GLuint normal_tex; + GLuint quadie; + GLuint quadie_array; + } resources; struct Info { @@ -178,6 +184,8 @@ public: virtual void texture_debug_usage(List *r_info); + virtual RID texture_create_pbr_cubemap(RID p_source,VS::PBRCubeMapMode p_mode,int p_resolution=-1) const; + /* SHADER API */ diff --git a/drivers/gles3/shaders/SCsub b/drivers/gles3/shaders/SCsub index 0fa0e3b73a..afffe10316 100644 --- a/drivers/gles3/shaders/SCsub +++ b/drivers/gles3/shaders/SCsub @@ -5,4 +5,5 @@ if env['BUILDERS'].has_key('GLES3_GLSL'): env.GLES3_GLSL('canvas.glsl'); env.GLES3_GLSL('canvas_shadow.glsl'); env.GLES3_GLSL('scene.glsl'); + env.GLES3_GLSL('cubemap_filter.glsl'); diff --git a/drivers/gles3/shaders/copy.glsl b/drivers/gles3/shaders/copy.glsl index aba280186a..eb58d66431 100644 --- a/drivers/gles3/shaders/copy.glsl +++ b/drivers/gles3/shaders/copy.glsl @@ -33,20 +33,31 @@ void main() { #ifdef USE_CUBEMAP in vec3 cube_interp; -uniform samplerCube source_cube; +uniform samplerCube source_cube; //texunit:0 #else in vec2 uv_interp; -uniform sampler2D source; +uniform sampler2D source; //texunit:0 #endif + +uniform float stuff; + in vec2 uv2_interp; -layout(location = 0) vec4 frag_color; //color:0 +layout(location = 0) out vec4 frag_color; void main() { //vec4 color = color_interp; +#ifdef USE_CUBEMAP + vec4 color = texture( source_cube, normalize(cube_interp) ); + +#else + vec4 color = texture( source, uv_interp ); +#endif + + frag_color = color; } diff --git a/drivers/gles3/shaders/cubemap_filter.glsl b/drivers/gles3/shaders/cubemap_filter.glsl new file mode 100644 index 0000000000..f450f34113 --- /dev/null +++ b/drivers/gles3/shaders/cubemap_filter.glsl @@ -0,0 +1,143 @@ +[vertex] + + +layout(location=0) in highp vec2 vertex; + +layout(location=1) in highp vec2 uv; + +out highp vec2 uv_interp; + +void main() { + + uv_interp=uv; + gl_Position=vec4(vertex,0,1); +} + +[fragment] + + +uniform samplerCube source_cube; //texunit:1 +uniform int face_id; +uniform float roughness; +in highp vec2 uv_interp; + + +layout(location = 0) vec4 frag_color; + + +vec3 texelCoordToVec(vec2 uv, int faceID) +{ + mat3 faceUvVectors[6]; + + // -x + faceUvVectors[1][0] = vec3(0.0, 0.0, 1.0); // u -> +z + faceUvVectors[1][1] = vec3(0.0, -1.0, 0.0); // v -> -y + faceUvVectors[1][2] = vec3(-1.0, 0.0, 0.0); // -x face + + // +x + faceUvVectors[0][0] = vec3(0.0, 0.0, -1.0); // u -> -z + faceUvVectors[0][1] = vec3(0.0, -1.0, 0.0); // v -> -y + faceUvVectors[0][2] = vec3(1.0, 0.0, 0.0); // +x face + + // -y + faceUvVectors[3][0] = vec3(1.0, 0.0, 0.0); // u -> +x + faceUvVectors[3][1] = vec3(0.0, 0.0, -1.0); // v -> -z + faceUvVectors[3][2] = vec3(0.0, -1.0, 0.0); // -y face + + // +y + faceUvVectors[2][0] = vec3(1.0, 0.0, 0.0); // u -> +x + faceUvVectors[2][1] = vec3(0.0, 0.0, 1.0); // v -> +z + faceUvVectors[2][2] = vec3(0.0, 1.0, 0.0); // +y face + + // -z + faceUvVectors[5][0] = vec3(-1.0, 0.0, 0.0); // u -> -x + faceUvVectors[5][1] = vec3(0.0, -1.0, 0.0); // v -> -y + faceUvVectors[5][2] = vec3(0.0, 0.0, -1.0); // -z face + + // +z + faceUvVectors[4][0] = vec3(1.0, 0.0, 0.0); // u -> +x + faceUvVectors[4][1] = vec3(0.0, -1.0, 0.0); // v -> -y + faceUvVectors[4][2] = vec3(0.0, 0.0, 1.0); // +z face + + // out = u * s_faceUv[0] + v * s_faceUv[1] + s_faceUv[2]. + vec3 result = (faceUvVectors[faceID][0] * uv.x) + (faceUvVectors[faceID][1] * uv.y) + faceUvVectors[faceID][2]; + return normalize(result); +} + +vec3 ImportanceSampleGGX(vec2 Xi, float Roughness, vec3 N) +{ + float a = Roughness * Roughness; // DISNEY'S ROUGHNESS [see Burley'12 siggraph] + + // Compute distribution direction + float Phi = 2.0 * M_PI * Xi.x; + float CosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y)); + float SinTheta = sqrt(1.0 - CosTheta * CosTheta); + + // Convert to spherical direction + vec3 H; + H.x = SinTheta * cos(Phi); + H.y = SinTheta * sin(Phi); + H.z = CosTheta; + + vec3 UpVector = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); + vec3 TangentX = normalize(cross(UpVector, N)); + vec3 TangentY = cross(N, TangentX); + + // Tangent to world space + return TangentX * H.x + TangentY * H.y + N * H.z; +} + +// http://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html +float GGX(float NdotV, float a) +{ + float k = a / 2.0; + return NdotV / (NdotV * (1.0 - k) + k); +} + +// http://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html +float G_Smith(float a, float nDotV, float nDotL) +{ + return GGX(nDotL, a * a) * GGX(nDotV, a * a); +} + +float radicalInverse_VdC(uint bits) { + bits = (bits << 16u) | (bits >> 16u); + bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); + bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); + bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); + bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); + return float(bits) * 2.3283064365386963e-10; // / 0x100000000 +} + +vec2 Hammersley(uint i, uint N) { + return vec2(float(i)/float(N), radicalInverse_VdC(i)); +} + +#define SAMPLE_COUNT 1024 + +void main() { + + vec2 uv = (uv_interp * 2.0) - 1.0; + vec3 N = texelCoordToVec(uv, face_id); + + //vec4 color = color_interp; + vec4 sum = vec4(0.0, 0.0, 0.0, 0.0); + + for(int sampleNum = 0; sampleNum < SAMPLE_COUNT; sampleNum++) { + vec2 xi = Hammersley(sampleNum, SAMPLE_COUNT); + vec2 xi = texture2DLod(Texture0, vec2(float(sampleNum) / float(SAMPLE_COUNT), 0.5), 0.0).xy; + + vec3 H = ImportanceSampleGGX( xi, roughness, N ); + vec3 V = N; + vec3 L = normalize(2.0 * dot( V, H ) * H - V); + + float ndotl = max(0.0, dot(N, L)); + vec3 s = textureCubeLod(u_skyCube, H, 0.0).rgb * ndotl; + + sum += vec4(s, 1.0); + } + sum /= sum.w; + + frag_color = vec4(sum.rgb, 1.0); +} + -- cgit v1.2.3 From 53d8f2b1ec1d86b189800b7fe156c464fdf9e380 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Thu, 27 Oct 2016 11:50:26 -0300 Subject: PBR more or less working, still working on bringing gizmos back --- drivers/gles3/rasterizer_scene_gles3.cpp | 709 ++++++++++++++++++++++++++--- drivers/gles3/rasterizer_scene_gles3.h | 138 +++++- drivers/gles3/rasterizer_storage_gles3.cpp | 226 +++++++-- drivers/gles3/rasterizer_storage_gles3.h | 26 +- drivers/gles3/shader_compiler_gles3.cpp | 81 +++- drivers/gles3/shader_gles3.cpp | 1 + drivers/gles3/shader_gles3.h | 1 + drivers/gles3/shaders/cubemap_filter.glsl | 59 ++- drivers/gles3/shaders/scene.glsl | 282 ++++++++++-- 9 files changed, 1343 insertions(+), 180 deletions(-) (limited to 'drivers/gles3') diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 4ce2bd2f37..aadf9e6336 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -75,7 +75,7 @@ void RasterizerSceneGLES3::environment_set_background(RID p_env,VS::EnvironmentB env->bg_mode=p_bg; } -void RasterizerSceneGLES3::environment_set_skybox(RID p_env, RID p_skybox, int p_radiance_size, int p_irradiance_size){ +void RasterizerSceneGLES3::environment_set_skybox(RID p_env, RID p_skybox, int p_radiance_size){ Environment *env=environment_owner.getornull(p_env); ERR_FAIL_COND(!env); @@ -87,15 +87,12 @@ void RasterizerSceneGLES3::environment_set_skybox(RID p_env, RID p_skybox, int p storage->free(env->skybox_radiance); env->skybox_radiance=RID(); } - if (env->skybox_irradiance.is_valid()) { - storage->free(env->skybox_irradiance); - env->skybox_irradiance=RID(); - } + if (p_skybox.is_valid()) { env->skybox_color=p_skybox; - // env->skybox_radiance=storage->texture_create_pbr_cubemap(p_skybox,VS::PBR_CUBEMAP_RADIANCE,p_radiance_size); + env->skybox_radiance=storage->texture_create_radiance_cubemap(p_skybox,p_radiance_size); //env->skybox_irradiance=storage->texture_create_pbr_cubemap(p_skybox,VS::PBR_CUBEMAP_IRRADIANCE,p_irradiance_size); } @@ -123,7 +120,7 @@ void RasterizerSceneGLES3::environment_set_bg_energy(RID p_env,float p_energy) { Environment *env=environment_owner.getornull(p_env); ERR_FAIL_COND(!env); - env->energy=p_energy; + env->bg_energy=p_energy; } @@ -135,14 +132,14 @@ void RasterizerSceneGLES3::environment_set_canvas_max_layer(RID p_env,int p_max_ env->canvas_max_layer=p_max_layer; } -void RasterizerSceneGLES3::environment_set_ambient_light(RID p_env, const Color& p_color, float p_energy, float p_skybox_energy){ +void RasterizerSceneGLES3::environment_set_ambient_light(RID p_env, const Color& p_color, float p_energy, float p_skybox_contribution){ Environment *env=environment_owner.getornull(p_env); ERR_FAIL_COND(!env); env->ambient_color=p_color; - env->ambient_anergy=p_energy; - env->skybox_ambient=p_skybox_energy; + env->ambient_energy=p_energy; + env->ambient_skybox_contribution=p_skybox_contribution; } @@ -174,13 +171,28 @@ void RasterizerSceneGLES3::environment_set_color_correction(RID p_env,bool p_ena RID RasterizerSceneGLES3::light_instance_create(RID p_light) { + LightInstance *light_instance = memnew( LightInstance ); + + light_instance->light=p_light; + light_instance->light_ptr=storage->light_owner.getornull(p_light); + + glGenBuffers(1, &light_instance->light_ubo); + glBindBuffer(GL_UNIFORM_BUFFER, light_instance->light_ubo); + glBufferData(GL_UNIFORM_BUFFER, sizeof(LightInstance::LightDataUBO), NULL, GL_DYNAMIC_DRAW); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + - return RID(); + ERR_FAIL_COND_V(!light_instance->light_ptr,RID()); + + return light_instance_owner.make_rid(light_instance); } void RasterizerSceneGLES3::light_instance_set_transform(RID p_light_instance,const Transform& p_transform){ + LightInstance *light_instance = light_instance_owner.getornull(p_light_instance); + ERR_FAIL_COND(!light_instance); + light_instance->transform=p_transform; } @@ -247,11 +259,13 @@ bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material* p_m //material parameters + state.scene_shader.set_custom_shader(p_material->shader->custom_code_id); bool rebind = state.scene_shader.bind(); if (p_material->ubo_id) { + glBindBufferBase(GL_UNIFORM_BUFFER,1,p_material->ubo_id); } @@ -267,6 +281,7 @@ bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material* p_m RasterizerStorageGLES3::Texture *t = storage->texture_owner.getornull( textures[i] ); if (!t) { //check hints + glBindTexture(GL_TEXTURE_2D,storage->resources.white_tex); continue; } @@ -328,7 +343,14 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) { } -void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_element_count,const Transform& p_view_transform,const CameraMatrix& p_projection,bool p_reverse_cull,bool p_alpha_pass) { +void RasterizerSceneGLES3::_setup_light(LightInstance *p_light) { + + + glBindBufferBase(GL_UNIFORM_BUFFER,3,p_light->light_ubo); //bind light uniform +} + + +void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_element_count,const Transform& p_view_transform,const CameraMatrix& p_projection,RasterizerStorageGLES3::Texture* p_base_env,bool p_reverse_cull,bool p_alpha_pass) { if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP]) { //p_reverse_cull=!p_reverse_cull; @@ -337,8 +359,22 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e glFrontFace(GL_CW); } + bool shadow=false; + glBindBufferBase(GL_UNIFORM_BUFFER,0,state.scene_ubo); //bind globals ubo + + glBindBufferBase(GL_UNIFORM_BUFFER,2,state.env_radiance_ubo); //bind environment radiance info + glActiveTexture(GL_TEXTURE0+storage->config.max_texture_image_units-1); + glBindTexture(GL_TEXTURE_2D,state.brdf_texture); + + if (p_base_env) { + glActiveTexture(GL_TEXTURE0+storage->config.max_texture_image_units-2); + glBindTexture(p_base_env->target,p_base_env->tex_id); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_CUBEMAP,true); + } + + state.scene_shader.set_conditional(SceneShaderGLES3::USE_SKELETON,false); state.current_blend_mode=-1; @@ -349,6 +385,11 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e RasterizerStorageGLES3::Geometry* prev_geometry=NULL; VS::InstanceType prev_base_type = VS::INSTANCE_MAX; + int prev_light_type=-1; + int prev_light_index=-1; + int prev_blend=-1; + int current_blend_mode=-1; + for (int i=0;isort_key>>RenderList::SORT_KEY_LIGHT_TYPE_SHIFT)&0xF; + int light_index=(e->sort_key>>RenderList::SORT_KEY_LIGHT_INDEX_SHIFT)&0xFFFF; + + bool additive=false; + + if (!shadow) { +#if 0 + if (texscreen_used && !texscreen_copied && material->shader_cache && material->shader_cache->valid && material->shader_cache->has_texscreen) { + texscreen_copied=true; + _copy_to_texscreen(); + + //force reset state + prev_material=NULL; + prev_light=0x777E; + prev_geometry_cmp=NULL; + prev_light_type=0xEF; + prev_skeleton =NULL; + prev_sort_flags=0xFF; + prev_morph_values=NULL; + prev_receive_shadows_state=-1; + glEnable(GL_BLEND); + glDepthMask(GL_TRUE); + glEnable(GL_DEPTH_TEST); + glDisable(GL_SCISSOR_TEST); + + } +#endif + if (light_type!=prev_light_type /* || receive_shadows_state!=prev_receive_shadows_state*/) { + + if (material->shader->spatial.unshaded/* || current_debug==VS::SCENARIO_DEBUG_SHADELESS*/) { + state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_LIGHTING,false); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_DIRECTIONAL,false); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_OMNI,false); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_SPOT,false); + state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS,true); + + //state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS,true); + } else { + state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS,false); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_LIGHTING,light_type!=0xF); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_DIRECTIONAL,light_type==VS::LIGHT_DIRECTIONAL); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_OMNI,light_type==VS::LIGHT_OMNI); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_SPOT,light_type==VS::LIGHT_SPOT); + /* + if (receive_shadows_state==1) { + state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_SHADOW,(light_type&0x8)); + state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM,(light_type&0x10)); + state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM4,(light_type&0x20)); + } + else { + state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_SHADOW,false); + state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM,false); + state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM4,false); + } + state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS,false); + */ + } + + rebind=true; + } + + + if (!*e->additive_ptr) { + + additive=false; + *e->additive_ptr=true; + } else { + additive=true; + } + + bool desired_blend=false; + int desired_blend_mode=RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_MIX; + + if (additive) { + desired_blend=true; + desired_blend_mode=RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_ADD; + } else { + desired_blend=p_alpha_pass; + desired_blend_mode=material->shader->spatial.blend_mode; + } + + if (prev_blend!=desired_blend) { + + if (desired_blend) { + glEnable(GL_BLEND); + if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { + glColorMask(1,1,1,0); + } + } else { + glDisable(GL_BLEND); + glColorMask(1,1,1,1); + } + + prev_blend=desired_blend; + } + + if (desired_blend && desired_blend_mode!=current_blend_mode) { + + + switch(desired_blend_mode) { + + case RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_MIX: { + glBlendEquation(GL_FUNC_ADD); + if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } + else { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + + } break; + case RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_ADD: { + + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(p_alpha_pass?GL_SRC_ALPHA:GL_ONE,GL_ONE); + + } break; + case RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_SUB: { + + glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); + glBlendFunc(GL_SRC_ALPHA,GL_ONE); + } break; + case RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_MUL: { + glBlendEquation(GL_FUNC_ADD); + if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } + else { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + + } break; + + } + + current_blend_mode=desired_blend_mode; + } + } + + if (light_index!=prev_light_index) { + if (light_index!=0xFFFF) { //not unshaded + _setup_light(light_instances[light_index]); + } + } + if (material!=prev_material || rebind) { rebind = _setup_material(material,p_alpha_pass); @@ -396,6 +582,7 @@ void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_g RasterizerStorageGLES3::Material *m=NULL; RID m_src=p_instance->material_override.is_valid() ? p_instance->material_override :(p_material>=0?p_instance->materials[p_material]:p_geometry->material); + /* #ifdef DEBUG_ENABLED if (current_debug==VS::SCENARIO_DEBUG_OVERDRAW) { @@ -404,8 +591,10 @@ void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_g #endif */ + if (m_src.is_valid()) { m=storage->material_owner.getornull( m_src ); + if (!m->shader) { m=NULL; } @@ -419,9 +608,10 @@ void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_g - //bool has_base_alpha=(m->shader_cache && m->shader_cache->has_alpha); - //bool has_blend_alpha=m->blend_mode!=VS::MATERIAL_BLEND_MODE_MIX || m->flags[VS::MATERIAL_FLAG_ONTOP]; - bool has_alpha = false; //has_base_alpha || has_blend_alpha; + bool has_base_alpha=(m->shader->spatial.uses_alpha); + bool has_blend_alpha=m->shader->spatial.blend_mode!=RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_MIX || m->shader->spatial.ontop; + bool has_alpha = has_base_alpha || has_blend_alpha; + bool shadow = false; #if 0 if (shadow) { @@ -488,12 +678,13 @@ void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_g e->additive_ptr=&e->additive; e->sort_key=0; + if (e->geometry->last_pass!=render_pass) { e->geometry->last_pass=render_pass; e->geometry->index=current_geometry_index++; } - e->sort_key|=uint64_t(e->instance->base_type)<sort_key|=uint64_t(e->geometry->index)<sort_key|=uint64_t(e->instance->base_type)<material->last_pass!=render_pass) { @@ -502,7 +693,6 @@ void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_g } e->sort_key|=uint64_t(e->material->index)<sort_key|=uint64_t(e->instance->depth_layer)<geometry->type==RasterizerStorageGLES3::Geometry::GEOMETRY_MULTISURFACE) @@ -510,42 +700,45 @@ void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_g bool mirror = e->instance->mirror; -// if (m->flags[VS::MATERIAL_FLAG_INVERT_FACES]) -// e->mirror=!e->mirror; + if (m->shader->spatial.cull_mode==RasterizerStorageGLES3::Shader::Spatial::CULL_MODE_FRONT) { + mirror=!mirror; + } if (mirror) { e->sort_key|=RenderList::SORT_KEY_MIRROR_FLAG; } //e->light_type=0xFF; // no lights! - e->sort_key|=uint64_t(0xF)<sort_key|=uint64_t(0xFFFF)<depth_draw_mode==VS::MATERIAL_DEPTH_DRAW_OPAQUE_PRE_PASS_ALPHA) { + + if (!shadow && !has_blend_alpha && has_alpha && m->shader->spatial.depth_draw_mode==RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) { //if nothing exists, add this element as opaque too - RenderList::Element *oe = opaque_render_list.add_element(); + RenderList::Element *oe = render_list.add_element(); if (!oe) return; - memcpy(oe,e,sizeof(RenderList::Element)); + copymem(oe,e,sizeof(RenderList::Element)); oe->additive_ptr=&oe->additive; } -*/ -#if 0 - if (shadow || m->flags[VS::MATERIAL_FLAG_UNSHADED] || current_debug==VS::SCENARIO_DEBUG_SHADELESS) { - e->light_type=0x7F; //unshaded is zero + + + if (shadow || m->shader->spatial.unshaded /*|| current_debug==VS::SCENARIO_DEBUG_SHADELESS*/) { + + e->sort_key=RenderList::SORT_KEY_LIGHT_INDEX_UNSHADED; + e->sort_key|=uint64_t(0xF)<sort_key|=uint64_t(0xFFFF)<sort_key; - uint8_t light_type = VS::LIGHT_DIRECTIONAL; + for(int i=0;ibase->shadow_enabled) { light_type|=0x8; if (directional_lights[i]->base->directional_shadow_mode==VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) @@ -554,22 +747,24 @@ void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_g light_type|=0x30; } +*/ RenderList::Element *ec; if (duplicate) { - - ec = render_list->add_element(); - memcpy(ec,e,sizeof(RenderList::Element)); + ec = render_list.add_element(); + copymem(ec,e,sizeof(RenderList::Element)); } else { ec=e; duplicate=true; } - ec->light_type=light_type; - ec->light=sort_key; ec->additive_ptr=&e->additive; + ec->sort_key|=uint64_t(directional_light_instances[i]->light_index) << RenderList::SORT_KEY_LIGHT_INDEX_SHIFT; + ec->sort_key|=uint64_t(VS::LIGHT_DIRECTIONAL) << RenderList::SORT_KEY_LIGHT_TYPE_SHIFT; + + lighted=true; } @@ -580,37 +775,45 @@ void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_g for(int i=0;ilast_pass!=scene_pass) //lit by light not in visible scene + LightInstance *li=light_instance_owner.getptr( liptr[i] ); + + if (!li || li->last_pass!=render_pass) //lit by light not in visible scene continue; - uint8_t light_type=li->base->type|0x40; //penalty to ensure directionals always go first - if (li->base->shadow_enabled) { - light_type|=0x8; - } - uint16_t sort_key =li->sort_key; + + +// if (li->base->shadow_enabled) { +// light_type|=0x8; +// } RenderList::Element *ec; if (duplicate) { - ec = render_list->add_element(); - memcpy(ec,e,sizeof(RenderList::Element)); + ec = render_list.add_element(); + copymem(ec,e,sizeof(RenderList::Element)); } else { duplicate=true; ec=e; } - ec->light_type=light_type; - ec->light=sort_key; ec->additive_ptr=&e->additive; + ec->sort_key|=uint64_t(li->light_index) << RenderList::SORT_KEY_LIGHT_INDEX_SHIFT; + ec->sort_key|=uint64_t(li->light_ptr->type) << RenderList::SORT_KEY_LIGHT_TYPE_SHIFT; + + lighted=true; } + if (!lighted) { + e->sort_key|=uint64_t(0xE)<sort_key|=uint64_t(0xFFFF)<frame.time[i]; } + //bg and ambient + if (env) { + state.ubo_data.bg_energy=env->bg_energy; + state.ubo_data.ambient_energy=env->ambient_energy; + Color linear_ambient_color = env->ambient_color.to_linear(); + state.ubo_data.ambient_light_color[0]=linear_ambient_color.r; + state.ubo_data.ambient_light_color[1]=linear_ambient_color.g; + state.ubo_data.ambient_light_color[2]=linear_ambient_color.b; + state.ubo_data.ambient_light_color[3]=linear_ambient_color.a; + + Color bg_color; + + switch(env->bg_mode) { + case VS::ENV_BG_CLEAR_COLOR: { + bg_color=storage->frame.clear_request_color.to_linear(); + } break; + case VS::ENV_BG_COLOR: { + bg_color=env->bg_color.to_linear(); + } break; + default: { + bg_color=Color(0,0,0,1); + } break; + } + + state.ubo_data.bg_color[0]=bg_color.r; + state.ubo_data.bg_color[1]=bg_color.g; + state.ubo_data.bg_color[2]=bg_color.b; + state.ubo_data.bg_color[3]=bg_color.a; + + state.env_radiance_data.ambient_contribution=env->ambient_skybox_contribution; + } else { + state.ubo_data.bg_energy=1.0; + state.ubo_data.ambient_energy=1.0; + //use from clear color instead, since there is no ambient + Color linear_ambient_color = storage->frame.clear_request_color.to_linear(); + state.ubo_data.ambient_light_color[0]=linear_ambient_color.r; + state.ubo_data.ambient_light_color[1]=linear_ambient_color.g; + state.ubo_data.ambient_light_color[2]=linear_ambient_color.b; + state.ubo_data.ambient_light_color[3]=linear_ambient_color.a; + + state.ubo_data.bg_color[0]=linear_ambient_color.r; + state.ubo_data.bg_color[1]=linear_ambient_color.g; + state.ubo_data.bg_color[2]=linear_ambient_color.b; + state.ubo_data.bg_color[3]=linear_ambient_color.a; + + state.env_radiance_data.ambient_contribution=0; + + } glBindBuffer(GL_UNIFORM_BUFFER, state.scene_ubo); glBufferSubData(GL_UNIFORM_BUFFER, 0,sizeof(State::SceneDataUBO), &state.ubo_data); glBindBuffer(GL_UNIFORM_BUFFER, 0); + //fill up environment + + store_transform(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); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + +} + +void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result,int p_light_cull_count,const Transform& p_camera_inverse_transform) { + + directional_light_instance_count=0; + light_instance_count=0; + + for(int i=0;i=RenderList::MAX_LIGHTS ); + + LightInstance *li = light_instance_owner.getptr(p_light_cull_result[i]); + + switch(li->light_ptr->type) { + + case VS::LIGHT_DIRECTIONAL: { + + ERR_FAIL_COND( directional_light_instance_count >= RenderList::MAX_LIGHTS); + directional_light_instances[directional_light_instance_count++]=li; + + li->light_ubo_data.light_color_energy[0]=li->light_ptr->color.r; + li->light_ubo_data.light_color_energy[1]=li->light_ptr->color.g; + li->light_ubo_data.light_color_energy[2]=li->light_ptr->color.b; + li->light_ubo_data.light_color_energy[3]=li->light_ptr->param[VS::LIGHT_PARAM_ENERGY]; + + //omni, keep at 0 + li->light_ubo_data.light_pos_inv_radius[0]=0.0; + li->light_ubo_data.light_pos_inv_radius[1]=0.0; + li->light_ubo_data.light_pos_inv_radius[2]=0.0; + li->light_ubo_data.light_pos_inv_radius[3]=0.0; + + Vector3 direction = p_camera_inverse_transform.basis.xform(li->transform.basis.xform(Vector3(0,0,-1))).normalized(); + li->light_ubo_data.light_direction_attenuation[0]=direction.x; + li->light_ubo_data.light_direction_attenuation[1]=direction.y; + li->light_ubo_data.light_direction_attenuation[2]=direction.z; + li->light_ubo_data.light_direction_attenuation[3]=1.0; + + li->light_ubo_data.light_params[0]=0; + li->light_ubo_data.light_params[1]=li->light_ptr->param[VS::LIGHT_PARAM_SPECULAR]; + li->light_ubo_data.light_params[2]=0; + li->light_ubo_data.light_params[3]=0; - render_list.clear(); + +#if 0 + if (li->light_ptr->shadow_enabled) { + CameraMatrix bias; + bias.set_light_bias(); + + int passes=light_instance_get_shadow_passes(p_light_instance); + + for(int i=0;icustom_transform[i]).inverse(); + li->shadow_projection[i] = bias * li->custom_projection[i] * modelview; + } + lights_use_shadow=true; + } +#endif + } break; + case VS::LIGHT_OMNI: { + + li->light_ubo_data.light_color_energy[0]=li->light_ptr->color.r; + li->light_ubo_data.light_color_energy[1]=li->light_ptr->color.g; + li->light_ubo_data.light_color_energy[2]=li->light_ptr->color.b; + li->light_ubo_data.light_color_energy[3]=li->light_ptr->param[VS::LIGHT_PARAM_ENERGY]; + + Vector3 pos = p_camera_inverse_transform.xform(li->transform.origin); + + //directional, keep at 0 + li->light_ubo_data.light_pos_inv_radius[0]=pos.x; + li->light_ubo_data.light_pos_inv_radius[1]=pos.y; + li->light_ubo_data.light_pos_inv_radius[2]=pos.z; + li->light_ubo_data.light_pos_inv_radius[3]=1.0/MAX(0.001,li->light_ptr->param[VS::LIGHT_PARAM_RANGE]); + + li->light_ubo_data.light_direction_attenuation[0]=0; + li->light_ubo_data.light_direction_attenuation[1]=0; + li->light_ubo_data.light_direction_attenuation[2]=0; + li->light_ubo_data.light_direction_attenuation[3]=li->light_ptr->param[VS::LIGHT_PARAM_ATTENUATION]; + + li->light_ubo_data.light_params[0]=0; + li->light_ubo_data.light_params[1]=li->light_ptr->param[VS::LIGHT_PARAM_SPECULAR]; + li->light_ubo_data.light_params[2]=0; + li->light_ubo_data.light_params[3]=0; + +#if 0 + if (li->light_ptr->shadow_enabled) { + li->shadow_projection[0] = Transform(camera_transform_inverse * li->transform).inverse(); + lights_use_shadow=true; + } +#endif + } break; + case VS::LIGHT_SPOT: { + + li->light_ubo_data.light_color_energy[0]=li->light_ptr->color.r; + li->light_ubo_data.light_color_energy[1]=li->light_ptr->color.g; + li->light_ubo_data.light_color_energy[2]=li->light_ptr->color.b; + li->light_ubo_data.light_color_energy[3]=li->light_ptr->param[VS::LIGHT_PARAM_ENERGY]; + + Vector3 pos = p_camera_inverse_transform.xform(li->transform.origin); + + //directional, keep at 0 + li->light_ubo_data.light_pos_inv_radius[0]=pos.x; + li->light_ubo_data.light_pos_inv_radius[1]=pos.y; + li->light_ubo_data.light_pos_inv_radius[2]=pos.z; + li->light_ubo_data.light_pos_inv_radius[3]=1.0/MAX(0.001,li->light_ptr->param[VS::LIGHT_PARAM_RANGE]); + + Vector3 direction = p_camera_inverse_transform.basis.xform(li->transform.basis.xform(Vector3(0,0,-1))).normalized(); + li->light_ubo_data.light_direction_attenuation[0]=direction.x; + li->light_ubo_data.light_direction_attenuation[1]=direction.y; + li->light_ubo_data.light_direction_attenuation[2]=direction.z; + li->light_ubo_data.light_direction_attenuation[3]=li->light_ptr->param[VS::LIGHT_PARAM_ATTENUATION]; + + li->light_ubo_data.light_params[0]=li->light_ptr->param[VS::LIGHT_PARAM_SPOT_ATTENUATION]; + li->light_ubo_data.light_params[1]=li->light_ptr->param[VS::LIGHT_PARAM_SPECULAR]; + li->light_ubo_data.light_params[2]=0; + li->light_ubo_data.light_params[3]=0; + +#if 0 + if (li->light_ptr->shadow_enabled) { + CameraMatrix bias; + bias.set_light_bias(); + Transform modelview=Transform(camera_transform_inverse * li->transform).inverse(); + li->shadow_projection[0] = bias * li->projection * modelview; + lights_use_shadow=true; + } +#endif + } break; + + } + + + /* make light hash */ + + // actually, not really a hash, but helps to sort the lights + // and avoid recompiling redudant shader versions + + + li->last_pass=render_pass; + li->light_index=i; + + //update UBO for forward rendering, blit to texture for clustered + + glBindBuffer(GL_UNIFORM_BUFFER, li->light_ubo); + glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(LightInstance::LightDataUBO), &li->light_ubo_data); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + + light_instances[i]=li; + } + +} + +void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,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_directional_lights,int p_directional_light_count,RID p_environment){ + + //first of all, make a new render pass render_pass++; + + //fill up ubo + + Environment *env = environment_owner.getornull(p_environment); + + _setup_environment(env,p_cam_projection,p_cam_transform); + + _setup_lights(p_light_cull_result,p_light_cull_count,p_cam_transform.affine_inverse()); + + render_list.clear(); + current_material_index=0; //fill list @@ -744,8 +1169,7 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,CameraM glClearDepth(1.0); glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->front.fbo); - - Environment *env = environment_owner.getornull(p_environment); + RasterizerStorageGLES3::Texture* env_radiance_tex; if (!env || env->bg_mode==VS::ENV_BG_CLEAR_COLOR) { @@ -756,12 +1180,21 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,CameraM storage->frame.clear_request=false; } + } else if (env->bg_mode==VS::ENV_BG_COLOR) { glClearColor( env->bg_color.r, env->bg_color.g, env->bg_color.b, env->bg_color.a ); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); storage->frame.clear_request=false; + } else if (env->bg_mode==VS::ENV_BG_SKYBOX) { + + if (env->skybox_radiance.is_valid()) { + env_radiance_tex = storage->texture_owner.getornull(env->skybox_radiance); + } + glClear(GL_DEPTH_BUFFER_BIT); + storage->frame.clear_request=false; + } else { glClear(GL_DEPTH_BUFFER_BIT); storage->frame.clear_request=false; @@ -810,7 +1243,7 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,CameraM // } - _render_list(render_list.elements,render_list.element_count,p_cam_transform,p_cam_projection,false,false); + _render_list(render_list.elements,render_list.element_count,p_cam_transform,p_cam_projection,env_radiance_tex,false,false); if (env && env->bg_mode==VS::ENV_BG_SKYBOX) { @@ -824,6 +1257,17 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,CameraM // state.scene_shader.set_conditional( SceneShaderGLES3::USE_FOG,false); glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); + glEnable(GL_BLEND); + glDepthMask(GL_TRUE); + glEnable(GL_DEPTH_TEST); + glDisable(GL_SCISSOR_TEST); + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->front.fbo); + + render_list.sort_by_depth(true); + + _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,env_radiance_tex,false,false); + + #if 0 if (use_fb) { @@ -972,7 +1416,143 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,CameraM bool RasterizerSceneGLES3::free(RID p_rid) { - return false; + if (light_instance_owner.owns(p_rid)) { + + LightInstance *light_instance = light_instance_owner.getptr(p_rid); + glDeleteBuffers(1,&light_instance->light_ubo); + light_instance_owner.free(p_rid); + memdelete(light_instance); + + + } else { + return false; + } + + + return true; + +} + +// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html +static _FORCE_INLINE_ float radicalInverse_VdC(uint32_t bits) { + bits = (bits << 16u) | (bits >> 16u); + bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); + bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); + bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); + bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); + return float(bits) * 2.3283064365386963e-10f; // / 0x100000000 +} + +static _FORCE_INLINE_ Vector2 Hammersley(uint32_t i, uint32_t N) { + return Vector2(float(i) / float(N), radicalInverse_VdC(i)); +} + +static _FORCE_INLINE_ Vector3 ImportanceSampleGGX(Vector2 Xi, float Roughness, Vector3 N) { + float a = Roughness * Roughness; // DISNEY'S ROUGHNESS [see Burley'12 siggraph] + + // Compute distribution direction + float Phi = 2.0f * M_PI * Xi.x; + float CosTheta = Math::sqrt((1.0f - Xi.y) / (1.0f + (a*a - 1.0f) * Xi.y)); + float SinTheta = Math::sqrt((float)Math::abs(1.0f - CosTheta * CosTheta)); + + // Convert to spherical direction + Vector3 H; + H.x = SinTheta * Math::cos(Phi); + H.y = SinTheta * Math::sin(Phi); + H.z = CosTheta; + + Vector3 UpVector = Math::abs(N.z) < 0.999 ? Vector3(0.0, 0.0, 1.0) : Vector3(1.0, 0.0, 0.0); + Vector3 TangentX = UpVector.cross(N); + TangentX.normalize(); + Vector3 TangentY = N.cross(TangentX); + + // Tangent to world space + return TangentX * H.x + TangentY * H.y + N * H.z; +} + +static _FORCE_INLINE_ float GGX(float NdotV, float a) { + float k = a / 2.0; + return NdotV / (NdotV * (1.0 - k) + k); +} + +// http://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html +float _FORCE_INLINE_ G_Smith(float a, float nDotV, float nDotL) +{ + return GGX(nDotL, a * a) * GGX(nDotV, a * a); +} + +void RasterizerSceneGLES3::_generate_brdf() { + + int brdf_size=GLOBAL_DEF("rendering/gles3/brdf_texture_size",64); + + + + DVector brdf; + brdf.resize(brdf_size*brdf_size*2); + + DVector::Write w = brdf.write(); + + + for(int i=0;i 0.0 ) { + float G = G_Smith( Roughness, NoV, NoL ); + float G_Vis = G * VoH / (NoH * NoV); + float Fc = pow(1.0 - VoH, 5.0); + + A += (1.0 - Fc) * G_Vis; + B += Fc * G_Vis; + } + } + + A/=512.0; + B/=512.0; + + int tofs = ((brdf_size-j-1)*brdf_size+i)*2; + w[tofs+0]=CLAMP(A*255,0,255); + w[tofs+1]=CLAMP(B*255,0,255); + } + } + + + //set up brdf texture + + + glGenTextures(1, &state.brdf_texture); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,state.brdf_texture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RG8, brdf_size, brdf_size, 0, GL_RG, GL_UNSIGNED_BYTE,w.ptr()); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glBindTexture(GL_TEXTURE_2D,0); } @@ -989,6 +1569,12 @@ void RasterizerSceneGLES3::initialize() { glBufferData(GL_UNIFORM_BUFFER, sizeof(State::SceneDataUBO), &state.scene_ubo, GL_DYNAMIC_DRAW); glBindBuffer(GL_UNIFORM_BUFFER, 0); + glGenBuffers(1, &state.env_radiance_ubo); + glBindBuffer(GL_UNIFORM_BUFFER, state.env_radiance_ubo); + glBufferData(GL_UNIFORM_BUFFER, sizeof(State::EnvironmentRadianceUBO), &state.env_radiance_ubo, GL_DYNAMIC_DRAW); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + + render_list.max_elements=GLOBAL_DEF("rendering/gles3/max_renderable_elements",(int)RenderList::DEFAULT_MAX_ELEMENTS); if (render_list.max_elements>1000000) render_list.max_elements=1000000; @@ -1017,6 +1603,7 @@ void RasterizerSceneGLES3::initialize() { glBindBuffer(GL_ARRAY_BUFFER,0); //unbind } render_list.init(); + _generate_brdf(); } void RasterizerSceneGLES3::finalize(){ diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 53088deb0d..4b1b77f13c 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -32,12 +32,28 @@ public: float camera_inverse_matrix[16]; float camera_matrix[16]; float time[4]; - float ambient_light[4]; + float ambient_light_color[4]; + float bg_color[4]; + float ambient_energy; + float bg_energy; } ubo_data; GLuint scene_ubo; + struct EnvironmentRadianceUBO { + + float transform[16]; + float box_min[4]; //unused for now + float box_max[4]; + float ambient_contribution; + + } env_radiance_data; + + GLuint env_radiance_ubo; + + GLuint brdf_texture; + GLuint skybox_verts; GLuint skybox_array; @@ -54,16 +70,15 @@ public: RID skybox_color; RID skybox_radiance; - RID skybox_irradiance; float skybox_scale; Color bg_color; - float energy; + float bg_energy; float skybox_ambient; Color ambient_color; - float ambient_anergy; - float ambient_skybox_energy; + float ambient_energy; + float ambient_skybox_contribution; int canvas_max_layer; @@ -71,10 +86,10 @@ public: Environment() { bg_mode=VS::ENV_BG_CLEAR_COLOR; skybox_scale=1.0; - energy=1.0; + bg_energy=1.0; skybox_ambient=0; - ambient_anergy=1.0; - ambient_skybox_energy=0.0; + ambient_energy=1.0; + ambient_skybox_contribution=0.0; canvas_max_layer=0; } }; @@ -84,12 +99,12 @@ public: virtual RID environment_create(); virtual void environment_set_background(RID p_env,VS::EnvironmentBG p_bg); - virtual void environment_set_skybox(RID p_env,RID p_skybox,int p_radiance_size,int p_irradiance_size); + virtual void environment_set_skybox(RID p_env,RID p_skybox,int p_radiance_size); virtual void environment_set_skybox_scale(RID p_env,float p_scale); 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_skybox_energy=0.0); + virtual void environment_set_ambient_light(RID p_env,const Color& p_color,float p_energy=1.0,float p_skybox_contribution=0.0); virtual void environment_set_glow(RID p_env,bool p_enable,int p_radius,float p_intensity,float p_strength,float p_bloom_treshold,VS::EnvironmentGlowBlendMode p_blend_mode); virtual void environment_set_fog(RID p_env,bool p_enable,float p_begin,float p_end,RID p_gradient_texture); @@ -100,19 +115,81 @@ public: virtual void environment_set_saturation(RID p_env,bool p_enable,float p_saturation); virtual void environment_set_color_correction(RID p_env,bool p_enable,RID p_ramp); + + /* LIGHT INSTANCE */ + + struct LightInstance : public RID_Data { + + struct SplitInfo { + + CameraMatrix camera; + Transform transform; + float near; + float far; + }; + + struct LightDataUBO { + + float light_pos_inv_radius[4]; + float light_direction_attenuation[4]; + float light_color_energy[4]; + float light_params[4]; //cone attenuation, specular, shadow darkening, + float shadow_split_offsets[4]; + float shadow_matrix1[16]; + float shadow_matrix2[16]; + float shadow_matrix3[16]; + float shadow_matrix4[16]; + + } light_ubo_data; + + + SplitInfo split_info[4]; + + RID light; + RasterizerStorageGLES3::Light *light_ptr; + + CameraMatrix shadow_matrix[4]; + + Transform transform; + + Vector3 light_vector; + Vector3 spot_vector; + float linear_att; + + GLuint light_ubo; + + uint64_t shadow_pass; + uint64_t last_pass; + uint16_t light_index; + + Vector2 dp; + + CameraMatrix shadow_projection[4]; + + + LightInstance() { } + + }; + + mutable RID_Owner light_instance_owner; + + virtual RID light_instance_create(RID p_light); + virtual void light_instance_set_transform(RID p_light_instance,const Transform& p_transform); + /* RENDER LIST */ struct RenderList { enum { DEFAULT_MAX_ELEMENTS=65536, - MAX_LIGHTS=4, SORT_FLAG_SKELETON=1, SORT_FLAG_INSTANCING=2, - + MAX_DIRECTIONAL_LIGHTS=16, + MAX_LIGHTS=4096, SORT_KEY_DEPTH_LAYER_SHIFT=58, SORT_KEY_LIGHT_TYPE_SHIFT=54, //type is most important SORT_KEY_LIGHT_INDEX_SHIFT=38, //type is most important + SORT_KEY_LIGHT_INDEX_UNSHADED=uint64_t(0xF) << SORT_KEY_LIGHT_TYPE_SHIFT, //type is most important SORT_KEY_MATERIAL_INDEX_SHIFT=22, SORT_KEY_GEOMETRY_INDEX_SHIFT=6, SORT_KEY_GEOMETRY_TYPE_SHIFT=2, @@ -161,7 +238,24 @@ public: SortArray sorter; if (p_alpha) { - sorter.sort(&elements[max_elements-alpha_element_count-1],alpha_element_count); + sorter.sort(&elements[max_elements-alpha_element_count],alpha_element_count); + } else { + sorter.sort(elements,element_count); + } + } + + struct SortByDepth { + + _FORCE_INLINE_ bool operator()(const Element* A, const Element* B ) const { + return A->instance->depth > B->instance->depth; + } + }; + + void sort_by_depth(bool p_alpha) { + + SortArray sorter; + if (p_alpha) { + sorter.sort(&elements[max_elements-alpha_element_count],alpha_element_count); } else { sorter.sort(elements,element_count); } @@ -197,6 +291,7 @@ public: } + RenderList() { max_elements=DEFAULT_MAX_ELEMENTS; @@ -210,26 +305,35 @@ public: + LightInstance *directional_light_instances[RenderList::MAX_DIRECTIONAL_LIGHTS]; + int directional_light_instance_count; + + LightInstance *light_instances[RenderList::MAX_LIGHTS]; + int light_instance_count; + RenderList render_list; _FORCE_INLINE_ bool _setup_material(RasterizerStorageGLES3::Material* p_material,bool p_alpha_pass); _FORCE_INLINE_ void _setup_geometry(RenderList::Element *e); _FORCE_INLINE_ void _render_geometry(RenderList::Element *e); + _FORCE_INLINE_ void _setup_light(LightInstance *p_light); + void _render_list(RenderList::Element **p_elements, int p_element_count, const Transform& p_view_transform, const CameraMatrix& p_projection, RasterizerStorageGLES3::Texture *p_base_env, bool p_reverse_cull, bool p_alpha_pass); - void _render_list(RenderList::Element **p_elements, int p_element_count, const Transform& p_view_transform, const CameraMatrix& p_projection, bool p_reverse_cull, bool p_alpha_pass); - - virtual RID light_instance_create(RID p_light); - virtual void light_instance_set_transform(RID p_light_instance,const Transform& p_transform); _FORCE_INLINE_ void _add_geometry( RasterizerStorageGLES3::Geometry* p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner,int p_material); void _draw_skybox(RID p_skybox, CameraMatrix& p_projection, const Transform& p_transform, bool p_vflip, float p_scale); + void _setup_environment(Environment *env,CameraMatrix& p_cam_projection, const Transform& p_cam_transform); + void _setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform); + virtual void render_scene(const Transform& p_cam_transform,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_directional_lights,int p_directional_light_count,RID p_environment); virtual bool free(RID p_rid); + void _generate_brdf(); + void initialize(); void finalize(); RasterizerSceneGLES3(); diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 94ad2afabe..1141a605c5 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -587,6 +587,7 @@ void RasterizerStorageGLES3::texture_allocate(RID p_texture,int p_width, int p_h texture->height=p_height; texture->format=p_format; texture->flags=p_flags; + texture->stored_cube_sides=0; texture->target = (p_flags & VS::TEXTURE_FLAG_CUBEMAP) ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D; _get_gl_image_and_format(Image(),texture->format,texture->flags,format,internal_format,type,compressed,srgb); @@ -759,8 +760,9 @@ void RasterizerStorageGLES3::texture_set_data(RID p_texture,const Image& p_image //printf("texture: %i x %i - size: %i - total: %i\n",texture->width,texture->height,tsize,_rinfo.texture_mem); + texture->stored_cube_sides|=(1<flags&VS::TEXTURE_FLAG_MIPMAPS && mipmaps==1 && !texture->ignore_mipmaps) { + if (texture->flags&VS::TEXTURE_FLAG_MIPMAPS && mipmaps==1 && !texture->ignore_mipmaps && (!(texture->flags&VS::TEXTURE_FLAG_CUBEMAP) || texture->stored_cube_sides==(1<<6)-1)) { //generate mipmaps if they were requested and the image does not contain them glGenerateMipmap(texture->target); } @@ -995,7 +997,7 @@ void RasterizerStorageGLES3::texture_set_shrink_all_x2_on_set_data(bool p_enable config.shrink_textures_x2=p_enable; } -RID RasterizerStorageGLES3::texture_create_pbr_cubemap(RID p_source,VS::PBRCubeMapMode p_mode,int p_resolution) const { +RID RasterizerStorageGLES3::texture_create_radiance_cubemap(RID p_source,int p_resolution) const { Texture * texture = texture_owner.get(p_source); ERR_FAIL_COND_V(!texture,RID()); @@ -1019,12 +1021,13 @@ RID RasterizerStorageGLES3::texture_create_pbr_cubemap(RID p_source,VS::PBRCubeM glDisable(GL_BLEND); - glActiveTexture(GL_TEXTURE1); + glActiveTexture(GL_TEXTURE0); glBindTexture(texture->target, texture->tex_id); - glActiveTexture(GL_TEXTURE0); + glActiveTexture(GL_TEXTURE1); GLuint new_cubemap; glGenTextures(1, &new_cubemap); + glBindTexture(GL_TEXTURE_CUBE_MAP, new_cubemap); GLuint tmp_fb; @@ -1033,8 +1036,7 @@ RID RasterizerStorageGLES3::texture_create_pbr_cubemap(RID p_source,VS::PBRCubeM glBindFramebuffer(GL_FRAMEBUFFER, tmp_fb); - int w = texture->width; - int h = texture->height; + int size = p_resolution; int lod=0; @@ -1044,19 +1046,42 @@ RID RasterizerStorageGLES3::texture_create_pbr_cubemap(RID p_source,VS::PBRCubeM int mm_level=mipmaps; + GLenum internal_format = use_float?GL_RGBA16F:GL_RGB10_A2; + GLenum format = GL_RGBA; + GLenum type = use_float?GL_HALF_FLOAT:GL_UNSIGNED_INT_2_10_10_10_REV; + + + while(mm_level) { + + for(int i=0;i<6;i++) { + glTexImage2D(_cube_side_enum[i], lod, internal_format, size, size, 0, format, type, NULL); + } + + lod++; + mm_level--; + + if (size>1) + size>>=1; + } + + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, lod-1); + + lod=0; + mm_level=mipmaps; + + size = p_resolution; + while(mm_level) { for(int i=0;i<6;i++) { - glTexImage2D(_cube_side_enum[i], lod, use_float?GL_RGBA16F:GL_RGB10_A2, w, h, 0, GL_RGBA, use_float?GL_HALF_FLOAT:GL_UNSIGNED_INT_2_10_10_10_REV, NULL); - glTexParameteri(_cube_side_enum[i], GL_TEXTURE_BASE_LEVEL, lod); - glTexParameteri(_cube_side_enum[i], GL_TEXTURE_MAX_LEVEL, lod); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, _cube_side_enum[i], new_cubemap, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, _cube_side_enum[i], new_cubemap, lod); - glViewport(0,0,w,h); + glViewport(0,0,size,size); glBindVertexArray(resources.quadie_array); shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::FACE_ID,i); - shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::ROUGHNESS,lod/float(mipmaps)); + shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::ROUGHNESS,lod/float(mipmaps-1)); glDrawArrays(GL_TRIANGLE_FAN,0,4); @@ -1069,29 +1094,51 @@ RID RasterizerStorageGLES3::texture_create_pbr_cubemap(RID p_source,VS::PBRCubeM - if (w>1) - w>>=1; - if (h>1) - h>>=1; - + if (size>1) + size>>=1; lod++; mm_level--; } - for(int i=0;i<6;i++) { - //restore ranges - glTexParameteri(_cube_side_enum[i], GL_TEXTURE_BASE_LEVEL, 0); - glTexParameteri(_cube_side_enum[i], GL_TEXTURE_MAX_LEVEL, lod); + //restore ranges + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, lod-1); - } + glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + 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); + glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); glBindFramebuffer(GL_FRAMEBUFFER, config.system_fbo); glDeleteFramebuffers(1, &tmp_fb); - - return RID(); + Texture * ctex = memnew( Texture ); + + ctex->flags=VS::TEXTURE_FLAG_CUBEMAP|VS::TEXTURE_FLAG_MIPMAPS|VS::TEXTURE_FLAG_FILTER; + ctex->width=p_resolution; + ctex->height=p_resolution; + ctex->alloc_width=p_resolution; + ctex->alloc_height=p_resolution; + ctex->format=use_float?Image::FORMAT_RGBAH:Image::FORMAT_RGBA8; + ctex->target=GL_TEXTURE_CUBE_MAP; + ctex->gl_format_cache=format; + ctex->gl_internal_format_cache=internal_format; + ctex->gl_type_cache=type; + ctex->data_size=0; + ctex->compressed=false; + ctex->srgb=false; + ctex->total_data_size=0; + ctex->ignore_mipmaps=false; + ctex->mipmaps=mipmaps; + ctex->active=true; + ctex->tex_id=new_cubemap; + ctex->stored_cube_sides=(1<<6)-1; + ctex->render_target=NULL; + + return texture_owner.make_rid(ctex); } @@ -1137,9 +1184,9 @@ void RasterizerStorageGLES3::shader_set_mode(RID p_shader,VS::ShaderMode p_mode) shader->mode=p_mode; ShaderGLES3* shaders[VS::SHADER_MAX]={ - &canvas->state.canvas_shader, &scene->state.scene_shader, &canvas->state.canvas_shader, + &canvas->state.canvas_shader, }; @@ -1231,10 +1278,14 @@ void RasterizerStorageGLES3::_update_shader(Shader* p_shader) const { shaders.actions_scene.render_mode_values["cull_back"]=Pair(&p_shader->spatial.cull_mode,Shader::Spatial::CULL_MODE_BACK); shaders.actions_scene.render_mode_values["cull_disable"]=Pair(&p_shader->spatial.cull_mode,Shader::Spatial::CULL_MODE_DISABLED); - shaders.actions_canvas.render_mode_flags["unshaded"]=&p_shader->spatial.unshaded; - shaders.actions_canvas.render_mode_flags["ontop"]=&p_shader->spatial.ontop; + shaders.actions_scene.render_mode_flags["unshaded"]=&p_shader->spatial.unshaded; + shaders.actions_scene.render_mode_flags["ontop"]=&p_shader->spatial.ontop; + + shaders.actions_scene.usage_flag_pointers["ALPHA"]=&p_shader->spatial.uses_alpha; + + actions=&shaders.actions_scene; + actions->uniforms=&p_shader->uniforms; - shaders.actions_canvas.usage_flag_pointers["ALPHA"]=&p_shader->spatial.uses_alpha; } @@ -1243,6 +1294,7 @@ void RasterizerStorageGLES3::_update_shader(Shader* p_shader) const { Error err = shaders.compiler.compile(p_shader->mode,p_shader->code,actions,p_shader->path,gen_code); + ERR_FAIL_COND(err!=OK); 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); @@ -1633,29 +1685,29 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy gui[0]=v.r; gui[1]=v.g; - gui[3]=v.b; - gui[4]=v.a; + gui[2]=v.b; + gui[3]=v.a; } else if (value.get_type()==Variant::RECT2) { Rect2 v=value; gui[0]=v.pos.x; gui[1]=v.pos.y; - gui[3]=v.size.x; - gui[4]=v.size.y; + gui[2]=v.size.x; + gui[3]=v.size.y; } else if (value.get_type()==Variant::QUAT) { Quat v=value; gui[0]=v.x; gui[1]=v.y; - gui[3]=v.z; - gui[4]=v.w; + gui[2]=v.z; + gui[3]=v.w; } else { Plane v=value; gui[0]=v.normal.x; gui[1]=v.normal.y; - gui[3]=v.normal.x; - gui[4]=v.d; + gui[2]=v.normal.x; + gui[3]=v.d; } } break; @@ -2307,8 +2359,6 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::P if (p_format&VS::ARRAY_FORMAT_INDEX) { index_array_size=attribs[VS::ARRAY_INDEX].stride*p_index_count; - - print_line("index count: "+itos(p_index_count)+" stride: "+itos(attribs[VS::ARRAY_INDEX].stride) ); } @@ -2882,55 +2932,134 @@ Matrix32 RasterizerStorageGLES3::skeleton_bone_get_transform_2d(RID p_skeleton,i RID RasterizerStorageGLES3::light_create(VS::LightType p_type){ - return RID(); + Light *light = memnew( Light ); + light->type=p_type; + + light->param[VS::LIGHT_PARAM_ENERGY]=1.0; + light->param[VS::LIGHT_PARAM_SPECULAR]=1.0; + light->param[VS::LIGHT_PARAM_RANGE]=1.0; + light->param[VS::LIGHT_PARAM_SPOT_ANGLE]=45; + light->param[VS::LIGHT_PARAM_SHADOW_MAX_DISTANCE]=0; + light->param[VS::LIGHT_PARAM_SHADOW_DARKNESS]=0; + light->param[VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET]=0.1; + light->param[VS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET]=0.3; + light->param[VS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET]=0.6; + light->param[VS::LIGHT_PARAM_SHADOW_SPLIT_4_OFFSET]=1.0; + light->param[VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS]=0.1; + light->param[VS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE]=0.1; + + + light->color=Color(1,1,1,1); + light->shadow=false; + light->negative=false; + light->cull_mask=0xFFFFFFFF; + light->directional_shadow_mode=VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; + + return light_owner.make_rid(light); } void RasterizerStorageGLES3::light_set_color(RID p_light,const Color& p_color){ + Light * light = light_owner.getornull(p_light); + ERR_FAIL_COND(!light); + light->color=p_color; } void RasterizerStorageGLES3::light_set_param(RID p_light,VS::LightParam p_param,float p_value){ + Light * light = light_owner.getornull(p_light); + ERR_FAIL_COND(!light); + ERR_FAIL_INDEX(p_param,VS::LIGHT_PARAM_MAX); + if (p_param==VS::LIGHT_PARAM_RANGE || p_param==VS::LIGHT_PARAM_SPOT_ANGLE) { + light->instance_change_notify(); + } + light->param[p_param]=p_value; } void RasterizerStorageGLES3::light_set_shadow(RID p_light,bool p_enabled){ + Light * light = light_owner.getornull(p_light); + ERR_FAIL_COND(!light); + light->shadow=p_enabled; } void RasterizerStorageGLES3::light_set_projector(RID p_light,RID p_texture){ + Light * light = light_owner.getornull(p_light); + ERR_FAIL_COND(!light); + } void RasterizerStorageGLES3::light_set_attenuation_texure(RID p_light,RID p_texture){ + Light * light = light_owner.getornull(p_light); + ERR_FAIL_COND(!light); + } void RasterizerStorageGLES3::light_set_negative(RID p_light,bool p_enable){ + Light * light = light_owner.getornull(p_light); + ERR_FAIL_COND(!light); + light->negative=p_enable; } void RasterizerStorageGLES3::light_set_cull_mask(RID p_light,uint32_t p_mask){ + Light * light = light_owner.getornull(p_light); + ERR_FAIL_COND(!light); + light->cull_mask=p_mask; } void RasterizerStorageGLES3::light_set_shader(RID p_light,RID p_shader){ + Light * light = light_owner.getornull(p_light); + ERR_FAIL_COND(!light); } void RasterizerStorageGLES3::light_directional_set_shadow_mode(RID p_light,VS::LightDirectionalShadowMode p_mode){ + Light * light = light_owner.getornull(p_light); + ERR_FAIL_COND(!light); } VS::LightType RasterizerStorageGLES3::light_get_type(RID p_light) const { + const Light * light = light_owner.getornull(p_light); + ERR_FAIL_COND_V(!light,VS::LIGHT_DIRECTIONAL); + return VS::LIGHT_DIRECTIONAL; } AABB RasterizerStorageGLES3::light_get_aabb(RID p_light) const { + const Light * light = light_owner.getornull(p_light); + ERR_FAIL_COND_V(!light,AABB()); + + switch( light->type ) { + + case VS::LIGHT_SPOT: { + + 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(); } @@ -3028,6 +3157,10 @@ void RasterizerStorageGLES3::instance_add_dependency(RID p_base,RasterizerScene: inst = mesh_owner.getornull(p_base); ERR_FAIL_COND(!inst); } break; + case VS::INSTANCE_LIGHT: { + inst = light_owner.getornull(p_base); + ERR_FAIL_COND(!inst); + } break; default: { ERR_FAIL(); } @@ -3046,6 +3179,10 @@ void RasterizerStorageGLES3::instance_remove_dependency(RID p_base,RasterizerSce ERR_FAIL_COND(!inst); } break; + case VS::INSTANCE_LIGHT: { + inst = light_owner.getornull(p_base); + ERR_FAIL_COND(!inst); + } break; default: { ERR_FAIL(); } @@ -3542,6 +3679,9 @@ VS::InstanceType RasterizerStorageGLES3::get_base_type(RID p_rid) const { if (mesh_owner.owns(p_rid)) { return VS::INSTANCE_MESH; } + if (light_owner.owns(p_rid)) { + return VS::INSTANCE_LIGHT; + } return VS::INSTANCE_NONE; } @@ -3617,6 +3757,14 @@ bool RasterizerStorageGLES3::free(RID p_rid){ mesh_owner.free(p_rid); memdelete(mesh); + } else if (light_owner.owns(p_rid)) { + + // delete the texture + Light *light = light_owner.get(p_rid); + + light_owner.free(p_rid); + memdelete(light); + } else if (canvas_occluder_owner.owns(p_rid)) { diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index c3022b3ac0..f052aa8019 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -135,10 +135,13 @@ public: bool active; GLuint tex_id; + uint16_t stored_cube_sides; + RenderTarget *render_target; Texture() { + stored_cube_sides=0; ignore_mipmaps=false; render_target=NULL; flags=width=height=0; @@ -184,7 +187,7 @@ public: virtual void texture_debug_usage(List *r_info); - virtual RID texture_create_pbr_cubemap(RID p_source,VS::PBRCubeMapMode p_mode,int p_resolution=-1) const; + virtual RID texture_create_radiance_cubemap(RID p_source,int p_resolution=-1) const; /* SHADER API */ @@ -351,13 +354,6 @@ public: struct Instantiable : public RID_Data { - enum Type { - GEOMETRY_INVALID, - GEOMETRY_SURFACE, - GEOMETRY_IMMEDIATE, - GEOMETRY_MULTISURFACE, - }; - SelfList::List instance_list; _FORCE_INLINE_ void instance_change_notify() { @@ -582,6 +578,20 @@ public: /* Light API */ + + struct Light : Instantiable { + + VS::LightType type; + float param[VS::LIGHT_PARAM_MAX]; + Color color; + bool shadow; + bool negative; + uint32_t cull_mask; + VS::LightDirectionalShadowMode directional_shadow_mode; + }; + + mutable RID_Owner light_owner; + virtual RID light_create(VS::LightType p_type); virtual void light_set_color(RID p_light,const Color& p_color); diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp index 49707400ca..da8f6689d0 100644 --- a/drivers/gles3/shader_compiler_gles3.cpp +++ b/drivers/gles3/shader_compiler_gles3.cpp @@ -48,7 +48,7 @@ static int _get_datatype_size(SL::DataType p_type) { case SL::TYPE_SAMPLERCUBE: return 16; } - + ERR_FAIL_V(0); } @@ -195,7 +195,12 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener for(Map::Element *E=pnode->uniforms.front();E;E=E->next()) { - String ucode="uniform "; + String ucode; + + if (SL::is_sampler_type(E->get().type)) { + ucode="uniform "; + } + ucode+=_prestr(E->get().precission); ucode+=_typestr(E->get().type); ucode+=" "+_mkid(E->key()); @@ -228,7 +233,7 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener for(int i=0;i0) - r_gen_code.uniform_offsets[i]=uniform_sizes[i]-1; + r_gen_code.uniform_offsets[i]=uniform_sizes[i-1]; else r_gen_code.uniform_offsets[i]=0; } @@ -320,7 +325,11 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener SL::VariableNode *vnode=(SL::VariableNode*)p_node; if (p_default_actions.usage_defines.has(vnode->name) && !used_name_defines.has(vnode->name)) { - r_gen_code.defines.push_back(p_default_actions.usage_defines[vnode->name].utf8()); + String define = p_default_actions.usage_defines[vnode->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(vnode->name); } @@ -451,6 +460,14 @@ Error ShaderCompilerGLES3::compile(VS::ShaderMode p_mode, const String& p_code, Error err = parser.compile(p_code,ShaderTypes::get_singleton()->get_functions(p_mode),ShaderTypes::get_singleton()->get_modes(p_mode)); if (err!=OK) { +#if 1 + + Vector shader = p_code.split("\n"); + for(int i=0;i func_list; ShaderLanguage::get_builtin_funcs(&func_list); diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp index ebdf60cf42..052c915241 100644 --- a/drivers/gles3/shader_gles3.cpp +++ b/drivers/gles3/shader_gles3.cpp @@ -751,6 +751,7 @@ void ShaderGLES3::set_custom_shader_code(uint32_t p_code_id, const String& p_ver ERR_FAIL_COND(!custom_code_map.has(p_code_id)); CustomCode *cc=&custom_code_map[p_code_id]; + cc->vertex=p_vertex; cc->vertex_globals=p_vertex_globals; cc->fragment=p_fragment; diff --git a/drivers/gles3/shader_gles3.h b/drivers/gles3/shader_gles3.h index 176a2282fd..4c7f682dff 100644 --- a/drivers/gles3/shader_gles3.h +++ b/drivers/gles3/shader_gles3.h @@ -29,6 +29,7 @@ #ifndef SHADER_GLES3_H #define SHADER_GLES3_H +#include #include "platform_config.h" #ifndef GLES3_INCLUDE_H diff --git a/drivers/gles3/shaders/cubemap_filter.glsl b/drivers/gles3/shaders/cubemap_filter.glsl index f450f34113..d3d4cbd435 100644 --- a/drivers/gles3/shaders/cubemap_filter.glsl +++ b/drivers/gles3/shaders/cubemap_filter.glsl @@ -16,19 +16,26 @@ void main() { [fragment] -uniform samplerCube source_cube; //texunit:1 +precision highp float; +precision highp int; + + +uniform samplerCube source_cube; //texunit:0 uniform int face_id; uniform float roughness; in highp vec2 uv_interp; -layout(location = 0) vec4 frag_color; +layout(location = 0) out vec4 frag_color; + + +#define M_PI 3.14159265359 vec3 texelCoordToVec(vec2 uv, int faceID) { mat3 faceUvVectors[6]; - +/* // -x faceUvVectors[1][0] = vec3(0.0, 0.0, 1.0); // u -> +z faceUvVectors[1][1] = vec3(0.0, -1.0, 0.0); // v -> -y @@ -58,6 +65,37 @@ vec3 texelCoordToVec(vec2 uv, int faceID) faceUvVectors[4][0] = vec3(1.0, 0.0, 0.0); // u -> +x faceUvVectors[4][1] = vec3(0.0, -1.0, 0.0); // v -> -y faceUvVectors[4][2] = vec3(0.0, 0.0, 1.0); // +z face +*/ + + // -x + faceUvVectors[0][0] = vec3(0.0, 0.0, 1.0); // u -> +z + faceUvVectors[0][1] = vec3(0.0, -1.0, 0.0); // v -> -y + faceUvVectors[0][2] = vec3(-1.0, 0.0, 0.0); // -x face + + // +x + faceUvVectors[1][0] = vec3(0.0, 0.0, -1.0); // u -> -z + faceUvVectors[1][1] = vec3(0.0, -1.0, 0.0); // v -> -y + faceUvVectors[1][2] = vec3(1.0, 0.0, 0.0); // +x face + + // -y + faceUvVectors[2][0] = vec3(1.0, 0.0, 0.0); // u -> +x + faceUvVectors[2][1] = vec3(0.0, 0.0, -1.0); // v -> -z + faceUvVectors[2][2] = vec3(0.0, -1.0, 0.0); // -y face + + // +y + faceUvVectors[3][0] = vec3(1.0, 0.0, 0.0); // u -> +x + faceUvVectors[3][1] = vec3(0.0, 0.0, 1.0); // v -> +z + faceUvVectors[3][2] = vec3(0.0, 1.0, 0.0); // +y face + + // -z + faceUvVectors[4][0] = vec3(-1.0, 0.0, 0.0); // u -> -x + faceUvVectors[4][1] = vec3(0.0, -1.0, 0.0); // v -> -y + faceUvVectors[4][2] = vec3(0.0, 0.0, -1.0); // -z face + + // +z + faceUvVectors[5][0] = vec3(1.0, 0.0, 0.0); // u -> +x + faceUvVectors[5][1] = vec3(0.0, -1.0, 0.0); // v -> -y + faceUvVectors[5][2] = vec3(0.0, 0.0, 1.0); // +z face // out = u * s_faceUv[0] + v * s_faceUv[1] + s_faceUv[2]. vec3 result = (faceUvVectors[faceID][0] * uv.x) + (faceUvVectors[faceID][1] * uv.y) + faceUvVectors[faceID][2]; @@ -113,7 +151,7 @@ vec2 Hammersley(uint i, uint N) { return vec2(float(i)/float(N), radicalInverse_VdC(i)); } -#define SAMPLE_COUNT 1024 +#define SAMPLE_COUNT 1024u void main() { @@ -123,20 +161,21 @@ void main() { //vec4 color = color_interp; vec4 sum = vec4(0.0, 0.0, 0.0, 0.0); - for(int sampleNum = 0; sampleNum < SAMPLE_COUNT; sampleNum++) { + for(uint sampleNum = 0u; sampleNum < SAMPLE_COUNT; sampleNum++) { vec2 xi = Hammersley(sampleNum, SAMPLE_COUNT); - vec2 xi = texture2DLod(Texture0, vec2(float(sampleNum) / float(SAMPLE_COUNT), 0.5), 0.0).xy; vec3 H = ImportanceSampleGGX( xi, roughness, N ); vec3 V = N; vec3 L = normalize(2.0 * dot( V, H ) * H - V); - float ndotl = max(0.0, dot(N, L)); - vec3 s = textureCubeLod(u_skyCube, H, 0.0).rgb * ndotl; + float ndotl = clamp(dot(N, L),0.0,1.0); - sum += vec4(s, 1.0); + if (ndotl>0.0) { + sum.rgb += textureLod(source_cube, H, 0.0).rgb *ndotl; + sum.a += ndotl; + } } - sum /= sum.w; + sum /= sum.a; frag_color = vec4(sum.rgb, 1.0); } diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index 4183e828f5..3f94252606 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -1,7 +1,7 @@ [vertex] - +#define ENABLE_UV_INTERP /* from VisualServer: @@ -52,14 +52,47 @@ layout(std140) uniform SceneData { //ubo:0 highp mat4 camera_matrix; highp vec4 time; - highp vec4 ambient_light; + highp vec4 ambient_light_color; + highp vec4 bg_color; + float ambient_energy; + float bg_energy; }; uniform highp mat4 world_transform; +#ifdef USE_FORWARD_LIGHTING + +layout(std140) uniform LightData { //ubo:3 + + highp vec4 light_pos_inv_radius; + mediump vec4 light_direction_attenuation; + mediump vec4 light_color_energy; + mediump vec4 light_params; //cone attenuation, specular, shadow darkening, + mediump vec4 shadow_split_offsets; + highp mat4 shadow_matrix1; + highp mat4 shadow_matrix2; + highp mat4 shadow_matrix3; + highp mat4 shadow_matrix4; +}; + +#ifdef USE_FORWARD_1_SHADOW_MAP +out mediump vec4 forward_shadow_pos1; +#endif + +#ifdef USE_FORWARD_2_SHADOW_MAP +out mediump vec4 forward_shadow_pos2; +#endif + +#ifdef USE_FORWARD_4_SHADOW_MAP +out mediump vec4 forward_shadow_pos3; +out mediump vec4 forward_shadow_pos4; +#endif + +#endif + /* Varyings */ -out vec3 vertex_interp; +out highp vec3 vertex_interp; out vec3 normal_interp; #if defined(ENABLE_COLOR_INTERP) @@ -74,13 +107,6 @@ out vec2 uv_interp; out vec2 uv2_interp; #endif -#if defined(ENABLE_VAR1_INTERP) -out vec4 var1_interp; -#endif - -#if defined(ENABLE_VAR2_INTERP) -out vec4 var2_interp; -#endif #if defined(ENABLE_TANGENT_INTERP) out vec3 tangent_interp; @@ -118,13 +144,13 @@ MATERIAL_UNIFORMS void main() { - highp vec4 vertex_in = vertex_attrib; // vec4(vertex_attrib.xyz * data_attrib.x,1.0); + highp vec4 vertex = vertex_attrib; // vec4(vertex_attrib.xyz * data_attrib.x,1.0); highp mat4 modelview = camera_inverse_matrix * world_transform; - vec3 normal_in = normal_attrib; - normal_in*=normal_mult; + vec3 normal = normal_attrib * normal_mult; + #if defined(ENABLE_TANGENT_INTERP) - vec3 tangent_in = tangent_attrib.xyz; - tangent_in*=normal_mult; + vec3 tangent = tangent_attrib.xyz; + tangent*=normal_mult; float binormalf = tangent_attrib.a; #endif @@ -137,23 +163,31 @@ void main() { m+=mat4(texture2D(skeleton_matrices,vec2((bone_indices.z*3.0+0.0)*skeltex_pixel_size,0.0)),texture2D(skeleton_matrices,vec2((bone_indices.z*3.0+1.0)*skeltex_pixel_size,0.0)),texture2D(skeleton_matrices,vec2((bone_indices.z*3.0+2.0)*skeltex_pixel_size,0.0)),vec4(0.0,0.0,0.0,1.0))*bone_weights.z; m+=mat4(texture2D(skeleton_matrices,vec2((bone_indices.w*3.0+0.0)*skeltex_pixel_size,0.0)),texture2D(skeleton_matrices,vec2((bone_indices.w*3.0+1.0)*skeltex_pixel_size,0.0)),texture2D(skeleton_matrices,vec2((bone_indices.w*3.0+2.0)*skeltex_pixel_size,0.0)),vec4(0.0,0.0,0.0,1.0))*bone_weights.w; - vertex_in = vertex_in * m; - normal_in = (vec4(normal_in,0.0) * m).xyz; + vertex = vertex_in * m; + normal = (vec4(normal,0.0) * m).xyz; #if defined(ENABLE_TANGENT_INTERP) - tangent_in = (vec4(tangent_in,0.0) * m).xyz; + tangent = (vec4(tangent,0.0) * m).xyz; #endif } #endif - vertex_interp = (modelview * vertex_in).xyz; - normal_interp = normalize((modelview * vec4(normal_in,0.0)).xyz); +#if !defined(SKIP_TRANSFORM_USED) + + vertex = modelview * vertex; + normal = normalize((modelview * vec4(normal,0.0)).xyz); +#endif #if defined(ENABLE_TANGENT_INTERP) - tangent_interp=normalize((modelview * vec4(tangent_in,0.0)).xyz); - binormal_interp = normalize( cross(normal_interp,tangent_interp) * binormalf ); +# if !defined(SKIP_TRANSFORM_USED) + + tangent=normalize((modelview * vec4(tangent,0.0)).xyz); +# endif + vec3 binormal = normalize( cross(normal,tangent) * binormalf ); #endif + + #if defined(ENABLE_COLOR_INTERP) color_interp = color_attrib; #endif @@ -161,13 +195,17 @@ void main() { #if defined(ENABLE_UV_INTERP) uv_interp = uv_attrib; #endif + #if defined(ENABLE_UV2_INTERP) uv2_interp = uv2_attrib; #endif +{ VERTEX_SHADER_CODE +} + #ifdef USE_SHADOW_PASS @@ -177,26 +215,32 @@ VERTEX_SHADER_CODE #endif -#ifdef USE_FOG + vertex_interp = vertex.xyz; + normal_interp = normal; - fog_interp.a = pow( clamp( (length(vertex_interp)-fog_params.x)/(fog_params.y-fog_params.x), 0.0, 1.0 ), fog_params.z ); - fog_interp.rgb = mix( fog_color_begin, fog_color_end, fog_interp.a ); +#if defined(ENABLE_TANGENT_INTERP) + tangent_interp = tangent; + binormal_interp = binormal; #endif -#ifndef VERTEX_SHADER_WRITE_POSITION -//vertex shader might write a position +#if !defined(SKIP_TRANSFORM_USED) gl_Position = projection_matrix * vec4(vertex_interp,1.0); +#else + gl_Position = vertex; #endif - - } [fragment] + +#define M_PI 3.14159265359 + + +#define ENABLE_UV_INTERP //hack to use uv if no uv present so it works with lightmap @@ -219,17 +263,27 @@ in vec3 tangent_interp; in vec3 binormal_interp; #endif -#if defined(ENABLE_VAR1_INTERP) -in vec4 var1_interp; -#endif +in highp vec3 vertex_interp; +in vec3 normal_interp; -#if defined(ENABLE_VAR2_INTERP) -in vec4 var2_interp; -#endif -in vec3 vertex_interp; -in vec3 normal_interp; +/* PBR CHANNELS */ + +#ifdef USE_RADIANCE_CUBEMAP + +uniform sampler2D brdf_texture; //texunit:-1 +uniform samplerCube radiance_cube; //texunit:-2 + +layout(std140) uniform Radiance { //ubo:2 + + mat4 radiance_inverse_xform; + vec3 radiance_box_min; + vec3 radiance_box_max; + float radiance_ambient_contribution; + +}; +#endif /* Material Uniforms */ @@ -255,18 +309,97 @@ layout(std140) uniform SceneData { highp mat4 camera_matrix; highp vec4 time; - highp vec4 ambient_light; + highp vec4 ambient_light_color; + highp vec4 bg_color; + float ambient_energy; + float bg_energy; }; + +#ifdef USE_FORWARD_LIGHTING + +layout(std140) uniform LightData { + + highp vec4 light_pos_inv_radius; + mediump vec4 light_direction_attenuation; + mediump vec4 light_color_energy; + mediump vec4 light_params; //cone attenuation, specular, shadow darkening, + mediump vec4 shadow_split_offsets; + highp mat4 shadow_matrix1; + highp mat4 shadow_matrix2; + highp mat4 shadow_matrix3; + highp mat4 shadow_matrix4; +}; + +#ifdef USE_FORWARD_1_SHADOW_MAP +in mediump vec4 forward_shadow_pos1; +#endif + +#ifdef USE_FORWARD_2_SHADOW_MAP +in mediump vec4 forward_shadow_pos2; +#endif + +#ifdef USE_FORWARD_4_SHADOW_MAP +in mediump vec4 forward_shadow_pos3; +in mediump vec4 forward_shadow_pos4; +#endif + +#endif + layout(location=0) out vec4 frag_color; + +// GGX Specular +// Source: http://www.filmicworlds.com/images/ggx-opt/optimized-ggx.hlsl +float G1V(float dotNV, float k) +{ + return 1.0 / (dotNV * (1.0 - k) + k); +} + +float specularGGX(vec3 N, vec3 V, vec3 L, float roughness, float F0) +{ + float alpha = roughness * roughness; + + vec3 H = normalize(V + L); + + float dotNL = max(dot(N,L), 0.0 ); + float dotNV = max(dot(N,V), 0.0 ); + float dotNH = max(dot(N,H), 0.0 ); + float dotLH = max(dot(L,H), 0.0 ); + + // D + float alphaSqr = alpha * alpha; + float pi = M_PI; + float denom = dotNH * dotNH * (alphaSqr - 1.0) + 1.0; + float D = alphaSqr / (pi * denom * denom); + + // F + float dotLH5 = pow(1.0 - dotLH, 5.0); + float F = F0 + (1.0 - F0) * (dotLH5); + + // V + float k = alpha / 2.0f; + float vis = G1V(dotNL, k) * G1V(dotNV, k); + + return dotNL * D * F * vis; +} + +void light_compute(vec3 normal, vec3 light_vec,vec3 eye_vec,vec3 diffuse_color, vec3 specular_color, float roughness, float attenuation, inout vec3 diffuse, inout vec3 specular) { + + diffuse += max(0.0,dot(normal,light_vec)) * diffuse_color * attenuation; + //specular += specular_ggx( roughness, max(0.0,dot(normal,eye_vec)) ) * specular_color * attenuation; + float s = roughness > 0.0 ? specularGGX(normal,eye_vec,light_vec,roughness,1.0) : 0.0; + specular += s * specular_color * attenuation; +} + + void main() { //lay out everything, whathever is unused is optimized away anyway vec3 vertex = vertex_interp; - vec3 albedo = vec3(0.9,0.9,0.9); - vec3 metal = vec3(0.0,0.0,0.0); - float rough = 0.0; + vec3 albedo = vec3(0.8,0.8,0.8); + vec3 specular = vec3(0.2,0.2,0.2); + float roughness = 1.0; float alpha = 1.0; #ifdef METERIAL_DOUBLESIDED @@ -334,6 +467,66 @@ FRAGMENT_SHADER_CODE } #endif +/////////////////////// LIGHTING ////////////////////////////// + + vec3 specular_light = vec3(0.0,0.0,0.0); + vec3 ambient_light = ambient_light_color.rgb; + vec3 diffuse_light = vec3(0.0,0.0,0.0); + + vec3 eye_vec = -normalize( vertex_interp ); + +#ifdef USE_RADIANCE_CUBEMAP + + { + + float ndotv = clamp(dot(normal,eye_vec),0.0,1.0); + vec2 brdf = texture(brdf_texture, vec2(roughness, ndotv)).xy; + + float lod = roughness * 5.0; + vec3 r = reflect(-eye_vec,normal); //2.0 * ndotv * normal - view; // reflect(v, n); + r=normalize((radiance_inverse_xform * vec4(r,0.0)).xyz); + vec3 radiance = textureLod(radiance_cube, r, lod).xyz * ( brdf.x + brdf.y); + + specular_light=mix(albedo,radiance,specular); + + } + + { + + vec3 ambient_dir=normalize((radiance_inverse_xform * vec4(normal,0.0)).xyz); + vec3 env_ambient=textureLod(radiance_cube, ambient_dir, 5.0).xyz; + + ambient_light=mix(ambient_light,env_ambient,radiance_ambient_contribution); + } + + +#else + + ambient_light=albedo; +#endif + + +#ifdef USE_FORWARD_LIGHTING + +#ifdef USE_FORWARD_DIRECTIONAL + + light_compute(normal,light_direction_attenuation.xyz,eye_vec,albedo,specular,roughness,1.0,diffuse_light,specular_light); +#endif + +#ifdef USE_FORWARD_OMNI + + vec3 light_rel_vec = light_pos_inv_radius.xyz-vertex; + float normalized_distance = length( light_rel_vec )*light_pos_inv_radius.w; + float light_attenuation = pow( max(1.0 - normalized_distance, 0.0), light_direction_attenuation.w ); + light_compute(normal,normalize(light_rel_vec),eye_vec,albedo,specular,roughness,light_attenuation,diffuse_light,specular_light); + +#endif + +#ifdef USE_FORWARD_SPOT + +#endif + +#endif #if defined(USE_LIGHT_SHADER_CODE) @@ -345,7 +538,14 @@ LIGHT_SHADER_CODE } #endif +#ifdef SHADELESS + frag_color=vec4(albedo,alpha); +#else + frag_color=vec4(ambient_light+diffuse_light+specular_light,alpha); + +#endif + } -- cgit v1.2.3 From d6567010bf1c65abcbe09b959cde63664778d923 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Sat, 29 Oct 2016 20:48:09 -0300 Subject: -Many many fixes -Gizmos work again --- drivers/gles3/rasterizer_canvas_gles3.cpp | 23 ++- drivers/gles3/rasterizer_gles3.cpp | 6 +- drivers/gles3/rasterizer_scene_gles3.cpp | 310 +++++++++++++++++++++++------ drivers/gles3/rasterizer_scene_gles3.h | 17 +- drivers/gles3/rasterizer_storage_gles3.cpp | 214 ++++++++++---------- drivers/gles3/rasterizer_storage_gles3.h | 40 ++-- drivers/gles3/shader_compiler_gles3.cpp | 88 ++++++-- drivers/gles3/shader_compiler_gles3.h | 2 + drivers/gles3/shaders/copy.glsl | 27 ++- drivers/gles3/shaders/cubemap_filter.glsl | 2 +- drivers/gles3/shaders/scene.glsl | 70 +++++-- 11 files changed, 579 insertions(+), 220 deletions(-) (limited to 'drivers/gles3') diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index b2228a6cfa..c10c5fee65 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -914,6 +914,7 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list,int p_z,const } + if (shader_ptr && shader_ptr!=shader_cache) { state.canvas_shader.set_custom_shader(shader_ptr->custom_code_id); @@ -925,6 +926,7 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list,int p_z,const int tc = material_ptr->textures.size(); RID* textures = material_ptr->textures.ptr(); + ShaderLanguage::ShaderNode::Uniform::Hint* texture_hints = shader_ptr->texture_hints.ptr(); for(int i=0;itexture_owner.getornull( textures[i] ); if (!t) { + + switch(texture_hints[i]) { + case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK: { + glBindTexture(GL_TEXTURE_2D,storage->resources.black_tex); + } break; + case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: { + glBindTexture(GL_TEXTURE_2D,storage->resources.normal_tex); + } break; + default: { + glBindTexture(GL_TEXTURE_2D,storage->resources.white_tex); + } break; + } + //check hints - glBindTexture(GL_TEXTURE_2D,storage->resources.white_tex); + continue; } + if (storage->config.srgb_decode_supported && t->using_srgb) { + //no srgb in 2D + glTexParameteri(t->target,_TEXTURE_SRGB_DECODE_EXT,_SKIP_DECODE_EXT); + t->using_srgb=false; + } + glBindTexture(t->target,t->tex_id); } diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index 83c40edc1d..e838020c45 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -253,10 +253,8 @@ void RasterizerGLES3::make_current() { void RasterizerGLES3::register_config() { - GLOBAL_DEF("rendering/gles3/framebuffer_format",RasterizerStorageGLES3::FBO_FORMAT_FLOAT); - Globals::get_singleton()->set_custom_property_info("rendering/gles3/framebuffer_format",PropertyInfo(Variant::INT,"",PROPERTY_HINT_ENUM,"16 Bits,32 Bits,Half Float")); - GLOBAL_DEF("rendering/gles3/lighting_technique",1); - Globals::get_singleton()->set_custom_property_info("rendering/gles3/lighting_technique",PropertyInfo(Variant::INT,"",PROPERTY_HINT_ENUM,"Forward,Deferred")); + GLOBAL_DEF("rendering/gles3/render_architecture",0); + Globals::get_singleton()->set_custom_property_info("rendering/gles3/render_architecture",PropertyInfo(Variant::INT,"",PROPERTY_HINT_ENUM,"Desktop,Mobile")); GLOBAL_DEF("rendering/gles3/use_nearest_mipmap_filter",false); GLOBAL_DEF("rendering/gles3/anisotropic_filter_level",4.0); diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index aadf9e6336..f7baf1a30b 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -150,27 +150,19 @@ void RasterizerSceneGLES3::environment_set_fog(RID p_env,bool p_enable,float p_b } -void RasterizerSceneGLES3::environment_set_tonemap(RID p_env,bool p_enable,float p_exposure,float p_white,float p_min_luminance,float p_max_luminance,float p_auto_exp_speed,VS::EnvironmentToneMapper p_tone_mapper){ +void RasterizerSceneGLES3::environment_set_tonemap(RID p_env, bool p_enable, float p_exposure, float p_white, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale, VS::EnvironmentToneMapper p_tone_mapper){ } -void RasterizerSceneGLES3::environment_set_brightness(RID p_env,bool p_enable,float p_brightness){ -} -void RasterizerSceneGLES3::environment_set_contrast(RID p_env,bool p_enable,float p_contrast){ +void RasterizerSceneGLES3::environment_set_adjustment(RID p_env,bool p_enable,float p_brightness,float p_contrast,float p_saturation,RID p_ramp) { -} -void RasterizerSceneGLES3::environment_set_saturation(RID p_env,bool p_enable,float p_saturation){ } -void RasterizerSceneGLES3::environment_set_color_correction(RID p_env,bool p_enable,RID p_ramp){ - -} - - RID RasterizerSceneGLES3::light_instance_create(RID p_light) { + print_line("hello light"); LightInstance *light_instance = memnew( LightInstance ); light_instance->light=p_light; @@ -204,6 +196,29 @@ bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material* p_m glEnable(GL_CULL_FACE); } + if (state.current_line_width!=p_material->line_width) { + glLineWidth(p_material->line_width); + state.current_line_width=p_material->line_width; + } + + 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_OPAQUE: { + + glDepthMask(!p_alpha_pass); + } break; + case RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALWAYS: { + glDepthMask(GL_TRUE); + } break; + case RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_NEVER: { + glDepthMask(GL_FALSE); + } break; + } + + state.current_depth_draw=p_material->shader->spatial.depth_draw_mode; + } + //glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); /* @@ -216,7 +231,7 @@ bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material* p_m //if (p_material->line_width) // glLineWidth(p_material->line_width); - +#if 0 //blend mode if (state.current_blend_mode!=p_material->shader->spatial.blend_mode) { @@ -256,7 +271,7 @@ bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material* p_m state.current_blend_mode=p_material->shader->spatial.blend_mode; } - +#endif //material parameters @@ -273,6 +288,7 @@ bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material* p_m int tc = p_material->textures.size(); RID* textures = p_material->textures.ptr(); + ShaderLanguage::ShaderNode::Uniform::Hint* texture_hints = p_material->shader->texture_hints.ptr(); for(int i=0;itexture_owner.getornull( textures[i] ); if (!t) { //check hints + switch(texture_hints[i]) { + case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK: { + glBindTexture(GL_TEXTURE_2D,storage->resources.black_tex); + } break; + case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: { + glBindTexture(GL_TEXTURE_2D,storage->resources.normal_tex); + } break; + default: { + glBindTexture(GL_TEXTURE_2D,storage->resources.white_tex); + } break; + } glBindTexture(GL_TEXTURE_2D,storage->resources.white_tex); continue; } + if (storage->config.srgb_decode_supported) { + //if SRGB decode extension is present, simply switch the texture to whathever is needed + bool must_srgb=false; + + if (t->srgb && texture_hints[i]==ShaderLanguage::ShaderNode::Uniform::HINT_ALBEDO) { + must_srgb=true; + } + + if (t->using_srgb!=must_srgb) { + if (must_srgb) { + glTexParameteri(t->target,_TEXTURE_SRGB_DECODE_EXT,_DECODE_EXT); +#ifdef TOOLS_ENABLED + if (!(t->flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) { + t->flags|=VS::TEXTURE_FLAG_CONVERT_TO_LINEAR; + //notify that texture must be set to linear beforehand, so it works in other platforms when exported + } +#endif + + } else { + glTexParameteri(t->target,_TEXTURE_SRGB_DECODE_EXT,_SKIP_DECODE_EXT); + } + t->using_srgb=must_srgb; + } + } + + glBindTexture(t->target,t->tex_id); } @@ -348,7 +401,60 @@ void RasterizerSceneGLES3::_setup_light(LightInstance *p_light) { glBindBufferBase(GL_UNIFORM_BUFFER,3,p_light->light_ubo); //bind light uniform } +void RasterizerSceneGLES3::_setup_transform(InstanceBase *p_instance,const Transform& p_view_transform,const CameraMatrix& p_projection) { + + if (p_instance->billboard || p_instance->billboard_y || p_instance->depth_scale) { + + Transform xf=p_instance->transform; + if (p_instance->depth_scale) { + + if (p_projection.matrix[3][3]) { + //orthogonal matrix, try to do about the same + //with viewport size + //real_t w = Math::abs( 1.0/(2.0*(p_projection.matrix[0][0])) ); + real_t h = Math::abs( 1.0/(2.0*p_projection.matrix[1][1]) ); + float sc = (h*2.0); //consistent with Y-fov + xf.basis.scale( Vector3(sc,sc,sc)); + } else { + //just scale by depth + real_t sc = Plane(p_view_transform.origin,-p_view_transform.get_basis().get_axis(2)).distance_to(xf.origin); + xf.basis.scale( Vector3(sc,sc,sc)); + } + } + + if (p_instance->billboard) { + + Vector3 scale = xf.basis.get_scale(); + + if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP]) { + xf.set_look_at(xf.origin, xf.origin + p_view_transform.get_basis().get_axis(2), -p_view_transform.get_basis().get_axis(1)); + } else { + xf.set_look_at(xf.origin, xf.origin + p_view_transform.get_basis().get_axis(2), p_view_transform.get_basis().get_axis(1)); + } + + xf.basis.scale(scale); + } + + if (p_instance->billboard_y) { + + Vector3 scale = xf.basis.get_scale(); + Vector3 look_at = p_view_transform.get_origin(); + look_at.y = 0.0; + Vector3 look_at_norm = look_at.normalized(); + if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP]) { + xf.set_look_at(xf.origin,xf.origin + look_at_norm, Vector3(0.0, -1.0, 0.0)); + } else { + xf.set_look_at(xf.origin,xf.origin + look_at_norm, Vector3(0.0, 1.0, 0.0)); + } + xf.basis.scale(scale); + } + state.scene_shader.set_uniform(SceneShaderGLES3::WORLD_TRANSFORM, xf); + + } else { + state.scene_shader.set_uniform(SceneShaderGLES3::WORLD_TRANSFORM, p_instance->transform); + } +} void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_element_count,const Transform& p_view_transform,const CameraMatrix& p_projection,RasterizerStorageGLES3::Texture* p_base_env,bool p_reverse_cull,bool p_alpha_pass) { @@ -372,12 +478,18 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e glActiveTexture(GL_TEXTURE0+storage->config.max_texture_image_units-2); glBindTexture(p_base_env->target,p_base_env->tex_id); state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_CUBEMAP,true); + } else { + state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_CUBEMAP,false); + } + state.scene_shader.set_conditional(SceneShaderGLES3::USE_SKELETON,false); state.current_blend_mode=-1; + state.current_line_width=-1; + state.current_depth_draw=-1; glDisable(GL_BLEND); @@ -390,6 +502,8 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e int prev_blend=-1; int current_blend_mode=-1; + bool prev_additive=false; + for (int i=0;imirror,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); + + _setup_transform(e->instance,p_view_transform,p_projection); // _render(e->geometry, material, skeleton,e->owner,e->instance->transform); @@ -567,6 +687,10 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e prev_material=material; prev_base_type=e->instance->base_type; prev_geometry=e->geometry; + prev_additive=additive; + prev_light_type=light_type; + prev_light_index=light_index; + } //print_line("shaderchanges: "+itos(p_alpha_pass)+": "+itos(_rinfo.shader_change_count)); @@ -824,6 +948,19 @@ void RasterizerSceneGLES3::_draw_skybox(RID p_skybox,CameraMatrix& p_projection, glActiveTexture(GL_TEXTURE0); glBindTexture(tex->target,tex->tex_id); + + if (storage->config.srgb_decode_supported && tex->srgb && !tex->using_srgb) { + + glTexParameteri(tex->target,_TEXTURE_SRGB_DECODE_EXT,_DECODE_EXT); + tex->using_srgb=true; +#ifdef TOOLS_ENABLED + if (!(tex->flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) { + tex->flags|=VS::TEXTURE_FLAG_CONVERT_TO_LINEAR; + //notify that texture must be set to linear beforehand, so it works in other platforms when exported + } +#endif + } + glDepthMask(GL_TRUE); glEnable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); @@ -876,6 +1013,7 @@ void RasterizerSceneGLES3::_draw_skybox(RID p_skybox,CameraMatrix& p_projection, glDrawArrays(GL_TRIANGLE_FAN,0,4); glBindVertexArray(0); + glColorMask(1,1,1,1); storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_CUBEMAP,false); @@ -977,9 +1115,10 @@ void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result,int p_light_cu ERR_FAIL_COND( directional_light_instance_count >= RenderList::MAX_LIGHTS); directional_light_instances[directional_light_instance_count++]=li; - li->light_ubo_data.light_color_energy[0]=li->light_ptr->color.r; - li->light_ubo_data.light_color_energy[1]=li->light_ptr->color.g; - li->light_ubo_data.light_color_energy[2]=li->light_ptr->color.b; + Color linear_col = li->light_ptr->color.to_linear(); + li->light_ubo_data.light_color_energy[0]=linear_col.r; + li->light_ubo_data.light_color_energy[1]=linear_col.g; + li->light_ubo_data.light_color_energy[2]=linear_col.b; li->light_ubo_data.light_color_energy[3]=li->light_ptr->param[VS::LIGHT_PARAM_ENERGY]; //omni, keep at 0 @@ -1018,9 +1157,10 @@ void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result,int p_light_cu } break; case VS::LIGHT_OMNI: { - li->light_ubo_data.light_color_energy[0]=li->light_ptr->color.r; - li->light_ubo_data.light_color_energy[1]=li->light_ptr->color.g; - li->light_ubo_data.light_color_energy[2]=li->light_ptr->color.b; + Color linear_col = li->light_ptr->color.to_linear(); + li->light_ubo_data.light_color_energy[0]=linear_col.r; + li->light_ubo_data.light_color_energy[1]=linear_col.g; + li->light_ubo_data.light_color_energy[2]=linear_col.b; li->light_ubo_data.light_color_energy[3]=li->light_ptr->param[VS::LIGHT_PARAM_ENERGY]; Vector3 pos = p_camera_inverse_transform.xform(li->transform.origin); @@ -1050,9 +1190,10 @@ void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result,int p_light_cu } break; case VS::LIGHT_SPOT: { - li->light_ubo_data.light_color_energy[0]=li->light_ptr->color.r; - li->light_ubo_data.light_color_energy[1]=li->light_ptr->color.g; - li->light_ubo_data.light_color_energy[2]=li->light_ptr->color.b; + Color linear_col = li->light_ptr->color.to_linear(); + li->light_ubo_data.light_color_energy[0]=linear_col.r; + li->light_ubo_data.light_color_energy[1]=linear_col.g; + li->light_ubo_data.light_color_energy[2]=linear_col.b; li->light_ubo_data.light_color_energy[3]=li->light_ptr->param[VS::LIGHT_PARAM_ENERGY]; Vector3 pos = p_camera_inverse_transform.xform(li->transform.origin); @@ -1108,6 +1249,51 @@ void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result,int p_light_cu } +void RasterizerSceneGLES3::_copy_screen() { + + glBindVertexArray(storage->resources.quadie_array); + glDrawArrays(GL_TRIANGLE_FAN,0,4); + glBindVertexArray(0); + +} + +void RasterizerSceneGLES3::_copy_to_front_buffer(Environment *env) { + + //copy to front buffer + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->front.fbo); + + 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,storage->frame.current_rt->buffers.diffuse); + + storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA,true); + + if (!env) { + //no environment, simply convert from linear to srgb + storage->shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB,true); + } else { + storage->shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB,true); + + } + + storage->shaders.copy.bind(); + + _copy_screen(); + + + //turn off everything used + storage->shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB,false); + storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA,false); + + +} + void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,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_directional_lights,int p_directional_light_count,RID p_environment){ //first of all, make a new render pass @@ -1125,6 +1311,8 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,CameraM current_material_index=0; + bool use_mrt=false; + //fill list for(int i=0;iframe.current_rt->buffers.fbo); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_MULTIPLE_RENDER_TARGETS,true); + + Color black(0,0,0,0); + glClearBufferfv(GL_COLOR,1,black.components); // specular + glClearBufferfv(GL_COLOR,2,black.components); // normal metal rough + + } else { + + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.alpha_fbo); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_MULTIPLE_RENDER_TARGETS,false); + + } + + glClearDepth(1.0); - glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->front.fbo); + glClear(GL_DEPTH_BUFFER_BIT); - RasterizerStorageGLES3::Texture* env_radiance_tex; + Color clear_color(0,0,0,0); if (!env || env->bg_mode==VS::ENV_BG_CLEAR_COLOR) { if (storage->frame.clear_request) { - 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 ); - glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + clear_color = storage->frame.clear_request_color.to_linear(); storage->frame.clear_request=false; } } else if (env->bg_mode==VS::ENV_BG_COLOR) { - - glClearColor( env->bg_color.r, env->bg_color.g, env->bg_color.b, env->bg_color.a ); - glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + clear_color = env->bg_color.to_linear(); storage->frame.clear_request=false; } else if (env->bg_mode==VS::ENV_BG_SKYBOX) { if (env->skybox_radiance.is_valid()) { env_radiance_tex = storage->texture_owner.getornull(env->skybox_radiance); } - glClear(GL_DEPTH_BUFFER_BIT); storage->frame.clear_request=false; } else { - glClear(GL_DEPTH_BUFFER_BIT); storage->frame.clear_request=false; - } - state.current_depth_test=true; - state.current_depth_mask=true; + glClearBufferfv(GL_COLOR,0,clear_color.components); // specular + + state.texscreen_copied=false; glBlendEquation(GL_FUNC_ADD); @@ -1214,43 +1417,33 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,CameraM } glDisable(GL_BLEND); - //current_blend_mode=VS::MATERIAL_BLEND_MODE_MIX; - render_list.sort_by_key(false); - //_render_list_forward(&opaque_render_list,camera_transform,camera_transform_inverse,camera_projection,false,fragment_lighting); -/* - if (draw_tex_background) { - - //most 3D vendors recommend drawing a texture bg or skybox here, - //after opaque geometry has been drawn - //so the zbuffer can get rid of most pixels - _draw_tex_bg(); - } -*/ if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); } else { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } -// glDisable(GL_BLEND); -// current_blend_mode=VS::MATERIAL_BLEND_MODE_MIX; -// state.scene_shader.set_conditional(SceneShaderGLES3::USE_GLOW,false); -// if (current_env && current_env->fx_enabled[VS::ENV_FX_GLOW]) { -// glColorMask(1,1,1,0); //don't touch alpha -// } - - _render_list(render_list.elements,render_list.element_count,p_cam_transform,p_cam_projection,env_radiance_tex,false,false); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_MULTIPLE_RENDER_TARGETS,false); + if (env && env->bg_mode==VS::ENV_BG_SKYBOX) { + if (use_mrt) { + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.alpha_fbo); //switch to alpha fbo for skybox, only diffuse/ambient matters + } + _draw_skybox(env->skybox_color,p_cam_projection,p_cam_transform,storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP],env->skybox_scale); } + + + + //_render_list_forward(&alpha_render_list,camera_transform,camera_transform_inverse,camera_projection,false,fragment_lighting,true); //glColorMask(1,1,1,1); @@ -1261,12 +1454,14 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,CameraM glDepthMask(GL_TRUE); glEnable(GL_DEPTH_TEST); glDisable(GL_SCISSOR_TEST); - glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->front.fbo); + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.alpha_fbo); render_list.sort_by_depth(true); - _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,env_radiance_tex,false,false); + _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,env_radiance_tex,false,true); + + _copy_to_front_buffer(env); #if 0 if (use_fb) { @@ -1418,6 +1613,7 @@ bool RasterizerSceneGLES3::free(RID p_rid) { if (light_instance_owner.owns(p_rid)) { + print_line("bye light"); LightInstance *light_instance = light_instance_owner.getptr(p_rid); glDeleteBuffers(1,&light_instance->light_ubo); light_instance_owner.free(p_rid); diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 4b1b77f13c..5457b5cde3 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -18,10 +18,11 @@ public: struct State { - bool current_depth_test; - bool current_depth_mask; + bool texscreen_copied; int current_blend_mode; + float current_line_width; + int current_depth_draw; SceneShaderGLES3 scene_shader; @@ -57,6 +58,8 @@ public: GLuint skybox_verts; GLuint skybox_array; + + } state; @@ -109,11 +112,8 @@ public: virtual void environment_set_glow(RID p_env,bool p_enable,int p_radius,float p_intensity,float p_strength,float p_bloom_treshold,VS::EnvironmentGlowBlendMode p_blend_mode); 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_tonemap(RID p_env,bool p_enable,float p_exposure,float p_white,float p_min_luminance,float p_max_luminance,float p_auto_exp_speed,VS::EnvironmentToneMapper p_tone_mapper); - virtual void environment_set_brightness(RID p_env,bool p_enable,float p_brightness); - virtual void environment_set_contrast(RID p_env,bool p_enable,float p_contrast); - virtual void environment_set_saturation(RID p_env,bool p_enable,float p_saturation); - virtual void environment_set_color_correction(RID p_env,bool p_enable,RID p_ramp); + virtual void environment_set_tonemap(RID p_env,bool p_enable,float p_exposure,float p_white,float p_min_luminance,float p_max_luminance,float p_auto_exp_speed,float p_auto_exp_scale,VS::EnvironmentToneMapper p_tone_mapper); + virtual void environment_set_adjustment(RID p_env,bool p_enable,float p_brightness,float p_contrast,float p_saturation,RID p_ramp); /* LIGHT INSTANCE */ @@ -314,6 +314,7 @@ public: RenderList render_list; _FORCE_INLINE_ bool _setup_material(RasterizerStorageGLES3::Material* p_material,bool p_alpha_pass); + _FORCE_INLINE_ void _setup_transform(InstanceBase *p_instance,const Transform& p_view_transform,const CameraMatrix& p_projection); _FORCE_INLINE_ void _setup_geometry(RenderList::Element *e); _FORCE_INLINE_ void _render_geometry(RenderList::Element *e); _FORCE_INLINE_ void _setup_light(LightInstance *p_light); @@ -327,6 +328,8 @@ public: void _setup_environment(Environment *env,CameraMatrix& p_cam_projection, const Transform& p_cam_transform); void _setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform); + void _copy_screen(); + void _copy_to_front_buffer(Environment *env); virtual void render_scene(const Transform& p_cam_transform,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_directional_lights,int p_directional_light_count,RID p_environment); diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 1141a605c5..a678c460f5 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -57,9 +57,6 @@ #define _EXT_ATC_RGBA_INTERPOLATED_ALPHA_AMD 0x87EE -#define _TEXTURE_SRGB_DECODE_EXT 0x8A48 -#define _DECODE_EXT 0x8A49 -#define _SKIP_DECODE_EXT 0x8A4A #define _GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE @@ -679,8 +676,10 @@ void RasterizerStorageGLES3::texture_set_data(RID p_texture,const Image& p_image if (texture->flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { glTexParameteri(texture->target,_TEXTURE_SRGB_DECODE_EXT,_DECODE_EXT); + texture->using_srgb=true; } else { glTexParameteri(texture->target,_TEXTURE_SRGB_DECODE_EXT,_SKIP_DECODE_EXT); + texture->using_srgb=false; } } @@ -892,8 +891,10 @@ void RasterizerStorageGLES3::texture_set_flags(RID p_texture,uint32_t p_flags) { if (texture->flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { glTexParameteri(texture->target,_TEXTURE_SRGB_DECODE_EXT,_DECODE_EXT); + texture->using_srgb=true; } else { glTexParameteri(texture->target,_TEXTURE_SRGB_DECODE_EXT,_SKIP_DECODE_EXT); + texture->using_srgb=false; } } @@ -1024,6 +1025,19 @@ RID RasterizerStorageGLES3::texture_create_radiance_cubemap(RID p_source,int p_r glActiveTexture(GL_TEXTURE0); glBindTexture(texture->target, texture->tex_id); + if (config.srgb_decode_supported && texture->srgb && !texture->using_srgb) { + + glTexParameteri(texture->target,_TEXTURE_SRGB_DECODE_EXT,_DECODE_EXT); + texture->using_srgb=true; +#ifdef TOOLS_ENABLED + if (!(texture->flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) { + texture->flags|=VS::TEXTURE_FLAG_CONVERT_TO_LINEAR; + //notify that texture must be set to linear beforehand, so it works in other platforms when exported + } +#endif + } + + glActiveTexture(GL_TEXTURE1); GLuint new_cubemap; glGenTextures(1, &new_cubemap); @@ -1302,6 +1316,7 @@ void RasterizerStorageGLES3::_update_shader(Shader* p_shader) const { p_shader->ubo_size=gen_code.uniform_total_size; p_shader->ubo_offsets=gen_code.uniform_offsets; p_shader->texture_count=gen_code.texture_uniforms.size(); + p_shader->texture_hints=gen_code.texture_hints; //all materials using this shader will have to be invalidated, unfortunately @@ -1510,7 +1525,17 @@ Variant RasterizerStorageGLES3::material_get_param(RID p_material, const StringN return Variant(); } -_FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataType type, const Variant& value, uint8_t *data) { +void RasterizerStorageGLES3::material_set_line_width(RID p_material, float p_width) { + + Material *material = material_owner.get( p_material ); + ERR_FAIL_COND(!material); + + material->line_width=p_width; + + +} + +_FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataType type, const Variant& value, uint8_t *data,bool p_linear_color) { switch(type) { case ShaderLanguage::TYPE_BOOL: { @@ -1683,6 +1708,10 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy if (value.get_type()==Variant::COLOR) { Color v=value; + if (p_linear_color) { + v=v.to_linear(); + } + gui[0]=v.r; gui[1]=v.g; gui[2]=v.b; @@ -2019,7 +2048,7 @@ void RasterizerStorageGLES3::_update_material(Material* material) { if (V) { //user provided - _fill_std140_variant_ubo_value(E->get().type,V->get(),data); + _fill_std140_variant_ubo_value(E->get().type,V->get(),data,material->shader->mode==VS::SHADER_SPATIAL); } else if (E->get().default_value.size()){ //default value _fill_std140_ubo_value(E->get().type,E->get().default_value,data); @@ -2641,9 +2670,7 @@ void RasterizerStorageGLES3::mesh_remove_surface(RID p_mesh, int p_surface){ Surface *surface = mesh->surfaces[p_surface]; - ERR_FAIL_COND(surface->index_array_len==0); - - glDeleteBuffers(1,&surface->array_id); + glDeleteBuffers(1,&surface->vertex_id); if (surface->index_id) { glDeleteBuffers(1,&surface->index_id); } @@ -3211,14 +3238,14 @@ void RasterizerStorageGLES3::_render_target_clear(RenderTarget *rt) { rt->back.fbo=0; } - if (rt->deferred.fbo) { - glDeleteFramebuffers(1,&rt->deferred.fbo); - glDeleteFramebuffers(1,&rt->deferred.fbo_color); - glDeleteTextures(1,&rt->deferred.albedo_ao); - glDeleteTextures(1,&rt->deferred.normal_special); - glDeleteTextures(1,&rt->deferred.metal_rough_motion); - rt->deferred.fbo=0; - rt->deferred.fbo_color=0; + if (rt->buffers.fbo) { + glDeleteFramebuffers(1,&rt->buffers.fbo); + glDeleteFramebuffers(1,&rt->buffers.alpha_fbo); + glDeleteTextures(1,&rt->buffers.diffuse); + glDeleteTextures(1,&rt->buffers.specular); + glDeleteTextures(1,&rt->buffers.normal_sr); + rt->buffers.fbo=0; + rt->buffers.alpha_fbo=0; } if (rt->depth) { @@ -3239,26 +3266,6 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){ if (rt->width<=0 || rt->height<=0) return; - glActiveTexture(GL_TEXTURE0); - - glGenFramebuffers(1, &rt->front.fbo); - glBindFramebuffer(GL_FRAMEBUFFER, rt->front.fbo); - - - glGenRenderbuffers(1, &rt->depth); - glBindRenderbuffer(GL_RENDERBUFFER, rt->depth ); - if (config.fbo_format==FBO_FORMAT_16_BITS) { - glRenderbufferStorage(GL_RENDERBUFFER,GL_DEPTH_COMPONENT16, rt->width, rt->height); - } else { - glRenderbufferStorage(GL_RENDERBUFFER,GL_DEPTH24_STENCIL8, rt->width, rt->height); - } - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth); - glBindRenderbuffer(GL_RENDERBUFFER, 0 ); - - - glGenTextures(1, &rt->front.color); - glBindTexture(GL_TEXTURE_2D, rt->front.color); - GLuint color_internal_format; GLuint color_format; @@ -3266,21 +3273,8 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){ Image::Format image_format; - if (config.fbo_format==FBO_FORMAT_16_BITS) { - if (rt->flags[RENDER_TARGET_TRANSPARENT]) { - color_internal_format=GL_RGB5_A1; - color_format=GL_RGBA; - color_type=GL_UNSIGNED_SHORT_5_5_5_1; - image_format=Image::FORMAT_RGBA5551; - } else { - color_internal_format=GL_RGB565; - color_format=GL_RGB; - color_type=GL_UNSIGNED_SHORT_5_6_5; - image_format=Image::FORMAT_RGB565; - } - - } else if (config.fbo_format==FBO_FORMAT_32_BITS || (config.fbo_format==FBO_FORMAT_FLOAT && rt->flags[RENDER_TARGET_NO_3D])) { + if (config.render_arch==RENDER_ARCH_MOBILE || rt->flags[RENDER_TARGET_NO_3D]) { if (rt->flags[RENDER_TARGET_TRANSPARENT]) { color_internal_format=GL_RGBA8; @@ -3293,53 +3287,75 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){ color_type=GL_UNSIGNED_INT_2_10_10_10_REV; image_format=Image::FORMAT_RGBA8;//todo } - } else if (config.fbo_format==FBO_FORMAT_FLOAT) { - + } else { color_internal_format=GL_RGBA16F; color_format=GL_RGBA; color_type=GL_HALF_FLOAT; image_format=Image::FORMAT_RGBAH; } - glTexImage2D(GL_TEXTURE_2D, 0, color_internal_format, rt->width, rt->height, 0, color_format, color_type, NULL); + { + /* FRONT FBO */ - 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, rt->front.color, 0); + glActiveTexture(GL_TEXTURE0); + + glGenFramebuffers(1, &rt->front.fbo); + glBindFramebuffer(GL_FRAMEBUFFER, rt->front.fbo); + + + glGenRenderbuffers(1, &rt->depth); + glBindRenderbuffer(GL_RENDERBUFFER, rt->depth ); + + + glRenderbufferStorage(GL_RENDERBUFFER,GL_DEPTH24_STENCIL8, rt->width, rt->height); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth); + glBindRenderbuffer(GL_RENDERBUFFER, 0 ); + + + glGenTextures(1, &rt->front.color); + glBindTexture(GL_TEXTURE_2D, rt->front.color); + + glTexImage2D(GL_TEXTURE_2D, 0, color_internal_format, rt->width, rt->height, 0, color_format, color_type, 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, rt->front.color, 0); - { GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); glBindFramebuffer(GL_FRAMEBUFFER, config.system_fbo); ERR_FAIL_COND( status != GL_FRAMEBUFFER_COMPLETE ); - } - Texture *tex = texture_owner.get(rt->texture); - tex->format=image_format; - tex->gl_format_cache=color_format; - tex->gl_type_cache=color_type; - tex->gl_internal_format_cache=color_internal_format; - tex->tex_id=rt->front.color; - tex->width=rt->width; - tex->alloc_width=rt->width; - tex->height=rt->height; - tex->alloc_height=rt->height; + Texture *tex = texture_owner.get(rt->texture); + tex->format=image_format; + tex->gl_format_cache=color_format; + tex->gl_type_cache=color_type; + tex->gl_internal_format_cache=color_internal_format; + tex->tex_id=rt->front.color; + tex->width=rt->width; + tex->alloc_width=rt->width; + tex->height=rt->height; + tex->alloc_height=rt->height; + + texture_set_flags(rt->texture,tex->flags); + + } - texture_set_flags(rt->texture,tex->flags); + + /* BACK FBO */ if (!rt->flags[RENDER_TARGET_NO_SAMPLING]) { glGenFramebuffers(1, &rt->back.fbo); glBindFramebuffer(GL_FRAMEBUFFER, rt->back.fbo); - + glBindRenderbuffer(GL_RENDERBUFFER, rt->depth ); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth); glGenTextures(1, &rt->back.color); glBindTexture(GL_TEXTURE_2D, rt->back.color); - glTexImage2D(GL_TEXTURE_2D, 0, color_internal_format, rt->width, rt->height, 0, color_format, color_type, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -3357,43 +3373,42 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){ } } + if (config.render_arch==RENDER_ARCH_DESKTOP && !rt->flags[RENDER_TARGET_NO_3D]) { - if (config.fbo_deferred && !rt->flags[RENDER_TARGET_NO_3D]) { - //regular fbo - glGenFramebuffers(1, &rt->deferred.fbo); - glBindFramebuffer(GL_FRAMEBUFFER, rt->deferred.fbo); + glGenFramebuffers(1, &rt->buffers.fbo); + glBindFramebuffer(GL_FRAMEBUFFER, rt->buffers.fbo); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth); - glGenTextures(1, &rt->deferred.albedo_ao); - glBindTexture(GL_TEXTURE_2D, rt->deferred.albedo_ao); + glGenTextures(1, &rt->buffers.diffuse); + glBindTexture(GL_TEXTURE_2D, rt->buffers.diffuse); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, rt->width, rt->height, 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, rt->deferred.albedo_ao, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->buffers.diffuse, 0); - glGenTextures(1, &rt->deferred.metal_rough_motion); - glBindTexture(GL_TEXTURE_2D, rt->deferred.metal_rough_motion); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, rt->width, rt->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glGenTextures(1, &rt->buffers.specular); + glBindTexture(GL_TEXTURE_2D, rt->buffers.specular); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, rt->width, rt->height, 0, GL_RGBA, GL_HALF_FLOAT, 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_ATTACHMENT1, GL_TEXTURE_2D, rt->deferred.metal_rough_motion, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, rt->buffers.specular, 0); - glGenTextures(1, &rt->deferred.normal_special); - glBindTexture(GL_TEXTURE_2D, rt->deferred.normal_special); + glGenTextures(1, &rt->buffers.normal_sr); + glBindTexture(GL_TEXTURE_2D, rt->buffers.normal_sr); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, rt->width, rt->height, 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_ATTACHMENT2, GL_TEXTURE_2D, rt->deferred.normal_special, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, rt->buffers.normal_sr, 0); GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); @@ -3402,19 +3417,15 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){ if (status != GL_FRAMEBUFFER_COMPLETE) { _render_target_clear(rt); ERR_FAIL_COND( status != GL_FRAMEBUFFER_COMPLETE ); - } + } - //regular fbo with color attachment (needed for emission or objects rendered as forward) - glGenFramebuffers(1, &rt->deferred.fbo_color); - glBindFramebuffer(GL_FRAMEBUFFER, rt->deferred.fbo_color); + //alpha fbo + glGenFramebuffers(1, &rt->buffers.alpha_fbo); + glBindFramebuffer(GL_FRAMEBUFFER, rt->buffers.alpha_fbo); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->deferred.albedo_ao, 0); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, rt->deferred.metal_rough_motion, 0); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, rt->deferred.normal_special, 0); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, rt->front.color, 0); - + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->buffers.diffuse, 0); status = glCheckFramebufferStatus(GL_FRAMEBUFFER); glBindFramebuffer(GL_FRAMEBUFFER, config.system_fbo); @@ -3423,6 +3434,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){ _render_target_clear(rt); ERR_FAIL_COND( status != GL_FRAMEBUFFER_COMPLETE ); } + } @@ -3797,8 +3809,8 @@ bool RasterizerStorageGLES3::free(RID p_rid){ void RasterizerStorageGLES3::initialize() { - config.fbo_format=FBOFormat(int(Globals::get_singleton()->get("rendering/gles3/framebuffer_format"))); - config.fbo_deferred=int(Globals::get_singleton()->get("rendering/gles3/lighting_technique")); + config.render_arch=RENDER_ARCH_DESKTOP; + //config.fbo_deferred=int(Globals::get_singleton()->get("rendering/gles3/lighting_technique")); config.system_fbo=0; @@ -3925,10 +3937,10 @@ void RasterizerStorageGLES3::initialize() { glGenVertexArrays(1,&resources.quadie_array); glBindVertexArray(resources.quadie_array); glBindBuffer(GL_ARRAY_BUFFER,resources.quadie); - glVertexAttribPointer(0,2,GL_FLOAT,GL_FALSE,sizeof(float)*4,0); + glVertexAttribPointer(VS::ARRAY_VERTEX,2,GL_FLOAT,GL_FALSE,sizeof(float)*4,0); glEnableVertexAttribArray(0); - glVertexAttribPointer(1,2,GL_FLOAT,GL_FALSE,sizeof(float)*4,((uint8_t*)NULL)+8); - glEnableVertexAttribArray(1); + glVertexAttribPointer(VS::ARRAY_TEX_UV,2,GL_FLOAT,GL_FALSE,sizeof(float)*4,((uint8_t*)NULL)+8); + glEnableVertexAttribArray(4); glBindVertexArray(0); glBindBuffer(GL_ARRAY_BUFFER,0); //unbind } diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index f052aa8019..b12c2d93b6 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -13,6 +13,9 @@ class RasterizerCanvasGLES3; class RasterizerSceneGLES3; +#define _TEXTURE_SRGB_DECODE_EXT 0x8A48 +#define _DECODE_EXT 0x8A49 +#define _SKIP_DECODE_EXT 0x8A4A class RasterizerStorageGLES3 : public RasterizerStorage { public: @@ -20,16 +23,15 @@ public: RasterizerCanvasGLES3 *canvas; RasterizerSceneGLES3 *scene; - enum FBOFormat { - FBO_FORMAT_16_BITS, - FBO_FORMAT_32_BITS, - FBO_FORMAT_FLOAT, + enum RenderArchitecture { + RENDER_ARCH_MOBILE, + RENDER_ARCH_DESKTOP, }; struct Config { - FBOFormat fbo_format; - bool fbo_deferred; + RenderArchitecture render_arch; + GLuint system_fbo; //on some devices, such as apple, screen is rendered to yet another fbo. bool shrink_textures_x2; @@ -135,12 +137,15 @@ public: bool active; GLuint tex_id; + bool using_srgb; + uint16_t stored_cube_sides; RenderTarget *render_target; Texture() { + using_srgb=false; stored_cube_sides=0; ignore_mipmaps=false; render_target=NULL; @@ -218,6 +223,8 @@ public: Map default_textures; + Vector texture_hints; + bool valid; String path; @@ -319,12 +326,14 @@ public: SelfList list; SelfList dirty_list; Vector textures; + float line_width; uint32_t index; uint64_t last_pass; Material() : list(this), dirty_list(this) { shader=NULL; + line_width=1.0; ubo_id=0; ubo_size=0; last_pass=0; @@ -346,6 +355,8 @@ public: virtual void material_set_param(RID p_material, const StringName& p_param, const Variant& p_value); virtual Variant material_get_param(RID p_material, const StringName& p_param) const; + virtual void material_set_line_width(RID p_material, float p_width); + void _update_material(Material* material); void update_dirty_materials(); @@ -655,14 +666,13 @@ public: GLuint depth; - struct Deferred { + struct Buffers { GLuint fbo; - GLuint fbo_color; - - GLuint albedo_ao; - GLuint metal_rough_motion; - GLuint normal_special; - } deferred; + GLuint alpha_fbo; //single buffer, just diffuse (for alpha pass) + GLuint specular; + GLuint diffuse; + GLuint normal_sr; + } buffers; int width,height; @@ -679,8 +689,8 @@ public: depth=0; front.fbo=0; back.fbo=0; - deferred.fbo=0; - deferred.fbo_color=0; + buffers.fbo=0; + buffers.alpha_fbo=0; used_in_frame=false; flags[RENDER_TARGET_VFLIP]=false; diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp index da8f6689d0..0dff53bfb9 100644 --- a/drivers/gles3/shader_compiler_gles3.cpp +++ b/drivers/gles3/shader_compiler_gles3.cpp @@ -75,25 +75,81 @@ static String _mkid(const String& p_id) { return "m_"+p_id; } +static String f2sp0(float p_float) { + + if (int(p_float)==p_float) + return itos(p_float)+".0"; + else + return rtoss(p_float); +} + static String get_constant_text(SL::DataType p_type, const Vector& p_values) { switch(p_type) { case SL::TYPE_BOOL: return p_values[0].boolean?"true":"false"; - case SL::TYPE_BVEC2: return String()+"bvec2("+(p_values[0].boolean?"true":"false")+(p_values[1].boolean?"true":"false")+")"; - case SL::TYPE_BVEC3: return String()+"bvec3("+(p_values[0].boolean?"true":"false")+","+(p_values[1].boolean?"true":"false")+","+(p_values[2].boolean?"true":"false")+")"; - case SL::TYPE_BVEC4: return String()+"bvec4("+(p_values[0].boolean?"true":"false")+","+(p_values[1].boolean?"true":"false")+","+(p_values[2].boolean?"true":"false")+","+(p_values[3].boolean?"true":"false")+")"; - case SL::TYPE_INT: return rtos(p_values[0].sint); - case SL::TYPE_IVEC2: return String()+"ivec2("+rtos(p_values[0].sint)+","+rtos(p_values[1].sint)+")"; - case SL::TYPE_IVEC3: return String()+"ivec3("+rtos(p_values[0].sint)+","+rtos(p_values[1].sint)+","+rtos(p_values[2].sint)+")"; - case SL::TYPE_IVEC4: return String()+"ivec4("+rtos(p_values[0].sint)+","+rtos(p_values[1].sint)+","+rtos(p_values[2].sint)+","+rtos(p_values[3].sint)+")"; - case SL::TYPE_UINT: return rtos(p_values[0].real); - case SL::TYPE_UVEC2: return String()+"uvec2("+rtos(p_values[0].real)+","+rtos(p_values[1].real)+")"; - case SL::TYPE_UVEC3: return String()+"uvec3("+rtos(p_values[0].real)+","+rtos(p_values[1].real)+","+rtos(p_values[2].real)+")"; - case SL::TYPE_UVEC4: return String()+"uvec4("+rtos(p_values[0].real)+","+rtos(p_values[1].real)+","+rtos(p_values[2].real)+","+rtos(p_values[3].real)+")"; - case SL::TYPE_FLOAT: return rtos(p_values[0].real); - case SL::TYPE_VEC2: return String()+"vec2("+rtos(p_values[0].real)+","+rtos(p_values[1].real)+")"; - case SL::TYPE_VEC3: return String()+"vec3("+rtos(p_values[0].real)+","+rtos(p_values[1].real)+","+rtos(p_values[2].real)+")"; - case SL::TYPE_VEC4: return String()+"vec4("+rtos(p_values[0].real)+","+rtos(p_values[1].real)+","+rtos(p_values[2].real)+","+rtos(p_values[3].real)+")"; + case SL::TYPE_BVEC2: + case SL::TYPE_BVEC3: + case SL::TYPE_BVEC4: { + + + String text="bvec"+itos(p_type-SL::TYPE_BOOL+1)+"("; + for(int i=0;i0) + text+=","; + + text+=p_values[i].boolean?"true":"false"; + } + text+=")"; + return text; + } + + case SL::TYPE_INT: return itos(p_values[0].sint); + case SL::TYPE_IVEC2: + case SL::TYPE_IVEC3: + case SL::TYPE_IVEC4: { + + String text="ivec"+itos(p_type-SL::TYPE_INT+1)+"("; + for(int i=0;i0) + text+=","; + + text+=itos(p_values[i].sint); + } + text+=")"; + return text; + + } break; + case SL::TYPE_UINT: return itos(p_values[0].uint)+"u"; + case SL::TYPE_UVEC2: + case SL::TYPE_UVEC3: + case SL::TYPE_UVEC4: { + + String text="uvec"+itos(p_type-SL::TYPE_UINT+1)+"("; + for(int i=0;i0) + text+=","; + + text+=itos(p_values[i].uint)+"u"; + } + text+=")"; + return text; + } break; + case SL::TYPE_FLOAT: return f2sp0(p_values[0].real)+"f"; + case SL::TYPE_VEC2: + case SL::TYPE_VEC3: + case SL::TYPE_VEC4: { + + String text="vec"+itos(p_type-SL::TYPE_FLOAT+1)+"("; + for(int i=0;i0) + text+=","; + + text+=f2sp0(p_values[i].real); + } + text+=")"; + return text; + + } break; default: ERR_FAIL_V(String()); } } @@ -189,6 +245,7 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener } r_gen_code.texture_uniforms.resize(max_texture_uniforms); + r_gen_code.texture_hints.resize(max_texture_uniforms); Vector uniform_sizes; uniform_sizes.resize(max_uniforms); @@ -209,6 +266,7 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener r_gen_code.vertex_global+=ucode; r_gen_code.fragment_global+=ucode; r_gen_code.texture_uniforms[E->get().texture_order]=_mkid(E->key()); + r_gen_code.texture_hints[E->get().texture_order]=E->get().hint; } else { if (r_gen_code.uniforms.empty()) { diff --git a/drivers/gles3/shader_compiler_gles3.h b/drivers/gles3/shader_compiler_gles3.h index ad51b99927..dcea82d773 100644 --- a/drivers/gles3/shader_compiler_gles3.h +++ b/drivers/gles3/shader_compiler_gles3.h @@ -21,6 +21,8 @@ public: Vector defines; Vector texture_uniforms; + Vector texture_hints; + Vector uniform_offsets; uint32_t uniform_total_size; String uniforms; diff --git a/drivers/gles3/shaders/copy.glsl b/drivers/gles3/shaders/copy.glsl index eb58d66431..79982ecf25 100644 --- a/drivers/gles3/shaders/copy.glsl +++ b/drivers/gles3/shaders/copy.glsl @@ -5,9 +5,9 @@ layout(location=0) in highp vec4 vertex_attrib; #ifdef USE_CUBEMAP layout(location=4) in vec3 cube_in; #else -layout(location=4) in vec2 uv_in; // attrib:4 +layout(location=4) in vec2 uv_in; #endif -layout(location=5) in vec2 uv2_in; // attrib:5 +layout(location=5) in vec2 uv2_in; #ifdef USE_CUBEMAP out vec3 cube_interp; @@ -40,6 +40,15 @@ uniform sampler2D source; //texunit:0 #endif +float sRGB_gamma_correct(float c){ + float a = 0.055; + if(c < 0.0031308) + return 12.92*c; + else + return (1.0+a)*pow(c, 1.0/2.4) - a; +} + + uniform float stuff; in vec2 uv2_interp; @@ -57,6 +66,20 @@ void main() { vec4 color = texture( source, uv_interp ); #endif +#ifdef LINEAR_TO_SRGB + //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))); +#endif + +#ifdef DEBUG_GRADIENT + color.rg=uv_interp; + color.b=0.0; +#endif + +#ifdef DISABLE_ALPHA + color.a=1.0; +#endif frag_color = color; } diff --git a/drivers/gles3/shaders/cubemap_filter.glsl b/drivers/gles3/shaders/cubemap_filter.glsl index d3d4cbd435..998a59833e 100644 --- a/drivers/gles3/shaders/cubemap_filter.glsl +++ b/drivers/gles3/shaders/cubemap_filter.glsl @@ -3,7 +3,7 @@ layout(location=0) in highp vec2 vertex; -layout(location=1) in highp vec2 uv; +layout(location=4) in highp vec2 uv; out highp vec2 uv_interp; diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index 3f94252606..60ac015a17 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -269,11 +269,16 @@ in vec3 normal_interp; /* PBR CHANNELS */ +//used on forward mainly +uniform bool no_ambient_light; + + #ifdef USE_RADIANCE_CUBEMAP uniform sampler2D brdf_texture; //texunit:-1 uniform samplerCube radiance_cube; //texunit:-2 + layout(std140) uniform Radiance { //ubo:2 mat4 radiance_inverse_xform; @@ -346,8 +351,18 @@ in mediump vec4 forward_shadow_pos4; #endif +#ifdef USE_MULTIPLE_RENDER_TARGETS + +layout(location=0) out vec4 diffuse_buffer; +layout(location=1) out vec4 specular_buffer; +layout(location=2) out vec4 normal_mr_buffer; + +#else + layout(location=0) out vec4 frag_color; +#endif + // GGX Specular // Source: http://www.filmicworlds.com/images/ggx-opt/optimized-ggx.hlsl @@ -470,39 +485,46 @@ FRAGMENT_SHADER_CODE /////////////////////// LIGHTING ////////////////////////////// vec3 specular_light = vec3(0.0,0.0,0.0); - vec3 ambient_light = ambient_light_color.rgb; + vec3 ambient_light; vec3 diffuse_light = vec3(0.0,0.0,0.0); vec3 eye_vec = -normalize( vertex_interp ); #ifdef USE_RADIANCE_CUBEMAP - { + if (no_ambient_light) { + ambient_light=vec3(0.0,0.0,0.0); + } else { + { - float ndotv = clamp(dot(normal,eye_vec),0.0,1.0); - vec2 brdf = texture(brdf_texture, vec2(roughness, ndotv)).xy; + float ndotv = clamp(dot(normal,eye_vec),0.0,1.0); + vec2 brdf = texture(brdf_texture, vec2(roughness, ndotv)).xy; - float lod = roughness * 5.0; - vec3 r = reflect(-eye_vec,normal); //2.0 * ndotv * normal - view; // reflect(v, n); - r=normalize((radiance_inverse_xform * vec4(r,0.0)).xyz); - vec3 radiance = textureLod(radiance_cube, r, lod).xyz * ( brdf.x + brdf.y); + float lod = roughness * 5.0; + vec3 r = reflect(-eye_vec,normal); //2.0 * ndotv * normal - view; // reflect(v, n); + r=normalize((radiance_inverse_xform * vec4(r,0.0)).xyz); + vec3 radiance = textureLod(radiance_cube, r, lod).xyz * ( brdf.x + brdf.y); - specular_light=mix(albedo,radiance,specular); + specular_light=mix(albedo,radiance,specular); - } + } - { + { - vec3 ambient_dir=normalize((radiance_inverse_xform * vec4(normal,0.0)).xyz); - vec3 env_ambient=textureLod(radiance_cube, ambient_dir, 5.0).xyz; + vec3 ambient_dir=normalize((radiance_inverse_xform * vec4(normal,0.0)).xyz); + vec3 env_ambient=textureLod(radiance_cube, ambient_dir, 5.0).xyz; - ambient_light=mix(ambient_light,env_ambient,radiance_ambient_contribution); + ambient_light=mix(ambient_light_color.rgb,env_ambient,radiance_ambient_contribution); + } } - #else - ambient_light=albedo; + if (no_ambient_light){ + ambient_light=vec3(0.0,0.0,0.0); + } else { + ambient_light=ambient_light_color.rgb; + } #endif @@ -538,11 +560,25 @@ LIGHT_SHADER_CODE } #endif -#ifdef SHADELESS +#ifdef USE_MULTIPLE_RENDER_TARGETS + + //approximate ambient scale for SSAO, since we will lack full ambient + float max_ambient=max(ambient_light.r,max(ambient_light.g,ambient_light.b)); + float max_diffuse=max(diffuse_light.r,max(diffuse_light.g,diffuse_light.b)); + float total_ambient = max_ambient+max_diffuse; + float ambient_scale = (total_ambient>0.0) ? max_ambient/total_ambient : 0.0; + diffuse_buffer=vec4(diffuse_light+ambient_light,ambient_scale); + specular_buffer=vec4(specular_light,0.0); + normal_mr_buffer=vec4(normal.x,normal.y,max(specular.r,max(specular.g,specular.b)),roughness); + +#else + +#ifdef SHADELESS frag_color=vec4(albedo,alpha); #else frag_color=vec4(ambient_light+diffuse_light+specular_light,alpha); +#endif #endif -- cgit v1.2.3 From acfa606915416a85106817974e5ba2ec3518c203 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Sat, 29 Oct 2016 22:11:05 -0300 Subject: resolved reflection cubemap blending --- drivers/gles3/rasterizer_storage_gles3.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/gles3') diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index a678c460f5..4b2c607297 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -57,7 +57,7 @@ #define _EXT_ATC_RGBA_INTERPOLATED_ALPHA_AMD 0x87EE - +#define _EXT_TEXTURE_CUBE_MAP_SEAMLESS 0x884F #define _GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE #define _GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF @@ -3946,6 +3946,8 @@ void RasterizerStorageGLES3::initialize() { } shaders.cubemap_filter.init(); + + glEnable(_EXT_TEXTURE_CUBE_MAP_SEAMLESS); } void RasterizerStorageGLES3::finalize() { -- cgit v1.2.3 From 6b2a27bbe5fa112365fc88b9b4678a61293bcb53 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Mon, 31 Oct 2016 08:47:46 -0300 Subject: shadow atlas allocation (work in progress) --- drivers/gles3/rasterizer_scene_gles3.cpp | 433 ++++++++++++++++++++++++++++++- drivers/gles3/rasterizer_scene_gles3.h | 62 ++++- drivers/gles3/shadow_atlas_gles3.cpp | 2 + drivers/gles3/shadow_atlas_gles3.h | 8 + 4 files changed, 493 insertions(+), 12 deletions(-) create mode 100644 drivers/gles3/shadow_atlas_gles3.cpp create mode 100644 drivers/gles3/shadow_atlas_gles3.h (limited to 'drivers/gles3') diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index f7baf1a30b..93dc01d473 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -1,6 +1,6 @@ #include "rasterizer_scene_gles3.h" #include "globals.h" - +#include "os/os.h" @@ -55,7 +55,351 @@ static _FORCE_INLINE_ void store_camera(const CameraMatrix& p_mtx, float* p_arra } } +/* SHADOW ATLAS API */ + +RID RasterizerSceneGLES3::shadow_atlas_create() { + + ShadowAtlas *shadow_atlas = memnew( ShadowAtlas ); + shadow_atlas->fbo=0; + shadow_atlas->depth=0; + shadow_atlas->size=0; + shadow_atlas->smallest_subdiv=0; + + for(int i=0;i<4;i++) { + shadow_atlas->size_order[i]=i; + } + + + return shadow_atlas_owner.make_rid(shadow_atlas); +} + +void RasterizerSceneGLES3::shadow_atlas_set_size(RID p_atlas,int p_size){ + + ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_atlas); + ERR_FAIL_COND(!shadow_atlas); + ERR_FAIL_COND(p_size<0); + if (p_size==shadow_atlas->size) + return; + + if (shadow_atlas->fbo) { + glDeleteTextures(1,&shadow_atlas->depth); + glDeleteFramebuffers(1,&shadow_atlas->fbo); + + shadow_atlas->depth=0; + shadow_atlas->fbo=0; + } + for(int i=0;i<4;i++) { + //clear subdivisions + shadow_atlas->quadrants[i].shadows.resize(0); + shadow_atlas->quadrants[i].shadows.resize( 1<quadrants[i].subdivision ); + } + + //erase shadow atlas reference from lights + for (Map::Element *E=shadow_atlas->shadow_owners.front();E;E=E->next()) { + LightInstance *li = light_instance_owner.getornull(E->key()); + ERR_CONTINUE(!li); + li->shadow_atlases.erase(p_atlas); + } + + //clear owners + shadow_atlas->shadow_owners.clear(); + + shadow_atlas->size=nearest_power_of_2(p_size); + + if (shadow_atlas->size) { + glGenFramebuffers(1, &shadow_atlas->fbo); + glBindFramebuffer(GL_FRAMEBUFFER, shadow_atlas->fbo); + + // Create a texture for storing the depth + 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); + + //interpola nearest (though nvidia can improve this) + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + // Remove artifact on the edges of the shadowmap + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + // We'll use a depth texture to store the depths in the shadow map + // Attach the depth texture to FBO depth attachment point + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GL_TEXTURE_2D, shadow_atlas->depth, 0); + } +} + + +void RasterizerSceneGLES3::shadow_atlas_set_quadrant_subdivision(RID p_atlas,int p_quadrant,int p_subdivision){ + + ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_atlas); + ERR_FAIL_COND(!shadow_atlas); + ERR_FAIL_INDEX(p_quadrant,4); + ERR_FAIL_INDEX(p_subdivision,16384); + + + uint32_t subdiv = nearest_power_of_2(p_subdivision); + if (subdiv&0xaaaaaaaa) { //sqrt(subdiv) must be integer + subdiv<<=1; + } + + subdiv=int(Math::sqrt(subdiv)); + + //obtain the number that will be x*x + + if (shadow_atlas->quadrants[p_quadrant].subdivision==subdiv) + return; + + //erase all data from quadrant + for(int i=0;iquadrants[p_quadrant].shadows.size();i++) { + + if (shadow_atlas->quadrants[p_quadrant].shadows[i].owner.is_valid()) { + shadow_atlas->shadow_owners.erase(shadow_atlas->quadrants[p_quadrant].shadows[i].owner); + LightInstance *li = light_instance_owner.getornull(shadow_atlas->quadrants[p_quadrant].shadows[i].owner); + ERR_CONTINUE(!li); + li->shadow_atlases.erase(p_atlas); + } + } + + shadow_atlas->quadrants[p_quadrant].shadows.resize(0); + shadow_atlas->quadrants[p_quadrant].shadows.resize(subdiv*subdiv); + shadow_atlas->quadrants[p_quadrant].subdivision=subdiv; + + //cache the smallest subdiv (for faster allocation in light update) + + shadow_atlas->smallest_subdiv=1<<30; + + for(int i=0;i<4;i++) { + if (shadow_atlas->quadrants[i].subdivision) { + shadow_atlas->smallest_subdiv=MIN(shadow_atlas->smallest_subdiv,shadow_atlas->quadrants[i].subdivision); + } + } + + if (shadow_atlas->smallest_subdiv==1<<30) { + shadow_atlas->smallest_subdiv=0; + } + + //resort the size orders, simple bublesort for 4 elements.. + + int swaps=0; + do { + swaps=0; + + for(int i=0;i<3;i++) { + if (shadow_atlas->quadrants[shadow_atlas->size_order[i]].subdivision > shadow_atlas->quadrants[shadow_atlas->size_order[i+1]].subdivision) { + SWAP(shadow_atlas->size_order[i],shadow_atlas->size_order[i+1]); + swaps++; + } + } + } while(swaps>0); + + + + + +} + +bool RasterizerSceneGLES3::_shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas,int *p_in_quadrants,int p_quadrant_count,int p_current_subdiv,uint64_t p_tick,int &r_quadrant,int &r_shadow) { + + + for(int i=p_quadrant_count-1;i>=0;i--) { + int qidx = p_in_quadrants[i]; + + if (shadow_atlas->quadrants[qidx].subdivision==p_current_subdiv) { + return false; + } + + //look for an empty space + int sc = shadow_atlas->quadrants[qidx].shadows.size(); + ShadowAtlas::Quadrant::Shadow *sarr = shadow_atlas->quadrants[qidx].shadows.ptr(); + + int found_free_idx=-1; //found a free one + int found_used_idx=-1; //found existing one, must steal it + uint64_t min_pass; // pass of the existing one, try to use the least recently used one (LRU fashion) + + for(int j=0;jlast_scene_pass!=scene_pass) { + + //was just allocated, don't kill it so soon, wait a bit.. + if (p_tick-sarr[j].alloc_tick < shadow_atlas_realloc_tolerance_msec) + continue; + + if (found_used_idx==-1 || sli->last_scene_passlast_scene_pass; + } + } + } + + if (found_free_idx==-1 && found_used_idx==-1) + continue; //nothing found + + if (found_free_idx==-1 && found_used_idx!=-1) { + found_free_idx=found_used_idx; + } + + r_quadrant=qidx; + r_shadow=found_free_idx; + + return true; + } + + return false; + +} + + +uint32_t RasterizerSceneGLES3::shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version){ + + ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_atlas); + ERR_FAIL_COND_V(!shadow_atlas,ShadowAtlas::SHADOW_INVALID); + + LightInstance *li = light_instance_owner.getornull(p_light_intance); + ERR_FAIL_COND_V(!li,ShadowAtlas::SHADOW_INVALID); + + if (shadow_atlas->size==0 || shadow_atlas->smallest_subdiv==0) { + return ShadowAtlas::SHADOW_INVALID; + } + + uint32_t quad_size = shadow_atlas->size>>1; + int desired_fit = MAX(quad_size/shadow_atlas->smallest_subdiv,nearest_power_of_2(quad_size*p_coverage)); + + int valid_quadrants[4]; + int valid_quadrant_count=0; + int best_size=-1; //best size found + int best_subdiv=-1; //subdiv for the best size + + //find the quadrants this fits into, and the best possible size it can fit into + for(int i=0;i<4;i++) { + int q = shadow_atlas->size_order[i]; + int sd = shadow_atlas->quadrants[q].subdivision; + if (sd==0) + continue; //unused + + int max_fit = quad_size / sd; + + if (best_size!=-1 && max_fit>best_size) + break; //too large + + valid_quadrants[valid_quadrant_count++]=q; + best_subdiv=sd; + + if (max_fit>=desired_fit) { + best_size=max_fit; + } + } + + + ERR_FAIL_COND_V(valid_quadrant_count==0,ShadowAtlas::SHADOW_INVALID); + + uint64_t tick = OS::get_singleton()->get_ticks_msec(); + + + //see if it already exists + + if (shadow_atlas->shadow_owners.has(p_light_intance)) { + //it does! + uint32_t key = shadow_atlas->shadow_owners[p_light_intance]; + uint32_t q = (key>>ShadowAtlas::QUADRANT_SHIFT)&0x3; + uint32_t s = key&ShadowAtlas::SHADOW_INDEX_MASK; + + bool should_realloc=shadow_atlas->quadrants[q].subdivision!=best_subdiv && (shadow_atlas->quadrants[q].shadows[s].alloc_tick-tick > shadow_atlas_realloc_tolerance_msec); + bool should_redraw=shadow_atlas->quadrants[q].shadows[s].version!=p_light_version; + + if (!should_realloc) { + //already existing, see if it should redraw or it's just OK + if (should_redraw) { + key|=ShadowAtlas::SHADOW_INDEX_DIRTY_BIT; + } + + return key; + } + + int new_quadrant,new_shadow; + + //find a better place + if (_shadow_atlas_find_shadow(shadow_atlas,valid_quadrants,valid_quadrant_count,shadow_atlas->quadrants[q].subdivision,tick,new_quadrant,new_shadow)) { + //found a better place! + ShadowAtlas::Quadrant::Shadow *sh = &shadow_atlas->quadrants[new_quadrant].shadows[new_shadow]; + if (sh->owner.is_valid()) { + //is taken, but is invalid, erasing it + shadow_atlas->shadow_owners.erase(sh->owner); + LightInstance *sli = light_instance_owner.get(sh->owner); + sli->shadow_atlases.erase(p_atlas); + } + + sh->owner=p_light_intance; + sh->alloc_tick=tick; + sh->version=p_light_version; + + //make new key + key=new_quadrant<shadow_owners[p_light_intance]=key; + //make it dirty, as it should redraw anyway + key|=ShadowAtlas::SHADOW_INDEX_DIRTY_BIT; + + return key; + } + + //no better place for this shadow found, keep current + + //already existing, see if it should redraw or it's just OK + if (should_redraw) { + key|=ShadowAtlas::SHADOW_INDEX_DIRTY_BIT; + } + + return key; + } + + int new_quadrant,new_shadow; + + //find a better place + if (_shadow_atlas_find_shadow(shadow_atlas,valid_quadrants,valid_quadrant_count,-1,tick,new_quadrant,new_shadow)) { + //found a better place! + ShadowAtlas::Quadrant::Shadow *sh = &shadow_atlas->quadrants[new_quadrant].shadows[new_shadow]; + if (sh->owner.is_valid()) { + //is taken, but is invalid, erasing it + shadow_atlas->shadow_owners.erase(sh->owner); + LightInstance *sli = light_instance_owner.get(sh->owner); + sli->shadow_atlases.erase(p_atlas); + } + + sh->owner=p_light_intance; + sh->alloc_tick=tick; + sh->version=p_light_version; + + //make new key + uint32_t key=new_quadrant<shadow_owners[p_light_intance]=key; + //make it dirty, as it should redraw anyway + key|=ShadowAtlas::SHADOW_INDEX_DIRTY_BIT; + + return key; + } + + //no place to allocate this light, apologies + + return ShadowAtlas::SHADOW_INVALID; + + + + +} /* ENVIRONMENT API */ @@ -162,9 +506,12 @@ void RasterizerSceneGLES3::environment_set_adjustment(RID p_env,bool p_enable,fl RID RasterizerSceneGLES3::light_instance_create(RID p_light) { - print_line("hello light"); + LightInstance *light_instance = memnew( LightInstance ); + light_instance->last_pass=0; + light_instance->last_scene_pass=0; + light_instance->light=p_light; light_instance->light_ptr=storage->light_owner.getornull(p_light); @@ -187,6 +534,18 @@ void RasterizerSceneGLES3::light_instance_set_transform(RID p_light_instance,con light_instance->transform=p_transform; } +void RasterizerSceneGLES3::light_instance_mark_visible(RID p_light_instance) { + + LightInstance *light_instance = light_instance_owner.getornull(p_light_instance); + ERR_FAIL_COND(!light_instance); + + light_instance->last_scene_pass=scene_pass; +} + + +//////////////////////////// +//////////////////////////// +//////////////////////////// bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material* p_material,bool p_alpha_pass) { @@ -851,13 +1210,13 @@ void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_g if (shadow || m->shader->spatial.unshaded /*|| current_debug==VS::SCENARIO_DEBUG_SHADELESS*/) { - e->sort_key=RenderList::SORT_KEY_LIGHT_INDEX_UNSHADED; + e->sort_key|=RenderList::SORT_KEY_LIGHT_INDEX_UNSHADED; e->sort_key|=uint64_t(0xF)<sort_key|=uint64_t(0xFFFF)<additive_ptr=&e->additive; + ec->sort_key&=~RenderList::SORT_KEY_LIGHT_MASK; ec->sort_key|=uint64_t(directional_light_instances[i]->light_index) << RenderList::SORT_KEY_LIGHT_INDEX_SHIFT; ec->sort_key|=uint64_t(VS::LIGHT_DIRECTIONAL) << RenderList::SORT_KEY_LIGHT_TYPE_SHIFT; - lighted=true; + lit=true; } @@ -922,14 +1282,16 @@ void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_g ec->additive_ptr=&e->additive; + ec->sort_key&=~RenderList::SORT_KEY_LIGHT_MASK; ec->sort_key|=uint64_t(li->light_index) << RenderList::SORT_KEY_LIGHT_INDEX_SHIFT; ec->sort_key|=uint64_t(li->light_ptr->type) << RenderList::SORT_KEY_LIGHT_TYPE_SHIFT; - lighted=true; + lit=true; } - if (!lighted) { + if (!lit) { + e->sort_key&=~RenderList::SORT_KEY_LIGHT_MASK; e->sort_key|=uint64_t(0xE)<sort_key|=uint64_t(0xFFFF)< lpercent; + for(int i=0;i=RenderList::MAX_LIGHTS ); @@ -1140,6 +1504,7 @@ void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result,int p_light_cu + #if 0 if (li->light_ptr->shadow_enabled) { CameraMatrix bias; @@ -1181,6 +1546,26 @@ void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result,int p_light_cu li->light_ubo_data.light_params[2]=0; li->light_ubo_data.light_params[3]=0; +#if 0 + + Transform ai = p_camera_inverse_transform.affine_inverse(); + float zn = p_camera_projection.get_z_near(); + Plane p (ai.origin + ai.basis.get_axis(2) * -zn, -ai.basis.get_axis(2) ); + + Vector3 point1 = li->transform.origin; + Vector3 point2 = li->transform.origin+p_camera_inverse_transform.affine_inverse().basis.get_axis(1).normalized()*li->light_ptr->param[VS::LIGHT_PARAM_RANGE]; + + p.intersects_segment(ai.origin,point1,&point1); + p.intersects_segment(ai.origin,point2,&point2); + float r = point1.distance_to(point2); + + float vp_w,vp_h; + p_camera_projection.get_viewport_size(vp_w,vp_h); + + lpercent.push_back(r*2/((vp_h+vp_w)*0.5)); + +#endif + #if 0 if (li->light_ptr->shadow_enabled) { li->shadow_projection[0] = Transform(camera_transform_inverse * li->transform).inverse(); @@ -1245,8 +1630,8 @@ void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result,int p_light_cu glBindBuffer(GL_UNIFORM_BUFFER, 0); light_instances[i]=li; + light_instance_count++; } - } void RasterizerSceneGLES3::_copy_screen() { @@ -1305,7 +1690,7 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,CameraM _setup_environment(env,p_cam_projection,p_cam_transform); - _setup_lights(p_light_cull_result,p_light_cull_count,p_cam_transform.affine_inverse()); + _setup_lights(p_light_cull_result,p_light_cull_count,p_cam_transform.affine_inverse(),p_cam_projection); render_list.clear(); @@ -1609,16 +1994,40 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,CameraM #endif } +void RasterizerSceneGLES3::set_scene_pass(uint64_t p_pass) { + scene_pass=p_pass; +} + bool RasterizerSceneGLES3::free(RID p_rid) { if (light_instance_owner.owns(p_rid)) { - print_line("bye light"); + LightInstance *light_instance = light_instance_owner.getptr(p_rid); + + //remove from shadow atlases.. + for(Set::Element *E=light_instance->shadow_atlases.front();E;E=E->next()) { + ShadowAtlas *shadow_atlas = shadow_atlas_owner.get(E->get()); + ERR_CONTINUE(!shadow_atlas->shadow_owners.has(p_rid)); + uint32_t key = shadow_atlas->shadow_owners[p_rid]; + uint32_t q = (key>>ShadowAtlas::QUADRANT_SHIFT)&0x3; + uint32_t s = key&ShadowAtlas::SHADOW_INDEX_MASK; + + shadow_atlas->quadrants[q].shadows[s].owner=RID(); + shadow_atlas->shadow_owners.erase(p_rid); + } + + glDeleteBuffers(1,&light_instance->light_ubo); light_instance_owner.free(p_rid); memdelete(light_instance); + } else if (shadow_atlas_owner.owns(p_rid)) { + + ShadowAtlas *shadow_atlas = shadow_atlas_owner.get(p_rid); + shadow_atlas_set_size(p_rid,0); + shadow_atlas_owner.free(p_rid); + memdelete(shadow_atlas); } else { return false; @@ -1800,6 +2209,8 @@ void RasterizerSceneGLES3::initialize() { } render_list.init(); _generate_brdf(); + + shadow_atlas_realloc_tolerance_msec=500; } void RasterizerSceneGLES3::finalize(){ diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 5457b5cde3..9df6315e45 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -7,7 +7,11 @@ class RasterizerSceneGLES3 : public RasterizerScene { public: + uint64_t shadow_atlas_realloc_tolerance_msec; + + uint64_t render_pass; + uint64_t scene_pass; uint32_t current_material_index; uint32_t current_geometry_index; @@ -62,8 +66,58 @@ public: } state; + /* SHADOW ATLAS API */ + + struct ShadowAtlas : public RID_Data { + + enum { + SHADOW_INDEX_DIRTY_BIT=(1<<31), + QUADRANT_SHIFT=27, + SHADOW_INDEX_MASK=(1< shadows; + Quadrant() { + subdivision=0; //not in use + } + + } quadrants[4]; + + int size_order[4]; + uint32_t smallest_subdiv; + + int size; + + GLuint fbo; + GLuint depth; + + Map shadow_owners; + }; + + RID_Owner shadow_atlas_owner; + + RID shadow_atlas_create(); + void shadow_atlas_set_size(RID p_atlas,int p_size); + void shadow_atlas_set_quadrant_subdivision(RID p_atlas,int p_quadrant,int p_subdivision); + bool _shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, int &r_quadrant, int &r_shadow); + uint32_t shadow_atlas_update_light(RID p_atlas,RID p_light_intance,float p_coverage,uint64_t p_light_version); /* ENVIRONMENT API */ @@ -159,6 +213,7 @@ public: GLuint light_ubo; uint64_t shadow_pass; + uint64_t last_scene_pass; uint64_t last_pass; uint16_t light_index; @@ -166,6 +221,7 @@ public: CameraMatrix shadow_projection[4]; + Set shadow_atlases; //shadow atlases where this light is registered LightInstance() { } @@ -175,6 +231,7 @@ public: virtual RID light_instance_create(RID p_light); virtual void light_instance_set_transform(RID p_light_instance,const Transform& p_transform); + virtual void light_instance_mark_visible(RID p_light_instance); /* RENDER LIST */ @@ -190,6 +247,7 @@ public: SORT_KEY_LIGHT_TYPE_SHIFT=54, //type is most important SORT_KEY_LIGHT_INDEX_SHIFT=38, //type is most important SORT_KEY_LIGHT_INDEX_UNSHADED=uint64_t(0xF) << SORT_KEY_LIGHT_TYPE_SHIFT, //type is most important + SORT_KEY_LIGHT_MASK=(uint64_t(0xFFFFF) << SORT_KEY_LIGHT_INDEX_SHIFT), //type is most important SORT_KEY_MATERIAL_INDEX_SHIFT=22, SORT_KEY_GEOMETRY_INDEX_SHIFT=6, SORT_KEY_GEOMETRY_TYPE_SHIFT=2, @@ -327,7 +385,7 @@ public: void _draw_skybox(RID p_skybox, CameraMatrix& p_projection, const Transform& p_transform, bool p_vflip, float p_scale); void _setup_environment(Environment *env,CameraMatrix& p_cam_projection, const Transform& p_cam_transform); - void _setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform); + void _setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform,const CameraMatrix& p_camera_projection); void _copy_screen(); void _copy_to_front_buffer(Environment *env); @@ -337,6 +395,8 @@ public: void _generate_brdf(); + virtual void set_scene_pass(uint64_t p_pass); + void initialize(); void finalize(); RasterizerSceneGLES3(); diff --git a/drivers/gles3/shadow_atlas_gles3.cpp b/drivers/gles3/shadow_atlas_gles3.cpp new file mode 100644 index 0000000000..38dee8bcea --- /dev/null +++ b/drivers/gles3/shadow_atlas_gles3.cpp @@ -0,0 +1,2 @@ +#include "shadow_atlas_gles3.h" + diff --git a/drivers/gles3/shadow_atlas_gles3.h b/drivers/gles3/shadow_atlas_gles3.h new file mode 100644 index 0000000000..46eaf581cb --- /dev/null +++ b/drivers/gles3/shadow_atlas_gles3.h @@ -0,0 +1,8 @@ +#ifndef SHADOW_ATLAS_GLES3_H +#define SHADOW_ATLAS_GLES3_H + +#include "rasterizer_storage_gles3.h" + + + +#endif // SHADOW_ATLAS_GLES3_H -- cgit v1.2.3 From cacf9ebb7fd8df8845daca9da2fe55456cc179aa Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Wed, 9 Nov 2016 23:55:06 -0300 Subject: all light types and shadows are working, pending a lot of clean-up --- drivers/gles3/rasterizer_canvas_gles3.cpp | 2 - drivers/gles3/rasterizer_scene_gles3.cpp | 1043 ++++++++++++++++++++++------ drivers/gles3/rasterizer_scene_gles3.h | 74 +- drivers/gles3/rasterizer_storage_gles3.cpp | 324 ++++++++- drivers/gles3/rasterizer_storage_gles3.h | 101 ++- drivers/gles3/shader_compiler_gles3.cpp | 15 +- drivers/gles3/shader_compiler_gles3.h | 7 + drivers/gles3/shaders/SCsub | 1 + drivers/gles3/shaders/cube_to_dp.glsl | 79 +++ drivers/gles3/shaders/scene.glsl | 341 +++++++-- 10 files changed, 1678 insertions(+), 309 deletions(-) create mode 100644 drivers/gles3/shaders/cube_to_dp.glsl (limited to 'drivers/gles3') diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index c10c5fee65..c455d4bd11 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -824,8 +824,6 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list,int p_z,const bool prev_distance_field=false; - - while(p_item_list) { Item *ci=p_item_list; diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 93dc01d473..287801b597 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -1,8 +1,18 @@ #include "rasterizer_scene_gles3.h" #include "globals.h" #include "os/os.h" +#include "rasterizer_canvas_gles3.h" +static const GLenum _cube_side_enum[6]={ + GL_TEXTURE_CUBE_MAP_NEGATIVE_X, + GL_TEXTURE_CUBE_MAP_POSITIVE_X, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, + GL_TEXTURE_CUBE_MAP_POSITIVE_Y, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, + GL_TEXTURE_CUBE_MAP_POSITIVE_Z, + +}; static _FORCE_INLINE_ void store_matrix32(const Matrix32& p_mtx, float* p_array) { @@ -78,6 +88,9 @@ void RasterizerSceneGLES3::shadow_atlas_set_size(RID p_atlas,int p_size){ ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_atlas); ERR_FAIL_COND(!shadow_atlas); ERR_FAIL_COND(p_size<0); + + p_size = nearest_power_of_2(p_size); + if (p_size==shadow_atlas->size) return; @@ -104,7 +117,7 @@ void RasterizerSceneGLES3::shadow_atlas_set_size(RID p_atlas,int p_size){ //clear owners shadow_atlas->shadow_owners.clear(); - shadow_atlas->size=nearest_power_of_2(p_size); + shadow_atlas->size=p_size; if (shadow_atlas->size) { glGenFramebuffers(1, &shadow_atlas->fbo); @@ -188,7 +201,7 @@ void RasterizerSceneGLES3::shadow_atlas_set_quadrant_subdivision(RID p_atlas,int swaps=0; for(int i=0;i<3;i++) { - if (shadow_atlas->quadrants[shadow_atlas->size_order[i]].subdivision > shadow_atlas->quadrants[shadow_atlas->size_order[i+1]].subdivision) { + if (shadow_atlas->quadrants[shadow_atlas->size_order[i]].subdivision < shadow_atlas->quadrants[shadow_atlas->size_order[i+1]].subdivision) { SWAP(shadow_atlas->size_order[i],shadow_atlas->size_order[i+1]); swaps++; } @@ -260,20 +273,22 @@ bool RasterizerSceneGLES3::_shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas,i } -uint32_t RasterizerSceneGLES3::shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version){ +bool RasterizerSceneGLES3::shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version){ + ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_atlas); - ERR_FAIL_COND_V(!shadow_atlas,ShadowAtlas::SHADOW_INVALID); + ERR_FAIL_COND_V(!shadow_atlas,false); LightInstance *li = light_instance_owner.getornull(p_light_intance); - ERR_FAIL_COND_V(!li,ShadowAtlas::SHADOW_INVALID); + ERR_FAIL_COND_V(!li,false); if (shadow_atlas->size==0 || shadow_atlas->smallest_subdiv==0) { - return ShadowAtlas::SHADOW_INVALID; + return false; } uint32_t quad_size = shadow_atlas->size>>1; - int desired_fit = MAX(quad_size/shadow_atlas->smallest_subdiv,nearest_power_of_2(quad_size*p_coverage)); + int desired_fit = MIN(quad_size/shadow_atlas->smallest_subdiv,nearest_power_of_2(quad_size*p_coverage)); + int valid_quadrants[4]; int valid_quadrant_count=0; @@ -300,8 +315,7 @@ uint32_t RasterizerSceneGLES3::shadow_atlas_update_light(RID p_atlas, RID p_ligh } } - - ERR_FAIL_COND_V(valid_quadrant_count==0,ShadowAtlas::SHADOW_INVALID); + ERR_FAIL_COND_V(valid_quadrant_count==0,false); uint64_t tick = OS::get_singleton()->get_ticks_msec(); @@ -317,13 +331,12 @@ uint32_t RasterizerSceneGLES3::shadow_atlas_update_light(RID p_atlas, RID p_ligh bool should_realloc=shadow_atlas->quadrants[q].subdivision!=best_subdiv && (shadow_atlas->quadrants[q].shadows[s].alloc_tick-tick > shadow_atlas_realloc_tolerance_msec); bool should_redraw=shadow_atlas->quadrants[q].shadows[s].version!=p_light_version; + + if (!should_realloc) { + shadow_atlas->quadrants[q].shadows[s].version=p_light_version; //already existing, see if it should redraw or it's just OK - if (should_redraw) { - key|=ShadowAtlas::SHADOW_INDEX_DIRTY_BIT; - } - - return key; + return should_redraw; } int new_quadrant,new_shadow; @@ -339,6 +352,10 @@ uint32_t RasterizerSceneGLES3::shadow_atlas_update_light(RID p_atlas, RID p_ligh sli->shadow_atlases.erase(p_atlas); } + //erase previous + shadow_atlas->quadrants[q].shadows[s].version=0; + shadow_atlas->quadrants[q].shadows[s].owner=RID(); + sh->owner=p_light_intance; sh->alloc_tick=tick; sh->version=p_light_version; @@ -349,19 +366,16 @@ uint32_t RasterizerSceneGLES3::shadow_atlas_update_light(RID p_atlas, RID p_ligh //update it in map shadow_atlas->shadow_owners[p_light_intance]=key; //make it dirty, as it should redraw anyway - key|=ShadowAtlas::SHADOW_INDEX_DIRTY_BIT; - - return key; + return true; } //no better place for this shadow found, keep current //already existing, see if it should redraw or it's just OK - if (should_redraw) { - key|=ShadowAtlas::SHADOW_INDEX_DIRTY_BIT; - } - return key; + shadow_atlas->quadrants[q].shadows[s].version=p_light_version; + + return should_redraw; } int new_quadrant,new_shadow; @@ -387,20 +401,49 @@ uint32_t RasterizerSceneGLES3::shadow_atlas_update_light(RID p_atlas, RID p_ligh //update it in map shadow_atlas->shadow_owners[p_light_intance]=key; //make it dirty, as it should redraw anyway - key|=ShadowAtlas::SHADOW_INDEX_DIRTY_BIT; - return key; + return true; } //no place to allocate this light, apologies - return ShadowAtlas::SHADOW_INVALID; + return false; } +void RasterizerSceneGLES3::set_directional_shadow_count(int p_count) { + + directional_shadow.light_count=p_count; + directional_shadow.current_light=0; +} + +int RasterizerSceneGLES3::get_directional_light_shadow_size(RID p_light_intance) { + + ERR_FAIL_COND_V(directional_shadow.light_count==0,0); + + int shadow_size; + + if (directional_shadow.light_count==1) { + shadow_size = directional_shadow.size; + } else { + shadow_size = directional_shadow.size/2; //more than 4 not supported anyway + } + + LightInstance *light_instance = light_instance_owner.getornull(p_light_intance); + ERR_FAIL_COND_V(!light_instance,0); + + switch(light_instance->light_ptr->directional_shadow_mode) { + case VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: break; //none + case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: + case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: shadow_size/=2; break; + } + + return shadow_size; + +} /* ENVIRONMENT API */ @@ -511,6 +554,7 @@ RID RasterizerSceneGLES3::light_instance_create(RID p_light) { light_instance->last_pass=0; light_instance->last_scene_pass=0; + light_instance->last_scene_shadow_pass=0; light_instance->light=p_light; light_instance->light_ptr=storage->light_owner.getornull(p_light); @@ -520,10 +564,11 @@ RID RasterizerSceneGLES3::light_instance_create(RID p_light) { glBufferData(GL_UNIFORM_BUFFER, sizeof(LightInstance::LightDataUBO), NULL, GL_DYNAMIC_DRAW); glBindBuffer(GL_UNIFORM_BUFFER, 0); - ERR_FAIL_COND_V(!light_instance->light_ptr,RID()); - return light_instance_owner.make_rid(light_instance); + light_instance->self=light_instance_owner.make_rid(light_instance); + + return light_instance->self; } void RasterizerSceneGLES3::light_instance_set_transform(RID p_light_instance,const Transform& p_transform){ @@ -534,6 +579,25 @@ void RasterizerSceneGLES3::light_instance_set_transform(RID p_light_instance,con light_instance->transform=p_transform; } +void RasterizerSceneGLES3::light_instance_set_shadow_transform(RID p_light_instance,const CameraMatrix& p_projection,const Transform& p_transform,float p_far,float p_split,int p_pass) { + + LightInstance *light_instance = light_instance_owner.getornull(p_light_instance); + ERR_FAIL_COND(!light_instance); + + if (light_instance->light_ptr->type!=VS::LIGHT_DIRECTIONAL) { + p_pass=0; + } + + ERR_FAIL_INDEX(p_pass,4); + + light_instance->shadow_transform[p_pass].camera=p_projection; + light_instance->shadow_transform[p_pass].transform=p_transform; + light_instance->shadow_transform[p_pass].far=p_far; + light_instance->shadow_transform[p_pass].split=p_split; + +} + + void RasterizerSceneGLES3::light_instance_mark_visible(RID p_light_instance) { LightInstance *light_instance = light_instance_owner.getornull(p_light_instance); @@ -542,7 +606,6 @@ void RasterizerSceneGLES3::light_instance_mark_visible(RID p_light_instance) { light_instance->last_scene_pass=scene_pass; } - //////////////////////////// //////////////////////////// //////////////////////////// @@ -757,9 +820,10 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) { void RasterizerSceneGLES3::_setup_light(LightInstance *p_light) { - glBindBufferBase(GL_UNIFORM_BUFFER,3,p_light->light_ubo); //bind light uniform } + + void RasterizerSceneGLES3::_setup_transform(InstanceBase *p_instance,const Transform& p_view_transform,const CameraMatrix& p_projection) { if (p_instance->billboard || p_instance->billboard_y || p_instance->depth_scale) { @@ -815,7 +879,22 @@ void RasterizerSceneGLES3::_setup_transform(InstanceBase *p_instance,const Trans } } -void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_element_count,const Transform& p_view_transform,const CameraMatrix& p_projection,RasterizerStorageGLES3::Texture* p_base_env,bool p_reverse_cull,bool p_alpha_pass) { +void RasterizerSceneGLES3::_set_cull(bool p_front,bool p_reverse_cull) { + + bool front = p_front; + if (p_reverse_cull) + front=!front; + + if (front!=state.cull_front) { + + glCullFace(front?GL_FRONT:GL_BACK); + state.cull_front=front; + } +} + + + +void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_element_count,const Transform& p_view_transform,const CameraMatrix& p_projection,RasterizerStorageGLES3::Texture* p_base_env,bool p_reverse_cull,bool p_alpha_pass,bool p_shadow) { if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP]) { //p_reverse_cull=!p_reverse_cull; @@ -824,25 +903,30 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e glFrontFace(GL_CW); } - bool shadow=false; - glBindBufferBase(GL_UNIFORM_BUFFER,0,state.scene_ubo); //bind globals ubo - glBindBufferBase(GL_UNIFORM_BUFFER,2,state.env_radiance_ubo); //bind environment radiance info - glActiveTexture(GL_TEXTURE0+storage->config.max_texture_image_units-1); - glBindTexture(GL_TEXTURE_2D,state.brdf_texture); + if (!p_shadow) { + glBindBufferBase(GL_UNIFORM_BUFFER,2,state.env_radiance_ubo); //bind environment radiance info + glActiveTexture(GL_TEXTURE0+storage->config.max_texture_image_units-1); + glBindTexture(GL_TEXTURE_2D,state.brdf_texture); - if (p_base_env) { - glActiveTexture(GL_TEXTURE0+storage->config.max_texture_image_units-2); - glBindTexture(p_base_env->target,p_base_env->tex_id); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_CUBEMAP,true); + if (p_base_env) { + glActiveTexture(GL_TEXTURE0+storage->config.max_texture_image_units-2); + glBindTexture(p_base_env->target,p_base_env->tex_id); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_CUBEMAP,true); + } else { + state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_CUBEMAP,false); + + } } else { - state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_CUBEMAP,false); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_CUBEMAP,false); } + state.cull_front=false; + glCullFace(GL_BACK); state.scene_shader.set_conditional(SceneShaderGLES3::USE_SKELETON,false); @@ -875,28 +959,8 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e bool additive=false; - if (!shadow) { -#if 0 - if (texscreen_used && !texscreen_copied && material->shader_cache && material->shader_cache->valid && material->shader_cache->has_texscreen) { - texscreen_copied=true; - _copy_to_texscreen(); - - //force reset state - prev_material=NULL; - prev_light=0x777E; - prev_geometry_cmp=NULL; - prev_light_type=0xEF; - prev_skeleton =NULL; - prev_sort_flags=0xFF; - prev_morph_values=NULL; - prev_receive_shadows_state=-1; - glEnable(GL_BLEND); - glDepthMask(GL_TRUE); - glEnable(GL_DEPTH_TEST); - glDisable(GL_SCISSOR_TEST); + if (!p_shadow) { - } -#endif if (light_type!=prev_light_type /* || receive_shadows_state!=prev_receive_shadows_state*/) { if (material->shader->spatial.unshaded/* || current_debug==VS::SCENARIO_DEBUG_SHADELESS*/) { @@ -905,27 +969,38 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_OMNI,false); state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_SPOT,false); state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS,true); + state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_DIRECTIONAL_SHADOW,false); + state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM4,false); + state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM2,false); + state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM_BLEND,false); + //state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS,true); } else { state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS,false); state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_LIGHTING,light_type!=0xF); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_DIRECTIONAL,light_type==VS::LIGHT_DIRECTIONAL); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_OMNI,light_type==VS::LIGHT_OMNI); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_SPOT,light_type==VS::LIGHT_SPOT); - /* - if (receive_shadows_state==1) { - state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_SHADOW,(light_type&0x8)); - state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM,(light_type&0x10)); - state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM4,(light_type&0x20)); - } - else { - state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_SHADOW,false); - state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM,false); - state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM4,false); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_DIRECTIONAL,(light_type&3)==VS::LIGHT_DIRECTIONAL); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_OMNI,(light_type&0xF)==VS::LIGHT_OMNI); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_SPOT,(light_type&0xF)==VS::LIGHT_SPOT); + state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_DIRECTIONAL_SHADOW,false); + state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM4,false); + state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM2,false); + state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM_BLEND,false); + + if ((light_type&3)==VS::LIGHT_DIRECTIONAL) { + + if (light_instances[light_index]->light_ptr->shadow) { + state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_DIRECTIONAL_SHADOW,true); + + switch(light_instances[light_index]->light_ptr->directional_shadow_mode) { + case VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: break; //none + case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM2,true); break; + case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM4,true); break; + } + } } - state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS,false); - */ + + } rebind=true; @@ -1007,14 +1082,16 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e current_blend_mode=desired_blend_mode; } - } - if (light_index!=prev_light_index) { - if (light_index!=0xFFFF) { //not unshaded - _setup_light(light_instances[light_index]); + if (light_index!=prev_light_index) { + if (light_index!=0xFFFF) { //not unshaded + _setup_light(light_instances[light_index]); + } } + } + if (material!=prev_material || rebind) { rebind = _setup_material(material,p_alpha_pass); @@ -1027,20 +1104,17 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e _setup_geometry(e); } - if (rebind || prev_additive!=additive) { + if (!p_shadow && (rebind || prev_additive!=additive)) { state.scene_shader.set_uniform(SceneShaderGLES3::NO_AMBIENT_LIGHT, additive); } -// _set_cull(e->mirror,p_reverse_cull); + _set_cull(e->sort_key&RenderList::SORT_KEY_MIRROR_FLAG,p_reverse_cull); state.scene_shader.set_uniform(SceneShaderGLES3::NORMAL_MULT, e->instance->mirror?-1.0:1.0); _setup_transform(e->instance,p_view_transform,p_projection); - -// _render(e->geometry, material, skeleton,e->owner,e->instance->transform); - _render_geometry(e); prev_material=material; @@ -1052,15 +1126,26 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e } - //print_line("shaderchanges: "+itos(p_alpha_pass)+": "+itos(_rinfo.shader_change_count)); glFrontFace(GL_CW); glBindVertexArray(0); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_CUBEMAP,false); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_LIGHTING,false); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_DIRECTIONAL,false); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_OMNI,false); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_SPOT,false); + state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_DIRECTIONAL_SHADOW,false); + state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM4,false); + state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM2,false); + state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM_BLEND,false); + state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS,false); + } -void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner,int p_material) { + +void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner,int p_material,bool p_shadow) { RasterizerStorageGLES3::Material *m=NULL; RID m_src=p_instance->material_override.is_valid() ? p_instance->material_override :(p_material>=0?p_instance->materials[p_material]:p_geometry->material); @@ -1096,57 +1181,29 @@ void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_g bool has_alpha = has_base_alpha || has_blend_alpha; bool shadow = false; -#if 0 - if (shadow) { + bool mirror = p_instance->mirror; - if (has_blend_alpha || (has_base_alpha && m->depth_draw_mode!=VS::MATERIAL_DEPTH_DRAW_OPAQUE_PRE_PASS_ALPHA)) + if (m->shader->spatial.cull_mode==RasterizerStorageGLES3::Shader::Spatial::CULL_MODE_FRONT) { + mirror=!mirror; + } + + if (p_shadow) { + + if (has_blend_alpha || (has_base_alpha && m->shader->spatial.depth_draw_mode!=RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS)) return; //bye - if (!m->shader_cache || (!m->shader_cache->writes_vertex && !m->shader_cache->uses_discard && m->depth_draw_mode!=VS::MATERIAL_DEPTH_DRAW_OPAQUE_PRE_PASS_ALPHA)) { + if (!m->shader->spatial.uses_vertex && !m->shader->spatial.uses_discard && m->shader->spatial.depth_draw_mode!=RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) { //shader does not use discard and does not write a vertex position, use generic material if (p_instance->cast_shadows == VS::SHADOW_CASTING_SETTING_DOUBLE_SIDED) - m = shadow_mat_double_sided_ptr; + m = storage->material_owner.getptr(default_material_twosided); else - m = shadow_mat_ptr; - if (m->last_pass!=frame) { - - if (m->shader.is_valid()) { - - m->shader_cache=shader_owner.get(m->shader); - if (m->shader_cache) { - - - if (!m->shader_cache->valid) - m->shader_cache=NULL; - } else { - m->shader=RID(); - } - - } else { - m->shader_cache=NULL; - } - - m->last_pass=frame; - } + m = storage->material_owner.getptr(default_material); } - render_list = &opaque_render_list; - /* notyet - if (!m->shader_cache || m->shader_cache->can_zpass) - render_list = &alpha_render_list; - } else { - render_list = &opaque_render_list; - }*/ - - } else { - if (has_alpha) { - render_list = &alpha_render_list; - } else { - render_list = &opaque_render_list; + has_alpha=false; - } } -#endif + RenderList::Element *e = has_alpha ? render_list.add_alpha_element() : render_list.add_element(); @@ -1161,50 +1218,49 @@ void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_g e->additive_ptr=&e->additive; e->sort_key=0; - if (e->geometry->last_pass!=render_pass) { e->geometry->last_pass=render_pass; e->geometry->index=current_geometry_index++; } + e->sort_key|=uint64_t(e->geometry->index)<sort_key|=uint64_t(e->instance->base_type)<material->last_pass!=render_pass) { - e->material->last_pass=render_pass; - e->material->index=current_material_index++; - } + if (!p_shadow) { - e->sort_key|=uint64_t(e->material->index)<sort_key|=uint64_t(e->instance->depth_layer)<geometry->type==RasterizerStorageGLES3::Geometry::GEOMETRY_MULTISURFACE) - // e->sort_flags|=RenderList::SORT_FLAG_INSTANCING; + if (e->material->last_pass!=render_pass) { + e->material->last_pass=render_pass; + e->material->index=current_material_index++; + } - bool mirror = e->instance->mirror; + e->sort_key|=uint64_t(e->material->index)<sort_key|=uint64_t(e->instance->depth_layer)<shader->spatial.cull_mode==RasterizerStorageGLES3::Shader::Spatial::CULL_MODE_FRONT) { - mirror=!mirror; - } + if (!has_blend_alpha && has_alpha && m->shader->spatial.depth_draw_mode==RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) { - if (mirror) { - e->sort_key|=RenderList::SORT_KEY_MIRROR_FLAG; - } + //if nothing exists, add this element as opaque too + RenderList::Element *oe = render_list.add_element(); - //e->light_type=0xFF; // no lights! + if (!oe) + return; - if (!shadow && !has_blend_alpha && has_alpha && m->shader->spatial.depth_draw_mode==RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) { + copymem(oe,e,sizeof(RenderList::Element)); + oe->additive_ptr=&oe->additive; + } + } - //if nothing exists, add this element as opaque too - RenderList::Element *oe = render_list.add_element(); + //if (e->geometry->type==RasterizerStorageGLES3::Geometry::GEOMETRY_MULTISURFACE) + // e->sort_flags|=RenderList::SORT_FLAG_INSTANCING; - if (!oe) - return; - copymem(oe,e,sizeof(RenderList::Element)); - oe->additive_ptr=&oe->additive; + if (mirror) { + e->sort_key|=RenderList::SORT_KEY_MIRROR_FLAG; } + //e->light_type=0xFF; // no lights! + @@ -1246,7 +1302,12 @@ void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_g ec->sort_key&=~RenderList::SORT_KEY_LIGHT_MASK; ec->sort_key|=uint64_t(directional_light_instances[i]->light_index) << RenderList::SORT_KEY_LIGHT_INDEX_SHIFT; - ec->sort_key|=uint64_t(VS::LIGHT_DIRECTIONAL) << RenderList::SORT_KEY_LIGHT_TYPE_SHIFT; + ec->sort_key|=uint64_t(VS::LIGHT_DIRECTIONAL) << RenderList::SORT_KEY_LIGHT_TYPE_SHIFT; //this is zero byt whathever + + if (directional_light_instances[i]->light_ptr->shadow) { + //add proper flags for directional shadow mode + ec->sort_key|=uint64_t(directional_light_instances[i]->light_ptr->directional_shadow_mode+1) << (RenderList::SORT_KEY_LIGHT_TYPE_SHIFT+2); + } lit=true; } @@ -1302,7 +1363,7 @@ void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_g } -void RasterizerSceneGLES3::_draw_skybox(RID p_skybox,CameraMatrix& p_projection,const Transform& p_transform,bool p_vflip,float p_scale) { +void RasterizerSceneGLES3::_draw_skybox(RID p_skybox,const CameraMatrix& p_projection,const Transform& p_transform,bool p_vflip,float p_scale) { RasterizerStorageGLES3::Texture *tex = storage->texture_owner.getornull(p_skybox); @@ -1382,7 +1443,7 @@ void RasterizerSceneGLES3::_draw_skybox(RID p_skybox,CameraMatrix& p_projection, } -void RasterizerSceneGLES3::_setup_environment(Environment *env,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) { //store camera into ubo @@ -1444,6 +1505,20 @@ void RasterizerSceneGLES3::_setup_environment(Environment *env,CameraMatrix& p_c } + { + //directional shadow + + state.ubo_data.shadow_directional_pixel_size[0]=1.0/directional_shadow.size; + state.ubo_data.shadow_directional_pixel_size[1]=1.0/directional_shadow.size; + + glActiveTexture(GL_TEXTURE0+storage->config.max_texture_image_units-4); + glBindTexture(GL_TEXTURE_2D,directional_shadow.depth); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LESS); + } + + + glBindBuffer(GL_UNIFORM_BUFFER, state.scene_ubo); glBufferSubData(GL_UNIFORM_BUFFER, 0,sizeof(State::SceneDataUBO), &state.ubo_data); glBindBuffer(GL_UNIFORM_BUFFER, 0); @@ -1459,13 +1534,14 @@ void RasterizerSceneGLES3::_setup_environment(Environment *env,CameraMatrix& p_c } -void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result,int p_light_cull_count,const Transform& p_camera_inverse_transform,const CameraMatrix& p_camera_projection) { +void RasterizerSceneGLES3::_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) { + + + ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas); directional_light_instance_count=0; light_instance_count=0; - Vector lpercent; - for(int i=0;i=RenderList::MAX_LIGHTS ); @@ -1502,23 +1578,90 @@ void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result,int p_light_cu li->light_ubo_data.light_params[2]=0; li->light_ubo_data.light_params[3]=0; + if (li->light_ptr->shadow) { + int shadow_count=0; + switch(li->light_ptr->directional_shadow_mode) { + case VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: { + shadow_count=1; + } break; + case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: { + shadow_count=2; + } break; + case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: { + shadow_count=4; + } break; -#if 0 - if (li->light_ptr->shadow_enabled) { - CameraMatrix bias; - bias.set_light_bias(); + } + + for(int j=0;jdirectional_rect.pos.x; + uint32_t y=li->directional_rect.pos.y; + uint32_t width=li->directional_rect.size.x; + uint32_t height=li->directional_rect.size.y; + + + + if (li->light_ptr->directional_shadow_mode==VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) { + + + width/=2; + height/=2; + + if (j==0) { + + } else if (j==1) { + x+=width; + } else if (j==2) { + y+=height; + } else if (j==3) { + x+=width; + y+=height; + + } + + + + } else if (li->light_ptr->directional_shadow_mode==VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) { - int passes=light_instance_get_shadow_passes(p_light_instance); + height/=2; + + if (j==0) { + + } else { + y+=height; + } + + } + + li->light_ubo_data.shadow_split_offsets[j]=1.0/li->shadow_transform[j].split; + + Transform modelview = (p_camera_inverse_transform * li->shadow_transform[j].transform).inverse(); + + CameraMatrix bias; + bias.set_light_bias(); + CameraMatrix rectm; + Rect2 atlas_rect = Rect2(float(x)/directional_shadow.size,float(y)/directional_shadow.size,float(width)/directional_shadow.size,float(height)/directional_shadow.size); + rectm.set_light_atlas_rect(atlas_rect); + +// print_line("atlas rect: "+atlas_rect); + + CameraMatrix shadow_mtx = rectm * bias * li->shadow_transform[j].camera * modelview; + + store_camera(shadow_mtx,&li->light_ubo_data.shadow_matrix1[16*j]); + + li->light_ubo_data.light_clamp[0]=atlas_rect.pos.x; + li->light_ubo_data.light_clamp[1]=atlas_rect.pos.y; + li->light_ubo_data.light_clamp[2]=atlas_rect.size.x; + li->light_ubo_data.light_clamp[3]=atlas_rect.size.y; - for(int i=0;icustom_transform[i]).inverse(); - li->shadow_projection[i] = bias * li->custom_projection[i] * modelview; } - lights_use_shadow=true; + } -#endif + } break; case VS::LIGHT_OMNI: { @@ -1542,29 +1685,57 @@ void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result,int p_light_cu li->light_ubo_data.light_direction_attenuation[3]=li->light_ptr->param[VS::LIGHT_PARAM_ATTENUATION]; li->light_ubo_data.light_params[0]=0; - li->light_ubo_data.light_params[1]=li->light_ptr->param[VS::LIGHT_PARAM_SPECULAR]; - li->light_ubo_data.light_params[2]=0; + li->light_ubo_data.light_params[1]=0; + li->light_ubo_data.light_params[2]=li->light_ptr->param[VS::LIGHT_PARAM_SPECULAR]; li->light_ubo_data.light_params[3]=0; -#if 0 - Transform ai = p_camera_inverse_transform.affine_inverse(); - float zn = p_camera_projection.get_z_near(); - Plane p (ai.origin + ai.basis.get_axis(2) * -zn, -ai.basis.get_axis(2) ); + if (li->light_ptr->shadow && shadow_atlas && shadow_atlas->shadow_owners.has(li->self)) { + // fill in the shadow information - Vector3 point1 = li->transform.origin; - Vector3 point2 = li->transform.origin+p_camera_inverse_transform.affine_inverse().basis.get_axis(1).normalized()*li->light_ptr->param[VS::LIGHT_PARAM_RANGE]; + uint32_t key = shadow_atlas->shadow_owners[li->self]; - p.intersects_segment(ai.origin,point1,&point1); - p.intersects_segment(ai.origin,point2,&point2); - float r = point1.distance_to(point2); + uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT)&0x3; + uint32_t shadow = key & ShadowAtlas::SHADOW_INDEX_MASK; + + ERR_CONTINUE(shadow>=shadow_atlas->quadrants[quadrant].shadows.size()); + + uint32_t atlas_size = shadow_atlas->size; + uint32_t quadrant_size = atlas_size>>1; + + uint32_t x=(quadrant&1)*quadrant_size; + uint32_t y=(quadrant>>1)*quadrant_size; + + uint32_t shadow_size = (quadrant_size / shadow_atlas->quadrants[quadrant].subdivision); + x+=(shadow % shadow_atlas->quadrants[quadrant].subdivision) * shadow_size; + y+=(shadow / shadow_atlas->quadrants[quadrant].subdivision) * shadow_size; + + uint32_t width=shadow_size; + uint32_t height=shadow_size; + + + if (li->light_ptr->omni_shadow_detail==VS::LIGHT_OMNI_SHADOW_DETAIL_HORIZONTAL) { + + height/=2; + } else { + width/=2; + + } + + Transform proj = (p_camera_inverse_transform * li->transform).inverse(); + + store_transform(proj,li->light_ubo_data.shadow_matrix1); + + li->light_ubo_data.light_params[3]=1.0; //means it has shadow + li->light_ubo_data.light_clamp[0]=float(x)/atlas_size; + li->light_ubo_data.light_clamp[1]=float(y)/atlas_size; + li->light_ubo_data.light_clamp[2]=float(width)/atlas_size; + li->light_ubo_data.light_clamp[3]=float(height)/atlas_size; + + } - float vp_w,vp_h; - p_camera_projection.get_viewport_size(vp_w,vp_h); - lpercent.push_back(r*2/((vp_h+vp_w)*0.5)); -#endif #if 0 if (li->light_ptr->shadow_enabled) { @@ -1596,10 +1767,54 @@ void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result,int p_light_cu li->light_ubo_data.light_direction_attenuation[3]=li->light_ptr->param[VS::LIGHT_PARAM_ATTENUATION]; li->light_ubo_data.light_params[0]=li->light_ptr->param[VS::LIGHT_PARAM_SPOT_ATTENUATION]; - li->light_ubo_data.light_params[1]=li->light_ptr->param[VS::LIGHT_PARAM_SPECULAR]; - li->light_ubo_data.light_params[2]=0; + li->light_ubo_data.light_params[1]=Math::cos(Math::deg2rad(li->light_ptr->param[VS::LIGHT_PARAM_SPOT_ANGLE])); + li->light_ubo_data.light_params[2]=li->light_ptr->param[VS::LIGHT_PARAM_SPECULAR]; li->light_ubo_data.light_params[3]=0; + if (li->light_ptr->shadow && shadow_atlas && shadow_atlas->shadow_owners.has(li->self)) { + // fill in the shadow information + + uint32_t key = shadow_atlas->shadow_owners[li->self]; + + uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT)&0x3; + uint32_t shadow = key & ShadowAtlas::SHADOW_INDEX_MASK; + + ERR_CONTINUE(shadow>=shadow_atlas->quadrants[quadrant].shadows.size()); + + uint32_t atlas_size = shadow_atlas->size; + uint32_t quadrant_size = atlas_size>>1; + + uint32_t x=(quadrant&1)*quadrant_size; + uint32_t y=(quadrant>>1)*quadrant_size; + + uint32_t shadow_size = (quadrant_size / shadow_atlas->quadrants[quadrant].subdivision); + x+=(shadow % shadow_atlas->quadrants[quadrant].subdivision) * shadow_size; + y+=(shadow / shadow_atlas->quadrants[quadrant].subdivision) * shadow_size; + + uint32_t width=shadow_size; + uint32_t height=shadow_size; + + Rect2 rect(float(x)/atlas_size,float(y)/atlas_size,float(width)/atlas_size,float(height)/atlas_size); + + li->light_ubo_data.light_params[3]=1.0; //means it has shadow + li->light_ubo_data.light_clamp[0]=rect.pos.x; + li->light_ubo_data.light_clamp[1]=rect.pos.y; + li->light_ubo_data.light_clamp[2]=rect.size.x; + li->light_ubo_data.light_clamp[3]=rect.size.y; + + Transform modelview = (p_camera_inverse_transform * li->transform).inverse(); + + CameraMatrix bias; + bias.set_light_bias(); + CameraMatrix rectm; + rectm.set_light_atlas_rect(rect); + + CameraMatrix shadow_mtx = rectm * bias * li->shadow_transform[0].camera * modelview; + + store_camera(shadow_mtx,li->light_ubo_data.shadow_matrix1); + + + } #if 0 if (li->light_ptr->shadow_enabled) { CameraMatrix bias; @@ -1679,24 +1894,39 @@ void RasterizerSceneGLES3::_copy_to_front_buffer(Environment *env) { } -void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,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_directional_lights,int p_directional_light_count,RID p_environment){ +void RasterizerSceneGLES3::_copy_texture_to_front_buffer(GLuint p_texture) { - //first of all, make a new render pass - render_pass++; + //copy to front buffer + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->front.fbo); - //fill up ubo + glDepthMask(GL_FALSE); + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + glDisable(GL_BLEND); + glDepthFunc(GL_LEQUAL); + glColorMask(1,1,1,1); - Environment *env = environment_owner.getornull(p_environment); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,p_texture); - _setup_environment(env,p_cam_projection,p_cam_transform); + glViewport(0,0,storage->frame.current_rt->width*0.5,storage->frame.current_rt->height*0.5); - _setup_lights(p_light_cull_result,p_light_cull_count,p_cam_transform.affine_inverse(),p_cam_projection); + storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA,true); + storage->shaders.copy.bind(); - render_list.clear(); + _copy_screen(); - current_material_index=0; + //turn off everything used + storage->shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB,false); + storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA,false); - bool use_mrt=false; + +} + +void RasterizerSceneGLES3::_fill_render_list(InstanceBase** p_cull_result,int p_cull_count,bool p_shadow){ + + current_geometry_index=0; + current_material_index=0; //fill list @@ -1716,7 +1946,7 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,CameraM int mat_idx = inst->materials[i].is_valid() ? i : -1; RasterizerStorageGLES3::Surface *s = mesh->surfaces[i]; - _add_geometry(s,inst,NULL,mat_idx); + _add_geometry(s,inst,NULL,mat_idx,p_shadow); } //mesh->last_pass=frame; @@ -1731,7 +1961,39 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,CameraM } } +} + + +void RasterizerSceneGLES3::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_environment,RID p_shadow_atlas){ + + //first of all, make a new render pass + render_pass++; + + //fill up ubo + + Environment *env = environment_owner.getornull(p_environment); + ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas); + + if (shadow_atlas && shadow_atlas->size) { + glActiveTexture(GL_TEXTURE0+storage->config.max_texture_image_units-3); + glBindTexture(GL_TEXTURE_2D,shadow_atlas->depth); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LESS); + state.ubo_data.shadow_atlas_pixel_size[0]=1.0/shadow_atlas->size; + state.ubo_data.shadow_atlas_pixel_size[1]=1.0/shadow_atlas->size; + } + + _setup_environment(env,p_cam_projection,p_cam_transform); + + _setup_lights(p_light_cull_result,p_light_cull_count,p_cam_transform.affine_inverse(),p_cam_projection,p_shadow_atlas); + + render_list.clear(); + + bool use_mrt=false; + + + _fill_render_list(p_cull_result,p_cull_count,false); // @@ -1742,6 +2004,8 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,CameraM RasterizerStorageGLES3::Texture* env_radiance_tex=NULL; + glViewport(0,0,storage->frame.current_rt->width,storage->frame.current_rt->height); + if (use_mrt) { glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.fbo); @@ -1811,7 +2075,7 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,CameraM glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } - _render_list(render_list.elements,render_list.element_count,p_cam_transform,p_cam_projection,env_radiance_tex,false,false); + _render_list(render_list.elements,render_list.element_count,p_cam_transform,p_cam_projection,env_radiance_tex,false,false,false); state.scene_shader.set_conditional(SceneShaderGLES3::USE_MULTIPLE_RENDER_TARGETS,false); @@ -1843,11 +2107,34 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,CameraM render_list.sort_by_depth(true); - _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,env_radiance_tex,false,true); + _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,env_radiance_tex,false,true,false); _copy_to_front_buffer(env); +/* if (shadow_atlas) { + + //_copy_texture_to_front_buffer(shadow_atlas->depth); + storage->canvas->canvas_begin(); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,shadow_atlas->depth); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); + 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 (directional_shadow.fbo) { + + //_copy_texture_to_front_buffer(shadow_atlas->depth); + storage->canvas->canvas_begin(); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,directional_shadow.depth); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); + 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 0 if (use_fb) { @@ -1994,6 +2281,294 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,CameraM #endif } +void RasterizerSceneGLES3::render_shadow(RID p_light,RID p_shadow_atlas,int p_pass,InstanceBase** p_cull_result,int p_cull_count) { + + render_pass++; + + LightInstance *light_instance = light_instance_owner.getornull(p_light); + ERR_FAIL_COND(!light_instance); + RasterizerStorageGLES3::Light *light = storage->light_owner.getornull(light_instance->light); + ERR_FAIL_COND(!light); + + uint32_t x,y,width,height,vp_height; + + + float dp_direction=0.0; + float zfar=0; + bool flip_facing=false; + int custom_vp_size=0; + GLuint fbo; + int current_cubemap=-1; + float bias=0; + float normal_bias=0; + + CameraMatrix light_projection; + Transform light_transform; + + + if (light->type==VS::LIGHT_DIRECTIONAL) { + //set pssm stuff + if (light_instance->last_scene_shadow_pass!=scene_pass) { + //assign rect if unassigned + light_instance->light_directional_index = directional_shadow.current_light; + light_instance->last_scene_shadow_pass=scene_pass; + directional_shadow.current_light++; + + if (directional_shadow.light_count==1) { + light_instance->directional_rect=Rect2(0,0,directional_shadow.size,directional_shadow.size); + } else if (directional_shadow.light_count==2) { + light_instance->directional_rect=Rect2(0,0,directional_shadow.size,directional_shadow.size/2); + if (light_instance->light_directional_index==1) { + light_instance->directional_rect.pos.x+=light_instance->directional_rect.size.x; + } + } else { //3 and 4 + light_instance->directional_rect=Rect2(0,0,directional_shadow.size/2,directional_shadow.size/2); + if (light_instance->light_directional_index&1) { + light_instance->directional_rect.pos.x+=light_instance->directional_rect.size.x; + } + if (light_instance->light_directional_index/2) { + light_instance->directional_rect.pos.y+=light_instance->directional_rect.size.y; + } + } + } + + light_projection=light_instance->shadow_transform[p_pass].camera; + light_transform=light_instance->shadow_transform[p_pass].transform; + + x=light_instance->directional_rect.pos.x; + y=light_instance->directional_rect.pos.y; + width=light_instance->directional_rect.size.x; + height=light_instance->directional_rect.size.y; + + + + if (light->directional_shadow_mode==VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) { + + + width/=2; + height/=2; + + if (p_pass==0) { + + } else if (p_pass==1) { + x+=width; + } else if (p_pass==2) { + y+=height; + } else if (p_pass==3) { + x+=width; + y+=height; + + } + + + + } else if (light->directional_shadow_mode==VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) { + + height/=2; + + if (p_pass==0) { + + } else { + y+=height; + } + + } + + zfar=light->param[VS::LIGHT_PARAM_RANGE]; + bias=light->param[VS::LIGHT_PARAM_SHADOW_BIAS]; + normal_bias=light->param[VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS]; + fbo=directional_shadow.fbo; + vp_height=directional_shadow.size; + + } else { + //set from shadow atlas + + ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas); + ERR_FAIL_COND(!shadow_atlas); + 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]; + + uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT)&0x3; + uint32_t shadow = key & ShadowAtlas::SHADOW_INDEX_MASK; + + ERR_FAIL_INDEX(shadow,shadow_atlas->quadrants[quadrant].shadows.size()); + + uint32_t quadrant_size = shadow_atlas->size>>1; + + x=(quadrant&1)*quadrant_size; + y=(quadrant>>1)*quadrant_size; + + uint32_t shadow_size = (quadrant_size / shadow_atlas->quadrants[quadrant].subdivision); + x+=(shadow % shadow_atlas->quadrants[quadrant].subdivision) * shadow_size; + y+=(shadow / shadow_atlas->quadrants[quadrant].subdivision) * shadow_size; + + width=shadow_size; + height=shadow_size; + + if (light->type==VS::LIGHT_OMNI) { + + + if (light->omni_shadow_mode==VS::LIGHT_OMNI_SHADOW_CUBE) { + + int cubemap_index=shadow_cubemaps.size()-1; + + for(int i=shadow_cubemaps.size()-1;i>=0;i--) { + //find appropriate cubemap to render to + if (shadow_cubemaps[i].size>shadow_size*2) + break; + + cubemap_index=i; + } + + fbo=shadow_cubemaps[cubemap_index].fbo_id[p_pass]; + light_projection=light_instance->shadow_transform[0].camera; + light_transform=light_instance->shadow_transform[0].transform; + custom_vp_size=shadow_cubemaps[cubemap_index].size; + zfar=light->param[VS::LIGHT_PARAM_RANGE]; + + current_cubemap=cubemap_index; + + + } else { + + light_projection=light_instance->shadow_transform[0].camera; + light_transform=light_instance->shadow_transform[0].transform; + + if (light->omni_shadow_detail==VS::LIGHT_OMNI_SHADOW_DETAIL_HORIZONTAL) { + + height/=2; + y+=p_pass*height; + } else { + width/=2; + x+=p_pass*width; + + } + + dp_direction = p_pass==0?1.0:-1.0; + flip_facing = (p_pass == 1); + zfar=light->param[VS::LIGHT_PARAM_RANGE]; + bias=light->param[VS::LIGHT_PARAM_SHADOW_BIAS]; + + state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_SHADOW_DUAL_PARABOLOID,true); + } + + } else if (light->type==VS::LIGHT_SPOT) { + + light_projection=light_instance->shadow_transform[0].camera; + light_transform=light_instance->shadow_transform[0].transform; + + dp_direction = 1.0; + flip_facing = false; + zfar=light->param[VS::LIGHT_PARAM_RANGE]; + bias=light->param[VS::LIGHT_PARAM_SHADOW_BIAS]; + normal_bias=light->param[VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS]; + } + + } + + //todo hacer que se redibuje cuando corresponde + + + render_list.clear(); + _fill_render_list(p_cull_result,p_cull_count,true); + + render_list.sort_by_depth(false); //shadow is front to back for performance + + glDepthMask(true); + glColorMask(0,0,0,0); + glDisable(GL_BLEND); + glDisable(GL_DITHER); + glEnable(GL_DEPTH_TEST); + + glBindFramebuffer(GL_FRAMEBUFFER,fbo); + + if (custom_vp_size) { + glViewport(0,0,custom_vp_size,custom_vp_size); + glScissor(0,0,custom_vp_size,custom_vp_size); + + } else { + glViewport(x,y,width,height); + glScissor(x,y,width,height); + } + + //glViewport(x,vp_height-(height+y),width,height); + //glScissor(x,vp_height-(height+y),width,height); + glEnable(GL_SCISSOR_TEST); + glClearDepth(1.0); + glClear(GL_DEPTH_BUFFER_BIT); + glDisable(GL_SCISSOR_TEST); + + state.ubo_data.shadow_z_offset=bias; + state.ubo_data.shadow_slope_scale=normal_bias; + state.ubo_data.shadow_dual_paraboloid_render_side=dp_direction; + state.ubo_data.shadow_dual_paraboloid_render_zfar=zfar; + + _setup_environment(NULL,light_projection,light_transform); + + state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_SHADOW,true); + + _render_list(render_list.elements,render_list.element_count,light_transform,light_projection,NULL,!flip_facing,false,true); + + state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_SHADOW,false); + state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_SHADOW_DUAL_PARABOLOID,false); + + + if (light->type==VS::LIGHT_OMNI && light->omni_shadow_mode==VS::LIGHT_OMNI_SHADOW_CUBE && p_pass==5) { + //convert the chosen cubemap to dual paraboloid! + + ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas); + + glBindFramebuffer(GL_FRAMEBUFFER,shadow_atlas->fbo); + state.cube_to_dp_shader.bind(); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_CUBE_MAP,shadow_cubemaps[current_cubemap].cubemap); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_MODE, GL_NONE); + glDisable(GL_CULL_FACE); + + for(int i=0;i<2;i++) { + + state.cube_to_dp_shader.set_uniform(CubeToDpShaderGLES3::Z_FLIP,i==1); + state.cube_to_dp_shader.set_uniform(CubeToDpShaderGLES3::Z_NEAR,light_projection.get_z_near()); + state.cube_to_dp_shader.set_uniform(CubeToDpShaderGLES3::Z_FAR,light_projection.get_z_far()); + state.cube_to_dp_shader.set_uniform(CubeToDpShaderGLES3::BIAS,light->param[VS::LIGHT_PARAM_SHADOW_BIAS]); + + uint32_t local_width=width,local_height=height; + uint32_t local_x=x,local_y=y; + if (light->omni_shadow_detail==VS::LIGHT_OMNI_SHADOW_DETAIL_HORIZONTAL) { + + local_height/=2; + local_y+=i*local_height; + } else { + local_width/=2; + local_x+=i*local_width; + } + + glViewport(local_x,local_y,local_width,local_height); + glScissor(local_x,local_y,local_width,local_height); + glEnable(GL_SCISSOR_TEST); + glClearDepth(1.0); + glClear(GL_DEPTH_BUFFER_BIT); + glDisable(GL_SCISSOR_TEST); + //glDisable(GL_DEPTH_TEST); + glDisable(GL_BLEND); + + _copy_screen(); + + } + + } + + glColorMask(1,1,1,1); + + +} + void RasterizerSceneGLES3::set_scene_pass(uint64_t p_pass) { scene_pass=p_pass; } @@ -2169,6 +2744,12 @@ void RasterizerSceneGLES3::initialize() { default_material = storage->material_create(); storage->material_set_shader(default_material,default_shader); + default_shader_twosided = storage->shader_create(VS::SHADER_SPATIAL); + default_material_twosided = storage->material_create(); + storage->shader_set_code(default_shader_twosided,"render_mode cull_disabled;\n"); + storage->material_set_shader(default_material_twosided,default_shader_twosided); + + glGenBuffers(1, &state.scene_ubo); glBindBuffer(GL_UNIFORM_BUFFER, state.scene_ubo); glBufferData(GL_UNIFORM_BUFFER, sizeof(State::SceneDataUBO), &state.scene_ubo, GL_DYNAMIC_DRAW); @@ -2208,9 +2789,77 @@ void RasterizerSceneGLES3::initialize() { glBindBuffer(GL_ARRAY_BUFFER,0); //unbind } render_list.init(); + state.cube_to_dp_shader.init(); _generate_brdf(); shadow_atlas_realloc_tolerance_msec=500; + + + + + + int max_shadow_cubemap_sampler_size=512; + + int cube_size = max_shadow_cubemap_sampler_size; + + glActiveTexture(GL_TEXTURE0); + + while(cube_size>=32) { + + ShadowCubeMap cube; + cube.size=cube_size; + + glGenTextures(1,&cube.cubemap); + glBindTexture(GL_TEXTURE_CUBE_MAP,cube.cubemap); + //gen cubemap first + 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); + } + + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + // Remove artifact on the edges of the shadowmap + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + + //gen renderbuffers second, because it needs a complete cubemap + for(int i=0;i<6;i++) { + + glGenFramebuffers(1, &cube.fbo_id[i]); + glBindFramebuffer(GL_FRAMEBUFFER, cube.fbo_id[i]); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,_cube_side_enum[i], cube.cubemap, 0); + + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + ERR_CONTINUE(status!=GL_FRAMEBUFFER_COMPLETE); + } + + shadow_cubemaps.push_back(cube); + + cube_size>>=1; + } + + { + //directional light shadow + directional_shadow.light_count=0; + directional_shadow.size=nearest_power_of_2(GLOBAL_DEF("renderer/directional_shadow_size",2048)); + glGenFramebuffers(1,&directional_shadow.fbo); + glBindFramebuffer(GL_FRAMEBUFFER,directional_shadow.fbo); + 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); + 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_WRAP_R, GL_CLAMP_TO_EDGE); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,GL_TEXTURE_2D, directional_shadow.depth, 0); + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (status!=GL_FRAMEBUFFER_COMPLETE) { + ERR_PRINT("Directional shadow framebuffer status invalid"); + } + } } void RasterizerSceneGLES3::finalize(){ diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 9df6315e45..d7beebbcf6 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -3,6 +3,7 @@ #include "rasterizer_storage_gles3.h" #include "drivers/gles3/shaders/scene.glsl.h" +#include "drivers/gles3/shaders/cube_to_dp.glsl.h" class RasterizerSceneGLES3 : public RasterizerScene { public: @@ -16,10 +17,13 @@ public: uint32_t current_geometry_index; RID default_material; + RID default_material_twosided; RID default_shader; + RID default_shader_twosided; RasterizerStorageGLES3 *storage; + struct State { @@ -29,6 +33,7 @@ public: int current_depth_draw; SceneShaderGLES3 scene_shader; + CubeToDpShaderGLES3 cube_to_dp_shader; struct SceneDataUBO { @@ -41,6 +46,12 @@ public: float bg_color[4]; float ambient_energy; float bg_energy; + float shadow_z_offset; + float shadow_slope_scale; + float shadow_dual_paraboloid_render_zfar; + float shadow_dual_paraboloid_render_side; + float shadow_atlas_pixel_size[2]; + float shadow_directional_pixel_size[2]; } ubo_data; @@ -62,7 +73,7 @@ public: GLuint skybox_verts; GLuint skybox_array; - + bool cull_front; } state; @@ -71,7 +82,6 @@ public: struct ShadowAtlas : public RID_Data { enum { - SHADOW_INDEX_DIRTY_BIT=(1<<31), QUADRANT_SHIFT=27, SHADOW_INDEX_MASK=(1< shadow_owners; }; + struct ShadowCubeMap { + + GLuint fbo_id[6]; + GLuint cubemap; + int size; + }; + + Vector shadow_cubemaps; + RID_Owner shadow_atlas_owner; RID shadow_atlas_create(); void shadow_atlas_set_size(RID p_atlas,int p_size); void shadow_atlas_set_quadrant_subdivision(RID p_atlas,int p_quadrant,int p_subdivision); bool _shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, int &r_quadrant, int &r_shadow); - uint32_t shadow_atlas_update_light(RID p_atlas,RID p_light_intance,float p_coverage,uint64_t p_light_version); + bool shadow_atlas_update_light(RID p_atlas,RID p_light_intance,float p_coverage,uint64_t p_light_version); + + + struct DirectionalShadow { + GLuint fbo; + GLuint depth; + int light_count; + int size; + int current_light; + } directional_shadow; + + virtual int get_directional_light_shadow_size(RID p_light_intance); + virtual void set_directional_shadow_count(int p_count); + /* ENVIRONMENT API */ @@ -174,12 +206,12 @@ public: struct LightInstance : public RID_Data { - struct SplitInfo { + struct ShadowTransform { CameraMatrix camera; Transform transform; - float near; float far; + float split; }; struct LightDataUBO { @@ -188,6 +220,7 @@ public: float light_direction_attenuation[4]; float light_color_energy[4]; float light_params[4]; //cone attenuation, specular, shadow darkening, + float light_clamp[4]; //cone attenuation, specular, shadow darkening, float shadow_split_offsets[4]; float shadow_matrix1[16]; float shadow_matrix2[16]; @@ -197,13 +230,11 @@ public: } light_ubo_data; - SplitInfo split_info[4]; + ShadowTransform shadow_transform[4]; + RID self; RID light; RasterizerStorageGLES3::Light *light_ptr; - - CameraMatrix shadow_matrix[4]; - Transform transform; Vector3 light_vector; @@ -214,12 +245,17 @@ public: uint64_t shadow_pass; uint64_t last_scene_pass; + uint64_t last_scene_shadow_pass; uint64_t last_pass; uint16_t light_index; + uint16_t light_directional_index; + + uint32_t current_shadow_atlas_key; Vector2 dp; - CameraMatrix shadow_projection[4]; + Rect2 directional_rect; + Set shadow_atlases; //shadow atlases where this light is registered @@ -231,6 +267,7 @@ public: virtual RID light_instance_create(RID p_light); virtual void light_instance_set_transform(RID p_light_instance,const Transform& p_transform); + virtual void light_instance_set_shadow_transform(RID p_light_instance,const CameraMatrix& p_projection,const Transform& p_transform,float p_far,float p_split,int p_pass); virtual void light_instance_mark_visible(RID p_light_instance); /* RENDER LIST */ @@ -371,26 +408,31 @@ public: RenderList render_list; + _FORCE_INLINE_ void _set_cull(bool p_front,bool p_reverse_cull); + _FORCE_INLINE_ bool _setup_material(RasterizerStorageGLES3::Material* p_material,bool p_alpha_pass); _FORCE_INLINE_ void _setup_transform(InstanceBase *p_instance,const Transform& p_view_transform,const CameraMatrix& p_projection); _FORCE_INLINE_ void _setup_geometry(RenderList::Element *e); _FORCE_INLINE_ void _render_geometry(RenderList::Element *e); _FORCE_INLINE_ void _setup_light(LightInstance *p_light); - void _render_list(RenderList::Element **p_elements, int p_element_count, const Transform& p_view_transform, const CameraMatrix& p_projection, RasterizerStorageGLES3::Texture *p_base_env, bool p_reverse_cull, bool p_alpha_pass); + void _render_list(RenderList::Element **p_elements, int p_element_count, const Transform& p_view_transform, const CameraMatrix& p_projection, RasterizerStorageGLES3::Texture *p_base_env, bool p_reverse_cull, bool p_alpha_pass, bool p_shadow); - _FORCE_INLINE_ void _add_geometry( RasterizerStorageGLES3::Geometry* p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner,int p_material); + _FORCE_INLINE_ void _add_geometry( RasterizerStorageGLES3::Geometry* p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner,int p_material,bool p_shadow); - void _draw_skybox(RID p_skybox, CameraMatrix& p_projection, const Transform& p_transform, bool p_vflip, float p_scale); + void _draw_skybox(RID p_skybox, const CameraMatrix& p_projection, const Transform& p_transform, bool p_vflip, float p_scale); - void _setup_environment(Environment *env,CameraMatrix& p_cam_projection, const Transform& p_cam_transform); - void _setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform,const CameraMatrix& p_camera_projection); + void _setup_environment(Environment *env, const CameraMatrix &p_cam_projection, const Transform& p_cam_transform); + 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 _copy_screen(); void _copy_to_front_buffer(Environment *env); + void _copy_texture_to_front_buffer(GLuint p_texture); //used for debug - virtual void render_scene(const Transform& p_cam_transform,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_directional_lights,int p_directional_light_count,RID p_environment); + void _fill_render_list(InstanceBase** p_cull_result,int p_cull_count,bool p_shadow); + 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_environment,RID p_shadow_atlas); + 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); void _generate_brdf(); diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 4b2c607297..b988781e14 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -1290,12 +1290,13 @@ void RasterizerStorageGLES3::_update_shader(Shader* p_shader) const { shaders.actions_scene.render_mode_values["cull_front"]=Pair(&p_shader->spatial.cull_mode,Shader::Spatial::CULL_MODE_FRONT); shaders.actions_scene.render_mode_values["cull_back"]=Pair(&p_shader->spatial.cull_mode,Shader::Spatial::CULL_MODE_BACK); - shaders.actions_scene.render_mode_values["cull_disable"]=Pair(&p_shader->spatial.cull_mode,Shader::Spatial::CULL_MODE_DISABLED); + shaders.actions_scene.render_mode_values["cull_disabled"]=Pair(&p_shader->spatial.cull_mode,Shader::Spatial::CULL_MODE_DISABLED); shaders.actions_scene.render_mode_flags["unshaded"]=&p_shader->spatial.unshaded; shaders.actions_scene.render_mode_flags["ontop"]=&p_shader->spatial.ontop; shaders.actions_scene.usage_flag_pointers["ALPHA"]=&p_shader->spatial.uses_alpha; + shaders.actions_scene.usage_flag_pointers["VERTEX"]=&p_shader->spatial.uses_vertex; actions=&shaders.actions_scene; actions->uniforms=&p_shader->uniforms; @@ -1318,6 +1319,9 @@ void RasterizerStorageGLES3::_update_shader(Shader* p_shader) const { p_shader->texture_count=gen_code.texture_uniforms.size(); p_shader->texture_hints=gen_code.texture_hints; + p_shader->uses_vertex_time=gen_code.uses_vertex_time; + p_shader->uses_fragment_time=gen_code.uses_fragment_time; + //all materials using this shader will have to be invalidated, unfortunately for (SelfList* E = p_shader->materials.first();E;E=E->next() ) { @@ -1535,6 +1539,57 @@ void RasterizerStorageGLES3::material_set_line_width(RID p_material, float p_wid } +bool RasterizerStorageGLES3::material_is_animated(RID p_material) { + + Material *material = material_owner.get( p_material ); + ERR_FAIL_COND_V(!material,false); + if (material->dirty_list.in_list()) { + _update_material(material); + } + + return material->is_animated_cache; + +} +bool RasterizerStorageGLES3::material_casts_shadows(RID p_material) { + + Material *material = material_owner.get( p_material ); + ERR_FAIL_COND_V(!material,false); + if (material->dirty_list.in_list()) { + _update_material(material); + } + + return material->can_cast_shadow_cache; +} + +void RasterizerStorageGLES3::material_add_instance_owner(RID p_material, RasterizerScene::InstanceBase *p_instance) { + + Material *material = material_owner.get( p_material ); + ERR_FAIL_COND(!material); + + Map::Element *E=material->instance_owners.find(p_instance); + if (E) { + E->get()++; + } else { + material->instance_owners[p_instance]=1; + } +} + +void RasterizerStorageGLES3::material_remove_instance_owner(RID p_material, RasterizerScene::InstanceBase *p_instance) { + + Material *material = material_owner.get( p_material ); + ERR_FAIL_COND(!material); + + Map::Element *E=material->instance_owners.find(p_instance); + ERR_FAIL_COND(!E); + E->get()--; + + if (E->get()==0) { + material->instance_owners.erase(E); + } +} + + + _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataType type, const Variant& value, uint8_t *data,bool p_linear_color) { switch(type) { case ShaderLanguage::TYPE_BOOL: { @@ -2011,6 +2066,48 @@ void RasterizerStorageGLES3::_update_material(Material* material) { if (material->dirty_list.in_list()) _material_dirty_list.remove( &material->dirty_list ); + + if (material->shader && material->shader->dirty_list.in_list()) { + _update_shader(material->shader); + } + //update caches + + { + bool can_cast_shadow = false; + bool is_animated = false; + + if (material->shader && material->shader->mode==VS::SHADER_SPATIAL) { + if (!material->shader->spatial.uses_alpha && material->shader->spatial.blend_mode==Shader::Spatial::BLEND_MODE_MIX) { + can_cast_shadow=true; + } + + if (material->shader->spatial.uses_discard && material->shader->uses_fragment_time) { + is_animated=true; + } + + if (material->shader->spatial.uses_vertex && material->shader->uses_vertex_time) { + is_animated=true; + } + + } + + if (can_cast_shadow!=material->can_cast_shadow_cache || is_animated!=material->is_animated_cache) { + material->can_cast_shadow_cache=can_cast_shadow; + material->is_animated_cache=is_animated; + + for(Map::Element *E=material->instantiable_owners.front();E;E=E->next()) { + E->key()->instance_material_change_notify(); + } + + for(Map::Element *E=material->instance_owners.front();E;E=E->next()) { + E->key()->base_material_changed(); + } + + } + + } + + //clear ubo if it needs to be cleared if (material->ubo_size) { @@ -2102,6 +2199,36 @@ void RasterizerStorageGLES3::_update_material(Material* material) { } +void RasterizerStorageGLES3::_material_add_instantiable(RID p_material,Instantiable *p_instantiable) { + + Material * material = material_owner.getornull(p_material); + ERR_FAIL_COND(!material); + + Map::Element *I = material->instantiable_owners.find(p_instantiable); + + if (I) { + I->get()++; + } else { + material->instantiable_owners[p_instantiable]=1; + } + +} + +void RasterizerStorageGLES3::_material_remove_instantiable(RID p_material,Instantiable *p_instantiable) { + + Material * material = material_owner.getornull(p_material); + ERR_FAIL_COND(!material); + + Map::Element *I = material->instantiable_owners.find(p_instantiable); + ERR_FAIL_COND(!I); + + I->get()--; + if (I->get()==0) { + material->instantiable_owners.erase(I); + } +} + + void RasterizerStorageGLES3::update_dirty_materials() { while( _material_dirty_list.first() ) { @@ -2406,6 +2533,8 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::P surface->active=true; surface->array_len=p_vertex_count; surface->index_array_len=p_index_count; + surface->array_byte_size=p_array.size(); + surface->index_array_byte_size=p_index_array.size(); surface->primitive=p_primitive; surface->mesh=mesh; surface->format=p_format; @@ -2556,8 +2685,22 @@ void RasterizerStorageGLES3::mesh_surface_set_material(RID p_mesh, int p_surface ERR_FAIL_COND(!mesh); ERR_FAIL_INDEX(p_surface,mesh->surfaces.size()); + if (mesh->surfaces[p_surface]->material==p_material) + return; + + if (mesh->surfaces[p_surface]->material.is_valid()) { + _material_remove_instantiable(mesh->surfaces[p_surface]->material,mesh); + } + mesh->surfaces[p_surface]->material=p_material; + if (mesh->surfaces[p_surface]->material.is_valid()) { + _material_add_instantiable(mesh->surfaces[p_surface]->material,mesh); + } + + mesh->instance_material_change_notify(); + + } RID RasterizerStorageGLES3::mesh_surface_get_material(RID p_mesh, int p_surface) const{ @@ -2595,17 +2738,17 @@ DVector RasterizerStorageGLES3::mesh_surface_get_array(RID p_mesh, int Surface *surface = mesh->surfaces[p_surface]; glBindBuffer(GL_ARRAY_BUFFER,surface->vertex_id); - void * data = glMapBufferRange(GL_ARRAY_BUFFER,0,surface->array_len,GL_MAP_READ_BIT); + void * data = glMapBufferRange(GL_ARRAY_BUFFER,0,surface->array_byte_size,GL_MAP_READ_BIT); ERR_FAIL_COND_V(!data,DVector()); DVector ret; - ret.resize(surface->array_len); + ret.resize(surface->array_byte_size); { DVector::Write w = ret.write(); - copymem(w.ptr(),data,surface->array_len); + copymem(w.ptr(),data,surface->array_byte_size); } glUnmapBuffer(GL_ARRAY_BUFFER); @@ -2622,18 +2765,18 @@ DVector RasterizerStorageGLES3::mesh_surface_get_index_array(RID p_mesh ERR_FAIL_COND_V(surface->index_array_len==0,DVector()); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,surface->vertex_id); - void * data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER,0,surface->index_array_len,GL_MAP_READ_BIT); + 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,DVector()); DVector ret; - ret.resize(surface->index_array_len); + ret.resize(surface->index_array_byte_size); { DVector::Write w = ret.write(); - copymem(w.ptr(),data,surface->index_array_len); + copymem(w.ptr(),data,surface->index_array_byte_size); } glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); @@ -2662,6 +2805,59 @@ VS::PrimitiveType RasterizerStorageGLES3::mesh_surface_get_primitive_type(RID p_ return mesh->surfaces[p_surface]->primitive; } +AABB RasterizerStorageGLES3::mesh_surface_get_aabb(RID p_mesh, int p_surface) const { + + const Mesh *mesh = mesh_owner.getornull(p_mesh); + ERR_FAIL_COND_V(!mesh,AABB()); + ERR_FAIL_INDEX_V(p_surface,mesh->surfaces.size(),AABB()); + + return mesh->surfaces[p_surface]->aabb; + + +} +Vector > RasterizerStorageGLES3::mesh_surface_get_blend_shapes(RID p_mesh, int p_surface) const{ + + const Mesh *mesh = mesh_owner.getornull(p_mesh); + ERR_FAIL_COND_V(!mesh,Vector >()); + ERR_FAIL_INDEX_V(p_surface,mesh->surfaces.size(),Vector >()); + + Vector > bsarr; + + for(int i=0;isurfaces[p_surface]->morph_targets.size();i++) { + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,mesh->surfaces[p_surface]->morph_targets[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 >()); + + DVector ret; + ret.resize(mesh->surfaces[p_surface]->array_byte_size); + + { + + DVector::Write w = ret.write(); + copymem(w.ptr(),data,mesh->surfaces[p_surface]->array_byte_size); + } + + bsarr.push_back(ret); + + glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); + } + + return bsarr; + +} +Vector RasterizerStorageGLES3::mesh_surface_get_skeleton_aabb(RID p_mesh, int p_surface) const{ + + const Mesh *mesh = mesh_owner.getornull(p_mesh); + ERR_FAIL_COND_V(!mesh,Vector()); + ERR_FAIL_INDEX_V(p_surface,mesh->surfaces.size(),Vector()); + + return mesh->surfaces[p_surface]->skeleton_bone_aabb; + +} + + void RasterizerStorageGLES3::mesh_remove_surface(RID p_mesh, int p_surface){ Mesh *mesh = mesh_owner.getornull(p_mesh); @@ -2670,6 +2866,10 @@ void RasterizerStorageGLES3::mesh_remove_surface(RID p_mesh, int p_surface){ Surface *surface = mesh->surfaces[p_surface]; + if (surface->material.is_valid()) { + _material_remove_instantiable(surface->material,mesh); + } + glDeleteBuffers(1,&surface->vertex_id); if (surface->index_id) { glDeleteBuffers(1,&surface->index_id); @@ -2683,6 +2883,8 @@ void RasterizerStorageGLES3::mesh_remove_surface(RID p_mesh, int p_surface){ glDeleteVertexArrays(1,&surface->morph_targets[i].array_id); } + mesh->instance_material_change_notify(); + memdelete(surface); mesh->surfaces.remove(p_surface); @@ -2971,7 +3173,6 @@ RID RasterizerStorageGLES3::light_create(VS::LightType p_type){ light->param[VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET]=0.1; light->param[VS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET]=0.3; light->param[VS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET]=0.6; - light->param[VS::LIGHT_PARAM_SHADOW_SPLIT_4_OFFSET]=1.0; light->param[VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS]=0.1; light->param[VS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE]=0.1; @@ -2981,6 +3182,10 @@ RID RasterizerStorageGLES3::light_create(VS::LightType p_type){ light->negative=false; light->cull_mask=0xFFFFFFFF; light->directional_shadow_mode=VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; + light->omni_shadow_mode=VS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID; + light->omni_shadow_detail=VS::LIGHT_OMNI_SHADOW_DETAIL_VERTICAL; + + light->version=0; return light_owner.make_rid(light); } @@ -2998,9 +3203,23 @@ void RasterizerStorageGLES3::light_set_param(RID p_light,VS::LightParam p_param, ERR_FAIL_COND(!light); ERR_FAIL_INDEX(p_param,VS::LIGHT_PARAM_MAX); - if (p_param==VS::LIGHT_PARAM_RANGE || p_param==VS::LIGHT_PARAM_SPOT_ANGLE) { - light->instance_change_notify(); + switch(p_param) { + case VS::LIGHT_PARAM_RANGE: + case VS::LIGHT_PARAM_SPOT_ANGLE: + case VS::LIGHT_PARAM_SHADOW_MAX_DISTANCE: + case VS::LIGHT_PARAM_SHADOW_DARKNESS: + case VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET: + case VS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET: + case VS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET: + case VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS: + case VS::LIGHT_PARAM_SHADOW_BIAS: + case VS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE: { + + light->version++; + light->instance_change_notify(); + } break; } + light->param[p_param]=p_value; } void RasterizerStorageGLES3::light_set_shadow(RID p_light,bool p_enabled){ @@ -3009,6 +3228,10 @@ void RasterizerStorageGLES3::light_set_shadow(RID p_light,bool p_enabled){ ERR_FAIL_COND(!light); light->shadow=p_enabled; + light->version++; + light->instance_change_notify(); + + } void RasterizerStorageGLES3::light_set_projector(RID p_light,RID p_texture){ @@ -3021,9 +3244,8 @@ void RasterizerStorageGLES3::light_set_attenuation_texure(RID p_light,RID p_text Light * light = light_owner.getornull(p_light); ERR_FAIL_COND(!light); - - } + void RasterizerStorageGLES3::light_set_negative(RID p_light,bool p_enable){ Light * light = light_owner.getornull(p_light); @@ -3037,6 +3259,10 @@ void RasterizerStorageGLES3::light_set_cull_mask(RID p_light,uint32_t p_mask){ ERR_FAIL_COND(!light); light->cull_mask=p_mask; + + light->version++; + light->instance_change_notify(); + } void RasterizerStorageGLES3::light_set_shader(RID p_light,RID p_shader){ @@ -3045,22 +3271,92 @@ void RasterizerStorageGLES3::light_set_shader(RID p_light,RID p_shader){ } +void RasterizerStorageGLES3::light_omni_set_shadow_mode(RID p_light,VS::LightOmniShadowMode p_mode) { + + Light * light = light_owner.getornull(p_light); + ERR_FAIL_COND(!light); + + light->omni_shadow_mode=p_mode; + + light->version++; + light->instance_change_notify(); + + +} + +VS::LightOmniShadowMode RasterizerStorageGLES3::light_omni_get_shadow_mode(RID p_light) { + + const Light * light = light_owner.getornull(p_light); + ERR_FAIL_COND_V(!light,VS::LIGHT_OMNI_SHADOW_CUBE); + + return light->omni_shadow_mode; +} + + +void RasterizerStorageGLES3::light_omni_set_shadow_detail(RID p_light,VS::LightOmniShadowDetail p_detail) { + + Light * light = light_owner.getornull(p_light); + ERR_FAIL_COND(!light); + + light->omni_shadow_detail=p_detail; + light->version++; + light->instance_change_notify(); +} + void RasterizerStorageGLES3::light_directional_set_shadow_mode(RID p_light,VS::LightDirectionalShadowMode p_mode){ Light * light = light_owner.getornull(p_light); ERR_FAIL_COND(!light); + light->directional_shadow_mode=p_mode; + light->version++; + light->instance_change_notify(); + +} + +VS::LightDirectionalShadowMode RasterizerStorageGLES3::light_directional_get_shadow_mode(RID p_light) { + + const Light * light = light_owner.getornull(p_light); + ERR_FAIL_COND_V(!light,VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL); + + return light->directional_shadow_mode; } + VS::LightType RasterizerStorageGLES3::light_get_type(RID p_light) const { const Light * light = light_owner.getornull(p_light); ERR_FAIL_COND_V(!light,VS::LIGHT_DIRECTIONAL); - return VS::LIGHT_DIRECTIONAL; + return light->type; } +float RasterizerStorageGLES3::light_get_param(RID p_light,VS::LightParam p_param) { + + const Light * light = light_owner.getornull(p_light); + ERR_FAIL_COND_V(!light,VS::LIGHT_DIRECTIONAL); + + return light->param[p_param]; +} + +bool RasterizerStorageGLES3::light_has_shadow(RID p_light) const { + + const Light * light = light_owner.getornull(p_light); + ERR_FAIL_COND_V(!light,VS::LIGHT_DIRECTIONAL); + + return light->shadow; +} + +uint64_t RasterizerStorageGLES3::light_get_version(RID p_light) const { + + const Light * light = light_owner.getornull(p_light); + ERR_FAIL_COND_V(!light,0); + + return light->version; +} + + AABB RasterizerStorageGLES3::light_get_aabb(RID p_light) const { const Light * light = light_owner.getornull(p_light); diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index b12c2d93b6..f8b34d6a16 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -99,6 +99,38 @@ public: + struct Instantiable : public RID_Data { + + SelfList::List instance_list; + + _FORCE_INLINE_ void instance_change_notify() { + + SelfList *instances = instance_list.first(); + while(instances) { + + instances->self()->base_changed(); + instances=instances->next(); + } + } + + _FORCE_INLINE_ void instance_material_change_notify() { + + SelfList *instances = instance_list.first(); + while(instances) { + + instances->self()->base_material_changed(); + instances=instances->next(); + } + } + + Instantiable() { } + virtual ~Instantiable() { + + while(instance_list.first()) { + instance_list.first()->self()->base_removed(); + } + } + }; @@ -282,9 +314,14 @@ public: bool uses_alpha; bool unshaded; bool ontop; + bool uses_vertex; + bool uses_discard; } spatial; + bool uses_vertex_time; + bool uses_fragment_time; + Shader() : dirty_list(this) { shader=NULL; @@ -315,6 +352,8 @@ public: void update_dirty_shaders(); + + /* COMMON MATERIAL API */ struct Material : public RID_Data { @@ -331,7 +370,15 @@ public: uint32_t index; uint64_t last_pass; + Map instantiable_owners; + Map instance_owners; + + bool can_cast_shadow_cache; + bool is_animated_cache; + Material() : list(this), dirty_list(this) { + can_cast_shadow_cache=false; + is_animated_cache=false; shader=NULL; line_width=1.0; ubo_id=0; @@ -343,6 +390,8 @@ public: mutable SelfList::List _material_dirty_list; void _material_make_dirty(Material *p_material) const; + void _material_add_instantiable(RID p_material,Instantiable *p_instantiable); + void _material_remove_instantiable(RID p_material, Instantiable *p_instantiable); mutable RID_Owner material_owner; @@ -357,34 +406,18 @@ public: virtual void material_set_line_width(RID p_material, float p_width); + virtual bool material_is_animated(RID p_material); + virtual bool material_casts_shadows(RID p_material); + + virtual void material_add_instance_owner(RID p_material, RasterizerScene::InstanceBase *p_instance); + virtual void material_remove_instance_owner(RID p_material, RasterizerScene::InstanceBase *p_instance); + void _update_material(Material* material); void update_dirty_materials(); /* MESH API */ - struct Instantiable : public RID_Data { - - SelfList::List instance_list; - - _FORCE_INLINE_ void instance_change_notify() { - - SelfList *instances = instance_list.first(); - while(instances) { - - instances->self()->base_changed(); - instances=instances->next(); - } - } - - Instantiable() { } - virtual ~Instantiable() { - - while(instance_list.first()) { - instance_list.first()->self()->base_removed(); - } - } - }; struct Geometry : Instantiable { @@ -455,7 +488,8 @@ public: int index_array_len; int max_bone; - int array_bytes; + int array_byte_size; + int index_array_byte_size; VS::PrimitiveType primitive; @@ -464,7 +498,8 @@ public: Surface() { - array_bytes=0; + array_byte_size=0; + index_array_byte_size=0; mesh=NULL; format=0; array_id=0; @@ -526,6 +561,10 @@ public: virtual uint32_t mesh_surface_get_format(RID p_mesh, int p_surface) const; virtual VS::PrimitiveType mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const; + virtual AABB mesh_surface_get_aabb(RID p_mesh, int p_surface) const; + virtual Vector > mesh_surface_get_blend_shapes(RID p_mesh, int p_surface) const; + virtual Vector mesh_surface_get_skeleton_aabb(RID p_mesh, int p_surface) const; + virtual void mesh_remove_surface(RID p_mesh, int p_surface); virtual int mesh_get_surface_count(RID p_mesh) const; @@ -598,7 +637,10 @@ public: bool shadow; bool negative; uint32_t cull_mask; + VS::LightOmniShadowMode omni_shadow_mode; + VS::LightOmniShadowDetail omni_shadow_detail; VS::LightDirectionalShadowMode directional_shadow_mode; + uint64_t version; }; mutable RID_Owner light_owner; @@ -614,11 +656,22 @@ public: virtual void light_set_cull_mask(RID p_light,uint32_t p_mask); virtual void light_set_shader(RID p_light,RID p_shader); + 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); virtual void light_directional_set_shadow_mode(RID p_light,VS::LightDirectionalShadowMode p_mode); + virtual VS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light); + virtual VS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light); + + virtual bool light_has_shadow(RID p_light) const; virtual VS::LightType light_get_type(RID p_light) const; + virtual float light_get_param(RID p_light,VS::LightParam p_param); + virtual AABB light_get_aabb(RID p_light) const; + virtual uint64_t light_get_version(RID p_light) const; + /* PROBE API */ virtual RID reflection_probe_create(); diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp index 0dff53bfb9..dce52ecd93 100644 --- a/drivers/gles3/shader_compiler_gles3.cpp +++ b/drivers/gles3/shader_compiler_gles3.cpp @@ -330,6 +330,7 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener SL::FunctionNode *fnode=pnode->functions[i].function; + current_func_name=fnode->name; if (fnode->name=="vertex") { @@ -401,6 +402,14 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener else code=_mkid(vnode->name); + if (vnode->name==time_name) { + if (current_func_name==vertex_name) { + r_gen_code.uses_vertex_time=true; + } + if (current_func_name==fragment_name) { + r_gen_code.uses_fragment_time=true; + } + } } break; case SL::Node::TYPE_CONSTANT: { @@ -536,6 +545,8 @@ Error ShaderCompilerGLES3::compile(VS::ShaderMode p_mode, const String& p_code, r_gen_code.fragment=String(); r_gen_code.fragment_global=String(); r_gen_code.light=String(); + r_gen_code.uses_fragment_time=false; + r_gen_code.uses_vertex_time=false; @@ -645,7 +656,9 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() { - + vertex_name="vertex"; + fragment_name="fragment"; + time_name="TIME"; diff --git a/drivers/gles3/shader_compiler_gles3.h b/drivers/gles3/shader_compiler_gles3.h index dcea82d773..3549526808 100644 --- a/drivers/gles3/shader_compiler_gles3.h +++ b/drivers/gles3/shader_compiler_gles3.h @@ -32,6 +32,9 @@ public: String fragment; String light; + bool uses_fragment_time; + bool uses_vertex_time; + }; private: @@ -49,6 +52,10 @@ private: String _dump_node_code(ShaderLanguage::Node *p_node, int p_level, GeneratedCode &r_gen_code, IdentifierActions& p_actions, const DefaultIdentifierActions& p_default_actions); + StringName current_func_name; + StringName vertex_name; + StringName fragment_name; + StringName time_name; Set used_name_defines; Set used_rmode_defines; diff --git a/drivers/gles3/shaders/SCsub b/drivers/gles3/shaders/SCsub index afffe10316..44d325b091 100644 --- a/drivers/gles3/shaders/SCsub +++ b/drivers/gles3/shaders/SCsub @@ -6,4 +6,5 @@ if env['BUILDERS'].has_key('GLES3_GLSL'): env.GLES3_GLSL('canvas_shadow.glsl'); env.GLES3_GLSL('scene.glsl'); env.GLES3_GLSL('cubemap_filter.glsl'); + env.GLES3_GLSL('cube_to_dp.glsl'); diff --git a/drivers/gles3/shaders/cube_to_dp.glsl b/drivers/gles3/shaders/cube_to_dp.glsl new file mode 100644 index 0000000000..5ffc78c0b9 --- /dev/null +++ b/drivers/gles3/shaders/cube_to_dp.glsl @@ -0,0 +1,79 @@ +[vertex] + + +layout(location=0) in highp vec4 vertex_attrib; +layout(location=4) in vec2 uv_in; + +out vec2 uv_interp; + +void main() { + + uv_interp = uv_in; + gl_Position = vertex_attrib; +} + +[fragment] + + +uniform highp samplerCube source_cube; //texunit:0 +in vec2 uv_interp; + +uniform bool z_flip; +uniform highp float z_far; +uniform highp float z_near; +uniform highp float bias; + +void main() { + + highp vec3 normal = vec3( uv_interp * 2.0 - 1.0, 0.0 ); +/* + if(z_flip) { + normal.z = 0.5 - 0.5*((normal.x * normal.x) + (normal.y * normal.y)); + } else { + normal.z = -0.5 + 0.5*((normal.x * normal.x) + (normal.y * normal.y)); + } +*/ + + //normal.z = sqrt(1.0-dot(normal.xy,normal.xy)); + //normal.xy*=1.0+normal.z; + + normal.z = 0.5 - 0.5*((normal.x * normal.x) + (normal.y * normal.y)); + normal = normalize(normal); + +/* + normal.z=0.5; + normal=normalize(normal); +*/ + if (!z_flip) { + normal.z=-normal.z; + } + + //normal = normalize(vec3( uv_interp * 2.0 - 1.0, 1.0 )); + float depth = texture(source_cube,normal).r; + + // absolute values for direction cosines, bigger value equals closer to basis axis + vec3 unorm = abs(normal); + + if ( (unorm.x >= unorm.y) && (unorm.x >= unorm.z) ) { + // x code + unorm = normal.x > 0.0 ? vec3( 1.0, 0.0, 0.0 ) : vec3( -1.0, 0.0, 0.0 ) ; + } else if ( (unorm.y > unorm.x) && (unorm.y >= unorm.z) ) { + // y code + unorm = normal.y > 0.0 ? vec3( 0.0, 1.0, 0.0 ) : vec3( 0.0, -1.0, 0.0 ) ; + } else if ( (unorm.z > unorm.x) && (unorm.z > unorm.y) ) { + // z code + unorm = normal.z > 0.0 ? vec3( 0.0, 0.0, 1.0 ) : vec3( 0.0, 0.0, -1.0 ) ; + } else { + // oh-no we messed up code + // has to be + unorm = vec3( 1.0, 0.0, 0.0 ); + } + + float depth_fix = 1.0 / dot(normal,unorm); + + + depth = 2.0 * depth - 1.0; + float linear_depth = 2.0 * z_near * z_far / (z_far + z_near - depth * (z_far - z_near)); + gl_FragDepth = (linear_depth*depth_fix+bias) / z_far; +} + diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index 60ac015a17..de1591e8ff 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -1,7 +1,6 @@ [vertex] -#define ENABLE_UV_INTERP /* from VisualServer: @@ -56,6 +55,15 @@ layout(std140) uniform SceneData { //ubo:0 highp vec4 bg_color; float ambient_energy; float bg_energy; + + float shadow_z_offset; + float shadow_z_slope_scale; + float shadow_dual_paraboloid_render_zfar; + float shadow_dual_paraboloid_render_side; + + vec2 shadow_atlas_pixel_size; + vec2 directional_shadow_pixel_size; + }; uniform highp mat4 world_transform; @@ -68,6 +76,7 @@ layout(std140) uniform LightData { //ubo:3 mediump vec4 light_direction_attenuation; mediump vec4 light_color_energy; mediump vec4 light_params; //cone attenuation, specular, shadow darkening, + mediump vec4 light_clamp; mediump vec4 shadow_split_offsets; highp mat4 shadow_matrix1; highp mat4 shadow_matrix2; @@ -75,19 +84,6 @@ layout(std140) uniform LightData { //ubo:3 highp mat4 shadow_matrix4; }; -#ifdef USE_FORWARD_1_SHADOW_MAP -out mediump vec4 forward_shadow_pos1; -#endif - -#ifdef USE_FORWARD_2_SHADOW_MAP -out mediump vec4 forward_shadow_pos2; -#endif - -#ifdef USE_FORWARD_4_SHADOW_MAP -out mediump vec4 forward_shadow_pos3; -out mediump vec4 forward_shadow_pos4; -#endif - #endif /* Varyings */ @@ -120,13 +116,6 @@ varying vec4 position_interp; #endif -#ifdef USE_SHADOW_PASS - -uniform highp float shadow_z_offset; -uniform highp float shadow_z_slope_scale; - -#endif - VERTEX_SHADER_GLOBALS @@ -141,6 +130,11 @@ MATERIAL_UNIFORMS #endif +#ifdef RENDER_SHADOW_DUAL_PARABOLOID + +out highp float dp_clip; + +#endif void main() { @@ -206,24 +200,49 @@ VERTEX_SHADER_CODE } + vertex_interp = vertex.xyz; + normal_interp = normal; + +#if defined(ENABLE_TANGENT_INTERP) + tangent_interp = tangent; + binormal_interp = binormal; +#endif + +#ifdef RENDER_SHADOW + + +#ifdef RENDER_SHADOW_DUAL_PARABOLOID + + vertex_interp.z*= shadow_dual_paraboloid_render_side; + normal_interp.z*= shadow_dual_paraboloid_render_side; -#ifdef USE_SHADOW_PASS + dp_clip=vertex_interp.z; //this attempts to avoid noise caused by objects sent to the other parabolloid side due to bias + + //for dual paraboloid shadow mapping, this is the fastest but least correct way, as it curves straight edges + + highp vec3 vtx = vertex_interp+normalize(vertex_interp)*shadow_z_offset; + highp float distance = length(vtx); + vtx = normalize(vtx); + vtx.xy/=1.0-vtx.z; + vtx.z=(distance/shadow_dual_paraboloid_render_zfar); + vtx.z=vtx.z * 2.0 - 1.0; + + vertex.xyz=vtx; + vertex.w=1.0; + + +#else float z_ofs = shadow_z_offset; z_ofs += (1.0-abs(normal_interp.z))*shadow_z_slope_scale; vertex_interp.z-=z_ofs; -#endif +#endif //RENDER_SHADOW_DUAL_PARABOLOID - vertex_interp = vertex.xyz; - normal_interp = normal; +#endif //RENDER_SHADOW -#if defined(ENABLE_TANGENT_INTERP) - tangent_interp = tangent; - binormal_interp = binormal; -#endif -#if !defined(SKIP_TRANSFORM_USED) +#if !defined(SKIP_TRANSFORM_USED) && !defined(RENDER_SHADOW_DUAL_PARABOLOID) gl_Position = projection_matrix * vec4(vertex_interp,1.0); #else gl_Position = vertex; @@ -239,11 +258,6 @@ VERTEX_SHADER_CODE #define M_PI 3.14159265359 - -#define ENABLE_UV_INTERP -//hack to use uv if no uv present so it works with lightmap - - /* Varyings */ #if defined(ENABLE_COLOR_INTERP) @@ -318,6 +332,15 @@ layout(std140) uniform SceneData { highp vec4 bg_color; float ambient_energy; float bg_energy; + + float shadow_z_offset; + float shadow_z_slope_scale; + float shadow_dual_paraboloid_render_zfar; + float shadow_dual_paraboloid_render_side; + + vec2 shadow_atlas_pixel_size; + vec2 directional_shadow_pixel_size; + }; @@ -328,7 +351,8 @@ layout(std140) uniform LightData { highp vec4 light_pos_inv_radius; mediump vec4 light_direction_attenuation; mediump vec4 light_color_energy; - mediump vec4 light_params; //cone attenuation, specular, shadow darkening, + mediump vec4 light_params; //cone attenuation, specular, shadow darkening, shadow enabled + mediump vec4 light_clamp; mediump vec4 shadow_split_offsets; highp mat4 shadow_matrix1; highp mat4 shadow_matrix2; @@ -336,20 +360,12 @@ layout(std140) uniform LightData { highp mat4 shadow_matrix4; }; -#ifdef USE_FORWARD_1_SHADOW_MAP -in mediump vec4 forward_shadow_pos1; #endif -#ifdef USE_FORWARD_2_SHADOW_MAP -in mediump vec4 forward_shadow_pos2; -#endif -#ifdef USE_FORWARD_4_SHADOW_MAP -in mediump vec4 forward_shadow_pos3; -in mediump vec4 forward_shadow_pos4; -#endif +uniform highp sampler2DShadow directional_shadow; //texunit:-4 +uniform highp sampler2DShadow shadow_atlas; //texunit:-3 -#endif #ifdef USE_MULTIPLE_RENDER_TARGETS @@ -408,10 +424,27 @@ void light_compute(vec3 normal, vec3 light_vec,vec3 eye_vec,vec3 diffuse_color, } +float sample_shadow(highp sampler2DShadow shadow, vec2 shadow_pixel_size, vec2 pos, float depth, vec4 clamp_rect) { + + return textureProj(shadow,vec4(pos,depth,1.0)); +} + +#ifdef RENDER_SHADOW_DUAL_PARABOLOID + +in highp float dp_clip; + +#endif + void main() { +#ifdef RENDER_SHADOW_DUAL_PARABOLOID + + if (dp_clip>0.0) + discard; +#endif + //lay out everything, whathever is unused is optimized away anyway - vec3 vertex = vertex_interp; + highp vec3 vertex = vertex_interp; vec3 albedo = vec3(0.8,0.8,0.8); vec3 specular = vec3(0.2,0.2,0.2); float roughness = 1.0; @@ -528,27 +561,216 @@ FRAGMENT_SHADER_CODE #endif -#ifdef USE_FORWARD_LIGHTING - #ifdef USE_FORWARD_DIRECTIONAL - light_compute(normal,light_direction_attenuation.xyz,eye_vec,albedo,specular,roughness,1.0,diffuse_light,specular_light); + float light_attenuation=1.0; + +#ifdef LIGHT_DIRECTIONAL_SHADOW + + if (gl_FragCoord.w > shadow_split_offsets.w) { + + vec3 pssm_coord; + +#ifdef LIGHT_USE_PSSM_BLEND + float pssm_blend; + vec3 pssm_coord2; + bool use_blend=true; + vec3 light_pssm_split_inv = 1.0/shadow_split_offsets.xyz; + float w_inv = 1.0/gl_FragCoord.w; #endif + +#ifdef LIGHT_USE_PSSM4 + + + if (gl_FragCoord.w > shadow_split_offsets.y) { + + if (gl_FragCoord.w > shadow_split_offsets.x) { + + highp vec4 splane=(shadow_matrix1 * vec4(vertex,1.0)); + pssm_coord=splane.xyz/splane.w; + ambient_light=vec3(1.0,0.4,0.4); + + +#if defined(LIGHT_USE_PSSM_BLEND) + + splane=(shadow_matrix2 * vec4(vertex,1.0)); + pssm_coord2=splane.xyz/splane.w; + pssm_blend=smoothstep(0.0,light_pssm_split_inv.x,w_inv); +#endif + + } else { + + highp vec4 splane=(shadow_matrix2 * vec4(vertex,1.0)); + pssm_coord=splane.xyz/splane.w; + ambient_light=vec3(0.4,1.0,0.4); + +#if defined(LIGHT_USE_PSSM_BLEND) + splane=(shadow_matrix3 * vec4(vertex,1.0)); + pssm_coord2=splane.xyz/splane.w; + pssm_blend=smoothstep(light_pssm_split_inv.x,light_pssm_split_inv.y,w_inv); +#endif + + } + } else { + + + if (gl_FragCoord.w > shadow_split_offsets.z) { + + highp vec4 splane=(shadow_matrix3 * vec4(vertex,1.0)); + pssm_coord=splane.xyz/splane.w; + ambient_light=vec3(0.4,0.4,1.0); + +#if defined(LIGHT_USE_PSSM_BLEND) + splane=(shadow_matrix4 * vec4(vertex,1.0)); + pssm_coord2=splane.xyz/splane.w; + pssm_blend=smoothstep(light_pssm_split_inv.y,light_pssm_split_inv.z,w_inv); +#endif + + } else { + highp vec4 splane=(shadow_matrix4 * vec4(vertex,1.0)); + pssm_coord=splane.xyz/splane.w; + diffuse_light*=vec3(1.0,0.4,1.0); + +#if defined(LIGHT_USE_PSSM_BLEND) + use_blend=false; + +#endif + + } + } + +#endif //LIGHT_USE_PSSM4 + +#ifdef LIGHT_USE_PSSM2 + + if (gl_FragCoord.w > shadow_split_offsets.x) { + + highp vec4 splane=(shadow_matrix1 * vec4(vertex,1.0)); + pssm_coord=splane.xyz/splane.w; + + +#if defined(LIGHT_USE_PSSM_BLEND) + + splane=(shadow_matrix2 * vec4(vertex,1.0)); + pssm_coord2=splane.xyz/splane.w; + pssm_blend=smoothstep(0.0,light_pssm_split_inv.x,w_inv); +#endif + + } else { + highp vec4 splane=(shadow_matrix2 * vec4(vertex,1.0)); + pssm_coord=splane.xyz/splane.w; +#if defined(LIGHT_USE_PSSM_BLEND) + use_blend=false; + +#endif + + } + +#endif //LIGHT_USE_PSSM2 + +#if !defined(LIGHT_USE_PSSM4) && !defined(LIGHT_USE_PSSM2) + { //regular orthogonal + highp vec4 splane=(shadow_matrix1 * vec4(vertex,1.0)); + pssm_coord=splane.xyz/splane.w; + } +#endif + + + //one one sample + light_attenuation=sample_shadow(directional_shadow,directional_shadow_pixel_size,pssm_coord.xy,pssm_coord.z,light_clamp); + + +#if defined(LIGHT_USE_PSSM_BLEND) + if (use_blend) { + float light_attenuation2=sample_shadow(directional_shadow,directional_shadow_pixel_size,pssm_coord2.xy,pssm_coord2.z,light_clamp); + light_attenuation=mix(light_attenuation,light_attenuation2,pssm_blend); + } +#endif + + } + +#endif //LIGHT_DIRECTIONAL_SHADOW + + light_compute(normal,-light_direction_attenuation.xyz,eye_vec,albedo,specular,roughness,light_attenuation,diffuse_light,specular_light); + + +#endif //USE_FORWARD_DIRECTIONAL + + #ifdef USE_FORWARD_OMNI vec3 light_rel_vec = light_pos_inv_radius.xyz-vertex; float normalized_distance = length( light_rel_vec )*light_pos_inv_radius.w; float light_attenuation = pow( max(1.0 - normalized_distance, 0.0), light_direction_attenuation.w ); + + if (light_params.w>0.5) { + //there is a shadowmap + + highp vec3 splane=(shadow_matrix1 * vec4(vertex,1.0)).xyz; + float shadow_len=length(splane); + splane=normalize(splane); + vec4 clamp_rect=light_clamp; + + if (splane.z>=0.0) { + + splane.z+=1.0; + + clamp_rect.y+=clamp_rect.w; + + } else { + + splane.z=1.0 - splane.z; + + //if (clamp_rect.z0.5) { + //there is a shadowmap + + highp vec4 splane=(shadow_matrix1 * vec4(vertex,1.0)); + splane.xyz/=splane.w; + // splane.xy=splane.xy*0.5+0.5; + + //splane.xy=light_clamp.xy+splane.xy*light_clamp.zw; + light_attenuation*=sample_shadow(shadow_atlas,shadow_atlas_pixel_size,splane.xy,splane.z,light_clamp); + + } + + light_compute(normal,normalize(light_rel_vec),eye_vec,albedo,specular,roughness,light_attenuation,diffuse_light,specular_light); + +#endif //USE_FORWARD_SPOT -#endif #if defined(USE_LIGHT_SHADER_CODE) @@ -560,6 +782,11 @@ LIGHT_SHADER_CODE } #endif +#ifdef RENDER_SHADOW +//nothing happens, so a tree-ssa optimizer will result in no fragment shader :) +#else + + #ifdef USE_MULTIPLE_RENDER_TARGETS //approximate ambient scale for SSAO, since we will lack full ambient @@ -574,13 +801,17 @@ LIGHT_SHADER_CODE #else + #ifdef SHADELESS frag_color=vec4(albedo,alpha); #else frag_color=vec4(ambient_light+diffuse_light+specular_light,alpha); -#endif +#endif //SHADELESS + +#endif //USE_MULTIPLE_RENDER_TARGETS + +#endif //RENDER_SHADOW -#endif } -- cgit v1.2.3 From a7078a4be9f4c44a41e5c7e7a633169b53f78d48 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Fri, 11 Nov 2016 12:27:52 -0300 Subject: Done with lights and shadows (wonder if i'm missing something..) --- drivers/gles3/rasterizer_gles3.cpp | 2 +- drivers/gles3/rasterizer_scene_gles3.cpp | 786 ++++++++++++++++------------- drivers/gles3/rasterizer_scene_gles3.h | 91 ++-- drivers/gles3/rasterizer_storage_gles3.cpp | 41 +- drivers/gles3/rasterizer_storage_gles3.h | 11 +- drivers/gles3/shader_gles3.cpp | 9 + drivers/gles3/shader_gles3.h | 6 + drivers/gles3/shaders/scene.glsl | 254 ++++++---- 8 files changed, 705 insertions(+), 495 deletions(-) (limited to 'drivers/gles3') diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index e838020c45..c799cd12af 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -125,6 +125,7 @@ void RasterizerGLES3::begin_frame(){ storage->update_dirty_shaders(); storage->update_dirty_materials(); + scene->iteration(); } @@ -258,7 +259,6 @@ void RasterizerGLES3::register_config() { GLOBAL_DEF("rendering/gles3/use_nearest_mipmap_filter",false); GLOBAL_DEF("rendering/gles3/anisotropic_filter_level",4.0); - } RasterizerGLES3::RasterizerGLES3() diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 287801b597..4ae257abc4 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -131,8 +131,10 @@ void RasterizerSceneGLES3::shadow_atlas_set_size(RID p_atlas,int p_size){ GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); //interpola nearest (though nvidia can improve this) - 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_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // Remove artifact on the edges of the shadowmap glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); @@ -559,11 +561,6 @@ RID RasterizerSceneGLES3::light_instance_create(RID p_light) { light_instance->light=p_light; light_instance->light_ptr=storage->light_owner.getornull(p_light); - glGenBuffers(1, &light_instance->light_ubo); - glBindBuffer(GL_UNIFORM_BUFFER, light_instance->light_ubo); - glBufferData(GL_UNIFORM_BUFFER, sizeof(LightInstance::LightDataUBO), NULL, GL_DYNAMIC_DRAW); - glBindBuffer(GL_UNIFORM_BUFFER, 0); - ERR_FAIL_COND_V(!light_instance->light_ptr,RID()); light_instance->self=light_instance_owner.make_rid(light_instance); @@ -818,9 +815,50 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) { } -void RasterizerSceneGLES3::_setup_light(LightInstance *p_light) { +void RasterizerSceneGLES3::_setup_light(RenderList::Element *e) { + + int omni_indices[16]; + int omni_count=0; + int spot_indices[16]; + int spot_count=0; + + int maxobj = MIN(16,state.max_forward_lights_per_object); + + int lc = e->instance->light_instances.size(); + if (lc) { + + const RID* lights=e->instance->light_instances.ptr(); + + for(int i=0;ilast_pass!=render_pass) //not visible + continue; + + if (li->light_ptr->type==VS::LIGHT_OMNI) { + if (omni_countinstance->layer_mask&li->light_ptr->cull_mask) { + omni_indices[omni_count++]=li->light_index; + } + } + + if (li->light_ptr->type==VS::LIGHT_SPOT) { + if (spot_countinstance->layer_mask&li->light_ptr->cull_mask) { + spot_indices[spot_count++]=li->light_index; + } + } + } + } + + state.scene_shader.set_uniform(SceneShaderGLES3::OMNI_LIGHT_COUNT,omni_count); + + if (omni_count) { + glUniform1iv(state.scene_shader.get_uniform(SceneShaderGLES3::OMNI_LIGHT_INDICES),omni_count,omni_indices); + } + + state.scene_shader.set_uniform(SceneShaderGLES3::SPOT_LIGHT_COUNT,spot_count); + if (spot_count) { + glUniform1iv(state.scene_shader.get_uniform(SceneShaderGLES3::SPOT_LIGHT_INDICES),spot_count,spot_indices); + } - glBindBufferBase(GL_UNIFORM_BUFFER,3,p_light->light_ubo); //bind light uniform } @@ -894,7 +932,7 @@ void RasterizerSceneGLES3::_set_cull(bool p_front,bool p_reverse_cull) { -void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_element_count,const Transform& p_view_transform,const CameraMatrix& p_projection,RasterizerStorageGLES3::Texture* p_base_env,bool p_reverse_cull,bool p_alpha_pass,bool p_shadow) { +void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_element_count,const Transform& p_view_transform,const CameraMatrix& p_projection,RasterizerStorageGLES3::Texture* p_base_env,bool p_reverse_cull,bool p_alpha_pass,bool p_shadow,bool p_directional_add) { if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP]) { //p_reverse_cull=!p_reverse_cull; @@ -906,7 +944,7 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e glBindBufferBase(GL_UNIFORM_BUFFER,0,state.scene_ubo); //bind globals ubo - if (!p_shadow) { + if (!p_shadow && !p_directional_add) { glBindBufferBase(GL_UNIFORM_BUFFER,2,state.env_radiance_ubo); //bind environment radiance info glActiveTexture(GL_TEXTURE0+storage->config.max_texture_image_units-1); glBindTexture(GL_TEXTURE_2D,state.brdf_texture); @@ -934,160 +972,147 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e state.current_line_width=-1; state.current_depth_draw=-1; - glDisable(GL_BLEND); - RasterizerStorageGLES3::Material* prev_material=NULL; RasterizerStorageGLES3::Geometry* prev_geometry=NULL; VS::InstanceType prev_base_type = VS::INSTANCE_MAX; - int prev_light_type=-1; - int prev_light_index=-1; - int prev_blend=-1; int current_blend_mode=-1; - bool prev_additive=false; + int prev_shading=-1; + + state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS,true); //by default unshaded (easier to set) + + bool first=true; for (int i=0;imaterial; - bool rebind=i==0; - - int light_type=(e->sort_key>>RenderList::SORT_KEY_LIGHT_TYPE_SHIFT)&0xF; - int light_index=(e->sort_key>>RenderList::SORT_KEY_LIGHT_INDEX_SHIFT)&0xFFFF; + bool rebind=first; - bool additive=false; + int shading = (e->sort_key>>RenderList::SORT_KEY_SHADING_SHIFT)&RenderList::SORT_KEY_SHADING_MASK; if (!p_shadow) { - if (light_type!=prev_light_type /* || receive_shadows_state!=prev_receive_shadows_state*/) { - if (material->shader->spatial.unshaded/* || current_debug==VS::SCENARIO_DEBUG_SHADELESS*/) { - state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_LIGHTING,false); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_DIRECTIONAL,false); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_OMNI,false); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_SPOT,false); + + if (p_directional_add) { + if (e->sort_key&RenderList::SORT_KEY_UNSHADED_FLAG || !(e->instance->layer_mask&directional_light->light_ptr->cull_mask)) { + continue; + } + + shading&=~1; //ignore the ignore directional for base pass + } + + if (shading!=prev_shading) { + + if (e->sort_key&RenderList::SORT_KEY_UNSHADED_FLAG) { + state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS,true); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_LIGHTING,false); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_LIGHT_DIRECTIONAL,false); state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_DIRECTIONAL_SHADOW,false); state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM4,false); state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM2,false); state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM_BLEND,false); + state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM_BLEND,false); + state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_5,false); + state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_13,false); + //state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS,true); } else { state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS,false); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_LIGHTING,light_type!=0xF); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_DIRECTIONAL,(light_type&3)==VS::LIGHT_DIRECTIONAL); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_OMNI,(light_type&0xF)==VS::LIGHT_OMNI); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_SPOT,(light_type&0xF)==VS::LIGHT_SPOT); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_LIGHTING,!p_directional_add); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_LIGHT_DIRECTIONAL,false); state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_DIRECTIONAL_SHADOW,false); state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM4,false); state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM2,false); state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM_BLEND,false); + state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_5,shadow_filter_mode==SHADOW_FILTER_PCF5); + state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_13,shadow_filter_mode==SHADOW_FILTER_PCF13); - if ((light_type&3)==VS::LIGHT_DIRECTIONAL) { - if (light_instances[light_index]->light_ptr->shadow) { + if (p_directional_add || (directional_light && (e->sort_key&RenderList::SORT_KEY_NO_DIRECTIONAL_FLAG)==0)) { + state.scene_shader.set_conditional(SceneShaderGLES3::USE_LIGHT_DIRECTIONAL,true); + + if (directional_light->light_ptr->shadow) { state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_DIRECTIONAL_SHADOW,true); - switch(light_instances[light_index]->light_ptr->directional_shadow_mode) { + switch(directional_light->light_ptr->directional_shadow_mode) { case VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: break; //none - case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM2,true); break; - case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM4,true); break; + case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: + state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM2,true); + state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM_BLEND,directional_light->light_ptr->directional_blend_splits); + break; + case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: + state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM4,true); + state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM_BLEND,directional_light->light_ptr->directional_blend_splits); + break; } } - } + } } rebind=true; } - - if (!*e->additive_ptr) { - - additive=false; - *e->additive_ptr=true; - } else { - additive=true; - } - - bool desired_blend=false; - int desired_blend_mode=RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_MIX; - - if (additive) { - desired_blend=true; - desired_blend_mode=RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_ADD; - } else { - desired_blend=p_alpha_pass; - desired_blend_mode=material->shader->spatial.blend_mode; - } - - if (prev_blend!=desired_blend) { - - if (desired_blend) { - glEnable(GL_BLEND); - if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { - glColorMask(1,1,1,0); - } + if (p_alpha_pass || p_directional_add) { + int desired_blend_mode; + if (p_directional_add) { + desired_blend_mode=RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_ADD; } else { - glDisable(GL_BLEND); - glColorMask(1,1,1,1); + desired_blend_mode=material->shader->spatial.blend_mode; } - prev_blend=desired_blend; - } + if (desired_blend_mode!=current_blend_mode) { - if (desired_blend && desired_blend_mode!=current_blend_mode) { + switch(desired_blend_mode) { - switch(desired_blend_mode) { + case RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_MIX: { + glBlendEquation(GL_FUNC_ADD); + if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } + else { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } - case RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_MIX: { - glBlendEquation(GL_FUNC_ADD); - if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - } - else { - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } + } break; + case RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_ADD: { - } break; - case RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_ADD: { + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(p_alpha_pass?GL_SRC_ALPHA:GL_ONE,GL_ONE); - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(p_alpha_pass?GL_SRC_ALPHA:GL_ONE,GL_ONE); + } break; + case RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_SUB: { - } break; - case RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_SUB: { + glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); + glBlendFunc(GL_SRC_ALPHA,GL_ONE); + } break; + case RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_MUL: { + glBlendEquation(GL_FUNC_ADD); + if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } + else { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } - glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); - glBlendFunc(GL_SRC_ALPHA,GL_ONE); - } break; - case RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_MUL: { - glBlendEquation(GL_FUNC_ADD); - if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - } - else { - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } + } break; - } break; + } + current_blend_mode=desired_blend_mode; } - current_blend_mode=desired_blend_mode; } - if (light_index!=prev_light_index) { - if (light_index!=0xFFFF) { //not unshaded - _setup_light(light_instances[light_index]); - } - } } @@ -1098,17 +1123,16 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e // _rinfo.mat_change_count++; } + if (!(e->sort_key&RenderList::SORT_KEY_UNSHADED_FLAG) && !p_directional_add && !p_shadow) { + _setup_light(e); + } + if (prev_base_type != e->instance->base_type || prev_geometry!=e->geometry) { _setup_geometry(e); } - if (!p_shadow && (rebind || prev_additive!=additive)) { - state.scene_shader.set_uniform(SceneShaderGLES3::NO_AMBIENT_LIGHT, additive); - - } - _set_cull(e->sort_key&RenderList::SORT_KEY_MIRROR_FLAG,p_reverse_cull); state.scene_shader.set_uniform(SceneShaderGLES3::NORMAL_MULT, e->instance->mirror?-1.0:1.0); @@ -1120,9 +1144,8 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e prev_material=material; prev_base_type=e->instance->base_type; prev_geometry=e->geometry; - prev_additive=additive; - prev_light_type=light_type; - prev_light_index=light_index; + prev_shading=shading; + first=false; } @@ -1133,14 +1156,14 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_CUBEMAP,false); state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_LIGHTING,false); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_DIRECTIONAL,false); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_OMNI,false); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_SPOT,false); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_LIGHT_DIRECTIONAL,false); state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_DIRECTIONAL_SHADOW,false); state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM4,false); state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM2,false); state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM_BLEND,false); state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS,false); + state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_5,false); + state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_13,false); } @@ -1214,8 +1237,6 @@ void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_g e->material=m; e->instance=p_instance; e->owner=p_owner; - e->additive=false; - e->additive_ptr=&e->additive; e->sort_key=0; if (e->geometry->last_pass!=render_pass) { @@ -1223,6 +1244,9 @@ void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_g e->geometry->index=current_geometry_index++; } + if (!p_shadow && directional_light && (directional_light->light_ptr->cull_mask&e->instance->layer_mask)==0) { + e->sort_key|=RenderList::SORT_KEY_NO_DIRECTIONAL_FLAG; + } e->sort_key|=uint64_t(e->geometry->index)<sort_key|=uint64_t(e->instance->base_type)<additive_ptr=&oe->additive; } } @@ -1261,106 +1284,10 @@ void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_g //e->light_type=0xFF; // no lights! - - - if (shadow || m->shader->spatial.unshaded /*|| current_debug==VS::SCENARIO_DEBUG_SHADELESS*/) { - e->sort_key|=RenderList::SORT_KEY_LIGHT_INDEX_UNSHADED; - e->sort_key|=uint64_t(0xF)<sort_key|=uint64_t(0xFFFF)<base->shadow_enabled) { - light_type|=0x8; - if (directional_lights[i]->base->directional_shadow_mode==VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) - light_type|=0x10; - else if (directional_lights[i]->base->directional_shadow_mode==VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) - light_type|=0x30; - - } -*/ - - RenderList::Element *ec; - if (duplicate) { - ec = render_list.add_element(); - copymem(ec,e,sizeof(RenderList::Element)); - } else { - - ec=e; - duplicate=true; - } - - ec->additive_ptr=&e->additive; - - ec->sort_key&=~RenderList::SORT_KEY_LIGHT_MASK; - ec->sort_key|=uint64_t(directional_light_instances[i]->light_index) << RenderList::SORT_KEY_LIGHT_INDEX_SHIFT; - ec->sort_key|=uint64_t(VS::LIGHT_DIRECTIONAL) << RenderList::SORT_KEY_LIGHT_TYPE_SHIFT; //this is zero byt whathever - - if (directional_light_instances[i]->light_ptr->shadow) { - //add proper flags for directional shadow mode - ec->sort_key|=uint64_t(directional_light_instances[i]->light_ptr->directional_shadow_mode+1) << (RenderList::SORT_KEY_LIGHT_TYPE_SHIFT+2); - } - - lit=true; - } - - - const RID *liptr = p_instance->light_instances.ptr(); - int ilc=p_instance->light_instances.size(); - - - - for(int i=0;ilast_pass!=render_pass) //lit by light not in visible scene - continue; - - -// if (li->base->shadow_enabled) { -// light_type|=0x8; -// } - - RenderList::Element *ec; - if (duplicate) { - - ec = render_list.add_element(); - copymem(ec,e,sizeof(RenderList::Element)); - } else { - - duplicate=true; - ec=e; - } - - ec->additive_ptr=&e->additive; - - ec->sort_key&=~RenderList::SORT_KEY_LIGHT_MASK; - ec->sort_key|=uint64_t(li->light_index) << RenderList::SORT_KEY_LIGHT_INDEX_SHIFT; - ec->sort_key|=uint64_t(li->light_ptr->type) << RenderList::SORT_KEY_LIGHT_TYPE_SHIFT; - - lit=true; - } - - - if (!lit) { - e->sort_key&=~RenderList::SORT_KEY_LIGHT_MASK; - e->sort_key|=uint64_t(0xE)<sort_key|=uint64_t(0xFFFF)<sort_key|=RenderList::SORT_KEY_UNSHADED_FLAG; } - - } void RasterizerSceneGLES3::_draw_skybox(RID p_skybox,const CameraMatrix& p_projection,const Transform& p_transform,bool p_vflip,float p_scale) { @@ -1534,161 +1461,202 @@ void RasterizerSceneGLES3::_setup_environment(Environment *env,const CameraMatri } -void RasterizerSceneGLES3::_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 RasterizerSceneGLES3::_setup_directional_light(int p_index,const Transform& p_camera_inverse_transform) { + LightInstance *li = directional_lights[p_index]; - ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas); + LightDataUBO ubo_data; //used for filling - directional_light_instance_count=0; - light_instance_count=0; + float sign = li->light_ptr->negative?-1:1; - for(int i=0;ilight_ptr->color.to_linear(); + ubo_data.light_color_energy[0]=linear_col.r*sign*li->light_ptr->param[VS::LIGHT_PARAM_ENERGY];; + ubo_data.light_color_energy[1]=linear_col.g*sign*li->light_ptr->param[VS::LIGHT_PARAM_ENERGY];; + ubo_data.light_color_energy[2]=linear_col.b*sign*li->light_ptr->param[VS::LIGHT_PARAM_ENERGY];; + ubo_data.light_color_energy[3]=0; - ERR_BREAK( i>=RenderList::MAX_LIGHTS ); + //omni, keep at 0 + ubo_data.light_pos_inv_radius[0]=0.0; + ubo_data.light_pos_inv_radius[1]=0.0; + ubo_data.light_pos_inv_radius[2]=0.0; + ubo_data.light_pos_inv_radius[3]=0.0; - LightInstance *li = light_instance_owner.getptr(p_light_cull_result[i]); + Vector3 direction = p_camera_inverse_transform.basis.xform(li->transform.basis.xform(Vector3(0,0,-1))).normalized(); + ubo_data.light_direction_attenuation[0]=direction.x; + ubo_data.light_direction_attenuation[1]=direction.y; + ubo_data.light_direction_attenuation[2]=direction.z; + ubo_data.light_direction_attenuation[3]=1.0; - switch(li->light_ptr->type) { + ubo_data.light_params[0]=0; + ubo_data.light_params[1]=li->light_ptr->param[VS::LIGHT_PARAM_SPECULAR]; + ubo_data.light_params[2]=0; + ubo_data.light_params[3]=0; - case VS::LIGHT_DIRECTIONAL: { + Color shadow_color = li->light_ptr->shadow_color.to_linear(); + ubo_data.light_shadow_color[0]=shadow_color.r; + ubo_data.light_shadow_color[1]=shadow_color.g; + ubo_data.light_shadow_color[2]=shadow_color.b; + ubo_data.light_shadow_color[3]=1.0; - ERR_FAIL_COND( directional_light_instance_count >= RenderList::MAX_LIGHTS); - directional_light_instances[directional_light_instance_count++]=li; - Color linear_col = li->light_ptr->color.to_linear(); - li->light_ubo_data.light_color_energy[0]=linear_col.r; - li->light_ubo_data.light_color_energy[1]=linear_col.g; - li->light_ubo_data.light_color_energy[2]=linear_col.b; - li->light_ubo_data.light_color_energy[3]=li->light_ptr->param[VS::LIGHT_PARAM_ENERGY]; + if (li->light_ptr->shadow) { - //omni, keep at 0 - li->light_ubo_data.light_pos_inv_radius[0]=0.0; - li->light_ubo_data.light_pos_inv_radius[1]=0.0; - li->light_ubo_data.light_pos_inv_radius[2]=0.0; - li->light_ubo_data.light_pos_inv_radius[3]=0.0; + int shadow_count=0; - Vector3 direction = p_camera_inverse_transform.basis.xform(li->transform.basis.xform(Vector3(0,0,-1))).normalized(); - li->light_ubo_data.light_direction_attenuation[0]=direction.x; - li->light_ubo_data.light_direction_attenuation[1]=direction.y; - li->light_ubo_data.light_direction_attenuation[2]=direction.z; - li->light_ubo_data.light_direction_attenuation[3]=1.0; + switch(li->light_ptr->directional_shadow_mode) { + case VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: { + shadow_count=1; + } break; + case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: { + shadow_count=2; + } break; + case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: { + shadow_count=4; + } break; - li->light_ubo_data.light_params[0]=0; - li->light_ubo_data.light_params[1]=li->light_ptr->param[VS::LIGHT_PARAM_SPECULAR]; - li->light_ubo_data.light_params[2]=0; - li->light_ubo_data.light_params[3]=0; + } - if (li->light_ptr->shadow) { + for(int j=0;jlight_ptr->directional_shadow_mode) { - case VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: { - shadow_count=1; - } break; - case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: { - shadow_count=2; - } break; - case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: { - shadow_count=4; - } break; + uint32_t x=li->directional_rect.pos.x; + uint32_t y=li->directional_rect.pos.y; + uint32_t width=li->directional_rect.size.x; + uint32_t height=li->directional_rect.size.y; - } - for(int j=0;jlight_ptr->directional_shadow_mode==VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) { - uint32_t x=li->directional_rect.pos.x; - uint32_t y=li->directional_rect.pos.y; - uint32_t width=li->directional_rect.size.x; - uint32_t height=li->directional_rect.size.y; + width/=2; + height/=2; + if (j==0) { - if (li->light_ptr->directional_shadow_mode==VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) { + } else if (j==1) { + x+=width; + } else if (j==2) { + y+=height; + } else if (j==3) { + x+=width; + y+=height; + } - width/=2; - height/=2; - if (j==0) { - } else if (j==1) { - x+=width; - } else if (j==2) { - y+=height; - } else if (j==3) { - x+=width; - y+=height; + } else if (li->light_ptr->directional_shadow_mode==VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) { - } + height/=2; + if (j==0) { + } else { + y+=height; + } - } else if (li->light_ptr->directional_shadow_mode==VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) { + } - height/=2; + ubo_data.shadow_split_offsets[j]=1.0/li->shadow_transform[j].split; - if (j==0) { + Transform modelview = (p_camera_inverse_transform * li->shadow_transform[j].transform).inverse(); - } else { - y+=height; - } + CameraMatrix bias; + bias.set_light_bias(); + CameraMatrix rectm; + Rect2 atlas_rect = Rect2(float(x)/directional_shadow.size,float(y)/directional_shadow.size,float(width)/directional_shadow.size,float(height)/directional_shadow.size); + rectm.set_light_atlas_rect(atlas_rect); - } +// print_line("atlas rect: "+atlas_rect); - li->light_ubo_data.shadow_split_offsets[j]=1.0/li->shadow_transform[j].split; + CameraMatrix shadow_mtx = rectm * bias * li->shadow_transform[j].camera * modelview; - Transform modelview = (p_camera_inverse_transform * li->shadow_transform[j].transform).inverse(); + store_camera(shadow_mtx,&ubo_data.shadow_matrix1[16*j]); - CameraMatrix bias; - bias.set_light_bias(); - CameraMatrix rectm; - Rect2 atlas_rect = Rect2(float(x)/directional_shadow.size,float(y)/directional_shadow.size,float(width)/directional_shadow.size,float(height)/directional_shadow.size); - rectm.set_light_atlas_rect(atlas_rect); + ubo_data.light_clamp[0]=atlas_rect.pos.x; + ubo_data.light_clamp[1]=atlas_rect.pos.y; + ubo_data.light_clamp[2]=atlas_rect.size.x; + ubo_data.light_clamp[3]=atlas_rect.size.y; -// print_line("atlas rect: "+atlas_rect); + } - CameraMatrix shadow_mtx = rectm * bias * li->shadow_transform[j].camera * modelview; + } - store_camera(shadow_mtx,&li->light_ubo_data.shadow_matrix1[16*j]); + glBindBuffer(GL_UNIFORM_BUFFER, state.directional_ubo); + glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(LightDataUBO), &ubo_data); + glBindBuffer(GL_UNIFORM_BUFFER, 0); - li->light_ubo_data.light_clamp[0]=atlas_rect.pos.x; - li->light_ubo_data.light_clamp[1]=atlas_rect.pos.y; - li->light_ubo_data.light_clamp[2]=atlas_rect.size.x; - li->light_ubo_data.light_clamp[3]=atlas_rect.size.y; + directional_light=li; - } + glBindBufferBase(GL_UNIFORM_BUFFER,3,state.directional_ubo); +} + +void RasterizerSceneGLES3::_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) { + + + state.omni_light_count=0; + state.spot_light_count=0; + state.directional_light_count=0; + + directional_light=NULL; + + ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas); + + + for(int i=0;i=RenderList::MAX_LIGHTS ); + + LightInstance *li = light_instance_owner.getptr(p_light_cull_result[i]); + + LightDataUBO ubo_data; //used for filling + + switch(li->light_ptr->type) { + + case VS::LIGHT_DIRECTIONAL: { + + if (state.directional_light_countlight_ptr->negative?-1:1; + Color linear_col = li->light_ptr->color.to_linear(); - li->light_ubo_data.light_color_energy[0]=linear_col.r; - li->light_ubo_data.light_color_energy[1]=linear_col.g; - li->light_ubo_data.light_color_energy[2]=linear_col.b; - li->light_ubo_data.light_color_energy[3]=li->light_ptr->param[VS::LIGHT_PARAM_ENERGY]; + ubo_data.light_color_energy[0]=linear_col.r*sign*li->light_ptr->param[VS::LIGHT_PARAM_ENERGY];; + ubo_data.light_color_energy[1]=linear_col.g*sign*li->light_ptr->param[VS::LIGHT_PARAM_ENERGY];; + ubo_data.light_color_energy[2]=linear_col.b*sign*li->light_ptr->param[VS::LIGHT_PARAM_ENERGY];; + ubo_data.light_color_energy[3]=0; + Vector3 pos = p_camera_inverse_transform.xform(li->transform.origin); //directional, keep at 0 - li->light_ubo_data.light_pos_inv_radius[0]=pos.x; - li->light_ubo_data.light_pos_inv_radius[1]=pos.y; - li->light_ubo_data.light_pos_inv_radius[2]=pos.z; - li->light_ubo_data.light_pos_inv_radius[3]=1.0/MAX(0.001,li->light_ptr->param[VS::LIGHT_PARAM_RANGE]); - - li->light_ubo_data.light_direction_attenuation[0]=0; - li->light_ubo_data.light_direction_attenuation[1]=0; - li->light_ubo_data.light_direction_attenuation[2]=0; - li->light_ubo_data.light_direction_attenuation[3]=li->light_ptr->param[VS::LIGHT_PARAM_ATTENUATION]; - - li->light_ubo_data.light_params[0]=0; - li->light_ubo_data.light_params[1]=0; - li->light_ubo_data.light_params[2]=li->light_ptr->param[VS::LIGHT_PARAM_SPECULAR]; - li->light_ubo_data.light_params[3]=0; - + ubo_data.light_pos_inv_radius[0]=pos.x; + ubo_data.light_pos_inv_radius[1]=pos.y; + ubo_data.light_pos_inv_radius[2]=pos.z; + ubo_data.light_pos_inv_radius[3]=1.0/MAX(0.001,li->light_ptr->param[VS::LIGHT_PARAM_RANGE]); + + ubo_data.light_direction_attenuation[0]=0; + ubo_data.light_direction_attenuation[1]=0; + ubo_data.light_direction_attenuation[2]=0; + ubo_data.light_direction_attenuation[3]=li->light_ptr->param[VS::LIGHT_PARAM_ATTENUATION]; + + ubo_data.light_params[0]=0; + ubo_data.light_params[1]=0; + ubo_data.light_params[2]=li->light_ptr->param[VS::LIGHT_PARAM_SPECULAR]; + ubo_data.light_params[3]=0; + + Color shadow_color = li->light_ptr->shadow_color.to_linear(); + ubo_data.light_shadow_color[0]=shadow_color.r; + ubo_data.light_shadow_color[1]=shadow_color.g; + ubo_data.light_shadow_color[2]=shadow_color.b; + ubo_data.light_shadow_color[3]=1.0; if (li->light_ptr->shadow && shadow_atlas && shadow_atlas->shadow_owners.has(li->self)) { // fill in the shadow information @@ -1724,17 +1692,21 @@ void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result,int p_light_cu Transform proj = (p_camera_inverse_transform * li->transform).inverse(); - store_transform(proj,li->light_ubo_data.shadow_matrix1); + store_transform(proj,ubo_data.shadow_matrix1); - li->light_ubo_data.light_params[3]=1.0; //means it has shadow - li->light_ubo_data.light_clamp[0]=float(x)/atlas_size; - li->light_ubo_data.light_clamp[1]=float(y)/atlas_size; - li->light_ubo_data.light_clamp[2]=float(width)/atlas_size; - li->light_ubo_data.light_clamp[3]=float(height)/atlas_size; + ubo_data.light_params[3]=1.0; //means it has shadow + ubo_data.light_clamp[0]=float(x)/atlas_size; + ubo_data.light_clamp[1]=float(y)/atlas_size; + ubo_data.light_clamp[2]=float(width)/atlas_size; + ubo_data.light_clamp[3]=float(height)/atlas_size; } + li->light_index=state.omni_light_count; + copymem(&state.omni_array_tmp[li->light_index*state.ubo_light_size],&ubo_data,state.ubo_light_size); + state.omni_light_count++; + #if 0 @@ -1746,30 +1718,38 @@ void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result,int p_light_cu } break; case VS::LIGHT_SPOT: { + float sign = li->light_ptr->negative?-1:1; + Color linear_col = li->light_ptr->color.to_linear(); - li->light_ubo_data.light_color_energy[0]=linear_col.r; - li->light_ubo_data.light_color_energy[1]=linear_col.g; - li->light_ubo_data.light_color_energy[2]=linear_col.b; - li->light_ubo_data.light_color_energy[3]=li->light_ptr->param[VS::LIGHT_PARAM_ENERGY]; + ubo_data.light_color_energy[0]=linear_col.r*sign*li->light_ptr->param[VS::LIGHT_PARAM_ENERGY];; + ubo_data.light_color_energy[1]=linear_col.g*sign*li->light_ptr->param[VS::LIGHT_PARAM_ENERGY];; + ubo_data.light_color_energy[2]=linear_col.b*sign*li->light_ptr->param[VS::LIGHT_PARAM_ENERGY];; + ubo_data.light_color_energy[3]=0; Vector3 pos = p_camera_inverse_transform.xform(li->transform.origin); //directional, keep at 0 - li->light_ubo_data.light_pos_inv_radius[0]=pos.x; - li->light_ubo_data.light_pos_inv_radius[1]=pos.y; - li->light_ubo_data.light_pos_inv_radius[2]=pos.z; - li->light_ubo_data.light_pos_inv_radius[3]=1.0/MAX(0.001,li->light_ptr->param[VS::LIGHT_PARAM_RANGE]); + ubo_data.light_pos_inv_radius[0]=pos.x; + ubo_data.light_pos_inv_radius[1]=pos.y; + ubo_data.light_pos_inv_radius[2]=pos.z; + ubo_data.light_pos_inv_radius[3]=1.0/MAX(0.001,li->light_ptr->param[VS::LIGHT_PARAM_RANGE]); Vector3 direction = p_camera_inverse_transform.basis.xform(li->transform.basis.xform(Vector3(0,0,-1))).normalized(); - li->light_ubo_data.light_direction_attenuation[0]=direction.x; - li->light_ubo_data.light_direction_attenuation[1]=direction.y; - li->light_ubo_data.light_direction_attenuation[2]=direction.z; - li->light_ubo_data.light_direction_attenuation[3]=li->light_ptr->param[VS::LIGHT_PARAM_ATTENUATION]; - - li->light_ubo_data.light_params[0]=li->light_ptr->param[VS::LIGHT_PARAM_SPOT_ATTENUATION]; - li->light_ubo_data.light_params[1]=Math::cos(Math::deg2rad(li->light_ptr->param[VS::LIGHT_PARAM_SPOT_ANGLE])); - li->light_ubo_data.light_params[2]=li->light_ptr->param[VS::LIGHT_PARAM_SPECULAR]; - li->light_ubo_data.light_params[3]=0; + ubo_data.light_direction_attenuation[0]=direction.x; + ubo_data.light_direction_attenuation[1]=direction.y; + ubo_data.light_direction_attenuation[2]=direction.z; + ubo_data.light_direction_attenuation[3]=li->light_ptr->param[VS::LIGHT_PARAM_ATTENUATION]; + + ubo_data.light_params[0]=li->light_ptr->param[VS::LIGHT_PARAM_SPOT_ATTENUATION]; + ubo_data.light_params[1]=Math::cos(Math::deg2rad(li->light_ptr->param[VS::LIGHT_PARAM_SPOT_ANGLE])); + ubo_data.light_params[2]=li->light_ptr->param[VS::LIGHT_PARAM_SPECULAR]; + ubo_data.light_params[3]=0; + + Color shadow_color = li->light_ptr->shadow_color.to_linear(); + ubo_data.light_shadow_color[0]=shadow_color.r; + ubo_data.light_shadow_color[1]=shadow_color.g; + ubo_data.light_shadow_color[2]=shadow_color.b; + ubo_data.light_shadow_color[3]=1.0; if (li->light_ptr->shadow && shadow_atlas && shadow_atlas->shadow_owners.has(li->self)) { // fill in the shadow information @@ -1796,11 +1776,11 @@ void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result,int p_light_cu Rect2 rect(float(x)/atlas_size,float(y)/atlas_size,float(width)/atlas_size,float(height)/atlas_size); - li->light_ubo_data.light_params[3]=1.0; //means it has shadow - li->light_ubo_data.light_clamp[0]=rect.pos.x; - li->light_ubo_data.light_clamp[1]=rect.pos.y; - li->light_ubo_data.light_clamp[2]=rect.size.x; - li->light_ubo_data.light_clamp[3]=rect.size.y; + ubo_data.light_params[3]=1.0; //means it has shadow + ubo_data.light_clamp[0]=rect.pos.x; + ubo_data.light_clamp[1]=rect.pos.y; + ubo_data.light_clamp[2]=rect.size.x; + ubo_data.light_clamp[3]=rect.size.y; Transform modelview = (p_camera_inverse_transform * li->transform).inverse(); @@ -1811,10 +1791,15 @@ void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result,int p_light_cu CameraMatrix shadow_mtx = rectm * bias * li->shadow_transform[0].camera * modelview; - store_camera(shadow_mtx,li->light_ubo_data.shadow_matrix1); + store_camera(shadow_mtx,ubo_data.shadow_matrix1); } + + li->light_index=state.spot_light_count; + copymem(&state.spot_array_tmp[li->light_index*state.ubo_light_size],&ubo_data,state.ubo_light_size); + state.spot_light_count++; + #if 0 if (li->light_ptr->shadow_enabled) { CameraMatrix bias; @@ -1829,24 +1814,34 @@ void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result,int p_light_cu } - /* make light hash */ + li->last_pass=render_pass; - // actually, not really a hash, but helps to sort the lights - // and avoid recompiling redudant shader versions + //update UBO for forward rendering, blit to texture for clustered + } - li->last_pass=render_pass; - li->light_index=i; - //update UBO for forward rendering, blit to texture for clustered - glBindBuffer(GL_UNIFORM_BUFFER, li->light_ubo); - glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(LightInstance::LightDataUBO), &li->light_ubo_data); + if (state.omni_light_count) { + + glBindBuffer(GL_UNIFORM_BUFFER, state.omni_array_ubo); + glBufferSubData(GL_UNIFORM_BUFFER, 0, state.omni_light_count*state.ubo_light_size, state.omni_array_tmp); glBindBuffer(GL_UNIFORM_BUFFER, 0); - light_instances[i]=li; - light_instance_count++; + glBindBufferBase(GL_UNIFORM_BUFFER,4,state.omni_array_ubo); } + + if (state.spot_light_count) { + + glBindBuffer(GL_UNIFORM_BUFFER, state.spot_array_ubo); + glBufferSubData(GL_UNIFORM_BUFFER, 0, state.spot_light_count*state.ubo_light_size, state.spot_array_tmp); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + + glBindBufferBase(GL_UNIFORM_BUFFER,5,state.spot_array_ubo); + } + + + } void RasterizerSceneGLES3::_copy_screen() { @@ -1969,6 +1964,7 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C //first of all, make a new render pass render_pass++; + //fill up ubo Environment *env = environment_owner.getornull(p_environment); @@ -2075,7 +2071,20 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } - _render_list(render_list.elements,render_list.element_count,p_cam_transform,p_cam_projection,env_radiance_tex,false,false,false); + if (state.directional_light_count==0) { + directional_light=NULL; + _render_list(render_list.elements,render_list.element_count,p_cam_transform,p_cam_projection,env_radiance_tex,false,false,false,false); + } else { + for(int i=0;i0) { + glEnable(GL_BLEND); + } + _setup_directional_light(i,p_cam_transform.affine_inverse()); + _render_list(render_list.elements,render_list.element_count,p_cam_transform,p_cam_projection,env_radiance_tex,false,false,false,i>0); + + } + } state.scene_shader.set_conditional(SceneShaderGLES3::USE_MULTIPLE_RENDER_TARGETS,false); @@ -2107,9 +2116,20 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C render_list.sort_by_depth(true); - _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,env_radiance_tex,false,true,false); + if (state.directional_light_count==0) { + directional_light=NULL; + _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,env_radiance_tex,false,true,false,false); + } else { + for(int i=0;i0); + + } + } + _copy_to_front_buffer(env); /* if (shadow_atlas) { @@ -2123,7 +2143,7 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C } */ - if (directional_shadow.fbo) { + if (false && directional_shadow.fbo) { //_copy_texture_to_front_buffer(shadow_atlas->depth); storage->canvas->canvas_begin(); @@ -2285,6 +2305,8 @@ void RasterizerSceneGLES3::render_shadow(RID p_light,RID p_shadow_atlas,int p_pa render_pass++; + directional_light=NULL; + LightInstance *light_instance = light_instance_owner.getornull(p_light); ERR_FAIL_COND(!light_instance); RasterizerStorageGLES3::Light *light = storage->light_owner.getornull(light_instance->light); @@ -2512,7 +2534,7 @@ void RasterizerSceneGLES3::render_shadow(RID p_light,RID p_shadow_atlas,int p_pa state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_SHADOW,true); - _render_list(render_list.elements,render_list.element_count,light_transform,light_projection,NULL,!flip_facing,false,true); + _render_list(render_list.elements,render_list.element_count,light_transform,light_projection,NULL,!flip_facing,false,true,false); state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_SHADOW,false); state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_SHADOW_DUAL_PARABOLOID,false); @@ -2593,7 +2615,6 @@ bool RasterizerSceneGLES3::free(RID p_rid) { } - glDeleteBuffers(1,&light_instance->light_ubo); light_instance_owner.free(p_rid); memdelete(light_instance); @@ -2860,6 +2881,53 @@ void RasterizerSceneGLES3::initialize() { ERR_PRINT("Directional shadow framebuffer status invalid"); } } + + { + //spot and omni ubos + + int max_ubo_size; + 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=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); + + + glGenBuffers(1, &state.spot_array_ubo); + glBindBuffer(GL_UNIFORM_BUFFER, state.spot_array_ubo); + glBufferData(GL_UNIFORM_BUFFER, ubo_light_size*state.max_ubo_lights, NULL, GL_DYNAMIC_DRAW); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + + glGenBuffers(1, &state.omni_array_ubo); + glBindBuffer(GL_UNIFORM_BUFFER, state.omni_array_ubo); + glBufferData(GL_UNIFORM_BUFFER, ubo_light_size*state.max_ubo_lights, NULL, GL_DYNAMIC_DRAW); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + + glGenBuffers(1, &state.directional_ubo); + glBindBuffer(GL_UNIFORM_BUFFER, state.directional_ubo); + glBufferData(GL_UNIFORM_BUFFER, sizeof(LightDataUBO), NULL, GL_DYNAMIC_DRAW); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + + state.max_forward_lights_per_object=8; + + 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"); + + + + } + + GLOBAL_DEF("rendering/gles3/shadow_filter_mode",1); + Globals::get_singleton()->set_custom_property_info("rendering/gles3/shadow_filter_mode",PropertyInfo(Variant::INT,"rendering/gles3/shadow_filter_mode",PROPERTY_HINT_ENUM,"Disabled,PCF5,PCF13")); + shadow_filter_mode=SHADOW_FILTER_NEAREST; + +} + +void RasterizerSceneGLES3::iteration() { + + shadow_filter_mode=ShadowFilterMode(int(Globals::get_singleton()->get("rendering/gles3/shadow_filter_mode"))); } void RasterizerSceneGLES3::finalize(){ diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index d7beebbcf6..24b6a36fcc 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -8,6 +8,15 @@ class RasterizerSceneGLES3 : public RasterizerScene { public: + enum ShadowFilterMode { + SHADOW_FILTER_NEAREST, + SHADOW_FILTER_PCF5, + SHADOW_FILTER_PCF13, + }; + + + ShadowFilterMode shadow_filter_mode; + uint64_t shadow_atlas_realloc_tolerance_msec; @@ -27,6 +36,7 @@ public: struct State { + bool texscreen_copied; int current_blend_mode; float current_line_width; @@ -73,6 +83,22 @@ public: GLuint skybox_verts; GLuint skybox_array; + GLuint directional_ubo; + + GLuint spot_array_ubo; + GLuint omni_array_ubo; + + uint32_t ubo_light_size; + uint8_t *spot_array_tmp; + uint8_t *omni_array_tmp; + + int max_ubo_lights; + int max_forward_lights_per_object; + + int spot_light_count; + int omni_light_count; + int directional_light_count; + bool cull_front; } state; @@ -204,6 +230,22 @@ public: /* LIGHT INSTANCE */ + struct LightDataUBO { + + float light_pos_inv_radius[4]; + float light_direction_attenuation[4]; + float light_color_energy[4]; + float light_params[4]; //spot attenuation, spot angle, specular, shadow enabled + float light_clamp[4]; + float light_shadow_color[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]; + float shadow_split_offsets[4]; + + }; + struct LightInstance : public RID_Data { struct ShadowTransform { @@ -214,20 +256,6 @@ public: float split; }; - struct LightDataUBO { - - float light_pos_inv_radius[4]; - float light_direction_attenuation[4]; - float light_color_energy[4]; - float light_params[4]; //cone attenuation, specular, shadow darkening, - float light_clamp[4]; //cone attenuation, specular, shadow darkening, - float shadow_split_offsets[4]; - float shadow_matrix1[16]; - float shadow_matrix2[16]; - float shadow_matrix3[16]; - float shadow_matrix4[16]; - - } light_ubo_data; ShadowTransform shadow_transform[4]; @@ -241,8 +269,6 @@ public: Vector3 spot_vector; float linear_att; - GLuint light_ubo; - uint64_t shadow_pass; uint64_t last_scene_pass; uint64_t last_scene_shadow_pass; @@ -280,14 +306,16 @@ public: SORT_FLAG_INSTANCING=2, MAX_DIRECTIONAL_LIGHTS=16, MAX_LIGHTS=4096, - SORT_KEY_DEPTH_LAYER_SHIFT=58, - SORT_KEY_LIGHT_TYPE_SHIFT=54, //type is most important - SORT_KEY_LIGHT_INDEX_SHIFT=38, //type is most important - SORT_KEY_LIGHT_INDEX_UNSHADED=uint64_t(0xF) << SORT_KEY_LIGHT_TYPE_SHIFT, //type is most important - SORT_KEY_LIGHT_MASK=(uint64_t(0xFFFFF) << SORT_KEY_LIGHT_INDEX_SHIFT), //type is most important - SORT_KEY_MATERIAL_INDEX_SHIFT=22, - SORT_KEY_GEOMETRY_INDEX_SHIFT=6, - SORT_KEY_GEOMETRY_TYPE_SHIFT=2, + + + SORT_KEY_DEPTH_LAYER_SHIFT=60, + SORT_KEY_UNSHADED_FLAG=uint64_t(1)<<59, + SORT_KEY_NO_DIRECTIONAL_FLAG=uint64_t(1)<<58, + SORT_KEY_SHADING_SHIFT=58, + SORT_KEY_SHADING_MASK=3, + SORT_KEY_MATERIAL_INDEX_SHIFT=40, + SORT_KEY_GEOMETRY_INDEX_SHIFT=20, + SORT_KEY_GEOMETRY_TYPE_SHIFT=15, SORT_KEY_SKELETON_FLAG=2, SORT_KEY_MIRROR_FLAG=1 @@ -302,8 +330,6 @@ public: RasterizerStorageGLES3::Material *material; RasterizerStorageGLES3::GeometryOwner *owner; uint64_t sort_key; - bool *additive_ptr; - bool additive; }; @@ -314,6 +340,7 @@ public: int element_count; int alpha_element_count; + void clear() { element_count=0; @@ -399,12 +426,10 @@ public: }; + LightInstance *directional_light; + LightInstance *directional_lights[RenderList::MAX_DIRECTIONAL_LIGHTS]; - LightInstance *directional_light_instances[RenderList::MAX_DIRECTIONAL_LIGHTS]; - int directional_light_instance_count; - LightInstance *light_instances[RenderList::MAX_LIGHTS]; - int light_instance_count; RenderList render_list; @@ -414,9 +439,9 @@ public: _FORCE_INLINE_ void _setup_transform(InstanceBase *p_instance,const Transform& p_view_transform,const CameraMatrix& p_projection); _FORCE_INLINE_ void _setup_geometry(RenderList::Element *e); _FORCE_INLINE_ void _render_geometry(RenderList::Element *e); - _FORCE_INLINE_ void _setup_light(LightInstance *p_light); + _FORCE_INLINE_ void _setup_light(RenderList::Element *e); - void _render_list(RenderList::Element **p_elements, int p_element_count, const Transform& p_view_transform, const CameraMatrix& p_projection, RasterizerStorageGLES3::Texture *p_base_env, bool p_reverse_cull, bool p_alpha_pass, bool p_shadow); + void _render_list(RenderList::Element **p_elements, int p_element_count, const Transform& p_view_transform, const CameraMatrix& p_projection, RasterizerStorageGLES3::Texture *p_base_env, bool p_reverse_cull, bool p_alpha_pass, bool p_shadow, bool p_directional_add); _FORCE_INLINE_ void _add_geometry( RasterizerStorageGLES3::Geometry* p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner,int p_material,bool p_shadow); @@ -424,6 +449,7 @@ public: void _draw_skybox(RID p_skybox, const CameraMatrix& p_projection, const Transform& p_transform, bool p_vflip, float p_scale); void _setup_environment(Environment *env, const CameraMatrix &p_cam_projection, const Transform& p_cam_transform); + void _setup_directional_light(int p_index, const Transform &p_camera_inverse_transform); 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 _copy_screen(); void _copy_to_front_buffer(Environment *env); @@ -439,6 +465,7 @@ public: virtual void set_scene_pass(uint64_t p_pass); + void iteration(); void initialize(); void finalize(); RasterizerSceneGLES3(); diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index b988781e14..6e278e563b 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -3169,7 +3169,6 @@ RID RasterizerStorageGLES3::light_create(VS::LightType p_type){ light->param[VS::LIGHT_PARAM_RANGE]=1.0; light->param[VS::LIGHT_PARAM_SPOT_ANGLE]=45; light->param[VS::LIGHT_PARAM_SHADOW_MAX_DISTANCE]=0; - light->param[VS::LIGHT_PARAM_SHADOW_DARKNESS]=0; light->param[VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET]=0.1; light->param[VS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET]=0.3; light->param[VS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET]=0.6; @@ -3184,6 +3183,7 @@ RID RasterizerStorageGLES3::light_create(VS::LightType p_type){ light->directional_shadow_mode=VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; light->omni_shadow_mode=VS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID; light->omni_shadow_detail=VS::LIGHT_OMNI_SHADOW_DETAIL_VERTICAL; + light->directional_blend_splits=false; light->version=0; @@ -3207,7 +3207,6 @@ void RasterizerStorageGLES3::light_set_param(RID p_light,VS::LightParam p_param, case VS::LIGHT_PARAM_RANGE: case VS::LIGHT_PARAM_SPOT_ANGLE: case VS::LIGHT_PARAM_SHADOW_MAX_DISTANCE: - case VS::LIGHT_PARAM_SHADOW_DARKNESS: case VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET: case VS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET: case VS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET: @@ -3230,20 +3229,22 @@ void RasterizerStorageGLES3::light_set_shadow(RID p_light,bool p_enabled){ light->version++; light->instance_change_notify(); - - } -void RasterizerStorageGLES3::light_set_projector(RID p_light,RID p_texture){ + +void RasterizerStorageGLES3::light_set_shadow_color(RID p_light,const Color& p_color) { Light * light = light_owner.getornull(p_light); ERR_FAIL_COND(!light); - + light->shadow_color=p_color; } -void RasterizerStorageGLES3::light_set_attenuation_texure(RID p_light,RID p_texture){ + +void RasterizerStorageGLES3::light_set_projector(RID p_light,RID p_texture){ Light * light = light_owner.getornull(p_light); ERR_FAIL_COND(!light); + + light->projector=p_texture; } void RasterizerStorageGLES3::light_set_negative(RID p_light,bool p_enable){ @@ -3263,12 +3264,6 @@ void RasterizerStorageGLES3::light_set_cull_mask(RID p_light,uint32_t p_mask){ light->version++; light->instance_change_notify(); -} -void RasterizerStorageGLES3::light_set_shader(RID p_light,RID p_shader){ - - Light * light = light_owner.getornull(p_light); - ERR_FAIL_COND(!light); - } void RasterizerStorageGLES3::light_omni_set_shadow_mode(RID p_light,VS::LightOmniShadowMode p_mode) { @@ -3315,6 +3310,26 @@ void RasterizerStorageGLES3::light_directional_set_shadow_mode(RID p_light,VS::L } +void RasterizerStorageGLES3::light_directional_set_blend_splits(RID p_light,bool p_enable) { + + Light * light = light_owner.getornull(p_light); + ERR_FAIL_COND(!light); + + light->directional_blend_splits=p_enable; + light->version++; + light->instance_change_notify(); + +} + + +bool RasterizerStorageGLES3::light_directional_get_blend_splits(RID p_light) const { + + const Light * light = light_owner.getornull(p_light); + ERR_FAIL_COND_V(!light,false); + + return light->directional_blend_splits; +} + VS::LightDirectionalShadowMode RasterizerStorageGLES3::light_directional_get_shadow_mode(RID p_light) { const Light * light = light_owner.getornull(p_light); diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index f8b34d6a16..0e3d47b61f 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -634,12 +634,15 @@ public: VS::LightType type; float param[VS::LIGHT_PARAM_MAX]; Color color; + Color shadow_color; + RID projector; bool shadow; bool negative; uint32_t cull_mask; VS::LightOmniShadowMode omni_shadow_mode; VS::LightOmniShadowDetail omni_shadow_detail; VS::LightDirectionalShadowMode directional_shadow_mode; + bool directional_blend_splits; uint64_t version; }; @@ -650,17 +653,19 @@ public: virtual void light_set_color(RID p_light,const Color& p_color); virtual void light_set_param(RID p_light,VS::LightParam p_param,float p_value); virtual void light_set_shadow(RID p_light,bool p_enabled); + virtual void light_set_shadow_color(RID p_light,const Color& p_color); virtual void light_set_projector(RID p_light,RID p_texture); - virtual void light_set_attenuation_texure(RID p_light,RID p_texture); 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_shader(RID p_light,RID p_shader); - virtual void light_omni_set_shadow_mode(RID p_light,VS::LightOmniShadowMode p_mode); + 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); virtual void light_directional_set_shadow_mode(RID p_light,VS::LightDirectionalShadowMode p_mode); + virtual void light_directional_set_blend_splits(RID p_light,bool p_enable); + virtual bool light_directional_get_blend_splits(RID p_light) const; + virtual VS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light); virtual VS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light); diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp index 052c915241..6f0616035a 100644 --- a/drivers/gles3/shader_gles3.cpp +++ b/drivers/gles3/shader_gles3.cpp @@ -228,8 +228,15 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() { #endif + int define_line_ofs=1; + for(int i=0;i custom_defines; + int base_material_tex_index; Version * get_current_version(); @@ -357,6 +359,10 @@ public: void set_base_material_tex_index(int p_idx); + void add_custom_define(const String& p_define) { + custom_defines.push_back(p_define.utf8()); + } + virtual ~ShaderGLES3(); }; diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index de1591e8ff..ceb5a72118 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -68,24 +68,26 @@ layout(std140) uniform SceneData { //ubo:0 uniform highp mat4 world_transform; -#ifdef USE_FORWARD_LIGHTING +#ifdef USE_LIGHT_DIRECTIONAL -layout(std140) uniform LightData { //ubo:3 +layout(std140) uniform DirectionalLightData { //ubo:3 highp vec4 light_pos_inv_radius; mediump vec4 light_direction_attenuation; mediump vec4 light_color_energy; - mediump vec4 light_params; //cone attenuation, specular, shadow darkening, + mediump vec4 light_params; //cone attenuation, angle, specular, shadow enabled, mediump vec4 light_clamp; - mediump vec4 shadow_split_offsets; + mediump vec4 shadow_color; highp mat4 shadow_matrix1; highp mat4 shadow_matrix2; highp mat4 shadow_matrix3; highp mat4 shadow_matrix4; + mediump vec4 shadow_split_offsets; }; #endif + /* Varyings */ out highp vec3 vertex_interp; @@ -343,30 +345,71 @@ layout(std140) uniform SceneData { }; +//directional light data -#ifdef USE_FORWARD_LIGHTING +#ifdef USE_LIGHT_DIRECTIONAL -layout(std140) uniform LightData { +layout(std140) uniform DirectionalLightData { highp vec4 light_pos_inv_radius; mediump vec4 light_direction_attenuation; mediump vec4 light_color_energy; - mediump vec4 light_params; //cone attenuation, specular, shadow darkening, shadow enabled + mediump vec4 light_params; //cone attenuation, angle, specular, shadow enabled, mediump vec4 light_clamp; - mediump vec4 shadow_split_offsets; + mediump vec4 shadow_color; highp mat4 shadow_matrix1; highp mat4 shadow_matrix2; highp mat4 shadow_matrix3; highp mat4 shadow_matrix4; + mediump vec4 shadow_split_offsets; }; + +uniform highp sampler2DShadow directional_shadow; //texunit:-4 + #endif +//omni and spot + +struct LightData { + + highp vec4 light_pos_inv_radius; + mediump vec4 light_direction_attenuation; + mediump vec4 light_color_energy; + mediump vec4 light_params; //cone attenuation, angle, specular, shadow enabled, + mediump vec4 light_clamp; + mediump vec4 shadow_color; + highp mat4 shadow_matrix; + +}; + + +layout(std140) uniform OmniLightData { //ubo:4 + + LightData omni_lights[MAX_LIGHT_DATA_STRUCTS]; +}; + +layout(std140) uniform SpotLightData { //ubo:5 + + LightData spot_lights[MAX_LIGHT_DATA_STRUCTS]; +}; + -uniform highp sampler2DShadow directional_shadow; //texunit:-4 uniform highp sampler2DShadow shadow_atlas; //texunit:-3 +#ifdef USE_FORWARD_LIGHTING + +uniform int omni_light_indices[MAX_FORWARD_LIGHTS]; +uniform int omni_light_count; + +uniform int spot_light_indices[MAX_FORWARD_LIGHTS]; +uniform int spot_light_count; + +#endif + + + #ifdef USE_MULTIPLE_RENDER_TARGETS layout(location=0) out vec4 diffuse_buffer; @@ -415,18 +458,51 @@ float specularGGX(vec3 N, vec3 V, vec3 L, float roughness, float F0) return dotNL * D * F * vis; } -void light_compute(vec3 normal, vec3 light_vec,vec3 eye_vec,vec3 diffuse_color, vec3 specular_color, float roughness, float attenuation, inout vec3 diffuse, inout vec3 specular) { +void light_compute(vec3 normal, vec3 light_vec,vec3 eye_vec,vec3 light_color,vec3 diffuse_color, vec3 specular_color, float roughness, inout vec3 diffuse, inout vec3 specular) { - diffuse += max(0.0,dot(normal,light_vec)) * diffuse_color * attenuation; + diffuse += max(0.0,dot(normal,light_vec)) * light_color * diffuse_color; //specular += specular_ggx( roughness, max(0.0,dot(normal,eye_vec)) ) * specular_color * attenuation; float s = roughness > 0.0 ? specularGGX(normal,eye_vec,light_vec,roughness,1.0) : 0.0; - specular += s * specular_color * attenuation; + specular += s * light_color * specular_color; } float sample_shadow(highp sampler2DShadow shadow, vec2 shadow_pixel_size, vec2 pos, float depth, vec4 clamp_rect) { +#ifdef SHADOW_MODE_PCF_13 + + float avg=textureProj(shadow,vec4(pos,depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(shadow_pixel_size.x,0.0),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(-shadow_pixel_size.x,0.0),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(0.0,shadow_pixel_size.y),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(0.0,-shadow_pixel_size.y),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(shadow_pixel_size.x,shadow_pixel_size.y),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(-shadow_pixel_size.x,shadow_pixel_size.y),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(shadow_pixel_size.x,-shadow_pixel_size.y),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(-shadow_pixel_size.x,-shadow_pixel_size.y),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(shadow_pixel_size.x*2.0,0.0),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(-shadow_pixel_size.x*2.0,0.0),depth,1.0)); + 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 + +#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)); + avg+=textureProj(shadow,vec4(pos+vec2(-shadow_pixel_size.x,0.0),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(0.0,shadow_pixel_size.y),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(0.0,-shadow_pixel_size.y),depth,1.0)); + return avg*(1.0/5.0); +#endif + +#if !defined(SHADOW_MODE_PCF_5) && !defined(SHADOW_MODE_PCF_13) + return textureProj(shadow,vec4(pos,depth,1.0)); +#endif + } #ifdef RENDER_SHADOW_DUAL_PARABOLOID @@ -435,6 +511,73 @@ in highp float dp_clip; #endif +void light_process_omni(int idx, vec3 vertex, vec3 eye_vec,vec3 normal,vec3 albedo, vec3 specular, float roughness, inout vec3 diffuse_light, inout vec3 specular_light) { + + vec3 light_rel_vec = omni_lights[idx].light_pos_inv_radius.xyz-vertex; + float normalized_distance = length( light_rel_vec )*omni_lights[idx].light_pos_inv_radius.w; + vec3 light_attenuation = vec3(pow( max(1.0 - normalized_distance, 0.0), omni_lights[idx].light_direction_attenuation.w )); + + if (omni_lights[idx].light_params.w>0.5) { + //there is a shadowmap + + highp vec3 splane=(omni_lights[idx].shadow_matrix * vec4(vertex,1.0)).xyz; + float shadow_len=length(splane); + splane=normalize(splane); + vec4 clamp_rect=omni_lights[idx].light_clamp; + + if (splane.z>=0.0) { + + splane.z+=1.0; + + clamp_rect.y+=clamp_rect.w; + + } else { + + splane.z=1.0 - splane.z; + + //if (clamp_rect.z0.5) { + //there is a shadowmap + highp vec4 splane=(spot_lights[idx].shadow_matrix * vec4(vertex,1.0)); + splane.xyz/=splane.w; + light_attenuation*=mix(spot_lights[idx].shadow_color.rgb,vec3(1.0),sample_shadow(shadow_atlas,shadow_atlas_pixel_size,splane.xy,splane.z,spot_lights[idx].light_clamp)); + } + + light_compute(normal,normalize(light_rel_vec),eye_vec,spot_lights[idx].light_color_energy.rgb*light_attenuation,albedo,specular,roughness,diffuse_light,specular_light); + +} + void main() { #ifdef RENDER_SHADOW_DUAL_PARABOLOID @@ -561,9 +704,9 @@ FRAGMENT_SHADER_CODE #endif -#ifdef USE_FORWARD_DIRECTIONAL +#ifdef USE_LIGHT_DIRECTIONAL - float light_attenuation=1.0; + vec3 light_attenuation=vec3(1.0); #ifdef LIGHT_DIRECTIONAL_SHADOW @@ -589,7 +732,6 @@ FRAGMENT_SHADER_CODE highp vec4 splane=(shadow_matrix1 * vec4(vertex,1.0)); pssm_coord=splane.xyz/splane.w; - ambient_light=vec3(1.0,0.4,0.4); #if defined(LIGHT_USE_PSSM_BLEND) @@ -603,7 +745,6 @@ FRAGMENT_SHADER_CODE highp vec4 splane=(shadow_matrix2 * vec4(vertex,1.0)); pssm_coord=splane.xyz/splane.w; - ambient_light=vec3(0.4,1.0,0.4); #if defined(LIGHT_USE_PSSM_BLEND) splane=(shadow_matrix3 * vec4(vertex,1.0)); @@ -619,7 +760,6 @@ FRAGMENT_SHADER_CODE highp vec4 splane=(shadow_matrix3 * vec4(vertex,1.0)); pssm_coord=splane.xyz/splane.w; - ambient_light=vec3(0.4,0.4,1.0); #if defined(LIGHT_USE_PSSM_BLEND) splane=(shadow_matrix4 * vec4(vertex,1.0)); @@ -678,12 +818,12 @@ FRAGMENT_SHADER_CODE //one one sample - light_attenuation=sample_shadow(directional_shadow,directional_shadow_pixel_size,pssm_coord.xy,pssm_coord.z,light_clamp); + light_attenuation=mix(shadow_color.rgb,vec3(1.0),sample_shadow(directional_shadow,directional_shadow_pixel_size,pssm_coord.xy,pssm_coord.z,light_clamp)); #if defined(LIGHT_USE_PSSM_BLEND) if (use_blend) { - float light_attenuation2=sample_shadow(directional_shadow,directional_shadow_pixel_size,pssm_coord2.xy,pssm_coord2.z,light_clamp); + vec3 light_attenuation2=mix(shadow_color.rgb,vec3(1.0),sample_shadow(directional_shadow,directional_shadow_pixel_size,pssm_coord2.xy,pssm_coord2.z,light_clamp)); light_attenuation=mix(light_attenuation,light_attenuation2,pssm_blend); } #endif @@ -692,84 +832,24 @@ FRAGMENT_SHADER_CODE #endif //LIGHT_DIRECTIONAL_SHADOW - light_compute(normal,-light_direction_attenuation.xyz,eye_vec,albedo,specular,roughness,light_attenuation,diffuse_light,specular_light); - - -#endif //USE_FORWARD_DIRECTIONAL - + light_compute(normal,-light_direction_attenuation.xyz,eye_vec,light_color_energy.rgb*light_attenuation,albedo,specular,roughness,diffuse_light,specular_light); -#ifdef USE_FORWARD_OMNI - vec3 light_rel_vec = light_pos_inv_radius.xyz-vertex; - float normalized_distance = length( light_rel_vec )*light_pos_inv_radius.w; - float light_attenuation = pow( max(1.0 - normalized_distance, 0.0), light_direction_attenuation.w ); +#endif //#USE_LIGHT_DIRECTIONAL - if (light_params.w>0.5) { - //there is a shadowmap - - highp vec3 splane=(shadow_matrix1 * vec4(vertex,1.0)).xyz; - float shadow_len=length(splane); - splane=normalize(splane); - vec4 clamp_rect=light_clamp; - - if (splane.z>=0.0) { - - splane.z+=1.0; - clamp_rect.y+=clamp_rect.w; - - } else { - - splane.z=1.0 - splane.z; - - //if (clamp_rect.z0.5) { - //there is a shadowmap - - highp vec4 splane=(shadow_matrix1 * vec4(vertex,1.0)); - splane.xyz/=splane.w; - // splane.xy=splane.xy*0.5+0.5; - - //splane.xy=light_clamp.xy+splane.xy*light_clamp.zw; - light_attenuation*=sample_shadow(shadow_atlas,shadow_atlas_pixel_size,splane.xy,splane.z,light_clamp); - + for(int i=0;i Date: Sat, 19 Nov 2016 13:23:37 -0300 Subject: working reflection probes!! --- drivers/gles3/rasterizer_canvas_gles3.cpp | 4 - drivers/gles3/rasterizer_gles3.cpp | 2 + drivers/gles3/rasterizer_scene_gles3.cpp | 730 ++++++++++++++++++++++++++--- drivers/gles3/rasterizer_scene_gles3.h | 103 +++- drivers/gles3/rasterizer_storage_gles3.cpp | 333 ++++++++++++- drivers/gles3/rasterizer_storage_gles3.h | 57 ++- drivers/gles3/shaders/cubemap_filter.glsl | 40 +- drivers/gles3/shaders/scene.glsl | 206 +++++++- 8 files changed, 1376 insertions(+), 99 deletions(-) (limited to 'drivers/gles3') diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index c455d4bd11..4573f94d22 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -1382,10 +1382,6 @@ void RasterizerCanvasGLES3::reset_canvas() { glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); glDisable(GL_SCISSOR_TEST); -#ifdef GLEW_ENABLED - glDisable(GL_POINT_SPRITE); - glDisable(GL_VERTEX_PROGRAM_POINT_SIZE); -#endif glEnable(GL_BLEND); glBlendEquation(GL_FUNC_ADD); if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index c799cd12af..dabb7918a9 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -122,11 +122,13 @@ void RasterizerGLES3::begin_frame(){ storage->frame.time[1]=Math::fmod(time_total,3600); storage->frame.time[2]=Math::fmod(time_total,900); storage->frame.time[3]=Math::fmod(time_total,60); + storage->frame.count++; storage->update_dirty_shaders(); storage->update_dirty_materials(); scene->iteration(); + } void RasterizerGLES3::set_current_render_target(RID p_render_target){ diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 4ae257abc4..e04908ea67 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -446,6 +446,338 @@ int RasterizerSceneGLES3::get_directional_light_shadow_size(RID p_light_intance) return shadow_size; } +////////////////////////////////////////////////////// + +RID RasterizerSceneGLES3::reflection_atlas_create() { + + ReflectionAtlas *reflection_atlas = memnew( ReflectionAtlas ); + reflection_atlas->subdiv=0; + reflection_atlas->color=0; + for(int i=0;i<6;i++) { + reflection_atlas->fbo[i]=0; + } + + return reflection_atlas_owner.make_rid(reflection_atlas); +} + +void RasterizerSceneGLES3::reflection_atlas_set_size(RID p_ref_atlas,int p_size) { + + ReflectionAtlas *reflection_atlas = reflection_atlas_owner.getornull(p_ref_atlas); + ERR_FAIL_COND(!reflection_atlas); + + int size = nearest_power_of_2(p_size); + + if (size==reflection_atlas->size) + return; + if (reflection_atlas->size) { + for(int i=0;i<6;i++) { + glDeleteFramebuffers(1,&reflection_atlas->fbo[i]); + reflection_atlas->fbo[i]=0; + } + glDeleteTextures(1,&reflection_atlas->color); + reflection_atlas->color=0; + } + + reflection_atlas->size=size; + + for(int i=0;ireflections.size();i++) { + //erase probes reference to this + if (reflection_atlas->reflections[i].owner.is_valid()) { + ReflectionProbeInstance *reflection_probe_instance = reflection_probe_instance_owner.getornull(reflection_atlas->reflections[i].owner); + reflection_atlas->reflections[i].owner=RID(); + + ERR_CONTINUE(!reflection_probe_instance); + reflection_probe_instance->reflection_atlas_index=-1; + reflection_probe_instance->atlas=RID(); + reflection_probe_instance->render_step=-1; + } + } + + + if (reflection_atlas->size) { + + bool use_float=true; + + + GLenum internal_format = use_float?GL_RGBA16F:GL_RGB10_A2; + GLenum format = GL_RGBA; + GLenum type = use_float?GL_HALF_FLOAT:GL_UNSIGNED_INT_2_10_10_10_REV; + + + // Create a texture for storing the color + glActiveTexture(GL_TEXTURE0); + glGenTextures(1, &reflection_atlas->color); + glBindTexture(GL_TEXTURE_2D, reflection_atlas->color); + + int mmsize=reflection_atlas->size; + + for(int i=0;i<6;i++) { + glTexImage2D(GL_TEXTURE_2D, i, internal_format, mmsize, mmsize, 0, + format, type, NULL); + + mmsize>>=1; + } + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + mmsize=reflection_atlas->size; + + for(int i=0;i<6;i++) { + glGenFramebuffers(1, &reflection_atlas->fbo[i]); + glBindFramebuffer(GL_FRAMEBUFFER, reflection_atlas->fbo[i]); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, reflection_atlas->color, i); + glDisable(GL_SCISSOR_TEST); + glViewport(0,0,mmsize,mmsize); + glClearColor(0,0,0,0); + glClear(GL_COLOR_BUFFER_BIT); //it needs to be cleared, to avoid generating garbage + + mmsize>>=1; + + } + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 5); + + } + + + +} +void RasterizerSceneGLES3::reflection_atlas_set_subdivision(RID p_ref_atlas,int p_subdiv) { + + ReflectionAtlas *reflection_atlas = reflection_atlas_owner.getornull(p_ref_atlas); + ERR_FAIL_COND(!reflection_atlas); + + uint32_t subdiv = nearest_power_of_2(p_subdiv); + if (subdiv&0xaaaaaaaa) { //sqrt(subdiv) must be integer + subdiv<<=1; + } + + subdiv=int(Math::sqrt(subdiv)); + + if (reflection_atlas->subdiv==subdiv) + return; + + + if (subdiv) { + + for(int i=0;ireflections.size();i++) { + //erase probes reference to this + if (reflection_atlas->reflections[i].owner.is_valid()) { + ReflectionProbeInstance *reflection_probe_instance = reflection_probe_instance_owner.getornull(reflection_atlas->reflections[i].owner); + reflection_atlas->reflections[i].owner=RID(); + + ERR_CONTINUE(!reflection_probe_instance); + reflection_probe_instance->reflection_atlas_index=-1; + reflection_probe_instance->atlas=RID(); + reflection_probe_instance->render_step=-1; + } + } + } + + reflection_atlas->subdiv=subdiv; + + reflection_atlas->reflections.resize(subdiv*subdiv); +} + + +//////////////////////////////////////////////////// + +RID RasterizerSceneGLES3::reflection_probe_instance_create(RID p_probe) { + + RasterizerStorageGLES3::ReflectionProbe *probe = storage->reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND_V(!probe,RID()); + + ReflectionProbeInstance *rpi = memnew( ReflectionProbeInstance ); + + rpi->probe_ptr=probe; + rpi->self=reflection_probe_instance_owner.make_rid(rpi); + rpi->probe=p_probe; + rpi->reflection_atlas_index=-1; + rpi->render_step=-1; + rpi->last_pass=0; + + return rpi->self; +} + +void RasterizerSceneGLES3::reflection_probe_instance_set_transform(RID p_instance,const Transform& p_transform) { + + ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); + ERR_FAIL_COND(!rpi); + rpi->transform=p_transform; + +} + +void RasterizerSceneGLES3::reflection_probe_release_atlas_index(RID p_instance) { + + ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); + ERR_FAIL_COND(!rpi); + if (rpi->reflection_atlas_index==-1) + return; + + ReflectionAtlas *reflection_atlas = reflection_atlas_owner.getornull(rpi->atlas); + ERR_FAIL_COND(!reflection_atlas); + + ERR_FAIL_INDEX(rpi->reflection_atlas_index,reflection_atlas->reflections.size()); + + ERR_FAIL_COND(reflection_atlas->reflections[rpi->reflection_atlas_index].owner!=rpi->self); + + reflection_atlas->reflections[rpi->reflection_atlas_index].owner=RID(); + + rpi->reflection_atlas_index=-1; + rpi->atlas=RID(); + rpi->render_step=-1; + +} + +bool RasterizerSceneGLES3::reflection_probe_instance_needs_redraw(RID p_instance) { + + ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); + ERR_FAIL_COND_V(!rpi,false); + + return rpi->reflection_atlas_index==-1 || rpi->probe_ptr->update_mode==VS::REFLECTION_PROBE_UPDATE_ALWAYS; +} + +bool RasterizerSceneGLES3::reflection_probe_instance_has_reflection(RID p_instance){ + + ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); + ERR_FAIL_COND_V(!rpi,false); + + return rpi->reflection_atlas_index!=-1; +} + +bool RasterizerSceneGLES3::reflection_probe_instance_begin_render(RID p_instance,RID p_reflection_atlas) { + + ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); + ERR_FAIL_COND_V(!rpi,false); + + rpi->render_step=0; + + if (rpi->reflection_atlas_index!=-1) { + return true; //got one already + } + + ReflectionAtlas *reflection_atlas = reflection_atlas_owner.getornull(p_reflection_atlas); + ERR_FAIL_COND_V(!reflection_atlas,false); + + + if (reflection_atlas->size==0 || reflection_atlas->subdiv==0) { + return false; + } + + + int best_free=-1; + int best_used=-1; + uint64_t best_used_frame; + + for(int i=0;ireflections.size();i++) { + if (reflection_atlas->reflections[i].owner==RID()) { + best_free=i; + break; + } + + if (rpi->render_step<0 && reflection_atlas->reflections[i].last_frameframe.count && + (best_used==-1 || reflection_atlas->reflections[i].last_framereflections[i].last_frame; + } + } + + if (best_free==-1 && best_used==-1) { + return false ;// sorry, can not do. Try again next frame. + } + + if (best_free==-1) { + //find best from what is used + best_free=best_used; + + ReflectionProbeInstance *victim_rpi = reflection_probe_instance_owner.getornull(reflection_atlas->reflections[best_free].owner); + ERR_FAIL_COND_V(!victim_rpi,false); + victim_rpi->atlas=RID(); + victim_rpi->reflection_atlas_index=-1; + + } + + reflection_atlas->reflections[best_free].owner=p_instance; + reflection_atlas->reflections[best_free].last_frame=storage->frame.count; + + rpi->reflection_atlas_index=best_free; + rpi->atlas=p_reflection_atlas; + rpi->render_step=0; + + return true; +} + +bool RasterizerSceneGLES3::reflection_probe_instance_postprocess_step(RID p_instance) { + + ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); + ERR_FAIL_COND_V(!rpi,true); + + ReflectionAtlas *reflection_atlas = reflection_atlas_owner.getornull(rpi->atlas); + ERR_FAIL_COND_V(!reflection_atlas,false); + + ERR_FAIL_COND_V(rpi->render_step>=6,true); + + glBindFramebuffer(GL_FRAMEBUFFER,reflection_atlas->fbo[rpi->render_step]); + state.cube_to_dp_shader.bind(); + + int target_size=reflection_atlas->size/reflection_atlas->subdiv; + + int cubemap_index=reflection_cubemaps.size()-1; + + for(int i=reflection_cubemaps.size()-1;i>=0;i--) { + //find appropriate cubemap to render to + if (reflection_cubemaps[i].size>target_size*2) + break; + + cubemap_index=i; + } + + glDisable(GL_BLEND); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_CUBE_MAP,reflection_cubemaps[cubemap_index].cubemap); + glDisable(GL_CULL_FACE); + + storage->shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DUAL_PARABOLOID,true); + storage->shaders.cubemap_filter.bind(); + + int cell_size = reflection_atlas->size / reflection_atlas->subdiv; + for(int i=0;irender_step;i++) { + cell_size>>=1; //mipmaps! + } + int x = (rpi->reflection_atlas_index % reflection_atlas->subdiv) * cell_size; + int y = (rpi->reflection_atlas_index / reflection_atlas->subdiv) * cell_size; + int width=cell_size; + int height=cell_size; + + storage->shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DIRECT_WRITE,rpi->render_step==0); + storage->shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::LOW_QUALITY,rpi->probe_ptr->update_mode==VS::REFLECTION_PROBE_UPDATE_ALWAYS); + for(int i=0;i<2;i++) { + + storage->shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::Z_FLIP,i>0); + storage->shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::ROUGHNESS,rpi->render_step/5.0); + + uint32_t local_width=width,local_height=height; + uint32_t local_x=x,local_y=y; + + local_height/=2; + local_y+=i*local_height; + + glViewport(local_x,local_y,local_width,local_height); + + _copy_screen(); + } + storage->shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DIRECT_WRITE,false); + storage->shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::LOW_QUALITY,false); + + + rpi->render_step++; + + return rpi->render_step==6; +} /* ENVIRONMENT API */ @@ -464,26 +796,12 @@ void RasterizerSceneGLES3::environment_set_background(RID p_env,VS::EnvironmentB env->bg_mode=p_bg; } -void RasterizerSceneGLES3::environment_set_skybox(RID p_env, RID p_skybox, int p_radiance_size){ +void RasterizerSceneGLES3::environment_set_skybox(RID p_env, RID p_skybox){ Environment *env=environment_owner.getornull(p_env); ERR_FAIL_COND(!env); - if (env->skybox_color.is_valid()) { - env->skybox_color=RID(); - } - if (env->skybox_radiance.is_valid()) { - storage->free(env->skybox_radiance); - env->skybox_radiance=RID(); - } - - - if (p_skybox.is_valid()) { - - env->skybox_color=p_skybox; - env->skybox_radiance=storage->texture_create_radiance_cubemap(p_skybox,p_radiance_size); - //env->skybox_irradiance=storage->texture_create_pbr_cubemap(p_skybox,VS::PBR_CUBEMAP_IRRADIANCE,p_irradiance_size); - } + env->skybox=p_skybox; } @@ -775,6 +1093,7 @@ void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e) { RasterizerStorageGLES3::Surface *s = static_cast(e->geometry); glBindVertexArray(s->array_id); // everything is so easy nowadays + } break; } @@ -821,6 +1140,8 @@ void RasterizerSceneGLES3::_setup_light(RenderList::Element *e) { int omni_count=0; int spot_indices[16]; int spot_count=0; + int reflection_indices[16]; + int reflection_count=0; int maxobj = MIN(16,state.max_forward_lights_per_object); @@ -859,6 +1180,32 @@ void RasterizerSceneGLES3::_setup_light(RenderList::Element *e) { glUniform1iv(state.scene_shader.get_uniform(SceneShaderGLES3::SPOT_LIGHT_INDICES),spot_count,spot_indices); } + + int rc = e->instance->reflection_probe_instances.size(); + + + if (rc) { + + + const RID* reflections=e->instance->reflection_probe_instances.ptr(); + + for(int i=0;ilast_pass!=render_pass) //not visible + continue; + + if (reflection_countreflection_index; + } + } + } + + state.scene_shader.set_uniform(SceneShaderGLES3::REFLECTION_COUNT,reflection_count); + if (reflection_count) { + glUniform1iv(state.scene_shader.get_uniform(SceneShaderGLES3::REFLECTION_INDICES),reflection_count,reflection_indices); + } + + } @@ -932,9 +1279,9 @@ void RasterizerSceneGLES3::_set_cull(bool p_front,bool p_reverse_cull) { -void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_element_count,const Transform& p_view_transform,const CameraMatrix& p_projection,RasterizerStorageGLES3::Texture* p_base_env,bool p_reverse_cull,bool p_alpha_pass,bool p_shadow,bool p_directional_add) { +void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_element_count,const Transform& p_view_transform,const CameraMatrix& p_projection,GLuint p_base_env,bool p_reverse_cull,bool p_alpha_pass,bool p_shadow,bool p_directional_add,bool p_directional_shadows) { - if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP]) { + if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP]) { //p_reverse_cull=!p_reverse_cull; glFrontFace(GL_CCW); } else { @@ -951,15 +1298,15 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e if (p_base_env) { glActiveTexture(GL_TEXTURE0+storage->config.max_texture_image_units-2); - glBindTexture(p_base_env->target,p_base_env->tex_id); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_CUBEMAP,true); + glBindTexture(GL_TEXTURE_2D,p_base_env); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_MAP,true); } else { - state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_CUBEMAP,false); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_MAP,false); } } else { - state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_CUBEMAP,false); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_MAP,false); } @@ -1038,7 +1385,7 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e if (p_directional_add || (directional_light && (e->sort_key&RenderList::SORT_KEY_NO_DIRECTIONAL_FLAG)==0)) { state.scene_shader.set_conditional(SceneShaderGLES3::USE_LIGHT_DIRECTIONAL,true); - if (directional_light->light_ptr->shadow) { + if (p_directional_shadows && directional_light->light_ptr->shadow) { state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_DIRECTIONAL_SHADOW,true); switch(directional_light->light_ptr->directional_shadow_mode) { @@ -1076,7 +1423,7 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e case RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_MIX: { glBlendEquation(GL_FUNC_ADD); - if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { + if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); } else { @@ -1097,7 +1444,7 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e } break; case RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_MUL: { glBlendEquation(GL_FUNC_ADD); - if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { + if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); } else { @@ -1154,7 +1501,7 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e glFrontFace(GL_CW); glBindVertexArray(0); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_CUBEMAP,false); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_MAP,false); state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_LIGHTING,false); state.scene_shader.set_conditional(SceneShaderGLES3::USE_LIGHT_DIRECTIONAL,false); state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_DIRECTIONAL_SHADOW,false); @@ -1290,9 +1637,12 @@ void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_g } } -void RasterizerSceneGLES3::_draw_skybox(RID p_skybox,const CameraMatrix& p_projection,const Transform& p_transform,bool p_vflip,float p_scale) { +void RasterizerSceneGLES3::_draw_skybox(RasterizerStorageGLES3::SkyBox *p_skybox,const CameraMatrix& p_projection,const Transform& p_transform,bool p_vflip,float p_scale) { + + if (!p_skybox) + return; - RasterizerStorageGLES3::Texture *tex = storage->texture_owner.getornull(p_skybox); + RasterizerStorageGLES3::Texture *tex = storage->texture_owner.getornull(p_skybox->cubemap); ERR_FAIL_COND(!tex); glActiveTexture(GL_TEXTURE0); @@ -1461,7 +1811,7 @@ void RasterizerSceneGLES3::_setup_environment(Environment *env,const CameraMatri } -void RasterizerSceneGLES3::_setup_directional_light(int p_index,const Transform& p_camera_inverse_transform) { +void RasterizerSceneGLES3::_setup_directional_light(int p_index,const Transform& p_camera_inverse_transform,bool p_use_shadows) { LightInstance *li = directional_lights[p_index]; @@ -1499,7 +1849,7 @@ void RasterizerSceneGLES3::_setup_directional_light(int p_index,const Transform& ubo_data.light_shadow_color[3]=1.0; - if (li->light_ptr->shadow) { + if (p_use_shadows && li->light_ptr->shadow) { int shadow_count=0; @@ -1568,7 +1918,6 @@ void RasterizerSceneGLES3::_setup_directional_light(int p_index,const Transform& Rect2 atlas_rect = Rect2(float(x)/directional_shadow.size,float(y)/directional_shadow.size,float(width)/directional_shadow.size,float(height)/directional_shadow.size); rectm.set_light_atlas_rect(atlas_rect); -// print_line("atlas rect: "+atlas_rect); CameraMatrix shadow_mtx = rectm * bias * li->shadow_transform[j].camera * modelview; @@ -1844,6 +2193,103 @@ void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result,int p_light_cu } +void RasterizerSceneGLES3::_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) { + + state.reflection_probe_count=0; + + for(int i=0;ireflection_atlas_index<0); + + + if (state.reflection_probe_count>=state.max_ubo_reflections) + break; + + rpi->last_pass=render_pass; + + + ReflectionProbeDataUBO reflection_ubo; + + reflection_ubo.box_extents[0]=rpi->probe_ptr->extents.x; + reflection_ubo.box_extents[1]=rpi->probe_ptr->extents.y; + reflection_ubo.box_extents[2]=rpi->probe_ptr->extents.z; + reflection_ubo.box_extents[3]=0; + + + + reflection_ubo.box_ofs[0]=rpi->probe_ptr->origin_offset.x; + reflection_ubo.box_ofs[1]=rpi->probe_ptr->origin_offset.y; + reflection_ubo.box_ofs[2]=rpi->probe_ptr->origin_offset.z; + reflection_ubo.box_ofs[3]=0; + + reflection_ubo.params[0]=rpi->probe_ptr->intensity; + reflection_ubo.params[1]=0; + reflection_ubo.params[2]=rpi->probe_ptr->interior?1.0:0.0; + reflection_ubo.params[3]=rpi->probe_ptr->box_projection?1.0:0.0; + + if (rpi->probe_ptr->interior) { + Color ambient_linear = rpi->probe_ptr->interior_ambient.to_linear(); + reflection_ubo.ambient[0]=ambient_linear.r*rpi->probe_ptr->interior_ambient_energy; + reflection_ubo.ambient[1]=ambient_linear.g*rpi->probe_ptr->interior_ambient_energy; + reflection_ubo.ambient[2]=ambient_linear.b*rpi->probe_ptr->interior_ambient_energy; + 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_skybox_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; + } + + int cell_size = reflection_atlas->size / reflection_atlas->subdiv; + int x = (rpi->reflection_atlas_index % reflection_atlas->subdiv) * cell_size; + int y = (rpi->reflection_atlas_index / reflection_atlas->subdiv) * cell_size; + int width=cell_size; + int height=cell_size; + + reflection_ubo.atlas_clamp[0]=float(x)/reflection_atlas->size; + reflection_ubo.atlas_clamp[1]=float(y)/reflection_atlas->size; + reflection_ubo.atlas_clamp[2]=float(width)/reflection_atlas->size; + reflection_ubo.atlas_clamp[3]=float(height/2)/reflection_atlas->size; + + Transform proj = (p_camera_inverse_transform * rpi->transform).inverse(); + store_transform(proj,reflection_ubo.local_matrix); + + rpi->reflection_index=state.reflection_probe_count; + copymem(&state.reflection_array_tmp[rpi->reflection_index*sizeof(ReflectionProbeDataUBO)],&reflection_ubo,sizeof(ReflectionProbeDataUBO)); + state.reflection_probe_count++; + + } + + + if (state.reflection_probe_count) { + + + glBindBuffer(GL_UNIFORM_BUFFER, state.reflection_array_ubo); + glBufferSubData(GL_UNIFORM_BUFFER, 0, state.reflection_probe_count*sizeof(ReflectionProbeDataUBO), state.reflection_array_tmp); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + + glBindBufferBase(GL_UNIFORM_BUFFER,6,state.reflection_array_ubo); + } + +} + + void RasterizerSceneGLES3::_copy_screen() { glBindVertexArray(storage->resources.quadie_array); @@ -1959,7 +2405,7 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase** p_cull_result,int p_ } -void RasterizerSceneGLES3::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_environment,RID p_shadow_atlas){ +void RasterizerSceneGLES3::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){ //first of all, make a new render pass render_pass++; @@ -1969,6 +2415,7 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C Environment *env = environment_owner.getornull(p_environment); ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas); + ReflectionAtlas *reflection_atlas = reflection_atlas_owner.getornull(p_reflection_atlas); if (shadow_atlas && shadow_atlas->size) { glActiveTexture(GL_TEXTURE0+storage->config.max_texture_image_units-3); @@ -1979,9 +2426,21 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C state.ubo_data.shadow_atlas_pixel_size[1]=1.0/shadow_atlas->size; } + + if (reflection_atlas && reflection_atlas->size) { + glActiveTexture(GL_TEXTURE0+storage->config.max_texture_image_units-5); + glBindTexture(GL_TEXTURE_2D,reflection_atlas->color); + } + + if (p_reflection_probe.is_valid()) { + state.ubo_data.reflection_multiplier=0.0; + } else { + state.ubo_data.reflection_multiplier=1.0; + } _setup_environment(env,p_cam_projection,p_cam_transform); _setup_lights(p_light_cull_result,p_light_cull_count,p_cam_transform.affine_inverse(),p_cam_projection,p_shadow_atlas); + _setup_reflections(p_reflection_probe_cull_result,p_reflection_probe_cull_count,p_cam_transform.affine_inverse(),p_cam_projection,p_reflection_atlas,env); render_list.clear(); @@ -1998,24 +2457,55 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C glEnable(GL_DEPTH_TEST); glDisable(GL_SCISSOR_TEST); - RasterizerStorageGLES3::Texture* env_radiance_tex=NULL; - glViewport(0,0,storage->frame.current_rt->width,storage->frame.current_rt->height); + ReflectionProbeInstance *probe = reflection_probe_instance_owner.getornull(p_reflection_probe); + GLuint current_fbo; - if (use_mrt) { + if (probe) { - glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.fbo); - state.scene_shader.set_conditional(SceneShaderGLES3::USE_MULTIPLE_RENDER_TARGETS,true); + ReflectionAtlas *ref_atlas = reflection_atlas_owner.getptr(probe->atlas); + ERR_FAIL_COND(!ref_atlas); - Color black(0,0,0,0); - glClearBufferfv(GL_COLOR,1,black.components); // specular - glClearBufferfv(GL_COLOR,2,black.components); // normal metal rough + int target_size=ref_atlas->size/ref_atlas->subdiv; - } else { + int cubemap_index=reflection_cubemaps.size()-1; - glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.alpha_fbo); + for(int i=reflection_cubemaps.size()-1;i>=0;i--) { + //find appropriate cubemap to render to + if (reflection_cubemaps[i].size>target_size*2) + break; + + cubemap_index=i; + } + + current_fbo=reflection_cubemaps[cubemap_index].fbo_id[p_reflection_probe_pass]; + use_mrt=false; state.scene_shader.set_conditional(SceneShaderGLES3::USE_MULTIPLE_RENDER_TARGETS,false); + glViewport(0,0,reflection_cubemaps[cubemap_index].size,reflection_cubemaps[cubemap_index].size); + glBindFramebuffer(GL_FRAMEBUFFER,current_fbo); + } else { + + glViewport(0,0,storage->frame.current_rt->width,storage->frame.current_rt->height); + + if (use_mrt) { + + current_fbo=storage->frame.current_rt->buffers.fbo; + + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.fbo); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_MULTIPLE_RENDER_TARGETS,true); + + Color black(0,0,0,0); + glClearBufferfv(GL_COLOR,1,black.components); // specular + glClearBufferfv(GL_COLOR,2,black.components); // normal metal rough + + } else { + + current_fbo = storage->frame.current_rt->buffers.alpha_fbo; + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.alpha_fbo); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_MULTIPLE_RENDER_TARGETS,false); + + } } @@ -2024,6 +2514,9 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C Color clear_color(0,0,0,0); + RasterizerStorageGLES3::SkyBox *skybox=NULL; + GLuint env_radiance_tex=0; + if (!env || env->bg_mode==VS::ENV_BG_CLEAR_COLOR) { if (storage->frame.clear_request) { @@ -2039,8 +2532,10 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C storage->frame.clear_request=false; } else if (env->bg_mode==VS::ENV_BG_SKYBOX) { - if (env->skybox_radiance.is_valid()) { - env_radiance_tex = storage->texture_owner.getornull(env->skybox_radiance); + skybox = storage->skybox_owner.getornull(env->skybox); + + if (skybox) { + env_radiance_tex=skybox->radiance; } storage->frame.clear_request=false; @@ -2055,7 +2550,7 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C glBlendEquation(GL_FUNC_ADD); - if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { + if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); } else { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -2065,23 +2560,25 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C render_list.sort_by_key(false); - if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { + if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); } else { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } + + if (state.directional_light_count==0) { directional_light=NULL; - _render_list(render_list.elements,render_list.element_count,p_cam_transform,p_cam_projection,env_radiance_tex,false,false,false,false); + _render_list(render_list.elements,render_list.element_count,p_cam_transform,p_cam_projection,env_radiance_tex,false,false,false,false,shadow_atlas!=NULL); } else { for(int i=0;i0) { glEnable(GL_BLEND); } - _setup_directional_light(i,p_cam_transform.affine_inverse()); - _render_list(render_list.elements,render_list.element_count,p_cam_transform,p_cam_projection,env_radiance_tex,false,false,false,i>0); + _setup_directional_light(i,p_cam_transform.affine_inverse(),shadow_atlas!=NULL); + _render_list(render_list.elements,render_list.element_count,p_cam_transform,p_cam_projection,env_radiance_tex,false,false,false,i>0,shadow_atlas!=NULL); } } @@ -2095,7 +2592,7 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.alpha_fbo); //switch to alpha fbo for skybox, only diffuse/ambient matters } - _draw_skybox(env->skybox_color,p_cam_projection,p_cam_transform,storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP],env->skybox_scale); + _draw_skybox(skybox,p_cam_projection,p_cam_transform,storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP],env->skybox_scale); } @@ -2112,24 +2609,30 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C glDepthMask(GL_TRUE); glEnable(GL_DEPTH_TEST); glDisable(GL_SCISSOR_TEST); - glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.alpha_fbo); - - render_list.sort_by_depth(true); + if (use_mrt) { + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.alpha_fbo); + } + render_list.sort_by_depth(true); if (state.directional_light_count==0) { directional_light=NULL; - _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,env_radiance_tex,false,true,false,false); + _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,env_radiance_tex,false,true,false,false,shadow_atlas!=NULL); } else { for(int i=0;i0); + _setup_directional_light(i,p_cam_transform.affine_inverse(),shadow_atlas!=NULL); + _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,env_radiance_tex,false,true,false,i>0,shadow_atlas!=NULL); } } + if (probe) { + //rendering a probe, do no more! + return; + } + _copy_to_front_buffer(env); /* if (shadow_atlas) { @@ -2143,6 +2646,17 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C } */ + + if (false && reflection_atlas && storage->frame.current_rt) { + + //_copy_texture_to_front_buffer(shadow_atlas->depth); + storage->canvas->canvas_begin(); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,reflection_atlas->color); + 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) { //_copy_texture_to_front_buffer(shadow_atlas->depth); @@ -2154,6 +2668,16 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C } + if (false && env_radiance_tex) { + + //_copy_texture_to_front_buffer(shadow_atlas->depth); + storage->canvas->canvas_begin(); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,env_radiance_tex); + 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 0 if (use_fb) { @@ -2534,7 +3058,7 @@ void RasterizerSceneGLES3::render_shadow(RID p_light,RID p_shadow_atlas,int p_pa state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_SHADOW,true); - _render_list(render_list.elements,render_list.element_count,light_transform,light_projection,NULL,!flip_facing,false,true,false); + _render_list(render_list.elements,render_list.element_count,light_transform,light_projection,NULL,!flip_facing,false,true,false,false); state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_SHADOW,false); state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_SHADOW_DUAL_PARABOLOID,false); @@ -2624,6 +3148,19 @@ bool RasterizerSceneGLES3::free(RID p_rid) { shadow_atlas_set_size(p_rid,0); shadow_atlas_owner.free(p_rid); memdelete(shadow_atlas); + } else if (reflection_atlas_owner.owns(p_rid)) { + + ReflectionAtlas *reflection_atlas = reflection_atlas_owner.get(p_rid); + reflection_atlas_set_size(p_rid,0); + reflection_atlas_owner.free(p_rid); + memdelete(reflection_atlas); + } else if (reflection_probe_instance_owner.owns(p_rid)) { + + ReflectionProbeInstance *reflection_instance = reflection_probe_instance_owner.get(p_rid); + + reflection_probe_release_atlas_index(p_rid); + reflection_probe_instance_owner.free(p_rid); + memdelete(reflection_instance); } else { return false; @@ -2890,6 +3427,7 @@ void RasterizerSceneGLES3::initialize() { const int ubo_light_size=160; state.ubo_light_size=ubo_light_size; state.max_ubo_lights=max_ubo_size/ubo_light_size; + print_line("max ubo light: "+itos(state.max_ubo_lights)); 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); @@ -2912,10 +3450,21 @@ void RasterizerSceneGLES3::initialize() { state.max_forward_lights_per_object=8; + 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=max_ubo_size/sizeof(ReflectionProbeDataUBO); + print_line("max ubo reflections: "+itos(state.max_ubo_reflections)+" ubo size: "+itos(sizeof(ReflectionProbeDataUBO))); + state.reflection_array_tmp = (uint8_t*)memalloc(sizeof(ReflectionProbeDataUBO)*state.max_ubo_reflections); + + glGenBuffers(1, &state.reflection_array_ubo); + glBindBuffer(GL_UNIFORM_BUFFER, state.reflection_array_ubo); + glBufferData(GL_UNIFORM_BUFFER, sizeof(ReflectionProbeDataUBO)*state.max_ubo_reflections, NULL, GL_DYNAMIC_DRAW); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + + state.scene_shader.add_custom_define("#define MAX_REFLECTION_DATA_STRUCTS "+itos(state.max_ubo_reflections)+"\n"); } @@ -2923,6 +3472,73 @@ void RasterizerSceneGLES3::initialize() { Globals::get_singleton()->set_custom_property_info("rendering/gles3/shadow_filter_mode",PropertyInfo(Variant::INT,"rendering/gles3/shadow_filter_mode",PROPERTY_HINT_ENUM,"Disabled,PCF5,PCF13")); shadow_filter_mode=SHADOW_FILTER_NEAREST; + { //reflection cubemaps + int max_reflection_cubemap_sampler_size=512; + + int cube_size = max_reflection_cubemap_sampler_size; + + glActiveTexture(GL_TEXTURE0); + + bool use_float=true; + + GLenum internal_format = use_float?GL_RGBA16F:GL_RGB10_A2; + GLenum format = GL_RGBA; + GLenum type = use_float?GL_HALF_FLOAT:GL_UNSIGNED_INT_2_10_10_10_REV; + + while(cube_size>=32) { + + ReflectionCubeMap cube; + cube.size=cube_size; + + glGenTextures(1,&cube.depth); + glBindTexture(GL_TEXTURE_2D,cube.depth); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, cube.size, cube.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); + + + glGenTextures(1,&cube.cubemap); + glBindTexture(GL_TEXTURE_CUBE_MAP,cube.cubemap); + //gen cubemap first + for(int i=0;i<6;i++) { + + glTexImage2D(_cube_side_enum[i], 0, internal_format, cube.size, cube.size, 0, format, type, NULL); + } + + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + // Remove artifact on the edges of the reflectionmap + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + + //gen renderbuffers second, because it needs a complete cubemap + for(int i=0;i<6;i++) { + + glGenFramebuffers(1, &cube.fbo_id[i]); + glBindFramebuffer(GL_FRAMEBUFFER, cube.fbo_id[i]); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,_cube_side_enum[i], cube.cubemap, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,GL_TEXTURE_2D, cube.depth, 0); + + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + ERR_CONTINUE(status!=GL_FRAMEBUFFER_COMPLETE); + } + + reflection_cubemaps.push_back(cube); + + cube_size>>=1; + } + } + + +#ifdef GLEW_ENABLED +//"desktop" opengl needs this. + glEnable(GL_POINT_SPRITE); + glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); + +#endif } void RasterizerSceneGLES3::iteration() { diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 24b6a36fcc..81c13bdc08 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -62,6 +62,7 @@ public: float shadow_dual_paraboloid_render_side; float shadow_atlas_pixel_size[2]; float shadow_directional_pixel_size[2]; + float reflection_multiplier; } ubo_data; @@ -87,17 +88,23 @@ public: GLuint spot_array_ubo; GLuint omni_array_ubo; + GLuint reflection_array_ubo; uint32_t ubo_light_size; uint8_t *spot_array_tmp; uint8_t *omni_array_tmp; + uint8_t *reflection_array_tmp; int max_ubo_lights; int max_forward_lights_per_object; + int max_ubo_reflections; + + int spot_light_count; int omni_light_count; int directional_light_count; + int reflection_probe_count; bool cull_front; @@ -176,6 +183,87 @@ public: virtual int get_directional_light_shadow_size(RID p_light_intance); virtual void set_directional_shadow_count(int p_count); + /* REFLECTION PROBE ATLAS API */ + + struct ReflectionAtlas : public RID_Data { + + int subdiv; + int size; + + struct Reflection { + RID owner; + uint64_t last_frame; + }; + + GLuint fbo[6]; + GLuint color; + + Vector reflections; + }; + + mutable RID_Owner reflection_atlas_owner; + + virtual RID reflection_atlas_create(); + virtual void reflection_atlas_set_size(RID p_ref_atlas,int p_size); + virtual void reflection_atlas_set_subdivision(RID p_ref_atlas,int p_subdiv); + + /* REFLECTION CUBEMAPS */ + + struct ReflectionCubeMap { + + GLuint fbo_id[6]; + GLuint cubemap; + GLuint depth; + int size; + }; + + Vector reflection_cubemaps; + + /* REFLECTION PROBE INSTANCE */ + + struct ReflectionProbeInstance : public RID_Data { + + RasterizerStorageGLES3::ReflectionProbe *probe_ptr; + RID probe; + RID self; + RID atlas; + + int reflection_atlas_index; + + int render_step; + + + + uint64_t last_pass; + int reflection_index; + + Transform transform; + }; + + struct ReflectionProbeDataUBO { + + float box_extents[4]; + float box_ofs[4]; + float params[4]; // intensity, 0, 0, boxproject + float ambient[4]; //color, probe contrib + float atlas_clamp[4]; + float local_matrix[16]; //up to here for spot and omni, rest is for directional + //notes: for ambientblend, use distance to edge to blend between already existing global environment + }; + + + mutable RID_Owner reflection_probe_instance_owner; + + virtual RID reflection_probe_instance_create(RID p_probe); + virtual void reflection_probe_instance_set_transform(RID p_instance,const Transform& p_transform); + virtual void reflection_probe_release_atlas_index(RID p_instance); + virtual bool reflection_probe_instance_needs_redraw(RID p_instance); + virtual bool reflection_probe_instance_has_reflection(RID p_instance); + virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas); + virtual bool reflection_probe_instance_postprocess_step(RID p_instance); + + + /* ENVIRONMENT API */ @@ -183,8 +271,7 @@ public: VS::EnvironmentBG bg_mode; - RID skybox_color; - RID skybox_radiance; + RID skybox; float skybox_scale; Color bg_color; @@ -214,7 +301,7 @@ public: virtual RID environment_create(); virtual void environment_set_background(RID p_env,VS::EnvironmentBG p_bg); - virtual void environment_set_skybox(RID p_env,RID p_skybox,int p_radiance_size); + virtual void environment_set_skybox(RID p_env,RID p_skybox); virtual void environment_set_skybox_scale(RID p_env,float p_scale); 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); @@ -441,23 +528,25 @@ public: _FORCE_INLINE_ void _render_geometry(RenderList::Element *e); _FORCE_INLINE_ void _setup_light(RenderList::Element *e); - void _render_list(RenderList::Element **p_elements, int p_element_count, const Transform& p_view_transform, const CameraMatrix& p_projection, RasterizerStorageGLES3::Texture *p_base_env, bool p_reverse_cull, bool p_alpha_pass, bool p_shadow, bool p_directional_add); + void _render_list(RenderList::Element **p_elements, int p_element_count, const Transform& p_view_transform, const CameraMatrix& p_projection, GLuint p_base_env, bool p_reverse_cull, bool p_alpha_pass, bool p_shadow, bool p_directional_add, bool p_directional_shadows); _FORCE_INLINE_ void _add_geometry( RasterizerStorageGLES3::Geometry* p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner,int p_material,bool p_shadow); - void _draw_skybox(RID p_skybox, const CameraMatrix& p_projection, const Transform& p_transform, bool p_vflip, float p_scale); + void _draw_skybox(RasterizerStorageGLES3::SkyBox *p_skybox, const CameraMatrix& p_projection, const Transform& p_transform, bool p_vflip, float p_scale); void _setup_environment(Environment *env, const CameraMatrix &p_cam_projection, const Transform& p_cam_transform); - void _setup_directional_light(int p_index, const Transform &p_camera_inverse_transform); + void _setup_directional_light(int p_index, const Transform &p_camera_inverse_transformm, 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); + void _copy_screen(); void _copy_to_front_buffer(Environment *env); void _copy_texture_to_front_buffer(GLuint p_texture); //used for debug void _fill_render_list(InstanceBase** p_cull_result,int p_cull_count,bool p_shadow); - 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_environment,RID p_shadow_atlas); + 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 6e278e563b..8188fe3adb 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -1015,10 +1015,6 @@ RID RasterizerStorageGLES3::texture_create_radiance_cubemap(RID p_source,int p_r glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); glDisable(GL_SCISSOR_TEST); -#ifdef GLEW_ENABLED - glDisable(GL_POINT_SPRITE); - glDisable(GL_VERTEX_PROGRAM_POINT_SIZE); -#endif glDisable(GL_BLEND); @@ -1086,6 +1082,8 @@ RID RasterizerStorageGLES3::texture_create_radiance_cubemap(RID p_source,int p_r size = p_resolution; + shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DUAL_PARABOLOID,false); + while(mm_level) { for(int i=0;i<6;i++) { @@ -1156,6 +1154,147 @@ RID RasterizerStorageGLES3::texture_create_radiance_cubemap(RID p_source,int p_r } +RID RasterizerStorageGLES3::skybox_create() { + + SkyBox *skybox = memnew( SkyBox ); + skybox->radiance=0; + return skybox_owner.make_rid(skybox); +} + +void RasterizerStorageGLES3::skybox_set_texture(RID p_skybox, RID p_cube_map, int p_radiance_size){ + + SkyBox *skybox = skybox_owner.getornull(p_skybox); + ERR_FAIL_COND(!skybox); + + if (skybox->cubemap.is_valid()) { + skybox->cubemap=RID(); + glDeleteTextures(1,&skybox->radiance); + skybox->radiance=0; + } + + skybox->cubemap=p_cube_map; + if (!skybox->cubemap.is_valid()) + return; //cleared + + Texture *texture = texture_owner.getornull(skybox->cubemap); + if (!texture || !(texture->flags&VS::TEXTURE_FLAG_CUBEMAP)) { + skybox->cubemap=RID(); + ERR_FAIL_COND(!texture || !(texture->flags&VS::TEXTURE_FLAG_CUBEMAP)); + } + + glBindVertexArray(0); + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glDisable(GL_SCISSOR_TEST); + glDisable(GL_BLEND); + + + glActiveTexture(GL_TEXTURE0); + glBindTexture(texture->target, texture->tex_id); + + if (config.srgb_decode_supported && texture->srgb && !texture->using_srgb) { + + glTexParameteri(texture->target,_TEXTURE_SRGB_DECODE_EXT,_DECODE_EXT); + texture->using_srgb=true; +#ifdef TOOLS_ENABLED + if (!(texture->flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) { + texture->flags|=VS::TEXTURE_FLAG_CONVERT_TO_LINEAR; + //notify that texture must be set to linear beforehand, so it works in other platforms when exported + } +#endif + } + + + glActiveTexture(GL_TEXTURE1); + glGenTextures(1, &skybox->radiance); + glBindTexture(GL_TEXTURE_2D, skybox->radiance); + + GLuint tmp_fb; + + glGenFramebuffers(1, &tmp_fb); + glBindFramebuffer(GL_FRAMEBUFFER, tmp_fb); + + + int size = p_radiance_size; + + int lod=0; + + + int mipmaps=6; + + int mm_level=mipmaps; + + bool use_float=true; + + GLenum internal_format = use_float?GL_RGBA16F:GL_RGB10_A2; + GLenum format = GL_RGBA; + GLenum type = use_float?GL_HALF_FLOAT:GL_UNSIGNED_INT_2_10_10_10_REV; + + while(mm_level) { + + glTexImage2D(GL_TEXTURE_2D, lod, internal_format, size, size*2, 0, format, type, NULL); + lod++; + mm_level--; + + if (size>1) + size>>=1; + } + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, lod-1); + + lod=0; + mm_level=mipmaps; + + size = p_radiance_size; + + shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DUAL_PARABOLOID,true); + shaders.cubemap_filter.bind(); + + while(mm_level) { + + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, skybox->radiance, lod); +#ifdef DEBUG_ENABLED + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + ERR_CONTINUE(status!=GL_FRAMEBUFFER_COMPLETE); +#endif + + for(int i=0;i<2;i++) { + glViewport(0,i*size,size,size); + glBindVertexArray(resources.quadie_array); + + shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::Z_FLIP,i>0); + shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::ROUGHNESS,lod/float(mipmaps-1)); + + + glDrawArrays(GL_TRIANGLE_FAN,0,4); + glBindVertexArray(0); + } + + if (size>1) + size>>=1; + lod++; + mm_level--; + + } + shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DUAL_PARABOLOID,false); + + + //restore ranges + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, lod-1); + + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glBindFramebuffer(GL_FRAMEBUFFER, config.system_fbo); + glDeleteFramebuffers(1, &tmp_fb); + +} + + /* SHADER API */ @@ -2144,7 +2283,7 @@ void RasterizerStorageGLES3::_update_material(Material* material) { Map::Element *V = material->params.find(E->key()); if (V) { - //user provided + //user provided _fill_std140_variant_ubo_value(E->get().type,V->get(),data,material->shader->mode==VS::SHADER_SPATIAL); } else if (E->get().default_value.size()){ //default value @@ -3405,46 +3544,197 @@ AABB RasterizerStorageGLES3::light_get_aabb(RID p_light) const { RID RasterizerStorageGLES3::reflection_probe_create(){ - return RID(); + ReflectionProbe *reflection_probe = memnew( ReflectionProbe ); + + reflection_probe->intensity=1.0; + reflection_probe->interior_ambient=Color(); + reflection_probe->interior_ambient_energy=1.0; + reflection_probe->max_distance=0; + reflection_probe->extents=Vector3(1,1,1); + reflection_probe->origin_offset=Vector3(0,0,0); + reflection_probe->interior=false; + reflection_probe->box_projection=false; + reflection_probe->enable_shadows=false; + reflection_probe->cull_mask=(1<<20)-1; + reflection_probe->update_mode=VS::REFLECTION_PROBE_UPDATE_ONCE; + + return reflection_probe_owner.make_rid(reflection_probe); } -void RasterizerStorageGLES3::reflection_probe_set_intensity(RID p_probe, float p_intensity){ +void RasterizerStorageGLES3::reflection_probe_set_update_mode(RID p_probe, VS::ReflectionProbeUpdateMode p_mode) { + ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND(!reflection_probe); + + reflection_probe->update_mode=p_mode; + reflection_probe->instance_change_notify(); } -void RasterizerStorageGLES3::reflection_probe_set_clip(RID p_probe, float p_near, float p_far){ +void RasterizerStorageGLES3::reflection_probe_set_intensity(RID p_probe, float p_intensity) { + + ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND(!reflection_probe); + + reflection_probe->intensity=p_intensity; + +} + +void RasterizerStorageGLES3::reflection_probe_set_interior_ambient(RID p_probe, const Color& p_ambient) { + + ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND(!reflection_probe); + + reflection_probe->interior_ambient=p_ambient; + +} + +void RasterizerStorageGLES3::reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy) { + + ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND(!reflection_probe); + + reflection_probe->interior_ambient_energy=p_energy; } -void RasterizerStorageGLES3::reflection_probe_set_min_blend_distance(RID p_probe, float p_distance){ +void RasterizerStorageGLES3::reflection_probe_set_interior_ambient_probe_contribution(RID p_probe, float p_contrib) { + + ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND(!reflection_probe); + + reflection_probe->interior_ambient_probe_contrib=p_contrib; + +} + + +void RasterizerStorageGLES3::reflection_probe_set_max_distance(RID p_probe, float p_distance){ + + ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND(!reflection_probe); + + reflection_probe->max_distance=p_distance; + reflection_probe->instance_change_notify(); } void RasterizerStorageGLES3::reflection_probe_set_extents(RID p_probe, const Vector3& p_extents){ + ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND(!reflection_probe); + + reflection_probe->extents=p_extents; + reflection_probe->instance_change_notify(); } void RasterizerStorageGLES3::reflection_probe_set_origin_offset(RID p_probe, const Vector3& p_offset){ + ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND(!reflection_probe); + + reflection_probe->origin_offset=p_offset; + reflection_probe->instance_change_notify(); } -void RasterizerStorageGLES3::reflection_probe_set_enable_parallax_correction(RID p_probe, bool p_enable){ +void RasterizerStorageGLES3::reflection_probe_set_as_interior(RID p_probe, bool p_enable){ + + ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND(!reflection_probe); + + reflection_probe->interior=p_enable; } -void RasterizerStorageGLES3::reflection_probe_set_resolution(RID p_probe, int p_resolution){ +void RasterizerStorageGLES3::reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable){ + + ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND(!reflection_probe); + reflection_probe->box_projection=p_enable; } -void RasterizerStorageGLES3::reflection_probe_set_hide_skybox(RID p_probe, bool p_hide){ +void RasterizerStorageGLES3::reflection_probe_set_enable_shadows(RID p_probe, bool p_enable){ + + ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND(!reflection_probe); + + reflection_probe->enable_shadows=p_enable; + reflection_probe->instance_change_notify(); } void RasterizerStorageGLES3::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers){ + ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND(!reflection_probe); + + reflection_probe->cull_mask=p_layers; + reflection_probe->instance_change_notify(); } +AABB RasterizerStorageGLES3::reflection_probe_get_aabb(RID p_probe) const { + const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND_V(!reflection_probe,AABB()); + + AABB aabb; + aabb.pos=-reflection_probe->extents; + aabb.size=reflection_probe->extents*2.0; + + return aabb; + + +} +VS::ReflectionProbeUpdateMode RasterizerStorageGLES3::reflection_probe_get_update_mode(RID p_probe) const{ + + const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND_V(!reflection_probe,VS::REFLECTION_PROBE_UPDATE_ALWAYS); + + return reflection_probe->update_mode; +} + +uint32_t RasterizerStorageGLES3::reflection_probe_get_cull_mask(RID p_probe) const { + + const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND_V(!reflection_probe,0); + + return reflection_probe->cull_mask; + +} + +Vector3 RasterizerStorageGLES3::reflection_probe_get_extents(RID p_probe) const { + + const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND_V(!reflection_probe,Vector3()); + + return reflection_probe->extents; + +} +Vector3 RasterizerStorageGLES3::reflection_probe_get_origin_offset(RID p_probe) const{ + + const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND_V(!reflection_probe,Vector3()); + + return reflection_probe->origin_offset; + +} + +bool RasterizerStorageGLES3::reflection_probe_renders_shadows(RID p_probe) const { + + const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND_V(!reflection_probe,false); + + return reflection_probe->enable_shadows; + +} + +float RasterizerStorageGLES3::reflection_probe_get_origin_max_distance(RID p_probe) const{ + + const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND_V(!reflection_probe,0); + + return reflection_probe->max_distance; + +} /* ROOM API */ @@ -3495,6 +3785,10 @@ void RasterizerStorageGLES3::instance_add_dependency(RID p_base,RasterizerScene: inst = mesh_owner.getornull(p_base); ERR_FAIL_COND(!inst); } break; + case VS::INSTANCE_REFLECTION_PROBE: { + inst = reflection_probe_owner.getornull(p_base); + ERR_FAIL_COND(!inst); + } break; case VS::INSTANCE_LIGHT: { inst = light_owner.getornull(p_base); ERR_FAIL_COND(!inst); @@ -3517,6 +3811,10 @@ void RasterizerStorageGLES3::instance_remove_dependency(RID p_base,RasterizerSce ERR_FAIL_COND(!inst); } break; + case VS::INSTANCE_REFLECTION_PROBE: { + inst = reflection_probe_owner.getornull(p_base); + ERR_FAIL_COND(!inst); + } break; case VS::INSTANCE_LIGHT: { inst = light_owner.getornull(p_base); ERR_FAIL_COND(!inst); @@ -4005,6 +4303,9 @@ VS::InstanceType RasterizerStorageGLES3::get_base_type(RID p_rid) const { if (light_owner.owns(p_rid)) { return VS::INSTANCE_LIGHT; } + if (reflection_probe_owner.owns(p_rid)) { + return VS::INSTANCE_REFLECTION_PROBE; + } return VS::INSTANCE_NONE; } @@ -4028,6 +4329,12 @@ bool RasterizerStorageGLES3::free(RID p_rid){ info.texture_mem-=texture->total_data_size; texture_owner.free(p_rid); memdelete(texture); + } else if (skybox_owner.owns(p_rid)) { + // delete the skybox + SkyBox *skybox = skybox_owner.get(p_rid); + skybox_set_texture(p_rid,RID(),256); + skybox_owner.free(p_rid); + memdelete(skybox); } else if (shader_owner.owns(p_rid)) { @@ -4259,6 +4566,8 @@ void RasterizerStorageGLES3::initialize() { shaders.cubemap_filter.init(); glEnable(_EXT_TEXTURE_CUBE_MAP_SEAMLESS); + + frame.count=0; } void RasterizerStorageGLES3::finalize() { diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index 0e3d47b61f..5f07efeb0a 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -226,6 +226,19 @@ public: virtual RID texture_create_radiance_cubemap(RID p_source,int p_resolution=-1) const; + /* SKYBOX API */ + + struct SkyBox : public RID_Data { + + RID cubemap; + GLuint radiance; + int radiance_size; + }; + + mutable RID_Owner skybox_owner; + + virtual RID skybox_create(); + virtual void skybox_set_texture(RID p_skybox,RID p_cube_map,int p_radiance_size); /* SHADER API */ @@ -679,18 +692,51 @@ public: /* PROBE API */ + struct ReflectionProbe : Instantiable { + + VS::ReflectionProbeUpdateMode update_mode; + float intensity; + Color interior_ambient; + float interior_ambient_energy; + float interior_ambient_probe_contrib; + float max_distance; + Vector3 extents; + Vector3 origin_offset; + bool interior; + bool box_projection; + bool enable_shadows; + uint32_t cull_mask; + + }; + + mutable RID_Owner reflection_probe_owner; + virtual RID reflection_probe_create(); + virtual void reflection_probe_set_update_mode(RID p_probe, VS::ReflectionProbeUpdateMode p_mode); virtual void reflection_probe_set_intensity(RID p_probe, float p_intensity); - virtual void reflection_probe_set_clip(RID p_probe, float p_near, float p_far); - virtual void reflection_probe_set_min_blend_distance(RID p_probe, float p_distance); + virtual void reflection_probe_set_interior_ambient(RID p_probe, const Color& p_ambient); + virtual void reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy); + virtual void reflection_probe_set_interior_ambient_probe_contribution(RID p_probe, float p_contrib); + virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance); virtual void reflection_probe_set_extents(RID p_probe, const Vector3& p_extents); virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3& p_offset); - virtual void reflection_probe_set_enable_parallax_correction(RID p_probe, bool p_enable); - virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution); - virtual void reflection_probe_set_hide_skybox(RID p_probe, bool p_hide); + virtual void reflection_probe_set_as_interior(RID p_probe, bool p_enable); + 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 AABB reflection_probe_get_aabb(RID p_probe) const; + virtual VS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const; + virtual uint32_t reflection_probe_get_cull_mask(RID p_probe) const; + + virtual Vector3 reflection_probe_get_extents(RID p_probe) const; + virtual Vector3 reflection_probe_get_origin_offset(RID p_probe) const; + virtual float reflection_probe_get_origin_max_distance(RID p_probe) const; + virtual bool reflection_probe_renders_shadows(RID p_probe) const; + + + /* ROOM API */ @@ -813,6 +859,7 @@ public: Color clear_request_color; int canvas_draw_commands; float time[4]; + uint64_t count; } frame; void initialize(); diff --git a/drivers/gles3/shaders/cubemap_filter.glsl b/drivers/gles3/shaders/cubemap_filter.glsl index 998a59833e..768d20ad22 100644 --- a/drivers/gles3/shaders/cubemap_filter.glsl +++ b/drivers/gles3/shaders/cubemap_filter.glsl @@ -151,14 +151,47 @@ vec2 Hammersley(uint i, uint N) { return vec2(float(i)/float(N), radicalInverse_VdC(i)); } -#define SAMPLE_COUNT 1024u + + +#ifdef LOW_QUALITY + +#define SAMPLE_COUNT 64u + +#else + +#define SAMPLE_COUNT 512u + +#endif + +uniform bool z_flip; void main() { +#ifdef USE_DUAL_PARABOLOID + + vec3 N = vec3( uv_interp * 2.0 - 1.0, 0.0 ); + N.z = 0.5 - 0.5*((N.x * N.x) + (N.y * N.y)); + N = normalize(N); + + if (!z_flip) { + N.y=-N.y; //y is flipped to improve blending between both sides + } else { + N.z=-N.z; + } + + +#else vec2 uv = (uv_interp * 2.0) - 1.0; vec3 N = texelCoordToVec(uv, face_id); - +#endif //vec4 color = color_interp; + +#ifdef USE_DIRECT_WRITE + + frag_color=vec4(texture(N,source_cube).rgb,1.0); + +#else + vec4 sum = vec4(0.0, 0.0, 0.0, 0.0); for(uint sampleNum = 0u; sampleNum < SAMPLE_COUNT; sampleNum++) { @@ -178,5 +211,8 @@ void main() { sum /= sum.a; frag_color = vec4(sum.rgb, 1.0); + +#endif + } diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index ceb5a72118..a923c130dc 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -64,6 +64,8 @@ layout(std140) uniform SceneData { //ubo:0 vec2 shadow_atlas_pixel_size; vec2 directional_shadow_pixel_size; + float reflection_multiplier; + }; uniform highp mat4 world_transform; @@ -288,11 +290,11 @@ in vec3 normal_interp; //used on forward mainly uniform bool no_ambient_light; +uniform sampler2D brdf_texture; //texunit:-1 -#ifdef USE_RADIANCE_CUBEMAP +#ifdef USE_RADIANCE_MAP -uniform sampler2D brdf_texture; //texunit:-1 -uniform samplerCube radiance_cube; //texunit:-2 +uniform sampler2D radiance_map; //texunit:-2 layout(std140) uniform Radiance { //ubo:2 @@ -343,6 +345,8 @@ layout(std140) uniform SceneData { vec2 shadow_atlas_pixel_size; vec2 directional_shadow_pixel_size; + float reflection_multiplier; + }; //directional light data @@ -398,6 +402,24 @@ layout(std140) uniform SpotLightData { //ubo:5 uniform highp sampler2DShadow shadow_atlas; //texunit:-3 +struct ReflectionData { + + mediump vec4 box_extents; + mediump vec4 box_offset; + mediump vec4 params; // intensity, 0, interior , boxproject + mediump vec4 ambient; //ambient color, energy + mediump vec4 atlas_clamp; + highp mat4 local_matrix; //up to here for spot and omni, rest is for directional + //notes: for ambientblend, use distance to edge to blend between already existing global environment +}; + +layout(std140) uniform ReflectionProbeData { //ubo:6 + + ReflectionData reflections[MAX_REFLECTION_DATA_STRUCTS]; +}; +uniform mediump sampler2D reflection_atlas; //texunit:-5 + + #ifdef USE_FORWARD_LIGHTING uniform int omni_light_indices[MAX_FORWARD_LIGHTS]; @@ -406,6 +428,9 @@ uniform int omni_light_count; uniform int spot_light_indices[MAX_FORWARD_LIGHTS]; uniform int spot_light_count; +uniform int reflection_indices[MAX_FORWARD_LIGHTS]; +uniform int reflection_count; + #endif @@ -578,6 +603,120 @@ void light_process_spot(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 al } +void reflection_process(int idx, vec3 vertex, vec3 normal,float roughness,vec3 ambient,vec3 skybox,vec2 brdf, inout highp vec4 reflection_accum,inout highp vec4 ambient_accum) { + + vec3 ref_vec = normalize(reflect(vertex,normal)); + vec3 local_pos = (reflections[idx].local_matrix * vec4(vertex,1.0)).xyz; + vec3 box_extents = reflections[idx].box_extents.xyz; + + if (any(greaterThan(abs(local_pos),box_extents))) { //out of the reflection box + return; + } + + vec3 inner_pos = abs(local_pos / box_extents); + float blend = max(inner_pos.x,max(inner_pos.y,inner_pos.z)); + //make blend more rounded + blend=mix(length(inner_pos),blend,blend); + blend*=blend; + blend=1.001-blend; + + if (reflections[idx].params.x>0.0){// compute reflection + + vec3 local_ref_vec = (reflections[idx].local_matrix * vec4(ref_vec,0.0)).xyz; + + if (reflections[idx].params.w > 0.5) { //box project + + vec3 nrdir = normalize(local_ref_vec); + vec3 rbmax = (box_extents - local_pos)/nrdir; + vec3 rbmin = (-box_extents - local_pos)/nrdir; + + + vec3 rbminmax = mix(rbmin,rbmax,greaterThan(nrdir,vec3(0.0,0.0,0.0))); + + float fa = min(min(rbminmax.x, rbminmax.y), rbminmax.z); + vec3 posonbox = local_pos + nrdir * fa; + local_ref_vec = posonbox - reflections[idx].box_offset.xyz; + } + + + + vec3 splane=normalize(local_ref_vec); + vec4 clamp_rect=reflections[idx].atlas_clamp; + + splane.z*=-1.0; + if (splane.z>=0.0) { + splane.z+=1.0; + clamp_rect.y+=clamp_rect.w; + } else { + splane.z=1.0 - splane.z; + splane.y=-splane.y; + } + + splane.xy/=splane.z; + splane.xy=splane.xy * 0.5 + 0.5; + + splane.xy = splane.xy * clamp_rect.zw + clamp_rect.xy; + splane.xy = clamp(splane.xy,clamp_rect.xy,clamp_rect.xy+clamp_rect.zw); + + highp vec4 reflection; + reflection.rgb = textureLod(reflection_atlas,splane.xy,roughness*5.0).rgb * ( brdf.x + brdf.y); + if (reflections[idx].params.z < 0.5) { + reflection.rgb = mix(skybox,reflection.rgb,blend); + } + reflection.rgb*=reflections[idx].params.x; + reflection.a = blend; + reflection.rgb*=reflection.a; + + reflection_accum+=reflection; + } + + if (reflections[idx].ambient.a>0.0) { //compute ambient using skybox + + + vec3 local_amb_vec = (reflections[idx].local_matrix * vec4(normal,0.0)).xyz; + + vec3 splane=normalize(local_amb_vec); + vec4 clamp_rect=reflections[idx].atlas_clamp; + + splane.z*=-1.0; + if (splane.z>=0.0) { + splane.z+=1.0; + clamp_rect.y+=clamp_rect.w; + } else { + splane.z=1.0 - splane.z; + splane.y=-splane.y; + } + + splane.xy/=splane.z; + splane.xy=splane.xy * 0.5 + 0.5; + + splane.xy = splane.xy * clamp_rect.zw + clamp_rect.xy; + splane.xy = clamp(splane.xy,clamp_rect.xy,clamp_rect.xy+clamp_rect.zw); + + highp vec4 ambient_out; + ambient_out.a=blend; + ambient_out.rgb = textureLod(reflection_atlas,splane.xy,5.0).rgb; + ambient_out.rgb=mix(reflections[idx].ambient.rgb,ambient_out.rgb,reflections[idx].ambient.a); + if (reflections[idx].params.z < 0.5) { + ambient_out.rgb = mix(ambient,ambient_out.rgb,blend); + } + + ambient_out.rgb *= ambient_out.a; + ambient_accum+=ambient_out; + } else { + + highp vec4 ambient_out; + ambient_out.a=blend; + ambient_out.rgb=reflections[idx].ambient.rgb; + if (reflections[idx].params.z < 0.5) { + ambient_out.rgb = mix(ambient,ambient_out.rgb,blend); + } + ambient_out.rgb *= ambient_out.a; + ambient_accum+=ambient_out; + + } +} + void main() { #ifdef RENDER_SHADOW_DUAL_PARABOLOID @@ -666,31 +805,56 @@ FRAGMENT_SHADER_CODE vec3 eye_vec = -normalize( vertex_interp ); -#ifdef USE_RADIANCE_CUBEMAP +#ifndef RENDER_SHADOW + float ndotv = clamp(dot(normal,eye_vec),0.0,1.0); + vec2 brdf = texture(brdf_texture, vec2(roughness, ndotv)).xy; +#endif + +#ifdef USE_RADIANCE_MAP if (no_ambient_light) { ambient_light=vec3(0.0,0.0,0.0); } else { { - float ndotv = clamp(dot(normal,eye_vec),0.0,1.0); - vec2 brdf = texture(brdf_texture, vec2(roughness, ndotv)).xy; + float lod = roughness * 5.0; - vec3 r = reflect(-eye_vec,normal); //2.0 * ndotv * normal - view; // reflect(v, n); - r=normalize((radiance_inverse_xform * vec4(r,0.0)).xyz); - vec3 radiance = textureLod(radiance_cube, r, lod).xyz * ( brdf.x + brdf.y); - specular_light=mix(albedo,radiance,specular); + { //read radiance from dual paraboloid + + vec3 ref_vec = reflect(-eye_vec,normal); //2.0 * ndotv * normal - view; // reflect(v, n); + ref_vec=normalize((radiance_inverse_xform * vec4(ref_vec,0.0)).xyz); + + vec3 norm = normalize(ref_vec); + float y_ofs=0.0; + if (norm.z>=0.0) { + + norm.z+=1.0; + y_ofs+=0.5; + } else { + norm.z=1.0 - norm.z; + norm.y=-norm.y; + } + + norm.xy/=norm.z; + norm.xy=norm.xy * vec2(0.5,0.25) + vec2(0.5,0.25+y_ofs); + vec3 radiance = textureLod(radiance_map, norm.xy, lod).xyz * ( brdf.x + brdf.y); + specular_light=mix(albedo,radiance,specular); + + } + //no longer a cubemap + //vec3 radiance = textureLod(radiance_cube, r, lod).xyz * ( brdf.x + brdf.y); } { - vec3 ambient_dir=normalize((radiance_inverse_xform * vec4(normal,0.0)).xyz); + /*vec3 ambient_dir=normalize((radiance_inverse_xform * vec4(normal,0.0)).xyz); vec3 env_ambient=textureLod(radiance_cube, ambient_dir, 5.0).xyz; - ambient_light=mix(ambient_light_color.rgb,env_ambient,radiance_ambient_contribution); + ambient_light=mix(ambient_light_color.rgb,env_ambient,radiance_ambient_contribution);*/ + ambient_light=vec3(0.0,0.0,0.0); } } @@ -840,6 +1004,21 @@ FRAGMENT_SHADER_CODE #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;i0.0) { + specular_light=reflection_accum.rgb/reflection_accum.a; + specular_light*=specular; + } + if (ambient_accum.a>0.0) { + ambient_light=ambient_accum.rgb/ambient_accum.a; + } + for(int i=0;i Date: Sun, 20 Nov 2016 22:49:53 -0300 Subject: Huge amount of improvement in the material system. Materials should be a lot more complete and usable now. --- drivers/gles3/rasterizer_canvas_gles3.cpp | 4 + drivers/gles3/rasterizer_scene_gles3.cpp | 7 +- drivers/gles3/rasterizer_storage_gles3.cpp | 20 ++- drivers/gles3/rasterizer_storage_gles3.h | 1 + drivers/gles3/shader_compiler_gles3.cpp | 51 +++++++- drivers/gles3/shaders/scene.glsl | 195 +++++++++++++++++++++-------- 6 files changed, 219 insertions(+), 59 deletions(-) (limited to 'drivers/gles3') diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index 4573f94d22..10a8912561 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -934,9 +934,13 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list,int p_z,const if (!t) { switch(texture_hints[i]) { + case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK: { glBindTexture(GL_TEXTURE_2D,storage->resources.black_tex); } break; + case ShaderLanguage::ShaderNode::Uniform::HINT_ANISO: { + glBindTexture(GL_TEXTURE_2D,storage->resources.aniso_tex); + } break; case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: { glBindTexture(GL_TEXTURE_2D,storage->resources.normal_tex); } break; diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index e04908ea67..3ead218226 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -1035,9 +1035,13 @@ bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material* p_m if (!t) { //check hints switch(texture_hints[i]) { + case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK: { glBindTexture(GL_TEXTURE_2D,storage->resources.black_tex); } break; + case ShaderLanguage::ShaderNode::Uniform::HINT_ANISO: { + glBindTexture(GL_TEXTURE_2D,storage->resources.aniso_tex); + } break; case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: { glBindTexture(GL_TEXTURE_2D,storage->resources.normal_tex); } break; @@ -1046,7 +1050,6 @@ bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material* p_m } break; } - glBindTexture(GL_TEXTURE_2D,storage->resources.white_tex); continue; } @@ -1054,7 +1057,7 @@ bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material* p_m //if SRGB decode extension is present, simply switch the texture to whathever is needed bool must_srgb=false; - if (t->srgb && texture_hints[i]==ShaderLanguage::ShaderNode::Uniform::HINT_ALBEDO) { + if (t->srgb && (texture_hints[i]==ShaderLanguage::ShaderNode::Uniform::HINT_ALBEDO || texture_hints[i]==ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO)) { must_srgb=true; } diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 8188fe3adb..669ab96036 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -2285,6 +2285,7 @@ void RasterizerStorageGLES3::_update_material(Material* material) { if (V) { //user provided _fill_std140_variant_ubo_value(E->get().type,V->get(),data,material->shader->mode==VS::SHADER_SPATIAL); + } else if (E->get().default_value.size()){ //default value _fill_std140_ubo_value(E->get().type,E->get().default_value,data); @@ -3304,7 +3305,7 @@ RID RasterizerStorageGLES3::light_create(VS::LightType p_type){ light->type=p_type; light->param[VS::LIGHT_PARAM_ENERGY]=1.0; - light->param[VS::LIGHT_PARAM_SPECULAR]=1.0; + light->param[VS::LIGHT_PARAM_SPECULAR]=0.5; light->param[VS::LIGHT_PARAM_RANGE]=1.0; light->param[VS::LIGHT_PARAM_SPOT_ANGLE]=45; light->param[VS::LIGHT_PARAM_SHADOW_MAX_DISTANCE]=0; @@ -4491,7 +4492,7 @@ void RasterizerStorageGLES3::initialize() { glGenTextures(1, &resources.black_tex); unsigned char blacktexdata[8*8*3]; - for(int i=0;i<8*8;i++) { + for(int i=0;i<8*8*3;i++) { blacktexdata[i]=0; } @@ -4515,6 +4516,21 @@ void RasterizerStorageGLES3::initialize() { glGenerateMipmap(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D,0); + + glGenTextures(1, &resources.aniso_tex); + unsigned char anisotexdata[8*8*3]; + for(int i=0;i<8*8*3;i+=3) { + anisotexdata[i+0]=255; + anisotexdata[i+1]=128; + anisotexdata[i+2]=0; + } + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,resources.aniso_tex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE,anisotexdata); + glGenerateMipmap(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D,0); + } glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS,&config.max_texture_image_units); diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index 5f07efeb0a..b433bcd517 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -74,6 +74,7 @@ public: GLuint white_tex; GLuint black_tex; GLuint normal_tex; + GLuint aniso_tex; GLuint quadie; GLuint quadie_array; diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp index dce52ecd93..c54fc011e9 100644 --- a/drivers/gles3/shader_compiler_gles3.cpp +++ b/drivers/gles3/shader_compiler_gles3.cpp @@ -52,6 +52,7 @@ static int _get_datatype_size(SL::DataType p_type) { } + static String _prestr(SL::DataPrecision p_pres) { @@ -248,7 +249,11 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener r_gen_code.texture_hints.resize(max_texture_uniforms); Vector uniform_sizes; + Vector uniform_alignments; + Vector uniform_defines; uniform_sizes.resize(max_uniforms); + uniform_alignments.resize(max_uniforms); + uniform_defines.resize(max_uniforms); for(Map::Element *E=pnode->uniforms.front();E;E=E->next()) { @@ -272,19 +277,31 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener r_gen_code.defines.push_back(String("#define USE_MATERIAL\n").ascii()); } - r_gen_code.uniforms+=ucode; + uniform_defines[E->get().order]=ucode; uniform_sizes[E->get().order]=_get_datatype_size(E->get().type); + uniform_alignments[E->get().order]=MIN(16,_get_datatype_size(E->get().type)); } p_actions.uniforms->insert(E->key(),E->get()); } + for(int i=0;i0) + if (i>0) { + + int align = uniform_sizes[i-1] % uniform_alignments[i]; + if (align!=0) { + uniform_sizes[i-1]+=uniform_alignments[i]-align; + } + uniform_sizes[i]=uniform_sizes[i]+uniform_sizes[i-1]; + + } } //offset r_gen_code.uniform_offsets.resize(uniform_sizes.size()); @@ -294,8 +311,21 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener r_gen_code.uniform_offsets[i]=uniform_sizes[i-1]; else r_gen_code.uniform_offsets[i]=0; + + } +/* + for(Map::Element *E=pnode->uniforms.front();E;E=E->next()) { + + if (SL::is_sampler_type(E->get().type)) { + continue; + } + + print_line("u - "+String(E->key())+" offset: "+itos(r_gen_code.uniform_offsets[E->get().order])); + } + +*/ if (uniform_sizes.size()) { r_gen_code.uniform_total_size=uniform_sizes[ uniform_sizes.size() -1 ]; } else { @@ -549,13 +579,11 @@ Error ShaderCompilerGLES3::compile(VS::ShaderMode p_mode, const String& p_code, r_gen_code.uses_vertex_time=false; - used_name_defines.clear(); used_rmode_defines.clear(); _dump_node_code(parser.get_shader(),1,r_gen_code,*p_actions,actions[p_mode]); - return OK; } @@ -636,8 +664,14 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() { actions[VS::SHADER_SPATIAL].renames["ALPHA"]="alpha"; actions[VS::SHADER_SPATIAL].renames["SPECULAR"]="specular"; actions[VS::SHADER_SPATIAL].renames["ROUGHNESS"]="roughness"; + actions[VS::SHADER_SPATIAL].renames["RIM"]="rim"; + actions[VS::SHADER_SPATIAL].renames["RIM_TINT"]="rim_tint"; + actions[VS::SHADER_SPATIAL].renames["CLEARCOAT"]="clearcoat"; + actions[VS::SHADER_SPATIAL].renames["CLEARCOAT_GLOSS"]="clearcoat_gloss"; + actions[VS::SHADER_SPATIAL].renames["ANISOTROPY"]="anisotropy"; + actions[VS::SHADER_SPATIAL].renames["ANISOTROPY_FLOW"]="anisotropy_flow"; + actions[VS::SHADER_SPATIAL].renames["AO"]="ao"; actions[VS::SHADER_SPATIAL].renames["EMISSION"]="emission"; - actions[VS::SHADER_SPATIAL].renames["SPECIAL"]="special"; actions[VS::SHADER_SPATIAL].renames["DISCARD"]="_discard"; // actions[VS::SHADER_SPATIAL].renames["SCREEN_UV"]=ShaderLanguage::TYPE_VEC2; actions[VS::SHADER_SPATIAL].renames["POINT_COORD"]="gl_PointCoord"; @@ -645,6 +679,13 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() { actions[VS::SHADER_SPATIAL].usage_defines["TANGENT"]="#define ENABLE_TANGENT_INTERP\n"; actions[VS::SHADER_SPATIAL].usage_defines["BINORMAL"]="@TANGENT"; + actions[VS::SHADER_SPATIAL].usage_defines["RIM"]="#define LIGHT_USE_RIM\n"; + actions[VS::SHADER_SPATIAL].usage_defines["RIM_TINT"]="@RIM"; + actions[VS::SHADER_SPATIAL].usage_defines["CLEARCOAT"]="#define LIGHT_USE_CLEARCOAT\n"; + actions[VS::SHADER_SPATIAL].usage_defines["CLEARCOAT_GLOSS"]="@CLEARCOAT"; + actions[VS::SHADER_SPATIAL].usage_defines["ANISOTROPY"]="#define LIGHT_USE_ANISOTROPY\n"; + actions[VS::SHADER_SPATIAL].usage_defines["ANISOTROPY_FLOW"]="@ANISOTROPY"; + actions[VS::SHADER_SPATIAL].usage_defines["AO"]="#define ENABLE_AO\n"; actions[VS::SHADER_SPATIAL].usage_defines["UV"]="#define ENABLE_UV_INTERP\n"; actions[VS::SHADER_SPATIAL].usage_defines["UV2"]="#define ENABLE_UV2_INTERP\n"; actions[VS::SHADER_SPATIAL].usage_defines["NORMALMAP"]="#define ENABLE_NORMALMAP\n"; diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index a923c130dc..aa8b3cacdc 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -108,7 +108,7 @@ out vec2 uv2_interp; #endif -#if defined(ENABLE_TANGENT_INTERP) +#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY) out vec3 tangent_interp; out vec3 binormal_interp; #endif @@ -146,7 +146,7 @@ void main() { highp mat4 modelview = camera_inverse_matrix * world_transform; vec3 normal = normal_attrib * normal_mult; -#if defined(ENABLE_TANGENT_INTERP) +#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; @@ -163,7 +163,7 @@ void main() { vertex = vertex_in * m; normal = (vec4(normal,0.0) * m).xyz; -#if defined(ENABLE_TANGENT_INTERP) +#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY) tangent = (vec4(tangent,0.0) * m).xyz; #endif } @@ -176,7 +176,7 @@ void main() { normal = normalize((modelview * vec4(normal,0.0)).xyz); #endif -#if defined(ENABLE_TANGENT_INTERP) +#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY) # if !defined(SKIP_TRANSFORM_USED) tangent=normalize((modelview * vec4(tangent,0.0)).xyz); @@ -207,7 +207,7 @@ VERTEX_SHADER_CODE vertex_interp = vertex.xyz; normal_interp = normal; -#if defined(ENABLE_TANGENT_INTERP) +#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY) tangent_interp = tangent; binormal_interp = binormal; #endif @@ -276,7 +276,7 @@ in vec2 uv_interp; in vec2 uv2_interp; #endif -#if defined(ENABLE_TANGENT_INTERP) +#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY) in vec3 tangent_interp; in vec3 binormal_interp; #endif @@ -455,40 +455,86 @@ float G1V(float dotNV, float k) return 1.0 / (dotNV * (1.0 - k) + k); } -float specularGGX(vec3 N, vec3 V, vec3 L, float roughness, float F0) + +float SchlickFresnel(float u) { - float alpha = roughness * roughness; + float m = 1.0-u; + float m2 = m*m; + return m2*m2*m; // pow(m,5) +} + +float GTR1(float NdotH, float a) +{ + if (a >= 1.0) return 1.0/M_PI; + float a2 = a*a; + float t = 1.0 + (a2-1.0)*NdotH*NdotH; + return (a2-1.0) / (M_PI*log(a2)*t); +} - vec3 H = normalize(V + L); +void light_compute(vec3 N, vec3 L,vec3 V,vec3 B, vec3 T,vec3 light_color,vec3 diffuse_color, vec3 specular_color, float specular_blob_intensity, float roughness, float rim,float rim_tint, float clearcoat, float clearcoat_gloss,float anisotropy,inout vec3 diffuse, inout vec3 specular) { - float dotNL = max(dot(N,L), 0.0 ); - float dotNV = max(dot(N,V), 0.0 ); - float dotNH = max(dot(N,H), 0.0 ); - float dotLH = max(dot(L,H), 0.0 ); + float dotNL = max(dot(N,L), 0.0 ); + float dotNV = max(dot(N,V), 0.0 ); - // D - float alphaSqr = alpha * alpha; - float pi = M_PI; - float denom = dotNH * dotNH * (alphaSqr - 1.0) + 1.0; - float D = alphaSqr / (pi * denom * denom); +#if defined(LIGHT_USE_RIM) + float rim_light = pow(1.0-dotNV,(1.0-roughness)*16.0); + diffuse += rim_light * rim * mix(vec3(1.0),diffuse_color,rim_tint) * light_color; +#endif - // F - float dotLH5 = pow(1.0 - dotLH, 5.0); - float F = F0 + (1.0 - F0) * (dotLH5); + diffuse += dotNL * light_color * diffuse_color; - // V - float k = alpha / 2.0f; - float vis = G1V(dotNL, k) * G1V(dotNV, k); + if (roughness > 0.0) { - return dotNL * D * F * vis; -} + float alpha = roughness * roughness; + + vec3 H = normalize(V + L); + + float dotNH = max(dot(N,H), 0.0 ); + float dotLH = max(dot(L,H), 0.0 ); + + // D +#if defined(LIGHT_USE_ANISOTROPY) + + 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 dotXH = dot( T, H ); + float dotYH = dot( B, H ); + float pi = M_PI; + float denom = dotXH*dotXH / (ax*ax) + dotYH*dotYH / (ay*ay) + dotNH*dotNH; + float D = 1.0 / ( pi * ax*ay * denom*denom ); + +#else + float alphaSqr = alpha * alpha; + float pi = M_PI; + float denom = dotNH * dotNH * (alphaSqr - 1.0) + 1.0; + float D = alphaSqr / (pi * denom * denom); +#endif + // F + float F0 = 1.0; + float dotLH5 = SchlickFresnel( dotLH ); + float F = F0 + (1.0 - F0) * (dotLH5); + + // V + float k = alpha / 2.0f; + float vis = G1V(dotNL, k) * G1V(dotNV, k); + + float speci = dotNL * D * F * vis; + + specular += speci * light_color * specular_color * specular_blob_intensity; + +#if defined(LIGHT_USE_CLEARCOAT) + float Dr = GTR1(dotNH, mix(.1,.001,clearcoat_gloss)); + float Fr = mix(.04, 1.0, dotLH5); + float Gr = G1V(dotNL, .25) * G1V(dotNV, .25); + + specular += .25*clearcoat*Gr*Fr*Dr; +#endif + } -void light_compute(vec3 normal, vec3 light_vec,vec3 eye_vec,vec3 light_color,vec3 diffuse_color, vec3 specular_color, float roughness, inout vec3 diffuse, inout vec3 specular) { - diffuse += max(0.0,dot(normal,light_vec)) * light_color * diffuse_color; - //specular += specular_ggx( roughness, max(0.0,dot(normal,eye_vec)) ) * specular_color * attenuation; - float s = roughness > 0.0 ? specularGGX(normal,eye_vec,light_vec,roughness,1.0) : 0.0; - specular += s * light_color * specular_color; } @@ -536,7 +582,7 @@ in highp float dp_clip; #endif -void light_process_omni(int idx, vec3 vertex, vec3 eye_vec,vec3 normal,vec3 albedo, vec3 specular, float roughness, 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 specular, float roughness, float rim, float rim_tint, float clearcoat, float clearcoat_gloss,float anisotropy,inout vec3 diffuse_light, inout vec3 specular_light) { vec3 light_rel_vec = omni_lights[idx].light_pos_inv_radius.xyz-vertex; float normalized_distance = length( light_rel_vec )*omni_lights[idx].light_pos_inv_radius.w; @@ -577,11 +623,11 @@ void light_process_omni(int idx, vec3 vertex, vec3 eye_vec,vec3 normal,vec3 albe light_attenuation*=mix(omni_lights[idx].shadow_color.rgb,vec3(1.0),sample_shadow(shadow_atlas,shadow_atlas_pixel_size,splane.xy,splane.z,clamp_rect)); } - light_compute(normal,normalize(light_rel_vec),eye_vec,omni_lights[idx].light_color_energy.rgb*light_attenuation,albedo,specular,roughness,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,specular,omni_lights[idx].light_params.z,roughness,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,diffuse_light,specular_light); } -void light_process_spot(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 albedo, vec3 specular, float roughness, 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 specular, float roughness, float rim,float rim_tint, float clearcoat, float clearcoat_gloss,float anisotropy, inout vec3 diffuse_light, inout vec3 specular_light) { vec3 light_rel_vec = spot_lights[idx].light_pos_inv_radius.xyz-vertex; float normalized_distance = length( light_rel_vec )*spot_lights[idx].light_pos_inv_radius.w; @@ -589,8 +635,8 @@ void light_process_spot(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 al vec3 spot_dir = spot_lights[idx].light_direction_attenuation.xyz; float spot_cutoff=spot_lights[idx].light_params.y; float scos = max(dot(-normalize(light_rel_vec), spot_dir),spot_cutoff); - float rim = (1.0 - scos) / (1.0 - spot_cutoff); - light_attenuation *= 1.0 - pow( rim, spot_lights[idx].light_params.x); + float spot_rim = (1.0 - scos) / (1.0 - spot_cutoff); + light_attenuation *= 1.0 - pow( spot_rim, spot_lights[idx].light_params.x); if (spot_lights[idx].light_params.w>0.5) { //there is a shadowmap @@ -599,11 +645,11 @@ void light_process_spot(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 al light_attenuation*=mix(spot_lights[idx].shadow_color.rgb,vec3(1.0),sample_shadow(shadow_atlas,shadow_atlas_pixel_size,splane.xy,splane.z,spot_lights[idx].light_clamp)); } - light_compute(normal,normalize(light_rel_vec),eye_vec,spot_lights[idx].light_color_energy.rgb*light_attenuation,albedo,specular,roughness,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,specular,spot_lights[idx].light_params.z,roughness,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,diffuse_light,specular_light); } -void reflection_process(int idx, vec3 vertex, vec3 normal,float roughness,vec3 ambient,vec3 skybox,vec2 brdf, inout highp vec4 reflection_accum,inout highp vec4 ambient_accum) { +void reflection_process(int idx, vec3 vertex, vec3 normal,vec3 binormal, vec3 tangent,float roughness,float anisotropy,vec3 ambient,vec3 skybox,vec2 brdf, inout highp vec4 reflection_accum,inout highp vec4 ambient_accum) { vec3 ref_vec = normalize(reflect(vertex,normal)); vec3 local_pos = (reflections[idx].local_matrix * vec4(vertex,1.0)).xyz; @@ -729,7 +775,19 @@ void main() { highp vec3 vertex = vertex_interp; vec3 albedo = vec3(0.8,0.8,0.8); vec3 specular = vec3(0.2,0.2,0.2); + vec3 emission = vec3(0.0,0.0,0.0); float roughness = 1.0; + float rim = 0.0; + float rim_tint = 0.0; + float clearcoat=0.0; + float clearcoat_gloss=0.0; + float anisotropy = 1.0; + vec2 anisotropy_flow = vec2(1.0,0.0); + +#if defined(ENABLE_AO) + float ao=1.0; +#endif + float alpha = 1.0; #ifdef METERIAL_DOUBLESIDED @@ -739,9 +797,12 @@ void main() { #endif -#if defined(ENABLE_TANGENT_INTERP) +#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY) vec3 binormal = normalize(binormal_interp)*side; vec3 tangent = normalize(tangent_interp)*side; +#else + vec3 binormal = vec3(0.0); + vec3 tangent = vec3(0.0); #endif vec3 normal = normalize(normal_interp)*side; @@ -777,9 +838,26 @@ FRAGMENT_SHADER_CODE } + + #if defined(ENABLE_NORMALMAP) - normal = normalize( mix(normal_interp,tangent_interp * normalmap.x + binormal_interp * normalmap.y + normal_interp * normalmap.z,normaldepth) ) * side; + normalmap.xy=normalmap.xy*2.0-1.0; + normalmap.z=sqrt(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; + +#endif + +#if defined(LIGHT_USE_ANISOTROPY) + + if (anisotropy>0.01) { + //rotation matrix + mat3 rot = mat3( tangent, binormal, normal ); + //make local to space + tangent = normalize(rot * vec3(anisotropy_flow.x,anisotropy_flow.y,0.0)); + binormal = normalize(rot * vec3(-anisotropy_flow.y,anisotropy_flow.x,0.0)); + } #endif @@ -799,6 +877,10 @@ FRAGMENT_SHADER_CODE /////////////////////// LIGHTING ////////////////////////////// + //apply energy conservation + vec3 diffuse=mix(albedo,vec3(0.0),specular); + specular = max(vec3(0.04),specular); + vec3 specular_light = vec3(0.0,0.0,0.0); vec3 ambient_light; vec3 diffuse_light = vec3(0.0,0.0,0.0); @@ -839,8 +921,7 @@ FRAGMENT_SHADER_CODE norm.xy/=norm.z; norm.xy=norm.xy * vec2(0.5,0.25) + vec2(0.5,0.25+y_ofs); - vec3 radiance = textureLod(radiance_map, norm.xy, lod).xyz * ( brdf.x + brdf.y); - specular_light=mix(albedo,radiance,specular); + specular_light = textureLod(radiance_map, norm.xy, lod).xyz * ( brdf.x + brdf.y); } //no longer a cubemap @@ -996,7 +1077,7 @@ FRAGMENT_SHADER_CODE #endif //LIGHT_DIRECTIONAL_SHADOW - light_compute(normal,-light_direction_attenuation.xyz,eye_vec,light_color_energy.rgb*light_attenuation,albedo,specular,roughness,diffuse_light,specular_light); + light_compute(normal,-light_direction_attenuation.xyz,eye_vec,binormal,tangent,light_color_energy.rgb*light_attenuation,diffuse,specular,light_params.z,roughness,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,diffuse_light,specular_light); #endif //#USE_LIGHT_DIRECTIONAL @@ -1008,23 +1089,22 @@ FRAGMENT_SHADER_CODE highp vec4 ambient_accum = vec4(0.0,0.0,0.0,0.0); for(int i=0;i0.0) { specular_light=reflection_accum.rgb/reflection_accum.a; - specular_light*=specular; } if (ambient_accum.a>0.0) { ambient_light=ambient_accum.rgb/ambient_accum.a; } for(int i=0;i0.0) ? max_ambient/total_ambient : 0.0; +#endif //ENABLE_AO - diffuse_buffer=vec4(diffuse_light+ambient_light,ambient_scale); + diffuse_buffer=vec4(emission+diffuse_light+ambient_light,ambient_scale); specular_buffer=vec4(specular_light,0.0); normal_mr_buffer=vec4(normal.x,normal.y,max(specular.r,max(specular.g,specular.b)),roughness); @@ -1067,11 +1159,14 @@ LIGHT_SHADER_CODE #ifdef SHADELESS frag_color=vec4(albedo,alpha); #else - frag_color=vec4(ambient_light+diffuse_light+specular_light,alpha); + frag_color=vec4(emission+ambient_light+diffuse_light+specular_light,alpha); #endif //SHADELESS + #endif //USE_MULTIPLE_RENDER_TARGETS + + #endif //RENDER_SHADOW -- cgit v1.2.3 From 70d095d8f201bd83a7106015f8f925ec54a8313c Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Mon, 21 Nov 2016 19:03:39 -0300 Subject: Skeletons are working now. --- drivers/gles3/rasterizer_gles3.cpp | 1 + drivers/gles3/rasterizer_scene_gles3.cpp | 20 +++ drivers/gles3/rasterizer_scene_gles3.h | 1 + drivers/gles3/rasterizer_storage_gles3.cpp | 228 ++++++++++++++++++++++++++--- drivers/gles3/rasterizer_storage_gles3.h | 21 +++ drivers/gles3/shaders/scene.glsl | 43 ++++-- 6 files changed, 285 insertions(+), 29 deletions(-) (limited to 'drivers/gles3') diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index dabb7918a9..63090e53a7 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -124,6 +124,7 @@ void RasterizerGLES3::begin_frame(){ storage->frame.time[3]=Math::fmod(time_total,60); storage->frame.count++; + storage->update_dirty_skeletons(); storage->update_dirty_shaders(); storage->update_dirty_materials(); scene->iteration(); diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 3ead218226..e0a3dbd36e 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -1329,6 +1329,7 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e int current_blend_mode=-1; int prev_shading=-1; + RID prev_skeleton; state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS,true); //by default unshaded (easier to set) @@ -1338,6 +1339,7 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e RenderList::Element *e = p_elements[i]; RasterizerStorageGLES3::Material* material= e->material; + RID skeleton = e->instance->skeleton; bool rebind=first; @@ -1466,6 +1468,18 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e } + if (prev_skeleton!=skeleton) { + if (prev_skeleton.is_valid() != skeleton.is_valid()) { + state.scene_shader.set_conditional(SceneShaderGLES3::USE_SKELETON,skeleton.is_valid()); + rebind=true; + } + if (skeleton.is_valid()) { + RasterizerStorageGLES3::Skeleton *sk = storage->skeleton_owner.getornull(skeleton); + if (sk->size) { + glBindBufferBase(GL_UNIFORM_BUFFER,7,sk->ubo); + } + } + } if (material!=prev_material || rebind) { @@ -1495,6 +1509,7 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e prev_base_type=e->instance->base_type; prev_geometry=e->geometry; prev_shading=shading; + prev_skeleton=skeleton; first=false; } @@ -1504,6 +1519,7 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e glFrontFace(GL_CW); glBindVertexArray(0); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_SKELETON,false); state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_MAP,false); state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_LIGHTING,false); state.scene_shader.set_conditional(SceneShaderGLES3::USE_LIGHT_DIRECTIONAL,false); @@ -3469,6 +3485,10 @@ void RasterizerSceneGLES3::initialize() { state.scene_shader.add_custom_define("#define MAX_REFLECTION_DATA_STRUCTS "+itos(state.max_ubo_reflections)+"\n"); + state.max_skeleton_bones=max_ubo_size/(12*sizeof(float)); + state.scene_shader.add_custom_define("#define MAX_SKELETON_BONES "+itos(state.max_skeleton_bones)+"\n"); + + } GLOBAL_DEF("rendering/gles3/shadow_filter_mode",1); diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 81c13bdc08..31253e56b6 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -98,6 +98,7 @@ public: int max_ubo_lights; int max_forward_lights_per_object; int max_ubo_reflections; + int max_skeleton_bones; diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 669ab96036..c2598e458f 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -2416,12 +2416,15 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::P if (! (p_format&(1<size==p_bones && skeleton->use_2d==p_2d_skeleton) + return; + + if (skeleton->ubo) { + glDeleteBuffers(1,&skeleton->ubo); + skeleton->ubo=0; + } + + skeleton->size=p_bones; + if (p_2d_skeleton) { + skeleton->bones.resize(p_bones*8); + for(int i=0;ibones.size();i+=8) { + skeleton->bones[i+0]=1; + skeleton->bones[i+1]=0; + skeleton->bones[i+2]=0; + skeleton->bones[i+3]=0; + skeleton->bones[i+4]=0; + skeleton->bones[i+5]=1; + skeleton->bones[i+6]=0; + skeleton->bones[i+7]=0; + } + + } else { + skeleton->bones.resize(p_bones*12); + for(int i=0;ibones.size();i+=12) { + skeleton->bones[i+0]=1; + skeleton->bones[i+1]=0; + skeleton->bones[i+2]=0; + skeleton->bones[i+3]=0; + skeleton->bones[i+4]=0; + skeleton->bones[i+5]=1; + skeleton->bones[i+6]=0; + skeleton->bones[i+7]=0; + skeleton->bones[i+8]=0; + skeleton->bones[i+9]=0; + skeleton->bones[i+10]=1; + skeleton->bones[i+11]=0; + } + + } + + + + if (p_bones) { + glGenBuffers(1, &skeleton->ubo); + glBindBuffer(GL_UNIFORM_BUFFER, skeleton->ubo); + glBufferData(GL_UNIFORM_BUFFER, skeleton->bones.size()*sizeof(float), NULL, GL_DYNAMIC_DRAW); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + } + + if (!skeleton->update_list.in_list()) { + skeleton_update_list.add(&skeleton->update_list); + } + + skeleton->instance_change_notify(); + } int RasterizerStorageGLES3::skeleton_get_bone_count(RID p_skeleton) const{ - return 0; + Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); + ERR_FAIL_COND_V(!skeleton,0); + + return skeleton->size; } + void RasterizerStorageGLES3::skeleton_bone_set_transform(RID p_skeleton,int p_bone, const Transform& p_transform){ + Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); + + ERR_FAIL_COND(!skeleton); + ERR_FAIL_INDEX(p_bone,skeleton->size); + ERR_FAIL_COND(skeleton->use_2d); + + float * bones = skeleton->bones.ptr(); + bones[p_bone*12+ 0]=p_transform.basis.elements[0][0]; + bones[p_bone*12+ 1]=p_transform.basis.elements[0][1]; + bones[p_bone*12+ 2]=p_transform.basis.elements[0][2]; + bones[p_bone*12+ 3]=p_transform.origin.x; + bones[p_bone*12+ 4]=p_transform.basis.elements[1][0]; + bones[p_bone*12+ 5]=p_transform.basis.elements[1][1]; + bones[p_bone*12+ 6]=p_transform.basis.elements[1][2]; + bones[p_bone*12+ 7]=p_transform.origin.y; + bones[p_bone*12+ 8]=p_transform.basis.elements[2][0]; + bones[p_bone*12+ 9]=p_transform.basis.elements[2][1]; + bones[p_bone*12+10]=p_transform.basis.elements[2][2]; + bones[p_bone*12+11]=p_transform.origin.z; + + if (!skeleton->update_list.in_list()) { + skeleton_update_list.add(&skeleton->update_list); + } } + + Transform RasterizerStorageGLES3::skeleton_bone_get_transform(RID p_skeleton,int p_bone) const{ - return Transform(); + Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); + + ERR_FAIL_COND_V(!skeleton,Transform()); + ERR_FAIL_INDEX_V(p_bone,skeleton->size,Transform()); + ERR_FAIL_COND_V(skeleton->use_2d,Transform()); + + float * bones = skeleton->bones.ptr(); + Transform mtx; + mtx.basis.elements[0][0]=bones[p_bone*12+ 0]; + mtx.basis.elements[0][1]=bones[p_bone*12+ 1]; + mtx.basis.elements[0][2]=bones[p_bone*12+ 2]; + mtx.origin.x=bones[p_bone*12+ 3]; + mtx.basis.elements[1][0]=bones[p_bone*12+ 4]; + mtx.basis.elements[1][1]=bones[p_bone*12+ 5]; + mtx.basis.elements[1][2]=bones[p_bone*12+ 6]; + mtx.origin.y=bones[p_bone*12+ 7]; + mtx.basis.elements[2][0]=bones[p_bone*12+ 8]; + mtx.basis.elements[2][1]=bones[p_bone*12+ 9]; + mtx.basis.elements[2][2]=bones[p_bone*12+10]; + mtx.origin.z=bones[p_bone*12+11]; + + return mtx; } void RasterizerStorageGLES3::skeleton_bone_set_transform_2d(RID p_skeleton,int p_bone, const Matrix32& p_transform){ + Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); + + ERR_FAIL_COND(!skeleton); + ERR_FAIL_INDEX(p_bone,skeleton->size); + ERR_FAIL_COND(!skeleton->use_2d); + + float * bones = skeleton->bones.ptr(); + bones[p_bone*12+ 0]=p_transform.elements[0][0]; + bones[p_bone*12+ 1]=p_transform.elements[1][0]; + bones[p_bone*12+ 2]=0; + bones[p_bone*12+ 3]=p_transform.elements[2][0]; + bones[p_bone*12+ 4]=p_transform.elements[0][1]; + bones[p_bone*12+ 5]=p_transform.elements[1][1]; + bones[p_bone*12+ 6]=0; + bones[p_bone*12+ 7]=p_transform.elements[2][1]; + + if (!skeleton->update_list.in_list()) { + skeleton_update_list.add(&skeleton->update_list); + } } Matrix32 RasterizerStorageGLES3::skeleton_bone_get_transform_2d(RID p_skeleton,int p_bone) const{ - return Matrix32(); + Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); + + + ERR_FAIL_COND_V(!skeleton,Matrix32()); + ERR_FAIL_INDEX_V(p_bone,skeleton->size,Matrix32()); + ERR_FAIL_COND_V(!skeleton->use_2d,Matrix32()); + + Matrix32 mtx; + + float * bones = skeleton->bones.ptr(); + mtx.elements[0][0]=bones[p_bone*12+ 0]; + mtx.elements[1][0]=bones[p_bone*12+ 1]; + mtx.elements[2][0]=bones[p_bone*12+ 3]; + mtx.elements[0][1]=bones[p_bone*12+ 4]; + mtx.elements[1][1]=bones[p_bone*12+ 5]; + mtx.elements[2][1]=bones[p_bone*12+ 7]; + + return mtx; +} + +void RasterizerStorageGLES3::update_dirty_skeletons() { + + while(skeleton_update_list.first()) { + + Skeleton *skeleton = skeleton_update_list.first()->self(); + if (skeleton->size) { + glBindBuffer(GL_UNIFORM_BUFFER, skeleton->ubo); + glBufferSubData(GL_UNIFORM_BUFFER,0,skeleton->bones.size()*sizeof(float),skeleton->bones.ptr()); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + } + skeleton->instance_change_notify(); + + skeleton_update_list.remove(skeleton_update_list.first()); + } + } /* Light API */ @@ -3795,7 +3966,12 @@ void RasterizerStorageGLES3::instance_add_dependency(RID p_base,RasterizerScene: ERR_FAIL_COND(!inst); } break; default: { - ERR_FAIL(); + if (skeleton_owner.owns(p_base)) { + inst=skeleton_owner.getornull(p_base); + } + if (!inst) { + ERR_FAIL(); + } } } @@ -3821,7 +3997,12 @@ void RasterizerStorageGLES3::instance_remove_dependency(RID p_base,RasterizerSce ERR_FAIL_COND(!inst); } break; default: { - ERR_FAIL(); + if (skeleton_owner.owns(p_base)) { + inst=skeleton_owner.getornull(p_base); + } + if (!inst) { + ERR_FAIL(); + } } } @@ -4378,6 +4559,17 @@ bool RasterizerStorageGLES3::free(RID p_rid){ material_owner.free(p_rid); memdelete(material); + } else if (skeleton_owner.owns(p_rid)) { + + // delete the texture + Skeleton *skeleton = skeleton_owner.get(p_rid); + if (skeleton->update_list.in_list()) { + skeleton_update_list.remove(&skeleton->update_list); + } + skeleton_allocate(p_rid,0,false); + skeleton_owner.free(p_rid); + memdelete(skeleton); + } else if (mesh_owner.owns(p_rid)) { // delete the texture diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index b433bcd517..b5eacacb4e 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -465,6 +465,7 @@ public: struct Attrib { bool enabled; + bool integer; GLuint index; GLint size; GLenum type; @@ -632,6 +633,26 @@ public: /* SKELETON API */ + struct Skeleton : Instantiable { + int size; + bool use_2d; + Vector bones; //4x3 or 4x2 depending on what is needed + GLuint ubo; + SelfList update_list; + + Skeleton() : update_list(this) { + size=0; + use_2d=false; + ubo=0; + } + }; + + mutable RID_Owner skeleton_owner; + + SelfList::List skeleton_update_list; + + void update_dirty_skeletons(); + virtual RID skeleton_create(); virtual void skeleton_allocate(RID p_skeleton,int p_bones,bool p_2d_skeleton=false); virtual int skeleton_get_bone_count(RID p_skeleton) const; diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index aa8b3cacdc..f3dade9e50 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -22,17 +22,27 @@ ARRAY_INDEX=8, layout(location=0) in highp vec4 vertex_attrib; layout(location=1) in vec3 normal_attrib; +#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY) layout(location=2) in vec4 tangent_attrib; +#endif + +#if defined(ENABLE_COLOR_INTERP) layout(location=3) in vec4 color_attrib; +#endif + +#if defined(ENABLE_UV_INTERP) layout(location=4) in vec2 uv_attrib; +#endif + +#if defined(ENABLE_UV2_INTERP) layout(location=5) in vec2 uv2_attrib; +#endif uniform float normal_mult; #ifdef USE_SKELETON -layout(location=6) mediump ivec4 bone_indices; // attrib:6 -layout(location=7) mediump vec4 bone_weights; // attrib:7 -uniform highp sampler2D skeleton_matrices; +layout(location=6) in ivec4 bone_indices; // attrib:6 +layout(location=7) in vec4 bone_weights; // attrib:7 #endif #ifdef USE_ATTRIBUTE_INSTANCING @@ -140,6 +150,15 @@ out highp float dp_clip; #endif +#ifdef USE_SKELETON + +layout(std140) uniform SkeletonData { //ubo:7 + + mat3x4 skeleton[MAX_SKELETON_BONES]; +}; + +#endif + void main() { highp vec4 vertex = vertex_attrib; // vec4(vertex_attrib.xyz * data_attrib.x,1.0); @@ -152,23 +171,25 @@ void main() { float binormalf = tangent_attrib.a; #endif + #ifdef USE_SKELETON { //skeleton transform - highp mat4 m=mat4(texture2D(skeleton_matrices,vec2((bone_indices.x*3.0+0.0)*skeltex_pixel_size,0.0)),texture2D(skeleton_matrices,vec2((bone_indices.x*3.0+1.0)*skeltex_pixel_size,0.0)),texture2D(skeleton_matrices,vec2((bone_indices.x*3.0+2.0)*skeltex_pixel_size,0.0)),vec4(0.0,0.0,0.0,1.0))*bone_weights.x; - m+=mat4(texture2D(skeleton_matrices,vec2((bone_indices.y*3.0+0.0)*skeltex_pixel_size,0.0)),texture2D(skeleton_matrices,vec2((bone_indices.y*3.0+1.0)*skeltex_pixel_size,0.0)),texture2D(skeleton_matrices,vec2((bone_indices.y*3.0+2.0)*skeltex_pixel_size,0.0)),vec4(0.0,0.0,0.0,1.0))*bone_weights.y; - m+=mat4(texture2D(skeleton_matrices,vec2((bone_indices.z*3.0+0.0)*skeltex_pixel_size,0.0)),texture2D(skeleton_matrices,vec2((bone_indices.z*3.0+1.0)*skeltex_pixel_size,0.0)),texture2D(skeleton_matrices,vec2((bone_indices.z*3.0+2.0)*skeltex_pixel_size,0.0)),vec4(0.0,0.0,0.0,1.0))*bone_weights.z; - m+=mat4(texture2D(skeleton_matrices,vec2((bone_indices.w*3.0+0.0)*skeltex_pixel_size,0.0)),texture2D(skeleton_matrices,vec2((bone_indices.w*3.0+1.0)*skeltex_pixel_size,0.0)),texture2D(skeleton_matrices,vec2((bone_indices.w*3.0+2.0)*skeltex_pixel_size,0.0)),vec4(0.0,0.0,0.0,1.0))*bone_weights.w; + highp mat3x4 m=skeleton[bone_indices.x]*bone_weights.x; + m+=skeleton[bone_indices.y]*bone_weights.y; + m+=skeleton[bone_indices.z]*bone_weights.z; + m+=skeleton[bone_indices.w]*bone_weights.w; - vertex = vertex_in * m; - normal = (vec4(normal,0.0) * m).xyz; + vertex.xyz = vertex * m; + + normal = vec4(normal,0.0) * m; #if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY) - tangent = (vec4(tangent,0.0) * m).xyz; + tangent.xyz = vec4(tangent.xyz,0.0) * mn; #endif } +#endif // USE_SKELETON1 -#endif #if !defined(SKIP_TRANSFORM_USED) -- cgit v1.2.3 From 943d27f46ded993105928c4a46414aa16d84115e Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Tue, 22 Nov 2016 01:26:56 -0300 Subject: Instancing is working! (hooray) --- drivers/gles3/rasterizer_gles3.cpp | 1 + drivers/gles3/rasterizer_scene_gles3.cpp | 92 +++++ drivers/gles3/rasterizer_storage_gles3.cpp | 540 ++++++++++++++++++++++++++--- drivers/gles3/rasterizer_storage_gles3.h | 42 ++- drivers/gles3/shaders/scene.glsl | 26 +- 5 files changed, 642 insertions(+), 59 deletions(-) (limited to 'drivers/gles3') diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index 63090e53a7..84fa349313 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -124,6 +124,7 @@ void RasterizerGLES3::begin_frame(){ storage->frame.time[3]=Math::fmod(time_total,60); storage->frame.count++; + storage->update_dirty_multimeshes(); storage->update_dirty_skeletons(); storage->update_dirty_shaders(); storage->update_dirty_materials(); diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index e0a3dbd36e..54dc3b914b 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -1098,6 +1098,55 @@ void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e) { glBindVertexArray(s->array_id); // everything is so easy nowadays } break; + + case VS::INSTANCE_MULTIMESH: { + + RasterizerStorageGLES3::MultiMesh *multi_mesh = static_cast(e->owner); + RasterizerStorageGLES3::Surface *s = static_cast(e->geometry); + glBindVertexArray(s->instancing_array_id); // use the instancing array ID + glBindBuffer(GL_ARRAY_BUFFER,multi_mesh->buffer); //modify the buffer + + int stride = (multi_mesh->xform_floats+multi_mesh->color_floats)*4; + glEnableVertexAttribArray(8); + glVertexAttribPointer(8,4,GL_FLOAT,GL_FALSE,stride,((uint8_t*)NULL)+0); + glVertexAttribDivisorARB(8,1); + glEnableVertexAttribArray(9); + glVertexAttribPointer(9,4,GL_FLOAT,GL_FALSE,stride,((uint8_t*)NULL)+4*4); + glVertexAttribDivisorARB(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); + glVertexAttribDivisorARB(10,1); + color_ofs=12*4; + } else { + glDisableVertexAttribArray(10); + glVertexAttrib4f(10,0,0,1,0); + color_ofs=8*4; + } + + switch(multi_mesh->color_format) { + + case VS::MULTIMESH_COLOR_NONE: { + glDisableVertexAttribArray(11); + glVertexAttrib4f(11,1,1,1,1); + } break; + case VS::MULTIMESH_COLOR_8BIT: { + glEnableVertexAttribArray(11); + glVertexAttribPointer(11,4,GL_UNSIGNED_BYTE,GL_TRUE,stride,((uint8_t*)NULL)+color_ofs); + glVertexAttribDivisorARB(11,1); + + } break; + case VS::MULTIMESH_COLOR_FLOAT: { + glEnableVertexAttribArray(11); + glVertexAttribPointer(11,4,GL_FLOAT,GL_FALSE,stride,((uint8_t*)NULL)+color_ofs); + glVertexAttribDivisorARB(11,1); + } break; + } + + } break; } } @@ -1133,6 +1182,25 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) { } } break; + case VS::INSTANCE_MULTIMESH: { + + RasterizerStorageGLES3::MultiMesh *multi_mesh = static_cast(e->owner); + RasterizerStorageGLES3::Surface *s = static_cast(e->geometry); + + int amount = MAX(multi_mesh->size,multi_mesh->visible_instances); + + if (s->index_array_len>0) { + + glDrawElementsInstancedARB(gl_primitive[s->primitive],s->index_array_len, (s->array_len>=(1<<16))?GL_UNSIGNED_INT:GL_UNSIGNED_SHORT,0,amount); + + } else { + + glDrawArraysInstancedARB(gl_primitive[s->primitive],0,s->array_len,amount); + + } + + } break; + } } @@ -1481,6 +1549,11 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e } } + if ((prev_base_type==VS::INSTANCE_MULTIMESH) != (e->instance->base_type==VS::INSTANCE_MULTIMESH)) { + state.scene_shader.set_conditional(SceneShaderGLES3::USE_INSTANCING,e->instance->base_type==VS::INSTANCE_MULTIMESH); + rebind=true; + } + if (material!=prev_material || rebind) { rebind = _setup_material(material,p_alpha_pass); @@ -1519,6 +1592,7 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e glFrontFace(GL_CW); glBindVertexArray(0); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_INSTANCING,false); state.scene_shader.set_conditional(SceneShaderGLES3::USE_SKELETON,false); state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_MAP,false); state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_LIGHTING,false); @@ -2414,6 +2488,24 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase** p_cull_result,int p_ } break; case VS::INSTANCE_MULTIMESH: { + RasterizerStorageGLES3::MultiMesh *multi_mesh = storage->multimesh_owner.getptr(inst->base); + ERR_CONTINUE(!multi_mesh); + + if (multi_mesh->size==0 || multi_mesh->visible_instances==0) + continue; + + RasterizerStorageGLES3::Mesh *mesh = storage->mesh_owner.getptr(multi_mesh->mesh); + if (!mesh) + continue; //mesh not assigned + + int ssize = mesh->surfaces.size(); + + for (int i=0;isurfaces[i]; + _add_geometry(s,inst,multi_mesh,-1,p_shadow); + } + } break; case VS::INSTANCE_IMMEDIATE: { diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index c2598e458f..e5a0cded8e 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -2716,31 +2716,45 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::P //generate arrays for faster state switching - glGenVertexArrays(1,&surface->array_id); - glBindVertexArray(surface->array_id); - glBindBuffer(GL_ARRAY_BUFFER,surface->vertex_id); + for(int i=0;i<2;i++) { - for(int i=0;iarray_id); + glBindVertexArray(surface->array_id); + glBindBuffer(GL_ARRAY_BUFFER,surface->vertex_id); + } else { + //for instancing draw (can be changed and no one cares) + glGenVertexArrays(1,&surface->instancing_array_id); + glBindVertexArray(surface->instancing_array_id); + glBindBuffer(GL_ARRAY_BUFFER,surface->vertex_id); - if (!attribs[i].enabled) - continue; + } + + + for(int i=0;iindex_id) { + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,surface->index_id); + } - if (surface->index_id) { - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,surface->index_id); + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER,0); //unbind + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); } - glBindVertexArray(0); - glBindBuffer(GL_ARRAY_BUFFER,0); //unbind - } { @@ -3068,14 +3082,14 @@ AABB RasterizerStorageGLES3::mesh_get_aabb(RID p_mesh,RID p_skeleton) const{ if (mesh->custom_aabb!=AABB()) return mesh->custom_aabb; -/* + Skeleton *sk=NULL; if (p_skeleton.is_valid()) sk=skeleton_owner.get(p_skeleton); -*/ + AABB aabb; - /* - if (sk && sk->bones.size()!=0) { + + if (sk && sk->size!=0) { for (int i=0;isurfaces.size();i++) { @@ -3088,21 +3102,67 @@ AABB RasterizerStorageGLES3::mesh_get_aabb(RID p_mesh,RID p_skeleton) const{ const AABB *skbones = mesh->surfaces[i]->skeleton_bone_aabb.ptr(); const bool *skused = mesh->surfaces[i]->skeleton_bone_used.ptr(); - int sbs = sk->bones.size(); + int sbs = sk->size; ERR_CONTINUE(bs>sbs); - Skeleton::Bone *skb = sk->bones.ptr(); + float *skb = sk->bones.ptr(); + + bool first=true; - for(int j=0;juse_2d) { + for(int j=0;jsurfaces.size();i++) { if (i==0) @@ -3125,9 +3185,9 @@ AABB RasterizerStorageGLES3::mesh_get_aabb(RID p_mesh,RID p_skeleton) const{ else aabb.merge_with(mesh->surfaces[i]->aabb); } -/* + } -*/ + return aabb; } @@ -3146,75 +3206,431 @@ void RasterizerStorageGLES3::mesh_clear(RID p_mesh){ RID RasterizerStorageGLES3::multimesh_create(){ - return RID(); + MultiMesh *multimesh = memnew( MultiMesh ); + return multimesh_owner.make_rid(multimesh); } -void RasterizerStorageGLES3::multimesh_allocate(RID p_multimesh,int p_instances,VS::MultimeshTransformFormat p_transform_format,VS::MultimeshColorFormat p_color_format,bool p_gen_aabb){ +void RasterizerStorageGLES3::multimesh_allocate(RID p_multimesh, int p_instances, VS::MultimeshTransformFormat p_transform_format, VS::MultimeshColorFormat p_color_format){ + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND(!multimesh); + + if (multimesh->size==p_instances && multimesh->transform_format==p_transform_format && multimesh->color_format==p_color_format) + return; + + if (multimesh->buffer) { + glDeleteBuffers(1,&multimesh->buffer); + multimesh->data.resize(0); + } + + multimesh->size=p_instances; + multimesh->transform_format=p_transform_format; + multimesh->color_format=p_color_format; + + if (multimesh->size) { + + if (multimesh->transform_format==VS::MULTIMESH_TRANSFORM_2D) { + multimesh->xform_floats=8; + } else { + multimesh->xform_floats=12; + + } + + if (multimesh->color_format==VS::MULTIMESH_COLOR_NONE) { + multimesh->color_floats=0; + } else if (multimesh->color_format==VS::MULTIMESH_COLOR_8BIT) { + multimesh->color_floats=1; + } else if (multimesh->color_format==VS::MULTIMESH_COLOR_FLOAT) { + multimesh->color_floats=4; + } + + int format_floats = multimesh->color_floats+multimesh->xform_floats; + multimesh->data.resize(format_floats*p_instances); + for(int i=0;itransform_format==VS::MULTIMESH_TRANSFORM_2D) { + multimesh->data[i+0]=1.0; + multimesh->data[i+1]=0.0; + multimesh->data[i+2]=0.0; + multimesh->data[i+3]=0.0; + multimesh->data[i+4]=0.0; + multimesh->data[i+5]=1.0; + multimesh->data[i+6]=0.0; + multimesh->data[i+7]=0.0; + color_from=8; + } else { + multimesh->data[i+0]=1.0; + multimesh->data[i+1]=0.0; + multimesh->data[i+2]=0.0; + multimesh->data[i+3]=0.0; + multimesh->data[i+4]=0.0; + multimesh->data[i+5]=1.0; + multimesh->data[i+6]=0.0; + multimesh->data[i+7]=0.0; + multimesh->data[i+8]=0.0; + multimesh->data[i+9]=0.0; + multimesh->data[i+10]=1.0; + multimesh->data[i+11]=0.0; + color_from=12; + } + + if (multimesh->color_format==VS::MULTIMESH_COLOR_NONE) { + //none + } else if (multimesh->color_format==VS::MULTIMESH_COLOR_8BIT) { + + union { + uint32_t colu; + float colf; + } cu; + + cu.colu=0xFFFFFFFF; + multimesh->data[i+color_from+0]=cu.colf; + + } else if (multimesh->color_format==VS::MULTIMESH_COLOR_FLOAT) { + multimesh->data[i+color_from+0]=1.0; + multimesh->data[i+color_from+1]=1.0; + multimesh->data[i+color_from+2]=1.0; + multimesh->data[i+color_from+3]=1.0; + } + } + + glGenBuffers(1,&multimesh->buffer); + glBindBuffer(GL_ARRAY_BUFFER,multimesh->buffer); + glBufferData(GL_ARRAY_BUFFER,multimesh->data.size()*sizeof(float),NULL,GL_DYNAMIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER,0); + + } + + multimesh->dirty_data=true; + multimesh->dirty_aabb=true; + + if (!multimesh->update_list.in_list()) { + multimesh_update_list.add(&multimesh->update_list); + } } + int RasterizerStorageGLES3::multimesh_get_instance_count(RID p_multimesh) const{ - return 0; + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND_V(!multimesh,0); + + return multimesh->size; } void RasterizerStorageGLES3::multimesh_set_mesh(RID p_multimesh,RID p_mesh){ + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND(!multimesh); -} -void RasterizerStorageGLES3::multimesh_set_custom_aabb(RID p_multimesh,const AABB& p_aabb){ + multimesh->mesh=p_mesh; + multimesh->dirty_aabb=true; + if (!multimesh->update_list.in_list()) { + multimesh_update_list.add(&multimesh->update_list); + } } -void RasterizerStorageGLES3::multimesh_instance_set_transform(RID p_multimesh,int p_index,const Transform& p_transform){ +void RasterizerStorageGLES3::multimesh_instance_set_transform(RID p_multimesh,int p_index,const Transform& p_transform){ + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND(!multimesh); + ERR_FAIL_INDEX(p_index,multimesh->size); + ERR_FAIL_COND(multimesh->transform_format==VS::MULTIMESH_TRANSFORM_2D); + + int stride = multimesh->color_floats+multimesh->xform_floats; + float *dataptr=&multimesh->data[stride*p_index]; + + dataptr[ 0]=p_transform.basis.elements[0][0]; + dataptr[ 1]=p_transform.basis.elements[0][1]; + dataptr[ 2]=p_transform.basis.elements[0][2]; + dataptr[ 3]=p_transform.origin.x; + dataptr[ 4]=p_transform.basis.elements[1][0]; + dataptr[ 5]=p_transform.basis.elements[1][1]; + dataptr[ 6]=p_transform.basis.elements[1][2]; + dataptr[ 7]=p_transform.origin.y; + dataptr[ 8]=p_transform.basis.elements[2][0]; + dataptr[ 9]=p_transform.basis.elements[2][1]; + dataptr[10]=p_transform.basis.elements[2][2]; + dataptr[11]=p_transform.origin.z; + + multimesh->dirty_data=true; + multimesh->dirty_aabb=true; + + if (!multimesh->update_list.in_list()) { + multimesh_update_list.add(&multimesh->update_list); + } } + void RasterizerStorageGLES3::multimesh_instance_set_transform_2d(RID p_multimesh,int p_index,const Matrix32& p_transform){ + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND(!multimesh); + ERR_FAIL_INDEX(p_index,multimesh->size); + ERR_FAIL_COND(multimesh->transform_format==VS::MULTIMESH_TRANSFORM_3D); + + int stride = multimesh->color_floats+multimesh->xform_floats; + float *dataptr=&multimesh->data[stride*p_index]; + + dataptr[ 0]=p_transform.elements[0][0]; + dataptr[ 1]=p_transform.elements[1][0]; + dataptr[ 2]=0; + dataptr[ 3]=p_transform.elements[2][0]; + dataptr[ 4]=p_transform.elements[0][1]; + dataptr[ 5]=p_transform.elements[1][1]; + dataptr[ 6]=0; + dataptr[ 7]=p_transform.elements[2][1]; + + multimesh->dirty_data=true; + multimesh->dirty_aabb=true; + if (!multimesh->update_list.in_list()) { + multimesh_update_list.add(&multimesh->update_list); + } } void RasterizerStorageGLES3::multimesh_instance_set_color(RID p_multimesh,int p_index,const Color& p_color){ + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND(!multimesh); + ERR_FAIL_INDEX(p_index,multimesh->size); + ERR_FAIL_COND(multimesh->color_format==VS::MULTIMESH_COLOR_NONE); + + int stride = multimesh->color_floats+multimesh->xform_floats; + float *dataptr=&multimesh->data[stride*p_index+multimesh->color_floats]; + + if (multimesh->color_format==VS::MULTIMESH_COLOR_8BIT) { + union { + uint32_t colu; + float colf; + } cu; + + cu.colu=p_color.to_32(); + dataptr[ 0]=cu.colf; + + } else if (multimesh->color_format==VS::MULTIMESH_COLOR_FLOAT) { + dataptr[ 0]=p_color.r; + dataptr[ 1]=p_color.g; + dataptr[ 2]=p_color.b; + dataptr[ 3]=p_color.a; + } + + + multimesh->dirty_data=true; + multimesh->dirty_aabb=true; + if (!multimesh->update_list.in_list()) { + multimesh_update_list.add(&multimesh->update_list); + } } RID RasterizerStorageGLES3::multimesh_get_mesh(RID p_multimesh) const{ + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND_V(!multimesh,RID()); - return RID(); + return multimesh->mesh; } -AABB RasterizerStorageGLES3::multimesh_get_custom_aabb(RID p_multimesh) const{ - return AABB(); -} Transform RasterizerStorageGLES3::multimesh_instance_get_transform(RID p_multimesh,int p_index) const{ - return Transform(); + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND_V(!multimesh,Transform()); + ERR_FAIL_INDEX_V(p_index,multimesh->size,Transform()); + ERR_FAIL_COND_V(multimesh->transform_format==VS::MULTIMESH_TRANSFORM_2D,Transform()); + + int stride = multimesh->color_floats+multimesh->xform_floats; + float *dataptr=&multimesh->data[stride*p_index]; + + Transform xform; + + xform.basis.elements[0][0]=dataptr[ 0]; + xform.basis.elements[0][1]=dataptr[ 1]; + xform.basis.elements[0][2]=dataptr[ 2]; + xform.origin.x=dataptr[ 3]; + xform.basis.elements[1][0]=dataptr[ 4]; + xform.basis.elements[1][1]=dataptr[ 5]; + xform.basis.elements[1][2]=dataptr[ 6]; + xform.origin.y=dataptr[ 7]; + xform.basis.elements[2][0]=dataptr[ 8]; + xform.basis.elements[2][1]=dataptr[ 9]; + xform.basis.elements[2][2]=dataptr[10]; + xform.origin.z=dataptr[11]; + + return xform; } Matrix32 RasterizerStorageGLES3::multimesh_instance_get_transform_2d(RID p_multimesh,int p_index) const{ + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND_V(!multimesh,Matrix32()); + ERR_FAIL_INDEX_V(p_index,multimesh->size,Matrix32()); + ERR_FAIL_COND_V(multimesh->transform_format==VS::MULTIMESH_TRANSFORM_3D,Matrix32()); + + int stride = multimesh->color_floats+multimesh->xform_floats; + float *dataptr=&multimesh->data[stride*p_index]; + + Matrix32 xform; + + xform.elements[0][0]=dataptr[ 0]; + xform.elements[1][0]=dataptr[ 1]; + xform.elements[2][0]=dataptr[ 3]; + xform.elements[0][1]=dataptr[ 4]; + xform.elements[1][1]=dataptr[ 5]; + xform.elements[2][1]=dataptr[ 7]; - return Matrix32(); + return xform; } + 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()); + ERR_FAIL_COND_V(multimesh->color_format==VS::MULTIMESH_COLOR_NONE,Color()); + + int stride = multimesh->color_floats+multimesh->xform_floats; + float *dataptr=&multimesh->data[stride*p_index+multimesh->color_floats]; + + if (multimesh->color_format==VS::MULTIMESH_COLOR_8BIT) { + union { + uint32_t colu; + float colf; + } cu; + + return Color::hex(cu.colu); + + } else if (multimesh->color_format==VS::MULTIMESH_COLOR_FLOAT) { + Color c; + c.r=dataptr[ 0]; + c.g=dataptr[ 1]; + c.b=dataptr[ 2]; + c.a=dataptr[ 3]; + + return c; + } + return Color(); + } void RasterizerStorageGLES3::multimesh_set_visible_instances(RID p_multimesh,int p_visible){ + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND(!multimesh); + multimesh->visible_instances=p_visible; } int RasterizerStorageGLES3::multimesh_get_visible_instances(RID p_multimesh) const{ - return 0; + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND_V(!multimesh,-1); + + return multimesh->visible_instances; } -AABB RasterizerStorageGLES3::multimesh_get_aabb(RID p_mesh) const{ +AABB RasterizerStorageGLES3::multimesh_get_aabb(RID p_multimesh) const{ - return AABB(); + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND_V(!multimesh,AABB()); + + const_cast(this)->update_dirty_multimeshes(); //update pending AABBs + + return multimesh->aabb; +} + +void RasterizerStorageGLES3::update_dirty_multimeshes() { + + while(multimesh_update_list.first()) { + + MultiMesh *multimesh = multimesh_update_list.first()->self(); + + if (multimesh->size && multimesh->dirty_data) { + + + glBindBuffer(GL_ARRAY_BUFFER,multimesh->buffer); + glBufferSubData(GL_ARRAY_BUFFER,0,multimesh->data.size()*sizeof(float),multimesh->data.ptr()); + glBindBuffer(GL_ARRAY_BUFFER,0); + + + } + + + + if (multimesh->size && multimesh->dirty_aabb) { + + AABB mesh_aabb; + + if (multimesh->mesh.is_valid()) { + mesh_aabb=mesh_get_aabb(multimesh->mesh,RID()); + } else { + mesh_aabb.size+=Vector3(0.001,0.001,0.001); + } + + int stride=multimesh->color_floats+multimesh->xform_floats; + int count = multimesh->data.size(); + float *data=multimesh->data.ptr(); + + AABB aabb; + + if (multimesh->transform_format==VS::MULTIMESH_TRANSFORM_2D) { + + for(int i=0;iaabb=aabb; + } + multimesh->dirty_aabb=false; + multimesh->dirty_data=false; + + multimesh->instance_change_notify(); + + multimesh_update_list.remove(multimesh_update_list.first()); + } } /* IMMEDIATE API */ @@ -3957,6 +4373,10 @@ void RasterizerStorageGLES3::instance_add_dependency(RID p_base,RasterizerScene: inst = mesh_owner.getornull(p_base); ERR_FAIL_COND(!inst); } break; + case VS::INSTANCE_MULTIMESH: { + inst = multimesh_owner.getornull(p_base); + ERR_FAIL_COND(!inst); + } break; case VS::INSTANCE_REFLECTION_PROBE: { inst = reflection_probe_owner.getornull(p_base); ERR_FAIL_COND(!inst); @@ -3988,6 +4408,10 @@ void RasterizerStorageGLES3::instance_remove_dependency(RID p_base,RasterizerSce ERR_FAIL_COND(!inst); } break; + case VS::INSTANCE_MULTIMESH: { + inst = multimesh_owner.getornull(p_base); + ERR_FAIL_COND(!inst); + } break; case VS::INSTANCE_REFLECTION_PROBE: { inst = reflection_probe_owner.getornull(p_base); ERR_FAIL_COND(!inst); @@ -4482,6 +4906,9 @@ VS::InstanceType RasterizerStorageGLES3::get_base_type(RID p_rid) const { if (mesh_owner.owns(p_rid)) { return VS::INSTANCE_MESH; } + if (multimesh_owner.owns(p_rid)) { + return VS::INSTANCE_MULTIMESH; + } if (light_owner.owns(p_rid)) { return VS::INSTANCE_LIGHT; } @@ -4580,6 +5007,17 @@ bool RasterizerStorageGLES3::free(RID p_rid){ mesh_owner.free(p_rid); memdelete(mesh); + } else if (multimesh_owner.owns(p_rid)) { + + // delete the texture + MultiMesh *multimesh = multimesh_owner.get(p_rid); + + multimesh_allocate(p_rid,0,VS::MULTIMESH_TRANSFORM_2D,VS::MULTIMESH_COLOR_NONE); //frees multimesh + update_dirty_multimeshes(); + + multimesh_owner.free(p_rid); + memdelete(multimesh); + } else if (light_owner.owns(p_rid)) { // delete the texture diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index b5eacacb4e..c6712bd8ea 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -482,6 +482,7 @@ public: uint32_t format; GLuint array_id; + GLuint instancing_array_id; GLuint vertex_id; GLuint index_id; @@ -591,20 +592,53 @@ public: /* MULTIMESH API */ + struct MultiMesh : public GeometryOwner { + RID mesh; + int size; + VS::MultimeshTransformFormat transform_format; + VS::MultimeshColorFormat color_format; + Vector data; + AABB aabb; + SelfList update_list; + GLuint buffer; + int visible_instances; + + int xform_floats; + int color_floats; + + bool dirty_aabb; + bool dirty_data; + + MultiMesh() : update_list(this) { + dirty_aabb=true; + dirty_data=true; + xform_floats=0; + color_floats=0; + visible_instances=-1; + size=0; + buffer=0; + transform_format=VS::MULTIMESH_TRANSFORM_2D; + color_format=VS::MULTIMESH_COLOR_NONE; + } + }; + + mutable RID_Owner multimesh_owner; + + SelfList::List multimesh_update_list; + + void update_dirty_multimeshes(); virtual RID multimesh_create(); - virtual void multimesh_allocate(RID p_multimesh,int p_instances,VS::MultimeshTransformFormat p_transform_format,VS::MultimeshColorFormat p_color_format,bool p_gen_aabb=true); + virtual void multimesh_allocate(RID p_multimesh,int p_instances,VS::MultimeshTransformFormat p_transform_format,VS::MultimeshColorFormat p_color_format); virtual int multimesh_get_instance_count(RID p_multimesh) const; virtual void multimesh_set_mesh(RID p_multimesh,RID p_mesh); - virtual void multimesh_set_custom_aabb(RID p_multimesh,const AABB& p_aabb); 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 Matrix32& p_transform); virtual void multimesh_instance_set_color(RID p_multimesh,int p_index,const Color& p_color); virtual RID multimesh_get_mesh(RID p_multimesh) const; - virtual AABB multimesh_get_custom_aabb(RID p_multimesh) const; virtual Transform multimesh_instance_get_transform(RID p_multimesh,int p_index) const; virtual Matrix32 multimesh_instance_get_transform_2d(RID p_multimesh,int p_index) const; @@ -613,7 +647,7 @@ public: virtual void multimesh_set_visible_instances(RID p_multimesh,int p_visible); virtual int multimesh_get_visible_instances(RID p_multimesh) const; - virtual AABB multimesh_get_aabb(RID p_mesh) const; + virtual AABB multimesh_get_aabb(RID p_multimesh) const; /* IMMEDIATE API */ diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index f3dade9e50..c198534728 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -45,7 +45,7 @@ layout(location=6) in ivec4 bone_indices; // attrib:6 layout(location=7) in vec4 bone_weights; // attrib:7 #endif -#ifdef USE_ATTRIBUTE_INSTANCING +#ifdef USE_INSTANCING layout(location=8) in highp vec4 instance_xform0; layout(location=9) in highp vec4 instance_xform1; @@ -171,6 +171,10 @@ void main() { float binormalf = tangent_attrib.a; #endif +#if defined(ENABLE_COLOR_INTERP) + color_interp = color_attrib; +#endif + #ifdef USE_SKELETON @@ -191,6 +195,23 @@ void main() { #endif // USE_SKELETON1 +#ifdef USE_INSTANCING + + { + highp mat3x4 m=mat3x4(instance_xform0,instance_xform1,instance_xform2); + + vertex.xyz = vertex * m; + normal = vec4(normal,0.0) * m; +#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY) + tangent.xyz = vec4(tangent.xyz,0.0) * mn; +#endif + +#if defined(ENABLE_COLOR_INTERP) + color_interp*=instance_color; +#endif + } +#endif //USE_INSTANCING + #if !defined(SKIP_TRANSFORM_USED) vertex = modelview * vertex; @@ -207,9 +228,6 @@ void main() { -#if defined(ENABLE_COLOR_INTERP) - color_interp = color_attrib; -#endif #if defined(ENABLE_UV_INTERP) uv_interp = uv_attrib; -- cgit v1.2.3 From 9d635f06298f84a59160e8e8cce0187cde6cf74e Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Tue, 22 Nov 2016 20:51:56 -0300 Subject: Migrated from GLES to GLAD, fixes many issues. --- drivers/gles3/rasterizer_canvas_gles3.cpp | 134 ++++++++++++++++------------- drivers/gles3/rasterizer_canvas_gles3.h | 3 + drivers/gles3/rasterizer_gles3.cpp | 77 +++++++++++++---- drivers/gles3/rasterizer_scene_gles3.cpp | 21 +++-- drivers/gles3/rasterizer_storage_gles3.cpp | 93 ++++++++++++++------ drivers/gles3/shader_gles3.cpp | 6 +- 6 files changed, 220 insertions(+), 114 deletions(-) (limited to 'drivers/gles3') diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index 10a8912561..1f23387516 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -274,17 +274,7 @@ void RasterizerCanvasGLES3::_draw_polygon(int p_vertex_count, const int* p_indic } if (p_indices) { -#ifdef GLEW_ENABLED glDrawElements(GL_TRIANGLES, p_vertex_count, GL_UNSIGNED_INT, p_indices ); -#else - static const int _max_draw_poly_indices = 16*1024; // change this size if needed!!! - ERR_FAIL_COND(p_vertex_count > _max_draw_poly_indices); - static uint16_t _draw_poly_indices[_max_draw_poly_indices]; - for (int i=0; iframe.canvas_draw_commands++; } @@ -471,14 +443,14 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item,Item *curr Vector2(line->to.x,line->to.y) }; -#ifdef GLEW_ENABLED +#ifdef GLES_OVER_GL if (line->antialiased) glEnable(GL_LINE_SMOOTH); #endif - glLineWidth(line->width); + //glLineWidth(line->width); _draw_gui_primitive(2,verts,NULL,NULL); -#ifdef GLEW_ENABLED +#ifdef GLES_OVER_GL if (line->antialiased) glDisable(GL_LINE_SMOOTH); #endif @@ -1395,7 +1367,7 @@ void RasterizerCanvasGLES3::reset_canvas() { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } //glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); - glLineWidth(1.0); + //glLineWidth(1.0); glBindBuffer(GL_ARRAY_BUFFER,0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); for(int i=0;iis_stdout_verbose()) { @@ -91,9 +124,17 @@ void RasterizerGLES3::initialize() { } #endif - glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB); +#ifdef GLAD_ENABLED + + if(!gladLoadGL()) { + ERR_PRINT("Error initializing GLAD"); + } + + glEnable(_EXT_DEBUG_OUTPUT_SYNCHRONOUS_ARB); glDebugMessageCallbackARB(_gl_debug_print, NULL); - glEnable(GL_DEBUG_OUTPUT); + glEnable(_EXT_DEBUG_OUTPUT); + +#endif /* glDebugMessageControlARB(GL_DEBUG_SOURCE_API_ARB,GL_DEBUG_TYPE_ERROR_ARB,GL_DEBUG_SEVERITY_HIGH_ARB,0,NULL,GL_TRUE); diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 54dc3b914b..f42eea45d4 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -934,7 +934,7 @@ bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material* p_m } if (state.current_line_width!=p_material->line_width) { - glLineWidth(p_material->line_width); + //glLineWidth(MAX(p_material->line_width,1.0)); state.current_line_width=p_material->line_width; } @@ -1109,17 +1109,17 @@ void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e) { int stride = (multi_mesh->xform_floats+multi_mesh->color_floats)*4; glEnableVertexAttribArray(8); glVertexAttribPointer(8,4,GL_FLOAT,GL_FALSE,stride,((uint8_t*)NULL)+0); - glVertexAttribDivisorARB(8,1); + glVertexAttribDivisor(8,1); glEnableVertexAttribArray(9); glVertexAttribPointer(9,4,GL_FLOAT,GL_FALSE,stride,((uint8_t*)NULL)+4*4); - glVertexAttribDivisorARB(9,1); + 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); - glVertexAttribDivisorARB(10,1); + glVertexAttribDivisor(10,1); color_ofs=12*4; } else { glDisableVertexAttribArray(10); @@ -1136,13 +1136,13 @@ void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e) { case VS::MULTIMESH_COLOR_8BIT: { glEnableVertexAttribArray(11); glVertexAttribPointer(11,4,GL_UNSIGNED_BYTE,GL_TRUE,stride,((uint8_t*)NULL)+color_ofs); - glVertexAttribDivisorARB(11,1); + glVertexAttribDivisor(11,1); } break; case VS::MULTIMESH_COLOR_FLOAT: { glEnableVertexAttribArray(11); glVertexAttribPointer(11,4,GL_FLOAT,GL_FALSE,stride,((uint8_t*)NULL)+color_ofs); - glVertexAttribDivisorARB(11,1); + glVertexAttribDivisor(11,1); } break; } @@ -1191,11 +1191,11 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) { if (s->index_array_len>0) { - glDrawElementsInstancedARB(gl_primitive[s->primitive],s->index_array_len, (s->array_len>=(1<<16))?GL_UNSIGNED_INT:GL_UNSIGNED_SHORT,0,amount); + glDrawElementsInstanced(gl_primitive[s->primitive],s->index_array_len, (s->array_len>=(1<<16))?GL_UNSIGNED_INT:GL_UNSIGNED_SHORT,0,amount); } else { - glDrawArraysInstancedARB(gl_primitive[s->primitive],0,s->array_len,amount); + glDrawArraysInstanced(gl_primitive[s->primitive],0,s->array_len,amount); } @@ -3648,10 +3648,9 @@ void RasterizerSceneGLES3::initialize() { } -#ifdef GLEW_ENABLED +#ifdef GLES_OVER_GL //"desktop" opengl needs this. - glEnable(GL_POINT_SPRITE); - glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); + glEnable(GL_PROGRAM_POINT_SIZE); #endif } diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index e5a0cded8e..60cbbc9023 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -62,7 +62,21 @@ #define _GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE #define _GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF - +#define _EXT_COMPRESSED_R11_EAC 0x9270 +#define _EXT_COMPRESSED_SIGNED_R11_EAC 0x9271 +#define _EXT_COMPRESSED_RG11_EAC 0x9272 +#define _EXT_COMPRESSED_SIGNED_RG11_EAC 0x9273 +#define _EXT_COMPRESSED_RGB8_ETC2 0x9274 +#define _EXT_COMPRESSED_SRGB8_ETC2 0x9275 +#define _EXT_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276 +#define _EXT_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277 +#define _EXT_COMPRESSED_RGBA8_ETC2_EAC 0x9278 +#define _EXT_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279 + +#define _EXT_COMPRESSED_RGBA_BPTC_UNORM 0x8E8C +#define _EXT_COMPRESSED_SRGB_ALPHA_BPTC_UNORM 0x8E8D +#define _EXT_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E +#define _EXT_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F Image RasterizerStorageGLES3::_get_gl_image_and_format(const Image& p_image, Image::Format p_format, uint32_t p_flags,GLenum& r_gl_format,GLenum& r_gl_internal_format,GLenum &r_gl_type,bool &r_compressed,bool &srgb) { @@ -77,17 +91,16 @@ Image RasterizerStorageGLES3::_get_gl_image_and_format(const Image& p_image, Ima switch(p_format) { case Image::FORMAT_L8: { - r_gl_internal_format=GL_LUMINANCE; - r_gl_format=GL_LUMINANCE; + r_gl_internal_format=GL_R8; + r_gl_format=GL_RED; r_gl_type=GL_UNSIGNED_BYTE; } break; case Image::FORMAT_LA8: { - r_gl_internal_format=GL_LUMINANCE_ALPHA; - r_gl_format=GL_LUMINANCE_ALPHA; + r_gl_internal_format=GL_RG8; + r_gl_format=GL_RG; r_gl_type=GL_UNSIGNED_BYTE; - } break; case Image::FORMAT_R8: { @@ -120,8 +133,9 @@ Image RasterizerStorageGLES3::_get_gl_image_and_format(const Image& p_image, Ima } break; case Image::FORMAT_RGB565: { - - r_gl_internal_format=GL_RGB565; +#warning TODO: Convert tod 555 if 565 is not supported (GLES3.3-) + r_gl_internal_format=GL_RGB5; + //r_gl_internal_format=GL_RGB565; r_gl_format=GL_RGB; r_gl_type=GL_UNSIGNED_SHORT_5_6_5; @@ -287,7 +301,7 @@ Image RasterizerStorageGLES3::_get_gl_image_and_format(const Image& p_image, Ima if (config.bptc_supported) { - r_gl_internal_format=(config.srgb_decode_supported || p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:GL_COMPRESSED_RGBA_BPTC_UNORM; + r_gl_internal_format=(config.srgb_decode_supported || p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:_EXT_COMPRESSED_RGBA_BPTC_UNORM; r_gl_format=GL_RGBA; r_gl_type=GL_UNSIGNED_BYTE; r_compressed=true; @@ -303,7 +317,7 @@ Image RasterizerStorageGLES3::_get_gl_image_and_format(const Image& p_image, Ima if (config.bptc_supported) { - r_gl_internal_format=GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT; + r_gl_internal_format=_EXT_COMPRESSED_RGB_BPTC_SIGNED_FLOAT; r_gl_format=GL_RGB; r_gl_type=GL_FLOAT; r_compressed=true; @@ -316,7 +330,7 @@ Image RasterizerStorageGLES3::_get_gl_image_and_format(const Image& p_image, Ima if (config.bptc_supported) { - r_gl_internal_format=GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT; + r_gl_internal_format=_EXT_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT; r_gl_format=GL_RGB; r_gl_type=GL_FLOAT; r_compressed=true; @@ -413,7 +427,7 @@ Image RasterizerStorageGLES3::_get_gl_image_and_format(const Image& p_image, Ima if (config.etc2_supported) { - r_gl_internal_format=GL_COMPRESSED_R11_EAC; + r_gl_internal_format=_EXT_COMPRESSED_R11_EAC; r_gl_format=GL_RED; r_gl_type=GL_UNSIGNED_BYTE; r_compressed=true; @@ -427,7 +441,7 @@ Image RasterizerStorageGLES3::_get_gl_image_and_format(const Image& p_image, Ima if (config.etc2_supported) { - r_gl_internal_format=GL_COMPRESSED_SIGNED_R11_EAC; + r_gl_internal_format=_EXT_COMPRESSED_SIGNED_R11_EAC; r_gl_format=GL_RED; r_gl_type=GL_UNSIGNED_BYTE; r_compressed=true; @@ -441,7 +455,7 @@ Image RasterizerStorageGLES3::_get_gl_image_and_format(const Image& p_image, Ima if (config.etc2_supported) { - r_gl_internal_format=GL_COMPRESSED_RG11_EAC; + r_gl_internal_format=_EXT_COMPRESSED_RG11_EAC; r_gl_format=GL_RG; r_gl_type=GL_UNSIGNED_BYTE; r_compressed=true; @@ -454,7 +468,7 @@ Image RasterizerStorageGLES3::_get_gl_image_and_format(const Image& p_image, Ima case Image::FORMAT_ETC2_RG11S: { if (config.etc2_supported) { - r_gl_internal_format=GL_COMPRESSED_SIGNED_RG11_EAC; + r_gl_internal_format=_EXT_COMPRESSED_SIGNED_RG11_EAC; r_gl_format=GL_RG; r_gl_type=GL_UNSIGNED_BYTE; r_compressed=true; @@ -467,7 +481,7 @@ Image RasterizerStorageGLES3::_get_gl_image_and_format(const Image& p_image, Ima if (config.etc2_supported) { - r_gl_internal_format=(config.srgb_decode_supported || p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?GL_COMPRESSED_SRGB8_ETC2:GL_COMPRESSED_RGB8_ETC2; + r_gl_internal_format=(config.srgb_decode_supported || p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB8_ETC2:_EXT_COMPRESSED_RGB8_ETC2; r_gl_format=GL_RGB; r_gl_type=GL_UNSIGNED_BYTE; r_compressed=true; @@ -483,7 +497,7 @@ Image RasterizerStorageGLES3::_get_gl_image_and_format(const Image& p_image, Ima if (config.etc2_supported) { - r_gl_internal_format=(config.srgb_decode_supported || p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:GL_COMPRESSED_RGBA8_ETC2_EAC; + r_gl_internal_format=(config.srgb_decode_supported || p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:_EXT_COMPRESSED_RGBA8_ETC2_EAC; r_gl_format=GL_RGBA; r_gl_type=GL_UNSIGNED_BYTE; r_compressed=true; @@ -499,7 +513,7 @@ Image RasterizerStorageGLES3::_get_gl_image_and_format(const Image& p_image, Ima if (config.etc2_supported) { - r_gl_internal_format=(config.srgb_decode_supported || p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2; + r_gl_internal_format=(config.srgb_decode_supported || p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:_EXT_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2; r_gl_format=GL_RGBA; r_gl_type=GL_UNSIGNED_BYTE; r_compressed=true; @@ -709,6 +723,32 @@ void RasterizerStorageGLES3::texture_set_data(RID p_texture,const Image& p_image glTexParameterf( texture->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); } + //set swizle for older format compatibility + switch(texture->format) { + + case Image::FORMAT_L8: { + glTexParameteri(texture->target,GL_TEXTURE_SWIZZLE_R,GL_RED); + glTexParameteri(texture->target,GL_TEXTURE_SWIZZLE_G,GL_RED); + glTexParameteri(texture->target,GL_TEXTURE_SWIZZLE_B,GL_RED); + glTexParameteri(texture->target,GL_TEXTURE_SWIZZLE_A,GL_ONE); + + } break; + case Image::FORMAT_LA8: { + + glTexParameteri(texture->target,GL_TEXTURE_SWIZZLE_R,GL_RED); + glTexParameteri(texture->target,GL_TEXTURE_SWIZZLE_G,GL_RED); + glTexParameteri(texture->target,GL_TEXTURE_SWIZZLE_B,GL_RED); + glTexParameteri(texture->target,GL_TEXTURE_SWIZZLE_A,GL_GREEN); + } break; + default: { + glTexParameteri(texture->target,GL_TEXTURE_SWIZZLE_R,GL_RED); + glTexParameteri(texture->target,GL_TEXTURE_SWIZZLE_G,GL_GREEN); + glTexParameteri(texture->target,GL_TEXTURE_SWIZZLE_B,GL_BLUE); + glTexParameteri(texture->target,GL_TEXTURE_SWIZZLE_A,GL_ALPHA); + + } break; + + } if (config.use_anisotropic_filter) { if (texture->flags&VS::TEXTURE_FLAG_ANISOTROPIC_FILTER) { @@ -782,7 +822,7 @@ Image RasterizerStorageGLES3::texture_get_data(RID p_texture,VS::CubeMapSide p_c ERR_FAIL_COND_V(texture->data_size==0,Image()); ERR_FAIL_COND_V(texture->render_target,Image()); -#ifdef GLEW_ENABLED +#ifdef GLES_OVER_GL DVector data; @@ -5068,9 +5108,14 @@ void RasterizerStorageGLES3::initialize() { /// { - Vector ext= String((const char*)glGetString( GL_EXTENSIONS )).split(" ",false); - for(int i=0;i strings; -#ifdef GLEW_ENABLED +#ifdef GLES_OVER_GL //strings.push_back("#version 330\n"); strings.push_back("#version 300 es\n"); #else @@ -709,6 +709,8 @@ void ShaderGLES3::setup(const char** p_conditional_defines, int p_conditional_co } } + glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS,&max_image_units); + } void ShaderGLES3::finish() { @@ -804,7 +806,7 @@ ShaderGLES3::ShaderGLES3() { last_custom_code=1; uniforms_dirty = true; base_material_tex_index=0; - glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS,&max_image_units); + } -- cgit v1.2.3 From b72ca046051018628a31bc458dd730384ebddbe8 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Tue, 22 Nov 2016 20:53:37 -0300 Subject: Changed to proper GLSL version --- drivers/gles3/shader_gles3.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gles3') diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp index 0a25f6c3b3..e906f9a790 100644 --- a/drivers/gles3/shader_gles3.cpp +++ b/drivers/gles3/shader_gles3.cpp @@ -221,8 +221,8 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() { Vector strings; #ifdef GLES_OVER_GL - //strings.push_back("#version 330\n"); - strings.push_back("#version 300 es\n"); + strings.push_back("#version 330\n"); + //strings.push_back("#version 300 es\n"); #else strings.push_back("#version 300 es\n"); //ATI requieres this before anything #endif -- cgit v1.2.3 From 7cf8d75cf8c49d02a72eac1d5342808526fa54ef Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Wed, 23 Nov 2016 07:04:55 -0300 Subject: WIP immediates and proper buffers swapping --- drivers/gles3/rasterizer_gles3.cpp | 3 +- drivers/gles3/rasterizer_storage_gles3.cpp | 134 +++++++++++++++++++++++++++-- drivers/gles3/rasterizer_storage_gles3.h | 36 +++++++- drivers/gles3/shader_gles3.cpp | 3 +- 4 files changed, 161 insertions(+), 15 deletions(-) (limited to 'drivers/gles3') diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index ebcedd5f05..9046028705 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -276,8 +276,7 @@ void RasterizerGLES3::end_frame(){ canvas->draw_generic_textured_rect(Rect2(0,0,15,15),Rect2(0,0,1,1)); #endif - if (ContextGL::get_singleton()) - ContextGL::get_singleton()->swap_buffers(); + OS::get_singleton()->swap_buffers(); } void RasterizerGLES3::finalize(){ diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 60cbbc9023..a618953b86 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -3675,57 +3675,157 @@ void RasterizerStorageGLES3::update_dirty_multimeshes() { /* IMMEDIATE API */ -RID RasterizerStorageGLES3::immediate_create(){ - return RID(); +RID RasterizerStorageGLES3::immediate_create() { + + Immediate *im = memnew( Immediate ); + return immediate_owner.make_rid(im); + } -void RasterizerStorageGLES3::immediate_begin(RID p_immediate,VS::PrimitiveType p_rimitive,RID p_texture){ + +void RasterizerStorageGLES3::immediate_begin(RID p_immediate, VS::PrimitiveType p_rimitive, RID p_texture){ + + Immediate *im = immediate_owner.get(p_immediate); + ERR_FAIL_COND(!im); + ERR_FAIL_COND(im->building); + + Immediate::Chunk ic; + ic.texture=p_texture; + ic.primitive=p_rimitive; + im->chunks.push_back(ic); + im->mask=0; + im->building=true; } void RasterizerStorageGLES3::immediate_vertex(RID p_immediate,const Vector3& p_vertex){ + Immediate *im = immediate_owner.get(p_immediate); + ERR_FAIL_COND(!im); + ERR_FAIL_COND(!im->building); -} -void RasterizerStorageGLES3::immediate_vertex_2d(RID p_immediate,const Vector3& p_vertex){ + Immediate::Chunk *c = &im->chunks.back()->get(); + + + if (c->vertices.empty() && im->chunks.size()==1) { + im->aabb.pos=p_vertex; + im->aabb.size=Vector3(); + } else { + im->aabb.expand_to(p_vertex); + } + + if (im->mask&VS::ARRAY_FORMAT_NORMAL) + c->normals.push_back(chunk_normal); + if (im->mask&VS::ARRAY_FORMAT_TANGENT) + c->tangents.push_back(chunk_tangent); + if (im->mask&VS::ARRAY_FORMAT_COLOR) + c->colors.push_back(chunk_color); + if (im->mask&VS::ARRAY_FORMAT_TEX_UV) + c->uvs.push_back(chunk_uv); + if (im->mask&VS::ARRAY_FORMAT_TEX_UV2) + c->uvs2.push_back(chunk_uv2); + im->mask|=VS::ARRAY_FORMAT_VERTEX; + c->vertices.push_back(p_vertex); } + + void RasterizerStorageGLES3::immediate_normal(RID p_immediate,const Vector3& p_normal){ + Immediate *im = immediate_owner.get(p_immediate); + ERR_FAIL_COND(!im); + ERR_FAIL_COND(!im->building); + + im->mask|=VS::ARRAY_FORMAT_NORMAL; + chunk_normal=p_normal; } void RasterizerStorageGLES3::immediate_tangent(RID p_immediate,const Plane& p_tangent){ + Immediate *im = immediate_owner.get(p_immediate); + ERR_FAIL_COND(!im); + ERR_FAIL_COND(!im->building); + + im->mask|=VS::ARRAY_FORMAT_TANGENT; + chunk_tangent=p_tangent; } void RasterizerStorageGLES3::immediate_color(RID p_immediate,const Color& p_color){ + Immediate *im = immediate_owner.get(p_immediate); + ERR_FAIL_COND(!im); + ERR_FAIL_COND(!im->building); + + im->mask|=VS::ARRAY_FORMAT_COLOR; + chunk_color=p_color; } void RasterizerStorageGLES3::immediate_uv(RID p_immediate,const Vector2& tex_uv){ + Immediate *im = immediate_owner.get(p_immediate); + ERR_FAIL_COND(!im); + ERR_FAIL_COND(!im->building); + + im->mask|=VS::ARRAY_FORMAT_TEX_UV; + chunk_uv=tex_uv; } void RasterizerStorageGLES3::immediate_uv2(RID p_immediate,const Vector2& tex_uv){ + Immediate *im = immediate_owner.get(p_immediate); + ERR_FAIL_COND(!im); + ERR_FAIL_COND(!im->building); + + im->mask|=VS::ARRAY_FORMAT_TEX_UV2; + chunk_uv2=tex_uv; } + void RasterizerStorageGLES3::immediate_end(RID p_immediate){ + Immediate *im = immediate_owner.get(p_immediate); + ERR_FAIL_COND(!im); + ERR_FAIL_COND(!im->building); + + im->building=false; + + im->instance_change_notify(); } -void RasterizerStorageGLES3::immediate_clear(RID p_immediate){ +void RasterizerStorageGLES3::immediate_clear(RID p_immediate) { + + Immediate *im = immediate_owner.get(p_immediate); + ERR_FAIL_COND(!im); + ERR_FAIL_COND(im->building); + im->chunks.clear(); + im->instance_change_notify(); } -void RasterizerStorageGLES3::immediate_set_material(RID p_immediate,RID p_material){ +AABB RasterizerStorageGLES3::immediate_get_aabb(RID p_immediate) const { + Immediate *im = immediate_owner.get(p_immediate); + ERR_FAIL_COND_V(!im,AABB()); + return im->aabb; } -RID RasterizerStorageGLES3::immediate_get_material(RID p_immediate) const{ - return RID(); +void RasterizerStorageGLES3::immediate_set_material(RID p_immediate,RID p_material) { + + Immediate *im = immediate_owner.get(p_immediate); + ERR_FAIL_COND(!im); + im->material=p_material; + im->instance_material_change_notify(); + +} + +RID RasterizerStorageGLES3::immediate_get_material(RID p_immediate) const { + + const Immediate *im = immediate_owner.get(p_immediate); + ERR_FAIL_COND_V(!im,RID()); + return im->material; + } /* SKELETON API */ @@ -4417,6 +4517,10 @@ void RasterizerStorageGLES3::instance_add_dependency(RID p_base,RasterizerScene: inst = multimesh_owner.getornull(p_base); ERR_FAIL_COND(!inst); } break; + case VS::INSTANCE_IMMEDIATE: { + inst = immediate_owner.getornull(p_base); + ERR_FAIL_COND(!inst); + } break; case VS::INSTANCE_REFLECTION_PROBE: { inst = reflection_probe_owner.getornull(p_base); ERR_FAIL_COND(!inst); @@ -4452,6 +4556,10 @@ void RasterizerStorageGLES3::instance_remove_dependency(RID p_base,RasterizerSce inst = multimesh_owner.getornull(p_base); ERR_FAIL_COND(!inst); } break; + case VS::INSTANCE_IMMEDIATE: { + inst = immediate_owner.getornull(p_base); + ERR_FAIL_COND(!inst); + } break; case VS::INSTANCE_REFLECTION_PROBE: { inst = reflection_probe_owner.getornull(p_base); ERR_FAIL_COND(!inst); @@ -4949,6 +5057,9 @@ VS::InstanceType RasterizerStorageGLES3::get_base_type(RID p_rid) const { if (multimesh_owner.owns(p_rid)) { return VS::INSTANCE_MULTIMESH; } + if (immediate_owner.owns(p_rid)) { + return VS::INSTANCE_IMMEDIATE; + } if (light_owner.owns(p_rid)) { return VS::INSTANCE_LIGHT; } @@ -5057,7 +5168,12 @@ bool RasterizerStorageGLES3::free(RID p_rid){ multimesh_owner.free(p_rid); memdelete(multimesh); + } else if (immediate_owner.owns(p_rid)) { + + Immediate *immediate = immediate_owner.get(p_rid); + immediate_owner.free(p_rid); + memdelete(immediate); } else if (light_owner.owns(p_rid)) { // delete the texture diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index c6712bd8ea..623962bf61 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -651,10 +651,41 @@ public: /* IMMEDIATE API */ + struct Immediate : public Geometry { + + struct Chunk { + + RID texture; + VS::PrimitiveType primitive; + Vector vertices; + Vector normals; + Vector tangents; + Vector colors; + Vector uvs; + Vector uvs2; + }; + + List chunks; + bool building; + int mask; + AABB aabb; + + Immediate() { type=GEOMETRY_IMMEDIATE; building=false;} + + }; + + Vector3 chunk_vertex; + Vector3 chunk_normal; + Plane chunk_tangent; + Color chunk_color; + Vector2 chunk_uv; + Vector2 chunk_uv2; + + mutable RID_Owner immediate_owner; + virtual RID immediate_create(); virtual void immediate_begin(RID p_immediate,VS::PrimitiveType p_rimitive,RID p_texture=RID()); - virtual void immediate_vertex(RID p_immediate,const Vector3& p_vertex); - virtual void immediate_vertex_2d(RID p_immediate,const Vector3& p_vertex); + virtual void immediate_vertex(RID p_immediate,const Vector3& p_vertex); virtual void immediate_normal(RID p_immediate,const Vector3& p_normal); virtual void immediate_tangent(RID p_immediate,const Plane& p_tangent); virtual void immediate_color(RID p_immediate,const Color& p_color); @@ -664,6 +695,7 @@ public: virtual void immediate_clear(RID p_immediate); virtual void immediate_set_material(RID p_immediate,RID p_material); virtual RID immediate_get_material(RID p_immediate) const; + virtual AABB immediate_get_aabb(RID p_immediate) const; /* SKELETON API */ diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp index e906f9a790..78f35c493a 100644 --- a/drivers/gles3/shader_gles3.cpp +++ b/drivers/gles3/shader_gles3.cpp @@ -222,9 +222,8 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() { Vector strings; #ifdef GLES_OVER_GL strings.push_back("#version 330\n"); - //strings.push_back("#version 300 es\n"); #else - strings.push_back("#version 300 es\n"); //ATI requieres this before anything + strings.push_back("#version 300 es\n"); #endif -- cgit v1.2.3 From 69c30709ec6908e0960707501cc7fea58eb64f01 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Wed, 23 Nov 2016 08:00:15 -0300 Subject: implemented immediates --- drivers/gles3/rasterizer_scene_gles3.cpp | 196 +++++++++++++++++++++++++++---- drivers/gles3/rasterizer_scene_gles3.h | 4 + 2 files changed, 177 insertions(+), 23 deletions(-) (limited to 'drivers/gles3') diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index f42eea45d4..7a0e21b620 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -1027,59 +1027,75 @@ bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material* p_m RID* textures = p_material->textures.ptr(); ShaderLanguage::ShaderNode::Uniform::Hint* texture_hints = p_material->shader->texture_hints.ptr(); + state.current_main_tex=0; + for(int i=0;itexture_owner.getornull( textures[i] ); + if (!t) { //check hints + target=GL_TEXTURE_2D; + switch(texture_hints[i]) { case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK: { - glBindTexture(GL_TEXTURE_2D,storage->resources.black_tex); + tex=storage->resources.black_tex; } break; case ShaderLanguage::ShaderNode::Uniform::HINT_ANISO: { - glBindTexture(GL_TEXTURE_2D,storage->resources.aniso_tex); + tex=storage->resources.aniso_tex; } break; case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: { - glBindTexture(GL_TEXTURE_2D,storage->resources.normal_tex); + tex=storage->resources.normal_tex; } break; default: { - glBindTexture(GL_TEXTURE_2D,storage->resources.white_tex); + tex=storage->resources.white_tex; } break; } - continue; - } - if (storage->config.srgb_decode_supported) { - //if SRGB decode extension is present, simply switch the texture to whathever is needed - bool must_srgb=false; + } else { - if (t->srgb && (texture_hints[i]==ShaderLanguage::ShaderNode::Uniform::HINT_ALBEDO || texture_hints[i]==ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO)) { - must_srgb=true; - } + if (storage->config.srgb_decode_supported) { + //if SRGB decode extension is present, simply switch the texture to whathever is needed + bool must_srgb=false; + + if (t->srgb && (texture_hints[i]==ShaderLanguage::ShaderNode::Uniform::HINT_ALBEDO || texture_hints[i]==ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO)) { + must_srgb=true; + } - if (t->using_srgb!=must_srgb) { - if (must_srgb) { - glTexParameteri(t->target,_TEXTURE_SRGB_DECODE_EXT,_DECODE_EXT); + if (t->using_srgb!=must_srgb) { + if (must_srgb) { + glTexParameteri(t->target,_TEXTURE_SRGB_DECODE_EXT,_DECODE_EXT); #ifdef TOOLS_ENABLED - if (!(t->flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) { - t->flags|=VS::TEXTURE_FLAG_CONVERT_TO_LINEAR; - //notify that texture must be set to linear beforehand, so it works in other platforms when exported - } + if (!(t->flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) { + t->flags|=VS::TEXTURE_FLAG_CONVERT_TO_LINEAR; + //notify that texture must be set to linear beforehand, so it works in other platforms when exported + } #endif - } else { - glTexParameteri(t->target,_TEXTURE_SRGB_DECODE_EXT,_SKIP_DECODE_EXT); + } else { + glTexParameteri(t->target,_TEXTURE_SRGB_DECODE_EXT,_SKIP_DECODE_EXT); + } + t->using_srgb=must_srgb; } - t->using_srgb=must_srgb; } + + target=t->target; + tex = t->tex_id; + } + glBindTexture(target,tex); - glBindTexture(t->target,t->tex_id); + if (i==0) { + state.current_main_tex=tex; + } } @@ -1200,6 +1216,125 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) { } } break; + case VS::INSTANCE_IMMEDIATE: { + + bool restore_tex=false; + const RasterizerStorageGLES3::Immediate *im = static_cast( e->geometry ); + + if (im->building) { + return; + } + + glBindBuffer(GL_ARRAY_BUFFER, state.immediate_buffer); + glBindVertexArray(state.immediate_array); + + + for(const List< RasterizerStorageGLES3::Immediate::Chunk>::Element *E=im->chunks.front();E;E=E->next()) { + + const RasterizerStorageGLES3::Immediate::Chunk &c=E->get(); + if (c.vertices.empty()) { + continue; + } + + int vertices = c.vertices.size(); + uint32_t buf_ofs=0; + + if (c.texture.is_valid() && storage->texture_owner.owns(c.texture)) { + + const RasterizerStorageGLES3::Texture *t = storage->texture_owner.get(c.texture); + glActiveTexture(GL_TEXTURE0); + glBindTexture(t->target,t->tex_id); + restore_tex=true; + + + } else if (restore_tex) { + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,state.current_main_tex); + restore_tex=false; + } + + + + if (!c.normals.empty()) { + + glEnableVertexAttribArray(VS::ARRAY_NORMAL); + glBufferSubData(GL_ARRAY_BUFFER,0,sizeof(Vector3)*vertices,c.normals.ptr()); + glVertexAttribPointer(VS::ARRAY_NORMAL, 3, GL_FLOAT, false,sizeof(Vector3)*vertices,((uint8_t*)NULL)+buf_ofs); + buf_ofs+=sizeof(Vector3)*vertices; + + } else { + + glDisableVertexAttribArray(VS::ARRAY_NORMAL); + } + + if (!c.tangents.empty()) { + + glEnableVertexAttribArray(VS::ARRAY_TANGENT); + glBufferSubData(GL_ARRAY_BUFFER,0,sizeof(Plane)*vertices,c.tangents.ptr()); + glVertexAttribPointer(VS::ARRAY_TANGENT, 4, GL_FLOAT, false,sizeof(Plane)*vertices,((uint8_t*)NULL)+buf_ofs); + buf_ofs+=sizeof(Plane)*vertices; + + } else { + + glDisableVertexAttribArray(VS::ARRAY_TANGENT); + } + + if (!c.colors.empty()) { + + glEnableVertexAttribArray(VS::ARRAY_COLOR); + glBufferSubData(GL_ARRAY_BUFFER,0,sizeof(Color)*vertices,c.colors.ptr()); + glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, false,sizeof(Color),((uint8_t*)NULL)+buf_ofs); + buf_ofs+=sizeof(Color)*vertices; + + } else { + + glDisableVertexAttribArray(VS::ARRAY_COLOR); + glVertexAttrib4f(VS::ARRAY_COLOR,1,1,1,1); + } + + + if (!c.uvs.empty()) { + + glEnableVertexAttribArray(VS::ARRAY_TEX_UV); + glBufferSubData(GL_ARRAY_BUFFER,0,sizeof(Vector2)*vertices,c.uvs.ptr()); + glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, false,sizeof(Vector2),((uint8_t*)NULL)+buf_ofs); + buf_ofs+=sizeof(Vector2)*vertices; + + } else { + + glDisableVertexAttribArray(VS::ARRAY_TEX_UV); + } + + if (!c.uvs2.empty()) { + + glEnableVertexAttribArray(VS::ARRAY_TEX_UV2); + glBufferSubData(GL_ARRAY_BUFFER,0,sizeof(Vector2)*vertices,c.uvs2.ptr()); + glVertexAttribPointer(VS::ARRAY_TEX_UV2, 2, GL_FLOAT, false,sizeof(Vector2),((uint8_t*)NULL)+buf_ofs); + buf_ofs+=sizeof(Vector2)*vertices; + + } else { + + glDisableVertexAttribArray(VS::ARRAY_TEX_UV2); + } + + + glEnableVertexAttribArray(VS::ARRAY_VERTEX); + glBufferSubData(GL_ARRAY_BUFFER,0,sizeof(Vector3)*vertices,c.vertices.ptr()); + glVertexAttribPointer(VS::ARRAY_VERTEX, 3, GL_FLOAT, false,sizeof(Vector3),((uint8_t*)NULL)+buf_ofs); + glDrawArrays(gl_primitive[c.primitive],0,c.vertices.size()); + + + } + + + if (restore_tex) { + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,state.current_main_tex); + restore_tex=false; + } + } break; } @@ -3647,6 +3782,21 @@ void RasterizerSceneGLES3::initialize() { } } + { + + + uint32_t immediate_buffer_size=GLOBAL_DEF("rendering/gles3/immediate_buffer_size_kb",2048); + + glGenBuffers(1, &state.immediate_buffer); + glBindBuffer(GL_ARRAY_BUFFER, state.immediate_buffer); + glBufferData(GL_ARRAY_BUFFER, immediate_buffer_size*1024, NULL, GL_DYNAMIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glGenVertexArrays(1,&state.immediate_array); + + + + } #ifdef GLES_OVER_GL //"desktop" opengl needs this. diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 31253e56b6..929b01e373 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -41,6 +41,7 @@ public: int current_blend_mode; float current_line_width; int current_depth_draw; + GLuint current_main_tex; SceneShaderGLES3 scene_shader; CubeToDpShaderGLES3 cube_to_dp_shader; @@ -90,6 +91,9 @@ public: GLuint omni_array_ubo; GLuint reflection_array_ubo; + GLuint immediate_buffer; + GLuint immediate_array; + uint32_t ubo_light_size; uint8_t *spot_array_tmp; uint8_t *omni_array_tmp; -- cgit v1.2.3 From a732708b9dad4ebc118a0ce854f950c6becb984c Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Thu, 24 Nov 2016 20:46:55 -0300 Subject: Blend shapes using transform feedback (GPU) --- drivers/gles3/rasterizer_scene_gles3.cpp | 11 +- drivers/gles3/rasterizer_storage_gles3.cpp | 401 ++++++++++++++++++++++------- drivers/gles3/rasterizer_storage_gles3.h | 72 ++++-- drivers/gles3/shader_gles3.cpp | 23 +- drivers/gles3/shader_gles3.h | 10 +- drivers/gles3/shaders/SCsub | 1 + drivers/gles3/shaders/blend_shape.glsl | 197 ++++++++++++++ 7 files changed, 591 insertions(+), 124 deletions(-) create mode 100644 drivers/gles3/shaders/blend_shape.glsl (limited to 'drivers/gles3') diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 7a0e21b620..9de441c2bb 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -1111,7 +1111,16 @@ void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e) { case VS::INSTANCE_MESH: { RasterizerStorageGLES3::Surface *s = static_cast(e->geometry); - glBindVertexArray(s->array_id); // everything is so easy nowadays + + if (s->morph_targets.size() && e->instance->morph_values.size()) { + //blend shapes, use transform feedback + storage->mesh_render_blend_shapes(s,e->instance->morph_values.ptr()); + //rebind shader + state.scene_shader.bind(); + } else { + + glBindVertexArray(s->array_id); // everything is so easy nowadays + } } break; diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index a618953b86..559f733e4d 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -2274,8 +2274,8 @@ void RasterizerStorageGLES3::_update_material(Material* material) { material->can_cast_shadow_cache=can_cast_shadow; material->is_animated_cache=is_animated; - for(Map::Element *E=material->instantiable_owners.front();E;E=E->next()) { - E->key()->instance_material_change_notify(); + for(Map::Element *E=material->geometry_owners.front();E;E=E->next()) { + E->key()->material_changed_notify(); } for(Map::Element *E=material->instance_owners.front();E;E=E->next()) { @@ -2379,32 +2379,32 @@ void RasterizerStorageGLES3::_update_material(Material* material) { } -void RasterizerStorageGLES3::_material_add_instantiable(RID p_material,Instantiable *p_instantiable) { +void RasterizerStorageGLES3::_material_add_geometry(RID p_material,Geometry *p_geometry) { Material * material = material_owner.getornull(p_material); ERR_FAIL_COND(!material); - Map::Element *I = material->instantiable_owners.find(p_instantiable); + Map::Element *I = material->geometry_owners.find(p_geometry); if (I) { I->get()++; } else { - material->instantiable_owners[p_instantiable]=1; + material->geometry_owners[p_geometry]=1; } } -void RasterizerStorageGLES3::_material_remove_instantiable(RID p_material,Instantiable *p_instantiable) { +void RasterizerStorageGLES3::_material_remove_geometry(RID p_material,Geometry *p_geometry) { Material * material = material_owner.getornull(p_material); ERR_FAIL_COND(!material); - Map::Element *I = material->instantiable_owners.find(p_instantiable); + Map::Element *I = material->geometry_owners.find(p_geometry); ERR_FAIL_COND(!I); I->get()--; if (I->get()==0) { - material->instantiable_owners.erase(I); + material->geometry_owners.erase(I); } } @@ -2446,18 +2446,15 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::P bool has_morph = p_blend_shapes.size(); - Surface::Attrib attribs[VS::ARRAY_MAX],morph_attribs[VS::ARRAY_MAX]; + Surface::Attrib attribs[VS::ARRAY_MAX]; int stride=0; - int morph_stride=0; for(int i=0;iattribs[i]=attribs[i]; - surface->morph_attribs[i]=morph_attribs[i]; } { @@ -2763,12 +2701,11 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::P glGenVertexArrays(1,&surface->array_id); glBindVertexArray(surface->array_id); glBindBuffer(GL_ARRAY_BUFFER,surface->vertex_id); - } else { + } else if (i==1) { //for instancing draw (can be changed and no one cares) glGenVertexArrays(1,&surface->instancing_array_id); glBindVertexArray(surface->instancing_array_id); glBindBuffer(GL_ARRAY_BUFFER,surface->vertex_id); - } @@ -2816,17 +2753,17 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::P glBindVertexArray(mt.array_id); glBindBuffer(GL_ARRAY_BUFFER,mt.vertex_id); - for(int i=0;isurfaces[p_surface]->material.is_valid()) { - _material_remove_instantiable(mesh->surfaces[p_surface]->material,mesh); + _material_remove_geometry(mesh->surfaces[p_surface]->material,mesh->surfaces[p_surface]); } mesh->surfaces[p_surface]->material=p_material; if (mesh->surfaces[p_surface]->material.is_valid()) { - _material_add_instantiable(mesh->surfaces[p_surface]->material,mesh); + _material_add_geometry(mesh->surfaces[p_surface]->material,mesh->surfaces[p_surface]); } mesh->instance_material_change_notify(); @@ -3067,7 +3004,7 @@ void RasterizerStorageGLES3::mesh_remove_surface(RID p_mesh, int p_surface){ Surface *surface = mesh->surfaces[p_surface]; if (surface->material.is_valid()) { - _material_remove_instantiable(surface->material,mesh); + _material_remove_geometry(surface->material,mesh->surfaces[p_surface]); } glDeleteBuffers(1,&surface->vertex_id); @@ -3241,6 +3178,227 @@ void RasterizerStorageGLES3::mesh_clear(RID p_mesh){ } } +void RasterizerStorageGLES3::mesh_render_blend_shapes(Surface *s, float *p_weights) { + + glBindVertexArray(s->array_id); + + BlendShapeShaderGLES3::Conditionals cond[VS::ARRAY_MAX-1]={ + BlendShapeShaderGLES3::ENABLE_NORMAL, //will be ignored + BlendShapeShaderGLES3::ENABLE_NORMAL, + BlendShapeShaderGLES3::ENABLE_TANGENT, + BlendShapeShaderGLES3::ENABLE_COLOR, + BlendShapeShaderGLES3::ENABLE_UV, + BlendShapeShaderGLES3::ENABLE_UV2, + BlendShapeShaderGLES3::ENABLE_SKELETON, + BlendShapeShaderGLES3::ENABLE_SKELETON, + }; + + int stride=0; + + if (s->format&VS::ARRAY_FLAG_USE_2D_VERTICES) { + stride=2*4; + } else { + stride=3*4; + } + + static const int sizes[VS::ARRAY_MAX-1]={ + 3*4, + 3*4, + 4*4, + 4*4, + 2*4, + 2*4, + 4*4, + 4*4 + }; + + for(int i=1;iformat&(1<format&(1<morph_targets.size(); + + if (s->mesh->morph_target_mode==VS::MORPH_MODE_NORMALIZED) { + + for(int i=0;iformat&VS::ARRAY_FLAG_USE_2D_VERTICES); //use 2D vertices if needed + + shaders.blend_shapes.bind(); + + shaders.blend_shapes.set_uniform(BlendShapeShaderGLES3::BLEND_AMOUNT,base_weight); + glEnable(GL_RASTERIZER_DISCARD); + + glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, resources.transform_feedback_buffers[0]); + glBeginTransformFeedback(GL_POINTS); + glDrawArrays(GL_POINTS,0,s->array_len); + glEndTransformFeedback(); + + + shaders.blend_shapes.set_conditional(BlendShapeShaderGLES3::ENABLE_BLEND,true); //first pass does not blend + shaders.blend_shapes.bind(); + + for(int ti=0;timorph_targets[ti].array_id); + glBindBuffer(GL_ARRAY_BUFFER, resources.transform_feedback_buffers[0]); + glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, resources.transform_feedback_buffers[1]); + + shaders.blend_shapes.set_uniform(BlendShapeShaderGLES3::BLEND_AMOUNT,weight); + + int ofs=0; + for(int i=0;iformat&(1<format&VS::ARRAY_FLAG_USE_2D_VERTICES) { + glVertexAttribPointer(i+8,2,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=2*4; + } else { + glVertexAttribPointer(i+8,3,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=3*4; + } + } break; + case VS::ARRAY_NORMAL: { + glVertexAttribPointer(i+8,3,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=3*4; + } break; + case VS::ARRAY_TANGENT: { + glVertexAttribPointer(i+8,4,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=4*4; + + } break; + case VS::ARRAY_COLOR: { + glVertexAttribPointer(i+8,4,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=4*4; + + } break; + case VS::ARRAY_TEX_UV: { + glVertexAttribPointer(i+8,2,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=2*4; + + } break; + case VS::ARRAY_TEX_UV2: { + glVertexAttribPointer(i+8,2,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=2*4; + + } break; + case VS::ARRAY_BONES: { + glVertexAttribIPointer(i+8,4,GL_UNSIGNED_INT,stride,((uint8_t*)0)+ofs); + ofs+=4*4; + + } break; + case VS::ARRAY_WEIGHTS: { + glVertexAttribPointer(i+8,4,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=4*4; + + } break; + } + + } else { + glDisableVertexAttribArray(i+8); + } + } + + glBeginTransformFeedback(GL_POINTS); + glDrawArrays(GL_POINTS,0,s->array_len); + glEndTransformFeedback(); + + + SWAP(resources.transform_feedback_buffers[0],resources.transform_feedback_buffers[1]); + + } + + glDisable(GL_RASTERIZER_DISCARD); + glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0); + + + glBindVertexArray(resources.transform_feedback_array); + glBindBuffer(GL_ARRAY_BUFFER, resources.transform_feedback_buffers[0]); + + int ofs=0; + for(int i=0;iformat&(1<format&VS::ARRAY_FLAG_USE_2D_VERTICES) { + glVertexAttribPointer(i,2,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=2*4; + } else { + glVertexAttribPointer(i,3,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=3*4; + } + } break; + case VS::ARRAY_NORMAL: { + glVertexAttribPointer(i,3,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=3*4; + } break; + case VS::ARRAY_TANGENT: { + glVertexAttribPointer(i,4,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=4*4; + + } break; + case VS::ARRAY_COLOR: { + glVertexAttribPointer(i,4,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=4*4; + + } break; + case VS::ARRAY_TEX_UV: { + glVertexAttribPointer(i,2,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=2*4; + + } break; + case VS::ARRAY_TEX_UV2: { + glVertexAttribPointer(i,2,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=2*4; + + } break; + case VS::ARRAY_BONES: { + glVertexAttribIPointer(i,4,GL_UNSIGNED_INT,stride,((uint8_t*)0)+ofs); + ofs+=4*4; + + } break; + case VS::ARRAY_WEIGHTS: { + glVertexAttribPointer(i,4,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=4*4; + + } break; + } + + } else { + glDisableVertexAttribArray(i); + } + } + + if (s->index_array_len) { + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,s->index_id); + } + +} + /* MULTIMESH API */ @@ -3896,7 +4054,6 @@ void RasterizerStorageGLES3::skeleton_allocate(RID p_skeleton,int p_bones,bool p skeleton_update_list.add(&skeleton->update_list); } - skeleton->instance_change_notify(); } @@ -4017,7 +4174,10 @@ void RasterizerStorageGLES3::update_dirty_skeletons() { glBufferSubData(GL_UNIFORM_BUFFER,0,skeleton->bones.size()*sizeof(float),skeleton->bones.ptr()); glBindBuffer(GL_UNIFORM_BUFFER, 0); } - skeleton->instance_change_notify(); + + for (Set::Element *E=skeleton->instances.front();E;E=E->next()) { + E->get()->base_changed(); + } skeleton_update_list.remove(skeleton_update_list.first()); } @@ -4505,6 +4665,23 @@ void RasterizerStorageGLES3::portal_set_disabled_color(RID p_portal, const Color } +void RasterizerStorageGLES3::instance_add_skeleton(RID p_skeleton,RasterizerScene::InstanceBase *p_instance) { + + Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); + ERR_FAIL_COND(!skeleton); + + skeleton->instances.insert(p_instance); +} + +void RasterizerStorageGLES3::instance_remove_skeleton(RID p_skeleton,RasterizerScene::InstanceBase *p_instance) { + + Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); + ERR_FAIL_COND(!skeleton); + + skeleton->instances.erase(p_instance); +} + + void RasterizerStorageGLES3::instance_add_dependency(RID p_base,RasterizerScene::InstanceBase *p_instance) { Instantiable *inst=NULL; @@ -4530,9 +4707,6 @@ void RasterizerStorageGLES3::instance_add_dependency(RID p_base,RasterizerScene: ERR_FAIL_COND(!inst); } break; default: { - if (skeleton_owner.owns(p_base)) { - inst=skeleton_owner.getornull(p_base); - } if (!inst) { ERR_FAIL(); } @@ -4550,7 +4724,6 @@ void RasterizerStorageGLES3::instance_remove_dependency(RID p_base,RasterizerSce case VS::INSTANCE_MESH: { inst = mesh_owner.getornull(p_base); ERR_FAIL_COND(!inst); - } break; case VS::INSTANCE_MULTIMESH: { inst = multimesh_owner.getornull(p_base); @@ -4569,9 +4742,7 @@ void RasterizerStorageGLES3::instance_remove_dependency(RID p_base,RasterizerSce ERR_FAIL_COND(!inst); } break; default: { - if (skeleton_owner.owns(p_base)) { - inst=skeleton_owner.getornull(p_base); - } + if (!inst) { ERR_FAIL(); } @@ -5134,6 +5305,26 @@ bool RasterizerStorageGLES3::free(RID p_rid){ glDeleteBuffers(1,&material->ubo_id); } + //remove from owners + for (Map::Element *E=material->geometry_owners.front();E;E=E->next()) { + + Geometry *g = E->key(); + g->material=RID(); + } + for (Map::Element *E=material->instance_owners.front();E;E=E->next()) { + RasterizerScene::InstanceBase*ins=E->key(); + if (ins->material_override==p_rid) { + ins->material_override=RID(); + } + + for(int i=0;imaterials.size();i++) { + if (ins->materials[i]==p_rid) { + ins->materials[i]=RID(); + } + } + + } + material_owner.free(p_rid); memdelete(material); @@ -5144,6 +5335,11 @@ bool RasterizerStorageGLES3::free(RID p_rid){ if (skeleton->update_list.in_list()) { skeleton_update_list.remove(&skeleton->update_list); } + + for (Set::Element *E=skeleton->instances.front();E;E=E->next()) { + E->get()->skeleton=RID(); + } + skeleton_allocate(p_rid,0,false); skeleton_owner.free(p_rid); memdelete(skeleton); @@ -5370,6 +5566,23 @@ void RasterizerStorageGLES3::initialize() { glBindBuffer(GL_ARRAY_BUFFER,0); //unbind } + + { + //transform feedback buffers + uint32_t xf_feedback_size = GLOBAL_DEF("rendering/gles3/blend_shape_max_buffer_size_kb",4096); + for(int i=0;i<2;i++) { + + glGenBuffers(1,&resources.transform_feedback_buffers[i]); + glBindBuffer(GL_ARRAY_BUFFER,resources.transform_feedback_buffers[i]); + glBufferData(GL_ARRAY_BUFFER,xf_feedback_size*1024,NULL,GL_STREAM_DRAW); + } + + shaders.blend_shapes.init();; + + glGenVertexArrays(1,&resources.transform_feedback_array); + + } + shaders.cubemap_filter.init(); glEnable(_EXT_TEXTURE_CUBE_MAP_SEAMLESS); diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index 623962bf61..361e738af5 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -6,6 +6,7 @@ #include "shader_gles3.h" #include "shaders/copy.glsl.h" #include "shaders/canvas.glsl.h" +#include "shaders/blend_shape.glsl.h" #include "shaders/cubemap_filter.glsl.h" #include "self_list.h" #include "shader_compiler_gles3.h" @@ -65,6 +66,8 @@ public: CubemapFilterShaderGLES3 cubemap_filter; + BlendShapeShaderGLES3 blend_shapes; + ShaderCompilerGLES3::IdentifierActions actions_canvas; ShaderCompilerGLES3::IdentifierActions actions_scene; } shaders; @@ -79,6 +82,9 @@ public: GLuint quadie; GLuint quadie_array; + GLuint transform_feedback_buffers[2]; + GLuint transform_feedback_array; + } resources; struct Info { @@ -133,8 +139,33 @@ public: } }; + struct GeometryOwner : public Instantiable { + + virtual ~GeometryOwner() {} + }; + struct Geometry : Instantiable { + + enum Type { + GEOMETRY_INVALID, + GEOMETRY_SURFACE, + GEOMETRY_IMMEDIATE, + GEOMETRY_MULTISURFACE, + }; + + + Type type; + RID material; + uint64_t last_pass; + uint32_t index; + virtual void material_changed_notify() {} + Geometry() { + last_pass=0; + index=0; + } + + }; @@ -384,7 +415,7 @@ public: uint32_t index; uint64_t last_pass; - Map instantiable_owners; + Map geometry_owners; Map instance_owners; bool can_cast_shadow_cache; @@ -404,8 +435,8 @@ public: mutable SelfList::List _material_dirty_list; void _material_make_dirty(Material *p_material) const; - void _material_add_instantiable(RID p_material,Instantiable *p_instantiable); - void _material_remove_instantiable(RID p_material, Instantiable *p_instantiable); + void _material_add_geometry(RID p_material,Geometry *p_instantiable); + void _material_remove_geometry(RID p_material, Geometry *p_instantiable); mutable RID_Owner material_owner; @@ -433,31 +464,9 @@ public: /* MESH API */ - struct Geometry : Instantiable { - - enum Type { - GEOMETRY_INVALID, - GEOMETRY_SURFACE, - GEOMETRY_IMMEDIATE, - GEOMETRY_MULTISURFACE, - }; - - Type type; - RID material; - uint64_t last_pass; - uint32_t index; - Geometry() { - last_pass=0; - index=0; - } - }; - struct GeometryOwner : public Instantiable { - - virtual ~GeometryOwner() {} - }; struct Mesh; struct Surface : public Geometry { @@ -475,7 +484,7 @@ public: }; Attrib attribs[VS::ARRAY_MAX]; - Attrib morph_attribs[VS::ARRAY_MAX]; + Mesh *mesh; @@ -512,6 +521,10 @@ public: bool active; + virtual void material_changed_notify() { + mesh->instance_material_change_notify(); + } + Surface() { array_byte_size=0; @@ -590,6 +603,8 @@ public: virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton) const; virtual void mesh_clear(RID p_mesh); + void mesh_render_blend_shapes(Surface *s, float *p_weights); + /* MULTIMESH API */ struct MultiMesh : public GeometryOwner { @@ -699,12 +714,13 @@ public: /* SKELETON API */ - struct Skeleton : Instantiable { + struct Skeleton : RID_Data { int size; bool use_2d; Vector bones; //4x3 or 4x2 depending on what is needed GLuint ubo; SelfList update_list; + Set instances; //instances using skeleton Skeleton() : update_list(this) { size=0; @@ -843,6 +859,8 @@ public: virtual void portal_set_disable_distance(RID p_portal, float p_distance); virtual void portal_set_disabled_color(RID p_portal, const Color& p_color); + virtual void instance_add_skeleton(RID p_skeleton,RasterizerScene::InstanceBase *p_instance); + virtual void instance_remove_skeleton(RID p_skeleton,RasterizerScene::InstanceBase *p_instance); virtual void instance_add_dependency(RID p_base,RasterizerScene::InstanceBase *p_instance); virtual void instance_remove_dependency(RID p_base,RasterizerScene::InstanceBase *p_instance); diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp index 78f35c493a..d29927b137 100644 --- a/drivers/gles3/shader_gles3.cpp +++ b/drivers/gles3/shader_gles3.cpp @@ -502,6 +502,25 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() { glBindAttribLocation(v.id, attribute_pairs[i].index, attribute_pairs[i].name ); } + //if feedback exists, set it up + + if (feedback_count) { + Vector feedback; + for(int i=0;i Date: Thu, 24 Nov 2016 23:30:54 -0300 Subject: fixed bug removing dependencies --- drivers/gles3/rasterizer_storage_gles3.cpp | 15 ++++++++++++++- drivers/gles3/rasterizer_storage_gles3.h | 14 +++++++++++--- 2 files changed, 25 insertions(+), 4 deletions(-) (limited to 'drivers/gles3') diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 559f733e4d..e9d9136a0b 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -5272,6 +5272,7 @@ bool RasterizerStorageGLES3::free(RID p_rid){ // delete the texture Shader *shader = shader_owner.get(p_rid); + if (shader->shader) shader->shader->free_custom_shader(shader->custom_code_id); @@ -5348,7 +5349,7 @@ bool RasterizerStorageGLES3::free(RID p_rid){ // delete the texture Mesh *mesh = mesh_owner.get(p_rid); - + mesh->instance_remove_deps(); mesh_clear(p_rid); mesh_owner.free(p_rid); @@ -5358,6 +5359,7 @@ bool RasterizerStorageGLES3::free(RID p_rid){ // delete the texture MultiMesh *multimesh = multimesh_owner.get(p_rid); + multimesh->instance_remove_deps(); multimesh_allocate(p_rid,0,VS::MULTIMESH_TRANSFORM_2D,VS::MULTIMESH_COLOR_NONE); //frees multimesh update_dirty_multimeshes(); @@ -5367,6 +5369,7 @@ bool RasterizerStorageGLES3::free(RID p_rid){ } else if (immediate_owner.owns(p_rid)) { Immediate *immediate = immediate_owner.get(p_rid); + immediate->instance_remove_deps(); immediate_owner.free(p_rid); memdelete(immediate); @@ -5374,10 +5377,20 @@ bool RasterizerStorageGLES3::free(RID p_rid){ // delete the texture Light *light = light_owner.get(p_rid); + light->instance_remove_deps(); light_owner.free(p_rid); memdelete(light); + } else if (reflection_probe_owner.owns(p_rid)) { + + // delete the texture + ReflectionProbe *reflection_probe = reflection_probe_owner.get(p_rid); + reflection_probe->instance_remove_deps(); + + reflection_probe_owner.free(p_rid); + memdelete(reflection_probe); + } else if (canvas_occluder_owner.owns(p_rid)) { diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index 361e738af5..62199b10ff 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -130,12 +130,20 @@ public: } } + _FORCE_INLINE_ void instance_remove_deps() { + SelfList *instances = instance_list.first(); + while(instances) { + + SelfList *next = instances->next(); + instances->self()->base_removed(); + instances=next; + } + } + + Instantiable() { } virtual ~Instantiable() { - while(instance_list.first()) { - instance_list.first()->self()->base_removed(); - } } }; -- cgit v1.2.3 From a47c78aed113a9b4c009c5a2ef29c690192c7eef Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Tue, 29 Nov 2016 19:55:12 -0300 Subject: Screen space reflection effect --- drivers/gles3/rasterizer_canvas_gles3.cpp | 2 +- drivers/gles3/rasterizer_gles3.cpp | 6 +- drivers/gles3/rasterizer_scene_gles3.cpp | 172 +++++++++- drivers/gles3/rasterizer_scene_gles3.h | 27 ++ drivers/gles3/rasterizer_storage_gles3.cpp | 169 ++++++---- drivers/gles3/rasterizer_storage_gles3.h | 37 ++- drivers/gles3/shader_gles3.cpp | 4 +- drivers/gles3/shaders/SCsub | 3 + drivers/gles3/shaders/copy.glsl | 19 ++ drivers/gles3/shaders/resolve.glsl | 45 +++ drivers/gles3/shaders/resolve.glsl.h | 166 ++++++++++ drivers/gles3/shaders/scene.glsl | 6 +- drivers/gles3/shaders/screen_space.glsl.h | 183 +++++++++++ drivers/gles3/shaders/screen_space_reflection.glsl | 350 +++++++++++++++++++++ 14 files changed, 1112 insertions(+), 77 deletions(-) create mode 100644 drivers/gles3/shaders/resolve.glsl create mode 100644 drivers/gles3/shaders/resolve.glsl.h create mode 100644 drivers/gles3/shaders/screen_space.glsl.h create mode 100644 drivers/gles3/shaders/screen_space_reflection.glsl (limited to 'drivers/gles3') diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index 1f23387516..3c6094a41d 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -1349,7 +1349,7 @@ void RasterizerCanvasGLES3::reset_canvas() { if (storage->frame.current_rt) { - glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->front.fbo); + glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo); glColorMask(1,1,1,1); //don't touch alpha } diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index 9046028705..3924ffb75f 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -178,7 +178,7 @@ void RasterizerGLES3::set_current_render_target(RID p_render_target){ if (!p_render_target.is_valid() && storage->frame.current_rt && storage->frame.clear_request) { //handle pending clear request, if the framebuffer was not cleared - glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->front.fbo); + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->fbo); print_line("unbind clear of: "+storage->frame.clear_request_color); glClearColor( storage->frame.clear_request_color.r, @@ -213,7 +213,7 @@ void RasterizerGLES3::restore_render_target() { ERR_FAIL_COND(storage->frame.current_rt==NULL); RasterizerStorageGLES3::RenderTarget * rt = storage->frame.current_rt; - glBindFramebuffer(GL_FRAMEBUFFER,rt->front.fbo); + glBindFramebuffer(GL_FRAMEBUFFER,rt->fbo); glViewport(0,0,rt->width,rt->height); } @@ -238,7 +238,7 @@ void RasterizerGLES3::blit_render_target_to_screen(RID p_render_target,const Rec glDisable(GL_BLEND); glBindFramebuffer(GL_FRAMEBUFFER,storage->config.system_fbo); glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D,rt->front.color); + glBindTexture(GL_TEXTURE_2D,rt->color); canvas->draw_generic_textured_rect(p_screen_rect,Rect2(0,0,1,-1)); glBindTexture(GL_TEXTURE_2D,0); canvas->canvas_end(); diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 9de441c2bb..16784246f6 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -857,6 +857,21 @@ void RasterizerSceneGLES3::environment_set_fog(RID p_env,bool p_enable,float p_b } +void RasterizerSceneGLES3::environment_set_ssr(RID p_env,bool p_enable, int p_max_steps,float p_accel,float p_fade,float p_depth_tolerance,bool p_smooth,bool p_roughness) { + + Environment *env=environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + + env->ssr_enabled=p_enable; + env->ssr_max_steps=p_max_steps; + env->ssr_accel=p_accel; + env->ssr_fade=p_fade; + env->ssr_depth_tolerance=p_depth_tolerance; + env->ssr_smooth=p_smooth; + env->ssr_roughness=p_roughness; + +} + void RasterizerSceneGLES3::environment_set_tonemap(RID p_env, bool p_enable, float p_exposure, float p_white, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale, VS::EnvironmentToneMapper p_tone_mapper){ } @@ -2538,7 +2553,7 @@ void RasterizerSceneGLES3::_copy_screen() { void RasterizerSceneGLES3::_copy_to_front_buffer(Environment *env) { //copy to front buffer - glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->front.fbo); + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->fbo); glDepthMask(GL_FALSE); glDisable(GL_DEPTH_TEST); @@ -2575,7 +2590,7 @@ void RasterizerSceneGLES3::_copy_to_front_buffer(Environment *env) { void RasterizerSceneGLES3::_copy_texture_to_front_buffer(GLuint p_texture) { //copy to front buffer - glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->front.fbo); + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->fbo); glDepthMask(GL_FALSE); glDisable(GL_DEPTH_TEST); @@ -2660,6 +2675,127 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase** p_cull_result,int p_ } +void RasterizerSceneGLES3::_render_mrts(Environment *env,const CameraMatrix &p_cam_projection) { + + + glDepthMask(GL_FALSE); + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + glDisable(GL_BLEND); + + if (env->ssr_enabled) { + //blur diffuse into effect mipmaps using separatable convolution + //storage->shaders.copy.set_conditional(CopyShaderGLES3::GAUSSIAN_HORIZONTAL,true); + for(int i=0;iframe.current_rt->effects.mip_maps[1].sizes.size();i++) { + + + int vp_w = storage->frame.current_rt->effects.mip_maps[1].sizes[i].width; + int vp_h = storage->frame.current_rt->effects.mip_maps[1].sizes[i].height; + glViewport(0,0,vp_w,vp_h); + //horizontal pass + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_HORIZONTAL,true); + state.effect_blur_shader.bind(); + 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)); + glActiveTexture(GL_TEXTURE0); + if (i==0) { + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.diffuse); + } else { + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.mip_maps[0].color); //previous level, since mipmaps[0] starts one level bigger + } + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->effects.mip_maps[1].sizes[i].fbo); + _copy_screen(); + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_HORIZONTAL,false); + + //vertical pass + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_VERTICAL,true); + state.effect_blur_shader.bind(); + 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)); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.mip_maps[1].color); + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->effects.mip_maps[0].sizes[i+1].fbo); //next level, since mipmaps[0] starts one level bigger + _copy_screen(); + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_VERTICAL,false); + } + + + //perform SSR + + state.ssr_shader.set_conditional(ScreenSpaceReflectionShaderGLES3::SMOOTH_ACCEL,env->ssr_accel>0 && env->ssr_smooth); + state.ssr_shader.set_conditional(ScreenSpaceReflectionShaderGLES3::REFLECT_ROUGHNESS,env->ssr_accel>0 && env->ssr_roughness); + + state.ssr_shader.bind(); + + int ssr_w = storage->frame.current_rt->effects.mip_maps[1].sizes[0].width; + int ssr_h = storage->frame.current_rt->effects.mip_maps[1].sizes[0].height; + + + state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::PIXEL_SIZE,Vector2(1.0/(ssr_w*0.5),1.0/(ssr_h*0.5))); + state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::CAMERA_Z_NEAR,p_cam_projection.get_z_near()); + state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::CAMERA_Z_FAR,p_cam_projection.get_z_far()); + state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::PROJECTION,p_cam_projection); + state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::INVERSE_PROJECTION,p_cam_projection.inverse()); + state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::VIEWPORT_SIZE,Size2(ssr_w,ssr_h)); + //state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::FRAME_INDEX,int(render_pass)); + state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::FILTER_MIPMAP_LEVELS,float(storage->frame.current_rt->effects.mip_maps[0].sizes.size())); + state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::NUM_STEPS,env->ssr_max_steps); + state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::ACCELERATION,env->ssr_accel); + state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::DEPTH_TOLERANCE,env->ssr_depth_tolerance); + state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::DISTANCE_FADE,env->ssr_fade); + + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.diffuse); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.normal_sr); + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->depth); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); + glActiveTexture(GL_TEXTURE3); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.mip_maps[0].color); + + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->effects.mip_maps[1].sizes[0].fbo); + glViewport(0,0,ssr_w,ssr_h); + + _copy_screen(); + glViewport(0,0,storage->frame.current_rt->width,storage->frame.current_rt->height); + + } + + + state.resolve_shader.set_conditional(ResolveShaderGLES3::USE_SSR,env->ssr_enabled); + state.resolve_shader.bind(); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.diffuse); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.specular); + if (env->ssr_enabled) { + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.mip_maps[1].color); + } + + + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo); + //glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->fbo); + _copy_screen(); + + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::SIMPLE_COPY,true); + state.effect_blur_shader.bind(); + state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::LOD,float(0)); + + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.alpha_fbo); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.mip_maps[0].color); + + _copy_screen(); + + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::SIMPLE_COPY,false); + + +} + + void RasterizerSceneGLES3::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){ //first of all, make a new render pass @@ -2700,7 +2836,7 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C render_list.clear(); - bool use_mrt=false; + bool use_mrt=true; _fill_render_list(p_cull_result,p_cull_count,false); @@ -2712,10 +2848,11 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C glEnable(GL_DEPTH_TEST); glDisable(GL_SCISSOR_TEST); - + //rendering to a probe cubemap side ReflectionProbeInstance *probe = reflection_probe_instance_owner.getornull(p_reflection_probe); GLuint current_fbo; + if (probe) { ReflectionAtlas *ref_atlas = reflection_atlas_owner.getptr(probe->atlas); @@ -2739,6 +2876,7 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C glViewport(0,0,reflection_cubemaps[cubemap_index].size,reflection_cubemaps[cubemap_index].size); glBindFramebuffer(GL_FRAMEBUFFER,current_fbo); + } else { glViewport(0,0,storage->frame.current_rt->width,storage->frame.current_rt->height); @@ -2750,6 +2888,13 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.fbo); state.scene_shader.set_conditional(SceneShaderGLES3::USE_MULTIPLE_RENDER_TARGETS,true); + + Vector draw_buffers; + draw_buffers.push_back(GL_COLOR_ATTACHMENT0); + draw_buffers.push_back(GL_COLOR_ATTACHMENT1); + draw_buffers.push_back(GL_COLOR_ATTACHMENT2); + glDrawBuffers(draw_buffers.size(),draw_buffers.ptr()); + Color black(0,0,0,0); glClearBufferfv(GL_COLOR,1,black.components); // specular glClearBufferfv(GL_COLOR,2,black.components); // normal metal rough @@ -2760,6 +2905,7 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.alpha_fbo); state.scene_shader.set_conditional(SceneShaderGLES3::USE_MULTIPLE_RENDER_TARGETS,false); + } } @@ -2841,6 +2987,11 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C state.scene_shader.set_conditional(SceneShaderGLES3::USE_MULTIPLE_RENDER_TARGETS,false); + if (use_mrt) { + GLenum gldb = GL_COLOR_ATTACHMENT0; + glDrawBuffers(1,&gldb); + } + if (env && env->bg_mode==VS::ENV_BG_SKYBOX) { if (use_mrt) { @@ -2859,16 +3010,17 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C // state.scene_shader.set_conditional( SceneShaderGLES3::USE_FOG,false); + + if (use_mrt) { + _render_mrts(env,p_cam_projection); + } + glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); glEnable(GL_BLEND); glDepthMask(GL_TRUE); glEnable(GL_DEPTH_TEST); glDisable(GL_SCISSOR_TEST); - if (use_mrt) { - glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.alpha_fbo); - } - render_list.sort_by_depth(true); if (state.directional_light_count==0) { @@ -3812,6 +3964,10 @@ void RasterizerSceneGLES3::initialize() { glEnable(GL_PROGRAM_POINT_SIZE); #endif + + state.resolve_shader.init(); + state.ssr_shader.init(); + state.effect_blur_shader.init(); } void RasterizerSceneGLES3::iteration() { diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 929b01e373..0b934085ed 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -4,6 +4,9 @@ #include "rasterizer_storage_gles3.h" #include "drivers/gles3/shaders/scene.glsl.h" #include "drivers/gles3/shaders/cube_to_dp.glsl.h" +#include "drivers/gles3/shaders/resolve.glsl.h" +#include "drivers/gles3/shaders/screen_space_reflection.glsl.h" +#include "drivers/gles3/shaders/effect_blur.glsl.h" class RasterizerSceneGLES3 : public RasterizerScene { public: @@ -45,6 +48,9 @@ public: SceneShaderGLES3 scene_shader; CubeToDpShaderGLES3 cube_to_dp_shader; + ResolveShaderGLES3 resolve_shader; + ScreenSpaceReflectionShaderGLES3 ssr_shader; + EffectBlurShaderGLES3 effect_blur_shader; struct SceneDataUBO { @@ -289,6 +295,15 @@ public: int canvas_max_layer; + bool ssr_enabled; + int ssr_max_steps; + float ssr_accel; + float ssr_fade; + float ssr_depth_tolerance; + bool ssr_smooth; + bool ssr_roughness; + + Environment() { bg_mode=VS::ENV_BG_CLEAR_COLOR; @@ -298,6 +313,15 @@ public: ambient_energy=1.0; ambient_skybox_contribution=0.0; canvas_max_layer=0; + + ssr_enabled=false; + ssr_max_steps=64; + ssr_accel=0.04; + ssr_fade=2.0; + ssr_depth_tolerance=0.2; + ssr_smooth=true; + ssr_roughness=true; + } }; @@ -316,6 +340,8 @@ public: virtual void environment_set_glow(RID p_env,bool p_enable,int p_radius,float p_intensity,float p_strength,float p_bloom_treshold,VS::EnvironmentGlowBlendMode p_blend_mode); 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_accel,float p_fade,float p_depth_tolerance,bool p_smooth,bool p_roughness); + virtual void environment_set_tonemap(RID p_env,bool p_enable,float p_exposure,float p_white,float p_min_luminance,float p_max_luminance,float p_auto_exp_speed,float p_auto_exp_scale,VS::EnvironmentToneMapper p_tone_mapper); virtual void environment_set_adjustment(RID p_env,bool p_enable,float p_brightness,float p_contrast,float p_saturation,RID p_ramp); @@ -551,6 +577,7 @@ public: void _fill_render_list(InstanceBase** p_cull_result,int p_cull_count,bool p_shadow); + void _render_mrts(Environment *env, const CameraMatrix &p_cam_projection); 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 e9d9136a0b..01668e728c 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -4760,16 +4760,10 @@ void RasterizerStorageGLES3::instance_remove_dependency(RID p_base,RasterizerSce void RasterizerStorageGLES3::_render_target_clear(RenderTarget *rt) { - if (rt->front.fbo) { - glDeleteFramebuffers(1,&rt->front.fbo); - glDeleteTextures(1,&rt->front.color); - rt->front.fbo=0; - } - - if (rt->back.fbo) { - glDeleteFramebuffers(1,&rt->back.fbo); - glDeleteTextures(1,&rt->back.color); - rt->back.fbo=0; + if (rt->fbo) { + glDeleteFramebuffers(1,&rt->fbo); + glDeleteTextures(1,&rt->color); + rt->fbo=0; } if (rt->buffers.fbo) { @@ -4783,7 +4777,7 @@ void RasterizerStorageGLES3::_render_target_clear(RenderTarget *rt) { } if (rt->depth) { - glDeleteRenderbuffers(1,&rt->depth); + glDeleteTextures(1,&rt->depth); rt->depth=0; } @@ -4793,6 +4787,22 @@ void RasterizerStorageGLES3::_render_target_clear(RenderTarget *rt) { tex->width=0; tex->height=0; + for(int i=0;i<2;i++) { + for(int j=0;jeffects.mip_maps[i].sizes.size();j++) { + glDeleteFramebuffers(1,&rt->effects.mip_maps[i].sizes[j].fbo); + } + + glDeleteTextures(1,&rt->effects.mip_maps[i].color); + rt->effects.mip_maps[i].sizes.clear(); + rt->effects.mip_maps[i].levels=0; + } +/* + if (rt->effects.screen_space_depth) { + glDeleteTextures(1,&rt->effects.screen_space_depth); + rt->effects.screen_space_depth=0; + + } +*/ } void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){ @@ -4833,21 +4843,24 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){ glActiveTexture(GL_TEXTURE0); - glGenFramebuffers(1, &rt->front.fbo); - glBindFramebuffer(GL_FRAMEBUFFER, rt->front.fbo); - - - glGenRenderbuffers(1, &rt->depth); - glBindRenderbuffer(GL_RENDERBUFFER, rt->depth ); + glGenFramebuffers(1, &rt->fbo); + glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo); - glRenderbufferStorage(GL_RENDERBUFFER,GL_DEPTH24_STENCIL8, rt->width, rt->height); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth); - glBindRenderbuffer(GL_RENDERBUFFER, 0 ); + glGenTextures(1, &rt->depth); + glBindTexture(GL_TEXTURE_2D, rt->depth); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 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); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GL_TEXTURE_2D, rt->depth, 0); - glGenTextures(1, &rt->front.color); - glBindTexture(GL_TEXTURE_2D, rt->front.color); + glGenTextures(1, &rt->color); + glBindTexture(GL_TEXTURE_2D, rt->color); glTexImage2D(GL_TEXTURE_2D, 0, color_internal_format, rt->width, rt->height, 0, color_format, color_type, NULL); @@ -4855,7 +4868,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){ 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, rt->front.color, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0); GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); glBindFramebuffer(GL_FRAMEBUFFER, config.system_fbo); @@ -4867,7 +4880,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){ tex->gl_format_cache=color_format; tex->gl_type_cache=color_type; tex->gl_internal_format_cache=color_internal_format; - tex->tex_id=rt->front.color; + tex->tex_id=rt->color; tex->width=rt->width; tex->alloc_width=rt->width; tex->height=rt->height; @@ -4881,32 +4894,6 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){ /* BACK FBO */ - if (!rt->flags[RENDER_TARGET_NO_SAMPLING]) { - - glGenFramebuffers(1, &rt->back.fbo); - glBindFramebuffer(GL_FRAMEBUFFER, rt->back.fbo); - glBindRenderbuffer(GL_RENDERBUFFER, rt->depth ); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth); - - glGenTextures(1, &rt->back.color); - glBindTexture(GL_TEXTURE_2D, rt->back.color); - glTexImage2D(GL_TEXTURE_2D, 0, color_internal_format, rt->width, rt->height, 0, color_format, color_type, 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, rt->back.color, 0); - - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - glBindFramebuffer(GL_FRAMEBUFFER, config.system_fbo); - - if (status != GL_FRAMEBUFFER_COMPLETE) { - _render_target_clear(rt); - ERR_FAIL_COND( status != GL_FRAMEBUFFER_COMPLETE ); - } - } - if (config.render_arch==RENDER_ARCH_DESKTOP && !rt->flags[RENDER_TARGET_NO_3D]) { @@ -4915,11 +4902,12 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){ glGenFramebuffers(1, &rt->buffers.fbo); glBindFramebuffer(GL_FRAMEBUFFER, rt->buffers.fbo); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GL_TEXTURE_2D, rt->depth, 0); glGenTextures(1, &rt->buffers.diffuse); glBindTexture(GL_TEXTURE_2D, rt->buffers.diffuse); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, rt->width, rt->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, rt->width, rt->height, 0, GL_RGBA, GL_HALF_FLOAT, 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); @@ -4958,7 +4946,9 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){ glGenFramebuffers(1, &rt->buffers.alpha_fbo); glBindFramebuffer(GL_FRAMEBUFFER, rt->buffers.alpha_fbo); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GL_TEXTURE_2D, rt->depth, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->buffers.diffuse, 0); status = glCheckFramebufferStatus(GL_FRAMEBUFFER); @@ -4969,9 +4959,80 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){ ERR_FAIL_COND( status != GL_FRAMEBUFFER_COMPLETE ); } - } + for(int i=0;i<2;i++) { + + ERR_FAIL_COND( rt->effects.mip_maps[i].sizes.size() ); + int w=rt->width; + int h=rt->height; + + + if (i>0) { + w>>=1; + h>>=1; + } + + + glGenTextures(1, &rt->effects.mip_maps[i].color); + glBindTexture(GL_TEXTURE_2D, rt->effects.mip_maps[i].color); + int level=0; + + while(true) { + + RenderTarget::Effects::MipMaps::Size mm; + + glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA16F, w, h, 0, GL_RGBA, GL_HALF_FLOAT, NULL); + mm.width=w; + mm.height=h; + rt->effects.mip_maps[i].sizes.push_back(mm); + + w>>=1; + h>>=1; + + if (w<32 || h<32) + break; //going less than 32 is pointless + + level++; + + } + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, level); + + + for(int j=0;jeffects.mip_maps[i].sizes.size();j++) { + + RenderTarget::Effects::MipMaps::Size &mm=rt->effects.mip_maps[i].sizes[j]; + + glGenFramebuffers(1, &mm.fbo); + glBindFramebuffer(GL_FRAMEBUFFER, mm.fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,rt->effects.mip_maps[i].color ,j); + + status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) { + _render_target_clear(rt); + ERR_FAIL_COND( status != GL_FRAMEBUFFER_COMPLETE ); + } + + + float zero[4]={1,0,1,0}; + glClearBufferfv(GL_COLOR,0,zero); + + + } + + glBindFramebuffer(GL_FRAMEBUFFER, config.system_fbo); + rt->effects.mip_maps[i].levels=level; + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + //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); + } + + } } diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index 62199b10ff..1eba8b42c9 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -877,11 +877,8 @@ public: struct RenderTarget : public RID_Data { - struct Color { - GLuint fbo; - GLuint color; - } front,back; - + GLuint fbo; + GLuint color; GLuint depth; struct Buffers { @@ -890,8 +887,35 @@ public: GLuint specular; GLuint diffuse; GLuint normal_sr; + GLuint temporal; } buffers; + struct Effects { + + struct MipMaps { + + struct Size { + GLuint fbo; + int width; + int height; + }; + + Vector sizes; + GLuint color; + int levels; + + MipMaps() { color=0; levels=0;} + }; + + MipMaps mip_maps[2]; //first mipmap chain starts from full-screen + //GLuint depth2; //depth for the second mipmap chain, in case of desiring upsampling + + Effects() { + + } + + } effects; + int width,height; bool flags[RENDER_TARGET_FLAG_MAX]; @@ -905,8 +929,7 @@ public: width=0; height=0; depth=0; - front.fbo=0; - back.fbo=0; + fbo=0; buffers.fbo=0; buffers.alpha_fbo=0; used_in_frame=false; diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp index d29927b137..778d3b23ec 100644 --- a/drivers/gles3/shader_gles3.cpp +++ b/drivers/gles3/shader_gles3.cpp @@ -393,8 +393,8 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() { strings.resize(strings_base_size); //fragment precision is medium - strings.push_back("precision mediump float;\n"); - strings.push_back("precision mediump int;\n"); + strings.push_back("precision highp float;\n"); + strings.push_back("precision highp int;\n"); #if 0 if (cc) { diff --git a/drivers/gles3/shaders/SCsub b/drivers/gles3/shaders/SCsub index a9808dcbcf..66a19eefd1 100644 --- a/drivers/gles3/shaders/SCsub +++ b/drivers/gles3/shaders/SCsub @@ -2,10 +2,13 @@ Import('env') if env['BUILDERS'].has_key('GLES3_GLSL'): env.GLES3_GLSL('copy.glsl'); + env.GLES3_GLSL('resolve.glsl'); env.GLES3_GLSL('canvas.glsl'); env.GLES3_GLSL('canvas_shadow.glsl'); env.GLES3_GLSL('scene.glsl'); env.GLES3_GLSL('cubemap_filter.glsl'); env.GLES3_GLSL('cube_to_dp.glsl'); env.GLES3_GLSL('blend_shape.glsl'); + env.GLES3_GLSL('screen_space_reflection.glsl'); + env.GLES3_GLSL('effect_blur.glsl'); diff --git a/drivers/gles3/shaders/copy.glsl b/drivers/gles3/shaders/copy.glsl index 79982ecf25..a87d62f2d7 100644 --- a/drivers/gles3/shaders/copy.glsl +++ b/drivers/gles3/shaders/copy.glsl @@ -50,6 +50,7 @@ float sRGB_gamma_correct(float c){ uniform float stuff; +uniform vec2 pixel_size; in vec2 uv2_interp; @@ -81,6 +82,24 @@ void main() { color.a=1.0; #endif + +#ifdef GAUSSIAN_HORIZONTAL + color*=0.38774; + color+=texture( source, uv_interp+vec2( 1.0, 0.0)*pixel_size )*0.24477; + color+=texture( source, uv_interp+vec2( 2.0, 0.0)*pixel_size )*0.06136; + color+=texture( source, uv_interp+vec2(-1.0, 0.0)*pixel_size )*0.24477; + color+=texture( source, uv_interp+vec2(-2.0, 0.0)*pixel_size )*0.06136; +#endif + +#ifdef GAUSSIAN_VERTICAL + color*=0.38774; + color+=texture( source, uv_interp+vec2( 0.0, 1.0)*pixel_size )*0.24477; + color+=texture( source, uv_interp+vec2( 0.0, 2.0)*pixel_size )*0.06136; + color+=texture( source, uv_interp+vec2( 0.0,-1.0)*pixel_size )*0.24477; + color+=texture( source, uv_interp+vec2( 0.0,-2.0)*pixel_size )*0.06136; +#endif + + frag_color = color; } diff --git a/drivers/gles3/shaders/resolve.glsl b/drivers/gles3/shaders/resolve.glsl new file mode 100644 index 0000000000..4ca6297303 --- /dev/null +++ b/drivers/gles3/shaders/resolve.glsl @@ -0,0 +1,45 @@ +[vertex] + + +layout(location=0) in highp vec4 vertex_attrib; +layout(location=4) in vec2 uv_in; + +out vec2 uv_interp; + + +void main() { + + uv_interp = uv_in; + gl_Position = vertex_attrib; +} + +[fragment] + + +in vec2 uv_interp; +uniform sampler2D source_diffuse; //texunit:0 +uniform sampler2D source_specular; //texunit:1 + + +uniform sampler2D source_ssr_ssao; //texunit:2 + +uniform float stuff; + +in vec2 uv2_interp; + +layout(location = 0) out vec4 frag_color; + +void main() { + + vec4 diffuse = texture( source_diffuse, uv_interp ); + vec4 specular = texture( source_specular, uv_interp ); + +#ifdef USE_SSR + + vec4 ssr = textureLod(source_ssr_ssao,uv_interp,0.0); + specular.rgb = mix(specular.rgb,ssr.rgb*specular.a,ssr.a); +#endif + + frag_color = vec4(diffuse.rgb,1.0)+vec4(specular.rgb,1.0); +} + diff --git a/drivers/gles3/shaders/resolve.glsl.h b/drivers/gles3/shaders/resolve.glsl.h new file mode 100644 index 0000000000..72baf50716 --- /dev/null +++ b/drivers/gles3/shaders/resolve.glsl.h @@ -0,0 +1,166 @@ +/* WARNING, THIS FILE WAS GENERATED, DO NOT EDIT */ +#ifndef RESOLVE_GLSL_HGLES3_120 +#define RESOLVE_GLSL_HGLES3_120 + + +#include "drivers/gles3/shader_gles3.h" + + +class ResolveShaderGLES3 : public ShaderGLES3 { + + virtual String get_shader_name() const { return "ResolveShaderGLES3"; } +public: + + enum Conditionals { + USE_SSR, + }; + + enum Uniforms { + STUFF, + }; + + _FORCE_INLINE_ int get_uniform(Uniforms p_uniform) const { return _get_uniform(p_uniform); } + + _FORCE_INLINE_ void set_conditional(Conditionals p_conditional,bool p_enable) { _set_conditional(p_conditional,p_enable); } + + #define _FU if (get_uniform(p_uniform)<0) return; ERR_FAIL_COND( get_active()!=this ); + + _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, float p_value) { _FU glUniform1f(get_uniform(p_uniform),p_value); } + + _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, double p_value) { _FU glUniform1f(get_uniform(p_uniform),p_value); } + + _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, uint8_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); } + + _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, int8_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); } + + _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, uint16_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); } + + _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, int16_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); } + + _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, uint32_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); } + + _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, int32_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); } + + _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Color& p_color) { _FU GLfloat col[4]={p_color.r,p_color.g,p_color.b,p_color.a}; glUniform4fv(get_uniform(p_uniform),1,col); } + + _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Vector2& p_vec2) { _FU GLfloat vec2[2]={p_vec2.x,p_vec2.y}; glUniform2fv(get_uniform(p_uniform),1,vec2); } + + _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Vector3& p_vec3) { _FU GLfloat vec3[3]={p_vec3.x,p_vec3.y,p_vec3.z}; glUniform3fv(get_uniform(p_uniform),1,vec3); } + + _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, float p_a, float p_b) { _FU glUniform2f(get_uniform(p_uniform),p_a,p_b); } + + _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, float p_a, float p_b, float p_c) { _FU glUniform3f(get_uniform(p_uniform),p_a,p_b,p_c); } + + _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, float p_a, float p_b, float p_c, float p_d) { _FU glUniform4f(get_uniform(p_uniform),p_a,p_b,p_c,p_d); } + + _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Transform& p_transform) { _FU + + const Transform &tr = p_transform; + + GLfloat matrix[16]={ /* build a 16x16 matrix */ + tr.basis.elements[0][0], + tr.basis.elements[1][0], + tr.basis.elements[2][0], + 0, + tr.basis.elements[0][1], + tr.basis.elements[1][1], + tr.basis.elements[2][1], + 0, + tr.basis.elements[0][2], + tr.basis.elements[1][2], + tr.basis.elements[2][2], + 0, + tr.origin.x, + tr.origin.y, + tr.origin.z, + 1 + }; + + + glUniformMatrix4fv(get_uniform(p_uniform),1,false,matrix); + + + } + + _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Matrix32& p_transform) { _FU + + const Matrix32 &tr = p_transform; + + GLfloat matrix[16]={ /* build a 16x16 matrix */ + tr.elements[0][0], + tr.elements[0][1], + 0, + 0, + tr.elements[1][0], + tr.elements[1][1], + 0, + 0, + 0, + 0, + 1, + 0, + tr.elements[2][0], + tr.elements[2][1], + 0, + 1 + }; + + + glUniformMatrix4fv(get_uniform(p_uniform),1,false,matrix); + + + } + + _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const CameraMatrix& p_matrix) { _FU + + GLfloat matrix[16]; + + for (int i=0;i<4;i++) { + for (int j=0;j<4;j++) { + + matrix[i*4+j]=p_matrix.matrix[i][j]; + } + } + + glUniformMatrix4fv(get_uniform(p_uniform),1,false,matrix); + }; + +#undef _FU + + + virtual void init() { + + static const Enum *_enums=NULL; + static const EnumValue *_enum_values=NULL; + static const char* _conditional_strings[]={ + "#define USE_SSR\n", + }; + + static const char* _uniform_strings[]={ + "stuff", + }; + + static AttributePair *_attribute_pairs=NULL; + static const Feedback* _feedbacks=NULL; + static TexUnitPair _texunit_pairs[]={ + {"source_diffuse",0}, + {"source_specular",1}, + {"source_ssr_ssao",2}, + }; + + static UBOPair *_ubo_pairs=NULL; + static const char _vertex_code[]={ +10,10,108,97,121,111,117,116,40,108,111,99,97,116,105,111,110,61,48,41,32,105,110,32,104,105,103,104,112,32,118,101,99,52,32,118,101,114,116,101,120,95,97,116,116,114,105,98,59,10,108,97,121,111,117,116,40,108,111,99,97,116,105,111,110,61,52,41,32,105,110,32,118,101,99,50,32,117,118,95,105,110,59,10,10,111,117,116,32,118,101,99,50,32,117,118,95,105,110,116,101,114,112,59,10,10,10,118,111,105,100,32,109,97,105,110,40,41,32,123,10,10,9,117,118,95,105,110,116,101,114,112,32,61,32,117,118,95,105,110,59,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,118,101,114,116,101,120,95,97,116,116,114,105,98,59,10,125,10,10, 0}; + + static const int _vertex_code_start=1; + static const char _fragment_code[]={ +10,10,105,110,32,118,101,99,50,32,117,118,95,105,110,116,101,114,112,59,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,115,111,117,114,99,101,95,100,105,102,102,117,115,101,59,32,47,47,116,101,120,117,110,105,116,58,48,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,115,111,117,114,99,101,95,115,112,101,99,117,108,97,114,59,32,47,47,116,101,120,117,110,105,116,58,49,10,10,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,115,111,117,114,99,101,95,115,115,114,95,115,115,97,111,59,32,47,47,116,101,120,117,110,105,116,58,50,10,10,117,110,105,102,111,114,109,32,102,108,111,97,116,32,115,116,117,102,102,59,10,10,105,110,32,118,101,99,50,32,117,118,50,95,105,110,116,101,114,112,59,10,10,108,97,121,111,117,116,40,108,111,99,97,116,105,111,110,32,61,32,48,41,32,111,117,116,32,118,101,99,52,32,102,114,97,103,95,99,111,108,111,114,59,10,10,118,111,105,100,32,109,97,105,110,40,41,32,123,10,10,9,118,101,99,52,32,100,105,102,102,117,115,101,32,61,32,116,101,120,116,117,114,101,40,32,115,111,117,114,99,101,95,100,105,102,102,117,115,101,44,32,32,117,118,95,105,110,116,101,114,112,32,41,59,10,9,118,101,99,52,32,115,112,101,99,117,108,97,114,32,61,32,116,101,120,116,117,114,101,40,32,115,111,117,114,99,101,95,115,112,101,99,117,108,97,114,44,32,32,117,118,95,105,110,116,101,114,112,32,41,59,10,10,35,105,102,100,101,102,32,85,83,69,95,83,83,82,10,10,9,118,101,99,52,32,115,115,114,32,61,32,116,101,120,116,117,114,101,76,111,100,40,115,111,117,114,99,101,95,115,115,114,95,115,115,97,111,44,117,118,95,105,110,116,101,114,112,44,48,46,48,41,59,10,9,115,112,101,99,117,108,97,114,46,114,103,98,32,61,32,109,105,120,40,115,112,101,99,117,108,97,114,46,114,103,98,44,115,115,114,46,114,103,98,42,115,112,101,99,117,108,97,114,46,97,44,115,115,114,46,97,41,59,10,35,101,110,100,105,102,10,10,9,102,114,97,103,95,99,111,108,111,114,32,61,32,118,101,99,52,40,100,105,102,102,117,115,101,46,114,103,98,44,49,46,48,41,43,118,101,99,52,40,115,112,101,99,117,108,97,114,46,114,103,98,44,49,46,48,41,59,10,125,10,10, 0}; + + static const int _fragment_code_start=16; + setup(_conditional_strings,1,_uniform_strings,1,_attribute_pairs,0, _texunit_pairs,3,_ubo_pairs,0,_feedbacks,0,_vertex_code,_fragment_code,_vertex_code_start,_fragment_code_start); + }; + +}; + +#endif + diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index c198534728..192042192e 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -1189,8 +1189,10 @@ LIGHT_SHADER_CODE #endif //ENABLE_AO diffuse_buffer=vec4(emission+diffuse_light+ambient_light,ambient_scale); - specular_buffer=vec4(specular_light,0.0); - normal_mr_buffer=vec4(normal.x,normal.y,max(specular.r,max(specular.g,specular.b)),roughness); + specular_buffer=vec4(specular_light,max(specular.r,max(specular.g,specular.b))); + + + normal_mr_buffer=vec4(normalize(normal)*0.5+0.5,roughness); #else diff --git a/drivers/gles3/shaders/screen_space.glsl.h b/drivers/gles3/shaders/screen_space.glsl.h new file mode 100644 index 0000000000..f39d04429d --- /dev/null +++ b/drivers/gles3/shaders/screen_space.glsl.h @@ -0,0 +1,183 @@ +/* WARNING, THIS FILE WAS GENERATED, DO NOT EDIT */ +#ifndef SCREEN_SPACE_GLSL_HGLES3_120 +#define SCREEN_SPACE_GLSL_HGLES3_120 + + +#include "drivers/gles3/shader_gles3.h" + + +class ScreenSpaceShaderGLES3 : public ShaderGLES3 { + + virtual String get_shader_name() const { return "ScreenSpaceShaderGLES3"; } +public: + + enum Conditionals { + BLEND_ACCEL, + REFLECT_ROUGHNESS, + }; + + enum Uniforms { + CAMERA_Z_NEAR, + CAMERA_Z_FAR, + VIEWPORT_SIZE, + PIXEL_SIZE, + FILTER_MIPMAP_LEVELS, + INVERSE_PROJECTION, + PROJECTION, + FRAME_INDEX, + }; + + _FORCE_INLINE_ int get_uniform(Uniforms p_uniform) const { return _get_uniform(p_uniform); } + + _FORCE_INLINE_ void set_conditional(Conditionals p_conditional,bool p_enable) { _set_conditional(p_conditional,p_enable); } + + #define _FU if (get_uniform(p_uniform)<0) return; ERR_FAIL_COND( get_active()!=this ); + + _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, float p_value) { _FU glUniform1f(get_uniform(p_uniform),p_value); } + + _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, double p_value) { _FU glUniform1f(get_uniform(p_uniform),p_value); } + + _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, uint8_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); } + + _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, int8_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); } + + _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, uint16_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); } + + _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, int16_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); } + + _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, uint32_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); } + + _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, int32_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); } + + _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Color& p_color) { _FU GLfloat col[4]={p_color.r,p_color.g,p_color.b,p_color.a}; glUniform4fv(get_uniform(p_uniform),1,col); } + + _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Vector2& p_vec2) { _FU GLfloat vec2[2]={p_vec2.x,p_vec2.y}; glUniform2fv(get_uniform(p_uniform),1,vec2); } + + _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Vector3& p_vec3) { _FU GLfloat vec3[3]={p_vec3.x,p_vec3.y,p_vec3.z}; glUniform3fv(get_uniform(p_uniform),1,vec3); } + + _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, float p_a, float p_b) { _FU glUniform2f(get_uniform(p_uniform),p_a,p_b); } + + _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, float p_a, float p_b, float p_c) { _FU glUniform3f(get_uniform(p_uniform),p_a,p_b,p_c); } + + _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, float p_a, float p_b, float p_c, float p_d) { _FU glUniform4f(get_uniform(p_uniform),p_a,p_b,p_c,p_d); } + + _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Transform& p_transform) { _FU + + const Transform &tr = p_transform; + + GLfloat matrix[16]={ /* build a 16x16 matrix */ + tr.basis.elements[0][0], + tr.basis.elements[1][0], + tr.basis.elements[2][0], + 0, + tr.basis.elements[0][1], + tr.basis.elements[1][1], + tr.basis.elements[2][1], + 0, + tr.basis.elements[0][2], + tr.basis.elements[1][2], + tr.basis.elements[2][2], + 0, + tr.origin.x, + tr.origin.y, + tr.origin.z, + 1 + }; + + + glUniformMatrix4fv(get_uniform(p_uniform),1,false,matrix); + + + } + + _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Matrix32& p_transform) { _FU + + const Matrix32 &tr = p_transform; + + GLfloat matrix[16]={ /* build a 16x16 matrix */ + tr.elements[0][0], + tr.elements[0][1], + 0, + 0, + tr.elements[1][0], + tr.elements[1][1], + 0, + 0, + 0, + 0, + 1, + 0, + tr.elements[2][0], + tr.elements[2][1], + 0, + 1 + }; + + + glUniformMatrix4fv(get_uniform(p_uniform),1,false,matrix); + + + } + + _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const CameraMatrix& p_matrix) { _FU + + GLfloat matrix[16]; + + for (int i=0;i<4;i++) { + for (int j=0;j<4;j++) { + + matrix[i*4+j]=p_matrix.matrix[i][j]; + } + } + + glUniformMatrix4fv(get_uniform(p_uniform),1,false,matrix); + }; + +#undef _FU + + + virtual void init() { + + static const Enum *_enums=NULL; + static const EnumValue *_enum_values=NULL; + static const char* _conditional_strings[]={ + "#define BLEND_ACCEL\n", + "#define REFLECT_ROUGHNESS\n", + }; + + static const char* _uniform_strings[]={ + "camera_z_near", + "camera_z_far", + "viewport_size", + "pixel_size", + "filter_mipmap_levels", + "inverse_projection", + "projection", + "frame_index", + }; + + static AttributePair *_attribute_pairs=NULL; + static const Feedback* _feedbacks=NULL; + static TexUnitPair _texunit_pairs[]={ + {"source_diffuse",0}, + {"source_normal_roughness",1}, + {"source_depth",2}, + {"source_diffuse_mipmaps",3}, + }; + + static UBOPair *_ubo_pairs=NULL; + static const char _vertex_code[]={ +10,10,108,97,121,111,117,116,40,108,111,99,97,116,105,111,110,61,48,41,32,105,110,32,104,105,103,104,112,32,118,101,99,52,32,118,101,114,116,101,120,95,97,116,116,114,105,98,59,10,108,97,121,111,117,116,40,108,111,99,97,116,105,111,110,61,52,41,32,105,110,32,118,101,99,50,32,117,118,95,105,110,59,10,10,111,117,116,32,118,101,99,50,32,117,118,95,105,110,116,101,114,112,59,10,111,117,116,32,118,101,99,50,32,112,111,115,95,105,110,116,101,114,112,59,10,10,118,111,105,100,32,109,97,105,110,40,41,32,123,10,10,9,117,118,95,105,110,116,101,114,112,32,61,32,117,118,95,105,110,59,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,118,101,114,116,101,120,95,97,116,116,114,105,98,59,10,9,112,111,115,95,105,110,116,101,114,112,46,120,121,61,103,108,95,80,111,115,105,116,105,111,110,46,120,121,59,10,125,10,10, 0}; + + static const int _vertex_code_start=1; + static const char _fragment_code[]={ +10,10,105,110,32,118,101,99,50,32,117,118,95,105,110,116,101,114,112,59,10,105,110,32,118,101,99,50,32,112,111,115,95,105,110,116,101,114,112,59,10,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,115,111,117,114,99,101,95,100,105,102,102,117,115,101,59,32,47,47,116,101,120,117,110,105,116,58,48,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,115,111,117,114,99,101,95,110,111,114,109,97,108,95,114,111,117,103,104,110,101,115,115,59,32,47,47,116,101,120,117,110,105,116,58,49,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,115,111,117,114,99,101,95,100,101,112,116,104,59,32,47,47,116,101,120,117,110,105,116,58,50,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,115,111,117,114,99,101,95,100,105,102,102,117,115,101,95,109,105,112,109,97,112,115,59,32,47,47,116,101,120,117,110,105,116,58,51,10,10,117,110,105,102,111,114,109,32,102,108,111,97,116,32,99,97,109,101,114,97,95,122,95,110,101,97,114,59,10,117,110,105,102,111,114,109,32,102,108,111,97,116,32,99,97,109,101,114,97,95,122,95,102,97,114,59,10,10,117,110,105,102,111,114,109,32,118,101,99,50,32,118,105,101,119,112,111,114,116,95,115,105,122,101,59,10,117,110,105,102,111,114,109,32,118,101,99,50,32,112,105,120,101,108,95,115,105,122,101,59,10,10,117,110,105,102,111,114,109,32,102,108,111,97,116,32,102,105,108,116,101,114,95,109,105,112,109,97,112,95,108,101,118,101,108,115,59,10,10,117,110,105,102,111,114,109,32,109,97,116,52,32,105,110,118,101,114,115,101,95,112,114,111,106,101,99,116,105,111,110,59,10,117,110,105,102,111,114,109,32,109,97,116,52,32,112,114,111,106,101,99,116,105,111,110,59,10,10,117,110,105,102,111,114,109,32,105,110,116,32,102,114,97,109,101,95,105,110,100,101,120,59,10,10,118,101,99,50,32,118,105,101,119,95,116,111,95,115,99,114,101,101,110,40,118,101,99,51,32,118,105,101,119,95,112,111,115,44,111,117,116,32,102,108,111,97,116,32,119,41,32,123,10,32,32,32,32,118,101,99,52,32,112,114,111,106,101,99,116,101,100,32,61,32,112,114,111,106,101,99,116,105,111,110,32,42,32,118,101,99,52,40,118,105,101,119,95,112,111,115,44,32,49,46,48,41,59,10,32,32,32,32,112,114,111,106,101,99,116,101,100,46,120,121,122,32,47,61,32,112,114,111,106,101,99,116,101,100,46,119,59,10,32,32,32,32,112,114,111,106,101,99,116,101,100,46,120,121,32,61,32,112,114,111,106,101,99,116,101,100,46,120,121,32,42,32,48,46,53,32,43,32,48,46,53,59,10,32,32,32,32,119,61,112,114,111,106,101,99,116,101,100,46,119,59,10,32,32,32,32,114,101,116,117,114,110,32,112,114,111,106,101,99,116,101,100,46,120,121,59,10,125,10,10,10,108,97,121,111,117,116,40,108,111,99,97,116,105,111,110,32,61,32,48,41,32,111,117,116,32,118,101,99,52,32,102,114,97,103,95,99,111,108,111,114,59,10,10,35,100,101,102,105,110,101,32,78,85,77,95,82,65,89,68,73,82,95,82,69,84,82,73,69,83,32,51,10,10,47,47,102,114,111,109,32,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,116,111,98,115,112,114,44,32,105,102,32,105,116,32,119,111,114,107,115,32,102,111,114,32,121,111,117,44,32,100,117,100,101,46,46,10,118,101,99,51,32,114,97,110,100,95,114,103,98,40,118,101,99,50,32,99,111,41,32,123,10,32,32,32,32,114,101,116,117,114,110,32,97,98,115,40,102,114,97,99,116,40,115,105,110,40,100,111,116,40,99,111,46,120,121,44,32,118,101,99,50,40,51,52,46,52,56,51,53,44,32,56,57,46,54,51,55,50,41,41,41,32,42,10,9,118,101,99,51,40,50,57,49,53,54,46,52,55,54,53,44,32,51,56,50,55,51,46,53,54,51,57,51,44,32,52,55,56,52,51,46,55,53,52,54,56,41,41,41,32,42,32,50,32,45,32,49,59,10,125,10,10,35,100,101,102,105,110,101,32,77,95,80,73,32,51,46,49,52,49,53,57,50,54,53,51,53,57,10,10,118,101,99,51,32,105,109,112,111,114,116,97,110,99,101,95,115,97,109,112,108,101,95,103,103,120,40,118,101,99,50,32,120,105,44,32,102,108,111,97,116,32,114,111,117,103,104,110,101,115,115,41,10,123,10,32,32,32,32,102,108,111,97,116,32,114,95,115,113,117,97,114,101,32,61,32,114,111,117,103,104,110,101,115,115,32,42,32,114,111,117,103,104,110,101,115,115,59,10,32,32,32,32,102,108,111,97,116,32,112,104,105,32,61,32,50,32,42,32,77,95,80,73,32,42,32,120,105,46,120,59,10,32,32,32,32,102,108,111,97,116,32,99,111,115,95,116,104,101,116,97,32,61,32,115,113,114,116,40,40,49,32,45,32,120,105,46,121,41,32,47,32,40,49,32,43,32,40,114,95,115,113,117,97,114,101,32,42,32,114,95,115,113,117,97,114,101,32,45,32,49,41,32,42,32,120,105,46,121,41,41,59,10,32,32,32,32,102,108,111,97,116,32,115,105,110,95,116,104,101,116,97,32,61,32,115,113,114,116,40,49,32,45,32,99,111,115,95,116,104,101,116,97,32,42,32,99,111,115,95,116,104,101,116,97,41,59,10,10,32,32,32,32,114,101,116,117,114,110,32,118,101,99,51,40,115,105,110,95,116,104,101,116,97,32,42,32,99,111,115,40,112,104,105,41,44,32,115,105,110,95,116,104,101,116,97,32,42,32,115,105,110,40,112,104,105,41,44,32,99,111,115,95,116,104,101,116,97,41,59,10,125,10,10,118,111,105,100,32,102,105,110,100,95,97,114,98,105,116,114,97,114,121,95,116,97,110,103,101,110,116,40,118,101,99,51,32,110,111,114,109,97,108,44,32,111,117,116,32,118,101,99,51,32,116,97,110,103,101,110,116,44,32,111,117,116,32,118,101,99,51,32,98,105,116,97,110,103,101,110,116,41,32,123,10,32,32,32,32,118,101,99,51,32,118,48,32,61,32,97,98,115,40,110,111,114,109,97,108,46,122,41,32,60,32,48,46,57,57,57,32,63,32,118,101,99,51,40,48,46,48,44,32,48,46,48,44,32,49,46,48,41,32,58,32,118,101,99,51,40,48,46,48,44,32,49,46,48,44,32,48,46,48,41,59,10,32,32,32,32,116,97,110,103,101,110,116,32,61,32,110,111,114,109,97,108,105,122,101,40,99,114,111,115,115,40,118,48,44,32,110,111,114,109,97,108,41,41,59,10,32,32,32,32,98,105,116,97,110,103,101,110,116,32,61,32,110,111,114,109,97,108,105,122,101,40,99,114,111,115,115,40,116,97,110,103,101,110,116,44,32,110,111,114,109,97,108,41,41,59,10,125,10,10,98,111,111,108,32,112,111,105,110,116,95,98,101,116,119,101,101,110,95,112,108,97,110,101,115,40,102,108,111,97,116,32,122,44,32,102,108,111,97,116,32,122,95,97,44,32,102,108,111,97,116,32,122,95,98,44,32,102,108,111,97,116,32,116,114,97,99,101,95,108,101,110,103,116,104,44,32,111,117,116,32,98,111,111,108,32,104,105,116,95,102,97,99,116,111,114,41,32,123,10,10,32,32,32,32,47,47,32,84,104,105,115,32,116,114,97,99,101,115,32,99,111,114,114,101,99,116,44,32,98,117,116,32,108,111,111,107,115,32,119,101,105,114,100,32,98,101,99,97,117,115,101,32,103,97,112,115,32,97,114,101,32,110,111,116,32,102,105,108,108,101,100,10,32,32,32,32,47,47,32,114,101,116,117,114,110,32,122,32,43,32,104,105,116,95,116,111,108,101,114,97,110,99,101,95,119,115,32,62,61,32,109,105,110,40,122,95,97,44,32,122,95,98,41,32,45,32,48,46,48,48,48,49,53,32,38,38,32,122,32,45,32,104,105,116,95,116,111,108,101,114,97,110,99,101,95,119,115,32,60,61,32,109,97,120,40,122,95,97,44,32,122,95,98,41,59,10,10,32,32,32,32,104,105,116,95,102,97,99,116,111,114,32,61,32,102,97,108,115,101,59,10,10,32,32,32,32,47,47,32,84,104,105,115,32,116,114,97,99,101,115,32,34,105,110,99,111,114,114,101,99,116,34,44,32,98,117,116,32,108,111,111,107,115,32,98,101,116,116,101,114,32,98,101,99,97,117,115,101,32,103,97,112,115,32,97,114,101,32,103,101,116,116,105,110,103,32,102,105,108,108,101,100,32,116,104,101,110,10,32,32,32,32,102,108,111,97,116,32,104,105,116,95,116,111,108,101,114,97,110,99,101,95,119,115,61,48,46,48,48,48,49,59,10,32,32,32,32,99,111,110,115,116,32,102,108,111,97,116,32,104,105,116,95,116,111,108,101,114,97,110,99,101,95,98,97,99,107,102,97,99,101,32,61,32,48,46,48,48,48,48,48,49,59,10,32,32,32,32,105,102,32,40,122,32,45,32,104,105,116,95,116,111,108,101,114,97,110,99,101,95,119,115,32,42,32,116,114,97,99,101,95,108,101,110,103,116,104,32,60,61,32,109,97,120,40,122,95,97,44,32,122,95,98,41,41,32,123,10,10,32,32,32,32,32,105,102,32,40,116,114,117,101,41,32,123,10,9,32,32,32,32,104,105,116,95,102,97,99,116,111,114,32,61,32,40,122,32,43,32,104,105,116,95,116,111,108,101,114,97,110,99,101,95,119,115,32,42,32,116,114,97,99,101,95,108,101,110,103,116,104,41,32,62,61,10,9,9,9,32,32,32,32,109,105,110,40,122,95,97,44,32,122,95,98,41,32,45,32,104,105,116,95,116,111,108,101,114,97,110,99,101,95,98,97,99,107,102,97,99,101,59,10,32,32,32,32,32,125,32,101,108,115,101,32,123,10,9,32,32,32,32,104,105,116,95,102,97,99,116,111,114,32,61,32,116,114,117,101,59,10,32,32,32,32,32,32,125,10,10,9,114,101,116,117,114,110,32,116,114,117,101,59,10,32,32,32,32,125,10,10,32,32,32,32,114,101,116,117,114,110,32,102,97,108,115,101,59,10,125,10,10,98,111,111,108,32,111,117,116,95,111,102,95,115,99,114,101,101,110,40,118,101,99,50,32,116,99,111,111,114,100,41,32,123,10,32,32,32,32,114,101,116,117,114,110,32,116,99,111,111,114,100,46,120,32,60,32,48,46,48,32,124,124,32,116,99,111,111,114,100,46,121,32,60,32,48,46,48,32,124,124,32,116,99,111,111,114,100,46,120,32,62,32,49,46,48,32,124,124,32,116,99,111,111,114,100,46,121,32,62,32,49,46,48,59,10,125,10,10,102,108,111,97,116,32,100,105,115,116,97,110,99,101,83,113,117,97,114,101,100,40,118,101,99,50,32,97,44,32,118,101,99,50,32,98,41,32,123,32,97,32,45,61,32,98,59,32,114,101,116,117,114,110,32,100,111,116,40,97,44,32,97,41,59,32,125,10,10,118,101,99,51,32,99,111,109,112,117,116,101,67,108,105,112,73,110,102,111,40,102,108,111,97,116,32,122,110,44,32,102,108,111,97,116,32,122,102,41,32,123,10,32,114,101,116,117,114,110,32,118,101,99,51,40,122,110,32,32,42,32,122,102,44,32,122,110,32,45,32,122,102,44,32,122,102,41,59,10,10,125,10,10,10,102,108,111,97,116,32,114,101,99,111,110,115,116,114,117,99,116,67,83,90,40,102,108,111,97,116,32,100,101,112,116,104,66,117,102,102,101,114,86,97,108,117,101,44,32,118,101,99,51,32,99,41,32,123,10,32,32,32,32,32,32,114,101,116,117,114,110,32,99,91,48,93,32,47,32,40,100,101,112,116,104,66,117,102,102,101,114,86,97,108,117,101,32,42,32,99,91,49,93,32,43,32,99,91,50,93,41,59,10,125,10,10,10,98,111,111,108,32,116,114,97,99,101,83,99,114,101,101,110,83,112,97,99,101,82,97,121,49,10,32,32,32,40,118,101,99,51,32,32,32,32,32,32,32,32,32,32,99,115,79,114,105,103,105,110,44,10,32,32,32,32,118,101,99,51,32,32,32,32,32,32,32,32,32,99,115,68,105,114,101,99,116,105,111,110,44,10,32,32,32,32,109,97,116,52,120,52,32,32,32,32,32,32,32,32,32,32,112,114,111,106,101,99,116,84,111,80,105,120,101,108,77,97,116,114,105,120,44,10,32,32,32,32,115,97,109,112,108,101,114,50,68,32,32,32,32,32,32,32,99,115,90,66,117,102,102,101,114,44,10,32,32,32,32,118,101,99,50,32,32,32,32,32,32,32,32,32,32,99,115,90,66,117,102,102,101,114,83,105,122,101,44,10,32,32,32,32,102,108,111,97,116,32,32,32,32,32,32,32,32,32,32,32,99,115,90,84,104,105,99,107,110,101,115,115,44,10,32,32,32,32,99,111,110,115,116,32,105,110,32,98,111,111,108,32,32,32,99,115,90,66,117,102,102,101,114,73,115,72,121,112,101,114,98,111,108,105,99,44,10,32,32,32,32,118,101,99,51,32,32,32,32,32,32,32,32,32,32,99,108,105,112,73,110,102,111,44,10,32,32,32,32,102,108,111,97,116,32,32,32,32,32,32,32,32,32,32,32,110,101,97,114,80,108,97,110,101,90,44,10,32,32,32,32,102,108,111,97,116,9,9,9,115,116,114,105,100,101,44,10,32,32,32,32,102,108,111,97,116,32,32,32,32,32,32,32,32,32,32,32,106,105,116,116,101,114,70,114,97,99,116,105,111,110,44,10,32,32,32,32,102,108,111,97,116,32,32,32,32,32,32,32,32,32,32,32,109,97,120,83,116,101,112,115,44,10,32,32,32,32,105,110,32,102,108,111,97,116,32,32,32,32,32,32,32,32,109,97,120,82,97,121,84,114,97,99,101,68,105,115,116,97,110,99,101,44,10,32,32,32,32,111,117,116,32,118,101,99,50,32,32,32,32,32,32,104,105,116,80,105,120,101,108,44,10,32,32,32,32,111,117,116,32,105,110,116,32,32,32,32,32,32,32,32,32,119,104,105,99,104,44,10,9,111,117,116,32,118,101,99,51,9,9,99,115,72,105,116,80,111,105,110,116,41,32,123,10,10,9,47,47,32,67,108,105,112,32,114,97,121,32,116,111,32,97,32,110,101,97,114,32,112,108,97,110,101,32,105,110,32,51,68,32,40,100,111,101,115,110,39,116,32,104,97,118,101,32,116,111,32,98,101,32,42,116,104,101,42,32,110,101,97,114,32,112,108,97,110,101,44,32,97,108,116,104,111,117,103,104,32,116,104,97,116,32,119,111,117,108,100,32,98,101,32,97,32,103,111,111,100,32,105,100,101,97,41,10,9,102,108,111,97,116,32,114,97,121,76,101,110,103,116,104,32,61,32,40,40,99,115,79,114,105,103,105,110,46,122,32,43,32,99,115,68,105,114,101,99,116,105,111,110,46,122,32,42,32,109,97,120,82,97,121,84,114,97,99,101,68,105,115,116,97,110,99,101,41,32,62,32,110,101,97,114,80,108,97,110,101,90,41,32,63,10,9,9,9,9,40,110,101,97,114,80,108,97,110,101,90,32,45,32,99,115,79,114,105,103,105,110,46,122,41,32,47,32,99,115,68,105,114,101,99,116,105,111,110,46,122,32,58,10,9,9,9,9,109,97,120,82,97,121,84,114,97,99,101,68,105,115,116,97,110,99,101,59,10,9,118,101,99,51,32,99,115,69,110,100,80,111,105,110,116,32,61,32,99,115,68,105,114,101,99,116,105,111,110,32,42,32,114,97,121,76,101,110,103,116,104,32,43,32,99,115,79,114,105,103,105,110,59,10,10,9,47,47,32,80,114,111,106,101,99,116,32,105,110,116,111,32,115,99,114,101,101,110,32,115,112,97,99,101,10,9,118,101,99,52,32,72,48,32,61,32,112,114,111,106,101,99,116,84,111,80,105,120,101,108,77,97,116,114,105,120,32,42,32,118,101,99,52,40,99,115,79,114,105,103,105,110,44,32,49,46,48,41,59,10,9,118,101,99,52,32,72,49,32,61,32,112,114,111,106,101,99,116,84,111,80,105,120,101,108,77,97,116,114,105,120,32,42,32,118,101,99,52,40,99,115,69,110,100,80,111,105,110,116,44,32,49,46,48,41,59,10,10,9,47,47,32,84,104,101,114,101,32,97,114,101,32,97,32,108,111,116,32,111,102,32,100,105,118,105,115,105,111,110,115,32,98,121,32,119,32,116,104,97,116,32,99,97,110,32,98,101,32,116,117,114,110,101,100,32,105,110,116,111,32,109,117,108,116,105,112,108,105,99,97,116,105,111,110,115,10,9,47,47,32,97,116,32,115,111,109,101,32,109,105,110,111,114,32,112,114,101,99,105,115,105,111,110,32,108,111,115,115,46,46,46,97,110,100,32,119,101,32,110,101,101,100,32,116,111,32,105,110,116,101,114,112,111,108,97,116,101,32,116,104,101,115,101,32,49,47,119,32,118,97,108,117,101,115,10,9,47,47,32,97,110,121,119,97,121,46,10,9,47,47,10,9,47,47,32,66,101,99,97,117,115,101,32,116,104,101,32,99,97,108,108,101,114,32,119,97,115,32,114,101,113,117,105,114,101,100,32,116,111,32,99,108,105,112,32,116,111,32,116,104,101,32,110,101,97,114,32,112,108,97,110,101,44,10,9,47,47,32,116,104,105,115,32,104,111,109,111,103,101,110,101,111,117,115,32,100,105,118,105,115,105,111,110,32,40,112,114,111,106,101,99,116,105,110,103,32,102,114,111,109,32,52,68,32,116,111,32,50,68,41,32,105,115,32,103,117,97,114,97,110,116,101,101,100,10,9,47,47,32,116,111,32,115,117,99,99,101,101,100,46,10,9,102,108,111,97,116,32,107,48,32,61,32,49,46,48,32,47,32,72,48,46,119,59,10,9,102,108,111,97,116,32,107,49,32,61,32,49,46,48,32,47,32,72,49,46,119,59,10,10,9,47,47,32,83,119,105,116,99,104,32,116,104,101,32,111,114,105,103,105,110,97,108,32,112,111,105,110,116,115,32,116,111,32,118,97,108,117,101,115,32,116,104,97,116,32,105,110,116,101,114,112,111,108,97,116,101,32,108,105,110,101,97,114,108,121,32,105,110,32,50,68,10,9,118,101,99,51,32,81,48,32,61,32,99,115,79,114,105,103,105,110,32,42,32,107,48,59,10,9,118,101,99,51,32,81,49,32,61,32,99,115,69,110,100,80,111,105,110,116,32,42,32,107,49,59,10,10,9,47,47,32,83,99,114,101,101,110,45,115,112,97,99,101,32,101,110,100,112,111,105,110,116,115,10,9,118,101,99,50,32,80,48,32,61,32,72,48,46,120,121,32,42,32,107,48,59,10,9,118,101,99,50,32,80,49,32,61,32,72,49,46,120,121,32,42,32,107,49,59,10,10,9,47,47,32,91,79,112,116,105,111,110,97,108,32,99,108,105,112,112,105,110,103,32,116,111,32,102,114,117,115,116,117,109,32,115,105,100,101,115,32,104,101,114,101,93,10,10,9,47,47,32,73,110,105,116,105,97,108,105,122,101,32,116,111,32,111,102,102,32,115,99,114,101,101,110,10,9,104,105,116,80,105,120,101,108,32,61,32,118,101,99,50,40,45,49,46,48,44,32,45,49,46,48,41,59,10,9,119,104,105,99,104,32,61,32,48,59,32,47,47,32,79,110,108,121,32,111,110,101,32,108,97,121,101,114,10,10,9,47,47,32,73,102,32,116,104,101,32,108,105,110,101,32,105,115,32,100,101,103,101,110,101,114,97,116,101,44,32,109,97,107,101,32,105,116,32,99,111,118,101,114,32,97,116,32,108,101,97,115,116,32,111,110,101,32,112,105,120,101,108,10,9,47,47,32,116,111,32,97,118,111,105,100,32,104,97,110,100,108,105,110,103,32,122,101,114,111,45,112,105,120,101,108,32,101,120,116,101,110,116,32,97,115,32,97,32,115,112,101,99,105,97,108,32,99,97,115,101,32,108,97,116,101,114,10,9,80,49,32,43,61,32,118,101,99,50,40,40,100,105,115,116,97,110,99,101,83,113,117,97,114,101,100,40,80,48,44,32,80,49,41,32,60,32,48,46,48,48,48,49,41,32,63,32,48,46,48,49,32,58,32,48,46,48,41,59,10,10,9,118,101,99,50,32,100,101,108,116,97,32,61,32,80,49,32,45,32,80,48,59,10,10,9,47,47,32,80,101,114,109,117,116,101,32,115,111,32,116,104,97,116,32,116,104,101,32,112,114,105,109,97,114,121,32,105,116,101,114,97,116,105,111,110,32,105,115,32,105,110,32,120,32,116,111,32,114,101,100,117,99,101,10,9,47,47,32,108,97,114,103,101,32,98,114,97,110,99,104,101,115,32,108,97,116,101,114,10,9,98,111,111,108,32,112,101,114,109,117,116,101,32,61,32,102,97,108,115,101,59,10,9,105,102,32,40,97,98,115,40,100,101,108,116,97,46,120,41,32,60,32,97,98,115,40,100,101,108,116,97,46,121,41,41,32,123,10,9,9,47,47,32,77,111,114,101,45,118,101,114,116,105,99,97,108,32,108,105,110,101,46,32,67,114,101,97,116,101,32,97,32,112,101,114,109,117,116,97,116,105,111,110,32,116,104,97,116,32,115,119,97,112,115,32,120,32,97,110,100,32,121,32,105,110,32,116,104,101,32,111,117,116,112,117,116,10,9,9,112,101,114,109,117,116,101,32,61,32,116,114,117,101,59,10,10,9,9,47,47,32,68,105,114,101,99,116,108,121,32,115,119,105,122,122,108,101,32,116,104,101,32,105,110,112,117,116,115,10,9,9,100,101,108,116,97,32,61,32,100,101,108,116,97,46,121,120,59,10,9,9,80,49,32,61,32,80,49,46,121,120,59,10,9,9,80,48,32,61,32,80,48,46,121,120,59,10,9,125,10,10,9,47,47,32,70,114,111,109,32,110,111,119,32,111,110,44,32,34,120,34,32,105,115,32,116,104,101,32,112,114,105,109,97,114,121,32,105,116,101,114,97,116,105,111,110,32,100,105,114,101,99,116,105,111,110,32,97,110,100,32,34,121,34,32,105,115,32,116,104,101,32,115,101,99,111,110,100,97,114,121,32,111,110,101,10,10,9,102,108,111,97,116,32,115,116,101,112,68,105,114,101,99,116,105,111,110,32,61,32,115,105,103,110,40,100,101,108,116,97,46,120,41,59,10,9,102,108,111,97,116,32,105,110,118,100,120,32,61,32,115,116,101,112,68,105,114,101,99,116,105,111,110,32,47,32,100,101,108,116,97,46,120,59,10,9,118,101,99,50,32,100,80,32,61,32,118,101,99,50,40,115,116,101,112,68,105,114,101,99,116,105,111,110,44,32,105,110,118,100,120,32,42,32,100,101,108,116,97,46,121,41,59,10,10,9,47,47,32,84,114,97,99,107,32,116,104,101,32,100,101,114,105,118,97,116,105,118,101,115,32,111,102,32,81,32,97,110,100,32,107,10,9,118,101,99,51,32,100,81,32,61,32,40,81,49,32,45,32,81,48,41,32,42,32,105,110,118,100,120,59,10,9,102,108,111,97,116,32,32,32,100,107,32,61,32,40,107,49,32,45,32,107,48,41,32,42,32,105,110,118,100,120,59,10,10,9,47,47,32,83,99,97,108,101,32,100,101,114,105,118,97,116,105,118,101,115,32,98,121,32,116,104,101,32,100,101,115,105,114,101,100,32,112,105,120,101,108,32,115,116,114,105,100,101,10,9,100,80,32,42,61,32,115,116,114,105,100,101,59,32,100,81,32,42,61,32,115,116,114,105,100,101,59,32,100,107,32,42,61,32,115,116,114,105,100,101,59,10,10,9,47,47,32,79,102,102,115,101,116,32,116,104,101,32,115,116,97,114,116,105,110,103,32,118,97,108,117,101,115,32,98,121,32,116,104,101,32,106,105,116,116,101,114,32,102,114,97,99,116,105,111,110,10,9,80,48,32,43,61,32,100,80,32,42,32,106,105,116,116,101,114,70,114,97,99,116,105,111,110,59,32,81,48,32,43,61,32,100,81,32,42,32,106,105,116,116,101,114,70,114,97,99,116,105,111,110,59,32,107,48,32,43,61,32,100,107,32,42,32,106,105,116,116,101,114,70,114,97,99,116,105,111,110,59,10,10,9,47,47,32,83,108,105,100,101,32,80,32,102,114,111,109,32,80,48,32,116,111,32,80,49,44,32,40,110,111,119,45,104,111,109,111,103,101,110,101,111,117,115,41,32,81,32,102,114,111,109,32,81,48,32,116,111,32,81,49,44,32,97,110,100,32,107,32,102,114,111,109,32,107,48,32,116,111,32,107,49,10,9,118,101,99,51,32,81,32,61,32,81,48,59,10,9,102,108,111,97,116,32,32,107,32,61,32,107,48,59,10,10,9,47,47,32,87,101,32,116,114,97,99,107,32,116,104,101,32,114,97,121,32,100,101,112,116,104,32,97,116,32,43,47,45,32,49,47,50,32,112,105,120,101,108,32,116,111,32,116,114,101,97,116,32,112,105,120,101,108,115,32,97,115,32,99,108,105,112,45,115,112,97,99,101,32,115,111,108,105,100,10,9,47,47,32,118,111,120,101,108,115,46,32,66,101,99,97,117,115,101,32,116,104,101,32,100,101,112,116,104,32,97,116,32,45,49,47,50,32,102,111,114,32,97,32,103,105,118,101,110,32,112,105,120,101,108,32,119,105,108,108,32,98,101,32,116,104,101,32,115,97,109,101,32,97,115,32,97,116,10,9,47,47,32,43,49,47,50,32,102,111,114,32,116,104,101,32,112,114,101,118,105,111,117,115,32,105,116,101,114,97,116,105,111,110,44,32,119,101,32,97,99,116,117,97,108,108,121,32,111,110,108,121,32,104,97,118,101,32,116,111,32,99,111,109,112,117,116,101,32,111,110,101,32,118,97,108,117,101,10,9,47,47,32,112,101,114,32,105,116,101,114,97,116,105,111,110,46,10,9,102,108,111,97,116,32,112,114,101,118,90,77,97,120,69,115,116,105,109,97,116,101,32,61,32,99,115,79,114,105,103,105,110,46,122,59,10,9,102,108,111,97,116,32,115,116,101,112,67,111,117,110,116,32,61,32,48,46,48,59,10,9,102,108,111,97,116,32,114,97,121,90,77,97,120,32,61,32,112,114,101,118,90,77,97,120,69,115,116,105,109,97,116,101,44,32,114,97,121,90,77,105,110,32,61,32,112,114,101,118,90,77,97,120,69,115,116,105,109,97,116,101,59,10,9,102,108,111,97,116,32,115,99,101,110,101,90,77,97,120,32,61,32,114,97,121,90,77,97,120,32,43,32,49,101,52,59,10,10,9,47,47,32,80,49,46,120,32,105,115,32,110,101,118,101,114,32,109,111,100,105,102,105,101,100,32,97,102,116,101,114,32,116,104,105,115,32,112,111,105,110,116,44,32,115,111,32,112,114,101,45,115,99,97,108,101,32,105,116,32,98,121,10,9,47,47,32,116,104,101,32,115,116,101,112,32,100,105,114,101,99,116,105,111,110,32,102,111,114,32,97,32,115,105,103,110,101,100,32,99,111,109,112,97,114,105,115,111,110,10,9,102,108,111,97,116,32,101,110,100,32,61,32,80,49,46,120,32,42,32,115,116,101,112,68,105,114,101,99,116,105,111,110,59,10,10,9,47,47,32,87,101,32,111,110,108,121,32,97,100,118,97,110,99,101,32,116,104,101,32,122,32,102,105,101,108,100,32,111,102,32,81,32,105,110,32,116,104,101,32,105,110,110,101,114,32,108,111,111,112,44,32,115,105,110,99,101,10,9,47,47,32,81,46,120,121,32,105,115,32,110,101,118,101,114,32,117,115,101,100,32,117,110,116,105,108,32,97,102,116,101,114,32,116,104,101,32,108,111,111,112,32,116,101,114,109,105,110,97,116,101,115,46,10,10,10,9,102,111,114,32,40,118,101,99,50,32,80,32,61,32,80,48,59,10,9,32,32,32,32,32,40,40,80,46,120,32,42,32,115,116,101,112,68,105,114,101,99,116,105,111,110,41,32,60,61,32,101,110,100,41,32,38,38,10,9,32,32,32,32,32,40,115,116,101,112,67,111,117,110,116,32,60,32,109,97,120,83,116,101,112,115,41,32,38,38,10,9,32,32,32,32,32,40,40,114,97,121,90,77,97,120,32,60,32,115,99,101,110,101,90,77,97,120,32,45,32,99,115,90,84,104,105,99,107,110,101,115,115,41,32,124,124,10,9,32,32,32,32,32,32,40,114,97,121,90,77,105,110,32,62,32,115,99,101,110,101,90,77,97,120,41,41,32,38,38,10,9,32,32,32,32,32,40,115,99,101,110,101,90,77,97,120,32,33,61,32,48,46,48,41,59,10,9,32,32,32,32,32,80,32,43,61,32,100,80,44,32,81,46,122,32,43,61,32,100,81,46,122,44,32,107,32,43,61,32,100,107,44,32,115,116,101,112,67,111,117,110,116,32,43,61,32,49,46,48,41,32,123,10,10,9,9,104,105,116,80,105,120,101,108,32,61,32,112,101,114,109,117,116,101,32,63,32,80,46,121,120,32,58,32,80,59,10,10,9,9,47,47,32,84,104,101,32,100,101,112,116,104,32,114,97,110,103,101,32,116,104,97,116,32,116,104,101,32,114,97,121,32,99,111,118,101,114,115,32,119,105,116,104,105,110,32,116,104,105,115,32,108,111,111,112,10,9,9,47,47,32,105,116,101,114,97,116,105,111,110,46,32,32,65,115,115,117,109,101,32,116,104,97,116,32,116,104,101,32,114,97,121,32,105,115,32,109,111,118,105,110,103,32,105,110,32,105,110,99,114,101,97,115,105,110,103,32,122,10,9,9,47,47,32,97,110,100,32,115,119,97,112,32,105,102,32,98,97,99,107,119,97,114,100,115,46,32,32,66,101,99,97,117,115,101,32,111,110,101,32,101,110,100,32,111,102,32,116,104,101,32,105,110,116,101,114,118,97,108,32,105,115,10,9,9,47,47,32,115,104,97,114,101,100,32,98,101,116,119,101,101,110,32,97,100,106,97,99,101,110,116,32,105,116,101,114,97,116,105,111,110,115,44,32,119,101,32,116,114,97,99,107,32,116,104,101,32,112,114,101,118,105,111,117,115,10,9,9,47,47,32,118,97,108,117,101,32,97,110,100,32,116,104,101,110,32,115,119,97,112,32,97,115,32,110,101,101,100,101,100,32,116,111,32,101,110,115,117,114,101,32,99,111,114,114,101,99,116,32,111,114,100,101,114,105,110,103,10,9,9,114,97,121,90,77,105,110,32,61,32,112,114,101,118,90,77,97,120,69,115,116,105,109,97,116,101,59,10,10,9,9,47,47,32,67,111,109,112,117,116,101,32,116,104,101,32,118,97,108,117,101,32,97,116,32,49,47,50,32,112,105,120,101,108,32,105,110,116,111,32,116,104,101,32,102,117,116,117,114,101,10,9,9,114,97,121,90,77,97,120,32,61,32,40,100,81,46,122,32,42,32,48,46,53,32,43,32,81,46,122,41,32,47,32,40,100,107,32,42,32,48,46,53,32,43,32,107,41,59,10,9,9,112,114,101,118,90,77,97,120,69,115,116,105,109,97,116,101,32,61,32,114,97,121,90,77,97,120,59,10,9,9,105,102,32,40,114,97,121,90,77,105,110,32,62,32,114,97,121,90,77,97,120,41,32,123,10,9,9,9,102,108,111,97,116,32,97,117,120,32,61,32,114,97,121,90,77,105,110,59,10,9,9,9,114,97,121,90,77,105,110,61,114,97,121,90,77,97,120,59,10,9,9,9,114,97,121,90,77,97,120,61,97,117,120,59,10,10,9,9,125,10,10,10,9,9,47,47,32,67,97,109,101,114,97,45,115,112,97,99,101,32,122,32,111,102,32,116,104,101,32,98,97,99,107,103,114,111,117,110,100,10,9,9,115,99,101,110,101,90,77,97,120,32,61,32,116,101,120,101,108,70,101,116,99,104,40,99,115,90,66,117,102,102,101,114,44,32,105,118,101,99,50,40,104,105,116,80,105,120,101,108,41,44,32,48,41,46,114,32,42,32,50,46,48,32,45,32,49,46,48,59,10,10,9,9,47,47,32,84,104,105,115,32,99,111,109,112,105,108,101,115,32,97,119,97,121,32,119,104,101,110,32,99,115,90,66,117,102,102,101,114,73,115,72,121,112,101,114,98,111,108,105,99,32,61,32,102,97,108,115,101,10,9,9,47,42,105,102,32,40,99,115,90,66,117,102,102,101,114,73,115,72,121,112,101,114,98,111,108,105,99,41,32,123,10,9,9,9,115,99,101,110,101,90,77,97,120,32,61,32,114,101,99,111,110,115,116,114,117,99,116,67,83,90,40,115,99,101,110,101,90,77,97,120,44,32,99,108,105,112,73,110,102,111,41,59,10,9,9,125,42,47,10,9,9,115,99,101,110,101,90,77,97,120,32,61,32,50,46,48,32,42,32,99,97,109,101,114,97,95,122,95,110,101,97,114,32,42,32,99,97,109,101,114,97,95,122,95,102,97,114,32,47,32,40,99,97,109,101,114,97,95,122,95,102,97,114,32,43,32,99,97,109,101,114,97,95,122,95,110,101,97,114,32,45,32,115,99,101,110,101,90,77,97,120,32,42,32,40,99,97,109,101,114,97,95,122,95,102,97,114,32,45,32,99,97,109,101,114,97,95,122,95,110,101,97,114,41,41,59,10,9,9,115,99,101,110,101,90,77,97,120,32,61,32,45,115,99,101,110,101,90,77,97,120,59,10,10,10,10,9,125,32,47,47,32,112,105,120,101,108,32,111,110,32,114,97,121,10,10,10,10,9,81,46,120,121,32,43,61,32,100,81,46,120,121,32,42,32,115,116,101,112,67,111,117,110,116,59,10,9,99,115,72,105,116,80,111,105,110,116,32,61,32,81,32,42,32,40,49,46,48,32,47,32,107,41,59,10,10,9,47,47,32,77,97,116,99,104,101,115,32,116,104,101,32,110,101,119,32,108,111,111,112,32,99,111,110,100,105,116,105,111,110,58,10,9,114,101,116,117,114,110,32,40,114,97,121,90,77,97,120,32,62,61,32,115,99,101,110,101,90,77,97,120,32,45,32,99,115,90,84,104,105,99,107,110,101,115,115,41,32,38,38,32,40,114,97,121,90,77,105,110,32,60,61,32,115,99,101,110,101,90,77,97,120,41,59,10,125,10,10,118,111,105,100,32,115,119,97,112,102,40,105,110,111,117,116,32,102,108,111,97,116,32,97,44,105,110,111,117,116,32,102,108,111,97,116,32,98,41,32,123,10,9,102,108,111,97,116,32,97,117,120,61,97,59,10,9,97,61,98,59,10,9,98,61,97,117,120,59,10,125,10,102,108,111,97,116,32,114,97,110,100,40,118,101,99,50,32,99,111,41,123,10,32,32,32,32,114,101,116,117,114,110,32,102,114,97,99,116,40,115,105,110,40,100,111,116,40,99,111,46,120,121,32,44,118,101,99,50,40,49,50,46,57,56,57,56,44,55,56,46,50,51,51,41,41,41,32,42,32,52,51,55,53,56,46,53,52,53,51,41,59,10,125,10,10,102,108,111,97,116,32,115,112,101,99,117,108,97,114,80,111,119,101,114,84,111,67,111,110,101,65,110,103,108,101,40,102,108,111,97,116,32,115,112,101,99,117,108,97,114,80,111,119,101,114,41,32,123,10,9,102,108,111,97,116,32,101,120,112,111,110,101,110,116,32,61,32,49,46,48,102,32,47,32,40,115,112,101,99,117,108,97,114,80,111,119,101,114,32,43,32,49,46,48,102,41,59,10,9,114,101,116,117,114,110,32,97,99,111,115,40,112,111,119,40,48,46,50,52,52,102,44,32,101,120,112,111,110,101,110,116,41,41,59,10,125,10,10,102,108,111,97,116,32,105,115,111,115,99,101,108,101,115,84,114,105,97,110,103,108,101,79,112,112,111,115,105,116,101,40,102,108,111,97,116,32,97,100,106,97,99,101,110,116,76,101,110,103,116,104,44,32,102,108,111,97,116,32,99,111,110,101,84,104,101,116,97,41,10,123,10,9,47,47,32,115,105,109,112,108,101,32,116,114,105,103,32,97,110,100,32,97,108,103,101,98,114,97,32,45,32,115,111,104,44,32,99,97,104,44,32,116,111,97,32,45,32,116,97,110,40,116,104,101,116,97,41,32,61,32,111,112,112,47,97,100,106,44,32,111,112,112,32,61,32,116,97,110,40,116,104,101,116,97,41,32,42,32,97,100,106,44,32,116,104,101,110,32,109,117,108,116,105,112,108,121,32,42,32,50,46,48,102,32,102,111,114,32,105,115,111,115,99,101,108,101,115,32,116,114,105,97,110,103,108,101,32,98,97,115,101,10,9,114,101,116,117,114,110,32,50,46,48,102,32,42,32,116,97,110,40,99,111,110,101,84,104,101,116,97,41,32,42,32,97,100,106,97,99,101,110,116,76,101,110,103,116,104,59,10,125,10,10,102,108,111,97,116,32,105,115,111,115,99,101,108,101,115,84,114,105,97,110,103,108,101,73,110,82,97,100,105,117,115,40,102,108,111,97,116,32,97,44,32,102,108,111,97,116,32,104,41,10,123,10,9,102,108,111,97,116,32,97,50,32,61,32,97,32,42,32,97,59,10,9,102,108,111,97,116,32,102,104,50,32,61,32,52,46,48,102,32,42,32,104,32,42,32,104,59,10,9,114,101,116,117,114,110,32,40,97,32,42,32,40,115,113,114,116,40,97,50,32,43,32,102,104,50,41,32,45,32,97,41,41,32,47,32,40,52,46,48,102,32,42,32,104,41,59,10,125,10,10,102,108,111,97,116,32,105,115,111,115,99,101,108,101,115,84,114,105,97,110,103,108,101,78,101,120,116,65,100,106,97,99,101,110,116,40,102,108,111,97,116,32,97,100,106,97,99,101,110,116,76,101,110,103,116,104,44,32,102,108,111,97,116,32,105,110,99,105,114,99,108,101,82,97,100,105,117,115,41,10,123,10,9,47,47,32,115,117,98,116,114,97,99,116,32,116,104,101,32,100,105,97,109,101,116,101,114,32,111,102,32,116,104,101,32,105,110,99,105,114,99,108,101,32,116,111,32,103,101,116,32,116,104,101,32,97,100,106,97,99,101,110,116,32,115,105,100,101,32,111,102,32,116,104,101,32,110,101,120,116,32,108,101,118,101,108,32,111,110,32,116,104,101,32,99,111,110,101,10,9,114,101,116,117,114,110,32,97,100,106,97,99,101,110,116,76,101,110,103,116,104,32,45,32,40,105,110,99,105,114,99,108,101,82,97,100,105,117,115,32,42,32,50,46,48,102,41,59,10,125,10,10,118,111,105,100,32,109,97,105,110,40,41,32,123,10,10,10,9,102,108,111,97,116,32,110,117,109,95,115,116,101,112,115,61,54,52,59,10,9,102,108,111,97,116,32,105,110,105,116,105,97,108,95,98,105,97,115,61,48,46,49,59,10,9,102,108,111,97,116,32,104,105,116,95,116,111,108,101,114,97,110,99,101,61,48,46,49,59,10,10,9,47,47,47,47,10,10,9,118,101,99,52,32,100,105,102,102,117,115,101,32,61,32,116,101,120,116,117,114,101,40,32,115,111,117,114,99,101,95,100,105,102,102,117,115,101,44,32,32,117,118,95,105,110,116,101,114,112,32,41,59,10,9,118,101,99,52,32,110,111,114,109,97,108,95,114,111,117,103,104,110,101,115,115,32,61,32,116,101,120,116,117,114,101,40,32,115,111,117,114,99,101,95,110,111,114,109,97,108,95,114,111,117,103,104,110,101,115,115,44,32,117,118,95,105,110,116,101,114,112,41,59,10,10,9,118,101,99,51,32,110,111,114,109,97,108,59,10,10,9,110,111,114,109,97,108,32,61,32,110,111,114,109,97,108,95,114,111,117,103,104,110,101,115,115,46,120,121,122,42,50,46,48,45,49,46,48,59,10,10,9,105,102,32,40,102,97,108,115,101,41,32,123,10,9,32,32,32,32,102,108,111,97,116,32,115,99,97,108,101,32,61,32,49,46,55,55,55,55,59,10,9,32,32,32,32,118,101,99,51,32,110,110,32,61,10,9,9,110,111,114,109,97,108,95,114,111,117,103,104,110,101,115,115,46,120,121,122,42,118,101,99,51,40,50,46,48,42,115,99,97,108,101,44,50,46,48,42,115,99,97,108,101,44,48,46,48,41,32,43,10,9,9,118,101,99,51,40,45,115,99,97,108,101,44,45,115,99,97,108,101,44,49,46,48,41,59,10,9,32,32,32,32,102,108,111,97,116,32,103,32,61,32,50,46,48,32,47,32,100,111,116,40,110,110,46,120,121,122,44,110,110,46,120,121,122,41,59,10,9,32,32,32,32,118,101,99,51,32,110,59,10,9,32,32,32,32,110,46,120,121,32,61,32,103,42,110,110,46,120,121,59,10,9,32,32,32,32,110,46,122,32,61,32,103,45,49,46,48,59,10,9,32,32,32,110,111,114,109,97,108,61,110,59,10,9,125,10,10,9,118,101,99,51,32,116,97,110,103,101,110,116,59,10,9,118,101,99,51,32,98,105,110,111,114,109,97,108,59,10,9,102,105,110,100,95,97,114,98,105,116,114,97,114,121,95,116,97,110,103,101,110,116,40,110,111,114,109,97,108,44,32,116,97,110,103,101,110,116,44,32,98,105,110,111,114,109,97,108,41,59,10,10,9,102,108,111,97,116,32,114,111,117,103,104,110,101,115,115,32,61,32,110,111,114,109,97,108,95,114,111,117,103,104,110,101,115,115,46,119,59,10,10,9,102,108,111,97,116,32,100,101,112,116,104,95,116,101,120,32,61,32,116,101,120,116,117,114,101,40,115,111,117,114,99,101,95,100,101,112,116,104,44,117,118,95,105,110,116,101,114,112,41,46,114,59,10,10,9,118,101,99,52,32,119,111,114,108,100,95,112,111,115,32,61,32,105,110,118,101,114,115,101,95,112,114,111,106,101,99,116,105,111,110,32,42,32,118,101,99,52,40,32,117,118,95,105,110,116,101,114,112,42,50,46,48,45,49,46,48,44,32,100,101,112,116,104,95,116,101,120,42,50,46,48,45,49,46,48,44,32,49,46,48,32,41,59,10,9,118,101,99,51,32,118,101,114,116,101,120,32,61,32,119,111,114,108,100,95,112,111,115,46,120,121,122,47,119,111,114,108,100,95,112,111,115,46,119,59,10,10,9,118,101,99,51,32,118,105,101,119,95,100,105,114,32,61,32,110,111,114,109,97,108,105,122,101,40,118,101,114,116,101,120,41,59,10,9,118,101,99,51,32,114,97,121,95,100,105,114,32,61,32,110,111,114,109,97,108,105,122,101,40,114,101,102,108,101,99,116,40,118,105,101,119,95,100,105,114,44,32,110,111,114,109,97,108,41,41,59,10,10,9,47,47,114,97,121,95,100,105,114,32,61,32,110,111,114,109,97,108,105,122,101,40,118,105,101,119,95,100,105,114,32,45,32,110,111,114,109,97,108,32,42,32,100,111,116,40,110,111,114,109,97,108,44,118,105,101,119,95,100,105,114,41,32,42,32,50,46,48,41,59,10,10,9,47,47,114,97,121,95,100,105,114,32,61,32,110,111,114,109,97,108,105,122,101,40,118,101,99,51,40,49,44,49,44,45,49,41,41,59,10,10,10,9,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,10,10,10,9,47,47,109,97,107,101,32,114,97,121,32,108,101,110,103,116,104,32,97,110,100,32,99,108,105,112,32,105,116,32,97,103,97,105,110,115,116,32,116,104,101,32,110,101,97,114,32,112,108,97,110,101,32,40,100,111,110,39,116,32,119,97,110,116,32,116,111,32,116,114,97,99,101,32,98,101,121,111,110,100,32,118,105,115,105,98,108,101,41,10,9,102,108,111,97,116,32,114,97,121,95,108,101,110,32,61,32,40,118,101,114,116,101,120,46,122,32,43,32,114,97,121,95,100,105,114,46,122,32,42,32,99,97,109,101,114,97,95,122,95,102,97,114,41,32,62,32,45,99,97,109,101,114,97,95,122,95,110,101,97,114,32,63,32,40,45,99,97,109,101,114,97,95,122,95,110,101,97,114,32,45,32,118,101,114,116,101,120,46,122,41,32,47,32,114,97,121,95,100,105,114,46,122,32,58,32,99,97,109,101,114,97,95,122,95,102,97,114,59,10,9,118,101,99,51,32,114,97,121,95,101,110,100,32,61,32,118,101,114,116,101,120,32,43,32,114,97,121,95,100,105,114,42,114,97,121,95,108,101,110,59,10,10,9,102,108,111,97,116,32,119,95,98,101,103,105,110,59,10,9,118,101,99,50,32,118,112,95,108,105,110,101,95,98,101,103,105,110,32,61,32,118,105,101,119,95,116,111,95,115,99,114,101,101,110,40,118,101,114,116,101,120,44,119,95,98,101,103,105,110,41,59,10,9,102,108,111,97,116,32,119,95,101,110,100,59,10,9,118,101,99,50,32,118,112,95,108,105,110,101,95,101,110,100,32,61,32,118,105,101,119,95,116,111,95,115,99,114,101,101,110,40,32,114,97,121,95,101,110,100,44,32,119,95,101,110,100,41,59,10,9,118,101,99,50,32,118,112,95,108,105,110,101,95,100,105,114,32,61,32,118,112,95,108,105,110,101,95,101,110,100,45,118,112,95,108,105,110,101,95,98,101,103,105,110,59,10,10,10,9,119,95,98,101,103,105,110,32,61,32,49,46,48,47,119,95,98,101,103,105,110,59,10,9,119,95,101,110,100,32,61,32,49,46,48,47,119,95,101,110,100,59,10,10,10,9,102,108,111,97,116,32,122,95,98,101,103,105,110,32,61,32,118,101,114,116,101,120,46,122,42,119,95,98,101,103,105,110,59,10,9,102,108,111,97,116,32,122,95,101,110,100,32,61,32,114,97,121,95,101,110,100,46,122,42,119,95,101,110,100,59,10,10,9,118,101,99,50,32,108,105,110,101,95,98,101,103,105,110,32,61,32,118,112,95,108,105,110,101,95,98,101,103,105,110,47,112,105,120,101,108,95,115,105,122,101,59,10,9,118,101,99,50,32,108,105,110,101,95,100,105,114,32,61,32,118,112,95,108,105,110,101,95,100,105,114,47,112,105,120,101,108,95,115,105,122,101,59,10,9,102,108,111,97,116,32,122,95,100,105,114,32,61,32,122,95,101,110,100,32,45,32,122,95,98,101,103,105,110,59,10,9,102,108,111,97,116,32,119,95,100,105,114,32,61,32,119,95,101,110,100,32,45,32,119,95,98,101,103,105,110,59,10,10,10,9,47,47,32,99,108,105,112,32,116,104,101,32,108,105,110,101,32,116,111,32,116,104,101,32,118,105,101,119,112,111,114,116,32,101,100,103,101,115,10,10,9,102,108,111,97,116,32,115,99,97,108,101,95,109,97,120,95,120,32,61,32,109,105,110,40,49,44,32,48,46,57,57,32,42,32,40,49,46,48,32,45,32,118,112,95,108,105,110,101,95,98,101,103,105,110,46,120,41,32,47,32,109,97,120,40,49,101,45,53,44,32,118,112,95,108,105,110,101,95,100,105,114,46,120,41,41,59,10,9,102,108,111,97,116,32,115,99,97,108,101,95,109,97,120,95,121,32,61,32,109,105,110,40,49,44,32,48,46,57,57,32,42,32,40,49,46,48,32,45,32,118,112,95,108,105,110,101,95,98,101,103,105,110,46,121,41,32,47,32,109,97,120,40,49,101,45,53,44,32,118,112,95,108,105,110,101,95,100,105,114,46,121,41,41,59,10,9,102,108,111,97,116,32,115,99,97,108,101,95,109,105,110,95,120,32,61,32,109,105,110,40,49,44,32,48,46,57,57,32,42,32,118,112,95,108,105,110,101,95,98,101,103,105,110,46,120,32,47,32,109,97,120,40,49,101,45,53,44,32,45,118,112,95,108,105,110,101,95,100,105,114,46,120,41,41,59,10,9,102,108,111,97,116,32,115,99,97,108,101,95,109,105,110,95,121,32,61,32,109,105,110,40,49,44,32,48,46,57,57,32,42,32,118,112,95,108,105,110,101,95,98,101,103,105,110,46,121,32,47,32,109,97,120,40,49,101,45,53,44,32,45,118,112,95,108,105,110,101,95,100,105,114,46,121,41,41,59,10,9,102,108,111,97,116,32,108,105,110,101,95,99,108,105,112,32,61,32,109,105,110,40,115,99,97,108,101,95,109,97,120,95,120,44,32,115,99,97,108,101,95,109,97,120,95,121,41,32,42,32,109,105,110,40,115,99,97,108,101,95,109,105,110,95,120,44,32,115,99,97,108,101,95,109,105,110,95,121,41,59,10,9,108,105,110,101,95,100,105,114,32,42,61,32,108,105,110,101,95,99,108,105,112,59,10,9,122,95,100,105,114,32,42,61,32,108,105,110,101,95,99,108,105,112,59,10,9,119,95,100,105,114,32,42,61,108,105,110,101,95,99,108,105,112,59,10,10,10,9,118,101,99,50,32,108,105,110,101,95,97,100,118,97,110,99,101,32,61,32,110,111,114,109,97,108,105,122,101,40,108,105,110,101,95,100,105,114,41,59,32,47,47,100,111,119,110,32,116,111,32,112,105,120,101,108,10,9,102,108,111,97,116,32,115,116,101,112,95,115,105,122,101,32,61,32,108,101,110,103,116,104,40,108,105,110,101,95,97,100,118,97,110,99,101,41,47,108,101,110,103,116,104,40,108,105,110,101,95,100,105,114,41,59,10,9,102,108,111,97,116,32,122,95,97,100,118,97,110,99,101,32,61,32,122,95,100,105,114,42,115,116,101,112,95,115,105,122,101,59,32,47,47,32,97,100,97,112,116,32,122,32,97,100,118,97,110,99,101,32,116,111,32,108,105,110,101,32,97,100,118,97,110,99,101,10,9,102,108,111,97,116,32,119,95,97,100,118,97,110,99,101,32,61,32,119,95,100,105,114,42,115,116,101,112,95,115,105,122,101,59,32,47,47,32,97,100,97,112,116,32,119,32,97,100,118,97,110,99,101,32,116,111,32,108,105,110,101,32,97,100,118,97,110,99,101,10,10,9,102,108,111,97,116,32,97,100,118,97,110,99,101,95,97,110,103,108,101,95,97,100,106,32,61,32,49,46,48,47,109,97,120,40,97,98,115,40,108,105,110,101,95,97,100,118,97,110,99,101,46,120,41,44,97,98,115,40,108,105,110,101,95,97,100,118,97,110,99,101,46,121,41,41,59,32,47,47,109,97,107,101,32,105,116,32,103,111,32,102,97,115,116,101,114,32,116,104,101,32,99,108,111,115,101,114,32,116,111,32,52,53,100,10,9,108,105,110,101,95,97,100,118,97,110,99,101,42,61,97,100,118,97,110,99,101,95,97,110,103,108,101,95,97,100,106,59,32,47,47,32,97,100,97,112,116,32,122,32,97,100,118,97,110,99,101,32,116,111,32,108,105,110,101,32,97,100,118,97,110,99,101,10,9,122,95,97,100,118,97,110,99,101,42,61,97,100,118,97,110,99,101,95,97,110,103,108,101,95,97,100,106,59,10,9,119,95,97,100,118,97,110,99,101,42,61,97,100,118,97,110,99,101,95,97,110,103,108,101,95,97,100,106,59,10,10,9,118,101,99,50,32,112,111,115,32,61,32,108,105,110,101,95,98,101,103,105,110,59,10,9,102,108,111,97,116,32,122,32,61,32,122,95,98,101,103,105,110,59,10,9,102,108,111,97,116,32,119,32,61,32,119,95,98,101,103,105,110,59,10,9,102,108,111,97,116,32,122,95,102,114,111,109,61,122,47,119,59,10,9,102,108,111,97,116,32,122,95,116,111,61,122,95,102,114,111,109,59,10,9,102,108,111,97,116,32,100,101,112,116,104,59,10,9,118,101,99,50,32,112,114,101,118,95,112,111,115,61,112,111,115,59,10,10,9,98,111,111,108,32,102,111,117,110,100,61,102,97,108,115,101,59,10,10,9,102,108,111,97,116,32,97,99,99,101,108,61,49,46,48,52,59,47,47,43,114,97,110,100,40,103,108,95,70,114,97,103,67,111,111,114,100,46,120,121,41,42,48,46,48,48,48,49,59,10,9,102,108,111,97,116,32,115,116,101,112,115,95,116,97,107,101,110,61,48,59,10,10,9,102,111,114,40,102,108,111,97,116,32,105,61,48,59,105,60,110,117,109,95,115,116,101,112,115,59,105,43,43,41,32,123,10,10,9,9,112,111,115,43,61,108,105,110,101,95,97,100,118,97,110,99,101,59,10,9,9,122,43,61,122,95,97,100,118,97,110,99,101,59,10,9,9,119,43,61,119,95,97,100,118,97,110,99,101,59,10,10,9,9,100,101,112,116,104,32,61,32,116,101,120,116,117,114,101,40,115,111,117,114,99,101,95,100,101,112,116,104,44,32,112,111,115,42,112,105,120,101,108,95,115,105,122,101,41,46,114,32,42,32,50,46,48,32,45,32,49,46,48,59,10,9,9,100,101,112,116,104,32,61,32,50,46,48,32,42,32,99,97,109,101,114,97,95,122,95,110,101,97,114,32,42,32,99,97,109,101,114,97,95,122,95,102,97,114,32,47,32,40,99,97,109,101,114,97,95,122,95,102,97,114,32,43,32,99,97,109,101,114,97,95,122,95,110,101,97,114,32,45,32,100,101,112,116,104,32,42,32,40,99,97,109,101,114,97,95,122,95,102,97,114,32,45,32,99,97,109,101,114,97,95,122,95,110,101,97,114,41,41,59,10,9,9,100,101,112,116,104,61,45,100,101,112,116,104,59,10,10,9,9,122,95,102,114,111,109,32,61,32,122,95,116,111,59,10,9,9,122,95,116,111,32,61,32,122,47,119,59,10,10,9,9,105,102,32,40,100,101,112,116,104,62,122,95,116,111,41,32,123,10,10,9,9,9,105,102,32,40,100,101,112,116,104,60,61,109,97,120,40,122,95,116,111,44,122,95,102,114,111,109,41,43,48,46,56,41,32,123,10,9,9,9,9,102,111,117,110,100,61,116,114,117,101,59,10,9,9,9,125,10,9,9,9,98,114,101,97,107,59,10,9,9,125,10,10,9,9,115,116,101,112,115,95,116,97,107,101,110,43,61,49,46,48,59,10,9,9,112,114,101,118,95,112,111,115,61,112,111,115,59,10,9,9,122,95,97,100,118,97,110,99,101,42,61,97,99,99,101,108,59,10,9,9,119,95,97,100,118,97,110,99,101,42,61,97,99,99,101,108,59,10,9,9,108,105,110,101,95,97,100,118,97,110,99,101,42,61,97,99,99,101,108,59,10,9,125,10,10,9,105,102,32,40,102,111,117,110,100,41,32,123,10,10,10,9,9,118,101,99,50,32,102,105,110,97,108,95,112,111,115,59,10,9,9,102,108,111,97,116,32,103,114,97,100,59,10,35,100,101,102,105,110,101,32,66,76,69,78,68,95,65,67,67,69,76,10,35,105,102,100,101,102,32,66,76,69,78,68,95,65,67,67,69,76,10,10,9,9,118,101,99,50,32,98,108,101,110,100,95,100,105,114,32,61,32,112,111,115,32,45,32,112,114,101,118,95,112,111,115,59,10,9,9,102,108,111,97,116,32,115,116,101,112,115,32,61,32,109,105,110,40,56,46,48,44,108,101,110,103,116,104,40,98,108,101,110,100,95,100,105,114,41,41,59,10,9,9,105,102,32,40,115,116,101,112,115,62,50,46,48,41,32,123,10,9,9,9,118,101,99,50,32,98,108,101,110,100,95,115,116,101,112,32,61,32,98,108,101,110,100,95,100,105,114,47,115,116,101,112,115,59,10,9,9,9,102,108,111,97,116,32,98,108,101,110,100,95,122,32,61,32,40,122,95,116,111,45,122,95,102,114,111,109,41,47,115,116,101,112,115,59,10,9,9,9,118,101,99,50,32,110,101,119,95,112,111,115,59,10,9,9,9,102,108,111,97,116,32,115,117,98,103,114,97,100,61,48,46,48,59,10,9,9,9,102,111,114,40,102,108,111,97,116,32,105,61,48,46,48,59,105,60,115,116,101,112,115,59,105,43,43,41,32,123,10,10,9,9,9,9,110,101,119,95,112,111,115,32,61,32,40,112,114,101,118,95,112,111,115,43,98,108,101,110,100,95,115,116,101,112,42,105,41,59,10,9,9,9,9,102,108,111,97,116,32,122,32,61,32,122,95,102,114,111,109,43,98,108,101,110,100,95,122,42,105,59,10,10,9,9,9,9,100,101,112,116,104,32,61,32,116,101,120,116,117,114,101,40,115,111,117,114,99,101,95,100,101,112,116,104,44,32,110,101,119,95,112,111,115,42,112,105,120,101,108,95,115,105,122,101,41,46,114,32,42,32,50,46,48,32,45,32,49,46,48,59,10,9,9,9,9,100,101,112,116,104,32,61,32,50,46,48,32,42,32,99,97,109,101,114,97,95,122,95,110,101,97,114,32,42,32,99,97,109,101,114,97,95,122,95,102,97,114,32,47,32,40,99,97,109,101,114,97,95,122,95,102,97,114,32,43,32,99,97,109,101,114,97,95,122,95,110,101,97,114,32,45,32,100,101,112,116,104,32,42,32,40,99,97,109,101,114,97,95,122,95,102,97,114,32,45,32,99,97,109,101,114,97,95,122,95,110,101,97,114,41,41,59,10,9,9,9,9,100,101,112,116,104,61,45,100,101,112,116,104,59,10,10,9,9,9,9,115,117,98,103,114,97,100,61,105,47,115,116,101,112,115,59,10,9,9,9,9,105,102,32,40,100,101,112,116,104,62,122,41,10,9,9,9,9,9,98,114,101,97,107,59,10,9,9,9,125,10,10,9,9,9,102,105,110,97,108,95,112,111,115,32,61,32,110,101,119,95,112,111,115,59,10,9,9,9,103,114,97,100,61,40,115,116,101,112,115,95,116,97,107,101,110,43,115,117,98,103,114,97,100,41,47,110,117,109,95,115,116,101,112,115,59,10,9,9,9,47,47,102,114,97,103,95,99,111,108,111,114,32,61,32,118,101,99,52,40,118,101,99,51,40,103,114,97,100,41,44,49,46,48,41,59,10,9,9,125,32,101,108,115,101,32,123,10,35,101,110,100,105,102,10,9,9,9,103,114,97,100,61,115,116,101,112,115,95,116,97,107,101,110,47,110,117,109,95,115,116,101,112,115,59,10,9,9,9,102,105,110,97,108,95,112,111,115,61,112,111,115,59,10,35,105,102,100,101,102,32,66,76,69,78,68,95,65,67,67,69,76,10,9,9,125,10,10,35,101,110,100,105,102,10,10,35,100,101,102,105,110,101,32,82,69,70,76,69,67,84,95,82,79,85,71,72,78,69,83,83,10,35,105,102,100,101,102,32,82,69,70,76,69,67,84,95,82,79,85,71,72,78,69,83,83,10,10,10,9,9,118,101,99,52,32,102,105,110,97,108,95,99,111,108,111,114,59,10,10,9,9,105,102,32,40,114,111,117,103,104,110,101,115,115,32,62,32,48,46,48,48,49,41,32,123,10,9,9,9,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,10,9,9,9,47,47,117,115,101,32,97,32,98,108,117,114,114,101,100,32,118,101,114,115,105,111,110,32,40,105,110,32,99,111,110,115,101,99,117,116,105,118,101,32,109,105,112,109,97,112,115,41,32,111,102,32,116,104,101,32,115,99,114,101,101,110,32,116,111,32,115,105,109,117,108,97,116,101,32,114,111,117,103,104,110,101,115,115,10,10,9,9,9,102,108,111,97,116,32,103,108,111,115,115,32,61,32,49,46,48,45,114,111,117,103,104,110,101,115,115,59,10,9,9,9,102,108,111,97,116,32,99,111,110,101,95,97,110,103,108,101,32,61,32,114,111,117,103,104,110,101,115,115,32,42,32,77,95,80,73,32,42,32,48,46,53,59,10,9,9,9,118,101,99,50,32,99,111,110,101,95,100,105,114,32,61,32,102,105,110,97,108,95,112,111,115,32,45,32,108,105,110,101,95,98,101,103,105,110,59,10,9,9,9,102,108,111,97,116,32,99,111,110,101,95,108,101,110,32,61,32,108,101,110,103,116,104,40,99,111,110,101,95,100,105,114,41,59,10,9,9,9,99,111,110,101,95,100,105,114,32,61,32,110,111,114,109,97,108,105,122,101,40,99,111,110,101,95,100,105,114,41,59,32,47,47,119,105,108,108,32,98,101,32,117,115,101,100,32,110,111,114,109,97,108,105,122,101,100,32,102,114,111,109,32,110,111,119,32,111,110,10,9,9,9,102,108,111,97,116,32,109,97,120,95,109,105,112,109,97,112,32,61,32,102,105,108,116,101,114,95,109,105,112,109,97,112,95,108,101,118,101,108,115,32,45,49,59,10,9,9,9,102,108,111,97,116,32,103,108,111,115,115,95,109,117,108,116,61,103,108,111,115,115,59,10,10,9,9,9,102,108,111,97,116,32,114,101,109,95,97,108,112,104,97,61,49,46,48,59,10,9,9,9,102,105,110,97,108,95,99,111,108,111,114,32,61,32,118,101,99,52,40,48,46,48,41,59,10,10,9,9,9,102,111,114,40,105,110,116,32,105,61,48,59,105,60,55,59,105,43,43,41,32,123,10,10,9,9,9,9,102,108,111,97,116,32,111,112,95,108,101,110,32,61,32,50,46,48,32,42,32,116,97,110,40,99,111,110,101,95,97,110,103,108,101,41,32,42,32,99,111,110,101,95,108,101,110,59,32,47,47,111,112,111,115,105,116,101,32,115,105,100,101,32,111,102,32,105,115,111,32,116,114,105,97,110,103,108,101,10,9,9,9,9,102,108,111,97,116,32,114,97,100,105,117,115,59,10,9,9,9,9,123,10,9,9,9,9,9,47,47,102,105,116,32,116,111,32,115,112,104,101,114,101,32,105,110,115,105,100,101,32,99,111,110,101,32,40,115,112,104,101,114,101,32,101,110,100,115,32,97,116,32,101,110,100,32,111,102,32,99,111,110,101,41,44,32,115,111,109,101,116,104,105,110,103,32,108,105,107,101,32,116,104,105,115,58,10,9,9,9,9,9,47,47,32,95,95,95,10,9,9,9,9,9,47,47,32,92,79,47,10,9,9,9,9,9,47,47,32,32,86,10,9,9,9,9,9,47,47,10,9,9,9,9,9,47,47,32,97,115,32,105,116,32,97,118,111,105,100,115,32,98,108,101,101,100,105,110,103,32,102,114,111,109,32,98,101,121,111,110,100,32,116,104,101,32,114,101,102,108,101,99,116,105,111,110,32,97,115,32,109,117,99,104,32,97,115,32,112,111,115,115,105,98,108,101,46,32,65,115,32,97,32,112,108,117,115,10,9,9,9,9,9,47,47,32,105,116,32,97,108,115,111,32,109,97,107,101,115,32,116,104,101,32,114,111,117,103,104,32,114,101,102,108,101,99,116,105,111,110,32,109,111,114,101,32,101,108,111,110,103,97,116,101,100,46,10,9,9,9,9,9,102,108,111,97,116,32,97,32,61,32,111,112,95,108,101,110,59,10,9,9,9,9,9,102,108,111,97,116,32,104,32,61,32,99,111,110,101,95,108,101,110,59,10,9,9,9,9,9,102,108,111,97,116,32,97,50,32,61,32,97,32,42,32,97,59,10,9,9,9,9,9,102,108,111,97,116,32,102,104,50,32,61,32,52,46,48,102,32,42,32,104,32,42,32,104,59,10,9,9,9,9,9,114,97,100,105,117,115,32,61,32,40,97,32,42,32,40,115,113,114,116,40,97,50,32,43,32,102,104,50,41,32,45,32,97,41,41,32,47,32,40,52,46,48,102,32,42,32,104,41,59,10,9,9,9,9,125,10,10,9,9,9,9,47,47,102,105,110,100,32,116,104,101,32,112,108,97,99,101,32,119,104,101,114,101,32,115,99,114,101,101,110,32,109,117,115,116,32,98,101,32,115,97,109,112,108,101,100,10,9,9,9,9,118,101,99,50,32,115,97,109,112,108,101,95,112,111,115,32,61,32,40,32,108,105,110,101,95,98,101,103,105,110,32,43,32,99,111,110,101,95,100,105,114,32,42,32,40,99,111,110,101,95,108,101,110,32,45,32,114,97,100,105,117,115,41,32,41,32,42,32,112,105,120,101,108,95,115,105,122,101,59,10,9,9,9,9,47,47,114,97,100,105,117,115,32,105,115,32,105,110,32,112,105,120,101,108,115,44,32,115,111,32,105,116,39,115,32,110,97,116,117,114,97,108,32,116,104,97,116,32,108,111,103,50,40,114,97,100,105,117,115,41,32,109,97,112,115,32,116,111,32,116,104,101,32,114,105,103,104,116,32,109,105,112,109,97,112,32,102,111,114,32,116,104,101,32,97,109,111,117,110,116,32,111,102,32,112,105,120,101,108,115,10,9,9,9,9,102,108,111,97,116,32,109,105,112,109,97,112,32,61,32,99,108,97,109,112,40,32,108,111,103,50,40,32,114,97,100,105,117,115,32,41,44,32,48,46,48,44,32,109,97,120,95,109,105,112,109,97,112,32,41,59,10,10,9,9,9,9,47,47,109,105,112,109,97,112,32,61,32,109,97,120,40,109,105,112,109,97,112,45,49,46,48,44,48,46,48,41,59,10,9,9,9,9,47,47,100,111,32,115,97,109,112,108,105,110,103,10,10,9,9,9,9,118,101,99,52,32,115,97,109,112,108,101,95,99,111,108,111,114,59,10,9,9,9,9,123,10,9,9,9,9,9,115,97,109,112,108,101,95,99,111,108,111,114,32,61,32,116,101,120,116,117,114,101,76,111,100,40,115,111,117,114,99,101,95,100,105,102,102,117,115,101,95,109,105,112,109,97,112,115,44,115,97,109,112,108,101,95,112,111,115,44,109,97,120,40,49,46,48,44,109,105,112,109,97,112,41,41,59,10,9,9,9,9,9,105,102,32,40,109,105,112,109,97,112,60,49,46,48,41,32,123,32,47,47,119,101,32,117,115,101,32,97,110,111,116,104,101,114,32,105,109,97,103,101,32,97,115,32,98,97,115,101,32,116,111,32,97,118,111,105,100,32,99,111,112,121,105,110,103,32,97,108,108,32,116,104,101,32,115,99,114,101,101,110,32,117,110,110,101,99,101,115,97,114,105,108,121,10,9,9,9,9,9,9,118,101,99,52,32,98,97,115,101,95,115,97,109,112,108,101,95,99,111,108,111,114,32,61,32,116,101,120,116,117,114,101,76,111,100,40,115,111,117,114,99,101,95,100,105,102,102,117,115,101,44,115,97,109,112,108,101,95,112,111,115,44,48,46,48,41,59,10,9,9,9,9,9,9,115,97,109,112,108,101,95,99,111,108,111,114,32,61,32,109,105,120,40,98,97,115,101,95,115,97,109,112,108,101,95,99,111,108,111,114,44,115,97,109,112,108,101,95,99,111,108,111,114,44,109,105,112,109,97,112,41,59,10,9,9,9,9,9,125,10,9,9,9,9,125,10,10,9,9,9,9,47,47,109,117,108,116,105,112,108,121,32,98,121,32,103,108,111,115,115,10,9,9,9,9,115,97,109,112,108,101,95,99,111,108,111,114,46,114,103,98,42,61,103,108,111,115,115,95,109,117,108,116,59,10,9,9,9,9,115,97,109,112,108,101,95,99,111,108,111,114,46,97,61,103,108,111,115,115,95,109,117,108,116,59,10,10,9,9,9,9,114,101,109,95,97,108,112,104,97,32,45,61,32,115,97,109,112,108,101,95,99,111,108,111,114,46,97,59,10,9,9,9,9,105,102,40,114,101,109,95,97,108,112,104,97,32,60,32,48,46,48,41,32,123,10,9,9,9,9,9,115,97,109,112,108,101,95,99,111,108,111,114,46,114,103,98,32,42,61,32,40,49,46,48,32,45,32,97,98,115,40,114,101,109,95,97,108,112,104,97,41,41,59,10,9,9,9,9,125,10,10,9,9,9,9,102,105,110,97,108,95,99,111,108,111,114,43,61,115,97,109,112,108,101,95,99,111,108,111,114,59,10,10,9,9,9,9,105,102,32,40,102,105,110,97,108,95,99,111,108,111,114,46,97,62,61,48,46,57,53,41,32,123,10,9,9,9,9,9,47,47,32,84,104,105,115,32,99,111,100,101,32,111,102,32,97,99,99,117,109,117,108,97,116,105,110,103,32,103,108,111,115,115,32,97,110,100,32,97,98,111,114,116,105,110,103,32,111,110,32,110,101,97,114,32,111,110,101,10,9,9,9,9,9,47,47,32,109,97,107,101,115,32,115,101,110,115,101,32,119,104,101,110,32,121,111,117,32,116,104,105,110,107,32,111,102,32,99,111,110,101,32,116,114,97,99,105,110,103,46,10,9,9,9,9,9,47,47,32,84,104,105,110,107,32,111,102,32,105,116,32,97,115,32,105,102,32,114,111,117,103,104,110,101,115,115,32,119,97,115,32,48,44,32,116,104,101,110,32,119,101,32,99,111,117,108,100,32,97,98,111,114,116,32,111,110,32,116,104,101,32,102,105,114,115,116,10,9,9,9,9,9,47,47,32,105,116,101,114,97,116,105,111,110,46,32,70,111,114,32,108,101,115,115,101,114,32,114,111,117,103,104,110,101,115,115,32,118,97,108,117,101,115,44,32,119,101,32,110,101,101,100,32,109,111,114,101,32,105,116,101,114,97,116,105,111,110,115,44,32,98,117,116,10,9,9,9,9,9,47,47,32,101,97,99,104,32,110,101,101,100,115,32,116,111,32,104,97,118,101,32,108,101,115,115,32,105,110,102,108,117,101,110,99,101,32,103,105,118,101,110,32,116,104,101,32,115,112,104,101,114,101,32,105,115,32,115,109,97,108,108,101,114,10,9,9,9,9,9,98,114,101,97,107,59,10,9,9,9,9,125,10,10,9,9,9,9,99,111,110,101,95,108,101,110,45,61,114,97,100,105,117,115,42,50,46,48,59,32,47,47,103,111,32,116,111,32,110,101,120,116,32,40,115,109,97,108,108,101,114,41,32,99,105,114,99,108,101,46,10,10,9,9,9,9,103,108,111,115,115,95,109,117,108,116,42,61,103,108,111,115,115,59,10,10,10,9,9,9,125,10,9,9,125,32,101,108,115,101,32,123,10,9,9,9,102,105,110,97,108,95,99,111,108,111,114,32,61,32,116,101,120,116,117,114,101,76,111,100,40,115,111,117,114,99,101,95,100,105,102,102,117,115,101,44,102,105,110,97,108,95,112,111,115,42,112,105,120,101,108,95,115,105,122,101,44,99,108,97,109,112,40,49,46,48,45,103,114,97,100,44,48,46,48,44,49,46,48,41,41,59,10,9,9,125,10,10,9,9,102,114,97,103,95,99,111,108,111,114,32,61,32,118,101,99,52,40,102,105,110,97,108,95,99,111,108,111,114,46,114,103,98,44,109,97,120,40,48,46,48,44,49,46,48,45,103,114,97,100,41,41,59,10,10,35,101,108,115,101,10,9,9,102,114,97,103,95,99,111,108,111,114,32,61,32,118,101,99,52,40,116,101,120,116,117,114,101,76,111,100,40,115,111,117,114,99,101,95,100,105,102,102,117,115,101,44,102,105,110,97,108,95,112,111,115,42,112,105,120,101,108,95,115,105,122,101,44,48,46,48,41,46,114,103,98,44,99,108,97,109,112,40,49,46,48,45,103,114,97,100,44,48,46,48,44,49,46,48,41,41,59,10,35,101,110,100,105,102,10,10,10,10,9,125,32,101,108,115,101,32,123,10,9,9,102,114,97,103,95,99,111,108,111,114,32,61,32,118,101,99,52,40,49,46,48,44,48,46,48,44,48,46,48,44,48,46,48,41,59,10,9,125,10,10,9,47,47,102,114,97,103,95,99,111,108,111,114,32,61,32,118,101,99,52,40,110,111,114,109,97,108,105,122,101,40,108,105,110,101,95,100,105,114,41,32,42,32,48,46,53,32,43,32,48,46,53,44,48,46,48,44,49,46,48,41,59,10,10,47,42,10,9,118,101,99,50,32,104,105,116,95,112,105,120,101,108,59,10,9,118,101,99,51,32,104,105,116,95,112,111,105,110,116,59,10,9,105,110,116,32,119,104,105,99,104,59,10,9,109,97,116,52,32,98,105,97,115,95,109,97,116,32,61,32,109,97,116,52,40,118,101,99,52,40,48,46,53,44,48,46,48,44,48,46,48,44,48,46,48,41,44,118,101,99,52,40,48,46,48,44,48,46,53,44,48,46,48,44,48,46,48,41,44,118,101,99,52,40,48,46,48,44,48,46,48,44,49,46,48,44,48,46,48,41,44,118,101,99,52,40,48,46,53,44,48,46,53,44,48,46,48,44,49,46,48,41,41,59,10,9,109,97,116,52,32,112,105,120,101,108,95,109,97,116,32,61,32,109,97,116,52,40,118,101,99,52,40,118,105,101,119,112,111,114,116,95,115,105,122,101,46,120,44,48,46,48,44,48,46,48,44,48,46,48,41,44,118,101,99,52,40,48,46,48,44,118,105,101,119,112,111,114,116,95,115,105,122,101,46,121,44,48,46,48,44,48,46,48,41,44,118,101,99,52,40,48,46,48,44,48,46,48,44,49,46,48,44,48,46,48,41,44,118,101,99,52,40,48,46,48,44,48,46,48,44,48,46,48,44,49,46,48,41,41,59,10,10,10,10,10,9,109,97,116,52,32,100,116,32,61,32,112,105,120,101,108,95,109,97,116,32,42,40,32,98,105,97,115,95,109,97,116,32,42,32,112,114,111,106,101,99,116,105,111,110,41,59,10,9,118,101,99,52,32,118,112,32,61,32,100,116,32,42,32,118,101,99,52,40,118,101,114,116,101,120,44,49,46,48,41,59,10,9,118,112,46,120,121,122,47,61,118,112,46,119,59,10,10,9,102,114,97,103,95,99,111,108,111,114,32,61,32,116,101,120,101,108,70,101,116,99,104,40,32,115,111,117,114,99,101,95,100,105,102,102,117,115,101,44,32,32,105,118,101,99,50,40,118,112,46,120,121,41,44,48,32,41,59,10,9,114,101,116,117,114,110,59,10,42,47,10,47,42,9,98,111,111,108,32,104,105,116,32,61,32,116,114,97,99,101,83,99,114,101,101,110,83,112,97,99,101,82,97,121,49,40,118,101,114,116,101,120,44,114,97,121,95,100,105,114,44,32,112,105,120,101,108,95,109,97,116,32,42,40,32,98,105,97,115,95,109,97,116,32,42,32,112,114,111,106,101,99,116,105,111,110,41,44,115,111,117,114,99,101,95,100,101,112,116,104,44,118,105,101,119,112,111,114,116,95,115,105,122,101,44,48,46,48,49,44,116,114,117,101,44,99,111,109,112,117,116,101,67,108,105,112,73,110,102,111,40,45,99,97,109,101,114,97,95,122,95,110,101,97,114,44,45,99,97,109,101,114,97,95,122,95,102,97,114,41,44,45,99,97,109,101,114,97,95,122,95,110,101,97,114,44,49,46,50,44,48,46,48,44,54,52,46,48,44,99,97,109,101,114,97,95,122,95,102,97,114,44,104,105,116,95,112,105,120,101,108,44,119,104,105,99,104,44,104,105,116,95,112,111,105,110,116,41,59,10,10,10,10,9,105,102,32,40,104,105,116,41,32,123,10,9,9,102,114,97,103,95,99,111,108,111,114,32,61,32,118,101,99,52,40,116,101,120,101,108,70,101,116,99,104,40,115,111,117,114,99,101,95,100,105,102,102,117,115,101,44,105,118,101,99,50,40,104,105,116,95,112,105,120,101,108,41,44,48,41,46,114,103,98,44,49,46,48,41,59,10,9,125,32,101,108,115,101,32,123,10,9,9,102,114,97,103,95,99,111,108,111,114,32,61,32,118,101,99,52,40,48,46,49,44,48,46,48,44,48,46,48,44,48,46,48,41,59,10,9,125,10,42,47,10,10,10,9,47,42,10,9,102,108,111,97,116,32,112,105,120,101,108,100,105,115,116,32,61,32,108,101,110,103,116,104,40,118,101,114,116,101,120,41,59,10,10,10,9,47,47,32,83,107,105,112,32,115,107,121,98,111,120,32,97,110,100,32,100,105,115,116,97,110,116,32,112,105,120,101,108,115,10,9,105,102,32,40,112,105,120,101,108,100,105,115,116,32,62,32,99,97,109,101,114,97,95,122,95,102,97,114,41,32,123,10,9,9,102,114,97,103,95,99,111,108,111,114,61,118,101,99,52,40,48,46,48,44,48,46,48,44,49,46,48,44,49,46,48,41,59,10,9,9,114,101,116,117,114,110,59,10,9,125,10,10,9,118,101,114,116,101,120,43,61,110,111,114,109,97,108,42,48,46,49,59,10,10,9,47,47,32,82,97,121,32,110,111,116,32,105,110,32,118,105,101,119,10,9,105,102,32,40,100,111,116,40,114,97,121,95,100,105,114,44,32,118,105,101,119,95,100,105,114,41,32,60,32,49,101,45,53,41,32,123,10,9,9,102,114,97,103,95,99,111,108,111,114,32,61,32,118,101,99,52,40,48,46,48,44,49,46,48,44,48,46,48,44,49,46,48,41,59,10,9,9,114,101,116,117,114,110,59,10,9,125,10,10,10,9,102,108,111,97,116,32,109,97,120,95,114,97,121,95,108,101,110,32,61,32,49,46,48,32,42,32,112,105,120,101,108,100,105,115,116,59,10,10,10,9,102,108,111,97,116,32,114,97,121,95,108,101,110,32,61,32,40,10,40,118,101,114,116,101,120,46,122,32,43,32,114,97,121,95,100,105,114,46,122,32,42,32,109,97,120,95,114,97,121,95,108,101,110,41,32,62,32,99,97,109,101,114,97,95,122,95,110,101,97,114,41,32,63,32,40,99,97,109,101,114,97,95,122,95,110,101,97,114,32,45,32,118,101,114,116,101,120,46,122,41,32,47,32,114,97,121,95,100,105,114,46,122,32,58,32,109,97,120,95,114,97,121,95,108,101,110,59,10,10,10,9,47,47,32,67,111,110,118,101,114,116,32,115,116,97,114,116,32,97,110,100,32,101,110,100,32,112,111,115,32,102,114,111,109,32,118,105,101,119,32,116,111,32,115,99,114,101,101,110,32,115,112,97,99,101,10,9,118,101,99,51,32,114,97,121,95,115,116,97,114,116,95,115,99,114,101,101,110,32,61,32,118,105,101,119,95,116,111,95,115,99,114,101,101,110,40,118,101,114,116,101,120,41,59,10,9,118,101,99,51,32,114,97,121,95,101,110,100,95,115,99,114,101,101,110,32,61,32,118,105,101,119,95,116,111,95,115,99,114,101,101,110,40,118,101,114,116,101,120,32,43,32,114,97,121,95,108,101,110,32,42,32,114,97,121,95,100,105,114,41,59,10,10,9,118,101,99,51,32,114,97,121,95,112,111,115,32,61,32,114,97,121,95,115,116,97,114,116,95,115,99,114,101,101,110,59,10,9,118,101,99,51,32,114,97,121,95,100,105,114,95,115,99,114,101,101,110,32,61,32,114,97,121,95,101,110,100,95,115,99,114,101,101,110,32,45,32,114,97,121,95,115,116,97,114,116,95,115,99,114,101,101,110,59,10,10,9,47,47,32,77,97,107,101,32,115,117,114,101,32,116,104,101,32,114,97,121,32,100,111,101,115,32,110,111,116,32,108,101,97,118,101,32,116,104,101,32,115,99,114,101,101,110,10,9,102,108,111,97,116,32,115,99,97,108,101,95,109,97,120,95,120,32,61,32,109,105,110,40,49,44,32,48,46,57,57,32,42,32,40,49,46,48,32,45,32,114,97,121,95,115,116,97,114,116,95,115,99,114,101,101,110,46,120,41,32,47,32,109,97,120,40,49,101,45,53,44,32,114,97,121,95,100,105,114,95,115,99,114,101,101,110,46,120,41,41,59,10,9,102,108,111,97,116,32,115,99,97,108,101,95,109,97,120,95,121,32,61,32,109,105,110,40,49,44,32,48,46,57,57,32,42,32,40,49,46,48,32,45,32,114,97,121,95,115,116,97,114,116,95,115,99,114,101,101,110,46,121,41,32,47,32,109,97,120,40,49,101,45,53,44,32,114,97,121,95,100,105,114,95,115,99,114,101,101,110,46,121,41,41,59,10,9,102,108,111,97,116,32,115,99,97,108,101,95,109,105,110,95,120,32,61,32,109,105,110,40,49,44,32,48,46,57,57,32,42,32,114,97,121,95,115,116,97,114,116,95,115,99,114,101,101,110,46,120,32,47,32,109,97,120,40,49,101,45,53,44,32,45,114,97,121,95,100,105,114,95,115,99,114,101,101,110,46,120,41,41,59,10,9,102,108,111,97,116,32,115,99,97,108,101,95,109,105,110,95,121,32,61,32,109,105,110,40,49,44,32,48,46,57,57,32,42,32,114,97,121,95,115,116,97,114,116,95,115,99,114,101,101,110,46,121,32,47,32,109,97,120,40,49,101,45,53,44,32,45,114,97,121,95,100,105,114,95,115,99,114,101,101,110,46,121,41,41,59,10,9,114,97,121,95,100,105,114,95,115,99,114,101,101,110,32,42,61,32,109,105,110,40,115,99,97,108,101,95,109,97,120,95,120,44,32,115,99,97,108,101,95,109,97,120,95,121,41,59,10,9,114,97,121,95,100,105,114,95,115,99,114,101,101,110,32,42,61,32,109,105,110,40,115,99,97,108,101,95,109,105,110,95,120,44,32,115,99,97,108,101,95,109,105,110,95,121,41,59,10,10,9,118,101,99,51,32,114,97,121,95,115,116,101,112,32,61,32,40,114,97,121,95,101,110,100,95,115,99,114,101,101,110,32,45,32,114,97,121,95,115,116,97,114,116,95,115,99,114,101,101,110,41,32,47,32,110,117,109,95,115,116,101,112,115,59,10,10,9,102,108,111,97,116,32,100,105,115,116,97,110,99,101,95,115,99,97,108,101,32,61,32,49,46,48,32,43,32,48,46,48,48,48,48,49,32,42,32,112,105,120,101,108,100,105,115,116,59,10,10,9,102,108,111,97,116,32,106,105,116,116,101,114,32,61,32,48,46,48,59,47,47,97,98,115,40,114,97,110,100,40,105,118,101,99,50,40,103,108,95,70,114,97,103,67,111,111,114,100,46,120,121,41,32,37,32,56,32,43,32,40,77,97,105,110,83,99,101,110,101,68,97,116,97,46,102,114,97,109,101,95,105,110,100,101,120,32,37,32,71,69,84,95,83,69,84,84,73,78,71,40,115,115,114,44,32,104,105,115,116,111,114,121,95,108,101,110,103,116,104,41,41,32,42,32,48,46,49,41,41,59,10,10,9,47,47,32,82,111,117,103,104,32,115,111,117,114,102,97,99,101,115,32,110,101,101,100,32,109,111,114,101,32,106,105,116,116,101,114,10,9,106,105,116,116,101,114,32,42,61,32,109,97,120,40,48,46,53,44,32,114,111,117,103,104,110,101,115,115,41,59,10,10,9,114,97,121,95,112,111,115,32,43,61,32,106,105,116,116,101,114,32,42,32,114,97,121,95,115,116,101,112,59,10,10,10,9,105,110,116,32,105,32,61,32,48,59,10,9,102,108,111,97,116,32,105,110,116,101,114,115,101,99,116,105,111,110,95,119,101,105,103,104,116,32,61,32,48,46,48,59,10,9,98,111,111,108,32,104,105,116,95,102,97,99,116,111,114,32,61,32,102,97,108,115,101,59,10,10,9,118,101,99,50,32,105,110,116,101,114,115,101,99,116,105,111,110,32,61,32,118,101,99,50,40,45,49,46,48,41,59,10,10,9,102,111,114,32,40,105,32,61,32,49,59,32,105,32,60,32,110,117,109,95,115,116,101,112,115,59,32,43,43,105,41,32,123,10,9,9,114,97,121,95,112,111,115,32,43,61,32,114,97,121,95,115,116,101,112,59,10,10,9,9,47,47,32,67,117,114,114,101,110,116,32,99,111,111,114,100,105,110,97,116,101,32,105,115,32,105,110,32,116,104,101,32,109,105,100,32,111,102,32,116,119,111,32,115,97,109,112,108,101,115,44,32,110,111,116,32,97,116,32,116,104,101,32,101,110,100,44,32,115,111,10,9,9,47,47,32,115,117,98,115,116,114,97,99,116,32,104,97,108,102,32,111,102,32,97,32,115,116,101,112,10,9,9,118,101,99,50,32,99,117,114,114,95,99,111,111,114,100,32,61,32,114,97,121,95,112,111,115,46,120,121,32,45,32,48,46,53,32,42,32,114,97,121,95,115,116,101,112,46,120,121,59,10,10,10,9,9,47,47,32,73,110,99,114,101,97,115,101,32,114,97,121,32,98,105,97,115,32,97,115,32,119,101,32,97,100,118,97,110,99,101,32,116,104,101,32,114,97,121,10,9,9,102,108,111,97,116,32,116,114,97,99,101,95,108,101,110,32,61,32,105,110,105,116,105,97,108,95,98,105,97,115,32,42,32,49,48,46,48,32,43,10,9,9,9,9,49,48,48,46,48,32,42,32,100,111,116,40,99,117,114,114,95,99,111,111,114,100,45,117,118,95,105,110,116,101,114,112,44,99,117,114,114,95,99,111,111,114,100,45,117,118,95,105,110,116,101,114,112,41,59,10,10,9,9,116,114,97,99,101,95,108,101,110,32,42,61,32,49,46,48,32,43,32,49,46,48,32,42,32,114,111,117,103,104,110,101,115,115,59,10,10,9,9,47,47,32,67,104,101,99,107,32,102,111,114,32,105,110,116,101,114,115,101,99,116,105,111,110,10,10,9,9,102,108,111,97,116,32,100,101,112,116,104,32,61,32,116,101,120,116,117,114,101,40,115,111,117,114,99,101,95,100,101,112,116,104,44,99,117,114,114,95,99,111,111,114,100,41,46,114,32,42,32,50,46,48,32,45,32,49,46,48,59,10,9,9,102,108,111,97,116,32,108,105,110,101,97,114,95,100,101,112,116,104,61,100,101,112,116,104,59,10,9,9,47,47,102,108,111,97,116,32,108,105,110,101,97,114,95,100,101,112,116,104,32,61,32,50,46,48,32,42,32,99,97,109,101,114,97,95,122,95,110,101,97,114,32,42,32,99,97,109,101,114,97,95,122,95,102,97,114,32,47,32,40,99,97,109,101,114,97,95,122,95,102,97,114,32,43,32,99,97,109,101,114,97,95,122,95,110,101,97,114,32,45,32,100,101,112,116,104,32,42,32,40,99,97,109,101,114,97,95,122,95,102,97,114,32,45,32,99,97,109,101,114,97,95,122,95,110,101,97,114,41,41,59,10,9,9,47,47,108,105,110,101,97,114,95,100,101,112,116,104,32,61,32,45,108,105,110,101,97,114,95,100,101,112,116,104,59,10,10,10,9,9,105,102,32,40,112,111,105,110,116,95,98,101,116,119,101,101,110,95,112,108,97,110,101,115,40,108,105,110,101,97,114,95,100,101,112,116,104,44,32,114,97,121,95,112,111,115,46,122,44,10,9,9,9,9,9,32,114,97,121,95,112,111,115,46,122,32,45,32,114,97,121,95,115,116,101,112,46,122,44,32,116,114,97,99,101,95,108,101,110,44,32,104,105,116,95,102,97,99,116,111,114,41,41,32,123,10,9,9,9,105,110,116,101,114,115,101,99,116,105,111,110,32,61,32,99,117,114,114,95,99,111,111,114,100,59,10,9,9,9,98,114,101,97,107,59,10,9,9,125,10,9,125,10,10,9,47,47,32,77,97,107,101,32,115,117,114,101,32,119,101,32,104,105,116,32,101,120,97,99,116,108,121,32,111,110,101,32,112,105,120,101,108,10,9,47,47,105,110,116,101,114,115,101,99,116,105,111,110,32,61,32,116,114,117,110,99,97,116,101,95,99,111,111,114,100,105,110,97,116,101,40,105,110,116,101,114,115,101,99,116,105,111,110,41,59,10,10,9,47,47,32,67,104,101,99,107,32,105,102,32,119,101,32,104,105,116,32,115,111,109,101,116,104,105,110,103,10,9,105,102,32,40,109,105,110,40,105,110,116,101,114,115,101,99,116,105,111,110,46,120,44,32,105,110,116,101,114,115,101,99,116,105,111,110,46,121,41,32,60,61,32,48,46,48,32,124,124,32,111,117,116,95,111,102,95,115,99,114,101,101,110,40,105,110,116,101,114,115,101,99,116,105,111,110,41,41,32,123,10,9,9,102,114,97,103,95,99,111,108,111,114,61,118,101,99,52,40,49,46,48,44,48,46,48,44,49,46,48,44,49,46,48,41,59,10,9,9,114,101,116,117,114,110,59,10,9,125,10,10,9,105,102,32,40,33,104,105,116,95,102,97,99,116,111,114,41,32,123,10,9,9,102,114,97,103,95,99,111,108,111,114,61,118,101,99,52,40,48,46,48,44,49,46,48,44,49,46,48,44,49,46,48,41,59,10,9,9,114,101,116,117,114,110,59,10,9,125,10,10,9,102,114,97,103,95,99,111,108,111,114,32,61,32,118,101,99,52,40,116,101,120,116,117,114,101,40,115,111,117,114,99,101,95,100,105,102,102,117,115,101,44,105,110,116,101,114,115,101,99,116,105,111,110,41,46,114,103,98,44,49,46,48,41,59,10,42,47,10,10,125,10,10, 0}; + + static const int _fragment_code_start=17; + setup(_conditional_strings,2,_uniform_strings,8,_attribute_pairs,0, _texunit_pairs,4,_ubo_pairs,0,_feedbacks,0,_vertex_code,_fragment_code,_vertex_code_start,_fragment_code_start); + }; + +}; + +#endif + diff --git a/drivers/gles3/shaders/screen_space_reflection.glsl b/drivers/gles3/shaders/screen_space_reflection.glsl new file mode 100644 index 0000000000..5b24013c07 --- /dev/null +++ b/drivers/gles3/shaders/screen_space_reflection.glsl @@ -0,0 +1,350 @@ +[vertex] + + +layout(location=0) in highp vec4 vertex_attrib; +layout(location=4) in vec2 uv_in; + +out vec2 uv_interp; +out vec2 pos_interp; + +void main() { + + uv_interp = uv_in; + gl_Position = vertex_attrib; + pos_interp.xy=gl_Position.xy; +} + +[fragment] + + +in vec2 uv_interp; +in vec2 pos_interp; + +uniform sampler2D source_diffuse; //texunit:0 +uniform sampler2D source_normal_roughness; //texunit:1 +uniform sampler2D source_depth; //texunit:2 +uniform sampler2D source_diffuse_mipmaps; //texunit:3 + +uniform float camera_z_near; +uniform float camera_z_far; + +uniform vec2 viewport_size; +uniform vec2 pixel_size; + +uniform float filter_mipmap_levels; + +uniform mat4 inverse_projection; +uniform mat4 projection; + +uniform int num_steps; +uniform float depth_tolerance; +uniform float distance_fade; +uniform float acceleration; + +layout(location = 0) out vec4 frag_color; + + +vec2 view_to_screen(vec3 view_pos,out float w) { + vec4 projected = projection * vec4(view_pos, 1.0); + projected.xyz /= projected.w; + projected.xy = projected.xy * 0.5 + 0.5; + w=projected.w; + return projected.xy; +} + + + +#define M_PI 3.14159265359 + + +void main() { + + + //// + + vec4 diffuse = texture( source_diffuse, uv_interp ); + vec4 normal_roughness = texture( source_normal_roughness, uv_interp); + + vec3 normal; + + normal = normal_roughness.xyz*2.0-1.0; + + float roughness = normal_roughness.w; + + float depth_tex = texture(source_depth,uv_interp).r; + + vec4 world_pos = inverse_projection * vec4( uv_interp*2.0-1.0, depth_tex*2.0-1.0, 1.0 ); + vec3 vertex = world_pos.xyz/world_pos.w; + + vec3 view_dir = normalize(vertex); + vec3 ray_dir = normalize(reflect(view_dir, normal)); + + if (dot(ray_dir,normal)<0.001) { + frag_color=vec4(0.0); + return; + } + //ray_dir = normalize(view_dir - normal * dot(normal,view_dir) * 2.0); + + //ray_dir = normalize(vec3(1,1,-1)); + + + //////////////// + + + //make ray length and clip it against the near plane (don't want to trace beyond visible) + float ray_len = (vertex.z + ray_dir.z * camera_z_far) > -camera_z_near ? (-camera_z_near - vertex.z) / ray_dir.z : camera_z_far; + vec3 ray_end = vertex + ray_dir*ray_len; + + float w_begin; + vec2 vp_line_begin = view_to_screen(vertex,w_begin); + float w_end; + vec2 vp_line_end = view_to_screen( ray_end, w_end); + vec2 vp_line_dir = vp_line_end-vp_line_begin; + + //we need to interpolate w along the ray, to generate perspective correct reflections + + w_begin = 1.0/w_begin; + w_end = 1.0/w_end; + + + float z_begin = vertex.z*w_begin; + float z_end = ray_end.z*w_end; + + vec2 line_begin = vp_line_begin/pixel_size; + vec2 line_dir = vp_line_dir/pixel_size; + float z_dir = z_end - z_begin; + float w_dir = w_end - w_begin; + + + // clip the line to the viewport edges + + float scale_max_x = min(1, 0.99 * (1.0 - vp_line_begin.x) / max(1e-5, vp_line_dir.x)); + float scale_max_y = min(1, 0.99 * (1.0 - vp_line_begin.y) / max(1e-5, vp_line_dir.y)); + float scale_min_x = min(1, 0.99 * vp_line_begin.x / max(1e-5, -vp_line_dir.x)); + float scale_min_y = min(1, 0.99 * vp_line_begin.y / max(1e-5, -vp_line_dir.y)); + float line_clip = min(scale_max_x, scale_max_y) * min(scale_min_x, scale_min_y); + line_dir *= line_clip; + z_dir *= line_clip; + w_dir *=line_clip; + + //clip z and w advance to line advance + vec2 line_advance = normalize(line_dir); //down to pixel + float step_size = length(line_advance)/length(line_dir); + float z_advance = z_dir*step_size; // adapt z advance to line advance + float w_advance = w_dir*step_size; // adapt w advance to line advance + + //make line advance faster if direction is closer to pixel edges (this avoids sampling the same pixel twice) + float advance_angle_adj = 1.0/max(abs(line_advance.x),abs(line_advance.y)); + line_advance*=advance_angle_adj; // adapt z advance to line advance + z_advance*=advance_angle_adj; + w_advance*=advance_angle_adj; + + vec2 pos = line_begin; + float z = z_begin; + float w = w_begin; + float z_from=z/w; + float z_to=z_from; + float depth; + vec2 prev_pos=pos; + + bool found=false; + + //if acceleration > 0, distance between pixels gets larger each step. This allows covering a larger area + float accel=1.0+acceleration; + float steps_taken=0; + + for(float i=0;iz_to) { + //if depth was surpassed + if (depth<=max(z_to,z_from)+depth_tolerance) { + //check the depth tolerance + found=true; + } + break; + } + + steps_taken+=1.0; + prev_pos=pos; + z_advance*=accel; + w_advance*=accel; + line_advance*=accel; + } + + + + + if (found) { + + float margin_blend=1.0; + + + vec2 margin = vec2((viewport_size.x+viewport_size.y)*0.5*0.05); //make a uniform margin + if (any(bvec4(lessThan(pos,-margin),greaterThan(pos,viewport_size+margin)))) { + //clip outside screen + margin + frag_color=vec4(0.0); + return; + } + + { + //blend fading out towards external margin + vec2 margin_grad = mix(pos-viewport_size,-pos,lessThan(pos,vec2(0.0))); + margin_blend = 1.0-smoothstep(0.0,margin.x,max(margin_grad.x,margin_grad.y)); + //margin_blend=1.0; + + } + + vec2 final_pos; + float grad; + +#ifdef SMOOTH_ACCEL + //if the distance between point and prev point is >1, then take some samples in the middle for smoothing out the image + vec2 blend_dir = pos - prev_pos; + float steps = min(8.0,length(blend_dir)); + if (steps>2.0) { + vec2 blend_step = blend_dir/steps; + float blend_z = (z_to-z_from)/steps; + vec2 new_pos; + float subgrad=0.0; + for(float i=0.0;iz) + break; + } + + final_pos = new_pos; + grad=(steps_taken+subgrad)/num_steps; + + } else { +#endif + grad=steps_taken/num_steps; + final_pos=pos; +#ifdef SMOOTH_ACCEL + } + +#endif + + + +#ifdef REFLECT_ROUGHNESS + + + vec4 final_color; + //if roughness is enabled, do screen space cone tracing + if (roughness > 0.001) { + /////////////////////////////////////////////////////////////////////////////////////// + //use a blurred version (in consecutive mipmaps) of the screen to simulate roughness + + float gloss = 1.0-roughness; + float cone_angle = roughness * M_PI * 0.5; + vec2 cone_dir = final_pos - line_begin; + float cone_len = length(cone_dir); + cone_dir = normalize(cone_dir); //will be used normalized from now on + float max_mipmap = filter_mipmap_levels -1; + float gloss_mult=gloss; + + float rem_alpha=1.0; + final_color = vec4(0.0); + + for(int i=0;i<7;i++) { + + float op_len = 2.0 * tan(cone_angle) * cone_len; //oposite side of iso triangle + float radius; + { + //fit to sphere inside cone (sphere ends at end of cone), something like this: + // ___ + // \O/ + // V + // + // as it avoids bleeding from beyond the reflection as much as possible. As a plus + // it also makes the rough reflection more elongated. + float a = op_len; + float h = cone_len; + float a2 = a * a; + float fh2 = 4.0f * h * h; + radius = (a * (sqrt(a2 + fh2) - a)) / (4.0f * h); + } + + //find the place where screen must be sampled + vec2 sample_pos = ( line_begin + cone_dir * (cone_len - radius) ) * pixel_size; + //radius is in pixels, so it's natural that log2(radius) maps to the right mipmap for the amount of pixels + float mipmap = clamp( log2( radius ), 0.0, max_mipmap ); + + //mipmap = max(mipmap-1.0,0.0); + //do sampling + + vec4 sample_color; + { + sample_color = textureLod(source_diffuse_mipmaps,sample_pos,max(1.0,mipmap)); + if (mipmap<1.0) { //we use another image as base to avoid copying all the screen unnecesarily + vec4 base_sample_color = textureLod(source_diffuse,sample_pos,0.0); + sample_color = mix(base_sample_color,sample_color,mipmap); + } + } + + //multiply by gloss + sample_color.rgb*=gloss_mult; + sample_color.a=gloss_mult; + + rem_alpha -= sample_color.a; + if(rem_alpha < 0.0) { + sample_color.rgb *= (1.0 - abs(rem_alpha)); + } + + final_color+=sample_color; + + if (final_color.a>=0.95) { + // This code of accumulating gloss and aborting on near one + // makes sense when you think of cone tracing. + // Think of it as if roughness was 0, then we could abort on the first + // iteration. For lesser roughness values, we need more iterations, but + // each needs to have less influence given the sphere is smaller + break; + } + + cone_len-=radius*2.0; //go to next (smaller) circle. + + gloss_mult*=gloss; + + + } + } else { + final_color = textureLod(source_diffuse,final_pos*pixel_size,0.0); + } + + frag_color = vec4(final_color.rgb,pow(clamp(1.0-grad,0.0,1.0),distance_fade)*margin_blend); + +#else + frag_color = vec4(textureLod(source_diffuse,final_pos*pixel_size,0.0).rgb,pow(clamp(1.0-grad,0.0,1.0),distance_fade)*margin_blend); +#endif + + + + } else { + frag_color = vec4(0.0,0.0,0.0,0.0); + } + + + +} + -- cgit v1.2.3 From 1652f876fd33972b0151c10beff66590fb413ec7 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Tue, 29 Nov 2016 21:08:02 -0300 Subject: Add missing glsl file and remove generated .h files --- drivers/gles3/shaders/effect_blur.glsl | 57 ++++++++++ drivers/gles3/shaders/resolve.glsl.h | 166 --------------------------- drivers/gles3/shaders/screen_space.glsl.h | 183 ------------------------------ drivers/gles3/shadow_atlas_gles3.cpp | 2 - drivers/gles3/shadow_atlas_gles3.h | 8 -- 5 files changed, 57 insertions(+), 359 deletions(-) create mode 100644 drivers/gles3/shaders/effect_blur.glsl delete mode 100644 drivers/gles3/shaders/resolve.glsl.h delete mode 100644 drivers/gles3/shaders/screen_space.glsl.h delete mode 100644 drivers/gles3/shadow_atlas_gles3.cpp delete mode 100644 drivers/gles3/shadow_atlas_gles3.h (limited to 'drivers/gles3') diff --git a/drivers/gles3/shaders/effect_blur.glsl b/drivers/gles3/shaders/effect_blur.glsl new file mode 100644 index 0000000000..fc6de7f654 --- /dev/null +++ b/drivers/gles3/shaders/effect_blur.glsl @@ -0,0 +1,57 @@ +[vertex] + + +layout(location=0) in highp vec4 vertex_attrib; +layout(location=4) in vec2 uv_in; + +out vec2 uv_interp; + + +void main() { + + uv_interp = uv_in; + gl_Position = vertex_attrib; +} + +[fragment] + + +in vec2 uv_interp; +uniform sampler2D source_color; //texunit:0 + +uniform float lod; +uniform vec2 pixel_size; + + +layout(location = 0) out vec4 frag_color; + +void main() { + + + +#ifdef GAUSSIAN_HORIZONTAL + vec4 color =textureLod( source_color, uv_interp+vec2( 0.0, 0.0)*pixel_size,lod )*0.38774; + color+=textureLod( source_color, uv_interp+vec2( 1.0, 0.0)*pixel_size,lod )*0.24477; + color+=textureLod( source_color, uv_interp+vec2( 2.0, 0.0)*pixel_size,lod )*0.06136; + color+=textureLod( source_color, uv_interp+vec2(-1.0, 0.0)*pixel_size,lod )*0.24477; + color+=textureLod( source_color, uv_interp+vec2(-2.0, 0.0)*pixel_size,lod )*0.06136; + frag_color = color; +#endif + +#ifdef GAUSSIAN_VERTICAL + vec4 color =textureLod( source_color, uv_interp+vec2( 0.0, 0.0)*pixel_size,lod )*0.38774; + color+=textureLod( source_color, uv_interp+vec2( 0.0, 1.0)*pixel_size,lod )*0.24477; + color+=textureLod( source_color, uv_interp+vec2( 0.0, 2.0)*pixel_size,lod )*0.06136; + color+=textureLod( source_color, uv_interp+vec2( 0.0,-1.0)*pixel_size,lod )*0.24477; + color+=textureLod( source_color, uv_interp+vec2( 0.0,-2.0)*pixel_size,lod )*0.06136; + frag_color = color; +#endif + +#ifdef SIMPLE_COPY + vec4 color =textureLod( source_color, uv_interp,0.0); + frag_color = color; +#endif + + +} + diff --git a/drivers/gles3/shaders/resolve.glsl.h b/drivers/gles3/shaders/resolve.glsl.h deleted file mode 100644 index 72baf50716..0000000000 --- a/drivers/gles3/shaders/resolve.glsl.h +++ /dev/null @@ -1,166 +0,0 @@ -/* WARNING, THIS FILE WAS GENERATED, DO NOT EDIT */ -#ifndef RESOLVE_GLSL_HGLES3_120 -#define RESOLVE_GLSL_HGLES3_120 - - -#include "drivers/gles3/shader_gles3.h" - - -class ResolveShaderGLES3 : public ShaderGLES3 { - - virtual String get_shader_name() const { return "ResolveShaderGLES3"; } -public: - - enum Conditionals { - USE_SSR, - }; - - enum Uniforms { - STUFF, - }; - - _FORCE_INLINE_ int get_uniform(Uniforms p_uniform) const { return _get_uniform(p_uniform); } - - _FORCE_INLINE_ void set_conditional(Conditionals p_conditional,bool p_enable) { _set_conditional(p_conditional,p_enable); } - - #define _FU if (get_uniform(p_uniform)<0) return; ERR_FAIL_COND( get_active()!=this ); - - _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, float p_value) { _FU glUniform1f(get_uniform(p_uniform),p_value); } - - _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, double p_value) { _FU glUniform1f(get_uniform(p_uniform),p_value); } - - _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, uint8_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); } - - _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, int8_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); } - - _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, uint16_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); } - - _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, int16_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); } - - _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, uint32_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); } - - _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, int32_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); } - - _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Color& p_color) { _FU GLfloat col[4]={p_color.r,p_color.g,p_color.b,p_color.a}; glUniform4fv(get_uniform(p_uniform),1,col); } - - _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Vector2& p_vec2) { _FU GLfloat vec2[2]={p_vec2.x,p_vec2.y}; glUniform2fv(get_uniform(p_uniform),1,vec2); } - - _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Vector3& p_vec3) { _FU GLfloat vec3[3]={p_vec3.x,p_vec3.y,p_vec3.z}; glUniform3fv(get_uniform(p_uniform),1,vec3); } - - _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, float p_a, float p_b) { _FU glUniform2f(get_uniform(p_uniform),p_a,p_b); } - - _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, float p_a, float p_b, float p_c) { _FU glUniform3f(get_uniform(p_uniform),p_a,p_b,p_c); } - - _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, float p_a, float p_b, float p_c, float p_d) { _FU glUniform4f(get_uniform(p_uniform),p_a,p_b,p_c,p_d); } - - _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Transform& p_transform) { _FU - - const Transform &tr = p_transform; - - GLfloat matrix[16]={ /* build a 16x16 matrix */ - tr.basis.elements[0][0], - tr.basis.elements[1][0], - tr.basis.elements[2][0], - 0, - tr.basis.elements[0][1], - tr.basis.elements[1][1], - tr.basis.elements[2][1], - 0, - tr.basis.elements[0][2], - tr.basis.elements[1][2], - tr.basis.elements[2][2], - 0, - tr.origin.x, - tr.origin.y, - tr.origin.z, - 1 - }; - - - glUniformMatrix4fv(get_uniform(p_uniform),1,false,matrix); - - - } - - _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Matrix32& p_transform) { _FU - - const Matrix32 &tr = p_transform; - - GLfloat matrix[16]={ /* build a 16x16 matrix */ - tr.elements[0][0], - tr.elements[0][1], - 0, - 0, - tr.elements[1][0], - tr.elements[1][1], - 0, - 0, - 0, - 0, - 1, - 0, - tr.elements[2][0], - tr.elements[2][1], - 0, - 1 - }; - - - glUniformMatrix4fv(get_uniform(p_uniform),1,false,matrix); - - - } - - _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const CameraMatrix& p_matrix) { _FU - - GLfloat matrix[16]; - - for (int i=0;i<4;i++) { - for (int j=0;j<4;j++) { - - matrix[i*4+j]=p_matrix.matrix[i][j]; - } - } - - glUniformMatrix4fv(get_uniform(p_uniform),1,false,matrix); - }; - -#undef _FU - - - virtual void init() { - - static const Enum *_enums=NULL; - static const EnumValue *_enum_values=NULL; - static const char* _conditional_strings[]={ - "#define USE_SSR\n", - }; - - static const char* _uniform_strings[]={ - "stuff", - }; - - static AttributePair *_attribute_pairs=NULL; - static const Feedback* _feedbacks=NULL; - static TexUnitPair _texunit_pairs[]={ - {"source_diffuse",0}, - {"source_specular",1}, - {"source_ssr_ssao",2}, - }; - - static UBOPair *_ubo_pairs=NULL; - static const char _vertex_code[]={ -10,10,108,97,121,111,117,116,40,108,111,99,97,116,105,111,110,61,48,41,32,105,110,32,104,105,103,104,112,32,118,101,99,52,32,118,101,114,116,101,120,95,97,116,116,114,105,98,59,10,108,97,121,111,117,116,40,108,111,99,97,116,105,111,110,61,52,41,32,105,110,32,118,101,99,50,32,117,118,95,105,110,59,10,10,111,117,116,32,118,101,99,50,32,117,118,95,105,110,116,101,114,112,59,10,10,10,118,111,105,100,32,109,97,105,110,40,41,32,123,10,10,9,117,118,95,105,110,116,101,114,112,32,61,32,117,118,95,105,110,59,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,118,101,114,116,101,120,95,97,116,116,114,105,98,59,10,125,10,10, 0}; - - static const int _vertex_code_start=1; - static const char _fragment_code[]={ -10,10,105,110,32,118,101,99,50,32,117,118,95,105,110,116,101,114,112,59,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,115,111,117,114,99,101,95,100,105,102,102,117,115,101,59,32,47,47,116,101,120,117,110,105,116,58,48,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,115,111,117,114,99,101,95,115,112,101,99,117,108,97,114,59,32,47,47,116,101,120,117,110,105,116,58,49,10,10,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,115,111,117,114,99,101,95,115,115,114,95,115,115,97,111,59,32,47,47,116,101,120,117,110,105,116,58,50,10,10,117,110,105,102,111,114,109,32,102,108,111,97,116,32,115,116,117,102,102,59,10,10,105,110,32,118,101,99,50,32,117,118,50,95,105,110,116,101,114,112,59,10,10,108,97,121,111,117,116,40,108,111,99,97,116,105,111,110,32,61,32,48,41,32,111,117,116,32,118,101,99,52,32,102,114,97,103,95,99,111,108,111,114,59,10,10,118,111,105,100,32,109,97,105,110,40,41,32,123,10,10,9,118,101,99,52,32,100,105,102,102,117,115,101,32,61,32,116,101,120,116,117,114,101,40,32,115,111,117,114,99,101,95,100,105,102,102,117,115,101,44,32,32,117,118,95,105,110,116,101,114,112,32,41,59,10,9,118,101,99,52,32,115,112,101,99,117,108,97,114,32,61,32,116,101,120,116,117,114,101,40,32,115,111,117,114,99,101,95,115,112,101,99,117,108,97,114,44,32,32,117,118,95,105,110,116,101,114,112,32,41,59,10,10,35,105,102,100,101,102,32,85,83,69,95,83,83,82,10,10,9,118,101,99,52,32,115,115,114,32,61,32,116,101,120,116,117,114,101,76,111,100,40,115,111,117,114,99,101,95,115,115,114,95,115,115,97,111,44,117,118,95,105,110,116,101,114,112,44,48,46,48,41,59,10,9,115,112,101,99,117,108,97,114,46,114,103,98,32,61,32,109,105,120,40,115,112,101,99,117,108,97,114,46,114,103,98,44,115,115,114,46,114,103,98,42,115,112,101,99,117,108,97,114,46,97,44,115,115,114,46,97,41,59,10,35,101,110,100,105,102,10,10,9,102,114,97,103,95,99,111,108,111,114,32,61,32,118,101,99,52,40,100,105,102,102,117,115,101,46,114,103,98,44,49,46,48,41,43,118,101,99,52,40,115,112,101,99,117,108,97,114,46,114,103,98,44,49,46,48,41,59,10,125,10,10, 0}; - - static const int _fragment_code_start=16; - setup(_conditional_strings,1,_uniform_strings,1,_attribute_pairs,0, _texunit_pairs,3,_ubo_pairs,0,_feedbacks,0,_vertex_code,_fragment_code,_vertex_code_start,_fragment_code_start); - }; - -}; - -#endif - diff --git a/drivers/gles3/shaders/screen_space.glsl.h b/drivers/gles3/shaders/screen_space.glsl.h deleted file mode 100644 index f39d04429d..0000000000 --- a/drivers/gles3/shaders/screen_space.glsl.h +++ /dev/null @@ -1,183 +0,0 @@ -/* WARNING, THIS FILE WAS GENERATED, DO NOT EDIT */ -#ifndef SCREEN_SPACE_GLSL_HGLES3_120 -#define SCREEN_SPACE_GLSL_HGLES3_120 - - -#include "drivers/gles3/shader_gles3.h" - - -class ScreenSpaceShaderGLES3 : public ShaderGLES3 { - - virtual String get_shader_name() const { return "ScreenSpaceShaderGLES3"; } -public: - - enum Conditionals { - BLEND_ACCEL, - REFLECT_ROUGHNESS, - }; - - enum Uniforms { - CAMERA_Z_NEAR, - CAMERA_Z_FAR, - VIEWPORT_SIZE, - PIXEL_SIZE, - FILTER_MIPMAP_LEVELS, - INVERSE_PROJECTION, - PROJECTION, - FRAME_INDEX, - }; - - _FORCE_INLINE_ int get_uniform(Uniforms p_uniform) const { return _get_uniform(p_uniform); } - - _FORCE_INLINE_ void set_conditional(Conditionals p_conditional,bool p_enable) { _set_conditional(p_conditional,p_enable); } - - #define _FU if (get_uniform(p_uniform)<0) return; ERR_FAIL_COND( get_active()!=this ); - - _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, float p_value) { _FU glUniform1f(get_uniform(p_uniform),p_value); } - - _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, double p_value) { _FU glUniform1f(get_uniform(p_uniform),p_value); } - - _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, uint8_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); } - - _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, int8_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); } - - _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, uint16_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); } - - _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, int16_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); } - - _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, uint32_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); } - - _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, int32_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); } - - _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Color& p_color) { _FU GLfloat col[4]={p_color.r,p_color.g,p_color.b,p_color.a}; glUniform4fv(get_uniform(p_uniform),1,col); } - - _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Vector2& p_vec2) { _FU GLfloat vec2[2]={p_vec2.x,p_vec2.y}; glUniform2fv(get_uniform(p_uniform),1,vec2); } - - _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Vector3& p_vec3) { _FU GLfloat vec3[3]={p_vec3.x,p_vec3.y,p_vec3.z}; glUniform3fv(get_uniform(p_uniform),1,vec3); } - - _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, float p_a, float p_b) { _FU glUniform2f(get_uniform(p_uniform),p_a,p_b); } - - _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, float p_a, float p_b, float p_c) { _FU glUniform3f(get_uniform(p_uniform),p_a,p_b,p_c); } - - _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, float p_a, float p_b, float p_c, float p_d) { _FU glUniform4f(get_uniform(p_uniform),p_a,p_b,p_c,p_d); } - - _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Transform& p_transform) { _FU - - const Transform &tr = p_transform; - - GLfloat matrix[16]={ /* build a 16x16 matrix */ - tr.basis.elements[0][0], - tr.basis.elements[1][0], - tr.basis.elements[2][0], - 0, - tr.basis.elements[0][1], - tr.basis.elements[1][1], - tr.basis.elements[2][1], - 0, - tr.basis.elements[0][2], - tr.basis.elements[1][2], - tr.basis.elements[2][2], - 0, - tr.origin.x, - tr.origin.y, - tr.origin.z, - 1 - }; - - - glUniformMatrix4fv(get_uniform(p_uniform),1,false,matrix); - - - } - - _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Matrix32& p_transform) { _FU - - const Matrix32 &tr = p_transform; - - GLfloat matrix[16]={ /* build a 16x16 matrix */ - tr.elements[0][0], - tr.elements[0][1], - 0, - 0, - tr.elements[1][0], - tr.elements[1][1], - 0, - 0, - 0, - 0, - 1, - 0, - tr.elements[2][0], - tr.elements[2][1], - 0, - 1 - }; - - - glUniformMatrix4fv(get_uniform(p_uniform),1,false,matrix); - - - } - - _FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const CameraMatrix& p_matrix) { _FU - - GLfloat matrix[16]; - - for (int i=0;i<4;i++) { - for (int j=0;j<4;j++) { - - matrix[i*4+j]=p_matrix.matrix[i][j]; - } - } - - glUniformMatrix4fv(get_uniform(p_uniform),1,false,matrix); - }; - -#undef _FU - - - virtual void init() { - - static const Enum *_enums=NULL; - static const EnumValue *_enum_values=NULL; - static const char* _conditional_strings[]={ - "#define BLEND_ACCEL\n", - "#define REFLECT_ROUGHNESS\n", - }; - - static const char* _uniform_strings[]={ - "camera_z_near", - "camera_z_far", - "viewport_size", - "pixel_size", - "filter_mipmap_levels", - "inverse_projection", - "projection", - "frame_index", - }; - - static AttributePair *_attribute_pairs=NULL; - static const Feedback* _feedbacks=NULL; - static TexUnitPair _texunit_pairs[]={ - {"source_diffuse",0}, - {"source_normal_roughness",1}, - {"source_depth",2}, - {"source_diffuse_mipmaps",3}, - }; - - static UBOPair *_ubo_pairs=NULL; - static const char _vertex_code[]={ -10,10,108,97,121,111,117,116,40,108,111,99,97,116,105,111,110,61,48,41,32,105,110,32,104,105,103,104,112,32,118,101,99,52,32,118,101,114,116,101,120,95,97,116,116,114,105,98,59,10,108,97,121,111,117,116,40,108,111,99,97,116,105,111,110,61,52,41,32,105,110,32,118,101,99,50,32,117,118,95,105,110,59,10,10,111,117,116,32,118,101,99,50,32,117,118,95,105,110,116,101,114,112,59,10,111,117,116,32,118,101,99,50,32,112,111,115,95,105,110,116,101,114,112,59,10,10,118,111,105,100,32,109,97,105,110,40,41,32,123,10,10,9,117,118,95,105,110,116,101,114,112,32,61,32,117,118,95,105,110,59,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,118,101,114,116,101,120,95,97,116,116,114,105,98,59,10,9,112,111,115,95,105,110,116,101,114,112,46,120,121,61,103,108,95,80,111,115,105,116,105,111,110,46,120,121,59,10,125,10,10, 0}; - - static const int _vertex_code_start=1; - static const char _fragment_code[]={ -10,10,105,110,32,118,101,99,50,32,117,118,95,105,110,116,101,114,112,59,10,105,110,32,118,101,99,50,32,112,111,115,95,105,110,116,101,114,112,59,10,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,115,111,117,114,99,101,95,100,105,102,102,117,115,101,59,32,47,47,116,101,120,117,110,105,116,58,48,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,115,111,117,114,99,101,95,110,111,114,109,97,108,95,114,111,117,103,104,110,101,115,115,59,32,47,47,116,101,120,117,110,105,116,58,49,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,115,111,117,114,99,101,95,100,101,112,116,104,59,32,47,47,116,101,120,117,110,105,116,58,50,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,115,111,117,114,99,101,95,100,105,102,102,117,115,101,95,109,105,112,109,97,112,115,59,32,47,47,116,101,120,117,110,105,116,58,51,10,10,117,110,105,102,111,114,109,32,102,108,111,97,116,32,99,97,109,101,114,97,95,122,95,110,101,97,114,59,10,117,110,105,102,111,114,109,32,102,108,111,97,116,32,99,97,109,101,114,97,95,122,95,102,97,114,59,10,10,117,110,105,102,111,114,109,32,118,101,99,50,32,118,105,101,119,112,111,114,116,95,115,105,122,101,59,10,117,110,105,102,111,114,109,32,118,101,99,50,32,112,105,120,101,108,95,115,105,122,101,59,10,10,117,110,105,102,111,114,109,32,102,108,111,97,116,32,102,105,108,116,101,114,95,109,105,112,109,97,112,95,108,101,118,101,108,115,59,10,10,117,110,105,102,111,114,109,32,109,97,116,52,32,105,110,118,101,114,115,101,95,112,114,111,106,101,99,116,105,111,110,59,10,117,110,105,102,111,114,109,32,109,97,116,52,32,112,114,111,106,101,99,116,105,111,110,59,10,10,117,110,105,102,111,114,109,32,105,110,116,32,102,114,97,109,101,95,105,110,100,101,120,59,10,10,118,101,99,50,32,118,105,101,119,95,116,111,95,115,99,114,101,101,110,40,118,101,99,51,32,118,105,101,119,95,112,111,115,44,111,117,116,32,102,108,111,97,116,32,119,41,32,123,10,32,32,32,32,118,101,99,52,32,112,114,111,106,101,99,116,101,100,32,61,32,112,114,111,106,101,99,116,105,111,110,32,42,32,118,101,99,52,40,118,105,101,119,95,112,111,115,44,32,49,46,48,41,59,10,32,32,32,32,112,114,111,106,101,99,116,101,100,46,120,121,122,32,47,61,32,112,114,111,106,101,99,116,101,100,46,119,59,10,32,32,32,32,112,114,111,106,101,99,116,101,100,46,120,121,32,61,32,112,114,111,106,101,99,116,101,100,46,120,121,32,42,32,48,46,53,32,43,32,48,46,53,59,10,32,32,32,32,119,61,112,114,111,106,101,99,116,101,100,46,119,59,10,32,32,32,32,114,101,116,117,114,110,32,112,114,111,106,101,99,116,101,100,46,120,121,59,10,125,10,10,10,108,97,121,111,117,116,40,108,111,99,97,116,105,111,110,32,61,32,48,41,32,111,117,116,32,118,101,99,52,32,102,114,97,103,95,99,111,108,111,114,59,10,10,35,100,101,102,105,110,101,32,78,85,77,95,82,65,89,68,73,82,95,82,69,84,82,73,69,83,32,51,10,10,47,47,102,114,111,109,32,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,116,111,98,115,112,114,44,32,105,102,32,105,116,32,119,111,114,107,115,32,102,111,114,32,121,111,117,44,32,100,117,100,101,46,46,10,118,101,99,51,32,114,97,110,100,95,114,103,98,40,118,101,99,50,32,99,111,41,32,123,10,32,32,32,32,114,101,116,117,114,110,32,97,98,115,40,102,114,97,99,116,40,115,105,110,40,100,111,116,40,99,111,46,120,121,44,32,118,101,99,50,40,51,52,46,52,56,51,53,44,32,56,57,46,54,51,55,50,41,41,41,32,42,10,9,118,101,99,51,40,50,57,49,53,54,46,52,55,54,53,44,32,51,56,50,55,51,46,53,54,51,57,51,44,32,52,55,56,52,51,46,55,53,52,54,56,41,41,41,32,42,32,50,32,45,32,49,59,10,125,10,10,35,100,101,102,105,110,101,32,77,95,80,73,32,51,46,49,52,49,53,57,50,54,53,51,53,57,10,10,118,101,99,51,32,105,109,112,111,114,116,97,110,99,101,95,115,97,109,112,108,101,95,103,103,120,40,118,101,99,50,32,120,105,44,32,102,108,111,97,116,32,114,111,117,103,104,110,101,115,115,41,10,123,10,32,32,32,32,102,108,111,97,116,32,114,95,115,113,117,97,114,101,32,61,32,114,111,117,103,104,110,101,115,115,32,42,32,114,111,117,103,104,110,101,115,115,59,10,32,32,32,32,102,108,111,97,116,32,112,104,105,32,61,32,50,32,42,32,77,95,80,73,32,42,32,120,105,46,120,59,10,32,32,32,32,102,108,111,97,116,32,99,111,115,95,116,104,101,116,97,32,61,32,115,113,114,116,40,40,49,32,45,32,120,105,46,121,41,32,47,32,40,49,32,43,32,40,114,95,115,113,117,97,114,101,32,42,32,114,95,115,113,117,97,114,101,32,45,32,49,41,32,42,32,120,105,46,121,41,41,59,10,32,32,32,32,102,108,111,97,116,32,115,105,110,95,116,104,101,116,97,32,61,32,115,113,114,116,40,49,32,45,32,99,111,115,95,116,104,101,116,97,32,42,32,99,111,115,95,116,104,101,116,97,41,59,10,10,32,32,32,32,114,101,116,117,114,110,32,118,101,99,51,40,115,105,110,95,116,104,101,116,97,32,42,32,99,111,115,40,112,104,105,41,44,32,115,105,110,95,116,104,101,116,97,32,42,32,115,105,110,40,112,104,105,41,44,32,99,111,115,95,116,104,101,116,97,41,59,10,125,10,10,118,111,105,100,32,102,105,110,100,95,97,114,98,105,116,114,97,114,121,95,116,97,110,103,101,110,116,40,118,101,99,51,32,110,111,114,109,97,108,44,32,111,117,116,32,118,101,99,51,32,116,97,110,103,101,110,116,44,32,111,117,116,32,118,101,99,51,32,98,105,116,97,110,103,101,110,116,41,32,123,10,32,32,32,32,118,101,99,51,32,118,48,32,61,32,97,98,115,40,110,111,114,109,97,108,46,122,41,32,60,32,48,46,57,57,57,32,63,32,118,101,99,51,40,48,46,48,44,32,48,46,48,44,32,49,46,48,41,32,58,32,118,101,99,51,40,48,46,48,44,32,49,46,48,44,32,48,46,48,41,59,10,32,32,32,32,116,97,110,103,101,110,116,32,61,32,110,111,114,109,97,108,105,122,101,40,99,114,111,115,115,40,118,48,44,32,110,111,114,109,97,108,41,41,59,10,32,32,32,32,98,105,116,97,110,103,101,110,116,32,61,32,110,111,114,109,97,108,105,122,101,40,99,114,111,115,115,40,116,97,110,103,101,110,116,44,32,110,111,114,109,97,108,41,41,59,10,125,10,10,98,111,111,108,32,112,111,105,110,116,95,98,101,116,119,101,101,110,95,112,108,97,110,101,115,40,102,108,111,97,116,32,122,44,32,102,108,111,97,116,32,122,95,97,44,32,102,108,111,97,116,32,122,95,98,44,32,102,108,111,97,116,32,116,114,97,99,101,95,108,101,110,103,116,104,44,32,111,117,116,32,98,111,111,108,32,104,105,116,95,102,97,99,116,111,114,41,32,123,10,10,32,32,32,32,47,47,32,84,104,105,115,32,116,114,97,99,101,115,32,99,111,114,114,101,99,116,44,32,98,117,116,32,108,111,111,107,115,32,119,101,105,114,100,32,98,101,99,97,117,115,101,32,103,97,112,115,32,97,114,101,32,110,111,116,32,102,105,108,108,101,100,10,32,32,32,32,47,47,32,114,101,116,117,114,110,32,122,32,43,32,104,105,116,95,116,111,108,101,114,97,110,99,101,95,119,115,32,62,61,32,109,105,110,40,122,95,97,44,32,122,95,98,41,32,45,32,48,46,48,48,48,49,53,32,38,38,32,122,32,45,32,104,105,116,95,116,111,108,101,114,97,110,99,101,95,119,115,32,60,61,32,109,97,120,40,122,95,97,44,32,122,95,98,41,59,10,10,32,32,32,32,104,105,116,95,102,97,99,116,111,114,32,61,32,102,97,108,115,101,59,10,10,32,32,32,32,47,47,32,84,104,105,115,32,116,114,97,99,101,115,32,34,105,110,99,111,114,114,101,99,116,34,44,32,98,117,116,32,108,111,111,107,115,32,98,101,116,116,101,114,32,98,101,99,97,117,115,101,32,103,97,112,115,32,97,114,101,32,103,101,116,116,105,110,103,32,102,105,108,108,101,100,32,116,104,101,110,10,32,32,32,32,102,108,111,97,116,32,104,105,116,95,116,111,108,101,114,97,110,99,101,95,119,115,61,48,46,48,48,48,49,59,10,32,32,32,32,99,111,110,115,116,32,102,108,111,97,116,32,104,105,116,95,116,111,108,101,114,97,110,99,101,95,98,97,99,107,102,97,99,101,32,61,32,48,46,48,48,48,48,48,49,59,10,32,32,32,32,105,102,32,40,122,32,45,32,104,105,116,95,116,111,108,101,114,97,110,99,101,95,119,115,32,42,32,116,114,97,99,101,95,108,101,110,103,116,104,32,60,61,32,109,97,120,40,122,95,97,44,32,122,95,98,41,41,32,123,10,10,32,32,32,32,32,105,102,32,40,116,114,117,101,41,32,123,10,9,32,32,32,32,104,105,116,95,102,97,99,116,111,114,32,61,32,40,122,32,43,32,104,105,116,95,116,111,108,101,114,97,110,99,101,95,119,115,32,42,32,116,114,97,99,101,95,108,101,110,103,116,104,41,32,62,61,10,9,9,9,32,32,32,32,109,105,110,40,122,95,97,44,32,122,95,98,41,32,45,32,104,105,116,95,116,111,108,101,114,97,110,99,101,95,98,97,99,107,102,97,99,101,59,10,32,32,32,32,32,125,32,101,108,115,101,32,123,10,9,32,32,32,32,104,105,116,95,102,97,99,116,111,114,32,61,32,116,114,117,101,59,10,32,32,32,32,32,32,125,10,10,9,114,101,116,117,114,110,32,116,114,117,101,59,10,32,32,32,32,125,10,10,32,32,32,32,114,101,116,117,114,110,32,102,97,108,115,101,59,10,125,10,10,98,111,111,108,32,111,117,116,95,111,102,95,115,99,114,101,101,110,40,118,101,99,50,32,116,99,111,111,114,100,41,32,123,10,32,32,32,32,114,101,116,117,114,110,32,116,99,111,111,114,100,46,120,32,60,32,48,46,48,32,124,124,32,116,99,111,111,114,100,46,121,32,60,32,48,46,48,32,124,124,32,116,99,111,111,114,100,46,120,32,62,32,49,46,48,32,124,124,32,116,99,111,111,114,100,46,121,32,62,32,49,46,48,59,10,125,10,10,102,108,111,97,116,32,100,105,115,116,97,110,99,101,83,113,117,97,114,101,100,40,118,101,99,50,32,97,44,32,118,101,99,50,32,98,41,32,123,32,97,32,45,61,32,98,59,32,114,101,116,117,114,110,32,100,111,116,40,97,44,32,97,41,59,32,125,10,10,118,101,99,51,32,99,111,109,112,117,116,101,67,108,105,112,73,110,102,111,40,102,108,111,97,116,32,122,110,44,32,102,108,111,97,116,32,122,102,41,32,123,10,32,114,101,116,117,114,110,32,118,101,99,51,40,122,110,32,32,42,32,122,102,44,32,122,110,32,45,32,122,102,44,32,122,102,41,59,10,10,125,10,10,10,102,108,111,97,116,32,114,101,99,111,110,115,116,114,117,99,116,67,83,90,40,102,108,111,97,116,32,100,101,112,116,104,66,117,102,102,101,114,86,97,108,117,101,44,32,118,101,99,51,32,99,41,32,123,10,32,32,32,32,32,32,114,101,116,117,114,110,32,99,91,48,93,32,47,32,40,100,101,112,116,104,66,117,102,102,101,114,86,97,108,117,101,32,42,32,99,91,49,93,32,43,32,99,91,50,93,41,59,10,125,10,10,10,98,111,111,108,32,116,114,97,99,101,83,99,114,101,101,110,83,112,97,99,101,82,97,121,49,10,32,32,32,40,118,101,99,51,32,32,32,32,32,32,32,32,32,32,99,115,79,114,105,103,105,110,44,10,32,32,32,32,118,101,99,51,32,32,32,32,32,32,32,32,32,99,115,68,105,114,101,99,116,105,111,110,44,10,32,32,32,32,109,97,116,52,120,52,32,32,32,32,32,32,32,32,32,32,112,114,111,106,101,99,116,84,111,80,105,120,101,108,77,97,116,114,105,120,44,10,32,32,32,32,115,97,109,112,108,101,114,50,68,32,32,32,32,32,32,32,99,115,90,66,117,102,102,101,114,44,10,32,32,32,32,118,101,99,50,32,32,32,32,32,32,32,32,32,32,99,115,90,66,117,102,102,101,114,83,105,122,101,44,10,32,32,32,32,102,108,111,97,116,32,32,32,32,32,32,32,32,32,32,32,99,115,90,84,104,105,99,107,110,101,115,115,44,10,32,32,32,32,99,111,110,115,116,32,105,110,32,98,111,111,108,32,32,32,99,115,90,66,117,102,102,101,114,73,115,72,121,112,101,114,98,111,108,105,99,44,10,32,32,32,32,118,101,99,51,32,32,32,32,32,32,32,32,32,32,99,108,105,112,73,110,102,111,44,10,32,32,32,32,102,108,111,97,116,32,32,32,32,32,32,32,32,32,32,32,110,101,97,114,80,108,97,110,101,90,44,10,32,32,32,32,102,108,111,97,116,9,9,9,115,116,114,105,100,101,44,10,32,32,32,32,102,108,111,97,116,32,32,32,32,32,32,32,32,32,32,32,106,105,116,116,101,114,70,114,97,99,116,105,111,110,44,10,32,32,32,32,102,108,111,97,116,32,32,32,32,32,32,32,32,32,32,32,109,97,120,83,116,101,112,115,44,10,32,32,32,32,105,110,32,102,108,111,97,116,32,32,32,32,32,32,32,32,109,97,120,82,97,121,84,114,97,99,101,68,105,115,116,97,110,99,101,44,10,32,32,32,32,111,117,116,32,118,101,99,50,32,32,32,32,32,32,104,105,116,80,105,120,101,108,44,10,32,32,32,32,111,117,116,32,105,110,116,32,32,32,32,32,32,32,32,32,119,104,105,99,104,44,10,9,111,117,116,32,118,101,99,51,9,9,99,115,72,105,116,80,111,105,110,116,41,32,123,10,10,9,47,47,32,67,108,105,112,32,114,97,121,32,116,111,32,97,32,110,101,97,114,32,112,108,97,110,101,32,105,110,32,51,68,32,40,100,111,101,115,110,39,116,32,104,97,118,101,32,116,111,32,98,101,32,42,116,104,101,42,32,110,101,97,114,32,112,108,97,110,101,44,32,97,108,116,104,111,117,103,104,32,116,104,97,116,32,119,111,117,108,100,32,98,101,32,97,32,103,111,111,100,32,105,100,101,97,41,10,9,102,108,111,97,116,32,114,97,121,76,101,110,103,116,104,32,61,32,40,40,99,115,79,114,105,103,105,110,46,122,32,43,32,99,115,68,105,114,101,99,116,105,111,110,46,122,32,42,32,109,97,120,82,97,121,84,114,97,99,101,68,105,115,116,97,110,99,101,41,32,62,32,110,101,97,114,80,108,97,110,101,90,41,32,63,10,9,9,9,9,40,110,101,97,114,80,108,97,110,101,90,32,45,32,99,115,79,114,105,103,105,110,46,122,41,32,47,32,99,115,68,105,114,101,99,116,105,111,110,46,122,32,58,10,9,9,9,9,109,97,120,82,97,121,84,114,97,99,101,68,105,115,116,97,110,99,101,59,10,9,118,101,99,51,32,99,115,69,110,100,80,111,105,110,116,32,61,32,99,115,68,105,114,101,99,116,105,111,110,32,42,32,114,97,121,76,101,110,103,116,104,32,43,32,99,115,79,114,105,103,105,110,59,10,10,9,47,47,32,80,114,111,106,101,99,116,32,105,110,116,111,32,115,99,114,101,101,110,32,115,112,97,99,101,10,9,118,101,99,52,32,72,48,32,61,32,112,114,111,106,101,99,116,84,111,80,105,120,101,108,77,97,116,114,105,120,32,42,32,118,101,99,52,40,99,115,79,114,105,103,105,110,44,32,49,46,48,41,59,10,9,118,101,99,52,32,72,49,32,61,32,112,114,111,106,101,99,116,84,111,80,105,120,101,108,77,97,116,114,105,120,32,42,32,118,101,99,52,40,99,115,69,110,100,80,111,105,110,116,44,32,49,46,48,41,59,10,10,9,47,47,32,84,104,101,114,101,32,97,114,101,32,97,32,108,111,116,32,111,102,32,100,105,118,105,115,105,111,110,115,32,98,121,32,119,32,116,104,97,116,32,99,97,110,32,98,101,32,116,117,114,110,101,100,32,105,110,116,111,32,109,117,108,116,105,112,108,105,99,97,116,105,111,110,115,10,9,47,47,32,97,116,32,115,111,109,101,32,109,105,110,111,114,32,112,114,101,99,105,115,105,111,110,32,108,111,115,115,46,46,46,97,110,100,32,119,101,32,110,101,101,100,32,116,111,32,105,110,116,101,114,112,111,108,97,116,101,32,116,104,101,115,101,32,49,47,119,32,118,97,108,117,101,115,10,9,47,47,32,97,110,121,119,97,121,46,10,9,47,47,10,9,47,47,32,66,101,99,97,117,115,101,32,116,104,101,32,99,97,108,108,101,114,32,119,97,115,32,114,101,113,117,105,114,101,100,32,116,111,32,99,108,105,112,32,116,111,32,116,104,101,32,110,101,97,114,32,112,108,97,110,101,44,10,9,47,47,32,116,104,105,115,32,104,111,109,111,103,101,110,101,111,117,115,32,100,105,118,105,115,105,111,110,32,40,112,114,111,106,101,99,116,105,110,103,32,102,114,111,109,32,52,68,32,116,111,32,50,68,41,32,105,115,32,103,117,97,114,97,110,116,101,101,100,10,9,47,47,32,116,111,32,115,117,99,99,101,101,100,46,10,9,102,108,111,97,116,32,107,48,32,61,32,49,46,48,32,47,32,72,48,46,119,59,10,9,102,108,111,97,116,32,107,49,32,61,32,49,46,48,32,47,32,72,49,46,119,59,10,10,9,47,47,32,83,119,105,116,99,104,32,116,104,101,32,111,114,105,103,105,110,97,108,32,112,111,105,110,116,115,32,116,111,32,118,97,108,117,101,115,32,116,104,97,116,32,105,110,116,101,114,112,111,108,97,116,101,32,108,105,110,101,97,114,108,121,32,105,110,32,50,68,10,9,118,101,99,51,32,81,48,32,61,32,99,115,79,114,105,103,105,110,32,42,32,107,48,59,10,9,118,101,99,51,32,81,49,32,61,32,99,115,69,110,100,80,111,105,110,116,32,42,32,107,49,59,10,10,9,47,47,32,83,99,114,101,101,110,45,115,112,97,99,101,32,101,110,100,112,111,105,110,116,115,10,9,118,101,99,50,32,80,48,32,61,32,72,48,46,120,121,32,42,32,107,48,59,10,9,118,101,99,50,32,80,49,32,61,32,72,49,46,120,121,32,42,32,107,49,59,10,10,9,47,47,32,91,79,112,116,105,111,110,97,108,32,99,108,105,112,112,105,110,103,32,116,111,32,102,114,117,115,116,117,109,32,115,105,100,101,115,32,104,101,114,101,93,10,10,9,47,47,32,73,110,105,116,105,97,108,105,122,101,32,116,111,32,111,102,102,32,115,99,114,101,101,110,10,9,104,105,116,80,105,120,101,108,32,61,32,118,101,99,50,40,45,49,46,48,44,32,45,49,46,48,41,59,10,9,119,104,105,99,104,32,61,32,48,59,32,47,47,32,79,110,108,121,32,111,110,101,32,108,97,121,101,114,10,10,9,47,47,32,73,102,32,116,104,101,32,108,105,110,101,32,105,115,32,100,101,103,101,110,101,114,97,116,101,44,32,109,97,107,101,32,105,116,32,99,111,118,101,114,32,97,116,32,108,101,97,115,116,32,111,110,101,32,112,105,120,101,108,10,9,47,47,32,116,111,32,97,118,111,105,100,32,104,97,110,100,108,105,110,103,32,122,101,114,111,45,112,105,120,101,108,32,101,120,116,101,110,116,32,97,115,32,97,32,115,112,101,99,105,97,108,32,99,97,115,101,32,108,97,116,101,114,10,9,80,49,32,43,61,32,118,101,99,50,40,40,100,105,115,116,97,110,99,101,83,113,117,97,114,101,100,40,80,48,44,32,80,49,41,32,60,32,48,46,48,48,48,49,41,32,63,32,48,46,48,49,32,58,32,48,46,48,41,59,10,10,9,118,101,99,50,32,100,101,108,116,97,32,61,32,80,49,32,45,32,80,48,59,10,10,9,47,47,32,80,101,114,109,117,116,101,32,115,111,32,116,104,97,116,32,116,104,101,32,112,114,105,109,97,114,121,32,105,116,101,114,97,116,105,111,110,32,105,115,32,105,110,32,120,32,116,111,32,114,101,100,117,99,101,10,9,47,47,32,108,97,114,103,101,32,98,114,97,110,99,104,101,115,32,108,97,116,101,114,10,9,98,111,111,108,32,112,101,114,109,117,116,101,32,61,32,102,97,108,115,101,59,10,9,105,102,32,40,97,98,115,40,100,101,108,116,97,46,120,41,32,60,32,97,98,115,40,100,101,108,116,97,46,121,41,41,32,123,10,9,9,47,47,32,77,111,114,101,45,118,101,114,116,105,99,97,108,32,108,105,110,101,46,32,67,114,101,97,116,101,32,97,32,112,101,114,109,117,116,97,116,105,111,110,32,116,104,97,116,32,115,119,97,112,115,32,120,32,97,110,100,32,121,32,105,110,32,116,104,101,32,111,117,116,112,117,116,10,9,9,112,101,114,109,117,116,101,32,61,32,116,114,117,101,59,10,10,9,9,47,47,32,68,105,114,101,99,116,108,121,32,115,119,105,122,122,108,101,32,116,104,101,32,105,110,112,117,116,115,10,9,9,100,101,108,116,97,32,61,32,100,101,108,116,97,46,121,120,59,10,9,9,80,49,32,61,32,80,49,46,121,120,59,10,9,9,80,48,32,61,32,80,48,46,121,120,59,10,9,125,10,10,9,47,47,32,70,114,111,109,32,110,111,119,32,111,110,44,32,34,120,34,32,105,115,32,116,104,101,32,112,114,105,109,97,114,121,32,105,116,101,114,97,116,105,111,110,32,100,105,114,101,99,116,105,111,110,32,97,110,100,32,34,121,34,32,105,115,32,116,104,101,32,115,101,99,111,110,100,97,114,121,32,111,110,101,10,10,9,102,108,111,97,116,32,115,116,101,112,68,105,114,101,99,116,105,111,110,32,61,32,115,105,103,110,40,100,101,108,116,97,46,120,41,59,10,9,102,108,111,97,116,32,105,110,118,100,120,32,61,32,115,116,101,112,68,105,114,101,99,116,105,111,110,32,47,32,100,101,108,116,97,46,120,59,10,9,118,101,99,50,32,100,80,32,61,32,118,101,99,50,40,115,116,101,112,68,105,114,101,99,116,105,111,110,44,32,105,110,118,100,120,32,42,32,100,101,108,116,97,46,121,41,59,10,10,9,47,47,32,84,114,97,99,107,32,116,104,101,32,100,101,114,105,118,97,116,105,118,101,115,32,111,102,32,81,32,97,110,100,32,107,10,9,118,101,99,51,32,100,81,32,61,32,40,81,49,32,45,32,81,48,41,32,42,32,105,110,118,100,120,59,10,9,102,108,111,97,116,32,32,32,100,107,32,61,32,40,107,49,32,45,32,107,48,41,32,42,32,105,110,118,100,120,59,10,10,9,47,47,32,83,99,97,108,101,32,100,101,114,105,118,97,116,105,118,101,115,32,98,121,32,116,104,101,32,100,101,115,105,114,101,100,32,112,105,120,101,108,32,115,116,114,105,100,101,10,9,100,80,32,42,61,32,115,116,114,105,100,101,59,32,100,81,32,42,61,32,115,116,114,105,100,101,59,32,100,107,32,42,61,32,115,116,114,105,100,101,59,10,10,9,47,47,32,79,102,102,115,101,116,32,116,104,101,32,115,116,97,114,116,105,110,103,32,118,97,108,117,101,115,32,98,121,32,116,104,101,32,106,105,116,116,101,114,32,102,114,97,99,116,105,111,110,10,9,80,48,32,43,61,32,100,80,32,42,32,106,105,116,116,101,114,70,114,97,99,116,105,111,110,59,32,81,48,32,43,61,32,100,81,32,42,32,106,105,116,116,101,114,70,114,97,99,116,105,111,110,59,32,107,48,32,43,61,32,100,107,32,42,32,106,105,116,116,101,114,70,114,97,99,116,105,111,110,59,10,10,9,47,47,32,83,108,105,100,101,32,80,32,102,114,111,109,32,80,48,32,116,111,32,80,49,44,32,40,110,111,119,45,104,111,109,111,103,101,110,101,111,117,115,41,32,81,32,102,114,111,109,32,81,48,32,116,111,32,81,49,44,32,97,110,100,32,107,32,102,114,111,109,32,107,48,32,116,111,32,107,49,10,9,118,101,99,51,32,81,32,61,32,81,48,59,10,9,102,108,111,97,116,32,32,107,32,61,32,107,48,59,10,10,9,47,47,32,87,101,32,116,114,97,99,107,32,116,104,101,32,114,97,121,32,100,101,112,116,104,32,97,116,32,43,47,45,32,49,47,50,32,112,105,120,101,108,32,116,111,32,116,114,101,97,116,32,112,105,120,101,108,115,32,97,115,32,99,108,105,112,45,115,112,97,99,101,32,115,111,108,105,100,10,9,47,47,32,118,111,120,101,108,115,46,32,66,101,99,97,117,115,101,32,116,104,101,32,100,101,112,116,104,32,97,116,32,45,49,47,50,32,102,111,114,32,97,32,103,105,118,101,110,32,112,105,120,101,108,32,119,105,108,108,32,98,101,32,116,104,101,32,115,97,109,101,32,97,115,32,97,116,10,9,47,47,32,43,49,47,50,32,102,111,114,32,116,104,101,32,112,114,101,118,105,111,117,115,32,105,116,101,114,97,116,105,111,110,44,32,119,101,32,97,99,116,117,97,108,108,121,32,111,110,108,121,32,104,97,118,101,32,116,111,32,99,111,109,112,117,116,101,32,111,110,101,32,118,97,108,117,101,10,9,47,47,32,112,101,114,32,105,116,101,114,97,116,105,111,110,46,10,9,102,108,111,97,116,32,112,114,101,118,90,77,97,120,69,115,116,105,109,97,116,101,32,61,32,99,115,79,114,105,103,105,110,46,122,59,10,9,102,108,111,97,116,32,115,116,101,112,67,111,117,110,116,32,61,32,48,46,48,59,10,9,102,108,111,97,116,32,114,97,121,90,77,97,120,32,61,32,112,114,101,118,90,77,97,120,69,115,116,105,109,97,116,101,44,32,114,97,121,90,77,105,110,32,61,32,112,114,101,118,90,77,97,120,69,115,116,105,109,97,116,101,59,10,9,102,108,111,97,116,32,115,99,101,110,101,90,77,97,120,32,61,32,114,97,121,90,77,97,120,32,43,32,49,101,52,59,10,10,9,47,47,32,80,49,46,120,32,105,115,32,110,101,118,101,114,32,109,111,100,105,102,105,101,100,32,97,102,116,101,114,32,116,104,105,115,32,112,111,105,110,116,44,32,115,111,32,112,114,101,45,115,99,97,108,101,32,105,116,32,98,121,10,9,47,47,32,116,104,101,32,115,116,101,112,32,100,105,114,101,99,116,105,111,110,32,102,111,114,32,97,32,115,105,103,110,101,100,32,99,111,109,112,97,114,105,115,111,110,10,9,102,108,111,97,116,32,101,110,100,32,61,32,80,49,46,120,32,42,32,115,116,101,112,68,105,114,101,99,116,105,111,110,59,10,10,9,47,47,32,87,101,32,111,110,108,121,32,97,100,118,97,110,99,101,32,116,104,101,32,122,32,102,105,101,108,100,32,111,102,32,81,32,105,110,32,116,104,101,32,105,110,110,101,114,32,108,111,111,112,44,32,115,105,110,99,101,10,9,47,47,32,81,46,120,121,32,105,115,32,110,101,118,101,114,32,117,115,101,100,32,117,110,116,105,108,32,97,102,116,101,114,32,116,104,101,32,108,111,111,112,32,116,101,114,109,105,110,97,116,101,115,46,10,10,10,9,102,111,114,32,40,118,101,99,50,32,80,32,61,32,80,48,59,10,9,32,32,32,32,32,40,40,80,46,120,32,42,32,115,116,101,112,68,105,114,101,99,116,105,111,110,41,32,60,61,32,101,110,100,41,32,38,38,10,9,32,32,32,32,32,40,115,116,101,112,67,111,117,110,116,32,60,32,109,97,120,83,116,101,112,115,41,32,38,38,10,9,32,32,32,32,32,40,40,114,97,121,90,77,97,120,32,60,32,115,99,101,110,101,90,77,97,120,32,45,32,99,115,90,84,104,105,99,107,110,101,115,115,41,32,124,124,10,9,32,32,32,32,32,32,40,114,97,121,90,77,105,110,32,62,32,115,99,101,110,101,90,77,97,120,41,41,32,38,38,10,9,32,32,32,32,32,40,115,99,101,110,101,90,77,97,120,32,33,61,32,48,46,48,41,59,10,9,32,32,32,32,32,80,32,43,61,32,100,80,44,32,81,46,122,32,43,61,32,100,81,46,122,44,32,107,32,43,61,32,100,107,44,32,115,116,101,112,67,111,117,110,116,32,43,61,32,49,46,48,41,32,123,10,10,9,9,104,105,116,80,105,120,101,108,32,61,32,112,101,114,109,117,116,101,32,63,32,80,46,121,120,32,58,32,80,59,10,10,9,9,47,47,32,84,104,101,32,100,101,112,116,104,32,114,97,110,103,101,32,116,104,97,116,32,116,104,101,32,114,97,121,32,99,111,118,101,114,115,32,119,105,116,104,105,110,32,116,104,105,115,32,108,111,111,112,10,9,9,47,47,32,105,116,101,114,97,116,105,111,110,46,32,32,65,115,115,117,109,101,32,116,104,97,116,32,116,104,101,32,114,97,121,32,105,115,32,109,111,118,105,110,103,32,105,110,32,105,110,99,114,101,97,115,105,110,103,32,122,10,9,9,47,47,32,97,110,100,32,115,119,97,112,32,105,102,32,98,97,99,107,119,97,114,100,115,46,32,32,66,101,99,97,117,115,101,32,111,110,101,32,101,110,100,32,111,102,32,116,104,101,32,105,110,116,101,114,118,97,108,32,105,115,10,9,9,47,47,32,115,104,97,114,101,100,32,98,101,116,119,101,101,110,32,97,100,106,97,99,101,110,116,32,105,116,101,114,97,116,105,111,110,115,44,32,119,101,32,116,114,97,99,107,32,116,104,101,32,112,114,101,118,105,111,117,115,10,9,9,47,47,32,118,97,108,117,101,32,97,110,100,32,116,104,101,110,32,115,119,97,112,32,97,115,32,110,101,101,100,101,100,32,116,111,32,101,110,115,117,114,101,32,99,111,114,114,101,99,116,32,111,114,100,101,114,105,110,103,10,9,9,114,97,121,90,77,105,110,32,61,32,112,114,101,118,90,77,97,120,69,115,116,105,109,97,116,101,59,10,10,9,9,47,47,32,67,111,109,112,117,116,101,32,116,104,101,32,118,97,108,117,101,32,97,116,32,49,47,50,32,112,105,120,101,108,32,105,110,116,111,32,116,104,101,32,102,117,116,117,114,101,10,9,9,114,97,121,90,77,97,120,32,61,32,40,100,81,46,122,32,42,32,48,46,53,32,43,32,81,46,122,41,32,47,32,40,100,107,32,42,32,48,46,53,32,43,32,107,41,59,10,9,9,112,114,101,118,90,77,97,120,69,115,116,105,109,97,116,101,32,61,32,114,97,121,90,77,97,120,59,10,9,9,105,102,32,40,114,97,121,90,77,105,110,32,62,32,114,97,121,90,77,97,120,41,32,123,10,9,9,9,102,108,111,97,116,32,97,117,120,32,61,32,114,97,121,90,77,105,110,59,10,9,9,9,114,97,121,90,77,105,110,61,114,97,121,90,77,97,120,59,10,9,9,9,114,97,121,90,77,97,120,61,97,117,120,59,10,10,9,9,125,10,10,10,9,9,47,47,32,67,97,109,101,114,97,45,115,112,97,99,101,32,122,32,111,102,32,116,104,101,32,98,97,99,107,103,114,111,117,110,100,10,9,9,115,99,101,110,101,90,77,97,120,32,61,32,116,101,120,101,108,70,101,116,99,104,40,99,115,90,66,117,102,102,101,114,44,32,105,118,101,99,50,40,104,105,116,80,105,120,101,108,41,44,32,48,41,46,114,32,42,32,50,46,48,32,45,32,49,46,48,59,10,10,9,9,47,47,32,84,104,105,115,32,99,111,109,112,105,108,101,115,32,97,119,97,121,32,119,104,101,110,32,99,115,90,66,117,102,102,101,114,73,115,72,121,112,101,114,98,111,108,105,99,32,61,32,102,97,108,115,101,10,9,9,47,42,105,102,32,40,99,115,90,66,117,102,102,101,114,73,115,72,121,112,101,114,98,111,108,105,99,41,32,123,10,9,9,9,115,99,101,110,101,90,77,97,120,32,61,32,114,101,99,111,110,115,116,114,117,99,116,67,83,90,40,115,99,101,110,101,90,77,97,120,44,32,99,108,105,112,73,110,102,111,41,59,10,9,9,125,42,47,10,9,9,115,99,101,110,101,90,77,97,120,32,61,32,50,46,48,32,42,32,99,97,109,101,114,97,95,122,95,110,101,97,114,32,42,32,99,97,109,101,114,97,95,122,95,102,97,114,32,47,32,40,99,97,109,101,114,97,95,122,95,102,97,114,32,43,32,99,97,109,101,114,97,95,122,95,110,101,97,114,32,45,32,115,99,101,110,101,90,77,97,120,32,42,32,40,99,97,109,101,114,97,95,122,95,102,97,114,32,45,32,99,97,109,101,114,97,95,122,95,110,101,97,114,41,41,59,10,9,9,115,99,101,110,101,90,77,97,120,32,61,32,45,115,99,101,110,101,90,77,97,120,59,10,10,10,10,9,125,32,47,47,32,112,105,120,101,108,32,111,110,32,114,97,121,10,10,10,10,9,81,46,120,121,32,43,61,32,100,81,46,120,121,32,42,32,115,116,101,112,67,111,117,110,116,59,10,9,99,115,72,105,116,80,111,105,110,116,32,61,32,81,32,42,32,40,49,46,48,32,47,32,107,41,59,10,10,9,47,47,32,77,97,116,99,104,101,115,32,116,104,101,32,110,101,119,32,108,111,111,112,32,99,111,110,100,105,116,105,111,110,58,10,9,114,101,116,117,114,110,32,40,114,97,121,90,77,97,120,32,62,61,32,115,99,101,110,101,90,77,97,120,32,45,32,99,115,90,84,104,105,99,107,110,101,115,115,41,32,38,38,32,40,114,97,121,90,77,105,110,32,60,61,32,115,99,101,110,101,90,77,97,120,41,59,10,125,10,10,118,111,105,100,32,115,119,97,112,102,40,105,110,111,117,116,32,102,108,111,97,116,32,97,44,105,110,111,117,116,32,102,108,111,97,116,32,98,41,32,123,10,9,102,108,111,97,116,32,97,117,120,61,97,59,10,9,97,61,98,59,10,9,98,61,97,117,120,59,10,125,10,102,108,111,97,116,32,114,97,110,100,40,118,101,99,50,32,99,111,41,123,10,32,32,32,32,114,101,116,117,114,110,32,102,114,97,99,116,40,115,105,110,40,100,111,116,40,99,111,46,120,121,32,44,118,101,99,50,40,49,50,46,57,56,57,56,44,55,56,46,50,51,51,41,41,41,32,42,32,52,51,55,53,56,46,53,52,53,51,41,59,10,125,10,10,102,108,111,97,116,32,115,112,101,99,117,108,97,114,80,111,119,101,114,84,111,67,111,110,101,65,110,103,108,101,40,102,108,111,97,116,32,115,112,101,99,117,108,97,114,80,111,119,101,114,41,32,123,10,9,102,108,111,97,116,32,101,120,112,111,110,101,110,116,32,61,32,49,46,48,102,32,47,32,40,115,112,101,99,117,108,97,114,80,111,119,101,114,32,43,32,49,46,48,102,41,59,10,9,114,101,116,117,114,110,32,97,99,111,115,40,112,111,119,40,48,46,50,52,52,102,44,32,101,120,112,111,110,101,110,116,41,41,59,10,125,10,10,102,108,111,97,116,32,105,115,111,115,99,101,108,101,115,84,114,105,97,110,103,108,101,79,112,112,111,115,105,116,101,40,102,108,111,97,116,32,97,100,106,97,99,101,110,116,76,101,110,103,116,104,44,32,102,108,111,97,116,32,99,111,110,101,84,104,101,116,97,41,10,123,10,9,47,47,32,115,105,109,112,108,101,32,116,114,105,103,32,97,110,100,32,97,108,103,101,98,114,97,32,45,32,115,111,104,44,32,99,97,104,44,32,116,111,97,32,45,32,116,97,110,40,116,104,101,116,97,41,32,61,32,111,112,112,47,97,100,106,44,32,111,112,112,32,61,32,116,97,110,40,116,104,101,116,97,41,32,42,32,97,100,106,44,32,116,104,101,110,32,109,117,108,116,105,112,108,121,32,42,32,50,46,48,102,32,102,111,114,32,105,115,111,115,99,101,108,101,115,32,116,114,105,97,110,103,108,101,32,98,97,115,101,10,9,114,101,116,117,114,110,32,50,46,48,102,32,42,32,116,97,110,40,99,111,110,101,84,104,101,116,97,41,32,42,32,97,100,106,97,99,101,110,116,76,101,110,103,116,104,59,10,125,10,10,102,108,111,97,116,32,105,115,111,115,99,101,108,101,115,84,114,105,97,110,103,108,101,73,110,82,97,100,105,117,115,40,102,108,111,97,116,32,97,44,32,102,108,111,97,116,32,104,41,10,123,10,9,102,108,111,97,116,32,97,50,32,61,32,97,32,42,32,97,59,10,9,102,108,111,97,116,32,102,104,50,32,61,32,52,46,48,102,32,42,32,104,32,42,32,104,59,10,9,114,101,116,117,114,110,32,40,97,32,42,32,40,115,113,114,116,40,97,50,32,43,32,102,104,50,41,32,45,32,97,41,41,32,47,32,40,52,46,48,102,32,42,32,104,41,59,10,125,10,10,102,108,111,97,116,32,105,115,111,115,99,101,108,101,115,84,114,105,97,110,103,108,101,78,101,120,116,65,100,106,97,99,101,110,116,40,102,108,111,97,116,32,97,100,106,97,99,101,110,116,76,101,110,103,116,104,44,32,102,108,111,97,116,32,105,110,99,105,114,99,108,101,82,97,100,105,117,115,41,10,123,10,9,47,47,32,115,117,98,116,114,97,99,116,32,116,104,101,32,100,105,97,109,101,116,101,114,32,111,102,32,116,104,101,32,105,110,99,105,114,99,108,101,32,116,111,32,103,101,116,32,116,104,101,32,97,100,106,97,99,101,110,116,32,115,105,100,101,32,111,102,32,116,104,101,32,110,101,120,116,32,108,101,118,101,108,32,111,110,32,116,104,101,32,99,111,110,101,10,9,114,101,116,117,114,110,32,97,100,106,97,99,101,110,116,76,101,110,103,116,104,32,45,32,40,105,110,99,105,114,99,108,101,82,97,100,105,117,115,32,42,32,50,46,48,102,41,59,10,125,10,10,118,111,105,100,32,109,97,105,110,40,41,32,123,10,10,10,9,102,108,111,97,116,32,110,117,109,95,115,116,101,112,115,61,54,52,59,10,9,102,108,111,97,116,32,105,110,105,116,105,97,108,95,98,105,97,115,61,48,46,49,59,10,9,102,108,111,97,116,32,104,105,116,95,116,111,108,101,114,97,110,99,101,61,48,46,49,59,10,10,9,47,47,47,47,10,10,9,118,101,99,52,32,100,105,102,102,117,115,101,32,61,32,116,101,120,116,117,114,101,40,32,115,111,117,114,99,101,95,100,105,102,102,117,115,101,44,32,32,117,118,95,105,110,116,101,114,112,32,41,59,10,9,118,101,99,52,32,110,111,114,109,97,108,95,114,111,117,103,104,110,101,115,115,32,61,32,116,101,120,116,117,114,101,40,32,115,111,117,114,99,101,95,110,111,114,109,97,108,95,114,111,117,103,104,110,101,115,115,44,32,117,118,95,105,110,116,101,114,112,41,59,10,10,9,118,101,99,51,32,110,111,114,109,97,108,59,10,10,9,110,111,114,109,97,108,32,61,32,110,111,114,109,97,108,95,114,111,117,103,104,110,101,115,115,46,120,121,122,42,50,46,48,45,49,46,48,59,10,10,9,105,102,32,40,102,97,108,115,101,41,32,123,10,9,32,32,32,32,102,108,111,97,116,32,115,99,97,108,101,32,61,32,49,46,55,55,55,55,59,10,9,32,32,32,32,118,101,99,51,32,110,110,32,61,10,9,9,110,111,114,109,97,108,95,114,111,117,103,104,110,101,115,115,46,120,121,122,42,118,101,99,51,40,50,46,48,42,115,99,97,108,101,44,50,46,48,42,115,99,97,108,101,44,48,46,48,41,32,43,10,9,9,118,101,99,51,40,45,115,99,97,108,101,44,45,115,99,97,108,101,44,49,46,48,41,59,10,9,32,32,32,32,102,108,111,97,116,32,103,32,61,32,50,46,48,32,47,32,100,111,116,40,110,110,46,120,121,122,44,110,110,46,120,121,122,41,59,10,9,32,32,32,32,118,101,99,51,32,110,59,10,9,32,32,32,32,110,46,120,121,32,61,32,103,42,110,110,46,120,121,59,10,9,32,32,32,32,110,46,122,32,61,32,103,45,49,46,48,59,10,9,32,32,32,110,111,114,109,97,108,61,110,59,10,9,125,10,10,9,118,101,99,51,32,116,97,110,103,101,110,116,59,10,9,118,101,99,51,32,98,105,110,111,114,109,97,108,59,10,9,102,105,110,100,95,97,114,98,105,116,114,97,114,121,95,116,97,110,103,101,110,116,40,110,111,114,109,97,108,44,32,116,97,110,103,101,110,116,44,32,98,105,110,111,114,109,97,108,41,59,10,10,9,102,108,111,97,116,32,114,111,117,103,104,110,101,115,115,32,61,32,110,111,114,109,97,108,95,114,111,117,103,104,110,101,115,115,46,119,59,10,10,9,102,108,111,97,116,32,100,101,112,116,104,95,116,101,120,32,61,32,116,101,120,116,117,114,101,40,115,111,117,114,99,101,95,100,101,112,116,104,44,117,118,95,105,110,116,101,114,112,41,46,114,59,10,10,9,118,101,99,52,32,119,111,114,108,100,95,112,111,115,32,61,32,105,110,118,101,114,115,101,95,112,114,111,106,101,99,116,105,111,110,32,42,32,118,101,99,52,40,32,117,118,95,105,110,116,101,114,112,42,50,46,48,45,49,46,48,44,32,100,101,112,116,104,95,116,101,120,42,50,46,48,45,49,46,48,44,32,49,46,48,32,41,59,10,9,118,101,99,51,32,118,101,114,116,101,120,32,61,32,119,111,114,108,100,95,112,111,115,46,120,121,122,47,119,111,114,108,100,95,112,111,115,46,119,59,10,10,9,118,101,99,51,32,118,105,101,119,95,100,105,114,32,61,32,110,111,114,109,97,108,105,122,101,40,118,101,114,116,101,120,41,59,10,9,118,101,99,51,32,114,97,121,95,100,105,114,32,61,32,110,111,114,109,97,108,105,122,101,40,114,101,102,108,101,99,116,40,118,105,101,119,95,100,105,114,44,32,110,111,114,109,97,108,41,41,59,10,10,9,47,47,114,97,121,95,100,105,114,32,61,32,110,111,114,109,97,108,105,122,101,40,118,105,101,119,95,100,105,114,32,45,32,110,111,114,109,97,108,32,42,32,100,111,116,40,110,111,114,109,97,108,44,118,105,101,119,95,100,105,114,41,32,42,32,50,46,48,41,59,10,10,9,47,47,114,97,121,95,100,105,114,32,61,32,110,111,114,109,97,108,105,122,101,40,118,101,99,51,40,49,44,49,44,45,49,41,41,59,10,10,10,9,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,10,10,10,9,47,47,109,97,107,101,32,114,97,121,32,108,101,110,103,116,104,32,97,110,100,32,99,108,105,112,32,105,116,32,97,103,97,105,110,115,116,32,116,104,101,32,110,101,97,114,32,112,108,97,110,101,32,40,100,111,110,39,116,32,119,97,110,116,32,116,111,32,116,114,97,99,101,32,98,101,121,111,110,100,32,118,105,115,105,98,108,101,41,10,9,102,108,111,97,116,32,114,97,121,95,108,101,110,32,61,32,40,118,101,114,116,101,120,46,122,32,43,32,114,97,121,95,100,105,114,46,122,32,42,32,99,97,109,101,114,97,95,122,95,102,97,114,41,32,62,32,45,99,97,109,101,114,97,95,122,95,110,101,97,114,32,63,32,40,45,99,97,109,101,114,97,95,122,95,110,101,97,114,32,45,32,118,101,114,116,101,120,46,122,41,32,47,32,114,97,121,95,100,105,114,46,122,32,58,32,99,97,109,101,114,97,95,122,95,102,97,114,59,10,9,118,101,99,51,32,114,97,121,95,101,110,100,32,61,32,118,101,114,116,101,120,32,43,32,114,97,121,95,100,105,114,42,114,97,121,95,108,101,110,59,10,10,9,102,108,111,97,116,32,119,95,98,101,103,105,110,59,10,9,118,101,99,50,32,118,112,95,108,105,110,101,95,98,101,103,105,110,32,61,32,118,105,101,119,95,116,111,95,115,99,114,101,101,110,40,118,101,114,116,101,120,44,119,95,98,101,103,105,110,41,59,10,9,102,108,111,97,116,32,119,95,101,110,100,59,10,9,118,101,99,50,32,118,112,95,108,105,110,101,95,101,110,100,32,61,32,118,105,101,119,95,116,111,95,115,99,114,101,101,110,40,32,114,97,121,95,101,110,100,44,32,119,95,101,110,100,41,59,10,9,118,101,99,50,32,118,112,95,108,105,110,101,95,100,105,114,32,61,32,118,112,95,108,105,110,101,95,101,110,100,45,118,112,95,108,105,110,101,95,98,101,103,105,110,59,10,10,10,9,119,95,98,101,103,105,110,32,61,32,49,46,48,47,119,95,98,101,103,105,110,59,10,9,119,95,101,110,100,32,61,32,49,46,48,47,119,95,101,110,100,59,10,10,10,9,102,108,111,97,116,32,122,95,98,101,103,105,110,32,61,32,118,101,114,116,101,120,46,122,42,119,95,98,101,103,105,110,59,10,9,102,108,111,97,116,32,122,95,101,110,100,32,61,32,114,97,121,95,101,110,100,46,122,42,119,95,101,110,100,59,10,10,9,118,101,99,50,32,108,105,110,101,95,98,101,103,105,110,32,61,32,118,112,95,108,105,110,101,95,98,101,103,105,110,47,112,105,120,101,108,95,115,105,122,101,59,10,9,118,101,99,50,32,108,105,110,101,95,100,105,114,32,61,32,118,112,95,108,105,110,101,95,100,105,114,47,112,105,120,101,108,95,115,105,122,101,59,10,9,102,108,111,97,116,32,122,95,100,105,114,32,61,32,122,95,101,110,100,32,45,32,122,95,98,101,103,105,110,59,10,9,102,108,111,97,116,32,119,95,100,105,114,32,61,32,119,95,101,110,100,32,45,32,119,95,98,101,103,105,110,59,10,10,10,9,47,47,32,99,108,105,112,32,116,104,101,32,108,105,110,101,32,116,111,32,116,104,101,32,118,105,101,119,112,111,114,116,32,101,100,103,101,115,10,10,9,102,108,111,97,116,32,115,99,97,108,101,95,109,97,120,95,120,32,61,32,109,105,110,40,49,44,32,48,46,57,57,32,42,32,40,49,46,48,32,45,32,118,112,95,108,105,110,101,95,98,101,103,105,110,46,120,41,32,47,32,109,97,120,40,49,101,45,53,44,32,118,112,95,108,105,110,101,95,100,105,114,46,120,41,41,59,10,9,102,108,111,97,116,32,115,99,97,108,101,95,109,97,120,95,121,32,61,32,109,105,110,40,49,44,32,48,46,57,57,32,42,32,40,49,46,48,32,45,32,118,112,95,108,105,110,101,95,98,101,103,105,110,46,121,41,32,47,32,109,97,120,40,49,101,45,53,44,32,118,112,95,108,105,110,101,95,100,105,114,46,121,41,41,59,10,9,102,108,111,97,116,32,115,99,97,108,101,95,109,105,110,95,120,32,61,32,109,105,110,40,49,44,32,48,46,57,57,32,42,32,118,112,95,108,105,110,101,95,98,101,103,105,110,46,120,32,47,32,109,97,120,40,49,101,45,53,44,32,45,118,112,95,108,105,110,101,95,100,105,114,46,120,41,41,59,10,9,102,108,111,97,116,32,115,99,97,108,101,95,109,105,110,95,121,32,61,32,109,105,110,40,49,44,32,48,46,57,57,32,42,32,118,112,95,108,105,110,101,95,98,101,103,105,110,46,121,32,47,32,109,97,120,40,49,101,45,53,44,32,45,118,112,95,108,105,110,101,95,100,105,114,46,121,41,41,59,10,9,102,108,111,97,116,32,108,105,110,101,95,99,108,105,112,32,61,32,109,105,110,40,115,99,97,108,101,95,109,97,120,95,120,44,32,115,99,97,108,101,95,109,97,120,95,121,41,32,42,32,109,105,110,40,115,99,97,108,101,95,109,105,110,95,120,44,32,115,99,97,108,101,95,109,105,110,95,121,41,59,10,9,108,105,110,101,95,100,105,114,32,42,61,32,108,105,110,101,95,99,108,105,112,59,10,9,122,95,100,105,114,32,42,61,32,108,105,110,101,95,99,108,105,112,59,10,9,119,95,100,105,114,32,42,61,108,105,110,101,95,99,108,105,112,59,10,10,10,9,118,101,99,50,32,108,105,110,101,95,97,100,118,97,110,99,101,32,61,32,110,111,114,109,97,108,105,122,101,40,108,105,110,101,95,100,105,114,41,59,32,47,47,100,111,119,110,32,116,111,32,112,105,120,101,108,10,9,102,108,111,97,116,32,115,116,101,112,95,115,105,122,101,32,61,32,108,101,110,103,116,104,40,108,105,110,101,95,97,100,118,97,110,99,101,41,47,108,101,110,103,116,104,40,108,105,110,101,95,100,105,114,41,59,10,9,102,108,111,97,116,32,122,95,97,100,118,97,110,99,101,32,61,32,122,95,100,105,114,42,115,116,101,112,95,115,105,122,101,59,32,47,47,32,97,100,97,112,116,32,122,32,97,100,118,97,110,99,101,32,116,111,32,108,105,110,101,32,97,100,118,97,110,99,101,10,9,102,108,111,97,116,32,119,95,97,100,118,97,110,99,101,32,61,32,119,95,100,105,114,42,115,116,101,112,95,115,105,122,101,59,32,47,47,32,97,100,97,112,116,32,119,32,97,100,118,97,110,99,101,32,116,111,32,108,105,110,101,32,97,100,118,97,110,99,101,10,10,9,102,108,111,97,116,32,97,100,118,97,110,99,101,95,97,110,103,108,101,95,97,100,106,32,61,32,49,46,48,47,109,97,120,40,97,98,115,40,108,105,110,101,95,97,100,118,97,110,99,101,46,120,41,44,97,98,115,40,108,105,110,101,95,97,100,118,97,110,99,101,46,121,41,41,59,32,47,47,109,97,107,101,32,105,116,32,103,111,32,102,97,115,116,101,114,32,116,104,101,32,99,108,111,115,101,114,32,116,111,32,52,53,100,10,9,108,105,110,101,95,97,100,118,97,110,99,101,42,61,97,100,118,97,110,99,101,95,97,110,103,108,101,95,97,100,106,59,32,47,47,32,97,100,97,112,116,32,122,32,97,100,118,97,110,99,101,32,116,111,32,108,105,110,101,32,97,100,118,97,110,99,101,10,9,122,95,97,100,118,97,110,99,101,42,61,97,100,118,97,110,99,101,95,97,110,103,108,101,95,97,100,106,59,10,9,119,95,97,100,118,97,110,99,101,42,61,97,100,118,97,110,99,101,95,97,110,103,108,101,95,97,100,106,59,10,10,9,118,101,99,50,32,112,111,115,32,61,32,108,105,110,101,95,98,101,103,105,110,59,10,9,102,108,111,97,116,32,122,32,61,32,122,95,98,101,103,105,110,59,10,9,102,108,111,97,116,32,119,32,61,32,119,95,98,101,103,105,110,59,10,9,102,108,111,97,116,32,122,95,102,114,111,109,61,122,47,119,59,10,9,102,108,111,97,116,32,122,95,116,111,61,122,95,102,114,111,109,59,10,9,102,108,111,97,116,32,100,101,112,116,104,59,10,9,118,101,99,50,32,112,114,101,118,95,112,111,115,61,112,111,115,59,10,10,9,98,111,111,108,32,102,111,117,110,100,61,102,97,108,115,101,59,10,10,9,102,108,111,97,116,32,97,99,99,101,108,61,49,46,48,52,59,47,47,43,114,97,110,100,40,103,108,95,70,114,97,103,67,111,111,114,100,46,120,121,41,42,48,46,48,48,48,49,59,10,9,102,108,111,97,116,32,115,116,101,112,115,95,116,97,107,101,110,61,48,59,10,10,9,102,111,114,40,102,108,111,97,116,32,105,61,48,59,105,60,110,117,109,95,115,116,101,112,115,59,105,43,43,41,32,123,10,10,9,9,112,111,115,43,61,108,105,110,101,95,97,100,118,97,110,99,101,59,10,9,9,122,43,61,122,95,97,100,118,97,110,99,101,59,10,9,9,119,43,61,119,95,97,100,118,97,110,99,101,59,10,10,9,9,100,101,112,116,104,32,61,32,116,101,120,116,117,114,101,40,115,111,117,114,99,101,95,100,101,112,116,104,44,32,112,111,115,42,112,105,120,101,108,95,115,105,122,101,41,46,114,32,42,32,50,46,48,32,45,32,49,46,48,59,10,9,9,100,101,112,116,104,32,61,32,50,46,48,32,42,32,99,97,109,101,114,97,95,122,95,110,101,97,114,32,42,32,99,97,109,101,114,97,95,122,95,102,97,114,32,47,32,40,99,97,109,101,114,97,95,122,95,102,97,114,32,43,32,99,97,109,101,114,97,95,122,95,110,101,97,114,32,45,32,100,101,112,116,104,32,42,32,40,99,97,109,101,114,97,95,122,95,102,97,114,32,45,32,99,97,109,101,114,97,95,122,95,110,101,97,114,41,41,59,10,9,9,100,101,112,116,104,61,45,100,101,112,116,104,59,10,10,9,9,122,95,102,114,111,109,32,61,32,122,95,116,111,59,10,9,9,122,95,116,111,32,61,32,122,47,119,59,10,10,9,9,105,102,32,40,100,101,112,116,104,62,122,95,116,111,41,32,123,10,10,9,9,9,105,102,32,40,100,101,112,116,104,60,61,109,97,120,40,122,95,116,111,44,122,95,102,114,111,109,41,43,48,46,56,41,32,123,10,9,9,9,9,102,111,117,110,100,61,116,114,117,101,59,10,9,9,9,125,10,9,9,9,98,114,101,97,107,59,10,9,9,125,10,10,9,9,115,116,101,112,115,95,116,97,107,101,110,43,61,49,46,48,59,10,9,9,112,114,101,118,95,112,111,115,61,112,111,115,59,10,9,9,122,95,97,100,118,97,110,99,101,42,61,97,99,99,101,108,59,10,9,9,119,95,97,100,118,97,110,99,101,42,61,97,99,99,101,108,59,10,9,9,108,105,110,101,95,97,100,118,97,110,99,101,42,61,97,99,99,101,108,59,10,9,125,10,10,9,105,102,32,40,102,111,117,110,100,41,32,123,10,10,10,9,9,118,101,99,50,32,102,105,110,97,108,95,112,111,115,59,10,9,9,102,108,111,97,116,32,103,114,97,100,59,10,35,100,101,102,105,110,101,32,66,76,69,78,68,95,65,67,67,69,76,10,35,105,102,100,101,102,32,66,76,69,78,68,95,65,67,67,69,76,10,10,9,9,118,101,99,50,32,98,108,101,110,100,95,100,105,114,32,61,32,112,111,115,32,45,32,112,114,101,118,95,112,111,115,59,10,9,9,102,108,111,97,116,32,115,116,101,112,115,32,61,32,109,105,110,40,56,46,48,44,108,101,110,103,116,104,40,98,108,101,110,100,95,100,105,114,41,41,59,10,9,9,105,102,32,40,115,116,101,112,115,62,50,46,48,41,32,123,10,9,9,9,118,101,99,50,32,98,108,101,110,100,95,115,116,101,112,32,61,32,98,108,101,110,100,95,100,105,114,47,115,116,101,112,115,59,10,9,9,9,102,108,111,97,116,32,98,108,101,110,100,95,122,32,61,32,40,122,95,116,111,45,122,95,102,114,111,109,41,47,115,116,101,112,115,59,10,9,9,9,118,101,99,50,32,110,101,119,95,112,111,115,59,10,9,9,9,102,108,111,97,116,32,115,117,98,103,114,97,100,61,48,46,48,59,10,9,9,9,102,111,114,40,102,108,111,97,116,32,105,61,48,46,48,59,105,60,115,116,101,112,115,59,105,43,43,41,32,123,10,10,9,9,9,9,110,101,119,95,112,111,115,32,61,32,40,112,114,101,118,95,112,111,115,43,98,108,101,110,100,95,115,116,101,112,42,105,41,59,10,9,9,9,9,102,108,111,97,116,32,122,32,61,32,122,95,102,114,111,109,43,98,108,101,110,100,95,122,42,105,59,10,10,9,9,9,9,100,101,112,116,104,32,61,32,116,101,120,116,117,114,101,40,115,111,117,114,99,101,95,100,101,112,116,104,44,32,110,101,119,95,112,111,115,42,112,105,120,101,108,95,115,105,122,101,41,46,114,32,42,32,50,46,48,32,45,32,49,46,48,59,10,9,9,9,9,100,101,112,116,104,32,61,32,50,46,48,32,42,32,99,97,109,101,114,97,95,122,95,110,101,97,114,32,42,32,99,97,109,101,114,97,95,122,95,102,97,114,32,47,32,40,99,97,109,101,114,97,95,122,95,102,97,114,32,43,32,99,97,109,101,114,97,95,122,95,110,101,97,114,32,45,32,100,101,112,116,104,32,42,32,40,99,97,109,101,114,97,95,122,95,102,97,114,32,45,32,99,97,109,101,114,97,95,122,95,110,101,97,114,41,41,59,10,9,9,9,9,100,101,112,116,104,61,45,100,101,112,116,104,59,10,10,9,9,9,9,115,117,98,103,114,97,100,61,105,47,115,116,101,112,115,59,10,9,9,9,9,105,102,32,40,100,101,112,116,104,62,122,41,10,9,9,9,9,9,98,114,101,97,107,59,10,9,9,9,125,10,10,9,9,9,102,105,110,97,108,95,112,111,115,32,61,32,110,101,119,95,112,111,115,59,10,9,9,9,103,114,97,100,61,40,115,116,101,112,115,95,116,97,107,101,110,43,115,117,98,103,114,97,100,41,47,110,117,109,95,115,116,101,112,115,59,10,9,9,9,47,47,102,114,97,103,95,99,111,108,111,114,32,61,32,118,101,99,52,40,118,101,99,51,40,103,114,97,100,41,44,49,46,48,41,59,10,9,9,125,32,101,108,115,101,32,123,10,35,101,110,100,105,102,10,9,9,9,103,114,97,100,61,115,116,101,112,115,95,116,97,107,101,110,47,110,117,109,95,115,116,101,112,115,59,10,9,9,9,102,105,110,97,108,95,112,111,115,61,112,111,115,59,10,35,105,102,100,101,102,32,66,76,69,78,68,95,65,67,67,69,76,10,9,9,125,10,10,35,101,110,100,105,102,10,10,35,100,101,102,105,110,101,32,82,69,70,76,69,67,84,95,82,79,85,71,72,78,69,83,83,10,35,105,102,100,101,102,32,82,69,70,76,69,67,84,95,82,79,85,71,72,78,69,83,83,10,10,10,9,9,118,101,99,52,32,102,105,110,97,108,95,99,111,108,111,114,59,10,10,9,9,105,102,32,40,114,111,117,103,104,110,101,115,115,32,62,32,48,46,48,48,49,41,32,123,10,9,9,9,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,10,9,9,9,47,47,117,115,101,32,97,32,98,108,117,114,114,101,100,32,118,101,114,115,105,111,110,32,40,105,110,32,99,111,110,115,101,99,117,116,105,118,101,32,109,105,112,109,97,112,115,41,32,111,102,32,116,104,101,32,115,99,114,101,101,110,32,116,111,32,115,105,109,117,108,97,116,101,32,114,111,117,103,104,110,101,115,115,10,10,9,9,9,102,108,111,97,116,32,103,108,111,115,115,32,61,32,49,46,48,45,114,111,117,103,104,110,101,115,115,59,10,9,9,9,102,108,111,97,116,32,99,111,110,101,95,97,110,103,108,101,32,61,32,114,111,117,103,104,110,101,115,115,32,42,32,77,95,80,73,32,42,32,48,46,53,59,10,9,9,9,118,101,99,50,32,99,111,110,101,95,100,105,114,32,61,32,102,105,110,97,108,95,112,111,115,32,45,32,108,105,110,101,95,98,101,103,105,110,59,10,9,9,9,102,108,111,97,116,32,99,111,110,101,95,108,101,110,32,61,32,108,101,110,103,116,104,40,99,111,110,101,95,100,105,114,41,59,10,9,9,9,99,111,110,101,95,100,105,114,32,61,32,110,111,114,109,97,108,105,122,101,40,99,111,110,101,95,100,105,114,41,59,32,47,47,119,105,108,108,32,98,101,32,117,115,101,100,32,110,111,114,109,97,108,105,122,101,100,32,102,114,111,109,32,110,111,119,32,111,110,10,9,9,9,102,108,111,97,116,32,109,97,120,95,109,105,112,109,97,112,32,61,32,102,105,108,116,101,114,95,109,105,112,109,97,112,95,108,101,118,101,108,115,32,45,49,59,10,9,9,9,102,108,111,97,116,32,103,108,111,115,115,95,109,117,108,116,61,103,108,111,115,115,59,10,10,9,9,9,102,108,111,97,116,32,114,101,109,95,97,108,112,104,97,61,49,46,48,59,10,9,9,9,102,105,110,97,108,95,99,111,108,111,114,32,61,32,118,101,99,52,40,48,46,48,41,59,10,10,9,9,9,102,111,114,40,105,110,116,32,105,61,48,59,105,60,55,59,105,43,43,41,32,123,10,10,9,9,9,9,102,108,111,97,116,32,111,112,95,108,101,110,32,61,32,50,46,48,32,42,32,116,97,110,40,99,111,110,101,95,97,110,103,108,101,41,32,42,32,99,111,110,101,95,108,101,110,59,32,47,47,111,112,111,115,105,116,101,32,115,105,100,101,32,111,102,32,105,115,111,32,116,114,105,97,110,103,108,101,10,9,9,9,9,102,108,111,97,116,32,114,97,100,105,117,115,59,10,9,9,9,9,123,10,9,9,9,9,9,47,47,102,105,116,32,116,111,32,115,112,104,101,114,101,32,105,110,115,105,100,101,32,99,111,110,101,32,40,115,112,104,101,114,101,32,101,110,100,115,32,97,116,32,101,110,100,32,111,102,32,99,111,110,101,41,44,32,115,111,109,101,116,104,105,110,103,32,108,105,107,101,32,116,104,105,115,58,10,9,9,9,9,9,47,47,32,95,95,95,10,9,9,9,9,9,47,47,32,92,79,47,10,9,9,9,9,9,47,47,32,32,86,10,9,9,9,9,9,47,47,10,9,9,9,9,9,47,47,32,97,115,32,105,116,32,97,118,111,105,100,115,32,98,108,101,101,100,105,110,103,32,102,114,111,109,32,98,101,121,111,110,100,32,116,104,101,32,114,101,102,108,101,99,116,105,111,110,32,97,115,32,109,117,99,104,32,97,115,32,112,111,115,115,105,98,108,101,46,32,65,115,32,97,32,112,108,117,115,10,9,9,9,9,9,47,47,32,105,116,32,97,108,115,111,32,109,97,107,101,115,32,116,104,101,32,114,111,117,103,104,32,114,101,102,108,101,99,116,105,111,110,32,109,111,114,101,32,101,108,111,110,103,97,116,101,100,46,10,9,9,9,9,9,102,108,111,97,116,32,97,32,61,32,111,112,95,108,101,110,59,10,9,9,9,9,9,102,108,111,97,116,32,104,32,61,32,99,111,110,101,95,108,101,110,59,10,9,9,9,9,9,102,108,111,97,116,32,97,50,32,61,32,97,32,42,32,97,59,10,9,9,9,9,9,102,108,111,97,116,32,102,104,50,32,61,32,52,46,48,102,32,42,32,104,32,42,32,104,59,10,9,9,9,9,9,114,97,100,105,117,115,32,61,32,40,97,32,42,32,40,115,113,114,116,40,97,50,32,43,32,102,104,50,41,32,45,32,97,41,41,32,47,32,40,52,46,48,102,32,42,32,104,41,59,10,9,9,9,9,125,10,10,9,9,9,9,47,47,102,105,110,100,32,116,104,101,32,112,108,97,99,101,32,119,104,101,114,101,32,115,99,114,101,101,110,32,109,117,115,116,32,98,101,32,115,97,109,112,108,101,100,10,9,9,9,9,118,101,99,50,32,115,97,109,112,108,101,95,112,111,115,32,61,32,40,32,108,105,110,101,95,98,101,103,105,110,32,43,32,99,111,110,101,95,100,105,114,32,42,32,40,99,111,110,101,95,108,101,110,32,45,32,114,97,100,105,117,115,41,32,41,32,42,32,112,105,120,101,108,95,115,105,122,101,59,10,9,9,9,9,47,47,114,97,100,105,117,115,32,105,115,32,105,110,32,112,105,120,101,108,115,44,32,115,111,32,105,116,39,115,32,110,97,116,117,114,97,108,32,116,104,97,116,32,108,111,103,50,40,114,97,100,105,117,115,41,32,109,97,112,115,32,116,111,32,116,104,101,32,114,105,103,104,116,32,109,105,112,109,97,112,32,102,111,114,32,116,104,101,32,97,109,111,117,110,116,32,111,102,32,112,105,120,101,108,115,10,9,9,9,9,102,108,111,97,116,32,109,105,112,109,97,112,32,61,32,99,108,97,109,112,40,32,108,111,103,50,40,32,114,97,100,105,117,115,32,41,44,32,48,46,48,44,32,109,97,120,95,109,105,112,109,97,112,32,41,59,10,10,9,9,9,9,47,47,109,105,112,109,97,112,32,61,32,109,97,120,40,109,105,112,109,97,112,45,49,46,48,44,48,46,48,41,59,10,9,9,9,9,47,47,100,111,32,115,97,109,112,108,105,110,103,10,10,9,9,9,9,118,101,99,52,32,115,97,109,112,108,101,95,99,111,108,111,114,59,10,9,9,9,9,123,10,9,9,9,9,9,115,97,109,112,108,101,95,99,111,108,111,114,32,61,32,116,101,120,116,117,114,101,76,111,100,40,115,111,117,114,99,101,95,100,105,102,102,117,115,101,95,109,105,112,109,97,112,115,44,115,97,109,112,108,101,95,112,111,115,44,109,97,120,40,49,46,48,44,109,105,112,109,97,112,41,41,59,10,9,9,9,9,9,105,102,32,40,109,105,112,109,97,112,60,49,46,48,41,32,123,32,47,47,119,101,32,117,115,101,32,97,110,111,116,104,101,114,32,105,109,97,103,101,32,97,115,32,98,97,115,101,32,116,111,32,97,118,111,105,100,32,99,111,112,121,105,110,103,32,97,108,108,32,116,104,101,32,115,99,114,101,101,110,32,117,110,110,101,99,101,115,97,114,105,108,121,10,9,9,9,9,9,9,118,101,99,52,32,98,97,115,101,95,115,97,109,112,108,101,95,99,111,108,111,114,32,61,32,116,101,120,116,117,114,101,76,111,100,40,115,111,117,114,99,101,95,100,105,102,102,117,115,101,44,115,97,109,112,108,101,95,112,111,115,44,48,46,48,41,59,10,9,9,9,9,9,9,115,97,109,112,108,101,95,99,111,108,111,114,32,61,32,109,105,120,40,98,97,115,101,95,115,97,109,112,108,101,95,99,111,108,111,114,44,115,97,109,112,108,101,95,99,111,108,111,114,44,109,105,112,109,97,112,41,59,10,9,9,9,9,9,125,10,9,9,9,9,125,10,10,9,9,9,9,47,47,109,117,108,116,105,112,108,121,32,98,121,32,103,108,111,115,115,10,9,9,9,9,115,97,109,112,108,101,95,99,111,108,111,114,46,114,103,98,42,61,103,108,111,115,115,95,109,117,108,116,59,10,9,9,9,9,115,97,109,112,108,101,95,99,111,108,111,114,46,97,61,103,108,111,115,115,95,109,117,108,116,59,10,10,9,9,9,9,114,101,109,95,97,108,112,104,97,32,45,61,32,115,97,109,112,108,101,95,99,111,108,111,114,46,97,59,10,9,9,9,9,105,102,40,114,101,109,95,97,108,112,104,97,32,60,32,48,46,48,41,32,123,10,9,9,9,9,9,115,97,109,112,108,101,95,99,111,108,111,114,46,114,103,98,32,42,61,32,40,49,46,48,32,45,32,97,98,115,40,114,101,109,95,97,108,112,104,97,41,41,59,10,9,9,9,9,125,10,10,9,9,9,9,102,105,110,97,108,95,99,111,108,111,114,43,61,115,97,109,112,108,101,95,99,111,108,111,114,59,10,10,9,9,9,9,105,102,32,40,102,105,110,97,108,95,99,111,108,111,114,46,97,62,61,48,46,57,53,41,32,123,10,9,9,9,9,9,47,47,32,84,104,105,115,32,99,111,100,101,32,111,102,32,97,99,99,117,109,117,108,97,116,105,110,103,32,103,108,111,115,115,32,97,110,100,32,97,98,111,114,116,105,110,103,32,111,110,32,110,101,97,114,32,111,110,101,10,9,9,9,9,9,47,47,32,109,97,107,101,115,32,115,101,110,115,101,32,119,104,101,110,32,121,111,117,32,116,104,105,110,107,32,111,102,32,99,111,110,101,32,116,114,97,99,105,110,103,46,10,9,9,9,9,9,47,47,32,84,104,105,110,107,32,111,102,32,105,116,32,97,115,32,105,102,32,114,111,117,103,104,110,101,115,115,32,119,97,115,32,48,44,32,116,104,101,110,32,119,101,32,99,111,117,108,100,32,97,98,111,114,116,32,111,110,32,116,104,101,32,102,105,114,115,116,10,9,9,9,9,9,47,47,32,105,116,101,114,97,116,105,111,110,46,32,70,111,114,32,108,101,115,115,101,114,32,114,111,117,103,104,110,101,115,115,32,118,97,108,117,101,115,44,32,119,101,32,110,101,101,100,32,109,111,114,101,32,105,116,101,114,97,116,105,111,110,115,44,32,98,117,116,10,9,9,9,9,9,47,47,32,101,97,99,104,32,110,101,101,100,115,32,116,111,32,104,97,118,101,32,108,101,115,115,32,105,110,102,108,117,101,110,99,101,32,103,105,118,101,110,32,116,104,101,32,115,112,104,101,114,101,32,105,115,32,115,109,97,108,108,101,114,10,9,9,9,9,9,98,114,101,97,107,59,10,9,9,9,9,125,10,10,9,9,9,9,99,111,110,101,95,108,101,110,45,61,114,97,100,105,117,115,42,50,46,48,59,32,47,47,103,111,32,116,111,32,110,101,120,116,32,40,115,109,97,108,108,101,114,41,32,99,105,114,99,108,101,46,10,10,9,9,9,9,103,108,111,115,115,95,109,117,108,116,42,61,103,108,111,115,115,59,10,10,10,9,9,9,125,10,9,9,125,32,101,108,115,101,32,123,10,9,9,9,102,105,110,97,108,95,99,111,108,111,114,32,61,32,116,101,120,116,117,114,101,76,111,100,40,115,111,117,114,99,101,95,100,105,102,102,117,115,101,44,102,105,110,97,108,95,112,111,115,42,112,105,120,101,108,95,115,105,122,101,44,99,108,97,109,112,40,49,46,48,45,103,114,97,100,44,48,46,48,44,49,46,48,41,41,59,10,9,9,125,10,10,9,9,102,114,97,103,95,99,111,108,111,114,32,61,32,118,101,99,52,40,102,105,110,97,108,95,99,111,108,111,114,46,114,103,98,44,109,97,120,40,48,46,48,44,49,46,48,45,103,114,97,100,41,41,59,10,10,35,101,108,115,101,10,9,9,102,114,97,103,95,99,111,108,111,114,32,61,32,118,101,99,52,40,116,101,120,116,117,114,101,76,111,100,40,115,111,117,114,99,101,95,100,105,102,102,117,115,101,44,102,105,110,97,108,95,112,111,115,42,112,105,120,101,108,95,115,105,122,101,44,48,46,48,41,46,114,103,98,44,99,108,97,109,112,40,49,46,48,45,103,114,97,100,44,48,46,48,44,49,46,48,41,41,59,10,35,101,110,100,105,102,10,10,10,10,9,125,32,101,108,115,101,32,123,10,9,9,102,114,97,103,95,99,111,108,111,114,32,61,32,118,101,99,52,40,49,46,48,44,48,46,48,44,48,46,48,44,48,46,48,41,59,10,9,125,10,10,9,47,47,102,114,97,103,95,99,111,108,111,114,32,61,32,118,101,99,52,40,110,111,114,109,97,108,105,122,101,40,108,105,110,101,95,100,105,114,41,32,42,32,48,46,53,32,43,32,48,46,53,44,48,46,48,44,49,46,48,41,59,10,10,47,42,10,9,118,101,99,50,32,104,105,116,95,112,105,120,101,108,59,10,9,118,101,99,51,32,104,105,116,95,112,111,105,110,116,59,10,9,105,110,116,32,119,104,105,99,104,59,10,9,109,97,116,52,32,98,105,97,115,95,109,97,116,32,61,32,109,97,116,52,40,118,101,99,52,40,48,46,53,44,48,46,48,44,48,46,48,44,48,46,48,41,44,118,101,99,52,40,48,46,48,44,48,46,53,44,48,46,48,44,48,46,48,41,44,118,101,99,52,40,48,46,48,44,48,46,48,44,49,46,48,44,48,46,48,41,44,118,101,99,52,40,48,46,53,44,48,46,53,44,48,46,48,44,49,46,48,41,41,59,10,9,109,97,116,52,32,112,105,120,101,108,95,109,97,116,32,61,32,109,97,116,52,40,118,101,99,52,40,118,105,101,119,112,111,114,116,95,115,105,122,101,46,120,44,48,46,48,44,48,46,48,44,48,46,48,41,44,118,101,99,52,40,48,46,48,44,118,105,101,119,112,111,114,116,95,115,105,122,101,46,121,44,48,46,48,44,48,46,48,41,44,118,101,99,52,40,48,46,48,44,48,46,48,44,49,46,48,44,48,46,48,41,44,118,101,99,52,40,48,46,48,44,48,46,48,44,48,46,48,44,49,46,48,41,41,59,10,10,10,10,10,9,109,97,116,52,32,100,116,32,61,32,112,105,120,101,108,95,109,97,116,32,42,40,32,98,105,97,115,95,109,97,116,32,42,32,112,114,111,106,101,99,116,105,111,110,41,59,10,9,118,101,99,52,32,118,112,32,61,32,100,116,32,42,32,118,101,99,52,40,118,101,114,116,101,120,44,49,46,48,41,59,10,9,118,112,46,120,121,122,47,61,118,112,46,119,59,10,10,9,102,114,97,103,95,99,111,108,111,114,32,61,32,116,101,120,101,108,70,101,116,99,104,40,32,115,111,117,114,99,101,95,100,105,102,102,117,115,101,44,32,32,105,118,101,99,50,40,118,112,46,120,121,41,44,48,32,41,59,10,9,114,101,116,117,114,110,59,10,42,47,10,47,42,9,98,111,111,108,32,104,105,116,32,61,32,116,114,97,99,101,83,99,114,101,101,110,83,112,97,99,101,82,97,121,49,40,118,101,114,116,101,120,44,114,97,121,95,100,105,114,44,32,112,105,120,101,108,95,109,97,116,32,42,40,32,98,105,97,115,95,109,97,116,32,42,32,112,114,111,106,101,99,116,105,111,110,41,44,115,111,117,114,99,101,95,100,101,112,116,104,44,118,105,101,119,112,111,114,116,95,115,105,122,101,44,48,46,48,49,44,116,114,117,101,44,99,111,109,112,117,116,101,67,108,105,112,73,110,102,111,40,45,99,97,109,101,114,97,95,122,95,110,101,97,114,44,45,99,97,109,101,114,97,95,122,95,102,97,114,41,44,45,99,97,109,101,114,97,95,122,95,110,101,97,114,44,49,46,50,44,48,46,48,44,54,52,46,48,44,99,97,109,101,114,97,95,122,95,102,97,114,44,104,105,116,95,112,105,120,101,108,44,119,104,105,99,104,44,104,105,116,95,112,111,105,110,116,41,59,10,10,10,10,9,105,102,32,40,104,105,116,41,32,123,10,9,9,102,114,97,103,95,99,111,108,111,114,32,61,32,118,101,99,52,40,116,101,120,101,108,70,101,116,99,104,40,115,111,117,114,99,101,95,100,105,102,102,117,115,101,44,105,118,101,99,50,40,104,105,116,95,112,105,120,101,108,41,44,48,41,46,114,103,98,44,49,46,48,41,59,10,9,125,32,101,108,115,101,32,123,10,9,9,102,114,97,103,95,99,111,108,111,114,32,61,32,118,101,99,52,40,48,46,49,44,48,46,48,44,48,46,48,44,48,46,48,41,59,10,9,125,10,42,47,10,10,10,9,47,42,10,9,102,108,111,97,116,32,112,105,120,101,108,100,105,115,116,32,61,32,108,101,110,103,116,104,40,118,101,114,116,101,120,41,59,10,10,10,9,47,47,32,83,107,105,112,32,115,107,121,98,111,120,32,97,110,100,32,100,105,115,116,97,110,116,32,112,105,120,101,108,115,10,9,105,102,32,40,112,105,120,101,108,100,105,115,116,32,62,32,99,97,109,101,114,97,95,122,95,102,97,114,41,32,123,10,9,9,102,114,97,103,95,99,111,108,111,114,61,118,101,99,52,40,48,46,48,44,48,46,48,44,49,46,48,44,49,46,48,41,59,10,9,9,114,101,116,117,114,110,59,10,9,125,10,10,9,118,101,114,116,101,120,43,61,110,111,114,109,97,108,42,48,46,49,59,10,10,9,47,47,32,82,97,121,32,110,111,116,32,105,110,32,118,105,101,119,10,9,105,102,32,40,100,111,116,40,114,97,121,95,100,105,114,44,32,118,105,101,119,95,100,105,114,41,32,60,32,49,101,45,53,41,32,123,10,9,9,102,114,97,103,95,99,111,108,111,114,32,61,32,118,101,99,52,40,48,46,48,44,49,46,48,44,48,46,48,44,49,46,48,41,59,10,9,9,114,101,116,117,114,110,59,10,9,125,10,10,10,9,102,108,111,97,116,32,109,97,120,95,114,97,121,95,108,101,110,32,61,32,49,46,48,32,42,32,112,105,120,101,108,100,105,115,116,59,10,10,10,9,102,108,111,97,116,32,114,97,121,95,108,101,110,32,61,32,40,10,40,118,101,114,116,101,120,46,122,32,43,32,114,97,121,95,100,105,114,46,122,32,42,32,109,97,120,95,114,97,121,95,108,101,110,41,32,62,32,99,97,109,101,114,97,95,122,95,110,101,97,114,41,32,63,32,40,99,97,109,101,114,97,95,122,95,110,101,97,114,32,45,32,118,101,114,116,101,120,46,122,41,32,47,32,114,97,121,95,100,105,114,46,122,32,58,32,109,97,120,95,114,97,121,95,108,101,110,59,10,10,10,9,47,47,32,67,111,110,118,101,114,116,32,115,116,97,114,116,32,97,110,100,32,101,110,100,32,112,111,115,32,102,114,111,109,32,118,105,101,119,32,116,111,32,115,99,114,101,101,110,32,115,112,97,99,101,10,9,118,101,99,51,32,114,97,121,95,115,116,97,114,116,95,115,99,114,101,101,110,32,61,32,118,105,101,119,95,116,111,95,115,99,114,101,101,110,40,118,101,114,116,101,120,41,59,10,9,118,101,99,51,32,114,97,121,95,101,110,100,95,115,99,114,101,101,110,32,61,32,118,105,101,119,95,116,111,95,115,99,114,101,101,110,40,118,101,114,116,101,120,32,43,32,114,97,121,95,108,101,110,32,42,32,114,97,121,95,100,105,114,41,59,10,10,9,118,101,99,51,32,114,97,121,95,112,111,115,32,61,32,114,97,121,95,115,116,97,114,116,95,115,99,114,101,101,110,59,10,9,118,101,99,51,32,114,97,121,95,100,105,114,95,115,99,114,101,101,110,32,61,32,114,97,121,95,101,110,100,95,115,99,114,101,101,110,32,45,32,114,97,121,95,115,116,97,114,116,95,115,99,114,101,101,110,59,10,10,9,47,47,32,77,97,107,101,32,115,117,114,101,32,116,104,101,32,114,97,121,32,100,111,101,115,32,110,111,116,32,108,101,97,118,101,32,116,104,101,32,115,99,114,101,101,110,10,9,102,108,111,97,116,32,115,99,97,108,101,95,109,97,120,95,120,32,61,32,109,105,110,40,49,44,32,48,46,57,57,32,42,32,40,49,46,48,32,45,32,114,97,121,95,115,116,97,114,116,95,115,99,114,101,101,110,46,120,41,32,47,32,109,97,120,40,49,101,45,53,44,32,114,97,121,95,100,105,114,95,115,99,114,101,101,110,46,120,41,41,59,10,9,102,108,111,97,116,32,115,99,97,108,101,95,109,97,120,95,121,32,61,32,109,105,110,40,49,44,32,48,46,57,57,32,42,32,40,49,46,48,32,45,32,114,97,121,95,115,116,97,114,116,95,115,99,114,101,101,110,46,121,41,32,47,32,109,97,120,40,49,101,45,53,44,32,114,97,121,95,100,105,114,95,115,99,114,101,101,110,46,121,41,41,59,10,9,102,108,111,97,116,32,115,99,97,108,101,95,109,105,110,95,120,32,61,32,109,105,110,40,49,44,32,48,46,57,57,32,42,32,114,97,121,95,115,116,97,114,116,95,115,99,114,101,101,110,46,120,32,47,32,109,97,120,40,49,101,45,53,44,32,45,114,97,121,95,100,105,114,95,115,99,114,101,101,110,46,120,41,41,59,10,9,102,108,111,97,116,32,115,99,97,108,101,95,109,105,110,95,121,32,61,32,109,105,110,40,49,44,32,48,46,57,57,32,42,32,114,97,121,95,115,116,97,114,116,95,115,99,114,101,101,110,46,121,32,47,32,109,97,120,40,49,101,45,53,44,32,45,114,97,121,95,100,105,114,95,115,99,114,101,101,110,46,121,41,41,59,10,9,114,97,121,95,100,105,114,95,115,99,114,101,101,110,32,42,61,32,109,105,110,40,115,99,97,108,101,95,109,97,120,95,120,44,32,115,99,97,108,101,95,109,97,120,95,121,41,59,10,9,114,97,121,95,100,105,114,95,115,99,114,101,101,110,32,42,61,32,109,105,110,40,115,99,97,108,101,95,109,105,110,95,120,44,32,115,99,97,108,101,95,109,105,110,95,121,41,59,10,10,9,118,101,99,51,32,114,97,121,95,115,116,101,112,32,61,32,40,114,97,121,95,101,110,100,95,115,99,114,101,101,110,32,45,32,114,97,121,95,115,116,97,114,116,95,115,99,114,101,101,110,41,32,47,32,110,117,109,95,115,116,101,112,115,59,10,10,9,102,108,111,97,116,32,100,105,115,116,97,110,99,101,95,115,99,97,108,101,32,61,32,49,46,48,32,43,32,48,46,48,48,48,48,49,32,42,32,112,105,120,101,108,100,105,115,116,59,10,10,9,102,108,111,97,116,32,106,105,116,116,101,114,32,61,32,48,46,48,59,47,47,97,98,115,40,114,97,110,100,40,105,118,101,99,50,40,103,108,95,70,114,97,103,67,111,111,114,100,46,120,121,41,32,37,32,56,32,43,32,40,77,97,105,110,83,99,101,110,101,68,97,116,97,46,102,114,97,109,101,95,105,110,100,101,120,32,37,32,71,69,84,95,83,69,84,84,73,78,71,40,115,115,114,44,32,104,105,115,116,111,114,121,95,108,101,110,103,116,104,41,41,32,42,32,48,46,49,41,41,59,10,10,9,47,47,32,82,111,117,103,104,32,115,111,117,114,102,97,99,101,115,32,110,101,101,100,32,109,111,114,101,32,106,105,116,116,101,114,10,9,106,105,116,116,101,114,32,42,61,32,109,97,120,40,48,46,53,44,32,114,111,117,103,104,110,101,115,115,41,59,10,10,9,114,97,121,95,112,111,115,32,43,61,32,106,105,116,116,101,114,32,42,32,114,97,121,95,115,116,101,112,59,10,10,10,9,105,110,116,32,105,32,61,32,48,59,10,9,102,108,111,97,116,32,105,110,116,101,114,115,101,99,116,105,111,110,95,119,101,105,103,104,116,32,61,32,48,46,48,59,10,9,98,111,111,108,32,104,105,116,95,102,97,99,116,111,114,32,61,32,102,97,108,115,101,59,10,10,9,118,101,99,50,32,105,110,116,101,114,115,101,99,116,105,111,110,32,61,32,118,101,99,50,40,45,49,46,48,41,59,10,10,9,102,111,114,32,40,105,32,61,32,49,59,32,105,32,60,32,110,117,109,95,115,116,101,112,115,59,32,43,43,105,41,32,123,10,9,9,114,97,121,95,112,111,115,32,43,61,32,114,97,121,95,115,116,101,112,59,10,10,9,9,47,47,32,67,117,114,114,101,110,116,32,99,111,111,114,100,105,110,97,116,101,32,105,115,32,105,110,32,116,104,101,32,109,105,100,32,111,102,32,116,119,111,32,115,97,109,112,108,101,115,44,32,110,111,116,32,97,116,32,116,104,101,32,101,110,100,44,32,115,111,10,9,9,47,47,32,115,117,98,115,116,114,97,99,116,32,104,97,108,102,32,111,102,32,97,32,115,116,101,112,10,9,9,118,101,99,50,32,99,117,114,114,95,99,111,111,114,100,32,61,32,114,97,121,95,112,111,115,46,120,121,32,45,32,48,46,53,32,42,32,114,97,121,95,115,116,101,112,46,120,121,59,10,10,10,9,9,47,47,32,73,110,99,114,101,97,115,101,32,114,97,121,32,98,105,97,115,32,97,115,32,119,101,32,97,100,118,97,110,99,101,32,116,104,101,32,114,97,121,10,9,9,102,108,111,97,116,32,116,114,97,99,101,95,108,101,110,32,61,32,105,110,105,116,105,97,108,95,98,105,97,115,32,42,32,49,48,46,48,32,43,10,9,9,9,9,49,48,48,46,48,32,42,32,100,111,116,40,99,117,114,114,95,99,111,111,114,100,45,117,118,95,105,110,116,101,114,112,44,99,117,114,114,95,99,111,111,114,100,45,117,118,95,105,110,116,101,114,112,41,59,10,10,9,9,116,114,97,99,101,95,108,101,110,32,42,61,32,49,46,48,32,43,32,49,46,48,32,42,32,114,111,117,103,104,110,101,115,115,59,10,10,9,9,47,47,32,67,104,101,99,107,32,102,111,114,32,105,110,116,101,114,115,101,99,116,105,111,110,10,10,9,9,102,108,111,97,116,32,100,101,112,116,104,32,61,32,116,101,120,116,117,114,101,40,115,111,117,114,99,101,95,100,101,112,116,104,44,99,117,114,114,95,99,111,111,114,100,41,46,114,32,42,32,50,46,48,32,45,32,49,46,48,59,10,9,9,102,108,111,97,116,32,108,105,110,101,97,114,95,100,101,112,116,104,61,100,101,112,116,104,59,10,9,9,47,47,102,108,111,97,116,32,108,105,110,101,97,114,95,100,101,112,116,104,32,61,32,50,46,48,32,42,32,99,97,109,101,114,97,95,122,95,110,101,97,114,32,42,32,99,97,109,101,114,97,95,122,95,102,97,114,32,47,32,40,99,97,109,101,114,97,95,122,95,102,97,114,32,43,32,99,97,109,101,114,97,95,122,95,110,101,97,114,32,45,32,100,101,112,116,104,32,42,32,40,99,97,109,101,114,97,95,122,95,102,97,114,32,45,32,99,97,109,101,114,97,95,122,95,110,101,97,114,41,41,59,10,9,9,47,47,108,105,110,101,97,114,95,100,101,112,116,104,32,61,32,45,108,105,110,101,97,114,95,100,101,112,116,104,59,10,10,10,9,9,105,102,32,40,112,111,105,110,116,95,98,101,116,119,101,101,110,95,112,108,97,110,101,115,40,108,105,110,101,97,114,95,100,101,112,116,104,44,32,114,97,121,95,112,111,115,46,122,44,10,9,9,9,9,9,32,114,97,121,95,112,111,115,46,122,32,45,32,114,97,121,95,115,116,101,112,46,122,44,32,116,114,97,99,101,95,108,101,110,44,32,104,105,116,95,102,97,99,116,111,114,41,41,32,123,10,9,9,9,105,110,116,101,114,115,101,99,116,105,111,110,32,61,32,99,117,114,114,95,99,111,111,114,100,59,10,9,9,9,98,114,101,97,107,59,10,9,9,125,10,9,125,10,10,9,47,47,32,77,97,107,101,32,115,117,114,101,32,119,101,32,104,105,116,32,101,120,97,99,116,108,121,32,111,110,101,32,112,105,120,101,108,10,9,47,47,105,110,116,101,114,115,101,99,116,105,111,110,32,61,32,116,114,117,110,99,97,116,101,95,99,111,111,114,100,105,110,97,116,101,40,105,110,116,101,114,115,101,99,116,105,111,110,41,59,10,10,9,47,47,32,67,104,101,99,107,32,105,102,32,119,101,32,104,105,116,32,115,111,109,101,116,104,105,110,103,10,9,105,102,32,40,109,105,110,40,105,110,116,101,114,115,101,99,116,105,111,110,46,120,44,32,105,110,116,101,114,115,101,99,116,105,111,110,46,121,41,32,60,61,32,48,46,48,32,124,124,32,111,117,116,95,111,102,95,115,99,114,101,101,110,40,105,110,116,101,114,115,101,99,116,105,111,110,41,41,32,123,10,9,9,102,114,97,103,95,99,111,108,111,114,61,118,101,99,52,40,49,46,48,44,48,46,48,44,49,46,48,44,49,46,48,41,59,10,9,9,114,101,116,117,114,110,59,10,9,125,10,10,9,105,102,32,40,33,104,105,116,95,102,97,99,116,111,114,41,32,123,10,9,9,102,114,97,103,95,99,111,108,111,114,61,118,101,99,52,40,48,46,48,44,49,46,48,44,49,46,48,44,49,46,48,41,59,10,9,9,114,101,116,117,114,110,59,10,9,125,10,10,9,102,114,97,103,95,99,111,108,111,114,32,61,32,118,101,99,52,40,116,101,120,116,117,114,101,40,115,111,117,114,99,101,95,100,105,102,102,117,115,101,44,105,110,116,101,114,115,101,99,116,105,111,110,41,46,114,103,98,44,49,46,48,41,59,10,42,47,10,10,125,10,10, 0}; - - static const int _fragment_code_start=17; - setup(_conditional_strings,2,_uniform_strings,8,_attribute_pairs,0, _texunit_pairs,4,_ubo_pairs,0,_feedbacks,0,_vertex_code,_fragment_code,_vertex_code_start,_fragment_code_start); - }; - -}; - -#endif - diff --git a/drivers/gles3/shadow_atlas_gles3.cpp b/drivers/gles3/shadow_atlas_gles3.cpp deleted file mode 100644 index 38dee8bcea..0000000000 --- a/drivers/gles3/shadow_atlas_gles3.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#include "shadow_atlas_gles3.h" - diff --git a/drivers/gles3/shadow_atlas_gles3.h b/drivers/gles3/shadow_atlas_gles3.h deleted file mode 100644 index 46eaf581cb..0000000000 --- a/drivers/gles3/shadow_atlas_gles3.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef SHADOW_ATLAS_GLES3_H -#define SHADOW_ATLAS_GLES3_H - -#include "rasterizer_storage_gles3.h" - - - -#endif // SHADOW_ATLAS_GLES3_H -- cgit v1.2.3 From 27a46d78ec43b69a70a1d84c540353e3cb3b04c0 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Fri, 2 Dec 2016 22:23:16 -0300 Subject: Subsurface scattering material param is now working! --- drivers/gles3/rasterizer_scene_gles3.cpp | 91 +++++++++-- drivers/gles3/rasterizer_scene_gles3.h | 12 ++ drivers/gles3/rasterizer_storage_gles3.cpp | 21 ++- drivers/gles3/rasterizer_storage_gles3.h | 5 +- drivers/gles3/shader_compiler_gles3.cpp | 11 +- drivers/gles3/shader_compiler_gles3.h | 1 + drivers/gles3/shaders/SCsub | 2 + drivers/gles3/shaders/resolve.glsl | 12 +- drivers/gles3/shaders/scene.glsl | 42 +++++ drivers/gles3/shaders/screen_space_reflection.glsl | 7 +- drivers/gles3/shaders/subsurf_scattering.glsl | 172 +++++++++++++++++++++ 11 files changed, 344 insertions(+), 32 deletions(-) create mode 100644 drivers/gles3/shaders/subsurf_scattering.glsl (limited to 'drivers/gles3') diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 16784246f6..c4c7d4409d 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -1809,6 +1809,10 @@ void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_g mirror=!mirror; } + if (m->shader->spatial.uses_sss) { + state.used_sss=true; + } + if (p_shadow) { if (has_blend_alpha || (has_base_alpha && m->shader->spatial.depth_draw_mode!=RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS)) @@ -1827,6 +1831,7 @@ void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_g } + RenderList::Element *e = has_alpha ? render_list.add_alpha_element() : render_list.add_element(); if (!e) @@ -2620,6 +2625,7 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase** p_cull_result,int p_ current_geometry_index=0; current_material_index=0; + state.used_sss=false; //fill list @@ -2683,6 +2689,50 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env,const CameraMatrix &p_c glDisable(GL_CULL_FACE); glDisable(GL_BLEND); + if (state.used_sss) {//sss enabled + //copy diffuse while performing sss + + state.sss_shader.set_conditional(SubsurfScatteringShaderGLES3::USE_11_SAMPLES,subsurface_scatter_quality==SSS_QUALITY_LOW); + state.sss_shader.set_conditional(SubsurfScatteringShaderGLES3::USE_17_SAMPLES,subsurface_scatter_quality==SSS_QUALITY_MEDIUM); + state.sss_shader.set_conditional(SubsurfScatteringShaderGLES3::USE_25_SAMPLES,subsurface_scatter_quality==SSS_QUALITY_HIGH); + state.sss_shader.set_conditional(SubsurfScatteringShaderGLES3::ENABLE_FOLLOW_SURFACE,subsurface_scatter_follow_surface); + state.sss_shader.bind(); + state.sss_shader.set_uniform(SubsurfScatteringShaderGLES3::MAX_RADIUS,subsurface_scatter_size); + state.sss_shader.set_uniform(SubsurfScatteringShaderGLES3::FOVY,p_cam_projection.get_fov()); + state.sss_shader.set_uniform(SubsurfScatteringShaderGLES3::CAMERA_Z_NEAR,p_cam_projection.get_z_near()); + state.sss_shader.set_uniform(SubsurfScatteringShaderGLES3::CAMERA_Z_FAR,p_cam_projection.get_z_far()); + state.sss_shader.set_uniform(SubsurfScatteringShaderGLES3::DIR,Vector2(1,0)); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.diffuse); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.motion_sss); + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->depth); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); + + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->fbo); //copy to front first + + _copy_screen(); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->color); + state.sss_shader.set_uniform(SubsurfScatteringShaderGLES3::DIR,Vector2(0,1)); + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo); // copy to base level + _copy_screen(); + + } else { + // just copy diffuse + storage->shaders.copy.bind(); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.diffuse); + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo); // copy to base level + _copy_screen(); + + } + + + if (env->ssr_enabled) { //blur diffuse into effect mipmaps using separatable convolution //storage->shaders.copy.set_conditional(CopyShaderGLES3::GAUSSIAN_HORIZONTAL,true); @@ -2698,11 +2748,7 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env,const CameraMatrix &p_c 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)); glActiveTexture(GL_TEXTURE0); - if (i==0) { - glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.diffuse); - } else { - glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.mip_maps[0].color); //previous level, since mipmaps[0] starts one level bigger - } + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.mip_maps[0].color); //previous level, since mipmaps[0] starts one level bigger glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->effects.mip_maps[1].sizes[i].fbo); _copy_screen(); state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_HORIZONTAL,false); @@ -2748,7 +2794,7 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env,const CameraMatrix &p_c glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.diffuse); glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.normal_sr); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.normal_rough); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->depth); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); @@ -2764,22 +2810,26 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env,const CameraMatrix &p_c } + //copy reflection over diffuse, resolving SSR if needed state.resolve_shader.set_conditional(ResolveShaderGLES3::USE_SSR,env->ssr_enabled); state.resolve_shader.bind(); glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.diffuse); - glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.specular); if (env->ssr_enabled) { - glActiveTexture(GL_TEXTURE2); + glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.mip_maps[1].color); } glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo); - //glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->fbo); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_ONE,GL_ONE); //use additive to accumulate one over the other + _copy_screen(); + glDisable(GL_BLEND); //end additive + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::SIMPLE_COPY,true); state.effect_blur_shader.bind(); state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::LOD,float(0)); @@ -2839,6 +2889,7 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C bool use_mrt=true; + _fill_render_list(p_cull_result,p_cull_count,false); // @@ -2893,11 +2944,17 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C draw_buffers.push_back(GL_COLOR_ATTACHMENT0); draw_buffers.push_back(GL_COLOR_ATTACHMENT1); draw_buffers.push_back(GL_COLOR_ATTACHMENT2); + if (state.used_sss) { + draw_buffers.push_back(GL_COLOR_ATTACHMENT3); + } glDrawBuffers(draw_buffers.size(),draw_buffers.ptr()); Color black(0,0,0,0); glClearBufferfv(GL_COLOR,1,black.components); // specular glClearBufferfv(GL_COLOR,2,black.components); // normal metal rough + if (state.used_sss) { + glClearBufferfv(GL_COLOR,3,black.components); // normal metal rough + } } else { @@ -3968,11 +4025,25 @@ void RasterizerSceneGLES3::initialize() { state.resolve_shader.init(); state.ssr_shader.init(); state.effect_blur_shader.init(); + state.sss_shader.init(); + + + { + GLOBAL_DEF("rendering/gles3/subsurface_scattering/quality",1); + Globals::get_singleton()->set_custom_property_info("rendering/gles3/subsurface_scattering/quality",PropertyInfo(Variant::INT,"rendering/gles3/subsurface_scattering/quality",PROPERTY_HINT_ENUM,"Low,Medium,High")); + GLOBAL_DEF("rendering/gles3/subsurface_scattering/max_size",1.0); + Globals::get_singleton()->set_custom_property_info("rendering/gles3/subsurface_scattering/max_size",PropertyInfo(Variant::INT,"rendering/gles3/subsurface_scattering/max_size",PROPERTY_HINT_RANGE,"0.01,8,0.01")); + GLOBAL_DEF("rendering/gles3/subsurface_scattering/follow_surface",false); + } + } void RasterizerSceneGLES3::iteration() { shadow_filter_mode=ShadowFilterMode(int(Globals::get_singleton()->get("rendering/gles3/shadow_filter_mode"))); + subsurface_scatter_follow_surface=Globals::get_singleton()->get("rendering/gles3/subsurface_scattering/follow_surface"); + subsurface_scatter_quality=SubSurfaceScatterQuality(int(Globals::get_singleton()->get("rendering/gles3/subsurface_scattering/quality"))); + subsurface_scatter_size=Globals::get_singleton()->get("rendering/gles3/subsurface_scattering/max_size"); } void RasterizerSceneGLES3::finalize(){ diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 0b934085ed..21711292a0 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -7,6 +7,7 @@ #include "drivers/gles3/shaders/resolve.glsl.h" #include "drivers/gles3/shaders/screen_space_reflection.glsl.h" #include "drivers/gles3/shaders/effect_blur.glsl.h" +#include "drivers/gles3/shaders/subsurf_scattering.glsl.h" class RasterizerSceneGLES3 : public RasterizerScene { public: @@ -22,6 +23,15 @@ public: uint64_t shadow_atlas_realloc_tolerance_msec; + enum SubSurfaceScatterQuality { + SSS_QUALITY_LOW, + SSS_QUALITY_MEDIUM, + SSS_QUALITY_HIGH, + }; + + SubSurfaceScatterQuality subsurface_scatter_quality; + float subsurface_scatter_size; + bool subsurface_scatter_follow_surface; uint64_t render_pass; uint64_t scene_pass; @@ -51,6 +61,7 @@ public: ResolveShaderGLES3 resolve_shader; ScreenSpaceReflectionShaderGLES3 ssr_shader; EffectBlurShaderGLES3 effect_blur_shader; + SubsurfScatteringShaderGLES3 sss_shader; struct SceneDataUBO { @@ -118,6 +129,7 @@ public: int reflection_probe_count; bool cull_front; + bool used_sss; } state; diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 01668e728c..7b9a3f2af1 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -1456,6 +1456,7 @@ void RasterizerStorageGLES3::_update_shader(Shader* p_shader) const { p_shader->spatial.uses_alpha=false; p_shader->spatial.unshaded=false; p_shader->spatial.ontop=false; + p_shader->spatial.uses_sss=false; shaders.actions_scene.render_mode_values["blend_add"]=Pair(&p_shader->spatial.blend_mode,Shader::Spatial::BLEND_MODE_ADD); shaders.actions_scene.render_mode_values["blend_mix"]=Pair(&p_shader->spatial.blend_mode,Shader::Spatial::BLEND_MODE_MIX); @@ -1477,6 +1478,8 @@ void RasterizerStorageGLES3::_update_shader(Shader* p_shader) const { shaders.actions_scene.usage_flag_pointers["ALPHA"]=&p_shader->spatial.uses_alpha; shaders.actions_scene.usage_flag_pointers["VERTEX"]=&p_shader->spatial.uses_vertex; + shaders.actions_scene.usage_flag_pointers["SSS_STRENGTH"]=&p_shader->spatial.uses_sss; + actions=&shaders.actions_scene; actions->uniforms=&p_shader->uniforms; @@ -4771,7 +4774,8 @@ void RasterizerStorageGLES3::_render_target_clear(RenderTarget *rt) { glDeleteFramebuffers(1,&rt->buffers.alpha_fbo); glDeleteTextures(1,&rt->buffers.diffuse); glDeleteTextures(1,&rt->buffers.specular); - glDeleteTextures(1,&rt->buffers.normal_sr); + glDeleteTextures(1,&rt->buffers.normal_rough); + glDeleteTextures(1,&rt->buffers.motion_sss); rt->buffers.fbo=0; rt->buffers.alpha_fbo=0; } @@ -4923,14 +4927,23 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, rt->buffers.specular, 0); - glGenTextures(1, &rt->buffers.normal_sr); - glBindTexture(GL_TEXTURE_2D, rt->buffers.normal_sr); + glGenTextures(1, &rt->buffers.normal_rough); + glBindTexture(GL_TEXTURE_2D, rt->buffers.normal_rough); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, rt->width, rt->height, 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_ATTACHMENT2, GL_TEXTURE_2D, rt->buffers.normal_sr, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, rt->buffers.normal_rough, 0); + + glGenTextures(1, &rt->buffers.motion_sss); + glBindTexture(GL_TEXTURE_2D, rt->buffers.motion_sss); + glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, rt->width, rt->height, 0, GL_RED_INTEGER, 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); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, rt->buffers.motion_sss, 0); GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index 1eba8b42c9..e6b89eb66c 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -369,6 +369,7 @@ public: bool ontop; bool uses_vertex; bool uses_discard; + bool uses_sss; } spatial; @@ -886,8 +887,8 @@ public: GLuint alpha_fbo; //single buffer, just diffuse (for alpha pass) GLuint specular; GLuint diffuse; - GLuint normal_sr; - GLuint temporal; + GLuint normal_rough; + GLuint motion_sss; } buffers; struct Effects { diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp index c54fc011e9..5c7a72ab17 100644 --- a/drivers/gles3/shader_compiler_gles3.cpp +++ b/drivers/gles3/shader_compiler_gles3.cpp @@ -422,9 +422,9 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener used_name_defines.insert(vnode->name); } - if (p_actions.usage_flag_pointers.has(vnode->name) && !used_name_defines.has(vnode->name)) { + if (p_actions.usage_flag_pointers.has(vnode->name) && !used_flag_pointers.has(vnode->name)) { *p_actions.usage_flag_pointers[vnode->name]=true; - used_name_defines.insert(vnode->name); + used_flag_pointers.insert(vnode->name); } if (p_default_actions.renames.has(vnode->name)) @@ -670,6 +670,8 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() { actions[VS::SHADER_SPATIAL].renames["CLEARCOAT_GLOSS"]="clearcoat_gloss"; actions[VS::SHADER_SPATIAL].renames["ANISOTROPY"]="anisotropy"; actions[VS::SHADER_SPATIAL].renames["ANISOTROPY_FLOW"]="anisotropy_flow"; + actions[VS::SHADER_SPATIAL].renames["SSS_SPREAD"]="sss_spread"; + actions[VS::SHADER_SPATIAL].renames["SSS_STRENGTH"]="sss_strength"; actions[VS::SHADER_SPATIAL].renames["AO"]="ao"; actions[VS::SHADER_SPATIAL].renames["EMISSION"]="emission"; actions[VS::SHADER_SPATIAL].renames["DISCARD"]="_discard"; @@ -692,6 +694,11 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() { actions[VS::SHADER_SPATIAL].usage_defines["NORMALMAP_DEPTH"]="@NORMALMAP"; actions[VS::SHADER_SPATIAL].usage_defines["COLOR"]="#define ENABLE_COLOR_INTERP\n"; + actions[VS::SHADER_SPATIAL].usage_defines["SSS_STRENGTH"]="#define ENABLE_SSS_MOTION\n"; + + actions[VS::SHADER_SPATIAL].renames["SSS_STRENGTH"]="sss_strength"; + + actions[VS::SHADER_SPATIAL].render_mode_defines["skip_transform"]="#define SKIP_TRANSFORM_USED\n"; diff --git a/drivers/gles3/shader_compiler_gles3.h b/drivers/gles3/shader_compiler_gles3.h index 3549526808..1beee66ad7 100644 --- a/drivers/gles3/shader_compiler_gles3.h +++ b/drivers/gles3/shader_compiler_gles3.h @@ -58,6 +58,7 @@ private: StringName time_name; Set used_name_defines; + Set used_flag_pointers; Set used_rmode_defines; Set internal_functions; diff --git a/drivers/gles3/shaders/SCsub b/drivers/gles3/shaders/SCsub index 66a19eefd1..b5797e78b8 100644 --- a/drivers/gles3/shaders/SCsub +++ b/drivers/gles3/shaders/SCsub @@ -11,4 +11,6 @@ if env['BUILDERS'].has_key('GLES3_GLSL'): env.GLES3_GLSL('blend_shape.glsl'); env.GLES3_GLSL('screen_space_reflection.glsl'); env.GLES3_GLSL('effect_blur.glsl'); + env.GLES3_GLSL('subsurf_scattering.glsl'); + diff --git a/drivers/gles3/shaders/resolve.glsl b/drivers/gles3/shaders/resolve.glsl index 4ca6297303..6acc712299 100644 --- a/drivers/gles3/shaders/resolve.glsl +++ b/drivers/gles3/shaders/resolve.glsl @@ -17,11 +17,8 @@ void main() { in vec2 uv_interp; -uniform sampler2D source_diffuse; //texunit:0 -uniform sampler2D source_specular; //texunit:1 - - -uniform sampler2D source_ssr_ssao; //texunit:2 +uniform sampler2D source_specular; //texunit:0 +uniform sampler2D source_ssr; //texunit:1 uniform float stuff; @@ -31,15 +28,14 @@ layout(location = 0) out vec4 frag_color; void main() { - vec4 diffuse = texture( source_diffuse, uv_interp ); vec4 specular = texture( source_specular, uv_interp ); #ifdef USE_SSR - vec4 ssr = textureLod(source_ssr_ssao,uv_interp,0.0); + vec4 ssr = textureLod(source_ssr,uv_interp,0.0); specular.rgb = mix(specular.rgb,ssr.rgb*specular.a,ssr.a); #endif - frag_color = vec4(diffuse.rgb,1.0)+vec4(specular.rgb,1.0); + frag_color = vec4(specular.rgb,1.0); } diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index 192042192e..230544c1c3 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -75,6 +75,7 @@ layout(std140) uniform SceneData { //ubo:0 vec2 directional_shadow_pixel_size; float reflection_multiplier; + float subsurface_scatter_width; }; @@ -385,6 +386,7 @@ layout(std140) uniform SceneData { vec2 directional_shadow_pixel_size; float reflection_multiplier; + float subsurface_scatter_width; }; @@ -479,6 +481,9 @@ uniform int reflection_count; layout(location=0) out vec4 diffuse_buffer; layout(location=1) out vec4 specular_buffer; layout(location=2) out vec4 normal_mr_buffer; +#if defined (ENABLE_SSS_MOTION) +layout(location=3) out uint motion_ssr_buffer; +#endif #else @@ -621,6 +626,35 @@ in highp float dp_clip; #endif +#if 0 +//need to save texture depth for this + +vec3 light_transmittance(float translucency,vec3 light_vec, vec3 normal, vec3 pos, float distance) { + + float scale = 8.25 * (1.0 - translucency) / subsurface_scatter_width; + float d = scale * distance; + + /** + * Armed with the thickness, we can now calculate the color by means of the + * precalculated transmittance profile. + * (It can be precomputed into a texture, for maximum performance): + */ + float dd = -d * d; + vec3 profile = vec3(0.233, 0.455, 0.649) * exp(dd / 0.0064) + + vec3(0.1, 0.336, 0.344) * exp(dd / 0.0484) + + vec3(0.118, 0.198, 0.0) * exp(dd / 0.187) + + vec3(0.113, 0.007, 0.007) * exp(dd / 0.567) + + vec3(0.358, 0.004, 0.0) * exp(dd / 1.99) + + vec3(0.078, 0.0, 0.0) * exp(dd / 7.41); + + /** + * Using the profile, we finally approximate the transmitted lighting from + * the back of the object: + */ + return profile * clamp(0.3 + dot(light_vec, normal),0.0,1.0); +} +#endif + void light_process_omni(int idx, vec3 vertex, vec3 eye_vec,vec3 normal,vec3 binormal, vec3 tangent, vec3 albedo, vec3 specular, float roughness, float rim, float rim_tint, float clearcoat, float clearcoat_gloss,float anisotropy,inout vec3 diffuse_light, inout vec3 specular_light) { vec3 light_rel_vec = omni_lights[idx].light_pos_inv_radius.xyz-vertex; @@ -870,6 +904,10 @@ void main() { bool discard_=false; #endif +#if defined (ENABLE_SSS_MOTION) + float sss_strength=0.0; +#endif + { @@ -1194,6 +1232,10 @@ LIGHT_SHADER_CODE normal_mr_buffer=vec4(normalize(normal)*0.5+0.5,roughness); +#if defined (ENABLE_SSS_MOTION) + motion_ssr_buffer = uint(clamp(sqrt(sss_strength)*255.0,0.0,255))<<24; +#endif + #else diff --git a/drivers/gles3/shaders/screen_space_reflection.glsl b/drivers/gles3/shaders/screen_space_reflection.glsl index 5b24013c07..ec4bdf86c9 100644 --- a/drivers/gles3/shaders/screen_space_reflection.glsl +++ b/drivers/gles3/shaders/screen_space_reflection.glsl @@ -23,7 +23,6 @@ in vec2 pos_interp; uniform sampler2D source_diffuse; //texunit:0 uniform sampler2D source_normal_roughness; //texunit:1 uniform sampler2D source_depth; //texunit:2 -uniform sampler2D source_diffuse_mipmaps; //texunit:3 uniform float camera_z_near; uniform float camera_z_far; @@ -295,11 +294,7 @@ void main() { vec4 sample_color; { - sample_color = textureLod(source_diffuse_mipmaps,sample_pos,max(1.0,mipmap)); - if (mipmap<1.0) { //we use another image as base to avoid copying all the screen unnecesarily - vec4 base_sample_color = textureLod(source_diffuse,sample_pos,0.0); - sample_color = mix(base_sample_color,sample_color,mipmap); - } + sample_color = textureLod(source_diffuse,sample_pos,mipmap); } //multiply by gloss diff --git a/drivers/gles3/shaders/subsurf_scattering.glsl b/drivers/gles3/shaders/subsurf_scattering.glsl new file mode 100644 index 0000000000..89e618b66c --- /dev/null +++ b/drivers/gles3/shaders/subsurf_scattering.glsl @@ -0,0 +1,172 @@ +[vertex] + + +layout(location=0) in highp vec4 vertex_attrib; +layout(location=4) in vec2 uv_in; + +out vec2 uv_interp; + + +void main() { + + uv_interp = uv_in; + gl_Position = vertex_attrib; +} + +[fragment] + +//#define QUALIFIER uniform // some guy on the interweb says it may be faster with this +#define QUALIFIER const + +#ifdef USE_25_SAMPLES + +const int kernel_size=25; +QUALIFIER vec4 kernel[25] = vec4[] ( + vec4(0.530605, 0.613514, 0.739601, 0.0), + vec4(0.000973794, 1.11862e-005, 9.43437e-007, -3.0), + vec4(0.00333804, 7.85443e-005, 1.2945e-005, -2.52083), + vec4(0.00500364, 0.00020094, 5.28848e-005, -2.08333), + vec4(0.00700976, 0.00049366, 0.000151938, -1.6875), + vec4(0.0094389, 0.00139119, 0.000416598, -1.33333), + vec4(0.0128496, 0.00356329, 0.00132016, -1.02083), + vec4(0.017924, 0.00711691, 0.00347194, -0.75), + vec4(0.0263642, 0.0119715, 0.00684598, -0.520833), + vec4(0.0410172, 0.0199899, 0.0118481, -0.333333), + vec4(0.0493588, 0.0367726, 0.0219485, -0.1875), + vec4(0.0402784, 0.0657244, 0.04631, -0.0833333), + vec4(0.0211412, 0.0459286, 0.0378196, -0.0208333), + vec4(0.0211412, 0.0459286, 0.0378196, 0.0208333), + vec4(0.0402784, 0.0657244, 0.04631, 0.0833333), + vec4(0.0493588, 0.0367726, 0.0219485, 0.1875), + vec4(0.0410172, 0.0199899, 0.0118481, 0.333333), + vec4(0.0263642, 0.0119715, 0.00684598, 0.520833), + vec4(0.017924, 0.00711691, 0.00347194, 0.75), + vec4(0.0128496, 0.00356329, 0.00132016, 1.02083), + vec4(0.0094389, 0.00139119, 0.000416598, 1.33333), + vec4(0.00700976, 0.00049366, 0.000151938, 1.6875), + vec4(0.00500364, 0.00020094, 5.28848e-005, 2.08333), + vec4(0.00333804, 7.85443e-005, 1.2945e-005, 2.52083), + vec4(0.000973794, 1.11862e-005, 9.43437e-007, 3.0) +); + +#endif //USE_25_SAMPLES + +#ifdef USE_17_SAMPLES + +const int kernel_size=17; + +QUALIFIER vec4 kernel[17] = vec4[]( + vec4(0.536343, 0.624624, 0.748867, 0.0), + vec4(0.00317394, 0.000134823, 3.77269e-005, -2.0), + vec4(0.0100386, 0.000914679, 0.000275702, -1.53125), + vec4(0.0144609, 0.00317269, 0.00106399, -1.125), + vec4(0.0216301, 0.00794618, 0.00376991, -0.78125), + vec4(0.0347317, 0.0151085, 0.00871983, -0.5), + vec4(0.0571056, 0.0287432, 0.0172844, -0.28125), + vec4(0.0582416, 0.0659959, 0.0411329, -0.125), + vec4(0.0324462, 0.0656718, 0.0532821, -0.03125), + vec4(0.0324462, 0.0656718, 0.0532821, 0.03125), + vec4(0.0582416, 0.0659959, 0.0411329, 0.125), + vec4(0.0571056, 0.0287432, 0.0172844, 0.28125), + vec4(0.0347317, 0.0151085, 0.00871983, 0.5), + vec4(0.0216301, 0.00794618, 0.00376991, 0.78125), + vec4(0.0144609, 0.00317269, 0.00106399, 1.125), + vec4(0.0100386, 0.000914679, 0.000275702, 1.53125), + vec4(0.00317394, 0.000134823, 3.77269e-005, 2.0) +); + +#endif //USE_17_SAMPLES + + +#ifdef USE_11_SAMPLES + +const int kernel_size=11; + +QUALIFIER vec4 kernel[11] = vec4[]( + vec4(0.560479, 0.669086, 0.784728, 0.0), + vec4(0.00471691, 0.000184771, 5.07566e-005, -2.0), + vec4(0.0192831, 0.00282018, 0.00084214, -1.28), + vec4(0.03639, 0.0130999, 0.00643685, -0.72), + vec4(0.0821904, 0.0358608, 0.0209261, -0.32), + vec4(0.0771802, 0.113491, 0.0793803, -0.08), + vec4(0.0771802, 0.113491, 0.0793803, 0.08), + vec4(0.0821904, 0.0358608, 0.0209261, 0.32), + vec4(0.03639, 0.0130999, 0.00643685, 0.72), + vec4(0.0192831, 0.00282018, 0.00084214, 1.28), + vec4(0.00471691, 0.000184771, 5.07565e-005, 2.0) +); + +#endif //USE_11_SAMPLES + + +uniform float max_radius; +uniform float fovy; +uniform float camera_z_far; +uniform float camera_z_near; +uniform vec2 dir; +in vec2 uv_interp; + +uniform sampler2D source_diffuse; //texunit:0 +uniform highp usampler2D source_motion_ss; //texunit:1 +uniform sampler2D source_depth; //texunit:2 + +layout(location = 0) out vec4 frag_color; + +void main() { + + float strength = float(texture(source_motion_ss,uv_interp).r>>24)*(1.0/255.0); + strength*=strength; //stored as sqrt + + // Fetch color of current pixel: + vec4 base_color = texture(source_diffuse, uv_interp); + + if (strength>0.0) { + + + // Fetch linear depth of current pixel: + float depth = texture(source_depth, uv_interp).r * 2.0 - 1.0; + depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth * (camera_z_far - camera_z_near)); + depth=-depth; + + + // Calculate the radius scale (1.0 for a unit plane sitting on the + // projection window): + float distance = 1.0 / tan(0.5 * fovy); + float scale = distance / -depth; //remember depth is negative by default in OpenGL + + // Calculate the final step to fetch the surrounding pixels: + vec2 step = max_radius * scale * dir; + step *= strength; // Modulate it using the alpha channel. + step *= 1.0 / 3.0; // Divide by 3 as the kernels range from -3 to 3. + + // Accumulate the center sample: + vec3 color_accum = base_color.rgb; + color_accum *= kernel[0].rgb; + + // Accumulate the other samples: + for (int i = 1; i < kernel_size; i++) { + // Fetch color and depth for current sample: + vec2 offset = uv_interp + kernel[i].a * step; + vec3 color = texture(source_diffuse, offset).rgb; + +#ifdef ENABLE_FOLLOW_SURFACE + // If the difference in depth is huge, we lerp color back to "colorM": + float depth_cmp = texture(source_depth, offset).r *2.0 - 1.0; + depth_cmp = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth_cmp * (camera_z_far - camera_z_near)); + depth_cmp=-depth_cmp; + + float s = clamp(300.0f * distance * + max_radius * abs(depth - depth_cmp),0.0,1.0); + color = mix(color, base_color.rgb, s); +#endif + + // Accumulate: + color_accum += kernel[i].rgb * color; + } + + frag_color = vec4(color_accum,base_color.a); //keep alpha (used for SSAO) + } else { + frag_color = base_color; + } +} + -- cgit v1.2.3 From a299c3ebf1ceb3ce108526b3e134e82e5bf4413b Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Sun, 4 Dec 2016 12:45:30 -0300 Subject: Support for SSAO --- drivers/gles3/rasterizer_scene_gles3.cpp | 185 ++++++++++++++++++++- drivers/gles3/rasterizer_scene_gles3.h | 28 ++++ drivers/gles3/rasterizer_storage_gles3.cpp | 76 +++++++++ drivers/gles3/rasterizer_storage_gles3.h | 11 ++ drivers/gles3/shaders/SCsub | 3 + drivers/gles3/shaders/effect_blur.glsl | 17 ++ drivers/gles3/shaders/scene.glsl | 4 +- drivers/gles3/shaders/ssao.glsl | 247 +++++++++++++++++++++++++++++ drivers/gles3/shaders/ssao_blur.glsl | 113 +++++++++++++ drivers/gles3/shaders/ssao_minify.glsl | 55 +++++++ 10 files changed, 732 insertions(+), 7 deletions(-) create mode 100644 drivers/gles3/shaders/ssao.glsl create mode 100644 drivers/gles3/shaders/ssao_blur.glsl create mode 100644 drivers/gles3/shaders/ssao_minify.glsl (limited to 'drivers/gles3') diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index c4c7d4409d..2488f51e99 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -872,6 +872,25 @@ void RasterizerSceneGLES3::environment_set_ssr(RID p_env,bool p_enable, int p_ma } + +void RasterizerSceneGLES3::environment_set_ssao(RID p_env,bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect,const Color &p_color,bool p_blur) { + + Environment *env=environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + + env->ssao_enabled=p_enable; + env->ssao_radius=p_radius; + env->ssao_intensity=p_intensity; + env->ssao_radius2=p_radius2; + env->ssao_intensity2=p_intensity2; + env->ssao_bias=p_bias; + env->ssao_light_affect=p_light_affect; + env->ssao_color=p_color; + env->ssao_filter=p_blur; + +} + + void RasterizerSceneGLES3::environment_set_tonemap(RID p_env, bool p_enable, float p_exposure, float p_white, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale, VS::EnvironmentToneMapper p_tone_mapper){ } @@ -1460,7 +1479,7 @@ void RasterizerSceneGLES3::_setup_transform(InstanceBase *p_instance,const Trans } } - if (p_instance->billboard) { + if (p_instance->billboard && storage->frame.current_rt) { Vector3 scale = xf.basis.get_scale(); @@ -1473,7 +1492,7 @@ void RasterizerSceneGLES3::_setup_transform(InstanceBase *p_instance,const Trans xf.basis.scale(scale); } - if (p_instance->billboard_y) { + if (p_instance->billboard_y && storage->frame.current_rt) { Vector3 scale = xf.basis.get_scale(); Vector3 look_at = p_view_transform.get_origin(); @@ -2020,6 +2039,7 @@ void RasterizerSceneGLES3::_setup_environment(Environment *env,const CameraMatri state.ubo_data.bg_color[3]=bg_color.a; state.env_radiance_data.ambient_contribution=env->ambient_skybox_contribution; + state.ubo_data.ambient_occlusion_affect_light=env->ssao_light_affect; } else { state.ubo_data.bg_energy=1.0; state.ubo_data.ambient_energy=1.0; @@ -2036,6 +2056,7 @@ void RasterizerSceneGLES3::_setup_environment(Environment *env,const CameraMatri state.ubo_data.bg_color[3]=linear_ambient_color.a; state.env_radiance_data.ambient_contribution=0; + state.ubo_data.ambient_occlusion_affect_light=0; } @@ -2549,7 +2570,7 @@ void RasterizerSceneGLES3::_setup_reflections(RID *p_reflection_probe_cull_resul void RasterizerSceneGLES3::_copy_screen() { - glBindVertexArray(storage->resources.quadie_array); + glBindVertexArray( storage->resources.quadie_array); glDrawArrays(GL_TRIANGLE_FAN,0,4); glBindVertexArray(0); @@ -2689,6 +2710,141 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env,const CameraMatrix &p_c glDisable(GL_CULL_FACE); glDisable(GL_BLEND); + bool diffuse_copied=false; + + if (env->ssao_enabled) { + //ssao + + //copy from depth, convert to linear + GLint ss[2]; + ss[0]=storage->frame.current_rt->width; + ss[1]=storage->frame.current_rt->height; + + for(int i=0;iframe.current_rt->effects.ssao.depth_mipmap_fbos.size();i++) { + + state.ssao_minify_shader.set_conditional(SsaoMinifyShaderGLES3::MINIFY_START,i==0); + state.ssao_minify_shader.bind(); + state.ssao_minify_shader.set_uniform(SsaoMinifyShaderGLES3::CAMERA_Z_FAR,p_cam_projection.get_z_far()); + state.ssao_minify_shader.set_uniform(SsaoMinifyShaderGLES3::CAMERA_Z_NEAR,p_cam_projection.get_z_near()); + state.ssao_minify_shader.set_uniform(SsaoMinifyShaderGLES3::SOURCE_MIPMAP,MAX(0,i-1)); + glUniform2iv(state.ssao_minify_shader.get_uniform(SsaoMinifyShaderGLES3::FROM_SIZE),1,ss); + ss[0]>>=1; + ss[1]>>=1; + + glActiveTexture(GL_TEXTURE0); + if (i==0) { + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->depth); + } else { + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.ssao.linear_depth); + } + + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->effects.ssao.depth_mipmap_fbos[i]); //copy to front first + glViewport(0,0,ss[0],ss[1]); + + _copy_screen(); + + } + ss[0]=storage->frame.current_rt->width; + ss[1]=storage->frame.current_rt->height; + + glViewport(0,0,ss[0],ss[1]); + + + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_GREATER); + // do SSAO! + state.ssao_shader.set_conditional(SsaoShaderGLES3::ENABLE_RADIUS2,env->ssao_radius2>0.001); + state.ssao_shader.bind(); + state.ssao_shader.set_uniform(SsaoShaderGLES3::CAMERA_Z_FAR,p_cam_projection.get_z_far()); + state.ssao_shader.set_uniform(SsaoShaderGLES3::CAMERA_Z_NEAR,p_cam_projection.get_z_near()); + glUniform2iv(state.ssao_shader.get_uniform(SsaoShaderGLES3::SCREEN_SIZE),1,ss); + float radius = env->ssao_radius; + state.ssao_shader.set_uniform(SsaoShaderGLES3::RADIUS,radius); + float intensity = env->ssao_intensity; + state.ssao_shader.set_uniform(SsaoShaderGLES3::INTENSITY_DIV_R6,intensity / pow(radius, 6.0f)); + + if (env->ssao_radius2>0.001) { + + float radius2 = env->ssao_radius2; + state.ssao_shader.set_uniform(SsaoShaderGLES3::RADIUS2,radius2); + float intensity2 = env->ssao_intensity2; + state.ssao_shader.set_uniform(SsaoShaderGLES3::INTENSITY_DIV_R62,intensity2 / pow(radius2, 6.0f)); + + } + + float proj_info[4]={ + -2.0f / (ss[0]*p_cam_projection.matrix[0][0]), + -2.0f / (ss[1]*p_cam_projection.matrix[1][1]), + ( 1.0f - p_cam_projection.matrix[0][2]) / p_cam_projection.matrix[0][0], + ( 1.0f + p_cam_projection.matrix[1][2]) / p_cam_projection.matrix[1][1] + }; + + glUniform4fv(state.ssao_shader.get_uniform(SsaoShaderGLES3::PROJ_INFO),1,proj_info); + float pixels_per_meter = float(p_cam_projection.get_pixels_per_meter(ss[0])); + + state.ssao_shader.set_uniform(SsaoShaderGLES3::PROJ_SCALE,pixels_per_meter); + state.ssao_shader.set_uniform(SsaoShaderGLES3::BIAS,env->ssao_bias); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->depth); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.ssao.linear_depth); + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.normal_rough); + + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->effects.ssao.blur_fbo[0]); //copy to front first + Color white(1,1,1,1); + glClearBufferfv(GL_COLOR,0,white.components); // specular + + _copy_screen(); + + //do the batm, i mean blur + + state.ssao_blur_shader.bind(); + + if (env->ssao_filter) { + for(int i=0;i<2;i++) { + + state.ssao_blur_shader.set_uniform(SsaoBlurShaderGLES3::CAMERA_Z_FAR,p_cam_projection.get_z_far()); + state.ssao_blur_shader.set_uniform(SsaoBlurShaderGLES3::CAMERA_Z_NEAR,p_cam_projection.get_z_near()); + GLint axis[2]={i,1-i}; + glUniform2iv(state.ssao_blur_shader.get_uniform(SsaoBlurShaderGLES3::AXIS),1,axis); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.ssao.blur_red[i]); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->depth); + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->effects.ssao.blur_fbo[1-i]); + if (i==0) { + glClearBufferfv(GL_COLOR,0,white.components); // specular + } + _copy_screen(); + + } + } + + glDisable(GL_DEPTH_TEST); + glDepthFunc(GL_LEQUAL); + + // just copy diffuse while applying SSAO + + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::SSAO_MERGE,true); + state.effect_blur_shader.bind(); + state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::SSAO_COLOR,env->ssao_color); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.diffuse); //previous level, since mipmaps[0] starts one level bigger + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.ssao.blur_red[0]); //previous level, since mipmaps[0] starts one level bigger + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo); // copy to base level + _copy_screen(); + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::SSAO_MERGE,false); + + + + + diffuse_copied=true; + } + + if (state.used_sss) {//sss enabled //copy diffuse while performing sss @@ -2704,7 +2860,13 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env,const CameraMatrix &p_c state.sss_shader.set_uniform(SubsurfScatteringShaderGLES3::DIR,Vector2(1,0)); glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.diffuse); + if (diffuse_copied) { + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.mip_maps[0].color); + } else { + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.diffuse); + diffuse_copied=true; + } + glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.motion_sss); glActiveTexture(GL_TEXTURE2); @@ -2721,7 +2883,10 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env,const CameraMatrix &p_c glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo); // copy to base level _copy_screen(); - } else { + } + + + if (!diffuse_copied) { // just copy diffuse storage->shaders.copy.bind(); glActiveTexture(GL_TEXTURE0); @@ -2826,7 +2991,7 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env,const CameraMatrix &p_c glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_ONE,GL_ONE); //use additive to accumulate one over the other - _copy_screen(); + //_copy_screen(); glDisable(GL_BLEND); //end additive @@ -2878,6 +3043,11 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C } else { state.ubo_data.reflection_multiplier=1.0; } + + state.ubo_data.subsurface_scatter_width=subsurface_scatter_size; + + + _setup_environment(env,p_cam_projection,p_cam_transform); _setup_lights(p_light_cull_result,p_light_cull_count,p_cam_transform.affine_inverse(),p_cam_projection,p_shadow_atlas); @@ -4026,6 +4196,9 @@ void RasterizerSceneGLES3::initialize() { state.ssr_shader.init(); state.effect_blur_shader.init(); state.sss_shader.init(); + state.ssao_minify_shader.init(); + state.ssao_shader.init(); + state.ssao_blur_shader.init(); { diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 21711292a0..6b9295deee 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -8,6 +8,9 @@ #include "drivers/gles3/shaders/screen_space_reflection.glsl.h" #include "drivers/gles3/shaders/effect_blur.glsl.h" #include "drivers/gles3/shaders/subsurf_scattering.glsl.h" +#include "drivers/gles3/shaders/ssao_minify.glsl.h" +#include "drivers/gles3/shaders/ssao.glsl.h" +#include "drivers/gles3/shaders/ssao_blur.glsl.h" class RasterizerSceneGLES3 : public RasterizerScene { public: @@ -62,6 +65,9 @@ public: ScreenSpaceReflectionShaderGLES3 ssr_shader; EffectBlurShaderGLES3 effect_blur_shader; SubsurfScatteringShaderGLES3 sss_shader; + SsaoMinifyShaderGLES3 ssao_minify_shader; + SsaoShaderGLES3 ssao_shader; + SsaoBlurShaderGLES3 ssao_blur_shader; struct SceneDataUBO { @@ -81,6 +87,8 @@ public: float shadow_atlas_pixel_size[2]; float shadow_directional_pixel_size[2]; float reflection_multiplier; + float subsurface_scatter_width; + float ambient_occlusion_affect_light; } ubo_data; @@ -316,6 +324,15 @@ public: bool ssr_roughness; + bool ssao_enabled; + float ssao_intensity; + float ssao_radius; + float ssao_intensity2; + float ssao_radius2; + float ssao_bias; + float ssao_light_affect; + Color ssao_color; + bool ssao_filter; Environment() { bg_mode=VS::ENV_BG_CLEAR_COLOR; @@ -334,6 +351,16 @@ public: ssr_smooth=true; 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_filter=true; + + } }; @@ -353,6 +380,7 @@ public: 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_accel,float p_fade,float p_depth_tolerance,bool p_smooth,bool p_roughness); + virtual void environment_set_ssao(RID p_env,bool p_enable, float p_radius, float p_radius2, float p_intensity2, float p_intensity, float p_bias, float p_light_affect,const Color &p_color,bool p_blur); virtual void environment_set_tonemap(RID p_env,bool p_enable,float p_exposure,float p_white,float p_min_luminance,float p_max_luminance,float p_auto_exp_speed,float p_auto_exp_scale,VS::EnvironmentToneMapper p_tone_mapper); virtual void environment_set_adjustment(RID p_env,bool p_enable,float p_brightness,float p_contrast,float p_saturation,RID p_ramp); diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 7b9a3f2af1..f21b7021e9 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -4785,6 +4785,20 @@ void RasterizerStorageGLES3::_render_target_clear(RenderTarget *rt) { rt->depth=0; } + if (rt->effects.ssao.blur_fbo[0]) { + glDeleteFramebuffers(1,&rt->effects.ssao.blur_fbo[0]); + glDeleteTextures(1,&rt->effects.ssao.blur_red[0]); + glDeleteFramebuffers(1,&rt->effects.ssao.blur_fbo[1]); + glDeleteTextures(1,&rt->effects.ssao.blur_red[1]); + for(int i=0;ieffects.ssao.depth_mipmap_fbos.size();i++) { + glDeleteFramebuffers(1,&rt->effects.ssao.depth_mipmap_fbos[i]); + } + + rt->effects.ssao.depth_mipmap_fbos.clear(); + + glDeleteTextures(1,&rt->effects.ssao.linear_depth); + } + Texture *tex = texture_owner.get(rt->texture); tex->alloc_height=0; tex->alloc_width=0; @@ -5043,6 +5057,67 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){ //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); + + + } + ///////////////// ssao + + //AO strength textures + for(int i=0;i<2;i++) { + + glGenFramebuffers(1, &rt->effects.ssao.blur_fbo[i]); + glBindFramebuffer(GL_FRAMEBUFFER, rt->effects.ssao.blur_fbo[i]); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GL_TEXTURE_2D, rt->depth, 0); + + glGenTextures(1, &rt->effects.ssao.blur_red[i]); + glBindTexture(GL_TEXTURE_2D, rt->effects.ssao.blur_red[i]); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, rt->width, rt->height, 0, GL_RED, 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, rt->effects.ssao.blur_red[i], 0); + + status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) { + _render_target_clear(rt); + ERR_FAIL_COND( status != GL_FRAMEBUFFER_COMPLETE ); + } + + } + //5 mip levels for depth texture, but base is read separately + + glGenTextures(1, &rt->effects.ssao.linear_depth); + glBindTexture(GL_TEXTURE_2D, rt->effects.ssao.linear_depth); + + int ssao_w=rt->width/2; + int ssao_h=rt->height/2; + + + for(int i=0;i<4;i++) { //5, but 4 mips, base is read directly to save bw + + glTexImage2D(GL_TEXTURE_2D, i, GL_R16UI, ssao_w, ssao_h, 0, GL_RED_INTEGER, GL_UNSIGNED_SHORT, NULL); + ssao_w>>=1; + ssao_h>>=1; + } + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_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); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 3); + + for(int i=0;i<4;i++) { //5, but 4 mips, base is read directly to save bw + + GLuint fbo; + glGenFramebuffers(1, &fbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->effects.ssao.linear_depth, i); + rt->effects.ssao.depth_mipmap_fbos.push_back(fbo); } } @@ -5653,6 +5728,7 @@ void RasterizerStorageGLES3::initialize() { glBindBuffer(GL_ARRAY_BUFFER,0); //unbind } + //generic quadie for copying without touching skybox { //transform feedback buffers diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index e6b89eb66c..c2aea391b1 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -911,6 +911,17 @@ public: MipMaps mip_maps[2]; //first mipmap chain starts from full-screen //GLuint depth2; //depth for the second mipmap chain, in case of desiring upsampling + struct SSAO { + GLuint blur_fbo[2]; // blur fbo + GLuint blur_red[2]; // 8 bits red buffer + + GLuint linear_depth; + + Vector depth_mipmap_fbos; //fbos for depth mipmapsla ver + + SSAO() { blur_fbo[0]=0; blur_fbo[1]=0; linear_depth=0; } + } ssao; + Effects() { } diff --git a/drivers/gles3/shaders/SCsub b/drivers/gles3/shaders/SCsub index b5797e78b8..dd7ec45242 100644 --- a/drivers/gles3/shaders/SCsub +++ b/drivers/gles3/shaders/SCsub @@ -12,5 +12,8 @@ if env['BUILDERS'].has_key('GLES3_GLSL'): env.GLES3_GLSL('screen_space_reflection.glsl'); env.GLES3_GLSL('effect_blur.glsl'); env.GLES3_GLSL('subsurf_scattering.glsl'); + env.GLES3_GLSL('ssao.glsl'); + env.GLES3_GLSL('ssao_minify.glsl'); + env.GLES3_GLSL('ssao_blur.glsl'); diff --git a/drivers/gles3/shaders/effect_blur.glsl b/drivers/gles3/shaders/effect_blur.glsl index fc6de7f654..211b60ca2e 100644 --- a/drivers/gles3/shaders/effect_blur.glsl +++ b/drivers/gles3/shaders/effect_blur.glsl @@ -19,12 +19,22 @@ void main() { in vec2 uv_interp; uniform sampler2D source_color; //texunit:0 +#ifdef SSAO_MERGE +uniform sampler2D source_ssao; //texunit:1 +#endif + uniform float lod; uniform vec2 pixel_size; layout(location = 0) out vec4 frag_color; +#ifdef SSAO_MERGE + +uniform vec4 ssao_color; + +#endif + void main() { @@ -52,6 +62,13 @@ void main() { frag_color = color; #endif +#ifdef SSAO_MERGE + + vec4 color =textureLod( source_color, uv_interp,0.0); + float ssao =textureLod( source_ssao, uv_interp,0.0).r; + frag_color = vec4( mix(color.rgb,color.rgb*mix(ssao_color.rgb,vec3(1.0),ssao),color.a), 1.0 ); + +#endif } diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index 230544c1c3..61e9e37d2b 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -76,6 +76,7 @@ layout(std140) uniform SceneData { //ubo:0 float reflection_multiplier; float subsurface_scatter_width; + float ambient_occlusion_affect_light; }; @@ -387,6 +388,7 @@ layout(std140) uniform SceneData { float reflection_multiplier; float subsurface_scatter_width; + float ambient_occlusion_affect_light; }; @@ -1223,7 +1225,7 @@ LIGHT_SHADER_CODE float max_ambient=max(ambient_light.r,max(ambient_light.g,ambient_light.b)); float max_diffuse=max(diffuse_light.r,max(diffuse_light.g,diffuse_light.b)); float total_ambient = max_ambient+max_diffuse+max_emission; - float ambient_scale = (total_ambient>0.0) ? max_ambient/total_ambient : 0.0; + float ambient_scale = (total_ambient>0.0) ? (max_ambient+ambient_occlusion_affect_light*max_diffuse)/total_ambient : 0.0; #endif //ENABLE_AO diffuse_buffer=vec4(emission+diffuse_light+ambient_light,ambient_scale); diff --git a/drivers/gles3/shaders/ssao.glsl b/drivers/gles3/shaders/ssao.glsl new file mode 100644 index 0000000000..75f49ef37a --- /dev/null +++ b/drivers/gles3/shaders/ssao.glsl @@ -0,0 +1,247 @@ +[vertex] + + +layout(location=0) in highp vec4 vertex_attrib; + +void main() { + + gl_Position = vertex_attrib; + gl_Position.z=1.0; +} + +[fragment] + + +#define NUM_SAMPLES (11) + +// If using depth mip levels, the log of the maximum pixel offset before we need to switch to a lower +// miplevel to maintain reasonable spatial locality in the cache +// If this number is too small (< 3), too many taps will land in the same pixel, and we'll get bad variance that manifests as flashing. +// If it is too high (> 5), we'll get bad performance because we're not using the MIP levels effectively +#define LOG_MAX_OFFSET (3) + +// This must be less than or equal to the MAX_MIP_LEVEL defined in SSAO.cpp +#define MAX_MIP_LEVEL (4) + +// This is the number of turns around the circle that the spiral pattern makes. This should be prime to prevent +// taps from lining up. This particular choice was tuned for NUM_SAMPLES == 9 +#define NUM_SPIRAL_TURNS (7) + + +uniform sampler2D source_depth; //texunit:0 +uniform usampler2D source_depth_mipmaps; //texunit:1 +uniform sampler2D source_normal; //texunit:2 + +uniform ivec2 screen_size; +uniform float camera_z_far; +uniform float camera_z_near; + +uniform float intensity_div_r6; +uniform float radius; + +#ifdef ENABLE_RADIUS2 +uniform float intensity_div_r62; +uniform float radius2; +#endif + +uniform float bias; +uniform float proj_scale; + +layout(location = 0) out float visibility; + +uniform vec4 proj_info; + +vec3 reconstructCSPosition(vec2 S, float z) { + return vec3((S.xy * proj_info.xy + proj_info.zw) * z, z); +} + +vec3 getPosition(ivec2 ssP) { + vec3 P; + P.z = texelFetch(source_depth, ssP, 0).r; + + P.z = P.z * 2.0 - 1.0; + P.z = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - P.z * (camera_z_far - camera_z_near)); + P.z = -P.z; + + // Offset to pixel center + P = reconstructCSPosition(vec2(ssP) + vec2(0.5), P.z); + return P; +} + +/** Reconstructs screen-space unit normal from screen-space position */ +vec3 reconstructCSFaceNormal(vec3 C) { + return normalize(cross(dFdy(C), dFdx(C))); +} + + + +/** Returns a unit vector and a screen-space radius for the tap on a unit disk (the caller should scale by the actual disk radius) */ +vec2 tapLocation(int sampleNumber, float spinAngle, out float ssR){ + // Radius relative to ssR + float alpha = float(sampleNumber + 0.5) * (1.0 / NUM_SAMPLES); + float angle = alpha * (NUM_SPIRAL_TURNS * 6.28) + spinAngle; + + ssR = alpha; + return vec2(cos(angle), sin(angle)); +} + + +/** Read the camera-space position of the point at screen-space pixel ssP + unitOffset * ssR. Assumes length(unitOffset) == 1 */ +vec3 getOffsetPosition(ivec2 ssC, vec2 unitOffset, float ssR) { + // Derivation: + // mipLevel = floor(log(ssR / MAX_OFFSET)); + int mipLevel = clamp(int(floor(log2(ssR))) - LOG_MAX_OFFSET, 0, MAX_MIP_LEVEL); + + ivec2 ssP = ivec2(ssR * unitOffset) + ssC; + + vec3 P; + + // We need to divide by 2^mipLevel to read the appropriately scaled coordinate from a MIP-map. + // Manually clamp to the texture size because texelFetch bypasses the texture unit + ivec2 mipP = clamp(ssP >> mipLevel, ivec2(0), (screen_size >> mipLevel) - ivec2(1)); + + + if (mipLevel < 1) { + //read from depth buffer + P.z = texelFetch(source_depth, mipP, 0).r; + P.z = P.z * 2.0 - 1.0; + P.z = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - P.z * (camera_z_far - camera_z_near)); + P.z = -P.z; + + } else { + //read from mipmaps + uint d = texelFetch(source_depth_mipmaps, mipP, mipLevel-1).r; + P.z = -(float(d)/65535.0)*camera_z_far; + } + + + // Offset to pixel center + P = reconstructCSPosition(vec2(ssP) + vec2(0.5), P.z); + + return P; +} + + + +/** Compute the occlusion due to sample with index \a i about the pixel at \a ssC that corresponds + to camera-space point \a C with unit normal \a n_C, using maximum screen-space sampling radius \a ssDiskRadius + + Note that units of H() in the HPG12 paper are meters, not + unitless. The whole falloff/sampling function is therefore + unitless. In this implementation, we factor out (9 / radius). + + Four versions of the falloff function are implemented below +*/ +float sampleAO(in ivec2 ssC, in vec3 C, in vec3 n_C, in float ssDiskRadius,in float p_radius, in int tapIndex, in float randomPatternRotationAngle) { + // Offset on the unit disk, spun for this pixel + float ssR; + vec2 unitOffset = tapLocation(tapIndex, randomPatternRotationAngle, ssR); + ssR *= ssDiskRadius; + + // The occluding point in camera space + vec3 Q = getOffsetPosition(ssC, unitOffset, ssR); + + vec3 v = Q - C; + + float vv = dot(v, v); + float vn = dot(v, n_C); + + const float epsilon = 0.01; + float radius2 = p_radius*p_radius; + + // A: From the HPG12 paper + // Note large epsilon to avoid overdarkening within cracks + //return float(vv < radius2) * max((vn - bias) / (epsilon + vv), 0.0) * radius2 * 0.6; + + // B: Smoother transition to zero (lowers contrast, smoothing out corners). [Recommended] + float f=max(radius2 - vv, 0.0); + return f * f * f * max((vn - bias) / (epsilon + vv), 0.0); + + // C: Medium contrast (which looks better at high radii), no division. Note that the + // contribution still falls off with radius^2, but we've adjusted the rate in a way that is + // more computationally efficient and happens to be aesthetically pleasing. + // return 4.0 * max(1.0 - vv * invRadius2, 0.0) * max(vn - bias, 0.0); + + // D: Low contrast, no division operation + // return 2.0 * float(vv < radius * radius) * max(vn - bias, 0.0); +} + + + +void main() { + + + // Pixel being shaded + ivec2 ssC = ivec2(gl_FragCoord.xy); + + // World space point being shaded + vec3 C = getPosition(ssC); + +/* if (C.z <= -camera_z_far*0.999) { + // We're on the skybox + visibility=1.0; + return; + }*/ + + //visibility=-C.z/camera_z_far; + //return; + + //vec3 n_C = texelFetch(source_normal,ssC,0).rgb * 2.0 - 1.0; + + vec3 n_C = reconstructCSFaceNormal(C); + n_C = -n_C; + + + // Hash function used in the HPG12 AlchemyAO paper + float randomPatternRotationAngle = (3 * ssC.x ^ ssC.y + ssC.x * ssC.y) * 10; + + // Reconstruct normals from positions. These will lead to 1-pixel black lines + // at depth discontinuities, however the blur will wipe those out so they are not visible + // in the final image. + + // Choose the screen-space sample radius + // proportional to the projected area of the sphere + float ssDiskRadius = -proj_scale * radius / C.z; + + float sum = 0.0; + for (int i = 0; i < NUM_SAMPLES; ++i) { + sum += sampleAO(ssC, C, n_C, ssDiskRadius, radius,i, randomPatternRotationAngle); + } + + float A = max(0.0, 1.0 - sum * intensity_div_r6 * (5.0 / NUM_SAMPLES)); + +#ifdef ENABLE_RADIUS2 + + //go again for radius2 + randomPatternRotationAngle = (5 * ssC.x ^ ssC.y + ssC.x * ssC.y) * 11; + + // Reconstruct normals from positions. These will lead to 1-pixel black lines + // at depth discontinuities, however the blur will wipe those out so they are not visible + // in the final image. + + // Choose the screen-space sample radius + // proportional to the projected area of the sphere + ssDiskRadius = -proj_scale * radius2 / C.z; + + sum = 0.0; + for (int i = 0; i < NUM_SAMPLES; ++i) { + sum += sampleAO(ssC, C, n_C, ssDiskRadius,radius2, i, randomPatternRotationAngle); + } + + A= min(A,max(0.0, 1.0 - sum * intensity_div_r62 * (5.0 / NUM_SAMPLES))); +#endif + // Bilateral box-filter over a quad for free, respecting depth edges + // (the difference that this makes is subtle) + if (abs(dFdx(C.z)) < 0.02) { + A -= dFdx(A) * ((ssC.x & 1) - 0.5); + } + if (abs(dFdy(C.z)) < 0.02) { + A -= dFdy(A) * ((ssC.y & 1) - 0.5); + } + + visibility = A; + +} + + + diff --git a/drivers/gles3/shaders/ssao_blur.glsl b/drivers/gles3/shaders/ssao_blur.glsl new file mode 100644 index 0000000000..31f3841a2a --- /dev/null +++ b/drivers/gles3/shaders/ssao_blur.glsl @@ -0,0 +1,113 @@ +[vertex] + + +layout(location=0) in highp vec4 vertex_attrib; + + +void main() { + + gl_Position = vertex_attrib; + gl_Position.z=1.0; +} + +[fragment] + + +uniform sampler2D source_ssao; //texunit:0 +uniform sampler2D source_depth; //texunit:1 + + +layout(location = 0) out float visibility; + + +////////////////////////////////////////////////////////////////////////////////////////////// +// Tunable Parameters: + +/** Increase to make depth edges crisper. Decrease to reduce flicker. */ +#define EDGE_SHARPNESS (1.0) + +/** Step in 2-pixel intervals since we already blurred against neighbors in the + first AO pass. This constant can be increased while R decreases to improve + performance at the expense of some dithering artifacts. + + Morgan found that a scale of 3 left a 1-pixel checkerboard grid that was + unobjectionable after shading was applied but eliminated most temporal incoherence + from using small numbers of sample taps. + */ +#define SCALE (3) + +/** Filter radius in pixels. This will be multiplied by SCALE. */ +#define R (4) + + +////////////////////////////////////////////////////////////////////////////////////////////// + + +// Gaussian coefficients +const float gaussian[R + 1] = +// float[](0.356642, 0.239400, 0.072410, 0.009869); +// float[](0.398943, 0.241971, 0.053991, 0.004432, 0.000134); // stddev = 1.0 + float[](0.153170, 0.144893, 0.122649, 0.092902, 0.062970); // stddev = 2.0 +// float[](0.111220, 0.107798, 0.098151, 0.083953, 0.067458, 0.050920, 0.036108); // stddev = 3.0 + +/** (1, 0) or (0, 1)*/ +uniform ivec2 axis; + +uniform float camera_z_far; +uniform float camera_z_near; + +void main() { + + ivec2 ssC = ivec2(gl_FragCoord.xy); + + float depth = texelFetch(source_depth, ssC, 0).r; + + depth = depth * 2.0 - 1.0; + depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth * (camera_z_far - camera_z_near)); + + float depth_divide = 1.0 / camera_z_far; + + depth*=depth_divide; + + //if (depth > camera_z_far*0.999) { + // discard;//skybox + //} + + float sum = texelFetch(source_ssao, ssC, 0).r; + + // Base weight for depth falloff. Increase this for more blurriness, + // decrease it for better edge discrimination + float BASE = gaussian[0]; + float totalWeight = BASE; + sum *= totalWeight; + + + for (int r = -R; r <= R; ++r) { + // We already handled the zero case above. This loop should be unrolled and the static branch optimized out, + // so the IF statement has no runtime cost + if (r != 0) { + + ivec2 ppos = ssC + axis * (r * SCALE); + float value = texelFetch(source_ssao, ppos, 0).r; + float temp_depth = texelFetch(source_depth, ssC, 0).r; + + temp_depth = temp_depth * 2.0 - 1.0; + temp_depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - temp_depth * (camera_z_far - camera_z_near)); + temp_depth *= depth_divide; + + // spatial domain: offset gaussian tap + float weight = 0.3 + gaussian[abs(r)]; + + // range domain (the "bilateral" weight). As depth difference increases, decrease weight. + weight *= max(0.0, 1.0 + - (EDGE_SHARPNESS * 2000.0) * abs(temp_depth - depth) + ); + + sum += value * weight; + totalWeight += weight; + } + } + + const float epsilon = 0.0001; + visibility = sum / (totalWeight + epsilon); +} diff --git a/drivers/gles3/shaders/ssao_minify.glsl b/drivers/gles3/shaders/ssao_minify.glsl new file mode 100644 index 0000000000..df9045c28a --- /dev/null +++ b/drivers/gles3/shaders/ssao_minify.glsl @@ -0,0 +1,55 @@ +[vertex] + + +layout(location=0) in highp vec4 vertex_attrib; + +void main() { + + gl_Position = vertex_attrib; +} + +[fragment] + + +#ifdef MINIFY_START + +#define SDEPTH_TYPE highp sampler2D +uniform float camera_z_far; +uniform float camera_z_near; + +#else + +#define SDEPTH_TYPE mediump usampler2D + +#endif + +uniform SDEPTH_TYPE source_depth; //texunit:0 + +uniform ivec2 from_size; +uniform int source_mipmap; + +layout(location = 0) out mediump uint depth; + +void main() { + + + ivec2 ssP = ivec2(gl_FragCoord.xy); + + // Rotated grid subsampling to avoid XY directional bias or Z precision bias while downsampling. + // On DX9, the bit-and can be implemented with floating-point modulo + +#ifdef MINIFY_START + float fdepth = texelFetch(source_depth, clamp(ssP * 2 + ivec2(ssP.y & 1, ssP.x & 1), ivec2(0), from_size - ivec2(1)), source_mipmap).r; + fdepth = fdepth * 2.0 - 1.0; + fdepth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - fdepth * (camera_z_far - camera_z_near)); + fdepth /= camera_z_far; + depth = uint(clamp(fdepth*65535,0.0,65535.0)); + +#else + depth = texelFetch(source_depth, clamp(ssP * 2 + ivec2(ssP.y & 1, ssP.x & 1), ivec2(0), from_size - ivec2(1)), source_mipmap).r; +#endif + + +} + + -- cgit v1.2.3 From 9bc506067a0913a2f1f1cef4f99c3a517497d453 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Sun, 4 Dec 2016 13:08:38 -0300 Subject: fix small issue with copying reflections --- drivers/gles3/rasterizer_scene_gles3.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gles3') diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 2488f51e99..ad88bda719 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -2991,7 +2991,7 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env,const CameraMatrix &p_c glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_ONE,GL_ONE); //use additive to accumulate one over the other - //_copy_screen(); + _copy_screen(); glDisable(GL_BLEND); //end additive -- cgit v1.2.3 From 8534ced22d7b889dafb64ab0c40435c5b12b7cbc Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Wed, 7 Dec 2016 17:49:52 -0300 Subject: Tonemapping and Auto Exposure support --- drivers/gles3/rasterizer_scene_gles3.cpp | 235 ++++++++++++++++++++++++++++- drivers/gles3/rasterizer_scene_gles3.h | 29 +++- drivers/gles3/rasterizer_storage_gles3.cpp | 21 +++ drivers/gles3/rasterizer_storage_gles3.h | 15 +- drivers/gles3/shaders/SCsub | 2 + drivers/gles3/shaders/exposure.glsl | 98 ++++++++++++ drivers/gles3/shaders/tonemap.glsl | 97 ++++++++++++ 7 files changed, 487 insertions(+), 10 deletions(-) create mode 100644 drivers/gles3/shaders/exposure.glsl create mode 100644 drivers/gles3/shaders/tonemap.glsl (limited to 'drivers/gles3') diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index ad88bda719..4abeef89be 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -890,11 +890,24 @@ void RasterizerSceneGLES3::environment_set_ssao(RID p_env,bool p_enable, float p } +void RasterizerSceneGLES3::environment_set_tonemap(RID p_env,VS::EnvironmentToneMapper p_tone_mapper,float p_exposure,float p_white,bool p_auto_exposure,float p_min_luminance,float p_max_luminance,float p_auto_exp_speed,float p_auto_exp_scale) { -void RasterizerSceneGLES3::environment_set_tonemap(RID p_env, bool p_enable, float p_exposure, float p_white, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale, VS::EnvironmentToneMapper p_tone_mapper){ + Environment *env=environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + + + env->tone_mapper=p_tone_mapper; + env->tone_mapper_exposure=p_exposure; + env->tone_mapper_exposure_white=p_white; + env->auto_exposure=p_auto_exposure; + env->auto_exposure_speed=p_auto_exp_speed; + env->auto_exposure_min=p_min_luminance; + env->auto_exposure_max=p_max_luminance; + env->auto_exposure_grey=p_auto_exp_scale; } + void RasterizerSceneGLES3::environment_set_adjustment(RID p_env,bool p_enable,float p_brightness,float p_contrast,float p_saturation,RID p_ramp) { @@ -3010,6 +3023,172 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env,const CameraMatrix &p_c } +void RasterizerSceneGLES3::_post_process(Environment *env){ + + //copy to front buffer + + glDepthMask(GL_FALSE); + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + glDisable(GL_BLEND); + glDepthFunc(GL_LEQUAL); + glColorMask(1,1,1,1); + + //turn off everything used + + if (!env) { + //no environment, simply return and convert to SRGB + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->fbo); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.diffuse); + storage->shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB,true); + storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA,true); + storage->shaders.copy.bind(); + + _copy_screen(); + + storage->shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB,false); + storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA,false); //compute luminance + + return; + + } + + + //order of operation + //1) DOF Blur (first blur, then copy to buffer applying the blur) + //2) Motion Blur + //3) Bloom + //4) Tonemap + //5) Adjustments + + GLuint composite_from = storage->frame.current_rt->buffers.diffuse; + + + if ( env->auto_exposure) { + + //compute auto exposure + //first step, copy from image to luminance buffer + state.exposure_shader.set_conditional(ExposureShaderGLES3::EXPOSURE_BEGIN,true); + state.exposure_shader.bind(); + int ss[2]={ + storage->frame.current_rt->width, + storage->frame.current_rt->height, + }; + int ds[2]={ + exposure_shrink_size, + exposure_shrink_size, + }; + + glUniform2iv(state.exposure_shader.get_uniform(ExposureShaderGLES3::SOURCE_RENDER_SIZE),1,ss); + glUniform2iv(state.exposure_shader.get_uniform(ExposureShaderGLES3::TARGET_SIZE),1,ds); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.diffuse); + + + glBindFramebuffer(GL_FRAMEBUFFER,exposure_shrink[0].fbo); + glViewport(0,0,exposure_shrink_size,exposure_shrink_size); + + _copy_screen(); + + + + + + //second step, shrink to 2x2 pixels + state.exposure_shader.set_conditional(ExposureShaderGLES3::EXPOSURE_BEGIN,false); + state.exposure_shader.bind(); + //shrink from second to previous to last level + + int s_size=exposure_shrink_size/3; + for(int i=1;iget_ticks_usec(); + uint64_t tick_diff = storage->frame.current_rt->last_exposure_tick==0?0:tick-storage->frame.current_rt->last_exposure_tick; + storage->frame.current_rt->last_exposure_tick=tick; + + if (tick_diff==0 || tick_diff>1000000) { + state.exposure_shader.set_conditional(ExposureShaderGLES3::EXPOSURE_FORCE_SET,true); + + } + + state.exposure_shader.bind(); + + glBindFramebuffer(GL_FRAMEBUFFER,exposure_shrink[exposure_shrink.size()-1].fbo); + glViewport(0,0,1,1); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,exposure_shrink[exposure_shrink.size()-2].color); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->exposure.color); //read from previous + + + state.exposure_shader.set_uniform(ExposureShaderGLES3::EXPOSURE_ADJUST,env->auto_exposure_speed*(tick_diff/1000000.0)); + state.exposure_shader.set_uniform(ExposureShaderGLES3::MAX_LUMINANCE,env->auto_exposure_max); + state.exposure_shader.set_uniform(ExposureShaderGLES3::MIN_LUMINANCE,env->auto_exposure_min); + + _copy_screen(); + + state.exposure_shader.set_conditional(ExposureShaderGLES3::EXPOSURE_FORCE_SET,false); + state.exposure_shader.set_conditional(ExposureShaderGLES3::EXPOSURE_END,false); + + //last step, swap with the framebuffer exposure, so the right exposure is kept int he framebuffer + SWAP(exposure_shrink[exposure_shrink.size()-1].fbo,storage->frame.current_rt->exposure.fbo); + SWAP(exposure_shrink[exposure_shrink.size()-1].color,storage->frame.current_rt->exposure.color); + + + glViewport(0,0,storage->frame.current_rt->width,storage->frame.current_rt->height); + + } + + + 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_AUTO_EXPOSURE,env->auto_exposure); + + state.tonemap_shader.bind(); + + state.tonemap_shader.set_uniform(TonemapShaderGLES3::EXPOSURE,env->tone_mapper_exposure); + state.tonemap_shader.set_uniform(TonemapShaderGLES3::WHITE,env->tone_mapper_exposure_white); + + + if (env->auto_exposure) { + + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->exposure.color); + state.tonemap_shader.set_uniform(TonemapShaderGLES3::AUTO_EXPOSURE_GREY,env->auto_exposure_grey); + + } + + _copy_screen(); + + //turn off everything used + 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); + +} void RasterizerSceneGLES3::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){ @@ -3056,8 +3235,7 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C render_list.clear(); - bool use_mrt=true; - + bool use_mrt=false; _fill_render_list(p_cull_result,p_cull_count,false); @@ -3074,6 +3252,7 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C GLuint current_fbo; + if (probe) { ReflectionAtlas *ref_atlas = reflection_atlas_owner.getptr(probe->atlas); @@ -3100,6 +3279,8 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C } else { + use_mrt = state.used_sss || (env && (env->ssao_enabled || env->ssr_enabled)); //only enable MRT rendering if any of these is enabled + glViewport(0,0,storage->frame.current_rt->width,storage->frame.current_rt->height); if (use_mrt) { @@ -3267,9 +3448,11 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C return; } - _copy_to_front_buffer(env); -/* if (shadow_atlas) { + _post_process(env); + + + if (false && shadow_atlas) { //_copy_texture_to_front_buffer(shadow_atlas->depth); storage->canvas->canvas_begin(); @@ -3279,7 +3462,17 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C 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) { + + //_copy_texture_to_front_buffer(shadow_atlas->depth); + storage->canvas->canvas_begin(); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,exposure_shrink[4].color); +// glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->exposure.color); + 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) { @@ -4199,6 +4392,8 @@ void RasterizerSceneGLES3::initialize() { state.ssao_minify_shader.init(); state.ssao_shader.init(); state.ssao_blur_shader.init(); + state.exposure_shader.init(); + state.tonemap_shader.init(); { @@ -4209,6 +4404,34 @@ void RasterizerSceneGLES3::initialize() { GLOBAL_DEF("rendering/gles3/subsurface_scattering/follow_surface",false); } + exposure_shrink_size=243; + int max_exposure_shrink_size=exposure_shrink_size; + + while(max_exposure_shrink_size>0) { + + RasterizerStorageGLES3::RenderTarget::Exposure e; + + glGenFramebuffers(1, &e.fbo); + glBindFramebuffer(GL_FRAMEBUFFER, e.fbo); + + glGenTextures(1, &e.color); + glBindTexture(GL_TEXTURE_2D, e.color); + glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, max_exposure_shrink_size, max_exposure_shrink_size, 0, GL_RED, GL_FLOAT, 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); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + exposure_shrink.push_back(e); + max_exposure_shrink_size/=3; + + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + ERR_CONTINUE(status!=GL_FRAMEBUFFER_COMPLETE); + + + } + } void RasterizerSceneGLES3::iteration() { diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 6b9295deee..b0a875aa16 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -11,6 +11,8 @@ #include "drivers/gles3/shaders/ssao_minify.glsl.h" #include "drivers/gles3/shaders/ssao.glsl.h" #include "drivers/gles3/shaders/ssao_blur.glsl.h" +#include "drivers/gles3/shaders/exposure.glsl.h" +#include "drivers/gles3/shaders/tonemap.glsl.h" class RasterizerSceneGLES3 : public RasterizerScene { public: @@ -48,6 +50,9 @@ public: RasterizerStorageGLES3 *storage; + Vector exposure_shrink; + int exposure_shrink_size; + struct State { @@ -68,6 +73,8 @@ public: SsaoMinifyShaderGLES3 ssao_minify_shader; SsaoShaderGLES3 ssao_shader; SsaoBlurShaderGLES3 ssao_blur_shader; + ExposureShaderGLES3 exposure_shader; + TonemapShaderGLES3 tonemap_shader; struct SceneDataUBO { @@ -334,6 +341,15 @@ public: Color ssao_color; bool ssao_filter; + VS::EnvironmentToneMapper tone_mapper; + float tone_mapper_exposure; + float tone_mapper_exposure_white; + bool auto_exposure; + float auto_exposure_speed; + float auto_exposure_min; + float auto_exposure_max; + float auto_exposure_grey; + Environment() { bg_mode=VS::ENV_BG_CLEAR_COLOR; skybox_scale=1.0; @@ -360,6 +376,14 @@ public: ssao_light_affect=0; ssao_filter=true; + 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; } }; @@ -382,7 +406,8 @@ public: virtual void environment_set_ssr(RID p_env,bool p_enable, int p_max_steps,float p_accel,float p_fade,float p_depth_tolerance,bool p_smooth,bool p_roughness); virtual void environment_set_ssao(RID p_env,bool p_enable, float p_radius, float p_radius2, float p_intensity2, float p_intensity, float p_bias, float p_light_affect,const Color &p_color,bool p_blur); - virtual void environment_set_tonemap(RID p_env,bool p_enable,float p_exposure,float p_white,float p_min_luminance,float p_max_luminance,float p_auto_exp_speed,float p_auto_exp_scale,VS::EnvironmentToneMapper p_tone_mapper); + virtual void environment_set_tonemap(RID p_env,VS::EnvironmentToneMapper p_tone_mapper,float p_exposure,float p_white,bool p_auto_exposure,float p_min_luminance,float p_max_luminance,float p_auto_exp_speed,float p_auto_exp_scale); + virtual void environment_set_adjustment(RID p_env,bool p_enable,float p_brightness,float p_contrast,float p_saturation,RID p_ramp); @@ -618,6 +643,8 @@ public: void _fill_render_list(InstanceBase** p_cull_result,int p_cull_count,bool p_shadow); void _render_mrts(Environment *env, const CameraMatrix &p_cam_projection); + void _post_process(Environment *env); + 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 f21b7021e9..ddb60273e4 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -4799,6 +4799,10 @@ void RasterizerStorageGLES3::_render_target_clear(RenderTarget *rt) { glDeleteTextures(1,&rt->effects.ssao.linear_depth); } + if (rt->exposure.fbo) { + glDeleteFramebuffers(1,&rt->exposure.fbo); + glDeleteTextures(1,&rt->exposure.color); + } Texture *tex = texture_owner.get(rt->texture); tex->alloc_height=0; tex->alloc_width=0; @@ -5120,6 +5124,23 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){ rt->effects.ssao.depth_mipmap_fbos.push_back(fbo); } + + //////Exposure + + glGenFramebuffers(1, &rt->exposure.fbo); + glBindFramebuffer(GL_FRAMEBUFFER, rt->exposure.fbo); + + 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); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->exposure.color, 0); + + status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) { + _render_target_clear(rt); + ERR_FAIL_COND( status != GL_FRAMEBUFFER_COMPLETE ); + } + } } diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index c2aea391b1..7802b28158 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -922,12 +922,19 @@ public: SSAO() { blur_fbo[0]=0; blur_fbo[1]=0; linear_depth=0; } } ssao; - Effects() { - - } + Effects() {} } effects; + struct Exposure { + GLuint fbo; + GLuint color; + + Exposure() { fbo=0; } + } exposure; + + uint64_t last_exposure_tick; + int width,height; bool flags[RENDER_TARGET_FLAG_MAX]; @@ -950,6 +957,8 @@ public: flags[RENDER_TARGET_TRANSPARENT]=false; flags[RENDER_TARGET_NO_3D]=false; flags[RENDER_TARGET_NO_SAMPLING]=false; + + last_exposure_tick=0; } }; diff --git a/drivers/gles3/shaders/SCsub b/drivers/gles3/shaders/SCsub index dd7ec45242..272f9bb5e1 100644 --- a/drivers/gles3/shaders/SCsub +++ b/drivers/gles3/shaders/SCsub @@ -15,5 +15,7 @@ if env['BUILDERS'].has_key('GLES3_GLSL'): env.GLES3_GLSL('ssao.glsl'); env.GLES3_GLSL('ssao_minify.glsl'); env.GLES3_GLSL('ssao_blur.glsl'); + env.GLES3_GLSL('exposure.glsl'); + env.GLES3_GLSL('tonemap.glsl'); diff --git a/drivers/gles3/shaders/exposure.glsl b/drivers/gles3/shaders/exposure.glsl new file mode 100644 index 0000000000..001b90a0f1 --- /dev/null +++ b/drivers/gles3/shaders/exposure.glsl @@ -0,0 +1,98 @@ +[vertex] + + +layout(location=0) in highp vec4 vertex_attrib; + + +void main() { + + gl_Position = vertex_attrib; + +} + +[fragment] + + +uniform highp sampler2D source_exposure; //texunit:0 + +#ifdef EXPOSURE_BEGIN + +uniform highp ivec2 source_render_size; +uniform highp ivec2 target_size; + +#endif + +#ifdef EXPOSURE_END + +uniform highp sampler2D prev_exposure; //texunit:1 +uniform highp float exposure_adjust; +uniform highp float min_luminance; +uniform highp float max_luminance; + +#endif + +layout(location = 0) out highp float exposure; + + + +void main() { + + + +#ifdef EXPOSURE_BEGIN + + + ivec2 src_pos = ivec2(gl_FragCoord.xy)*source_render_size/target_size; + +#if 1 + //more precise and expensive, but less jittery + ivec2 next_pos = ivec2(gl_FragCoord.xy+ivec2(1))*source_render_size/target_size; + next_pos = max(next_pos,src_pos+ivec2(1)); //so it at least reads one pixel + highp vec3 source_color=vec3(0.0); + for(int i=src_pos.x;i 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))); + + + + + frag_color=vec4(color.rgb,1.0); +} + + -- cgit v1.2.3 From 18ebd22000478dffc91255e89b9845f74b05b606 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Thu, 8 Dec 2016 09:48:38 -0300 Subject: Multi stage glow with light bleeding from HDR --- drivers/gles3/rasterizer_scene_gles3.cpp | 160 ++++++++++++++++++++++++++++- drivers/gles3/rasterizer_scene_gles3.h | 22 +++- drivers/gles3/rasterizer_storage_gles3.cpp | 4 +- drivers/gles3/shaders/effect_blur.glsl | 67 ++++++++++++ drivers/gles3/shaders/tonemap.glsl | 81 +++++++++++++++ 5 files changed, 329 insertions(+), 5 deletions(-) (limited to 'drivers/gles3') diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 4abeef89be..ec304e7a46 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -850,7 +850,19 @@ void RasterizerSceneGLES3::environment_set_ambient_light(RID p_env, const Color& } -void RasterizerSceneGLES3::environment_set_glow(RID p_env,bool p_enable,int p_radius,float p_intensity,float p_strength,float p_bloom_treshold,VS::EnvironmentGlowBlendMode p_blend_mode){ +void RasterizerSceneGLES3::environment_set_glow(RID p_env,bool p_enable,int p_level_flags,float p_intensity,float p_strength,float p_bloom_treshold,VS::EnvironmentGlowBlendMode p_blend_mode,float p_hdr_bleed_treshold,float p_hdr_bleed_scale) { + + Environment *env=environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + + env->glow_enabled=p_enable; + env->glow_levels=p_level_flags; + env->glow_intensity=p_intensity; + env->glow_strength=p_strength; + env->glow_bloom=p_bloom_treshold; + env->glow_blend_mode=p_blend_mode; + env->glow_hdr_bleed_treshold=p_hdr_bleed_treshold; + env->glow_hdr_bleed_scale=p_hdr_bleed_scale; } void RasterizerSceneGLES3::environment_set_fog(RID p_env,bool p_enable,float p_begin,float p_end,RID p_gradient_texture){ @@ -3155,6 +3167,95 @@ void RasterizerSceneGLES3::_post_process(Environment *env){ } + int max_glow_level=-1; + int glow_mask=0; + + + if (env->glow_enabled) { + + + for(int i=0;iglow_levels&(1<=storage->frame.current_rt->effects.mip_maps[1].sizes.size()) { + max_glow_level=storage->frame.current_rt->effects.mip_maps[1].sizes.size()-1; + glow_mask|=1<shaders.copy.set_conditional(CopyShaderGLES3::GAUSSIAN_HORIZONTAL,true); + + for(int i=0;i<(max_glow_level+1);i++) { + + + int vp_w = storage->frame.current_rt->effects.mip_maps[1].sizes[i].width; + int vp_h = storage->frame.current_rt->effects.mip_maps[1].sizes[i].height; + glViewport(0,0,vp_w,vp_h); + //horizontal pass + if (i==0) { + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GLOW_FIRST_PASS,true); + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GLOW_USE_AUTO_EXPOSURE,env->auto_exposure); + } + + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GLOW_GAUSSIAN_HORIZONTAL,true); + state.effect_blur_shader.bind(); + 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); + + glActiveTexture(GL_TEXTURE0); + if (i==0) { + glBindTexture(GL_TEXTURE_2D,composite_from); + + state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::EXPOSURE,env->tone_mapper_exposure); + if (env->auto_exposure) { + state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::AUTO_EXPOSURE_GREY,env->auto_exposure_grey); + } + + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->exposure.color); + + state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::GLOW_BLOOM,env->glow_bloom); + state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::GLOW_HDR_TRESHOLD,env->glow_hdr_bleed_treshold); + state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::GLOW_HDR_SCALE,env->glow_hdr_bleed_scale); + + } else { + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.mip_maps[0].color); //previous level, since mipmaps[0] starts one level bigger + } + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->effects.mip_maps[1].sizes[i].fbo); + _copy_screen(); + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GLOW_GAUSSIAN_HORIZONTAL,false); + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GLOW_FIRST_PASS,false); + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GLOW_USE_AUTO_EXPOSURE,false); + + //vertical pass + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GLOW_GAUSSIAN_VERTICAL,true); + state.effect_blur_shader.bind(); + 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); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.mip_maps[1].color); + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->effects.mip_maps[0].sizes[i+1].fbo); //next level, since mipmaps[0] starts one level bigger + _copy_screen(); + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GLOW_GAUSSIAN_VERTICAL,false); + } + + glViewport(0,0,storage->frame.current_rt->width,storage->frame.current_rt->height); + + } + + + + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->fbo); glActiveTexture(GL_TEXTURE0); @@ -3166,11 +3267,55 @@ void RasterizerSceneGLES3::_post_process(Environment *env){ state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_AUTO_EXPOSURE,env->auto_exposure); + + + if (max_glow_level>=0) { + + + for(int i=0;i<(max_glow_level+1);i++) { + + if (glow_mask&(1<glow_blend_mode==VS::GLOW_BLEND_MODE_SCREEN); + state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_SOFTLIGHT,env->glow_blend_mode==VS::GLOW_BLEND_MODE_SOFTLIGHT); + state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_REPLACE,env->glow_blend_mode==VS::GLOW_BLEND_MODE_REPLACE); + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.mip_maps[0].color); + + } + state.tonemap_shader.bind(); state.tonemap_shader.set_uniform(TonemapShaderGLES3::EXPOSURE,env->tone_mapper_exposure); state.tonemap_shader.set_uniform(TonemapShaderGLES3::WHITE,env->tone_mapper_exposure_white); + if (max_glow_level>=0) { + + state.tonemap_shader.set_uniform(TonemapShaderGLES3::GLOW_INTENSITY,env->glow_intensity); + } if (env->auto_exposure) { @@ -3180,6 +3325,8 @@ void RasterizerSceneGLES3::_post_process(Environment *env){ } + + _copy_screen(); //turn off everything used @@ -3187,7 +3334,16 @@ void RasterizerSceneGLES3::_post_process(Environment *env){ 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_GLOW_LEVEL1,false); + state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL2,false); + state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL3,false); + state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL4,false); + state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL5,false); + state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL6,false); + state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL7,false); + state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_REPLACE,false); + state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_SCREEN,false); + state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_SOFTLIGHT,false); } void RasterizerSceneGLES3::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){ diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index b0a875aa16..6ca4529ed9 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -341,6 +341,15 @@ public: Color ssao_color; bool ssao_filter; + bool glow_enabled; + int glow_levels; + float glow_intensity; + float glow_strength; + float glow_bloom; + VS::EnvironmentGlowBlendMode glow_blend_mode; + float glow_hdr_bleed_treshold; + float glow_hdr_bleed_scale; + VS::EnvironmentToneMapper tone_mapper; float tone_mapper_exposure; float tone_mapper_exposure_white; @@ -350,6 +359,7 @@ public: float auto_exposure_max; float auto_exposure_grey; + Environment() { bg_mode=VS::ENV_BG_CLEAR_COLOR; skybox_scale=1.0; @@ -385,6 +395,16 @@ public: 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_treshold=1.0; + glow_hdr_bleed_scale=2.0; + + } }; @@ -400,7 +420,7 @@ public: 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_skybox_contribution=0.0); - virtual void environment_set_glow(RID p_env,bool p_enable,int p_radius,float p_intensity,float p_strength,float p_bloom_treshold,VS::EnvironmentGlowBlendMode p_blend_mode); + virtual void environment_set_glow(RID p_env,bool p_enable,int p_level_flags,float p_intensity,float p_strength,float p_bloom_treshold,VS::EnvironmentGlowBlendMode p_blend_mode,float p_hdr_bleed_treshold,float p_hdr_bleed_scale); 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_accel,float p_fade,float p_depth_tolerance,bool p_smooth,bool p_roughness); diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index ddb60273e4..cfa50f6100 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -5020,8 +5020,8 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){ w>>=1; h>>=1; - if (w<32 || h<32) - break; //going less than 32 is pointless + if (w<2 || h<2) + break; level++; diff --git a/drivers/gles3/shaders/effect_blur.glsl b/drivers/gles3/shaders/effect_blur.glsl index 211b60ca2e..589af64d44 100644 --- a/drivers/gles3/shaders/effect_blur.glsl +++ b/drivers/gles3/shaders/effect_blur.glsl @@ -35,6 +35,31 @@ uniform vec4 ssao_color; #endif +#if defined (GLOW_GAUSSIAN_HORIZONTAL) || defined(GLOW_GAUSSIAN_VERTICAL) + +uniform float glow_strength; + +#endif + + +#ifdef GLOW_FIRST_PASS + +uniform float exposure; +uniform float white; + +#ifdef GLOW_USE_AUTO_EXPOSURE + +uniform highp sampler2D source_auto_exposure; //texunit:1 +uniform highp float auto_exposure_grey; + +#endif + +uniform float glow_bloom; +uniform float glow_hdr_treshold; +uniform float glow_hdr_scale; + +#endif + void main() { @@ -57,6 +82,48 @@ void main() { frag_color = color; #endif + + +#ifdef GLOW_GAUSSIAN_HORIZONTAL + vec4 color =textureLod( source_color, uv_interp+vec2( 0.0, 0.0)*pixel_size,lod )*0.174938; + color+=textureLod( source_color, uv_interp+vec2( 1.0, 0.0)*pixel_size,lod )*0.165569; + color+=textureLod( source_color, uv_interp+vec2( 2.0, 0.0)*pixel_size,lod )*0.140367; + color+=textureLod( source_color, uv_interp+vec2( 3.0, 0.0)*pixel_size,lod )*0.106595; + color+=textureLod( source_color, uv_interp+vec2(-1.0, 0.0)*pixel_size,lod )*0.165569; + color+=textureLod( source_color, uv_interp+vec2(-2.0, 0.0)*pixel_size,lod )*0.140367; + color+=textureLod( source_color, uv_interp+vec2(-3.0, 0.0)*pixel_size,lod )*0.165569; + color*=glow_strength; + frag_color = color; +#endif + +#ifdef GLOW_GAUSSIAN_VERTICAL + vec4 color =textureLod( source_color, uv_interp+vec2(0.0, 0.0)*pixel_size,lod )*0.174938; + color+=textureLod( source_color, uv_interp+vec2(0.0, 1.0)*pixel_size,lod )*0.165569; + color+=textureLod( source_color, uv_interp+vec2(0.0, 2.0)*pixel_size,lod )*0.140367; + color+=textureLod( source_color, uv_interp+vec2(0.0, 3.0)*pixel_size,lod )*0.106595; + color+=textureLod( source_color, uv_interp+vec2(0.0,-1.0)*pixel_size,lod )*0.165569; + color+=textureLod( source_color, uv_interp+vec2(0.0,-2.0)*pixel_size,lod )*0.140367; + color+=textureLod( source_color, uv_interp+vec2(0.0,-3.0)*pixel_size,lod )*0.165569; + color*=glow_strength; + frag_color = color; +#endif + +#ifdef GLOW_FIRST_PASS + +#ifdef GLOW_USE_AUTO_EXPOSURE + + frag_color/=texelFetch(source_auto_exposure,ivec2(0,0),0).r/auto_exposure_grey; +#endif + frag_color*=exposure; + + float luminance = max(frag_color.r,max(frag_color.g,frag_color.b)); + float feedback = max( smoothstep(glow_hdr_treshold,glow_hdr_treshold+glow_hdr_scale,luminance), glow_bloom ); + + frag_color *= feedback; + +#endif + + #ifdef SIMPLE_COPY vec4 color =textureLod( source_color, uv_interp,0.0); frag_color = color; diff --git a/drivers/gles3/shaders/tonemap.glsl b/drivers/gles3/shaders/tonemap.glsl index 566d194a02..8ee51e9d0c 100644 --- a/drivers/gles3/shaders/tonemap.glsl +++ b/drivers/gles3/shaders/tonemap.glsl @@ -2,17 +2,24 @@ layout(location=0) in highp vec4 vertex_attrib; +layout(location=4) in vec2 uv_in; + +out vec2 uv_interp; + void main() { gl_Position = vertex_attrib; + uv_interp = uv_in; } [fragment] +in vec2 uv_interp; + uniform highp sampler2D source; //texunit:0 uniform float exposure; @@ -25,6 +32,12 @@ uniform highp float auto_exposure_grey; #endif +#if defined(USE_GLOW_LEVEL1) || defined(USE_GLOW_LEVEL2) || defined(USE_GLOW_LEVEL3) || defined(USE_GLOW_LEVEL4) || defined(USE_GLOW_LEVEL5) || defined(USE_GLOW_LEVEL6) || defined(USE_GLOW_LEVEL7) + +uniform highp sampler2D source_glow; //texunit:2 +uniform highp float glow_intensity; + +#endif layout(location = 0) out vec4 frag_color; @@ -43,6 +56,74 @@ void main() { color*=exposure; +#if defined(USE_GLOW_LEVEL1) || defined(USE_GLOW_LEVEL2) || defined(USE_GLOW_LEVEL3) || defined(USE_GLOW_LEVEL4) || defined(USE_GLOW_LEVEL5) || defined(USE_GLOW_LEVEL6) || defined(USE_GLOW_LEVEL7) + vec3 glow = vec3(0.0); + +#ifdef USE_GLOW_LEVEL1 + glow+=textureLod(source_glow,uv_interp,1.0).rgb; +#endif + +#ifdef USE_GLOW_LEVEL2 + glow+=textureLod(source_glow,uv_interp,2.0).rgb; +#endif + +#ifdef USE_GLOW_LEVEL3 + glow+=textureLod(source_glow,uv_interp,3.0).rgb; +#endif + +#ifdef USE_GLOW_LEVEL4 + glow+=textureLod(source_glow,uv_interp,4.0).rgb; +#endif + +#ifdef USE_GLOW_LEVEL5 + glow+=textureLod(source_glow,uv_interp,5.0).rgb; +#endif + +#ifdef USE_GLOW_LEVEL6 + glow+=textureLod(source_glow,uv_interp,6.0).rgb; +#endif + +#ifdef USE_GLOW_LEVEL7 + glow+=textureLod(source_glow,uv_interp,7.0).rgb; +#endif + + + glow *= glow_intensity; + + + +#ifdef USE_GLOW_REPLACE + + color.rgb = glow; + +#endif + +#ifdef USE_GLOW_SCREEN + + color.rgb = clamp((color.rgb + glow) - (color.rgb * glow), 0.0, 1.0); + +#endif + +#ifdef USE_GLOW_SOFTLIGHT + + { + + glow = (glow * 0.5) + 0.5; + color.r = (glow.r <= 0.5) ? (color.r - (1.0 - 2.0 * glow.r) * color.r * (1.0 - color.r)) : (((glow.r > 0.5) && (color.r <= 0.25)) ? (color.r + (2.0 * glow.r - 1.0) * (4.0 * color.r * (4.0 * color.r + 1.0) * (color.r - 1.0) + 7.0 * color.r)) : (color.r + (2.0 * glow.r - 1.0) * (sqrt(color.r) - color.r))); + color.g = (glow.g <= 0.5) ? (color.g - (1.0 - 2.0 * glow.g) * color.g * (1.0 - color.g)) : (((glow.g > 0.5) && (color.g <= 0.25)) ? (color.g + (2.0 * glow.g - 1.0) * (4.0 * color.g * (4.0 * color.g + 1.0) * (color.g - 1.0) + 7.0 * color.g)) : (color.g + (2.0 * glow.g - 1.0) * (sqrt(color.g) - color.g))); + color.b = (glow.b <= 0.5) ? (color.b - (1.0 - 2.0 * glow.b) * color.b * (1.0 - color.b)) : (((glow.b > 0.5) && (color.b <= 0.25)) ? (color.b + (2.0 * glow.b - 1.0) * (4.0 * color.b * (4.0 * color.b + 1.0) * (color.b - 1.0) + 7.0 * color.b)) : (color.b + (2.0 * glow.b - 1.0) * (sqrt(color.b) - color.b))); + } + +#endif + +#if !defined(USE_GLOW_SCREEN) && !defined(USE_GLOW_SOFTLIGHT) && !defined(USE_GLOW_REPLACE) + color.rgb+=glow; +#endif + + +#endif + + #ifdef USE_REINDHART_TONEMAPPER { -- cgit v1.2.3 From 22a90e8f2acce60f92958788a52b3f0bdb1a0cdf Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Sat, 10 Dec 2016 01:13:20 -0300 Subject: DOF blur, near and far fields.. --- drivers/gles3/rasterizer_scene_gles3.cpp | 196 ++++++++++++++++++++++++++++++- drivers/gles3/rasterizer_scene_gles3.h | 31 ++++- drivers/gles3/shaders/effect_blur.glsl | 177 ++++++++++++++++++++++++---- drivers/gles3/shaders/tonemap.glsl | 99 ++++++++++++++-- 4 files changed, 471 insertions(+), 32 deletions(-) (limited to 'drivers/gles3') diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index ec304e7a46..2c6c9dd9ba 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -850,7 +850,36 @@ void RasterizerSceneGLES3::environment_set_ambient_light(RID p_env, const Color& } -void RasterizerSceneGLES3::environment_set_glow(RID p_env,bool p_enable,int p_level_flags,float p_intensity,float p_strength,float p_bloom_treshold,VS::EnvironmentGlowBlendMode p_blend_mode,float p_hdr_bleed_treshold,float p_hdr_bleed_scale) { + + +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){ + + Environment *env=environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + + env->dof_blur_far_enabled=p_enable; + env->dof_blur_far_distance=p_distance; + env->dof_blur_far_transition=p_transition; + env->dof_blur_far_amount=p_amount; + env->dof_blur_far_quality=p_quality; + + +} + +void RasterizerSceneGLES3::environment_set_dof_blur_near(RID p_env,bool p_enable,float p_distance,float p_transition,float p_amount,VS::EnvironmentDOFBlurQuality p_quality){ + + Environment *env=environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + + env->dof_blur_near_enabled=p_enable; + env->dof_blur_near_distance=p_distance; + env->dof_blur_near_transition=p_transition; + 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_treshold, VS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_treshold, float p_hdr_bleed_scale, bool p_bicubic_upscale) { Environment *env=environment_owner.getornull(p_env); ERR_FAIL_COND(!env); @@ -863,6 +892,7 @@ void RasterizerSceneGLES3::environment_set_glow(RID p_env,bool p_enable,int p_le env->glow_blend_mode=p_blend_mode; env->glow_hdr_bleed_treshold=p_hdr_bleed_treshold; env->glow_hdr_bleed_scale=p_hdr_bleed_scale; + 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){ @@ -3035,7 +3065,7 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env,const CameraMatrix &p_c } -void RasterizerSceneGLES3::_post_process(Environment *env){ +void RasterizerSceneGLES3::_post_process(Environment *env,const CameraMatrix &p_cam_projection){ //copy to front buffer @@ -3077,6 +3107,157 @@ void RasterizerSceneGLES3::_post_process(Environment *env){ GLuint composite_from = storage->frame.current_rt->buffers.diffuse; + if (env->dof_blur_far_enabled) { + + //blur diffuse into effect mipmaps using separatable convolution + //storage->shaders.copy.set_conditional(CopyShaderGLES3::GAUSSIAN_HORIZONTAL,true); + + int vp_h = storage->frame.current_rt->height; + int vp_w = storage->frame.current_rt->width; + + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_FAR_BLUR,true); + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_LOW,env->dof_blur_far_quality==VS::ENV_DOF_BLUR_QUALITY_LOW); + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_MEDIUM,env->dof_blur_far_quality==VS::ENV_DOF_BLUR_QUALITY_MEDIUM); + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_HIGH,env->dof_blur_far_quality==VS::ENV_DOF_BLUR_QUALITY_HIGH); + + state.effect_blur_shader.bind(); + int qsteps[3]={4,10,20}; + + float radius = (env->dof_blur_far_amount*env->dof_blur_far_amount) / qsteps[env->dof_blur_far_quality]; + + state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_BEGIN,env->dof_blur_far_distance); + state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_END,env->dof_blur_far_distance+env->dof_blur_far_transition); + state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_DIR,Vector2(1,0)); + state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_RADIUS,radius); + 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::CAMERA_Z_NEAR,p_cam_projection.get_z_near()); + state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::CAMERA_Z_FAR,p_cam_projection.get_z_far()); + + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->depth); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,composite_from); + 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); + + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->fbo); //copy to front first + + _copy_screen(); + + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->color); + state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_DIR,Vector2(0,1)); + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo); // copy to base level + _copy_screen(); + + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_FAR_BLUR,false); + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_FAR_BLUR,false); + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_LOW,false); + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_MEDIUM,false); + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_HIGH,false); + + + composite_from=storage->frame.current_rt->effects.mip_maps[0].color; + + } + + if (env->dof_blur_near_enabled) { + + //blur diffuse into effect mipmaps using separatable convolution + //storage->shaders.copy.set_conditional(CopyShaderGLES3::GAUSSIAN_HORIZONTAL,true); + + int vp_h = storage->frame.current_rt->height; + int vp_w = storage->frame.current_rt->width; + + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_NEAR_BLUR,true); + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_NEAR_FIRST_TAP,true); + + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_LOW,env->dof_blur_near_quality==VS::ENV_DOF_BLUR_QUALITY_LOW); + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_MEDIUM,env->dof_blur_near_quality==VS::ENV_DOF_BLUR_QUALITY_MEDIUM); + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_HIGH,env->dof_blur_near_quality==VS::ENV_DOF_BLUR_QUALITY_HIGH); + + state.effect_blur_shader.bind(); + int qsteps[3]={4,10,20}; + + float radius = (env->dof_blur_near_amount*env->dof_blur_near_amount) / qsteps[env->dof_blur_near_quality]; + + state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_BEGIN,env->dof_blur_near_distance); + state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_END,env->dof_blur_near_distance-env->dof_blur_near_transition); + state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_DIR,Vector2(1,0)); + state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_RADIUS,radius); + 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::CAMERA_Z_NEAR,p_cam_projection.get_z_near()); + state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::CAMERA_Z_FAR,p_cam_projection.get_z_far()); + + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->depth); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,composite_from); + 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); + + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->fbo); //copy to front first + + _copy_screen(); + //manually do the blend if this is the first operation resolving from the diffuse buffer + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_NEAR_BLUR_MERGE,composite_from == storage->frame.current_rt->buffers.diffuse); + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_NEAR_FIRST_TAP,false); + state.effect_blur_shader.bind(); + + + + state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_BEGIN,env->dof_blur_near_distance); + state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_END,env->dof_blur_near_distance-env->dof_blur_near_transition); + state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_DIR,Vector2(0,1)); + state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_RADIUS,radius); + 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::CAMERA_Z_NEAR,p_cam_projection.get_z_near()); + state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::CAMERA_Z_FAR,p_cam_projection.get_z_far()); + + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->color); + + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo); // copy to base level + + if (composite_from != storage->frame.current_rt->buffers.diffuse) { + + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + } else { + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.diffuse); + + } + + _copy_screen(); + + if (composite_from != storage->frame.current_rt->buffers.diffuse) { + + glDisable(GL_BLEND); + } + + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_NEAR_BLUR,false); + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_NEAR_FIRST_TAP,false); + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_NEAR_BLUR_MERGE,false); + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_LOW,false); + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_MEDIUM,false); + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_HIGH,false); + + + composite_from=storage->frame.current_rt->effects.mip_maps[0].color; + + } + if ( env->auto_exposure) { //compute auto exposure @@ -3266,6 +3447,7 @@ void RasterizerSceneGLES3::_post_process(Environment *env){ state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_REINDHART_TONEMAPPER,env->tone_mapper==VS::ENV_TONE_MAPPER_REINHARDT); state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_AUTO_EXPOSURE,env->auto_exposure); + state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_FILTER_BICUBIC,env->glow_bicubic_upscale); @@ -3315,6 +3497,12 @@ void RasterizerSceneGLES3::_post_process(Environment *env){ if (max_glow_level>=0) { state.tonemap_shader.set_uniform(TonemapShaderGLES3::GLOW_INTENSITY,env->glow_intensity); + int ss[2]={ + storage->frame.current_rt->width, + storage->frame.current_rt->height, + }; + glUniform2iv(state.tonemap_shader.get_uniform(TonemapShaderGLES3::GLOW_TEXTURE_SIZE),1,ss); + } if (env->auto_exposure) { @@ -3344,6 +3532,8 @@ void RasterizerSceneGLES3::_post_process(Environment *env){ state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_REPLACE,false); state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_SCREEN,false); state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_SOFTLIGHT,false); + state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_FILTER_BICUBIC,false); + } void RasterizerSceneGLES3::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){ @@ -3605,7 +3795,7 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C } - _post_process(env); + _post_process(env,p_cam_projection); if (false && shadow_atlas) { diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 6ca4529ed9..78e8b3e477 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -349,6 +349,7 @@ public: VS::EnvironmentGlowBlendMode glow_blend_mode; float glow_hdr_bleed_treshold; float glow_hdr_bleed_scale; + bool glow_bicubic_upscale; VS::EnvironmentToneMapper tone_mapper; float tone_mapper_exposure; @@ -359,6 +360,17 @@ public: float auto_exposure_max; float auto_exposure_grey; + bool dof_blur_far_enabled; + float dof_blur_far_distance; + float dof_blur_far_transition; + float dof_blur_far_amount; + VS::EnvironmentDOFBlurQuality dof_blur_far_quality; + + bool dof_blur_near_enabled; + float dof_blur_near_distance; + float dof_blur_near_transition; + float dof_blur_near_amount; + VS::EnvironmentDOFBlurQuality dof_blur_near_quality; Environment() { bg_mode=VS::ENV_BG_CLEAR_COLOR; @@ -403,7 +415,19 @@ public: glow_blend_mode=VS::GLOW_BLEND_MODE_SOFTLIGHT; glow_hdr_bleed_treshold=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; } }; @@ -420,12 +444,15 @@ public: 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_skybox_contribution=0.0); - virtual void environment_set_glow(RID p_env,bool p_enable,int p_level_flags,float p_intensity,float p_strength,float p_bloom_treshold,VS::EnvironmentGlowBlendMode p_blend_mode,float p_hdr_bleed_treshold,float p_hdr_bleed_scale); + virtual void environment_set_dof_blur_near(RID p_env,bool p_enable,float p_distance,float p_transition,float p_far_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_far_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_treshold,VS::EnvironmentGlowBlendMode p_blend_mode,float p_hdr_bleed_treshold,float p_hdr_bleed_scale,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_accel,float p_fade,float p_depth_tolerance,bool p_smooth,bool p_roughness); virtual void environment_set_ssao(RID p_env,bool p_enable, float p_radius, float p_radius2, float p_intensity2, float p_intensity, float p_bias, float p_light_affect,const Color &p_color,bool p_blur); + virtual void environment_set_tonemap(RID p_env,VS::EnvironmentToneMapper p_tone_mapper,float p_exposure,float p_white,bool p_auto_exposure,float p_min_luminance,float p_max_luminance,float p_auto_exp_speed,float p_auto_exp_scale); virtual void environment_set_adjustment(RID p_env,bool p_enable,float p_brightness,float p_contrast,float p_saturation,RID p_ramp); @@ -663,7 +690,7 @@ public: void _fill_render_list(InstanceBase** p_cull_result,int p_cull_count,bool p_shadow); void _render_mrts(Environment *env, const CameraMatrix &p_cam_projection); - void _post_process(Environment *env); + void _post_process(Environment *env, const CameraMatrix &p_cam_projection); 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); diff --git a/drivers/gles3/shaders/effect_blur.glsl b/drivers/gles3/shaders/effect_blur.glsl index 589af64d44..89afa12f60 100644 --- a/drivers/gles3/shaders/effect_blur.glsl +++ b/drivers/gles3/shaders/effect_blur.glsl @@ -41,6 +41,40 @@ uniform float glow_strength; #endif +#if defined(DOF_FAR_BLUR) || defined (DOF_NEAR_BLUR) + +#ifdef DOF_QUALITY_LOW +const int dof_kernel_size=5; +const int dof_kernel_from=2; +const float dof_kernel[5] = float[] (0.153388,0.221461,0.250301,0.221461,0.153388); +#endif + +#ifdef DOF_QUALITY_MEDIUM +const int dof_kernel_size=11; +const int dof_kernel_from=5; +const float dof_kernel[11] = float[] (0.055037,0.072806,0.090506,0.105726,0.116061,0.119726,0.116061,0.105726,0.090506,0.072806,0.055037); + +#endif + +#ifdef DOF_QUALITY_HIGH +const int dof_kernel_size=21; +const int dof_kernel_from=10; +const float dof_kernel[21] = float[] (0.028174,0.032676,0.037311,0.041944,0.046421,0.050582,0.054261,0.057307,0.059587,0.060998,0.061476,0.060998,0.059587,0.057307,0.054261,0.050582,0.046421,0.041944,0.037311,0.032676,0.028174); +#endif + +uniform sampler2D dof_source_depth; //texunit:1 +uniform float dof_begin; +uniform float dof_end; +uniform vec2 dof_dir; +uniform float dof_radius; + +#ifdef DOF_NEAR_BLUR_MERGE + +uniform sampler2D source_dof_original; //texunit:2 +#endif + +#endif + #ifdef GLOW_FIRST_PASS @@ -60,16 +94,23 @@ uniform float glow_hdr_scale; #endif +uniform float camera_z_far; +uniform float camera_z_near; + void main() { #ifdef GAUSSIAN_HORIZONTAL - vec4 color =textureLod( source_color, uv_interp+vec2( 0.0, 0.0)*pixel_size,lod )*0.38774; - color+=textureLod( source_color, uv_interp+vec2( 1.0, 0.0)*pixel_size,lod )*0.24477; - color+=textureLod( source_color, uv_interp+vec2( 2.0, 0.0)*pixel_size,lod )*0.06136; - color+=textureLod( source_color, uv_interp+vec2(-1.0, 0.0)*pixel_size,lod )*0.24477; - color+=textureLod( source_color, uv_interp+vec2(-2.0, 0.0)*pixel_size,lod )*0.06136; + vec2 pix_size = pixel_size; + pix_size*=0.5; //reading from larger buffer, so use more samples + 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( 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(-3.0, 0.0)*pix_size,lod )*0.071303; frag_color = color; #endif @@ -82,32 +123,126 @@ void main() { frag_color = color; #endif - +//glow uses larger sigma for a more rounded blur effect #ifdef GLOW_GAUSSIAN_HORIZONTAL - vec4 color =textureLod( source_color, uv_interp+vec2( 0.0, 0.0)*pixel_size,lod )*0.174938; - color+=textureLod( source_color, uv_interp+vec2( 1.0, 0.0)*pixel_size,lod )*0.165569; - color+=textureLod( source_color, uv_interp+vec2( 2.0, 0.0)*pixel_size,lod )*0.140367; - color+=textureLod( source_color, uv_interp+vec2( 3.0, 0.0)*pixel_size,lod )*0.106595; - color+=textureLod( source_color, uv_interp+vec2(-1.0, 0.0)*pixel_size,lod )*0.165569; - color+=textureLod( source_color, uv_interp+vec2(-2.0, 0.0)*pixel_size,lod )*0.140367; - color+=textureLod( source_color, uv_interp+vec2(-3.0, 0.0)*pixel_size,lod )*0.165569; + vec2 pix_size = pixel_size; + pix_size*=0.5; //reading from larger buffer, so use more samples + vec4 color =textureLod( source_color, uv_interp+vec2( 0.0, 0.0)*pix_size,lod )*0.174938; + color+=textureLod( source_color, uv_interp+vec2( 1.0, 0.0)*pix_size,lod )*0.165569; + color+=textureLod( source_color, uv_interp+vec2( 2.0, 0.0)*pix_size,lod )*0.140367; + color+=textureLod( source_color, uv_interp+vec2( 3.0, 0.0)*pix_size,lod )*0.106595; + color+=textureLod( source_color, uv_interp+vec2(-1.0, 0.0)*pix_size,lod )*0.165569; + color+=textureLod( source_color, uv_interp+vec2(-2.0, 0.0)*pix_size,lod )*0.140367; + color+=textureLod( source_color, uv_interp+vec2(-3.0, 0.0)*pix_size,lod )*0.106595; color*=glow_strength; frag_color = color; #endif #ifdef GLOW_GAUSSIAN_VERTICAL - vec4 color =textureLod( source_color, uv_interp+vec2(0.0, 0.0)*pixel_size,lod )*0.174938; - color+=textureLod( source_color, uv_interp+vec2(0.0, 1.0)*pixel_size,lod )*0.165569; - color+=textureLod( source_color, uv_interp+vec2(0.0, 2.0)*pixel_size,lod )*0.140367; - color+=textureLod( source_color, uv_interp+vec2(0.0, 3.0)*pixel_size,lod )*0.106595; - color+=textureLod( source_color, uv_interp+vec2(0.0,-1.0)*pixel_size,lod )*0.165569; - color+=textureLod( source_color, uv_interp+vec2(0.0,-2.0)*pixel_size,lod )*0.140367; - color+=textureLod( source_color, uv_interp+vec2(0.0,-3.0)*pixel_size,lod )*0.165569; + vec4 color =textureLod( source_color, uv_interp+vec2(0.0, 0.0)*pixel_size,lod )*0.288713; + color+=textureLod( source_color, uv_interp+vec2(0.0, 1.0)*pixel_size,lod )*0.233062; + color+=textureLod( source_color, uv_interp+vec2(0.0, 2.0)*pixel_size,lod )*0.122581; + color+=textureLod( source_color, uv_interp+vec2(0.0,-1.0)*pixel_size,lod )*0.233062; + color+=textureLod( source_color, uv_interp+vec2(0.0,-2.0)*pixel_size,lod )*0.122581; color*=glow_strength; frag_color = color; #endif +#ifdef DOF_FAR_BLUR + + vec4 color_accum = vec4(0.0); + + float depth = textureLod( dof_source_depth, uv_interp, 0.0).r; + depth = depth * 2.0 - 1.0; + depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth * (camera_z_far - camera_z_near)); + + float amount = smoothstep(dof_begin,dof_end,depth); + float k_accum=0.0; + + for(int i=0;i0.0) { + color_accum/=k_accum; + } + + frag_color = color_accum;///k_accum; + +#endif + +#ifdef DOF_NEAR_BLUR + + vec4 color_accum = vec4(0.0); + + float max_accum=0; + + for(int i=0;i> p_lod); + vec2 pixel_size =1.0/tex_size; + uv = uv*tex_size + 0.5; + vec2 iuv = floor( uv ); + vec2 fuv = fract( uv ); + + float g0x = g0(fuv.x); + float g1x = g1(fuv.x); + float h0x = h0(fuv.x); + float h1x = h1(fuv.x); + float h0y = h0(fuv.y); + float h1y = h1(fuv.y); + + vec2 p0 = (vec2(iuv.x + h0x, iuv.y + h0y) - 0.5) * pixel_size; + vec2 p1 = (vec2(iuv.x + h1x, iuv.y + h0y) - 0.5) * pixel_size; + vec2 p2 = (vec2(iuv.x + h0x, iuv.y + h1y) - 0.5) * pixel_size; + vec2 p3 = (vec2(iuv.x + h1x, iuv.y + h1y) - 0.5) * pixel_size; + + return g0(fuv.y) * (g0x * textureLod(tex, p0,lod) + + g1x * textureLod(tex, p1,lod)) + + g1(fuv.y) * (g0x * textureLod(tex, p2,lod) + + g1x * textureLod(tex, p3,lod)); +} + + + +#define GLOW_TEXTURE_SAMPLE(m_tex,m_uv,m_lod) texture2D_bicubic(m_tex,m_uv,m_lod) + +#else + +#define GLOW_TEXTURE_SAMPLE(m_tex,m_uv,m_lod) textureLod(m_tex,m_uv,float(m_lod)) + +#endif + void main() { @@ -60,31 +144,32 @@ void main() { vec3 glow = vec3(0.0); #ifdef USE_GLOW_LEVEL1 - glow+=textureLod(source_glow,uv_interp,1.0).rgb; + + glow+=GLOW_TEXTURE_SAMPLE(source_glow,uv_interp,1).rgb; #endif #ifdef USE_GLOW_LEVEL2 - glow+=textureLod(source_glow,uv_interp,2.0).rgb; + glow+=GLOW_TEXTURE_SAMPLE(source_glow,uv_interp,2).rgb; #endif #ifdef USE_GLOW_LEVEL3 - glow+=textureLod(source_glow,uv_interp,3.0).rgb; + glow+=GLOW_TEXTURE_SAMPLE(source_glow,uv_interp,3).rgb; #endif #ifdef USE_GLOW_LEVEL4 - glow+=textureLod(source_glow,uv_interp,4.0).rgb; + glow+=GLOW_TEXTURE_SAMPLE(source_glow,uv_interp,4).rgb; #endif #ifdef USE_GLOW_LEVEL5 - glow+=textureLod(source_glow,uv_interp,5.0).rgb; + glow+=GLOW_TEXTURE_SAMPLE(source_glow,uv_interp,5).rgb; #endif #ifdef USE_GLOW_LEVEL6 - glow+=textureLod(source_glow,uv_interp,6.0).rgb; + glow+=GLOW_TEXTURE_SAMPLE(source_glow,uv_interp,6).rgb; #endif #ifdef USE_GLOW_LEVEL7 - glow+=textureLod(source_glow,uv_interp,7.0).rgb; + glow+=GLOW_TEXTURE_SAMPLE(source_glow,uv_interp,7).rgb; #endif -- cgit v1.2.3 From 075fde7f26d6c3b02df5108065d1a9f979437bb8 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Tue, 20 Dec 2016 00:21:07 -0300 Subject: work in progress global illumination --- drivers/gles3/rasterizer_scene_gles3.cpp | 85 +++++++- drivers/gles3/rasterizer_scene_gles3.h | 26 ++- drivers/gles3/rasterizer_storage_gles3.cpp | 317 ++++++++++++++++++++++++++++- drivers/gles3/rasterizer_storage_gles3.h | 79 +++++++ drivers/gles3/shaders/scene.glsl | 135 +++++++++++- 5 files changed, 627 insertions(+), 15 deletions(-) (limited to 'drivers/gles3') diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 2c6c9dd9ba..524e683738 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -1010,6 +1010,48 @@ void RasterizerSceneGLES3::light_instance_mark_visible(RID p_light_instance) { light_instance->last_scene_pass=scene_pass; } + +////////////////////// + +RID RasterizerSceneGLES3::gi_probe_instance_create() { + + GIProbeInstance *gipi = memnew(GIProbeInstance); + + return gi_probe_instance_owner.make_rid(gipi); +} + +void RasterizerSceneGLES3::gi_probe_instance_set_light_data(RID p_probe,RID p_data) { + + GIProbeInstance *gipi = gi_probe_instance_owner.getornull(p_probe); + ERR_FAIL_COND(!gipi); + gipi->data=p_data; + 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; + } + } +} +void RasterizerSceneGLES3::gi_probe_instance_set_transform_to_data(RID p_probe,const Transform& p_xform) { + + GIProbeInstance *gipi = gi_probe_instance_owner.getornull(p_probe); + ERR_FAIL_COND(!gipi); + gipi->transform_to_data=p_xform; + +} + +void RasterizerSceneGLES3::gi_probe_instance_set_bounds(RID p_probe,const Vector3& p_bounds) { + + GIProbeInstance *gipi = gi_probe_instance_owner.getornull(p_probe); + ERR_FAIL_COND(!gipi); + gipi->bounds=p_bounds; + +} + //////////////////////////// //////////////////////////// //////////////////////////// @@ -1438,7 +1480,7 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) { } -void RasterizerSceneGLES3::_setup_light(RenderList::Element *e) { +void RasterizerSceneGLES3::_setup_light(RenderList::Element *e,const Transform& p_view_transform) { int omni_indices[16]; int omni_count=0; @@ -1509,7 +1551,33 @@ void RasterizerSceneGLES3::_setup_light(RenderList::Element *e) { glUniform1iv(state.scene_shader.get_uniform(SceneShaderGLES3::REFLECTION_INDICES),reflection_count,reflection_indices); } + int gi_probe_count = e->instance->gi_probe_instances.size(); + if (gi_probe_count) { + const RID * ridp = e->instance->gi_probe_instances.ptr(); + GIProbeInstance *gipi = gi_probe_instance_owner.getptr(ridp[0]); + + glActiveTexture(GL_TEXTURE0+storage->config.max_texture_image_units-6); + glBindTexture(GL_TEXTURE_3D,gipi->tex_cache); + state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_XFORM1, gipi->transform_to_data * p_view_transform); + state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BOUNDS1, gipi->bounds); + state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_CELL_SIZE1, gipi->cell_size_cache); + if (gi_probe_count>1) { + + GIProbeInstance *gipi2 = gi_probe_instance_owner.getptr(ridp[1]); + + glActiveTexture(GL_TEXTURE0+storage->config.max_texture_image_units-7); + glBindTexture(GL_TEXTURE_3D,gipi2->tex_cache); + state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_XFORM2, gipi2->transform_to_data * p_view_transform); + state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BOUNDS2, gipi2->bounds); + state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_CELL_SIZE2, gipi2->cell_size_cache); + + state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE2_ENABLED, true ); + } else { + + state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE2_ENABLED, false ); + } + } } @@ -1672,11 +1740,15 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM_BLEND,false); state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_5,false); state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_13,false); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_GI_PROBES,false); //state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS,true); } else { + + state.scene_shader.set_conditional(SceneShaderGLES3::USE_GI_PROBES,e->instance->gi_probe_instances.size()>0); + state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS,false); state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_LIGHTING,!p_directional_add); state.scene_shader.set_conditional(SceneShaderGLES3::USE_LIGHT_DIRECTIONAL,false); @@ -1711,9 +1783,12 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e } + + rebind=true; } + if (p_alpha_pass || p_directional_add) { int desired_blend_mode; if (p_directional_add) { @@ -1794,7 +1869,8 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e } if (!(e->sort_key&RenderList::SORT_KEY_UNSHADED_FLAG) && !p_directional_add && !p_shadow) { - _setup_light(e); + _setup_light(e,p_view_transform); + } @@ -1837,6 +1913,7 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS,false); state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_5,false); state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_13,false); + state.scene_shader.set_conditional(SceneShaderGLES3::USE_GI_PROBES,false); } @@ -1950,6 +2027,10 @@ void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_g copymem(oe,e,sizeof(RenderList::Element)); } + + if (e->instance->gi_probe_instances.size()) { + e->sort_key|=RenderList::SORT_KEY_GI_PROBES_FLAG; + } } //if (e->geometry->type==RasterizerStorageGLES3::Geometry::GEOMETRY_MULTISURFACE) diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 78e8b3e477..5eb2be1cc2 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -526,6 +526,25 @@ public: virtual void light_instance_set_shadow_transform(RID p_light_instance,const CameraMatrix& p_projection,const Transform& p_transform,float p_far,float p_split,int p_pass); virtual void light_instance_mark_visible(RID p_light_instance); + /* REFLECTION INSTANCE */ + + struct GIProbeInstance : public RID_Data { + RID data; + GLuint tex_cache; + Vector3 cell_size_cache; + Vector3 bounds; + Transform transform_to_data; + }; + + + + mutable RID_Owner gi_probe_instance_owner; + + virtual RID gi_probe_instance_create(); + virtual void gi_probe_instance_set_light_data(RID p_probe,RID p_data); + virtual void gi_probe_instance_set_transform_to_data(RID p_probe,const Transform& p_xform); + virtual void gi_probe_instance_set_bounds(RID p_probe,const Vector3& p_bounds); + /* RENDER LIST */ struct RenderList { @@ -541,8 +560,9 @@ public: SORT_KEY_DEPTH_LAYER_SHIFT=60, SORT_KEY_UNSHADED_FLAG=uint64_t(1)<<59, SORT_KEY_NO_DIRECTIONAL_FLAG=uint64_t(1)<<58, - SORT_KEY_SHADING_SHIFT=58, - SORT_KEY_SHADING_MASK=3, + SORT_KEY_GI_PROBES_FLAG=uint64_t(1)<<57, + SORT_KEY_SHADING_SHIFT=57, + SORT_KEY_SHADING_MASK=7, SORT_KEY_MATERIAL_INDEX_SHIFT=40, SORT_KEY_GEOMETRY_INDEX_SHIFT=20, SORT_KEY_GEOMETRY_TYPE_SHIFT=15, @@ -669,7 +689,7 @@ public: _FORCE_INLINE_ void _setup_transform(InstanceBase *p_instance,const Transform& p_view_transform,const CameraMatrix& p_projection); _FORCE_INLINE_ void _setup_geometry(RenderList::Element *e); _FORCE_INLINE_ void _render_geometry(RenderList::Element *e); - _FORCE_INLINE_ void _setup_light(RenderList::Element *e); + _FORCE_INLINE_ void _setup_light(RenderList::Element *e,const Transform& p_view_transform); void _render_list(RenderList::Element **p_elements, int p_element_count, const Transform& p_view_transform, const CameraMatrix& p_projection, GLuint p_base_env, bool p_reverse_cull, bool p_alpha_pass, bool p_shadow, bool p_directional_add, bool p_directional_shadows); diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index cfa50f6100..8262487f9d 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -1514,6 +1514,7 @@ void RasterizerStorageGLES3::_update_shader(Shader* p_shader) const { p_shader->valid=true; p_shader->version++; + } void RasterizerStorageGLES3::update_dirty_shaders() { @@ -3600,16 +3601,15 @@ void RasterizerStorageGLES3::multimesh_instance_set_color(RID p_multimesh,int p_ ERR_FAIL_COND(multimesh->color_format==VS::MULTIMESH_COLOR_NONE); int stride = multimesh->color_floats+multimesh->xform_floats; - float *dataptr=&multimesh->data[stride*p_index+multimesh->color_floats]; + float *dataptr=&multimesh->data[stride*p_index+multimesh->xform_floats]; if (multimesh->color_format==VS::MULTIMESH_COLOR_8BIT) { - union { - uint32_t colu; - float colf; - } cu; - cu.colu=p_color.to_32(); - dataptr[ 0]=cu.colf; + uint8_t *data8=(uint8_t*)dataptr; + data8[0]=CLAMP(p_color.r*255.0,0,255); + data8[1]=CLAMP(p_color.g*255.0,0,255); + data8[2]=CLAMP(p_color.b*255.0,0,255); + data8[3]=CLAMP(p_color.a*255.0,0,255); } else if (multimesh->color_format==VS::MULTIMESH_COLOR_FLOAT) { dataptr[ 0]=p_color.r; @@ -3701,7 +3701,7 @@ Color RasterizerStorageGLES3::multimesh_instance_get_color(RID p_multimesh,int p float colf; } cu; - return Color::hex(cu.colu); + return Color::hex(BSWAP32(cu.colu)); } else if (multimesh->color_format==VS::MULTIMESH_COLOR_FLOAT) { Color c; @@ -4385,6 +4385,15 @@ float RasterizerStorageGLES3::light_get_param(RID p_light,VS::LightParam p_param return light->param[p_param]; } +Color RasterizerStorageGLES3::light_get_color(RID p_light) { + + const Light * light = light_owner.getornull(p_light); + ERR_FAIL_COND_V(!light,Color()); + + return light->color; + +} + bool RasterizerStorageGLES3::light_has_shadow(RID p_light) const { const Light * light = light_owner.getornull(p_light); @@ -4668,6 +4677,261 @@ void RasterizerStorageGLES3::portal_set_disabled_color(RID p_portal, const Color } +RID RasterizerStorageGLES3::gi_probe_create() { + + GIProbe *gip = memnew( GIProbe ); + + gip->data_width=0; + gip->data_height=0; + gip->data_depth=0; + gip->bounds=AABB(Vector3(),Vector3(1,1,1)); + gip->dynamic_range=1.0; + gip->version=1; + gip->cell_size=1.0; + + return gi_probe_owner.make_rid(gip); +} + +void RasterizerStorageGLES3::gi_probe_set_bounds(RID p_probe,const AABB& p_bounds){ + + GIProbe *gip = gi_probe_owner.getornull(p_probe); + ERR_FAIL_COND(!gip); + + gip->bounds=p_bounds; + gip->version++; + gip->instance_change_notify(); +} +AABB RasterizerStorageGLES3::gi_probe_get_bounds(RID p_probe) const{ + + const GIProbe *gip = gi_probe_owner.getornull(p_probe); + ERR_FAIL_COND_V(!gip,AABB()); + + return gip->bounds; +} + +void RasterizerStorageGLES3::gi_probe_set_cell_size(RID p_probe,float p_size) { + + GIProbe *gip = gi_probe_owner.getornull(p_probe); + ERR_FAIL_COND(!gip); + + gip->cell_size=p_size; + gip->version++; + gip->instance_change_notify(); +} + +float RasterizerStorageGLES3::gi_probe_get_cell_size(RID p_probe) const { + + const GIProbe *gip = gi_probe_owner.getornull(p_probe); + ERR_FAIL_COND_V(!gip,0); + + return gip->cell_size; + +} + +void RasterizerStorageGLES3::gi_probe_set_to_cell_xform(RID p_probe,const Transform& p_xform) { + + GIProbe *gip = gi_probe_owner.getornull(p_probe); + ERR_FAIL_COND(!gip); + + gip->to_cell=p_xform; +} + +Transform RasterizerStorageGLES3::gi_probe_get_to_cell_xform(RID p_probe) const { + + const GIProbe *gip = gi_probe_owner.getornull(p_probe); + ERR_FAIL_COND_V(!gip,Transform()); + + return gip->to_cell; + +} + + + +void RasterizerStorageGLES3::gi_probe_set_dynamic_data(RID p_probe,const DVector& p_data){ + GIProbe *gip = gi_probe_owner.getornull(p_probe); + ERR_FAIL_COND(!gip); + + gip->dynamic_data=p_data; + gip->version++; + gip->instance_change_notify(); + +} +DVector RasterizerStorageGLES3::gi_probe_get_dynamic_data(RID p_probe) const{ + + const GIProbe *gip = gi_probe_owner.getornull(p_probe); + ERR_FAIL_COND_V(!gip,DVector()); + + return gip->dynamic_data; +} + +void RasterizerStorageGLES3::gi_probe_set_dynamic_range(RID p_probe,float p_range){ + + GIProbe *gip = gi_probe_owner.getornull(p_probe); + ERR_FAIL_COND(!gip); + + gip->dynamic_range=p_range; + +} +float RasterizerStorageGLES3::gi_probe_get_dynamic_range(RID p_probe) const{ + + const GIProbe *gip = gi_probe_owner.getornull(p_probe); + ERR_FAIL_COND_V(!gip,0); + + return gip->dynamic_range; +} + + +void RasterizerStorageGLES3::gi_probe_set_static_data(RID p_gi_probe,const DVector& p_data,VS::GIProbeDataFormat p_format,int p_width,int p_height,int p_depth) { + + GIProbe *gip = gi_probe_owner.getornull(p_gi_probe); + ERR_FAIL_COND(!gip); + + if (gip->data.is_valid()) { + free(gip->data); + } + + gip->data=RID(); + //this is platform dependent + + gip->version++; + gip->instance_change_notify(); + +} +DVector RasterizerStorageGLES3::gi_probe_get_static_data(RID p_gi_probe) const { + + const GIProbe *gip = gi_probe_owner.getornull(p_gi_probe); + ERR_FAIL_COND_V(!gip,DVector()); + + //platform dependent + return DVector(); +} +VS::GIProbeDataFormat RasterizerStorageGLES3::gi_probe_get_static_data_format(RID p_gi_probe) const { + + const GIProbe *gip = gi_probe_owner.getornull(p_gi_probe); + ERR_FAIL_COND_V(!gip,VS::GI_PROBE_DATA_RGBA8); + + return gip->data_format; +} +int RasterizerStorageGLES3::gi_probe_get_static_data_width(RID p_probe) const { + + const GIProbe *gip = gi_probe_owner.getornull(p_probe); + ERR_FAIL_COND_V(!gip,0); + + return gip->data_width; +} +int RasterizerStorageGLES3::gi_probe_get_static_data_height(RID p_probe) const { + + const GIProbe *gip = gi_probe_owner.getornull(p_probe); + ERR_FAIL_COND_V(!gip,0); + return gip->data_height; +} +int RasterizerStorageGLES3::gi_probe_get_static_data_depth(RID p_probe) const { + + const GIProbe *gip = gi_probe_owner.getornull(p_probe); + ERR_FAIL_COND_V(!gip,0); + return gip->data_depth; +} + +RID RasterizerStorageGLES3::gi_probe_get_data(RID p_probe) { + + const GIProbe *gip = gi_probe_owner.getornull(p_probe); + ERR_FAIL_COND_V(!gip,RID()); + + return gip->data; +} + +uint32_t RasterizerStorageGLES3::gi_probe_get_version(RID p_probe) { + + const GIProbe *gip = gi_probe_owner.getornull(p_probe); + ERR_FAIL_COND_V(!gip,0); + + return gip->version; +} + +RID RasterizerStorageGLES3::gi_probe_dynamic_data_create(int p_width,int p_height,int p_depth) { + + GIProbeData *gipd = memnew( GIProbeData ); + + gipd->width=p_width; + gipd->height=p_height; + gipd->depth=p_depth; + + glActiveTexture(GL_TEXTURE0); + glGenTextures(1,&gipd->tex_id); + glBindTexture(GL_TEXTURE_3D,gipd->tex_id); + + int level=0; + + print_line("dyndata create"); + while(true) { + + Vector data; + data.resize(p_width*p_height*p_depth*4); + + + for(int i=0;i>=1; + p_height>>=1; + p_depth>>=1; + level++; + } + + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 0); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, level); + + gipd->levels=level+1; + + return gi_probe_data_owner.make_rid(gipd); +} + +void RasterizerStorageGLES3::gi_probe_dynamic_data_update_rgba8(RID p_gi_probe_data, int p_depth_slice, int p_slice_count, int p_mipmap, const void *p_data) { + + GIProbeData *gipd = gi_probe_data_owner.getornull(p_gi_probe_data); + ERR_FAIL_COND(!gipd); +/* + Vector data; + data.resize((gipd->width>>p_mipmap)*(gipd->height>>p_mipmap)*(gipd->depth>>p_mipmap)*4); + + for(int i=0;i<(gipd->width>>p_mipmap);i++) { + for(int j=0;j<(gipd->height>>p_mipmap);j++) { + for(int k=0;k<(gipd->depth>>p_mipmap);k++) { + + int ofs = (k*(gipd->height>>p_mipmap)*(gipd->width>>p_mipmap)) + j *(gipd->width>>p_mipmap) + i; + ofs*=4; + data[ofs+0]=i*0xFF/(gipd->width>>p_mipmap); + data[ofs+1]=j*0xFF/(gipd->height>>p_mipmap); + data[ofs+2]=k*0xFF/(gipd->depth>>p_mipmap); + data[ofs+3]=0xFF; + } + } + } +*/ + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_3D,gipd->tex_id); + glTexSubImage3D(GL_TEXTURE_3D,p_mipmap,0,0,p_depth_slice,gipd->width>>p_mipmap,gipd->height>>p_mipmap,p_slice_count,GL_RGBA,GL_UNSIGNED_BYTE,p_data); + //glTexImage3D(GL_TEXTURE_3D,p_mipmap,GL_RGBA8,gipd->width>>p_mipmap,gipd->height>>p_mipmap,gipd->depth>>p_mipmap,0,GL_RGBA,GL_UNSIGNED_BYTE,p_data); + //glTexImage3D(GL_TEXTURE_3D,p_mipmap,GL_RGBA8,gipd->width>>p_mipmap,gipd->height>>p_mipmap,gipd->depth>>p_mipmap,0,GL_RGBA,GL_UNSIGNED_BYTE,data.ptr()); + print_line("update rgba8 "+itos(p_mipmap)); +} + + + + void RasterizerStorageGLES3::instance_add_skeleton(RID p_skeleton,RasterizerScene::InstanceBase *p_instance) { Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); @@ -4709,6 +4973,10 @@ void RasterizerStorageGLES3::instance_add_dependency(RID p_base,RasterizerScene: inst = light_owner.getornull(p_base); ERR_FAIL_COND(!inst); } break; + case VS::INSTANCE_GI_PROBE: { + inst = gi_probe_owner.getornull(p_base); + ERR_FAIL_COND(!inst); + } break; default: { if (!inst) { ERR_FAIL(); @@ -4744,6 +5012,10 @@ void RasterizerStorageGLES3::instance_remove_dependency(RID p_base,RasterizerSce inst = light_owner.getornull(p_base); ERR_FAIL_COND(!inst); } break; + case VS::INSTANCE_GI_PROBE: { + inst = gi_probe_owner.getornull(p_base); + ERR_FAIL_COND(!inst); + } break; default: { if (!inst) { @@ -5395,19 +5667,27 @@ VS::InstanceType RasterizerStorageGLES3::get_base_type(RID p_rid) const { if (mesh_owner.owns(p_rid)) { return VS::INSTANCE_MESH; } + if (multimesh_owner.owns(p_rid)) { return VS::INSTANCE_MULTIMESH; } + if (immediate_owner.owns(p_rid)) { return VS::INSTANCE_IMMEDIATE; } + if (light_owner.owns(p_rid)) { return VS::INSTANCE_LIGHT; } + if (reflection_probe_owner.owns(p_rid)) { return VS::INSTANCE_REFLECTION_PROBE; } + if (gi_probe_owner.owns(p_rid)) { + return VS::INSTANCE_GI_PROBE; + } + return VS::INSTANCE_NONE; } @@ -5561,6 +5841,27 @@ bool RasterizerStorageGLES3::free(RID p_rid){ reflection_probe_owner.free(p_rid); memdelete(reflection_probe); + } else if (gi_probe_owner.owns(p_rid)) { + + // delete the texture + GIProbe *gi_probe = gi_probe_owner.get(p_rid); + + if (gi_probe->data.is_valid()) { + free(gi_probe->data); + } + + gi_probe_owner.free(p_rid); + memdelete(gi_probe); + } else if (gi_probe_data_owner.owns(p_rid)) { + + // delete the texture + GIProbeData *gi_probe_data = gi_probe_data_owner.get(p_rid); + + print_line("dyndata delete"); + glDeleteTextures(1,&gi_probe_data->tex_id); + gi_probe_owner.free(p_rid); + memdelete(gi_probe_data); + } else if (canvas_occluder_owner.owns(p_rid)) { diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index 7802b28158..b81c3df78a 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -799,6 +799,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 AABB light_get_aabb(RID p_light) const; virtual uint64_t light_get_version(RID p_light) const; @@ -868,6 +869,84 @@ public: virtual void portal_set_disable_distance(RID p_portal, float p_distance); virtual void portal_set_disabled_color(RID p_portal, const Color& p_color); + + + + + + + /* GI PROBE API */ + + struct GIProbe : public Instantiable { + + + AABB bounds; + Transform to_cell; + float cell_size; + + float dynamic_range; + + uint32_t version; + + DVector dynamic_data; + + RID data; + int data_width; + int data_height; + int data_depth; + VS::GIProbeDataFormat data_format; + + + }; + + mutable RID_Owner gi_probe_owner; + + virtual RID gi_probe_create(); + + virtual void gi_probe_set_bounds(RID p_probe,const AABB& p_bounds); + virtual AABB gi_probe_get_bounds(RID p_probe) const; + + virtual void gi_probe_set_cell_size(RID p_probe, float p_size); + virtual float gi_probe_get_cell_size(RID p_probe) const; + + virtual void gi_probe_set_to_cell_xform(RID p_probe,const Transform& p_xform); + virtual Transform gi_probe_get_to_cell_xform(RID p_probe) const; + + virtual void gi_probe_set_dynamic_data(RID p_probe,const DVector& p_data); + virtual DVector gi_probe_get_dynamic_data(RID p_probe) const; + + virtual void gi_probe_set_dynamic_range(RID p_probe,float p_range); + virtual float gi_probe_get_dynamic_range(RID p_probe) const; + + + virtual void gi_probe_set_static_data(RID p_gi_probe,const DVector& p_data,VS::GIProbeDataFormat p_format,int p_width,int p_height,int p_depth); + virtual DVector gi_probe_get_static_data(RID p_gi_probe) const; + virtual VS::GIProbeDataFormat gi_probe_get_static_data_format(RID p_gi_probe) const; + virtual int gi_probe_get_static_data_width(RID p_probe) const; + virtual int gi_probe_get_static_data_height(RID p_probe) const; + virtual int gi_probe_get_static_data_depth(RID p_probe) const; + + virtual RID gi_probe_get_data(RID p_probe); //get data in case this is static + virtual uint32_t gi_probe_get_version(RID p_probe); + + struct GIProbeData : public RID_Data { + + int width; + int height; + int depth; + int levels; + GLuint tex_id; + + GIProbeData() { + } + }; + + mutable RID_Owner gi_probe_data_owner; + + virtual RID gi_probe_dynamic_data_create(int p_width,int p_height,int p_depth); + virtual void gi_probe_dynamic_data_update_rgba8(RID p_gi_probe_data,int p_depth_slice,int p_slice_count,int p_mipmap,const void* p_data); + + virtual void instance_add_skeleton(RID p_skeleton,RasterizerScene::InstanceBase *p_instance); virtual void instance_remove_skeleton(RID p_skeleton,RasterizerScene::InstanceBase *p_instance); diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index 61e9e37d2b..bf561a7e46 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -838,6 +838,131 @@ void reflection_process(int idx, vec3 vertex, vec3 normal,vec3 binormal, vec3 ta } } +#ifdef USE_GI_PROBES + +uniform mediump sampler3D gi_probe1; //texunit:-6 +uniform highp mat4 gi_probe_xform1; +uniform highp vec3 gi_probe_bounds1; +uniform highp vec3 gi_probe_cell_size1; + +uniform mediump sampler3D gi_probe2; //texunit:-7 +uniform highp mat4 gi_probe_xform2; +uniform highp vec3 gi_probe_bounds2; +uniform highp vec3 gi_probe_cell_size2; +uniform bool gi_probe2_enabled; + +vec3 voxel_cone_trace(sampler3D probe, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance) { + + + float dist = dot(direction,mix(vec3(-1.0),vec3(1.0),greaterThan(direction,vec3(0.0))))*2.0; + float alpha=0.0; + vec4 color = vec4(0.0); + + while(dist < max_distance && alpha < 0.95) { + float diameter = max(1.0, 2.0 * tan_half_angle * dist); + vec4 scolor = textureLod(probe, (pos + dist * direction) * cell_size, log2(diameter) ); + float a = (1.0 - alpha); + color.rgb += a * scolor.rgb; + alpha += a * scolor.a; + dist += diameter * 0.5; + } + + return color.rgb; +} + +void gi_probe_compute(sampler3D probe, mat4 probe_xform, vec3 bounds,vec3 cell_size,vec3 pos, mat3 normal_mtx,vec3 ref_vec, float roughness, out vec4 out_spec, out vec4 out_diff) { + + + + vec3 probe_pos = (probe_xform * vec4(pos,1.0)).xyz; + vec3 ref_pos = (probe_xform * vec4(pos+ref_vec,1.0)).xyz; + + ref_vec = normalize(ref_pos - probe_pos); + +/* out_diff.rgb = voxel_cone_trace(probe,cell_size,probe_pos,normalize((probe_xform * vec4(ref_vec,0.0)).xyz),0.0 ,100.0); + out_diff.a = 1.0; + return;*/ + //out_diff = vec4(textureLod(probe,probe_pos*cell_size,3.0).rgb,1.0); + //return; + + if (any(bvec2(any(lessThan(probe_pos,vec3(0.0))),any(greaterThan(probe_pos,bounds))))) + return; + + vec3 blendv = probe_pos/bounds * 2.0 - 1.0; + float blend = 1.001-max(blendv.x,max(blendv.y,blendv.z)); + blend=1.0; + + //radiance + +#define MAX_CONE_DIRS 6 + vec3 cone_dirs[MAX_CONE_DIRS] = 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) + ); + + float cone_weights[MAX_CONE_DIRS] = float[](0.25, 0.15, 0.15, 0.15, 0.15, 0.15); + + float max_distance = length(bounds); + vec3 light=vec3(0.0); + for(int i=0;i0.0) { + diff_accum.rgb/=diff_accum.a; + } + + if (spec_accum.a>0.0) { + spec_accum.rgb/=spec_accum.a; + } + + out_specular+=spec_accum.rgb; + out_ambient+=diff_accum.rgb; + +} + +#endif + + void main() { #ifdef RENDER_SHADOW_DUAL_PARABOLOID @@ -1161,21 +1286,27 @@ FRAGMENT_SHADER_CODE #endif //#USE_LIGHT_DIRECTIONAL +#ifdef USE_GI_PROBES + gi_probes_compute(vertex,normal,roughness,specular,specular_light,ambient_light); +#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;i0.0) { - specular_light=reflection_accum.rgb/reflection_accum.a; + specular_light+=reflection_accum.rgb/reflection_accum.a; } if (ambient_accum.a>0.0) { - ambient_light=ambient_accum.rgb/ambient_accum.a; + ambient_light+=ambient_accum.rgb/ambient_accum.a; } for(int i=0;i Date: Wed, 21 Dec 2016 02:29:58 -0300 Subject: Godot works on Windows again.. --- drivers/gles3/rasterizer_canvas_gles3.cpp | 8 ++++---- drivers/gles3/rasterizer_gles3.cpp | 2 +- drivers/gles3/rasterizer_scene_gles3.cpp | 4 ++-- drivers/gles3/rasterizer_scene_gles3.h | 2 +- drivers/gles3/rasterizer_storage_gles3.cpp | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers/gles3') diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index 3c6094a41d..6bd440eec1 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -1257,16 +1257,16 @@ void RasterizerCanvasGLES3::canvas_light_shadow_buffer_update(RID p_buffer, cons CameraMatrix projection; { real_t fov = 90; - real_t near = p_near; - real_t far = p_far; + real_t nearp = p_near; + real_t farp = p_far; real_t aspect = 1.0; - real_t ymax = near * Math::tan( Math::deg2rad( fov * 0.5 ) ); + real_t ymax = nearp * Math::tan( Math::deg2rad( fov * 0.5 ) ); real_t ymin = - ymax; real_t xmin = ymin * aspect; real_t xmax = ymax * aspect; - projection.set_frustum( xmin, xmax, ymin, ymax, near, far ); + projection.set_frustum( xmin, xmax, ymin, ymax, nearp, farp ); } Vector3 cam_target=Matrix3(Vector3(0,0,Math_PI*2*(i/4.0))).xform(Vector3(0,1,0)); diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index 3924ffb75f..110436b9d5 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -131,7 +131,7 @@ void RasterizerGLES3::initialize() { } glEnable(_EXT_DEBUG_OUTPUT_SYNCHRONOUS_ARB); - glDebugMessageCallbackARB(_gl_debug_print, NULL); +// glDebugMessageCallbackARB(_gl_debug_print, NULL); glEnable(_EXT_DEBUG_OUTPUT); #endif diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 524e683738..65591de56e 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -996,7 +996,7 @@ void RasterizerSceneGLES3::light_instance_set_shadow_transform(RID p_light_insta light_instance->shadow_transform[p_pass].camera=p_projection; light_instance->shadow_transform[p_pass].transform=p_transform; - light_instance->shadow_transform[p_pass].far=p_far; + light_instance->shadow_transform[p_pass].farplane=p_far; light_instance->shadow_transform[p_pass].split=p_split; } @@ -4443,7 +4443,7 @@ static _FORCE_INLINE_ Vector3 ImportanceSampleGGX(Vector2 Xi, float Roughness, V float a = Roughness * Roughness; // DISNEY'S ROUGHNESS [see Burley'12 siggraph] // Compute distribution direction - float Phi = 2.0f * M_PI * Xi.x; + float Phi = 2.0f * Math_PI * Xi.x; float CosTheta = Math::sqrt((1.0f - Xi.y) / (1.0f + (a*a - 1.0f) * Xi.y)); float SinTheta = Math::sqrt((float)Math::abs(1.0f - CosTheta * CosTheta)); diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 5eb2be1cc2..ef1b7b8d38 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -482,7 +482,7 @@ public: CameraMatrix camera; Transform transform; - float far; + float farplane; float split; }; diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 8262487f9d..eca916854a 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -133,7 +133,7 @@ Image RasterizerStorageGLES3::_get_gl_image_and_format(const Image& p_image, Ima } break; case Image::FORMAT_RGB565: { -#warning TODO: Convert tod 555 if 565 is not supported (GLES3.3-) +//#warning TODO: Convert tod 555 if 565 is not supported (GLES3.3-) r_gl_internal_format=GL_RGB5; //r_gl_internal_format=GL_RGB565; r_gl_format=GL_RGB; -- cgit v1.2.3 From 37f558cd7b2308f6442f74c5265f12425d9887c8 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Wed, 21 Dec 2016 14:20:35 -0300 Subject: Some BRDF fixes --- drivers/gles3/rasterizer_gles3.cpp | 19 +++++++++++-- drivers/gles3/rasterizer_scene_gles3.cpp | 21 +++++++++++++- drivers/gles3/rasterizer_scene_gles3.h | 1 + drivers/gles3/rasterizer_storage_gles3.cpp | 13 +++++++-- drivers/gles3/rasterizer_storage_gles3.h | 6 ++++ drivers/gles3/shaders/scene.glsl | 44 ++++++++++++++++++++++-------- 6 files changed, 87 insertions(+), 17 deletions(-) (limited to 'drivers/gles3') diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index 110436b9d5..cb42790e67 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -130,9 +130,9 @@ void RasterizerGLES3::initialize() { ERR_PRINT("Error initializing GLAD"); } - glEnable(_EXT_DEBUG_OUTPUT_SYNCHRONOUS_ARB); +// glEnable(_EXT_DEBUG_OUTPUT_SYNCHRONOUS_ARB); // glDebugMessageCallbackARB(_gl_debug_print, NULL); - glEnable(_EXT_DEBUG_OUTPUT); +// glEnable(_EXT_DEBUG_OUTPUT); #endif @@ -169,6 +169,14 @@ void RasterizerGLES3::begin_frame(){ storage->update_dirty_skeletons(); storage->update_dirty_shaders(); storage->update_dirty_materials(); + + storage->info.render_object_count=0; + storage->info.render_material_switch_count=0; + storage->info.render_surface_switch_count=0; + storage->info.render_shader_rebind_count=0; + storage->info.render_vertices_count=0; + + scene->iteration(); @@ -277,6 +285,13 @@ void RasterizerGLES3::end_frame(){ canvas->draw_generic_textured_rect(Rect2(0,0,15,15),Rect2(0,0,1,1)); #endif OS::get_singleton()->swap_buffers(); + +/* print_line("objects: "+itos(storage->info.render_object_count)); + print_line("material chages: "+itos(storage->info.render_material_switch_count)); + print_line("surface changes: "+itos(storage->info.render_surface_switch_count)); + print_line("shader changes: "+itos(storage->info.render_shader_rebind_count)); + print_line("vertices: "+itos(storage->info.render_vertices_count)); +*/ } void RasterizerGLES3::finalize(){ diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 65591de56e..675b6f228d 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -1331,10 +1331,14 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) { 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; + } } break; @@ -1349,10 +1353,14 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) { glDrawElementsInstanced(gl_primitive[s->primitive],s->index_array_len, (s->array_len>=(1<<16))?GL_UNSIGNED_INT:GL_UNSIGNED_SHORT,0,amount); + storage->info.render_vertices_count+=s->index_array_len * amount; + } else { glDrawArraysInstanced(gl_primitive[s->primitive],0,s->array_len,amount); + storage->info.render_vertices_count+=s->array_len * amount; + } } break; @@ -1379,6 +1387,8 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) { int vertices = c.vertices.size(); uint32_t buf_ofs=0; + storage->info.render_vertices_count+=vertices; + if (c.texture.is_valid() && storage->texture_owner.owns(c.texture)) { const RasterizerStorageGLES3::Texture *t = storage->texture_owner.get(c.texture); @@ -1704,6 +1714,8 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e bool first=true; + storage->info.render_object_count+=p_element_count; + for (int i=0;iinfo.render_material_switch_count++; + rebind = _setup_material(material,p_alpha_pass); -// _rinfo.mat_change_count++; + + if (rebind) { + storage->info.render_shader_rebind_count++; + } } if (!(e->sort_key&RenderList::SORT_KEY_UNSHADED_FLAG) && !p_directional_add && !p_shadow) { @@ -1877,6 +1894,8 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e if (prev_base_type != e->instance->base_type || prev_geometry!=e->geometry) { _setup_geometry(e); + storage->info.render_surface_switch_count++; + } _set_cull(e->sort_key&RenderList::SORT_KEY_MIRROR_FLAG,p_reverse_cull); diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index ef1b7b8d38..ce869da131 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -148,6 +148,7 @@ public: } state; + /* SHADOW ATLAS API */ struct ShadowAtlas : public RID_Data { diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index eca916854a..9edc37fe3b 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -826,15 +826,20 @@ Image RasterizerStorageGLES3::texture_get_data(RID p_texture,VS::CubeMapSide p_c DVector data; - int data_size = Image::get_image_data_size(texture->width,texture->height,texture->format,texture->mipmaps>1?-1:0); + int data_size = Image::get_image_data_size(texture->alloc_width,texture->alloc_height,texture->format,texture->mipmaps>1?-1:0); - data.resize(data_size); + data.resize(data_size*2); //add some memory at the end, just in case for buggy drivers DVector::Write wb = data.write(); glActiveTexture(GL_TEXTURE0); glBindTexture(texture->target,texture->tex_id); + glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); + + print_line("GET FORMAT: "+Image::get_format_name(texture->format)+" mipmaps: "+itos(texture->mipmaps)); + + for(int i=0;imipmaps;i++) { int ofs=0; @@ -848,7 +853,9 @@ Image RasterizerStorageGLES3::texture_get_data(RID p_texture,VS::CubeMapSide p_c glGetCompressedTexImage(texture->target,i,&wb[ofs]); } else { + glPixelStorei(GL_PACK_ALIGNMENT, 1); + glGetTexImage(texture->target,i,texture->gl_format_cache,texture->gl_type_cache,&wb[ofs]); } } @@ -856,6 +863,8 @@ Image RasterizerStorageGLES3::texture_get_data(RID p_texture,VS::CubeMapSide p_c wb=DVector::Write(); + data.resize(data_size); + Image img(texture->alloc_width,texture->alloc_height,texture->mipmaps>1?true:false,texture->format,data); return img; diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index b81c3df78a..5d07d0be87 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -91,6 +91,12 @@ public: uint64_t texture_mem; + uint32_t render_object_count; + uint32_t render_material_switch_count; + uint32_t render_surface_switch_count; + uint32_t render_shader_rebind_count; + uint32_t render_vertices_count; + } info; diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index bf561a7e46..c9de56be4f 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -569,7 +569,7 @@ void light_compute(vec3 N, vec3 L,vec3 V,vec3 B, vec3 T,vec3 light_color,vec3 di float speci = dotNL * D * F * vis; - specular += speci * light_color * specular_color * specular_blob_intensity; + specular += speci * light_color /* specular_color*/ * specular_blob_intensity; #if defined(LIGHT_USE_CLEARCOAT) float Dr = GTR1(dotNH, mix(.1,.001,clearcoat_gloss)); @@ -780,7 +780,8 @@ void reflection_process(int idx, vec3 vertex, vec3 normal,vec3 binormal, vec3 ta splane.xy = clamp(splane.xy,clamp_rect.xy,clamp_rect.xy+clamp_rect.zw); highp vec4 reflection; - reflection.rgb = textureLod(reflection_atlas,splane.xy,roughness*5.0).rgb * ( brdf.x + brdf.y); + reflection.rgb = textureLod(reflection_atlas,splane.xy,roughness*5.0).rgb * brdf.x + brdf.y; + if (reflections[idx].params.z < 0.5) { reflection.rgb = mix(skybox,reflection.rgb,blend); } @@ -893,6 +894,7 @@ void gi_probe_compute(sampler3D probe, mat4 probe_xform, vec3 bounds,vec3 cell_s blend=1.0; //radiance +#ifdef VCT_QUALITY_HIGH #define MAX_CONE_DIRS 6 vec3 cone_dirs[MAX_CONE_DIRS] = vec3[] ( @@ -905,13 +907,28 @@ void gi_probe_compute(sampler3D probe, mat4 probe_xform, vec3 bounds,vec3 cell_s ); float cone_weights[MAX_CONE_DIRS] = float[](0.25, 0.15, 0.15, 0.15, 0.15, 0.15); + float cone_angle_tan = 0.577; +#else + +#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) + ); + + float cone_weights[MAX_CONE_DIRS] = float[](0.25, 0.25, 0.25, 0.25); + float cone_angle_tan = 0.98269; +#endif float max_distance = length(bounds); vec3 light=vec3(0.0); for(int i=0;i Date: Thu, 22 Dec 2016 10:00:15 -0300 Subject: can bake for omni and spotlight store normal when baking --- drivers/gles3/rasterizer_gles3.cpp | 6 ++--- drivers/gles3/rasterizer_scene_gles3.cpp | 39 ++++++++++++++++------------ drivers/gles3/rasterizer_scene_gles3.h | 3 ++- drivers/gles3/rasterizer_storage_gles3.cpp | 41 ++++++++++++++++++++++++++++-- drivers/gles3/rasterizer_storage_gles3.h | 13 +++++++--- drivers/gles3/shaders/scene.glsl | 29 ++++++++++++++++----- 6 files changed, 100 insertions(+), 31 deletions(-) (limited to 'drivers/gles3') diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index cb42790e67..bf3b902c5c 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -130,9 +130,9 @@ void RasterizerGLES3::initialize() { ERR_PRINT("Error initializing GLAD"); } -// glEnable(_EXT_DEBUG_OUTPUT_SYNCHRONOUS_ARB); -// glDebugMessageCallbackARB(_gl_debug_print, NULL); -// glEnable(_EXT_DEBUG_OUTPUT); + glEnable(_EXT_DEBUG_OUTPUT_SYNCHRONOUS_ARB); + glDebugMessageCallbackARB(_gl_debug_print, NULL); + glEnable(_EXT_DEBUG_OUTPUT); #endif diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 675b6f228d..1a63d451b1 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -100,6 +100,8 @@ void RasterizerSceneGLES3::shadow_atlas_set_size(RID p_atlas,int p_size){ shadow_atlas->depth=0; shadow_atlas->fbo=0; + + print_line("erasing atlas"); } for(int i=0;i<4;i++) { //clear subdivisions @@ -130,19 +132,18 @@ void RasterizerSceneGLES3::shadow_atlas_set_size(RID p_atlas,int p_size){ glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, shadow_atlas->size, shadow_atlas->size, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); - //interpola nearest (though nvidia can improve this) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); -// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); -// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - // Remove artifact on the edges of the shadowmap glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - // We'll use a depth texture to store the depths in the shadow map - // Attach the depth texture to FBO depth attachment point glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadow_atlas->depth, 0); + + glViewport(0,0,shadow_atlas->size,shadow_atlas->size); + glClearDepth(0); + glClear(GL_DEPTH_BUFFER_BIT); + } } @@ -523,12 +524,19 @@ void RasterizerSceneGLES3::reflection_atlas_set_size(RID p_ref_atlas,int p_size) 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_BASE_LEVEL, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 5); + mmsize=reflection_atlas->size; for(int i=0;i<6;i++) { glGenFramebuffers(1, &reflection_atlas->fbo[i]); glBindFramebuffer(GL_FRAMEBUFFER, reflection_atlas->fbo[i]); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, reflection_atlas->color, i); + + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + ERR_CONTINUE(status!=GL_FRAMEBUFFER_COMPLETE); + glDisable(GL_SCISSOR_TEST); glViewport(0,0,mmsize,mmsize); glClearColor(0,0,0,0); @@ -538,8 +546,6 @@ void RasterizerSceneGLES3::reflection_atlas_set_size(RID p_ref_atlas,int p_size) } - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 5); } @@ -1020,11 +1026,12 @@ RID RasterizerSceneGLES3::gi_probe_instance_create() { return gi_probe_instance_owner.make_rid(gipi); } -void RasterizerSceneGLES3::gi_probe_instance_set_light_data(RID p_probe,RID p_data) { +void RasterizerSceneGLES3::gi_probe_instance_set_light_data(RID p_probe, RID p_base, RID p_data) { GIProbeInstance *gipi = gi_probe_instance_owner.getornull(p_probe); ERR_FAIL_COND(!gipi); gipi->data=p_data; + gipi->probe=storage->gi_probe_owner.getornull(p_base); if (p_data.is_valid()) { RasterizerStorageGLES3::GIProbeData *gipd = storage->gi_probe_data_owner.getornull(p_data); ERR_FAIL_COND(!gipd); @@ -1571,6 +1578,8 @@ void RasterizerSceneGLES3::_setup_light(RenderList::Element *e,const Transform& glBindTexture(GL_TEXTURE_3D,gipi->tex_cache); state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_XFORM1, gipi->transform_to_data * p_view_transform); state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BOUNDS1, gipi->bounds); + state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_MULTIPLIER1, gipi->probe?gipi->probe->dynamic_range*gipi->probe->energy:0.0); + state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BLEND_AMBIENT1, gipi->probe?!gipi->probe->interior:false); state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_CELL_SIZE1, gipi->cell_size_cache); if (gi_probe_count>1) { @@ -1581,7 +1590,8 @@ void RasterizerSceneGLES3::_setup_light(RenderList::Element *e,const Transform& state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_XFORM2, gipi2->transform_to_data * p_view_transform); state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BOUNDS2, gipi2->bounds); state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_CELL_SIZE2, gipi2->cell_size_cache); - + state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_MULTIPLIER2, gipi2->probe?gipi2->probe->dynamic_range*gipi2->probe->energy:0.0); + state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BLEND_AMBIENT2, gipi2->probe?!gipi2->probe->interior:false); state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE2_ENABLED, true ); } else { @@ -4209,7 +4219,6 @@ void RasterizerSceneGLES3::render_shadow(RID p_light,RID p_shadow_atlas,int p_pa fbo=shadow_atlas->fbo; vp_height=shadow_atlas->size; - uint32_t key = shadow_atlas->shadow_owners[p_light]; uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT)&0x3; @@ -4299,24 +4308,22 @@ void RasterizerSceneGLES3::render_shadow(RID p_light,RID p_shadow_atlas,int p_pa render_list.sort_by_depth(false); //shadow is front to back for performance glDepthMask(true); - glColorMask(0,0,0,0); + glColorMask(1,1,1,1); glDisable(GL_BLEND); glDisable(GL_DITHER); glEnable(GL_DEPTH_TEST); - glBindFramebuffer(GL_FRAMEBUFFER,fbo); if (custom_vp_size) { glViewport(0,0,custom_vp_size,custom_vp_size); glScissor(0,0,custom_vp_size,custom_vp_size); + } else { glViewport(x,y,width,height); glScissor(x,y,width,height); } - //glViewport(x,vp_height-(height+y),width,height); - //glScissor(x,vp_height-(height+y),width,height); glEnable(GL_SCISSOR_TEST); glClearDepth(1.0); glClear(GL_DEPTH_BUFFER_BIT); @@ -4331,7 +4338,7 @@ void RasterizerSceneGLES3::render_shadow(RID p_light,RID p_shadow_atlas,int p_pa state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_SHADOW,true); - _render_list(render_list.elements,render_list.element_count,light_transform,light_projection,NULL,!flip_facing,false,true,false,false); + _render_list(render_list.elements,render_list.element_count,light_transform,light_projection,0,!flip_facing,false,true,false,false); state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_SHADOW,false); state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_SHADOW_DUAL_PARABOLOID,false); diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index ce869da131..31d9964ab0 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -531,6 +531,7 @@ public: struct GIProbeInstance : public RID_Data { RID data; + RasterizerStorageGLES3::GIProbe *probe; GLuint tex_cache; Vector3 cell_size_cache; Vector3 bounds; @@ -542,7 +543,7 @@ public: mutable RID_Owner gi_probe_instance_owner; virtual RID gi_probe_instance_create(); - virtual void gi_probe_instance_set_light_data(RID p_probe,RID p_data); + virtual void gi_probe_instance_set_light_data(RID p_probe,RID p_base,RID p_data); virtual void gi_probe_instance_set_transform_to_data(RID p_probe,const Transform& p_xform); virtual void gi_probe_instance_set_bounds(RID p_probe,const Vector3& p_bounds); diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 9edc37fe3b..fe8373b20d 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -4695,6 +4695,8 @@ RID RasterizerStorageGLES3::gi_probe_create() { gip->data_depth=0; gip->bounds=AABB(Vector3(),Vector3(1,1,1)); gip->dynamic_range=1.0; + gip->energy=1.0; + gip->interior=false; gip->version=1; gip->cell_size=1.0; @@ -4773,7 +4775,7 @@ DVector RasterizerStorageGLES3::gi_probe_get_dynamic_data(RID p_probe) cons return gip->dynamic_data; } -void RasterizerStorageGLES3::gi_probe_set_dynamic_range(RID p_probe,float p_range){ +void RasterizerStorageGLES3::gi_probe_set_dynamic_range(RID p_probe,int p_range){ GIProbe *gip = gi_probe_owner.getornull(p_probe); ERR_FAIL_COND(!gip); @@ -4781,7 +4783,7 @@ void RasterizerStorageGLES3::gi_probe_set_dynamic_range(RID p_probe,float p_rang gip->dynamic_range=p_range; } -float RasterizerStorageGLES3::gi_probe_get_dynamic_range(RID p_probe) const{ +int RasterizerStorageGLES3::gi_probe_get_dynamic_range(RID p_probe) const{ const GIProbe *gip = gi_probe_owner.getornull(p_probe); ERR_FAIL_COND_V(!gip,0); @@ -4789,6 +4791,41 @@ float RasterizerStorageGLES3::gi_probe_get_dynamic_range(RID p_probe) const{ return gip->dynamic_range; } +void RasterizerStorageGLES3::gi_probe_set_energy(RID p_probe,float p_range){ + + GIProbe *gip = gi_probe_owner.getornull(p_probe); + ERR_FAIL_COND(!gip); + + gip->energy=p_range; + +} + +void RasterizerStorageGLES3::gi_probe_set_interior(RID p_probe,bool p_enable) { + + GIProbe *gip = gi_probe_owner.getornull(p_probe); + ERR_FAIL_COND(!gip); + + gip->interior=p_enable; + +} + +bool RasterizerStorageGLES3::gi_probe_is_interior(RID p_probe) const{ + + const GIProbe *gip = gi_probe_owner.getornull(p_probe); + ERR_FAIL_COND_V(!gip,false); + + return gip->interior; + +} + +float RasterizerStorageGLES3::gi_probe_get_energy(RID p_probe) const{ + + const GIProbe *gip = gi_probe_owner.getornull(p_probe); + ERR_FAIL_COND_V(!gip,0); + + return gip->energy; +} + void RasterizerStorageGLES3::gi_probe_set_static_data(RID p_gi_probe,const DVector& p_data,VS::GIProbeDataFormat p_format,int p_width,int p_height,int p_depth) { diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index 5d07d0be87..c51cd8d90b 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -890,7 +890,9 @@ public: Transform to_cell; float cell_size; - float dynamic_range; + int dynamic_range; + float energy; + bool interior; uint32_t version; @@ -921,9 +923,14 @@ public: virtual void gi_probe_set_dynamic_data(RID p_probe,const DVector& p_data); virtual DVector gi_probe_get_dynamic_data(RID p_probe) const; - virtual void gi_probe_set_dynamic_range(RID p_probe,float p_range); - virtual float gi_probe_get_dynamic_range(RID p_probe) const; + virtual void gi_probe_set_dynamic_range(RID p_probe,int p_range); + virtual int gi_probe_get_dynamic_range(RID p_probe) const; + + virtual void gi_probe_set_energy(RID p_probe,float p_range); + virtual float gi_probe_get_energy(RID p_probe) const; + virtual void gi_probe_set_interior(RID p_probe,bool p_enable); + virtual bool gi_probe_is_interior(RID p_probe) const; virtual void gi_probe_set_static_data(RID p_gi_probe,const DVector& p_data,VS::GIProbeDataFormat p_format,int p_width,int p_height,int p_depth); virtual DVector gi_probe_get_static_data(RID p_gi_probe) const; diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index c9de56be4f..2dfbbd340d 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -845,14 +845,18 @@ uniform mediump sampler3D gi_probe1; //texunit:-6 uniform highp mat4 gi_probe_xform1; uniform highp vec3 gi_probe_bounds1; uniform highp vec3 gi_probe_cell_size1; +uniform highp float gi_probe_multiplier1; +uniform bool gi_probe_blend_ambient1; uniform mediump sampler3D gi_probe2; //texunit:-7 uniform highp mat4 gi_probe_xform2; uniform highp vec3 gi_probe_bounds2; uniform highp vec3 gi_probe_cell_size2; +uniform highp float gi_probe_multiplier2; uniform bool gi_probe2_enabled; +uniform bool gi_probe_blend_ambient2; -vec3 voxel_cone_trace(sampler3D probe, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance) { +vec3 voxel_cone_trace(sampler3D probe, vec3 cell_size, vec3 pos, vec3 ambient, bool blend_ambient, vec3 direction, float tan_half_angle, float max_distance) { float dist = dot(direction,mix(vec3(-1.0),vec3(1.0),greaterThan(direction,vec3(0.0))))*2.0; @@ -868,10 +872,12 @@ vec3 voxel_cone_trace(sampler3D probe, vec3 cell_size, vec3 pos, vec3 direction, dist += diameter * 0.5; } + color.rgb = mix(color.rgb,mix(ambient,color.rgb,alpha),blend_ambient); + return color.rgb; } -void gi_probe_compute(sampler3D probe, mat4 probe_xform, vec3 bounds,vec3 cell_size,vec3 pos, mat3 normal_mtx,vec3 ref_vec, float roughness, out vec4 out_spec, out vec4 out_diff) { +void gi_probe_compute(sampler3D probe, mat4 probe_xform, vec3 bounds,vec3 cell_size,vec3 pos, vec3 ambient, vec3 environment, bool blend_ambient,float multiplier, mat3 normal_mtx,vec3 ref_vec, float roughness, out vec4 out_spec, out vec4 out_diff) { @@ -928,15 +934,19 @@ void gi_probe_compute(sampler3D probe, mat4 probe_xform, vec3 bounds,vec3 cell_s for(int i=0;i0.0) { -- cgit v1.2.3 From 4e729f38e02274afc91319d8dc9d2dfea9e9438e Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Fri, 23 Dec 2016 00:37:38 -0300 Subject: baking now shows a proper button, and bakes can be saved. --- drivers/gles3/rasterizer_storage_gles3.cpp | 78 ++++++------------------------ drivers/gles3/rasterizer_storage_gles3.h | 20 +++----- 2 files changed, 20 insertions(+), 78 deletions(-) (limited to 'drivers/gles3') diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index fe8373b20d..24e6be588e 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -645,6 +645,10 @@ void RasterizerStorageGLES3::texture_set_data(RID p_texture,const Image& p_image bool srgb; + if (config.keep_original_textures && !(texture->flags&VS::TEXTURE_FLAG_USED_FOR_STREAMING)) { + texture->images[p_cube_side]=p_image; + } + Image img = _get_gl_image_and_format(p_image, p_image.get_format(),texture->flags,format,internal_format,type,compressed,srgb); if (config.shrink_textures_x2 && (p_image.has_mipmaps() || !p_image.is_compressed()) && !(texture->flags&VS::TEXTURE_FLAG_USED_FOR_STREAMING)) { @@ -822,6 +826,9 @@ Image RasterizerStorageGLES3::texture_get_data(RID p_texture,VS::CubeMapSide p_c ERR_FAIL_COND_V(texture->data_size==0,Image()); ERR_FAIL_COND_V(texture->render_target,Image()); + if (!texture->images[p_cube_side].empty()) + return texture->images[p_cube_side]; + #ifdef GLES_OVER_GL DVector data; @@ -871,6 +878,7 @@ Image RasterizerStorageGLES3::texture_get_data(RID p_texture,VS::CubeMapSide p_c #else ERR_EXPLAIN("Sorry, It's not posible to obtain images back in OpenGL ES"); + return Image(); #endif } @@ -1047,6 +1055,11 @@ void RasterizerStorageGLES3::texture_set_shrink_all_x2_on_set_data(bool p_enable config.shrink_textures_x2=p_enable; } +void RasterizerStorageGLES3::textures_keep_original(bool p_enable) { + + config.keep_original_textures=p_enable; +} + RID RasterizerStorageGLES3::texture_create_radiance_cubemap(RID p_source,int p_resolution) const { Texture * texture = texture_owner.get(p_source); @@ -4690,9 +4703,6 @@ RID RasterizerStorageGLES3::gi_probe_create() { GIProbe *gip = memnew( GIProbe ); - gip->data_width=0; - gip->data_height=0; - gip->data_depth=0; gip->bounds=AABB(Vector3(),Vector3(1,1,1)); gip->dynamic_range=1.0; gip->energy=1.0; @@ -4827,64 +4837,6 @@ float RasterizerStorageGLES3::gi_probe_get_energy(RID p_probe) const{ } -void RasterizerStorageGLES3::gi_probe_set_static_data(RID p_gi_probe,const DVector& p_data,VS::GIProbeDataFormat p_format,int p_width,int p_height,int p_depth) { - - GIProbe *gip = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND(!gip); - - if (gip->data.is_valid()) { - free(gip->data); - } - - gip->data=RID(); - //this is platform dependent - - gip->version++; - gip->instance_change_notify(); - -} -DVector RasterizerStorageGLES3::gi_probe_get_static_data(RID p_gi_probe) const { - - const GIProbe *gip = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gip,DVector()); - - //platform dependent - return DVector(); -} -VS::GIProbeDataFormat RasterizerStorageGLES3::gi_probe_get_static_data_format(RID p_gi_probe) const { - - const GIProbe *gip = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gip,VS::GI_PROBE_DATA_RGBA8); - - return gip->data_format; -} -int RasterizerStorageGLES3::gi_probe_get_static_data_width(RID p_probe) const { - - const GIProbe *gip = gi_probe_owner.getornull(p_probe); - ERR_FAIL_COND_V(!gip,0); - - return gip->data_width; -} -int RasterizerStorageGLES3::gi_probe_get_static_data_height(RID p_probe) const { - - const GIProbe *gip = gi_probe_owner.getornull(p_probe); - ERR_FAIL_COND_V(!gip,0); - return gip->data_height; -} -int RasterizerStorageGLES3::gi_probe_get_static_data_depth(RID p_probe) const { - - const GIProbe *gip = gi_probe_owner.getornull(p_probe); - ERR_FAIL_COND_V(!gip,0); - return gip->data_depth; -} - -RID RasterizerStorageGLES3::gi_probe_get_data(RID p_probe) { - - const GIProbe *gip = gi_probe_owner.getornull(p_probe); - ERR_FAIL_COND_V(!gip,RID()); - - return gip->data; -} uint32_t RasterizerStorageGLES3::gi_probe_get_version(RID p_probe) { @@ -5892,9 +5844,6 @@ bool RasterizerStorageGLES3::free(RID p_rid){ // delete the texture GIProbe *gi_probe = gi_probe_owner.get(p_rid); - if (gi_probe->data.is_valid()) { - free(gi_probe->data); - } gi_probe_owner.free(p_rid); memdelete(gi_probe); @@ -6119,6 +6068,7 @@ void RasterizerStorageGLES3::initialize() { glEnable(_EXT_TEXTURE_CUBE_MAP_SEAMLESS); frame.count=0; + config.keep_original_textures=false; } void RasterizerStorageGLES3::finalize() { diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index c51cd8d90b..5a8246f030 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -56,6 +56,8 @@ public: int max_texture_size; Set extensions; + + bool keep_original_textures; } config; mutable struct Shaders { @@ -221,6 +223,8 @@ public: RenderTarget *render_target; + Image images[6]; + Texture() { using_srgb=false; @@ -272,6 +276,8 @@ public: virtual RID texture_create_radiance_cubemap(RID p_source,int p_resolution=-1) const; + virtual void textures_keep_original(bool p_enable); + /* SKYBOX API */ struct SkyBox : public RID_Data { @@ -898,12 +904,6 @@ public: DVector dynamic_data; - RID data; - int data_width; - int data_height; - int data_depth; - VS::GIProbeDataFormat data_format; - }; @@ -932,14 +932,6 @@ public: virtual void gi_probe_set_interior(RID p_probe,bool p_enable); virtual bool gi_probe_is_interior(RID p_probe) const; - virtual void gi_probe_set_static_data(RID p_gi_probe,const DVector& p_data,VS::GIProbeDataFormat p_format,int p_width,int p_height,int p_depth); - virtual DVector gi_probe_get_static_data(RID p_gi_probe) const; - virtual VS::GIProbeDataFormat gi_probe_get_static_data_format(RID p_gi_probe) const; - virtual int gi_probe_get_static_data_width(RID p_probe) const; - virtual int gi_probe_get_static_data_height(RID p_probe) const; - virtual int gi_probe_get_static_data_depth(RID p_probe) const; - - virtual RID gi_probe_get_data(RID p_probe); //get data in case this is static virtual uint32_t gi_probe_get_version(RID p_probe); struct GIProbeData : public RID_Data { -- cgit v1.2.3 From 19ba45587c878e1859383797a454852c5b525c64 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Fri, 23 Dec 2016 01:05:21 -0300 Subject: put some limits to max ubo sizes to avoid crashes --- drivers/gles3/rasterizer_scene_gles3.cpp | 6 +++--- drivers/gles3/rasterizer_scene_gles3.h | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/gles3') diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 1a63d451b1..d559d96287 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -4706,7 +4706,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=max_ubo_size/ubo_light_size; + state.max_ubo_lights=MIN(RenderList::MAX_LIGHTS,max_ubo_size/ubo_light_size); print_line("max ubo light: "+itos(state.max_ubo_lights)); state.spot_array_tmp = (uint8_t*)memalloc(ubo_light_size*state.max_ubo_lights); @@ -4734,7 +4734,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=max_ubo_size/sizeof(ReflectionProbeDataUBO); + state.max_ubo_reflections=MIN(RenderList::MAX_REFLECTIONS,max_ubo_size/sizeof(ReflectionProbeDataUBO)); print_line("max ubo reflections: "+itos(state.max_ubo_reflections)+" ubo size: "+itos(sizeof(ReflectionProbeDataUBO))); state.reflection_array_tmp = (uint8_t*)memalloc(sizeof(ReflectionProbeDataUBO)*state.max_ubo_reflections); @@ -4746,7 +4746,7 @@ void RasterizerSceneGLES3::initialize() { state.scene_shader.add_custom_define("#define MAX_REFLECTION_DATA_STRUCTS "+itos(state.max_ubo_reflections)+"\n"); - state.max_skeleton_bones=max_ubo_size/(12*sizeof(float)); + state.max_skeleton_bones=MIN(2048,max_ubo_size/(12*sizeof(float))); state.scene_shader.add_custom_define("#define MAX_SKELETON_BONES "+itos(state.max_skeleton_bones)+"\n"); diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 31d9964ab0..61628f102f 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -557,6 +557,7 @@ public: SORT_FLAG_INSTANCING=2, MAX_DIRECTIONAL_LIGHTS=16, MAX_LIGHTS=4096, + MAX_REFLECTIONS=1024, SORT_KEY_DEPTH_LAYER_SHIFT=60, -- cgit v1.2.3 From 6b35211c53f14e5c9ea00b4e8382f497a11240c8 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Fri, 23 Dec 2016 01:16:04 -0300 Subject: eliminated some crashes according to llvm address sanitizer --- drivers/gles3/rasterizer_scene_gles3.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gles3') diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 61628f102f..3fdbdb95d0 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -536,6 +536,8 @@ public: Vector3 cell_size_cache; Vector3 bounds; Transform transform_to_data; + + GIProbeInstance() { probe=NULL; tex_cache=0; } }; -- cgit v1.2.3 From 3adb42e217d29033e0637ae334790aa1d742d194 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Fri, 23 Dec 2016 08:47:16 -0300 Subject: Fixed many more bugs reported by Valgrind --- drivers/gles3/rasterizer_scene_gles3.cpp | 4 ++++ drivers/gles3/rasterizer_storage_gles3.cpp | 3 +++ drivers/gles3/shader_compiler_gles3.cpp | 1 + 3 files changed, 8 insertions(+) (limited to 'drivers/gles3') diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index d559d96287..d380d8d149 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -454,6 +454,7 @@ RID RasterizerSceneGLES3::reflection_atlas_create() { ReflectionAtlas *reflection_atlas = memnew( ReflectionAtlas ); reflection_atlas->subdiv=0; reflection_atlas->color=0; + reflection_atlas->size=0; for(int i=0;i<6;i++) { reflection_atlas->fbo[i]=0; } @@ -4576,6 +4577,9 @@ void RasterizerSceneGLES3::_generate_brdf() { void RasterizerSceneGLES3::initialize() { + + render_pass=0; + state.scene_shader.init(); default_shader = storage->shader_create(VS::SHADER_SPATIAL); diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 24e6be588e..ec71f64049 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -1476,9 +1476,11 @@ void RasterizerStorageGLES3::_update_shader(Shader* p_shader) const { p_shader->spatial.depth_draw_mode=Shader::Spatial::DEPTH_DRAW_OPAQUE; p_shader->spatial.cull_mode=Shader::Spatial::CULL_MODE_BACK; p_shader->spatial.uses_alpha=false; + p_shader->spatial.uses_discard=false; p_shader->spatial.unshaded=false; p_shader->spatial.ontop=false; p_shader->spatial.uses_sss=false; + p_shader->spatial.uses_vertex=false; shaders.actions_scene.render_mode_values["blend_add"]=Pair(&p_shader->spatial.blend_mode,Shader::Spatial::BLEND_MODE_ADD); shaders.actions_scene.render_mode_values["blend_mix"]=Pair(&p_shader->spatial.blend_mode,Shader::Spatial::BLEND_MODE_MIX); @@ -1501,6 +1503,7 @@ void RasterizerStorageGLES3::_update_shader(Shader* p_shader) const { shaders.actions_scene.usage_flag_pointers["VERTEX"]=&p_shader->spatial.uses_vertex; shaders.actions_scene.usage_flag_pointers["SSS_STRENGTH"]=&p_shader->spatial.uses_sss; + shaders.actions_scene.usage_flag_pointers["DISCARD"]=&p_shader->spatial.uses_discard; actions=&shaders.actions_scene; actions->uniforms=&p_shader->uniforms; diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp index 5c7a72ab17..336cf7b34b 100644 --- a/drivers/gles3/shader_compiler_gles3.cpp +++ b/drivers/gles3/shader_compiler_gles3.cpp @@ -579,6 +579,7 @@ Error ShaderCompilerGLES3::compile(VS::ShaderMode p_mode, const String& p_code, r_gen_code.uses_vertex_time=false; + used_name_defines.clear(); used_rmode_defines.clear(); -- cgit v1.2.3 From 0d4abf2aa3a336a8a04c83f0576c6b42783ba6e9 Mon Sep 17 00:00:00 2001 From: reduz Date: Sat, 24 Dec 2016 16:23:30 -0300 Subject: fixed a horrible bug on Windows AMD, scenes saved until now in this branch are no longer valid :( --- drivers/gles3/rasterizer_gles3.cpp | 8 +++++++- drivers/gles3/rasterizer_scene_gles3.cpp | 4 ++++ drivers/gles3/rasterizer_storage_gles3.cpp | 13 ++++++++----- drivers/gles3/shaders/scene.glsl | 2 +- 4 files changed, 20 insertions(+), 7 deletions(-) (limited to 'drivers/gles3') diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index bf3b902c5c..ccc5c70c97 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -42,7 +42,13 @@ RasterizerScene *RasterizerGLES3::get_scene() { #define _EXT_DEBUG_SEVERITY_LOW_ARB 0x9148 #define _EXT_DEBUG_OUTPUT 0x92E0 -static void _gl_debug_print(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const GLvoid *userParam) +#ifdef WINDOWS_ENABLED +#define GLAPIENTRY APIENTRY +#else +#define GLAPIENTRY +#endif + +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) diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index d380d8d149..7fdd08a834 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -1337,6 +1337,7 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) { 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; @@ -1349,6 +1350,9 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) { } + + + } break; case VS::INSTANCE_MULTIMESH: { diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index ec71f64049..ffcd462808 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -2481,6 +2481,8 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::P for(int i=0;iindex_id); glBufferData(GL_ELEMENT_ARRAY_BUFFER,index_array_size,ir.ptr(),GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); //unbind + + } //generate arrays for faster state switching - for(int i=0;i<2;i++) { + for(int ai=0;ai<2;ai++) { - if (i==0) { + if (ai==0) { //for normal draw glGenVertexArrays(1,&surface->array_id); glBindVertexArray(surface->array_id); glBindBuffer(GL_ARRAY_BUFFER,surface->vertex_id); - } else if (i==1) { + } else if (ai==1) { //for instancing draw (can be changed and no one cares) glGenVertexArrays(1,&surface->instancing_array_id); glBindVertexArray(surface->instancing_array_id); diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index 2dfbbd340d..b0b2782307 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -872,7 +872,7 @@ vec3 voxel_cone_trace(sampler3D probe, vec3 cell_size, vec3 pos, vec3 ambient, b dist += diameter * 0.5; } - color.rgb = mix(color.rgb,mix(ambient,color.rgb,alpha),blend_ambient); + //color.rgb = mix(color.rgb,mix(ambient,color.rgb,alpha),blend_ambient); return color.rgb; } -- cgit v1.2.3 From 289bc881aaec35cc127256137abc7dcf116afd48 Mon Sep 17 00:00:00 2001 From: reduz Date: Sun, 25 Dec 2016 08:05:23 -0300 Subject: now it really works on window for real --- drivers/gles3/rasterizer_storage_gles3.cpp | 38 +++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) (limited to 'drivers/gles3') diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index ffcd462808..698788316c 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -2460,6 +2460,8 @@ RID RasterizerStorageGLES3::mesh_create(){ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::PrimitiveType p_primitive,const DVector& p_array,int p_vertex_count,const DVector& p_index_array,int p_index_count,const AABB& p_aabb,const Vector >& p_blend_shapes,const Vector& p_bone_aabbs){ + DVector array = p_array; + Mesh *mesh = mesh_owner.getornull(p_mesh); ERR_FAIL_COND(!mesh); @@ -2657,7 +2659,35 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::P int array_size = stride * p_vertex_count; int index_array_size=0; - ERR_FAIL_COND(p_array.size()!=array_size); + print_line("desired size: "+itos(array_size)+" vcount "+itos(p_vertex_count)+" should be: "+itos(array.size()+p_vertex_count*2)+" but is "+itos(array.size())); + if (array.size()!=array_size && array.size()+p_vertex_count*2 == array_size) { + //old format, convert + array = DVector(); + + array.resize( p_array.size()+p_vertex_count*2 ); + + DVector::Write w = array.write(); + DVector::Read r = p_array.read(); + + uint16_t *w16 = (uint16_t*)w.ptr(); + const uint16_t *r16 = (uint16_t*)r.ptr(); + + uint16_t one = Math::make_half_float(1); + + for(int i=0;iactive=true; surface->array_len=p_vertex_count; surface->index_array_len=p_index_count; - surface->array_byte_size=p_array.size(); + surface->array_byte_size=array.size(); surface->index_array_byte_size=p_index_array.size(); surface->primitive=p_primitive; surface->mesh=mesh; @@ -2704,7 +2734,7 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::P { - DVector::Read vr = p_array.read(); + DVector::Read vr = array.read(); glGenBuffers(1,&surface->vertex_id); glBindBuffer(GL_ARRAY_BUFFER,surface->vertex_id); @@ -5907,7 +5937,9 @@ void RasterizerStorageGLES3::initialize() { { int max_extensions=0; + print_line("getting extensions"); glGetIntegerv(GL_NUM_EXTENSIONS,&max_extensions); + print_line("total "+itos(max_extensions)); for(int i=0;i Date: Fri, 30 Dec 2016 08:35:54 -0300 Subject: begin work on new particle system --- drivers/gles3/rasterizer_storage_gles3.cpp | 194 ++++++++++++++++++++++++++--- drivers/gles3/rasterizer_storage_gles3.h | 86 ++++++++++++- drivers/gles3/shaders/SCsub | 1 + drivers/gles3/shaders/particles.glsl | 114 +++++++++++++++++ drivers/gles3/shaders/scene.glsl | 10 +- 5 files changed, 384 insertions(+), 21 deletions(-) create mode 100644 drivers/gles3/shaders/particles.glsl (limited to 'drivers/gles3') diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 698788316c..3fc0513542 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -4882,37 +4882,45 @@ uint32_t RasterizerStorageGLES3::gi_probe_get_version(RID p_probe) { return gip->version; } -RID RasterizerStorageGLES3::gi_probe_dynamic_data_create(int p_width,int p_height,int p_depth) { +RasterizerStorage::GIProbeCompression RasterizerStorageGLES3::gi_probe_get_dynamic_data_get_preferred_compression() const { + if (config.s3tc_supported) { + return GI_PROBE_S3TC; + } else { + return GI_PROBE_UNCOMPRESSED; + } +} + +RID RasterizerStorageGLES3::gi_probe_dynamic_data_create(int p_width, int p_height, int p_depth, GIProbeCompression p_compression) { GIProbeData *gipd = memnew( GIProbeData ); gipd->width=p_width; gipd->height=p_height; gipd->depth=p_depth; + gipd->compression=p_compression; glActiveTexture(GL_TEXTURE0); glGenTextures(1,&gipd->tex_id); glBindTexture(GL_TEXTURE_3D,gipd->tex_id); int level=0; + int min_size=1; + + if (gipd->compression==GI_PROBE_S3TC) { + min_size=4; + } print_line("dyndata create"); while(true) { - Vector data; - data.resize(p_width*p_height*p_depth*4); - - - for(int i=0;icompression==GI_PROBE_S3TC) { + int size = p_width * p_height * p_depth; + glCompressedTexImage3D(GL_TEXTURE_3D,level,_EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT,p_width,p_height,p_depth,0, size,NULL); + } else { + glTexImage3D(GL_TEXTURE_3D,level,GL_RGBA8,p_width,p_height,p_depth,0,GL_RGBA,GL_UNSIGNED_BYTE,NULL); } - glTexImage3D(GL_TEXTURE_3D,level,GL_RGBA8,p_width,p_height,p_depth,0,GL_RGBA,GL_UNSIGNED_BYTE,data.ptr()); - if (p_width<=1 || p_height<=1 || p_depth<=1) + if (p_width<=min_size || p_height<=min_size || p_depth<=min_size) break; p_width>>=1; p_height>>=1; @@ -4933,7 +4941,7 @@ RID RasterizerStorageGLES3::gi_probe_dynamic_data_create(int p_width,int p_heigh return gi_probe_data_owner.make_rid(gipd); } -void RasterizerStorageGLES3::gi_probe_dynamic_data_update_rgba8(RID p_gi_probe_data, int p_depth_slice, int p_slice_count, int p_mipmap, const void *p_data) { +void RasterizerStorageGLES3::gi_probe_dynamic_data_update(RID p_gi_probe_data, int p_depth_slice, int p_slice_count, int p_mipmap, const void *p_data) { GIProbeData *gipd = gi_probe_data_owner.getornull(p_gi_probe_data); ERR_FAIL_COND(!gipd); @@ -4957,14 +4965,168 @@ void RasterizerStorageGLES3::gi_probe_dynamic_data_update_rgba8(RID p_gi_probe_d */ glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_3D,gipd->tex_id); - glTexSubImage3D(GL_TEXTURE_3D,p_mipmap,0,0,p_depth_slice,gipd->width>>p_mipmap,gipd->height>>p_mipmap,p_slice_count,GL_RGBA,GL_UNSIGNED_BYTE,p_data); + if (gipd->compression==GI_PROBE_S3TC) { + int size = (gipd->width>>p_mipmap) * (gipd->height>>p_mipmap) * p_slice_count; + glCompressedTexSubImage3D(GL_TEXTURE_3D,p_mipmap,0,0,p_depth_slice,gipd->width>>p_mipmap,gipd->height>>p_mipmap,p_slice_count,_EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT,size, p_data); + } else { + glTexSubImage3D(GL_TEXTURE_3D,p_mipmap,0,0,p_depth_slice,gipd->width>>p_mipmap,gipd->height>>p_mipmap,p_slice_count,GL_RGBA,GL_UNSIGNED_BYTE,p_data); + } //glTexImage3D(GL_TEXTURE_3D,p_mipmap,GL_RGBA8,gipd->width>>p_mipmap,gipd->height>>p_mipmap,gipd->depth>>p_mipmap,0,GL_RGBA,GL_UNSIGNED_BYTE,p_data); //glTexImage3D(GL_TEXTURE_3D,p_mipmap,GL_RGBA8,gipd->width>>p_mipmap,gipd->height>>p_mipmap,gipd->depth>>p_mipmap,0,GL_RGBA,GL_UNSIGNED_BYTE,data.ptr()); - print_line("update rgba8 "+itos(p_mipmap)); + +} + +/////// + + +RID RasterizerStorageGLES3::particles_create() { + + Particles *particles = memnew( Particles ); + + + return particles_owner.make_rid(particles); +} + +void RasterizerStorageGLES3::particles_set_emitting(RID p_particles,bool p_emitting) { + + Particles *particles = particles_owner.getornull(p_particles); + ERR_FAIL_COND(!particles); + particles->emitting=p_emitting; + +} +void RasterizerStorageGLES3::particles_set_amount(RID p_particles,int p_amount) { + + Particles *particles = particles_owner.getornull(p_particles); + ERR_FAIL_COND(!particles); + +} +void RasterizerStorageGLES3::particles_set_lifetime(RID p_particles,float p_lifetime){ + + Particles *particles = particles_owner.getornull(p_particles); + ERR_FAIL_COND(!particles); + particles->lifetime=p_lifetime; +} +void RasterizerStorageGLES3::particles_set_pre_process_time(RID p_particles,float p_time) { + + Particles *particles = particles_owner.getornull(p_particles); + ERR_FAIL_COND(!particles); + particles->pre_process_time=p_time; + +} +void RasterizerStorageGLES3::particles_set_explosiveness_ratio(RID p_particles,float p_ratio) { + + Particles *particles = particles_owner.getornull(p_particles); + ERR_FAIL_COND(!particles); + particles->explosiveness=p_ratio; +} +void RasterizerStorageGLES3::particles_set_randomness_ratio(RID p_particles,float p_ratio) { + + Particles *particles = particles_owner.getornull(p_particles); + ERR_FAIL_COND(!particles); + particles->randomness=p_ratio; + +} +void RasterizerStorageGLES3::particles_set_custom_aabb(RID p_particles,const AABB& p_aabb) { + + Particles *particles = particles_owner.getornull(p_particles); + ERR_FAIL_COND(!particles); + particles->custom_aabb=p_aabb; + } +void RasterizerStorageGLES3::particles_set_gravity(RID p_particles,const Vector3& p_gravity) { + Particles *particles = particles_owner.getornull(p_particles); + ERR_FAIL_COND(!particles); + particles->gravity=p_gravity; + +} +void RasterizerStorageGLES3::particles_set_use_local_coordinates(RID p_particles,bool p_enable) { + + Particles *particles = particles_owner.getornull(p_particles); + ERR_FAIL_COND(!particles); + + particles->use_local_coords=p_enable; +} +void RasterizerStorageGLES3::particles_set_process_material(RID p_particles,RID p_material) { + + Particles *particles = particles_owner.getornull(p_particles); + ERR_FAIL_COND(!particles); + + particles->process_material=p_material; +} + +void RasterizerStorageGLES3::particles_set_emission_shape(RID p_particles, VS::ParticlesEmissionShape p_shape) { + + Particles *particles = particles_owner.getornull(p_particles); + ERR_FAIL_COND(!particles); + + particles->emission_shape=p_shape; +} +void RasterizerStorageGLES3::particles_set_emission_sphere_radius(RID p_particles,float p_radius) { + + Particles *particles = particles_owner.getornull(p_particles); + ERR_FAIL_COND(!particles); + + particles->emission_sphere_radius=p_radius; +} +void RasterizerStorageGLES3::particles_set_emission_box_extents(RID p_particles,const Vector3& p_extents) { + + Particles *particles = particles_owner.getornull(p_particles); + ERR_FAIL_COND(!particles); + + particles->emission_box_extents=p_extents; +} +void RasterizerStorageGLES3::particles_set_emission_points(RID p_particles,const DVector& p_points) { + + Particles *particles = particles_owner.getornull(p_particles); + ERR_FAIL_COND(!particles); + + particles->emission_points=p_points; +} + + +void RasterizerStorageGLES3::particles_set_draw_order(RID p_particles,VS::ParticlesDrawOrder p_order) { + + Particles *particles = particles_owner.getornull(p_particles); + ERR_FAIL_COND(!particles); + + particles->draw_order=p_order; +} + +void RasterizerStorageGLES3::particles_set_draw_passes(RID p_particles,int p_count) { + + Particles *particles = particles_owner.getornull(p_particles); + ERR_FAIL_COND(!particles); + + particles->draw_passes.resize(p_count); +} +void RasterizerStorageGLES3::particles_set_draw_pass_material(RID p_particles,int p_pass, RID p_material) { + + Particles *particles = particles_owner.getornull(p_particles); + ERR_FAIL_COND(!particles); + ERR_FAIL_INDEX(p_pass,particles->draw_passes.size()); + p_pass,particles->draw_passes[p_pass].material=p_material; + +} +void RasterizerStorageGLES3::particles_set_draw_pass_mesh(RID p_particles,int p_pass, RID p_mesh) { + + Particles *particles = particles_owner.getornull(p_particles); + ERR_FAIL_COND(!particles); + ERR_FAIL_INDEX(p_pass,particles->draw_passes.size()); + p_pass,particles->draw_passes[p_pass].mesh=p_mesh; + +} + +AABB RasterizerStorageGLES3::particles_get_current_aabb(RID p_particles) { + + const Particles *particles = particles_owner.getornull(p_particles); + ERR_FAIL_COND_V(!particles,AABB()); + + return particles->computed_aabb; +} +//////// void RasterizerStorageGLES3::instance_add_skeleton(RID p_skeleton,RasterizerScene::InstanceBase *p_instance) { diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index 5a8246f030..b0f9800159 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -941,6 +941,7 @@ public: int depth; int levels; GLuint tex_id; + GIProbeCompression compression; GIProbeData() { } @@ -948,9 +949,90 @@ public: mutable RID_Owner gi_probe_data_owner; - virtual RID gi_probe_dynamic_data_create(int p_width,int p_height,int p_depth); - virtual void gi_probe_dynamic_data_update_rgba8(RID p_gi_probe_data,int p_depth_slice,int p_slice_count,int p_mipmap,const void* p_data); + virtual GIProbeCompression gi_probe_get_dynamic_data_get_preferred_compression() const; + virtual RID gi_probe_dynamic_data_create(int p_width,int p_height,int p_depth,GIProbeCompression p_compression); + virtual void gi_probe_dynamic_data_update(RID p_gi_probe_data,int p_depth_slice,int p_slice_count,int p_mipmap,const void* p_data); + /* PARTICLES */ + + struct Particles : public Instantiable { + + bool emitting; + int amount; + float lifetime; + float pre_process_time; + float explosiveness; + float randomness; + AABB custom_aabb; + Vector3 gravity; + bool use_local_coords; + RID process_material; + + VS::ParticlesEmissionShape emission_shape; + float emission_sphere_radius; + Vector3 emission_box_extents; + DVector emission_points; + GLuint emission_point_texture; + + VS::ParticlesDrawOrder draw_order; + struct DrawPass { + RID mesh; + RID material; + }; + + Vector draw_passes; + + AABB computed_aabb; + + Particles() { + emitting=false; + amount=0; + lifetime=1.0;; + pre_process_time=0.0; + explosiveness=0.0; + randomness=0.0; + use_local_coords=true; + + draw_order=VS::PARTICLES_DRAW_ORDER_INDEX; + emission_shape=VS::PARTICLES_EMSSION_POINT; + emission_sphere_radius=1.0; + float emission_sphere_radius; + emission_box_extents=Vector3(1,1,1); + emission_point_texture=0; + } + + }; + + mutable RID_Owner particles_owner; + + virtual RID particles_create(); + + virtual void particles_set_emitting(RID p_particles,bool p_emitting); + virtual void particles_set_amount(RID p_particles,int p_amount); + virtual void particles_set_lifetime(RID p_particles,float p_lifetime); + virtual void particles_set_pre_process_time(RID p_particles,float p_time); + virtual void particles_set_explosiveness_ratio(RID p_particles,float p_ratio); + virtual void particles_set_randomness_ratio(RID p_particles,float p_ratio); + virtual void particles_set_custom_aabb(RID p_particles,const AABB& p_aabb); + virtual void particles_set_gravity(RID p_particles,const Vector3& p_gravity); + virtual void particles_set_use_local_coordinates(RID p_particles,bool p_enable); + virtual void particles_set_process_material(RID p_particles,RID p_material); + + virtual void particles_set_emission_shape(RID p_particles,VS::ParticlesEmissionShape p_shape); + virtual void particles_set_emission_sphere_radius(RID p_particles,float p_radius); + virtual void particles_set_emission_box_extents(RID p_particles,const Vector3& p_extents); + virtual void particles_set_emission_points(RID p_particles,const DVector& p_points); + + + virtual void particles_set_draw_order(RID p_particles,VS::ParticlesDrawOrder p_order); + + virtual void particles_set_draw_passes(RID p_particles,int p_count); + virtual void particles_set_draw_pass_material(RID p_particles,int p_pass, RID p_material); + virtual void particles_set_draw_pass_mesh(RID p_particles,int p_pass, RID p_mesh); + + virtual AABB particles_get_current_aabb(RID p_particles); + + /* INSTANCE */ virtual void instance_add_skeleton(RID p_skeleton,RasterizerScene::InstanceBase *p_instance); virtual void instance_remove_skeleton(RID p_skeleton,RasterizerScene::InstanceBase *p_instance); diff --git a/drivers/gles3/shaders/SCsub b/drivers/gles3/shaders/SCsub index 272f9bb5e1..f9baeae97d 100644 --- a/drivers/gles3/shaders/SCsub +++ b/drivers/gles3/shaders/SCsub @@ -17,5 +17,6 @@ if env['BUILDERS'].has_key('GLES3_GLSL'): env.GLES3_GLSL('ssao_blur.glsl'); env.GLES3_GLSL('exposure.glsl'); env.GLES3_GLSL('tonemap.glsl'); + env.GLES3_GLSL('particles.glsl'); diff --git a/drivers/gles3/shaders/particles.glsl b/drivers/gles3/shaders/particles.glsl new file mode 100644 index 0000000000..fb6060957e --- /dev/null +++ b/drivers/gles3/shaders/particles.glsl @@ -0,0 +1,114 @@ +[vertex] + + + +layout(location=0) in highp vec4 pos_lifetime; +layout(location=1) in highp vec4 color; +layout(location=2) in highp vec4 velocity_seed; +layout(location=3) in highp vec4 rot_active; + + +struct Attractor { + + vec3 pos; + vec3 dir; + float radius; + float eat_radius; + float strength; + float attenuation; +}; + +#define MAX_ATTRACTORS 64 + +uniform mat4 origin; +uniform float system_phase; +uniform float prev_system_phase; +uniform float total_particles; +uniform float explosiveness; +uniform vec4 time; +uniform float delta; +uniform vec3 gravity; +uniform int attractor_count; +uniform Attractor attractors[MAX_ATTRACTORS]; + + +out highp vec4 out_pos_lifetime; //tfb: +out highp vec4 out_color; //tfb: +out highp vec4 out_velocity_seed; //tfb: +out highp vec4 out_rot_active; //tfb: + +void main() { + + bool apply_forces=true; + bool apply_velocity=true; + + float mass = 1.0; + + float restart_phase = float(gl_InstanceID)/total_particles; + restart_phase*= explosiveness; + bool restart=false; + + if (system_phase > prev_system_phase) { + restart = prev_system_phase < restart_phase && system_phase >= restart_phase; + } else { + restart = prev_system_phase < restart_phase || system_phase >= restart_phase; + } + + if (restart) { + out_rot_active.a=1.0; + } + + out_pos_lifetime=pos_lifetime; + out_color=color; + out_velocity_seed=velocity_seed; + out_rot_active=rot_active; + + if (out_rot_active.a) { + //execute shader + + } + + + if (apply_forces) { + + vec3 force = gravity; + for(int i=0;i0 && attractors[i].eat_radius > dist) { + rot_active.a=0.0; + } + + rel_vec = normalize(rel_vec); + + float attenuation = pow(dist / attractors[i].radius,attractors[i].attenuation); + + if (attractors[i].dir==vec3(0.0)) { + //towards center + force+=attractors[i].strength * rel_vec * attenuation * mass; + } else { + force+=attractors[i].strength * attractors[i].dir * attenuation *mass; + + } + } + + out_velocity_seed.xyz += force * delta; + } + + if (apply_velocity) { + + out_pos_lifetime.xyz += out_velocity_seed.xyz * delta; + } + +} + +[fragment] + + +void main() { + + +} diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index b0b2782307..90c501ea32 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -899,8 +899,10 @@ void gi_probe_compute(sampler3D probe, mat4 probe_xform, vec3 bounds,vec3 cell_s float blend = 1.001-max(blendv.x,max(blendv.y,blendv.z)); blend=1.0; + float max_distance = length(bounds); + //radiance -#ifdef VCT_QUALITY_HIGH +#ifndef VCT_QUALITY_HIGH #define MAX_CONE_DIRS 6 vec3 cone_dirs[MAX_CONE_DIRS] = vec3[] ( @@ -914,6 +916,7 @@ void gi_probe_compute(sampler3D probe, mat4 probe_xform, vec3 bounds,vec3 cell_s float cone_weights[MAX_CONE_DIRS] = float[](0.25, 0.15, 0.15, 0.15, 0.15, 0.15); float cone_angle_tan = 0.577; + float min_ref_tan = 0.0; #else #define MAX_CONE_DIRS 4 @@ -927,9 +930,10 @@ void gi_probe_compute(sampler3D probe, mat4 probe_xform, vec3 bounds,vec3 cell_s float cone_weights[MAX_CONE_DIRS] = float[](0.25, 0.25, 0.25, 0.25); float cone_angle_tan = 0.98269; + max_distance*=0.5; + float min_ref_tan = 0.2; #endif - float max_distance = length(bounds); vec3 light=vec3(0.0); for(int i=0;i Date: Sat, 31 Dec 2016 10:53:29 -0300 Subject: Some fixes and clean ups --- drivers/gles3/rasterizer_scene_gles3.cpp | 53 ++++++++++++++++++++++++++---- drivers/gles3/rasterizer_storage_gles3.cpp | 19 +++++++++++ drivers/gles3/rasterizer_storage_gles3.h | 4 +++ drivers/gles3/shaders/scene.glsl | 28 ++++++++-------- 4 files changed, 83 insertions(+), 21 deletions(-) (limited to 'drivers/gles3') diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 7fdd08a834..1b080a1216 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -3687,9 +3687,47 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C state.ubo_data.subsurface_scatter_width=subsurface_scatter_size; + state.ubo_data.shadow_z_offset=0; + state.ubo_data.shadow_slope_scale=0; + state.ubo_data.shadow_dual_paraboloid_render_side=0; + state.ubo_data.shadow_dual_paraboloid_render_zfar=0; _setup_environment(env,p_cam_projection,p_cam_transform); + bool fb_cleared=false; + + glDepthFunc(GL_LEQUAL); + + + if (storage->frame.current_rt && true) { + //pre z pass + glDisable(GL_BLEND); + glDepthMask(GL_TRUE); + glEnable(GL_DEPTH_TEST); + glDisable(GL_SCISSOR_TEST); + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->fbo); + glViewport(0,0,storage->frame.current_rt->width,storage->frame.current_rt->height); + + glColorMask(0,0,0,0); + + glClearDepth(1.0); + glClear(GL_DEPTH_BUFFER_BIT); + + + render_list.clear(); + _fill_render_list(p_cull_result,p_cull_count,true); + render_list.sort_by_depth(false); + state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_DEPTH,true); + _render_list(render_list.elements,render_list.element_count,p_cam_transform,p_cam_projection,0,false,false,true,false,false); + state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_DEPTH,false); + + glColorMask(1,1,1,1); + + fb_cleared=true; + render_pass++; + } + + _setup_lights(p_light_cull_result,p_light_cull_count,p_cam_transform.affine_inverse(),p_cam_projection,p_shadow_atlas); _setup_reflections(p_reflection_probe_cull_result,p_reflection_probe_cull_count,p_cam_transform.affine_inverse(),p_cam_projection,p_reflection_atlas,env); @@ -3778,9 +3816,10 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C } } - - glClearDepth(1.0); - glClear(GL_DEPTH_BUFFER_BIT); + if (!fb_cleared) { + glClearDepth(1.0); + glClear(GL_DEPTH_BUFFER_BIT); + } Color clear_color(0,0,0,0); @@ -4287,7 +4326,7 @@ void RasterizerSceneGLES3::render_shadow(RID p_light,RID p_shadow_atlas,int p_pa zfar=light->param[VS::LIGHT_PARAM_RANGE]; bias=light->param[VS::LIGHT_PARAM_SHADOW_BIAS]; - state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_SHADOW_DUAL_PARABOLOID,true); + state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_DEPTH_DUAL_PARABOLOID,true); } } else if (light->type==VS::LIGHT_SPOT) { @@ -4341,12 +4380,12 @@ void RasterizerSceneGLES3::render_shadow(RID p_light,RID p_shadow_atlas,int p_pa _setup_environment(NULL,light_projection,light_transform); - state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_SHADOW,true); + state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_DEPTH,true); _render_list(render_list.elements,render_list.element_count,light_transform,light_projection,0,!flip_facing,false,true,false,false); - state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_SHADOW,false); - state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_SHADOW_DUAL_PARABOLOID,false); + state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_DEPTH,false); + state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_DEPTH_DUAL_PARABOLOID,false); if (light->type==VS::LIGHT_OMNI && light->omni_shadow_mode==VS::LIGHT_OMNI_SHADOW_CUBE && p_pass==5) { diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 3fc0513542..2875c1f788 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -4743,6 +4743,7 @@ RID RasterizerStorageGLES3::gi_probe_create() { gip->dynamic_range=1.0; gip->energy=1.0; gip->interior=false; + gip->compress=false; gip->version=1; gip->cell_size=1.0; @@ -4864,6 +4865,24 @@ bool RasterizerStorageGLES3::gi_probe_is_interior(RID p_probe) const{ } + +void RasterizerStorageGLES3::gi_probe_set_compress(RID p_probe,bool p_enable) { + + GIProbe *gip = gi_probe_owner.getornull(p_probe); + ERR_FAIL_COND(!gip); + + gip->compress=p_enable; + +} + +bool RasterizerStorageGLES3::gi_probe_is_compressed(RID p_probe) const{ + + const GIProbe *gip = gi_probe_owner.getornull(p_probe); + ERR_FAIL_COND_V(!gip,false); + + return gip->compress; + +} float RasterizerStorageGLES3::gi_probe_get_energy(RID p_probe) const{ const GIProbe *gip = gi_probe_owner.getornull(p_probe); diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index b0f9800159..690a169ca2 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -899,6 +899,7 @@ public: int dynamic_range; float energy; bool interior; + bool compress; uint32_t version; @@ -932,6 +933,9 @@ public: virtual void gi_probe_set_interior(RID p_probe,bool p_enable); virtual bool gi_probe_is_interior(RID p_probe) const; + virtual void gi_probe_set_compress(RID p_probe,bool p_enable); + virtual bool gi_probe_is_compressed(RID p_probe) const; + virtual uint32_t gi_probe_get_version(RID p_probe); struct GIProbeData : public RID_Data { diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index 90c501ea32..c18a356a54 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -146,7 +146,7 @@ MATERIAL_UNIFORMS #endif -#ifdef RENDER_SHADOW_DUAL_PARABOLOID +#ifdef RENDER_DEPTH_DUAL_PARABOLOID out highp float dp_clip; @@ -253,10 +253,10 @@ VERTEX_SHADER_CODE binormal_interp = binormal; #endif -#ifdef RENDER_SHADOW +#ifdef RENDER_DEPTH -#ifdef RENDER_SHADOW_DUAL_PARABOLOID +#ifdef RENDER_DEPTH_DUAL_PARABOLOID vertex_interp.z*= shadow_dual_paraboloid_render_side; normal_interp.z*= shadow_dual_paraboloid_render_side; @@ -282,12 +282,12 @@ VERTEX_SHADER_CODE z_ofs += (1.0-abs(normal_interp.z))*shadow_z_slope_scale; vertex_interp.z-=z_ofs; -#endif //RENDER_SHADOW_DUAL_PARABOLOID +#endif //RENDER_DEPTH_DUAL_PARABOLOID -#endif //RENDER_SHADOW +#endif //RENDER_DEPTH -#if !defined(SKIP_TRANSFORM_USED) && !defined(RENDER_SHADOW_DUAL_PARABOLOID) +#if !defined(SKIP_TRANSFORM_USED) && !defined(RENDER_DEPTH_DUAL_PARABOLOID) gl_Position = projection_matrix * vec4(vertex_interp,1.0); #else gl_Position = vertex; @@ -622,7 +622,7 @@ float sample_shadow(highp sampler2DShadow shadow, vec2 shadow_pixel_size, vec2 p } -#ifdef RENDER_SHADOW_DUAL_PARABOLOID +#ifdef RENDER_DEPTH_DUAL_PARABOLOID in highp float dp_clip; @@ -861,20 +861,20 @@ vec3 voxel_cone_trace(sampler3D probe, vec3 cell_size, vec3 pos, vec3 ambient, b float dist = dot(direction,mix(vec3(-1.0),vec3(1.0),greaterThan(direction,vec3(0.0))))*2.0; float alpha=0.0; - vec4 color = vec4(0.0); + vec3 color = vec3(0.0); while(dist < max_distance && alpha < 0.95) { float diameter = max(1.0, 2.0 * tan_half_angle * dist); vec4 scolor = textureLod(probe, (pos + dist * direction) * cell_size, log2(diameter) ); float a = (1.0 - alpha); - color.rgb += a * scolor.rgb; + color += scolor.rgb * a; alpha += a * scolor.a; dist += diameter * 0.5; } //color.rgb = mix(color.rgb,mix(ambient,color.rgb,alpha),blend_ambient); - return color.rgb; + return color; } void gi_probe_compute(sampler3D probe, mat4 probe_xform, vec3 bounds,vec3 cell_size,vec3 pos, vec3 ambient, vec3 environment, bool blend_ambient,float multiplier, mat3 normal_mtx,vec3 ref_vec, float roughness, out vec4 out_spec, out vec4 out_diff) { @@ -1004,7 +1004,7 @@ void gi_probes_compute(vec3 pos, vec3 normal, float roughness, vec3 specular, in void main() { -#ifdef RENDER_SHADOW_DUAL_PARABOLOID +#ifdef RENDER_DEPTH_DUAL_PARABOLOID if (dp_clip>0.0) discard; @@ -1128,7 +1128,7 @@ FRAGMENT_SHADER_CODE vec3 eye_vec = -normalize( vertex_interp ); -#ifndef RENDER_SHADOW +#ifndef RENDER_DEPTH float ndotv = clamp(dot(normal,eye_vec),0.0,1.0); vec2 brdf = texture(brdf_texture, vec2(roughness, ndotv)).xy; @@ -1370,7 +1370,7 @@ LIGHT_SHADER_CODE } #endif -#ifdef RENDER_SHADOW +#ifdef RENDER_DEPTH //nothing happens, so a tree-ssa optimizer will result in no fragment shader :) #else @@ -1424,7 +1424,7 @@ LIGHT_SHADER_CODE -#endif //RENDER_SHADOW +#endif //RENDER_DEPTH } -- cgit v1.2.3 From c2a217c3501b8006a3d2cdf2c678e33def15f275 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Sun, 1 Jan 2017 22:16:52 -0300 Subject: WIP particle system Ability to enable and change MSAA settings Ability to change VCT quality Ability to enable/disable HDR rendering --- drivers/gles3/rasterizer_gles3.cpp | 16 +- drivers/gles3/rasterizer_scene_gles3.cpp | 124 +++++++--- drivers/gles3/rasterizer_scene_gles3.h | 1 - drivers/gles3/rasterizer_storage_gles3.cpp | 318 ++++++++++++++++++++------ drivers/gles3/rasterizer_storage_gles3.h | 53 ++++- drivers/gles3/shader_compiler_gles3.cpp | 19 +- drivers/gles3/shaders/particles.glsl | 121 +++++++--- drivers/gles3/shaders/scene.glsl | 6 +- drivers/gles3/shaders/subsurf_scattering.glsl | 4 +- 9 files changed, 517 insertions(+), 145 deletions(-) (limited to 'drivers/gles3') diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index ccc5c70c97..0998d9c423 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -163,18 +163,30 @@ void RasterizerGLES3::initialize() { void RasterizerGLES3::begin_frame(){ - double time_total = double(OS::get_singleton()->get_ticks_usec())/1000000.0; + uint64_t tick = OS::get_singleton()->get_ticks_usec(); + + double time_total = double(tick)/1000000.0; storage->frame.time[0]=time_total; storage->frame.time[1]=Math::fmod(time_total,3600); storage->frame.time[2]=Math::fmod(time_total,900); storage->frame.time[3]=Math::fmod(time_total,60); storage->frame.count++; + storage->frame.delta = double(tick-storage->frame.prev_tick)/1000000.0; + if (storage->frame.prev_tick==0) { + //to avoid hiccups + storage->frame.delta=0.001; + } + + storage->frame.prev_tick=tick; + + storage->update_dirty_multimeshes(); storage->update_dirty_skeletons(); storage->update_dirty_shaders(); storage->update_dirty_materials(); + storage->update_particles(); storage->info.render_object_count=0; storage->info.render_material_switch_count=0; @@ -186,6 +198,8 @@ void RasterizerGLES3::begin_frame(){ scene->iteration(); + + } void RasterizerGLES3::set_current_render_target(RID p_render_target){ diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 1b080a1216..17e429657b 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -2880,10 +2880,17 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env,const CameraMatrix &p_c glDisable(GL_CULL_FACE); glDisable(GL_BLEND); - bool diffuse_copied=false; if (env->ssao_enabled) { - //ssao + //copy diffuse to front 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_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); + + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + //copy from depth, convert to linear GLint ss[2]; @@ -2960,7 +2967,7 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env,const CameraMatrix &p_c glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.ssao.linear_depth); glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.normal_rough); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.effect); glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->effects.ssao.blur_fbo[0]); //copy to front first Color white(1,1,1,1); @@ -3001,23 +3008,36 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env,const CameraMatrix &p_c state.effect_blur_shader.bind(); state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::SSAO_COLOR,env->ssao_color); glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.diffuse); //previous level, since mipmaps[0] starts one level bigger + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->color); //previous level, since mipmaps[0] starts one level bigger glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.ssao.blur_red[0]); //previous level, since mipmaps[0] starts one level bigger glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo); // copy to base level _copy_screen(); state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::SSAO_MERGE,false); + } else { + //copy diffuse to effect buffer + glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo); + glReadBuffer(GL_COLOR_ATTACHMENT0); + 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_DEPTH_BUFFER_BIT, GL_NEAREST); + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - diffuse_copied=true; } if (state.used_sss) {//sss enabled //copy diffuse while performing sss + //copy normal and roughness to effect buffer + glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo); + glReadBuffer(GL_COLOR_ATTACHMENT3); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->buffers.effect_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); + state.sss_shader.set_conditional(SubsurfScatteringShaderGLES3::USE_11_SAMPLES,subsurface_scatter_quality==SSS_QUALITY_LOW); state.sss_shader.set_conditional(SubsurfScatteringShaderGLES3::USE_17_SAMPLES,subsurface_scatter_quality==SSS_QUALITY_MEDIUM); state.sss_shader.set_conditional(SubsurfScatteringShaderGLES3::USE_25_SAMPLES,subsurface_scatter_quality==SSS_QUALITY_HIGH); @@ -3030,15 +3050,10 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env,const CameraMatrix &p_c state.sss_shader.set_uniform(SubsurfScatteringShaderGLES3::DIR,Vector2(1,0)); glActiveTexture(GL_TEXTURE0); - if (diffuse_copied) { - glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.mip_maps[0].color); - } else { - glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.diffuse); - diffuse_copied=true; - } + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.mip_maps[0].color); glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.motion_sss); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.effect); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->depth); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); @@ -3056,19 +3071,16 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env,const CameraMatrix &p_c } - if (!diffuse_copied) { - // just copy diffuse - storage->shaders.copy.bind(); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.diffuse); - glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo); // copy to base level - _copy_screen(); - } + if (env->ssr_enabled) { + //copy normal and roughness to effect buffer + glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo); + glReadBuffer(GL_COLOR_ATTACHMENT2); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->buffers.effect_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); - if (env->ssr_enabled) { //blur diffuse into effect mipmaps using separatable convolution //storage->shaders.copy.set_conditional(CopyShaderGLES3::GAUSSIAN_HORIZONTAL,true); for(int i=0;iframe.current_rt->effects.mip_maps[1].sizes.size();i++) { @@ -3127,14 +3139,12 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env,const CameraMatrix &p_c glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.diffuse); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.mip_maps[0].color); glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.normal_rough); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.effect); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->depth); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); - glActiveTexture(GL_TEXTURE3); - glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.mip_maps[0].color); glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->effects.mip_maps[1].sizes[0].fbo); glViewport(0,0,ssr_w,ssr_h); @@ -3145,11 +3155,22 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env,const CameraMatrix &p_c } + + glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo); + glReadBuffer(GL_COLOR_ATTACHMENT1); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->fbo); + //glDrawBuffer(GL_COLOR_ATTACHMENT0); + 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); + glReadBuffer(GL_COLOR_ATTACHMENT0); + + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + //copy reflection over diffuse, resolving SSR if needed state.resolve_shader.set_conditional(ResolveShaderGLES3::USE_SSR,env->ssr_enabled); state.resolve_shader.bind(); glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.specular); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->color); if (env->ssr_enabled) { glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.mip_maps[1].color); @@ -3169,7 +3190,12 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env,const CameraMatrix &p_c state.effect_blur_shader.bind(); state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::LOD,float(0)); - glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.alpha_fbo); + { + GLuint db = GL_COLOR_ATTACHMENT0; + glDrawBuffers(1,&db); + } + + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.fbo); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.mip_maps[0].color); @@ -3193,11 +3219,23 @@ void RasterizerSceneGLES3::_post_process(Environment *env,const CameraMatrix &p_ //turn off everything used + //copy specular to front buffer + //copy diffuse to effect buffer + + + 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); + + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + if (!env) { //no environment, simply return and convert to SRGB glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->fbo); glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.diffuse); + 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::DISABLE_ALPHA,true); storage->shaders.copy.bind(); @@ -3219,7 +3257,7 @@ void RasterizerSceneGLES3::_post_process(Environment *env,const CameraMatrix &p_ //4) Tonemap //5) Adjustments - GLuint composite_from = storage->frame.current_rt->buffers.diffuse; + GLuint composite_from = storage->frame.current_rt->effects.mip_maps[0].color; if (env->dof_blur_far_enabled) { @@ -3701,11 +3739,15 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C if (storage->frame.current_rt && true) { //pre z pass + + glDisable(GL_BLEND); glDepthMask(GL_TRUE); glEnable(GL_DEPTH_TEST); glDisable(GL_SCISSOR_TEST); - glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->fbo); + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.fbo); + glDrawBuffers(0,NULL); + glViewport(0,0,storage->frame.current_rt->width,storage->frame.current_rt->height); glColorMask(0,0,0,0); @@ -3808,10 +3850,15 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C } else { - current_fbo = storage->frame.current_rt->buffers.alpha_fbo; - glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.alpha_fbo); + + + current_fbo = storage->frame.current_rt->buffers.fbo; + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.fbo); state.scene_shader.set_conditional(SceneShaderGLES3::USE_MULTIPLE_RENDER_TARGETS,false); + Vector draw_buffers; + draw_buffers.push_back(GL_COLOR_ATTACHMENT0); + glDrawBuffers(draw_buffers.size(),draw_buffers.ptr()); } } @@ -3902,9 +3949,9 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C if (env && env->bg_mode==VS::ENV_BG_SKYBOX) { - if (use_mrt) { - glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.alpha_fbo); //switch to alpha fbo for skybox, only diffuse/ambient matters - } + //if (use_mrt) { + // glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.fbo); //switch to alpha fbo for skybox, only diffuse/ambient matters + // _draw_skybox(skybox,p_cam_projection,p_cam_transform,storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP],env->skybox_scale); } @@ -4902,6 +4949,10 @@ void RasterizerSceneGLES3::initialize() { GLOBAL_DEF("rendering/gles3/subsurface_scattering/max_size",1.0); Globals::get_singleton()->set_custom_property_info("rendering/gles3/subsurface_scattering/max_size",PropertyInfo(Variant::INT,"rendering/gles3/subsurface_scattering/max_size",PROPERTY_HINT_RANGE,"0.01,8,0.01")); GLOBAL_DEF("rendering/gles3/subsurface_scattering/follow_surface",false); + + GLOBAL_DEF("rendering/gles3/high_quality_vct_gi",true); + + } exposure_shrink_size=243; @@ -4940,6 +4991,9 @@ void RasterizerSceneGLES3::iteration() { subsurface_scatter_follow_surface=Globals::get_singleton()->get("rendering/gles3/subsurface_scattering/follow_surface"); subsurface_scatter_quality=SubSurfaceScatterQuality(int(Globals::get_singleton()->get("rendering/gles3/subsurface_scattering/quality"))); subsurface_scatter_size=Globals::get_singleton()->get("rendering/gles3/subsurface_scattering/max_size"); + + + state.scene_shader.set_conditional(SceneShaderGLES3::VCT_QUALITY_HIGH,Globals::get_singleton()->get("rendering/gles3/high_quality_vct_gi")); } void RasterizerSceneGLES3::finalize(){ diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 3fdbdb95d0..7838345e59 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -53,7 +53,6 @@ public: Vector exposure_shrink; int exposure_shrink_size; - struct State { diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 2875c1f788..c632d1c2da 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -1401,7 +1401,7 @@ void RasterizerStorageGLES3::shader_set_mode(RID p_shader,VS::ShaderMode p_mode) ShaderGLES3* shaders[VS::SHADER_MAX]={ &scene->state.scene_shader, &canvas->state.canvas_shader, - &canvas->state.canvas_shader, + &this->shaders.particles, }; @@ -1510,6 +1510,11 @@ void RasterizerStorageGLES3::_update_shader(Shader* p_shader) const { } + case VS::SHADER_PARTICLES: { + + actions=&shaders.actions_particles; + actions->uniforms=&p_shader->uniforms; + } } @@ -4998,6 +5003,7 @@ void RasterizerStorageGLES3::gi_probe_dynamic_data_update(RID p_gi_probe_data, i /////// + RID RasterizerStorageGLES3::particles_create() { Particles *particles = memnew( Particles ); @@ -5018,7 +5024,30 @@ void RasterizerStorageGLES3::particles_set_amount(RID p_particles,int p_amount) Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); + int floats = p_amount*24; + float * data = memnew_arr(float,floats); + + for(int i=0;iparticle_buffers[0]); + glBufferData(GL_ARRAY_BUFFER,floats*sizeof(float),data,GL_DYNAMIC_DRAW); + + glBindBuffer(GL_ARRAY_BUFFER,particles->particle_buffers[1]); + glBufferData(GL_ARRAY_BUFFER,floats*sizeof(float),data,GL_DYNAMIC_DRAW); + + glBindBuffer(GL_ARRAY_BUFFER,0); + + particles->prev_ticks=0; + particles->phase=0; + particles->prev_phase=0; + + memdelete_arr(data); + } + void RasterizerStorageGLES3::particles_set_lifetime(RID p_particles,float p_lifetime){ Particles *particles = particles_owner.getornull(p_particles); @@ -5125,7 +5154,7 @@ void RasterizerStorageGLES3::particles_set_draw_pass_material(RID p_particles,in Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); ERR_FAIL_INDEX(p_pass,particles->draw_passes.size()); - p_pass,particles->draw_passes[p_pass].material=p_material; + particles->draw_passes[p_pass].material=p_material; } void RasterizerStorageGLES3::particles_set_draw_pass_mesh(RID p_particles,int p_pass, RID p_mesh) { @@ -5133,7 +5162,7 @@ void RasterizerStorageGLES3::particles_set_draw_pass_mesh(RID p_particles,int p_ Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); ERR_FAIL_INDEX(p_pass,particles->draw_passes.size()); - p_pass,particles->draw_passes[p_pass].mesh=p_mesh; + particles->draw_passes[p_pass].mesh=p_mesh; } @@ -5145,6 +5174,124 @@ AABB RasterizerStorageGLES3::particles_get_current_aabb(RID p_particles) { return particles->computed_aabb; } +void RasterizerStorageGLES3::update_particles() { + + glEnable(GL_RASTERIZER_DISCARD); + glBindVertexArray(0); + + + while (particle_update_list.first()) { + + //use transform feedback to process particles + + Particles *particles = particle_update_list.first()->self(); + + + Material *material = material_owner.getornull(particles->process_material); + if (!material || !material->shader || material->shader->mode!=VS::SHADER_PARTICLES) { + + shaders.particles.set_custom_shader(0); + } else { + shaders.particles.set_custom_shader( material->shader->custom_code_id ); + + if (material->ubo_id) { + + glBindBufferBase(GL_UNIFORM_BUFFER,0,material->ubo_id); + } + + int tc = material->textures.size(); + RID* textures = material->textures.ptr(); + ShaderLanguage::ShaderNode::Uniform::Hint* texture_hints = material->shader->texture_hints.ptr(); + + + for(int i=0;itarget; + tex = t->tex_id; + + } + + glBindTexture(target,tex); + } + + } + + shaders.particles.bind(); + + shaders.particles.set_uniform(ParticlesShaderGLES3::ORIGIN,particles->origin); + + float new_phase = Math::fmod(particles->phase+(frame.delta/particles->lifetime),1.0); + + shaders.particles.set_uniform(ParticlesShaderGLES3::SYSTEM_PHASE,new_phase); + shaders.particles.set_uniform(ParticlesShaderGLES3::PREV_SYSTEM_PHASE,particles->phase); + particles->phase = new_phase; + + shaders.particles.set_uniform(ParticlesShaderGLES3::TOTAL_PARTICLES,particles->amount); + shaders.particles.set_uniform(ParticlesShaderGLES3::TIME,0.0); + shaders.particles.set_uniform(ParticlesShaderGLES3::EXPLOSIVENESS,particles->explosiveness); + shaders.particles.set_uniform(ParticlesShaderGLES3::DELTA,frame.delta); + shaders.particles.set_uniform(ParticlesShaderGLES3::GRAVITY,particles->gravity); + shaders.particles.set_uniform(ParticlesShaderGLES3::ATTRACTOR_COUNT,0); + + + + + glBindBuffer(GL_ARRAY_BUFFER,particles->particle_buffers[0]); + glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, particles->particle_buffers[1]); + + 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)); + } + + + glBeginTransformFeedback(GL_POINTS); + glDrawArrays(GL_POINTS,0,particles->amount); + glEndTransformFeedback(); + + particle_update_list.remove(particle_update_list.first()); + + SWAP(particles->particle_buffers[0],particles->particle_buffers[1]); + } + + glDisable(GL_RASTERIZER_DISCARD); + + for(int i=0;i<6;i++) { + glDisableVertexAttribArray(i); + } + +} + //////// void RasterizerStorageGLES3::instance_add_skeleton(RID p_skeleton,RasterizerScene::InstanceBase *p_instance) { @@ -5258,13 +5405,15 @@ void RasterizerStorageGLES3::_render_target_clear(RenderTarget *rt) { if (rt->buffers.fbo) { glDeleteFramebuffers(1,&rt->buffers.fbo); - glDeleteFramebuffers(1,&rt->buffers.alpha_fbo); - glDeleteTextures(1,&rt->buffers.diffuse); - glDeleteTextures(1,&rt->buffers.specular); - glDeleteTextures(1,&rt->buffers.normal_rough); - glDeleteTextures(1,&rt->buffers.motion_sss); + glDeleteRenderbuffers(1,&rt->buffers.depth); + glDeleteRenderbuffers(1,&rt->buffers.diffuse); + glDeleteRenderbuffers(1,&rt->buffers.specular); + glDeleteRenderbuffers(1,&rt->buffers.normal_rough); + glDeleteRenderbuffers(1,&rt->buffers.motion_sss); + glDeleteFramebuffers(1,&rt->buffers.effect_fbo); + glDeleteTextures(1,&rt->buffers.effect); + rt->buffers.fbo=0; - rt->buffers.alpha_fbo=0; } if (rt->depth) { @@ -5327,19 +5476,12 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){ - if (config.render_arch==RENDER_ARCH_MOBILE || rt->flags[RENDER_TARGET_NO_3D]) { + if (!rt->flags[RENDER_TARGET_HDR] || rt->flags[RENDER_TARGET_NO_3D]) { - if (rt->flags[RENDER_TARGET_TRANSPARENT]) { - color_internal_format=GL_RGBA8; - color_format=GL_RGBA; - color_type=GL_UNSIGNED_BYTE; - image_format=Image::FORMAT_RGBA8; - } else { - color_internal_format=GL_RGB10_A2; - color_format=GL_RGBA; - color_type=GL_UNSIGNED_INT_2_10_10_10_REV; - image_format=Image::FORMAT_RGBA8;//todo - } + color_internal_format=GL_RGBA8; + color_format=GL_RGBA; + color_type=GL_UNSIGNED_BYTE; + image_format=Image::FORMAT_RGBA8; } else { color_internal_format=GL_RGBA16F; color_format=GL_RGBA; @@ -5347,6 +5489,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){ image_format=Image::FORMAT_RGBAH; } + { /* FRONT FBO */ @@ -5407,69 +5550,99 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){ + static const int msaa_value[]={0,2,4,8,16}; + int msaa=msaa_value[rt->msaa]; + //regular fbo glGenFramebuffers(1, &rt->buffers.fbo); glBindFramebuffer(GL_FRAMEBUFFER, rt->buffers.fbo); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, - GL_TEXTURE_2D, rt->depth, 0); + glGenRenderbuffers(1, &rt->buffers.depth); + glBindRenderbuffer(GL_RENDERBUFFER, rt->buffers.depth); + if (msaa==0) + glRenderbufferStorage(GL_RENDERBUFFER,GL_DEPTH24_STENCIL8,rt->width,rt->height); + else + glRenderbufferStorageMultisample(GL_RENDERBUFFER,msaa,GL_DEPTH24_STENCIL8,rt->width,rt->height); - glGenTextures(1, &rt->buffers.diffuse); - glBindTexture(GL_TEXTURE_2D, rt->buffers.diffuse); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, rt->width, rt->height, 0, GL_RGBA, GL_HALF_FLOAT, 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, rt->buffers.diffuse, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_RENDERBUFFER,rt->buffers.depth); + + glGenRenderbuffers(1, &rt->buffers.diffuse); + glBindRenderbuffer(GL_RENDERBUFFER, rt->buffers.diffuse); - glGenTextures(1, &rt->buffers.specular); - glBindTexture(GL_TEXTURE_2D, rt->buffers.specular); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, rt->width, rt->height, 0, GL_RGBA, GL_HALF_FLOAT, 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_ATTACHMENT1, GL_TEXTURE_2D, rt->buffers.specular, 0); + if (msaa==0) + glRenderbufferStorage(GL_RENDERBUFFER,color_internal_format,rt->width,rt->height); + else + glRenderbufferStorageMultisample(GL_RENDERBUFFER,msaa,GL_RGBA16F,rt->width,rt->height); - glGenTextures(1, &rt->buffers.normal_rough); - glBindTexture(GL_TEXTURE_2D, rt->buffers.normal_rough); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, rt->width, rt->height, 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_ATTACHMENT2, GL_TEXTURE_2D, rt->buffers.normal_rough, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_RENDERBUFFER,rt->buffers.diffuse); + + glGenRenderbuffers(1, &rt->buffers.specular); + glBindRenderbuffer(GL_RENDERBUFFER, rt->buffers.specular); + + if (msaa==0) + glRenderbufferStorage(GL_RENDERBUFFER,GL_RGBA16F,rt->width,rt->height); + else + glRenderbufferStorageMultisample(GL_RENDERBUFFER,msaa,color_internal_format,rt->width,rt->height); + + glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT1,GL_RENDERBUFFER,rt->buffers.specular); + + glGenRenderbuffers(1, &rt->buffers.normal_rough); + glBindRenderbuffer(GL_RENDERBUFFER, rt->buffers.normal_rough); + + if (msaa==0) + glRenderbufferStorage(GL_RENDERBUFFER,GL_RGBA8,rt->width,rt->height); + else + glRenderbufferStorageMultisample(GL_RENDERBUFFER,msaa,GL_RGBA8,rt->width,rt->height); + + glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT2,GL_RENDERBUFFER,rt->buffers.normal_rough); + + + glGenRenderbuffers(1, &rt->buffers.motion_sss); + glBindRenderbuffer(GL_RENDERBUFFER, rt->buffers.motion_sss); + + if (msaa==0) + glRenderbufferStorage(GL_RENDERBUFFER,GL_RGBA8,rt->width,rt->height); + else + glRenderbufferStorageMultisample(GL_RENDERBUFFER,msaa,GL_RGBA8,rt->width,rt->height); + + glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT3,GL_RENDERBUFFER,rt->buffers.motion_sss); - glGenTextures(1, &rt->buffers.motion_sss); - glBindTexture(GL_TEXTURE_2D, rt->buffers.motion_sss); - glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, rt->width, rt->height, 0, GL_RED_INTEGER, 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); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, rt->buffers.motion_sss, 0); GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); glBindFramebuffer(GL_FRAMEBUFFER, config.system_fbo); if (status != GL_FRAMEBUFFER_COMPLETE) { + printf("err status: %x\n",status); _render_target_clear(rt); ERR_FAIL_COND( status != GL_FRAMEBUFFER_COMPLETE ); - } + } + glBindRenderbuffer(GL_RENDERBUFFER,0); - //alpha fbo - glGenFramebuffers(1, &rt->buffers.alpha_fbo); - glBindFramebuffer(GL_FRAMEBUFFER, rt->buffers.alpha_fbo); + // effect resolver - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, - GL_TEXTURE_2D, rt->depth, 0); + glGenFramebuffers(1, &rt->buffers.effect_fbo); + glBindFramebuffer(GL_FRAMEBUFFER, rt->buffers.effect_fbo); + + glGenTextures(1, &rt->buffers.effect); + glBindTexture(GL_TEXTURE_2D, rt->buffers.effect); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, rt->width, rt->height, 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, rt->buffers.effect, 0); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->buffers.diffuse, 0); - status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) { + printf("err status: %x\n",status); + _render_target_clear(rt); + ERR_FAIL_COND( status != GL_FRAMEBUFFER_COMPLETE ); + } + glBindFramebuffer(GL_FRAMEBUFFER, config.system_fbo); if (status != GL_FRAMEBUFFER_COMPLETE) { @@ -5499,7 +5672,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){ RenderTarget::Effects::MipMaps::Size mm; - glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA16F, w, h, 0, GL_RGBA, GL_HALF_FLOAT, NULL); + glTexImage2D(GL_TEXTURE_2D, level, color_internal_format, w, h, 0, color_format, color_type, NULL); mm.width=w; mm.height=h; rt->effects.mip_maps[i].sizes.push_back(mm); @@ -5711,6 +5884,20 @@ bool RasterizerStorageGLES3::render_target_renedered_in_frame(RID p_render_targe return false; } +void RasterizerStorageGLES3::render_target_set_msaa(RID p_render_target,VS::ViewportMSAA p_msaa) { + + RenderTarget *rt = render_target_owner.getornull(p_render_target); + ERR_FAIL_COND(!rt); + + if (rt->msaa==p_msaa) + return; + + _render_target_clear(rt); + rt->msaa=p_msaa; + _render_target_allocate(rt); + +} + /* CANVAS SHADOW */ @@ -6283,10 +6470,13 @@ void RasterizerStorageGLES3::initialize() { } shaders.cubemap_filter.init(); + shaders.particles.init(); glEnable(_EXT_TEXTURE_CUBE_MAP_SEAMLESS); frame.count=0; + frame.prev_tick=0; + frame.delta=0; config.keep_original_textures=false; } diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index 690a169ca2..357b69183e 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -8,6 +8,7 @@ #include "shaders/canvas.glsl.h" #include "shaders/blend_shape.glsl.h" #include "shaders/cubemap_filter.glsl.h" +#include "shaders/particles.glsl.h" #include "self_list.h" #include "shader_compiler_gles3.h" @@ -70,8 +71,11 @@ public: BlendShapeShaderGLES3 blend_shapes; + ParticlesShaderGLES3 particles; + ShaderCompilerGLES3::IdentifierActions actions_canvas; ShaderCompilerGLES3::IdentifierActions actions_scene; + ShaderCompilerGLES3::IdentifierActions actions_particles; } shaders; struct Resources { @@ -385,6 +389,12 @@ public: } spatial; + struct Particles { + + + } particles; + + bool uses_vertex_time; bool uses_fragment_time; @@ -988,7 +998,17 @@ public: AABB computed_aabb; - Particles() { + GLuint particle_buffers[2]; + + SelfList particle_element; + + float phase; + float prev_phase; + uint64_t prev_ticks; + + Transform origin; + + Particles() : particle_element(this) { emitting=false; amount=0; lifetime=1.0;; @@ -1000,13 +1020,29 @@ public: draw_order=VS::PARTICLES_DRAW_ORDER_INDEX; emission_shape=VS::PARTICLES_EMSSION_POINT; emission_sphere_radius=1.0; - float emission_sphere_radius; emission_box_extents=Vector3(1,1,1); emission_point_texture=0; + particle_buffers[0]=0; + particle_buffers[1]=0; + + prev_ticks=0; + + glGenBuffers(2,particle_buffers); } + ~Particles() { + + glDeleteBuffers(2,particle_buffers); + } + + }; + SelfList::List particle_update_list; + + void update_particles(); + + mutable RID_Owner particles_owner; virtual RID particles_create(); @@ -1054,11 +1090,15 @@ public: struct Buffers { GLuint fbo; - GLuint alpha_fbo; //single buffer, just diffuse (for alpha pass) + GLuint depth; GLuint specular; GLuint diffuse; GLuint normal_rough; GLuint motion_sss; + + GLuint effect_fbo; + GLuint effect; + } buffers; struct Effects { @@ -1110,22 +1150,24 @@ public: bool flags[RENDER_TARGET_FLAG_MAX]; bool used_in_frame; + VS::ViewportMSAA msaa; RID texture; RenderTarget() { + msaa=VS::VIEWPORT_MSAA_DISABLED; width=0; height=0; depth=0; fbo=0; buffers.fbo=0; - buffers.alpha_fbo=0; used_in_frame=false; flags[RENDER_TARGET_VFLIP]=false; flags[RENDER_TARGET_TRANSPARENT]=false; flags[RENDER_TARGET_NO_3D]=false; + flags[RENDER_TARGET_HDR]=true; flags[RENDER_TARGET_NO_SAMPLING]=false; last_exposure_tick=0; @@ -1143,6 +1185,7 @@ public: virtual void render_target_set_flag(RID p_render_target,RenderTargetFlags p_flag,bool p_value); virtual bool render_target_renedered_in_frame(RID p_render_target); + virtual void render_target_set_msaa(RID p_render_target,VS::ViewportMSAA p_msaa); /* CANVAS SHADOW */ @@ -1187,6 +1230,8 @@ public: Color clear_request_color; int canvas_draw_commands; float time[4]; + float delta; + uint64_t prev_tick; uint64_t count; } frame; diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp index 336cf7b34b..26b9aeada4 100644 --- a/drivers/gles3/shader_compiler_gles3.cpp +++ b/drivers/gles3/shader_compiler_gles3.cpp @@ -703,6 +703,24 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() { actions[VS::SHADER_SPATIAL].render_mode_defines["skip_transform"]="#define SKIP_TRANSFORM_USED\n"; + /* PARTICLES SHADER */ + + actions[VS::SHADER_PARTICLES].renames["COLOR"]="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["RESTART"]="restart"; + actions[VS::SHADER_PARTICLES].renames["CUSTOM"]="out_custom"; + actions[VS::SHADER_PARTICLES].renames["TRANSFORM"]="xform"; + actions[VS::SHADER_PARTICLES].renames["TIME"]="time"; + actions[VS::SHADER_PARTICLES].renames["LIFETIME"]="lifetime"; + actions[VS::SHADER_PARTICLES].renames["DELTA"]="delta"; + actions[VS::SHADER_PARTICLES].renames["SEED"]="seed"; + actions[VS::SHADER_PARTICLES].renames["ORIGIN"]="origin"; + actions[VS::SHADER_PARTICLES].renames["INDEX"]="index"; + + 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"; vertex_name="vertex"; @@ -710,7 +728,6 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() { time_name="TIME"; - List func_list; ShaderLanguage::get_builtin_funcs(&func_list); diff --git a/drivers/gles3/shaders/particles.glsl b/drivers/gles3/shaders/particles.glsl index fb6060957e..e72f12cc5e 100644 --- a/drivers/gles3/shaders/particles.glsl +++ b/drivers/gles3/shaders/particles.glsl @@ -2,10 +2,12 @@ -layout(location=0) in highp vec4 pos_lifetime; -layout(location=1) in highp vec4 color; -layout(location=2) in highp vec4 velocity_seed; -layout(location=3) in highp vec4 rot_active; +layout(location=0) in highp vec4 color; +layout(location=1) in highp vec4 velocity_active; +layout(location=2) in highp vec4 custom; +layout(location=3) in highp vec4 xform_1; +layout(location=4) in highp vec4 xform_2; +layout(location=5) in highp vec4 xform_3; struct Attractor { @@ -32,10 +34,24 @@ uniform int attractor_count; uniform Attractor attractors[MAX_ATTRACTORS]; -out highp vec4 out_pos_lifetime; //tfb: out highp vec4 out_color; //tfb: -out highp vec4 out_velocity_seed; //tfb: -out highp vec4 out_rot_active; //tfb: +out highp vec4 out_velocity_active; //tfb: +out highp vec4 out_custom; //tfb: +out highp vec4 out_xform_1; //tfb: +out highp vec4 out_xform_2; //tfb: +out highp vec4 out_xform_3; //tfb: + +VERTEX_SHADER_GLOBALS + +#if defined(USE_MATERIAL) + +layout(std140) uniform UniformData { //ubo:0 + +MATERIAL_UNIFORMS + +}; + +#endif void main() { @@ -47,6 +63,7 @@ void main() { float restart_phase = float(gl_InstanceID)/total_particles; restart_phase*= explosiveness; bool restart=false; + bool active = out_velocity_active.a > 0.5; if (system_phase > prev_system_phase) { restart = prev_system_phase < restart_phase && system_phase >= restart_phase; @@ -55,60 +72,96 @@ void main() { } if (restart) { - out_rot_active.a=1.0; + active=true; } - out_pos_lifetime=pos_lifetime; out_color=color; - out_velocity_seed=velocity_seed; + out_velocity_active=velocity_active; + out_custom=custom; + + mat4 xform = transpose(mat4(xform_1,xform_2,xform_3,vec4(vec3(0.0),1.0))); + + out_rot_active=rot_active; - if (out_rot_active.a) { + if (active) { //execute shader - } + { + VERTEX_SHADER_CODE + } +#if !defined(DISABLE_FORCE) - if (apply_forces) { + { - vec3 force = gravity; - for(int i=0;i0 && attractors[i].eat_radius > dist) { - rot_active.a=0.0; - } + vec3 rel_vec = out_pos_lifetime.xyz - attractors[i].pos; + float dist = rel_vec.length(); + if (attractors[i].radius < dist) + continue; + if (attractors[i].eat_radius>0 && attractors[i].eat_radius > dist) { + out_velocity_active.a=0.0; + } - rel_vec = normalize(rel_vec); + rel_vec = normalize(rel_vec); - float attenuation = pow(dist / attractors[i].radius,attractors[i].attenuation); + float attenuation = pow(dist / attractors[i].radius,attractors[i].attenuation); - if (attractors[i].dir==vec3(0.0)) { - //towards center - force+=attractors[i].strength * rel_vec * attenuation * mass; - } else { - force+=attractors[i].strength * attractors[i].dir * attenuation *mass; + if (attractors[i].dir==vec3(0.0)) { + //towards center + force+=attractors[i].strength * rel_vec * attenuation * mass; + } else { + force+=attractors[i].strength * attractors[i].dir * attenuation *mass; + } } + + out_velocity_seed.xyz += force * delta; } +#endif - out_velocity_seed.xyz += force * delta; - } +#if !defined(DISABLE_VELOCITY) - if (apply_velocity) { + { - out_pos_lifetime.xyz += out_velocity_seed.xyz * delta; + out_pos_lifetime.xyz += out_velocity_seed.xyz * delta; + } +#endif } + xform = transpose(xform); + + out_velocity_active.a = mix(0.0,1.0,active); + + out_xform_1 = xform[0]; + out_xform_2 = xform[1]; + out_xform_3 = xform[2]; + + } [fragment] +//any code here is never executed, stuff is filled just so it works -void main() { +FRAGMENT_SHADER_GLOBALS + +#if defined(USE_MATERIAL) +layout(std140) uniform UniformData { +MATERIAL_UNIFORMS + +}; + +#endif + +void main() { + + { + FRAGMENT_SHADER_CODE + } } diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index c18a356a54..c5af010c96 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -484,7 +484,7 @@ layout(location=0) out vec4 diffuse_buffer; layout(location=1) out vec4 specular_buffer; layout(location=2) out vec4 normal_mr_buffer; #if defined (ENABLE_SSS_MOTION) -layout(location=3) out uint motion_ssr_buffer; +layout(location=3) out vec4 motion_ssr_buffer; #endif #else @@ -902,7 +902,7 @@ void gi_probe_compute(sampler3D probe, mat4 probe_xform, vec3 bounds,vec3 cell_s float max_distance = length(bounds); //radiance -#ifndef VCT_QUALITY_HIGH +#ifdef VCT_QUALITY_HIGH #define MAX_CONE_DIRS 6 vec3 cone_dirs[MAX_CONE_DIRS] = vec3[] ( @@ -1407,7 +1407,7 @@ LIGHT_SHADER_CODE normal_mr_buffer=vec4(normalize(normal)*0.5+0.5,roughness); #if defined (ENABLE_SSS_MOTION) - motion_ssr_buffer = uint(clamp(sqrt(sss_strength)*255.0,0.0,255))<<24; + motion_ssr_buffer = vec4(vec3(0.0),sss_strength); #endif #else diff --git a/drivers/gles3/shaders/subsurf_scattering.glsl b/drivers/gles3/shaders/subsurf_scattering.glsl index 89e618b66c..eb329dbaed 100644 --- a/drivers/gles3/shaders/subsurf_scattering.glsl +++ b/drivers/gles3/shaders/subsurf_scattering.glsl @@ -107,14 +107,14 @@ uniform vec2 dir; in vec2 uv_interp; uniform sampler2D source_diffuse; //texunit:0 -uniform highp usampler2D source_motion_ss; //texunit:1 +uniform sampler2D source_motion_ss; //texunit:1 uniform sampler2D source_depth; //texunit:2 layout(location = 0) out vec4 frag_color; void main() { - float strength = float(texture(source_motion_ss,uv_interp).r>>24)*(1.0/255.0); + float strength = texture(source_motion_ss,uv_interp).a; strength*=strength; //stored as sqrt // Fetch color of current pixel: -- cgit v1.2.3