GLES2 refactors

This commit unhacks some parts of the 3D rendering.

Most notably:

 - possibility to use negative texture units
   (no longer weird manual index allocation for user samplers)

 - refactoring of light code, now sorts in a different way,
   should yield better performance

 - fixes a crash while saving (because of "Illegal instruction" execution)
   when using a decent compiler (clang, it's clang. Thanks GCC for not telling me about UB).
This commit is contained in:
Thomas Herzog 2018-08-06 18:26:17 +02:00
parent 6ffd2d3529
commit 73fe08be2e
7 changed files with 225 additions and 149 deletions

View File

@ -349,7 +349,7 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_UV_ATTRIBUTE, false); state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_UV_ATTRIBUTE, false);
if (state.canvas_shader.bind()) { if (state.canvas_shader.bind()) {
_set_uniforms(); _set_uniforms();
state.canvas_shader.use_material((void *)p_material, 2); state.canvas_shader.use_material((void *)p_material);
} }
_bind_canvas_texture(RID(), RID()); _bind_canvas_texture(RID(), RID());
@ -393,7 +393,7 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_UV_ATTRIBUTE, false); state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_UV_ATTRIBUTE, false);
if (state.canvas_shader.bind()) { if (state.canvas_shader.bind()) {
_set_uniforms(); _set_uniforms();
state.canvas_shader.use_material((void *)p_material, 2); state.canvas_shader.use_material((void *)p_material);
} }
RasterizerStorageGLES2::Texture *tex = _bind_canvas_texture(r->texture, r->normal_map); RasterizerStorageGLES2::Texture *tex = _bind_canvas_texture(r->texture, r->normal_map);
@ -476,7 +476,7 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_UV_ATTRIBUTE, true); state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_UV_ATTRIBUTE, true);
if (state.canvas_shader.bind()) { if (state.canvas_shader.bind()) {
_set_uniforms(); _set_uniforms();
state.canvas_shader.use_material((void *)p_material, 2); state.canvas_shader.use_material((void *)p_material);
} }
glDisableVertexAttribArray(VS::ARRAY_COLOR); glDisableVertexAttribArray(VS::ARRAY_COLOR);
@ -642,7 +642,7 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
if (state.canvas_shader.bind()) { if (state.canvas_shader.bind()) {
_set_uniforms(); _set_uniforms();
state.canvas_shader.use_material((void *)p_material, 2); state.canvas_shader.use_material((void *)p_material);
} }
static const int num_points = 32; static const int num_points = 32;
@ -673,7 +673,7 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
if (state.canvas_shader.bind()) { if (state.canvas_shader.bind()) {
_set_uniforms(); _set_uniforms();
state.canvas_shader.use_material((void *)p_material, 2); state.canvas_shader.use_material((void *)p_material);
} }
RasterizerStorageGLES2::Texture *texture = _bind_canvas_texture(polygon->texture, polygon->normal_map); RasterizerStorageGLES2::Texture *texture = _bind_canvas_texture(polygon->texture, polygon->normal_map);
@ -694,7 +694,7 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
if (state.canvas_shader.bind()) { if (state.canvas_shader.bind()) {
_set_uniforms(); _set_uniforms();
state.canvas_shader.use_material((void *)p_material, 2); state.canvas_shader.use_material((void *)p_material);
} }
_bind_canvas_texture(RID(), RID()); _bind_canvas_texture(RID(), RID());
@ -727,7 +727,7 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
if (state.canvas_shader.bind()) { if (state.canvas_shader.bind()) {
_set_uniforms(); _set_uniforms();
state.canvas_shader.use_material((void *)p_material, 2); state.canvas_shader.use_material((void *)p_material);
} }
ERR_CONTINUE(primitive->points.size() < 1); ERR_CONTINUE(primitive->points.size() < 1);
@ -926,7 +926,7 @@ void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, cons
state.canvas_shader.set_custom_shader(0); state.canvas_shader.set_custom_shader(0);
state.canvas_shader.bind(); state.canvas_shader.bind();
} }
state.canvas_shader.use_material((void *)material_ptr, 2); state.canvas_shader.use_material((void *)material_ptr);
shader_cache = shader_ptr; shader_cache = shader_ptr;

View File

@ -35,6 +35,8 @@
#include "rasterizer_canvas_gles2.h" #include "rasterizer_canvas_gles2.h"
#include "servers/visual/visual_server_raster.h" #include "servers/visual/visual_server_raster.h"
#include "vmap.h"
#ifndef GLES_OVER_GL #ifndef GLES_OVER_GL
#define glClearDepth glClearDepthf #define glClearDepth glClearDepthf
#endif #endif
@ -827,7 +829,7 @@ static const GLenum gl_primitive[] = {
GL_TRIANGLE_FAN GL_TRIANGLE_FAN
}; };
void RasterizerSceneGLES2::_setup_material(RasterizerStorageGLES2::Material *p_material, bool p_use_radiance_map, bool p_reverse_cull, bool p_shadow_atlas, bool p_skeleton_tex, Size2i p_skeleton_tex_size) { void RasterizerSceneGLES2::_setup_material(RasterizerStorageGLES2::Material *p_material, bool p_reverse_cull, Size2i p_skeleton_tex_size) {
// material parameters // material parameters
@ -864,25 +866,11 @@ void RasterizerSceneGLES2::_setup_material(RasterizerStorageGLES2::Material *p_m
ShaderLanguage::ShaderNode::Uniform::Hint *texture_hints = p_material->shader->texture_hints.ptrw(); ShaderLanguage::ShaderNode::Uniform::Hint *texture_hints = p_material->shader->texture_hints.ptrw();
int num_default_tex = p_use_radiance_map ? 1 : 0; state.scene_shader.set_uniform(SceneShaderGLES2::SKELETON_TEXTURE_SIZE, p_skeleton_tex_size);
if (p_material->shader->spatial.uses_screen_texture) {
num_default_tex = MIN(num_default_tex, 2);
}
if (p_shadow_atlas) {
num_default_tex = MIN(num_default_tex, 3);
}
if (p_skeleton_tex) {
num_default_tex = MIN(num_default_tex, 4);
state.scene_shader.set_uniform(SceneShaderGLES2::SKELETON_TEXTURE_SIZE, p_skeleton_tex_size);
}
for (int i = 0; i < tc; i++) { for (int i = 0; i < tc; i++) {
glActiveTexture(GL_TEXTURE0 + num_default_tex + i); glActiveTexture(GL_TEXTURE0 + i);
RasterizerStorageGLES2::Texture *t = storage->texture_owner.getornull(textures[i].second); RasterizerStorageGLES2::Texture *t = storage->texture_owner.getornull(textures[i].second);
@ -911,7 +899,7 @@ void RasterizerSceneGLES2::_setup_material(RasterizerStorageGLES2::Material *p_m
glBindTexture(t->target, t->tex_id); glBindTexture(t->target, t->tex_id);
} }
state.scene_shader.use_material((void *)p_material, num_default_tex); state.scene_shader.use_material((void *)p_material);
} }
void RasterizerSceneGLES2::_setup_geometry(RenderList::Element *p_element, RasterizerStorageGLES2::Skeleton *p_skeleton) { void RasterizerSceneGLES2::_setup_geometry(RenderList::Element *p_element, RasterizerStorageGLES2::Skeleton *p_skeleton) {
@ -1279,7 +1267,7 @@ void RasterizerSceneGLES2::_render_geometry(RenderList::Element *p_element) {
} }
} }
void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements, int p_element_count, const RID *p_light_cull_result, int p_light_cull_count, const Transform &p_view_transform, const CameraMatrix &p_projection, RID p_shadow_atlas, Environment *p_env, GLuint p_base_env, float p_shadow_bias, float p_shadow_normal_bias, bool p_reverse_cull, bool p_alpha_pass, bool p_shadow, bool p_directional_add, bool p_directional_shadows) { void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements, int p_element_count, const RID *p_directional_lights, int p_directional_light_count, const Transform &p_view_transform, const CameraMatrix &p_projection, RID p_shadow_atlas, Environment *p_env, GLuint p_base_env, float p_shadow_bias, float p_shadow_normal_bias, bool p_reverse_cull, bool p_alpha_pass, bool p_shadow, bool p_directional_add) {
ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas); ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas);
@ -1289,6 +1277,8 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
bool use_radiance_map = false; bool use_radiance_map = false;
VMap<RID, Vector<RenderList::Element *> > lit_objects;
for (int i = 0; i < p_element_count; i++) { for (int i = 0; i < p_element_count; i++) {
RenderList::Element *e = p_elements[i]; RenderList::Element *e = p_elements[i];
@ -1297,7 +1287,7 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
RasterizerStorageGLES2::Skeleton *skeleton = storage->skeleton_owner.getornull(e->instance->skeleton); RasterizerStorageGLES2::Skeleton *skeleton = storage->skeleton_owner.getornull(e->instance->skeleton);
if (p_base_env) { if (p_base_env) {
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 2);
glBindTexture(GL_TEXTURE_CUBE_MAP, p_base_env); glBindTexture(GL_TEXTURE_CUBE_MAP, p_base_env);
use_radiance_map = true; use_radiance_map = true;
} }
@ -1315,7 +1305,7 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
_setup_geometry(e, skeleton); _setup_geometry(e, skeleton);
_setup_material(material, use_radiance_map, p_reverse_cull, false, skeleton ? (skeleton->tex_id != 0) : 0, Size2i(skeleton ? skeleton->size * 3 : 0, 0)); _setup_material(material, p_reverse_cull, Size2i(skeleton ? skeleton->size * 3 : 0, 0));
if (use_radiance_map) { if (use_radiance_map) {
state.scene_shader.set_uniform(SceneShaderGLES2::RADIANCE_INVERSE_XFORM, p_view_transform); state.scene_shader.set_uniform(SceneShaderGLES2::RADIANCE_INVERSE_XFORM, p_view_transform);
@ -1404,66 +1394,88 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
_render_geometry(e); _render_geometry(e);
// render lights
if (material->shader->spatial.unshaded) if (material->shader->spatial.unshaded)
continue; continue;
if (p_shadow) if (p_shadow)
continue; continue;
state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_PASS, true); for (int light = 0; light < e->instance->light_instances.size(); light++) {
state.scene_shader.bind(); RID light_instance = e->instance->light_instances[light];
glBlendEquation(GL_FUNC_ADD); lit_objects[light_instance].push_back(e);
glBlendFunc(GL_SRC_ALPHA, GL_ONE); }
}
{ if (p_shadow) {
bool has_shadow_atlas = shadow_atlas != NULL; state.scene_shader.set_conditional(SceneShaderGLES2::USE_RADIANCE_MAP, false);
_setup_material(material, false, p_reverse_cull, has_shadow_atlas, skeleton ? (skeleton->tex_id != 0) : 0, Size2i(skeleton ? skeleton->size * 3 : 0, 0)); state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM4, false);
state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM2, false);
state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM_BLEND, false);
return;
}
if (has_shadow_atlas) { state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_PASS, true);
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth); glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
for (int lo = 0; lo < lit_objects.size(); lo++) {
RID key = lit_objects.getk(lo);
LightInstance *light = light_instance_owner.getornull(key);
RasterizerStorageGLES2::Light *light_ptr = light->light_ptr;
const Vector<RenderList::Element *> &list = lit_objects.getv(lo);
for (int i = 0; i < list.size(); i++) {
RenderList::Element *e = list[i];
RasterizerStorageGLES2::Material *material = e->material;
RasterizerStorageGLES2::Skeleton *skeleton = storage->skeleton_owner.getornull(e->instance->skeleton);
{
_setup_geometry(e, skeleton);
_setup_material(material, p_reverse_cull, Size2i(skeleton ? skeleton->size * 3 : 0, 0));
if (shadow_atlas != NULL) {
glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4);
glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth);
}
state.scene_shader.set_uniform(SceneShaderGLES2::CAMERA_MATRIX, p_view_transform.inverse());
state.scene_shader.set_uniform(SceneShaderGLES2::CAMERA_INVERSE_MATRIX, p_view_transform);
state.scene_shader.set_uniform(SceneShaderGLES2::PROJECTION_MATRIX, p_projection);
state.scene_shader.set_uniform(SceneShaderGLES2::PROJECTION_INVERSE_MATRIX, p_projection.inverse());
state.scene_shader.set_uniform(SceneShaderGLES2::TIME, storage->frame.time[0]);
state.scene_shader.set_uniform(SceneShaderGLES2::SCREEN_PIXEL_SIZE, screen_pixel_size);
state.scene_shader.set_uniform(SceneShaderGLES2::NORMAL_MULT, 1.0); // TODO mirror?
state.scene_shader.set_uniform(SceneShaderGLES2::WORLD_TRANSFORM, e->instance->transform);
} }
state.scene_shader.set_uniform(SceneShaderGLES2::CAMERA_MATRIX, p_view_transform.inverse()); switch (light_ptr->type) {
state.scene_shader.set_uniform(SceneShaderGLES2::CAMERA_INVERSE_MATRIX, p_view_transform);
state.scene_shader.set_uniform(SceneShaderGLES2::PROJECTION_MATRIX, p_projection);
state.scene_shader.set_uniform(SceneShaderGLES2::PROJECTION_INVERSE_MATRIX, p_projection.inverse());
state.scene_shader.set_uniform(SceneShaderGLES2::TIME, storage->frame.time[0]);
state.scene_shader.set_uniform(SceneShaderGLES2::SCREEN_PIXEL_SIZE, screen_pixel_size);
state.scene_shader.set_uniform(SceneShaderGLES2::NORMAL_MULT, 1.0); // TODO mirror?
state.scene_shader.set_uniform(SceneShaderGLES2::WORLD_TRANSFORM, e->instance->transform);
}
for (int j = 0; j < e->instance->light_instances.size(); j++) {
RID light_rid = e->instance->light_instances[j];
LightInstance *light = light_instance_owner.get(light_rid);
switch (light->light_ptr->type) {
case VS::LIGHT_DIRECTIONAL: {
continue;
} break;
case VS::LIGHT_OMNI: { case VS::LIGHT_OMNI: {
state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_TYPE, (int)1); state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_TYPE, (int)1);
Vector3 position = p_view_transform.inverse().xform(light->transform.origin); Vector3 position = p_view_transform.inverse().xform(light->transform.origin);
state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_POSITION, position); state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_POSITION, position);
float range = light->light_ptr->param[VS::LIGHT_PARAM_RANGE]; float range = light_ptr->param[VS::LIGHT_PARAM_RANGE];
state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_RANGE, range); state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_RANGE, range);
Color attenuation = Color(0.0, 0.0, 0.0, 0.0); Color attenuation = Color(0.0, 0.0, 0.0, 0.0);
attenuation.a = light->light_ptr->param[VS::LIGHT_PARAM_ATTENUATION]; attenuation.a = light_ptr->param[VS::LIGHT_PARAM_ATTENUATION];
state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_ATTENUATION, attenuation); state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_ATTENUATION, attenuation);
if (light->light_ptr->shadow && shadow_atlas->shadow_owners.has(light->self)) { if (light_ptr->shadow && shadow_atlas->shadow_owners.has(light->self)) {
uint32_t key = shadow_atlas->shadow_owners[light->self]; uint32_t key = shadow_atlas->shadow_owners[light->self];
@ -1516,10 +1528,10 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
Vector3 direction = p_view_transform.inverse().basis.xform(light->transform.basis.xform(Vector3(0, 0, -1))).normalized(); Vector3 direction = p_view_transform.inverse().basis.xform(light->transform.basis.xform(Vector3(0, 0, -1))).normalized();
state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_DIRECTION, direction); state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_DIRECTION, direction);
Color attenuation = Color(0.0, 0.0, 0.0, 0.0); Color attenuation = Color(0.0, 0.0, 0.0, 0.0);
attenuation.a = light->light_ptr->param[VS::LIGHT_PARAM_ATTENUATION]; attenuation.a = light_ptr->param[VS::LIGHT_PARAM_ATTENUATION];
float range = light->light_ptr->param[VS::LIGHT_PARAM_RANGE]; float range = light_ptr->param[VS::LIGHT_PARAM_RANGE];
float spot_attenuation = light->light_ptr->param[VS::LIGHT_PARAM_SPOT_ATTENUATION]; float spot_attenuation = light_ptr->param[VS::LIGHT_PARAM_SPOT_ATTENUATION];
float angle = light->light_ptr->param[VS::LIGHT_PARAM_SPOT_ANGLE]; float angle = light_ptr->param[VS::LIGHT_PARAM_SPOT_ANGLE];
angle = Math::cos(Math::deg2rad(angle)); angle = Math::cos(Math::deg2rad(angle));
state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_ATTENUATION, attenuation); state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_ATTENUATION, attenuation);
state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SPOT_ATTENUATION, spot_attenuation); state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SPOT_ATTENUATION, spot_attenuation);
@ -1576,9 +1588,7 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
} break; } break;
default: { default: break;
print_line("wat.");
} break;
} }
float energy = light->light_ptr->param[VS::LIGHT_PARAM_ENERGY]; float energy = light->light_ptr->param[VS::LIGHT_PARAM_ENERGY];
@ -1590,62 +1600,57 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
_render_geometry(e); _render_geometry(e);
} }
}
for (int j = 0; j < p_light_cull_count; j++) { for (int dl = 0; dl < p_directional_light_count; dl++) {
RID light_rid = p_light_cull_result[j]; RID light_rid = p_directional_lights[dl];
LightInstance *light = light_instance_owner.getornull(light_rid);
RasterizerStorageGLES2::Light *light_ptr = light->light_ptr;
LightInstance *light = light_instance_owner.getornull(light_rid); switch (light_ptr->directional_shadow_mode) {
case VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: {
} break;
case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: {
state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM2, true);
state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM_BLEND, light_ptr->directional_blend_splits);
} break;
RasterizerStorageGLES2::Light *light_ptr = light->light_ptr; case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: {
state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM4, true);
state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM_BLEND, light_ptr->directional_blend_splits);
} break;
default:
break;
}
switch (light_ptr->type) { for (int i = 0; i < p_element_count; i++) {
case VS::LIGHT_DIRECTIONAL: {
switch (light_ptr->directional_shadow_mode) { RenderList::Element *e = p_elements[i];
case VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: { RasterizerStorageGLES2::Material *material = e->material;
} break; RasterizerStorageGLES2::Skeleton *skeleton = storage->skeleton_owner.getornull(e->instance->skeleton);
case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: {
state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM2, true);
state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM_BLEND, light_ptr->directional_blend_splits);
} break;
case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: { {
state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM4, true); _setup_material(material, p_reverse_cull, Size2i(skeleton ? skeleton->size * 3 : 0, 0));
state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM_BLEND, light_ptr->directional_blend_splits);
} break;
default:
break;
}
{ if (directional_shadow.depth) {
_setup_material(material, false, p_reverse_cull, false, skeleton ? (skeleton->tex_id != 0) : 0, Size2i(skeleton ? skeleton->size * 3 : 0, 0)); glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4); // TODO move into base pass
glBindTexture(GL_TEXTURE_2D, directional_shadow.depth);
}
if (directional_shadow.depth) { state.scene_shader.set_uniform(SceneShaderGLES2::CAMERA_MATRIX, p_view_transform.inverse());
glActiveTexture(GL_TEXTURE3); state.scene_shader.set_uniform(SceneShaderGLES2::CAMERA_INVERSE_MATRIX, p_view_transform);
glBindTexture(GL_TEXTURE_2D, directional_shadow.depth); state.scene_shader.set_uniform(SceneShaderGLES2::PROJECTION_MATRIX, p_projection);
} state.scene_shader.set_uniform(SceneShaderGLES2::PROJECTION_INVERSE_MATRIX, p_projection.inverse());
state.scene_shader.set_uniform(SceneShaderGLES2::CAMERA_MATRIX, p_view_transform.inverse()); state.scene_shader.set_uniform(SceneShaderGLES2::TIME, storage->frame.time[0]);
state.scene_shader.set_uniform(SceneShaderGLES2::CAMERA_INVERSE_MATRIX, p_view_transform);
state.scene_shader.set_uniform(SceneShaderGLES2::PROJECTION_MATRIX, p_projection);
state.scene_shader.set_uniform(SceneShaderGLES2::PROJECTION_INVERSE_MATRIX, p_projection.inverse());
state.scene_shader.set_uniform(SceneShaderGLES2::TIME, storage->frame.time[0]); state.scene_shader.set_uniform(SceneShaderGLES2::SCREEN_PIXEL_SIZE, screen_pixel_size);
state.scene_shader.set_uniform(SceneShaderGLES2::NORMAL_MULT, 1.0); // TODO mirror?
state.scene_shader.set_uniform(SceneShaderGLES2::SCREEN_PIXEL_SIZE, screen_pixel_size); state.scene_shader.set_uniform(SceneShaderGLES2::WORLD_TRANSFORM, e->instance->transform);
state.scene_shader.set_uniform(SceneShaderGLES2::NORMAL_MULT, 1.0); // TODO mirror?
state.scene_shader.set_uniform(SceneShaderGLES2::WORLD_TRANSFORM, e->instance->transform);
}
state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_TYPE, (int)0);
Vector3 direction = p_view_transform.inverse().basis.xform(light->transform.basis.xform(Vector3(0, 0, -1))).normalized();
state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_DIRECTION, direction);
} break;
default: {
continue;
} break;
} }
state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_TYPE, (int)0);
Vector3 direction = p_view_transform.inverse().basis.xform(light->transform.basis.xform(Vector3(0, 0, -1))).normalized();
state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_DIRECTION, direction);
float energy = light_ptr->param[VS::LIGHT_PARAM_ENERGY]; float energy = light_ptr->param[VS::LIGHT_PARAM_ENERGY];
float specular = light_ptr->param[VS::LIGHT_PARAM_SPECULAR]; float specular = light_ptr->param[VS::LIGHT_PARAM_SPECULAR];
@ -1753,10 +1758,10 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
_render_geometry(e); _render_geometry(e);
} }
state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_PASS, false);
} }
state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_PASS, false);
state.scene_shader.set_conditional(SceneShaderGLES2::USE_RADIANCE_MAP, false); state.scene_shader.set_conditional(SceneShaderGLES2::USE_RADIANCE_MAP, false);
state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM4, false); state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM4, false);
state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM2, false); state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM2, false);
@ -1911,9 +1916,21 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
} }
} }
Vector<RID> directional_lights;
for (int i = 0; i < p_light_cull_count; i++) {
RID light_rid = p_light_cull_result[i];
LightInstance *light = light_instance_owner.getornull(light_rid);
if (light->light_ptr->type == VS::LIGHT_DIRECTIONAL) {
directional_lights.push_back(light_rid);
}
}
// render opaque things first // render opaque things first
render_list.sort_by_key(false); render_list.sort_by_key(false);
_render_render_list(render_list.elements, render_list.element_count, p_light_cull_result, p_light_cull_count, p_cam_transform, p_cam_projection, p_shadow_atlas, env, env_radiance_tex, 0.0, 0.0, false, false, false, false, false); _render_render_list(render_list.elements, render_list.element_count, directional_lights.ptr(), directional_lights.size(), p_cam_transform, p_cam_projection, p_shadow_atlas, env, env_radiance_tex, 0.0, 0.0, false, false, false, false);
// alpha pass // alpha pass
@ -1921,7 +1938,7 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
render_list.sort_by_key(true); render_list.sort_by_key(true);
_render_render_list(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, p_light_cull_result, p_light_cull_count, p_cam_transform, p_cam_projection, p_shadow_atlas, env, env_radiance_tex, 0.0, 0.0, false, true, false, false, false); _render_render_list(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, directional_lights.ptr(), directional_lights.size(), p_cam_transform, p_cam_projection, p_shadow_atlas, env, env_radiance_tex, 0.0, 0.0, false, true, false, false);
glDepthMask(GL_FALSE); glDepthMask(GL_FALSE);
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
@ -2136,7 +2153,7 @@ void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_
state.scene_shader.set_conditional(SceneShaderGLES2::RENDER_DEPTH, true); state.scene_shader.set_conditional(SceneShaderGLES2::RENDER_DEPTH, true);
_render_render_list(render_list.elements, render_list.element_count, NULL, 0, light_transform, light_projection, RID(), NULL, 0, bias, normal_bias, false, false, true, false, false); _render_render_list(render_list.elements, render_list.element_count, NULL, 0, light_transform, light_projection, RID(), NULL, 0, bias, normal_bias, false, false, true, false);
state.scene_shader.set_conditional(SceneShaderGLES2::RENDER_DEPTH, false); state.scene_shader.set_conditional(SceneShaderGLES2::RENDER_DEPTH, false);

View File

@ -545,11 +545,23 @@ public:
void _add_geometry_with_material(RasterizerStorageGLES2::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES2::GeometryOwner *p_owner, RasterizerStorageGLES2::Material *p_material, bool p_depth_pass, bool p_shadow_pass); void _add_geometry_with_material(RasterizerStorageGLES2::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES2::GeometryOwner *p_owner, RasterizerStorageGLES2::Material *p_material, bool p_depth_pass, bool p_shadow_pass);
void _fill_render_list(InstanceBase **p_cull_result, int p_cull_count, bool p_depth_pass, bool p_shadow_pass); void _fill_render_list(InstanceBase **p_cull_result, int p_cull_count, bool p_depth_pass, bool p_shadow_pass);
void _render_render_list(RenderList::Element **p_elements, int p_element_count, const RID *p_light_cull_result, int p_light_cull_count, const Transform &p_view_transform, const CameraMatrix &p_projection, RID p_shadow_atlas, Environment *p_env, GLuint p_base_env, float p_shadow_bias, float p_shadow_normal_bias, bool p_reverse_cull, bool p_alpha_pass, bool p_shadow, bool p_directional_add, bool p_directional_shadows); void _render_render_list(RenderList::Element **p_elements, int p_element_count,
const RID *p_directional_lights, int p_directional_light_count,
const Transform &p_view_transform,
const CameraMatrix &p_projection,
RID p_shadow_atlas,
Environment *p_env,
GLuint p_base_env,
float p_shadow_bias,
float p_shadow_normal_bias,
bool p_reverse_cull,
bool p_alpha_pass,
bool p_shadow,
bool p_directional_add);
void _draw_sky(RasterizerStorageGLES2::Sky *p_sky, const CameraMatrix &p_projection, const Transform &p_transform, bool p_vflip, float p_custom_fov, float p_energy); void _draw_sky(RasterizerStorageGLES2::Sky *p_sky, const CameraMatrix &p_projection, const Transform &p_transform, bool p_vflip, float p_custom_fov, float p_energy);
void _setup_material(RasterizerStorageGLES2::Material *p_material, bool p_use_radiance_map, bool p_reverse_cull, bool p_shadow_atlas = false, bool p_skeleton_tex = false, Size2i p_skeleton_tex_size = Size2i(0, 0)); void _setup_material(RasterizerStorageGLES2::Material *p_material, bool p_reverse_cull, Size2i p_skeleton_tex_size = Size2i(0, 0));
void _setup_geometry(RenderList::Element *p_element, RasterizerStorageGLES2::Skeleton *p_skeleton); void _setup_geometry(RenderList::Element *p_element, RasterizerStorageGLES2::Skeleton *p_skeleton);
void _render_geometry(RenderList::Element *p_element); void _render_geometry(RenderList::Element *p_element);

View File

@ -567,7 +567,7 @@ Ref<Image> RasterizerStorageGLES2::texture_get_data(RID p_texture, int p_layer)
ERR_FAIL_COND_V(!texture->active, Ref<Image>()); ERR_FAIL_COND_V(!texture->active, Ref<Image>());
ERR_FAIL_COND_V(texture->data_size == 0 && !texture->render_target, Ref<Image>()); ERR_FAIL_COND_V(texture->data_size == 0 && !texture->render_target, Ref<Image>());
if (!texture->images[p_layer].is_null()) { if (texture->type == VS::TEXTURE_TYPE_CUBEMAP && p_layer < 6 && p_layer >= 0 && !texture->images[p_layer].is_null()) {
return texture->images[p_layer]; return texture->images[p_layer];
} }
#ifdef GLES_OVER_GL #ifdef GLES_OVER_GL
@ -594,9 +594,13 @@ Ref<Image> RasterizerStorageGLES2::texture_get_data(RID p_texture, int p_layer)
ofs = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, texture->format, i - 1); ofs = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, texture->format, i - 1);
} }
glPixelStorei(GL_PACK_ALIGNMENT, 1); if (texture->compressed) {
glPixelStorei(GL_PACK_ALIGNMENT, 4);
glGetTexImage(texture->target, i, texture->gl_format_cache, texture->gl_type_cache, &wb[ofs]); glGetCompressedTexImage(texture->target, i, &wb[ofs]);
} else {
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glGetTexImage(texture->target, i, texture->gl_format_cache, texture->gl_type_cache, &wb[ofs]);
}
} }
wb = PoolVector<uint8_t>::Write(); wb = PoolVector<uint8_t>::Write();
@ -3961,7 +3965,7 @@ void RasterizerStorageGLES2::initialize() {
frame.clear_request = false; frame.clear_request = false;
// config.keep_original_textures = false; // config.keep_original_textures = false;
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &config.max_texture_image_units); glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &config.max_texture_image_units);
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &config.max_texture_size); glGetIntegerv(GL_MAX_TEXTURE_SIZE, &config.max_texture_size);
shaders.copy.init(); shaders.copy.init();

View File

@ -527,8 +527,13 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() {
for (int i = 0; i < texunit_pair_count; i++) { for (int i = 0; i < texunit_pair_count; i++) {
GLint loc = glGetUniformLocation(v.id, texunit_pairs[i].name); GLint loc = glGetUniformLocation(v.id, texunit_pairs[i].name);
if (loc >= 0) if (loc >= 0) {
glUniform1i(loc, texunit_pairs[i].index); if (texunit_pairs[i].index < 0) {
glUniform1i(loc, max_image_units + texunit_pairs[i].index);
} else {
glUniform1i(loc, texunit_pairs[i].index);
}
}
} }
if (cc) { if (cc) {
@ -643,6 +648,8 @@ void ShaderGLES2::setup(
} }
} }
} }
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_image_units);
} }
void ShaderGLES2::finish() { void ShaderGLES2::finish() {
@ -717,7 +724,7 @@ void ShaderGLES2::free_custom_shader(uint32_t p_code_id) {
custom_code_map.erase(p_code_id); custom_code_map.erase(p_code_id);
} }
void ShaderGLES2::use_material(void *p_material, int p_num_predef_textures) { void ShaderGLES2::use_material(void *p_material) {
RasterizerStorageGLES2::Material *material = (RasterizerStorageGLES2::Material *)p_material; RasterizerStorageGLES2::Material *material = (RasterizerStorageGLES2::Material *)p_material;
if (!material) { if (!material) {
@ -906,20 +913,58 @@ void ShaderGLES2::use_material(void *p_material, int p_num_predef_textures) {
case ShaderLanguage::TYPE_MAT2: { case ShaderLanguage::TYPE_MAT2: {
Transform2D val = V->get(); Transform2D val = V->get();
// TODO if (value.second.size() < 4) {
value.second.resize(4);
}
value.second.write[0].real = val.elements[0][0];
value.second.write[1].real = val.elements[0][1];
value.second.write[2].real = val.elements[1][0];
value.second.write[3].real = val.elements[1][1];
} break; } break;
case ShaderLanguage::TYPE_MAT3: { case ShaderLanguage::TYPE_MAT3: {
Basis val = V->get(); Basis val = V->get();
// TODO if (value.second.size() < 9) {
value.second.resize(9);
}
value.second.write[0].real = val.elements[0][0];
value.second.write[1].real = val.elements[0][1];
value.second.write[2].real = val.elements[0][2];
value.second.write[3].real = val.elements[1][0];
value.second.write[4].real = val.elements[1][1];
value.second.write[5].real = val.elements[1][2];
value.second.write[6].real = val.elements[2][0];
value.second.write[7].real = val.elements[2][1];
value.second.write[8].real = val.elements[2][2];
} break; } break;
case ShaderLanguage::TYPE_MAT4: { case ShaderLanguage::TYPE_MAT4: {
Transform val = V->get(); Transform val = V->get();
// TODO if (value.second.size() < 16) {
value.second.resize(16);
}
value.second.write[0].real = val.basis.elements[0][0];
value.second.write[0].real = val.basis.elements[0][1];
value.second.write[0].real = val.basis.elements[0][2];
value.second.write[0].real = 0;
value.second.write[0].real = val.basis.elements[1][0];
value.second.write[0].real = val.basis.elements[1][1];
value.second.write[0].real = val.basis.elements[1][2];
value.second.write[0].real = 0;
value.second.write[0].real = val.basis.elements[2][0];
value.second.write[0].real = val.basis.elements[2][1];
value.second.write[0].real = val.basis.elements[2][2];
value.second.write[0].real = 0;
value.second.write[0].real = val.origin[0];
value.second.write[0].real = val.origin[1];
value.second.write[0].real = val.origin[2];
value.second.write[0].real = 1;
} break; } break;
case ShaderLanguage::TYPE_SAMPLER2D: { case ShaderLanguage::TYPE_SAMPLER2D: {
@ -1034,7 +1079,7 @@ void ShaderGLES2::use_material(void *p_material, int p_num_predef_textures) {
Pair<ShaderLanguage::DataType, Vector<ShaderLanguage::ConstantNode::Value> > value; Pair<ShaderLanguage::DataType, Vector<ShaderLanguage::ConstantNode::Value> > value;
value.first = ShaderLanguage::TYPE_INT; value.first = ShaderLanguage::TYPE_INT;
value.second.resize(1); value.second.resize(1);
value.second.write[0].sint = p_num_predef_textures + i; value.second.write[0].sint = i;
// GLint location = get_uniform_location(textures[i].first); // GLint location = get_uniform_location(textures[i].first);

View File

@ -465,7 +465,7 @@ public:
// this void* is actually a RasterizerStorageGLES2::Material, but C++ doesn't // this void* is actually a RasterizerStorageGLES2::Material, but C++ doesn't
// like forward declared nested classes. // like forward declared nested classes.
void use_material(void *p_material, int p_num_predef_textures); void use_material(void *p_material);
uint32_t get_version() const { return new_conditional_version.version; } uint32_t get_version() const { return new_conditional_version.version; }

View File

@ -48,7 +48,7 @@ attribute highp vec4 bone_transform_row_2; // attrib:11
attribute vec4 bone_ids; // attrib:6 attribute vec4 bone_ids; // attrib:6
attribute highp vec4 bone_weights; // attrib:7 attribute highp vec4 bone_weights; // attrib:7
uniform highp sampler2D bone_transforms; // texunit:4 uniform highp sampler2D bone_transforms; // texunit:-1
uniform ivec2 skeleton_texture_size; uniform ivec2 skeleton_texture_size;
#endif #endif
@ -294,17 +294,17 @@ uniform highp float time;
uniform vec2 screen_pixel_size; uniform vec2 screen_pixel_size;
#endif #endif
uniform highp sampler2D depth_buffer; //texunit:1 uniform highp sampler2D depth_buffer; //texunit:-5
#if defined(SCREEN_TEXTURE_USED) #if defined(SCREEN_TEXTURE_USED)
uniform highp sampler2D screen_texture; //texunit:2 uniform highp sampler2D screen_texture; //texunit:-6
#endif #endif
#ifdef USE_RADIANCE_MAP #ifdef USE_RADIANCE_MAP
#define RADIANCE_MAX_LOD 6.0 #define RADIANCE_MAX_LOD 6.0
uniform samplerCube radiance_map; // texunit:0 uniform samplerCube radiance_map; // texunit:-2
uniform mat4 radiance_inverse_xform; uniform mat4 radiance_inverse_xform;
@ -345,7 +345,7 @@ uniform float light_spot_angle;
// shadows // shadows
uniform highp sampler2D light_shadow_atlas; //texunit:3 uniform highp sampler2D light_shadow_atlas; //texunit:-4
uniform float light_has_shadow; uniform float light_has_shadow;
uniform mat4 light_shadow_matrix; uniform mat4 light_shadow_matrix;
@ -353,7 +353,7 @@ uniform vec4 light_clamp;
// directional shadow // directional shadow
uniform highp sampler2D light_directional_shadow; // texunit:3 uniform highp sampler2D light_directional_shadow; // texunit:-4
uniform vec4 light_split_offsets; uniform vec4 light_split_offsets;
uniform mat4 light_shadow_matrix1; uniform mat4 light_shadow_matrix1;
@ -439,11 +439,10 @@ void light_compute(vec3 N,
{ {
// calculate specular reflection // calculate specular reflection
vec3 R = normalize(-reflect(L,N)); vec3 R = normalize(-reflect(L,N));
float cRdotV = max(dot(R, V), 0.0); float cRdotV = max(dot(R, V), 0.0);
float blob_intensity = pow(cRdotV, (1.0 - roughness) * 256.0); float blob_intensity = pow(cRdotV, (1.0 - roughness) * 256.0);
specular_light += light_color * attenuation * blob_intensity * specular_blob_intensity; specular_light += light_color * attenuation * blob_intensity * specular_blob_intensity;
} }
} }
@ -808,7 +807,6 @@ FRAGMENT_SHADER_CODE
anisotropy, anisotropy,
diffuse_light, diffuse_light,
specular_light); specular_light);
} }
gl_FragColor = vec4(ambient_light + diffuse_light + specular_light, alpha); gl_FragColor = vec4(ambient_light + diffuse_light + specular_light, alpha);