support for 2D shadow casters
Added support for 2D shadow casters. *DANGER* Shaders in CanvasItem CHANGED, if you are using shader in a CanvasItem and pull this, you will lose them. Shaders now work through a 2D material system similar to 3D. If you don't want to lose the 2D shader code, save the shader as a .shd, then create a material in CanvasItem and re-assign the shader.
This commit is contained in:
parent
0e732637d0
commit
a1f715a4da
|
@ -1778,6 +1778,11 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path,const RES& p_
|
|||
f->store_32(VERSION_MINOR);
|
||||
f->store_32(FORMAT_VERSION);
|
||||
|
||||
if (f->get_error()!=OK && f->get_error()!=ERR_FILE_EOF) {
|
||||
f->close();
|
||||
return ERR_CANT_CREATE;
|
||||
}
|
||||
|
||||
//f->store_32(saved_resources.size()+external_resources.size()); // load steps -not needed
|
||||
save_unicode_string(p_resource->get_type());
|
||||
uint64_t md_at = f->get_pos();
|
||||
|
@ -1910,6 +1915,11 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path,const RES& p_
|
|||
|
||||
f->store_buffer((const uint8_t*)"RSRC",4); //magic at end
|
||||
|
||||
if (f->get_error()!=OK && f->get_error()!=ERR_FILE_EOF) {
|
||||
f->close();
|
||||
return ERR_CANT_CREATE;
|
||||
}
|
||||
|
||||
f->close();
|
||||
|
||||
|
||||
|
|
|
@ -2592,6 +2592,11 @@ Error ResourceFormatSaverXMLInstance::save(const String &p_path,const RES& p_res
|
|||
}
|
||||
|
||||
exit_tag("resource_file");
|
||||
if (f->get_error()!=OK && f->get_error()!=ERR_FILE_EOF) {
|
||||
f->close();
|
||||
return ERR_CANT_CREATE;
|
||||
}
|
||||
|
||||
f->close();
|
||||
//memdelete(f);
|
||||
|
||||
|
|
|
@ -121,7 +121,7 @@ void CameraMatrix::set_orthogonal(float p_size, float p_aspect, float p_znear, f
|
|||
|
||||
|
||||
void CameraMatrix::set_frustum(float p_left, float p_right, float p_bottom, float p_top, float p_near, float p_far) {
|
||||
|
||||
#if 0
|
||||
///@TODO, give a check to this. I'm not sure if it's working.
|
||||
set_identity();
|
||||
|
||||
|
@ -133,10 +133,27 @@ void CameraMatrix::set_frustum(float p_left, float p_right, float p_bottom, floa
|
|||
matrix[2][3]=-(2*p_far*p_near) / (p_far-p_near);
|
||||
matrix[3][2]=-1;
|
||||
matrix[3][3]=0;
|
||||
#else
|
||||
float *te = &matrix[0][0];
|
||||
float x = 2 * p_near / ( p_right - p_left );
|
||||
float y = 2 * p_near / ( p_top - p_bottom );
|
||||
|
||||
float a = ( p_right + p_left ) / ( p_right - p_left );
|
||||
float b = ( p_top + p_bottom ) / ( p_top - p_bottom );
|
||||
float c = - ( p_far + p_near ) / ( p_far - p_near );
|
||||
float d = - 2 * p_far * p_near / ( p_far - p_near );
|
||||
|
||||
te[0] = x; te[4] = 0; te[8] = a; te[12] = 0;
|
||||
te[1] = 0; te[5] = y; te[9] = b; te[13] = 0;
|
||||
te[2] = 0; te[6] = 0; te[10] = c; te[14] = d;
|
||||
te[3] = 0; te[7] = 0; te[11] = - 1; te[15] = 0;
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
float CameraMatrix::get_z_far() const {
|
||||
|
||||
const float * matrix = (const float*)this->matrix;
|
||||
|
|
|
@ -552,6 +552,9 @@ void Variant::evaluate(const Operator& p_op, const Variant& p_a, const Variant&
|
|||
if (p_b.type==MATRIX32) {
|
||||
_RETURN( *p_a._data._matrix32 * *p_b._data._matrix32 );
|
||||
};
|
||||
if (p_b.type==VECTOR2) {
|
||||
_RETURN( p_a._data._matrix32->xform( *(const Vector2*)p_b._data._mem) );
|
||||
};
|
||||
r_valid=false;
|
||||
return;
|
||||
} break;
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -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');
|
||||
|
||||
|
|
|
@ -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
|
||||
|
@ -7874,7 +7878,8 @@ void RasterizerGLES2::canvas_begin() {
|
|||
canvas_blend_mode=VS::MATERIAL_BLEND_MODE_MIX;
|
||||
canvas_texscreen_used=false;
|
||||
uses_texpixel_size=false;
|
||||
canvas_last_shader=RID();
|
||||
|
||||
canvas_last_material=NULL;
|
||||
|
||||
}
|
||||
|
||||
|
@ -8364,6 +8369,476 @@ 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_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)
|
||||
|
@ -8508,14 +8983,14 @@ void RasterizerGLES2::_canvas_item_render_commands(CanvasItem *p_item,CanvasItem
|
|||
|
||||
}
|
||||
|
||||
void RasterizerGLES2::_canvas_item_setup_shader_params(CanvasItem *shader_owner,Shader* shader) {
|
||||
void RasterizerGLES2::_canvas_item_setup_shader_params(CanvasItemMaterial *material,Shader* shader) {
|
||||
|
||||
if (canvas_shader.bind())
|
||||
rebind_texpixel_size=true;
|
||||
|
||||
if (shader_owner->shader_version!=shader->version) {
|
||||
if (material->shader_version!=shader->version) {
|
||||
//todo optimize uniforms
|
||||
shader_owner->shader_version=shader->version;
|
||||
material->shader_version=shader->version;
|
||||
}
|
||||
|
||||
if (shader->has_texscreen && framebuffer.active) {
|
||||
|
@ -8558,14 +9033,14 @@ void RasterizerGLES2::_canvas_item_setup_shader_params(CanvasItem *shader_owner,
|
|||
|
||||
}
|
||||
|
||||
void RasterizerGLES2::_canvas_item_setup_shader_uniforms(CanvasItem *shader_owner,Shader* shader) {
|
||||
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=shader_owner->shader_param.find(E->key());
|
||||
Map<StringName,Variant>::Element *F=material->shader_param.find(E->key());
|
||||
|
||||
if ((E->get().type==ShaderLanguage::TYPE_TEXTURE || E->get().type==ShaderLanguage::TYPE_CUBEMAP)) {
|
||||
|
||||
|
@ -8623,6 +9098,8 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
|
|||
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;
|
||||
|
@ -8632,12 +9109,13 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
|
|||
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;
|
||||
|
||||
|
||||
}
|
||||
|
@ -8660,13 +9138,14 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
|
|||
|
||||
|
||||
//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 || rebind_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;
|
||||
}
|
||||
|
@ -8676,7 +9155,7 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
|
|||
|
||||
if (shader) {
|
||||
canvas_shader.set_custom_shader(shader->custom_code_id);
|
||||
_canvas_item_setup_shader_params(shader_owner,shader);
|
||||
_canvas_item_setup_shader_params(material,shader);
|
||||
} else {
|
||||
shader_cache=NULL;
|
||||
canvas_shader.set_custom_shader(0);
|
||||
|
@ -8688,16 +9167,26 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
|
|||
|
||||
canvas_shader.set_uniform(CanvasShaderGLES2::PROJECTION_MATRIX,canvas_transform);
|
||||
if (canvas_use_modulate)
|
||||
canvas_shader.set_uniform(CanvasShaderGLES2::MODULATE,canvas_modulate);
|
||||
canvas_last_shader=shader_owner->shader;
|
||||
reset_modulate=true;
|
||||
canvas_last_material=material;
|
||||
rebind_shader=false;
|
||||
}
|
||||
|
||||
if (shader_cache) {
|
||||
if (material && shader_cache) {
|
||||
|
||||
_canvas_item_setup_shader_uniforms(shader_owner,shader_cache);
|
||||
_canvas_item_setup_shader_uniforms(material,shader_cache);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX,ci->final_transform);
|
||||
canvas_shader.set_uniform(CanvasShaderGLES2::EXTRA_MATRIX,Matrix32());
|
||||
|
||||
|
@ -8747,7 +9236,7 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
|
|||
|
||||
_canvas_item_render_commands<false>(ci,current_clip,reclip);
|
||||
|
||||
if (canvas_blend_mode==VS::MATERIAL_BLEND_MODE_MIX && p_light) {
|
||||
if (canvas_blend_mode==VS::MATERIAL_BLEND_MODE_MIX && p_light && (!material || !material->unshaded)) {
|
||||
|
||||
CanvasLight *light = p_light;
|
||||
bool light_used=false;
|
||||
|
@ -8785,13 +9274,15 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
|
|||
normal_flip=Vector2(1,1);
|
||||
|
||||
}
|
||||
canvas_shader.set_conditional(CanvasShaderGLES2::USE_SHADOWS,light->shadow_buffer.is_valid());
|
||||
|
||||
bool light_rebind = canvas_shader.bind();
|
||||
|
||||
if (light_rebind) {
|
||||
|
||||
if (shader_owner && shader_cache) {
|
||||
_canvas_item_setup_shader_params(shader_owner,shader_cache);
|
||||
_canvas_item_setup_shader_uniforms(shader_owner,shader_cache);
|
||||
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);
|
||||
|
@ -8800,6 +9291,7 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
|
|||
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);
|
||||
|
||||
|
||||
}
|
||||
|
@ -8808,6 +9300,23 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
|
|||
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()) {
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
|
@ -8831,12 +9340,13 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
|
|||
|
||||
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);
|
||||
|
||||
canvas_shader.bind();
|
||||
|
||||
if (shader_owner && shader_cache) {
|
||||
_canvas_item_setup_shader_params(shader_owner,shader_cache);
|
||||
_canvas_item_setup_shader_uniforms(shader_owner,shader_cache);
|
||||
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);
|
||||
|
@ -9067,6 +9577,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;
|
||||
}
|
||||
|
||||
|
@ -9244,7 +9759,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);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -9779,10 +10317,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
|
||||
|
||||
|
@ -9923,8 +10463,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();
|
||||
|
@ -9946,6 +10489,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);
|
||||
|
||||
}
|
||||
|
||||
|
@ -9978,7 +10522,7 @@ void RasterizerGLES2::init() {
|
|||
|
||||
void RasterizerGLES2::finish() {
|
||||
|
||||
|
||||
free(canvas_shadow_blur);
|
||||
}
|
||||
|
||||
int RasterizerGLES2::get_render_info(VS::RenderInfo p_info) {
|
||||
|
|
|
@ -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;
|
||||
|
@ -1160,6 +1162,7 @@ class RasterizerGLES2 : public Rasterizer {
|
|||
void _process_glow_and_bloom();
|
||||
//void _update_blur_buffer();
|
||||
|
||||
|
||||
/*********/
|
||||
/* FRAME */
|
||||
/*********/
|
||||
|
@ -1178,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;
|
||||
|
@ -1192,7 +1234,7 @@ class RasterizerGLES2 : public Rasterizer {
|
|||
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);
|
||||
|
@ -1227,10 +1269,12 @@ 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;
|
||||
|
||||
|
@ -1254,8 +1298,8 @@ class RasterizerGLES2 : public Rasterizer {
|
|||
|
||||
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(CanvasItem *shader_owner,Shader* p_shader);
|
||||
_FORCE_INLINE_ void _canvas_item_setup_shader_uniforms(CanvasItem *shader_owner,Shader* p_shader);
|
||||
_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 */
|
||||
|
@ -1572,7 +1616,17 @@ public:
|
|||
virtual void canvas_set_transform(const Matrix32& p_transform);
|
||||
|
||||
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 */
|
||||
|
||||
|
@ -1611,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();
|
||||
|
|
|
@ -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');
|
||||
|
||||
|
|
|
@ -34,6 +34,10 @@ varying vec4 local_rot;
|
|||
uniform vec2 normal_flip;
|
||||
#endif
|
||||
|
||||
#ifdef USE_SHADOWS
|
||||
highp varying vec2 pos;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(ENABLE_VAR1_INTERP)
|
||||
|
@ -63,6 +67,8 @@ VERTEX_SHADER_CODE
|
|||
outvec = modelview_matrix * outvec;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef USE_PIXEL_SNAP
|
||||
|
||||
outvec.xy=floor(outvec.xy+0.5);
|
||||
|
@ -75,6 +81,9 @@ VERTEX_SHADER_CODE
|
|||
|
||||
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;
|
||||
|
@ -154,6 +163,15 @@ varying vec4 local_rot;
|
|||
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
|
||||
|
@ -173,10 +191,6 @@ void main() {
|
|||
vec3 normal = vec3(0,0,1);
|
||||
#endif
|
||||
|
||||
#ifdef USE_MODULATE
|
||||
|
||||
color*=modulate;
|
||||
#endif
|
||||
|
||||
color *= texture2D( texture, uv_interp );
|
||||
#if defined(ENABLE_SCREEN_UV)
|
||||
|
@ -191,6 +205,12 @@ FRAGMENT_SHADER_CODE
|
|||
color = vec4(vec3(enc32),1.0);
|
||||
#endif
|
||||
|
||||
#ifdef USE_MODULATE
|
||||
|
||||
color*=modulate;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef USE_LIGHTING
|
||||
|
||||
#if defined(NORMAL_USED)
|
||||
|
@ -201,13 +221,96 @@ FRAGMENT_SHADER_CODE
|
|||
|
||||
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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
}
|
||||
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -2696,7 +2696,10 @@ Error ResourceFormatSaverGDScript::save(const String &p_path,const RES& p_resour
|
|||
}
|
||||
|
||||
file->store_string(source);
|
||||
|
||||
if (file->get_error()!=OK && file->get_error()!=ERR_FILE_EOF) {
|
||||
memdelete(file);
|
||||
return ERR_CANT_CREATE;
|
||||
}
|
||||
file->close();
|
||||
memdelete(file);
|
||||
return OK;
|
||||
|
|
|
@ -396,6 +396,14 @@ void AudioDriverOpenSL::finish(){
|
|||
void AudioDriverOpenSL::set_pause(bool p_pause) {
|
||||
|
||||
pause=p_pause;
|
||||
|
||||
if (active) {
|
||||
if (pause) {
|
||||
(*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PAUSED);
|
||||
} else {
|
||||
(*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PLAYING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -151,7 +151,7 @@ void OS_Android::initialize(const VideoMode& p_desired,int p_video_driver,int p_
|
|||
sample_manager = memnew( SampleManagerMallocSW );
|
||||
audio_server = memnew( AudioServerSW(sample_manager) );
|
||||
|
||||
audio_server->set_mixer_params(AudioMixerSW::INTERPOLATION_LINEAR,false);
|
||||
audio_server->set_mixer_params(AudioMixerSW::INTERPOLATION_LINEAR,true);
|
||||
audio_server->init();
|
||||
|
||||
spatial_sound_server = memnew( SpatialSoundServerSW );
|
||||
|
|
|
@ -115,7 +115,7 @@ def configure(env):
|
|||
env.Append(CCFLAGS=['/DGLES2_ENABLED'])
|
||||
|
||||
env.Append(CCFLAGS=['/DGLEW_ENABLED'])
|
||||
LIBS=['winmm','opengl32','dsound','kernel32','ole32','user32','gdi32', 'IPHLPAPI', 'wsock32', 'shell32','advapi32']
|
||||
LIBS=['winmm','opengl32','dsound','kernel32','ole32','user32','gdi32', 'IPHLPAPI','Shlwapi', 'wsock32', 'shell32','advapi32']
|
||||
env.Append(LINKFLAGS=[p+env["LIBSUFFIX"] for p in LIBS])
|
||||
|
||||
env.Append(LIBPATH=[os.getenv("WindowsSdkDir")+"/Lib"])
|
||||
|
@ -229,7 +229,7 @@ def configure(env):
|
|||
env.Append(CCFLAGS=['-DWINDOWS_ENABLED','-mwindows'])
|
||||
env.Append(CPPFLAGS=['-DRTAUDIO_ENABLED'])
|
||||
env.Append(CCFLAGS=['-DGLES2_ENABLED','-DGLEW_ENABLED'])
|
||||
env.Append(LIBS=['mingw32','opengl32', 'dsound', 'ole32', 'd3d9','winmm','gdi32','iphlpapi','wsock32','kernel32'])
|
||||
env.Append(LIBS=['mingw32','opengl32', 'dsound', 'ole32', 'd3d9','winmm','gdi32','iphlpapi','shlwapi','wsock32','kernel32'])
|
||||
|
||||
if (env["bits"]=="32" and env["mingw64_for_32"]!="yes"):
|
||||
# env.Append(LIBS=['gcc_s'])
|
||||
|
|
|
@ -36,6 +36,192 @@
|
|||
#include "scene/resources/texture.h"
|
||||
#include "scene/resources/style_box.h"
|
||||
|
||||
|
||||
bool CanvasItemMaterial::_set(const StringName& p_name, const Variant& p_value) {
|
||||
|
||||
if (p_name==SceneStringNames::get_singleton()->shader_shader) {
|
||||
set_shader(p_value);
|
||||
return true;
|
||||
} else if (p_name==SceneStringNames::get_singleton()->shader_unshaded) {
|
||||
set_unshaded(p_value);
|
||||
print_line("set unshaded");
|
||||
return true;
|
||||
} else {
|
||||
|
||||
if (shader.is_valid()) {
|
||||
|
||||
|
||||
StringName pr = shader->remap_param(p_name);
|
||||
if (!pr) {
|
||||
String n = p_name;
|
||||
if (n.find("param/")==0) { //backwards compatibility
|
||||
pr = n.substr(6,n.length());
|
||||
}
|
||||
}
|
||||
if (pr) {
|
||||
VisualServer::get_singleton()->canvas_item_material_set_shader_param(material,pr,p_value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CanvasItemMaterial::_get(const StringName& p_name,Variant &r_ret) const {
|
||||
|
||||
|
||||
if (p_name==SceneStringNames::get_singleton()->shader_shader) {
|
||||
|
||||
r_ret=get_shader();
|
||||
return true;
|
||||
} else if (p_name==SceneStringNames::get_singleton()->shader_unshaded) {
|
||||
|
||||
|
||||
r_ret=unshaded;
|
||||
return true;
|
||||
} else {
|
||||
|
||||
if (shader.is_valid()) {
|
||||
|
||||
StringName pr = shader->remap_param(p_name);
|
||||
if (pr) {
|
||||
r_ret=VisualServer::get_singleton()->canvas_item_material_get_shader_param(material,pr);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void CanvasItemMaterial::_get_property_list( List<PropertyInfo> *p_list) const {
|
||||
|
||||
p_list->push_back( PropertyInfo( Variant::OBJECT, "shader/shader", PROPERTY_HINT_RESOURCE_TYPE,"CanvasItemShader,CanvasItemShaderGraph" ) );
|
||||
p_list->push_back( PropertyInfo( Variant::BOOL, "shader/unshaded") );
|
||||
|
||||
if (!shader.is_null()) {
|
||||
|
||||
shader->get_param_list(p_list);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CanvasItemMaterial::set_shader(const Ref<Shader>& p_shader) {
|
||||
|
||||
ERR_FAIL_COND(p_shader.is_valid() && p_shader->get_mode()!=Shader::MODE_CANVAS_ITEM);
|
||||
#ifdef TOOLS_ENABLED
|
||||
|
||||
if (shader.is_valid()) {
|
||||
shader->disconnect("changed",this,"_shader_changed");
|
||||
}
|
||||
#endif
|
||||
shader=p_shader;
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
|
||||
if (shader.is_valid()) {
|
||||
shader->connect("changed",this,"_shader_changed");
|
||||
}
|
||||
#endif
|
||||
|
||||
RID rid;
|
||||
if (shader.is_valid())
|
||||
rid=shader->get_rid();
|
||||
|
||||
VS::get_singleton()->canvas_item_material_set_shader(material,rid);
|
||||
_change_notify(); //properties for shader exposed
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
Ref<Shader> CanvasItemMaterial::get_shader() const{
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
void CanvasItemMaterial::set_shader_param(const StringName& p_param,const Variant& p_value){
|
||||
|
||||
VS::get_singleton()->canvas_item_material_set_shader_param(material,p_param,p_value);
|
||||
}
|
||||
|
||||
Variant CanvasItemMaterial::get_shader_param(const StringName& p_param) const{
|
||||
|
||||
return VS::get_singleton()->canvas_item_material_get_shader_param(material,p_param);
|
||||
}
|
||||
|
||||
void CanvasItemMaterial::_shader_changed() {
|
||||
|
||||
|
||||
}
|
||||
|
||||
RID CanvasItemMaterial::get_rid() const {
|
||||
|
||||
return material;
|
||||
}
|
||||
|
||||
void CanvasItemMaterial::set_unshaded(bool p_unshaded) {
|
||||
|
||||
unshaded=p_unshaded;
|
||||
VS::get_singleton()->canvas_item_material_set_unshaded(material,p_unshaded);
|
||||
}
|
||||
|
||||
bool CanvasItemMaterial::is_unshaded() const{
|
||||
|
||||
return unshaded;
|
||||
}
|
||||
|
||||
void CanvasItemMaterial::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_shader","shader:Shader"),&CanvasItemMaterial::set_shader);
|
||||
ObjectTypeDB::bind_method(_MD("get_shader:Shader"),&CanvasItemMaterial::get_shader);
|
||||
ObjectTypeDB::bind_method(_MD("set_shader_param","param","value"),&CanvasItemMaterial::set_shader_param);
|
||||
ObjectTypeDB::bind_method(_MD("get_shader_param","param"),&CanvasItemMaterial::get_shader_param);
|
||||
ObjectTypeDB::bind_method(_MD("set_unshaded","unshaded"),&CanvasItemMaterial::set_unshaded);
|
||||
ObjectTypeDB::bind_method(_MD("is_unshaded"),&CanvasItemMaterial::is_unshaded);
|
||||
|
||||
}
|
||||
|
||||
void CanvasItemMaterial::get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const {
|
||||
|
||||
String f = p_function.operator String();
|
||||
if ((f=="get_shader_param" || f=="set_shader_param") && p_idx==0) {
|
||||
|
||||
if (shader.is_valid()) {
|
||||
List<PropertyInfo> pl;
|
||||
shader->get_param_list(&pl);
|
||||
for (List<PropertyInfo>::Element *E=pl.front();E;E=E->next()) {
|
||||
r_options->push_back("\""+E->get().name.replace_first("shader_param/","")+"\"");
|
||||
}
|
||||
}
|
||||
}
|
||||
Resource::get_argument_options(p_function,p_idx,r_options);
|
||||
}
|
||||
|
||||
CanvasItemMaterial::CanvasItemMaterial() {
|
||||
|
||||
material=VS::get_singleton()->canvas_item_material_create();
|
||||
unshaded=false;
|
||||
}
|
||||
|
||||
CanvasItemMaterial::~CanvasItemMaterial(){
|
||||
|
||||
VS::get_singleton()->free(material);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
bool CanvasItem::is_visible() const {
|
||||
|
||||
if (!is_inside_tree())
|
||||
|
@ -730,111 +916,35 @@ bool CanvasItem::is_draw_behind_parent_enabled() const{
|
|||
return behind;
|
||||
}
|
||||
|
||||
void CanvasItem::set_shader(const Ref<Shader>& p_shader) {
|
||||
void CanvasItem::set_material(const Ref<CanvasItemMaterial>& p_material) {
|
||||
|
||||
ERR_FAIL_COND(p_shader.is_valid() && p_shader->get_mode()!=Shader::MODE_CANVAS_ITEM);
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
|
||||
if (shader.is_valid()) {
|
||||
shader->disconnect("changed",this,"_shader_changed");
|
||||
}
|
||||
#endif
|
||||
shader=p_shader;
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
|
||||
if (shader.is_valid()) {
|
||||
shader->connect("changed",this,"_shader_changed");
|
||||
}
|
||||
#endif
|
||||
|
||||
material=p_material;
|
||||
RID rid;
|
||||
if (shader.is_valid())
|
||||
rid=shader->get_rid();
|
||||
VS::get_singleton()->canvas_item_set_shader(canvas_item,rid);
|
||||
_change_notify(); //properties for shader exposed
|
||||
if (material.is_valid())
|
||||
rid=material->get_rid();
|
||||
VS::get_singleton()->canvas_item_set_material(canvas_item,rid);
|
||||
_change_notify(); //properties for material exposed
|
||||
}
|
||||
|
||||
void CanvasItem::set_use_parent_shader(bool p_use_parent_shader) {
|
||||
void CanvasItem::set_use_parent_material(bool p_use_parent_material) {
|
||||
|
||||
use_parent_shader=p_use_parent_shader;
|
||||
VS::get_singleton()->canvas_item_set_use_parent_shader(canvas_item,p_use_parent_shader);
|
||||
use_parent_material=p_use_parent_material;
|
||||
VS::get_singleton()->canvas_item_set_use_parent_material(canvas_item,p_use_parent_material);
|
||||
}
|
||||
|
||||
bool CanvasItem::get_use_parent_shader() const{
|
||||
bool CanvasItem::get_use_parent_material() const{
|
||||
|
||||
return use_parent_shader;
|
||||
return use_parent_material;
|
||||
}
|
||||
|
||||
Ref<Shader> CanvasItem::get_shader() const{
|
||||
Ref<CanvasItemMaterial> CanvasItem::get_material() const{
|
||||
|
||||
return shader;
|
||||
return material;
|
||||
}
|
||||
|
||||
void CanvasItem::set_shader_param(const StringName& p_param,const Variant& p_value) {
|
||||
|
||||
VS::get_singleton()->canvas_item_set_shader_param(canvas_item,p_param,p_value);
|
||||
}
|
||||
|
||||
Variant CanvasItem::get_shader_param(const StringName& p_param) const {
|
||||
|
||||
return VS::get_singleton()->canvas_item_get_shader_param(canvas_item,p_param);
|
||||
}
|
||||
|
||||
bool CanvasItem::_set(const StringName& p_name, const Variant& p_value) {
|
||||
|
||||
if (shader.is_valid()) {
|
||||
StringName pr = shader->remap_param(p_name);
|
||||
if (pr) {
|
||||
set_shader_param(pr,p_value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CanvasItem::_get(const StringName& p_name,Variant &r_ret) const{
|
||||
|
||||
if (shader.is_valid()) {
|
||||
StringName pr = shader->remap_param(p_name);
|
||||
if (pr) {
|
||||
r_ret=get_shader_param(pr);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
void CanvasItem::_get_property_list( List<PropertyInfo> *p_list) const{
|
||||
|
||||
if (shader.is_valid()) {
|
||||
shader->get_param_list(p_list);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
void CanvasItem::_shader_changed() {
|
||||
|
||||
_change_notify();
|
||||
}
|
||||
#endif
|
||||
|
||||
void CanvasItem::get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const {
|
||||
|
||||
if (p_idx==0 && shader.is_valid() && (p_function.operator String()=="get_shader_param" || p_function.operator String()=="set_shader_param")) {
|
||||
|
||||
List<PropertyInfo> pl;
|
||||
shader->get_param_list(&pl);
|
||||
for(List<PropertyInfo>::Element *E=pl.front();E;E=E->next()) {
|
||||
r_options->push_back("\""+E->get().name.replace_first("shader_param/","")+"\"");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Node::get_argument_options(p_function,p_idx,r_options);
|
||||
}
|
||||
|
||||
|
||||
void CanvasItem::_bind_methods() {
|
||||
|
@ -880,9 +990,6 @@ void CanvasItem::_bind_methods() {
|
|||
|
||||
ObjectTypeDB::bind_method(_MD("_set_on_top","on_top"),&CanvasItem::_set_on_top);
|
||||
ObjectTypeDB::bind_method(_MD("_is_on_top"),&CanvasItem::_is_on_top);
|
||||
#ifdef TOOLS_ENABLED
|
||||
ObjectTypeDB::bind_method(_MD("_shader_changed"),&CanvasItem::_shader_changed);
|
||||
#endif
|
||||
//ObjectTypeDB::bind_method(_MD("get_transform"),&CanvasItem::get_transform);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("draw_line","from","to","color","width"),&CanvasItem::draw_line,DEFVAL(1.0));
|
||||
|
@ -901,20 +1008,18 @@ void CanvasItem::_bind_methods() {
|
|||
ObjectTypeDB::bind_method(_MD("draw_set_transform","pos","rot","scale"),&CanvasItem::draw_set_transform);
|
||||
ObjectTypeDB::bind_method(_MD("get_transform"),&CanvasItem::get_transform);
|
||||
ObjectTypeDB::bind_method(_MD("get_global_transform"),&CanvasItem::get_global_transform);
|
||||
ObjectTypeDB::bind_method(_MD("get_global_transform_with_canvas"),&CanvasItem::get_global_transform_with_canvas);
|
||||
ObjectTypeDB::bind_method(_MD("get_viewport_transform"),&CanvasItem::get_viewport_transform);
|
||||
ObjectTypeDB::bind_method(_MD("get_viewport_rect"),&CanvasItem::get_viewport_rect);
|
||||
ObjectTypeDB::bind_method(_MD("get_canvas"),&CanvasItem::get_canvas);
|
||||
ObjectTypeDB::bind_method(_MD("get_world_2d"),&CanvasItem::get_world_2d);
|
||||
//ObjectTypeDB::bind_method(_MD("get_viewport"),&CanvasItem::get_viewport);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_shader","shader"),&CanvasItem::set_shader);
|
||||
ObjectTypeDB::bind_method(_MD("get_shader"),&CanvasItem::get_shader);
|
||||
ObjectTypeDB::bind_method(_MD("set_use_parent_shader","enable"),&CanvasItem::set_use_parent_shader);
|
||||
ObjectTypeDB::bind_method(_MD("get_use_parent_shader"),&CanvasItem::get_use_parent_shader);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_shader_param","param","value"),&CanvasItem::set_shader_param);
|
||||
ObjectTypeDB::bind_method(_MD("get_shader_param","param"),&CanvasItem::get_shader_param);
|
||||
ObjectTypeDB::bind_method(_MD("set_material","material:CanvasItemMaterial"),&CanvasItem::set_material);
|
||||
ObjectTypeDB::bind_method(_MD("get_material:CanvasItemMaterial"),&CanvasItem::get_material);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_use_parent_material","enable"),&CanvasItem::set_use_parent_material);
|
||||
ObjectTypeDB::bind_method(_MD("get_use_parent_material"),&CanvasItem::get_use_parent_material);
|
||||
|
||||
BIND_VMETHOD(MethodInfo("_draw"));
|
||||
|
||||
|
@ -926,8 +1031,8 @@ void CanvasItem::_bind_methods() {
|
|||
|
||||
ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"visibility/blend_mode",PROPERTY_HINT_ENUM, "Mix,Add,Sub,Mul,PMAlpha"), _SCS("set_blend_mode"),_SCS("get_blend_mode") );
|
||||
ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"visibility/light_mask",PROPERTY_HINT_ALL_FLAGS), _SCS("set_light_mask"),_SCS("get_light_mask") );
|
||||
ADD_PROPERTYNZ( PropertyInfo(Variant::OBJECT,"shader/shader",PROPERTY_HINT_RESOURCE_TYPE, "CanvasItemShader,CanvasItemShaderGraph"), _SCS("set_shader"),_SCS("get_shader") );
|
||||
ADD_PROPERTYNZ( PropertyInfo(Variant::BOOL,"shader/use_parent"), _SCS("set_use_parent_shader"),_SCS("get_use_parent_shader") );
|
||||
ADD_PROPERTYNZ( PropertyInfo(Variant::OBJECT,"material/material",PROPERTY_HINT_RESOURCE_TYPE, "CanvasItemMaterial"), _SCS("set_material"),_SCS("get_material") );
|
||||
ADD_PROPERTYNZ( PropertyInfo(Variant::BOOL,"material/use_parent"), _SCS("set_use_parent_material"),_SCS("get_use_parent_material") );
|
||||
//exporting these two things doesn't really make much sense i think
|
||||
//ADD_PROPERTY( PropertyInfo(Variant::BOOL,"transform/toplevel"), _SCS("set_as_toplevel"),_SCS("is_set_as_toplevel") );
|
||||
//ADD_PROPERTY(PropertyInfo(Variant::BOOL,"transform/notify"),_SCS("set_transform_notify"),_SCS("is_transform_notify_enabled"));
|
||||
|
@ -1004,7 +1109,7 @@ CanvasItem::CanvasItem() : xform_change(this) {
|
|||
block_transform_notify=false;
|
||||
// viewport=NULL;
|
||||
canvas_layer=NULL;
|
||||
use_parent_shader=false;
|
||||
use_parent_material=false;
|
||||
global_invalid=true;
|
||||
light_mask=1;
|
||||
|
||||
|
|
|
@ -40,6 +40,41 @@ class Font;
|
|||
|
||||
class StyleBox;
|
||||
|
||||
class CanvasItemMaterial : public Resource{
|
||||
|
||||
OBJ_TYPE(CanvasItemMaterial,Resource);
|
||||
RID material;
|
||||
Ref<Shader> shader;
|
||||
bool unshaded;
|
||||
|
||||
protected:
|
||||
|
||||
bool _set(const StringName& p_name, const Variant& p_value);
|
||||
bool _get(const StringName& p_name,Variant &r_ret) const;
|
||||
void _get_property_list( List<PropertyInfo> *p_list) const;
|
||||
|
||||
void _shader_changed();
|
||||
static void _bind_methods();
|
||||
|
||||
void get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const;
|
||||
|
||||
public:
|
||||
|
||||
void set_shader(const Ref<Shader>& p_shader);
|
||||
Ref<Shader> get_shader() const;
|
||||
|
||||
void set_shader_param(const StringName& p_param,const Variant& p_value);
|
||||
Variant get_shader_param(const StringName& p_param) const;
|
||||
|
||||
void set_unshaded(bool p_unshaded);
|
||||
bool is_unshaded() const;
|
||||
|
||||
virtual RID get_rid() const;
|
||||
CanvasItemMaterial();
|
||||
~CanvasItemMaterial();
|
||||
};
|
||||
|
||||
|
||||
class CanvasItem : public Node {
|
||||
|
||||
OBJ_TYPE( CanvasItem, Node );
|
||||
|
@ -81,9 +116,9 @@ private:
|
|||
bool drawing;
|
||||
bool block_transform_notify;
|
||||
bool behind;
|
||||
bool use_parent_shader;
|
||||
bool use_parent_material;
|
||||
|
||||
Ref<Shader> shader;
|
||||
Ref<CanvasItemMaterial> material;
|
||||
|
||||
mutable Matrix32 global_transform;
|
||||
mutable bool global_invalid;
|
||||
|
@ -104,9 +139,6 @@ private:
|
|||
void _queue_sort_children();
|
||||
void _sort_children();
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
void _shader_changed();
|
||||
#endif
|
||||
void _notify_transform(CanvasItem *p_node);
|
||||
|
||||
void _set_on_top(bool p_on_top) { set_draw_behind_parent(!p_on_top); }
|
||||
|
@ -114,11 +146,6 @@ private:
|
|||
|
||||
protected:
|
||||
|
||||
bool _set(const StringName& p_name, const Variant& p_value);
|
||||
bool _get(const StringName& p_name,Variant &r_ret) const;
|
||||
void _get_property_list( List<PropertyInfo> *p_list) const;
|
||||
|
||||
|
||||
_FORCE_INLINE_ void _notify_transform() { if (!is_inside_tree()) return; _notify_transform(this); if (!block_transform_notify) notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED); }
|
||||
|
||||
void item_rect_changed();
|
||||
|
@ -216,16 +243,12 @@ public:
|
|||
RID get_canvas() const;
|
||||
Ref<World2D> get_world_2d() const;
|
||||
|
||||
void set_shader(const Ref<Shader>& p_shader);
|
||||
Ref<Shader> get_shader() const;
|
||||
void set_material(const Ref<CanvasItemMaterial>& p_material);
|
||||
Ref<CanvasItemMaterial> get_material() const;
|
||||
|
||||
void set_use_parent_shader(bool p_use_parent_shader);
|
||||
bool get_use_parent_shader() const;
|
||||
void set_use_parent_material(bool p_use_parent_material);
|
||||
bool get_use_parent_material() const;
|
||||
|
||||
void set_shader_param(const StringName& p_param,const Variant& p_value);
|
||||
Variant get_shader_param(const StringName& p_param) const;
|
||||
|
||||
void get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const;
|
||||
|
||||
CanvasItem();
|
||||
~CanvasItem();
|
||||
|
|
|
@ -170,6 +170,29 @@ bool Light2D::is_shadow_enabled() const {
|
|||
return shadow;
|
||||
}
|
||||
|
||||
void Light2D::set_shadow_buffer_size( int p_size ) {
|
||||
|
||||
shadow_buffer_size=p_size;
|
||||
VS::get_singleton()->canvas_light_set_shadow_buffer_size(canvas_light,shadow_buffer_size);
|
||||
}
|
||||
|
||||
int Light2D::get_shadow_buffer_size() const {
|
||||
|
||||
return shadow_buffer_size;
|
||||
}
|
||||
|
||||
void Light2D::set_shadow_esm_multiplier( float p_multiplier) {
|
||||
|
||||
shadow_esm_multiplier=p_multiplier;
|
||||
VS::get_singleton()->canvas_light_set_shadow_esm_multiplier(canvas_light,p_multiplier);
|
||||
}
|
||||
|
||||
float Light2D::get_shadow_esm_multiplier() const{
|
||||
|
||||
return shadow_esm_multiplier;
|
||||
}
|
||||
|
||||
|
||||
void Light2D::_notification(int p_what) {
|
||||
|
||||
if (p_what==NOTIFICATION_ENTER_TREE) {
|
||||
|
@ -229,18 +252,26 @@ void Light2D::_bind_methods() {
|
|||
ObjectTypeDB::bind_method(_MD("set_shadow_enabled","enabled"),&Light2D::set_shadow_enabled);
|
||||
ObjectTypeDB::bind_method(_MD("is_shadow_enabled"),&Light2D::is_shadow_enabled);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_shadow_buffer_size","size"),&Light2D::set_shadow_buffer_size);
|
||||
ObjectTypeDB::bind_method(_MD("get_shadow_buffer_size"),&Light2D::get_shadow_buffer_size);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_shadow_esm_multiplier","multiplier"),&Light2D::set_shadow_esm_multiplier);
|
||||
ObjectTypeDB::bind_method(_MD("get_shadow_esm_multiplier"),&Light2D::get_shadow_esm_multiplier);
|
||||
|
||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"enabled"),_SCS("set_enabled"),_SCS("is_enabled"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"texture_offset"),_SCS("set_texture_offset"),_SCS("get_texture_offset"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"offset"),_SCS("set_texture_offset"),_SCS("get_texture_offset"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::COLOR,"color"),_SCS("set_color"),_SCS("get_color"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"height"),_SCS("set_height"),_SCS("get_height"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::INT,"z_range_min",PROPERTY_HINT_RANGE,itos(VS::CANVAS_ITEM_Z_MIN)+","+itos(VS::CANVAS_ITEM_Z_MAX)+",1"),_SCS("set_z_range_min"),_SCS("get_z_range_min"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::INT,"z_range_max",PROPERTY_HINT_RANGE,itos(VS::CANVAS_ITEM_Z_MIN)+","+itos(VS::CANVAS_ITEM_Z_MAX)+",1"),_SCS("set_z_range_max"),_SCS("get_z_range_max"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::INT,"layer_range_min",PROPERTY_HINT_RANGE,"-512,512,1"),_SCS("set_layer_range_min"),_SCS("get_layer_range_min"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::INT,"layer_range_max",PROPERTY_HINT_RANGE,"-512,512,1"),_SCS("set_layer_range_max"),_SCS("get_layer_range_max"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::INT,"item_mask",PROPERTY_HINT_ALL_FLAGS),_SCS("set_item_mask"),_SCS("get_item_mask"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"subtract"),_SCS("set_subtract_mode"),_SCS("get_subtract_mode"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"shadow_enabled"),_SCS("set_shadow_enabled"),_SCS("is_shadow_enabled"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"range/height"),_SCS("set_height"),_SCS("get_height"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::INT,"range/z_min",PROPERTY_HINT_RANGE,itos(VS::CANVAS_ITEM_Z_MIN)+","+itos(VS::CANVAS_ITEM_Z_MAX)+",1"),_SCS("set_z_range_min"),_SCS("get_z_range_min"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::INT,"range/z_max",PROPERTY_HINT_RANGE,itos(VS::CANVAS_ITEM_Z_MIN)+","+itos(VS::CANVAS_ITEM_Z_MAX)+",1"),_SCS("set_z_range_max"),_SCS("get_z_range_max"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::INT,"range/layer_min",PROPERTY_HINT_RANGE,"-512,512,1"),_SCS("set_layer_range_min"),_SCS("get_layer_range_min"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::INT,"range/layer_max",PROPERTY_HINT_RANGE,"-512,512,1"),_SCS("set_layer_range_max"),_SCS("get_layer_range_max"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::INT,"range/item_mask",PROPERTY_HINT_ALL_FLAGS),_SCS("set_item_mask"),_SCS("get_item_mask"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"shadow/enabled"),_SCS("set_shadow_enabled"),_SCS("is_shadow_enabled"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::INT,"shadow/buffer_size",PROPERTY_HINT_RANGE,"32,16384,1"),_SCS("set_shadow_buffer_size"),_SCS("get_shadow_buffer_size"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"shadow/esm_multiplier",PROPERTY_HINT_RANGE,"1,4096,0.1"),_SCS("set_shadow_esm_multiplier"),_SCS("get_shadow_esm_multiplier"));
|
||||
|
||||
|
||||
}
|
||||
|
@ -258,6 +289,8 @@ Light2D::Light2D() {
|
|||
layer_max=0;
|
||||
item_mask=1;
|
||||
subtract_mode=false;
|
||||
shadow_buffer_size=2048;
|
||||
shadow_esm_multiplier=80;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,8 @@ private:
|
|||
int layer_min;
|
||||
int layer_max;
|
||||
int item_mask;
|
||||
int shadow_buffer_size;
|
||||
float shadow_esm_multiplier;
|
||||
bool subtract_mode;
|
||||
Ref<Texture> texture;
|
||||
Vector2 texture_offset;
|
||||
|
@ -68,6 +70,12 @@ public:
|
|||
void set_shadow_enabled( bool p_enabled);
|
||||
bool is_shadow_enabled() const;
|
||||
|
||||
void set_shadow_buffer_size( int p_size );
|
||||
int get_shadow_buffer_size() const;
|
||||
|
||||
void set_shadow_esm_multiplier( float p_multiplier);
|
||||
float get_shadow_esm_multiplier() const;
|
||||
|
||||
virtual Rect2 get_item_rect() const;
|
||||
|
||||
Light2D();
|
||||
|
|
|
@ -0,0 +1,201 @@
|
|||
#include "light_occluder_2d.h"
|
||||
|
||||
|
||||
void OccluderPolygon2D::set_polygon(const DVector<Vector2>& p_polygon) {
|
||||
|
||||
polygon=p_polygon;
|
||||
VS::get_singleton()->canvas_occluder_polygon_set_shape(occ_polygon,p_polygon,closed);
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
DVector<Vector2> OccluderPolygon2D::get_polygon() const{
|
||||
|
||||
return polygon;
|
||||
}
|
||||
|
||||
void OccluderPolygon2D::set_closed(bool p_closed) {
|
||||
|
||||
if (closed==p_closed)
|
||||
return;
|
||||
closed=p_closed;
|
||||
VS::get_singleton()->canvas_occluder_polygon_set_shape(occ_polygon,polygon,closed);
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
bool OccluderPolygon2D::is_closed() const{
|
||||
|
||||
return closed;
|
||||
}
|
||||
|
||||
void OccluderPolygon2D::set_cull_mode(CullMode p_mode){
|
||||
|
||||
cull=p_mode;
|
||||
VS::get_singleton()->canvas_occluder_polygon_set_cull_mode(occ_polygon,VS::CanvasOccluderPolygonCullMode(p_mode));
|
||||
}
|
||||
|
||||
OccluderPolygon2D::CullMode OccluderPolygon2D::get_cull_mode() const{
|
||||
|
||||
return cull;
|
||||
}
|
||||
|
||||
|
||||
RID OccluderPolygon2D::get_rid() const {
|
||||
|
||||
return occ_polygon;
|
||||
}
|
||||
|
||||
void OccluderPolygon2D::_bind_methods() {
|
||||
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_closed","closed"),&OccluderPolygon2D::set_closed);
|
||||
ObjectTypeDB::bind_method(_MD("is_closed"),&OccluderPolygon2D::is_closed);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_cull_mode","cull_mode"),&OccluderPolygon2D::set_cull_mode);
|
||||
ObjectTypeDB::bind_method(_MD("get_cull_mode"),&OccluderPolygon2D::get_cull_mode);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_polygon","polygon"),&OccluderPolygon2D::set_polygon);
|
||||
ObjectTypeDB::bind_method(_MD("get_polygon"),&OccluderPolygon2D::get_polygon);
|
||||
|
||||
ADD_PROPERTY( PropertyInfo(Variant::VECTOR2_ARRAY,"polygon"),_SCS("set_polygon"),_SCS("get_polygon"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"closed"),_SCS("set_closed"),_SCS("is_closed"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::INT,"cull_mode",PROPERTY_HINT_ENUM,"Disabled,ClockWise,CounterClockWise"),_SCS("set_cull_mode"),_SCS("get_cull_mode"));
|
||||
|
||||
BIND_CONSTANT(CULL_DISABLED);
|
||||
BIND_CONSTANT(CULL_CLOCKWISE);
|
||||
BIND_CONSTANT(CULL_COUNTER_CLOCKWISE);
|
||||
}
|
||||
|
||||
|
||||
OccluderPolygon2D::OccluderPolygon2D() {
|
||||
|
||||
occ_polygon=VS::get_singleton()->canvas_occluder_polygon_create();
|
||||
closed=true;
|
||||
cull=CULL_DISABLED;
|
||||
}
|
||||
|
||||
OccluderPolygon2D::~OccluderPolygon2D() {
|
||||
|
||||
VS::get_singleton()->free(occ_polygon);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
void LightOccluder2D::_poly_changed() {
|
||||
|
||||
update();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void LightOccluder2D::_notification(int p_what) {
|
||||
|
||||
if (p_what==NOTIFICATION_ENTER_CANVAS) {
|
||||
|
||||
VS::get_singleton()->canvas_light_occluder_attach_to_canvas(occluder,get_canvas());
|
||||
VS::get_singleton()->canvas_light_occluder_set_transform(occluder,get_global_transform());
|
||||
|
||||
}
|
||||
if (p_what==NOTIFICATION_TRANSFORM_CHANGED) {
|
||||
|
||||
VS::get_singleton()->canvas_light_occluder_set_transform(occluder,get_global_transform());
|
||||
}
|
||||
|
||||
if (p_what==NOTIFICATION_DRAW) {
|
||||
|
||||
if (get_tree()->is_editor_hint()) {
|
||||
|
||||
if (occluder_polygon.is_valid()) {
|
||||
|
||||
DVector<Vector2> poly = occluder_polygon->get_polygon();
|
||||
|
||||
if (poly.size()) {
|
||||
if (occluder_polygon->is_closed()) {
|
||||
Vector<Color> color;
|
||||
color.push_back(Color(0,0,0,0.6));
|
||||
draw_polygon(Variant(poly),color);
|
||||
} else {
|
||||
|
||||
int ps=poly.size();
|
||||
DVector<Vector2>::Read r = poly.read();
|
||||
for(int i=0;i<ps-1;i++) {
|
||||
|
||||
draw_line(r[i],r[i+1],Color(0,0,0,0.6),3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (p_what==NOTIFICATION_EXIT_CANVAS) {
|
||||
|
||||
VS::get_singleton()->canvas_light_occluder_attach_to_canvas(occluder,RID());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void LightOccluder2D::set_occluder_polygon(const Ref<OccluderPolygon2D>& p_polygon) {
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (occluder_polygon.is_valid())
|
||||
occluder_polygon->disconnect("changed",this,"_poly_changed");
|
||||
#endif
|
||||
occluder_polygon=p_polygon;
|
||||
|
||||
if (occluder_polygon.is_valid())
|
||||
VS::get_singleton()->canvas_light_occluder_set_polygon(occluder,occluder_polygon->get_rid());
|
||||
else
|
||||
VS::get_singleton()->canvas_light_occluder_set_polygon(occluder,RID());
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (occluder_polygon.is_valid())
|
||||
occluder_polygon->connect("changed",this,"_poly_changed");
|
||||
update();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
Ref<OccluderPolygon2D> LightOccluder2D::get_occluder_polygon() const {
|
||||
|
||||
return occluder_polygon;
|
||||
}
|
||||
|
||||
void LightOccluder2D::set_occluder_light_mask(int p_mask) {
|
||||
|
||||
mask=p_mask;
|
||||
VS::get_singleton()->canvas_light_occluder_set_light_mask(occluder,mask);
|
||||
}
|
||||
|
||||
int LightOccluder2D::get_occluder_light_mask() const{
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
void LightOccluder2D::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_occluder_polygon","polygon:OccluderPolygon2D"),&LightOccluder2D::set_occluder_polygon);
|
||||
ObjectTypeDB::bind_method(_MD("get_occluder_polygon:OccluderPolygon2D"),&LightOccluder2D::get_occluder_polygon);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_occluder_light_mask","mask"),&LightOccluder2D::set_occluder_light_mask);
|
||||
ObjectTypeDB::bind_method(_MD("get_occluder_light_mask"),&LightOccluder2D::get_occluder_light_mask);
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
ObjectTypeDB::bind_method("_poly_changed",&LightOccluder2D::_poly_changed);
|
||||
#endif
|
||||
|
||||
ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"occluder",PROPERTY_HINT_RESOURCE_TYPE,"OccluderPolygon2D"),_SCS("set_occluder_polygon"),_SCS("get_occluder_polygon"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::INT,"light_mask",PROPERTY_HINT_ALL_FLAGS),_SCS("set_occluder_light_mask"),_SCS("get_occluder_light_mask"));
|
||||
}
|
||||
|
||||
LightOccluder2D::LightOccluder2D() {
|
||||
|
||||
occluder=VS::get_singleton()->canvas_light_occluder_create();
|
||||
mask=1;
|
||||
}
|
||||
|
||||
LightOccluder2D::~LightOccluder2D() {
|
||||
|
||||
VS::get_singleton()->free(occluder);
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
#ifndef LIGHTOCCLUDER2D_H
|
||||
#define LIGHTOCCLUDER2D_H
|
||||
|
||||
#include "scene/2d/node_2d.h"
|
||||
|
||||
class OccluderPolygon2D : public Resource {
|
||||
|
||||
OBJ_TYPE(OccluderPolygon2D,Resource);
|
||||
public:
|
||||
|
||||
enum CullMode {
|
||||
CULL_DISABLED,
|
||||
CULL_CLOCKWISE,
|
||||
CULL_COUNTER_CLOCKWISE
|
||||
};
|
||||
private:
|
||||
|
||||
|
||||
RID occ_polygon;
|
||||
DVector<Vector2> polygon;
|
||||
bool closed;
|
||||
CullMode cull;
|
||||
|
||||
protected:
|
||||
|
||||
static void _bind_methods();
|
||||
public:
|
||||
|
||||
void set_polygon(const DVector<Vector2>& p_polygon);
|
||||
DVector<Vector2> get_polygon() const;
|
||||
|
||||
void set_closed(bool p_closed);
|
||||
bool is_closed() const;
|
||||
|
||||
void set_cull_mode(CullMode p_mode);
|
||||
CullMode get_cull_mode() const;
|
||||
|
||||
virtual RID get_rid() const;
|
||||
OccluderPolygon2D();
|
||||
~OccluderPolygon2D();
|
||||
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(OccluderPolygon2D::CullMode);
|
||||
|
||||
class LightOccluder2D : public Node2D {
|
||||
OBJ_TYPE(LightOccluder2D,Node2D);
|
||||
|
||||
RID occluder;
|
||||
bool enabled;
|
||||
int mask;
|
||||
Ref<OccluderPolygon2D> occluder_polygon;
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
void _poly_changed();
|
||||
#endif
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
public:
|
||||
|
||||
void set_occluder_polygon(const Ref<OccluderPolygon2D>& p_polygon);
|
||||
Ref<OccluderPolygon2D> get_occluder_polygon() const;
|
||||
|
||||
void set_occluder_light_mask(int p_mask);
|
||||
int get_occluder_light_mask() const;
|
||||
|
||||
LightOccluder2D();
|
||||
~LightOccluder2D();
|
||||
};
|
||||
|
||||
#endif // LIGHTOCCLUDER2D_H
|
|
@ -152,11 +152,11 @@ void Camera::_get_property_list( List<PropertyInfo> *p_list) const {
|
|||
|
||||
case PROJECTION_PERSPECTIVE: {
|
||||
|
||||
p_list->push_back( PropertyInfo( Variant::REAL, "fov" , PROPERTY_HINT_RANGE, "1,89,0.1",PROPERTY_USAGE_NOEDITOR) );
|
||||
p_list->push_back( PropertyInfo( Variant::REAL, "fov" , PROPERTY_HINT_RANGE, "1,179,0.1",PROPERTY_USAGE_NOEDITOR) );
|
||||
if (keep_aspect==KEEP_WIDTH)
|
||||
p_list->push_back( PropertyInfo( Variant::REAL, "fovx" , PROPERTY_HINT_RANGE, "1,89,0.1",PROPERTY_USAGE_EDITOR) );
|
||||
p_list->push_back( PropertyInfo( Variant::REAL, "fovx" , PROPERTY_HINT_RANGE, "1,179,0.1",PROPERTY_USAGE_EDITOR) );
|
||||
else
|
||||
p_list->push_back( PropertyInfo( Variant::REAL, "fovy" , PROPERTY_HINT_RANGE, "1,89,0.1",PROPERTY_USAGE_EDITOR) );
|
||||
p_list->push_back( PropertyInfo( Variant::REAL, "fovy" , PROPERTY_HINT_RANGE, "1,179,0.1",PROPERTY_USAGE_EDITOR) );
|
||||
|
||||
|
||||
} break;
|
||||
|
|
|
@ -310,6 +310,17 @@ int GeometryInstance::get_baked_light_texture_id() const{
|
|||
return baked_light_texture_id;
|
||||
}
|
||||
|
||||
void GeometryInstance::set_extra_cull_margin(float p_margin) {
|
||||
|
||||
ERR_FAIL_COND(p_margin<0);
|
||||
extra_cull_margin=p_margin;
|
||||
VS::get_singleton()->instance_set_extra_visibility_margin(get_instance(),extra_cull_margin);
|
||||
}
|
||||
|
||||
float GeometryInstance::get_extra_cull_margin() const{
|
||||
|
||||
return extra_cull_margin;
|
||||
}
|
||||
|
||||
void GeometryInstance::_bind_methods() {
|
||||
|
||||
|
@ -328,6 +339,9 @@ void GeometryInstance::_bind_methods() {
|
|||
ObjectTypeDB::bind_method(_MD("set_baked_light_texture_id","id"), &GeometryInstance::set_baked_light_texture_id);
|
||||
ObjectTypeDB::bind_method(_MD("get_baked_light_texture_id"), &GeometryInstance::get_baked_light_texture_id);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_extra_cull_margin","margin"), &GeometryInstance::set_extra_cull_margin);
|
||||
ObjectTypeDB::bind_method(_MD("get_extra_cull_margin"), &GeometryInstance::get_extra_cull_margin);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("_baked_light_changed"), &GeometryInstance::_baked_light_changed);
|
||||
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "geometry/visible"), _SCS("set_flag"), _SCS("get_flag"),FLAG_VISIBLE);
|
||||
|
@ -336,6 +350,7 @@ void GeometryInstance::_bind_methods() {
|
|||
ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "geometry/receive_shadows"), _SCS("set_flag"), _SCS("get_flag"),FLAG_RECEIVE_SHADOWS);
|
||||
ADD_PROPERTY( PropertyInfo( Variant::INT, "geometry/range_begin",PROPERTY_HINT_RANGE,"0,32768,0.01"), _SCS("set_draw_range_begin"), _SCS("get_draw_range_begin"));
|
||||
ADD_PROPERTY( PropertyInfo( Variant::INT, "geometry/range_end",PROPERTY_HINT_RANGE,"0,32768,0.01"), _SCS("set_draw_range_end"), _SCS("get_draw_range_end"));
|
||||
ADD_PROPERTY( PropertyInfo( Variant::REAL, "geometry/extra_cull_margin",PROPERTY_HINT_RANGE,"0,16384,0"), _SCS("set_extra_cull_margin"), _SCS("get_extra_cull_margin"));
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "geometry/billboard"), _SCS("set_flag"), _SCS("get_flag"),FLAG_BILLBOARD);
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "geometry/billboard_y"), _SCS("set_flag"), _SCS("get_flag"),FLAG_BILLBOARD_FIX_Y);
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "geometry/depth_scale"), _SCS("set_flag"), _SCS("get_flag"),FLAG_DEPH_SCALE);
|
||||
|
|
|
@ -108,6 +108,7 @@ private:
|
|||
void _find_baked_light();
|
||||
BakedLightInstance *baked_light_instance;
|
||||
int baked_light_texture_id;
|
||||
float extra_cull_margin;
|
||||
|
||||
void _baked_light_changed();
|
||||
void _update_visibility();
|
||||
|
@ -132,6 +133,9 @@ public:
|
|||
void set_baked_light_texture_id(int p_id);
|
||||
int get_baked_light_texture_id() const;
|
||||
|
||||
void set_extra_cull_margin(float p_margin);
|
||||
float get_extra_cull_margin() const;
|
||||
|
||||
GeometryInstance();
|
||||
};
|
||||
|
||||
|
|
|
@ -80,6 +80,7 @@
|
|||
#include "scene/2d/particles_2d.h"
|
||||
#include "scene/2d/path_2d.h"
|
||||
#include "scene/2d/light_2d.h"
|
||||
#include "scene/2d/light_occluder_2d.h"
|
||||
|
||||
#include "scene/2d/canvas_item.h"
|
||||
#include "scene/2d/sprite.h"
|
||||
|
@ -454,6 +455,7 @@ void register_scene_types() {
|
|||
//ObjectTypeDB::set_type_enabled("BodyVolumeCylinder",false);
|
||||
//ObjectTypeDB::set_type_enabled("BodyVolumeConvexPolygon",false);
|
||||
|
||||
ObjectTypeDB::register_type<CanvasItemMaterial>();
|
||||
ObjectTypeDB::register_virtual_type<CanvasItem>();
|
||||
ObjectTypeDB::register_type<Node2D>();
|
||||
ObjectTypeDB::register_type<Particles2D>();
|
||||
|
@ -476,6 +478,8 @@ void register_scene_types() {
|
|||
ObjectTypeDB::register_type<VisibilityEnabler2D>();
|
||||
ObjectTypeDB::register_type<Polygon2D>();
|
||||
ObjectTypeDB::register_type<Light2D>();
|
||||
ObjectTypeDB::register_type<LightOccluder2D>();
|
||||
ObjectTypeDB::register_type<OccluderPolygon2D>();
|
||||
ObjectTypeDB::register_type<YSort>();
|
||||
|
||||
ObjectTypeDB::set_type_enabled("CollisionShape2D",false);
|
||||
|
|
|
@ -41,6 +41,7 @@ SceneStringNames::SceneStringNames() {
|
|||
visibility_changed=StaticCString::create("visibility_changed");
|
||||
input_event=StaticCString::create("input_event");
|
||||
shader_shader=StaticCString::create("shader/shader");
|
||||
shader_unshaded=StaticCString::create("shader/unshaded");
|
||||
enter_tree=StaticCString::create("enter_tree");
|
||||
exit_tree=StaticCString::create("exit_tree");
|
||||
item_rect_changed=StaticCString::create("item_rect_changed");
|
||||
|
|
|
@ -56,6 +56,7 @@ public:
|
|||
StringName _input_event;
|
||||
StringName item_rect_changed;
|
||||
StringName shader_shader;
|
||||
StringName shader_unshaded;
|
||||
StringName enter_tree;
|
||||
StringName exit_tree;
|
||||
StringName size_flags_changed;
|
||||
|
|
|
@ -572,8 +572,8 @@ public:
|
|||
struct CanvasLight {
|
||||
|
||||
|
||||
|
||||
bool enabled;
|
||||
bool shadow;
|
||||
Color color;
|
||||
Matrix32 xform;
|
||||
float height;
|
||||
|
@ -586,21 +586,26 @@ public:
|
|||
RID texture;
|
||||
Vector2 texture_offset;
|
||||
RID canvas;
|
||||
RID shadow_buffer;
|
||||
int shadow_buffer_size;
|
||||
float shadow_esm_mult;
|
||||
|
||||
|
||||
void *texture_cache; // implementation dependent
|
||||
Rect2 rect_cache;
|
||||
Matrix32 xform_cache;
|
||||
float radius_cache; //used for shadow far plane
|
||||
CameraMatrix shadow_matrix_cache;
|
||||
|
||||
Matrix32 light_shader_xform;
|
||||
Vector2 light_shader_pos;
|
||||
|
||||
CanvasLight *shadows_next_ptr;
|
||||
CanvasLight *filter_next_ptr;
|
||||
CanvasLight *next_ptr;
|
||||
|
||||
CanvasLight() {
|
||||
enabled=true;
|
||||
shadow=false;
|
||||
enabled=true;
|
||||
color=Color(1,1,1);
|
||||
height=0;
|
||||
z_min=-1024;
|
||||
|
@ -612,9 +617,24 @@ public:
|
|||
texture_cache=NULL;
|
||||
next_ptr=NULL;
|
||||
filter_next_ptr=NULL;
|
||||
shadow_buffer_size=2048;
|
||||
shadow_esm_mult=80;
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
struct CanvasItem;
|
||||
|
||||
struct CanvasItemMaterial {
|
||||
|
||||
RID shader;
|
||||
Map<StringName,Variant> shader_param;
|
||||
uint32_t shader_version;
|
||||
Set<CanvasItem*> owners;
|
||||
bool unshaded;
|
||||
|
||||
CanvasItemMaterial() {unshaded=false; shader_version=0; }
|
||||
};
|
||||
|
||||
struct CanvasItem {
|
||||
|
||||
|
@ -744,16 +764,14 @@ public:
|
|||
mutable bool rect_dirty;
|
||||
mutable Rect2 rect;
|
||||
CanvasItem*next;
|
||||
RID shader;
|
||||
Map<StringName,Variant> shader_param;
|
||||
uint32_t shader_version;
|
||||
CanvasItemMaterial* material;
|
||||
|
||||
|
||||
float final_opacity;
|
||||
Matrix32 final_transform;
|
||||
Rect2 final_clip_rect;
|
||||
CanvasItem* final_clip_owner;
|
||||
CanvasItem* shader_owner;
|
||||
CanvasItem* material_owner;
|
||||
ViewportRender *vp_render;
|
||||
|
||||
Rect2 global_rect_cache;
|
||||
|
@ -881,8 +899,8 @@ public:
|
|||
return rect;
|
||||
}
|
||||
|
||||
void clear() { for (int i=0;i<commands.size();i++) memdelete( commands[i] ); commands.clear(); clip=false; rect_dirty=true; final_clip_owner=NULL; shader_owner=NULL;}
|
||||
CanvasItem() { light_mask=1; vp_render=NULL; next=NULL; final_clip_owner=NULL; clip=false; final_opacity=1; blend_mode=VS::MATERIAL_BLEND_MODE_MIX; visible=true; rect_dirty=true; custom_rect=false; ontop=true; shader_version=0; shader_owner=NULL;}
|
||||
void clear() { for (int i=0;i<commands.size();i++) memdelete( commands[i] ); commands.clear(); clip=false; rect_dirty=true; final_clip_owner=NULL; material_owner=NULL;}
|
||||
CanvasItem() { light_mask=1; vp_render=NULL; next=NULL; final_clip_owner=NULL; clip=false; final_opacity=1; blend_mode=VS::MATERIAL_BLEND_MODE_MIX; visible=true; rect_dirty=true; custom_rect=false; ontop=true; material_owner=NULL; material=NULL; }
|
||||
virtual ~CanvasItem() { clear(); }
|
||||
};
|
||||
|
||||
|
@ -905,7 +923,36 @@ public:
|
|||
virtual void canvas_set_transform(const Matrix32& p_transform)=0;
|
||||
|
||||
virtual void canvas_render_items(CanvasItem *p_item_list,int p_z,const Color& p_modulate,CanvasLight *p_light)=0;
|
||||
virtual void canvas_debug_viewport_shadows(CanvasLight* p_lights_with_shadow)=0;
|
||||
/* LIGHT SHADOW MAPPING */
|
||||
|
||||
virtual RID canvas_light_occluder_create()=0;
|
||||
virtual void canvas_light_occluder_set_polylines(RID p_occluder, const DVector<Vector2>& p_lines)=0;
|
||||
|
||||
|
||||
virtual RID canvas_light_shadow_buffer_create(int p_width)=0;
|
||||
|
||||
struct CanvasLightOccluderInstance {
|
||||
|
||||
|
||||
bool enabled;
|
||||
RID canvas;
|
||||
RID polygon;
|
||||
RID polygon_buffer;
|
||||
Rect2 aabb_cache;
|
||||
Matrix32 xform;
|
||||
Matrix32 xform_cache;
|
||||
int light_mask;
|
||||
VS::CanvasOccluderPolygonCullMode cull_cache;
|
||||
|
||||
CanvasLightOccluderInstance *next;
|
||||
|
||||
CanvasLightOccluderInstance() { enabled=true; next=NULL; light_mask=1; cull_cache=VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
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)=0;
|
||||
|
||||
/* ENVIRONMENT */
|
||||
|
||||
|
@ -945,6 +992,8 @@ public:
|
|||
virtual bool is_environment(const RID& p_rid) const=0;
|
||||
virtual bool is_shader(const RID& p_rid) const=0;
|
||||
|
||||
virtual bool is_canvas_light_occluder(const RID& p_rid) const=0;
|
||||
|
||||
virtual void free(const RID& p_rid)=0;
|
||||
|
||||
virtual void init()=0;
|
||||
|
|
|
@ -3765,55 +3765,32 @@ void VisualServerRaster::canvas_item_set_z_as_relative_to_parent(RID p_item, boo
|
|||
|
||||
}
|
||||
|
||||
void VisualServerRaster::canvas_item_set_use_parent_shader(RID p_item, bool p_enable) {
|
||||
void VisualServerRaster::canvas_item_set_use_parent_material(RID p_item, bool p_enable) {
|
||||
|
||||
VS_CHANGED;
|
||||
CanvasItem *canvas_item = canvas_item_owner.get( p_item );
|
||||
ERR_FAIL_COND(!canvas_item);
|
||||
canvas_item->use_parent_shader=p_enable;
|
||||
canvas_item->use_parent_material=p_enable;
|
||||
|
||||
}
|
||||
|
||||
void VisualServerRaster::canvas_item_set_shader(RID p_item, RID p_shader) {
|
||||
void VisualServerRaster::canvas_item_set_material(RID p_item, RID p_material) {
|
||||
|
||||
VS_CHANGED;
|
||||
CanvasItem *canvas_item = canvas_item_owner.get( p_item );
|
||||
ERR_FAIL_COND(!canvas_item);
|
||||
canvas_item->shader=p_shader;
|
||||
}
|
||||
|
||||
RID VisualServerRaster::canvas_item_get_shader(RID p_item) const{
|
||||
if (canvas_item->material)
|
||||
canvas_item->material->owners.erase(canvas_item);
|
||||
|
||||
CanvasItem *canvas_item = canvas_item_owner.get( p_item );
|
||||
ERR_FAIL_COND_V(!canvas_item,RID());
|
||||
return canvas_item->shader;
|
||||
canvas_item->material=NULL;
|
||||
|
||||
}
|
||||
|
||||
void VisualServerRaster::canvas_item_set_shader_param(RID p_canvas_item, const StringName& p_param, const Variant& p_value){
|
||||
|
||||
VS_CHANGED;
|
||||
CanvasItem *canvas_item = canvas_item_owner.get( p_canvas_item );
|
||||
ERR_FAIL_COND(!canvas_item);
|
||||
if (p_value.get_type()==Variant::NIL)
|
||||
canvas_item->shader_param.erase(p_param);
|
||||
else
|
||||
canvas_item->shader_param[p_param]=p_value;
|
||||
|
||||
}
|
||||
Variant VisualServerRaster::canvas_item_get_shader_param(RID p_canvas_item, const StringName& p_param) const{
|
||||
|
||||
CanvasItem *canvas_item = canvas_item_owner.get( p_canvas_item );
|
||||
ERR_FAIL_COND_V(!canvas_item,Variant());
|
||||
if (!canvas_item->shader_param.has(p_param)) {
|
||||
ERR_FAIL_COND_V(!canvas_item->shader.is_valid(),Variant());
|
||||
return rasterizer->shader_get_default_param(canvas_item->shader,p_param);
|
||||
if (canvas_item_material_owner.owns(p_material)) {
|
||||
canvas_item->material=canvas_item_material_owner.get(p_material);
|
||||
canvas_item->material->owners.insert(canvas_item);
|
||||
}
|
||||
|
||||
return canvas_item->shader_param[p_param];
|
||||
}
|
||||
|
||||
|
||||
void VisualServerRaster::canvas_item_set_sort_children_by_y(RID p_item, bool p_enable) {
|
||||
|
||||
VS_CHANGED;
|
||||
|
@ -3989,19 +3966,41 @@ void VisualServerRaster::canvas_light_set_shadow_enabled(RID p_light, bool p_ena
|
|||
|
||||
Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light);
|
||||
ERR_FAIL_COND(!clight);
|
||||
clight->shadow=p_enabled;
|
||||
|
||||
if (clight->shadow_buffer.is_valid()==p_enabled)
|
||||
return;
|
||||
if (p_enabled) {
|
||||
clight->shadow_buffer=rasterizer->canvas_light_shadow_buffer_create(clight->shadow_buffer_size);
|
||||
} else {
|
||||
rasterizer->free(clight->shadow_buffer);
|
||||
clight->shadow_buffer=RID();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void VisualServerRaster::canvas_light_set_shadow_buffer_size(RID p_light, int p_size){
|
||||
|
||||
Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light);
|
||||
ERR_FAIL_COND(!clight);
|
||||
|
||||
ERR_FAIL_COND(p_size<32 || p_size>16384);
|
||||
|
||||
clight->shadow_buffer_size=nearest_power_of_2(p_size);
|
||||
|
||||
|
||||
if (clight->shadow_buffer.is_valid()) {
|
||||
rasterizer->free(clight->shadow_buffer);
|
||||
clight->shadow_buffer=rasterizer->canvas_light_shadow_buffer_create(clight->shadow_buffer_size);
|
||||
}
|
||||
|
||||
}
|
||||
void VisualServerRaster::canvas_light_set_shadow_filter(RID p_light, int p_size){
|
||||
|
||||
void VisualServerRaster::canvas_light_set_shadow_esm_multiplier(RID p_light, float p_multiplier) {
|
||||
|
||||
Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light);
|
||||
ERR_FAIL_COND(!clight);
|
||||
clight->shadow_esm_mult=p_multiplier;
|
||||
|
||||
}
|
||||
|
||||
|
@ -4009,26 +4008,217 @@ void VisualServerRaster::canvas_light_set_shadow_filter(RID p_light, int p_size)
|
|||
|
||||
RID VisualServerRaster::canvas_light_occluder_create() {
|
||||
|
||||
return RID();
|
||||
Rasterizer::CanvasLightOccluderInstance *occluder = memnew( Rasterizer::CanvasLightOccluderInstance );
|
||||
|
||||
return canvas_light_occluder_owner.make_rid( occluder );
|
||||
|
||||
}
|
||||
|
||||
void VisualServerRaster::canvas_light_occluder_attach_to_canvas(RID p_occluder,RID p_canvas) {
|
||||
|
||||
Rasterizer::CanvasLightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder);
|
||||
ERR_FAIL_COND(!occluder);
|
||||
|
||||
if (occluder->canvas.is_valid()) {
|
||||
|
||||
Canvas *canvas = canvas_owner.get(occluder->canvas);
|
||||
canvas->occluders.erase(occluder);
|
||||
}
|
||||
|
||||
if (!canvas_owner.owns(p_canvas))
|
||||
p_canvas=RID();
|
||||
|
||||
occluder->canvas=p_canvas;
|
||||
|
||||
if (occluder->canvas.is_valid()) {
|
||||
|
||||
Canvas *canvas = canvas_owner.get(occluder->canvas);
|
||||
canvas->occluders.insert(occluder);
|
||||
}
|
||||
}
|
||||
|
||||
void VisualServerRaster::canvas_light_occluder_set_enabled(RID p_occluder,bool p_enabled){
|
||||
|
||||
Rasterizer::CanvasLightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder);
|
||||
ERR_FAIL_COND(!occluder);
|
||||
|
||||
occluder->enabled=p_enabled;
|
||||
|
||||
}
|
||||
|
||||
void VisualServerRaster::canvas_light_occluder_set_shape(RID p_occluder,const DVector<Vector2>& p_shape){
|
||||
void VisualServerRaster::canvas_light_occluder_set_polygon(RID p_occluder,RID p_polygon) {
|
||||
|
||||
Rasterizer::CanvasLightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder);
|
||||
ERR_FAIL_COND(!occluder);
|
||||
|
||||
if (occluder->polygon.is_valid()) {
|
||||
CanvasLightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get(p_polygon);
|
||||
if (occluder_poly) {
|
||||
occluder_poly->owners.erase(occluder);
|
||||
}
|
||||
}
|
||||
|
||||
occluder->polygon=p_polygon;
|
||||
occluder->polygon_buffer=RID();
|
||||
|
||||
if (occluder->polygon.is_valid()) {
|
||||
CanvasLightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get(p_polygon);
|
||||
if (!occluder_poly)
|
||||
occluder->polygon=RID();
|
||||
ERR_FAIL_COND(!occluder_poly);
|
||||
occluder_poly->owners.insert(occluder);
|
||||
occluder->polygon_buffer=occluder_poly->occluder;
|
||||
occluder->aabb_cache=occluder_poly->aabb;
|
||||
occluder->cull_cache=occluder_poly->cull_mode;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void VisualServerRaster::canvas_light_occluder_set_transform(RID p_occluder,const Matrix32& p_xform) {
|
||||
|
||||
Rasterizer::CanvasLightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder);
|
||||
ERR_FAIL_COND(!occluder);
|
||||
|
||||
occluder->xform=p_xform;
|
||||
|
||||
}
|
||||
|
||||
void VisualServerRaster::canvas_light_occluder_set_light_mask(RID p_occluder,int p_mask) {
|
||||
|
||||
Rasterizer::CanvasLightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder);
|
||||
ERR_FAIL_COND(!occluder);
|
||||
|
||||
occluder->light_mask=p_mask;
|
||||
|
||||
}
|
||||
|
||||
|
||||
RID VisualServerRaster::canvas_occluder_polygon_create() {
|
||||
|
||||
CanvasLightOccluderPolygon * occluder_poly = memnew( CanvasLightOccluderPolygon );
|
||||
occluder_poly->occluder=rasterizer->canvas_light_occluder_create();
|
||||
return canvas_light_occluder_polygon_owner.make_rid(occluder_poly);
|
||||
|
||||
}
|
||||
|
||||
void VisualServerRaster::canvas_occluder_polygon_set_shape(RID p_occluder_polygon, const DVector<Vector2>& p_shape, bool p_close){
|
||||
|
||||
if (p_shape.size()<3) {
|
||||
canvas_occluder_polygon_set_shape_as_lines(p_occluder_polygon,p_shape);
|
||||
return;
|
||||
}
|
||||
|
||||
DVector<Vector2> lines;
|
||||
int lc = p_shape.size()*2;
|
||||
|
||||
lines.resize(lc-(p_close?0:2));
|
||||
{
|
||||
DVector<Vector2>::Write w = lines.write();
|
||||
DVector<Vector2>::Read r = p_shape.read();
|
||||
|
||||
int max=lc/2;
|
||||
if (!p_close) {
|
||||
max--;
|
||||
}
|
||||
for(int i=0;i<max;i++) {
|
||||
|
||||
Vector2 a = r[i];
|
||||
Vector2 b = r[(i+1)%(lc/2)];
|
||||
w[i*2+0]=a;
|
||||
w[i*2+1]=b;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
canvas_occluder_polygon_set_shape_as_lines(p_occluder_polygon,lines);
|
||||
}
|
||||
|
||||
void VisualServerRaster::canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon,const DVector<Vector2>& p_shape) {
|
||||
|
||||
CanvasLightOccluderPolygon * occluder_poly = canvas_light_occluder_polygon_owner.get(p_occluder_polygon);
|
||||
ERR_FAIL_COND(!occluder_poly);
|
||||
ERR_FAIL_COND(p_shape.size()&1);
|
||||
|
||||
int lc = p_shape.size();
|
||||
occluder_poly->aabb=Rect2();
|
||||
{
|
||||
DVector<Vector2>::Read r = p_shape.read();
|
||||
for(int i=0;i<lc;i++) {
|
||||
if (i==0)
|
||||
occluder_poly->aabb.pos=r[i];
|
||||
else
|
||||
occluder_poly->aabb.expand_to(r[i]);
|
||||
}
|
||||
}
|
||||
|
||||
rasterizer->canvas_light_occluder_set_polylines(occluder_poly->occluder,p_shape);
|
||||
for( Set<Rasterizer::CanvasLightOccluderInstance*>::Element *E=occluder_poly->owners.front();E;E=E->next()) {
|
||||
E->get()->aabb_cache=occluder_poly->aabb;
|
||||
}
|
||||
}
|
||||
|
||||
void VisualServerRaster::canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon,CanvasOccluderPolygonCullMode p_mode) {
|
||||
|
||||
CanvasLightOccluderPolygon * occluder_poly = canvas_light_occluder_polygon_owner.get(p_occluder_polygon);
|
||||
ERR_FAIL_COND(!occluder_poly);
|
||||
occluder_poly->cull_mode=p_mode;
|
||||
for( Set<Rasterizer::CanvasLightOccluderInstance*>::Element *E=occluder_poly->owners.front();E;E=E->next()) {
|
||||
E->get()->cull_cache=p_mode;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
RID VisualServerRaster::canvas_item_material_create() {
|
||||
|
||||
Rasterizer::CanvasItemMaterial *material = memnew( Rasterizer::CanvasItemMaterial );
|
||||
return canvas_item_material_owner.make_rid(material);
|
||||
|
||||
}
|
||||
|
||||
void VisualServerRaster::canvas_item_material_set_shader(RID p_material, RID p_shader){
|
||||
|
||||
VS_CHANGED;
|
||||
Rasterizer::CanvasItemMaterial *material = canvas_item_material_owner.get( p_material );
|
||||
ERR_FAIL_COND(!material);
|
||||
material->shader=p_shader;
|
||||
|
||||
}
|
||||
void VisualServerRaster::canvas_item_material_set_shader_param(RID p_material, const StringName& p_param, const Variant& p_value){
|
||||
|
||||
VS_CHANGED;
|
||||
Rasterizer::CanvasItemMaterial *material = canvas_item_material_owner.get( p_material );
|
||||
ERR_FAIL_COND(!material);
|
||||
if (p_value.get_type()==Variant::NIL)
|
||||
material->shader_param.erase(p_param);
|
||||
else
|
||||
material->shader_param[p_param]=p_value;
|
||||
|
||||
|
||||
}
|
||||
Variant VisualServerRaster::canvas_item_material_get_shader_param(RID p_material, const StringName& p_param) const{
|
||||
Rasterizer::CanvasItemMaterial *material = canvas_item_material_owner.get( p_material );
|
||||
ERR_FAIL_COND_V(!material,Variant());
|
||||
if (!material->shader_param.has(p_param)) {
|
||||
ERR_FAIL_COND_V(!material->shader.is_valid(),Variant());
|
||||
return rasterizer->shader_get_default_param(material->shader,p_param);
|
||||
}
|
||||
|
||||
return material->shader_param[p_param];
|
||||
}
|
||||
|
||||
void VisualServerRaster::canvas_item_material_set_unshaded(RID p_material, bool p_unshaded){
|
||||
|
||||
VS_CHANGED;
|
||||
Rasterizer::CanvasItemMaterial *material = canvas_item_material_owner.get( p_material );
|
||||
ERR_FAIL_COND(!material);
|
||||
material->unshaded=p_unshaded;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/******** CANVAS *********/
|
||||
|
||||
|
||||
|
@ -4285,6 +4475,10 @@ void VisualServerRaster::free( RID p_rid ) {
|
|||
E->get()->canvas=RID();
|
||||
}
|
||||
|
||||
for (Set<Rasterizer::CanvasLightOccluderInstance*>::Element *E=canvas->occluders.front();E;E=E->next()) {
|
||||
|
||||
E->get()->canvas=RID();
|
||||
}
|
||||
|
||||
canvas_owner.free( p_rid );
|
||||
|
||||
|
@ -4314,10 +4508,26 @@ void VisualServerRaster::free( RID p_rid ) {
|
|||
canvas_item->child_items[i]->parent=RID();
|
||||
}
|
||||
|
||||
if (canvas_item->material) {
|
||||
canvas_item->material->owners.erase(canvas_item);
|
||||
}
|
||||
|
||||
canvas_item_owner.free( p_rid );
|
||||
|
||||
memdelete( canvas_item );
|
||||
|
||||
} else if (canvas_item_material_owner.owns(p_rid)) {
|
||||
|
||||
Rasterizer::CanvasItemMaterial *material = canvas_item_material_owner.get(p_rid);
|
||||
ERR_FAIL_COND(!material);
|
||||
for(Set<Rasterizer::CanvasItem*>::Element *E=material->owners.front();E;E=E->next()) {
|
||||
|
||||
E->get()->material=NULL;
|
||||
}
|
||||
|
||||
canvas_item_material_owner.free(p_rid);
|
||||
memdelete(material);
|
||||
|
||||
} else if (canvas_light_owner.owns(p_rid)) {
|
||||
|
||||
Rasterizer::CanvasLight *canvas_light = canvas_light_owner.get(p_rid);
|
||||
|
@ -4329,9 +4539,44 @@ void VisualServerRaster::free( RID p_rid ) {
|
|||
canvas->lights.erase(canvas_light);
|
||||
}
|
||||
|
||||
if (canvas_light->shadow_buffer.is_valid())
|
||||
rasterizer->free(canvas_light->shadow_buffer);
|
||||
|
||||
canvas_light_owner.free( p_rid );
|
||||
memdelete( canvas_light );
|
||||
|
||||
} else if (canvas_light_occluder_owner.owns(p_rid)) {
|
||||
|
||||
Rasterizer::CanvasLightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_rid);
|
||||
ERR_FAIL_COND(!occluder);
|
||||
|
||||
if (occluder->polygon.is_valid()) {
|
||||
|
||||
CanvasLightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get(occluder->polygon);
|
||||
if (occluder_poly) {
|
||||
occluder_poly->owners.erase(occluder);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
canvas_light_occluder_owner.free( p_rid );
|
||||
memdelete(occluder);
|
||||
|
||||
} else if (canvas_light_occluder_polygon_owner.owns(p_rid)) {
|
||||
|
||||
CanvasLightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get(p_rid);
|
||||
ERR_FAIL_COND(!occluder_poly);
|
||||
rasterizer->free(occluder_poly->occluder);
|
||||
|
||||
while(occluder_poly->owners.size()) {
|
||||
|
||||
occluder_poly->owners.front()->get()->polygon=RID();
|
||||
occluder_poly->owners.erase( occluder_poly->owners.front() );
|
||||
}
|
||||
|
||||
canvas_light_occluder_polygon_owner.free( p_rid );
|
||||
memdelete(occluder_poly);
|
||||
|
||||
} else if (scenario_owner.owns(p_rid)) {
|
||||
|
||||
Scenario *scenario=scenario_owner.get(p_rid);
|
||||
|
@ -6410,7 +6655,7 @@ void VisualServerRaster::_render_canvas_item_viewport(VisualServer* p_self,void
|
|||
|
||||
}
|
||||
|
||||
void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Matrix32& p_transform,const Rect2& p_clip_rect, float p_opacity,int p_z,Rasterizer::CanvasItem **z_list,Rasterizer::CanvasItem **z_last_list,CanvasItem *p_canvas_clip,CanvasItem *p_shader_owner) {
|
||||
void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Matrix32& p_transform,const Rect2& p_clip_rect, float p_opacity,int p_z,Rasterizer::CanvasItem **z_list,Rasterizer::CanvasItem **z_last_list,CanvasItem *p_canvas_clip,CanvasItem *p_material_owner) {
|
||||
|
||||
CanvasItem *ci = p_canvas_item;
|
||||
|
||||
|
@ -6455,11 +6700,11 @@ void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Mat
|
|||
ci->vp_render=NULL;
|
||||
}
|
||||
|
||||
if (ci->use_parent_shader && p_shader_owner)
|
||||
ci->shader_owner=p_shader_owner;
|
||||
if (ci->use_parent_material && p_material_owner)
|
||||
ci->material_owner=p_material_owner;
|
||||
else {
|
||||
p_shader_owner=ci;
|
||||
ci->shader_owner=NULL;
|
||||
p_material_owner=ci;
|
||||
ci->material_owner=NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -6493,7 +6738,7 @@ void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Mat
|
|||
|
||||
if (child_items[i]->ontop)
|
||||
continue;
|
||||
_render_canvas_item(child_items[i],xform,p_clip_rect,opacity,p_z,z_list,z_last_list,(CanvasItem*)ci->final_clip_owner,p_shader_owner);
|
||||
_render_canvas_item(child_items[i],xform,p_clip_rect,opacity,p_z,z_list,z_last_list,(CanvasItem*)ci->final_clip_owner,p_material_owner);
|
||||
}
|
||||
|
||||
|
||||
|
@ -6524,7 +6769,7 @@ void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Mat
|
|||
|
||||
if (!child_items[i]->ontop)
|
||||
continue;
|
||||
_render_canvas_item(child_items[i],xform,p_clip_rect,opacity,p_z,z_list,z_last_list,(CanvasItem*)ci->final_clip_owner,p_shader_owner);
|
||||
_render_canvas_item(child_items[i],xform,p_clip_rect,opacity,p_z,z_list,z_last_list,(CanvasItem*)ci->final_clip_owner,p_material_owner);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -6658,6 +6903,8 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_
|
|||
|
||||
Rect2 clip_rect(0,0,viewport_rect.width,viewport_rect.height);
|
||||
Rasterizer::CanvasLight *lights=NULL;
|
||||
Rasterizer::CanvasLight *lights_with_shadow=NULL;
|
||||
Rect2 shadow_rect;
|
||||
|
||||
for (Map<RID,Viewport::CanvasData>::Element *E=p_viewport->canvas_map.front();E;E=E->next()) {
|
||||
|
||||
|
@ -6676,6 +6923,7 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_
|
|||
cl->rect_cache=Rect2(-offset+cl->texture_offset,tsize);
|
||||
cl->xform_cache=xf * cl->xform;
|
||||
|
||||
|
||||
if (clip_rect.intersects_transformed(cl->xform_cache,cl->rect_cache)) {
|
||||
cl->filter_next_ptr=lights;
|
||||
lights=cl;
|
||||
|
@ -6685,11 +6933,18 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_
|
|||
scale.elements[2]=cl->rect_cache.pos;
|
||||
cl->light_shader_xform = (cl->xform_cache * scale).affine_inverse();
|
||||
cl->light_shader_pos=cl->xform_cache[2];
|
||||
if (cl->shadow_buffer.is_valid()) {
|
||||
cl->shadows_next_ptr=lights_with_shadow;
|
||||
if (lights_with_shadow==NULL) {
|
||||
shadow_rect = cl->xform_cache.xform(cl->rect_cache);
|
||||
} else {
|
||||
shadow_rect=shadow_rect.merge( cl->xform_cache.xform(cl->rect_cache) );
|
||||
}
|
||||
lights_with_shadow=cl;
|
||||
cl->radius_cache=cl->rect_cache.size.length();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6697,6 +6952,38 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_
|
|||
|
||||
}
|
||||
|
||||
if (lights_with_shadow) {
|
||||
//update shadows if any
|
||||
|
||||
Rasterizer::CanvasLightOccluderInstance * occluders=NULL;
|
||||
|
||||
//make list of occluders
|
||||
for (Map<RID,Viewport::CanvasData>::Element *E=p_viewport->canvas_map.front();E;E=E->next()) {
|
||||
|
||||
Matrix32 xf = p_viewport->global_transform * E->get().transform;
|
||||
|
||||
for(Set<Rasterizer::CanvasLightOccluderInstance*>::Element *F=E->get().canvas->occluders.front();F;F=F->next()) {
|
||||
|
||||
F->get()->xform_cache = xf * F->get()->xform;
|
||||
if (shadow_rect.intersects_transformed(F->get()->xform_cache,F->get()->aabb_cache)) {
|
||||
|
||||
F->get()->next=occluders;
|
||||
occluders=F->get();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
//update the light shadowmaps with them
|
||||
Rasterizer::CanvasLight *light=lights_with_shadow;
|
||||
while(light) {
|
||||
|
||||
rasterizer->canvas_light_shadow_buffer_update(light->shadow_buffer,light->xform_cache.affine_inverse(),light->item_mask,light->radius_cache/1000.0,light->radius_cache*1.1,occluders,&light->shadow_matrix_cache);
|
||||
light=light->shadows_next_ptr;
|
||||
}
|
||||
|
||||
rasterizer->set_viewport(viewport_rect); //must reset viewport afterwards
|
||||
}
|
||||
|
||||
for (Map<Viewport::CanvasKey,Viewport::CanvasData*>::Element *E=canvas_map.front();E;E=E->next()) {
|
||||
|
||||
|
||||
|
@ -6719,6 +7006,8 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_
|
|||
i++;
|
||||
|
||||
}
|
||||
|
||||
rasterizer->canvas_debug_viewport_shadows(lights_with_shadow);
|
||||
}
|
||||
|
||||
//capture
|
||||
|
|
|
@ -371,7 +371,7 @@ class VisualServerRaster : public VisualServer {
|
|||
|
||||
|
||||
|
||||
|
||||
mutable RID_Owner<Rasterizer::CanvasItemMaterial> canvas_item_material_owner;
|
||||
|
||||
struct CanvasItem : public Rasterizer::CanvasItem {
|
||||
|
||||
|
@ -384,7 +384,7 @@ class VisualServerRaster : public VisualServer {
|
|||
bool sort_y;
|
||||
float opacity;
|
||||
float self_opacity;
|
||||
bool use_parent_shader;
|
||||
bool use_parent_material;
|
||||
|
||||
|
||||
Vector<CanvasItem*> child_items;
|
||||
|
@ -396,7 +396,7 @@ class VisualServerRaster : public VisualServer {
|
|||
opacity=1;
|
||||
self_opacity=1;
|
||||
sort_y=false;
|
||||
use_parent_shader=false;
|
||||
use_parent_material=false;
|
||||
z_relative=true;
|
||||
}
|
||||
};
|
||||
|
@ -410,6 +410,24 @@ class VisualServerRaster : public VisualServer {
|
|||
}
|
||||
};
|
||||
|
||||
struct CanvasLightOccluder;
|
||||
|
||||
struct CanvasLightOccluderPolygon {
|
||||
|
||||
bool active;
|
||||
Rect2 aabb;
|
||||
CanvasOccluderPolygonCullMode cull_mode;
|
||||
RID occluder;
|
||||
Set<Rasterizer::CanvasLightOccluderInstance*> owners;
|
||||
|
||||
CanvasLightOccluderPolygon() { active=false; cull_mode=CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; }
|
||||
};
|
||||
|
||||
|
||||
RID_Owner<CanvasLightOccluderPolygon> canvas_light_occluder_polygon_owner;
|
||||
|
||||
RID_Owner<Rasterizer::CanvasLightOccluderInstance> canvas_light_occluder_owner;
|
||||
|
||||
struct CanvasLight;
|
||||
|
||||
struct Canvas {
|
||||
|
@ -422,6 +440,7 @@ class VisualServerRaster : public VisualServer {
|
|||
};
|
||||
|
||||
Set<Rasterizer::CanvasLight*> lights;
|
||||
Set<Rasterizer::CanvasLightOccluderInstance*> occluders;
|
||||
|
||||
Vector<ChildItem> child_items;
|
||||
Color modulate;
|
||||
|
@ -610,7 +629,7 @@ class VisualServerRaster : public VisualServer {
|
|||
void _render_camera(Viewport *p_viewport,Camera *p_camera, Scenario *p_scenario);
|
||||
static void _render_canvas_item_viewport(VisualServer* p_self,void *p_vp,const Rect2& p_rect);
|
||||
void _render_canvas_item_tree(CanvasItem *p_canvas_item, const Matrix32& p_transform, const Rect2& p_clip_rect, const Color &p_modulate, Rasterizer::CanvasLight *p_lights);
|
||||
void _render_canvas_item(CanvasItem *p_canvas_item,const Matrix32& p_transform,const Rect2& p_clip_rect, float p_opacity,int p_z,Rasterizer::CanvasItem **z_list,Rasterizer::CanvasItem **z_last_list,CanvasItem *p_canvas_clip,CanvasItem *p_shader_owner);
|
||||
void _render_canvas_item(CanvasItem *p_canvas_item, const Matrix32& p_transform, const Rect2& p_clip_rect, float p_opacity, int p_z, Rasterizer::CanvasItem **z_list, Rasterizer::CanvasItem **z_last_list, CanvasItem *p_canvas_clip, CanvasItem *p_material_owner);
|
||||
void _render_canvas(Canvas *p_canvas, const Matrix32 &p_transform, Rasterizer::CanvasLight *p_lights);
|
||||
Vector<Vector3> _camera_generate_endpoints(Instance *p_light,Camera *p_camera,float p_range_min, float p_range_max);
|
||||
Vector<Plane> _camera_generate_orthogonal_planes(Instance *p_light,Camera *p_camera,float p_range_min, float p_range_max);
|
||||
|
@ -1131,15 +1150,8 @@ public:
|
|||
virtual void canvas_item_set_z(RID p_item, int p_z);
|
||||
virtual void canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable);
|
||||
|
||||
virtual void canvas_item_set_shader(RID p_item, RID p_shader);
|
||||
virtual RID canvas_item_get_shader(RID p_item) const;
|
||||
|
||||
virtual void canvas_item_set_use_parent_shader(RID p_item, bool p_enable);
|
||||
|
||||
|
||||
|
||||
virtual void canvas_item_set_shader_param(RID p_canvas_item, const StringName& p_param, const Variant& p_value);
|
||||
virtual Variant canvas_item_get_shader_param(RID p_canvas_item, const StringName& p_param) const;
|
||||
virtual void canvas_item_set_material(RID p_item, RID p_material);
|
||||
virtual void canvas_item_set_use_parent_material(RID p_item, bool p_enable);
|
||||
|
||||
virtual RID canvas_light_create();
|
||||
virtual void canvas_light_attach_to_canvas(RID p_light,RID p_canvas);
|
||||
|
@ -1156,17 +1168,36 @@ public:
|
|||
virtual void canvas_light_set_subtract_mode(RID p_light, bool p_enable);
|
||||
virtual void canvas_light_set_shadow_enabled(RID p_light, bool p_enabled);
|
||||
virtual void canvas_light_set_shadow_buffer_size(RID p_light, int p_size);
|
||||
virtual void canvas_light_set_shadow_filter(RID p_light, int p_size);
|
||||
virtual void canvas_light_set_shadow_esm_multiplier(RID p_light, float p_multiplier);
|
||||
|
||||
|
||||
virtual RID canvas_light_occluder_create();
|
||||
virtual void canvas_light_occluder_attach_to_canvas(RID p_occluder,RID p_canvas);
|
||||
virtual void canvas_light_occluder_set_enabled(RID p_occluder,bool p_enabled);
|
||||
virtual void canvas_light_occluder_set_shape(RID p_occluder,const DVector<Vector2>& p_shape);
|
||||
virtual void canvas_light_occluder_set_polygon(RID p_occluder,RID p_polygon);
|
||||
virtual void canvas_light_occluder_set_transform(RID p_occluder,const Matrix32& p_xform);
|
||||
virtual void canvas_light_occluder_set_light_mask(RID p_occluder,int p_mask);
|
||||
|
||||
|
||||
virtual RID canvas_occluder_polygon_create();
|
||||
virtual void canvas_occluder_polygon_set_shape(RID p_occluder_polygon,const DVector<Vector2>& p_shape,bool p_close);
|
||||
virtual void canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon,const DVector<Vector2>& p_shape);
|
||||
virtual void canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon,CanvasOccluderPolygonCullMode p_mode);
|
||||
|
||||
|
||||
|
||||
virtual void canvas_item_clear(RID p_item);
|
||||
virtual void canvas_item_raise(RID p_item);
|
||||
|
||||
/* CANVAS ITEM MATERIAL */
|
||||
|
||||
virtual RID canvas_item_material_create();
|
||||
virtual void canvas_item_material_set_shader(RID p_material, RID p_shader);
|
||||
virtual void canvas_item_material_set_shader_param(RID p_material, const StringName& p_param, const Variant& p_value);
|
||||
virtual Variant canvas_item_material_get_shader_param(RID p_material, const StringName& p_param) const;
|
||||
virtual void canvas_item_material_set_unshaded(RID p_material, bool p_unshaded);
|
||||
|
||||
|
||||
/* CURSOR */
|
||||
virtual void cursor_set_rotation(float p_rotation, int p_cursor = 0); // radians
|
||||
virtual void cursor_set_texture(RID p_texture, const Point2 &p_center_offset, int p_cursor=0);
|
||||
|
|
|
@ -1139,14 +1139,9 @@ public:
|
|||
FUNC2(canvas_item_set_z,RID,int);
|
||||
FUNC2(canvas_item_set_z_as_relative_to_parent,RID,bool);
|
||||
|
||||
FUNC2(canvas_item_set_shader,RID, RID );
|
||||
FUNC1RC(RID,canvas_item_get_shader,RID );
|
||||
FUNC2(canvas_item_set_material,RID, RID );
|
||||
|
||||
FUNC2(canvas_item_set_use_parent_shader,RID, bool );
|
||||
|
||||
|
||||
FUNC3(canvas_item_set_shader_param,RID,const StringName&,const Variant&);
|
||||
FUNC2RC(Variant,canvas_item_get_shader_param,RID,const StringName&);
|
||||
FUNC2(canvas_item_set_use_parent_material,RID, bool );
|
||||
|
||||
FUNC1(canvas_item_clear,RID);
|
||||
FUNC1(canvas_item_raise,RID);
|
||||
|
@ -1167,14 +1162,31 @@ public:
|
|||
FUNC2(canvas_light_set_subtract_mode,RID,bool);
|
||||
FUNC2(canvas_light_set_shadow_enabled,RID,bool);
|
||||
FUNC2(canvas_light_set_shadow_buffer_size,RID,int);
|
||||
FUNC2(canvas_light_set_shadow_filter,RID,int);
|
||||
FUNC2(canvas_light_set_shadow_esm_multiplier,RID,float);
|
||||
|
||||
|
||||
/* CANVAS OCCLUDER */
|
||||
|
||||
FUNC0R(RID,canvas_light_occluder_create);
|
||||
FUNC2(canvas_light_occluder_attach_to_canvas,RID,RID);
|
||||
FUNC2(canvas_light_occluder_set_enabled,RID,bool);
|
||||
FUNC2(canvas_light_occluder_set_shape,RID,const DVector<Vector2>&);
|
||||
FUNC2(canvas_light_occluder_set_polygon,RID,RID);
|
||||
FUNC2(canvas_light_occluder_set_transform,RID,const Matrix32&);
|
||||
FUNC2(canvas_light_occluder_set_light_mask,RID,int);
|
||||
|
||||
|
||||
FUNC0R(RID,canvas_occluder_polygon_create);
|
||||
FUNC3(canvas_occluder_polygon_set_shape,RID,const DVector<Vector2>&,bool);
|
||||
FUNC2(canvas_occluder_polygon_set_shape_as_lines,RID,const DVector<Vector2>&);
|
||||
FUNC2(canvas_occluder_polygon_set_cull_mode,RID,CanvasOccluderPolygonCullMode);
|
||||
|
||||
/* CANVAS MATERIAL */
|
||||
|
||||
FUNC0R(RID,canvas_item_material_create);
|
||||
FUNC2(canvas_item_material_set_shader,RID,RID);
|
||||
FUNC3(canvas_item_material_set_shader_param,RID,const StringName&,const Variant&);
|
||||
FUNC2RC(Variant,canvas_item_material_get_shader_param,RID,const StringName&);
|
||||
FUNC2(canvas_item_material_set_unshaded,RID,bool);
|
||||
|
||||
/* CURSOR */
|
||||
FUNC2(cursor_set_rotation,float , int ); // radians
|
||||
|
|
|
@ -998,13 +998,9 @@ public:
|
|||
virtual void canvas_item_clear(RID p_item)=0;
|
||||
virtual void canvas_item_raise(RID p_item)=0;
|
||||
|
||||
virtual void canvas_item_set_shader(RID p_item, RID p_shader)=0;
|
||||
virtual RID canvas_item_get_shader(RID p_item) const=0;
|
||||
virtual void canvas_item_set_material(RID p_item, RID p_material)=0;
|
||||
|
||||
virtual void canvas_item_set_use_parent_shader(RID p_item, bool p_enable)=0;
|
||||
|
||||
virtual void canvas_item_set_shader_param(RID p_canvas_item, const StringName& p_param, const Variant& p_value)=0;
|
||||
virtual Variant canvas_item_get_shader_param(RID p_canvas_item, const StringName& p_param) const=0;
|
||||
virtual void canvas_item_set_use_parent_material(RID p_item, bool p_enable)=0;
|
||||
|
||||
virtual RID canvas_light_create()=0;
|
||||
virtual void canvas_light_attach_to_canvas(RID p_light,RID p_canvas)=0;
|
||||
|
@ -1021,13 +1017,34 @@ public:
|
|||
virtual void canvas_light_set_subtract_mode(RID p_light, bool p_enable)=0;
|
||||
virtual void canvas_light_set_shadow_enabled(RID p_light, bool p_enabled)=0;
|
||||
virtual void canvas_light_set_shadow_buffer_size(RID p_light, int p_size)=0;
|
||||
virtual void canvas_light_set_shadow_filter(RID p_light, int p_size)=0;
|
||||
virtual void canvas_light_set_shadow_esm_multiplier(RID p_light, float p_multiplier)=0;
|
||||
|
||||
|
||||
|
||||
virtual RID canvas_light_occluder_create()=0;
|
||||
virtual void canvas_light_occluder_attach_to_canvas(RID p_occluder,RID p_canvas)=0;
|
||||
virtual void canvas_light_occluder_set_enabled(RID p_occluder,bool p_enabled)=0;
|
||||
virtual void canvas_light_occluder_set_shape(RID p_occluder,const DVector<Vector2>& p_shape)=0;
|
||||
virtual void canvas_light_occluder_set_polygon(RID p_occluder,RID p_polygon)=0;
|
||||
virtual void canvas_light_occluder_set_transform(RID p_occluder,const Matrix32& p_xform)=0;
|
||||
virtual void canvas_light_occluder_set_light_mask(RID p_occluder,int p_mask)=0;
|
||||
|
||||
virtual RID canvas_occluder_polygon_create()=0;
|
||||
virtual void canvas_occluder_polygon_set_shape(RID p_occluder_polygon,const DVector<Vector2>& p_shape,bool p_closed)=0;
|
||||
virtual void canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon,const DVector<Vector2>& p_shape)=0;
|
||||
enum CanvasOccluderPolygonCullMode {
|
||||
CANVAS_OCCLUDER_POLYGON_CULL_DISABLED,
|
||||
CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE,
|
||||
CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE,
|
||||
};
|
||||
virtual void canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon,CanvasOccluderPolygonCullMode p_mode)=0;
|
||||
|
||||
/* CANVAS ITEM MATERIAL */
|
||||
|
||||
virtual RID canvas_item_material_create()=0;
|
||||
virtual void canvas_item_material_set_shader(RID p_material, RID p_shader)=0;
|
||||
virtual void canvas_item_material_set_shader_param(RID p_material, const StringName& p_param, const Variant& p_value)=0;
|
||||
virtual Variant canvas_item_material_get_shader_param(RID p_material, const StringName& p_param) const=0;
|
||||
virtual void canvas_item_material_set_unshaded(RID p_material, bool p_unshaded)=0;
|
||||
|
||||
/* CURSOR */
|
||||
virtual void cursor_set_rotation(float p_rotation, int p_cursor = 0)=0; // radians
|
||||
|
|
|
@ -90,6 +90,7 @@
|
|||
#include "plugins/baked_light_editor_plugin.h"
|
||||
#include "plugins/polygon_2d_editor_plugin.h"
|
||||
#include "plugins/navigation_polygon_editor_plugin.h"
|
||||
#include "plugins/light_occluder_2d_editor_plugin.h"
|
||||
// end
|
||||
#include "tools/editor/io_plugins/editor_texture_import_plugin.h"
|
||||
#include "tools/editor/io_plugins/editor_scene_import_plugin.h"
|
||||
|
@ -4115,6 +4116,7 @@ EditorNode::EditorNode() {
|
|||
add_editor_plugin( memnew( PathEditorPlugin(this) ) );
|
||||
add_editor_plugin( memnew( BakedLightEditorPlugin(this) ) );
|
||||
add_editor_plugin( memnew( Polygon2DEditorPlugin(this) ) );
|
||||
add_editor_plugin( memnew( LightOccluder2DEditorPlugin(this) ) );
|
||||
add_editor_plugin( memnew( NavigationPolygonEditorPlugin(this) ) );
|
||||
|
||||
for(int i=0;i<EditorPlugins::get_plugin_count();i++)
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 835 B |
Binary file not shown.
After Width: | Height: | Size: 441 B |
Binary file not shown.
After Width: | Height: | Size: 516 B |
Binary file not shown.
After Width: | Height: | Size: 581 B |
|
@ -4,6 +4,7 @@
|
|||
#include "os/file_access.h"
|
||||
#include "tools/editor/editor_settings.h"
|
||||
|
||||
|
||||
void CollisionPolygon2DEditor::_notification(int p_what) {
|
||||
|
||||
switch(p_what) {
|
||||
|
|
|
@ -0,0 +1,500 @@
|
|||
#include "light_occluder_2d_editor_plugin.h"
|
||||
|
||||
#include "canvas_item_editor_plugin.h"
|
||||
#include "os/file_access.h"
|
||||
#include "tools/editor/editor_settings.h"
|
||||
|
||||
void LightOccluder2DEditor::_notification(int p_what) {
|
||||
|
||||
switch(p_what) {
|
||||
|
||||
case NOTIFICATION_READY: {
|
||||
|
||||
button_create->set_icon( get_icon("Edit","EditorIcons"));
|
||||
button_edit->set_icon( get_icon("MovePoint","EditorIcons"));
|
||||
button_edit->set_pressed(true);
|
||||
get_tree()->connect("node_removed",this,"_node_removed");
|
||||
create_poly->connect("confirmed",this,"_create_poly");
|
||||
|
||||
} break;
|
||||
case NOTIFICATION_FIXED_PROCESS: {
|
||||
|
||||
|
||||
} break;
|
||||
}
|
||||
|
||||
}
|
||||
void LightOccluder2DEditor::_node_removed(Node *p_node) {
|
||||
|
||||
if(p_node==node) {
|
||||
node=NULL;
|
||||
hide();
|
||||
canvas_item_editor->get_viewport_control()->update();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Vector2 LightOccluder2DEditor::snap_point(const Vector2& p_point) const {
|
||||
|
||||
if (canvas_item_editor->is_snap_active()) {
|
||||
|
||||
return p_point.snapped(Vector2(1,1)*canvas_item_editor->get_snap());
|
||||
|
||||
} else {
|
||||
return p_point;
|
||||
}
|
||||
}
|
||||
|
||||
void LightOccluder2DEditor::_menu_option(int p_option) {
|
||||
|
||||
switch(p_option) {
|
||||
|
||||
case MODE_CREATE: {
|
||||
|
||||
mode=MODE_CREATE;
|
||||
button_create->set_pressed(true);
|
||||
button_edit->set_pressed(false);
|
||||
} break;
|
||||
case MODE_EDIT: {
|
||||
|
||||
mode=MODE_EDIT;
|
||||
button_create->set_pressed(false);
|
||||
button_edit->set_pressed(true);
|
||||
} break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void LightOccluder2DEditor::_wip_close(bool p_closed) {
|
||||
|
||||
undo_redo->create_action("Create Poly");
|
||||
undo_redo->add_undo_method(node->get_occluder_polygon().ptr(),"set_polygon",node->get_occluder_polygon()->get_polygon());
|
||||
undo_redo->add_do_method(node->get_occluder_polygon().ptr(),"set_polygon",wip);
|
||||
undo_redo->add_undo_method(node->get_occluder_polygon().ptr(),"set_closed",node->get_occluder_polygon()->is_closed());
|
||||
undo_redo->add_do_method(node->get_occluder_polygon().ptr(),"set_closed",p_closed);
|
||||
|
||||
undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
|
||||
undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
|
||||
undo_redo->commit_action();
|
||||
wip.clear();
|
||||
wip_active=false;
|
||||
mode=MODE_EDIT;
|
||||
button_edit->set_pressed(true);
|
||||
button_create->set_pressed(false);
|
||||
edited_point=-1;
|
||||
}
|
||||
|
||||
bool LightOccluder2DEditor::forward_input_event(const InputEvent& p_event) {
|
||||
|
||||
|
||||
if (!node)
|
||||
return false;
|
||||
|
||||
if (node->get_occluder_polygon().is_null()) {
|
||||
if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1 && p_event.mouse_button.pressed) {
|
||||
create_poly->set_text("No OccluderPolygon2D resource on this node.\nCreate and assign one?");
|
||||
create_poly->popup_centered_minsize();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
switch(p_event.type) {
|
||||
|
||||
case InputEvent::MOUSE_BUTTON: {
|
||||
|
||||
const InputEventMouseButton &mb=p_event.mouse_button;
|
||||
|
||||
Matrix32 xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
|
||||
|
||||
|
||||
Vector2 gpoint = Point2(mb.x,mb.y);
|
||||
Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
|
||||
cpoint=snap_point(cpoint);
|
||||
cpoint = node->get_global_transform().affine_inverse().xform(cpoint);
|
||||
|
||||
Vector<Vector2> poly = Variant(node->get_occluder_polygon()->get_polygon());
|
||||
|
||||
//first check if a point is to be added (segment split)
|
||||
real_t grab_treshold=EDITOR_DEF("poly_editor/point_grab_radius",8);
|
||||
|
||||
switch(mode) {
|
||||
|
||||
|
||||
case MODE_CREATE: {
|
||||
|
||||
if (mb.button_index==BUTTON_LEFT && mb.pressed) {
|
||||
|
||||
|
||||
if (!wip_active) {
|
||||
|
||||
wip.clear();
|
||||
wip.push_back( cpoint );
|
||||
wip_active=true;
|
||||
edited_point_pos=cpoint;
|
||||
canvas_item_editor->get_viewport_control()->update();
|
||||
edited_point=1;
|
||||
return true;
|
||||
} else {
|
||||
|
||||
|
||||
if (wip.size()>1 && xform.xform(wip[0]).distance_to(gpoint)<grab_treshold) {
|
||||
//wip closed
|
||||
_wip_close(true);
|
||||
|
||||
return true;
|
||||
} else if (wip.size()>1 && xform.xform(wip[wip.size()-1]).distance_to(gpoint)<grab_treshold) {
|
||||
//wip closed
|
||||
_wip_close(false);
|
||||
return true;
|
||||
|
||||
} else {
|
||||
|
||||
wip.push_back( cpoint );
|
||||
edited_point=wip.size();
|
||||
canvas_item_editor->get_viewport_control()->update();
|
||||
return true;
|
||||
|
||||
//add wip point
|
||||
}
|
||||
}
|
||||
} else if (mb.button_index==BUTTON_RIGHT && mb.pressed && wip_active) {
|
||||
_wip_close(true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
} break;
|
||||
|
||||
case MODE_EDIT: {
|
||||
|
||||
if (mb.button_index==BUTTON_LEFT) {
|
||||
if (mb.pressed) {
|
||||
|
||||
if (mb.mod.control) {
|
||||
|
||||
|
||||
if (poly.size() < 3) {
|
||||
|
||||
undo_redo->create_action("Edit Poly");
|
||||
undo_redo->add_undo_method(node->get_occluder_polygon().ptr(),"set_polygon",poly);
|
||||
poly.push_back(cpoint);
|
||||
undo_redo->add_do_method(node->get_occluder_polygon().ptr(),"set_polygon",poly);
|
||||
undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
|
||||
undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
|
||||
undo_redo->commit_action();
|
||||
return true;
|
||||
}
|
||||
|
||||
//search edges
|
||||
int closest_idx=-1;
|
||||
Vector2 closest_pos;
|
||||
real_t closest_dist=1e10;
|
||||
for(int i=0;i<poly.size();i++) {
|
||||
|
||||
Vector2 points[2] ={ xform.xform(poly[i]),
|
||||
xform.xform(poly[(i+1)%poly.size()]) };
|
||||
|
||||
Vector2 cp = Geometry::get_closest_point_to_segment_2d(gpoint,points);
|
||||
if (cp.distance_squared_to(points[0])<CMP_EPSILON2 || cp.distance_squared_to(points[1])<CMP_EPSILON2)
|
||||
continue; //not valid to reuse point
|
||||
|
||||
real_t d = cp.distance_to(gpoint);
|
||||
if (d<closest_dist && d<grab_treshold) {
|
||||
closest_dist=d;
|
||||
closest_pos=cp;
|
||||
closest_idx=i;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (closest_idx>=0) {
|
||||
|
||||
pre_move_edit=poly;
|
||||
poly.insert(closest_idx+1,xform.affine_inverse().xform(closest_pos));
|
||||
edited_point=closest_idx+1;
|
||||
edited_point_pos=xform.affine_inverse().xform(closest_pos);
|
||||
node->get_occluder_polygon()->set_polygon(Variant(poly));
|
||||
canvas_item_editor->get_viewport_control()->update();
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
|
||||
//look for points to move
|
||||
|
||||
int closest_idx=-1;
|
||||
Vector2 closest_pos;
|
||||
real_t closest_dist=1e10;
|
||||
for(int i=0;i<poly.size();i++) {
|
||||
|
||||
Vector2 cp =xform.xform(poly[i]);
|
||||
|
||||
real_t d = cp.distance_to(gpoint);
|
||||
if (d<closest_dist && d<grab_treshold) {
|
||||
closest_dist=d;
|
||||
closest_pos=cp;
|
||||
closest_idx=i;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (closest_idx>=0) {
|
||||
|
||||
pre_move_edit=poly;
|
||||
edited_point=closest_idx;
|
||||
edited_point_pos=xform.affine_inverse().xform(closest_pos);
|
||||
canvas_item_editor->get_viewport_control()->update();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
if (edited_point!=-1) {
|
||||
|
||||
//apply
|
||||
|
||||
ERR_FAIL_INDEX_V(edited_point,poly.size(),false);
|
||||
poly[edited_point]=edited_point_pos;
|
||||
undo_redo->create_action("Edit Poly");
|
||||
undo_redo->add_do_method(node->get_occluder_polygon().ptr(),"set_polygon",poly);
|
||||
undo_redo->add_undo_method(node->get_occluder_polygon().ptr(),"set_polygon",pre_move_edit);
|
||||
undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
|
||||
undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
|
||||
undo_redo->commit_action();
|
||||
|
||||
edited_point=-1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} if (mb.button_index==BUTTON_RIGHT && mb.pressed && edited_point==-1) {
|
||||
|
||||
|
||||
|
||||
int closest_idx=-1;
|
||||
Vector2 closest_pos;
|
||||
real_t closest_dist=1e10;
|
||||
for(int i=0;i<poly.size();i++) {
|
||||
|
||||
Vector2 cp =xform.xform(poly[i]);
|
||||
|
||||
real_t d = cp.distance_to(gpoint);
|
||||
if (d<closest_dist && d<grab_treshold) {
|
||||
closest_dist=d;
|
||||
closest_pos=cp;
|
||||
closest_idx=i;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (closest_idx>=0) {
|
||||
|
||||
|
||||
undo_redo->create_action("Edit Poly (Remove Point)");
|
||||
undo_redo->add_undo_method(node->get_occluder_polygon().ptr(),"set_polygon",poly);
|
||||
poly.remove(closest_idx);
|
||||
undo_redo->add_do_method(node->get_occluder_polygon().ptr(),"set_polygon",poly);
|
||||
undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
|
||||
undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
|
||||
undo_redo->commit_action();
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
} break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} break;
|
||||
case InputEvent::MOUSE_MOTION: {
|
||||
|
||||
const InputEventMouseMotion &mm=p_event.mouse_motion;
|
||||
|
||||
if (edited_point!=-1 && (wip_active || mm.button_mask&BUTTON_MASK_LEFT)) {
|
||||
|
||||
Vector2 gpoint = Point2(mm.x,mm.y);
|
||||
Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
|
||||
cpoint=snap_point(cpoint);
|
||||
edited_point_pos = node->get_global_transform().affine_inverse().xform(cpoint);
|
||||
|
||||
canvas_item_editor->get_viewport_control()->update();
|
||||
|
||||
}
|
||||
|
||||
} break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
void LightOccluder2DEditor::_canvas_draw() {
|
||||
|
||||
if (!node || !node->get_occluder_polygon().is_valid())
|
||||
return;
|
||||
|
||||
Control *vpc = canvas_item_editor->get_viewport_control();
|
||||
|
||||
Vector<Vector2> poly;
|
||||
|
||||
if (wip_active)
|
||||
poly=wip;
|
||||
else
|
||||
poly=Variant(node->get_occluder_polygon()->get_polygon());
|
||||
|
||||
|
||||
Matrix32 xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
|
||||
Ref<Texture> handle= get_icon("EditorHandle","EditorIcons");
|
||||
|
||||
int len = poly.size();
|
||||
|
||||
for(int i=0;i<poly.size();i++) {
|
||||
|
||||
|
||||
Vector2 p,p2;
|
||||
p = i==edited_point ? edited_point_pos : poly[i];
|
||||
if ((wip_active && i==poly.size()-1) || (((i+1)%poly.size())==edited_point))
|
||||
p2=edited_point_pos;
|
||||
else
|
||||
p2 = poly[(i+1)%poly.size()];
|
||||
|
||||
Vector2 point = xform.xform(p);
|
||||
Vector2 next_point = xform.xform(p2);
|
||||
|
||||
Color col=Color(1,0.3,0.1,0.8);
|
||||
|
||||
if (i==poly.size()-1 && (!node->get_occluder_polygon()->is_closed() || wip_active)) {
|
||||
|
||||
} else {
|
||||
vpc->draw_line(point,next_point,col,2);
|
||||
}
|
||||
vpc->draw_texture(handle,point-handle->get_size()*0.5);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LightOccluder2DEditor::edit(Node *p_collision_polygon) {
|
||||
|
||||
if (!canvas_item_editor) {
|
||||
canvas_item_editor=CanvasItemEditor::get_singleton();
|
||||
}
|
||||
|
||||
if (p_collision_polygon) {
|
||||
|
||||
node=p_collision_polygon->cast_to<LightOccluder2D>();
|
||||
if (!canvas_item_editor->get_viewport_control()->is_connected("draw",this,"_canvas_draw"))
|
||||
canvas_item_editor->get_viewport_control()->connect("draw",this,"_canvas_draw");
|
||||
wip.clear();
|
||||
wip_active=false;
|
||||
edited_point=-1;
|
||||
|
||||
} else {
|
||||
node=NULL;
|
||||
|
||||
if (canvas_item_editor->get_viewport_control()->is_connected("draw",this,"_canvas_draw"))
|
||||
canvas_item_editor->get_viewport_control()->disconnect("draw",this,"_canvas_draw");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void LightOccluder2DEditor::_create_poly() {
|
||||
|
||||
undo_redo->create_action("Create Occluder Polygon");
|
||||
undo_redo->add_do_method(node,"set_occluder_polygon",Ref<OccluderPolygon2D>(memnew( OccluderPolygon2D)));
|
||||
undo_redo->add_undo_method(node,"set_occluder_polygon",Variant(REF()));
|
||||
undo_redo->commit_action();
|
||||
}
|
||||
|
||||
void LightOccluder2DEditor::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("_menu_option"),&LightOccluder2DEditor::_menu_option);
|
||||
ObjectTypeDB::bind_method(_MD("_canvas_draw"),&LightOccluder2DEditor::_canvas_draw);
|
||||
ObjectTypeDB::bind_method(_MD("_node_removed"),&LightOccluder2DEditor::_node_removed);
|
||||
ObjectTypeDB::bind_method(_MD("_create_poly"),&LightOccluder2DEditor::_create_poly);
|
||||
|
||||
}
|
||||
|
||||
|
||||
LightOccluder2DEditor::LightOccluder2DEditor(EditorNode *p_editor) {
|
||||
|
||||
canvas_item_editor=NULL;
|
||||
editor=p_editor;
|
||||
undo_redo = editor->get_undo_redo();
|
||||
|
||||
add_child( memnew( VSeparator ));
|
||||
button_create = memnew( ToolButton );
|
||||
add_child(button_create);
|
||||
button_create->connect("pressed",this,"_menu_option",varray(MODE_CREATE));
|
||||
button_create->set_toggle_mode(true);
|
||||
button_create->set_tooltip("Create a new polygon from scratch");
|
||||
|
||||
button_edit = memnew( ToolButton );
|
||||
add_child(button_edit);
|
||||
button_edit->connect("pressed",this,"_menu_option",varray(MODE_EDIT));
|
||||
button_edit->set_toggle_mode(true);
|
||||
button_edit->set_tooltip("Edit existing polygon:\nLMB: Move Point.\nCtrl+LMB: Split Segment.\nRMB: Erase Point.");
|
||||
|
||||
create_poly = memnew( ConfirmationDialog );
|
||||
add_child(create_poly);
|
||||
create_poly->get_ok()->set_text("Create");
|
||||
|
||||
|
||||
//add_constant_override("separation",0);
|
||||
|
||||
#if 0
|
||||
options = memnew( MenuButton );
|
||||
add_child(options);
|
||||
options->set_area_as_parent_rect();
|
||||
options->set_text("Polygon");
|
||||
//options->get_popup()->add_item("Parse BBCODE",PARSE_BBCODE);
|
||||
options->get_popup()->connect("item_pressed", this,"_menu_option");
|
||||
#endif
|
||||
|
||||
mode = MODE_EDIT;
|
||||
wip_active=false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void LightOccluder2DEditorPlugin::edit(Object *p_object) {
|
||||
|
||||
collision_polygon_editor->edit(p_object->cast_to<Node>());
|
||||
}
|
||||
|
||||
bool LightOccluder2DEditorPlugin::handles(Object *p_object) const {
|
||||
|
||||
return p_object->is_type("LightOccluder2D");
|
||||
}
|
||||
|
||||
void LightOccluder2DEditorPlugin::make_visible(bool p_visible) {
|
||||
|
||||
if (p_visible) {
|
||||
collision_polygon_editor->show();
|
||||
} else {
|
||||
|
||||
collision_polygon_editor->hide();
|
||||
collision_polygon_editor->edit(NULL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
LightOccluder2DEditorPlugin::LightOccluder2DEditorPlugin(EditorNode *p_node) {
|
||||
|
||||
editor=p_node;
|
||||
collision_polygon_editor = memnew( LightOccluder2DEditor(p_node) );
|
||||
CanvasItemEditor::get_singleton()->add_control_to_menu_panel(collision_polygon_editor);
|
||||
|
||||
collision_polygon_editor->hide();
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
LightOccluder2DEditorPlugin::~LightOccluder2DEditorPlugin()
|
||||
{
|
||||
}
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
#ifndef LIGHT_OCCLUDER_2D_EDITOR_PLUGIN_H
|
||||
#define LIGHT_OCCLUDER_2D_EDITOR_PLUGIN_H
|
||||
|
||||
|
||||
|
||||
#include "tools/editor/editor_plugin.h"
|
||||
#include "tools/editor/editor_node.h"
|
||||
#include "scene/2d/light_occluder_2d.h"
|
||||
#include "scene/gui/tool_button.h"
|
||||
#include "scene/gui/button_group.h"
|
||||
|
||||
/**
|
||||
@author Juan Linietsky <reduzio@gmail.com>
|
||||
*/
|
||||
class CanvasItemEditor;
|
||||
|
||||
class LightOccluder2DEditor : public HBoxContainer {
|
||||
|
||||
OBJ_TYPE(LightOccluder2DEditor, HBoxContainer );
|
||||
|
||||
UndoRedo *undo_redo;
|
||||
enum Mode {
|
||||
|
||||
MODE_CREATE,
|
||||
MODE_EDIT,
|
||||
|
||||
};
|
||||
|
||||
Mode mode;
|
||||
|
||||
ToolButton *button_create;
|
||||
ToolButton *button_edit;
|
||||
|
||||
CanvasItemEditor *canvas_item_editor;
|
||||
EditorNode *editor;
|
||||
Panel *panel;
|
||||
LightOccluder2D *node;
|
||||
MenuButton *options;
|
||||
|
||||
int edited_point;
|
||||
Vector2 edited_point_pos;
|
||||
Vector<Vector2> pre_move_edit;
|
||||
Vector<Vector2> wip;
|
||||
bool wip_active;
|
||||
|
||||
ConfirmationDialog *create_poly;
|
||||
|
||||
void _wip_close(bool p_closed);
|
||||
void _canvas_draw();
|
||||
void _menu_option(int p_option);
|
||||
void _create_poly();
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
void _node_removed(Node *p_node);
|
||||
static void _bind_methods();
|
||||
public:
|
||||
|
||||
Vector2 snap_point(const Vector2& p_point) const;
|
||||
bool forward_input_event(const InputEvent& p_event);
|
||||
void edit(Node *p_collision_polygon);
|
||||
LightOccluder2DEditor(EditorNode *p_editor);
|
||||
};
|
||||
|
||||
class LightOccluder2DEditorPlugin : public EditorPlugin {
|
||||
|
||||
OBJ_TYPE( LightOccluder2DEditorPlugin, EditorPlugin );
|
||||
|
||||
LightOccluder2DEditor *collision_polygon_editor;
|
||||
EditorNode *editor;
|
||||
|
||||
public:
|
||||
|
||||
virtual bool forward_input_event(const InputEvent& p_event) { return collision_polygon_editor->forward_input_event(p_event); }
|
||||
|
||||
virtual String get_name() const { return "LightOccluder2D"; }
|
||||
bool has_main_screen() const { return false; }
|
||||
virtual void edit(Object *p_node);
|
||||
virtual bool handles(Object *p_node) const;
|
||||
virtual void make_visible(bool p_visible);
|
||||
|
||||
LightOccluder2DEditorPlugin(EditorNode *p_node);
|
||||
~LightOccluder2DEditorPlugin();
|
||||
|
||||
};
|
||||
|
||||
#endif // LIGHT_OCCLUDER_2D_EDITOR_PLUGIN_H
|
|
@ -1857,8 +1857,33 @@ void PropertyEditor::set_item_text(TreeItem *p_item, int p_type, const String& p
|
|||
} else {
|
||||
p_item->set_text(1,"<"+res->get_type()+">");
|
||||
};
|
||||
|
||||
if (has_icon(res->get_type(),"EditorIcons")) {
|
||||
|
||||
p_item->set_icon(1,get_icon(res->get_type(),"EditorIcons"));
|
||||
} else {
|
||||
|
||||
Dictionary d = p_item->get_metadata(0);
|
||||
int hint=d.has("hint")?d["hint"].operator int():-1;
|
||||
String hint_text=d.has("hint_text")?d["hint_text"]:"";
|
||||
if (hint==PROPERTY_HINT_RESOURCE_TYPE) {
|
||||
|
||||
if (has_icon(hint_text,"EditorIcons")) {
|
||||
|
||||
p_item->set_icon(1,get_icon(hint_text,"EditorIcons"));
|
||||
|
||||
} else {
|
||||
p_item->set_icon(1,get_icon("Object","EditorIcons"));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
} break;
|
||||
default: {};
|
||||
}
|
||||
|
@ -2529,7 +2554,10 @@ void PropertyEditor::update_tree() {
|
|||
item->set_editable( 1, !read_only );
|
||||
item->add_button(1,get_icon("EditResource","EditorIcons"));
|
||||
String type;
|
||||
if (p.hint==PROPERTY_HINT_RESOURCE_TYPE)
|
||||
type=p.hint_string;
|
||||
bool notnil=false;
|
||||
|
||||
if (obj->get( p.name ).get_type() == Variant::NIL || obj->get( p.name ).operator RefPtr().is_null()) {
|
||||
item->set_text(1,"<null>");
|
||||
|
||||
|
@ -2553,12 +2581,18 @@ void PropertyEditor::update_tree() {
|
|||
};
|
||||
notnil=true;
|
||||
|
||||
if (has_icon(res->get_type(),"EditorIcons")) {
|
||||
type=res->get_type();
|
||||
}
|
||||
}
|
||||
|
||||
if (p.hint==PROPERTY_HINT_RESOURCE_TYPE) {
|
||||
|
||||
if (type!=String()) {
|
||||
if (type.find(",")!=-1)
|
||||
type=type.get_slice(",",0);
|
||||
//printf("prop %s , type %s\n",p.name.ascii().get_data(),p.hint_string.ascii().get_data());
|
||||
if (has_icon(p.hint_string,"EditorIcons"))
|
||||
item->set_icon( 0, get_icon(p.hint_string,"EditorIcons") );
|
||||
if (has_icon(type,"EditorIcons"))
|
||||
item->set_icon( 0, get_icon(type,"EditorIcons") );
|
||||
else
|
||||
item->set_icon( 0, get_icon("Object","EditorIcons") );
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue