diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/gles3/rasterizer_scene_gles3.cpp | 72 | ||||
| -rw-r--r-- | drivers/gles3/rasterizer_storage_gles3.cpp | 10 | ||||
| -rw-r--r-- | drivers/gles3/shader_compiler_gles3.cpp | 1 | ||||
| -rw-r--r-- | drivers/gles3/shaders/copy.glsl | 24 | ||||
| -rw-r--r-- | drivers/gles3/shaders/scene.glsl | 214 | ||||
| -rw-r--r-- | drivers/gles3/shaders/subsurf_scattering.glsl | 25 | ||||
| -rw-r--r-- | drivers/gles3/shaders/tonemap.glsl | 7 | ||||
| -rw-r--r-- | drivers/unix/file_access_unix.cpp | 6 | ||||
| -rw-r--r-- | drivers/unix/file_access_unix.h | 1 | ||||
| -rw-r--r-- | drivers/unix/os_unix.cpp | 103 | ||||
| -rw-r--r-- | drivers/unix/os_unix.h | 14 | ||||
| -rw-r--r-- | drivers/unix/syslog_logger.cpp | 71 | ||||
| -rw-r--r-- | drivers/unix/syslog_logger.h | 48 | ||||
| -rw-r--r-- | drivers/windows/dir_access_windows.cpp | 4 | ||||
| -rw-r--r-- | drivers/windows/file_access_windows.cpp | 6 | ||||
| -rw-r--r-- | drivers/windows/file_access_windows.h | 1 |
16 files changed, 408 insertions, 199 deletions
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index eaf0b06664..6117c91a6a 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -379,6 +379,7 @@ bool RasterizerSceneGLES3::shadow_atlas_update_light(RID p_atlas, RID p_light_in sh->owner = p_light_intance; sh->alloc_tick = tick; sh->version = p_light_version; + li->shadow_atlases.insert(p_atlas); //make new key key = new_quadrant << ShadowAtlas::QUADRANT_SHIFT; @@ -414,6 +415,7 @@ bool RasterizerSceneGLES3::shadow_atlas_update_light(RID p_atlas, RID p_light_in sh->owner = p_light_intance; sh->alloc_tick = tick; sh->version = p_light_version; + li->shadow_atlases.insert(p_atlas); //make new key uint32_t key = new_quadrant << ShadowAtlas::QUADRANT_SHIFT; @@ -2140,7 +2142,6 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_ first = false; } - glFrontFace(GL_CW); glBindVertexArray(0); state.scene_shader.set_conditional(SceneShaderGLES3::USE_INSTANCING, false); @@ -2349,22 +2350,7 @@ void RasterizerSceneGLES3::_draw_sky(RasterizerStorageGLES3::Sky *p_sky, const C glDepthFunc(GL_LEQUAL); glColorMask(1, 1, 1, 1); - float flip_sign = p_vflip ? -1 : 1; - - Vector3 vertices[8] = { - Vector3(-1, -1 * flip_sign, 1), - Vector3(0, 1, 0), - Vector3(1, -1 * flip_sign, 1), - Vector3(1, 1, 0), - Vector3(1, 1 * flip_sign, 1), - Vector3(1, 0, 0), - Vector3(-1, 1 * flip_sign, 1), - Vector3(0, 0, 0) - - }; - - //sky uv vectors - float vw, vh, zn; + // Camera CameraMatrix camera; if (p_custom_fov) { @@ -2379,17 +2365,39 @@ void RasterizerSceneGLES3::_draw_sky(RasterizerStorageGLES3::Sky *p_sky, const C camera = p_projection; } - camera.get_viewport_size(vw, vh); - zn = p_projection.get_z_near(); + float flip_sign = p_vflip ? -1 : 1; - for (int i = 0; i < 4; i++) { + /* + If matrix[2][0] or matrix[2][1] we're dealing with an asymmetrical projection matrix. This is the case for stereoscopic rendering (i.e. VR). + To ensure the image rendered is perspective correct we need to move some logic into the shader. For this the USE_ASYM_PANO option is introduced. + It also means the uv coordinates are ignored in this mode and we don't need our loop. + */ + bool asymmetrical = ((camera.matrix[2][0] != 0.0) || (camera.matrix[2][1] != 0.0)); - Vector3 uv = vertices[i * 2 + 1]; - uv.x = (uv.x * 2.0 - 1.0) * vw; - uv.y = -(uv.y * 2.0 - 1.0) * vh; - uv.z = -zn; - vertices[i * 2 + 1] = p_transform.basis.xform(uv).normalized(); - vertices[i * 2 + 1].z = -vertices[i * 2 + 1].z; + Vector3 vertices[8] = { + Vector3(-1, -1 * flip_sign, 1), + Vector3(0, 1, 0), + Vector3(1, -1 * flip_sign, 1), + Vector3(1, 1, 0), + Vector3(1, 1 * flip_sign, 1), + Vector3(1, 0, 0), + Vector3(-1, 1 * flip_sign, 1), + Vector3(0, 0, 0) + }; + + if (!asymmetrical) { + float vw, vh, zn; + camera.get_viewport_size(vw, vh); + zn = p_projection.get_z_near(); + + for (int i = 0; i < 4; i++) { + Vector3 uv = vertices[i * 2 + 1]; + uv.x = (uv.x * 2.0 - 1.0) * vw; + uv.y = -(uv.y * 2.0 - 1.0) * vh; + 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.sky_verts); @@ -2398,16 +2406,24 @@ void RasterizerSceneGLES3::_draw_sky(RasterizerStorageGLES3::Sky *p_sky, const C glBindVertexArray(state.sky_array); - storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_PANORAMA, true); + storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_ASYM_PANO, asymmetrical); + storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_PANORAMA, !asymmetrical); storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_MULTIPLIER, true); storage->shaders.copy.bind(); storage->shaders.copy.set_uniform(CopyShaderGLES3::MULTIPLIER, p_energy); + if (asymmetrical) { + // pack the bits we need from our projection matrix + storage->shaders.copy.set_uniform(CopyShaderGLES3::ASYM_PROJ, camera.matrix[2][0], camera.matrix[0][0], camera.matrix[2][1], camera.matrix[1][1]); + ///@TODO I couldn't get mat3 + p_transform.basis to work, that would be better here. + storage->shaders.copy.set_uniform(CopyShaderGLES3::PANO_TRANSFORM, p_transform); + } glDrawArrays(GL_TRIANGLE_FAN, 0, 4); glBindVertexArray(0); glColorMask(1, 1, 1, 1); + storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_ASYM_PANO, false); storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_MULTIPLIER, false); storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_PANORAMA, false); } @@ -5024,6 +5040,8 @@ void RasterizerSceneGLES3::initialize() { } state.debug_draw = VS::VIEWPORT_DEBUG_DRAW_DISABLED; + + glFrontFace(GL_CW); } void RasterizerSceneGLES3::iteration() { diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index ae41a936c6..44a9909bd7 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -2473,7 +2473,7 @@ void RasterizerStorageGLES3::_update_material(Material *material) { glGenBuffers(1, &material->ubo_id); glBindBuffer(GL_UNIFORM_BUFFER, material->ubo_id); - glBufferData(GL_UNIFORM_BUFFER, material->shader->ubo_size, NULL, GL_DYNAMIC_DRAW); + glBufferData(GL_UNIFORM_BUFFER, material->shader->ubo_size, NULL, GL_STATIC_DRAW); glBindBuffer(GL_UNIFORM_BUFFER, 0); material->ubo_size = material->shader->ubo_size; } @@ -3768,7 +3768,7 @@ void RasterizerStorageGLES3::multimesh_allocate(RID p_multimesh, int p_instances glGenBuffers(1, &multimesh->buffer); glBindBuffer(GL_ARRAY_BUFFER, multimesh->buffer); - glBufferData(GL_ARRAY_BUFFER, multimesh->data.size() * sizeof(float), NULL, GL_DYNAMIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, multimesh->data.size() * sizeof(float), NULL, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); } @@ -5215,7 +5215,7 @@ void RasterizerStorageGLES3::particles_set_amount(RID p_particles, int p_amount) glBindVertexArray(particles->particle_vaos[i]); glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffers[i]); - glBufferData(GL_ARRAY_BUFFER, floats * sizeof(float), data, GL_DYNAMIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, floats * sizeof(float), data, GL_STATIC_DRAW); for (int i = 0; i < 6; i++) { glEnableVertexAttribArray(i); @@ -6198,7 +6198,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { rt->buffers.effects_active = true; } - if (!rt->flags[RENDER_TARGET_NO_SAMPLING]) { + if (!rt->flags[RENDER_TARGET_NO_SAMPLING] && rt->width >= 2 && rt->height >= 2) { for (int i = 0; i < 2; i++) { @@ -6511,7 +6511,7 @@ void RasterizerStorageGLES3::canvas_light_occluder_set_polylines(RID p_occluder, 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_DYNAMIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, lc * 6 * sizeof(real_t), vw.ptr(), GL_STATIC_DRAW); } else { glBindBuffer(GL_ARRAY_BUFFER, co->vertex_id); diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp index 91159e3381..5fe7b53a7d 100644 --- a/drivers/gles3/shader_compiler_gles3.cpp +++ b/drivers/gles3/shader_compiler_gles3.cpp @@ -838,6 +838,7 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() { actions[VS::SHADER_SPATIAL].render_mode_defines["diffuse_lambert_wrap"] = "#define DIFFUSE_LAMBERT_WRAP\n"; actions[VS::SHADER_SPATIAL].render_mode_defines["diffuse_toon"] = "#define DIFFUSE_TOON\n"; + actions[VS::SHADER_SPATIAL].render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_SCHLICK_GGX\n"; actions[VS::SHADER_SPATIAL].render_mode_defines["specular_blinn"] = "#define SPECULAR_BLINN\n"; actions[VS::SHADER_SPATIAL].render_mode_defines["specular_phong"] = "#define SPECULAR_PHONG\n"; actions[VS::SHADER_SPATIAL].render_mode_defines["specular_toon"] = "#define SPECULAR_TOON\n"; diff --git a/drivers/gles3/shaders/copy.glsl b/drivers/gles3/shaders/copy.glsl index d33193ee50..743fe122d1 100644 --- a/drivers/gles3/shaders/copy.glsl +++ b/drivers/gles3/shaders/copy.glsl @@ -27,6 +27,8 @@ void main() { #if defined(USE_CUBEMAP) || defined(USE_PANORAMA) cube_interp = cube_in; +#elif defined(USE_ASYM_PANO) + uv_interp = vertex_attrib.xy; #else uv_interp = uv_in; #ifdef V_FLIP @@ -59,6 +61,11 @@ in vec3 cube_interp; in vec2 uv_interp; #endif +#ifdef USE_ASYM_PANO +uniform highp mat4 pano_transform; +uniform highp vec4 asym_proj; +#endif + #ifdef USE_CUBEMAP uniform samplerCube source_cube; //texunit:0 #else @@ -70,7 +77,7 @@ uniform sampler2D source; //texunit:0 uniform float multiplier; #endif -#ifdef USE_PANORAMA +#if defined(USE_PANORAMA) || defined(USE_ASYM_PANO) vec4 texturePanorama(vec3 normal,sampler2D pano ) { @@ -122,6 +129,21 @@ void main() { vec4 color = texturePanorama( normalize(cube_interp), source ); +#elif defined(USE_ASYM_PANO) + + // When an assymetrical projection matrix is used (applicable for stereoscopic rendering i.e. VR) we need to do this calculation per fragment to get a perspective correct result. + // Note that we're ignoring the x-offset for IPD, with Z sufficiently in the distance it becomes neglectible, as a result we could probably just set cube_normal.z to -1. + // The Matrix[2][0] (= asym_proj.x) and Matrix[2][1] (= asym_proj.z) values are what provide the right shift in the image. + + vec3 cube_normal; + cube_normal.z = -1000000.0; + cube_normal.x = (cube_normal.z * (-uv_interp.x - asym_proj.x)) / asym_proj.y; + cube_normal.y = (cube_normal.z * (-uv_interp.y - asym_proj.z)) / asym_proj.a; + cube_normal = mat3(pano_transform) * cube_normal; + cube_normal.z = -cube_normal.z; + + vec4 color = texturePanorama( normalize(cube_normal.xyz), source ); + #elif defined(USE_CUBEMAP) vec4 color = texture( source_cube, normalize(cube_interp) ); diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index 41d5ef5bc9..2c6dd5552e 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -164,7 +164,7 @@ uniform int spot_light_count; out vec4 diffuse_light_interp; out vec4 specular_light_interp; -void light_compute(vec3 N, vec3 L,vec3 V, vec3 light_color,float roughness,inout vec3 diffuse, inout vec3 specular) { +void light_compute(vec3 N, vec3 L,vec3 V, vec3 light_color, float roughness, inout vec3 diffuse, inout vec3 specular) { float dotNL = max(dot(N,L), 0.0 ); diffuse += dotNL * light_color / M_PI; @@ -865,11 +865,57 @@ float contact_shadow_compute(vec3 pos, vec3 dir, float max_distance) { #endif -// GGX Specular -// Source: http://www.filmicworlds.com/images/ggx-opt/optimized-ggx.hlsl -float G1V(float dotNV, float k) -{ - return 1.0 / (dotNV * (1.0 - k) + k); + +// This returns the G_GGX function divided by 2 cos_theta_m, where in practice cos_theta_m is either N.L or N.V. +// We're dividing this factor off because the overall term we'll end up looks like +// (see, for example, the first unnumbered equation in B. Burley, "Physically Based Shading at Disney", SIGGRAPH 2012): +// +// F(L.V) D(N.H) G(N.L) G(N.V) / (4 N.L N.V) +// +// We're basically regouping this as +// +// F(L.V) D(N.H) [G(N.L)/(2 N.L)] [G(N.V) / (2 N.V)] +// +// and thus, this function implements the [G(N.m)/(2 N.m)] part with m = L or V. +// +// The contents of the D and G (G1) functions (GGX) are taken from +// E. Heitz, "Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs", J. Comp. Graph. Tech. 3 (2) (2014). +// Eqns 71-72 and 85-86 (see also Eqns 43 and 80). + +float G_GGX_2cos(float cos_theta_m, float alpha) { + // Schlick's approximation + // C. Schlick, "An Inexpensive BRDF Model for Physically-based Rendering", Computer Graphics Forum. 13 (3): 233 (1994) + // Eq. (19), although see Heitz (2014) the about the problems with his derivation. + // It nevertheless approximates GGX well with k = alpha/2. + float k = 0.5*alpha; + return 0.5 / (cos_theta_m * (1.0 - k) + k); + + // float cos2 = cos_theta_m*cos_theta_m; + // float sin2 = (1.0-cos2); + // return 1.0 /( cos_theta_m + sqrt(cos2 + alpha*alpha*sin2) ); +} + +float D_GGX(float cos_theta_m, float alpha) { + float alpha2 = alpha*alpha; + float d = 1.0 + (alpha2-1.0)*cos_theta_m*cos_theta_m; + return alpha2/(M_PI * d * d); +} + +float G_GGX_anisotropic_2cos(float cos_theta_m, float alpha_x, float alpha_y, float cos_phi, float sin_phi) { + float cos2 = cos_theta_m * cos_theta_m; + float sin2 = (1.0-cos2); + float s_x = alpha_x * cos_phi; + float s_y = alpha_y * sin_phi; + return 1.0 / (cos_theta_m + sqrt(cos2 + (s_x*s_x + s_y*s_y)*sin2 )); +} + +float D_GGX_anisotropic(float cos_theta_m, float alpha_x, float alpha_y, float cos_phi, float sin_phi) { + float cos2 = cos_theta_m * cos_theta_m; + float sin2 = (1.0-cos2); + float r_x = cos_phi/alpha_x; + float r_y = sin_phi/alpha_y; + float d = cos2 + sin2*(r_x * r_x + r_y * r_y); + return 1.0 / (M_PI * alpha_x * alpha_y * d * d ); } @@ -888,9 +934,13 @@ float GTR1(float NdotH, float a) return (a2-1.0) / (M_PI*log(a2)*t); } +vec3 metallic_to_specular_color(float metallic, float specular, vec3 albedo) { + float dielectric = (0.034 * 2.0) * specular; + // energy conservation + return mix(vec3(dielectric), albedo, metallic); // TODO: reference? +} - -void light_compute(vec3 N, vec3 L,vec3 V,vec3 B, vec3 T,vec3 light_color,vec3 attenuation,vec3 diffuse_color, vec3 transmission, float specular_blob_intensity, float roughness, float rim,float rim_tint, float clearcoat, float clearcoat_gloss,float anisotropy,inout vec3 diffuse, inout vec3 specular) { +void light_compute(vec3 N, vec3 L, vec3 V, vec3 B, vec3 T, vec3 light_color, vec3 attenuation, vec3 diffuse_color, vec3 transmission, float specular_blob_intensity, float roughness, float rim, float rim_tint, float clearcoat, float clearcoat_gloss, float anisotropy, inout vec3 diffuse_light, inout vec3 specular_light) { #if defined(USE_LIGHT_SHADER_CODE) //light is written by the light shader @@ -904,41 +954,42 @@ LIGHT_SHADER_CODE #else - - float dotNL = max(dot(N,L), 0.0 ); + float NdotL = dot(N,L); + float cNdotL = max(NdotL, 0.0); // clamped NdotL + float NdotV = dot(N, V); + float cNdotV = max(NdotV, 0.0); #if defined(DIFFUSE_OREN_NAYAR) - vec3 light_amount; + vec3 diffuse_brdf_NL; #else - float light_amount; + float diffuse_brdf_NL; // BRDF times N.L for calculating diffuse radiance #endif #if defined(DIFFUSE_LAMBERT_WRAP) //energy conserving lambert wrap shader - light_amount = max(0.0,(dot(N,L) + roughness) / ((1.0 + roughness) * (1.0 + roughness))); + diffuse_brdf_NL = max(0.0,(NdotL + roughness) / ((1.0 + roughness) * (1.0 + roughness))); #elif defined(DIFFUSE_OREN_NAYAR) { // see http://mimosa-pudica.net/improved-oren-nayar.html float LdotV = dot(L, V); - float NdotL = dot(L, N); - float NdotV = dot(N, V); + float s = LdotV - NdotL * NdotV; float t = mix(1.0, max(NdotL, NdotV), step(0.0, s)); - float sigma2 = roughness * roughness; + float sigma2 = roughness * roughness; // TODO: this needs checking vec3 A = 1.0 + sigma2 * (- 0.5 / (sigma2 + 0.33) + 0.17*diffuse_color / (sigma2 + 0.13) ); float B = 0.45 * sigma2 / (sigma2 + 0.09); - light_amount = dotNL * (A + vec3(B) * s / t) / M_PI; + diffuse_brdf_NL = cNdotL * (A + vec3(B) * s / t) * (1.0 / M_PI); } #elif defined(DIFFUSE_TOON) - light_amount = smoothstep(-roughness,max(roughness,0.01),dot(N,L)); + diffuse_brdf_NL = smoothstep(-roughness,max(roughness,0.01),NdotL); #elif defined(DIFFUSE_BURLEY) @@ -946,40 +997,38 @@ LIGHT_SHADER_CODE vec3 H = normalize(V + L); - float NoL = max(0.0,dot(N, L)); - float LoH = max(0.0,dot(L, H)); - float NoV = max(0.0,dot(N, V)); - - float FD90 = 0.5 + 2.0 * LoH * LoH * roughness; - float FdV = 1.0 + (FD90 - 1.0) * SchlickFresnel(NoV); - float FdL = 1.0 + (FD90 - 1.0) * SchlickFresnel(NoL); - light_amount = ( (1.0 / M_PI) * FdV * FdL ) * NoL; + float cLdotH = max(0.0,dot(L, H)); + + float FD90 = 0.5 + 2.0 * cLdotH * cLdotH * roughness; + float FdV = 1.0 + (FD90 - 1.0) * SchlickFresnel(cNdotV); + float FdL = 1.0 + (FD90 - 1.0) * SchlickFresnel(cNdotL); + diffuse_brdf_NL = (1.0 / M_PI) * FdV * FdL * cNdotL; /* float energyBias = mix(roughness, 0.0, 0.5); float energyFactor = mix(roughness, 1.0, 1.0 / 1.51); float fd90 = energyBias + 2.0 * VoH * VoH * roughness; float f0 = 1.0; - float lightScatter = f0 + (fd90 - f0) * pow(1.0 - NoL, 5.0); - float viewScatter = f0 + (fd90 - f0) * pow(1.0 - NoV, 5.0); + float lightScatter = f0 + (fd90 - f0) * pow(1.0 - cNdotL, 5.0); + float viewScatter = f0 + (fd90 - f0) * pow(1.0 - cNdotV, 5.0); - light_amount = lightScatter * viewScatter * energyFactor;*/ + diffuse_brdf_NL = lightScatter * viewScatter * energyFactor;*/ } #else //lambert - light_amount = dotNL / M_PI; + diffuse_brdf_NL = cNdotL * (1.0 / M_PI); #endif #if defined(TRANSMISSION_USED) - diffuse += light_color * diffuse_color * mix(vec3(light_amount),vec3(M_PI),transmission) * attenuation; + diffuse_light += light_color * diffuse_color * mix(vec3(diffuse_brdf_NL), vec3(M_PI), transmission) * attenuation; #else - diffuse += light_color * diffuse_color * light_amount * attenuation; + diffuse_light += light_color * diffuse_color * diffuse_brdf_NL * attenuation; #endif - float dotNV = max(dot(N,V), 0.0 ); + #if defined(LIGHT_USE_RIM) - float rim_light = pow(1.0-dotNV,(1.0-roughness)*16.0); - diffuse += rim_light * rim * mix(vec3(1.0),diffuse_color,rim_tint) * light_color; + float rim_light = pow(1.0-cNdotV, (1.0-roughness)*16.0); + diffuse_light += rim_light * rim * mix(vec3(1.0),diffuse_color,rim_tint) * light_color; #endif @@ -991,37 +1040,36 @@ LIGHT_SHADER_CODE #if defined(SPECULAR_BLINN) vec3 H = normalize(V + L); - float dotNH = max(dot(N,H), 0.0 ); - float intensity = pow( dotNH, (1.0-roughness) * 256.0); - specular += light_color * intensity * specular_blob_intensity * attenuation; + float cNdotH = max(dot(N,H), 0.0 ); + float intensity = pow( cNdotH, (1.0-roughness) * 256.0); + specular_light += light_color * intensity * specular_blob_intensity * attenuation; #elif defined(SPECULAR_PHONG) vec3 R = normalize(-reflect(L,N)); - float dotNV = max(0.0,dot(R,V)); - float intensity = pow( dotNV, (1.0-roughness) * 256.0); - specular += light_color * intensity * specular_blob_intensity * attenuation; + float cRdotV = max(0.0,dot(R,V)); + float intensity = pow( cRdotV, (1.0-roughness) * 256.0); + specular_light += light_color * intensity * specular_blob_intensity * attenuation; #elif defined(SPECULAR_TOON) vec3 R = normalize(-reflect(L,N)); - float dotNV = dot(R,V); + float RdotV = dot(R,V); float mid = 1.0-roughness; mid*=mid; - float intensity = smoothstep(mid-roughness*0.5,mid+roughness*0.5,dotNV) * mid; - diffuse += light_color * intensity * specular_blob_intensity * attenuation; //write to diffuse, as in toon shading you generally want no reflection + float intensity = smoothstep(mid-roughness*0.5, mid+roughness*0.5, RdotV) * mid; + diffuse_light += light_color * intensity * specular_blob_intensity * attenuation; // write to diffuse_light, as in toon shading you generally want no reflection #elif defined(SPECULAR_DISABLED) //none.. -#else +#elif defined(SPECULAR_SCHLICK_GGX) // shlick+ggx as default - float alpha = roughness * roughness; vec3 H = normalize(V + L); - float dotNH = max(dot(N,H), 0.0 ); - float dotLH = max(dot(L,H), 0.0 ); + float cNdotH = max(dot(N,H), 0.0); + float cLdotH = max(dot(L,H), 0.0); #if defined(LIGHT_USE_ANISOTROPY) @@ -1030,38 +1078,42 @@ LIGHT_SHADER_CODE float ry = roughness*aspect; float ax = rx*rx; float ay = ry*ry; - float dotXH = dot( T, H ); - float dotYH = dot( B, H ); - float pi = M_PI; - float denom = dotXH*dotXH / (ax*ax) + dotYH*dotYH / (ay*ay) + dotNH*dotNH; - float D = 1.0 / ( pi * ax*ay * denom*denom ); + float XdotH = dot( T, H ); + float YdotH = dot( B, H ); + float D = D_GGX_anisotropic(cNdotH, ax, ay, XdotH, YdotH); + float G = G_GGX_anisotropic_2cos(cNdotL, ax, ay, XdotH, YdotH) * G_GGX_anisotropic_2cos(cNdotV, ax, ay, XdotH, YdotH); #else - float alphaSqr = alpha * alpha; - float pi = M_PI; - float denom = dotNH * dotNH * (alphaSqr - 1.0) + 1.0; - float D = alphaSqr / (pi * denom * denom); + float alpha = roughness * roughness; + float D = D_GGX(cNdotH, alpha); + float G = G_GGX_2cos(cNdotL, alpha) * G_GGX_2cos(cNdotV, alpha); #endif // F - float F0 = 1.0; - float dotLH5 = SchlickFresnel( dotLH ); - float F = F0 + (1.0 - F0) * (dotLH5); - - // V - float k = alpha / 2.0f; - float vis = G1V(dotNL, k) * G1V(dotNV, k); + float F0 = 1.0; // FIXME + float cLdotH5 = SchlickFresnel(cLdotH); + float F = mix(cLdotH5, 1.0, F0); - float speci = dotNL * D * F * vis; + float specular_brdf_NL = cNdotL * D * F * G; - specular += speci * light_color * specular_blob_intensity * attenuation; + specular_light += specular_brdf_NL * light_color * specular_blob_intensity * attenuation; #endif #if defined(LIGHT_USE_CLEARCOAT) - float Dr = GTR1(dotNH, mix(.1,.001,clearcoat_gloss)); - float Fr = mix(.04, 1.0, dotLH5); - float Gr = G1V(dotNL, .25) * G1V(dotNV, .25); - specular += .25*clearcoat*Gr*Fr*Dr; +# if !defined(SPECULAR_SCHLICK_GGX) && !defined(SPECULAR_BLINN) + vec3 H = normalize(V + L); +# endif +# if !defined(SPECULAR_SCHLICK_GGX) + float cNdotH = max(dot(N,H), 0.0); + float cLdotH = max(dot(L,H), 0.0); + float cLdotH5 = SchlickFresnel(cLdotH); +#endif + float Dr = GTR1(cNdotH, mix(.1, .001, clearcoat_gloss)); + float Fr = mix(.04, 1.0, cLdotH5); + float Gr = G_GGX_2cos(cNdotL, .25) * G_GGX_2cos(cNdotV, .25); + + + specular_light += .25*clearcoat*Gr*Fr*Dr; #endif } @@ -1089,9 +1141,7 @@ float sample_shadow(highp sampler2DShadow shadow, vec2 shadow_pixel_size, vec2 p avg+=textureProj(shadow,vec4(pos+vec2(0.0,-shadow_pixel_size.y*2.0),depth,1.0)); return avg*(1.0/13.0); -#endif - -#ifdef SHADOW_MODE_PCF_5 +#elif defined(SHADOW_MODE_PCF_5) float avg=textureProj(shadow,vec4(pos,depth,1.0)); avg+=textureProj(shadow,vec4(pos+vec2(shadow_pixel_size.x,0.0),depth,1.0)); @@ -1099,11 +1149,11 @@ float sample_shadow(highp sampler2DShadow shadow, vec2 shadow_pixel_size, vec2 p avg+=textureProj(shadow,vec4(pos+vec2(0.0,shadow_pixel_size.y),depth,1.0)); avg+=textureProj(shadow,vec4(pos+vec2(0.0,-shadow_pixel_size.y),depth,1.0)); return avg*(1.0/5.0); -#endif -#if !defined(SHADOW_MODE_PCF_5) && !defined(SHADOW_MODE_PCF_13) +#else return textureProj(shadow,vec4(pos,depth,1.0)); + #endif } @@ -1145,7 +1195,7 @@ vec3 light_transmittance(float translucency,vec3 light_vec, vec3 normal, vec3 po } #endif -void light_process_omni(int idx, vec3 vertex, vec3 eye_vec,vec3 normal,vec3 binormal, vec3 tangent, vec3 albedo, vec3 transmission, float roughness, float rim, float rim_tint, float clearcoat, float clearcoat_gloss,float anisotropy,float p_blob_intensity,inout vec3 diffuse_light, inout vec3 specular_light) { +void light_process_omni(int idx, vec3 vertex, vec3 eye_vec,vec3 normal,vec3 binormal, vec3 tangent, vec3 albedo, vec3 transmission, float roughness, float rim, float rim_tint, float clearcoat, float clearcoat_gloss, float anisotropy, float p_blob_intensity, inout vec3 diffuse_light, inout vec3 specular_light) { vec3 light_rel_vec = omni_lights[idx].light_pos_inv_radius.xyz-vertex; float light_length = length( light_rel_vec ); @@ -1934,9 +1984,9 @@ FRAGMENT_SHADER_CODE - //energu conservation - diffuse_light=mix(diffuse_light,vec3(0.0),metallic); - ambient_light=mix(ambient_light,vec3(0.0),metallic); + //energy conservation + diffuse_light *= 1.0-metallic; // TODO: avoid diffuse and ambient light calculations when metallic == 1 + ambient_light *= 1.0-metallic; { @@ -1945,9 +1995,6 @@ FRAGMENT_SHADER_CODE //simplify for toon, as specular_light *= specular * metallic * albedo * 2.0; #else - //energy conservation - vec3 dielectric = vec3(0.034) * specular * 2.0; - vec3 specular_color = mix(dielectric, albedo, metallic); // Environment brdf approximation (Lazarov 2013) // see https://www.unrealengine.com/en-US/blog/physically-based-shading-on-mobile const vec4 c0 = vec4(-1.0, -0.0275, -0.572, 0.022); @@ -1957,6 +2004,7 @@ FRAGMENT_SHADER_CODE float a004 = min( r.x * r.x, exp2( -9.28 * ndotv ) ) * r.x + r.y; vec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw; + vec3 specular_color = metallic_to_specular_color(metallic, specular, albedo); specular_light *= AB.x * specular_color + AB.y; #endif @@ -2056,5 +2104,3 @@ FRAGMENT_SHADER_CODE } - - diff --git a/drivers/gles3/shaders/subsurf_scattering.glsl b/drivers/gles3/shaders/subsurf_scattering.glsl index 20c3b7473f..fc66d66198 100644 --- a/drivers/gles3/shaders/subsurf_scattering.glsl +++ b/drivers/gles3/shaders/subsurf_scattering.glsl @@ -82,18 +82,18 @@ QUALIFIER vec2 kernel[17] = vec2[]( const int kernel_size=11; -QUALIFIER vec4 kernel[11] = vec4[]( - vec4(0.560479, 0.0), - vec4(0.00471691, -2.0), - vec4(0.0192831, -1.28), - vec4(0.03639, -0.72), - vec4(0.0821904, -0.32), - vec4(0.0771802, -0.08), - vec4(0.0771802, 0.08), - vec4(0.0821904, 0.32), - vec4(0.03639, 0.72), - vec4(0.0192831, 1.28), - vec4(0.00471691,2.0) +QUALIFIER vec2 kernel[11] = vec2[]( + vec2(0.560479, 0.0), + vec2(0.00471691, -2.0), + vec2(0.0192831, -1.28), + vec2(0.03639, -0.72), + vec2(0.0821904, -0.32), + vec2(0.0771802, -0.08), + vec2(0.0771802, 0.08), + vec2(0.0821904, 0.32), + vec2(0.03639, 0.72), + vec2(0.0192831, 1.28), + vec2(0.00471691,2.0) ); #endif //USE_11_SAMPLES @@ -190,4 +190,3 @@ void main() { frag_color = base_color; } } - diff --git a/drivers/gles3/shaders/tonemap.glsl b/drivers/gles3/shaders/tonemap.glsl index 73dec4f90c..2f671158b2 100644 --- a/drivers/gles3/shaders/tonemap.glsl +++ b/drivers/gles3/shaders/tonemap.glsl @@ -175,12 +175,9 @@ vec3 tonemap_reindhart(vec3 color,float white) { return ( color * ( 1.0 + ( color / ( white) ) ) ) / ( 1.0 + color ); } - void main() { - ivec2 coord = ivec2(gl_FragCoord.xy); - vec3 color = texelFetch(source,coord,0).rgb; - + vec4 color = textureLod(source, uv_interp, 0.0); #ifdef USE_AUTO_EXPOSURE @@ -324,5 +321,3 @@ void main() { frag_color=vec4(color.rgb,1.0); } - - diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp index 649f874cf4..206f57d4a2 100644 --- a/drivers/unix/file_access_unix.cpp +++ b/drivers/unix/file_access_unix.cpp @@ -223,6 +223,12 @@ Error FileAccessUnix::get_error() const { return last_error; } +void FileAccessUnix::flush() { + + ERR_FAIL_COND(!f); + fflush(f); +} + void FileAccessUnix::store_8(uint8_t p_dest) { ERR_FAIL_COND(!f); diff --git a/drivers/unix/file_access_unix.h b/drivers/unix/file_access_unix.h index e2848e4128..96f2ff8e26 100644 --- a/drivers/unix/file_access_unix.h +++ b/drivers/unix/file_access_unix.h @@ -72,6 +72,7 @@ public: virtual Error get_error() const; ///< get last error + virtual void flush(); virtual void store_8(uint8_t p_dest); ///< store a byte virtual bool file_exists(const String &p_path); ///< return true if a file exists diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index 75c8a153f6..2a3d48746f 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -64,39 +64,7 @@ #include <string.h> #include <sys/time.h> #include <sys/wait.h> - -extern bool _print_error_enabled; - -void OS_Unix::print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) { - - if (!_print_error_enabled) - return; - - const char *err_details; - if (p_rationale && p_rationale[0]) - err_details = p_rationale; - else - err_details = p_code; - - switch (p_type) { - case ERR_ERROR: - print("\E[1;31mERROR: %s: \E[0m\E[1m%s\n", p_function, err_details); - print("\E[0;31m At: %s:%i.\E[0m\n", p_file, p_line); - break; - case ERR_WARNING: - print("\E[1;33mWARNING: %s: \E[0m\E[1m%s\n", p_function, err_details); - print("\E[0;33m At: %s:%i.\E[0m\n", p_file, p_line); - break; - case ERR_SCRIPT: - print("\E[1;35mSCRIPT ERROR: %s: \E[0m\E[1m%s\n", p_function, err_details); - print("\E[0;35m At: %s:%i.\E[0m\n", p_file, p_line); - break; - case ERR_SHADER: - print("\E[1;36mSHADER ERROR: %s: \E[0m\E[1m%s\n", p_function, err_details); - print("\E[0;36m At: %s:%i.\E[0m\n", p_file, p_line); - break; - } -} +#include <unistd.h> void OS_Unix::debug_break() { @@ -165,29 +133,16 @@ void OS_Unix::initialize_core() { } } -void OS_Unix::finalize_core() { +void OS_Unix::initialize_logger() { + Vector<Logger *> loggers; + loggers.push_back(memnew(UnixTerminalLogger)); + loggers.push_back(memnew(RotatedFileLogger("user://logs/log.txt"))); + _set_logger(memnew(CompositeLogger(loggers))); } -void OS_Unix::vprint(const char *p_format, va_list p_list, bool p_stder) { - - if (p_stder) { - - vfprintf(stderr, p_format, p_list); - fflush(stderr); - } else { - - vprintf(p_format, p_list); - fflush(stdout); - } +void OS_Unix::finalize_core() { } -void OS_Unix::print(const char *p_format, ...) { - - va_list argp; - va_start(argp, p_format); - vprintf(p_format, argp); - va_end(argp); -} void OS_Unix::alert(const String &p_alert, const String &p_title) { fprintf(stderr, "ERROR: %s\n", p_alert.utf8().get_data()); @@ -330,7 +285,7 @@ uint64_t OS_Unix::get_ticks_usec() const { return longtime; } -Error OS_Unix::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode) { +Error OS_Unix::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr) { if (p_blocking && r_pipe) { @@ -342,7 +297,11 @@ Error OS_Unix::execute(const String &p_path, const List<String> &p_arguments, bo argss += String(" \"") + p_arguments[i] + "\""; } - argss += " 2>/dev/null"; //silence stderr + if (read_stderr) { + argss += " 2>&1"; // Read stderr too + } else { + argss += " 2>/dev/null"; //silence stderr + } FILE *f = popen(argss.utf8().get_data(), "r"); ERR_FAIL_COND_V(!f, ERR_CANT_OPEN); @@ -384,7 +343,7 @@ Error OS_Unix::execute(const String &p_path, const List<String> &p_arguments, bo execvp(getprogname(), &args[0]); } #else - execv(p_path.utf8().get_data(), &args[0]); + execvp(p_path.utf8().get_data(), &args[0]); #endif // still alive? something failed.. fprintf(stderr, "**ERROR** OS_Unix::execute - Could not create child process while executing: %s\n", p_path.utf8().get_data()); @@ -559,4 +518,38 @@ String OS_Unix::get_executable_path() const { #endif } +void UnixTerminalLogger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) { + if (!should_log(true)) { + return; + } + + const char *err_details; + if (p_rationale && p_rationale[0]) + err_details = p_rationale; + else + err_details = p_code; + + switch (p_type) { + case ERR_WARNING: + logf_error("\E[1;33mWARNING: %s: \E[0m\E[1m%s\n", p_function, err_details); + logf_error("\E[0;33m At: %s:%i.\E[0m\n", p_file, p_line); + break; + case ERR_SCRIPT: + logf_error("\E[1;35mSCRIPT ERROR: %s: \E[0m\E[1m%s\n", p_function, err_details); + logf_error("\E[0;35m At: %s:%i.\E[0m\n", p_file, p_line); + break; + case ERR_SHADER: + logf_error("\E[1;36mSHADER ERROR: %s: \E[0m\E[1m%s\n", p_function, err_details); + logf_error("\E[0;36m At: %s:%i.\E[0m\n", p_file, p_line); + break; + case ERR_ERROR: + default: + logf_error("\E[1;31mERROR: %s: \E[0m\E[1m%s\n", p_function, err_details); + logf_error("\E[0;31m At: %s:%i.\E[0m\n", p_file, p_line); + break; + } +} + +UnixTerminalLogger::~UnixTerminalLogger() {} + #endif diff --git a/drivers/unix/os_unix.h b/drivers/unix/os_unix.h index 19e79728fb..87e73534c4 100644 --- a/drivers/unix/os_unix.h +++ b/drivers/unix/os_unix.h @@ -54,11 +54,11 @@ protected: virtual int get_audio_driver_count() const; virtual const char *get_audio_driver_name(int p_driver) const; + virtual void initialize_logger(); virtual void initialize_core(); virtual int unix_initialize_audio(int p_audio_driver); //virtual void initialize(int p_video_driver,int p_audio_driver); - //virtual void finalize(); virtual void finalize_core(); String stdin_buf; @@ -66,10 +66,6 @@ protected: String get_global_settings_path() const; public: - virtual void print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR); - - virtual void print(const char *p_format, ...); - virtual void vprint(const char *p_format, va_list p_list, bool p_stder = false); virtual void alert(const String &p_alert, const String &p_title = "ALERT!"); virtual String get_stdin_string(bool p_block); @@ -101,7 +97,7 @@ public: virtual void delay_usec(uint32_t p_usec) const; virtual uint64_t get_ticks_usec() const; - virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id = NULL, String *r_pipe = NULL, int *r_exitcode = NULL); + virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id = NULL, String *r_pipe = NULL, int *r_exitcode = NULL, bool read_stderr = false); virtual Error kill(const ProcessID &p_pid); virtual int get_process_id() const; @@ -120,6 +116,12 @@ public: //virtual void run( MainLoop * p_main_loop ); }; +class UnixTerminalLogger : public StdLogger { +public: + virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR); + virtual ~UnixTerminalLogger(); +}; + #endif #endif diff --git a/drivers/unix/syslog_logger.cpp b/drivers/unix/syslog_logger.cpp new file mode 100644 index 0000000000..d57f391325 --- /dev/null +++ b/drivers/unix/syslog_logger.cpp @@ -0,0 +1,71 @@ +/*************************************************************************/ +/* syslog_logger.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifdef UNIX_ENABLED + +#include "syslog_logger.h" +#include "print_string.h" +#include <syslog.h> + +void SyslogLogger::logv(const char *p_format, va_list p_list, bool p_err) { + if (!should_log(p_err)) { + return; + } + + vsyslog(p_err ? LOG_ERR : LOG_INFO, p_format, p_list); +} + +void SyslogLogger::print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) { + if (!should_log(true)) { + return; + } + + const char *err_type = "**ERROR**"; + switch (p_type) { + case ERR_ERROR: err_type = "**ERROR**"; break; + case ERR_WARNING: err_type = "**WARNING**"; break; + case ERR_SCRIPT: err_type = "**SCRIPT ERROR**"; break; + case ERR_SHADER: err_type = "**SHADER ERROR**"; break; + default: ERR_PRINT("Unknown error type"); break; + } + + const char *err_details; + if (p_rationale && *p_rationale) + err_details = p_rationale; + else + err_details = p_code; + + syslog(p_type == ERR_WARNING ? LOG_WARNING : LOG_ERR, "%s: %s\n At: %s:%i:%s() - %s", err_type, err_details, p_file, p_line, p_function, p_code); +} + +SyslogLogger::~SyslogLogger() { +} + +#endif
\ No newline at end of file diff --git a/drivers/unix/syslog_logger.h b/drivers/unix/syslog_logger.h new file mode 100644 index 0000000000..b3cf2f9e3a --- /dev/null +++ b/drivers/unix/syslog_logger.h @@ -0,0 +1,48 @@ +/*************************************************************************/ +/* syslog_logger.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef SYSLOG_LOGGER_H +#define SYSLOG_LOGGER_H + +#ifdef UNIX_ENABLED + +#include "io/logger.h" + +class SyslogLogger : public Logger { +public: + virtual void logv(const char *p_format, va_list p_list, bool p_err); + virtual void print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type); + + virtual ~SyslogLogger(); +}; + +#endif + +#endif
\ No newline at end of file diff --git a/drivers/windows/dir_access_windows.cpp b/drivers/windows/dir_access_windows.cpp index 6d6a6027d9..0bc4201ba3 100644 --- a/drivers/windows/dir_access_windows.cpp +++ b/drivers/windows/dir_access_windows.cpp @@ -162,10 +162,10 @@ Error DirAccessWindows::make_dir(String p_dir) { GLOBAL_LOCK_FUNCTION + p_dir = fix_path(p_dir); if (p_dir.is_rel_path()) - p_dir = get_current_dir().plus_file(p_dir); + p_dir = current_dir.plus_file(p_dir); - p_dir = fix_path(p_dir); p_dir = p_dir.replace("/", "\\"); bool success; diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp index d128b58244..3b6e469c9c 100644 --- a/drivers/windows/file_access_windows.cpp +++ b/drivers/windows/file_access_windows.cpp @@ -207,6 +207,12 @@ Error FileAccessWindows::get_error() const { return last_error; } +void FileAccessWindows::flush() { + + ERR_FAIL_COND(!f); + fflush(f); +} + void FileAccessWindows::store_8(uint8_t p_dest) { ERR_FAIL_COND(!f); diff --git a/drivers/windows/file_access_windows.h b/drivers/windows/file_access_windows.h index 15cbdca739..e5e7fd4a13 100644 --- a/drivers/windows/file_access_windows.h +++ b/drivers/windows/file_access_windows.h @@ -64,6 +64,7 @@ public: virtual Error get_error() const; ///< get last error + virtual void flush(); virtual void store_8(uint8_t p_dest); ///< store a byte virtual bool file_exists(const String &p_name); ///< return true if a file exists |