work in progress global illumination

This commit is contained in:
Juan Linietsky 2016-12-20 00:21:07 -03:00
parent 22a90e8f2a
commit 075fde7f26
29 changed files with 5222 additions and 964 deletions

View file

@ -1010,6 +1010,48 @@ void RasterizerSceneGLES3::light_instance_mark_visible(RID p_light_instance) {
light_instance->last_scene_pass=scene_pass;
}
//////////////////////
RID RasterizerSceneGLES3::gi_probe_instance_create() {
GIProbeInstance *gipi = memnew(GIProbeInstance);
return gi_probe_instance_owner.make_rid(gipi);
}
void RasterizerSceneGLES3::gi_probe_instance_set_light_data(RID p_probe,RID p_data) {
GIProbeInstance *gipi = gi_probe_instance_owner.getornull(p_probe);
ERR_FAIL_COND(!gipi);
gipi->data=p_data;
if (p_data.is_valid()) {
RasterizerStorageGLES3::GIProbeData *gipd = storage->gi_probe_data_owner.getornull(p_data);
ERR_FAIL_COND(!gipd);
if (gipd) {
gipi->tex_cache=gipd->tex_id;
gipi->cell_size_cache.x=1.0/gipd->width;
gipi->cell_size_cache.y=1.0/gipd->height;
gipi->cell_size_cache.z=1.0/gipd->depth;
}
}
}
void RasterizerSceneGLES3::gi_probe_instance_set_transform_to_data(RID p_probe,const Transform& p_xform) {
GIProbeInstance *gipi = gi_probe_instance_owner.getornull(p_probe);
ERR_FAIL_COND(!gipi);
gipi->transform_to_data=p_xform;
}
void RasterizerSceneGLES3::gi_probe_instance_set_bounds(RID p_probe,const Vector3& p_bounds) {
GIProbeInstance *gipi = gi_probe_instance_owner.getornull(p_probe);
ERR_FAIL_COND(!gipi);
gipi->bounds=p_bounds;
}
////////////////////////////
////////////////////////////
////////////////////////////
@ -1438,7 +1480,7 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) {
}
void RasterizerSceneGLES3::_setup_light(RenderList::Element *e) {
void RasterizerSceneGLES3::_setup_light(RenderList::Element *e,const Transform& p_view_transform) {
int omni_indices[16];
int omni_count=0;
@ -1509,7 +1551,33 @@ void RasterizerSceneGLES3::_setup_light(RenderList::Element *e) {
glUniform1iv(state.scene_shader.get_uniform(SceneShaderGLES3::REFLECTION_INDICES),reflection_count,reflection_indices);
}
int gi_probe_count = e->instance->gi_probe_instances.size();
if (gi_probe_count) {
const RID * ridp = e->instance->gi_probe_instances.ptr();
GIProbeInstance *gipi = gi_probe_instance_owner.getptr(ridp[0]);
glActiveTexture(GL_TEXTURE0+storage->config.max_texture_image_units-6);
glBindTexture(GL_TEXTURE_3D,gipi->tex_cache);
state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_XFORM1, gipi->transform_to_data * p_view_transform);
state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BOUNDS1, gipi->bounds);
state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_CELL_SIZE1, gipi->cell_size_cache);
if (gi_probe_count>1) {
GIProbeInstance *gipi2 = gi_probe_instance_owner.getptr(ridp[1]);
glActiveTexture(GL_TEXTURE0+storage->config.max_texture_image_units-7);
glBindTexture(GL_TEXTURE_3D,gipi2->tex_cache);
state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_XFORM2, gipi2->transform_to_data * p_view_transform);
state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BOUNDS2, gipi2->bounds);
state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_CELL_SIZE2, gipi2->cell_size_cache);
state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE2_ENABLED, true );
} else {
state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE2_ENABLED, false );
}
}
}
@ -1672,11 +1740,15 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e
state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM_BLEND,false);
state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_5,false);
state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_13,false);
state.scene_shader.set_conditional(SceneShaderGLES3::USE_GI_PROBES,false);
//state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS,true);
} else {
state.scene_shader.set_conditional(SceneShaderGLES3::USE_GI_PROBES,e->instance->gi_probe_instances.size()>0);
state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS,false);
state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_LIGHTING,!p_directional_add);
state.scene_shader.set_conditional(SceneShaderGLES3::USE_LIGHT_DIRECTIONAL,false);
@ -1711,9 +1783,12 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e
}
rebind=true;
}
if (p_alpha_pass || p_directional_add) {
int desired_blend_mode;
if (p_directional_add) {
@ -1794,7 +1869,8 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e
}
if (!(e->sort_key&RenderList::SORT_KEY_UNSHADED_FLAG) && !p_directional_add && !p_shadow) {
_setup_light(e);
_setup_light(e,p_view_transform);
}
@ -1837,6 +1913,7 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e
state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS,false);
state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_5,false);
state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_13,false);
state.scene_shader.set_conditional(SceneShaderGLES3::USE_GI_PROBES,false);
}
@ -1950,6 +2027,10 @@ void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_g
copymem(oe,e,sizeof(RenderList::Element));
}
if (e->instance->gi_probe_instances.size()) {
e->sort_key|=RenderList::SORT_KEY_GI_PROBES_FLAG;
}
}
//if (e->geometry->type==RasterizerStorageGLES3::Geometry::GEOMETRY_MULTISURFACE)

View file

@ -526,6 +526,25 @@ public:
virtual void light_instance_set_shadow_transform(RID p_light_instance,const CameraMatrix& p_projection,const Transform& p_transform,float p_far,float p_split,int p_pass);
virtual void light_instance_mark_visible(RID p_light_instance);
/* REFLECTION INSTANCE */
struct GIProbeInstance : public RID_Data {
RID data;
GLuint tex_cache;
Vector3 cell_size_cache;
Vector3 bounds;
Transform transform_to_data;
};
mutable RID_Owner<GIProbeInstance> gi_probe_instance_owner;
virtual RID gi_probe_instance_create();
virtual void gi_probe_instance_set_light_data(RID p_probe,RID p_data);
virtual void gi_probe_instance_set_transform_to_data(RID p_probe,const Transform& p_xform);
virtual void gi_probe_instance_set_bounds(RID p_probe,const Vector3& p_bounds);
/* RENDER LIST */
struct RenderList {
@ -541,8 +560,9 @@ public:
SORT_KEY_DEPTH_LAYER_SHIFT=60,
SORT_KEY_UNSHADED_FLAG=uint64_t(1)<<59,
SORT_KEY_NO_DIRECTIONAL_FLAG=uint64_t(1)<<58,
SORT_KEY_SHADING_SHIFT=58,
SORT_KEY_SHADING_MASK=3,
SORT_KEY_GI_PROBES_FLAG=uint64_t(1)<<57,
SORT_KEY_SHADING_SHIFT=57,
SORT_KEY_SHADING_MASK=7,
SORT_KEY_MATERIAL_INDEX_SHIFT=40,
SORT_KEY_GEOMETRY_INDEX_SHIFT=20,
SORT_KEY_GEOMETRY_TYPE_SHIFT=15,
@ -669,7 +689,7 @@ public:
_FORCE_INLINE_ void _setup_transform(InstanceBase *p_instance,const Transform& p_view_transform,const CameraMatrix& p_projection);
_FORCE_INLINE_ void _setup_geometry(RenderList::Element *e);
_FORCE_INLINE_ void _render_geometry(RenderList::Element *e);
_FORCE_INLINE_ void _setup_light(RenderList::Element *e);
_FORCE_INLINE_ void _setup_light(RenderList::Element *e,const Transform& p_view_transform);
void _render_list(RenderList::Element **p_elements, int p_element_count, const Transform& p_view_transform, const CameraMatrix& p_projection, GLuint p_base_env, bool p_reverse_cull, bool p_alpha_pass, bool p_shadow, bool p_directional_add, bool p_directional_shadows);

View file

@ -1514,6 +1514,7 @@ void RasterizerStorageGLES3::_update_shader(Shader* p_shader) const {
p_shader->valid=true;
p_shader->version++;
}
void RasterizerStorageGLES3::update_dirty_shaders() {
@ -3600,16 +3601,15 @@ void RasterizerStorageGLES3::multimesh_instance_set_color(RID p_multimesh,int p_
ERR_FAIL_COND(multimesh->color_format==VS::MULTIMESH_COLOR_NONE);
int stride = multimesh->color_floats+multimesh->xform_floats;
float *dataptr=&multimesh->data[stride*p_index+multimesh->color_floats];
float *dataptr=&multimesh->data[stride*p_index+multimesh->xform_floats];
if (multimesh->color_format==VS::MULTIMESH_COLOR_8BIT) {
union {
uint32_t colu;
float colf;
} cu;
cu.colu=p_color.to_32();
dataptr[ 0]=cu.colf;
uint8_t *data8=(uint8_t*)dataptr;
data8[0]=CLAMP(p_color.r*255.0,0,255);
data8[1]=CLAMP(p_color.g*255.0,0,255);
data8[2]=CLAMP(p_color.b*255.0,0,255);
data8[3]=CLAMP(p_color.a*255.0,0,255);
} else if (multimesh->color_format==VS::MULTIMESH_COLOR_FLOAT) {
dataptr[ 0]=p_color.r;
@ -3701,7 +3701,7 @@ Color RasterizerStorageGLES3::multimesh_instance_get_color(RID p_multimesh,int p
float colf;
} cu;
return Color::hex(cu.colu);
return Color::hex(BSWAP32(cu.colu));
} else if (multimesh->color_format==VS::MULTIMESH_COLOR_FLOAT) {
Color c;
@ -4385,6 +4385,15 @@ float RasterizerStorageGLES3::light_get_param(RID p_light,VS::LightParam p_param
return light->param[p_param];
}
Color RasterizerStorageGLES3::light_get_color(RID p_light) {
const Light * light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light,Color());
return light->color;
}
bool RasterizerStorageGLES3::light_has_shadow(RID p_light) const {
const Light * light = light_owner.getornull(p_light);
@ -4668,6 +4677,261 @@ void RasterizerStorageGLES3::portal_set_disabled_color(RID p_portal, const Color
}
RID RasterizerStorageGLES3::gi_probe_create() {
GIProbe *gip = memnew( GIProbe );
gip->data_width=0;
gip->data_height=0;
gip->data_depth=0;
gip->bounds=AABB(Vector3(),Vector3(1,1,1));
gip->dynamic_range=1.0;
gip->version=1;
gip->cell_size=1.0;
return gi_probe_owner.make_rid(gip);
}
void RasterizerStorageGLES3::gi_probe_set_bounds(RID p_probe,const AABB& p_bounds){
GIProbe *gip = gi_probe_owner.getornull(p_probe);
ERR_FAIL_COND(!gip);
gip->bounds=p_bounds;
gip->version++;
gip->instance_change_notify();
}
AABB RasterizerStorageGLES3::gi_probe_get_bounds(RID p_probe) const{
const GIProbe *gip = gi_probe_owner.getornull(p_probe);
ERR_FAIL_COND_V(!gip,AABB());
return gip->bounds;
}
void RasterizerStorageGLES3::gi_probe_set_cell_size(RID p_probe,float p_size) {
GIProbe *gip = gi_probe_owner.getornull(p_probe);
ERR_FAIL_COND(!gip);
gip->cell_size=p_size;
gip->version++;
gip->instance_change_notify();
}
float RasterizerStorageGLES3::gi_probe_get_cell_size(RID p_probe) const {
const GIProbe *gip = gi_probe_owner.getornull(p_probe);
ERR_FAIL_COND_V(!gip,0);
return gip->cell_size;
}
void RasterizerStorageGLES3::gi_probe_set_to_cell_xform(RID p_probe,const Transform& p_xform) {
GIProbe *gip = gi_probe_owner.getornull(p_probe);
ERR_FAIL_COND(!gip);
gip->to_cell=p_xform;
}
Transform RasterizerStorageGLES3::gi_probe_get_to_cell_xform(RID p_probe) const {
const GIProbe *gip = gi_probe_owner.getornull(p_probe);
ERR_FAIL_COND_V(!gip,Transform());
return gip->to_cell;
}
void RasterizerStorageGLES3::gi_probe_set_dynamic_data(RID p_probe,const DVector<int>& p_data){
GIProbe *gip = gi_probe_owner.getornull(p_probe);
ERR_FAIL_COND(!gip);
gip->dynamic_data=p_data;
gip->version++;
gip->instance_change_notify();
}
DVector<int> RasterizerStorageGLES3::gi_probe_get_dynamic_data(RID p_probe) const{
const GIProbe *gip = gi_probe_owner.getornull(p_probe);
ERR_FAIL_COND_V(!gip,DVector<int>());
return gip->dynamic_data;
}
void RasterizerStorageGLES3::gi_probe_set_dynamic_range(RID p_probe,float p_range){
GIProbe *gip = gi_probe_owner.getornull(p_probe);
ERR_FAIL_COND(!gip);
gip->dynamic_range=p_range;
}
float RasterizerStorageGLES3::gi_probe_get_dynamic_range(RID p_probe) const{
const GIProbe *gip = gi_probe_owner.getornull(p_probe);
ERR_FAIL_COND_V(!gip,0);
return gip->dynamic_range;
}
void RasterizerStorageGLES3::gi_probe_set_static_data(RID p_gi_probe,const DVector<uint8_t>& p_data,VS::GIProbeDataFormat p_format,int p_width,int p_height,int p_depth) {
GIProbe *gip = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND(!gip);
if (gip->data.is_valid()) {
free(gip->data);
}
gip->data=RID();
//this is platform dependent
gip->version++;
gip->instance_change_notify();
}
DVector<uint8_t> RasterizerStorageGLES3::gi_probe_get_static_data(RID p_gi_probe) const {
const GIProbe *gip = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND_V(!gip,DVector<uint8_t>());
//platform dependent
return DVector<uint8_t>();
}
VS::GIProbeDataFormat RasterizerStorageGLES3::gi_probe_get_static_data_format(RID p_gi_probe) const {
const GIProbe *gip = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND_V(!gip,VS::GI_PROBE_DATA_RGBA8);
return gip->data_format;
}
int RasterizerStorageGLES3::gi_probe_get_static_data_width(RID p_probe) const {
const GIProbe *gip = gi_probe_owner.getornull(p_probe);
ERR_FAIL_COND_V(!gip,0);
return gip->data_width;
}
int RasterizerStorageGLES3::gi_probe_get_static_data_height(RID p_probe) const {
const GIProbe *gip = gi_probe_owner.getornull(p_probe);
ERR_FAIL_COND_V(!gip,0);
return gip->data_height;
}
int RasterizerStorageGLES3::gi_probe_get_static_data_depth(RID p_probe) const {
const GIProbe *gip = gi_probe_owner.getornull(p_probe);
ERR_FAIL_COND_V(!gip,0);
return gip->data_depth;
}
RID RasterizerStorageGLES3::gi_probe_get_data(RID p_probe) {
const GIProbe *gip = gi_probe_owner.getornull(p_probe);
ERR_FAIL_COND_V(!gip,RID());
return gip->data;
}
uint32_t RasterizerStorageGLES3::gi_probe_get_version(RID p_probe) {
const GIProbe *gip = gi_probe_owner.getornull(p_probe);
ERR_FAIL_COND_V(!gip,0);
return gip->version;
}
RID RasterizerStorageGLES3::gi_probe_dynamic_data_create(int p_width,int p_height,int p_depth) {
GIProbeData *gipd = memnew( GIProbeData );
gipd->width=p_width;
gipd->height=p_height;
gipd->depth=p_depth;
glActiveTexture(GL_TEXTURE0);
glGenTextures(1,&gipd->tex_id);
glBindTexture(GL_TEXTURE_3D,gipd->tex_id);
int level=0;
print_line("dyndata create");
while(true) {
Vector<uint8_t> data;
data.resize(p_width*p_height*p_depth*4);
for(int i=0;i<data.size();i+=4) {
data[i+0]=0xFF;
data[i+1]=0x00;
data[i+2]=0xFF;
data[i+3]=0xFF;
}
glTexImage3D(GL_TEXTURE_3D,level,GL_RGBA8,p_width,p_height,p_depth,0,GL_RGBA,GL_UNSIGNED_BYTE,data.ptr());
if (p_width<=1 || p_height<=1 || p_depth<=1)
break;
p_width>>=1;
p_height>>=1;
p_depth>>=1;
level++;
}
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, level);
gipd->levels=level+1;
return gi_probe_data_owner.make_rid(gipd);
}
void RasterizerStorageGLES3::gi_probe_dynamic_data_update_rgba8(RID p_gi_probe_data, int p_depth_slice, int p_slice_count, int p_mipmap, const void *p_data) {
GIProbeData *gipd = gi_probe_data_owner.getornull(p_gi_probe_data);
ERR_FAIL_COND(!gipd);
/*
Vector<uint8_t> data;
data.resize((gipd->width>>p_mipmap)*(gipd->height>>p_mipmap)*(gipd->depth>>p_mipmap)*4);
for(int i=0;i<(gipd->width>>p_mipmap);i++) {
for(int j=0;j<(gipd->height>>p_mipmap);j++) {
for(int k=0;k<(gipd->depth>>p_mipmap);k++) {
int ofs = (k*(gipd->height>>p_mipmap)*(gipd->width>>p_mipmap)) + j *(gipd->width>>p_mipmap) + i;
ofs*=4;
data[ofs+0]=i*0xFF/(gipd->width>>p_mipmap);
data[ofs+1]=j*0xFF/(gipd->height>>p_mipmap);
data[ofs+2]=k*0xFF/(gipd->depth>>p_mipmap);
data[ofs+3]=0xFF;
}
}
}
*/
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_3D,gipd->tex_id);
glTexSubImage3D(GL_TEXTURE_3D,p_mipmap,0,0,p_depth_slice,gipd->width>>p_mipmap,gipd->height>>p_mipmap,p_slice_count,GL_RGBA,GL_UNSIGNED_BYTE,p_data);
//glTexImage3D(GL_TEXTURE_3D,p_mipmap,GL_RGBA8,gipd->width>>p_mipmap,gipd->height>>p_mipmap,gipd->depth>>p_mipmap,0,GL_RGBA,GL_UNSIGNED_BYTE,p_data);
//glTexImage3D(GL_TEXTURE_3D,p_mipmap,GL_RGBA8,gipd->width>>p_mipmap,gipd->height>>p_mipmap,gipd->depth>>p_mipmap,0,GL_RGBA,GL_UNSIGNED_BYTE,data.ptr());
print_line("update rgba8 "+itos(p_mipmap));
}
void RasterizerStorageGLES3::instance_add_skeleton(RID p_skeleton,RasterizerScene::InstanceBase *p_instance) {
Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
@ -4709,6 +4973,10 @@ void RasterizerStorageGLES3::instance_add_dependency(RID p_base,RasterizerScene:
inst = light_owner.getornull(p_base);
ERR_FAIL_COND(!inst);
} break;
case VS::INSTANCE_GI_PROBE: {
inst = gi_probe_owner.getornull(p_base);
ERR_FAIL_COND(!inst);
} break;
default: {
if (!inst) {
ERR_FAIL();
@ -4744,6 +5012,10 @@ void RasterizerStorageGLES3::instance_remove_dependency(RID p_base,RasterizerSce
inst = light_owner.getornull(p_base);
ERR_FAIL_COND(!inst);
} break;
case VS::INSTANCE_GI_PROBE: {
inst = gi_probe_owner.getornull(p_base);
ERR_FAIL_COND(!inst);
} break;
default: {
if (!inst) {
@ -5395,19 +5667,27 @@ VS::InstanceType RasterizerStorageGLES3::get_base_type(RID p_rid) const {
if (mesh_owner.owns(p_rid)) {
return VS::INSTANCE_MESH;
}
if (multimesh_owner.owns(p_rid)) {
return VS::INSTANCE_MULTIMESH;
}
if (immediate_owner.owns(p_rid)) {
return VS::INSTANCE_IMMEDIATE;
}
if (light_owner.owns(p_rid)) {
return VS::INSTANCE_LIGHT;
}
if (reflection_probe_owner.owns(p_rid)) {
return VS::INSTANCE_REFLECTION_PROBE;
}
if (gi_probe_owner.owns(p_rid)) {
return VS::INSTANCE_GI_PROBE;
}
return VS::INSTANCE_NONE;
}
@ -5561,6 +5841,27 @@ bool RasterizerStorageGLES3::free(RID p_rid){
reflection_probe_owner.free(p_rid);
memdelete(reflection_probe);
} else if (gi_probe_owner.owns(p_rid)) {
// delete the texture
GIProbe *gi_probe = gi_probe_owner.get(p_rid);
if (gi_probe->data.is_valid()) {
free(gi_probe->data);
}
gi_probe_owner.free(p_rid);
memdelete(gi_probe);
} else if (gi_probe_data_owner.owns(p_rid)) {
// delete the texture
GIProbeData *gi_probe_data = gi_probe_data_owner.get(p_rid);
print_line("dyndata delete");
glDeleteTextures(1,&gi_probe_data->tex_id);
gi_probe_owner.free(p_rid);
memdelete(gi_probe_data);
} else if (canvas_occluder_owner.owns(p_rid)) {

View file

@ -799,6 +799,7 @@ public:
virtual VS::LightType light_get_type(RID p_light) const;
virtual float light_get_param(RID p_light,VS::LightParam p_param);
virtual Color light_get_color(RID p_light);
virtual AABB light_get_aabb(RID p_light) const;
virtual uint64_t light_get_version(RID p_light) const;
@ -868,6 +869,84 @@ public:
virtual void portal_set_disable_distance(RID p_portal, float p_distance);
virtual void portal_set_disabled_color(RID p_portal, const Color& p_color);
/* GI PROBE API */
struct GIProbe : public Instantiable {
AABB bounds;
Transform to_cell;
float cell_size;
float dynamic_range;
uint32_t version;
DVector<int> dynamic_data;
RID data;
int data_width;
int data_height;
int data_depth;
VS::GIProbeDataFormat data_format;
};
mutable RID_Owner<GIProbe> gi_probe_owner;
virtual RID gi_probe_create();
virtual void gi_probe_set_bounds(RID p_probe,const AABB& p_bounds);
virtual AABB gi_probe_get_bounds(RID p_probe) const;
virtual void gi_probe_set_cell_size(RID p_probe, float p_size);
virtual float gi_probe_get_cell_size(RID p_probe) const;
virtual void gi_probe_set_to_cell_xform(RID p_probe,const Transform& p_xform);
virtual Transform gi_probe_get_to_cell_xform(RID p_probe) const;
virtual void gi_probe_set_dynamic_data(RID p_probe,const DVector<int>& p_data);
virtual DVector<int> gi_probe_get_dynamic_data(RID p_probe) const;
virtual void gi_probe_set_dynamic_range(RID p_probe,float p_range);
virtual float gi_probe_get_dynamic_range(RID p_probe) const;
virtual void gi_probe_set_static_data(RID p_gi_probe,const DVector<uint8_t>& p_data,VS::GIProbeDataFormat p_format,int p_width,int p_height,int p_depth);
virtual DVector<uint8_t> gi_probe_get_static_data(RID p_gi_probe) const;
virtual VS::GIProbeDataFormat gi_probe_get_static_data_format(RID p_gi_probe) const;
virtual int gi_probe_get_static_data_width(RID p_probe) const;
virtual int gi_probe_get_static_data_height(RID p_probe) const;
virtual int gi_probe_get_static_data_depth(RID p_probe) const;
virtual RID gi_probe_get_data(RID p_probe); //get data in case this is static
virtual uint32_t gi_probe_get_version(RID p_probe);
struct GIProbeData : public RID_Data {
int width;
int height;
int depth;
int levels;
GLuint tex_id;
GIProbeData() {
}
};
mutable RID_Owner<GIProbeData> gi_probe_data_owner;
virtual RID gi_probe_dynamic_data_create(int p_width,int p_height,int p_depth);
virtual void gi_probe_dynamic_data_update_rgba8(RID p_gi_probe_data,int p_depth_slice,int p_slice_count,int p_mipmap,const void* p_data);
virtual void instance_add_skeleton(RID p_skeleton,RasterizerScene::InstanceBase *p_instance);
virtual void instance_remove_skeleton(RID p_skeleton,RasterizerScene::InstanceBase *p_instance);

View file

@ -838,6 +838,131 @@ void reflection_process(int idx, vec3 vertex, vec3 normal,vec3 binormal, vec3 ta
}
}
#ifdef USE_GI_PROBES
uniform mediump sampler3D gi_probe1; //texunit:-6
uniform highp mat4 gi_probe_xform1;
uniform highp vec3 gi_probe_bounds1;
uniform highp vec3 gi_probe_cell_size1;
uniform mediump sampler3D gi_probe2; //texunit:-7
uniform highp mat4 gi_probe_xform2;
uniform highp vec3 gi_probe_bounds2;
uniform highp vec3 gi_probe_cell_size2;
uniform bool gi_probe2_enabled;
vec3 voxel_cone_trace(sampler3D probe, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance) {
float dist = dot(direction,mix(vec3(-1.0),vec3(1.0),greaterThan(direction,vec3(0.0))))*2.0;
float alpha=0.0;
vec4 color = vec4(0.0);
while(dist < max_distance && alpha < 0.95) {
float diameter = max(1.0, 2.0 * tan_half_angle * dist);
vec4 scolor = textureLod(probe, (pos + dist * direction) * cell_size, log2(diameter) );
float a = (1.0 - alpha);
color.rgb += a * scolor.rgb;
alpha += a * scolor.a;
dist += diameter * 0.5;
}
return color.rgb;
}
void gi_probe_compute(sampler3D probe, mat4 probe_xform, vec3 bounds,vec3 cell_size,vec3 pos, mat3 normal_mtx,vec3 ref_vec, float roughness, out vec4 out_spec, out vec4 out_diff) {
vec3 probe_pos = (probe_xform * vec4(pos,1.0)).xyz;
vec3 ref_pos = (probe_xform * vec4(pos+ref_vec,1.0)).xyz;
ref_vec = normalize(ref_pos - probe_pos);
/* out_diff.rgb = voxel_cone_trace(probe,cell_size,probe_pos,normalize((probe_xform * vec4(ref_vec,0.0)).xyz),0.0 ,100.0);
out_diff.a = 1.0;
return;*/
//out_diff = vec4(textureLod(probe,probe_pos*cell_size,3.0).rgb,1.0);
//return;
if (any(bvec2(any(lessThan(probe_pos,vec3(0.0))),any(greaterThan(probe_pos,bounds)))))
return;
vec3 blendv = probe_pos/bounds * 2.0 - 1.0;
float blend = 1.001-max(blendv.x,max(blendv.y,blendv.z));
blend=1.0;
//radiance
#define MAX_CONE_DIRS 6
vec3 cone_dirs[MAX_CONE_DIRS] = vec3[] (
vec3(0, 0, 1),
vec3(0.866025, 0, 0.5),
vec3(0.267617, 0.823639, 0.5),
vec3(-0.700629, 0.509037, 0.5),
vec3(-0.700629, -0.509037, 0.5),
vec3(0.267617, -0.823639, 0.5)
);
float cone_weights[MAX_CONE_DIRS] = float[](0.25, 0.15, 0.15, 0.15, 0.15, 0.15);
float max_distance = length(bounds);
vec3 light=vec3(0.0);
for(int i=0;i<MAX_CONE_DIRS;i++) {
vec3 dir = normalize( (probe_xform * vec4(pos + normal_mtx * cone_dirs[i],1.0)).xyz - probe_pos);
light+=cone_weights[i] * voxel_cone_trace(probe,cell_size,probe_pos,dir,0.577,max_distance);
}
out_diff = vec4(light*blend,blend);
//irradiance
vec3 irr_light = voxel_cone_trace(probe,cell_size,probe_pos,ref_vec,tan(roughness * 0.5 * M_PI) ,max_distance);
//irr_light=vec3(0.0);
out_spec = vec4(irr_light*blend,blend);
}
void gi_probes_compute(vec3 pos, vec3 normal, float roughness, vec3 specular, inout vec3 out_specular, inout vec3 out_ambient) {
vec3 ref_vec = normalize(reflect(normalize(pos),normal));
//find arbitrary tangent and bitangent, then build a matrix
vec3 v0 = abs(normal.z) < 0.999 ? vec3(0, 0, 1) : vec3(0, 1, 0);
vec3 tangent = normalize(cross(v0, normal));
vec3 bitangent = normalize(cross(tangent, normal));
mat3 normal_mat = mat3(tangent,bitangent,normal);
vec4 diff_accum = vec4(0.0);
vec4 spec_accum = vec4(0.0);
gi_probe_compute(gi_probe1,gi_probe_xform1,gi_probe_bounds1,gi_probe_cell_size1,pos,normal_mat,ref_vec,roughness,spec_accum,diff_accum);
if (gi_probe2_enabled) {
gi_probe_compute(gi_probe2,gi_probe_xform2,gi_probe_bounds2,gi_probe_cell_size2,pos,normal_mat,ref_vec,roughness,spec_accum,diff_accum);
}
if (diff_accum.a>0.0) {
diff_accum.rgb/=diff_accum.a;
}
if (spec_accum.a>0.0) {
spec_accum.rgb/=spec_accum.a;
}
out_specular+=spec_accum.rgb;
out_ambient+=diff_accum.rgb;
}
#endif
void main() {
#ifdef RENDER_SHADOW_DUAL_PARABOLOID
@ -1161,21 +1286,27 @@ FRAGMENT_SHADER_CODE
#endif //#USE_LIGHT_DIRECTIONAL
#ifdef USE_GI_PROBES
gi_probes_compute(vertex,normal,roughness,specular,specular_light,ambient_light);
#endif
#ifdef USE_FORWARD_LIGHTING
highp vec4 reflection_accum = vec4(0.0,0.0,0.0,0.0);
highp vec4 ambient_accum = vec4(0.0,0.0,0.0,0.0);
for(int i=0;i<reflection_count;i++) {
reflection_process(reflection_indices[i],vertex,normal,binormal,tangent,roughness,anisotropy,ambient_light,specular_light,brdf,reflection_accum,ambient_accum);
}
if (reflection_accum.a>0.0) {
specular_light=reflection_accum.rgb/reflection_accum.a;
specular_light+=reflection_accum.rgb/reflection_accum.a;
}
if (ambient_accum.a>0.0) {
ambient_light=ambient_accum.rgb/ambient_accum.a;
ambient_light+=ambient_accum.rgb/ambient_accum.a;
}
for(int i=0;i<omni_light_count;i++) {