Support lights and shadows in GLES2, fixes #21853
This commit is contained in:
parent
6cdcde7114
commit
3bdd1ff387
7 changed files with 852 additions and 30 deletions
|
@ -186,6 +186,42 @@ RasterizerStorageGLES2::Texture *RasterizerCanvasGLES2::_bind_canvas_texture(con
|
|||
glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex);
|
||||
}
|
||||
|
||||
if (p_normal_map == state.current_normal) {
|
||||
//do none
|
||||
state.canvas_shader.set_uniform(CanvasShaderGLES2::USE_DEFAULT_NORMAL, state.current_normal.is_valid());
|
||||
|
||||
} else if (p_normal_map.is_valid()) {
|
||||
|
||||
RasterizerStorageGLES2::Texture *normal_map = storage->texture_owner.getornull(p_normal_map);
|
||||
|
||||
if (!normal_map) {
|
||||
state.current_normal = RID();
|
||||
glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 2);
|
||||
glBindTexture(GL_TEXTURE_2D, storage->resources.normal_tex);
|
||||
state.canvas_shader.set_uniform(CanvasShaderGLES2::USE_DEFAULT_NORMAL, false);
|
||||
|
||||
} else {
|
||||
|
||||
normal_map = normal_map->get_ptr();
|
||||
|
||||
if (normal_map->redraw_if_visible) { //check before proxy, because this is usually used with proxies
|
||||
VisualServerRaster::redraw_request();
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 2);
|
||||
glBindTexture(GL_TEXTURE_2D, normal_map->tex_id);
|
||||
state.current_normal = p_normal_map;
|
||||
state.canvas_shader.set_uniform(CanvasShaderGLES2::USE_DEFAULT_NORMAL, true);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
state.current_normal = RID();
|
||||
glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 2);
|
||||
glBindTexture(GL_TEXTURE_2D, storage->resources.normal_tex);
|
||||
state.canvas_shader.set_uniform(CanvasShaderGLES2::USE_DEFAULT_NORMAL, false);
|
||||
}
|
||||
|
||||
return tex_return;
|
||||
}
|
||||
|
||||
|
@ -1053,10 +1089,164 @@ void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, cons
|
|||
|
||||
_set_uniforms();
|
||||
|
||||
_canvas_item_render_commands(p_item_list, NULL, reclip, material_ptr);
|
||||
if (unshaded || (state.uniforms.final_modulate.a > 0.001 && (!shader_cache || shader_cache->canvas_item.light_mode != RasterizerStorageGLES2::Shader::CanvasItem::LIGHT_MODE_LIGHT_ONLY) && !ci->light_masked))
|
||||
_canvas_item_render_commands(p_item_list, NULL, reclip, material_ptr);
|
||||
|
||||
rebind_shader = true; // hacked in for now.
|
||||
|
||||
if ((blend_mode == RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_MIX || blend_mode == RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_PMALPHA) && p_light && !unshaded) {
|
||||
|
||||
Light *light = p_light;
|
||||
bool light_used = false;
|
||||
VS::CanvasLightMode mode = VS::CANVAS_LIGHT_MODE_ADD;
|
||||
state.uniforms.final_modulate = ci->final_modulate; // remove the canvas modulate
|
||||
|
||||
while (light) {
|
||||
|
||||
if (ci->light_mask & light->item_mask && p_z >= light->z_min && p_z <= light->z_max && ci->global_rect_cache.intersects_transformed(light->xform_cache, light->rect_cache)) {
|
||||
|
||||
//intersects this light
|
||||
|
||||
if (!light_used || mode != light->mode) {
|
||||
|
||||
mode = light->mode;
|
||||
|
||||
switch (mode) {
|
||||
|
||||
case VS::CANVAS_LIGHT_MODE_ADD: {
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
||||
|
||||
} break;
|
||||
case VS::CANVAS_LIGHT_MODE_SUB: {
|
||||
glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
||||
} break;
|
||||
case VS::CANVAS_LIGHT_MODE_MIX:
|
||||
case VS::CANVAS_LIGHT_MODE_MASK: {
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!light_used) {
|
||||
|
||||
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_LIGHTING, true);
|
||||
light_used = true;
|
||||
}
|
||||
|
||||
bool has_shadow = light->shadow_buffer.is_valid() && ci->light_mask & light->item_shadow_mask;
|
||||
|
||||
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_SHADOWS, has_shadow);
|
||||
if (has_shadow) {
|
||||
state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_USE_GRADIENT, light->shadow_gradient_length > 0);
|
||||
switch (light->shadow_filter) {
|
||||
|
||||
case VS::CANVAS_LIGHT_FILTER_NONE: state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_NEAREST, true); break;
|
||||
case VS::CANVAS_LIGHT_FILTER_PCF3: state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF3, true); break;
|
||||
case VS::CANVAS_LIGHT_FILTER_PCF5: state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF5, true); break;
|
||||
case VS::CANVAS_LIGHT_FILTER_PCF7: state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF7, true); break;
|
||||
case VS::CANVAS_LIGHT_FILTER_PCF9: state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF9, true); break;
|
||||
case VS::CANVAS_LIGHT_FILTER_PCF13: state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF13, true); break;
|
||||
}
|
||||
}
|
||||
|
||||
bool light_rebind = state.canvas_shader.bind();
|
||||
|
||||
if (light_rebind) {
|
||||
|
||||
_set_uniforms();
|
||||
}
|
||||
|
||||
state.canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_MATRIX, light->light_shader_xform);
|
||||
Transform2D basis_inverse = light->light_shader_xform.affine_inverse().orthonormalized();
|
||||
basis_inverse[2] = Vector2();
|
||||
state.canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_MATRIX_INVERSE, basis_inverse);
|
||||
state.canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_LOCAL_MATRIX, light->xform_cache.affine_inverse());
|
||||
state.canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_COLOR, light->color * light->energy);
|
||||
state.canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_POS, light->light_shader_pos);
|
||||
state.canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_HEIGHT, light->height);
|
||||
state.canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_OUTSIDE_ALPHA, light->mode == VS::CANVAS_LIGHT_MODE_MASK ? 1.0 : 0.0);
|
||||
|
||||
if (has_shadow) {
|
||||
RasterizerStorageGLES2::CanvasLightShadow *cls = storage->canvas_light_shadow_owner.get(light->shadow_buffer);
|
||||
glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4);
|
||||
glBindTexture(GL_TEXTURE_2D, cls->distance);
|
||||
state.canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_MATRIX, light->shadow_matrix_cache);
|
||||
state.canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_SHADOW_COLOR, light->shadow_color);
|
||||
state.canvas_shader.set_uniform(CanvasShaderGLES2::SHADOWPIXEL_SIZE, (1.0 / light->shadow_buffer_size) * (1.0 + light->shadow_smooth));
|
||||
if (light->radius_cache == 0) {
|
||||
state.canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_GRADIENT, 0.0);
|
||||
} else {
|
||||
state.canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_GRADIENT, light->shadow_gradient_length / (light->radius_cache * 1.1));
|
||||
}
|
||||
state.canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_DISTANCE_MULT, light->radius_cache * 1.1);
|
||||
|
||||
/*canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_MATRIX,light->shadow_matrix_cache);
|
||||
canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_ESM_MULTIPLIER,light->shadow_esm_mult);
|
||||
canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_SHADOW_COLOR,light->shadow_color);*/
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 3);
|
||||
RasterizerStorageGLES2::Texture *t = storage->texture_owner.getornull(light->texture);
|
||||
if (!t) {
|
||||
glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex);
|
||||
} else {
|
||||
t = t->get_ptr();
|
||||
|
||||
glBindTexture(t->target, t->tex_id);
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
_canvas_item_render_commands(p_item_list, NULL, reclip, material_ptr); //redraw using light
|
||||
}
|
||||
|
||||
light = light->next_ptr;
|
||||
}
|
||||
|
||||
if (light_used) {
|
||||
|
||||
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_LIGHTING, false);
|
||||
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_SHADOWS, false);
|
||||
state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_NEAREST, false);
|
||||
state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF3, false);
|
||||
state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF5, false);
|
||||
state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF7, false);
|
||||
state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF9, false);
|
||||
state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF13, false);
|
||||
|
||||
state.canvas_shader.bind();
|
||||
|
||||
last_blend_mode = -1;
|
||||
|
||||
/*
|
||||
//this is set again, so it should not be needed anyway?
|
||||
state.canvas_item_modulate = unshaded ? ci->final_modulate : Color(
|
||||
ci->final_modulate.r * p_modulate.r,
|
||||
ci->final_modulate.g * p_modulate.g,
|
||||
ci->final_modulate.b * p_modulate.b,
|
||||
ci->final_modulate.a * p_modulate.a );
|
||||
|
||||
|
||||
state.canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX,state.final_transform);
|
||||
state.canvas_shader.set_uniform(CanvasShaderGLES2::EXTRA_MATRIX,Transform2D());
|
||||
state.canvas_shader.set_uniform(CanvasShaderGLES2::FINAL_MODULATE,state.canvas_item_modulate);
|
||||
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
|
||||
if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
} else {
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
//@TODO RESET canvas_blend_mode
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
if (reclip) {
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
int y = storage->frame.current_rt->height - (current_clip->final_clip_rect.position.y + current_clip->final_clip_rect.size.y);
|
||||
|
@ -1077,8 +1267,116 @@ void RasterizerCanvasGLES2::canvas_debug_viewport_shadows(Light *p_lights_with_s
|
|||
}
|
||||
|
||||
void RasterizerCanvasGLES2::canvas_light_shadow_buffer_update(RID p_buffer, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders, CameraMatrix *p_xform_cache) {
|
||||
}
|
||||
|
||||
RasterizerStorageGLES2::CanvasLightShadow *cls = storage->canvas_light_shadow_owner.get(p_buffer);
|
||||
ERR_FAIL_COND(!cls);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glDisable(GL_DITHER);
|
||||
glDisable(GL_CULL_FACE);
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(true);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, cls->fbo);
|
||||
|
||||
state.canvas_shadow_shader.set_conditional(CanvasShadowShaderGLES2::USE_RGBA_SHADOWS, storage->config.use_rgba_2d_shadows);
|
||||
state.canvas_shadow_shader.bind();
|
||||
|
||||
glViewport(0, 0, cls->size, cls->height);
|
||||
glClearDepth(1.0f);
|
||||
glClearColor(1, 1, 1, 1);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
VS::CanvasOccluderPolygonCullMode cull = VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
|
||||
//make sure it remains orthogonal, makes easy to read angle later
|
||||
|
||||
Transform light;
|
||||
light.origin[0] = p_light_xform[2][0];
|
||||
light.origin[1] = p_light_xform[2][1];
|
||||
light.basis[0][0] = p_light_xform[0][0];
|
||||
light.basis[0][1] = p_light_xform[1][0];
|
||||
light.basis[1][0] = p_light_xform[0][1];
|
||||
light.basis[1][1] = p_light_xform[1][1];
|
||||
|
||||
//light.basis.scale(Vector3(to_light.elements[0].length(),to_light.elements[1].length(),1));
|
||||
|
||||
//p_near=1;
|
||||
CameraMatrix projection;
|
||||
{
|
||||
real_t fov = 90;
|
||||
real_t nearp = p_near;
|
||||
real_t farp = p_far;
|
||||
real_t aspect = 1.0;
|
||||
|
||||
real_t ymax = nearp * Math::tan(Math::deg2rad(fov * 0.5));
|
||||
real_t ymin = -ymax;
|
||||
real_t xmin = ymin * aspect;
|
||||
real_t xmax = ymax * aspect;
|
||||
|
||||
projection.set_frustum(xmin, xmax, ymin, ymax, nearp, farp);
|
||||
}
|
||||
|
||||
Vector3 cam_target = Basis(Vector3(0, 0, Math_PI * 2 * (i / 4.0))).xform(Vector3(0, 1, 0));
|
||||
projection = projection * CameraMatrix(Transform().looking_at(cam_target, Vector3(0, 0, -1)).affine_inverse());
|
||||
|
||||
state.canvas_shadow_shader.set_uniform(CanvasShadowShaderGLES2::PROJECTION_MATRIX, projection);
|
||||
state.canvas_shadow_shader.set_uniform(CanvasShadowShaderGLES2::LIGHT_MATRIX, light);
|
||||
state.canvas_shadow_shader.set_uniform(CanvasShadowShaderGLES2::DISTANCE_NORM, 1.0 / p_far);
|
||||
|
||||
if (i == 0)
|
||||
*p_xform_cache = projection;
|
||||
|
||||
glViewport(0, (cls->height / 4) * i, cls->size, cls->height / 4);
|
||||
|
||||
LightOccluderInstance *instance = p_occluders;
|
||||
|
||||
while (instance) {
|
||||
|
||||
RasterizerStorageGLES2::CanvasOccluder *cc = storage->canvas_occluder_owner.get(instance->polygon_buffer);
|
||||
if (!cc || cc->len == 0 || !(p_light_mask & instance->light_mask)) {
|
||||
|
||||
instance = instance->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
state.canvas_shadow_shader.set_uniform(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;
|
||||
}
|
||||
}
|
||||
|
||||
glBindVertexArray(cc->array_id);
|
||||
glDrawElements(GL_TRIANGLES, cc->len * 3, GL_UNSIGNED_SHORT, 0);
|
||||
|
||||
instance = instance->next;
|
||||
}
|
||||
}
|
||||
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
void RasterizerCanvasGLES2::reset_canvas() {
|
||||
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
@ -1094,7 +1392,7 @@ void RasterizerCanvasGLES2::reset_canvas() {
|
|||
}
|
||||
|
||||
// bind the back buffer to a texture so shaders can use it.
|
||||
// It should probably use texture unit -3 (as GLES3 does as well) but currently that's buggy.
|
||||
// It should probably use texture unit -3 (as GLES2 does as well) but currently that's buggy.
|
||||
// keeping this for now as there's nothing else that uses texture unit 2
|
||||
// TODO ^
|
||||
if (storage->frame.current_rt) {
|
||||
|
@ -1264,6 +1562,8 @@ void RasterizerCanvasGLES2::initialize() {
|
|||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
state.canvas_shadow_shader.init();
|
||||
|
||||
state.canvas_shader.init();
|
||||
|
||||
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, true);
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
#include "shaders/canvas.glsl.gen.h"
|
||||
#include "shaders/lens_distorted.glsl.gen.h"
|
||||
|
||||
// #include "shaders/canvas_shadow.glsl.gen.h"
|
||||
#include "shaders/canvas_shadow.glsl.gen.h"
|
||||
|
||||
class RasterizerSceneGLES2;
|
||||
|
||||
|
@ -70,7 +70,7 @@ public:
|
|||
Uniforms uniforms;
|
||||
bool canvas_texscreen_used;
|
||||
CanvasShaderGLES2 canvas_shader;
|
||||
// CanvasShadowShaderGLES3 canvas_shadow_shader;
|
||||
CanvasShadowShaderGLES2 canvas_shadow_shader;
|
||||
LensDistortedShaderGLES2 lens_shader;
|
||||
|
||||
bool using_texture_rect;
|
||||
|
|
|
@ -1138,6 +1138,7 @@ void RasterizerStorageGLES2::_update_shader(Shader *p_shader) const {
|
|||
|
||||
case VS::SHADER_CANVAS_ITEM: {
|
||||
|
||||
p_shader->canvas_item.light_mode = Shader::CanvasItem::LIGHT_MODE_NORMAL;
|
||||
p_shader->canvas_item.blend_mode = Shader::CanvasItem::BLEND_MODE_MIX;
|
||||
|
||||
p_shader->canvas_item.uses_screen_texture = false;
|
||||
|
@ -1150,8 +1151,8 @@ void RasterizerStorageGLES2::_update_shader(Shader *p_shader) const {
|
|||
shaders.actions_canvas.render_mode_values["blend_mul"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_MUL);
|
||||
shaders.actions_canvas.render_mode_values["blend_premul_alpha"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_PMALPHA);
|
||||
|
||||
// shaders.actions_canvas.render_mode_values["unshaded"] = Pair<int *, int>(&p_shader->canvas_item.light_mode, Shader::CanvasItem::LIGHT_MODE_UNSHADED);
|
||||
// shaders.actions_canvas.render_mode_values["light_only"] = Pair<int *, int>(&p_shader->canvas_item.light_mode, Shader::CanvasItem::LIGHT_MODE_LIGHT_ONLY);
|
||||
shaders.actions_canvas.render_mode_values["unshaded"] = Pair<int *, int>(&p_shader->canvas_item.light_mode, Shader::CanvasItem::LIGHT_MODE_UNSHADED);
|
||||
shaders.actions_canvas.render_mode_values["light_only"] = Pair<int *, int>(&p_shader->canvas_item.light_mode, Shader::CanvasItem::LIGHT_MODE_LIGHT_ONLY);
|
||||
|
||||
shaders.actions_canvas.usage_flag_pointers["SCREEN_UV"] = &p_shader->canvas_item.uses_screen_uv;
|
||||
shaders.actions_canvas.usage_flag_pointers["SCREEN_PIXEL_SIZE"] = &p_shader->canvas_item.uses_screen_uv;
|
||||
|
@ -4193,16 +4194,161 @@ void RasterizerStorageGLES2::render_target_set_msaa(RID p_render_target, VS::Vie
|
|||
/* CANVAS SHADOW */
|
||||
|
||||
RID RasterizerStorageGLES2::canvas_light_shadow_buffer_create(int p_width) {
|
||||
return RID();
|
||||
|
||||
CanvasLightShadow *cls = memnew(CanvasLightShadow);
|
||||
if (p_width > config.max_texture_size)
|
||||
p_width = config.max_texture_size;
|
||||
|
||||
cls->size = p_width;
|
||||
cls->height = 16;
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
glGenFramebuffers(1, &cls->fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, cls->fbo);
|
||||
|
||||
glGenRenderbuffers(1, &cls->depth);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, cls->depth);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, cls->size, cls->height);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, cls->depth);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
|
||||
glGenTextures(1, &cls->distance);
|
||||
glBindTexture(GL_TEXTURE_2D, cls->distance);
|
||||
if (config.use_rgba_2d_shadows) {
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, cls->size, cls->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
} else {
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, cls->size, cls->height, 0, GL_RED, GL_FLOAT, NULL);
|
||||
}
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, cls->distance, 0);
|
||||
|
||||
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
//printf("errnum: %x\n",status);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES2::system_fbo);
|
||||
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
||||
memdelete(cls);
|
||||
ERR_FAIL_COND_V(status != GL_FRAMEBUFFER_COMPLETE, RID());
|
||||
}
|
||||
|
||||
return canvas_light_shadow_owner.make_rid(cls);
|
||||
}
|
||||
|
||||
/* LIGHT SHADOW MAPPING */
|
||||
|
||||
RID RasterizerStorageGLES2::canvas_light_occluder_create() {
|
||||
return RID();
|
||||
|
||||
CanvasOccluder *co = memnew(CanvasOccluder);
|
||||
co->index_id = 0;
|
||||
co->vertex_id = 0;
|
||||
co->len = 0;
|
||||
glGenVertexArrays(1, &co->array_id);
|
||||
|
||||
return canvas_occluder_owner.make_rid(co);
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES2::canvas_light_occluder_set_polylines(RID p_occluder, const PoolVector<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()) {
|
||||
|
||||
PoolVector<float> geometry;
|
||||
PoolVector<uint16_t> indices;
|
||||
int lc = p_lines.size();
|
||||
|
||||
geometry.resize(lc * 6);
|
||||
indices.resize(lc * 3);
|
||||
|
||||
PoolVector<float>::Write vw = geometry.write();
|
||||
PoolVector<uint16_t>::Write iw = indices.write();
|
||||
|
||||
PoolVector<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_DYNAMIC_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;
|
||||
glBindVertexArray(co->array_id);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, co->vertex_id);
|
||||
glEnableVertexAttribArray(VS::ARRAY_VERTEX);
|
||||
glVertexAttribPointer(VS::ARRAY_VERTEX, 3, GL_FLOAT, false, 0, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, co->index_id);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
}
|
||||
|
||||
VS::InstanceType RasterizerStorageGLES2::get_base_type(RID p_rid) const {
|
||||
|
@ -4415,6 +4561,32 @@ bool RasterizerStorageGLES2::free(RID p_rid) {
|
|||
lightmap_capture_data_owner.free(p_rid);
|
||||
memdelete(lightmap_capture);
|
||||
return true;
|
||||
|
||||
} 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);
|
||||
|
||||
glDeleteVertexArrays(1, &co->array_id);
|
||||
|
||||
canvas_occluder_owner.free(p_rid);
|
||||
memdelete(co);
|
||||
|
||||
return true;
|
||||
|
||||
} else if (canvas_light_shadow_owner.owns(p_rid)) {
|
||||
|
||||
CanvasLightShadow *cls = canvas_light_shadow_owner.get(p_rid);
|
||||
glDeleteFramebuffers(1, &cls->fbo);
|
||||
glDeleteRenderbuffers(1, &cls->depth);
|
||||
glDeleteTextures(1, &cls->distance);
|
||||
canvas_light_shadow_owner.free(p_rid);
|
||||
memdelete(cls);
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
@ -4471,6 +4643,7 @@ void RasterizerStorageGLES2::initialize() {
|
|||
config.float_texture_supported = config.extensions.has("GL_ARB_texture_float") || config.extensions.has("GL_OES_texture_float");
|
||||
config.s3tc_supported = config.extensions.has("GL_EXT_texture_compression_s3tc");
|
||||
config.etc1_supported = config.extensions.has("GL_OES_compressed_ETC1_RGB8_texture");
|
||||
config.use_rgba_2d_shadows = false;
|
||||
|
||||
frame.count = 0;
|
||||
frame.delta = 0;
|
||||
|
|
|
@ -76,6 +76,8 @@ public:
|
|||
bool keep_original_textures;
|
||||
|
||||
bool force_vertex_shading;
|
||||
|
||||
bool use_rgba_2d_shadows;
|
||||
} config;
|
||||
|
||||
struct Resources {
|
||||
|
@ -86,6 +88,7 @@ public:
|
|||
GLuint aniso_tex;
|
||||
|
||||
GLuint radical_inverse_vdc_cache_tex;
|
||||
bool use_rgba_2d_shadows;
|
||||
|
||||
GLuint quadie;
|
||||
|
||||
|
@ -400,7 +403,6 @@ public:
|
|||
|
||||
int blend_mode;
|
||||
|
||||
/*
|
||||
enum LightMode {
|
||||
LIGHT_MODE_NORMAL,
|
||||
LIGHT_MODE_UNSHADED,
|
||||
|
@ -408,7 +410,6 @@ public:
|
|||
};
|
||||
|
||||
int light_mode;
|
||||
*/
|
||||
|
||||
bool uses_screen_texture;
|
||||
bool uses_screen_uv;
|
||||
|
@ -1161,10 +1162,32 @@ public:
|
|||
|
||||
/* CANVAS SHADOW */
|
||||
|
||||
struct CanvasLightShadow : public RID_Data {
|
||||
|
||||
int size;
|
||||
int height;
|
||||
GLuint fbo;
|
||||
GLuint depth;
|
||||
GLuint distance; //for older devices
|
||||
};
|
||||
|
||||
RID_Owner<CanvasLightShadow> canvas_light_shadow_owner;
|
||||
|
||||
virtual RID canvas_light_shadow_buffer_create(int p_width);
|
||||
|
||||
/* LIGHT SHADOW MAPPING */
|
||||
|
||||
struct CanvasOccluder : public RID_Data {
|
||||
|
||||
GLuint array_id; // 0 means, unconfigured
|
||||
GLuint vertex_id; // 0 means, unconfigured
|
||||
GLuint index_id; // 0 means, unconfigured
|
||||
PoolVector<Vector2> lines;
|
||||
int len;
|
||||
};
|
||||
|
||||
RID_Owner<CanvasOccluder> canvas_occluder_owner;
|
||||
|
||||
virtual RID canvas_light_occluder_create();
|
||||
virtual void canvas_light_occluder_set_polylines(RID p_occluder, const PoolVector<Vector2> &p_lines);
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ if 'GLES2_GLSL' in env['BUILDERS']:
|
|||
env.GLES2_GLSL('copy.glsl');
|
||||
# env.GLES2_GLSL('resolve.glsl');
|
||||
env.GLES2_GLSL('canvas.glsl');
|
||||
# env.GLES2_GLSL('canvas_shadow.glsl');
|
||||
env.GLES2_GLSL('canvas_shadow.glsl');
|
||||
env.GLES2_GLSL('scene.glsl');
|
||||
env.GLES2_GLSL('cubemap_filter.glsl');
|
||||
env.GLES2_GLSL('cube_to_dp.glsl');
|
||||
|
|
|
@ -31,6 +31,38 @@ uniform vec4 src_rect;
|
|||
|
||||
uniform highp float time;
|
||||
|
||||
|
||||
|
||||
#ifdef USE_LIGHTING
|
||||
|
||||
// light matrices
|
||||
uniform highp mat4 light_matrix;
|
||||
uniform highp mat4 light_matrix_inverse;
|
||||
uniform highp mat4 light_local_matrix;
|
||||
uniform highp mat4 shadow_matrix;
|
||||
uniform highp vec4 light_color;
|
||||
uniform highp vec4 light_shadow_color;
|
||||
uniform highp vec2 light_pos;
|
||||
uniform highp float shadowpixel_size;
|
||||
uniform highp float shadow_gradient;
|
||||
uniform highp float light_height;
|
||||
uniform highp float light_outside_alpha;
|
||||
uniform highp float shadow_distance_mult;
|
||||
|
||||
varying vec4 light_uv_interp;
|
||||
varying vec2 transformed_light_uv;
|
||||
varying vec4 local_rot;
|
||||
|
||||
#ifdef USE_SHADOWS
|
||||
varying highp vec2 pos;
|
||||
#endif
|
||||
|
||||
const bool at_light_pass = true;
|
||||
#else
|
||||
const bool at_light_pass = false;
|
||||
#endif
|
||||
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
VERTEX_SHADER_GLOBALS
|
||||
|
@ -48,8 +80,19 @@ vec2 select(vec2 a, vec2 b, bvec2 c) {
|
|||
|
||||
void main() {
|
||||
|
||||
|
||||
vec4 color = color_attrib;
|
||||
|
||||
#ifdef USE_INSTANCING
|
||||
mat4 extra_matrix_instance = extra_matrix * transpose(mat4(instance_xform0, instance_xform1, instance_xform2, vec4(0.0, 0.0, 0.0, 1.0)));
|
||||
color *= instance_color;
|
||||
vec4 instance_custom = instance_custom_data;
|
||||
|
||||
#else
|
||||
mat4 extra_matrix_instance = extra_matrix;
|
||||
vec4 instance_custom = vec4(0.0);
|
||||
#endif
|
||||
|
||||
#ifdef USE_TEXTURE_RECT
|
||||
|
||||
if (dst_rect.z < 0.0) { // Transpose is encoded as negative dst_rect.z
|
||||
|
@ -96,6 +139,27 @@ VERTEX_SHADER_CODE
|
|||
#endif
|
||||
|
||||
gl_Position = projection_matrix * outvec;
|
||||
|
||||
#ifdef USE_LIGHTING
|
||||
|
||||
light_uv_interp.xy = (light_matrix * outvec).xy;
|
||||
light_uv_interp.zw = (light_local_matrix * outvec).xy;
|
||||
|
||||
transformed_light_uv = (mat3(light_matrix_inverse) * vec3(light_uv_interp.zw, 0.0)).xy; //for normal mapping
|
||||
|
||||
#ifdef USE_SHADOWS
|
||||
pos = outvec.xy;
|
||||
#endif
|
||||
|
||||
local_rot.xy = normalize((modelview_matrix * (extra_matrix_instance * vec4(1.0, 0.0, 0.0, 0.0))).xy);
|
||||
local_rot.zw = normalize((modelview_matrix * (extra_matrix_instance * vec4(0.0, 1.0, 0.0, 0.0))).xy);
|
||||
#ifdef USE_TEXTURE_RECT
|
||||
local_rot.xy *= sign(src_rect.z);
|
||||
local_rot.zw *= sign(src_rect.w);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
|
@ -133,6 +197,41 @@ uniform vec2 screen_pixel_size;
|
|||
|
||||
#endif
|
||||
|
||||
#ifdef USE_LIGHTING
|
||||
|
||||
uniform highp mat4 light_matrix;
|
||||
uniform highp mat4 light_local_matrix;
|
||||
uniform highp mat4 shadow_matrix;
|
||||
uniform highp vec4 light_color;
|
||||
uniform highp vec4 light_shadow_color;
|
||||
uniform highp vec2 light_pos;
|
||||
uniform highp float shadowpixel_size;
|
||||
uniform highp float shadow_gradient;
|
||||
uniform highp float light_height;
|
||||
uniform highp float light_outside_alpha;
|
||||
uniform highp float shadow_distance_mult;
|
||||
|
||||
uniform lowp sampler2D light_texture; // texunit:-3
|
||||
varying vec4 light_uv_interp;
|
||||
varying vec2 transformed_light_uv;
|
||||
|
||||
varying vec4 local_rot;
|
||||
|
||||
#ifdef USE_SHADOWS
|
||||
|
||||
uniform highp sampler2D shadow_texture; // texunit:-4
|
||||
varying highp vec2 pos;
|
||||
|
||||
#endif
|
||||
|
||||
const bool at_light_pass = true;
|
||||
#else
|
||||
const bool at_light_pass = false;
|
||||
#endif
|
||||
|
||||
uniform bool use_default_normal;
|
||||
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
FRAGMENT_SHADER_GLOBALS
|
||||
|
@ -151,15 +250,236 @@ void main() {
|
|||
#ifdef SCREEN_UV_USED
|
||||
vec2 screen_uv = gl_FragCoord.xy * screen_pixel_size;
|
||||
#endif
|
||||
|
||||
vec3 normal;
|
||||
|
||||
#if defined(NORMAL_USED)
|
||||
|
||||
bool normal_used = true;
|
||||
#else
|
||||
bool normal_used = false;
|
||||
#endif
|
||||
|
||||
if (use_default_normal) {
|
||||
normal.xy = texture2D(normal_texture, uv_interp).xy * 2.0 - 1.0;
|
||||
normal.z = sqrt(1.0 - dot(normal.xy, normal.xy));
|
||||
normal_used = true;
|
||||
} else {
|
||||
normal = vec3(0.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
{
|
||||
float normal_depth = 1.0;
|
||||
|
||||
#if defined(NORMALMAP_USED)
|
||||
vec3 normal_map = vec3(0.0, 0.0, 1.0);
|
||||
normal_used = true;
|
||||
#endif
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
FRAGMENT_SHADER_CODE
|
||||
|
||||
/* clang-format on */
|
||||
|
||||
#if defined(NORMALMAP_USED)
|
||||
normal = mix(vec3(0.0, 0.0, 1.0), normal_map * vec3(2.0, -2.0, 1.0) - vec3(1.0, -1.0, 0.0), normal_depth);
|
||||
#endif
|
||||
}
|
||||
color *= final_modulate;
|
||||
|
||||
#ifdef USE_LIGHTING
|
||||
|
||||
vec2 light_vec = transformed_light_uv;
|
||||
|
||||
if (normal_used) {
|
||||
normal.xy = mat2(local_rot.xy, local_rot.zw) * normal.xy;
|
||||
}
|
||||
|
||||
color *= final_modulate;
|
||||
float att = 1.0;
|
||||
|
||||
vec2 light_uv = light_uv_interp.xy;
|
||||
vec4 light = texture2D(light_texture, light_uv);
|
||||
|
||||
if (any(lessThan(light_uv_interp.xy, vec2(0.0, 0.0))) || any(greaterThanEqual(light_uv_interp.xy, vec2(1.0, 1.0)))) {
|
||||
color.a *= light_outside_alpha; //invisible
|
||||
|
||||
} else {
|
||||
float real_light_height = light_height;
|
||||
vec4 real_light_color = light_color;
|
||||
vec4 real_light_shadow_color = light_shadow_color;
|
||||
|
||||
#if defined(USE_LIGHT_SHADER_CODE)
|
||||
//light is written by the light shader
|
||||
light_compute(
|
||||
light,
|
||||
light_vec,
|
||||
real_light_height,
|
||||
real_light_color,
|
||||
light_uv,
|
||||
real_light_shadow_color,
|
||||
normal,
|
||||
uv,
|
||||
#if defined(SCREEN_UV_USED)
|
||||
screen_uv,
|
||||
#endif
|
||||
color);
|
||||
#endif
|
||||
|
||||
light *= real_light_color;
|
||||
|
||||
if (normal_used) {
|
||||
vec3 light_normal = normalize(vec3(light_vec, -real_light_height));
|
||||
light *= max(dot(-light_normal, normal), 0.0);
|
||||
}
|
||||
|
||||
color *= light;
|
||||
|
||||
#ifdef USE_SHADOWS
|
||||
light_vec = light_uv_interp.zw; //for shadows
|
||||
float angle_to_light = -atan(light_vec.x, light_vec.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 = light_vec;
|
||||
sh = 0.0 + (1.0 / 8.0);
|
||||
} else if (abs_angle > 135.0 * PI / 180.0) {
|
||||
point = -light_vec;
|
||||
sh = 0.5 + (1.0 / 8.0);
|
||||
} else if (angle_to_light > 0.0) {
|
||||
|
||||
point = vec2(light_vec.y, -light_vec.x);
|
||||
sh = 0.25 + (1.0 / 8.0);
|
||||
} else {
|
||||
|
||||
point = vec2(-light_vec.y, light_vec.x);
|
||||
sh = 0.75 + (1.0 / 8.0);
|
||||
}
|
||||
|
||||
highp vec4 s = shadow_matrix * vec4(point, 0.0, 1.0);
|
||||
s.xyz /= s.w;
|
||||
su = s.x * 0.5 + 0.5;
|
||||
sz = s.z * 0.5 + 0.5;
|
||||
//sz=lightlength(light_vec);
|
||||
|
||||
highp float shadow_attenuation = 0.0;
|
||||
|
||||
#ifdef USE_RGBA_SHADOWS
|
||||
|
||||
#define SHADOW_DEPTH(m_tex, m_uv) dot(texture2D((m_tex), (m_uv)), vec4(1.0 / (256.0 * 256.0 * 256.0), 1.0 / (256.0 * 256.0), 1.0 / 256.0, 1))
|
||||
|
||||
#else
|
||||
|
||||
#define SHADOW_DEPTH(m_tex, m_uv) (texture2D((m_tex), (m_uv)).r)
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef SHADOW_USE_GRADIENT
|
||||
|
||||
#define SHADOW_TEST(m_ofs) \
|
||||
{ \
|
||||
highp float sd = SHADOW_DEPTH(shadow_texture, vec2(m_ofs, sh)); \
|
||||
shadow_attenuation += 1.0 - smoothstep(sd, sd + shadow_gradient, sz); \
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define SHADOW_TEST(m_ofs) \
|
||||
{ \
|
||||
highp float sd = SHADOW_DEPTH(shadow_texture, vec2(m_ofs, sh)); \
|
||||
shadow_attenuation += step(sz, sd); \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef SHADOW_FILTER_NEAREST
|
||||
|
||||
SHADOW_TEST(su);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef SHADOW_FILTER_PCF3
|
||||
|
||||
SHADOW_TEST(su + shadowpixel_size);
|
||||
SHADOW_TEST(su);
|
||||
SHADOW_TEST(su - shadowpixel_size);
|
||||
shadow_attenuation /= 3.0;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef SHADOW_FILTER_PCF5
|
||||
|
||||
SHADOW_TEST(su + shadowpixel_size * 2.0);
|
||||
SHADOW_TEST(su + shadowpixel_size);
|
||||
SHADOW_TEST(su);
|
||||
SHADOW_TEST(su - shadowpixel_size);
|
||||
SHADOW_TEST(su - shadowpixel_size * 2.0);
|
||||
shadow_attenuation /= 5.0;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef SHADOW_FILTER_PCF7
|
||||
|
||||
SHADOW_TEST(su + shadowpixel_size * 3.0);
|
||||
SHADOW_TEST(su + shadowpixel_size * 2.0);
|
||||
SHADOW_TEST(su + shadowpixel_size);
|
||||
SHADOW_TEST(su);
|
||||
SHADOW_TEST(su - shadowpixel_size);
|
||||
SHADOW_TEST(su - shadowpixel_size * 2.0);
|
||||
SHADOW_TEST(su - shadowpixel_size * 3.0);
|
||||
shadow_attenuation /= 7.0;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef SHADOW_FILTER_PCF9
|
||||
|
||||
SHADOW_TEST(su + shadowpixel_size * 4.0);
|
||||
SHADOW_TEST(su + shadowpixel_size * 3.0);
|
||||
SHADOW_TEST(su + shadowpixel_size * 2.0);
|
||||
SHADOW_TEST(su + shadowpixel_size);
|
||||
SHADOW_TEST(su);
|
||||
SHADOW_TEST(su - shadowpixel_size);
|
||||
SHADOW_TEST(su - shadowpixel_size * 2.0);
|
||||
SHADOW_TEST(su - shadowpixel_size * 3.0);
|
||||
SHADOW_TEST(su - shadowpixel_size * 4.0);
|
||||
shadow_attenuation /= 9.0;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef SHADOW_FILTER_PCF13
|
||||
|
||||
SHADOW_TEST(su + shadowpixel_size * 6.0);
|
||||
SHADOW_TEST(su + shadowpixel_size * 5.0);
|
||||
SHADOW_TEST(su + shadowpixel_size * 4.0);
|
||||
SHADOW_TEST(su + shadowpixel_size * 3.0);
|
||||
SHADOW_TEST(su + shadowpixel_size * 2.0);
|
||||
SHADOW_TEST(su + shadowpixel_size);
|
||||
SHADOW_TEST(su);
|
||||
SHADOW_TEST(su - shadowpixel_size);
|
||||
SHADOW_TEST(su - shadowpixel_size * 2.0);
|
||||
SHADOW_TEST(su - shadowpixel_size * 3.0);
|
||||
SHADOW_TEST(su - shadowpixel_size * 4.0);
|
||||
SHADOW_TEST(su - shadowpixel_size * 5.0);
|
||||
SHADOW_TEST(su - shadowpixel_size * 6.0);
|
||||
shadow_attenuation /= 13.0;
|
||||
|
||||
#endif
|
||||
|
||||
//color *= shadow_attenuation;
|
||||
color = mix(real_light_shadow_color, color, shadow_attenuation);
|
||||
//use shadows
|
||||
#endif
|
||||
}
|
||||
|
||||
//use lighting
|
||||
#endif
|
||||
|
||||
gl_FragColor = color;
|
||||
}
|
||||
|
|
|
@ -1,15 +1,23 @@
|
|||
/* clang-format off */
|
||||
[vertex]
|
||||
|
||||
#ifdef USE_GLES_OVER_GL
|
||||
#define mediump
|
||||
#define highp
|
||||
#else
|
||||
precision highp float;
|
||||
precision highp int;
|
||||
#endif
|
||||
|
||||
attribute highp vec3 vertex; // attrib:0
|
||||
|
||||
uniform highp mat4 projection_matrix;
|
||||
/* clang-format on */
|
||||
uniform highp mat4 light_matrix;
|
||||
uniform highp mat4 world_matrix;
|
||||
uniform highp float distance_norm;
|
||||
|
||||
layout(location = 0) in highp vec3 vertex;
|
||||
|
||||
out highp vec4 position_interp;
|
||||
varying highp vec4 position_interp;
|
||||
|
||||
void main() {
|
||||
|
||||
|
@ -20,31 +28,29 @@ void main() {
|
|||
/* clang-format off */
|
||||
[fragment]
|
||||
|
||||
in highp vec4 position_interp;
|
||||
#ifdef USE_GLES_OVER_GL
|
||||
#define mediump
|
||||
#define highp
|
||||
#else
|
||||
precision mediump float;
|
||||
precision mediump int;
|
||||
#endif
|
||||
|
||||
varying highp vec4 position_interp;
|
||||
/* clang-format on */
|
||||
|
||||
#ifdef USE_RGBA_SHADOWS
|
||||
|
||||
layout(location = 0) out lowp vec4 distance_buf;
|
||||
|
||||
#else
|
||||
|
||||
layout(location = 0) out highp float distance_buf;
|
||||
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
|
||||
highp float depth = ((position_interp.z / position_interp.w) + 1.0) * 0.5 + 0.0; //bias;
|
||||
highp float depth = ((position_interp.z / position_interp.w) + 1.0) * 0.5 + 0.0; // bias
|
||||
|
||||
#ifdef USE_RGBA_SHADOWS
|
||||
|
||||
highp vec4 comp = fract(depth * vec4(256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0));
|
||||
comp -= comp.xxyz * vec4(0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0);
|
||||
distance_buf = comp;
|
||||
gl_FragColor = comp;
|
||||
#else
|
||||
|
||||
distance_buf = depth;
|
||||
|
||||
gl_FragColor = vec4(depth);
|
||||
#endif
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue