summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorhurikhan <m4r10.5ch14ck@gmail.com>2015-03-08 15:10:48 +0800
committerhurikhan <m4r10.5ch14ck@gmail.com>2015-03-08 15:10:48 +0800
commit87be945d49e1f53a34f7e4a27fa9b17e527b43c4 (patch)
treec1fb9e1ac10bac08c25c31bbf3a29848b90a4c49 /drivers
parentf5d2e1f42cca1c5b078073133fccda63c556a0da (diff)
parent2c2894ceb674927a35d2798b3e63adabdb020077 (diff)
Merge remote-tracking branch 'upstream/master' into x11-window-management
Diffstat (limited to 'drivers')
-rw-r--r--drivers/SCsub1
-rw-r--r--drivers/gles2/rasterizer_gles2.cpp1163
-rw-r--r--drivers/gles2/rasterizer_gles2.h72
-rw-r--r--drivers/gles2/shader_compiler_gles2.cpp7
-rw-r--r--drivers/gles2/shaders/SCsub1
-rw-r--r--drivers/gles2/shaders/canvas.glsl177
-rw-r--r--drivers/gles2/shaders/canvas_shadow.glsl62
-rw-r--r--drivers/windows/file_access_windows.cpp20
8 files changed, 1272 insertions, 231 deletions
diff --git a/drivers/SCsub b/drivers/SCsub
index 46334468ba..a1a2191cbc 100644
--- a/drivers/SCsub
+++ b/drivers/SCsub
@@ -10,7 +10,6 @@ SConscript('alsa/SCsub');
SConscript('pulseaudio/SCsub');
SConscript('windows/SCsub');
SConscript('gles2/SCsub');
-SConscript('gles1/SCsub');
SConscript('gl_context/SCsub');
SConscript('openssl/SCsub');
diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp
index d1e55f2488..e167b647e7 100644
--- a/drivers/gles2/rasterizer_gles2.cpp
+++ b/drivers/gles2/rasterizer_gles2.cpp
@@ -971,7 +971,7 @@ void RasterizerGLES2::texture_set_data(RID p_texture,const Image& p_image,VS::Cu
- if ((!texture->flags&VS::TEXTURE_FLAG_VIDEO_SURFACE) && img.detect_alpha()==Image::ALPHA_BLEND) {
+ if (!(texture->flags&VS::TEXTURE_FLAG_VIDEO_SURFACE) && img.detect_alpha()==Image::ALPHA_BLEND) {
texture->has_alpha=true;
}
@@ -2525,7 +2525,7 @@ Error RasterizerGLES2::_surface_set_arrays(Surface *p_surface, uint8_t *p_mem,ui
void RasterizerGLES2::mesh_add_custom_surface(RID p_mesh,const Variant& p_dat) {
ERR_EXPLAIN("OpenGL Rasterizer does not support custom surfaces. Running on wrong platform?");
- ERR_FAIL_V();
+ ERR_FAIL();
}
Array RasterizerGLES2::mesh_get_surface_arrays(RID p_mesh,int p_surface) const {
@@ -4116,6 +4116,10 @@ void RasterizerGLES2::begin_frame() {
shadow_filter=ShadowFilterTechnique(int(Globals::get_singleton()->get("rasterizer/shadow_filter")));
#endif
+ canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_PCF5,shadow_filter==SHADOW_FILTER_PCF5);
+ canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_PCF13,shadow_filter==SHADOW_FILTER_PCF13);
+ canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_ESM,shadow_filter==SHADOW_FILTER_ESM);
+
window_size = Size2( OS::get_singleton()->get_video_mode().width, OS::get_singleton()->get_video_mode().height );
double time = (OS::get_singleton()->get_ticks_usec()/1000); // get msec
@@ -4280,7 +4284,7 @@ void RasterizerGLES2::clear_viewport(const Color& p_color) {
}
glEnable(GL_SCISSOR_TEST);
- glClearColor(p_color.r,p_color.g,p_color.b,1.0);
+ glClearColor(p_color.r,p_color.g,p_color.b,p_color.a);
glClear(GL_COLOR_BUFFER_BIT); //should not clear if anything else cleared..
glDisable(GL_SCISSOR_TEST);
};
@@ -6398,7 +6402,12 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans
case VS::MATERIAL_BLEND_MODE_MIX: {
glBlendEquation(GL_FUNC_ADD);
- glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ 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: {
@@ -6409,12 +6418,17 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans
} break;
case VS::MATERIAL_BLEND_MODE_SUB: {
- glBlendEquation(GL_FUNC_SUBTRACT);
+ glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
glBlendFunc(GL_SRC_ALPHA,GL_ONE);
} break;
case VS::MATERIAL_BLEND_MODE_MUL: {
glBlendEquation(GL_FUNC_ADD);
- glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ 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;
@@ -6681,7 +6695,12 @@ void RasterizerGLES2::_copy_to_texscreen() {
#endif
glDisable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ 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);
+ }
//glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
glBindBuffer(GL_ARRAY_BUFFER,0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
@@ -7155,7 +7174,12 @@ void RasterizerGLES2::end_scene() {
current_depth_mask=true;
texscreen_copied=false;
glBlendEquation(GL_FUNC_ADD);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ 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);
+ }
glDisable(GL_BLEND);
current_blend_mode=VS::MATERIAL_BLEND_MODE_MIX;
@@ -7172,7 +7196,12 @@ void RasterizerGLES2::end_scene() {
}
glBlendEquation(GL_FUNC_ADD);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ 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);
+ }
glDisable(GL_BLEND);
current_blend_mode=VS::MATERIAL_BLEND_MODE_MIX;
material_shader.set_conditional(MaterialShaderGLES2::USE_GLOW,false);
@@ -7809,7 +7838,12 @@ void RasterizerGLES2::canvas_begin() {
#endif
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ 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);
+ }
//glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
glLineWidth(1.0);
glBindBuffer(GL_ARRAY_BUFFER,0);
@@ -7824,8 +7858,10 @@ void RasterizerGLES2::canvas_begin() {
//material_shader.unbind();
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;
_set_color_attrib(Color(1,1,1));
canvas_transform=Transform();
canvas_transform.translate(-(viewport.width / 2.0f), -(viewport.height / 2.0f), 0.0f);
@@ -7840,10 +7876,10 @@ void RasterizerGLES2::canvas_begin() {
canvas_opacity=1.0;
canvas_blend_mode=VS::MATERIAL_BLEND_MODE_MIX;
-
canvas_texscreen_used=false;
uses_texpixel_size=false;
- canvas_last_shader=RID();
+
+ canvas_last_material=NULL;
}
@@ -7865,7 +7901,12 @@ void RasterizerGLES2::canvas_set_blend_mode(VS::MaterialBlendMode p_mode) {
case VS::MATERIAL_BLEND_MODE_MIX: {
glBlendEquation(GL_FUNC_ADD);
- glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ 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: {
@@ -7876,7 +7917,7 @@ void RasterizerGLES2::canvas_set_blend_mode(VS::MaterialBlendMode p_mode) {
} break;
case VS::MATERIAL_BLEND_MODE_SUB: {
- glBlendEquation(GL_FUNC_SUBTRACT);
+ glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
glBlendFunc(GL_SRC_ALPHA,GL_ONE);
} break;
case VS::MATERIAL_BLEND_MODE_MUL: {
@@ -8103,7 +8144,7 @@ void RasterizerGLES2::_draw_gui_primitive2(int p_points, const Vector2 *p_vertic
_rinfo.ci_draw_commands++;
}
-void RasterizerGLES2::_draw_textured_quad(const Rect2& p_rect, const Rect2& p_src_region, const Size2& p_tex_size,bool p_h_flip, bool p_v_flip ) {
+void RasterizerGLES2::_draw_textured_quad(const Rect2& p_rect, const Rect2& p_src_region, const Size2& p_tex_size,bool p_h_flip, bool p_v_flip, bool p_transpose ) {
Vector2 texcoords[4]= {
Vector2( p_src_region.pos.x/p_tex_size.width,
@@ -8119,6 +8160,9 @@ void RasterizerGLES2::_draw_textured_quad(const Rect2& p_rect, const Rect2& p_sr
(p_src_region.pos.y+p_src_region.size.height)/p_tex_size.height)
};
+ if (p_transpose) {
+ SWAP( texcoords[1], texcoords[3] );
+ }
if (p_h_flip) {
SWAP( texcoords[0], texcoords[1] );
SWAP( texcoords[2], texcoords[3] );
@@ -8166,11 +8210,11 @@ void RasterizerGLES2::canvas_draw_rect(const Rect2& p_rect, int p_flags, const R
if (!(p_flags&CANVAS_RECT_REGION)) {
Rect2 region = Rect2(0,0,texture->width,texture->height);
- _draw_textured_quad(p_rect,region,region.size,p_flags&CANVAS_RECT_FLIP_H,p_flags&CANVAS_RECT_FLIP_V);
+ _draw_textured_quad(p_rect,region,region.size,p_flags&CANVAS_RECT_FLIP_H,p_flags&CANVAS_RECT_FLIP_V,p_flags&CANVAS_RECT_TRANSPOSE);
} else {
- _draw_textured_quad(p_rect, p_source, Size2(texture->width,texture->height),p_flags&CANVAS_RECT_FLIP_H,p_flags&CANVAS_RECT_FLIP_V );
+ _draw_textured_quad(p_rect, p_source, Size2(texture->width,texture->height),p_flags&CANVAS_RECT_FLIP_H,p_flags&CANVAS_RECT_FLIP_V,p_flags&CANVAS_RECT_TRANSPOSE);
}
} else {
@@ -8325,13 +8369,739 @@ void RasterizerGLES2::canvas_set_transform(const Matrix32& p_transform) {
//canvas_transform = Variant(p_transform);
}
+RID RasterizerGLES2::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 RasterizerGLES2::canvas_light_occluder_set_polylines(RID p_occluder, const DVector<Vector2>& 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<float> geometry;
+ DVector<uint16_t> indices;
+ int lc = p_lines.size();
+
+ geometry.resize(lc*6);
+ indices.resize(lc*3);
+
+ DVector<float>::Write vw=geometry.write();
+ DVector<uint16_t>::Write iw=indices.write();
+
+
+ DVector<Vector2>::Read lr=p_lines.read();
+
+ const int POLY_HEIGHT = 16384;
+
+ for(int i=0;i<lc/2;i++) {
+
+ vw[i*12+0]=lr[i*2+0].x;
+ vw[i*12+1]=lr[i*2+0].y;
+ vw[i*12+2]=POLY_HEIGHT;
+
+ vw[i*12+3]=lr[i*2+1].x;
+ vw[i*12+4]=lr[i*2+1].y;
+ vw[i*12+5]=POLY_HEIGHT;
+
+ vw[i*12+6]=lr[i*2+1].x;
+ vw[i*12+7]=lr[i*2+1].y;
+ vw[i*12+8]=-POLY_HEIGHT;
+
+ vw[i*12+9]=lr[i*2+0].x;
+ vw[i*12+10]=lr[i*2+0].y;
+ vw[i*12+11]=-POLY_HEIGHT;
+
+ iw[i*6+0]=i*4+0;
+ iw[i*6+1]=i*4+1;
+ iw[i*6+2]=i*4+2;
+
+ iw[i*6+3]=i*4+2;
+ iw[i*6+4]=i*4+3;
+ iw[i*6+5]=i*4+0;
+
+ }
+
+ //if same buffer len is being set, just use BufferSubData to avoid a pipeline flush
+
+
+ if (!co->vertex_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;
+
+ }
+
+
+
+}
+
+RID RasterizerGLES2::canvas_light_shadow_buffer_create(int p_width) {
+
+ CanvasLightShadow *cls = memnew( CanvasLightShadow );
+ if (p_width>max_texture_size)
+ p_width=max_texture_size;
+
+ cls->size=p_width;
+ glActiveTexture(GL_TEXTURE0);
+
+ glGenFramebuffers(1, &cls->fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, cls->fbo);
+
+ // Create a render buffer
+ glGenRenderbuffers(1, &cls->rbo);
+ glBindRenderbuffer(GL_RENDERBUFFER, cls->rbo);
+
+ // Create a texture for storing the depth
+ glGenTextures(1, &cls->depth);
+ glBindTexture(GL_TEXTURE_2D, cls->depth);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ // 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);
+
+ cls->height=16;
+
+ //print_line("ERROR? "+itos(glGetError()));
+ if ( read_depth_supported ) {
+
+ // We'll use a depth texture to store the depths in the shadow map
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, cls->size, cls->height, 0,
+ GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
+
+#ifdef GLEW_ENABLED
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+#endif
+
+ // Attach the depth texture to FBO depth attachment point
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+ GL_TEXTURE_2D, cls->depth, 0);
+
+#ifdef GLEW_ENABLED
+ glDrawBuffer(GL_NONE);
+#endif
+ } else {
+ // We'll use a RGBA texture into which we pack the depth info
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, cls->size, cls->height, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+
+ // Attach the RGBA texture to FBO color attachment point
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D, cls->depth, 0);
+
+ // Allocate 16-bit depth buffer
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, cls->size, cls->height);
+
+ // Attach the render buffer as depth buffer - will be ignored
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+ GL_RENDERBUFFER, cls->rbo);
+
+
+ }
+
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ //printf("errnum: %x\n",status);
+#ifdef GLEW_ENABLED
+ if (read_depth_supported) {
+ glDrawBuffer(GL_BACK);
+ }
+#endif
+ glBindFramebuffer(GL_FRAMEBUFFER, base_framebuffer);
+ DEBUG_TEST_ERROR("2D Shadow Buffer Init");
+ ERR_FAIL_COND_V( status != GL_FRAMEBUFFER_COMPLETE, RID() );
+
+#ifdef GLEW_ENABLED
+ if (read_depth_supported) {
+ glDrawBuffer(GL_BACK);
+ }
+#endif
+
+ return canvas_light_shadow_owner.make_rid(cls);
+}
+
+void RasterizerGLES2::canvas_light_shadow_buffer_update(RID p_buffer, const Matrix32& p_light_xform, int p_light_mask,float p_near, float p_far, CanvasLightOccluderInstance* p_occluders, CameraMatrix *p_xform_cache) {
+
+ CanvasLightShadow *cls = 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);
+
+ if (!use_rgba_shadowmaps)
+ glColorMask(0, 0, 0, 0);
+
+ glEnableVertexAttribArray(VS::ARRAY_VERTEX);
+ canvas_shadow_shader.bind();
+
+ const int vp_height = 10;
+
+ 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());
+
+ //print_line("near: "+rtos(p_near));
+ //print_line("far: "+rtos(p_far));
+ //projection.set_perspective(60,size/float(vp_height),p_near,p_far);
+
+ // CameraMatrix light_mat = projection * CameraMatrix(camera);
+
+ canvas_shadow_shader.set_uniform(CanvasShadowShaderGLES2::PROJECTION_MATRIX,projection);
+ canvas_shadow_shader.set_uniform(CanvasShadowShaderGLES2::LIGHT_MATRIX,light);
+
+ if (i==0)
+ *p_xform_cache=projection;
+
+ glViewport(0, (cls->height/4)*i, cls->size,cls->height/4);
+
+ CanvasLightOccluderInstance *instance=p_occluders;
+
+ while(instance) {
+
+ CanvasOccluder *cc = canvas_occluder_owner.get(instance->polygon_buffer);
+ if (!cc || cc->len==0 || !(p_light_mask&instance->light_mask)) {
+
+ instance=instance->next;
+ continue;
+ }
+
+ canvas_shadow_shader.set_uniform(CanvasShadowShaderGLES2::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;i<cc->lines.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);
+
+ if (shadow_filter==SHADOW_FILTER_ESM) {
+ //blur the buffer
+#if 0
+ //this is ignord, it did not make any difference..
+ if (read_depth_supported) {
+ glDepthFunc(GL_ALWAYS);
+ } else {
+ glDisable(GL_DEPTH_TEST);
+ glDepthMask(false);
+ }
+ glDisable(GL_CULL_FACE);
+ glViewport(0, 0, cls->size,cls->height);
+
+ int passes=1;
+ CanvasLightShadow *blur = canvas_light_shadow_owner.get(canvas_shadow_blur);
+
+ copy_shader.set_conditional(CopyShaderGLES2::SHADOW_BLUR_H_PASS,true);
+ copy_shader.bind();
+ copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SCALE,1);
+ copy_shader.set_uniform(CopyShaderGLES2::BLUR_MAGNITUDE,1);
+ glUniform1i(copy_shader.get_uniform_location(CopyShaderGLES2::SOURCE),0);
+
+ for(int i=0;i<passes;i++) {
+
+ glBindFramebuffer(GL_FRAMEBUFFER, blur->fbo);
+ glActiveTexture(GL_TEXTURE0);
+
+ if (read_depth_supported)
+ glBindTexture(GL_TEXTURE_2D,cls->depth);
+ else
+ glBindTexture(GL_TEXTURE_2D,cls->rgba);
+
+
+ {
+ Vector2 src_sb_uv[4]={
+ Vector2( 0, 1),
+ Vector2( 1, 1),
+ Vector2( 1, 0),
+ Vector2( 0, 0)
+ };
+ static const Vector2 dst_pos[4]={
+ Vector2(-1, 1),
+ Vector2( 1, 1),
+ Vector2( 1,-1),
+ Vector2(-1,-1)
+ };
+
+
+
+ copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SIZE,Vector2(1.0,1.0)/cls->size);
+ _draw_gui_primitive(4,dst_pos,NULL,src_sb_uv);
+ }
+
+ glActiveTexture(GL_TEXTURE0);
+ if (read_depth_supported)
+ glBindTexture(GL_TEXTURE_2D,blur->depth);
+ else
+ glBindTexture(GL_TEXTURE_2D,blur->rgba);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, cls->fbo);
+
+ {
+ float hlimit = float(cls->size) / blur->size;
+ //hlimit*=2.0;
+ Vector2 src_sb_uv[4]={
+ Vector2( 0, 1),
+ Vector2( hlimit, 1),
+ Vector2( hlimit, 0),
+ Vector2( 0, 0)
+ };
+ static const Vector2 dst_pos[4]={
+ Vector2(-1, 1),
+ Vector2( 1, 1),
+ Vector2( 1,-1),
+ Vector2(-1,-1)
+ };
+
+
+ copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SIZE,Vector2(1.0,1.0)/blur->size);
+ _draw_gui_primitive(4,dst_pos,NULL,src_sb_uv);
+ }
+
+ }
+ copy_shader.set_conditional(CopyShaderGLES2::SHADOW_BLUR_H_PASS,false);
+ glDepthFunc(GL_LEQUAL);
+#endif
+ }
+
+ glBindFramebuffer(GL_FRAMEBUFFER, current_rt?current_rt->fbo:base_framebuffer);
+ glColorMask(1, 1, 1, 1);
-void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list) {
+
+
+}
+
+
+void RasterizerGLES2::canvas_debug_viewport_shadows(CanvasLight* p_lights_with_shadow) {
+
+ CanvasLight* light=p_lights_with_shadow;
+
+ canvas_begin(); //reset
+
+ int h = 10;
+ int w = viewport.width;
+ int ofs = h;
+ while(light) {
+
+ if (light->shadow_buffer.is_valid()) {
+
+ CanvasLightShadow * sb = canvas_light_shadow_owner.get(light->shadow_buffer);
+ if (sb) {
+ glActiveTexture(GL_TEXTURE0);
+ if (read_depth_supported)
+ glBindTexture(GL_TEXTURE_2D,sb->depth);
+ else
+ glBindTexture(GL_TEXTURE_2D,sb->rgba);
+ _draw_textured_quad(Rect2(h,ofs,w-h*2,h),Rect2(0,0,sb->size,10),Size2(sb->size,10),false,false);
+ ofs+=h*2;
+
+ }
+ }
+
+ light=light->shadows_next_ptr;
+ }
+
+}
+
+void RasterizerGLES2::_canvas_normal_set_flip(const Vector2& p_flip) {
+
+ if (p_flip==normal_flip)
+ return;
+ normal_flip=p_flip;
+ canvas_shader.set_uniform(CanvasShaderGLES2::NORMAL_FLIP,normal_flip);
+}
+
+
+template<bool use_normalmap>
+void RasterizerGLES2::_canvas_item_render_commands(CanvasItem *p_item,CanvasItem *current_clip,bool &reclip) {
+
+ int cc=p_item->commands.size();
+ CanvasItem::Command **commands = p_item->commands.ptr();
+
+
+ for(int i=0;i<cc;i++) {
+
+ CanvasItem::Command *c=commands[i];
+
+ switch(c->type) {
+ case CanvasItem::Command::TYPE_LINE: {
+
+ CanvasItem::CommandLine* line = static_cast<CanvasItem::CommandLine*>(c);
+ canvas_draw_line(line->from,line->to,line->color,line->width);
+ } break;
+ case CanvasItem::Command::TYPE_RECT: {
+
+ CanvasItem::CommandRect* rect = static_cast<CanvasItem::CommandRect*>(c);
+// canvas_draw_rect(rect->rect,rect->region,rect->source,rect->flags&CanvasItem::CommandRect::FLAG_TILE,rect->flags&CanvasItem::CommandRect::FLAG_FLIP_H,rect->flags&CanvasItem::CommandRect::FLAG_FLIP_V,rect->texture,rect->modulate);
+#if 0
+ int flags=0;
+
+ if (rect->flags&CanvasItem::CommandRect::FLAG_REGION) {
+ flags|=Rasterizer::CANVAS_RECT_REGION;
+ }
+ if (rect->flags&CanvasItem::CommandRect::FLAG_TILE) {
+ flags|=Rasterizer::CANVAS_RECT_TILE;
+ }
+ if (rect->flags&CanvasItem::CommandRect::FLAG_FLIP_H) {
+
+ flags|=Rasterizer::CANVAS_RECT_FLIP_H;
+ }
+ if (rect->flags&CanvasItem::CommandRect::FLAG_FLIP_V) {
+
+ flags|=Rasterizer::CANVAS_RECT_FLIP_V;
+ }
+#else
+
+ int flags=rect->flags;
+#endif
+ if (use_normalmap)
+ _canvas_normal_set_flip(Vector2((flags&CANVAS_RECT_FLIP_H)?-1:1,(flags&CANVAS_RECT_FLIP_V)?-1:1));
+ canvas_draw_rect(rect->rect,flags,rect->source,rect->texture,rect->modulate);
+
+ } break;
+ case CanvasItem::Command::TYPE_STYLE: {
+
+ CanvasItem::CommandStyle* style = static_cast<CanvasItem::CommandStyle*>(c);
+ if (use_normalmap)
+ _canvas_normal_set_flip(Vector2(1,1));
+ canvas_draw_style_box(style->rect,style->texture,style->margin,style->draw_center,style->color);
+
+ } break;
+ case CanvasItem::Command::TYPE_PRIMITIVE: {
+
+ if (use_normalmap)
+ _canvas_normal_set_flip(Vector2(1,1));
+ CanvasItem::CommandPrimitive* primitive = static_cast<CanvasItem::CommandPrimitive*>(c);
+ canvas_draw_primitive(primitive->points,primitive->colors,primitive->uvs,primitive->texture,primitive->width);
+ } break;
+ case CanvasItem::Command::TYPE_POLYGON: {
+
+ if (use_normalmap)
+ _canvas_normal_set_flip(Vector2(1,1));
+ CanvasItem::CommandPolygon* polygon = static_cast<CanvasItem::CommandPolygon*>(c);
+ canvas_draw_polygon(polygon->count,polygon->indices.ptr(),polygon->points.ptr(),polygon->uvs.ptr(),polygon->colors.ptr(),polygon->texture,polygon->colors.size()==1);
+
+ } break;
+
+ case CanvasItem::Command::TYPE_POLYGON_PTR: {
+
+ if (use_normalmap)
+ _canvas_normal_set_flip(Vector2(1,1));
+ CanvasItem::CommandPolygonPtr* polygon = static_cast<CanvasItem::CommandPolygonPtr*>(c);
+ canvas_draw_polygon(polygon->count,polygon->indices,polygon->points,polygon->uvs,polygon->colors,polygon->texture,false);
+ } break;
+ case CanvasItem::Command::TYPE_CIRCLE: {
+
+ CanvasItem::CommandCircle* circle = static_cast<CanvasItem::CommandCircle*>(c);
+ static const int numpoints=32;
+ Vector2 points[numpoints+1];
+ points[numpoints]=circle->pos;
+ int indices[numpoints*3];
+
+ for(int i=0;i<numpoints;i++) {
+
+ points[i]=circle->pos+Vector2( Math::sin(i*Math_PI*2.0/numpoints),Math::cos(i*Math_PI*2.0/numpoints) )*circle->radius;
+ indices[i*3+0]=i;
+ indices[i*3+1]=(i+1)%numpoints;
+ indices[i*3+2]=numpoints;
+ }
+ canvas_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 CanvasItem::Command::TYPE_TRANSFORM: {
+
+ CanvasItem::CommandTransform* transform = static_cast<CanvasItem::CommandTransform*>(c);
+ canvas_set_transform(transform->xform);
+ } break;
+ case CanvasItem::Command::TYPE_BLEND_MODE: {
+
+ CanvasItem::CommandBlendMode* bm = static_cast<CanvasItem::CommandBlendMode*>(c);
+ canvas_set_blend_mode(bm->blend_mode);
+
+ } break;
+ case CanvasItem::Command::TYPE_CLIP_IGNORE: {
+
+ CanvasItem::CommandClipIgnore* ci = static_cast<CanvasItem::CommandClipIgnore*>(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);
+ reclip=false;
+ }
+ }
+ }
+
+
+
+ } break;
+ }
+ }
+
+}
+
+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
+ glReadBuffer(GL_COLOR_ATTACHMENT0);
+#endif
+ 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;
+
+}
+
+void RasterizerGLES2::_canvas_item_setup_shader_uniforms(CanvasItemMaterial *material,Shader* shader) {
+
+ //this can be optimized..
+ int tex_id=1;
+ int idx=0;
+ for(Map<StringName,ShaderLanguage::Uniform>::Element *E=shader->uniforms.front();E;E=E->next()) {
+
+ Map<StringName,Variant>::Element *F=material->shader_param.find(E->key());
+
+ if ((E->get().type==ShaderLanguage::TYPE_TEXTURE || E->get().type==ShaderLanguage::TYPE_CUBEMAP)) {
+
+ RID rid;
+ if (F) {
+ rid=F->get();
+ }
+
+ if (!rid.is_valid()) {
+
+ Map<StringName,RID>::Element *DT=shader->default_textures.find(E->key());
+ if (DT) {
+ rid=DT->get();
+ }
+ }
+
+ if (rid.is_valid()) {
+
+ int loc = canvas_shader.get_custom_uniform_location(idx); //should be automatic..
+
+ glActiveTexture(GL_TEXTURE0+tex_id);
+ Texture *t=texture_owner.get(rid);
+ if (!t)
+ glBindTexture(GL_TEXTURE_2D,white_tex);
+ else
+ glBindTexture(t->target,t->tex_id);
+
+ glUniform1i(loc,tex_id);
+ tex_id++;
+ }
+ } else {
+ Variant &v=F?F->get():E->get().default_value;
+ canvas_shader.set_custom_uniform(idx,v);
+ }
+
+ idx++;
+ }
+
+ if (tex_id>1) {
+ glActiveTexture(GL_TEXTURE0);
+ }
+
+ if (shader->uses_time) {
+ canvas_shader.set_uniform(CanvasShaderGLES2::TIME,Math::fmod(last_time,300.0));
+ draw_next_frame=true;
+ }
+ //if uses TIME - draw_next_frame=true
+
+
+}
+
+void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const Color& p_modulate,CanvasLight *p_light) {
CanvasItem *current_clip=NULL;
Shader *shader_cache=NULL;
+
+ bool rebind_shader=true;
+
canvas_opacity=1.0;
+ canvas_use_modulate=p_modulate!=Color(1,1,1,1);
+ canvas_modulate=p_modulate;
+ canvas_shader.set_conditional(CanvasShaderGLES2::USE_MODULATE,canvas_use_modulate);
+
+ bool reset_modulate=false;
+
while(p_item_list) {
CanvasItem *ci=p_item_list;
@@ -8341,8 +9111,15 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list) {
draw_viewport_func(ci->vp_render->owner,ci->vp_render->udata,ci->vp_render->rect);
}
memdelete(ci->vp_render);
- ci->vp_render=NULL;
- canvas_last_shader=RID();
+ ci->vp_render=NULL;
+ canvas_last_material=NULL;
+ canvas_use_modulate=p_modulate!=Color(1,1,1,1);
+ canvas_modulate=p_modulate;
+ canvas_shader.set_conditional(CanvasShaderGLES2::USE_MODULATE,canvas_use_modulate);
+ rebind_shader=true;
+ reset_modulate=true;
+
+
}
if (current_clip!=ci->final_clip_owner) {
@@ -8363,13 +9140,14 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list) {
//begin rect
- CanvasItem *shader_owner = ci->shader_owner?ci->shader_owner:ci;
+ CanvasItem *material_owner = ci->material_owner?ci->material_owner:ci;
+ CanvasItemMaterial *material = material_owner->material;
- if (shader_owner->shader!=canvas_last_shader) {
+ if (material!=canvas_last_material || rebind_shader) {
Shader *shader = NULL;
- if (shader_owner->shader.is_valid()) {
- shader = this->shader_owner.get(shader_owner->shader);
+ if (material && material->shader.is_valid()) {
+ shader = shader_owner.get(material->shader);
if (shader && !shader->valid) {
shader=NULL;
}
@@ -8379,52 +9157,7 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list) {
if (shader) {
canvas_shader.set_custom_shader(shader->custom_code_id);
- if (canvas_shader.bind())
- rebind_texpixel_size=true;
-
- if (shader_owner->shader_version!=shader->version) {
- //todo optimize uniforms
- shader_owner->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
- glReadBuffer(GL_COLOR_ATTACHMENT0);
-#endif
- 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));
- }
-
- if (shader->uses_time) {
- canvas_shader.set_uniform(CanvasShaderGLES2::TIME,Math::fmod(last_time,300.0));
- draw_next_frame=true;
- }
- //if uses TIME - draw_next_frame=true
-
- uses_texpixel_size=shader->uses_texpixel_size;
-
+ _canvas_item_setup_shader_params(material,shader);
} else {
shader_cache=NULL;
canvas_shader.set_custom_shader(0);
@@ -8435,61 +9168,26 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list) {
canvas_shader.set_uniform(CanvasShaderGLES2::PROJECTION_MATRIX,canvas_transform);
- canvas_last_shader=shader_owner->shader;
+ if (canvas_use_modulate)
+ reset_modulate=true;
+ canvas_last_material=material;
+ rebind_shader=false;
}
- if (shader_cache) {
-
- Shader *shader = shader_cache;
- //this can be optimized..
- int tex_id=1;
- int idx=0;
- for(Map<StringName,ShaderLanguage::Uniform>::Element *E=shader->uniforms.front();E;E=E->next()) {
-
- Map<StringName,Variant>::Element *F=shader_owner->shader_param.find(E->key());
-
- if ((E->get().type==ShaderLanguage::TYPE_TEXTURE || E->get().type==ShaderLanguage::TYPE_CUBEMAP)) {
-
- RID rid;
- if (F) {
- rid=F->get();
- }
-
- if (!rid.is_valid()) {
-
- Map<StringName,RID>::Element *DT=shader->default_textures.find(E->key());
- if (DT) {
- rid=DT->get();
- }
- }
-
- if (rid.is_valid()) {
-
- int loc = canvas_shader.get_custom_uniform_location(idx); //should be automatic..
+ if (material && shader_cache) {
- glActiveTexture(GL_TEXTURE0+tex_id);
- Texture *t=texture_owner.get(rid);
- if (!t)
- glBindTexture(GL_TEXTURE_2D,white_tex);
- else
- glBindTexture(t->target,t->tex_id);
-
- glUniform1i(loc,tex_id);
- tex_id++;
- }
- } else {
- Variant &v=F?F->get():E->get().default_value;
- canvas_shader.set_custom_uniform(idx,v);
- }
+ _canvas_item_setup_shader_uniforms(material,shader_cache);
+ }
- idx++;
- }
+ if (material && material->unshaded) {
+ canvas_shader.set_uniform(CanvasShaderGLES2::MODULATE,Color(1,1,1,1));
+ reset_modulate=true;
+ } else if (reset_modulate) {
+ canvas_shader.set_uniform(CanvasShaderGLES2::MODULATE,canvas_modulate);
+ reset_modulate=false;
+ }
- if (tex_id>1) {
- glActiveTexture(GL_TEXTURE0);
- }
- }
canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX,ci->final_transform);
canvas_shader.set_uniform(CanvasShaderGLES2::EXTRA_MATRIX,Matrix32());
@@ -8503,7 +9201,12 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list) {
case VS::MATERIAL_BLEND_MODE_MIX: {
glBlendEquation(GL_FUNC_ADD);
- glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ 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: {
@@ -8514,7 +9217,7 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list) {
} break;
case VS::MATERIAL_BLEND_MODE_SUB: {
- glBlendEquation(GL_FUNC_SUBTRACT);
+ glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
glBlendFunc(GL_SRC_ALPHA,GL_ONE);
} break;
case VS::MATERIAL_BLEND_MODE_MUL: {
@@ -8531,128 +9234,140 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list) {
canvas_blend_mode=ci->blend_mode;
}
- int cc=ci->commands.size();
- CanvasItem::Command **commands = ci->commands.ptr();
-
canvas_opacity = ci->final_opacity;
- for(int i=0;i<cc;i++) {
+ _canvas_item_render_commands<false>(ci,current_clip,reclip);
- CanvasItem::Command *c=commands[i];
+ if (canvas_blend_mode==VS::MATERIAL_BLEND_MODE_MIX && p_light && (!material || !material->unshaded)) {
- switch(c->type) {
- case CanvasItem::Command::TYPE_LINE: {
+ CanvasLight *light = p_light;
+ bool light_used=false;
+ bool subtract=false;
- CanvasItem::CommandLine* line = static_cast<CanvasItem::CommandLine*>(c);
- canvas_draw_line(line->from,line->to,line->color,line->width);
- } break;
- case CanvasItem::Command::TYPE_RECT: {
- CanvasItem::CommandRect* rect = static_cast<CanvasItem::CommandRect*>(c);
-// canvas_draw_rect(rect->rect,rect->region,rect->source,rect->flags&CanvasItem::CommandRect::FLAG_TILE,rect->flags&CanvasItem::CommandRect::FLAG_FLIP_H,rect->flags&CanvasItem::CommandRect::FLAG_FLIP_V,rect->texture,rect->modulate);
-#if 0
- int flags=0;
+ while(light) {
- if (rect->flags&CanvasItem::CommandRect::FLAG_REGION) {
- flags|=Rasterizer::CANVAS_RECT_REGION;
- }
- if (rect->flags&CanvasItem::CommandRect::FLAG_TILE) {
- flags|=Rasterizer::CANVAS_RECT_TILE;
- }
- if (rect->flags&CanvasItem::CommandRect::FLAG_FLIP_H) {
+ 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 || subtract!=light->subtract) {
+
+ subtract=light->subtract;
+
+ if (subtract) {
+
+ glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE);
+
+ } else {
+
+ glBlendEquation(GL_FUNC_ADD);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE);
- flags|=Rasterizer::CANVAS_RECT_FLIP_H;
+ }
}
- if (rect->flags&CanvasItem::CommandRect::FLAG_FLIP_V) {
- flags|=Rasterizer::CANVAS_RECT_FLIP_V;
+ if (!light_used) {
+
+ canvas_shader.set_conditional(CanvasShaderGLES2::USE_LIGHTING,true);
+ canvas_shader.set_conditional(CanvasShaderGLES2::USE_MODULATE,false);
+ light_used=true;
+ normal_flip=Vector2(1,1);
+
}
-#else
+ canvas_shader.set_conditional(CanvasShaderGLES2::USE_SHADOWS,light->shadow_buffer.is_valid());
- int flags=rect->flags;
-#endif
- canvas_draw_rect(rect->rect,flags,rect->source,rect->texture,rect->modulate);
+ bool light_rebind = canvas_shader.bind();
- } break;
- case CanvasItem::Command::TYPE_STYLE: {
+ if (light_rebind) {
- CanvasItem::CommandStyle* style = static_cast<CanvasItem::CommandStyle*>(c);
- canvas_draw_style_box(style->rect,style->texture,style->margin,style->draw_center,style->color);
+ if (material && shader_cache) {
+ _canvas_item_setup_shader_params(material,shader_cache);
+ _canvas_item_setup_shader_uniforms(material,shader_cache);
+ }
- } break;
- case CanvasItem::Command::TYPE_PRIMITIVE: {
+ canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX,ci->final_transform);
+ canvas_shader.set_uniform(CanvasShaderGLES2::EXTRA_MATRIX,Matrix32());
+ canvas_shader.set_uniform(CanvasShaderGLES2::PROJECTION_MATRIX,canvas_transform);
+ if (canvas_use_modulate)
+ canvas_shader.set_uniform(CanvasShaderGLES2::MODULATE,canvas_modulate);
+ canvas_shader.set_uniform(CanvasShaderGLES2::NORMAL_FLIP,Vector2(1,1));
+ canvas_shader.set_uniform(CanvasShaderGLES2::SHADOWPIXEL_SIZE,1.0/light->shadow_buffer_size);
- CanvasItem::CommandPrimitive* primitive = static_cast<CanvasItem::CommandPrimitive*>(c);
- canvas_draw_primitive(primitive->points,primitive->colors,primitive->uvs,primitive->texture,primitive->width);
- } break;
- case CanvasItem::Command::TYPE_POLYGON: {
- CanvasItem::CommandPolygon* polygon = static_cast<CanvasItem::CommandPolygon*>(c);
- canvas_draw_polygon(polygon->count,polygon->indices.ptr(),polygon->points.ptr(),polygon->uvs.ptr(),polygon->colors.ptr(),polygon->texture,polygon->colors.size()==1);
+ }
- } break;
+ canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_MATRIX,light->light_shader_xform);
+ canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_POS,light->light_shader_pos);
+ canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_COLOR,light->color);
+ canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_HEIGHT,light->height);
+ if (light->shadow_buffer.is_valid()) {
- case CanvasItem::Command::TYPE_POLYGON_PTR: {
+ CanvasLightShadow *cls = canvas_light_shadow_owner.get(light->shadow_buffer);
+ glActiveTexture(GL_TEXTURE0+max_texture_units-3);
+ if (read_depth_supported)
+ glBindTexture(GL_TEXTURE_2D,cls->depth);
+ else
+ glBindTexture(GL_TEXTURE_2D,cls->rgba);
- CanvasItem::CommandPolygonPtr* polygon = static_cast<CanvasItem::CommandPolygonPtr*>(c);
- canvas_draw_polygon(polygon->count,polygon->indices,polygon->points,polygon->uvs,polygon->colors,polygon->texture,false);
- } break;
- case CanvasItem::Command::TYPE_CIRCLE: {
+ canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_TEXTURE,max_texture_units-3);
+ canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_MATRIX,light->shadow_matrix_cache);
+ canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_LOCAL_MATRIX,light->xform_cache.affine_inverse());
+ canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_ESM_MULTIPLIER,light->shadow_esm_mult);
- CanvasItem::CommandCircle* circle = static_cast<CanvasItem::CommandCircle*>(c);
- static const int numpoints=32;
- Vector2 points[numpoints+1];
- points[numpoints]=circle->pos;
- int indices[numpoints*3];
+ }
- for(int i=0;i<numpoints;i++) {
- points[i]=circle->pos+Vector2( Math::sin(i*Math_PI*2.0/numpoints),Math::cos(i*Math_PI*2.0/numpoints) )*circle->radius;
- indices[i*3+0]=i;
- indices[i*3+1]=(i+1)%numpoints;
- indices[i*3+2]=numpoints;
+ glActiveTexture(GL_TEXTURE0+max_texture_units-2);
+ canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_TEXTURE,max_texture_units-2);
+ Texture *t = texture_owner.get(light->texture);
+ if (!t) {
+ glBindTexture(GL_TEXTURE_2D,white_tex);
+ } else {
+
+ glBindTexture(t->target,t->tex_id);
}
- canvas_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 CanvasItem::Command::TYPE_TRANSFORM: {
- CanvasItem::CommandTransform* transform = static_cast<CanvasItem::CommandTransform*>(c);
- canvas_set_transform(transform->xform);
- } break;
- case CanvasItem::Command::TYPE_BLEND_MODE: {
+ glActiveTexture(GL_TEXTURE0);
+ _canvas_item_render_commands<true>(ci,current_clip,reclip); //redraw using light
- CanvasItem::CommandBlendMode* bm = static_cast<CanvasItem::CommandBlendMode*>(c);
- canvas_set_blend_mode(bm->blend_mode);
+ }
- } break;
- case CanvasItem::Command::TYPE_CLIP_IGNORE: {
+ light=light->next_ptr;
+ }
- CanvasItem::CommandClipIgnore* ci = static_cast<CanvasItem::CommandClipIgnore*>(c);
- if (current_clip) {
+ if (light_used) {
- if (ci->ignore!=reclip) {
- if (ci->ignore) {
- glDisable(GL_SCISSOR_TEST);
- reclip=true;
- } else {
+ canvas_shader.set_conditional(CanvasShaderGLES2::USE_LIGHTING,false);
+ canvas_shader.set_conditional(CanvasShaderGLES2::USE_MODULATE,canvas_use_modulate);
+ canvas_shader.set_conditional(CanvasShaderGLES2::USE_SHADOWS,false);
- 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);
- reclip=false;
- }
- }
- }
+ canvas_shader.bind();
+ if (material && shader_cache) {
+ _canvas_item_setup_shader_params(material,shader_cache);
+ _canvas_item_setup_shader_uniforms(material,shader_cache);
+ }
+ canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX,ci->final_transform);
+ canvas_shader.set_uniform(CanvasShaderGLES2::EXTRA_MATRIX,Matrix32());
+ if (canvas_use_modulate)
+ canvas_shader.set_uniform(CanvasShaderGLES2::MODULATE,canvas_modulate);
- } break;
+ 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);
+ }
}
- }
+ }
+
if (reclip) {
glEnable(GL_SCISSOR_TEST);
@@ -8864,6 +9579,11 @@ bool RasterizerGLES2::is_environment(const RID& p_rid) const {
}
bool RasterizerGLES2::is_shader(const RID& p_rid) const {
+ return shader_owner.owns(p_rid);
+}
+
+bool RasterizerGLES2::is_canvas_light_occluder(const RID& p_rid) const {
+
return false;
}
@@ -9041,7 +9761,30 @@ void RasterizerGLES2::free(const RID& p_rid) {
glDeleteTextures(1,&sampled_light->texture);
sampled_light_owner.free(p_rid);
memdelete( sampled_light );
+ } 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->rbo);
+ glDeleteTextures(1,&cls->depth);
+ if (!read_depth_supported) {
+ glDeleteTextures(1,&cls->rgba);
+ }
+
+ canvas_light_shadow_owner.free(p_rid);
+ memdelete(cls);
};
}
@@ -9576,10 +10319,12 @@ void RasterizerGLES2::init() {
material_shader.init();
canvas_shader.init();
copy_shader.init();
+ canvas_shadow_shader.init();
#ifdef GLEW_ENABLED
material_shader.set_conditional(MaterialShaderGLES2::USE_GLES_OVER_GL,true);
canvas_shader.set_conditional(CanvasShaderGLES2::USE_GLES_OVER_GL,true);
+ canvas_shadow_shader.set_conditional(CanvasShadowShaderGLES2::USE_GLES_OVER_GL,true);
copy_shader.set_conditional(CopyShaderGLES2::USE_GLES_OVER_GL,true);
#endif
@@ -9720,8 +10465,11 @@ void RasterizerGLES2::init() {
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &max_texture_units);
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE,&max_texture_size);
//read_depth_supported=false;
+ canvas_shadow_blur = canvas_light_shadow_buffer_create(max_texture_size);
+
{
//shadowmaps
OS::VideoMode vm=OS::get_singleton()->get_video_mode();
@@ -9743,6 +10491,7 @@ void RasterizerGLES2::init() {
//material_shader
material_shader.set_conditional(MaterialShaderGLES2::USE_DEPTH_SHADOWS,!use_rgba_shadowmaps);
+ canvas_shadow_shader.set_conditional(CanvasShadowShaderGLES2::USE_DEPTH_SHADOWS,!use_rgba_shadowmaps);
}
@@ -9775,7 +10524,7 @@ void RasterizerGLES2::init() {
void RasterizerGLES2::finish() {
-
+ free(canvas_shadow_blur);
}
int RasterizerGLES2::get_render_info(VS::RenderInfo p_info) {
diff --git a/drivers/gles2/rasterizer_gles2.h b/drivers/gles2/rasterizer_gles2.h
index 508adf2859..f09714f50c 100644
--- a/drivers/gles2/rasterizer_gles2.h
+++ b/drivers/gles2/rasterizer_gles2.h
@@ -51,6 +51,7 @@
#include "drivers/gles2/shaders/material.glsl.h"
#include "drivers/gles2/shaders/canvas.glsl.h"
+#include "drivers/gles2/shaders/canvas_shadow.glsl.h"
#include "drivers/gles2/shaders/blur.glsl.h"
#include "drivers/gles2/shaders/copy.glsl.h"
#include "drivers/gles2/shader_compiler_gles2.h"
@@ -816,6 +817,7 @@ class RasterizerGLES2 : public Rasterizer {
bool current_depth_mask;
VS::MaterialBlendMode current_blend_mode;
bool use_fast_texture_filter;
+ int max_texture_size;
bool fragment_lighting;
RID shadow_material;
@@ -1127,6 +1129,7 @@ class RasterizerGLES2 : public Rasterizer {
bool active;
int blur_size;
+
struct Blur {
GLuint fbo;
@@ -1159,6 +1162,7 @@ class RasterizerGLES2 : public Rasterizer {
void _process_glow_and_bloom();
//void _update_blur_buffer();
+
/*********/
/* FRAME */
/*********/
@@ -1177,6 +1181,45 @@ class RasterizerGLES2 : public Rasterizer {
} _rinfo;
+ /*******************/
+ /* CANVAS OCCLUDER */
+ /*******************/
+
+
+ struct CanvasOccluder {
+
+ GLuint vertex_id; // 0 means, unconfigured
+ GLuint index_id; // 0 means, unconfigured
+ DVector<Vector2> lines;
+ int len;
+ };
+
+ RID_Owner<CanvasOccluder> canvas_occluder_owner;
+
+ /***********************/
+ /* CANVAS LIGHT SHADOW */
+ /***********************/
+
+
+ struct CanvasLightShadow {
+
+ int size;
+ int height;
+ GLuint fbo;
+ GLuint rbo;
+ GLuint depth;
+ GLuint rgba; //for older devices
+
+ GLuint blur;
+
+ };
+
+ RID_Owner<CanvasLightShadow> canvas_light_shadow_owner;
+
+ RID canvas_shadow_blur;
+
+ /* ETC */
+
RenderTarget *current_rt;
bool current_rt_transparent;
bool current_rt_vflip;
@@ -1186,11 +1229,15 @@ class RasterizerGLES2 : public Rasterizer {
GLuint white_tex;
RID canvas_tex;
float canvas_opacity;
+ Color canvas_modulate;
+ bool canvas_use_modulate;
bool uses_texpixel_size;
bool rebind_texpixel_size;
Transform canvas_transform;
- RID canvas_last_shader;
+ CanvasItemMaterial *canvas_last_material;
bool canvas_texscreen_used;
+ Vector2 normal_flip;
+ _FORCE_INLINE_ void _canvas_normal_set_flip(const Vector2& p_flip);
_FORCE_INLINE_ Texture* _bind_canvas_texture(const RID& p_texture);
@@ -1222,17 +1269,19 @@ class RasterizerGLES2 : public Rasterizer {
VS::ScenarioDebugMode current_debug;
RID overdraw_material;
+
mutable MaterialShaderGLES2 material_shader;
mutable CanvasShaderGLES2 canvas_shader;
BlurShaderGLES2 blur_shader;
CopyShaderGLES2 copy_shader;
+ mutable CanvasShadowShaderGLES2 canvas_shadow_shader;
mutable ShaderCompilerGLES2 shader_precompiler;
void _draw_primitive(int p_points, const Vector3 *p_vertices, const Vector3 *p_normals, const Color* p_colors, const Vector3 *p_uvs,const Plane *p_tangents=NULL,int p_instanced=1);
_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_gui_primitive2(int p_points, const Vector2 *p_vertices, const Color* p_colors, const Vector2 *p_uvs, const Vector2 *p_uvs2);
- void _draw_textured_quad(const Rect2& p_rect, const Rect2& p_src_region, const Size2& p_tex_size,bool p_h_flip=false, bool p_v_flip=false );
+ void _draw_textured_quad(const Rect2& p_rect, const Rect2& p_src_region, const Size2& p_tex_size,bool p_h_flip=false, bool p_v_flip=false, bool p_transpose=false );
void _draw_quad(const Rect2& p_rect);
void _copy_screen_quad();
void _copy_to_texscreen();
@@ -1247,6 +1296,10 @@ class RasterizerGLES2 : public Rasterizer {
GLuint tc0_id_cache;
GLuint tc0_idx;
+ template<bool use_normalmap>
+ _FORCE_INLINE_ void _canvas_item_render_commands(CanvasItem *p_item,CanvasItem *current_clip,bool &reclip);
+ _FORCE_INLINE_ void _canvas_item_setup_shader_params(CanvasItemMaterial *material,Shader* p_shader);
+ _FORCE_INLINE_ void _canvas_item_setup_shader_uniforms(CanvasItemMaterial *material,Shader* p_shader);
public:
/* TEXTURE API */
@@ -1562,7 +1615,18 @@ public:
virtual void canvas_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);
virtual void canvas_set_transform(const Matrix32& p_transform);
- virtual void canvas_render_items(CanvasItem *p_item_list);
+ virtual void canvas_render_items(CanvasItem *p_item_list,int p_z,const Color& p_modulate,CanvasLight *p_light);
+ virtual void canvas_debug_viewport_shadows(CanvasLight* p_lights_with_shadow);
+
+ /* CANVAS LIGHT SHADOW */
+
+ //buffer
+ virtual RID canvas_light_shadow_buffer_create(int p_width);
+ 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, CanvasLightOccluderInstance* p_occluders, CameraMatrix *p_xform_cache);
+
+ //occluder
+ virtual RID canvas_light_occluder_create();
+ virtual void canvas_light_occluder_set_polylines(RID p_occluder, const DVector<Vector2>& p_lines);
/* ENVIRONMENT */
@@ -1601,6 +1665,8 @@ public:
virtual bool is_environment(const RID& p_rid) const;
virtual bool is_shader(const RID& p_rid) const;
+ virtual bool is_canvas_light_occluder(const RID& p_rid) const;
+
virtual void free(const RID& p_rid);
virtual void init();
diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp
index d8841d407e..b2052c7cbb 100644
--- a/drivers/gles2/shader_compiler_gles2.cpp
+++ b/drivers/gles2/shader_compiler_gles2.cpp
@@ -261,6 +261,11 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a
uses_light=true;
}
+ if (vnode->name==vname_normal) {
+ uses_normal=true;
+ }
+
+
}
if (vnode->name==vname_time) {
@@ -636,7 +641,7 @@ Error ShaderCompilerGLES2::compile(const String& p_code, ShaderLanguage::ShaderT
r_flags.uses_light=uses_light;
r_flags.uses_time=uses_time;
r_flags.uses_normalmap=uses_normalmap;
- r_flags.uses_normal=uses_normalmap;
+ r_flags.uses_normal=uses_normal;
r_flags.uses_texpixel_size=uses_texpixel_size;
r_flags.uses_worldvec=uses_worldvec;
r_code_line=code;
diff --git a/drivers/gles2/shaders/SCsub b/drivers/gles2/shaders/SCsub
index c665cf9036..9679223b16 100644
--- a/drivers/gles2/shaders/SCsub
+++ b/drivers/gles2/shaders/SCsub
@@ -3,6 +3,7 @@ Import('env')
if env['BUILDERS'].has_key('GLSL120GLES'):
env.GLSL120GLES('material.glsl');
env.GLSL120GLES('canvas.glsl');
+ env.GLSL120GLES('canvas_shadow.glsl');
env.GLSL120GLES('blur.glsl');
env.GLSL120GLES('copy.glsl');
diff --git a/drivers/gles2/shaders/canvas.glsl b/drivers/gles2/shaders/canvas.glsl
index dc0af017d0..9022f30d7f 100644
--- a/drivers/gles2/shaders/canvas.glsl
+++ b/drivers/gles2/shaders/canvas.glsl
@@ -26,7 +26,17 @@ uniform float time;
#ifdef USE_LIGHTING
uniform highp mat4 light_matrix;
-varying vec4 light_tex_pos;
+uniform vec2 light_pos;
+varying vec4 light_uv_interp;
+
+#if defined(NORMAL_USED)
+varying vec4 local_rot;
+uniform vec2 normal_flip;
+#endif
+
+#ifdef USE_SHADOWS
+highp varying vec2 pos;
+#endif
#endif
@@ -57,6 +67,8 @@ VERTEX_SHADER_CODE
outvec = modelview_matrix * outvec;
#endif
+
+
#ifdef USE_PIXEL_SNAP
outvec.xy=floor(outvec.xy+0.5);
@@ -67,8 +79,16 @@ VERTEX_SHADER_CODE
#ifdef USE_LIGHTING
- light_tex_pos.xy = light_matrix * gl_Position;
- light_tex_pos.zw=outvec.xy - light_matrix[4].xy; //likely wrong
+ light_uv_interp.xy = (light_matrix * outvec).xy;
+ light_uv_interp.zw = outvec.xy-light_pos;
+#ifdef USE_SHADOWS
+ pos=outvec.xy;
+#endif
+
+#if defined(NORMAL_USED)
+ local_rot.xy=normalize( (modelview_matrix * ( extra_matrix * vec4(1.0,0.0,0.0,0.0) )).xy )*normal_flip.x;
+ local_rot.zw=normalize( (modelview_matrix * ( extra_matrix * vec4(0.0,1.0,0.0,0.0) )).xy )*normal_flip.y;
+#endif
#endif
@@ -121,17 +141,37 @@ varying vec4 var2_interp;
uniform float time;
#endif
+#ifdef USE_MODULATE
+
+uniform vec4 modulate;
+
+#endif
#ifdef USE_LIGHTING
uniform sampler2D light_texture;
-varying vec4 light_tex_pos;
+uniform vec4 light_color;
+uniform float light_height;
+varying vec4 light_uv_interp;
+
+#if defined(NORMAL_USED)
+varying vec4 local_rot;
+#endif
#ifdef USE_SHADOWS
uniform sampler2D shadow_texture;
uniform float shadow_attenuation;
+uniform highp mat4 shadow_matrix;
+uniform highp mat4 light_local_matrix;
+highp varying vec2 pos;
+uniform float shadowpixel_size;
+
+#ifdef SHADOW_ESM
+uniform float shadow_esm_multiplier;
+#endif
+
#endif
#endif
@@ -151,6 +191,7 @@ void main() {
vec3 normal = vec3(0,0,1);
#endif
+
color *= texture2D( texture, uv_interp );
#if defined(ENABLE_SCREEN_UV)
vec2 screen_uv = gl_FragCoord.xy*screen_uv_mult;
@@ -164,37 +205,141 @@ FRAGMENT_SHADER_CODE
color = vec4(vec3(enc32),1.0);
#endif
+#ifdef USE_MODULATE
+
+ color*=modulate;
+#endif
+
+
#ifdef USE_LIGHTING
+#if defined(NORMAL_USED)
+ normal.xy = mat2(local_rot.xy,local_rot.zw) * normal.xy;
+#endif
+
float att=1.0;
- vec3 light = texture2D(light_texture,light_tex_pos).rgb;
+ vec4 light = texture2D(light_texture,light_uv_interp.xy) * light_color;
#ifdef USE_SHADOWS
- //this might not be that great on mobile?
- float light_dist = length(light_texture.zw);
- float light_angle = atan2(light_texture.x,light_texture.z) + 1.0 * 0.5;
- float shadow_dist = texture2D(shadow_texture,vec2(light_angle,0));
- if (light_dist>shadow_dist) {
- light*=shadow_attenuation;
+
+
+ vec2 lpos = (light_local_matrix * vec4(pos,0.0,1.0)).xy;
+ float angle_to_light = -atan(lpos.x,lpos.y);
+ float PI = 3.14159265358979323846264;
+ /*int i = int(mod(floor((angle_to_light+7.0*PI/6.0)/(4.0*PI/6.0))+1.0, 3.0)); // +1 pq os indices estao em ordem 2,0,1 nos arrays
+ float ang*/
+
+ float su,sz;
+
+ float abs_angle = abs(angle_to_light);
+ vec2 point;
+ float sh;
+ if (abs_angle<45.0*PI/180.0) {
+ point = lpos;
+ sh=0+(1.0/8.0);
+ } else if (abs_angle>135.0*PI/180.0) {
+ point = -lpos;
+ sh = 0.5+(1.0/8.0);
+ } else if (angle_to_light>0) {
+
+ point = vec2(lpos.y,-lpos.x);
+ sh = 0.25+(1.0/8.0);
+ } else {
+
+ point = vec2(-lpos.y,lpos.x);
+ sh = 0.75+(1.0/8.0);
+
}
+
+
+ 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;
+
+ float shadow_attenuation;
+
+#ifdef SHADOW_PCF5
+
+ shadow_attenuation=0.0;
+ shadow_attenuation += texture2D(shadow_texture,vec2(su,sh)).z<sz?0.0:1.0;
+ shadow_attenuation += texture2D(shadow_texture,vec2(su+shadowpixel_size,sh)).z<sz?0.0:1.0;
+ shadow_attenuation += texture2D(shadow_texture,vec2(su+shadowpixel_size*2.0,sh)).z<sz?0.0:1.0;
+ shadow_attenuation += texture2D(shadow_texture,vec2(su-shadowpixel_size,sh)).z<sz?0.0:1.0;
+ shadow_attenuation += texture2D(shadow_texture,vec2(su-shadowpixel_size*2.0,sh)).z<sz?0.0:1.0;
+ shadow_attenuation/=5.0;
+
+#endif
+
+#ifdef SHADOW_PCF13
+
+ shadow_attenuation += texture2D(shadow_texture,vec2(su,sh)).z<sz?0.0:1.0;
+ shadow_attenuation += texture2D(shadow_texture,vec2(su+shadowpixel_size,sh)).z<sz?0.0:1.0;
+ shadow_attenuation += texture2D(shadow_texture,vec2(su+shadowpixel_size*2.0,sh)).z<sz?0.0:1.0;
+ shadow_attenuation += texture2D(shadow_texture,vec2(su+shadowpixel_size*3.0,sh)).z<sz?0.0:1.0;
+ shadow_attenuation += texture2D(shadow_texture,vec2(su+shadowpixel_size*4.0,sh)).z<sz?0.0:1.0;
+ shadow_attenuation += texture2D(shadow_texture,vec2(su+shadowpixel_size*5.0,sh)).z<sz?0.0:1.0;
+ shadow_attenuation += texture2D(shadow_texture,vec2(su+shadowpixel_size*6.0,sh)).z<sz?0.0:1.0;
+ shadow_attenuation += texture2D(shadow_texture,vec2(su-shadowpixel_size*2.0,sh)).z<sz?0.0:1.0;
+ shadow_attenuation += texture2D(shadow_texture,vec2(su-shadowpixel_size*3.0,sh)).z<sz?0.0:1.0;
+ shadow_attenuation += texture2D(shadow_texture,vec2(su-shadowpixel_size*4.0,sh)).z<sz?0.0:1.0;
+ shadow_attenuation += texture2D(shadow_texture,vec2(su-shadowpixel_size*5.0,sh)).z<sz?0.0:1.0;
+ shadow_attenuation += texture2D(shadow_texture,vec2(su-shadowpixel_size*6.0,sh)).z<sz?0.0:1.0;
+ shadow_attenuation/=13.0;
+
+#endif
+
+#ifdef SHADOW_ESM
+
+
+ {
+ float unnormalized = su/shadowpixel_size;
+ float fractional = fract(unnormalized);
+ unnormalized = floor(unnormalized);
+ float zc = texture2D(shadow_texture,vec2((unnormalized-0.5)*shadowpixel_size,sh)).z;
+ float zn = texture2D(shadow_texture,vec2((unnormalized+0.5)*shadowpixel_size,sh)).z;
+ float z = mix(zc,zn,fractional);
+ shadow_attenuation=clamp(exp(shadow_esm_multiplier* ( z - sz )),0.0,1.0);
+ }
+
+#endif
+
+#if !defined(SHADOW_PCF5) && !defined(SHADOW_PCF13) && !defined(SHADOW_ESM)
+
+ shadow_attenuation = texture2D(shadow_texture,vec2(su+shadowpixel_size,sh)).z<sz?0.0:1.0;
+
+#endif
+
+ light*=shadow_attenuation;
//use shadows
#endif
#if defined(USE_LIGHT_SHADER_CODE)
//light is written by the light shader
{
- vec2 light_dir = normalize(light_tex_pos.zw);
- float light_distance = length(light_tex_pos.zw);
+ vec2 light_dir = normalize(light_uv_interp.zw);
+ float light_distance = length(light_uv_interp.zw);
LIGHT_SHADER_CODE
}
+
#else
#if defined(NORMAL_USED)
- vec2 light_normal = normalize(light_tex_pos.zw);
- light = color.rgb * light * max(dot(light_normal,normal),0);
+ vec3 light_normal = normalize(vec3(light_uv_interp.zw,-light_height));
+ light*=max(dot(-light_normal,normal),0);
#endif
- color.rgb=light;
+ color*=light;
+/*
+#ifdef USE_NORMAL
+ color.xy=local_rot.xy;//normal.xy;
+ color.zw=vec2(0.0,1.0);
+#endif
+*/
+ if (any(lessThan(light_uv_interp.xy,vec2(0.0,0.0))) || any(greaterThanEqual(light_uv_interp.xy,vec2(1.0,1.0)))) {
+ color.a=0.0; //invisible
+ }
+
//light shader code
#endif
diff --git a/drivers/gles2/shaders/canvas_shadow.glsl b/drivers/gles2/shaders/canvas_shadow.glsl
new file mode 100644
index 0000000000..40cf321dce
--- /dev/null
+++ b/drivers/gles2/shaders/canvas_shadow.glsl
@@ -0,0 +1,62 @@
+[vertex]
+
+#ifdef USE_GLES_OVER_GL
+#define mediump
+#define highp
+#else
+precision mediump float;
+precision mediump int;
+#endif
+
+uniform highp mat4 projection_matrix;
+uniform highp mat4 light_matrix;
+uniform highp mat4 world_matrix;
+
+attribute highp vec3 vertex; // attrib:0
+
+#ifndef USE_DEPTH_SHADOWS
+
+varying vec4 position_interp;
+
+#endif
+
+
+void main() {
+
+ gl_Position = projection_matrix * (light_matrix * (world_matrix * vec4(vertex,1.0)));
+
+#ifndef USE_DEPTH_SHADOWS
+ position_interp = gl_Position;
+#endif
+
+}
+
+[fragment]
+
+#ifdef USE_GLES_OVER_GL
+#define mediump
+#define highp
+#else
+precision mediump float;
+precision mediump int;
+#endif
+
+#ifndef USE_DEPTH_SHADOWS
+
+varying vec4 position_interp;
+
+#endif
+
+void main() {
+
+#ifdef USE_DEPTH_SHADOWS
+
+#else
+ highp float depth = ((position_interp.z / position_interp.w) + 1.0) * 0.5 + 0.0;//bias;
+ 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);
+ gl_FragColor = comp;
+#endif
+
+}
+
diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp
index a6073cbb29..e24685432c 100644
--- a/drivers/windows/file_access_windows.cpp
+++ b/drivers/windows/file_access_windows.cpp
@@ -28,14 +28,18 @@
/*************************************************************************/
#ifdef WINDOWS_ENABLED
+#include <Windows.h>
+#include "Shlwapi.h"
#include "file_access_windows.h"
+
#include <sys/types.h>
#include <sys/stat.h>
#include <wchar.h>
#include <tchar.h>
#include "print_string.h"
+
#ifdef _MSC_VER
#define S_ISREG(m) ((m)&_S_IFREG)
#endif
@@ -111,10 +115,20 @@ void FileAccessWindows::close() {
//unlink(save_path.utf8().get_data());
//print_line("renaming..");
- _wunlink(save_path.c_str()); //unlink if exists
- int rename_error = _wrename((save_path+".tmp").c_str(),save_path.c_str());
+ //_wunlink(save_path.c_str()); //unlink if exists
+ //int rename_error = _wrename((save_path+".tmp").c_str(),save_path.c_str());
+
+
+ bool rename_error;
+ if (!PathFileExistsW(save_path.c_str())) {
+ //creating new file
+ rename_error = _wrename((save_path+".tmp").c_str(),save_path.c_str())!=0;
+ } else {
+ //atomic replace for existing file
+ rename_error = !ReplaceFileW(save_path.c_str(), (save_path+".tmp").c_str(), NULL, 2|4, NULL, NULL);
+ }
save_path="";
- ERR_FAIL_COND( rename_error != 0);
+ ERR_FAIL_COND( rename_error );
}