summaryrefslogtreecommitdiff
path: root/drivers/gles3
diff options
context:
space:
mode:
authorJuan Linietsky <reduzio@gmail.com>2016-10-21 07:27:13 -0300
committerJuan Linietsky <reduzio@gmail.com>2016-10-21 07:27:13 -0300
commitcb34b70df13ad9f7942b0c363edc71cfd417bb21 (patch)
tree0d1aefab73e839ae9a4d27547938ca4546a380a8 /drivers/gles3
parent4428115916144b45c4697cd65d9c8c093631bec6 (diff)
More scene work, can display a skybox
Diffstat (limited to 'drivers/gles3')
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp1
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp225
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.h66
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp137
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.h8
-rw-r--r--drivers/gles3/shaders/SCsub1
-rw-r--r--drivers/gles3/shaders/copy.glsl17
-rw-r--r--drivers/gles3/shaders/cubemap_filter.glsl143
8 files changed, 590 insertions, 8 deletions
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp
index 237b3ec3fc..b2228a6cfa 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.cpp
+++ b/drivers/gles3/rasterizer_canvas_gles3.cpp
@@ -117,7 +117,6 @@ void RasterizerCanvasGLES3::canvas_begin(){
glClearColor( storage->frame.clear_request_color.r, storage->frame.clear_request_color.g, storage->frame.clear_request_color.b, storage->frame.clear_request_color.a );
glClear(GL_COLOR_BUFFER_BIT);
storage->frame.clear_request=false;
- print_line("canvas clear?");
}
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index 121620594d..4ce2bd2f37 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -1,5 +1,10 @@
#include "rasterizer_scene_gles3.h"
#include "globals.h"
+
+
+
+
+
static _FORCE_INLINE_ void store_matrix32(const Matrix32& p_mtx, float* p_array) {
p_array[ 0]=p_mtx.elements[0][0];
@@ -52,6 +57,121 @@ static _FORCE_INLINE_ void store_camera(const CameraMatrix& p_mtx, float* p_arra
+
+/* ENVIRONMENT API */
+
+RID RasterizerSceneGLES3::environment_create(){
+
+
+ Environment *env = memnew( Environment );
+
+ return environment_owner.make_rid(env);
+}
+
+void RasterizerSceneGLES3::environment_set_background(RID p_env,VS::EnvironmentBG p_bg){
+
+ Environment *env=environment_owner.getornull(p_env);
+ ERR_FAIL_COND(!env);
+ env->bg_mode=p_bg;
+}
+
+void RasterizerSceneGLES3::environment_set_skybox(RID p_env, RID p_skybox, int p_radiance_size, int p_irradiance_size){
+
+ Environment *env=environment_owner.getornull(p_env);
+ ERR_FAIL_COND(!env);
+
+ if (env->skybox_color.is_valid()) {
+ env->skybox_color=RID();
+ }
+ if (env->skybox_radiance.is_valid()) {
+ storage->free(env->skybox_radiance);
+ env->skybox_radiance=RID();
+ }
+ if (env->skybox_irradiance.is_valid()) {
+ storage->free(env->skybox_irradiance);
+ env->skybox_irradiance=RID();
+ }
+
+ if (p_skybox.is_valid()) {
+
+ env->skybox_color=p_skybox;
+ // env->skybox_radiance=storage->texture_create_pbr_cubemap(p_skybox,VS::PBR_CUBEMAP_RADIANCE,p_radiance_size);
+ //env->skybox_irradiance=storage->texture_create_pbr_cubemap(p_skybox,VS::PBR_CUBEMAP_IRRADIANCE,p_irradiance_size);
+ }
+
+}
+
+void RasterizerSceneGLES3::environment_set_skybox_scale(RID p_env,float p_scale) {
+
+ Environment *env=environment_owner.getornull(p_env);
+ ERR_FAIL_COND(!env);
+
+ env->skybox_scale=p_scale;
+
+}
+
+void RasterizerSceneGLES3::environment_set_bg_color(RID p_env,const Color& p_color){
+
+ Environment *env=environment_owner.getornull(p_env);
+ ERR_FAIL_COND(!env);
+
+ env->bg_color=p_color;
+
+}
+void RasterizerSceneGLES3::environment_set_bg_energy(RID p_env,float p_energy) {
+
+ Environment *env=environment_owner.getornull(p_env);
+ ERR_FAIL_COND(!env);
+
+ env->energy=p_energy;
+
+}
+
+void RasterizerSceneGLES3::environment_set_canvas_max_layer(RID p_env,int p_max_layer){
+
+ Environment *env=environment_owner.getornull(p_env);
+ ERR_FAIL_COND(!env);
+
+ env->canvas_max_layer=p_max_layer;
+
+}
+void RasterizerSceneGLES3::environment_set_ambient_light(RID p_env, const Color& p_color, float p_energy, float p_skybox_energy){
+
+ Environment *env=environment_owner.getornull(p_env);
+ ERR_FAIL_COND(!env);
+
+ env->ambient_color=p_color;
+ env->ambient_anergy=p_energy;
+ env->skybox_ambient=p_skybox_energy;
+
+}
+
+void RasterizerSceneGLES3::environment_set_glow(RID p_env,bool p_enable,int p_radius,float p_intensity,float p_strength,float p_bloom_treshold,VS::EnvironmentGlowBlendMode p_blend_mode){
+
+}
+void RasterizerSceneGLES3::environment_set_fog(RID p_env,bool p_enable,float p_begin,float p_end,RID p_gradient_texture){
+
+}
+
+void RasterizerSceneGLES3::environment_set_tonemap(RID p_env,bool p_enable,float p_exposure,float p_white,float p_min_luminance,float p_max_luminance,float p_auto_exp_speed,VS::EnvironmentToneMapper p_tone_mapper){
+
+}
+void RasterizerSceneGLES3::environment_set_brightness(RID p_env,bool p_enable,float p_brightness){
+
+}
+void RasterizerSceneGLES3::environment_set_contrast(RID p_env,bool p_enable,float p_contrast){
+
+}
+void RasterizerSceneGLES3::environment_set_saturation(RID p_env,bool p_enable,float p_saturation){
+
+}
+void RasterizerSceneGLES3::environment_set_color_correction(RID p_env,bool p_enable,RID p_ramp){
+
+}
+
+
+
+
RID RasterizerSceneGLES3::light_instance_create(RID p_light) {
@@ -493,6 +613,70 @@ void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_g
#endif
}
+void RasterizerSceneGLES3::_draw_skybox(RID p_skybox,CameraMatrix& p_projection,const Transform& p_transform,bool p_vflip,float p_scale) {
+
+ RasterizerStorageGLES3::Texture *tex = storage->texture_owner.getornull(p_skybox);
+
+ ERR_FAIL_COND(!tex);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(tex->target,tex->tex_id);
+
+ glDepthMask(GL_TRUE);
+ glEnable(GL_DEPTH_TEST);
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_BLEND);
+ glColorMask(1,1,1,1);
+
+ float flip_sign = p_vflip?-1:1;
+
+ Vector3 vertices[8]={
+ Vector3(-1,-1*flip_sign,0.1),
+ Vector3( 0, 1, 0),
+ Vector3( 1,-1*flip_sign,0.1),
+ Vector3( 1, 1, 0),
+ Vector3( 1, 1*flip_sign,0.1),
+ Vector3( 1, 0, 0),
+ Vector3(-1, 1*flip_sign,0.1),
+ Vector3( 0, 0, 0),
+
+ };
+
+
+
+ //skybox uv vectors
+ float vw,vh,zn;
+ p_projection.get_viewport_size(vw,vh);
+ zn=p_projection.get_z_near();
+
+ float scale=p_scale;
+
+ for(int i=0;i<4;i++) {
+
+ Vector3 uv=vertices[i*2+1];
+ uv.x=(uv.x*2.0-1.0)*vw*scale;
+ uv.y=-(uv.y*2.0-1.0)*vh*scale;
+ uv.z=-zn;
+ vertices[i*2+1] = p_transform.basis.xform(uv).normalized();
+ vertices[i*2+1].z = -vertices[i*2+1].z;
+ }
+
+ glBindBuffer(GL_ARRAY_BUFFER,state.skybox_verts);
+ glBufferSubData(GL_ARRAY_BUFFER,0,sizeof(Vector3)*8,vertices);
+ glBindBuffer(GL_ARRAY_BUFFER,0); //unbind
+
+ glBindVertexArray(state.skybox_array);
+
+ storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_CUBEMAP,true);
+ storage->shaders.copy.bind();
+
+ glDrawArrays(GL_TRIANGLE_FAN,0,4);
+
+ glBindVertexArray(0);
+
+ storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_CUBEMAP,false);
+
+}
+
void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,CameraMatrix& p_cam_projection,bool p_cam_ortogonal,InstanceBase** p_cull_result,int p_cull_count,RID* p_light_cull_result,int p_light_cull_count,RID* p_directional_lights,int p_directional_light_count,RID p_environment){
@@ -561,7 +745,9 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,CameraM
glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->front.fbo);
- if (true) {
+ Environment *env = environment_owner.getornull(p_environment);
+
+ if (!env || env->bg_mode==VS::ENV_BG_CLEAR_COLOR) {
if (storage->frame.clear_request) {
@@ -570,6 +756,16 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,CameraM
storage->frame.clear_request=false;
}
+ } else if (env->bg_mode==VS::ENV_BG_COLOR) {
+
+
+ glClearColor( env->bg_color.r, env->bg_color.g, env->bg_color.b, env->bg_color.a );
+ glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
+ storage->frame.clear_request=false;
+ } else {
+ glClear(GL_DEPTH_BUFFER_BIT);
+ storage->frame.clear_request=false;
+
}
state.current_depth_test=true;
@@ -616,6 +812,12 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,CameraM
_render_list(render_list.elements,render_list.element_count,p_cam_transform,p_cam_projection,false,false);
+
+ if (env && env->bg_mode==VS::ENV_BG_SKYBOX) {
+
+ _draw_skybox(env->skybox_color,p_cam_projection,p_cam_transform,storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP],env->skybox_scale);
+ }
+
//_render_list_forward(&alpha_render_list,camera_transform,camera_transform_inverse,camera_projection,false,fragment_lighting,true);
//glColorMask(1,1,1,1);
@@ -793,6 +995,27 @@ void RasterizerSceneGLES3::initialize() {
if (render_list.max_elements<1024)
render_list.max_elements=1024;
+
+
+ {
+ //quad buffers
+
+ glGenBuffers(1,&state.skybox_verts);
+ glBindBuffer(GL_ARRAY_BUFFER,state.skybox_verts);
+ glBufferData(GL_ARRAY_BUFFER,sizeof(Vector3)*8,NULL,GL_DYNAMIC_DRAW);
+ glBindBuffer(GL_ARRAY_BUFFER,0); //unbind
+
+
+ glGenVertexArrays(1,&state.skybox_array);
+ glBindVertexArray(state.skybox_array);
+ glBindBuffer(GL_ARRAY_BUFFER,state.skybox_verts);
+ glVertexAttribPointer(VS::ARRAY_VERTEX,3,GL_FLOAT,GL_FALSE,sizeof(Vector3)*2,0);
+ glEnableVertexAttribArray(VS::ARRAY_VERTEX);
+ glVertexAttribPointer(VS::ARRAY_TEX_UV,3,GL_FLOAT,GL_FALSE,sizeof(Vector3)*2,((uint8_t*)NULL)+sizeof(Vector3));
+ glEnableVertexAttribArray(VS::ARRAY_TEX_UV);
+ glBindVertexArray(0);
+ glBindBuffer(GL_ARRAY_BUFFER,0); //unbind
+ }
render_list.init();
}
diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h
index 6fba777fc8..53088deb0d 100644
--- a/drivers/gles3/rasterizer_scene_gles3.h
+++ b/drivers/gles3/rasterizer_scene_gles3.h
@@ -16,8 +16,6 @@ public:
RasterizerStorageGLES3 *storage;
-
-
struct State {
bool current_depth_test;
@@ -40,10 +38,70 @@ public:
GLuint scene_ubo;
-
+ GLuint skybox_verts;
+ GLuint skybox_array;
} state;
+
+
+
+ /* ENVIRONMENT API */
+
+ struct Environment : public RID_Data {
+
+ VS::EnvironmentBG bg_mode;
+
+ RID skybox_color;
+ RID skybox_radiance;
+ RID skybox_irradiance;
+ float skybox_scale;
+
+ Color bg_color;
+ float energy;
+ float skybox_ambient;
+
+ Color ambient_color;
+ float ambient_anergy;
+ float ambient_skybox_energy;
+
+ int canvas_max_layer;
+
+
+ Environment() {
+ bg_mode=VS::ENV_BG_CLEAR_COLOR;
+ skybox_scale=1.0;
+ energy=1.0;
+ skybox_ambient=0;
+ ambient_anergy=1.0;
+ ambient_skybox_energy=0.0;
+ canvas_max_layer=0;
+ }
+ };
+
+ RID_Owner<Environment> environment_owner;
+
+ virtual RID environment_create();
+
+ virtual void environment_set_background(RID p_env,VS::EnvironmentBG p_bg);
+ virtual void environment_set_skybox(RID p_env,RID p_skybox,int p_radiance_size,int p_irradiance_size);
+ virtual void environment_set_skybox_scale(RID p_env,float p_scale);
+ virtual void environment_set_bg_color(RID p_env,const Color& p_color);
+ virtual void environment_set_bg_energy(RID p_env,float p_energy);
+ virtual void environment_set_canvas_max_layer(RID p_env,int p_max_layer);
+ virtual void environment_set_ambient_light(RID p_env,const Color& p_color,float p_energy=1.0,float p_skybox_energy=0.0);
+
+ virtual void environment_set_glow(RID p_env,bool p_enable,int p_radius,float p_intensity,float p_strength,float p_bloom_treshold,VS::EnvironmentGlowBlendMode p_blend_mode);
+ virtual void environment_set_fog(RID p_env,bool p_enable,float p_begin,float p_end,RID p_gradient_texture);
+
+ virtual void environment_set_tonemap(RID p_env,bool p_enable,float p_exposure,float p_white,float p_min_luminance,float p_max_luminance,float p_auto_exp_speed,VS::EnvironmentToneMapper p_tone_mapper);
+ virtual void environment_set_brightness(RID p_env,bool p_enable,float p_brightness);
+ virtual void environment_set_contrast(RID p_env,bool p_enable,float p_contrast);
+ virtual void environment_set_saturation(RID p_env,bool p_enable,float p_saturation);
+ virtual void environment_set_color_correction(RID p_env,bool p_enable,RID p_ramp);
+
+ /* RENDER LIST */
+
struct RenderList {
enum {
@@ -166,6 +224,8 @@ public:
_FORCE_INLINE_ void _add_geometry( RasterizerStorageGLES3::Geometry* p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner,int p_material);
+ void _draw_skybox(RID p_skybox, CameraMatrix& p_projection, const Transform& p_transform, bool p_vflip, float p_scale);
+
virtual void render_scene(const Transform& p_cam_transform,CameraMatrix& p_cam_projection,bool p_cam_ortogonal,InstanceBase** p_cull_result,int p_cull_count,RID* p_light_cull_result,int p_light_cull_count,RID* p_directional_lights,int p_directional_light_count,RID p_environment);
virtual bool free(RID p_rid);
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index f633ef21cc..94ad2afabe 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -995,6 +995,104 @@ void RasterizerStorageGLES3::texture_set_shrink_all_x2_on_set_data(bool p_enable
config.shrink_textures_x2=p_enable;
}
+RID RasterizerStorageGLES3::texture_create_pbr_cubemap(RID p_source,VS::PBRCubeMapMode p_mode,int p_resolution) const {
+
+ Texture * texture = texture_owner.get(p_source);
+ ERR_FAIL_COND_V(!texture,RID());
+ ERR_FAIL_COND_V(!(texture->flags&VS::TEXTURE_FLAG_CUBEMAP),RID());
+
+ bool use_float=true;
+
+ if (p_resolution<0) {
+ p_resolution=texture->width;
+ }
+
+
+ glBindVertexArray(0);
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_SCISSOR_TEST);
+#ifdef GLEW_ENABLED
+ glDisable(GL_POINT_SPRITE);
+ glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
+#endif
+ glDisable(GL_BLEND);
+
+
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(texture->target, texture->tex_id);
+
+ glActiveTexture(GL_TEXTURE0);
+ GLuint new_cubemap;
+ glGenTextures(1, &new_cubemap);
+
+
+ GLuint tmp_fb;
+
+ glGenFramebuffers(1, &tmp_fb);
+ glBindFramebuffer(GL_FRAMEBUFFER, tmp_fb);
+
+
+ int w = texture->width;
+ int h = texture->height;
+
+ int lod=0;
+
+ shaders.cubemap_filter.bind();
+
+ int mipmaps=6;
+
+ int mm_level=mipmaps;
+
+ while(mm_level) {
+
+ for(int i=0;i<6;i++) {
+ glTexImage2D(_cube_side_enum[i], lod, use_float?GL_RGBA16F:GL_RGB10_A2, w, h, 0, GL_RGBA, use_float?GL_HALF_FLOAT:GL_UNSIGNED_INT_2_10_10_10_REV, NULL);
+ glTexParameteri(_cube_side_enum[i], GL_TEXTURE_BASE_LEVEL, lod);
+ glTexParameteri(_cube_side_enum[i], GL_TEXTURE_MAX_LEVEL, lod);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, _cube_side_enum[i], new_cubemap, 0);
+
+ glViewport(0,0,w,h);
+ glBindVertexArray(resources.quadie_array);
+
+ shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::FACE_ID,i);
+ shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::ROUGHNESS,lod/float(mipmaps));
+
+
+ glDrawArrays(GL_TRIANGLE_FAN,0,4);
+ glBindVertexArray(0);
+#ifdef DEBUG_ENABLED
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ ERR_CONTINUE(status!=GL_FRAMEBUFFER_COMPLETE);
+#endif
+ }
+
+
+
+ if (w>1)
+ w>>=1;
+ if (h>1)
+ h>>=1;
+
+ lod++;
+ mm_level--;
+
+ }
+
+
+ for(int i=0;i<6;i++) {
+ //restore ranges
+ glTexParameteri(_cube_side_enum[i], GL_TEXTURE_BASE_LEVEL, 0);
+ glTexParameteri(_cube_side_enum[i], GL_TEXTURE_MAX_LEVEL, lod);
+
+ }
+
+ glBindFramebuffer(GL_FRAMEBUFFER, config.system_fbo);
+ glDeleteFramebuffers(1, &tmp_fb);
+
+
+ return RID();
+}
/* SHADER API */
@@ -3649,6 +3747,45 @@ void RasterizerStorageGLES3::initialize() {
#else
config.use_rgba_2d_shadows=true;
#endif
+
+
+ //generic quadie for copying
+
+ {
+ //quad buffers
+
+ glGenBuffers(1,&resources.quadie);
+ glBindBuffer(GL_ARRAY_BUFFER,resources.quadie);
+ {
+ const float qv[16]={
+ -1,-1,
+ 0, 0,
+ -1, 1,
+ 0, 1,
+ 1, 1,
+ 1, 1,
+ 1,-1,
+ 1, 0,
+ };
+
+ glBufferData(GL_ARRAY_BUFFER,sizeof(float)*16,qv,GL_STATIC_DRAW);
+ }
+
+ glBindBuffer(GL_ARRAY_BUFFER,0); //unbind
+
+
+ glGenVertexArrays(1,&resources.quadie_array);
+ glBindVertexArray(resources.quadie_array);
+ glBindBuffer(GL_ARRAY_BUFFER,resources.quadie);
+ glVertexAttribPointer(0,2,GL_FLOAT,GL_FALSE,sizeof(float)*4,0);
+ glEnableVertexAttribArray(0);
+ glVertexAttribPointer(1,2,GL_FLOAT,GL_FALSE,sizeof(float)*4,((uint8_t*)NULL)+8);
+ glEnableVertexAttribArray(1);
+ glBindVertexArray(0);
+ glBindBuffer(GL_ARRAY_BUFFER,0); //unbind
+ }
+
+ shaders.cubemap_filter.init();
}
void RasterizerStorageGLES3::finalize() {
diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h
index 950d65b9d0..c3022b3ac0 100644
--- a/drivers/gles3/rasterizer_storage_gles3.h
+++ b/drivers/gles3/rasterizer_storage_gles3.h
@@ -6,6 +6,7 @@
#include "shader_gles3.h"
#include "shaders/copy.glsl.h"
#include "shaders/canvas.glsl.h"
+#include "shaders/cubemap_filter.glsl.h"
#include "self_list.h"
#include "shader_compiler_gles3.h"
@@ -60,6 +61,8 @@ public:
ShaderCompilerGLES3 compiler;
+ CubemapFilterShaderGLES3 cubemap_filter;
+
ShaderCompilerGLES3::IdentifierActions actions_canvas;
ShaderCompilerGLES3::IdentifierActions actions_scene;
} shaders;
@@ -70,6 +73,9 @@ public:
GLuint black_tex;
GLuint normal_tex;
+ GLuint quadie;
+ GLuint quadie_array;
+
} resources;
struct Info {
@@ -178,6 +184,8 @@ public:
virtual void texture_debug_usage(List<VS::TextureInfo> *r_info);
+ virtual RID texture_create_pbr_cubemap(RID p_source,VS::PBRCubeMapMode p_mode,int p_resolution=-1) const;
+
/* SHADER API */
diff --git a/drivers/gles3/shaders/SCsub b/drivers/gles3/shaders/SCsub
index 0fa0e3b73a..afffe10316 100644
--- a/drivers/gles3/shaders/SCsub
+++ b/drivers/gles3/shaders/SCsub
@@ -5,4 +5,5 @@ if env['BUILDERS'].has_key('GLES3_GLSL'):
env.GLES3_GLSL('canvas.glsl');
env.GLES3_GLSL('canvas_shadow.glsl');
env.GLES3_GLSL('scene.glsl');
+ env.GLES3_GLSL('cubemap_filter.glsl');
diff --git a/drivers/gles3/shaders/copy.glsl b/drivers/gles3/shaders/copy.glsl
index aba280186a..eb58d66431 100644
--- a/drivers/gles3/shaders/copy.glsl
+++ b/drivers/gles3/shaders/copy.glsl
@@ -33,20 +33,31 @@ void main() {
#ifdef USE_CUBEMAP
in vec3 cube_interp;
-uniform samplerCube source_cube;
+uniform samplerCube source_cube; //texunit:0
#else
in vec2 uv_interp;
-uniform sampler2D source;
+uniform sampler2D source; //texunit:0
#endif
+
+uniform float stuff;
+
in vec2 uv2_interp;
-layout(location = 0) vec4 frag_color; //color:0
+layout(location = 0) out vec4 frag_color;
void main() {
//vec4 color = color_interp;
+#ifdef USE_CUBEMAP
+ vec4 color = texture( source_cube, normalize(cube_interp) );
+
+#else
+ vec4 color = texture( source, uv_interp );
+#endif
+
+
frag_color = color;
}
diff --git a/drivers/gles3/shaders/cubemap_filter.glsl b/drivers/gles3/shaders/cubemap_filter.glsl
new file mode 100644
index 0000000000..f450f34113
--- /dev/null
+++ b/drivers/gles3/shaders/cubemap_filter.glsl
@@ -0,0 +1,143 @@
+[vertex]
+
+
+layout(location=0) in highp vec2 vertex;
+
+layout(location=1) in highp vec2 uv;
+
+out highp vec2 uv_interp;
+
+void main() {
+
+ uv_interp=uv;
+ gl_Position=vec4(vertex,0,1);
+}
+
+[fragment]
+
+
+uniform samplerCube source_cube; //texunit:1
+uniform int face_id;
+uniform float roughness;
+in highp vec2 uv_interp;
+
+
+layout(location = 0) vec4 frag_color;
+
+
+vec3 texelCoordToVec(vec2 uv, int faceID)
+{
+ mat3 faceUvVectors[6];
+
+ // -x
+ faceUvVectors[1][0] = vec3(0.0, 0.0, 1.0); // u -> +z
+ faceUvVectors[1][1] = vec3(0.0, -1.0, 0.0); // v -> -y
+ faceUvVectors[1][2] = vec3(-1.0, 0.0, 0.0); // -x face
+
+ // +x
+ faceUvVectors[0][0] = vec3(0.0, 0.0, -1.0); // u -> -z
+ faceUvVectors[0][1] = vec3(0.0, -1.0, 0.0); // v -> -y
+ faceUvVectors[0][2] = vec3(1.0, 0.0, 0.0); // +x face
+
+ // -y
+ faceUvVectors[3][0] = vec3(1.0, 0.0, 0.0); // u -> +x
+ faceUvVectors[3][1] = vec3(0.0, 0.0, -1.0); // v -> -z
+ faceUvVectors[3][2] = vec3(0.0, -1.0, 0.0); // -y face
+
+ // +y
+ faceUvVectors[2][0] = vec3(1.0, 0.0, 0.0); // u -> +x
+ faceUvVectors[2][1] = vec3(0.0, 0.0, 1.0); // v -> +z
+ faceUvVectors[2][2] = vec3(0.0, 1.0, 0.0); // +y face
+
+ // -z
+ faceUvVectors[5][0] = vec3(-1.0, 0.0, 0.0); // u -> -x
+ faceUvVectors[5][1] = vec3(0.0, -1.0, 0.0); // v -> -y
+ faceUvVectors[5][2] = vec3(0.0, 0.0, -1.0); // -z face
+
+ // +z
+ faceUvVectors[4][0] = vec3(1.0, 0.0, 0.0); // u -> +x
+ faceUvVectors[4][1] = vec3(0.0, -1.0, 0.0); // v -> -y
+ faceUvVectors[4][2] = vec3(0.0, 0.0, 1.0); // +z face
+
+ // out = u * s_faceUv[0] + v * s_faceUv[1] + s_faceUv[2].
+ vec3 result = (faceUvVectors[faceID][0] * uv.x) + (faceUvVectors[faceID][1] * uv.y) + faceUvVectors[faceID][2];
+ return normalize(result);
+}
+
+vec3 ImportanceSampleGGX(vec2 Xi, float Roughness, vec3 N)
+{
+ float a = Roughness * Roughness; // DISNEY'S ROUGHNESS [see Burley'12 siggraph]
+
+ // Compute distribution direction
+ float Phi = 2.0 * M_PI * Xi.x;
+ float CosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y));
+ float SinTheta = sqrt(1.0 - CosTheta * CosTheta);
+
+ // Convert to spherical direction
+ vec3 H;
+ H.x = SinTheta * cos(Phi);
+ H.y = SinTheta * sin(Phi);
+ H.z = CosTheta;
+
+ vec3 UpVector = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
+ vec3 TangentX = normalize(cross(UpVector, N));
+ vec3 TangentY = cross(N, TangentX);
+
+ // Tangent to world space
+ return TangentX * H.x + TangentY * H.y + N * H.z;
+}
+
+// http://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html
+float GGX(float NdotV, float a)
+{
+ float k = a / 2.0;
+ return NdotV / (NdotV * (1.0 - k) + k);
+}
+
+// http://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html
+float G_Smith(float a, float nDotV, float nDotL)
+{
+ return GGX(nDotL, a * a) * GGX(nDotV, a * a);
+}
+
+float radicalInverse_VdC(uint bits) {
+ bits = (bits << 16u) | (bits >> 16u);
+ bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
+ bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
+ bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
+ bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
+ return float(bits) * 2.3283064365386963e-10; // / 0x100000000
+}
+
+vec2 Hammersley(uint i, uint N) {
+ return vec2(float(i)/float(N), radicalInverse_VdC(i));
+}
+
+#define SAMPLE_COUNT 1024
+
+void main() {
+
+ vec2 uv = (uv_interp * 2.0) - 1.0;
+ vec3 N = texelCoordToVec(uv, face_id);
+
+ //vec4 color = color_interp;
+ vec4 sum = vec4(0.0, 0.0, 0.0, 0.0);
+
+ for(int sampleNum = 0; sampleNum < SAMPLE_COUNT; sampleNum++) {
+ vec2 xi = Hammersley(sampleNum, SAMPLE_COUNT);
+ vec2 xi = texture2DLod(Texture0, vec2(float(sampleNum) / float(SAMPLE_COUNT), 0.5), 0.0).xy;
+
+ vec3 H = ImportanceSampleGGX( xi, roughness, N );
+ vec3 V = N;
+ vec3 L = normalize(2.0 * dot( V, H ) * H - V);
+
+ float ndotl = max(0.0, dot(N, L));
+ vec3 s = textureCubeLod(u_skyCube, H, 0.0).rgb * ndotl;
+
+ sum += vec4(s, 1.0);
+ }
+ sum /= sum.w;
+
+ frag_color = vec4(sum.rgb, 1.0);
+}
+